wip checkpoint
This commit is contained in:
parent
3dc13caab8
commit
21fa871b92
|
|
@ -0,0 +1,62 @@
|
|||
import { w } from "../../../utils/types/general";
|
||||
import { fetchViaProxy } from "../proxy";
|
||||
|
||||
export const loadApiProxyDef = async (url: string, with_types: boolean) => {
|
||||
const raw = await fetchViaProxy(urlPath(url, "/_prasi/_"));
|
||||
let ver = "";
|
||||
if (raw && (raw as any).prasi) {
|
||||
ver = (raw as any).prasi;
|
||||
}
|
||||
const base = baseUrl(url);
|
||||
|
||||
if (ver === "v2") {
|
||||
await new Promise<void>((done) => {
|
||||
const d = document;
|
||||
const script = d.createElement("script");
|
||||
script.onload = async () => {
|
||||
done();
|
||||
};
|
||||
if (with_types) {
|
||||
script.src = `${base}/_prasi/load.js?url=${url}&dev=1`;
|
||||
} else {
|
||||
script.src = `${base}/_prasi/load.js?url=${url}`;
|
||||
}
|
||||
d.body.appendChild(script);
|
||||
});
|
||||
} else {
|
||||
const apiEntry = await fetch(base + "/_prasi/api-entry");
|
||||
w.prasiApi[url] = {
|
||||
apiEntry: (await apiEntry.json()).srv,
|
||||
};
|
||||
|
||||
if (with_types) {
|
||||
const apiTypes = await fetch(base + "/_prasi/api-types");
|
||||
w.prasiApi[url].apiTypes = await apiTypes.text();
|
||||
w.prasiApi[url].prismaTypes = {
|
||||
"prisma.d.ts": await loadText(`${base}/_prasi/prisma/index.d.ts`),
|
||||
"runtime/index.d.ts": await loadText(
|
||||
`${base}/_prasi/prisma/runtime/index.d.ts`
|
||||
),
|
||||
"runtime/library.d.ts": await loadText(
|
||||
`${base}/_prasi/prisma/runtime/library.d.ts`
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const baseUrl = (url: string) => {
|
||||
const base = new URL(url);
|
||||
return `${base.protocol}//${base.host}`;
|
||||
};
|
||||
|
||||
const urlPath = (url: string, pathname: string) => {
|
||||
const base = new URL(url);
|
||||
base.pathname = pathname;
|
||||
return base.toString();
|
||||
};
|
||||
|
||||
const loadText = async (url: string, v2?: boolean) => {
|
||||
const res = await fetch(url);
|
||||
return await res.text();
|
||||
};
|
||||
|
|
@ -1,40 +1,49 @@
|
|||
import { fetchSendApi } from "./client-frame";
|
||||
import { w } from "../../../utils/types/general";
|
||||
import { fetchViaProxy } from "../proxy";
|
||||
import { loadApiProxyDef } from "./api-proxy-def";
|
||||
|
||||
export const apiClient = (
|
||||
api: Record<string, { url: string; args: any[] }>,
|
||||
apiUrl: string
|
||||
) => {
|
||||
export type ApiProxy<T extends Record<string, any> = {}> = any;
|
||||
|
||||
export const apiProxy = (api_url: string) => {
|
||||
return new Proxy(
|
||||
{},
|
||||
{
|
||||
get: (_, actionName: string) => {
|
||||
const createFn = (actionName: string) => {
|
||||
return function (this: { apiUrl: string } | undefined, ...rest: any) {
|
||||
return function (
|
||||
this: { api_url: string } | undefined,
|
||||
...rest: any
|
||||
) {
|
||||
return new Promise<any>(async (resolve, reject) => {
|
||||
try {
|
||||
let _apiURL = apiUrl;
|
||||
if (typeof this?.apiUrl === "string") {
|
||||
_apiURL = this.apiUrl;
|
||||
let base_url = api_url;
|
||||
if (typeof this?.api_url === "string") {
|
||||
base_url = this.api_url;
|
||||
}
|
||||
|
||||
if (!api) {
|
||||
reject(
|
||||
new Error(`API Definition for ${_apiURL} is not loaded.`)
|
||||
);
|
||||
return;
|
||||
if (!w.prasiApi) {
|
||||
w.prasiApi = {};
|
||||
}
|
||||
|
||||
if (api && !api[actionName]) {
|
||||
if (!w.prasiApi[base_url]) {
|
||||
await loadApiProxyDef(base_url, false);
|
||||
}
|
||||
|
||||
const api_def = w.prasiApi[base_url];
|
||||
if (api_def) {
|
||||
if (!api_def.apiEntry) api_def.apiEntry = {};
|
||||
if (api_def.apiEntry && !api_def.apiEntry[actionName]) {
|
||||
reject(
|
||||
`API ${actionName.toString()} not found, existing API: \n - ${Object.keys(
|
||||
api || {}
|
||||
api_def || {}
|
||||
).join("\n - ")}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let actionUrl = api[actionName].url;
|
||||
const actionParams = api[actionName].args;
|
||||
let actionUrl = api_def.apiEntry[actionName].url;
|
||||
const actionParams = api_def.apiEntry[actionName].args;
|
||||
if (actionUrl && actionParams) {
|
||||
if (rest.length > 0 && actionParams.length > 0) {
|
||||
for (const [idx, p] of Object.entries(rest)) {
|
||||
|
|
@ -53,7 +62,7 @@ export const apiClient = (
|
|||
}
|
||||
}
|
||||
|
||||
const url = `${_apiURL}${actionUrl}`;
|
||||
const url = `${base_url}${actionUrl}`;
|
||||
|
||||
const result = await fetchSendApi(url, rest);
|
||||
resolve(result);
|
||||
|
|
@ -82,3 +91,9 @@ export const apiClient = (
|
|||
}
|
||||
);
|
||||
};
|
||||
|
||||
const fetchSendApi = async (url: string, params: any) => {
|
||||
return await fetchViaProxy(url, params, {
|
||||
"content-type": "application/json",
|
||||
});
|
||||
};
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
import { waitUntil } from "web-utils";
|
||||
import { createFrameCors } from "./client-frame";
|
||||
import hash_sum from "hash-sum";
|
||||
import { fetchViaProxy } from "../proxy";
|
||||
|
||||
export const dbClient = (name: string, dburl?: string) => {
|
||||
export const dbProxy = (dburl: string) => {
|
||||
return new Proxy(
|
||||
{},
|
||||
{
|
||||
|
|
@ -10,7 +9,6 @@ export const dbClient = (name: string, dburl?: string) => {
|
|||
if (table === "_tables") {
|
||||
return () => {
|
||||
return fetchSendDb(
|
||||
name,
|
||||
{
|
||||
name,
|
||||
action: "definition",
|
||||
|
|
@ -24,7 +22,6 @@ export const dbClient = (name: string, dburl?: string) => {
|
|||
if (table === "_definition") {
|
||||
return (table: string) => {
|
||||
return fetchSendDb(
|
||||
name,
|
||||
{
|
||||
name,
|
||||
action: "definition",
|
||||
|
|
@ -38,7 +35,6 @@ export const dbClient = (name: string, dburl?: string) => {
|
|||
if (table.startsWith("$")) {
|
||||
return (...params: any[]) => {
|
||||
return fetchSendDb(
|
||||
name,
|
||||
{
|
||||
name,
|
||||
action: "query",
|
||||
|
|
@ -60,7 +56,6 @@ export const dbClient = (name: string, dburl?: string) => {
|
|||
action = "query";
|
||||
}
|
||||
return fetchSendDb(
|
||||
name,
|
||||
{
|
||||
name,
|
||||
action,
|
||||
|
|
@ -83,37 +78,13 @@ const cachedQueryResult: Record<
|
|||
{ timestamp: number; result: any; promise: Promise<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>>;
|
||||
|
||||
export const fetchSendDb = async (params: any, dburl: string) => {
|
||||
const base = new URL(dburl);
|
||||
base.pathname = `/_dbs/`;
|
||||
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;
|
||||
});
|
||||
base.pathname += `/${params.table}`;
|
||||
}
|
||||
const url = base.toString();
|
||||
|
||||
const hsum = hash_sum(params);
|
||||
const cached = cachedQueryResult[hsum];
|
||||
|
|
@ -121,7 +92,9 @@ export const fetchSendDb = async (
|
|||
if (!cached || (cached && Date.now() - cached.timestamp > 1000)) {
|
||||
cachedQueryResult[hsum] = {
|
||||
timestamp: Date.now(),
|
||||
promise: frm.send(url, params, w.apiHeaders),
|
||||
promise: fetchViaProxy(url, params, {
|
||||
"content-type": "application/json",
|
||||
}),
|
||||
result: null,
|
||||
};
|
||||
|
||||
|
|
@ -47,11 +47,16 @@ export const fetchViaProxy = async (
|
|||
const cur = new URL(location.href);
|
||||
const base = new URL(url);
|
||||
if (cur.host === base.host) {
|
||||
const res = await fetch(base.pathname, {
|
||||
const res = await fetch(
|
||||
base.pathname,
|
||||
data
|
||||
? {
|
||||
method: "POST",
|
||||
body,
|
||||
headers,
|
||||
});
|
||||
}
|
||||
: undefined
|
||||
);
|
||||
const raw = await res.text();
|
||||
try {
|
||||
return JSON.parse(raw);
|
||||
|
|
@ -59,17 +64,15 @@ export const fetchViaProxy = async (
|
|||
return raw;
|
||||
}
|
||||
} else {
|
||||
console.log(url);
|
||||
return null;
|
||||
// const res = await fetch(`/_proxy`, {
|
||||
// method: "POST",
|
||||
// body: JSON.stringify({
|
||||
// url,
|
||||
// body,
|
||||
// headers,
|
||||
// }),
|
||||
// headers: { "content-type": "application/json" },
|
||||
// });
|
||||
// return res.json();
|
||||
const res = await fetch(`/_proxy`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
url,
|
||||
body,
|
||||
headers,
|
||||
}),
|
||||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
return res.json();
|
||||
}
|
||||
};
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
import { Root as ReactRoot, createRoot } from "react-dom/client";
|
||||
import { defineReact, defineWindow } from "web-utils";
|
||||
import { apiProxy } from "./base/load/api/api-proxy";
|
||||
import { dbProxy } from "./base/load/db/db-proxy";
|
||||
import { Root } from "./base/root";
|
||||
import "./index.css";
|
||||
import { registerMobile } from "./render/live/logic/mobile";
|
||||
import { reloadDBAPI } from "./utils/script/init-api";
|
||||
import { w } from "./utils/types/general";
|
||||
import { sworkerAddCache, sworkerRegister } from "./sworker-boot";
|
||||
import { dbClient } from "./base/load/db/client-db";
|
||||
import { w } from "./utils/types/general";
|
||||
|
||||
const start = async () => {
|
||||
const base = `${location.protocol}//${location.host}`;
|
||||
|
|
@ -14,7 +14,12 @@ const start = async () => {
|
|||
root: null as null | ReactRoot,
|
||||
};
|
||||
w.mobile = registerMobile();
|
||||
w.db = dbClient("prasi", location.origin);
|
||||
|
||||
const cur = new URL(location.href);
|
||||
const base_url = `${cur.protocol}//${cur.host}`;
|
||||
w.db = dbProxy(base_url);
|
||||
w.api = apiProxy(base_url);
|
||||
|
||||
w.serverurl = base;
|
||||
|
||||
sworkerRegister(react);
|
||||
|
|
|
|||
|
|
@ -1,17 +1,18 @@
|
|||
import init from "wasm-gzip";
|
||||
import { jscript } from "../../../utils/script/jscript";
|
||||
import { dbClient } from "../../../base/load/db/client-db";
|
||||
import { dbProxy } from "../../../base/load/db/db-proxy";
|
||||
import { PG } from "./ed-global";
|
||||
import { fetchViaProxy } from "../../vi/load/proxy";
|
||||
import { fetchViaProxy } from "../../../base/load/proxy";
|
||||
import { ApiProxy, apiProxy } from "../../../base/load/api/api-proxy";
|
||||
|
||||
let w = window as unknown as { db: ReturnType<typeof dbClient> };
|
||||
let w = window as unknown as {
|
||||
db: ReturnType<typeof dbProxy>;
|
||||
api: ApiProxy;
|
||||
};
|
||||
|
||||
export const edInit = async (p: PG) => {
|
||||
p.status = "ready";
|
||||
|
||||
const cur = new URL(location.href);
|
||||
w.db = dbClient("prasi", `${cur.protocol}//${cur.host}`);
|
||||
|
||||
await init();
|
||||
jscript.init(p.render, { esbuild: false });
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { IContent } from "../../../../utils/types/general";
|
||||
import { VG } from "../../../vi/render/global";
|
||||
import { IMeta, PG, active } from "../../logic/ed-global";
|
||||
import { treeRebuild } from "../../logic/tree/build";
|
||||
|
||||
type MPIVParam = Parameters<Exclude<VG["visit"], undefined>>;
|
||||
export const mainPerItemVisit = (
|
||||
|
|
@ -59,6 +60,12 @@ export const mainPerItemVisit = (
|
|||
parts.props.onPointerDown = (e) => {
|
||||
e.stopPropagation();
|
||||
|
||||
if (active.comp_id && !p.comp.list[active.comp_id]) {
|
||||
active.comp_id = "";
|
||||
treeRebuild(p);
|
||||
return;
|
||||
}
|
||||
|
||||
const item = getOuterItem(
|
||||
{
|
||||
meta: active.comp_id ? p.comp.list[active.comp_id].meta : p.page.meta,
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ export const EdPopUser = ({
|
|||
</div>
|
||||
))}
|
||||
</div>
|
||||
{user.all.length > 0 && onAdd && (
|
||||
{Array.isArray(user.all) && user.all.length > 0 && onAdd && (
|
||||
<Select
|
||||
options={user.all
|
||||
.filter((e) => {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import Downshift from "downshift";
|
||||
import { FC, useEffect } from "react";
|
||||
import { useGlobal, useLocal } from "web-utils";
|
||||
import { createAPI, createDB } from "../../../../../utils/script/init-api";
|
||||
import { apiProxy } from "../../../../../base/load/api/api-proxy";
|
||||
import { dbProxy } from "../../../../../base/load/db/db-proxy";
|
||||
import { FMCompDef, FNCompDef } from "../../../../../utils/types/meta-fn";
|
||||
import { EDGlobal } from "../../../logic/ed-global";
|
||||
import { EdPropLabel } from "./prop-label";
|
||||
|
|
@ -27,8 +28,8 @@ export const EdPropInstanceOptions: FC<{
|
|||
if (!local.loaded) {
|
||||
try {
|
||||
if (p.site.config.api_url) {
|
||||
if (!p.script.db) p.script.db = createDB(p.site.config.api_url);
|
||||
if (!p.script.api) p.script.api = createAPI(p.site.config.api_url);
|
||||
if (!p.script.db) p.script.db = dbProxy(p.site.config.api_url);
|
||||
if (!p.script.api) p.script.api = apiProxy(p.site.config.api_url);
|
||||
}
|
||||
|
||||
const args = {
|
||||
|
|
|
|||
|
|
@ -1,17 +1,12 @@
|
|||
import get from "lodash.get";
|
||||
import {
|
||||
createAPI,
|
||||
createDB,
|
||||
initApi,
|
||||
reloadDBAPI,
|
||||
} from "../../../utils/script/init-api";
|
||||
import { apiProxy } from "../../../base/load/api/api-proxy";
|
||||
import { dbProxy } from "../../../base/load/db/db-proxy";
|
||||
import { jscript } from "../../../utils/script/jscript";
|
||||
import { devLoader } from "../../live/dev-loader";
|
||||
import { LSite } from "../../live/logic/global";
|
||||
import { validateLayout } from "../../live/logic/layout";
|
||||
import importModule from "../tools/dynamic-import";
|
||||
import { EditorGlobal, PG } from "./global";
|
||||
import { devLoader } from "../../live/dev-loader";
|
||||
import { jscript } from "../../../utils/script/jscript";
|
||||
import { deepClone } from "web-utils";
|
||||
|
||||
export const w = window as unknown as {
|
||||
basepath: string;
|
||||
|
|
@ -121,7 +116,7 @@ export const initEditor = async (p: PG, site_id: string) => {
|
|||
prodUrl: localStorage.getItem(`prasi-ext-prod-url-${p.site.id}`) || "",
|
||||
};
|
||||
|
||||
p.site.api_url = await initApi(site.config);
|
||||
p.site.api_url = site.config.api_url;
|
||||
|
||||
if (w.externalAPI.prodUrl !== p.site.api_url) {
|
||||
w.externalAPI.prodUrl = p.site.api_url;
|
||||
|
|
@ -129,7 +124,6 @@ export const initEditor = async (p: PG, site_id: string) => {
|
|||
}
|
||||
if (w.externalAPI.mode === "dev" && w.externalAPI.devUrl) {
|
||||
p.site.api_url = w.externalAPI.devUrl;
|
||||
await reloadDBAPI(w.externalAPI.devUrl);
|
||||
}
|
||||
|
||||
w.apiurl = p.site.api_url;
|
||||
|
|
@ -173,8 +167,8 @@ export const execSiteJS = (p: PG) => {
|
|||
};
|
||||
|
||||
const fn = p.site.js_compiled;
|
||||
scope["api"] = createAPI(p.site.api_url);
|
||||
scope["db"] = createDB(p.site.api_url);
|
||||
scope["api"] = apiProxy(p.site.api_url);
|
||||
scope["db"] = dbProxy(p.site.api_url);
|
||||
const f = new Function(...Object.keys(scope), fn);
|
||||
try {
|
||||
const res = f(...Object.values(scope));
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { FC } from "react";
|
||||
import { createAPI, createDB } from "../../../utils/script/init-api";
|
||||
import { apiProxy } from "../../../base/load/api/api-proxy";
|
||||
import { dbProxy } from "../../../base/load/db/db-proxy";
|
||||
import { FNCompDef } from "../../../utils/types/meta-fn";
|
||||
import { EItem } from "../elements/e-item";
|
||||
import { ItemMeta, PG } from "./global";
|
||||
|
|
@ -15,8 +16,8 @@ export const treePropEval = (
|
|||
) => {
|
||||
if (meta.item.type === "item" && meta.item.component) {
|
||||
if (p.site.api_url) {
|
||||
if (!p.script.db) p.script.db = createDB(p.site.api_url);
|
||||
if (!p.script.api) p.script.api = createAPI(p.site.api_url);
|
||||
if (!p.script.db) p.script.db = dbProxy(p.site.api_url);
|
||||
if (!p.script.api) p.script.api = apiProxy(p.site.api_url);
|
||||
}
|
||||
|
||||
const props = meta.item.component.props;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { FC, ReactNode, Suspense, useEffect } from "react";
|
||||
import { deepClone } from "web-utils";
|
||||
import { createAPI, createDB } from "../../../utils/script/init-api";
|
||||
import { apiProxy } from "../../../base/load/api/api-proxy";
|
||||
import { dbProxy } from "../../../base/load/db/db-proxy";
|
||||
import { ErrorBox } from "../elements/e-error";
|
||||
import { ItemMeta, PG } from "./global";
|
||||
|
||||
|
|
@ -30,8 +31,8 @@ export const treeScopeEval = (
|
|||
|
||||
// prepare args
|
||||
if (p.site.api_url) {
|
||||
if (!p.script.db) p.script.db = createDB(p.site.api_url);
|
||||
if (!p.script.api) p.script.api = createAPI(p.site.api_url);
|
||||
if (!p.script.db) p.script.db = dbProxy(p.site.api_url);
|
||||
if (!p.script.api) p.script.api = apiProxy(p.site.api_url);
|
||||
}
|
||||
const w = window as any;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import { useGlobal } from "web-utils";
|
|||
import { EditorGlobal } from "../../../../logic/global";
|
||||
import { ExternalDeploy } from "./ExternalDeploy";
|
||||
import { w } from "../../../../logic/init";
|
||||
import { reloadDBAPI } from "../../../../../../utils/script/init-api";
|
||||
|
||||
export const ExternalAPI = ({
|
||||
status,
|
||||
|
|
@ -88,11 +87,9 @@ export const ExternalAPI = ({
|
|||
if (w.externalAPI.mode === "dev") {
|
||||
p.site.api_url = w.externalAPI.devUrl;
|
||||
checkApi();
|
||||
await reloadDBAPI(w.externalAPI.devUrl, "dev");
|
||||
} else {
|
||||
p.site.api_url = w.externalAPI.prodUrl;
|
||||
checkApi();
|
||||
await reloadDBAPI(w.externalAPI.prodUrl, "dev");
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ import { formatDistance } from "date-fns/esm";
|
|||
import trim from "lodash.trim";
|
||||
import { useEffect } from "react";
|
||||
import { deepClone, useGlobal, useLocal } from "web-utils";
|
||||
import { createAPI } from "../../../../../../utils/script/init-api";
|
||||
import { AutoHeightTextarea } from "../../../../../../utils/ui/auto-textarea";
|
||||
import { EditorGlobal } from "../../../../logic/global";
|
||||
import { apiProxy } from "../../../../../../base/load/api/api-proxy";
|
||||
|
||||
const server = {
|
||||
status: "ready" as
|
||||
|
|
@ -40,7 +40,7 @@ export const ExternalDeploy = () => {
|
|||
try {
|
||||
const url = p.site.api_url;
|
||||
|
||||
local.api = createAPI(url);
|
||||
local.api = apiProxy(url);
|
||||
let res = await local.api._deploy({
|
||||
type: "check",
|
||||
id_site: p.site.id,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import trim from "lodash.trim";
|
|||
import { EditorGlobal } from "../../../../logic/global";
|
||||
import { Loading } from "../../../../../../utils/ui/loading";
|
||||
import { w } from "../../../../../../utils/types/general";
|
||||
import { reloadDBAPI } from "../../../../../../utils/script/init-api";
|
||||
|
||||
export const InternalAPI: FC<{
|
||||
close: () => void;
|
||||
|
|
@ -178,10 +177,6 @@ export const InternalAPI: FC<{
|
|||
config.api_url = `https://${p.site.api_prasi.port}.prasi.world`;
|
||||
|
||||
const base = trim(config.api_url, "/");
|
||||
|
||||
try {
|
||||
await reloadDBAPI(base);
|
||||
} catch (e) {}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
|
|
@ -198,16 +193,7 @@ export const InternalAPI: FC<{
|
|||
|
||||
<div
|
||||
className={cx("cursor-pointer hover:underline")}
|
||||
onClick={async () => {
|
||||
local.clearingCache = true;
|
||||
local.render();
|
||||
try {
|
||||
await reloadDBAPI(p.site.api_url, "dev");
|
||||
} catch (e) {}
|
||||
local.clearingCache = false;
|
||||
local.render();
|
||||
alert("API Cache Cleared");
|
||||
}}
|
||||
onClick={async () => {}}
|
||||
>
|
||||
{local.clearingCache ? "Clearing Cache..." : "Clear API Cache"}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { createRouter } from "radix3";
|
||||
import { validate } from "uuid";
|
||||
import { type apiClient } from "web-utils";
|
||||
import { createAPI, createDB, initApi } from "../../../utils/script/init-api";
|
||||
import { apiProxy } from "../../../base/load/api/api-proxy";
|
||||
import { dbProxy } from "../../../base/load/db/db-proxy";
|
||||
import importModule from "../../editor/tools/dynamic-import";
|
||||
import { LSite, PG } from "./global";
|
||||
import { validateLayout } from "./layout";
|
||||
|
|
@ -17,7 +17,6 @@ export const w = window as unknown as {
|
|||
isDesktop: boolean;
|
||||
exports: any;
|
||||
params: any;
|
||||
apiClient: typeof apiClient;
|
||||
apiurl: string;
|
||||
preload: (path: string) => void;
|
||||
mobile?: ReturnType<typeof registerMobile>;
|
||||
|
|
@ -94,7 +93,7 @@ export const initLive = async (p: PG, domain_or_siteid: string) => {
|
|||
|
||||
await validateLayout(p);
|
||||
|
||||
p.site.api_url = await initApi(site.config, "prod");
|
||||
p.site.api_url = site.config.api_url || "";
|
||||
|
||||
w.apiurl = p.site.api_url;
|
||||
|
||||
|
|
@ -104,8 +103,8 @@ export const initLive = async (p: PG, domain_or_siteid: string) => {
|
|||
const exec = (fn: string, scopes: any) => {
|
||||
if (p) {
|
||||
if (p.site.api_url) {
|
||||
scopes["api"] = createAPI(p.site.api_url);
|
||||
scopes["db"] = createDB(p.site.api_url);
|
||||
scopes["api"] = apiProxy(p.site.api_url);
|
||||
scopes["db"] = dbProxy(p.site.api_url);
|
||||
}
|
||||
if (!w.params) {
|
||||
w.params = {};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { w } from "../../../utils/script/init-api";
|
||||
import { w } from "../../../utils/types/general";
|
||||
import { PG } from "./global";
|
||||
|
||||
type NOTIF_ARG = {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { FC } from "react";
|
||||
import { createAPI, createDB } from "../../../utils/script/init-api";
|
||||
import { apiProxy } from "../../../base/load/api/api-proxy";
|
||||
import { dbProxy } from "../../../base/load/db/db-proxy";
|
||||
import { FNCompDef } from "../../../utils/types/meta-fn";
|
||||
import { LItem } from "../elements/l-item";
|
||||
import { PG } from "./global";
|
||||
|
|
@ -19,8 +20,8 @@ export const treePropEval = (
|
|||
|
||||
if (meta.item.type === "item" && meta.item.component) {
|
||||
if (p.site.api_url) {
|
||||
if (!p.script.db) p.script.db = createDB(p.site.api_url);
|
||||
if (!p.script.api) p.script.api = createAPI(p.site.api_url);
|
||||
if (!p.script.db) p.script.db = dbProxy(p.site.api_url);
|
||||
if (!p.script.api) p.script.api = apiProxy(p.site.api_url);
|
||||
}
|
||||
|
||||
const props = meta.item.component.props;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import hash_sum from "hash-sum";
|
||||
import { FC, ReactNode, Suspense, useEffect, useState } from "react";
|
||||
import { deepClone } from "web-utils";
|
||||
import { createAPI, createDB } from "../../../utils/script/init-api";
|
||||
import { apiProxy } from "../../../base/load/api/api-proxy";
|
||||
import { dbProxy } from "../../../base/load/db/db-proxy";
|
||||
import { ErrorBox } from "../../editor/elements/e-error";
|
||||
import { ItemMeta, PG } from "./global";
|
||||
import { extractNavigate, preload } from "./route";
|
||||
import hash_sum from "hash-sum";
|
||||
|
||||
export const JS_DEBUG = false;
|
||||
|
||||
|
|
@ -43,8 +44,8 @@ export const treeScopeEval = (
|
|||
|
||||
// prepare args
|
||||
if (p.site.api_url) {
|
||||
if (!p.script.db) p.script.db = createDB(p.site.api_url);
|
||||
if (!p.script.api) p.script.api = createAPI(p.site.api_url);
|
||||
if (!p.script.db) p.script.db = dbProxy(p.site.api_url);
|
||||
if (!p.script.api) p.script.api = apiProxy(p.site.api_url);
|
||||
}
|
||||
const w = window as any;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { w } from "../../utils/script/init-api";
|
||||
import { w } from "../../utils/types/general";
|
||||
import { Loader } from "../live/logic/global";
|
||||
|
||||
const cache = {
|
||||
|
|
@ -55,7 +55,7 @@ export const mobileLoader: Loader = {
|
|||
};
|
||||
|
||||
const load = async (url: string) => {
|
||||
const res = await fetch(`${w.mobilepath}${url}`);
|
||||
const res = await fetch(`${(w as any).mobilepath}${url}`);
|
||||
try {
|
||||
const text = await res.text();
|
||||
const json = JSON.parse(text);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { w } from "../../utils/script/init-api";
|
||||
import { w } from "../../utils/types/general";
|
||||
import { Loader } from "../live/logic/global";
|
||||
|
||||
const base = `/_web/${(window as any).id_site}`;
|
||||
|
|
|
|||
|
|
@ -1,154 +0,0 @@
|
|||
import { createStore, get, set } from "idb-keyval";
|
||||
import trim from "lodash.trim";
|
||||
import { apiClient, dbClient, waitUntil } from "web-utils";
|
||||
import { createFrameCors } from "web-utils";
|
||||
export const w = window as unknown as {
|
||||
prasiApi: Record<string, any>;
|
||||
apiHeaders: any;
|
||||
apiClient: typeof apiClient;
|
||||
dbClient: typeof dbClient;
|
||||
serverurl: string;
|
||||
apiurl: string;
|
||||
mobilepath: string;
|
||||
};
|
||||
|
||||
export const createAPI = (url: string) => {
|
||||
if (!w.apiClient) {
|
||||
w.apiClient = apiClient;
|
||||
}
|
||||
|
||||
if (!w.prasiApi) {
|
||||
w.prasiApi = {};
|
||||
}
|
||||
if (!url) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return w.apiClient(w.prasiApi[url]?.apiEntry, url);
|
||||
};
|
||||
|
||||
export const createDB = (url: string) => {
|
||||
if (!w.dbClient) {
|
||||
w.dbClient = dbClient;
|
||||
}
|
||||
|
||||
const dbc: typeof dbClient = w.dbClient;
|
||||
return dbc("db", url);
|
||||
};
|
||||
|
||||
export const initApi = async (config: any, mode: "dev" | "prod" = "dev") => {
|
||||
let url = "";
|
||||
if (config.prasi) {
|
||||
if (
|
||||
!(
|
||||
location.hostname === "prasi.app" ||
|
||||
location.hostname === "api.prasi.app"
|
||||
) // android localhost
|
||||
) {
|
||||
if (
|
||||
location.hostname === "localhost" ||
|
||||
location.hostname === "127.0.0.1" ||
|
||||
location.hostname === "10.0.2.2"
|
||||
) {
|
||||
url = `https://${config.prasi.port}.prasi.world`;
|
||||
} else {
|
||||
url = `https://${location.hostname}:${config.prasi.port}`;
|
||||
}
|
||||
} else {
|
||||
url = `https://${config.prasi.port}.prasi.world`;
|
||||
}
|
||||
} else if (config.api_url) {
|
||||
url = config.api_url;
|
||||
}
|
||||
if (!w.prasiApi) {
|
||||
w.prasiApi = {};
|
||||
}
|
||||
if (url) {
|
||||
if (!w.prasiApi[url]) {
|
||||
try {
|
||||
await reloadDBAPI(url, mode);
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
return url;
|
||||
};
|
||||
|
||||
const loadText = async (url: string, v2?: boolean) => {
|
||||
const res = await fetch(url);
|
||||
return await res.text();
|
||||
};
|
||||
|
||||
export const reloadDBAPI = async (
|
||||
url: string,
|
||||
mode: "dev" | "prod" = "dev"
|
||||
) => {
|
||||
const base = trim(url, "/");
|
||||
|
||||
if (!w.prasiApi) {
|
||||
w.prasiApi = {};
|
||||
}
|
||||
|
||||
const cache = createStore(`prasi-api`, "config");
|
||||
|
||||
const forceReload = async () => {
|
||||
if (!w.prasiApi[url]) {
|
||||
w.prasiApi[url] = {};
|
||||
}
|
||||
const frm = await createFrameCors(base);
|
||||
const raw = await frm.sendRaw(`/_prasi/_`);
|
||||
let ver = "";
|
||||
if (raw && (raw as any).prasi) {
|
||||
ver = (raw as any).prasi;
|
||||
}
|
||||
|
||||
if (ver === "v2") {
|
||||
await new Promise<void>((done) => {
|
||||
const d = document;
|
||||
const script = d.createElement("script");
|
||||
script.onload = async () => {
|
||||
done();
|
||||
};
|
||||
script.src = `${base}/_prasi/load.js?url=${url}${
|
||||
mode === "dev" ? "&dev=1" : ""
|
||||
}`;
|
||||
d.body.appendChild(script);
|
||||
});
|
||||
} else {
|
||||
const apiTypes = await fetch(base + "/_prasi/api-types");
|
||||
const apiEntry = await fetch(base + "/_prasi/api-entry");
|
||||
w.prasiApi[url] = {
|
||||
apiEntry: (await apiEntry.json()).srv,
|
||||
prismaTypes: {
|
||||
"prisma.d.ts": await loadText(`${base}/_prasi/prisma/index.d.ts`),
|
||||
"runtime/index.d.ts": await loadText(
|
||||
`${base}/_prasi/prisma/runtime/index.d.ts`
|
||||
),
|
||||
"runtime/library.d.ts": await loadText(
|
||||
`${base}/_prasi/prisma/runtime/library.d.ts`
|
||||
),
|
||||
},
|
||||
apiTypes: await apiTypes.text(),
|
||||
};
|
||||
}
|
||||
|
||||
await set(url, JSON.stringify(w.prasiApi[url]), cache);
|
||||
};
|
||||
const prasiBase = `${location.protocol}//${location.host}`;
|
||||
|
||||
try {
|
||||
const found = await get(url, cache);
|
||||
if (found) {
|
||||
w.prasiApi[url] = JSON.parse(found);
|
||||
await forceReload();
|
||||
} else {
|
||||
await forceReload();
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn("Failed to load API");
|
||||
|
||||
if (url === prasiBase) {
|
||||
console.error("Failed to load prasi. Reloading...");
|
||||
setTimeout(() => location.reload(), 3000);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -12,12 +12,12 @@ export type PageProps = {
|
|||
|
||||
export type PrasiAPI = {
|
||||
apiEntry: any;
|
||||
prismaTypes: {
|
||||
prismaTypes?: {
|
||||
"prisma.d.ts": string;
|
||||
"runtime/library.d.ts": string;
|
||||
"runtime/index.d.ts": string;
|
||||
};
|
||||
apiTypes: string;
|
||||
apiTypes?: string;
|
||||
};
|
||||
|
||||
export const w = window as unknown as {
|
||||
|
|
@ -32,6 +32,7 @@ export const w = window as unknown as {
|
|||
editorGlbDefault: string;
|
||||
ts: number;
|
||||
serverurl: string;
|
||||
apiurl: string;
|
||||
api: any;
|
||||
db: any;
|
||||
offline: boolean;
|
||||
|
|
|
|||
|
|
@ -1,21 +0,0 @@
|
|||
import { apiContext } from "../server/api/api-ctx";
|
||||
import { g } from "../utils/global";
|
||||
|
||||
export const _ = {
|
||||
url: "/_api_frm",
|
||||
async api() {
|
||||
const { req, res } = apiContext(this);
|
||||
let allowUrl = req.headers.get("origin") || req.headers.get("referer");
|
||||
|
||||
res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT");
|
||||
res.setHeader("Access-Control-Allow-Headers", "content-type");
|
||||
res.setHeader("Access-Control-Allow-Credentials", "true");
|
||||
if (allowUrl) {
|
||||
res.setHeader("Access-Control-Allow-Origin", allowUrl);
|
||||
}
|
||||
|
||||
res.setHeader("content-type", "text/html");
|
||||
res.setHeader("etag", g.frm.etag);
|
||||
res.send(`<script>${g.frm.js}</script>`);
|
||||
},
|
||||
};
|
||||
|
|
@ -2,8 +2,8 @@ import { apiContext } from "../server/api/api-ctx";
|
|||
import { DBArg, execQuery } from "../utils/query";
|
||||
|
||||
export const _ = {
|
||||
url: "/_dbs/:dbName/:action",
|
||||
async api(dbName: any, action?: string) {
|
||||
url: "/_dbs/:action",
|
||||
async api(action?: string) {
|
||||
const { req, res } = apiContext(this);
|
||||
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { createRouter } from "radix3";
|
||||
import { g } from "utils/global";
|
||||
import { createResponse } from "./api/api-ctx";
|
||||
import { prepareApiRoutes } from "./api/api-scan";
|
||||
|
||||
export const serveAPI = {
|
||||
init: async () => {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ export const serveStatic = {
|
|||
if (filename) {
|
||||
const path = join("static", filename);
|
||||
const file = Bun.file(dir.path(`app/${path}`));
|
||||
console.log(_, filename);
|
||||
if (await file.exists()) {
|
||||
cache.static[`/${filename}`] = {
|
||||
type: mime.getType(path) || "application/octet-stream",
|
||||
|
|
|
|||
|
|
@ -1,205 +0,0 @@
|
|||
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 (
|
||||
rawUrl: string,
|
||||
params: any,
|
||||
parentWindow?: any
|
||||
) => {
|
||||
let w: any = typeof window === "object" ? window : globalThis;
|
||||
|
||||
const win = parentWindow || w;
|
||||
const url = new URL(rawUrl);
|
||||
let frm: Awaited<ReturnType<typeof createFrameCors>>;
|
||||
|
||||
const base = `${url.protocol}//${url.host}`;
|
||||
|
||||
if (!win.frmapi) {
|
||||
win.frmapi = {};
|
||||
}
|
||||
if (!win.frmapi[base]) {
|
||||
win.frmapi[base] = await createFrameCors(base, win);
|
||||
}
|
||||
|
||||
frm = win.frmapi[base];
|
||||
|
||||
if (!win.apiHeaders) {
|
||||
win.apiHeaders = {};
|
||||
}
|
||||
|
||||
if (!frm) {
|
||||
await waitUntil(() => {
|
||||
frm = win.frmapi[base];
|
||||
return frm;
|
||||
});
|
||||
}
|
||||
|
||||
if (url.pathname.startsWith("//")) {
|
||||
url.pathname = url.pathname.substring(1);
|
||||
}
|
||||
|
||||
return await frm.send(url.pathname, params, win.apiHeaders);
|
||||
};
|
||||
|
|
@ -7,7 +7,4 @@ 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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue