check point
This commit is contained in:
parent
20606a83ca
commit
8aa920ac52
|
|
@ -58,20 +58,22 @@ export const _ = {
|
|||
}
|
||||
}
|
||||
|
||||
const res = JSON.stringify(await parseTypeDef(path));
|
||||
await Bun.write(
|
||||
dir.data(
|
||||
`/code/${site_id}/site/type_def.${file.lastModified}.json`
|
||||
),
|
||||
res
|
||||
);
|
||||
try {
|
||||
const res = JSON.stringify(await parseTypeDef(path));
|
||||
await Bun.write(
|
||||
dir.data(
|
||||
`/code/${site_id}/site/type_def.${file.lastModified}.json`
|
||||
),
|
||||
res
|
||||
);
|
||||
|
||||
return new Response(Bun.gzipSync(res), {
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
"content-encoding": "gzip",
|
||||
},
|
||||
});
|
||||
return new Response(Bun.gzipSync(res), {
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
"content-encoding": "gzip",
|
||||
},
|
||||
});
|
||||
} catch (e) {}
|
||||
}
|
||||
return new Response("{}", {
|
||||
headers: { "content-type": "application/json" },
|
||||
|
|
@ -79,17 +81,25 @@ export const _ = {
|
|||
}
|
||||
case "typings.d.ts": {
|
||||
const build_path = dir.data(`/code/${site_id}/site/typings.d.ts`);
|
||||
const file = Bun.file(build_path);
|
||||
let file = Bun.file(build_path);
|
||||
|
||||
if (!(await file.exists())) {
|
||||
const root = `/code/${site_id}/site/src`;
|
||||
await initFrontEnd(root, site_id);
|
||||
file = Bun.file(build_path);
|
||||
}
|
||||
const body = Bun.gzipSync(await file.arrayBuffer());
|
||||
|
||||
return new Response(body, {
|
||||
headers: { "content-type": file.type, "content-encoding": "gzip" },
|
||||
});
|
||||
if (await file.exists()) {
|
||||
const body = Bun.gzipSync(await file.arrayBuffer());
|
||||
|
||||
return new Response(body, {
|
||||
headers: {
|
||||
"content-type": file.type,
|
||||
"content-encoding": "gzip",
|
||||
},
|
||||
});
|
||||
}
|
||||
return new Response("", { status: 403 });
|
||||
}
|
||||
case "code": {
|
||||
const arr = pathname.split("/").slice(2);
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -10,7 +10,6 @@ export const parseTypeDef = async (path: string) => {
|
|||
const ast = await parseFile(path, { syntax: "typescript" });
|
||||
|
||||
const exports = {} as Record<string, SingleExport[]>;
|
||||
|
||||
visit(ast, {
|
||||
visitWithPath: {
|
||||
visitDecl(node, path) {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@ import { cleanPlugin } from "esbuild-clean-plugin";
|
|||
import isEqual from "lodash.isequal";
|
||||
import { appendFile } from "node:fs/promises";
|
||||
import { code } from "../../code";
|
||||
import { user } from "../../../entity/user";
|
||||
import { conns } from "../../../entity/conn";
|
||||
import { SyncType } from "../../../type";
|
||||
import { sendWS } from "../../../sync-handler";
|
||||
|
||||
const decoder = new TextDecoder();
|
||||
export const initFrontEnd = async (
|
||||
|
|
@ -74,6 +78,22 @@ export const initFrontEnd = async (
|
|||
await installDeps(root, res, id_site);
|
||||
} else {
|
||||
await codeError(id_site, "");
|
||||
|
||||
const client_ids = new Set<string>();
|
||||
user.active.findAll({ site_id: id_site }).forEach((e) => {
|
||||
client_ids.add(e.client_id);
|
||||
});
|
||||
|
||||
const now = Date.now();
|
||||
client_ids.forEach((client_id) => {
|
||||
const ws = conns.get(client_id)?.ws;
|
||||
if (ws)
|
||||
sendWS(ws, {
|
||||
type: SyncType.Event,
|
||||
event: "code_changes",
|
||||
data: { ts: now, mode: "frontend" },
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,10 @@ import { watch } from "fs";
|
|||
import { Glob } from "bun";
|
||||
import { removeAsync } from "fs-jetpack";
|
||||
import { parseTypeDef } from "../../../../../util/parse-type-def";
|
||||
import { user } from "../../../entity/user";
|
||||
import { conns } from "../../../entity/conn";
|
||||
import { sendWS } from "../../../sync-handler";
|
||||
import { SyncType } from "../../../type";
|
||||
export const initTypings = async (
|
||||
root: string,
|
||||
id_site: string,
|
||||
|
|
@ -21,9 +25,15 @@ export const initTypings = async (
|
|||
}
|
||||
|
||||
try {
|
||||
const typings_path = dir.data(`/code/${id_site}/site/typings.d.ts`);
|
||||
const typings_file = Bun.file(typings_path);
|
||||
|
||||
if (!(await typings_file.exists())) {
|
||||
return false;
|
||||
}
|
||||
code.internal.typings[id_site] = {
|
||||
timeout: Date.now(),
|
||||
watch: watch(dir.data(`/code/${id_site}/site/typings.d.ts`)),
|
||||
watch: watch(typings_path),
|
||||
spawn: Bun.spawn({
|
||||
cmd: [
|
||||
...`tsc --watch --moduleResolution node --emitDeclarationOnly --outFile ../typings.d.ts --declaration --noEmit false`.split(
|
||||
|
|
@ -69,6 +79,22 @@ export const initTypings = async (
|
|||
dir.data(`/code/${id_site}/site/type_def.${file.lastModified}.json`),
|
||||
res
|
||||
);
|
||||
|
||||
const client_ids = new Set<string>();
|
||||
user.active.findAll({ site_id: id_site }).forEach((e) => {
|
||||
client_ids.add(e.client_id);
|
||||
});
|
||||
|
||||
const now = Date.now();
|
||||
client_ids.forEach((client_id) => {
|
||||
const ws = conns.get(client_id)?.ws;
|
||||
if (ws)
|
||||
sendWS(ws, {
|
||||
type: SyncType.Event,
|
||||
event: "code_changes",
|
||||
data: { ts: now, mode: "typings" },
|
||||
});
|
||||
});
|
||||
}, 180);
|
||||
});
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -1,18 +1,28 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"@/*": ["./lib/*"],
|
||||
"app/*": ["./app/*"],
|
||||
"server/*": ["./server/*"]
|
||||
"lib/*": [
|
||||
"./lib/*"
|
||||
],
|
||||
"app/*": [
|
||||
"./app/*"
|
||||
],
|
||||
"server/*": [
|
||||
"./server/*"
|
||||
],
|
||||
"@/*": [
|
||||
"./lib/*"
|
||||
]
|
||||
},
|
||||
"lib": ["ESNext", "DOM"],
|
||||
"lib": [
|
||||
"ESNext",
|
||||
"DOM"
|
||||
],
|
||||
"module": "esnext",
|
||||
"target": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"moduleDetection": "force",
|
||||
"declaration": true,
|
||||
"outFile": "types.d.ts",
|
||||
"emitDeclarationOnly": true,
|
||||
"moduleResolution": "Node",
|
||||
"noEmit": true,
|
||||
"composite": true,
|
||||
"strict": true,
|
||||
"downlevelIteration": true,
|
||||
|
|
@ -21,6 +31,9 @@
|
|||
"allowSyntheticDefaultImports": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"allowJs": true,
|
||||
"typeRoots": ["./node_modules/@types", "./lib/types"]
|
||||
"typeRoots": [
|
||||
"./node_modules/@types",
|
||||
"./lib/types"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import { PG } from "./ed-global";
|
||||
|
||||
export const loadCode = async (p: PG, ts?: number) => {
|
||||
export const loadFrontEnd = async (p: PG, ts?: number) => {
|
||||
const id_site = p.site.id;
|
||||
const url = `/prod/${id_site}/_prasi/code/index.js?ts=${ts}`;
|
||||
const fn = new Function(
|
||||
|
|
@ -11,41 +11,48 @@ import("${url}")
|
|||
.then(callback)`
|
||||
);
|
||||
try {
|
||||
Promise.all([
|
||||
fetch(`/prod/${id_site}/_prasi/typings.d.ts`)
|
||||
.catch(() => {})
|
||||
.then(async (res) => {
|
||||
if (res) {
|
||||
p.site_dts = await res.text();
|
||||
p.render();
|
||||
await new Promise<any>((resolve) => {
|
||||
try {
|
||||
fn((exports: any) => {
|
||||
const w = window as any;
|
||||
for (const [k, v] of Object.entries(exports)) {
|
||||
w[k] = v;
|
||||
p.site_exports[k] = v;
|
||||
}
|
||||
}),
|
||||
fetch(`/prod/${id_site}/_prasi/type_def`)
|
||||
.catch(() => {})
|
||||
.then(async (res) => {
|
||||
if (res) {
|
||||
p.site_dts_entry = await res.json();
|
||||
p.render();
|
||||
}
|
||||
}),
|
||||
new Promise<any>((resolve) => {
|
||||
try {
|
||||
fn((exports: any) => {
|
||||
const w = window as any;
|
||||
for (const [k, v] of Object.entries(exports)) {
|
||||
w[k] = v;
|
||||
p.site_exports[k] = v;
|
||||
}
|
||||
resolve(exports);
|
||||
});
|
||||
} catch (e) {
|
||||
console.log("Failed to load site code", e);
|
||||
resolve(exports);
|
||||
});
|
||||
} catch (e) {
|
||||
console.log("Failed to load site code", e);
|
||||
}
|
||||
});
|
||||
} catch (e) {}
|
||||
};
|
||||
export const loadTypings = async (p: PG) => {
|
||||
const id_site = p.site.id;
|
||||
await Promise.all([
|
||||
fetch(`/prod/${id_site}/_prasi/typings.d.ts`)
|
||||
.catch(() => {})
|
||||
.then(async (res) => {
|
||||
if (res) {
|
||||
p.site_dts = await res.text();
|
||||
p.render();
|
||||
}
|
||||
}),
|
||||
]);
|
||||
fetch(`/prod/${id_site}/_prasi/type_def`)
|
||||
.catch(() => {})
|
||||
.then(async (res) => {
|
||||
if (res) {
|
||||
p.site_dts_entry = await res.json();
|
||||
p.render();
|
||||
}
|
||||
}),
|
||||
]);
|
||||
};
|
||||
|
||||
export const loadCode = async (p: PG, ts?: number) => {
|
||||
try {
|
||||
await Promise.all([loadTypings(p), loadFrontEnd(p, ts)]);
|
||||
} catch (e) {
|
||||
console.log("Failed to load site code", e);
|
||||
}
|
||||
|
||||
return {};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -202,6 +202,7 @@ export const EDGlobal = {
|
|||
code: {} as Record<string, { doc: null | DCode }>,
|
||||
global_prop: [] as string[],
|
||||
ui: {
|
||||
monaco: null as any,
|
||||
comp_editable: localStorage.getItem("prasi-comp-editable") === "yes",
|
||||
zoom: localStorage.zoom || "100%",
|
||||
side: { prop: true },
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ import { reloadPage } from "./ed-route";
|
|||
import { loadSite } from "./ed-site";
|
||||
import { updateComponentMeta } from "./comp/load";
|
||||
import { createRouter, RadixRouter } from "radix3";
|
||||
import { loadCode } from "./code-loader";
|
||||
import { loadCode, loadFrontEnd, loadTypings } from "./code-loader";
|
||||
import { registerSiteTypings } from "../../../utils/script/typings";
|
||||
|
||||
const decoder = new TextDecoder();
|
||||
|
||||
|
|
@ -183,8 +184,16 @@ export const edInitSync = (p: PG) => {
|
|||
}
|
||||
p.render();
|
||||
},
|
||||
async code_changes({ ts }) {
|
||||
await loadCode(p, ts);
|
||||
async code_changes({ ts, mode }) {
|
||||
if (mode === "frontend") {
|
||||
await loadFrontEnd(p, ts);
|
||||
} else {
|
||||
console.log("Code updated");
|
||||
await loadTypings(p);
|
||||
if (p.ui.monaco) {
|
||||
registerSiteTypings(p.ui.monaco, p);
|
||||
}
|
||||
}
|
||||
await treeRebuild(p);
|
||||
p.render();
|
||||
},
|
||||
|
|
|
|||
|
|
@ -52,10 +52,15 @@ export const EdScriptMonaco: FC<{}> = () => {
|
|||
let val = "";
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
p.ui.monaco = null;
|
||||
p.script.do_edit = async () => {};
|
||||
};
|
||||
}, []);
|
||||
|
||||
if (local.monaco) {
|
||||
p.ui.monaco = local.monaco;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
clearTimeout(scriptEdit.timeout);
|
||||
(async () => {
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ export const jsMount = async (editor: MonacoEditor, monaco: Monaco, p?: PG) => {
|
|||
}
|
||||
|
||||
const compilerOptions: CompilerOptions = {
|
||||
jsx: monaco.languages.typescript.JsxEmit.ReactNative,
|
||||
jsx: monaco.languages.typescript.JsxEmit.ReactJSX,
|
||||
jsxFactory: "React.createElement",
|
||||
jsxFragmentFactory: "React.Fragment",
|
||||
target: monaco.languages.typescript.ScriptTarget.ES2015,
|
||||
|
|
|
|||
|
|
@ -8,16 +8,12 @@ type Monaco = Parameters<OnMount>[1];
|
|||
|
||||
const map = new WeakMap<any>();
|
||||
|
||||
export const monacoTypings = async (
|
||||
export const registerSiteTypings = (
|
||||
monaco: Monaco,
|
||||
p: {
|
||||
site_dts: string;
|
||||
site_dts_entry: any;
|
||||
site: { api_url: string };
|
||||
site_exports: Record<string, any>;
|
||||
script: { siteTypes: Record<string, string> };
|
||||
},
|
||||
monaco: Monaco,
|
||||
prop: { values: Record<string, any>; types: Record<string, string> }
|
||||
}
|
||||
) => {
|
||||
if (p.site_dts) {
|
||||
register(monaco, p.site_dts, "ts:site.d.ts");
|
||||
|
|
@ -38,7 +34,20 @@ export const monacoTypings = async (
|
|||
"ts:active_global.d.ts"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const monacoTypings = async (
|
||||
p: {
|
||||
site_dts: string;
|
||||
site_dts_entry: any;
|
||||
site: { api_url: string };
|
||||
site_exports: Record<string, any>;
|
||||
script: { siteTypes: Record<string, string> };
|
||||
},
|
||||
monaco: Monaco,
|
||||
prop: { values: Record<string, any>; types: Record<string, string> }
|
||||
) => {
|
||||
registerSiteTypings(monaco, p);
|
||||
if (!map.has(prop.values)) {
|
||||
map.set(prop.values, true);
|
||||
} else {
|
||||
|
|
@ -94,15 +103,19 @@ declare module "ts:prisma" {
|
|||
monaco.languages.typescript.typescriptDefaults.setExtraLibs([
|
||||
{
|
||||
filePath: "react.d.ts",
|
||||
content: await loadText(
|
||||
"https://cdn.jsdelivr.net/npm/@types/react@18.2.0/index.d.ts"
|
||||
),
|
||||
content: `declare module "react" {
|
||||
${await loadText("https://cdn.jsdelivr.net/npm/@types/react@18.3.1/index.d.ts")}
|
||||
}`,
|
||||
},
|
||||
{
|
||||
filePath: "jsx-runtime.d.ts",
|
||||
content: await loadText(
|
||||
"https://cdn.jsdelivr.net/npm/@types/react@18.2.0/jsx-runtime.d.ts"
|
||||
),
|
||||
content: `declare module "react/jsx-runtime" {
|
||||
${(
|
||||
await loadText(
|
||||
"https://cdn.jsdelivr.net/npm/@types/react@18.3.1/jsx-runtime.d.ts"
|
||||
)
|
||||
).replaceAll('from "./"', 'from "react"')}
|
||||
}`,
|
||||
},
|
||||
]);
|
||||
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ export const clientStartSync = async (arg: {
|
|||
}
|
||||
>
|
||||
) => void;
|
||||
code_changes: (arg: { ts: number }) => void;
|
||||
code_changes: (arg: { ts: number; mode: "frontend" | "typings" }) => void;
|
||||
disconnected: () => { reconnect: boolean };
|
||||
opened: () => void;
|
||||
shakehand: (client_id: string) => void;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import { ensureNotRunning } from "./utils/ensure";
|
|||
import { g } from "./utils/global";
|
||||
import { createLogger } from "./utils/logger";
|
||||
import { preparePrisma } from "./utils/prisma";
|
||||
// import "../docker-prep";
|
||||
|
||||
g.status = "init";
|
||||
|
||||
|
|
|
|||
|
|
@ -47,18 +47,24 @@ export const ${name}: SAction${saction} = async function (
|
|||
index_js.push(`export * from "./${name}";`);
|
||||
}
|
||||
|
||||
await writeAsync(
|
||||
dir.path(`app/srv/ws/sync/actions/index.ts`),
|
||||
index_js.join("\n")
|
||||
);
|
||||
const existing = await Bun.file(
|
||||
dir.path(`app/srv/ws/sync/actions/index.ts`)
|
||||
).text();
|
||||
|
||||
const content = `\
|
||||
if (existing !== index_js.join("\n")) {
|
||||
await writeAsync(
|
||||
dir.path(`app/srv/ws/sync/actions/index.ts`),
|
||||
index_js.join("\n")
|
||||
);
|
||||
|
||||
const content = `\
|
||||
export const SyncActionDefinition = ${JSON.stringify(def, null, 2)};
|
||||
export const SyncActionPaths = ${JSON.stringify(paths, null, 2)};
|
||||
`;
|
||||
|
||||
const path = dir.path("app/srv/ws/sync/actions-def.ts");
|
||||
if ((await readAsync(path)) !== content) {
|
||||
await writeAsync(path, content);
|
||||
const path = dir.path("app/srv/ws/sync/actions-def.ts");
|
||||
if ((await readAsync(path)) !== content) {
|
||||
await writeAsync(path, content);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue