This commit is contained in:
Rizky 2023-10-20 19:18:21 +07:00
parent b5273222ba
commit da2cb75001
20 changed files with 142 additions and 40 deletions

View File

@ -1,14 +1,21 @@
import { component, site, page } from "dbgen";
import { ESite } from "../../../web/src/render/ed/logic/ed-global";
/*
WARNING:
CHANGING FUNCTION NAME / OBJECT STRUCTURE
WILL *BREAK* OFFLINE STORAGE --
ONLY ADDITION IS ALLOWED
*/
export type SAction = typeof SyncActions;
export const SyncActions = {
site: {
list: () =>
({}) as Promise<
Record<string, { id: string; name: string; domain: string }>
>,
group: () => ({}) as Promise<Record<string, string[]>>,
load: (id: string) => ({}) as Promise<site>,
list: async () =>
({}) as Record<string, { id: string; name: string; domain: string }>,
group: async () => ({}) as Record<string, string[]>,
load: async (id: string) => ({}) as ESite | undefined,
},
comp: {
list: () => ({}) as Record<string, Exclude<component, "content_tree">>,

View File

@ -1 +1,2 @@
export * from "./site_load";
export * from "./site_group";

View File

@ -0,0 +1,6 @@
import { ActionCtx } from "../type";
export const site_group = async function (this: ActionCtx) {
console.log(this.user);
return "gruop";
};

View File

@ -1,3 +1,23 @@
export const site_load = async () => {
return "moka";
import { validate } from "uuid";
import { ActionCtx } from "../type";
import { ESite } from "../../../../web/src/render/ed/logic/ed-global";
import { SAction } from "../actions";
export const site_load: SAction["site"]["load"] = async function (
this: ActionCtx,
id: string
) {
if (validate(id)) {
const site = await db.site.findFirst({ where: { id } });
if (site) {
return {
id: site.id,
config: site.config as ESite["config"],
domain: site.domain,
js: site.js || "",
js_compiled: site.js_compiled || "",
name: site.name,
};
}
}
};

View File

@ -1,7 +1,7 @@
import { user } from "../user";
export const loadUserConf = async (user_id: string) => {
const conf = user.conf.getOrCreate(user_id);
export const loadDefaultSite = async (user_id: string) => {
const conf = user.conf.get(user_id);
if (conf) {
if (!conf.site_id) {
const site = await db.site.findFirst({

View File

@ -3,16 +3,18 @@ import { ServerWebSocket, WebSocketHandler } from "bun";
import { Packr } from "msgpackr";
import { WSData } from "../../../../pkgs/core/server/create";
import { ClientEvent } from "../../../web/src/utils/sync/client";
import { loadUserConf } from "./editor/load";
import { SyncType } from "./type";
import { loadDefaultSite } from "./editor/load";
import { ActionCtx, SyncType } from "./type";
import { SyncActionPaths } from "./actions-def";
import * as actions from "./actions/index";
import { UserConf, user } from "./user";
const packr = new Packr({ structuredClone: true });
const conns = new Map<
string,
{
user_id: string;
conf?: UserConf & { toJSON: () => UserConf };
ws: ServerWebSocket<WSData>;
msg: {
pending: Record<string, Promise<any>>;
@ -51,18 +53,35 @@ export const syncHandler: WebSocketHandler<WSData> = {
if (msg.type === SyncType.UserID) {
const { user_id } = msg;
conn.user_id = user_id;
const conf = await loadUserConf(user_id);
const conf = user.conf.getOrCreate(user_id);
if (!conf.site_id) {
await loadDefaultSite(user_id);
}
conn.conf = new Proxy(conf, {
get(_, p) {
const conf = user.conf.get(user_id);
if (p === "toJSON") return () => conf;
if (conf) return conf[p as keyof typeof conf];
},
set(_, p, newValue) {
user.conf.set(user_id, p as keyof UserConf, newValue);
return true;
},
}) as UserConf & { toJSON: () => UserConf };
send(ws, {
type: SyncType.Event,
event: "editor_start" as ClientEvent,
data: conf,
data: conn.conf.toJSON(),
});
}
if (msg.type === SyncType.Action) {
const code = msg.code as keyof typeof SyncActionPaths;
const actionName = SyncActionPaths[code].replace(/\./gi, "_");
if (actionName) {
const action = (actions as any)[actionName];
const action = (actions as any)[actionName].bind({
user: { id: conn.user_id, conf: conn.conf },
} as ActionCtx);
ws.sendBinary(
packr.pack({

View File

@ -1,7 +1,12 @@
import { UserConf } from "./user";
export enum SyncType {
ClientID,
UserID,
Event,
Action,
ActionResult,
}
}
export type ActionCtx = {
user: { id: string; conf: UserConf & { toJSON: () => UserConf } };
};

View File

@ -6,7 +6,7 @@ const defaultConf = {
site_id: "",
page_id: "",
};
type UserConf = typeof defaultConf;
export type UserConf = typeof defaultConf;
const db = open<UserConf, string>({
name: "user-conf",
@ -16,12 +16,12 @@ const db = open<UserConf, string>({
export const user = {
conf: {
getOrCreate(user_id: string) {
const res = db.get(user_id);
let res = db.get(user_id);
if (!res) {
db.put(user_id, structuredClone(defaultConf));
return db.get(user_id);
res = db.get(user_id);
}
return res;
return res as UserConf;
},
get(user_id: string) {
return db.get(user_id);

View File

@ -1,5 +1,5 @@
import { page, useGlobal } from "web-utils";
import { EDGlobal } from "../../render/ed/logic/global";
import { EDGlobal } from "../../render/ed/logic/ed-global";
import { clientStartSync } from "../../utils/sync/client";
import { Loading } from "../../utils/ui/loading";
import { Ed } from "../../render/ed/ed";

View File

@ -10,9 +10,23 @@ const start = async () => {
let react = {
root: null as null | ReactRoot,
};
if (!["localhost", "127.0.0.1"].includes(location.hostname)) {
if (true || !["localhost", "127.0.0.1"].includes(location.hostname)) {
const sw = await registerServiceWorker();
const cacheCurrentPage = () => {
const swc = navigator.serviceWorker.controller;
if (swc) {
[location.href, "", "/", "/ed", "/ed/_/_", "/login"].forEach((url) => {
swc.postMessage({
type: "add-cache",
url: url,
});
});
}
};
cacheCurrentPage();
navigator.serviceWorker.addEventListener("message", (e) => {
cacheCurrentPage();
if (react.root) {
if (e.data.type === "offline") {
w.offline = true;
@ -100,7 +114,8 @@ const start = async () => {
className="bg-green-600 text-white px-4 py-2 rounded-full text-sm"
onClick={click}
>
App Updated, Ready to use offline
App Updated{" "}
<span className="opacity-50">{e.data.version}</span>
</div>
</div>
</>

View File

@ -1,12 +1,22 @@
import { useGlobal } from "web-utils";
import { Loading } from "../../utils/ui/loading";
import { EDGlobal } from "./logic/global";
import { edRoute } from "./logic/route";
import { EDGlobal } from "./logic/ed-global";
import { edRoute } from "./logic/ed-route";
export const Ed = () => {
const p = useGlobal(EDGlobal, "EDITOR");
edRoute(p);
return <Loading />;
console.log(p.status);
if (p.status === "loading") {
return <Loading />;
}
if (p.status === "site-not-found" || p.status === "page-not-found") {
return (
<div className="flex fixed inset-0 items-center justify-center">
{p.status === "site-not-found" ? "Site not found" : "Page not found"}
</div>
);
}
return <div>asfa</div>;
};

View File

@ -14,6 +14,12 @@ const EmptyPage = {
};
export const EDGlobal = {
status: "init" as
| "init"
| "loading"
| "site-not-found"
| "page-not-found"
| "ready",
sync: null as unknown as Awaited<ReturnType<typeof clientStartSync>>,
site: EmptySite,
page: EmptyPage,

View File

@ -0,0 +1,21 @@
import { PG } from "./ed-global";
export const edRoute = async (p: PG) => {
if (p.status === "init") {
if (!p.site.domain && !p.site.name) {
p.status = "loading";
const site = await p.sync.site.load(p.site.id);
if (!site) {
p.status = "site-not-found";
p.render();
return;
}
p.site = site;
}
if (p.site) {
console.log(p.site);
}
}
};

View File

@ -1,8 +0,0 @@
import { PG } from "./global";
export const edRoute = async (p: PG) => {
if (!p.site.domain && !p.site.name) {
const res = await p.sync.site.load(p.site.id);
console.log(res);
}
};

View File

@ -8,7 +8,7 @@ import { SyncActionDefinition } from "../../../../srv/ws/sync/actions-def";
import { initIDB } from "./idb";
import { SyncType } from "../../../../srv/ws/sync/type";
import { w } from "../types/general";
import { ESite } from "../../render/ed/logic/global";
import { ESite } from "../../render/ed/logic/ed-global";
const packr = new Packr({ structuredClone: true });
const conf = {
ws: null as null | WebSocket,

View File

@ -3,16 +3,17 @@
"module": "src/index.ts",
"type": "module",
"scripts": {
"dev": "bun clean && bun run --silent --watch ./pkgs/core/index.ts dev",
"dev": "bun run --silent --watch ./pkgs/core/index.ts dev",
"clean": "rm -rf app/static && rm -rf app/web/.parcel-cache",
"build": "bun run --silent ./pkgs/core/build.ts",
"db-pull": "bun run ./pkgs/core/db-pull.ts",
"parcel": "bun clean && bun run ./pkgs/core/parcel.ts",
"prod": "bun run --silent ./pkgs/core/index.ts",
"local-prod": "bun run build && bun run db-pull && bun run ./pkgs/core/index.ts",
"pull": "cd app/db && bun prisma db pull && bun prisma generate",
"pkgs-upgrade": "bun run --silent ./pkgs/core/upgrade.ts"
},
"workspaces": [
"workspaces": [
"app/*",
"pkgs/*"
],

View File

@ -31,7 +31,7 @@ if (g.db) {
g.log.error(`[DB ERROR]\n${e.message}`);
});
}
await syncActionDefinition();
await parcelBuild();
await generateAPIFrm();

View File

@ -3,7 +3,6 @@ import { dirAsync } from "fs-jetpack";
import { dir } from "./dir";
import { g } from "./global";
const decoder = new TextDecoder();
export const parcelBuild = async () => {
await dirAsync("app/static");

Binary file not shown.

Binary file not shown.