This commit is contained in:
Rizky 2024-05-08 04:27:14 +07:00
parent d807a82aa9
commit b0f9240dee
13 changed files with 340 additions and 173 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -2,6 +2,10 @@
"extends": [ "extends": [
"@parcel/config-default" "@parcel/config-default"
], ],
"runtimes": [
"parcel-runtime-custom-service-worker",
"..."
],
"reporters": [ "reporters": [
"...", "...",
"@tinijs/parcel-reporter-copy-public" "@tinijs/parcel-reporter-copy-public"
@ -15,4 +19,4 @@
"@parcel/transformer-raw" "@parcel/transformer-raw"
] ]
} }
} }

145
app/web/.service-worker-rc Normal file
View File

@ -0,0 +1,145 @@
{
"filesToCache": [
"public/favicon.ico",
"public/index.html",
"public/min/vs/loader.js",
"public/min/vs/editor/editor.main.nls.ru.js",
"public/min/vs/editor/editor.main.css",
"public/min/vs/editor/editor.main.nls.ko.js",
"public/min/vs/editor/editor.main.nls.zh-cn.js",
"public/min/vs/editor/editor.main.js",
"public/min/vs/editor/editor.main.nls.ja.js",
"public/min/vs/editor/editor.main.nls.zh-tw.js",
"public/min/vs/editor/editor.main.nls.de.js",
"public/min/vs/editor/editor.main.nls.it.js",
"public/min/vs/editor/editor.main.nls.es.js",
"public/min/vs/editor/editor.main.nls.js",
"public/min/vs/editor/editor.main.nls.fr.js",
"public/min/vs/base/worker/workerMain.js",
"public/min/vs/base/common/worker/simpleWorker.nls.it.js",
"public/min/vs/base/common/worker/simpleWorker.nls.es.js",
"public/min/vs/base/common/worker/simpleWorker.nls.fr.js",
"public/min/vs/base/common/worker/simpleWorker.nls.de.js",
"public/min/vs/base/common/worker/simpleWorker.nls.js",
"public/min/vs/base/common/worker/simpleWorker.nls.ja.js",
"public/min/vs/base/common/worker/simpleWorker.nls.ru.js",
"public/min/vs/base/common/worker/simpleWorker.nls.zh-cn.js",
"public/min/vs/base/common/worker/simpleWorker.nls.zh-tw.js",
"public/min/vs/base/common/worker/simpleWorker.nls.ko.js",
"public/min/vs/base/browser/ui/codicons/codicon/codicon.ttf",
"public/min/vs/language/json/jsonWorker.js",
"public/min/vs/language/json/jsonMode.js",
"public/min/vs/language/html/htmlMode.js",
"public/min/vs/language/html/htmlWorker.js",
"public/min/vs/language/typescript/tsWorker.js",
"public/min/vs/language/typescript/tsMode.js",
"public/min/vs/language/css/cssMode.js",
"public/min/vs/language/css/cssWorker.js",
"public/min/vs/basic-languages/sql/sql.js",
"public/min/vs/basic-languages/flow9/flow9.js",
"public/min/vs/basic-languages/ruby/ruby.js",
"public/min/vs/basic-languages/ecl/ecl.js",
"public/min/vs/basic-languages/protobuf/protobuf.js",
"public/min/vs/basic-languages/objective-c/objective-c.js",
"public/min/vs/basic-languages/restructuredtext/restructuredtext.js",
"public/min/vs/basic-languages/wgsl/wgsl.js",
"public/min/vs/basic-languages/msdax/msdax.js",
"public/min/vs/basic-languages/twig/twig.js",
"public/min/vs/basic-languages/bicep/bicep.js",
"public/min/vs/basic-languages/javascript/javascript.js",
"public/min/vs/basic-languages/bat/bat.js",
"public/min/vs/basic-languages/julia/julia.js",
"public/min/vs/basic-languages/csharp/csharp.js",
"public/min/vs/basic-languages/yaml/yaml.js",
"public/min/vs/basic-languages/m3/m3.js",
"public/min/vs/basic-languages/pgsql/pgsql.js",
"public/min/vs/basic-languages/csp/csp.js",
"public/min/vs/basic-languages/coffee/coffee.js",
"public/min/vs/basic-languages/mysql/mysql.js",
"public/min/vs/basic-languages/qsharp/qsharp.js",
"public/min/vs/basic-languages/graphql/graphql.js",
"public/min/vs/basic-languages/swift/swift.js",
"public/min/vs/basic-languages/cpp/cpp.js",
"public/min/vs/basic-languages/hcl/hcl.js",
"public/min/vs/basic-languages/scala/scala.js",
"public/min/vs/basic-languages/handlebars/handlebars.js",
"public/min/vs/basic-languages/ini/ini.js",
"public/min/vs/basic-languages/tcl/tcl.js",
"public/min/vs/basic-languages/pla/pla.js",
"public/min/vs/basic-languages/mips/mips.js",
"public/min/vs/basic-languages/powershell/powershell.js",
"public/min/vs/basic-languages/vb/vb.js",
"public/min/vs/basic-languages/redshift/redshift.js",
"public/min/vs/basic-languages/st/st.js",
"public/min/vs/basic-languages/solidity/solidity.js",
"public/min/vs/basic-languages/pascaligo/pascaligo.js",
"public/min/vs/basic-languages/xml/xml.js",
"public/min/vs/basic-languages/lua/lua.js",
"public/min/vs/basic-languages/php/php.js",
"public/min/vs/basic-languages/cypher/cypher.js",
"public/min/vs/basic-languages/kotlin/kotlin.js",
"public/min/vs/basic-languages/abap/abap.js",
"public/min/vs/basic-languages/html/html.js",
"public/min/vs/basic-languages/java/java.js",
"public/min/vs/basic-languages/liquid/liquid.js",
"public/min/vs/basic-languages/freemarker2/freemarker2.js",
"public/min/vs/basic-languages/r/r.js",
"public/min/vs/basic-languages/fsharp/fsharp.js",
"public/min/vs/basic-languages/pug/pug.js",
"public/min/vs/basic-languages/rust/rust.js",
"public/min/vs/basic-languages/typescript/typescript.js",
"public/min/vs/basic-languages/perl/perl.js",
"public/min/vs/basic-languages/sophia/sophia.js",
"public/min/vs/basic-languages/scss/scss.js",
"public/min/vs/basic-languages/markdown/markdown.js",
"public/min/vs/basic-languages/shell/shell.js",
"public/min/vs/basic-languages/dart/dart.js",
"public/min/vs/basic-languages/dockerfile/dockerfile.js",
"public/min/vs/basic-languages/lexon/lexon.js",
"public/min/vs/basic-languages/redis/redis.js",
"public/min/vs/basic-languages/elixir/elixir.js",
"public/min/vs/basic-languages/less/less.js",
"public/min/vs/basic-languages/clojure/clojure.js",
"public/min/vs/basic-languages/css/css.js",
"public/min/vs/basic-languages/python/python.js",
"public/min/vs/basic-languages/azcli/azcli.js",
"public/min/vs/basic-languages/sparql/sparql.js",
"public/min/vs/basic-languages/systemverilog/systemverilog.js",
"public/min/vs/basic-languages/go/go.js",
"public/min/vs/basic-languages/apex/apex.js",
"public/min/vs/basic-languages/powerquery/powerquery.js",
"public/min/vs/basic-languages/razor/razor.js",
"public/min/vs/basic-languages/cameligo/cameligo.js",
"public/min/vs/basic-languages/pascal/pascal.js",
"public/min/vs/basic-languages/mdx/mdx.js",
"public/min/vs/basic-languages/sb/sb.js",
"public/min/vs/basic-languages/scheme/scheme.js",
"public/min/vs/basic-languages/postiats/postiats.js",
"public/min-maps/vs/loader.js.map",
"public/min-maps/vs/editor/editor.main.nls.ko.js.map",
"public/min-maps/vs/editor/editor.main.nls.ja.js.map",
"public/min-maps/vs/editor/editor.main.nls.fr.js.map",
"public/min-maps/vs/editor/editor.main.nls.zh-cn.js.map",
"public/min-maps/vs/editor/editor.main.nls.js.map",
"public/min-maps/vs/editor/editor.main.js.map",
"public/min-maps/vs/editor/editor.main.nls.it.js.map",
"public/min-maps/vs/editor/editor.main.nls.zh-tw.js.map",
"public/min-maps/vs/editor/editor.main.nls.ru.js.map",
"public/min-maps/vs/editor/editor.main.nls.es.js.map",
"public/min-maps/vs/editor/editor.main.nls.de.js.map",
"public/min-maps/vs/base/worker/workerMain.js.map",
"public/min-maps/vs/base/common/worker/simpleWorker.nls.js.map",
"public/min-maps/vs/base/common/worker/simpleWorker.nls.zh-tw.js.map",
"public/min-maps/vs/base/common/worker/simpleWorker.nls.ko.js.map",
"public/min-maps/vs/base/common/worker/simpleWorker.nls.ja.js.map",
"public/min-maps/vs/base/common/worker/simpleWorker.nls.fr.js.map",
"public/min-maps/vs/base/common/worker/simpleWorker.nls.ru.js.map",
"public/min-maps/vs/base/common/worker/simpleWorker.nls.it.js.map",
"public/min-maps/vs/base/common/worker/simpleWorker.nls.es.js.map",
"public/min-maps/vs/base/common/worker/simpleWorker.nls.zh-cn.js.map",
"public/min-maps/vs/base/common/worker/simpleWorker.nls.de.js.map",
"public/img/empty.png",
"public/img/logo-white.png",
"public/img/logo.png"
]
}

View File

@ -10,28 +10,22 @@
"@floating-ui/react": "^0.26.4", "@floating-ui/react": "^0.26.4",
"@leeoniya/ufuzzy": "^1.0.14", "@leeoniya/ufuzzy": "^1.0.14",
"@minoru/react-dnd-treeview": "^3.4.4", "@minoru/react-dnd-treeview": "^3.4.4",
"@wojtekmaj/react-qr-svg": "^1.0.0",
"constrained-editor-plugin": "^1.3.0",
"react-resizable-panels": "^2.0.9",
"json-diff-ts": "^2.2.1",
"axios": "^1.6.7",
"@monaco-editor/react": "^4.6.0", "@monaco-editor/react": "^4.6.0",
"@paralleldrive/cuid2": "2.2.2", "@paralleldrive/cuid2": "2.2.2",
"react-contenteditable": "^3.3.7",
"react-dropzone": "14.2.3",
"@parcel/packager-wasm": "^2.10.3", "@parcel/packager-wasm": "^2.10.3",
"@parcel/service-worker": "^2.10.3",
"recast": "^0.23.4",
"@qiwi/deep-proxy": "^2.0.3", "@qiwi/deep-proxy": "^2.0.3",
"@wojtekmaj/react-qr-svg": "^1.0.0",
"algoliasearch": "^4.22.0", "algoliasearch": "^4.22.0",
"axios": "^1.6.7",
"constrained-editor-plugin": "^1.3.0",
"date-fns": "^2.30.0", "date-fns": "^2.30.0",
"safe-flat": "^2.1.0",
"dbgen": "workspace:*", "dbgen": "workspace:*",
"esbuild-wasm": "^0.19.10", "esbuild-wasm": "^0.19.10",
"hash-wasm": "^4.11.0", "hash-wasm": "^4.11.0",
"idb-keyval": "^6.2.1", "idb-keyval": "^6.2.1",
"immer": "^10.0.3", "immer": "^10.0.3",
"js-base64": "^3.7.5", "js-base64": "^3.7.5",
"json-diff-ts": "^2.2.1",
"lodash.capitalize": "^4.2.1", "lodash.capitalize": "^4.2.1",
"lodash.concat": "^4.5.0", "lodash.concat": "^4.5.0",
"lodash.debounce": "^4.0.8", "lodash.debounce": "^4.0.8",
@ -49,6 +43,8 @@
"lodash.uniqby": "^4.7.0", "lodash.uniqby": "^4.7.0",
"monaco-jsx-syntax-highlight-v2": "^1.2.2", "monaco-jsx-syntax-highlight-v2": "^1.2.2",
"msgpackr": "^1.10.0", "msgpackr": "^1.10.0",
"pako": "^2.1.0",
"parcel-plugin-custom-service-worker": "^1.0.2",
"polywasm": "^0.1.4", "polywasm": "^0.1.4",
"prettier": "3.1.1", "prettier": "3.1.1",
"prop-types": "^15.8.1", "prop-types": "^15.8.1",
@ -56,18 +52,22 @@
"radix3": "^1.1.0", "radix3": "^1.1.0",
"react": "18.2.0", "react": "18.2.0",
"react-colorful": "^5.6.1", "react-colorful": "^5.6.1",
"react-contenteditable": "^3.3.7",
"react-dnd": "^16.0.1", "react-dnd": "^16.0.1",
"react-dom": "18.2.0", "react-dom": "18.2.0",
"react-dropzone": "14.2.3",
"react-is": "^18.2.0", "react-is": "^18.2.0",
"react-resizable-panels": "^2.0.9",
"react-use-error-boundary": "^3.0.0", "react-use-error-boundary": "^3.0.0",
"react-virtuoso": "^4.6.2", "react-virtuoso": "^4.6.2",
"recast": "^0.23.4",
"safe-flat": "^2.1.0",
"safe-stable-stringify": "^2.4.3", "safe-stable-stringify": "^2.4.3",
"svgo": "^3.1.0", "svgo": "^3.1.0",
"textdiff-create": "^1.1.10", "textdiff-create": "^1.1.10",
"tinycolor2": "^1.6.0", "tinycolor2": "^1.6.0",
"ua-parser-js": "^1.0.37", "ua-parser-js": "^1.0.37",
"uuid": "9.0.1", "uuid": "9.0.1",
"pako": "^2.1.0",
"wasm-gzip": "^2.0.3", "wasm-gzip": "^2.0.3",
"web-utils": "workspace:*", "web-utils": "workspace:*",
"y-pojo": "^0.0.8", "y-pojo": "^0.0.8",

