fix
This commit is contained in:
parent
415f42cefc
commit
3cb7c393ec
|
|
@ -1,15 +1,19 @@
|
|||
import { Websocket } from "hyper-express";
|
||||
import { ServerWebSocket } from "bun";
|
||||
import { compress } from "lz-string";
|
||||
import { syncronize } from "y-pojo";
|
||||
import * as Y from "yjs";
|
||||
import { WSData } from "../../../../../pkgs/core/server/create";
|
||||
import { SingleComp, eg } from "../edit-global";
|
||||
import {
|
||||
WS_MSG_GET_COMP,
|
||||
WS_MSG_SET_COMP,
|
||||
WS_MSG_SV_LOCAL,
|
||||
} from "../../../web/src/utils/types/ws";
|
||||
import { SingleComp, eg } from "../edit-global";
|
||||
} from "../../../../web/src/utils/types/ws";
|
||||
|
||||
export const getComp = async (ws: Websocket, msg: WS_MSG_GET_COMP) => {
|
||||
export const getComp = async (
|
||||
ws: ServerWebSocket<WSData>,
|
||||
msg: WS_MSG_GET_COMP
|
||||
) => {
|
||||
const comp_id = msg.comp_id;
|
||||
|
||||
if (!eg.edit.comp[comp_id]) {
|
||||
|
|
@ -17,6 +21,15 @@ export const getComp = async (ws: Websocket, msg: WS_MSG_GET_COMP) => {
|
|||
where: {
|
||||
id: comp_id,
|
||||
},
|
||||
select: {
|
||||
component_group: true,
|
||||
content_tree: true,
|
||||
id: true,
|
||||
id_component_group: true,
|
||||
name: true,
|
||||
props: true,
|
||||
type: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!rawComp) {
|
||||
|
|
@ -34,7 +47,7 @@ export const getComp = async (ws: Websocket, msg: WS_MSG_GET_COMP) => {
|
|||
const map = ydoc.getMap("map");
|
||||
syncronize(map as any, rawComp);
|
||||
|
||||
const ws = new Set<Websocket>();
|
||||
const ws = new Set<ServerWebSocket<WSData>>();
|
||||
const um = new Y.UndoManager(map, { ignoreRemoteMapChanges: true });
|
||||
const broadcast = () => {
|
||||
const sv_local = compress(Y.encodeStateVector(ydoc as any).toString());
|
||||
|
|
|
|||
|
|
@ -1,54 +0,0 @@
|
|||
import { Websocket } from "hyper-express";
|
||||
import { syncronize } from "y-pojo";
|
||||
import * as Y from "yjs";
|
||||
import { fillID } from "../../../web/src/utils/page/tools/fill-id";
|
||||
import { IContent, MContent } from "../../../web/src/utils/types/general";
|
||||
import { IItem } from "../../../web/src/utils/types/item";
|
||||
import { IRoot } from "../../../web/src/utils/types/root";
|
||||
import { getComp } from "../action/get-comp";
|
||||
import { eg } from "../edit-global";
|
||||
|
||||
const MAX_STRING_LENGTH = 15000;
|
||||
export const validateTreeMap = async (
|
||||
ws: Websocket,
|
||||
item: MContent,
|
||||
changed?: boolean
|
||||
) => {
|
||||
let _changed = changed;
|
||||
const type = item.get("type") as IContent["type"] | "root";
|
||||
if (type !== "root") {
|
||||
item.forEach((val, key, map) => {
|
||||
if (typeof val === "string") {
|
||||
if (val.length > MAX_STRING_LENGTH) {
|
||||
map.set(key, "");
|
||||
_changed = true;
|
||||
}
|
||||
} else {
|
||||
if (typeof val === "object" && val instanceof Y.Map) {
|
||||
val._map.forEach((ival, ikey, imap) => {
|
||||
if (typeof ival === "string") {
|
||||
if ((ival as string).length > MAX_STRING_LENGTH) {
|
||||
imap.set(ikey, "" as any);
|
||||
_changed = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (item) {
|
||||
if (type !== "text") {
|
||||
const childs = item.get("childs");
|
||||
if (childs) {
|
||||
for (const c of childs) {
|
||||
if (await validateTreeMap(ws, c)) {
|
||||
_changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return !!_changed;
|
||||
};
|
||||
|
|
@ -1,19 +1,19 @@
|
|||
import { Suspense, lazy, useEffect } from "react";
|
||||
import { page, useLocal } from "web-utils";
|
||||
import { FC, useEffect } from "react";
|
||||
import { page, useGlobal, useLocal } from "web-utils";
|
||||
import { EditorGlobal } from "../../render/editor/logic/global";
|
||||
import { Loading } from "../../utils/ui/loading";
|
||||
|
||||
const Editor = lazy(async () => ({
|
||||
default: (await import("../../render/editor/editor")).Editor,
|
||||
}));
|
||||
|
||||
export default page({
|
||||
url: "/editor/:site_id/:page_id",
|
||||
component: ({}) => {
|
||||
const p = useGlobal(EditorGlobal, "EDITOR");
|
||||
|
||||
const local = useLocal({
|
||||
loading: true,
|
||||
session: null as any,
|
||||
notfound: false,
|
||||
init: false,
|
||||
Editor: null as null | FC<any>,
|
||||
});
|
||||
const site_id = params.site_id === "_" ? "" : params.site_id;
|
||||
const page_id = params.page_id === "_" ? "" : params.page_id;
|
||||
|
|
@ -21,6 +21,10 @@ export default page({
|
|||
useEffect(() => {
|
||||
if (!local.init) {
|
||||
(async () => {
|
||||
if (!local.Editor) {
|
||||
local.Editor = (await import("../../render/editor/editor")).Editor;
|
||||
}
|
||||
|
||||
let ses: any = null;
|
||||
try {
|
||||
ses = JSON.parse(localStorage.getItem("prasi-session") || "");
|
||||
|
|
@ -129,12 +133,11 @@ export default page({
|
|||
}
|
||||
}, [local.init]);
|
||||
|
||||
if (local.loading) return <Loading note="base-page" />;
|
||||
const Editor = local.Editor;
|
||||
if (local.loading || !Editor) return <Loading note="base-page" />;
|
||||
|
||||
return (
|
||||
<Suspense fallback={<Loading note="editor-init" />}>
|
||||
<Editor session={local.session} site_id={site_id} page_id={page_id} />
|
||||
</Suspense>
|
||||
<Editor session={local.session} site_id={site_id} page_id={page_id} />
|
||||
);
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ export const Root: FC<{}> = ({}) => {
|
|||
);
|
||||
|
||||
prasiContext.render = local.render;
|
||||
|
||||
const Provider = GlobalContext.Provider as FC<{ value: any; children: any }>;
|
||||
|
||||
const found = local.router.lookup(location.pathname);
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ export const Editor: FC<{ site_id: string; page_id: string; session: any }> = ({
|
|||
useEffect(() => {
|
||||
if (p.status !== "init" && w.prasiApi) {
|
||||
for (const [k, v] of Object.entries(deepClone(EditorGlobal))) {
|
||||
if (k === "session" || k === "site") continue;
|
||||
if (k === "session" || k === "site" || "status") continue;
|
||||
(p as any)[k] = v;
|
||||
}
|
||||
|
||||
|
|
@ -99,6 +99,7 @@ export const Editor: FC<{ site_id: string; page_id: string; session: any }> = ({
|
|||
}
|
||||
|
||||
if (p.status === "init") {
|
||||
(window as any).mok = ((window as any).mok || 0) + 1;
|
||||
p.ui.loading = <Loading note="load-page" />;
|
||||
p.ui.preload = <Loading note="preload-root" backdrop={false} />;
|
||||
p.ui.notfound = (
|
||||
|
|
@ -109,6 +110,7 @@ export const Editor: FC<{ site_id: string; page_id: string; session: any }> = ({
|
|||
PREVIEW ERROR
|
||||
</div>
|
||||
);
|
||||
p.status = "loading";
|
||||
initEditor(p, site_id);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,119 +32,119 @@ export const w = window as unknown as {
|
|||
};
|
||||
|
||||
export const initEditor = async (p: PG, site_id: string) => {
|
||||
if (p.status === "init") {
|
||||
p.status = "loading";
|
||||
|
||||
w.isEditor = true;
|
||||
if (typeof w.isLayout === "undefined") {
|
||||
w.isLayout = false;
|
||||
}
|
||||
w.isMobile = p.mode === "mobile";
|
||||
w.isDesktop = p.mode === "desktop";
|
||||
w.apiHeaders = {};
|
||||
w.preload = () => {};
|
||||
w.isEditor = true;
|
||||
if (typeof w.isLayout === "undefined") {
|
||||
w.isLayout = false;
|
||||
}
|
||||
w.isMobile = p.mode === "mobile";
|
||||
w.isDesktop = p.mode === "desktop";
|
||||
w.apiHeaders = {};
|
||||
w.preload = () => {};
|
||||
|
||||
w.navigateOverride = (_href) => {
|
||||
if (_href.startsWith("/ed")) return _href;
|
||||
return "";
|
||||
};
|
||||
w.navigateOverride = (_href) => {
|
||||
if (_href.startsWith("/ed")) return _href;
|
||||
return "";
|
||||
};
|
||||
|
||||
p.item.active = localStorage.getItem("prasi-item-active-id") || "";
|
||||
p.item.activeOriginalId =
|
||||
localStorage.getItem("prasi-item-active-oid") || "";
|
||||
const comp: any = {
|
||||
id: localStorage.getItem("prasi-comp-active-id"),
|
||||
instance_id: localStorage.getItem("prasi-comp-instance-id"),
|
||||
last: localStorage.getItem("prasi-comp-active-last"),
|
||||
props: localStorage.getItem("prasi-comp-active-props"),
|
||||
};
|
||||
if (comp.last) {
|
||||
comp.last = JSON.parse(comp.last);
|
||||
p.item.active = localStorage.getItem("prasi-item-active-id") || "";
|
||||
p.item.activeOriginalId = localStorage.getItem("prasi-item-active-oid") || "";
|
||||
const comp: any = {
|
||||
id: localStorage.getItem("prasi-comp-active-id"),
|
||||
instance_id: localStorage.getItem("prasi-comp-instance-id"),
|
||||
last: localStorage.getItem("prasi-comp-active-last"),
|
||||
props: localStorage.getItem("prasi-comp-active-props"),
|
||||
};
|
||||
if (comp.last) {
|
||||
comp.last = JSON.parse(comp.last);
|
||||
}
|
||||
if (comp.props) {
|
||||
comp.props = JSON.parse(comp.props);
|
||||
}
|
||||
if (comp.id) {
|
||||
p.comp = comp;
|
||||
}
|
||||
|
||||
let site = null as any;
|
||||
try {
|
||||
site = JSON.parse(localStorage.getItem(`prasi-site-${site_id}`) || "");
|
||||
} catch (e) {}
|
||||
|
||||
const querySite = async () => {
|
||||
const site = await defaultLoader.site(p as any, { id: site_id });
|
||||
|
||||
localStorage.setItem(`prasi-site-${site_id}`, JSON.stringify(site));
|
||||
return site;
|
||||
};
|
||||
const processSite = async (site: LSite) => {
|
||||
if (!w.exports) {
|
||||
w.exports = {};
|
||||
}
|
||||
if (comp.props) {
|
||||
comp.props = JSON.parse(comp.props);
|
||||
}
|
||||
if (comp.id) {
|
||||
p.comp = comp;
|
||||
if (site.cgroup_ids) {
|
||||
for (const id of site.cgroup_ids) {
|
||||
await importModule(`${serverurl}/npm/site/${id}/site.js`);
|
||||
}
|
||||
}
|
||||
|
||||
let site = null as any;
|
||||
try {
|
||||
site = JSON.parse(localStorage.getItem(`prasi-site-${site_id}`) || "");
|
||||
} catch (e) {}
|
||||
await importModule(`${serverurl}/npm/site/${site.id}/site.js`);
|
||||
p.lsite = site;
|
||||
p.site.id = site.id;
|
||||
p.site.js = site.js || "";
|
||||
p.site.js_compiled = site.js_compiled || "";
|
||||
p.site.name = site.name;
|
||||
p.site.domain = site.domain;
|
||||
p.site.responsive = site.responsive as any;
|
||||
p.site.layout = site.layout;
|
||||
p.site.layout_id = site.layout_id;
|
||||
|
||||
const querySite = async () => {
|
||||
const site = await defaultLoader.site(p as any, { id: site_id });
|
||||
localStorage.setItem(`prasi-site-${site_id}`, JSON.stringify(site));
|
||||
return site;
|
||||
await validateLayout(p);
|
||||
|
||||
w.externalAPI = {
|
||||
mode: (localStorage.getItem(`prasi-ext-api-mode-${p.site.id}`) ||
|
||||
"prod") as any,
|
||||
devUrl: localStorage.getItem(`prasi-ext-dev-url-${p.site.id}`) || "",
|
||||
prodUrl: localStorage.getItem(`prasi-ext-prod-url-${p.site.id}`) || "",
|
||||
};
|
||||
const processSite = async (site: LSite) => {
|
||||
if (!w.exports) {
|
||||
w.exports = {};
|
||||
}
|
||||
if (site.cgroup_ids) {
|
||||
for (const id of site.cgroup_ids) {
|
||||
await importModule(`${serverurl}/npm/site/${id}/site.js`);
|
||||
}
|
||||
}
|
||||
|
||||
await importModule(`${serverurl}/npm/site/${site.id}/site.js`);
|
||||
p.lsite = site;
|
||||
p.site.id = site.id;
|
||||
p.site.js = site.js || "";
|
||||
p.site.js_compiled = site.js_compiled || "";
|
||||
p.site.name = site.name;
|
||||
p.site.domain = site.domain;
|
||||
p.site.responsive = site.responsive as any;
|
||||
p.site.layout = site.layout;
|
||||
p.site.layout_id = site.layout_id;
|
||||
p.site.api_url = await initApi(site.config);
|
||||
|
||||
await validateLayout(p);
|
||||
if (w.externalAPI.prodUrl !== p.site.api_url) {
|
||||
w.externalAPI.prodUrl = p.site.api_url;
|
||||
localStorage.setItem(`prasi-ext-prod-url-${p.site.id}`, p.site.api_url);
|
||||
}
|
||||
if (w.externalAPI.mode === "dev" && w.externalAPI.devUrl) {
|
||||
p.site.api_url = w.externalAPI.devUrl;
|
||||
await reloadDBAPI(w.externalAPI.devUrl);
|
||||
}
|
||||
|
||||
w.externalAPI = {
|
||||
mode: (localStorage.getItem(`prasi-ext-api-mode-${p.site.id}`) ||
|
||||
"prod") as any,
|
||||
devUrl: localStorage.getItem(`prasi-ext-dev-url-${p.site.id}`) || "",
|
||||
prodUrl: localStorage.getItem(`prasi-ext-prod-url-${p.site.id}`) || "",
|
||||
};
|
||||
w.apiurl = p.site.api_url;
|
||||
api.site_dts(p.site.id).then((e: any) => {
|
||||
p.site_dts = e || "";
|
||||
p.render();
|
||||
});
|
||||
const configLocal: any = get(site, "config.prasi");
|
||||
if (configLocal) {
|
||||
p.site.api_prasi.db = configLocal.dburl ? configLocal.dburl : "";
|
||||
p.site.api_prasi.port = configLocal.port ? configLocal.port : "";
|
||||
}
|
||||
execSiteJS(p);
|
||||
};
|
||||
|
||||
p.site.api_url = await initApi(site.config);
|
||||
|
||||
if (w.externalAPI.prodUrl !== p.site.api_url) {
|
||||
w.externalAPI.prodUrl = p.site.api_url;
|
||||
localStorage.setItem(`prasi-ext-prod-url-${p.site.id}`, p.site.api_url);
|
||||
}
|
||||
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;
|
||||
api.site_dts(p.site.id).then((e) => {
|
||||
p.site_dts = e || "";
|
||||
p.render();
|
||||
});
|
||||
const configLocal: any = get(site, "config.prasi");
|
||||
if (configLocal) {
|
||||
p.site.api_prasi.db = configLocal.dburl ? configLocal.dburl : "";
|
||||
p.site.api_prasi.port = configLocal.port ? configLocal.port : "";
|
||||
}
|
||||
execSiteJS(p);
|
||||
};
|
||||
if (!site || (site && !site.id)) {
|
||||
const site = await querySite();
|
||||
if (!site || (site && !site.id)) {
|
||||
const site = await querySite();
|
||||
if (site) {
|
||||
await processSite(site);
|
||||
} else {
|
||||
await processSite(site);
|
||||
querySite();
|
||||
}
|
||||
} else {
|
||||
await processSite(site);
|
||||
querySite();
|
||||
}
|
||||
|
||||
p.status = "ready";
|
||||
p.render();
|
||||
p.status = "ready";
|
||||
p.render();
|
||||
|
||||
if (!jscript.build) {
|
||||
jscript.init();
|
||||
}
|
||||
if (!jscript.build) {
|
||||
jscript.init();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,10 @@ export const defaultLoader: Loader = {
|
|||
},
|
||||
})) as unknown as LSite;
|
||||
|
||||
if (!site) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const cgroups = await db.site_use_comp.findMany({
|
||||
where: { id_site: site.id },
|
||||
select: { use_id_site: true },
|
||||
|
|
|
|||
|
|
@ -83,9 +83,8 @@ export const liveWS = async (p: PG) => {
|
|||
|
||||
console.clear();
|
||||
console.log(
|
||||
`🔥 Page updated: ${
|
||||
p.page?.url
|
||||
} ${new Date().toLocaleString()}`
|
||||
`🔥 Page updated: ${p.page
|
||||
?.url} ${new Date().toLocaleString()}`
|
||||
);
|
||||
}
|
||||
})
|
||||
|
|
@ -179,49 +178,6 @@ export const liveWS = async (p: PG) => {
|
|||
}
|
||||
}
|
||||
break;
|
||||
case "sitejs_reload":
|
||||
if (msg.js) {
|
||||
p.site.js = msg.js;
|
||||
|
||||
const exec = (fn: string, scopes: any) => {
|
||||
if (p) {
|
||||
if (!p.script.api) p.script.api = createAPI(p.site.api_url);
|
||||
if (!p.script.db) p.script.db = createDB(p.site.api_url);
|
||||
|
||||
scopes["db"] = p.script.db;
|
||||
scopes["api"] = p.script.api;
|
||||
const f = new Function(...Object.keys(scopes), fn);
|
||||
const res = f(...Object.values(scopes));
|
||||
return res;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
const w = window as any;
|
||||
const scope = {
|
||||
types: {},
|
||||
exports: w.exports,
|
||||
load: importModule,
|
||||
render: p.render,
|
||||
module: {
|
||||
exports: {} as any,
|
||||
},
|
||||
};
|
||||
|
||||
p.status = "init";
|
||||
console.log(
|
||||
`🔥 Site JS Reloaded: ${new Date().toLocaleString()}`
|
||||
);
|
||||
exec(p.site.js, scope);
|
||||
|
||||
if (scope.module.exports) {
|
||||
for (const [k, v] of Object.entries(scope.module.exports)) {
|
||||
w.exports[k] = v;
|
||||
}
|
||||
}
|
||||
|
||||
p.render();
|
||||
}
|
||||
break;
|
||||
case "undo":
|
||||
case "redo":
|
||||
case "new_comp":
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { dir } from "./dir";
|
|||
import { g } from "./global";
|
||||
import { spawn } from "bun";
|
||||
|
||||
const decoder = new TextDecoder();
|
||||
export const parcelBuild = async () => {
|
||||
await dirAsync("app/static");
|
||||
const args = [
|
||||
|
|
@ -20,53 +21,60 @@ export const parcelBuild = async () => {
|
|||
await removeAsync(dir.path("app/web/.parcel-cache"));
|
||||
|
||||
const parcel = spawn({
|
||||
cmd: args,
|
||||
cmd: args,
|
||||
cwd: dir.path("app/web"),
|
||||
stdio: ["ignore", "inherit", "inherit"],
|
||||
});
|
||||
await parcel.exited;
|
||||
} else {
|
||||
const parcel = spawn({
|
||||
cmd: args,
|
||||
cwd: dir.path("app/web"),
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
});
|
||||
await new Promise<void>((resolve) => {
|
||||
const parcel = spawn({
|
||||
cmd: args,
|
||||
cwd: dir.path("app/web"),
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
});
|
||||
|
||||
g.parcel = parcel;
|
||||
g.parcel = parcel;
|
||||
|
||||
let output = true;
|
||||
(async () => {
|
||||
if (parcel.stdout) {
|
||||
for await (const chunk of parcel.stdout) {
|
||||
if (output) process.stdout.write(chunk);
|
||||
let output = true;
|
||||
let decoded = false;
|
||||
(async () => {
|
||||
if (parcel.stdout) {
|
||||
for await (const chunk of parcel.stdout) {
|
||||
if (!decoded && decoder.decode(chunk).includes("✨")) {
|
||||
resolve();
|
||||
decoded = true;
|
||||
}
|
||||
if (output) process.stdout.write(chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
})();
|
||||
|
||||
(async () => {
|
||||
if (parcel.stderr) {
|
||||
for await (const chunk of parcel.stderr) {
|
||||
if (output) process.stderr.write(chunk);
|
||||
(async () => {
|
||||
if (parcel.stderr) {
|
||||
for await (const chunk of parcel.stderr) {
|
||||
if (output) process.stderr.write(chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
})();
|
||||
|
||||
const cleanup = async () => {
|
||||
output = false;
|
||||
};
|
||||
const cleanup = async () => {
|
||||
output = false;
|
||||
};
|
||||
|
||||
process.on("SIGINT", async () => {
|
||||
await cleanup();
|
||||
process.exit();
|
||||
});
|
||||
process.on("SIGINT", async () => {
|
||||
await cleanup();
|
||||
process.exit();
|
||||
});
|
||||
|
||||
process.on("SIGTERM", async () => {
|
||||
await cleanup();
|
||||
process.exit();
|
||||
});
|
||||
process.on("SIGTERM", async () => {
|
||||
await cleanup();
|
||||
process.exit();
|
||||
});
|
||||
|
||||
process.on("beforeExit", async () => {
|
||||
await cleanup();
|
||||
process.on("beforeExit", async () => {
|
||||
await cleanup();
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ export const useGlobal = <T extends object>(
|
|||
if (!_id) {
|
||||
_id = "GLOBAL_DEFAULT";
|
||||
}
|
||||
|
||||
const ctx = useContext(GlobalContext);
|
||||
const { global, render } = ctx;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue