diff --git a/app/web/package.json b/app/web/package.json index e4fc94a6..a788c239 100644 --- a/app/web/package.json +++ b/app/web/package.json @@ -16,7 +16,6 @@ "algoliasearch": "^4.20.0", "date-fns": "^2.30.0", "downshift": "^8.2.2", - "emmet-monaco-es": "^5.3.0", "esbuild-wasm": "^0.19.4", "idb-keyval": "^6.2.1", "js-base64": "^3.7.5", @@ -84,8 +83,8 @@ "@types/lodash.set": "^4.3.7", "@types/lodash.trim": "4.5.7", "@types/prettier": "3.0.0", - "@types/react": "18.2.28", - "@types/react-dom": "18.2.13", + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", "@types/tinycolor2": "^1.4.4", "@types/uuid": "9.0.5", "@types/vscode": "^1.83.0", diff --git a/app/web/src/base/page/all.tsx b/app/web/src/base/page/all.tsx index a4dd39ab..4655d4f3 100644 --- a/app/web/src/base/page/all.tsx +++ b/app/web/src/base/page/all.tsx @@ -1,4 +1,4 @@ -import { page } from "web-init"; +import { page } from "web-utils"; export default page({ url: "*", diff --git a/app/web/src/base/page/auth/login.tsx b/app/web/src/base/page/auth/login.tsx index ebbafd04..47637ead 100644 --- a/app/web/src/base/page/auth/login.tsx +++ b/app/web/src/base/page/auth/login.tsx @@ -1,4 +1,4 @@ -import { page } from "web-init"; +import { page } from "web-utils"; import { useLocal } from "web-utils"; import { Loading } from "../../../utils/ui/loading"; import { formStyle } from "../../../utils/ui/form.style"; diff --git a/app/web/src/base/page/auth/logout.tsx b/app/web/src/base/page/auth/logout.tsx index ccca1685..c6d67631 100644 --- a/app/web/src/base/page/auth/logout.tsx +++ b/app/web/src/base/page/auth/logout.tsx @@ -1,4 +1,4 @@ -import { page } from "web-init"; +import { page } from "web-utils"; import { Loading } from "../../../utils/ui/loading"; export default page({ diff --git a/app/web/src/base/page/auth/register.tsx b/app/web/src/base/page/auth/register.tsx index a6c402e1..e1351771 100644 --- a/app/web/src/base/page/auth/register.tsx +++ b/app/web/src/base/page/auth/register.tsx @@ -1,4 +1,4 @@ -import { page } from "web-init"; +import { page } from "web-utils"; import { useLocal } from "web-utils"; import { Loading } from "../../../utils/ui/loading"; import { formStyle } from "../../../utils/ui/form.style"; diff --git a/app/web/src/base/page/ed.tsx b/app/web/src/base/page/ed.tsx index 1f68e5b2..74ed93db 100644 --- a/app/web/src/base/page/ed.tsx +++ b/app/web/src/base/page/ed.tsx @@ -1,4 +1,4 @@ -import { page } from "web-init"; +import { page } from "web-utils"; import { Loading } from "../../utils/ui/loading"; export default page({ diff --git a/app/web/src/base/page/editor.tsx b/app/web/src/base/page/editor.tsx index fe0345c3..00323375 100644 --- a/app/web/src/base/page/editor.tsx +++ b/app/web/src/base/page/editor.tsx @@ -1,4 +1,4 @@ -import { page } from "web-init"; +import { page } from "web-utils"; import { useLocal } from "web-utils"; import { Loading } from "../../utils/ui/loading"; import { Suspense, lazy, useEffect } from "react"; diff --git a/app/web/src/base/page/live.tsx b/app/web/src/base/page/live.tsx index 4da87496..f98d47d9 100644 --- a/app/web/src/base/page/live.tsx +++ b/app/web/src/base/page/live.tsx @@ -1,5 +1,5 @@ import { validate } from "uuid"; -import { page } from "web-init"; +import { page } from "web-utils"; import { Live } from "../../render/live/live"; import { defaultLoader } from "../../render/live/logic/default-loader"; diff --git a/app/web/src/base/pages.ts b/app/web/src/base/pages.ts new file mode 100644 index 00000000..e69de29b diff --git a/app/web/src/base/root.tsx b/app/web/src/base/root.tsx new file mode 100644 index 00000000..8aa6671d --- /dev/null +++ b/app/web/src/base/root.tsx @@ -0,0 +1,25 @@ +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() {}, +}; + +export const Root: FC<{}> = ({}) => { + const [_, render] = useState({}); + w.prasiContext.render = () => { + render({}); + }; + w.rootRender = w.prasiContext.render; + + const Provider = GlobalContext.Provider as FC<{ value: any; children: any }>; + return Hello mantapun alamuko; +}; diff --git a/app/web/src/index.tsx b/app/web/src/index.tsx index d03da4fe..5561ed89 100644 --- a/app/web/src/index.tsx +++ b/app/web/src/index.tsx @@ -1,4 +1,6 @@ +import { createRoot } from "react-dom/client"; import "./index.css"; +import { Root } from "./base/root"; const registerServiceWorker = async () => { if ("serviceWorker" in navigator) { @@ -17,3 +19,8 @@ const registerServiceWorker = async () => { }; registerServiceWorker(); + +const el = document.getElementById("root"); +if (el) { + createRoot(el).render(); +} diff --git a/app/web/src/render/editor/logic/global.ts b/app/web/src/render/editor/logic/global.ts index 048a9c86..34d80dec 100644 --- a/app/web/src/render/editor/logic/global.ts +++ b/app/web/src/render/editor/logic/global.ts @@ -1,5 +1,5 @@ import { FC, ReactElement, ReactNode } from "react"; -import { createRouter } from "web-init"; +import { createRouter } from "web-utils"; import { CompDoc } from "../../../base/global/content-editor"; import { IContent, MContent, MPage } from "../../../utils/types/general"; import { IItem, MItem } from "../../../utils/types/item"; diff --git a/app/web/src/render/editor/panel/side/ui/FileImageGallery.tsx b/app/web/src/render/editor/panel/side/ui/FileImageGallery.tsx index 70734149..6cd6e176 100644 --- a/app/web/src/render/editor/panel/side/ui/FileImageGallery.tsx +++ b/app/web/src/render/editor/panel/side/ui/FileImageGallery.tsx @@ -1,5 +1,5 @@ import { FC } from "react"; -import { fetchSendApi } from "web-init/src/web/iframe-cors"; +import { fetchSendApi } from "web-utils/src/web/iframe-cors"; import { useGlobal, useLocal } from "web-utils"; import { Gallery } from "./Gallery"; import { Loading } from "../../../../../utils/ui/loading"; diff --git a/app/web/src/render/editor/panel/side/ui/FilePicker.tsx b/app/web/src/render/editor/panel/side/ui/FilePicker.tsx index db41539c..95164901 100644 --- a/app/web/src/render/editor/panel/side/ui/FilePicker.tsx +++ b/app/web/src/render/editor/panel/side/ui/FilePicker.tsx @@ -1,5 +1,5 @@ import { FC, useTransition } from "react"; -import { fetchSendApi } from "web-init/src/web/iframe-cors"; +import { fetchSendApi } from "web-utils/src/web/iframe-cors"; import { useLocal } from "web-utils"; import { Button } from "./Button"; export const FilePicker: FC<{ diff --git a/app/web/src/render/editor/panel/side/ui/Gallery.tsx b/app/web/src/render/editor/panel/side/ui/Gallery.tsx index b9eb3a0d..c2d5085f 100644 --- a/app/web/src/render/editor/panel/side/ui/Gallery.tsx +++ b/app/web/src/render/editor/panel/side/ui/Gallery.tsx @@ -1,7 +1,7 @@ import { format } from "date-fns"; import get from "lodash.get"; import { FC, useTransition } from "react"; -import { fetchSendApi } from "web-init/src/web/iframe-cors"; +import { fetchSendApi } from "web-utils/src/web/iframe-cors"; import { useGlobal, useLocal } from "web-utils"; import { Loading } from "../../../../../utils/ui/loading"; import { EditorGlobal } from "../../../logic/global"; diff --git a/app/web/src/render/live/logic/global.ts b/app/web/src/render/live/logic/global.ts index cbf9bda1..e7109aef 100644 --- a/app/web/src/render/live/logic/global.ts +++ b/app/web/src/render/live/logic/global.ts @@ -1,5 +1,5 @@ import { FC } from "react"; -import { createRouter } from "web-init"; +import { createRouter } from "web-utils"; import { CompDoc } from "../../../base/global/content-editor"; import { IContent, MContent, MPage } from "../../../utils/types/general"; import { IItem, MItem } from "../../../utils/types/item"; diff --git a/app/web/src/render/live/logic/init.tsx b/app/web/src/render/live/logic/init.tsx index d86080a0..40ad5efb 100644 --- a/app/web/src/render/live/logic/init.tsx +++ b/app/web/src/render/live/logic/init.tsx @@ -1,5 +1,5 @@ import { validate } from "uuid"; -import { createRouter, type apiClient } from "web-init"; +import { createRouter, type apiClient } from "web-utils"; import { createAPI, createDB, diff --git a/app/web/src/render/site/site.tsx b/app/web/src/render/site/site.tsx index 02e97dc4..0bb328a3 100644 --- a/app/web/src/render/site/site.tsx +++ b/app/web/src/render/site/site.tsx @@ -1,8 +1,6 @@ import { FC, useState } from "react"; import { createRoot } from "react-dom/client"; -import { defineReact } from "web-init/src/web/define-react"; -import { defineWindow } from "web-init/src/web/define-window"; -import { GlobalContext } from "web-utils"; +import { GlobalContext, defineReact, defineWindow } from "web-utils"; import { SiteLoader } from "./site-loader"; const w = window as unknown as { @@ -22,15 +20,16 @@ const Root: FC<{ url: URL; Live: any }> = ({ url, Live }) => { }; w.rootRender = w.prasiContext.render; + const Provider = GlobalContext.Provider as FC<{ value: any; children: any }>; return ( - + - + ); }; diff --git a/app/web/src/utils/script/init-api.ts b/app/web/src/utils/script/init-api.ts index 83afa7be..c5ef4abe 100644 --- a/app/web/src/utils/script/init-api.ts +++ b/app/web/src/utils/script/init-api.ts @@ -1,7 +1,7 @@ import { createStore, get, set } from "idb-keyval"; import trim from "lodash.trim"; -import { apiClient, dbClient } from "web-init"; -import { createFrameCors } from "web-init/src/web/iframe-cors"; +import { apiClient, dbClient } from "web-utils"; +import { createFrameCors } from "web-utils/src/web/iframe-cors"; export const w = window as unknown as { prasiApi: Record; apiHeaders: any; diff --git a/app/web/tsconfig.json b/app/web/tsconfig.json index 05438c1e..f5832eec 100644 --- a/app/web/tsconfig.json +++ b/app/web/tsconfig.json @@ -20,12 +20,5 @@ "isolatedModules": true, // "noEmit": true, "jsx": "react-jsx", - "baseUrl": "./src", }, - "include": [ - "./src/**/*", - "./jsx-*.ts", - "pkgs/coditor", - "public/jsx-worker.js", - ] } \ No newline at end of file diff --git a/app/web/types/content.ts b/app/web/types/content.ts deleted file mode 100644 index 8de85480..00000000 --- a/app/web/types/content.ts +++ /dev/null @@ -1,3 +0,0 @@ -import * as PAGES from "../../../app/gen/web/page/web"; - -export const pages = PAGES; diff --git a/bun.lockb b/bun.lockb index 1efe5955..4fa6d14f 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 4d6a2444..faa9281c 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "type": "module", "scripts": { "dev": "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", "pkgs-upgrade": "bun run --silent ./pkgs/core/upgrade.ts" diff --git a/pkgs/core/utils/global.ts b/pkgs/core/utils/global.ts index 0d233968..77948f11 100644 --- a/pkgs/core/utils/global.ts +++ b/pkgs/core/utils/global.ts @@ -1,4 +1,4 @@ -import { Server } from "bun"; +import { Server, Subprocess } from "bun"; import { Logger } from "pino"; import { RadixRouter } from "radix3"; import { PrismaClient } from "../../../app/db/db"; @@ -24,4 +24,5 @@ export const g = global as unknown as { js: string; etag: string; }; + parcel: Subprocess; }; diff --git a/pkgs/core/utils/parcel.ts b/pkgs/core/utils/parcel.ts index 08446628..6a6c5f06 100644 --- a/pkgs/core/utils/parcel.ts +++ b/pkgs/core/utils/parcel.ts @@ -14,13 +14,13 @@ export const parcelBuild = async () => { "--dist-dir", dir(`app/static`), ]; - - await removeAsync(dir("app/static")); - g.log.info(`Building web with parcel`); if (g.mode !== "dev") { + await removeAsync(dir("app/static")); + await removeAsync(dir("app/web/.parcel-cache")); + const parcel = spawn({ - cmd: args, + cmd: args, cwd: dir("app/web"), stdio: ["ignore", "inherit", "inherit"], }); @@ -32,6 +32,8 @@ export const parcelBuild = async () => { stdio: ["ignore", "pipe", "pipe"], }); + g.parcel = parcel; + let output = true; (async () => { if (parcel.stdout) { diff --git a/pkgs/web-utils/package.json b/pkgs/web-utils/package.json index b221f58e..d960a4ce 100644 --- a/pkgs/web-utils/package.json +++ b/pkgs/web-utils/package.json @@ -3,6 +3,7 @@ "main": "src/export.ts", "dependencies": { "@paralleldrive/cuid2": "2.2.0", + "goober": "^2.1.13", "react": "18.2.0", "react-dom": "18.2.0" }, diff --git a/pkgs/web-utils/src/define-react.ts b/pkgs/web-utils/src/define-react.ts new file mode 100644 index 00000000..9fa6039f --- /dev/null +++ b/pkgs/web-utils/src/define-react.ts @@ -0,0 +1,14 @@ +import React from "react"; +import ReactDOM from "react-dom"; +import JSXDevRuntime from "react/jsx-dev-runtime"; +import JSXRuntime from "react/jsx-runtime"; + +export const defineReact = () => { + const w = typeof window === "object" ? window : (globalThis as any); + + w.React = React; + w.ReactDOM = ReactDOM; + w.JSXRuntime = JSXRuntime; + w.JSXDevRuntime = JSXDevRuntime; + w.Fragment = React.Fragment; +}; diff --git a/pkgs/web-utils/src/define-window.ts b/pkgs/web-utils/src/define-window.ts new file mode 100644 index 00000000..0fb4e654 --- /dev/null +++ b/pkgs/web-utils/src/define-window.ts @@ -0,0 +1,93 @@ +import { css, extractCss } from "goober"; +import { waitUntil } from "web-utils"; + +export const defineWindow = async (awaitServerUrl = true) => { + let w = typeof window === "object" ? window : (globalThis as any); + + if (awaitServerUrl) await waitUntil(() => w.__SRV_URL__); + + const location = window["location"]; + + const host = + 0 === location.protocol.indexOf("http") ? location.hostname : "localhost", + scheme = + "https:" != location.protocol || /localhost|127.0.0.1|0.0.0.0/.test(host) + ? "http" + : "https"; + + if (w.__SRV_URL__) { + w.serverurl = w.__SRV_URL__; + const serverURL = new URL(w.serverurl); + if ( + serverURL.hostname === "localhost" || + serverURL.hostname === "127.0.0.1" + ) { + serverURL.hostname = location.hostname; + serverURL.pathname = serverURL.pathname === "/" ? "" : serverURL.pathname; + w.serverurl = serverURL.toString(); + if (w.serverurl.endsWith("/")) { + w.serverurl = w.serverurl.substring(0, w.serverurl.length - 1); + } + } + } + + const port = location.port; + w.baseurl = scheme + "://" + host + (port ? ":" + port : "") + "/"; + w.basepath = "/"; + w.css = css; + w.extractCss = extractCss; + w.pathname = location.pathname; + + w.cx = (...classNames: any[]) => { + const result: string[] = []; + + classNames + .filter((e) => { + if (e) { + if (typeof e === "string" && e.trim()) return true; + else return true; + } + return false; + }) + .forEach((e) => { + if (Array.isArray(e)) { + for (const f of e) { + if (typeof f === "string" && f.trim()) { + result.push(f.trim()); + } + } + } else result.push(e.trim()); + }); + return result.join(" "); + }; + + w.navigate = (href: string) => { + let _href = href; + + if (typeof w.navigateOverride === "function") { + _href = w.navigateOverride(href); + if (!_href) return null; + } + + history.pushState({}, "", _href); + if (w.rootRes) w.rootRes.pathname = href; + w.pathname = href; + + if (w.rootRender) { + w.rootRender(); + } + }; + + if (typeof window === "object") { + window.addEventListener("popstate", () => { + if (w.preventPopRender) { + w.preventPopRender = false; + return; + } + if (w.rootRender) { + w.pathname = location.pathname; + w.rootRender(); + } + }); + } +}; diff --git a/pkgs/web-utils/src/export.ts b/pkgs/web-utils/src/export.ts index 0ad88aba..6525a0f1 100644 --- a/pkgs/web-utils/src/export.ts +++ b/pkgs/web-utils/src/export.ts @@ -3,4 +3,8 @@ export * from "./wait-until"; export * from "./lazify"; export * from "./use-global"; import * as _React from "react"; +export * from "./page"; +export * from "./global"; +export * from "./define-react"; +export * from "./define-window"; export const React = _React; diff --git a/pkgs/web-utils/src/global.ts b/pkgs/web-utils/src/global.ts new file mode 100644 index 00000000..9797c034 --- /dev/null +++ b/pkgs/web-utils/src/global.ts @@ -0,0 +1,4 @@ +declare global { + const navigate: (path: string) => void; +} +export {}; diff --git a/pkgs/web-utils/src/page.ts b/pkgs/web-utils/src/page.ts new file mode 100644 index 00000000..9a003752 --- /dev/null +++ b/pkgs/web-utils/src/page.ts @@ -0,0 +1,5 @@ +import { FC, ReactElement } from "react"; + +export const page = (arg: { url: string; component: FC }) => { + return arg; +}; diff --git a/pkgs/web-utils/src/use-local.ts b/pkgs/web-utils/src/use-local.ts index 70230034..7442859c 100644 --- a/pkgs/web-utils/src/use-local.ts +++ b/pkgs/web-utils/src/use-local.ts @@ -1,6 +1,5 @@ import { useEffect, useRef, useState } from "react"; -import "../../web-init/src/types"; export const useLocal = ( data: T,