View File

@ -1,110 +1,110 @@
import { manifest } from "@parcel/service-worker"; import { manifest } from "parcel-plugin-custom-service-worker";
import { RadixRouter, createRouter } from "radix3"; import { RadixRouter, createRouter } from "radix3";
import { version } from "../timestamp"; import { version } from "../timestamp";
const g = { const g = {
router: null as null | RadixRouter<any>, router: null as null | RadixRouter<any>,
offline: false, offline: false,
broadcast(msg: any) { broadcast(msg: any) {
// @ts-ignore // @ts-ignore
const c: Clients = self.clients; const c: Clients = self.clients;
c.matchAll({ includeUncontrolled: true }).then((clients) => { c.matchAll({ includeUncontrolled: true }).then((clients) => {
clients.forEach((client) => { clients.forEach((client) => {
client.postMessage(msg); client.postMessage(msg);
}); });
}); });
}, },
}; };
async function install() { async function install() {
const cache = await caches.open(version); const cache = await caches.open(version);
await cache.addAll(manifest); await cache.addAll(manifest);
g.broadcast({ type: "installed" }); g.broadcast({ type: "installed" });
} }
addEventListener("install", (e) => (e as ExtendableEvent).waitUntil(install())); addEventListener("install", (e) => (e as ExtendableEvent).waitUntil(install()));
async function activate() { async function activate() {
let shouldRefresh = false; let shouldRefresh = false;
if (!g.offline) { if (!g.offline) {
const keys = await caches.keys(); const keys = await caches.keys();
await Promise.all( await Promise.all(
keys.map(async (key) => { keys.map(async (key) => {
if (key !== version) { if (key !== version) {
await caches.delete(key); await caches.delete(key);
shouldRefresh = true; shouldRefresh = true;
} }
}), })
); );
g.broadcast({ type: "activated", shouldRefresh, version }); g.broadcast({ type: "activated", shouldRefresh, version });
} }
} }
addEventListener("activate", (e) => addEventListener("activate", (e) =>
(e as ExtendableEvent).waitUntil(activate()), (e as ExtendableEvent).waitUntil(activate())
); );
addEventListener("fetch", async (evt) => { addEventListener("fetch", async (evt) => {
const e = evt as FetchEvent; const e = evt as FetchEvent;
const url = new URL(e.request.url); const url = new URL(e.request.url);
if (g.router) { if (g.router) {
const found = g.router.lookup(url.pathname); const found = g.router.lookup(url.pathname);
if (found) { if (found) {
return; return;
} }
} }
e.respondWith( e.respondWith(
(async () => { (async () => {
const r = await caches.match(e.request); const r = await caches.match(e.request);
if (r) { if (r) {
return r; return r;
} }
try { try {
g.offline = false; g.offline = false;
return await fetch(e.request); return await fetch(e.request);
} catch (e) { } catch (e) {
g.offline = true; g.offline = true;
g.broadcast({ type: "offline" }); g.broadcast({ type: "offline" });
return new Response(); return new Response();
} }
})(), })()
); );
}); });
addEventListener("message", async (e) => { addEventListener("message", async (e) => {
const type = e.data.type; const type = e.data.type;
const cache = await caches.open(version); const cache = await caches.open(version);
switch (type) { switch (type) {
case "add-cache": case "add-cache":
{ {
const cached = await cache.match(e.data.url); const cached = await cache.match(e.data.url);
if (!cached) { if (!cached) {
await cache.add(e.data.url); await cache.add(e.data.url);
} }
} }
break; break;
case "define-route": case "define-route":
g.router = createRouter({ strictTrailingSlash: false }); g.router = createRouter({ strictTrailingSlash: false });
for (const route of e.data.routes) { for (const route of e.data.routes) {
g.router.insert(route.url, route); g.router.insert(route.url, route);
} }
await activate(); await activate();
break; break;
case "force-update": case "force-update":
{ {
const keys = await caches.keys(); const keys = await caches.keys();
await Promise.all( await Promise.all(
keys.map(async (key) => { keys.map(async (key) => {
if (key !== version) { if (key !== version) {
await caches.delete(key); await caches.delete(key);
} }
}), })
); );
await install(); await install();
} }
break; break;
} }
}); });

