From cbab0edec2754d410104a369d3c83f8dca74a19c Mon Sep 17 00:00:00 2001 From: Rizky Date: Sun, 15 Oct 2023 23:08:00 +0700 Subject: [PATCH] fix server content-type --- app/srv/api/npm-bundle.ts | 189 ++++++ app/srv/api/npm-size.ts | 16 + app/srv/api/npm.ts | 5 +- app/srv/exports.d.ts | 582 +++++++++++++++++- app/srv/exports.ts | 14 + app/srv/package.json | 3 + app/web/src/base/page/ed.tsx | 3 +- app/web/src/base/page/editor.tsx | 3 +- .../editor/panel/manager/site/site-mgr.tsx | 1 + app/web/src/render/live/elements/l-item.tsx | 1 + app/web/src/render/live/elements/l-page.tsx | 6 +- app/web/src/render/live/logic/tree-scope.tsx | 5 +- app/web/src/sworker.ts | 31 +- bun.lockb | Bin 9067 -> 18646 bytes pkgs/core/server/api-ctx.ts | 15 +- pkgs/core/server/serve-api.ts | 14 + pkgs/web-utils/src/global.ts | 2 +- 17 files changed, 856 insertions(+), 34 deletions(-) create mode 100644 app/srv/api/npm-bundle.ts create mode 100644 app/srv/api/npm-size.ts 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 72c44113b21c8618b92645a8053eaf377badd9d5..d0ba8ae4464cb5e274a27bff4ac2077c52f3b7d0 100755 GIT binary patch literal 18646 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 Tjkko;yfR04vEOc{Zs)N- { 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;