fix export

This commit is contained in:
Rizky 2023-10-25 14:03:17 +07:00
parent ec4aae0111
commit 49e1569b07
5 changed files with 251 additions and 174 deletions

View File

@ -11,179 +11,12 @@ import { g } from "utils/global";
import { validate } from "uuid"; import { validate } from "uuid";
import { glb } from "../global"; import { glb } from "../global";
import { eg } from "../ws/edit/edit-global"; import { eg } from "../ws/edit/edit-global";
import { buildNpm } from "../util/build-npm";
export type NPMImportAs = {
main: { mode: "default" | "*"; name: string };
names: string[];
custom?: string;
};
export const _ = { export const _ = {
url: "/npm-bundle/:mode/:id", url: "/npm-bundle/:mode/:id",
async api(mode: "site" | "page", id: string) { async api(mode: "site" | "page", id: string) {
const {} = apiContext(this); const {} = apiContext(this);
if (!validate(id)) return "-"; return await buildNpm({ id, mode });
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<string, string> = {};
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 "-";
}
}, },
}; };

View File

@ -48,7 +48,7 @@ export const _ = {
} }
} }
if (path.length > dir.path(`../npm/${mode}/${id}`).length) { if (path.length > dir.path(`${g.datadir}/npm/${mode}/${id}`).length) {
const file = await readAsync(path, "buffer"); const file = await readAsync(path, "buffer");
if (file) { if (file) {

View File

@ -5,6 +5,8 @@ import fs from "fs";
import { exists } from "fs-jetpack"; import { exists } from "fs-jetpack";
import { gzipSync } from "zlib"; import { gzipSync } from "zlib";
import path from "path"; import path from "path";
import { g } from "utils/global";
import { buildNpm } from "../util/build-npm";
export const _ = { export const _ = {
url: "/site-export/:site_id", url: "/site-export/:site_id",
@ -19,7 +21,7 @@ export const _ = {
is_deleted: false, is_deleted: false,
name: { not: { startsWith: "layout:" } }, name: { not: { startsWith: "layout:" } },
}, },
}); });
if (site) { if (site) {
const layout = await db.page.findFirst({ const layout = await db.page.findFirst({
@ -67,12 +69,39 @@ export const _ = {
site: {} as Record<string, string>, site: {} as Record<string, string>,
pages: {} as Record<string, Record<string, string>>, pages: {} as Record<string, Record<string, string>>,
}; };
npm.site = readDirectoryRecursively(dir.path(`../npm/site/${site_id}`)); const page_ids = await db.page.findMany({
where: { id_site: site_id, is_deleted: false },
select: { id: true },
});
const npm_page = await db.npm_page.findMany({
where: { id_page: { in: page_ids.map((e) => e.id) } },
});
if (!exists(dir.path(`${g.datadir}/npm/site/${site_id}`))) {
await buildNpm({ id: site_id, mode: "site" });
}
const npm_page_ids = {} as Record<string, any[]>;
for (const np of npm_page) {
if (!npm_page_ids[np.id_page]) {
npm_page_ids[np.id_page] = [];
}
npm_page_ids[np.id_page].push(np);
}
for (const [k, v] of Object.entries(npm_page_ids)) {
if (!exists(dir.path(`${g.datadir}/npm/page/${k}`))) {
await buildNpm({ id: k, mode: "page", _items: v });
}
}
npm.site = readDirectoryRecursively(
dir.path(`${g.datadir}/npm/site/${site_id}`)
);
for (const page of pages) { for (const page of pages) {
if (exists(dir.path(`../npm/page/${page.id}`))) { if (exists(dir.path(`${g.datadir}/npm/page/${page.id}`))) {
npm.pages[page.id] = readDirectoryRecursively( npm.pages[page.id] = readDirectoryRecursively(
dir.path(`../npm/page/${page.id}`) dir.path(`${g.datadir}/npm/page/${page.id}`)
); );
} }
} }
@ -99,6 +128,7 @@ function readDirectoryRecursively(
result[[...(baseDir || []), item].join("/")] = content; result[[...(baseDir || []), item].join("/")] = content;
} else if (stats.isDirectory()) { } else if (stats.isDirectory()) {
if (item !== "node_modules") { if (item !== "node_modules") {
console.log(itemPath);
const subdirResult = readDirectoryRecursively(itemPath, [ const subdirResult = readDirectoryRecursively(itemPath, [
...(baseDir || []), ...(baseDir || []),
item, item,

194
app/srv/util/build-npm.ts Normal file
View File

@ -0,0 +1,194 @@
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 buildNpm = async ({
id,
mode,
_items,
}: {
id: string;
mode: "site" | "page";
_items?: npm_page[] | npm_site[];
}) => {
if (!validate(id)) return "-";
let items = _items;
if (!items) {
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<string, string> = {};
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 "-";
}
};

View File

@ -0,0 +1,20 @@
import { Popover } from "../../../../utils/ui/popover";
export const EdPopUser = (users: { id: string; username: string }[]) => {
return (
<Popover>
<div className="ed-pop-user">
<div className="ed-pop-user-list">
{users.map((user) => (
<div key={user.id} className="ed-pop-user-item">
<div className="ed-pop-user-item-avatar">
<img src="" alt="" />
</div>
<div className="ed-pop-user-item-username">{user.username}</div>
</div>
))}
</div>
</div>
</Popover>
);
};