BIN
bun.lockb

Binary file not shown.

View File

@ -1,100 +1,118 @@
import { createId } from "@paralleldrive/cuid2"; import { createId } from "@paralleldrive/cuid2";
import brotliPromise from "brotli-wasm"; import brotliPromise from "brotli-wasm";
import { spawn } from "bun"; import { Glob, spawn } from "bun";
import { dir } from "dir"; import { dir } from "dir";
import { fdir } from "fdir"; import { fdir } from "fdir";
import { statSync } from "fs"; import { statSync } from "fs";
import { copyAsync, existsAsync, listAsync, removeAsync, writeAsync } from "fs-jetpack"; import {
copyAsync,
existsAsync,
listAsync,
removeAsync,
writeAsync,
} from "fs-jetpack";
const brotli = await brotliPromise; const brotli = await brotliPromise;
const glob = new Glob("**");
const swrc = {
filesToCache: [] as string[],
};
for await (const file of glob.scan(dir.path("app/web/public"))) {
swrc.filesToCache.push(`public/${file}`);
}
await Bun.write(
dir.path("app/web/.service-worker-rc"),
JSON.stringify(swrc, null, 2)
);
await removeAsync(dir.path("app/web/.parcel-cache")); await removeAsync(dir.path("app/web/.parcel-cache"));
await removeAsync(dir.path("app/static")); await removeAsync(dir.path("app/static"));
await writeAsync( await writeAsync(
dir.path("app/web/timestamp.ts"), dir.path("app/web/timestamp.ts"),
`export const version = "${createId().substring(0, 7)}";`, `export const version = "${createId().substring(0, 7)}";`
); );
const args = [ const args = [
"node", "node",
dir.path("node_modules/.bin/parcel"), dir.path("node_modules/.bin/parcel"),
"build", "build",
"./src/index.tsx", "./src/index.tsx",
// "--no-optimize", // "--no-optimize",
"--no-scope-hoist", "--no-scope-hoist",
"--dist-dir", "--dist-dir",
dir.path(`app/static`), dir.path(`app/static`),
]; ];
const parcel = spawn({ const parcel = spawn({
cmd: args, cmd: args,
cwd: dir.path("app/web"), cwd: dir.path("app/web"),
stdio: ["ignore", "inherit", "inherit"], stdio: ["ignore", "inherit", "inherit"],
}); });
await parcel.exited; await parcel.exited;
const public_br = dir.path("app/web/public-br"); const public_br = dir.path("app/web/public-br");
if (!(await existsAsync(public_br))) { if (!(await existsAsync(public_br))) {
const api = new fdir().withRelativePaths().crawl(dir.path("app/web/public")); const api = new fdir().withRelativePaths().crawl(dir.path("app/web/public"));
const files = api.sync(); const files = api.sync();
if (files) { if (files) {
await Promise.all( await Promise.all(
files.map(async (file) => { files.map(async (file) => {
const br = brotli.compress( const br = brotli.compress(
new Uint8Array( new Uint8Array(
await Bun.file(dir.path(`app/web/public/${file}`)).arrayBuffer(), await Bun.file(dir.path(`app/web/public/${file}`)).arrayBuffer()
), ),
{ quality: 11 }, { quality: 11 }
); );
if (br) { if (br) {
console.log(`Compressing [public] ${file}`); console.log(`Compressing [public] ${file}`);
await writeAsync( await writeAsync(
dir.path(`app/web/public-br/${file}`), dir.path(`app/web/public-br/${file}`),
Buffer.from(br), Buffer.from(br)
); );
} }
}), })
); );
} }
} }
const static_br = dir.path("app/static-br"); const static_br = dir.path("app/static-br");
await removeAsync(static_br); await removeAsync(static_br);
const files = await listAsync(dir.path("app/static")); const files = await listAsync(dir.path("app/static"));
if (files) { if (files) {
await Promise.all( await Promise.all(
files files
.filter((file) => statSync(dir.path(`app/static/${file}`)).isFile()) .filter((file) => statSync(dir.path(`app/static/${file}`)).isFile())
.map(async (file) => { .map(async (file) => {
if (!(await Bun.file(dir.path(`app/static-br/${file}`)).exists())) { if (!(await Bun.file(dir.path(`app/static-br/${file}`)).exists())) {
const br = brotli.compress( const br = brotli.compress(
new Uint8Array( new Uint8Array(
await Bun.file(dir.path(`app/static/${file}`)).arrayBuffer(), await Bun.file(dir.path(`app/static/${file}`)).arrayBuffer()
), ),
{ quality: 11 }, { quality: 11 }
); );
if (br) { if (br) {
console.log(`Compressing [static] ${file}`); console.log(`Compressing [static] ${file}`);
await writeAsync( await writeAsync(
dir.path(`app/static-br/${file}`), dir.path(`app/static-br/${file}`),
Buffer.from(br), Buffer.from(br)
); );
} }
} }
}), })
); );
const pub = await listAsync(dir.path("app/web/public-br")); const pub = await listAsync(dir.path("app/web/public-br"));
if (pub) { if (pub) {
await Promise.all( await Promise.all(
pub.map(async (file) => { pub.map(async (file) => {
if (await existsAsync(`app/static-br/${file}`)) { if (await existsAsync(`app/static-br/${file}`)) {
await removeAsync(`app/static-br/${file}`); await removeAsync(`app/static-br/${file}`);
} }
await copyAsync( await copyAsync(
dir.path(`app/web/public-br/${file}`), dir.path(`app/web/public-br/${file}`),
dir.path(`app/static-br/${file}`), dir.path(`app/static-br/${file}`)
); );
}), })
); );
} }
} }