diff --git a/app/srv/api/npm-bundle.ts b/app/srv/api/npm-bundle.ts new file mode 100644 index 00000000..60378f6f --- /dev/null +++ b/app/srv/api/npm-bundle.ts @@ -0,0 +1,189 @@ +import globalExternals from "@fal-works/esbuild-plugin-global-externals"; +import { style } from "@hyrious/esbuild-plugin-style"; +import { npm_page, npm_site } from "dbgen"; +import { dir } from "dir"; +import { build } from "esbuild"; +import { $ } from "execa"; +import { dirAsync, writeAsync } from "fs-jetpack"; +import { stat } from "fs/promises"; +import { apiContext } from "service-srv"; +import { g } from "utils/global"; +import { validate } from "uuid"; +import { glb } from "../global"; +import { eg } from "../ws/edit/edit-global"; + +export type NPMImportAs = { + main: { mode: "default" | "*"; name: string }; + names: string[]; + custom?: string; +}; + +export const _ = { + url: "/npm-bundle/:mode/:id", + async api(mode: "site" | "page", id: string) { + const {} = apiContext(this); + if (!validate(id)) return "-"; + + let items = [] as npm_page[] | npm_site[]; + + if (mode === "site") { + items = await db.npm_site.findMany({ where: { id_site: id } }); + } else { + items = await db.npm_page.findMany({ where: { id_page: id } }); + } + const packages: Record = {}; + + const imports = items + .map((e) => { + const import_as = e.import_as as NPMImportAs; + + packages[e.module] = e.version; + if (import_as.main.name || import_as.names.length > 0) { + let main = ""; + let names = import_as.names.map((e) => `${e} as __${e}`); + + if (import_as.main.name) { + main = + import_as.main.mode === "default" + ? `__${import_as.main.name}` + : `* as __${import_as.main.name}`; + } + + const imports = [ + main.trim(), + (names.length > 0 ? `{ ${names.join(",")} }` : "").trim(), + ].filter((e) => e); + + let final = ""; + if (imports.length > 0) { + final = `import ${imports.join(",")} from "${e.module}";`; + } + + if (import_as.custom) { + final = final + "\n" + import_as.custom; + } + return final; + } + return ""; + }) + .filter((e) => !!e) + .join("\n"); + + const exports = items + .map((e) => { + const import_as = e.import_as as NPMImportAs; + const res: string[] = []; + + if (import_as.main.name || import_as.names.length > 0) { + let main = ""; + let names = import_as.names; + + if (import_as.main.name) { + main = import_as.main.name; + } + + if (main) { + res.push(`window.exports.${main} = __${main};`); + } + + if (names.length > 0) { + names.forEach((e) => { + res.push(`window.exports.${e} = __${e};`); + }); + } + } + + return res.join("\n").trim(); + }) + .filter((e) => !!e) + .join("\n"); + + const src = `\ +${imports} +${exports} +`.trim(); + await dirAsync(dir.path(`${g.datadir}/npm/${mode}/${id}`)); + await writeAsync(dir.path(`${g.datadir}/npm/${mode}/${id}/input.js`), src); + packages["react"] = "18.2.0"; + packages["react-dom"] = "18.2.0"; + await writeAsync(dir.path(`${g.datadir}/npm/${mode}/${id}/package.json`), { + dependencies: packages, + }); + await writeAsync( + dir.path(`${g.datadir}/npm/${mode}/${id}/pnpm-workspace.yaml`), + `\ +packages: + - ./*` + ); + try { + await $({ + cwd: dir.path(`${g.datadir}/npm/${mode}/${id}`), + })`pnpm i`; + + await build({ + absWorkingDir: dir.path(`${g.datadir}/npm/${mode}/${id}`), + entryPoints: ["input.js"], + bundle: true, + outfile: "index.js", + minify: true, + treeShaking: true, + sourcemap: true, + plugins: [ + style(), + globalExternals({ + react: { + varName: "window.React", + type: "cjs", + }, + "react-dom": { + varName: "window.ReactDOM", + type: "cjs", + }, + }), + ], + logLevel: "silent", + }); + } catch (e) { + return e; + } + + try { + const s = await stat(dir.path(`${g.datadir}/npm/${mode}/${id}/index.js`)); + + if (mode === "page") { + delete glb.npm.page[id]; + await db.npm_page.updateMany({ + where: { + id_page: id, + }, + data: { bundled: true }, + }); + const p = eg.edit.page[id]; + if (p) { + await db.page.update({ + where: { + id, + }, + data: { + updated_at: new Date(), + }, + }); + p.doc.getMap("map").set("updated_at", new Date().toISOString()); + } + } else if (mode === "site") { + delete glb.npm.site[id]; + + await db.npm_site.updateMany({ + where: { + id_site: id, + }, + data: { bundled: true }, + }); + } + + return s.size.toString(); + } catch (e) { + return "-"; + } + }, +}; diff --git a/app/srv/api/npm-size.ts b/app/srv/api/npm-size.ts new file mode 100644 index 00000000..1b52b704 --- /dev/null +++ b/app/srv/api/npm-size.ts @@ -0,0 +1,16 @@ +import { dir } from "dir"; +import { stat } from "fs/promises"; +import { apiContext } from "service-srv"; +import { g } from "utils/global"; + +export const _ = { + url: "/npm-size/:mode/:id", + async api(mode: "site" | "page", id: string) { + const { req, res } = apiContext(this); + try { + const s = await stat(dir.path(`${g.datadir}/npm/${mode}/${id}/index.js`)); + return s.size.toString(); + } catch (e) {} + return "-"; + }, +}; diff --git a/app/srv/api/npm.ts b/app/srv/api/npm.ts index 32384d81..c974a737 100644 --- a/app/srv/api/npm.ts +++ b/app/srv/api/npm.ts @@ -4,14 +4,13 @@ import { readAsync } from "fs-jetpack"; import mime from "mime-types"; import { apiContext } from "service-srv"; import { glb } from "../global"; +import { g } from "utils/global"; export const _ = { url: "/npm/:mode/:id/*", async api(mode: "site" | "page", id: string) { const { req, res, mode: _mode } = apiContext(this); - let path = dir.path(`../npm/${mode}/${id}/${req.params._}`); - - res.setHeader("Access-Control-Allow-Origin", "*"); + let path = dir.path(`${g.datadir}/npm/${mode}/${id}/${req.params._}`); if (!glb.npm) { glb.npm = { page: {}, site: {} }; diff --git a/app/srv/exports.d.ts b/app/srv/exports.d.ts index cf4e8189..9591e1a7 100644 --- a/app/srv/exports.d.ts +++ b/app/srv/exports.d.ts @@ -1,5 +1,11 @@ /// -declare module "api/auth/login" { +declare module "app/srv/api/npm-size" { + export const _: { + url: string; + api(mode: "site" | "page", id: string): Promise; + }; +} +declare module "app/srv/api/auth/login" { export const _: { url: string; api(username: string, password: string): Promise<{ @@ -13,13 +19,13 @@ declare module "api/auth/login" { }>; }; } -declare module "api/session" { +declare module "app/srv/api/session" { export const _: { url: string; api(): Promise; }; } -declare module "global" { +declare module "app/srv/global" { import { site, user } from "dbgen"; import { ExecaChildProcess } from "execa"; export const glb: { @@ -45,46 +51,602 @@ declare module "global" { }; }; } -declare module "api/npm" { +declare module "app/srv/api/npm" { export const _: { url: string; api(mode: "site" | "page", id: string): Promise; }; } -declare module "api/site-dts" { +declare module "app/web/src/utils/types/ws" { + export type WS_MSG = WS_MSG_GET_COMP | WS_MSG_SET_COMP | WS_MSG_GET_PAGE | WS_MSG_SET_PAGE | WS_MSG_SV_LOCAL | WS_MSG_SVDIFF_REMOTE | WS_MSG_DIFF_LOCAL | WS_MSG_UNDO | WS_MSG_REDO | WS_MSG_NEW_COMP | WS_SITE_JS | { + type: "ping"; + } | { + type: "pong"; + }; + export type WS_SITE_JS = { + type: "site-js"; + id_site: string; + src: string; + }; + export type WS_MSG_GET_COMP = { + type: "get_comp"; + comp_id: string; + }; + export type WS_MSG_SET_COMP = { + type: "set_comp"; + comp_id: string; + changes: string; + }; + export type WS_MSG_GET_PAGE = { + type: "get_page"; + page_id: string; + }; + export type WS_MSG_SET_PAGE = { + type: "set_page"; + changes: string; + }; + export type WS_MSG_NEW_COMP = { + type: "new_comp"; + id: string; + doc: string; + }; + export type WS_MSG_UNDO = { + type: "undo"; + mode: "page" | "site" | "comp"; + id: string; + }; + export type WS_MSG_REDO = { + type: "redo"; + mode: "page" | "site" | "comp"; + id: string; + }; + export type WS_MSG_SV_LOCAL = { + type: "sv_local"; + mode: "page" | "site" | "comp"; + id: string; + sv_local: string; + }; + export type WS_MSG_SVDIFF_REMOTE = { + type: "svd_remote"; + mode: "page" | "site" | "comp"; + id: string; + sv_remote: string; + diff_remote: string; + }; + export type WS_MSG_DIFF_LOCAL = { + type: "diff_local"; + mode: "page" | "site" | "comp"; + id: string; + diff_local: string; + }; +} +declare module "app/web/src/utils/types/meta-fn" { + import { TypedMap } from "yjs-types"; + import { IItem, MItem } from "app/web/src/utils/types/item"; + import * as Y from "yjs"; + export type FNLayout = { + dir: "row" | "col" | "row-reverse" | "col-reverse"; + align: FNAlign; + gap: number | "auto"; + wrap: undefined | "flex-wrap" | "flex-nowrap"; + }; + export type FMLayout = TypedMap; + export type FNAdv = { + js?: Y.Text | string; + jsBuilt?: string; + css?: Y.Text | string; + html?: Y.Text | string; + }; + export type FMAdv = TypedMap; + export type FNComponent = { + id: string; + name: string; + updated_at?: number; + props: Record; + }; + export type FNCompDef = { + idx: number; + type: string; + value: any; + valueBuilt: any; + gen?: string; + genBuilt?: string; + content?: IItem; + visible?: string; + meta?: FNCompMeta; + }; + type FNCompMeta = { + type: "text" | "option" | "content-element"; + options?: string; + optionsBuilt?: string; + option_mode?: "dropdown" | "button"; + }; + export type FMCompDef = TypedMap & { + content: MItem; + meta: TypedMap; + }>; + export type FMComponent = TypedMap & { + props: TypedMap>; + }>; + export type FNAlign = "top-left" | "top-center" | "top-right" | "top" | "left" | "center" | "right" | "bottom" | "bottom-left" | "bottom-center" | "bottom-right" | "stretch"; + export type FNPadding = { + t?: number; + b?: number; + l?: number; + r?: number; + }; + export type FMPadding = TypedMap; + export type FNDimension = { + w?: number | "fit" | "full"; + h?: number | "fit" | "full"; + wUnit?: "px" | "%"; + hUnit?: "px" | "%"; + proportion?: boolean; + }; + export type FMDimension = TypedMap; + export type FNBackground = { + color?: string; + url?: string; + size?: "cover" | "contain" | "full" | "auto" | "%" | "px"; + repeat?: "repeat" | "repeat-x" | "repeat-y" | "space" | "round" | "no-repeat"; + pos?: "top" | "left" | "center" | "bottom" | "right"; + }; + export type FMBackground = TypedMap; + export type FNBorder = { + style?: "solid" | "dash"; + stroke?: FNBorderCorner; + rounded?: FNRounded; + color?: string; + }; + export type FNBorderCorner = { + t?: number; + b?: number; + l?: number; + r?: number; + }; + export type FNRounded = { + tr?: number; + tl?: number; + bl?: number; + br?: number; + }; + export type FMBorder = TypedMap; + export type FNFont = { + color?: string; + size?: number; + family?: string; + height?: number | "auto"; + align?: "center" | "left" | "right"; + whitespace?: "whitespace-normal" | "whitespace-nowrap" | "whitespace-pre" | "whitespace-pre-line" | "whitespace-pre-wrap" | "whitespace-break-spaces"; + wordBreak?: "break-normal" | "break-words" | "break-all" | "break-keep"; + }; + export type FMFont = TypedMap; + export type FNLinkTag = { + tag?: string; + link?: string; + class?: string; + }; + export type FMLinkTag = TypedMap; +} +declare module "app/web/src/utils/types/meta" { + import { FMAdv, FMBackground, FMBorder, FMComponent, FMDimension, FMFont, FMLayout, FMLinkTag, FMPadding, FNBackground, FNBorder, FNDimension, FNFont, FNPadding } from "app/web/src/utils/types/meta-fn"; + export type MetaItem = { + id: string; + originalId?: string; + type: "text" | "section" | "item"; + name: string; + field?: string; + html?: string; + text?: string; + hidden?: "only-editor" | "all" | false; + }; + export type BasicItem = { + padding?: FNPadding; + bg?: FNBackground; + font?: FNFont; + dim?: FNDimension; + border?: FNBorder; + }; + export type MBasicItem = { + padding?: FMPadding; + bg?: FMBackground; + font?: FMFont; + component?: FMComponent; + dim?: FMDimension; + layout?: FMLayout; + linktag?: FMLinkTag; + adv?: FMAdv; + border?: FMBorder; + }; +} +declare module "app/web/src/utils/types/root" { + import { TypedArray, TypedMap } from "yjs-types"; + import { ISection } from "app/web/src/utils/types/section"; + export type IRoot = { + id: "root"; + type: "root"; + id_page: string; + childs: ISection[]; + }; + export type MRoot = TypedMap<{ + id: "root"; + type: "root"; + childs: TypedArray; + }>; +} +declare module "app/web/src/utils/types/section" { + import { TypedArray, TypedMap } from "yjs-types"; + import { IItem, MItem } from "app/web/src/utils/types/item"; + import { BasicItem, MBasicItem, MetaItem } from "app/web/src/utils/types/meta"; + import { FNAdv, FNLayout, FNLinkTag } from "app/web/src/utils/types/meta-fn"; + import { MRoot } from "app/web/src/utils/types/root"; + export type ISection = { + layout?: FNLayout; + mobile?: ISection; + linktag?: FNLinkTag; + adv?: FNAdv; + type: "section"; + childs: IItem[]; + } & MetaItem & BasicItem; + export type MSection = TypedMap<{ + mobile?: MSection; + type: "section"; + childs?: TypedArray; + } & MBasicItem & MetaItem> & { + parent: TypedArray & { + parent: MRoot; + }; + }; +} +declare module "app/web/src/utils/types/text" { + import { TypedArray, TypedMap } from "yjs-types"; + import { BasicItem, MBasicItem, MetaItem } from "app/web/src/utils/types/meta"; + import { FNAdv, FNLayout, FNLinkTag } from "app/web/src/utils/types/meta-fn"; + import { MItem } from "app/web/src/utils/types/item"; + export type IText = { + mobile?: IText; + type: "text"; + layout?: FNLayout; + linktag?: FNLinkTag; + text: string; + html: string; + adv?: FNAdv; + } & BasicItem & MetaItem; + export type MText = TypedMap<{ + type: "text"; + mobile?: MText; + childs?: TypedArray; + } & MBasicItem & MetaItem> & { + parent: TypedArray & { + parent: MItem; + }; + }; +} +declare module "app/web/src/utils/types/item" { + import { TypedArray, TypedMap } from "yjs-types"; + import { BasicItem, MBasicItem, MetaItem } from "app/web/src/utils/types/meta"; + import { FNAdv, FNComponent, FNLayout, FNLinkTag } from "app/web/src/utils/types/meta-fn"; + import { MSection } from "app/web/src/utils/types/section"; + import { IText, MText } from "app/web/src/utils/types/text"; + export type IItem = { + layout?: FNLayout; + linktag?: FNLinkTag; + mobile?: IItem; + adv?: FNAdv; + type: "item"; + component?: FNComponent; + childs: (IItem | IText)[]; + } & MetaItem & BasicItem; + export type MItem = TypedMap<{ + type: "item"; + mobile?: MItem; + childs?: TypedArray; + } & MBasicItem & MetaItem> & { + parent: TypedArray & { + parent: MSection | MItem; + }; + }; +} +declare module "app/web/src/utils/types/general" { + import { page as dbpage } from "dbgen"; + import { TypedDoc, TypedMap } from "yjs-types"; + import { IItem, MItem } from "app/web/src/utils/types/item"; + import { IRoot, MRoot } from "app/web/src/utils/types/root"; + import { ISection, MSection } from "app/web/src/utils/types/section"; + import { IText, MText } from "app/web/src/utils/types/text"; + export type PageProps = { + pathname: string; + domain: string; + params: any; + }; + export type PrasiAPI = { + apiEntry: any; + prismaTypes: { + "prisma.d.ts": string; + "runtime/library.d.ts": string; + "runtime/index.d.ts": string; + }; + apiTypes: string; + }; + export const w: { + isEditor: boolean; + isMobile: boolean; + isDesktop: boolean; + prasiApi: Record; + loadedFonts: string[]; + prasiApiDbPull: boolean; + params: any; + editorGlbDefault: string; + ts: number; + serverurl: string; + api: any; + db: any; + }; + export type Page = { + id: string; + content_tree: IRoot; + js: string | null; + js_compiled: string | null; + }; + export type MPage = TypedDoc<{ + map: TypedMap & { + content_tree: MRoot; + updated_at: string; + }>; + }>; + export type IContent = ISection | IItem | IText; + export type MContent = MSection | MItem | MText; + export type RenderContentProp = Partial<{ + active: IContent | null; + hover: IContent | null; + update: (updateID: string, name: string, newState: IRoot) => void; + onHover: (e: React.MouseEvent, item: IContent) => Promise; + onOut: (e: React.MouseEvent, item: IContent) => Promise; + onClick: (e: React.MouseEvent, item: IContent) => Promise; + isEditor: boolean; + setContent: (item: IContent) => Promise; + _onlyChildren?: true; + }>; + export type ERenderProp = { + item: ITEM; + }; +} +declare module "app/srv/ws/edit/tools/load-page" { + import { Page } from "app/web/src/utils/types/general"; + export const loadPage: (page_id: string) => Promise; +} +declare module "app/srv/ws/edit/action/get-page" { + import { WSData } from "pkgs/core/server/create"; + import { WS_MSG_GET_PAGE } from "app/web/src/utils/types/ws"; + export const getPage: (ws: ServerWebSocket, msg: WS_MSG_GET_PAGE) => Promise; +} +declare module "app/srv/ws/edit/action/get-comp" { + import { WSData } from "pkgs/core/server/create"; + import { WS_MSG_GET_COMP } from "app/web/src/utils/types/ws"; + export const getComp: (ws: ServerWebSocket, msg: WS_MSG_GET_COMP) => Promise; +} +declare module "app/srv/ws/edit/action/sv-local" { + export const svLocal: (ws: Websocket, msg: WS_MSG_SV_LOCAL) => Promise; +} +declare module "app/srv/ws/edit/action/diff-local" { + export const diffLocal: (ws: Websocket, msg: any) => Promise; +} +declare module "app/srv/ws/edit/action/svdiff-remote" { + export const svdiffRemote: (ws: Websocket, msg: WS_MSG_SVDIFF_REMOTE) => Promise; +} +declare module "app/srv/ws/edit/action/undo-redo" { + export const undo: (ws: Websocket, msg: WS_MSG_UNDO) => void; + export const redo: (ws: Websocket, msg: WS_MSG_REDO) => void; +} +declare module "app/srv/ws/handler" { + import { WebSocketHandler } from "bun"; + import { WSData } from "pkgs/core/server/create"; + export const wsHandler: Record>; +} +declare module "pkgs/core/utils/dir" { + export const dir: { + path: (path: string) => string; + }; +} +declare module "app/db/db" { + +} +declare module "pkgs/core/utils/global" { + import { Logger } from "pino"; + import { RadixRouter } from "radix3"; + + type SingleRoute = { + url: string; + args: string[]; + fn: (...arg: any[]) => Promise; + path: string; + }; + export const g: { + status: "init" | "ready"; + datadir: string; + + dburl: string; + mode: "dev" | "prod"; + + log: Logger; + api: Record; + domains: null | Record; + router: RadixRouter; + port: number; + frm: { + js: string; + etag: string; + }; + parcel: Subprocess; + }; +} +declare module "pkgs/core/server/api-ctx" { + export const apiContext: (ctx: any) => { + mode: any; + req: Request & { + params: any; + query_parameters: any; + }; + res: Response & { + send: (body?: string | object) => void; + setHeader: (key: string, value: string) => void; + sendStatus: (code: number) => void; + }; + }; + export const createResponse: (existingRes: any, body: any) => Response; +} +declare module "pkgs/core/server/serve-api" { + export const serveAPI: (url: URL, req: Request) => Promise; +} +declare module "pkgs/core/server/create" { + export type WSData = { + url: URL; + }; + export const createServer: () => Promise; +} +declare module "app/srv/ws/edit/tools/load-site" { + export type SiteConfig = { + api_url?: string; + prasi?: { + port: number; + dburl: string; + }; + }; + export type Site = Exclude>, null>; + export const loadSite: (idOrDomain: string) => Promise & { + config?: SiteConfig; + page: { + id: string; + url: string; + updated_at: Date | null; + name: string; + }[]; + }>; +} +declare module "app/srv/ws/edit/edit-global" { + import { ServerWebSocket } from "bun"; + import { component } from "dbgen"; + import { UndoManager } from "yjs"; + import { TypedArray, TypedDoc, TypedMap } from "yjs-types"; + import type { WSData } from "pkgs/core/server/create"; + import { IItem } from "app/web/src/utils/types/item"; + import { IRoot } from "app/web/src/utils/types/root"; + import { Site } from "app/srv/ws/edit/tools/load-site"; + import { MPage } from "app/web/src/utils/types/general"; + import type { RadixRouter } from "radix3"; + type ArrayElement = ArrayType extends readonly (infer ElementType)[] ? ElementType : never; + export type SingleComp = { + id: string; + doc: TypedDoc<{ + map: TypedMap; + }>; + }>; + undoManager: UndoManager; + saveTimeout?: ReturnType; + ws: Set>; + }; + export const eg: { + cache: Record>; + router: Record>; + edit: { + site: Record>; + }>; + }>; + undoManager: UndoManager; + saveTimeout?: ReturnType; + ws: Set>; + }>; + comp: Record; + page: Record; + ws: Set>; + }>; + ws: WeakMap, { + clientID: string; + }>; + }; + }; +} +declare module "app/srv/api/npm-bundle" { + export type NPMImportAs = { + main: { + mode: "default" | "*"; + name: string; + }; + names: string[]; + custom?: string; + }; + export const _: { + url: string; + api(mode: "site" | "page", id: string): Promise; + }; +} +declare module "app/srv/api/site-dts" { export const _: { url: string; api(site_id: string): Promise; }; } -declare module "exports" { +declare module "app/srv/exports" { + export const npm_size: { + name: string; + url: string; + path: string; + args: string[]; + handler: Promise; + }; export const login: { name: string; url: string; path: string; args: string[]; - handler: Promise; + handler: Promise; }; export const session: { name: string; url: string; path: string; args: any[]; - handler: Promise; + handler: Promise; }; export const npm: { name: string; url: string; path: string; args: string[]; - handler: Promise; + handler: Promise; + }; + export const npm_bundle: { + name: string; + url: string; + path: string; + args: string[]; + handler: Promise; }; export const site_dts: { name: string; url: string; path: string; args: string[]; - handler: Promise; + handler: Promise; }; export const _upload: { name: string; diff --git a/app/srv/exports.ts b/app/srv/exports.ts index 82335c16..f8c5153d 100644 --- a/app/srv/exports.ts +++ b/app/srv/exports.ts @@ -1,3 +1,10 @@ +export const npm_size = { + name: "npm_size", + url: "/npm-size/:mode/:id", + path: "app/srv/api/npm-size.ts", + args: ["mode","id"], + handler: import("./api/npm-size") +} export const login = { name: "login", url: "/_login", @@ -19,6 +26,13 @@ export const npm = { args: ["mode","id"], handler: import("./api/npm") } +export const npm_bundle = { + name: "npm_bundle", + url: "/npm-bundle/:mode/:id", + path: "app/srv/api/npm-bundle.ts", + args: ["mode","id"], + handler: import("./api/npm-bundle") +} export const site_dts = { name: "site_dts", url: "/site-dts/:site_id", diff --git a/app/srv/package.json b/app/srv/package.json index bcd4284f..e164f6df 100644 --- a/app/srv/package.json +++ b/app/srv/package.json @@ -1,9 +1,12 @@ { "name": "srv", "dependencies": { + "@fal-works/esbuild-plugin-global-externals": "^2.1.2", + "@hyrious/esbuild-plugin-style": "^0.3.5", "@node-rs/argon2": "^1.5.2", "@paralleldrive/cuid2": "^2.2.2", "@types/mime-types": "^2.1.2", + "esbuild": "^0.19.4", "lz-string": "^1.5.0", "mime-types": "^2.1.35", "radix3": "^1.1.0" diff --git a/app/web/src/base/page/ed.tsx b/app/web/src/base/page/ed.tsx index 800666e6..eb6923e7 100644 --- a/app/web/src/base/page/ed.tsx +++ b/app/web/src/base/page/ed.tsx @@ -33,8 +33,7 @@ export default page({ let e = await api.session(); if (!e) { (window as any).redirectTo = location.pathname; - console.log("session not found"); - // navigate("/login"); + navigate("/login"); localStorage.removeItem("prasi-session"); } else { localStorage.setItem("prasi-session", JSON.stringify(e)); diff --git a/app/web/src/base/page/editor.tsx b/app/web/src/base/page/editor.tsx index 5eb04857..0d04e743 100644 --- a/app/web/src/base/page/editor.tsx +++ b/app/web/src/base/page/editor.tsx @@ -38,8 +38,7 @@ export default page({ let e = await api.session(); if (!e) { (window as any).redirectTo = location.pathname; - console.log("session not found"); - // navigate("/login"); + navigate("/login"); localStorage.removeItem("prasi-session"); } else { localStorage.setItem("prasi-session", JSON.stringify(e)); diff --git a/app/web/src/render/editor/panel/manager/site/site-mgr.tsx b/app/web/src/render/editor/panel/manager/site/site-mgr.tsx index 4ad35cb6..137d0d8f 100644 --- a/app/web/src/render/editor/panel/manager/site/site-mgr.tsx +++ b/app/web/src/render/editor/panel/manager/site/site-mgr.tsx @@ -22,6 +22,7 @@ export const SiteManager = () => { }); const reloadSites = async () => { + const orgs = await db.org_user.findMany({ where: { id_user: p.session.data.user.id, diff --git a/app/web/src/render/live/elements/l-item.tsx b/app/web/src/render/live/elements/l-item.tsx index c269175b..803f39bf 100644 --- a/app/web/src/render/live/elements/l-item.tsx +++ b/app/web/src/render/live/elements/l-item.tsx @@ -6,6 +6,7 @@ export const LItem: FC<{ id: string; fromProp?: boolean; }> = ({ id, fromProp }) => { + return ( {(childs) => { diff --git a/app/web/src/render/live/elements/l-page.tsx b/app/web/src/render/live/elements/l-page.tsx index 078693f1..7f22ca23 100644 --- a/app/web/src/render/live/elements/l-page.tsx +++ b/app/web/src/render/live/elements/l-page.tsx @@ -65,5 +65,9 @@ export const mobileCSS = css` linear-gradient(-45deg, transparent 75%, #fafafa 75%); background-size: 20px 20px; - background-position: 0 0, 0 10px, 10px -10px, -10px 0px; + background-position: + 0 0, + 0 10px, + 10px -10px, + -10px 0px; `; diff --git a/app/web/src/render/live/logic/tree-scope.tsx b/app/web/src/render/live/logic/tree-scope.tsx index 04dd8c16..c853c47a 100644 --- a/app/web/src/render/live/logic/tree-scope.tsx +++ b/app/web/src/render/live/logic/tree-scope.tsx @@ -51,6 +51,7 @@ export const treeScopeEval = ( } } } + const output = { jsx: null as any }; args = { ...w.exports, @@ -86,7 +87,9 @@ export const treeScopeEval = ( console.warn(`Available var:`, args, `\n\n`); }); } - } catch (e) {} + } catch (e) { + console.error(e); + } return output.jsx; } catch (e) { diff --git a/app/web/src/sworker.ts b/app/web/src/sworker.ts index 690d8444..bcf6165c 100644 --- a/app/web/src/sworker.ts +++ b/app/web/src/sworker.ts @@ -2,6 +2,8 @@ import { manifest, version } from "@parcel/service-worker"; const g = { cache: null as null | Cache, + dev: false, + baseUrl: "", }; async function install() { @@ -22,27 +24,34 @@ addEventListener("activate", (e) => addEventListener("fetch", async (evt) => { const e = evt as FetchEvent; + if (g.baseUrl) { + const url = e.request.url; + if (url.startsWith(g.baseUrl)) { + return; + } + } + e.respondWith( (async () => { if (!g.cache) { g.cache = await caches.open(version); } + + if (!g.baseUrl) { + const keys = await g.cache.keys(); + const url = new URL(keys[0].url); + url.pathname = ""; + g.baseUrl = url.toString(); + } + const cache = g.cache; + const r = await cache.match(e.request); if (r) { + cache.add(e.request); return r; } - const url = new URL(e.request.url); - - const res = await fetch(e.request); - if ( - url.pathname.includes("_api_frm") || - url.pathname.startsWith("/_prasi") - ) { - await cache.put(e.request, res); - } - - return res; + return await fetch(e.request.url); })() ); }); diff --git a/bun.lockb b/bun.lockb index 72c44113..d0ba8ae4 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/pkgs/core/server/api-ctx.ts b/pkgs/core/server/api-ctx.ts index 044b7fbf..2ad8c0c5 100644 --- a/pkgs/core/server/api-ctx.ts +++ b/pkgs/core/server/api-ctx.ts @@ -51,8 +51,15 @@ export const createResponse = (existingRes: any, body: any) => { const status = typeof existingRes._status === "number" ? existingRes._status : undefined; + let finalBody = body; + if (body instanceof Buffer) { + } else { + finalBody = + typeof body === "string" ? body : JSON.stringify(body, replacer); + } + let res = new Response( - typeof body === "string" ? body : JSON.stringify(body, replacer), + finalBody, status ? { status, @@ -61,12 +68,14 @@ export const createResponse = (existingRes: any, body: any) => { ); if (typeof body === "object") { - res.headers.append("content-type", "application/json"); + if (!res.headers.get("content-type")) { + res.headers.set("content-type", "application/json"); + } } const cur = existingRes as Response; for (const [key, value] of cur.headers.entries()) { - res.headers.append(key, value); + res.headers.set(key, value); } return res; diff --git a/pkgs/core/server/serve-api.ts b/pkgs/core/server/serve-api.ts index 4d1d9eba..4596bee2 100644 --- a/pkgs/core/server/serve-api.ts +++ b/pkgs/core/server/serve-api.ts @@ -74,6 +74,20 @@ export const serveAPI = async (url: URL, req: Request) => { if (finalResponse) { return createResponse(current.res, finalResponse); } + if ( + (current.res as any)._status && + (current.res as any)._status !== current.res.status + ) { + const res = new Response(current.res.body, { + status: (current.res as any)._status, + }); + + current.res.headers.forEach((v, k) => { + res.headers.set(k, v); + }); + + return res; + } return current.res; } diff --git a/pkgs/web-utils/src/global.ts b/pkgs/web-utils/src/global.ts index 6fd446cf..6759005c 100644 --- a/pkgs/web-utils/src/global.ts +++ b/pkgs/web-utils/src/global.ts @@ -4,7 +4,7 @@ declare global { const navigate: (path: string) => void; const params: any; const css: typeof goober.css; - const cx: (...arg: string[]) => string; + const cx: (...arg: any[]) => string; const api: any; const db: PrismaClient; const prasiContext: any;