ryugi-artifacts 1.15.1 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +48 -15
- package/dist/server.cjs +572 -252
- package/dist/viewer/CloudDocument-CM9pTTjC.js +1 -0
- package/dist/viewer/CloudLiveDocument-DGNdJWbj.js +1 -0
- package/dist/viewer/{DocumentLayout-BDQ2bRgn.js → DocumentLayout-BMPgq8pc.js} +157 -157
- package/dist/viewer/DocumentPage-g1CqDkue.js +1 -0
- package/dist/viewer/{abnfDiagram-VCTEODGH-DXcz0DY8.js → abnfDiagram-VCTEODGH-R_qwpGkI.js} +1 -1
- package/dist/viewer/{ar-SA-G6X2FPQ2-DaFICdeh.js → ar-SA-G6X2FPQ2-CQRrwr6s.js} +1 -1
- package/dist/viewer/{architectureDiagram-5GKGNRK7-7HwBC9Wz.js → architectureDiagram-5GKGNRK7-B-nxVlz4.js} +1 -1
- package/dist/viewer/{az-AZ-76LH7QW2-ro71YLew.js → az-AZ-76LH7QW2-BSmwjSSb.js} +1 -1
- package/dist/viewer/{bg-BG-XCXSNQG7-BBql1i2c.js → bg-BG-XCXSNQG7--cdnQcg0.js} +1 -1
- package/dist/viewer/{blockDiagram-I7D4REHJ-DN6_CCIZ.js → blockDiagram-I7D4REHJ-C0OuOJoH.js} +1 -1
- package/dist/viewer/{bn-BD-2XOGV67Q-D0nEk_sk.js → bn-BD-2XOGV67Q-1ryNaFLF.js} +1 -1
- package/dist/viewer/{c4Diagram-7LVT6UL2-BiKuFZ_0.js → c4Diagram-7LVT6UL2-DZkEOB1y.js} +1 -1
- package/dist/viewer/{ca-ES-6MX7JW3Y-BzXg8v5p.js → ca-ES-6MX7JW3Y-VdWP3ryz.js} +1 -1
- package/dist/viewer/{chunk-4HAMMTFA-D8wduydj.js → chunk-4HAMMTFA-VNoPgKvb.js} +1 -1
- package/dist/viewer/{chunk-EIO257PC-KVQLe9-1.js → chunk-EIO257PC-CZIhLO_W.js} +1 -1
- package/dist/viewer/{chunk-GMAD6QVW-BPxTHMTi.js → chunk-GMAD6QVW-CqoLeHeY.js} +1 -1
- package/dist/viewer/{chunk-GVQU2GXP-C5_2EAAn.js → chunk-GVQU2GXP-CQg0Jmx3.js} +1 -1
- package/dist/viewer/{chunk-IMKFNOWR-CoST25Zy.js → chunk-IMKFNOWR-DXIxj3u0.js} +1 -1
- package/dist/viewer/{chunk-L3NEJ4N5-DqtaXAcI.js → chunk-L3NEJ4N5-x6DZXmqs.js} +1 -1
- package/dist/viewer/{chunk-OSK3NFVY-DacvL7tA.js → chunk-OSK3NFVY-CPGpRAxP.js} +1 -1
- package/dist/viewer/{chunk-PWAF6VOD-Cxj_hOdt.js → chunk-PWAF6VOD-B4vVusV7.js} +1 -1
- package/dist/viewer/{chunk-SHT3W25Y-D9pKJ6Au.js → chunk-SHT3W25Y-D1zbaWDs.js} +1 -1
- package/dist/viewer/{chunk-SVP7TREG-svneeNVA.js → chunk-SVP7TREG-BWLqA0kk.js} +1 -1
- package/dist/viewer/{chunk-TICWLB2K-xfr9ROyW.js → chunk-TICWLB2K-D8K_a2Dt.js} +1 -1
- package/dist/viewer/{classDiagram-ZZMXUADV-lu71gUXJ.js → classDiagram-ZZMXUADV-Ck-ZG83x.js} +1 -1
- package/dist/viewer/{classDiagram-v2-VYDZK3BY-lu71gUXJ.js → classDiagram-v2-VYDZK3BY-Ck-ZG83x.js} +1 -1
- package/dist/viewer/{cs-CZ-2BRQDIVT-bwZx9UIu.js → cs-CZ-2BRQDIVT-CgQlVQeV.js} +1 -1
- package/dist/viewer/{cynefinDiagram-5FMLGOSQ-DlNaJbj_.js → cynefinDiagram-5FMLGOSQ-Dm5JUsZt.js} +1 -1
- package/dist/viewer/{da-DK-5WZEPLOC-BApDVcwE.js → da-DK-5WZEPLOC-BgjfHXZN.js} +1 -1
- package/dist/viewer/{dagre-GXQ25YYZ-DWu2Ycc5.js → dagre-GXQ25YYZ-C4a96VLk.js} +1 -1
- package/dist/viewer/{de-DE-XR44H4JA-COcHc6Zt.js → de-DE-XR44H4JA-DX-3RcAq.js} +1 -1
- package/dist/viewer/{diagram-S7CK7UJ4-D8VO7YKc.js → diagram-S7CK7UJ4-PaaBHmBV.js} +1 -1
- package/dist/viewer/{diagram-UQ7AKVKN-D5OcQNY9.js → diagram-UQ7AKVKN-CFIzU-ol.js} +1 -1
- package/dist/viewer/{diagram-VX7I27RA-DRHmiAWI.js → diagram-VX7I27RA-CbcVVLx5.js} +1 -1
- package/dist/viewer/{diagram-Z3DM3KII-ClXzWLem.js → diagram-Z3DM3KII-2bnKxhw3.js} +1 -1
- package/dist/viewer/{dist-BuKe8NdN.js → dist-BB8Cm8p1.js} +1 -1
- package/dist/viewer/dist-BGDD3Qfs.js +1 -0
- package/dist/viewer/{dist-M7Lz5R2v.js → dist-BNUmLPG3.js} +1 -1
- package/dist/viewer/{dist-TX5rYYGW.js → dist-ByHcWAsz.js} +4 -4
- package/dist/viewer/{dist-G2JHMLgK.js → dist-C84cxxJs.js} +1 -1
- package/dist/viewer/{dist-q1jFGEbP.js → dist-C85UfTX9.js} +1 -1
- package/dist/viewer/{dist-BKtxxS1a.js → dist-CAYAG4sb.js} +1 -1
- package/dist/viewer/{dist-DLh5uREE.js → dist-CHo5vjEE.js} +1 -1
- package/dist/viewer/{dist-CFkCXjQP.js → dist-CPsNYKE1.js} +1 -1
- package/dist/viewer/dist-CbM-kcUd.js +6 -0
- package/dist/viewer/{dist-C_NwF-ep.js → dist-Cifjyebz.js} +9 -9
- package/dist/viewer/{dist-Bgijnk4D.js → dist-Cmmhn-X1.js} +1 -1
- package/dist/viewer/dist-DA1ZUPA2.js +1 -0
- package/dist/viewer/{dist-DlANbAUX.js → dist-DOIJJqiU.js} +1 -1
- package/dist/viewer/{dist-CByD4sdq.js → dist-DYmYmDEo.js} +1 -1
- package/dist/viewer/{dist-rgdCugHI.js → dist-DdnIT8Pk.js} +1 -1
- package/dist/viewer/{dist-mDWB-P3S.js → dist-DfU4jTpk.js} +1 -1
- package/dist/viewer/{dist-DB3o8dUU.js → dist-DuNQu2Qs.js} +1 -1
- package/dist/viewer/dist-DyvqUJBr.js +1 -0
- package/dist/viewer/{dist-CV7QdHTq.js → dist-Dz0HV18p.js} +1 -1
- package/dist/viewer/{dist-DzBPEHnz.js → dist-KZU_4K7q.js} +5 -5
- package/dist/viewer/dist-LjHj6cw9.js +9 -0
- package/dist/viewer/{dist-a8BuHhYq.js → dist-Saw8jlKm.js} +1 -1
- package/dist/viewer/{dist-DfWxOyg4.js → dist-all60C8n.js} +2 -2
- package/dist/viewer/{ebnfDiagram-PWID7BFC-BOzsyHEk.js → ebnfDiagram-PWID7BFC-BElETRrd.js} +1 -1
- package/dist/viewer/{el-GR-BZB4AONW-h1eLQlP7.js → el-GR-BZB4AONW-CCgkhpuC.js} +1 -1
- package/dist/viewer/{en-B4ZKOASM-EdleGu9D.js → en-B4ZKOASM-CkNYcd6h.js} +1 -1
- package/dist/viewer/{erDiagram-RLTQ6QDP-BF_tpcM3.js → erDiagram-RLTQ6QDP-BvirYYn6.js} +1 -1
- package/dist/viewer/{es-ES-U4NZUMDT-DeaeHEK9.js → es-ES-U4NZUMDT-CHGDrG6V.js} +1 -1
- package/dist/viewer/{eu-ES-A7QVB2H4-BzoRNYbw.js → eu-ES-A7QVB2H4-CJvnBnSO.js} +1 -1
- package/dist/viewer/{fa-IR-HGAKTJCU-fXYoNuWo.js → fa-IR-HGAKTJCU-DOhVqJIY.js} +1 -1
- package/dist/viewer/{fi-FI-Z5N7JZ37-CTVEZXqM.js → fi-FI-Z5N7JZ37-KtjD042q.js} +1 -1
- package/dist/viewer/flowDiagram-HODETNUW-B9qTl1Fa.js +1 -0
- package/dist/viewer/{fr-FR-RHASNOE6-BizkpgaG.js → fr-FR-RHASNOE6-Fhuh4xKm.js} +1 -1
- package/dist/viewer/ganttDiagram-EL5Y4UJY-vMMpYRDJ.js +292 -0
- package/dist/viewer/{gl-ES-HMX3MZ6V-rsfHb2R9.js → gl-ES-HMX3MZ6V-GaQgPV8F.js} +1 -1
- package/dist/viewer/{he-IL-6SHJWFNN-BmWEwAWC.js → he-IL-6SHJWFNN-DHPr7Ged.js} +1 -1
- package/dist/viewer/{hi-IN-IWLTKZ5I-gzYZTFIt.js → hi-IN-IWLTKZ5I-d4wZNnj5.js} +1 -1
- package/dist/viewer/{hu-HU-A5ZG7DT2-DqXGHJ4g.js → hu-HU-A5ZG7DT2-qpHSyZvF.js} +1 -1
- package/dist/viewer/{id-ID-SAP4L64H-CVbSVAc3.js → id-ID-SAP4L64H-CPrjJiXr.js} +1 -1
- package/dist/viewer/{image-GAAHSSAO-B0g7YyLf.js → image-GAAHSSAO-xfEH5EVg.js} +1 -1
- package/dist/viewer/index.html +1 -1
- package/dist/viewer/index.js +6 -6
- package/dist/viewer/index2.css +171 -18
- package/dist/viewer/{infoDiagram-27XIBGKW-DOxIYIRL.js → infoDiagram-27XIBGKW-B0yRhU0B.js} +1 -1
- package/dist/viewer/{ishikawaDiagram-5VMMS53U-D-U6Fi8F.js → ishikawaDiagram-5VMMS53U-ZFUPUZ0x.js} +1 -1
- package/dist/viewer/{it-IT-JPQ66NNP-6PNiI36L.js → it-IT-JPQ66NNP-BnOpgYU3.js} +1 -1
- package/dist/viewer/{ja-JP-DBVTYXUO-D3SJtNp5.js → ja-JP-DBVTYXUO-Fma_1_jf.js} +1 -1
- package/dist/viewer/{journeyDiagram-3NMN7TZE-8Mz0Nae3.js → journeyDiagram-3NMN7TZE-GaSIHccq.js} +1 -1
- package/dist/viewer/{kaa-6HZHGXH3-Bz3WA5yL.js → kaa-6HZHGXH3-Bgd1Vsyj.js} +1 -1
- package/dist/viewer/{kab-KAB-ZGHBKWFO-W2PtzMEV.js → kab-KAB-ZGHBKWFO-97ekuQIQ.js} +1 -1
- package/dist/viewer/{kanban-definition-UXKFOSKX-BP8HwPzL.js → kanban-definition-UXKFOSKX-BfckuyD5.js} +1 -1
- package/dist/viewer/{kk-KZ-P5N5QNE5-Dc1i0Bup.js → kk-KZ-P5N5QNE5-Bxv4UjqE.js} +1 -1
- package/dist/viewer/{km-KH-HSX4SM5Z-C88_w0rR.js → km-KH-HSX4SM5Z-8ccFfBZa.js} +1 -1
- package/dist/viewer/{ko-KR-MTYHY66A-DWOt-6As.js → ko-KR-MTYHY66A-D-a1HV8D.js} +1 -1
- package/dist/viewer/{ku-TR-6OUDTVRD-B7qeFzlo.js → ku-TR-6OUDTVRD-BsdyU65I.js} +1 -1
- package/dist/viewer/{lt-LT-XHIRWOB4-Dc9eguDu.js → lt-LT-XHIRWOB4-CIq7DtVN.js} +1 -1
- package/dist/viewer/{lv-LV-5QDEKY6T-D9CzWKMj.js → lv-LV-5QDEKY6T-B5B57KgN.js} +1 -1
- package/dist/viewer/{mindmap-definition-YA3MSWOX-Bikv3SLv.js → mindmap-definition-YA3MSWOX-x4MVcn_H.js} +1 -1
- package/dist/viewer/{mr-IN-CRQNXWMA-CtlsKIl9.js → mr-IN-CRQNXWMA-D1VztqX3.js} +1 -1
- package/dist/viewer/{my-MM-5M5IBNSE-CiyAGqHH.js → my-MM-5M5IBNSE-VGJv_B79.js} +1 -1
- package/dist/viewer/{nb-NO-T6EIAALU-l9uMRUdk.js → nb-NO-T6EIAALU-CW7CbXP6.js} +1 -1
- package/dist/viewer/{nl-NL-IS3SIHDZ-zja_zaqN.js → nl-NL-IS3SIHDZ-0fova8mt.js} +1 -1
- package/dist/viewer/{nn-NO-6E72VCQL-BiP5RLsf.js → nn-NO-6E72VCQL-Bl8c9odx.js} +1 -1
- package/dist/viewer/{oc-FR-POXYY2M6-CvKUzwab.js → oc-FR-POXYY2M6-Csx8D3AS.js} +1 -1
- package/dist/viewer/{pa-IN-N4M65BXN-DioFchQd.js → pa-IN-N4M65BXN-DrioQ4p2.js} +1 -1
- package/dist/viewer/{pegDiagram-XKGWAZYB-BSllNtPI.js → pegDiagram-XKGWAZYB-jgQ4-VU8.js} +1 -1
- package/dist/viewer/percentages-BXMCSKIN-DRVY_37B.js +1 -0
- package/dist/viewer/{pieDiagram-E7YTZNPT-b1-BsaA4.js → pieDiagram-E7YTZNPT-D4W5LODC.js} +3 -3
- package/dist/viewer/{pl-PL-T2D74RX3-Ci7dAnI8.js → pl-PL-T2D74RX3-BlG3Tr5U.js} +1 -1
- package/dist/viewer/{prod-CPZkgD7t.js → prod-DoKZsOaX.js} +9 -9
- package/dist/viewer/{pt-BR-5N22H2LF--VT7NYYE.js → pt-BR-5N22H2LF-BJ_dJDoY.js} +1 -1
- package/dist/viewer/{pt-PT-UZXXM6DQ-CWdbQilC.js → pt-PT-UZXXM6DQ-JuaprDPL.js} +1 -1
- package/dist/viewer/{quadrantDiagram-AXDQQJYC-D0pucWR0.js → quadrantDiagram-AXDQQJYC-Bjo_a-l0.js} +1 -1
- package/dist/viewer/{railroadDiagram-O6MQD6OU-DIPJ2PKr.js → railroadDiagram-O6MQD6OU-B0jgFLfP.js} +1 -1
- package/dist/viewer/{requirementDiagram-BXWQKSXE-DEGhiwJ9.js → requirementDiagram-BXWQKSXE-Dsdz_3bL.js} +1 -1
- package/dist/viewer/{ro-RO-JPDTUUEW-BK4wLUL7.js → ro-RO-JPDTUUEW-CPbEkuPw.js} +1 -1
- package/dist/viewer/{ru-RU-B4JR7IUQ-BDPQ8blU.js → ru-RU-B4JR7IUQ-DtGFv7Yn.js} +1 -1
- package/dist/viewer/{sequenceDiagram-WJ2MYXX4-D7sLhGYb.js → sequenceDiagram-WJ2MYXX4-BNHp74bi.js} +1 -1
- package/dist/viewer/{si-LK-N5RQ5JYF-D5DWsUAA.js → si-LK-N5RQ5JYF-Cw7PrSGM.js} +1 -1
- package/dist/viewer/{sk-SK-C5VTKIMK-Cia9j1Te.js → sk-SK-C5VTKIMK-BdEWLdAf.js} +1 -1
- package/dist/viewer/{sl-SI-NN7IZMDC-CV304k5j.js → sl-SI-NN7IZMDC-DWsrAmPB.js} +1 -1
- package/dist/viewer/{stateDiagram-D77RDMKH-BMNx9_M8.js → stateDiagram-D77RDMKH-bROf90_R.js} +1 -1
- package/dist/viewer/{stateDiagram-v2-MP3YSRHH-CPa9DZs4.js → stateDiagram-v2-MP3YSRHH-BY5bPCMJ.js} +1 -1
- package/dist/viewer/subset-shared.chunk-BStnlZMO.js +1 -0
- package/dist/viewer/{subset-worker.chunk-CHQzlaj3.js → subset-worker.chunk-ZX5ZauYv.js} +1 -1
- package/dist/viewer/{sv-SE-XGPEYMSR-CXdp-XZD.js → sv-SE-XGPEYMSR-CIhIa_l2.js} +1 -1
- package/dist/viewer/{swimlanes-42K2YHIH-BwUyxwi3.js → swimlanes-42K2YHIH-DWgSkFMr.js} +1 -1
- package/dist/viewer/{swimlanesDiagram-VR7AAH4N-BgxS36EG.js → swimlanesDiagram-VR7AAH4N-CJlfxAhN.js} +1 -1
- package/dist/viewer/{ta-IN-2NMHFXQM-CObY6q-8.js → ta-IN-2NMHFXQM-j2fOOXe2.js} +1 -1
- package/dist/viewer/{th-TH-HPSO5L25-CEOiELZN.js → th-TH-HPSO5L25-CkgXnjpf.js} +1 -1
- package/dist/viewer/{timeline-definition-24CTP7MA-BJ-7Fdfr.js → timeline-definition-24CTP7MA-rnUpi-7k.js} +1 -1
- package/dist/viewer/{tr-TR-DEFEU3FU-CPj5dFcB.js → tr-TR-DEFEU3FU-bgJR1iXd.js} +1 -1
- package/dist/viewer/{uk-UA-QMV73CPH-BkZyFeXP.js → uk-UA-QMV73CPH-q6uSQxvU.js} +1 -1
- package/dist/viewer/{useSandboxFrame-BpJ9uM86.js → useSandboxFrame-Dzr1V3HK.js} +1 -1
- package/dist/viewer/{vennDiagram-4TSXK5OY-DnFbjWDw.js → vennDiagram-4TSXK5OY-CeqdYGwH.js} +1 -1
- package/dist/viewer/{vi-VN-M7AON7JQ-CkKKOpBQ.js → vi-VN-M7AON7JQ-DTYGZATL.js} +1 -1
- package/dist/viewer/{wardleyDiagram-VM6X3IG4-CN_pm__V.js → wardleyDiagram-VM6X3IG4-C8cYdu7b.js} +1 -1
- package/dist/viewer/{xychartDiagram-S5SC5T6Z-C7XLywXm.js → xychartDiagram-S5SC5T6Z-Djgu6Zdz.js} +2 -2
- package/dist/viewer/{zh-CN-LNUGB5OW-BQcCqsDg.js → zh-CN-LNUGB5OW-BWV3WswS.js} +1 -1
- package/dist/viewer/{zh-HK-E62DVLB3-Bp-jK0zw.js → zh-HK-E62DVLB3-Bd20M5Rq.js} +1 -1
- package/dist/viewer/{zh-TW-RAJ6MFWO-KmFL88Bs.js → zh-TW-RAJ6MFWO-CVDAstAU.js} +1 -1
- package/package.json +1 -1
- package/dist/viewer/CloudDocument-CgM3kbiO.js +0 -1
- package/dist/viewer/CloudLiveDocument-CdN71jfH.js +0 -1
- package/dist/viewer/DocumentPage-BBzAFj4H.js +0 -1
- package/dist/viewer/dist-C2adJeNZ.js +0 -9
- package/dist/viewer/dist-D0Emc84u.js +0 -1
- package/dist/viewer/dist-DcGUli8O.js +0 -1
- package/dist/viewer/dist-VupXLYv6.js +0 -1
- package/dist/viewer/dist-_3NL_2LS.js +0 -6
- package/dist/viewer/flowDiagram-HODETNUW-DpY3t4b0.js +0 -1
- package/dist/viewer/ganttDiagram-EL5Y4UJY-DvL8TKGV.js +0 -292
- package/dist/viewer/percentages-BXMCSKIN-BRZnWvym.js +0 -1
- package/dist/viewer/subset-shared.chunk-ChUk9bHw.js +0 -1
package/dist/server.cjs
CHANGED
|
@@ -5171,14 +5171,14 @@ var require_websocket_server = __commonJS({
|
|
|
5171
5171
|
|
|
5172
5172
|
// src/server/main.ts
|
|
5173
5173
|
var import_node_child_process2 = require("node:child_process");
|
|
5174
|
-
var
|
|
5174
|
+
var import_node_fs25 = __toESM(require("node:fs"), 1);
|
|
5175
5175
|
var import_node_os = __toESM(require("node:os"), 1);
|
|
5176
|
-
var
|
|
5176
|
+
var import_node_path21 = __toESM(require("node:path"), 1);
|
|
5177
5177
|
|
|
5178
5178
|
// src/server/app.ts
|
|
5179
|
-
var
|
|
5179
|
+
var import_node_fs23 = __toESM(require("node:fs"), 1);
|
|
5180
5180
|
var import_node_http = __toESM(require("node:http"), 1);
|
|
5181
|
-
var
|
|
5181
|
+
var import_node_path20 = __toESM(require("node:path"), 1);
|
|
5182
5182
|
|
|
5183
5183
|
// src/shared/types.ts
|
|
5184
5184
|
var ARTIFACT_TYPES = ["artboard", "document", "html"];
|
|
@@ -5230,7 +5230,7 @@ function artifactKeyOf(relative) {
|
|
|
5230
5230
|
if (!type || !id2 || !isArtifactType(type) || !isArtifactId(id2)) return null;
|
|
5231
5231
|
return { type, id: id2 };
|
|
5232
5232
|
}
|
|
5233
|
-
function artifactSignature(dir) {
|
|
5233
|
+
function artifactSignature(dir, type) {
|
|
5234
5234
|
let count = 0;
|
|
5235
5235
|
let size = 0;
|
|
5236
5236
|
let latest = 0;
|
|
@@ -5243,6 +5243,7 @@ function artifactSignature(dir) {
|
|
|
5243
5243
|
}
|
|
5244
5244
|
for (const entry of entries2) {
|
|
5245
5245
|
if (entry.name.startsWith(".")) continue;
|
|
5246
|
+
if (type === "artboard" && current === dir && entry.name === "comments.json") continue;
|
|
5246
5247
|
const full = import_node_path.default.join(current, entry.name);
|
|
5247
5248
|
try {
|
|
5248
5249
|
const stat = import_node_fs.default.statSync(full);
|
|
@@ -17727,12 +17728,19 @@ function stampBlockIds(state) {
|
|
|
17727
17728
|
return { ...state, root: { ...state.root, children } };
|
|
17728
17729
|
}
|
|
17729
17730
|
|
|
17730
|
-
// src/server/
|
|
17731
|
-
var
|
|
17731
|
+
// src/server/board-comments.ts
|
|
17732
|
+
var import_node_crypto2 = __toESM(require("node:crypto"), 1);
|
|
17733
|
+
var import_node_fs8 = __toESM(require("node:fs"), 1);
|
|
17734
|
+
var import_node_path7 = __toESM(require("node:path"), 1);
|
|
17732
17735
|
|
|
17733
17736
|
// src/shared/comments.ts
|
|
17734
17737
|
var emptyComments = () => ({ version: 1, threads: [] });
|
|
17735
17738
|
var isObject = (value) => typeof value === "object" && value !== null;
|
|
17739
|
+
var documentAnchors = {
|
|
17740
|
+
read: (value) => isObject(value) && typeof value.blockId === "string" && value.blockId ? { blockId: value.blockId, quote: typeof value.quote === "string" ? value.quote : "" } : null,
|
|
17741
|
+
same: (a5, b6) => a5.blockId === b6.blockId && a5.quote === b6.quote,
|
|
17742
|
+
missing: "a new thread needs anchor.blockId; dropped it"
|
|
17743
|
+
};
|
|
17736
17744
|
function parseComments(text2) {
|
|
17737
17745
|
const raw = JSON.parse(text2);
|
|
17738
17746
|
if (!isObject(raw)) throw new Error("comments.json must be an object");
|
|
@@ -17745,13 +17753,14 @@ function parseComments(text2) {
|
|
|
17745
17753
|
return raw;
|
|
17746
17754
|
}
|
|
17747
17755
|
var isSavedMessage = (m11) => !!m11.id && (m11.author === "human" || m11.author === "agent") && typeof m11.text === "string" && typeof m11.at === "string";
|
|
17748
|
-
function savedComments(incoming) {
|
|
17756
|
+
function savedComments(incoming, spec = documentAnchors) {
|
|
17749
17757
|
const threads = [];
|
|
17750
17758
|
for (const t7 of incoming.threads) {
|
|
17751
|
-
|
|
17759
|
+
const anchor = spec.read(t7.anchor);
|
|
17760
|
+
if (!t7.id || !anchor || !t7.statusAt || t7.status !== "open" && t7.status !== "resolved") continue;
|
|
17752
17761
|
const messages = (t7.messages ?? []).filter(isSavedMessage);
|
|
17753
17762
|
const statusBy = t7.statusBy === "human" || t7.statusBy === "agent" ? { statusBy: t7.statusBy } : {};
|
|
17754
|
-
threads.push({ id: t7.id, anchor
|
|
17763
|
+
threads.push({ id: t7.id, anchor, status: t7.status, statusAt: t7.statusAt, ...statusBy, messages });
|
|
17755
17764
|
}
|
|
17756
17765
|
return { version: 1, threads };
|
|
17757
17766
|
}
|
|
@@ -17791,32 +17800,36 @@ function mergeThread(base, incoming, origin, now, newId, warnings, name) {
|
|
|
17791
17800
|
messages.sort((a5, b6) => a5.at < b6.at ? -1 : a5.at > b6.at ? 1 : 0);
|
|
17792
17801
|
let { status, statusAt, statusBy } = base;
|
|
17793
17802
|
if (incoming.status && incoming.status !== base.status) {
|
|
17794
|
-
const
|
|
17795
|
-
if (
|
|
17803
|
+
const stamp2 = incoming.statusAt && incoming.statusAt !== base.statusAt ? incoming.statusAt : now;
|
|
17804
|
+
if (stamp2 >= base.statusAt) {
|
|
17796
17805
|
status = incoming.status;
|
|
17797
|
-
statusAt =
|
|
17806
|
+
statusAt = stamp2;
|
|
17798
17807
|
statusBy = origin;
|
|
17799
17808
|
}
|
|
17800
17809
|
}
|
|
17801
17810
|
return { ...base, status, statusAt, ...statusBy ? { statusBy } : {}, messages };
|
|
17802
17811
|
}
|
|
17803
|
-
|
|
17804
|
-
|
|
17812
|
+
function sameUnsavedThread(existing, incoming, spec) {
|
|
17813
|
+
const anchor = spec.read(incoming.anchor);
|
|
17814
|
+
return !!anchor && spec.same(existing.anchor, anchor) && existing.messages[0]?.text === incoming.messages?.[0]?.text;
|
|
17815
|
+
}
|
|
17816
|
+
function mergeComments(base, incoming, origin, now, newId, name, spec = documentAnchors) {
|
|
17805
17817
|
const warnings = [];
|
|
17806
17818
|
const threads = [...base.threads];
|
|
17807
17819
|
for (const thread of incoming.threads) {
|
|
17808
|
-
const index = thread.id ? threads.findIndex((t7) => t7.id === thread.id) : threads.findIndex((t7) => sameUnsavedThread(t7, thread));
|
|
17820
|
+
const index = thread.id ? threads.findIndex((t7) => t7.id === thread.id) : threads.findIndex((t7) => sameUnsavedThread(t7, thread, spec));
|
|
17809
17821
|
if (index >= 0) {
|
|
17810
17822
|
threads[index] = mergeThread(threads[index], thread, origin, now, newId, warnings, name);
|
|
17811
17823
|
continue;
|
|
17812
17824
|
}
|
|
17813
|
-
|
|
17814
|
-
|
|
17825
|
+
const anchor = spec.read(thread.anchor);
|
|
17826
|
+
if (!anchor) {
|
|
17827
|
+
warnings.push(spec.missing);
|
|
17815
17828
|
continue;
|
|
17816
17829
|
}
|
|
17817
17830
|
const fresh = {
|
|
17818
17831
|
id: thread.id ?? newId(),
|
|
17819
|
-
anchor
|
|
17832
|
+
anchor,
|
|
17820
17833
|
status: "open",
|
|
17821
17834
|
statusAt: now,
|
|
17822
17835
|
statusBy: origin,
|
|
@@ -17834,23 +17847,15 @@ var updateHumanMessage = (thread, messageId, update2) => ({
|
|
|
17834
17847
|
...thread,
|
|
17835
17848
|
messages: thread.messages.map((m11) => m11.id === messageId && m11.author === "human" && !m11.deleted ? update2(m11) : m11)
|
|
17836
17849
|
});
|
|
17850
|
+
function openThread(anchor, author, text2, now, newId, who) {
|
|
17851
|
+
return { id: newId(), anchor, status: "open", statusAt: now, statusBy: author, messages: [{ id: newId(), author, ...personOf(who), text: text2, at: now }] };
|
|
17852
|
+
}
|
|
17837
17853
|
function applyHumanOp(file, op, now, newId, who) {
|
|
17854
|
+
if (op.op === "create") return { ...file, threads: [...file.threads, openThread({ blockId: op.blockId, quote: op.quote }, "human", op.text, now, newId, who)] };
|
|
17855
|
+
return applyThreadOp(file, op, now, newId, who);
|
|
17856
|
+
}
|
|
17857
|
+
function applyThreadOp(file, op, now, newId, who) {
|
|
17838
17858
|
switch (op.op) {
|
|
17839
|
-
case "create":
|
|
17840
|
-
return {
|
|
17841
|
-
...file,
|
|
17842
|
-
threads: [
|
|
17843
|
-
...file.threads,
|
|
17844
|
-
{
|
|
17845
|
-
id: newId(),
|
|
17846
|
-
anchor: { blockId: op.blockId, quote: op.quote },
|
|
17847
|
-
status: "open",
|
|
17848
|
-
statusAt: now,
|
|
17849
|
-
statusBy: "human",
|
|
17850
|
-
messages: [{ id: newId(), author: "human", ...personOf(who), text: op.text, at: now }]
|
|
17851
|
-
}
|
|
17852
|
-
]
|
|
17853
|
-
};
|
|
17854
17859
|
case "reply":
|
|
17855
17860
|
return updateThread(file, op.threadId, (t7) => ({ ...t7, messages: [...t7.messages, { id: newId(), author: "human", ...personOf(who), text: op.text, at: now }] }));
|
|
17856
17861
|
case "edit":
|
|
@@ -17905,7 +17910,7 @@ function unreadThreads(file, cursor) {
|
|
|
17905
17910
|
const threads = [];
|
|
17906
17911
|
let newest = cursor;
|
|
17907
17912
|
for (const thread of file.threads) {
|
|
17908
|
-
for (const
|
|
17913
|
+
for (const stamp2 of humanStamps(thread)) if (!newest || stamp2 > newest) newest = stamp2;
|
|
17909
17914
|
const unread = cursor === null ? waitingOn(thread) === "agent" ? waitingSince(thread) : null : changesSince(thread, cursor);
|
|
17910
17915
|
if (unread && unread.changes.length > 0) threads.push({ ...thread, ...unread });
|
|
17911
17916
|
}
|
|
@@ -17913,16 +17918,12 @@ function unreadThreads(file, cursor) {
|
|
|
17913
17918
|
}
|
|
17914
17919
|
function applyAgentOp(file, op, now, newId, name) {
|
|
17915
17920
|
if (op.op === "add") {
|
|
17916
|
-
const thread = {
|
|
17917
|
-
id: newId(),
|
|
17918
|
-
anchor: { blockId: op.blockId, quote: op.quote },
|
|
17919
|
-
status: "open",
|
|
17920
|
-
statusAt: now,
|
|
17921
|
-
statusBy: "agent",
|
|
17922
|
-
messages: [{ id: newId(), author: "agent", ...personOf({ name }), text: op.text, at: now }]
|
|
17923
|
-
};
|
|
17921
|
+
const thread = openThread({ blockId: op.blockId, quote: op.quote }, "agent", op.text, now, newId, { name });
|
|
17924
17922
|
return { file: { ...file, threads: [...file.threads, thread] }, threadId: thread.id, messageId: thread.messages[0].id };
|
|
17925
17923
|
}
|
|
17924
|
+
return applyAgentThreadOp(file, op, now, newId, name);
|
|
17925
|
+
}
|
|
17926
|
+
function applyAgentThreadOp(file, op, now, newId, name) {
|
|
17926
17927
|
if (!file.threads.some((t7) => t7.id === op.threadId)) throw new Error(`no thread ${op.threadId}`);
|
|
17927
17928
|
if (op.op === "resolve") {
|
|
17928
17929
|
return { file: updateThread(file, op.threadId, (t7) => ({ ...t7, status: "resolved", statusAt: now, statusBy: "agent" })), threadId: op.threadId };
|
|
@@ -17931,6 +17932,76 @@ function applyAgentOp(file, op, now, newId, name) {
|
|
|
17931
17932
|
return { file: updateThread(file, op.threadId, (t7) => ({ ...t7, messages: [...t7.messages, message] })), threadId: op.threadId, messageId: message.id };
|
|
17932
17933
|
}
|
|
17933
17934
|
|
|
17935
|
+
// src/shared/board-comments.ts
|
|
17936
|
+
var MAX_ID = 100;
|
|
17937
|
+
var MAX_PATH = 2e3;
|
|
17938
|
+
var MAX_NODES = 50;
|
|
17939
|
+
var isName = (value, max = MAX_ID) => typeof value === "string" && value.length > 0 && value.length <= max;
|
|
17940
|
+
var isFiniteNumber = (value) => typeof value === "number" && Number.isFinite(value);
|
|
17941
|
+
var isFraction = (value) => isFiniteNumber(value) && value >= 0 && value <= 1;
|
|
17942
|
+
function readNodes(value) {
|
|
17943
|
+
if (!Array.isArray(value) || value.length === 0 || value.length > MAX_NODES) return null;
|
|
17944
|
+
const nodes = [];
|
|
17945
|
+
for (const node of value) {
|
|
17946
|
+
if (!isObject(node) || !isName(node.board) || !isName(node.path, MAX_PATH)) return null;
|
|
17947
|
+
nodes.push({ board: node.board, path: node.path });
|
|
17948
|
+
}
|
|
17949
|
+
return nodes;
|
|
17950
|
+
}
|
|
17951
|
+
function readHashes(value) {
|
|
17952
|
+
if (!isObject(value) || Array.isArray(value)) return null;
|
|
17953
|
+
const entries2 = Object.entries(value);
|
|
17954
|
+
if (entries2.length > MAX_NODES || !entries2.every(([board, hash]) => isName(board) && isName(hash))) return null;
|
|
17955
|
+
return Object.fromEntries(entries2);
|
|
17956
|
+
}
|
|
17957
|
+
function readBoardAnchor(value) {
|
|
17958
|
+
if (!isObject(value) || !isName(value.page) || !isFiniteNumber(value.x) || !isFiniteNumber(value.y)) return null;
|
|
17959
|
+
const anchor = { page: value.page, x: value.x, y: value.y };
|
|
17960
|
+
if (value.board !== void 0) {
|
|
17961
|
+
if (!isName(value.board)) return null;
|
|
17962
|
+
anchor.board = value.board;
|
|
17963
|
+
}
|
|
17964
|
+
if (value.nodes !== void 0) {
|
|
17965
|
+
const nodes = readNodes(value.nodes);
|
|
17966
|
+
if (!nodes) return null;
|
|
17967
|
+
anchor.nodes = nodes;
|
|
17968
|
+
}
|
|
17969
|
+
if (value.offset !== void 0) {
|
|
17970
|
+
const offset = value.offset;
|
|
17971
|
+
if (!anchor.nodes || !isObject(offset) || !isFraction(offset.x) || !isFraction(offset.y)) return null;
|
|
17972
|
+
anchor.offset = { x: offset.x, y: offset.y };
|
|
17973
|
+
}
|
|
17974
|
+
if (value.hashes !== void 0) {
|
|
17975
|
+
const hashes = readHashes(value.hashes);
|
|
17976
|
+
if (!hashes) return null;
|
|
17977
|
+
anchor.hashes = hashes;
|
|
17978
|
+
}
|
|
17979
|
+
return anchor;
|
|
17980
|
+
}
|
|
17981
|
+
var boardAnchors = {
|
|
17982
|
+
read: readBoardAnchor,
|
|
17983
|
+
same: (a5, b6) => a5.page === b6.page && a5.board === b6.board && a5.x === b6.x && a5.y === b6.y,
|
|
17984
|
+
missing: "a new thread needs a board anchor (page, x, y); dropped it"
|
|
17985
|
+
};
|
|
17986
|
+
var emptyBoardComments = () => ({ version: 1, threads: [] });
|
|
17987
|
+
var savedBoardComments = (incoming) => savedComments(incoming, boardAnchors);
|
|
17988
|
+
var mergeBoardComments = (base, incoming, origin, now, newId, name) => mergeComments(base, incoming, origin, now, newId, name, boardAnchors);
|
|
17989
|
+
function applyBoardHumanOp(file, op, now, newId, who) {
|
|
17990
|
+
if (op.op === "create") return { ...file, threads: [...file.threads, openThread(op.anchor, "human", op.text, now, newId, who)] };
|
|
17991
|
+
return applyThreadOp(file, op, now, newId, who);
|
|
17992
|
+
}
|
|
17993
|
+
function applyBoardAgentOp(file, op, now, newId, name) {
|
|
17994
|
+
if (op.op === "add") {
|
|
17995
|
+
const thread = openThread(op.anchor, "agent", op.text, now, newId, { name });
|
|
17996
|
+
return { file: { ...file, threads: [...file.threads, thread] }, threadId: thread.id, messageId: thread.messages[0].id };
|
|
17997
|
+
}
|
|
17998
|
+
return applyAgentThreadOp(file, op, now, newId, name);
|
|
17999
|
+
}
|
|
18000
|
+
|
|
18001
|
+
// src/server/comment-cursors.ts
|
|
18002
|
+
var import_node_fs6 = __toESM(require("node:fs"), 1);
|
|
18003
|
+
var import_node_path6 = __toESM(require("node:path"), 1);
|
|
18004
|
+
|
|
17934
18005
|
// src/server/state.ts
|
|
17935
18006
|
var import_node_fs5 = __toESM(require("node:fs"), 1);
|
|
17936
18007
|
var import_node_path5 = __toESM(require("node:path"), 1);
|
|
@@ -18282,7 +18353,31 @@ function writeArtifactState(stateDir, ref, payload, extra = {}) {
|
|
|
18282
18353
|
});
|
|
18283
18354
|
}
|
|
18284
18355
|
|
|
18356
|
+
// src/server/comment-cursors.ts
|
|
18357
|
+
var cursorsFile = (stateDir, id2, type = "document") => import_node_path6.default.join(stateDir, type, id2, "comment-cursors.json");
|
|
18358
|
+
function read(file) {
|
|
18359
|
+
try {
|
|
18360
|
+
const value = JSON.parse(import_node_fs6.default.readFileSync(file, "utf8"));
|
|
18361
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return {};
|
|
18362
|
+
return Object.fromEntries(Object.entries(value).filter((entry) => typeof entry[1] === "string"));
|
|
18363
|
+
} catch {
|
|
18364
|
+
return {};
|
|
18365
|
+
}
|
|
18366
|
+
}
|
|
18367
|
+
function createCommentCursors(stateDir, type = "document") {
|
|
18368
|
+
return {
|
|
18369
|
+
get: (id2, agent) => read(cursorsFile(stateDir, id2, type))[agent] ?? null,
|
|
18370
|
+
set: (id2, agent, stamp2) => {
|
|
18371
|
+
const file = cursorsFile(stateDir, id2, type);
|
|
18372
|
+
const all = read(file);
|
|
18373
|
+
if (all[agent] === stamp2) return;
|
|
18374
|
+
writeJsonAtomic(file, { ...all, [agent]: stamp2 });
|
|
18375
|
+
}
|
|
18376
|
+
};
|
|
18377
|
+
}
|
|
18378
|
+
|
|
18285
18379
|
// src/server/document-comments.ts
|
|
18380
|
+
var import_node_fs7 = __toESM(require("node:fs"), 1);
|
|
18286
18381
|
var MAX_TEXT = 2e4;
|
|
18287
18382
|
var isText3 = (value, max = MAX_TEXT) => typeof value === "string" && value.length <= max;
|
|
18288
18383
|
var isId = (value) => isText3(value, 100) && value.length > 0;
|
|
@@ -18319,20 +18414,30 @@ function asAgentOp(value) {
|
|
|
18319
18414
|
return null;
|
|
18320
18415
|
}
|
|
18321
18416
|
}
|
|
18417
|
+
var documentRules = {
|
|
18418
|
+
empty: emptyComments,
|
|
18419
|
+
saved: savedComments,
|
|
18420
|
+
merge: mergeComments,
|
|
18421
|
+
human: applyHumanOp,
|
|
18422
|
+
agent: applyAgentOp
|
|
18423
|
+
};
|
|
18322
18424
|
var noNames = { human: () => void 0, agent: () => void 0 };
|
|
18323
18425
|
function createCommentStore(file, names = noNames, now = () => (/* @__PURE__ */ new Date()).toISOString(), newId = () => nanoid2(10)) {
|
|
18324
|
-
|
|
18426
|
+
return createStore(file, documentRules, names, now, newId);
|
|
18427
|
+
}
|
|
18428
|
+
function createStore(file, rules, names = noNames, now = () => (/* @__PURE__ */ new Date()).toISOString(), newId = () => nanoid2(10)) {
|
|
18429
|
+
let current = rules.empty();
|
|
18325
18430
|
let lastSeen = null;
|
|
18326
18431
|
let warnings = [];
|
|
18327
18432
|
let loaded = false;
|
|
18328
18433
|
const write = () => {
|
|
18329
18434
|
writeJsonAtomic(file, current);
|
|
18330
|
-
lastSeen =
|
|
18435
|
+
lastSeen = import_node_fs7.default.readFileSync(file, "utf8");
|
|
18331
18436
|
};
|
|
18332
18437
|
const sync = () => {
|
|
18333
18438
|
let text2;
|
|
18334
18439
|
try {
|
|
18335
|
-
text2 =
|
|
18440
|
+
text2 = import_node_fs7.default.readFileSync(file, "utf8");
|
|
18336
18441
|
} catch {
|
|
18337
18442
|
return false;
|
|
18338
18443
|
}
|
|
@@ -18340,8 +18445,8 @@ function createCommentStore(file, names = noNames, now = () => (/* @__PURE__ */
|
|
|
18340
18445
|
lastSeen = text2;
|
|
18341
18446
|
try {
|
|
18342
18447
|
const incoming = parseComments(text2);
|
|
18343
|
-
const base = loaded ? current :
|
|
18344
|
-
const merged =
|
|
18448
|
+
const base = loaded ? current : rules.saved(incoming);
|
|
18449
|
+
const merged = rules.merge(base, incoming, "agent", now(), newId, names.agent());
|
|
18345
18450
|
current = merged.file;
|
|
18346
18451
|
warnings = merged.warnings;
|
|
18347
18452
|
if (`${JSON.stringify(current, null, 2)}
|
|
@@ -18359,13 +18464,13 @@ function createCommentStore(file, names = noNames, now = () => (/* @__PURE__ */
|
|
|
18359
18464
|
sync,
|
|
18360
18465
|
apply: (op) => {
|
|
18361
18466
|
sync();
|
|
18362
|
-
current =
|
|
18467
|
+
current = rules.human(current, op, now(), newId, names.human());
|
|
18363
18468
|
write();
|
|
18364
18469
|
return current;
|
|
18365
18470
|
},
|
|
18366
18471
|
applyAgent: (op, name) => {
|
|
18367
18472
|
sync();
|
|
18368
|
-
const result =
|
|
18473
|
+
const result = rules.agent(current, op, now(), newId, name ?? names.agent());
|
|
18369
18474
|
current = result.file;
|
|
18370
18475
|
write();
|
|
18371
18476
|
return result;
|
|
@@ -18373,38 +18478,166 @@ function createCommentStore(file, names = noNames, now = () => (/* @__PURE__ */
|
|
|
18373
18478
|
};
|
|
18374
18479
|
}
|
|
18375
18480
|
|
|
18376
|
-
// src/server/
|
|
18377
|
-
var
|
|
18378
|
-
|
|
18379
|
-
|
|
18380
|
-
|
|
18381
|
-
|
|
18382
|
-
|
|
18383
|
-
|
|
18384
|
-
|
|
18481
|
+
// src/server/board-comments.ts
|
|
18482
|
+
var boardRules = {
|
|
18483
|
+
empty: emptyBoardComments,
|
|
18484
|
+
saved: savedBoardComments,
|
|
18485
|
+
merge: mergeBoardComments,
|
|
18486
|
+
human: (file, op, now, newId, who) => applyBoardHumanOp(file, op, now, newId, who),
|
|
18487
|
+
agent: applyBoardAgentOp
|
|
18488
|
+
};
|
|
18489
|
+
var withoutHashes = ({ hashes: _hashes, ...anchor }) => anchor;
|
|
18490
|
+
function asBoardHumanOp(value) {
|
|
18491
|
+
if (typeof value !== "object" || value === null) return null;
|
|
18492
|
+
const v6 = value;
|
|
18493
|
+
if (v6.op !== "create") {
|
|
18494
|
+
const op = asHumanOp(value);
|
|
18495
|
+
return op && op.op !== "create" ? op : null;
|
|
18496
|
+
}
|
|
18497
|
+
const anchor = readBoardAnchor(v6.anchor);
|
|
18498
|
+
return anchor && isText3(v6.text) && v6.text.length > 0 ? { op: "create", anchor: withoutHashes(anchor), text: v6.text } : null;
|
|
18499
|
+
}
|
|
18500
|
+
function asBoardAgentOp(value) {
|
|
18501
|
+
if (typeof value !== "object" || value === null) return null;
|
|
18502
|
+
const v6 = value;
|
|
18503
|
+
if (v6.op === "add") {
|
|
18504
|
+
const anchor = readBoardAnchor(v6.anchor);
|
|
18505
|
+
return anchor && isText3(v6.text) && v6.text.length > 0 ? { op: "add", anchor: withoutHashes(anchor), text: v6.text } : null;
|
|
18506
|
+
}
|
|
18507
|
+
if (v6.op === "reply") return isId(v6.threadId) && isText3(v6.text) && v6.text.length > 0 ? { op: "reply", threadId: v6.threadId, text: v6.text } : null;
|
|
18508
|
+
if (v6.op === "resolve") return isId(v6.threadId) ? { op: "resolve", threadId: v6.threadId } : null;
|
|
18509
|
+
return null;
|
|
18510
|
+
}
|
|
18511
|
+
function boardSpecs(dir) {
|
|
18385
18512
|
try {
|
|
18386
|
-
const
|
|
18387
|
-
|
|
18388
|
-
|
|
18513
|
+
const canvas = JSON.parse(import_node_fs8.default.readFileSync(import_node_path7.default.join(dir, "canvas.json"), "utf8"));
|
|
18514
|
+
return Object.fromEntries(Object.entries(canvas.boards ?? {}).flatMap(
|
|
18515
|
+
([id2, board]) => typeof board?.file === "string" ? [[id2, { file: board.file, page: typeof board.page === "string" ? board.page : "", w: typeof board.w === "number" ? board.w : 0 }]] : []
|
|
18516
|
+
));
|
|
18389
18517
|
} catch {
|
|
18390
18518
|
return {};
|
|
18391
18519
|
}
|
|
18392
18520
|
}
|
|
18393
|
-
|
|
18521
|
+
var boardFiles = (dir) => Object.fromEntries(Object.entries(boardSpecs(dir)).map(([id2, spec]) => [id2, spec.file]));
|
|
18522
|
+
function agentAddOnBoard(value, specs) {
|
|
18523
|
+
if (typeof value !== "object" || value === null) return null;
|
|
18524
|
+
const v6 = value;
|
|
18525
|
+
if (v6.op !== "add" || typeof v6.board !== "string" || v6.anchor !== void 0) return null;
|
|
18526
|
+
const spec = specs[v6.board];
|
|
18527
|
+
if (!spec) return { error: `no board ${v6.board}` };
|
|
18528
|
+
return asBoardAgentOp({ op: "add", anchor: { page: spec.page, board: v6.board, x: v6.x ?? spec.w, y: v6.y ?? 0 }, text: v6.text });
|
|
18529
|
+
}
|
|
18530
|
+
function fileHash(dir, relative) {
|
|
18531
|
+
const file = resolveBoardFile(dir, relative);
|
|
18532
|
+
if (!file) return null;
|
|
18533
|
+
try {
|
|
18534
|
+
return import_node_crypto2.default.createHash("sha1").update(import_node_fs8.default.readFileSync(file)).digest("hex").slice(0, 12);
|
|
18535
|
+
} catch {
|
|
18536
|
+
return null;
|
|
18537
|
+
}
|
|
18538
|
+
}
|
|
18539
|
+
function boardHashes(dir) {
|
|
18540
|
+
return Object.fromEntries(Object.entries(boardFiles(dir)).flatMap(([id2, file]) => {
|
|
18541
|
+
const hash = fileHash(dir, file);
|
|
18542
|
+
return hash ? [[id2, hash]] : [];
|
|
18543
|
+
}));
|
|
18544
|
+
}
|
|
18545
|
+
var boardsOf = (anchor) => [.../* @__PURE__ */ new Set([...anchor.board ? [anchor.board] : [], ...(anchor.nodes ?? []).map((node) => node.board)])];
|
|
18546
|
+
function stamp(anchor, hashes) {
|
|
18547
|
+
const boards = boardsOf(anchor);
|
|
18548
|
+
if (!boards.length) return withoutHashes(anchor);
|
|
18549
|
+
return { ...withoutHashes(anchor), hashes: Object.fromEntries(boards.map((board) => [board, hashes[board] ?? "missing"])) };
|
|
18550
|
+
}
|
|
18551
|
+
var isStale = (thread, hashes) => Object.entries(thread.anchor.hashes ?? {}).some(([board, hash]) => hashes[board] !== hash);
|
|
18552
|
+
function createBoardCommentRegistry(options) {
|
|
18553
|
+
const stores = /* @__PURE__ */ new Map();
|
|
18554
|
+
const hashes = /* @__PURE__ */ new Map();
|
|
18555
|
+
const lastStale = /* @__PURE__ */ new Map();
|
|
18556
|
+
const cursors = createCommentCursors(options.stateDir, "artboard");
|
|
18557
|
+
const dirOf = (id2) => import_node_path7.default.join(options.root, "artboard", id2);
|
|
18558
|
+
const store = (id2) => {
|
|
18559
|
+
let found = stores.get(id2);
|
|
18560
|
+
if (!found) {
|
|
18561
|
+
found = createStore(import_node_path7.default.join(dirOf(id2), "comments.json"), boardRules, options.names);
|
|
18562
|
+
stores.set(id2, found);
|
|
18563
|
+
}
|
|
18564
|
+
return found;
|
|
18565
|
+
};
|
|
18566
|
+
const currentHashes = (id2) => {
|
|
18567
|
+
let found = hashes.get(id2);
|
|
18568
|
+
if (!found) {
|
|
18569
|
+
found = boardHashes(dirOf(id2));
|
|
18570
|
+
hashes.set(id2, found);
|
|
18571
|
+
}
|
|
18572
|
+
return found;
|
|
18573
|
+
};
|
|
18574
|
+
const stale = (id2) => {
|
|
18575
|
+
const now = currentHashes(id2);
|
|
18576
|
+
return store(id2).current().threads.filter((thread) => isStale(thread, now)).map((thread) => thread.id);
|
|
18577
|
+
};
|
|
18578
|
+
const push2 = (id2) => {
|
|
18579
|
+
const ids = stale(id2);
|
|
18580
|
+
lastStale.set(id2, JSON.stringify(ids));
|
|
18581
|
+
options.broadcast({ type: "board-comments", artifact: `artboard/${id2}`, comments: store(id2).current(), stale: ids });
|
|
18582
|
+
};
|
|
18583
|
+
const fresh = (id2) => {
|
|
18584
|
+
hashes.delete(id2);
|
|
18585
|
+
return currentHashes(id2);
|
|
18586
|
+
};
|
|
18587
|
+
const forAgent2 = (id2, staleIds) => {
|
|
18588
|
+
const files = boardFiles(dirOf(id2));
|
|
18589
|
+
return (thread) => ({
|
|
18590
|
+
...thread,
|
|
18591
|
+
stale: staleIds.has(thread.id),
|
|
18592
|
+
waitingOn: waitingOn(thread),
|
|
18593
|
+
files: Object.fromEntries(boardsOf(thread.anchor).flatMap((board) => files[board] ? [[board, files[board]]] : [])),
|
|
18594
|
+
messages: thread.messages.map(({ avatar: _avatar, ...message }) => message)
|
|
18595
|
+
});
|
|
18596
|
+
};
|
|
18394
18597
|
return {
|
|
18395
|
-
|
|
18396
|
-
|
|
18397
|
-
|
|
18398
|
-
|
|
18399
|
-
|
|
18400
|
-
|
|
18598
|
+
comments: (id2) => store(id2).current(),
|
|
18599
|
+
stale,
|
|
18600
|
+
warnings: (id2) => store(id2).warnings(),
|
|
18601
|
+
apply: (id2, op) => {
|
|
18602
|
+
const stamped = op.op === "create" ? { ...op, anchor: stamp(op.anchor, fresh(id2)) } : op;
|
|
18603
|
+
store(id2).apply(stamped);
|
|
18604
|
+
push2(id2);
|
|
18605
|
+
return { comments: store(id2).current(), stale: stale(id2) };
|
|
18606
|
+
},
|
|
18607
|
+
applyAgent: (id2, op, agent) => {
|
|
18608
|
+
const stamped = op.op === "add" ? { ...op, anchor: stamp(op.anchor, fresh(id2)) } : op;
|
|
18609
|
+
const { threadId, messageId } = store(id2).applyAgent(stamped, agent);
|
|
18610
|
+
push2(id2);
|
|
18611
|
+
return { threadId, ...messageId ? { messageId } : {} };
|
|
18612
|
+
},
|
|
18613
|
+
list: (id2, agent, all) => {
|
|
18614
|
+
const changed = store(id2).sync();
|
|
18615
|
+
if (changed) push2(id2);
|
|
18616
|
+
const file = store(id2).current();
|
|
18617
|
+
const format = forAgent2(id2, new Set(stale(id2)));
|
|
18618
|
+
if (all) return file.threads.filter((t7) => !t7.messages.every((m11) => m11.deleted)).map(format);
|
|
18619
|
+
const { threads, newest } = unreadThreads(file, cursors.get(id2, agent));
|
|
18620
|
+
if (newest) cursors.set(id2, agent, newest);
|
|
18621
|
+
return threads.map(format);
|
|
18622
|
+
},
|
|
18623
|
+
sync: (id2) => {
|
|
18624
|
+
if (store(id2).sync()) push2(id2);
|
|
18625
|
+
},
|
|
18626
|
+
boardsChanged: (id2) => {
|
|
18627
|
+
fresh(id2);
|
|
18628
|
+
if (!stores.has(id2) && !import_node_fs8.default.existsSync(import_node_path7.default.join(dirOf(id2), "comments.json"))) return;
|
|
18629
|
+
if (JSON.stringify(stale(id2)) !== (lastStale.get(id2) ?? "[]")) push2(id2);
|
|
18401
18630
|
}
|
|
18402
18631
|
};
|
|
18403
18632
|
}
|
|
18404
18633
|
|
|
18634
|
+
// src/server/documents.ts
|
|
18635
|
+
var import_node_fs9 = __toESM(require("node:fs"), 1);
|
|
18636
|
+
var import_node_path9 = __toESM(require("node:path"), 1);
|
|
18637
|
+
|
|
18405
18638
|
// src/server/document-session.ts
|
|
18406
18639
|
var import_promises = __toESM(require("node:fs/promises"), 1);
|
|
18407
|
-
var
|
|
18640
|
+
var import_node_path8 = __toESM(require("node:path"), 1);
|
|
18408
18641
|
|
|
18409
18642
|
// node_modules/.pnpm/lexical@0.52.0_typescript@5.9.3/node_modules/lexical/dist/Lexical.dev.js
|
|
18410
18643
|
var Lexical_dev_exports = {};
|
|
@@ -19262,19 +19495,19 @@ var ElementDOMSlot = class _ElementDOMSlot extends DOMSlot {
|
|
|
19262
19495
|
}
|
|
19263
19496
|
};
|
|
19264
19497
|
function indexPath(root, child) {
|
|
19265
|
-
const
|
|
19498
|
+
const path22 = [];
|
|
19266
19499
|
let node = child;
|
|
19267
19500
|
for (; node !== root && node !== null; node = node.parentNode) {
|
|
19268
19501
|
let i6 = 0;
|
|
19269
19502
|
for (let sibling = node.previousSibling; sibling !== null; sibling = sibling.previousSibling) {
|
|
19270
19503
|
i6++;
|
|
19271
19504
|
}
|
|
19272
|
-
|
|
19505
|
+
path22.push(i6);
|
|
19273
19506
|
}
|
|
19274
19507
|
if (!(node === root)) {
|
|
19275
19508
|
formatDevErrorMessage(`indexPath: root is not a parent of child`);
|
|
19276
19509
|
}
|
|
19277
|
-
return
|
|
19510
|
+
return path22.reverse();
|
|
19278
19511
|
}
|
|
19279
19512
|
// @__NO_SIDE_EFFECTS__
|
|
19280
19513
|
function readLexicalVersion() {
|
|
@@ -34054,9 +34287,9 @@ function getActiveElementDeep(root) {
|
|
|
34054
34287
|
function getComposedEventTarget(event) {
|
|
34055
34288
|
const target = event.target;
|
|
34056
34289
|
if (target !== null && isHTMLElement(target) && target.shadowRoot !== null && typeof event.composedPath === "function") {
|
|
34057
|
-
const
|
|
34058
|
-
if (
|
|
34059
|
-
return
|
|
34290
|
+
const path22 = event.composedPath();
|
|
34291
|
+
if (path22.length > 0) {
|
|
34292
|
+
return path22[0];
|
|
34060
34293
|
}
|
|
34061
34294
|
}
|
|
34062
34295
|
return target;
|
|
@@ -35967,7 +36200,7 @@ __export(Lexical_prod_exports, {
|
|
|
35967
36200
|
$getNodeFromDOMNode: () => Qc,
|
|
35968
36201
|
$getPreviousSelection: () => ds,
|
|
35969
36202
|
$getRoot: () => ra,
|
|
35970
|
-
$getSelection: () =>
|
|
36203
|
+
$getSelection: () => fs9,
|
|
35971
36204
|
$getSelectionSlotFrame: () => Df,
|
|
35972
36205
|
$getSiblingCaret: () => ad,
|
|
35973
36206
|
$getSlot: () => Lf,
|
|
@@ -36707,9 +36940,9 @@ function Ct(t7, e5, n7) {
|
|
|
36707
36940
|
const o8 = performance.now() - _t > 100;
|
|
36708
36941
|
try {
|
|
36709
36942
|
al(t7, () => {
|
|
36710
|
-
const r7 =
|
|
36943
|
+
const r7 = fs9() || (function(t8) {
|
|
36711
36944
|
return t8.read("latest", () => {
|
|
36712
|
-
const t9 =
|
|
36945
|
+
const t9 = fs9();
|
|
36713
36946
|
return null !== t9 ? t9.clone() : null;
|
|
36714
36947
|
});
|
|
36715
36948
|
})(t7), i6 = /* @__PURE__ */ new Map(), s7 = t7._editorState, l8 = t7._blockCursorElement;
|
|
@@ -37989,7 +38222,7 @@ function Yo(t7, n7, o8) {
|
|
|
37989
38222
|
al(n7, () => {
|
|
37990
38223
|
if (!o8) return void sa(null);
|
|
37991
38224
|
if (!Dc(n7, r7, s7)) return;
|
|
37992
|
-
let a5 =
|
|
38225
|
+
let a5 = fs9();
|
|
37993
38226
|
if (c10.postDeleteSelectionToRestore && zi(a5) && a5.isCollapsed()) {
|
|
37994
38227
|
const t8 = a5.anchor, e5 = c10.postDeleteSelectionToRestore.anchor;
|
|
37995
38228
|
(t8.key === e5.key && t8.offset === e5.offset + 1 || 1 === t8.offset && e5.getNode().is(t8.getNode().getPreviousSibling())) && (a5 = c10.postDeleteSelectionToRestore.clone(), sa(a5));
|
|
@@ -38031,7 +38264,7 @@ function Xo(t7, e5) {
|
|
|
38031
38264
|
}
|
|
38032
38265
|
function Qo(t7, e5) {
|
|
38033
38266
|
al(e5, () => {
|
|
38034
|
-
const n7 =
|
|
38267
|
+
const n7 = fs9(), o8 = Qa(Wa(e5)), r7 = ds();
|
|
38035
38268
|
if (o8) {
|
|
38036
38269
|
if (zi(n7)) {
|
|
38037
38270
|
const t8 = n7.anchor, e6 = t8.getNode();
|
|
@@ -38080,7 +38313,7 @@ function er(t7) {
|
|
|
38080
38313
|
if (null == t7 || t7.length <= 1 || null == e5) return;
|
|
38081
38314
|
const n7 = 1 === e5.length ? e5 : "Enter" === e5 ? "\n" : "Tab" === e5 ? " " : null;
|
|
38082
38315
|
if (!n7) return;
|
|
38083
|
-
const o8 =
|
|
38316
|
+
const o8 = fs9();
|
|
38084
38317
|
if (!zi(o8) || !o8.isCollapsed()) return;
|
|
38085
38318
|
const r7 = o8.anchor.getNode();
|
|
38086
38319
|
if (!ki(r7)) return;
|
|
@@ -38112,7 +38345,7 @@ function rr(t7, e5) {
|
|
|
38112
38345
|
return null !== r7 && o8.contains(r7) && Ju(r7, e5);
|
|
38113
38346
|
}
|
|
38114
38347
|
function ir(t7) {
|
|
38115
|
-
const n7 = t7.inputType, o8 = tr(t7), r7 = Vs(), i6 = r7._inputState, s7 =
|
|
38348
|
+
const n7 = t7.inputType, o8 = tr(t7), r7 = Vs(), i6 = r7._inputState, s7 = fs9();
|
|
38116
38349
|
if ("insertText" === n7 && t7.data && i6.isInsertTextAfterHandledSelectionCommand) {
|
|
38117
38350
|
if (nr(i6), t7.preventDefault(), zi(s7) && !s7.isCollapsed()) {
|
|
38118
38351
|
const t8 = s7.isBackward() ? s7.anchor : s7.focus;
|
|
@@ -38146,7 +38379,7 @@ function ir(t7) {
|
|
|
38146
38379
|
let u9 = m && n8 && !a6 && c11;
|
|
38147
38380
|
if (u9 && s7.isCollapsed() && (u9 = !Sl(Ea(s7.anchor, true))), !u9) {
|
|
38148
38381
|
Ma(r7, jn, true);
|
|
38149
|
-
const t8 =
|
|
38382
|
+
const t8 = fs9();
|
|
38150
38383
|
m && zi(t8) && t8.isCollapsed() && (i6.postDeleteSelectionToRestore = t8, setTimeout(() => i6.postDeleteSelectionToRestore = null));
|
|
38151
38384
|
}
|
|
38152
38385
|
}
|
|
@@ -38246,7 +38479,7 @@ function sr(t7, e5) {
|
|
|
38246
38479
|
}, { event: t7 }), n7.unprocessedBeforeInputData = null;
|
|
38247
38480
|
}
|
|
38248
38481
|
function lr(t7) {
|
|
38249
|
-
const e5 = Vs(), n7 = e5._inputState, o8 =
|
|
38482
|
+
const e5 = Vs(), n7 = e5._inputState, o8 = fs9(), r7 = t7.data, i6 = tr(t7);
|
|
38250
38483
|
let s7 = false;
|
|
38251
38484
|
if (null != r7 && zi(o8)) {
|
|
38252
38485
|
const l8 = Qa(Wa(e5)), c10 = null !== l8 ? cu(l8, e5._rootElement) : null, a5 = "insertCompositionText" === t7.inputType && "ending-firefox" !== n7.compositionPhase && !e5.isComposing();
|
|
@@ -38271,13 +38504,13 @@ function cr(t7, e5) {
|
|
|
38271
38504
|
Ma(e5, Wn, t7);
|
|
38272
38505
|
}
|
|
38273
38506
|
function ar(t7) {
|
|
38274
|
-
const e5 = Vs(), n7 = e5._inputState, o8 =
|
|
38507
|
+
const e5 = Vs(), n7 = e5._inputState, o8 = fs9();
|
|
38275
38508
|
if (zi(o8) && !e5.isComposing()) {
|
|
38276
38509
|
n7.compositionPhase = "composing", n7.hadOrphanedCompositionEvents = false;
|
|
38277
38510
|
const r7 = o8.anchor, i6 = o8.anchor.getNode();
|
|
38278
38511
|
if (Yc(r7.key), za(Ur), t7.timeStamp < n7.lastKeyDownTimeStamp + 30 || "element" === r7.type || !o8.isCollapsed() || !m && (i6.getFormat() !== o8.format || ki(i6) && i6.getStyle() !== o8.style) || ki(i6) && (Bc(i6) || 0 === r7.offset && !i6.canInsertTextBefore() || r7.offset === i6.getTextContentSize() && !i6.canInsertTextAfter())) {
|
|
38279
38512
|
Ma(e5, Jn, F);
|
|
38280
|
-
const t8 =
|
|
38513
|
+
const t8 = fs9();
|
|
38281
38514
|
zi(t8) && Yc(t8.anchor.key);
|
|
38282
38515
|
}
|
|
38283
38516
|
}
|
|
@@ -38291,7 +38524,7 @@ function fr(t7) {
|
|
|
38291
38524
|
if (null === t7) return;
|
|
38292
38525
|
const e5 = Xc(t7);
|
|
38293
38526
|
if (!ki(e5) || "text" === e5.getType() || Bc(e5) || !e5.isAttached()) return;
|
|
38294
|
-
const n7 =
|
|
38527
|
+
const n7 = fs9(), o8 = zi(n7) && n7.anchor.key === t7 ? n7.anchor.offset : null, r7 = vi(e5.getTextContent());
|
|
38295
38528
|
if (r7.setFormat(e5.getFormat()), r7.setStyle(e5.getStyle()), e5.replace(r7), null !== o8) {
|
|
38296
38529
|
const t8 = Math.min(o8, r7.getTextContentSize());
|
|
38297
38530
|
r7.select(t8, t8);
|
|
@@ -38310,7 +38543,7 @@ function dr(t7, e5) {
|
|
|
38310
38543
|
return fr(n7), false;
|
|
38311
38544
|
}
|
|
38312
38545
|
if ("\n" === e5[e5.length - 1]) {
|
|
38313
|
-
const e6 =
|
|
38546
|
+
const e6 = fs9();
|
|
38314
38547
|
if (zi(e6) || Bi(e6)) {
|
|
38315
38548
|
if (zi(e6)) {
|
|
38316
38549
|
const t8 = e6.focus;
|
|
@@ -38322,7 +38555,7 @@ function dr(t7, e5) {
|
|
|
38322
38555
|
const o8 = Xc(n7);
|
|
38323
38556
|
if (null !== o8 && ki(o8) && Bc(o8)) {
|
|
38324
38557
|
o8.markDirty();
|
|
38325
|
-
const t8 =
|
|
38558
|
+
const t8 = fs9(), r7 = o8.getTextContentSize(), i6 = zi(t8) && t8.anchor.key === n7 ? t8.anchor.offset : r7;
|
|
38326
38559
|
return o8.select(i6, i6).insertText(e5), true;
|
|
38327
38560
|
}
|
|
38328
38561
|
}
|
|
@@ -38449,7 +38682,7 @@ function wr(t7, n7, o8) {
|
|
|
38449
38682
|
const r7 = t7.__key, i6 = t7.getParent();
|
|
38450
38683
|
if (null === i6) return void (null !== Of(t7) && e(367, r7, String(Of(t7))));
|
|
38451
38684
|
const s7 = (function(t8) {
|
|
38452
|
-
const e5 =
|
|
38685
|
+
const e5 = fs9();
|
|
38453
38686
|
if (!zi(e5) || !yl(t8)) return e5;
|
|
38454
38687
|
const { anchor: n8, focus: o9 } = e5, r8 = n8.getNode(), i7 = o9.getNode();
|
|
38455
38688
|
return Ba(r8, t8) && n8.set(t8.__key, 0, "element"), Ba(i7, t8) && o9.set(t8.__key, 0, "element"), e5;
|
|
@@ -38521,7 +38754,7 @@ var Fr = class {
|
|
|
38521
38754
|
return false;
|
|
38522
38755
|
}
|
|
38523
38756
|
isSelected(t7) {
|
|
38524
|
-
const e5 = t7 ||
|
|
38757
|
+
const e5 = t7 || fs9();
|
|
38525
38758
|
if (null == e5) return false;
|
|
38526
38759
|
const n7 = e5.getNodes().some((t8) => t8.__key === this.__key);
|
|
38527
38760
|
if (ki(this)) return n7;
|
|
@@ -38711,7 +38944,7 @@ var Fr = class {
|
|
|
38711
38944
|
}
|
|
38712
38945
|
replace(t7, n7) {
|
|
38713
38946
|
Ws();
|
|
38714
|
-
let o8 =
|
|
38947
|
+
let o8 = fs9();
|
|
38715
38948
|
null !== o8 && (o8 = o8.clone()), qa(this, t7);
|
|
38716
38949
|
const r7 = this.getLatest(), i6 = this.__key, s7 = Mf(r7);
|
|
38717
38950
|
null !== s7 && e(400, i6, r7.getType(), s7.getKey(), s7.getType());
|
|
@@ -38731,7 +38964,7 @@ var Fr = class {
|
|
|
38731
38964
|
Ws(), qa(this, t7);
|
|
38732
38965
|
const n7 = this.getWritable(), o8 = t7.getWritable();
|
|
38733
38966
|
this.getParentOrThrow();
|
|
38734
|
-
const r7 = o8.getParent(), i6 =
|
|
38967
|
+
const r7 = o8.getParent(), i6 = fs9();
|
|
38735
38968
|
let s7 = false, l8 = false, c10 = -1;
|
|
38736
38969
|
if (null !== r7 && e5 && zi(i6) && hs(i6, r7)) {
|
|
38737
38970
|
const e6 = r7.__key, n8 = i6.anchor, o9 = i6.focus;
|
|
@@ -38752,7 +38985,7 @@ var Fr = class {
|
|
|
38752
38985
|
Ws(), qa(this, t7);
|
|
38753
38986
|
const n7 = this.getWritable(), o8 = t7.getWritable();
|
|
38754
38987
|
this.getParentOrThrow();
|
|
38755
|
-
const r7 = o8.__key, i6 =
|
|
38988
|
+
const r7 = o8.__key, i6 = fs9(), s7 = o8.getParent(), l8 = null !== s7 && e5 && zi(i6) && hs(i6, s7), c10 = l8 ? o8.getIndexWithinParent() : -1;
|
|
38756
38989
|
Jc(o8), l8 && null !== s7 && zi(i6) && gs(i6, s7, c10, -1);
|
|
38757
38990
|
const a5 = this.getPreviousSibling(), u8 = this.getParentOrThrow().getWritable(), f6 = n7.__prev, d9 = e5 && zi(i6) && hs(i6, u8), h9 = d9 ? this.getIndexWithinParent() : -1;
|
|
38758
38991
|
return null === a5 ? u8.__first = r7 : a5.getWritable().__next = r7, u8.__size++, n7.__prev = r7, o8.__prev = f6, o8.__next = n7.__key, o8.__parent = n7.__parent, d9 && zi(i6) && gs(i6, u8, h9), t7;
|
|
@@ -39150,7 +39383,7 @@ var hi = class extends Fr {
|
|
|
39150
39383
|
select(t7, e5) {
|
|
39151
39384
|
Ws();
|
|
39152
39385
|
let n7 = t7, o8 = e5;
|
|
39153
|
-
const r7 =
|
|
39386
|
+
const r7 = fs9(), i6 = this.getTextContent(), s7 = this.__key;
|
|
39154
39387
|
if ("string" == typeof i6) {
|
|
39155
39388
|
const t8 = i6.length;
|
|
39156
39389
|
void 0 === n7 && (n7 = t8), void 0 === o8 && (o8 = t8);
|
|
@@ -39173,7 +39406,7 @@ var hi = class extends Fr {
|
|
|
39173
39406
|
const r7 = this.getWritable(), i6 = r7.__text, s7 = n7.length;
|
|
39174
39407
|
let l8 = t7;
|
|
39175
39408
|
l8 < 0 && (l8 = s7 + l8, l8 < 0 && (l8 = 0));
|
|
39176
|
-
const c10 =
|
|
39409
|
+
const c10 = fs9();
|
|
39177
39410
|
if (o8 && zi(c10)) {
|
|
39178
39411
|
const e6 = t7 + s7;
|
|
39179
39412
|
c10.setTextNodeRange(r7, e6, r7, e6);
|
|
@@ -39204,7 +39437,7 @@ var hi = class extends Fr {
|
|
|
39204
39437
|
let f6;
|
|
39205
39438
|
const d9 = e5.getFormat(), h9 = e5.getStyle(), g8 = e5.__detail;
|
|
39206
39439
|
let _5 = false, p7 = null, y5 = null;
|
|
39207
|
-
const m11 =
|
|
39440
|
+
const m11 = fs9();
|
|
39208
39441
|
if (zi(m11)) {
|
|
39209
39442
|
const [t8, e6] = m11.isBackward() ? [m11.focus, m11.anchor] : [m11.anchor, m11.focus];
|
|
39210
39443
|
"text" === t8.type && t8.key === o8 && (p7 = t8), "text" === e6.type && e6.key === o8 && (y5 = e6);
|
|
@@ -39243,7 +39476,7 @@ var hi = class extends Fr {
|
|
|
39243
39476
|
n7 || t7 === this.getNextSibling() || e(50);
|
|
39244
39477
|
const o8 = this.__key, r7 = t7.__key, i6 = this.__text, s7 = i6.length;
|
|
39245
39478
|
Gc() === r7 && Yc(o8);
|
|
39246
|
-
const l8 =
|
|
39479
|
+
const l8 = fs9();
|
|
39247
39480
|
if (zi(l8)) {
|
|
39248
39481
|
const e5 = l8.anchor, i7 = l8.focus;
|
|
39249
39482
|
null !== e5 && e5.key === r7 && ys(e5, n7, o8, t7, s7), null !== i7 && i7.key === r7 && ys(i7, n7, o8, t7, s7);
|
|
@@ -39530,7 +39763,7 @@ var Ii = class _Ii {
|
|
|
39530
39763
|
}
|
|
39531
39764
|
deleteNodes() {
|
|
39532
39765
|
const t7 = this.getNodes().filter((t8) => null === Of(t8));
|
|
39533
|
-
if ((
|
|
39766
|
+
if ((fs9() || ds()) === this && t7[0]) {
|
|
39534
39767
|
const e5 = ad(t7[0], "next");
|
|
39535
39768
|
Kl(vd(e5, e5));
|
|
39536
39769
|
}
|
|
@@ -39540,7 +39773,7 @@ var Ii = class _Ii {
|
|
|
39540
39773
|
};
|
|
39541
39774
|
function Li() {
|
|
39542
39775
|
const t7 = ra();
|
|
39543
|
-
if (0 === t7.getChildrenSize() && null === Df(
|
|
39776
|
+
if (0 === t7.getChildrenSize() && null === Df(fs9())) {
|
|
39544
39777
|
const e5 = oc();
|
|
39545
39778
|
t7.append(e5), e5.select();
|
|
39546
39779
|
}
|
|
@@ -39667,8 +39900,8 @@ var Ki = class _Ki {
|
|
|
39667
39900
|
else {
|
|
39668
39901
|
const t8 = vi(r7.getTextContent());
|
|
39669
39902
|
t8.setFormat(n7), t8.setStyle(o8);
|
|
39670
|
-
const e6 =
|
|
39671
|
-
r7.replace(t8), this.setTextNodeRange(t8, i6, t8, i6), e6 &&
|
|
39903
|
+
const e6 = fs9() === this;
|
|
39904
|
+
r7.replace(t8), this.setTextNodeRange(t8, i6, t8, i6), e6 && fs9() !== this && sa(this);
|
|
39672
39905
|
}
|
|
39673
39906
|
return void ("" !== t7 && this.insertText(t7));
|
|
39674
39907
|
}
|
|
@@ -39703,14 +39936,14 @@ var Ki = class _Ki {
|
|
|
39703
39936
|
r7.spliceText(i6, 0, t7, true), r7.isComposing() && "text" === this.anchor.type && this.anchor.set(this.anchor.key, this.anchor.offset - t7.length, this.anchor.type);
|
|
39704
39937
|
}
|
|
39705
39938
|
removeText() {
|
|
39706
|
-
const t7 =
|
|
39939
|
+
const t7 = fs9() === this, e5 = this.anchor.key;
|
|
39707
39940
|
Bl(this, Ul(Rl(this))), this.isCollapsed() && (function(t8, e6) {
|
|
39708
39941
|
const n7 = t8.anchor;
|
|
39709
39942
|
if (n7.key === e6) return;
|
|
39710
39943
|
const o8 = n7.getNode();
|
|
39711
39944
|
let r7 = 0, i6 = "";
|
|
39712
39945
|
ki(o8) ? (r7 = o8.getFormat(), i6 = o8.getStyle()) : yl(o8) && (r7 = o8.getTextFormat(), i6 = o8.getTextStyle()), t8.format === r7 && t8.style === i6 || (t8.format = r7, t8.style = i6, t8.dirty = true);
|
|
39713
|
-
})(this, e5), t7 &&
|
|
39946
|
+
})(this, e5), t7 && fs9() !== this && sa(this);
|
|
39714
39947
|
}
|
|
39715
39948
|
formatText(t7, e5 = null) {
|
|
39716
39949
|
$i(this, t7, e5);
|
|
@@ -39727,7 +39960,7 @@ var Ki = class _Ki {
|
|
|
39727
39960
|
}
|
|
39728
39961
|
if (null !== o9) {
|
|
39729
39962
|
o9.selectStart();
|
|
39730
|
-
const n8 =
|
|
39963
|
+
const n8 = fs9();
|
|
39731
39964
|
return zi(n8) || e(369), n8.insertNodes(t7);
|
|
39732
39965
|
}
|
|
39733
39966
|
}
|
|
@@ -40321,7 +40554,7 @@ function us(t7, e5, n7, o8) {
|
|
|
40321
40554
|
const x9 = new Ki(g8, _5, y5, m11);
|
|
40322
40555
|
return p7 && (x9.dirty = true), x9;
|
|
40323
40556
|
}
|
|
40324
|
-
function
|
|
40557
|
+
function fs9() {
|
|
40325
40558
|
return js()._selection;
|
|
40326
40559
|
}
|
|
40327
40560
|
function ds() {
|
|
@@ -40491,7 +40724,7 @@ function Ss(t7, e5, n7, o8, r7, i6) {
|
|
|
40491
40724
|
}
|
|
40492
40725
|
}
|
|
40493
40726
|
function Cs(t7) {
|
|
40494
|
-
let e5 =
|
|
40727
|
+
let e5 = fs9() || ds();
|
|
40495
40728
|
null === e5 && (e5 = ra().selectEnd()), e5.insertNodes(t7);
|
|
40496
40729
|
}
|
|
40497
40730
|
function vs(t7, e5) {
|
|
@@ -40502,7 +40735,7 @@ function ks(t7) {
|
|
|
40502
40735
|
return vs(t7, { linebreak: () => e5.push(Al()), tab: () => e5.push(wi()), text: (t8) => e5.push(vi(t8)) }), e5;
|
|
40503
40736
|
}
|
|
40504
40737
|
function bs() {
|
|
40505
|
-
const t7 =
|
|
40738
|
+
const t7 = fs9();
|
|
40506
40739
|
return null === t7 ? "" : t7.getTextContent();
|
|
40507
40740
|
}
|
|
40508
40741
|
function Ts(t7) {
|
|
@@ -40513,7 +40746,7 @@ function Ts(t7) {
|
|
|
40513
40746
|
function Ns(t7, n7 = false) {
|
|
40514
40747
|
let o8 = t7;
|
|
40515
40748
|
t7.isCollapsed() || o8.removeText();
|
|
40516
|
-
const r7 =
|
|
40749
|
+
const r7 = fs9();
|
|
40517
40750
|
zi(r7) && (o8 = r7), zi(o8) || e(161);
|
|
40518
40751
|
const i6 = o8.anchor;
|
|
40519
40752
|
let s7 = i6.getNode(), l8 = i6.offset;
|
|
@@ -41196,7 +41429,7 @@ var pl = class extends Fr {
|
|
|
41196
41429
|
}
|
|
41197
41430
|
select(t7, e5) {
|
|
41198
41431
|
Ws();
|
|
41199
|
-
const n7 =
|
|
41432
|
+
const n7 = fs9();
|
|
41200
41433
|
let o8 = t7, r7 = e5;
|
|
41201
41434
|
const i6 = this.getChildrenSize();
|
|
41202
41435
|
if (!this.canBeEmpty()) {
|
|
@@ -41293,7 +41526,7 @@ var pl = class extends Fr {
|
|
|
41293
41526
|
} else t8.__prev = null;
|
|
41294
41527
|
}
|
|
41295
41528
|
if (i6.__size = f6, c10.length) {
|
|
41296
|
-
const t8 =
|
|
41529
|
+
const t8 = fs9();
|
|
41297
41530
|
if (zi(t8)) {
|
|
41298
41531
|
const e5 = new Set(c10), n8 = new Set(l8), { anchor: o9, focus: r8 } = t8;
|
|
41299
41532
|
ml(o9, e5, n8) && ps(o9, o9.getNode(), this, u8, a5), ml(r8, e5, n8) && ps(r8, r8.getNode(), this, u8, a5), 0 !== f6 || this.canBeEmpty() || Va(this) || this.remove();
|
|
@@ -41576,7 +41809,7 @@ function zl(t7, n7) {
|
|
|
41576
41809
|
nd(n7) ? t7.set(o8.getKey(), n7.offset, "text") : rd(n7) ? ki(o8) ? t7.set(o8.getKey(), fd(o8, r7), "text") : t7.set(o8.getParentOrThrow().getKey(), o8.getIndexWithinParent() + (i6 ? 1 : 0), "element") : (id(n7) && yl(o8) || e(268), t7.set(o8.getKey(), i6 ? 0 : o8.getChildrenSize(), "element"));
|
|
41577
41810
|
}
|
|
41578
41811
|
function Kl(t7) {
|
|
41579
|
-
const e5 =
|
|
41812
|
+
const e5 = fs9(), n7 = zi(e5) ? e5 : ls();
|
|
41580
41813
|
return Bl(n7, t7), sa(n7), n7;
|
|
41581
41814
|
}
|
|
41582
41815
|
function Bl(t7, e5) {
|
|
@@ -42196,7 +42429,7 @@ var vc = class {
|
|
|
42196
42429
|
focus(t7, e5 = {}) {
|
|
42197
42430
|
const n7 = this._rootElement;
|
|
42198
42431
|
null !== n7 && (n7.setAttribute("autocapitalize", "off"), al(this, () => {
|
|
42199
|
-
const o8 =
|
|
42432
|
+
const o8 = fs9(), r7 = ra();
|
|
42200
42433
|
null !== o8 ? o8.dirty || sa(o8.clone()) : 0 !== r7.getChildrenSize() && ("rootStart" === e5.defaultSelection ? r7.selectStart() : r7.selectEnd()), za("focus"), Ka(() => {
|
|
42201
42434
|
n7.removeAttribute("autocapitalize"), t7 && t7();
|
|
42202
42435
|
});
|
|
@@ -42458,7 +42691,7 @@ function ga(t7, e5, n7, o8, r7) {
|
|
|
42458
42691
|
}
|
|
42459
42692
|
const c10 = i6.getTextContent();
|
|
42460
42693
|
if (r7 || l8 !== c10) {
|
|
42461
|
-
const e6 =
|
|
42694
|
+
const e6 = fs9();
|
|
42462
42695
|
if ("" === l8) {
|
|
42463
42696
|
if (Yc(null), p || g || x) i6.remove();
|
|
42464
42697
|
else {
|
|
@@ -44152,10 +44385,10 @@ function _loadWasmModule(sync, filepath, src, imports2) {
|
|
|
44152
44385
|
var buf = null;
|
|
44153
44386
|
var isNode2 = typeof process !== "undefined" && process.versions != null && process.versions.node != null;
|
|
44154
44387
|
if (filepath && isNode2) {
|
|
44155
|
-
var
|
|
44156
|
-
var
|
|
44388
|
+
var fs28 = null;
|
|
44389
|
+
var path22 = null;
|
|
44157
44390
|
return new Promise((resolve, reject) => {
|
|
44158
|
-
|
|
44391
|
+
fs28.readFile(path22.resolve(__dirname, filepath), (error, buffer) => {
|
|
44159
44392
|
if (error != null) {
|
|
44160
44393
|
reject(error);
|
|
44161
44394
|
} else {
|
|
@@ -45458,10 +45691,10 @@ var LoroDoc = class _LoroDoc {
|
|
|
45458
45691
|
* @param {string} path
|
|
45459
45692
|
* @returns {Value | Container | undefined}
|
|
45460
45693
|
*/
|
|
45461
|
-
getByPath(
|
|
45694
|
+
getByPath(path22) {
|
|
45462
45695
|
try {
|
|
45463
45696
|
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
45464
|
-
const ptr0 = passStringToWasm0(
|
|
45697
|
+
const ptr0 = passStringToWasm0(path22, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
45465
45698
|
const len0 = WASM_VECTOR_LEN;
|
|
45466
45699
|
wasm.lorodoc_getByPath(retptr, this.__wbg_ptr, ptr0, len0);
|
|
45467
45700
|
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
@@ -87436,7 +87669,7 @@ async function readText(file) {
|
|
|
87436
87669
|
}
|
|
87437
87670
|
}
|
|
87438
87671
|
async function writeAtomic(file, data) {
|
|
87439
|
-
await import_promises.default.mkdir(
|
|
87672
|
+
await import_promises.default.mkdir(import_node_path8.default.dirname(file), { recursive: true });
|
|
87440
87673
|
const tmp = `${file}.${process.pid}.tmp`;
|
|
87441
87674
|
await import_promises.default.writeFile(tmp, data);
|
|
87442
87675
|
await import_promises.default.rename(tmp, file);
|
|
@@ -87645,13 +87878,13 @@ function outcomeWarnings(outcome, streaming) {
|
|
|
87645
87878
|
function createDocumentRegistry(options) {
|
|
87646
87879
|
const sessions = /* @__PURE__ */ new Map();
|
|
87647
87880
|
const warnings = /* @__PURE__ */ new Map();
|
|
87648
|
-
const docFile = (id2) =>
|
|
87881
|
+
const docFile = (id2) => import_node_path9.default.join(options.root, "document", id2, "doc.xml");
|
|
87649
87882
|
const commentStores = /* @__PURE__ */ new Map();
|
|
87650
87883
|
const cursors = createCommentCursors(options.stateDir);
|
|
87651
87884
|
const commentStore = (id2) => {
|
|
87652
87885
|
let store = commentStores.get(id2);
|
|
87653
87886
|
if (!store) {
|
|
87654
|
-
store = createCommentStore(
|
|
87887
|
+
store = createCommentStore(import_node_path9.default.join(options.root, "document", id2, "comments.json"), options.names);
|
|
87655
87888
|
commentStores.set(id2, store);
|
|
87656
87889
|
}
|
|
87657
87890
|
return store;
|
|
@@ -87665,10 +87898,10 @@ function createDocumentRegistry(options) {
|
|
|
87665
87898
|
if (JSON.stringify(store.warnings()) !== before2) options.onWarningsChange(id2);
|
|
87666
87899
|
};
|
|
87667
87900
|
const create3 = async (id2) => {
|
|
87668
|
-
if (!
|
|
87901
|
+
if (!import_node_fs9.default.existsSync(docFile(id2))) return null;
|
|
87669
87902
|
const session = await createDocumentSession({
|
|
87670
87903
|
file: docFile(id2),
|
|
87671
|
-
snapshotFile:
|
|
87904
|
+
snapshotFile: import_node_path9.default.join(options.stateDir, "document", id2, "doc.loro"),
|
|
87672
87905
|
...options.timing,
|
|
87673
87906
|
log: options.log
|
|
87674
87907
|
});
|
|
@@ -87711,7 +87944,7 @@ function createDocumentRegistry(options) {
|
|
|
87711
87944
|
const known = sessions.has(id2);
|
|
87712
87945
|
void open(id2).then((session) => {
|
|
87713
87946
|
if (!session || !known) return;
|
|
87714
|
-
|
|
87947
|
+
import_node_fs9.default.readFile(docFile(id2), "utf8", (err, text2) => {
|
|
87715
87948
|
if (!err) session.onFileText(text2);
|
|
87716
87949
|
});
|
|
87717
87950
|
});
|
|
@@ -87746,7 +87979,7 @@ function createDocumentRegistry(options) {
|
|
|
87746
87979
|
}
|
|
87747
87980
|
|
|
87748
87981
|
// src/inspector/runtime.ts
|
|
87749
|
-
function installInspector(win, properties) {
|
|
87982
|
+
function installInspector(win, properties, commentCursor = "crosshair") {
|
|
87750
87983
|
const doc = win.document;
|
|
87751
87984
|
const session = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
|
|
87752
87985
|
const ids = /* @__PURE__ */ new WeakMap();
|
|
@@ -87755,6 +87988,7 @@ function installInspector(win, properties) {
|
|
|
87755
87988
|
const ignored2 = /* @__PURE__ */ new Set(["SCRIPT", "STYLE", "META", "LINK", "NOSCRIPT", "HEAD"]);
|
|
87756
87989
|
let nextId = 0;
|
|
87757
87990
|
let enabled = false;
|
|
87991
|
+
let mode = "select";
|
|
87758
87992
|
let connection = "";
|
|
87759
87993
|
let selected = null;
|
|
87760
87994
|
let treeTimer = 0;
|
|
@@ -87926,6 +88160,7 @@ function installInspector(win, properties) {
|
|
|
87926
88160
|
suppressClick = false;
|
|
87927
88161
|
return;
|
|
87928
88162
|
}
|
|
88163
|
+
if (mode === "comment") return;
|
|
87929
88164
|
selected = event.target.closest("svg") || event.target;
|
|
87930
88165
|
selection("user", event.shiftKey || event.metaKey || event.ctrlKey);
|
|
87931
88166
|
};
|
|
@@ -87985,7 +88220,7 @@ function installInspector(win, properties) {
|
|
|
87985
88220
|
};
|
|
87986
88221
|
const key2 = (event) => {
|
|
87987
88222
|
if (!enabled || event.composedPath().some((target) => target instanceof win.Element && target.matches("input,textarea,select,[contenteditable]"))) return;
|
|
87988
|
-
if (!["Space", "KeyH", "KeyV", "Escape", "Equal", "Minus", "Digit0", "Digit1"].includes(event.code)) return;
|
|
88223
|
+
if (!["Space", "KeyH", "KeyV", "KeyC", "Escape", "Equal", "Minus", "Digit0", "Digit1"].includes(event.code)) return;
|
|
87989
88224
|
event.preventDefault();
|
|
87990
88225
|
event.stopImmediatePropagation();
|
|
87991
88226
|
post("key", { key: event.key, code: event.code, down: event.type === "keydown", ctrlKey: event.ctrlKey, metaKey: event.metaKey, shiftKey: event.shiftKey, altKey: event.altKey });
|
|
@@ -88028,6 +88263,11 @@ function installInspector(win, properties) {
|
|
|
88028
88263
|
disable();
|
|
88029
88264
|
return;
|
|
88030
88265
|
}
|
|
88266
|
+
if (data.action === "mode" && (data.mode === "select" || data.mode === "comment")) {
|
|
88267
|
+
mode = data.mode;
|
|
88268
|
+
cursor.textContent = `*{cursor:${mode === "comment" ? commentCursor : "default"}!important}`;
|
|
88269
|
+
return;
|
|
88270
|
+
}
|
|
88031
88271
|
if (!enabled && data.action !== "reset") return;
|
|
88032
88272
|
if (data.session !== session) return;
|
|
88033
88273
|
if (data.action === "cancel-drag") {
|
|
@@ -88156,6 +88396,8 @@ var INSPECTOR_PROPERTIES = [
|
|
|
88156
88396
|
"color",
|
|
88157
88397
|
"box-shadow"
|
|
88158
88398
|
];
|
|
88399
|
+
var COMMENT_CURSOR_SVG = "<svg xmlns='http://www.w3.org/2000/svg' width='26' height='26' viewBox='0 0 26 26'><path d='M2 24V13a11 11 0 1 1 11 11z' fill='white' stroke='black' stroke-width='1.5' stroke-linejoin='round'/><path d='M13 8.5v9M8.5 13h9' stroke='black' stroke-width='1.8' stroke-linecap='round'/></svg>";
|
|
88400
|
+
var COMMENT_CURSOR = `url("data:image/svg+xml,${encodeURIComponent(COMMENT_CURSOR_SVG)}") 2 24, crosshair`;
|
|
88159
88401
|
|
|
88160
88402
|
// src/server/inject.ts
|
|
88161
88403
|
var RUNTIME = `(() => {
|
|
@@ -88266,7 +88508,7 @@ var EMBEDDED_STYLE = "<style>:root{color-scheme:light dark;background:transparen
|
|
|
88266
88508
|
var UI_MARKER = /<ryugi-[a-z0-9-]+(?:\s|>)/i;
|
|
88267
88509
|
var UI_META = /<meta[^>]+name=["']ryugi-ui["'][^>]*>/i;
|
|
88268
88510
|
function injectRuntime(html, options = {}) {
|
|
88269
|
-
const inspect = options.inspector ? `;(${installInspector.toString().replace(/\n/g, " ")})(window,${JSON.stringify(INSPECTOR_PROPERTIES)});` : "";
|
|
88511
|
+
const inspect = options.inspector ? `;(${installInspector.toString().replace(/\n/g, " ")})(window,${JSON.stringify(INSPECTOR_PROPERTIES)},${JSON.stringify(COMMENT_CURSOR)});` : "";
|
|
88270
88512
|
const tag = `${options.embedded ? EMBEDDED_STYLE : ""}<script>${inspect || RUNTIME_LINE}</script>`;
|
|
88271
88513
|
const ui2 = options.uiRuntimeUrl && !options.inspector && (UI_MARKER.test(html) || UI_META.test(html)) ? `<script defer src="${options.uiRuntimeUrl.replace(/"/g, """)}"></script>` : "";
|
|
88272
88514
|
const head = HEAD.exec(html);
|
|
@@ -88275,9 +88517,9 @@ function injectRuntime(html, options = {}) {
|
|
|
88275
88517
|
}
|
|
88276
88518
|
|
|
88277
88519
|
// src/server/http.ts
|
|
88278
|
-
var
|
|
88279
|
-
var
|
|
88280
|
-
var
|
|
88520
|
+
var import_node_crypto3 = __toESM(require("node:crypto"), 1);
|
|
88521
|
+
var import_node_fs10 = __toESM(require("node:fs"), 1);
|
|
88522
|
+
var import_node_path10 = __toESM(require("node:path"), 1);
|
|
88281
88523
|
var MIME2 = {
|
|
88282
88524
|
".html": "text/html; charset=utf-8",
|
|
88283
88525
|
".js": "text/javascript; charset=utf-8",
|
|
@@ -88300,12 +88542,12 @@ var MIME2 = {
|
|
|
88300
88542
|
".mp4": "video/mp4",
|
|
88301
88543
|
".webm": "video/webm"
|
|
88302
88544
|
};
|
|
88303
|
-
var mimeOf = (file) => MIME2[
|
|
88304
|
-
var randomToken = () =>
|
|
88545
|
+
var mimeOf = (file) => MIME2[import_node_path10.default.extname(file).toLowerCase()] ?? "application/octet-stream";
|
|
88546
|
+
var randomToken = () => import_node_crypto3.default.randomBytes(24).toString("base64url");
|
|
88305
88547
|
function safeEqual(a5, b6) {
|
|
88306
88548
|
const ab = Buffer.from(a5);
|
|
88307
88549
|
const bb = Buffer.from(b6);
|
|
88308
|
-
return ab.length === bb.length &&
|
|
88550
|
+
return ab.length === bb.length && import_node_crypto3.default.timingSafeEqual(ab, bb);
|
|
88309
88551
|
}
|
|
88310
88552
|
function parseCookies(header) {
|
|
88311
88553
|
const cookies = {};
|
|
@@ -88317,7 +88559,7 @@ function parseCookies(header) {
|
|
|
88317
88559
|
}
|
|
88318
88560
|
function readPersisted(file) {
|
|
88319
88561
|
try {
|
|
88320
|
-
return
|
|
88562
|
+
return import_node_fs10.default.readFileSync(file, "utf8").trim();
|
|
88321
88563
|
} catch {
|
|
88322
88564
|
return "";
|
|
88323
88565
|
}
|
|
@@ -88346,15 +88588,15 @@ function sendJson(res, status, value) {
|
|
|
88346
88588
|
send(res, status, JSON.stringify(value), { "Content-Type": MIME2[".json"] });
|
|
88347
88589
|
}
|
|
88348
88590
|
function sendFile(res, file, headers = {}) {
|
|
88349
|
-
|
|
88591
|
+
import_node_fs10.default.readFile(file, (err, data) => {
|
|
88350
88592
|
if (err) send(res, 404, "Not found");
|
|
88351
88593
|
else send(res, 200, data, { "Content-Type": mimeOf(file), ...headers });
|
|
88352
88594
|
});
|
|
88353
88595
|
}
|
|
88354
88596
|
|
|
88355
88597
|
// src/server/dynamic-blocks.ts
|
|
88356
|
-
var
|
|
88357
|
-
var
|
|
88598
|
+
var import_node_fs11 = __toESM(require("node:fs"), 1);
|
|
88599
|
+
var import_node_path11 = __toESM(require("node:path"), 1);
|
|
88358
88600
|
function dynamicUrls(xml) {
|
|
88359
88601
|
const urls = /* @__PURE__ */ new Set();
|
|
88360
88602
|
for (const match of stripOpaque(xml).matchAll(TAG)) {
|
|
@@ -88367,7 +88609,7 @@ function dynamicUrls(xml) {
|
|
|
88367
88609
|
}
|
|
88368
88610
|
var mtimeOf = (file) => {
|
|
88369
88611
|
try {
|
|
88370
|
-
return
|
|
88612
|
+
return import_node_fs11.default.statSync(file).mtimeMs;
|
|
88371
88613
|
} catch {
|
|
88372
88614
|
return -1;
|
|
88373
88615
|
}
|
|
@@ -88384,7 +88626,7 @@ function createDynamicBlocks(limits) {
|
|
|
88384
88626
|
};
|
|
88385
88627
|
const entry = (id2, dir, file) => {
|
|
88386
88628
|
const map = files(id2);
|
|
88387
|
-
const mtime = mtimeOf(
|
|
88629
|
+
const mtime = mtimeOf(import_node_path11.default.join(dir, file));
|
|
88388
88630
|
let state = map.get(file);
|
|
88389
88631
|
if (!state || state.mtime !== mtime) {
|
|
88390
88632
|
state = { mtime, errors: [], ran: false };
|
|
@@ -88409,19 +88651,19 @@ function createDynamicBlocks(limits) {
|
|
|
88409
88651
|
state(id2, dir) {
|
|
88410
88652
|
let xml = "";
|
|
88411
88653
|
try {
|
|
88412
|
-
xml =
|
|
88654
|
+
xml = import_node_fs11.default.readFileSync(import_node_path11.default.join(dir, "doc.xml"), "utf8");
|
|
88413
88655
|
} catch {
|
|
88414
88656
|
return { warnings: [], dynamic: {} };
|
|
88415
88657
|
}
|
|
88416
88658
|
const urls = dynamicUrls(xml);
|
|
88417
88659
|
const map = files(id2);
|
|
88418
88660
|
for (const [file, state] of map) {
|
|
88419
|
-
if (!urls.includes(file) || state.mtime !== mtimeOf(
|
|
88661
|
+
if (!urls.includes(file) || state.mtime !== mtimeOf(import_node_path11.default.join(dir, file))) map.delete(file);
|
|
88420
88662
|
}
|
|
88421
88663
|
const warnings = [];
|
|
88422
88664
|
const dynamic = {};
|
|
88423
88665
|
for (const url of urls) {
|
|
88424
|
-
if (!
|
|
88666
|
+
if (!import_node_fs11.default.existsSync(import_node_path11.default.join(dir, url))) warnings.push(`${url} not found`);
|
|
88425
88667
|
const state = map.get(url);
|
|
88426
88668
|
for (const error of state?.errors ?? []) warnings.push(`runtime: ${url}: ${error}`);
|
|
88427
88669
|
dynamic[url] = { ran: state?.ran ?? false };
|
|
@@ -88432,8 +88674,8 @@ function createDynamicBlocks(limits) {
|
|
|
88432
88674
|
}
|
|
88433
88675
|
|
|
88434
88676
|
// src/server/selection.ts
|
|
88435
|
-
var
|
|
88436
|
-
var
|
|
88677
|
+
var import_node_fs12 = __toESM(require("node:fs"), 1);
|
|
88678
|
+
var import_node_path12 = __toESM(require("node:path"), 1);
|
|
88437
88679
|
|
|
88438
88680
|
// src/shared/selection.ts
|
|
88439
88681
|
var SELECTION_FULL_NODES = 20;
|
|
@@ -88508,14 +88750,14 @@ function readAnySelection(value) {
|
|
|
88508
88750
|
function createSelectionStore(stateDir, exists) {
|
|
88509
88751
|
const tabs = /* @__PURE__ */ new Map();
|
|
88510
88752
|
let clock = 0;
|
|
88511
|
-
const fileOf = (kind, id2) =>
|
|
88753
|
+
const fileOf = (kind, id2) => import_node_path12.default.join(stateDir, kind, id2, "selection.json");
|
|
88512
88754
|
const write = (kind, id2) => {
|
|
88513
88755
|
let winner;
|
|
88514
88756
|
for (const tab of tabs.values()) {
|
|
88515
88757
|
if (tab.kind !== kind || tab.id !== id2) continue;
|
|
88516
88758
|
if (!winner || tab.humanAt > winner.humanAt || tab.humanAt === winner.humanAt && tab.seenAt > winner.seenAt) winner = tab;
|
|
88517
88759
|
}
|
|
88518
|
-
if (!winner?.state)
|
|
88760
|
+
if (!winner?.state) import_node_fs12.default.rmSync(fileOf(kind, id2), { force: true });
|
|
88519
88761
|
else writeJsonAtomic(fileOf(kind, id2), { artifact: `${kind}/${id2}`, updatedAt: (/* @__PURE__ */ new Date()).toISOString(), ...winner.state });
|
|
88520
88762
|
};
|
|
88521
88763
|
return {
|
|
@@ -88546,19 +88788,19 @@ function createSelectionStore(stateDir, exists) {
|
|
|
88546
88788
|
for (const kind of ["artboard", "document"]) {
|
|
88547
88789
|
let ids = [];
|
|
88548
88790
|
try {
|
|
88549
|
-
ids =
|
|
88791
|
+
ids = import_node_fs12.default.readdirSync(import_node_path12.default.join(stateDir, kind));
|
|
88550
88792
|
} catch {
|
|
88551
88793
|
continue;
|
|
88552
88794
|
}
|
|
88553
|
-
for (const id2 of ids)
|
|
88795
|
+
for (const id2 of ids) import_node_fs12.default.rmSync(fileOf(kind, id2), { force: true });
|
|
88554
88796
|
}
|
|
88555
88797
|
}
|
|
88556
88798
|
};
|
|
88557
88799
|
}
|
|
88558
88800
|
|
|
88559
88801
|
// src/server/config.ts
|
|
88560
|
-
var
|
|
88561
|
-
var
|
|
88802
|
+
var import_node_fs13 = __toESM(require("node:fs"), 1);
|
|
88803
|
+
var import_node_path13 = __toESM(require("node:path"), 1);
|
|
88562
88804
|
|
|
88563
88805
|
// src/shared/cloud.ts
|
|
88564
88806
|
var ownLink = (url, hostId) => hostId ? `${url}#ryugi-host=${hostId}` : url;
|
|
@@ -88593,7 +88835,7 @@ function normalize(raw) {
|
|
|
88593
88835
|
function readConfig(file) {
|
|
88594
88836
|
let text2;
|
|
88595
88837
|
try {
|
|
88596
|
-
text2 =
|
|
88838
|
+
text2 = import_node_fs13.default.readFileSync(file, "utf8");
|
|
88597
88839
|
} catch {
|
|
88598
88840
|
return { config: defaults() };
|
|
88599
88841
|
}
|
|
@@ -88604,22 +88846,22 @@ function readConfig(file) {
|
|
|
88604
88846
|
}
|
|
88605
88847
|
}
|
|
88606
88848
|
function ensureGitignore(dir) {
|
|
88607
|
-
const file =
|
|
88849
|
+
const file = import_node_path13.default.join(dir, ".gitignore");
|
|
88608
88850
|
let current = "";
|
|
88609
88851
|
try {
|
|
88610
|
-
current =
|
|
88852
|
+
current = import_node_fs13.default.readFileSync(file, "utf8");
|
|
88611
88853
|
} catch {
|
|
88612
|
-
|
|
88854
|
+
import_node_fs13.default.writeFileSync(file, "config.json\n");
|
|
88613
88855
|
return;
|
|
88614
88856
|
}
|
|
88615
88857
|
if (current.split(/\r?\n/).some((line) => line.trim() === "config.json")) return;
|
|
88616
|
-
|
|
88858
|
+
import_node_fs13.default.writeFileSync(file, `${current}${current === "" || current.endsWith("\n") ? "" : "\n"}config.json
|
|
88617
88859
|
`);
|
|
88618
88860
|
}
|
|
88619
88861
|
function ensureConfig(file) {
|
|
88620
|
-
|
|
88621
|
-
ensureGitignore(
|
|
88622
|
-
if (!
|
|
88862
|
+
import_node_fs13.default.mkdirSync(import_node_path13.default.dirname(file), { recursive: true });
|
|
88863
|
+
ensureGitignore(import_node_path13.default.dirname(file));
|
|
88864
|
+
if (!import_node_fs13.default.existsSync(file)) writeJsonAtomic(file, defaults());
|
|
88623
88865
|
}
|
|
88624
88866
|
function updateArtifactConfig(file, key2, patch) {
|
|
88625
88867
|
const { config, warning } = readConfig(file);
|
|
@@ -88639,21 +88881,21 @@ function setProjectAutoPublish(file, value) {
|
|
|
88639
88881
|
if (warning) throw new Error(warning);
|
|
88640
88882
|
if (value === null) delete config.autoPublish;
|
|
88641
88883
|
else config.autoPublish = value;
|
|
88642
|
-
|
|
88884
|
+
import_node_fs13.default.mkdirSync(import_node_path13.default.dirname(file), { recursive: true });
|
|
88643
88885
|
writeJsonAtomic(file, config);
|
|
88644
88886
|
}
|
|
88645
88887
|
|
|
88646
88888
|
// src/server/credentials.ts
|
|
88647
|
-
var
|
|
88648
|
-
var
|
|
88889
|
+
var import_node_fs14 = __toESM(require("node:fs"), 1);
|
|
88890
|
+
var import_node_path14 = __toESM(require("node:path"), 1);
|
|
88649
88891
|
function credentialsFile(env, platform, home) {
|
|
88650
|
-
if (platform === "win32" && env.APPDATA) return
|
|
88651
|
-
return
|
|
88892
|
+
if (platform === "win32" && env.APPDATA) return import_node_path14.default.join(env.APPDATA, "ryugi", "credentials.json");
|
|
88893
|
+
return import_node_path14.default.join(env.XDG_CONFIG_HOME || import_node_path14.default.join(home, ".config"), "ryugi", "credentials.json");
|
|
88652
88894
|
}
|
|
88653
88895
|
function readCredentials(file, origin) {
|
|
88654
88896
|
let raw;
|
|
88655
88897
|
try {
|
|
88656
|
-
raw = JSON.parse(
|
|
88898
|
+
raw = JSON.parse(import_node_fs14.default.readFileSync(file, "utf8"));
|
|
88657
88899
|
} catch {
|
|
88658
88900
|
return null;
|
|
88659
88901
|
}
|
|
@@ -88664,11 +88906,11 @@ function readCredentials(file, origin) {
|
|
|
88664
88906
|
return { origin: savedOrigin, token, login };
|
|
88665
88907
|
}
|
|
88666
88908
|
function writeCredentials(file, credentials) {
|
|
88667
|
-
|
|
88909
|
+
import_node_fs14.default.mkdirSync(import_node_path14.default.dirname(file), { recursive: true, mode: 448 });
|
|
88668
88910
|
writeJsonAtomic(file, credentials);
|
|
88669
88911
|
}
|
|
88670
88912
|
function clearCredentials(file) {
|
|
88671
|
-
|
|
88913
|
+
import_node_fs14.default.rmSync(file, { force: true });
|
|
88672
88914
|
}
|
|
88673
88915
|
|
|
88674
88916
|
// node_modules/.pnpm/ws@8.18.3/node_modules/ws/wrapper.mjs
|
|
@@ -88796,7 +89038,7 @@ function createRelayClient(options) {
|
|
|
88796
89038
|
}
|
|
88797
89039
|
|
|
88798
89040
|
// src/server/ws.ts
|
|
88799
|
-
var
|
|
89041
|
+
var import_node_crypto4 = __toESM(require("node:crypto"), 1);
|
|
88800
89042
|
var WS_MAGIC = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
|
|
88801
89043
|
var OPCODE_TEXT = 1;
|
|
88802
89044
|
var OPCODE_CLOSE = 8;
|
|
@@ -88804,7 +89046,7 @@ var OPCODE_PING = 9;
|
|
|
88804
89046
|
var OPCODE_PONG = 10;
|
|
88805
89047
|
var MAX_CLIENT_FRAME = 8 * 1024 * 1024;
|
|
88806
89048
|
function acceptKey(clientKey) {
|
|
88807
|
-
return
|
|
89049
|
+
return import_node_crypto4.default.createHash("sha1").update(clientKey + WS_MAGIC).digest("base64");
|
|
88808
89050
|
}
|
|
88809
89051
|
function encodeFrame(opcode, payload) {
|
|
88810
89052
|
const len = payload.length;
|
|
@@ -88929,21 +89171,21 @@ function createDirectRelay(options) {
|
|
|
88929
89171
|
}
|
|
88930
89172
|
|
|
88931
89173
|
// src/server/host-id.ts
|
|
88932
|
-
var
|
|
88933
|
-
var
|
|
89174
|
+
var import_node_fs15 = __toESM(require("node:fs"), 1);
|
|
89175
|
+
var import_node_path15 = __toESM(require("node:path"), 1);
|
|
88934
89176
|
function hostIdFor(credentialsFile2) {
|
|
88935
|
-
const file =
|
|
89177
|
+
const file = import_node_path15.default.join(import_node_path15.default.dirname(credentialsFile2), "host-id");
|
|
88936
89178
|
const saved = readPersisted(file);
|
|
88937
89179
|
if (/^[A-Za-z0-9_-]{16,64}$/.test(saved)) return saved;
|
|
88938
89180
|
const id2 = randomToken();
|
|
88939
|
-
|
|
88940
|
-
|
|
89181
|
+
import_node_fs15.default.mkdirSync(import_node_path15.default.dirname(file), { recursive: true, mode: 448 });
|
|
89182
|
+
import_node_fs15.default.writeFileSync(file, `${id2}
|
|
88941
89183
|
`, { mode: 384 });
|
|
88942
89184
|
return id2;
|
|
88943
89185
|
}
|
|
88944
89186
|
|
|
88945
89187
|
// src/server/avatars.ts
|
|
88946
|
-
var
|
|
89188
|
+
var import_node_crypto5 = require("node:crypto");
|
|
88947
89189
|
var AVATAR_ROUTE = /^\/api\/avatar\/([a-z]+)\/([^/]+)$/;
|
|
88948
89190
|
var MAX_BYTES = 512 * 1024;
|
|
88949
89191
|
var TIMEOUT_MS = 5e3;
|
|
@@ -88952,7 +89194,7 @@ var SOURCES = {
|
|
|
88952
89194
|
gravatar: { valid: /^[0-9a-f]{64}$/, url: (id2) => `https://gravatar.com/avatar/${id2}?s=64&d=404` }
|
|
88953
89195
|
};
|
|
88954
89196
|
var githubAvatar = (login) => `/api/avatar/github/${login}`;
|
|
88955
|
-
var gravatarAvatar = (email) => `/api/avatar/gravatar/${(0,
|
|
89197
|
+
var gravatarAvatar = (email) => `/api/avatar/gravatar/${(0, import_node_crypto5.createHash)("sha256").update(email.trim().toLowerCase()).digest("hex")}`;
|
|
88956
89198
|
function createAvatars(fetchImpl = fetch) {
|
|
88957
89199
|
const cache = /* @__PURE__ */ new Map();
|
|
88958
89200
|
const fetchAvatar = async (url) => {
|
|
@@ -88984,7 +89226,7 @@ function createAvatars(fetchImpl = fetch) {
|
|
|
88984
89226
|
}
|
|
88985
89227
|
|
|
88986
89228
|
// src/server/cloud.ts
|
|
88987
|
-
var
|
|
89229
|
+
var import_node_crypto6 = __toESM(require("node:crypto"), 1);
|
|
88988
89230
|
|
|
88989
89231
|
// src/shared/brand.ts
|
|
88990
89232
|
var RYUGI_MARK_VIEWBOX = "0 0 512 512";
|
|
@@ -89094,32 +89336,32 @@ function callbackPage(result) {
|
|
|
89094
89336
|
}
|
|
89095
89337
|
|
|
89096
89338
|
// src/server/pack.ts
|
|
89097
|
-
var
|
|
89098
|
-
var
|
|
89339
|
+
var import_node_fs16 = __toESM(require("node:fs"), 1);
|
|
89340
|
+
var import_node_path16 = __toESM(require("node:path"), 1);
|
|
89099
89341
|
var MAX_ARTIFACT_BYTES = 20 * 1024 * 1024;
|
|
89100
89342
|
function formatBytes(bytes) {
|
|
89101
89343
|
if (bytes < 1024) return `${bytes} B`;
|
|
89102
89344
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
89103
89345
|
return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
|
89104
89346
|
}
|
|
89105
|
-
var excluded = (type, relative) => type === "document" && relative === "comments.json";
|
|
89347
|
+
var excluded = (type, relative) => (type === "document" || type === "artboard") && relative === "comments.json";
|
|
89106
89348
|
function packArtifact(dir, type, { maxBytes = MAX_ARTIFACT_BYTES } = {}) {
|
|
89107
|
-
const rootReal =
|
|
89349
|
+
const rootReal = import_node_fs16.default.realpathSync(dir);
|
|
89108
89350
|
const found = [];
|
|
89109
89351
|
const visited = /* @__PURE__ */ new Set([rootReal]);
|
|
89110
89352
|
let total = 0;
|
|
89111
89353
|
const walk = (current) => {
|
|
89112
|
-
for (const entry of
|
|
89354
|
+
for (const entry of import_node_fs16.default.readdirSync(current, { withFileTypes: true })) {
|
|
89113
89355
|
if (entry.name.startsWith(".")) continue;
|
|
89114
|
-
const full =
|
|
89356
|
+
const full = import_node_path16.default.join(current, entry.name);
|
|
89115
89357
|
let real;
|
|
89116
89358
|
try {
|
|
89117
|
-
real =
|
|
89359
|
+
real = import_node_fs16.default.realpathSync(full);
|
|
89118
89360
|
} catch {
|
|
89119
89361
|
continue;
|
|
89120
89362
|
}
|
|
89121
|
-
if (!real.startsWith(rootReal +
|
|
89122
|
-
const stat =
|
|
89363
|
+
if (!real.startsWith(rootReal + import_node_path16.default.sep)) continue;
|
|
89364
|
+
const stat = import_node_fs16.default.statSync(real);
|
|
89123
89365
|
if (stat.isDirectory()) {
|
|
89124
89366
|
if (visited.has(real)) continue;
|
|
89125
89367
|
visited.add(real);
|
|
@@ -89127,7 +89369,7 @@ function packArtifact(dir, type, { maxBytes = MAX_ARTIFACT_BYTES } = {}) {
|
|
|
89127
89369
|
continue;
|
|
89128
89370
|
}
|
|
89129
89371
|
if (!stat.isFile()) continue;
|
|
89130
|
-
const relative =
|
|
89372
|
+
const relative = import_node_path16.default.relative(dir, full).split(import_node_path16.default.sep).join("/");
|
|
89131
89373
|
if (excluded(type, relative)) continue;
|
|
89132
89374
|
total += stat.size;
|
|
89133
89375
|
found.push({ path: relative, real });
|
|
@@ -89137,12 +89379,12 @@ function packArtifact(dir, type, { maxBytes = MAX_ARTIFACT_BYTES } = {}) {
|
|
|
89137
89379
|
if (total > maxBytes) {
|
|
89138
89380
|
throw new Error(`artifact is ${formatBytes(total)}; the limit is ${formatBytes(maxBytes)}`);
|
|
89139
89381
|
}
|
|
89140
|
-
return found.map((file) => ({ path: file.path, data:
|
|
89382
|
+
return found.map((file) => ({ path: file.path, data: import_node_fs16.default.readFileSync(file.real) }));
|
|
89141
89383
|
}
|
|
89142
89384
|
|
|
89143
89385
|
// src/server/publish-payload.ts
|
|
89144
|
-
var
|
|
89145
|
-
var
|
|
89386
|
+
var import_node_fs17 = __toESM(require("node:fs"), 1);
|
|
89387
|
+
var import_node_path17 = __toESM(require("node:path"), 1);
|
|
89146
89388
|
var CLOUD_RUNTIME_URL = "/_ryugi/runtime/ryugi-ui.js";
|
|
89147
89389
|
function sharedComments(file) {
|
|
89148
89390
|
return {
|
|
@@ -89155,7 +89397,7 @@ function publishPayload(ref, dir, title, payload, comments = emptyComments()) {
|
|
|
89155
89397
|
const { canvas, layout, versions } = payload;
|
|
89156
89398
|
return { canvas, layout, versions };
|
|
89157
89399
|
}
|
|
89158
|
-
if (ref.type === "document") return { title, state: parseDocument2(
|
|
89400
|
+
if (ref.type === "document") return { title, state: parseDocument2(import_node_fs17.default.readFileSync(import_node_path17.default.join(dir, "doc.xml"), "utf8")), comments: sharedComments(comments) };
|
|
89159
89401
|
return { title };
|
|
89160
89402
|
}
|
|
89161
89403
|
var isPage = (type, file) => type === "html" ? file === "index.html" : (type === "document" || type === "artboard") && file.endsWith(".html");
|
|
@@ -89166,12 +89408,12 @@ function withCloudRuntime(type, files) {
|
|
|
89166
89408
|
}
|
|
89167
89409
|
|
|
89168
89410
|
// src/server/settings.ts
|
|
89169
|
-
var
|
|
89170
|
-
var
|
|
89171
|
-
var settingsFileFor = (credentialsFile2) =>
|
|
89411
|
+
var import_node_fs18 = __toESM(require("node:fs"), 1);
|
|
89412
|
+
var import_node_path18 = __toESM(require("node:path"), 1);
|
|
89413
|
+
var settingsFileFor = (credentialsFile2) => import_node_path18.default.join(import_node_path18.default.dirname(credentialsFile2), "config.json");
|
|
89172
89414
|
function readSettings(file) {
|
|
89173
89415
|
try {
|
|
89174
|
-
const raw = JSON.parse(
|
|
89416
|
+
const raw = JSON.parse(import_node_fs18.default.readFileSync(file, "utf8"));
|
|
89175
89417
|
return typeof raw === "object" && raw !== null && !Array.isArray(raw) ? raw : {};
|
|
89176
89418
|
} catch {
|
|
89177
89419
|
return {};
|
|
@@ -89182,7 +89424,7 @@ function readGlobalAutoPublish(file) {
|
|
|
89182
89424
|
return typeof value === "boolean" ? value : void 0;
|
|
89183
89425
|
}
|
|
89184
89426
|
function writeGlobalAutoPublish(file, value) {
|
|
89185
|
-
|
|
89427
|
+
import_node_fs18.default.mkdirSync(import_node_path18.default.dirname(file), { recursive: true, mode: 448 });
|
|
89186
89428
|
writeJsonAtomic(file, { ...readSettings(file), autoPublish: value });
|
|
89187
89429
|
}
|
|
89188
89430
|
function defaultGlobalAutoPublish(file) {
|
|
@@ -89254,10 +89496,10 @@ function createCloudRoutes(options) {
|
|
|
89254
89496
|
const state = randomToken();
|
|
89255
89497
|
const verifier = randomToken();
|
|
89256
89498
|
pendingStates.set(state, { expires: now + LOGIN_STATE_TTL_MS, verifier });
|
|
89257
|
-
const challenge =
|
|
89499
|
+
const challenge = import_node_crypto6.default.createHash("sha256").update(verifier).digest("base64url");
|
|
89258
89500
|
return `${origin}/auth/cli?port=${options.port()}&state=${state}&challenge=${challenge}`;
|
|
89259
89501
|
};
|
|
89260
|
-
const cloudFetch = async (method,
|
|
89502
|
+
const cloudFetch = async (method, path22, body) => {
|
|
89261
89503
|
const credentials = readCredentials(credentialsFile2, origin);
|
|
89262
89504
|
if (!credentials) throw new SignedOut();
|
|
89263
89505
|
const headers = { Authorization: `Bearer ${credentials.token}` };
|
|
@@ -89271,7 +89513,7 @@ function createCloudRoutes(options) {
|
|
|
89271
89513
|
}
|
|
89272
89514
|
let res;
|
|
89273
89515
|
try {
|
|
89274
|
-
res = await fetch(`${origin}${
|
|
89516
|
+
res = await fetch(`${origin}${path22}`, { method, headers, body: payload });
|
|
89275
89517
|
} catch (err) {
|
|
89276
89518
|
throw new CloudRefused(502, `could not reach ${origin}: ${err.message}`);
|
|
89277
89519
|
}
|
|
@@ -89328,9 +89570,9 @@ function createCloudRoutes(options) {
|
|
|
89328
89570
|
}
|
|
89329
89571
|
const key2 = `${ref.type}/${ref.id}`;
|
|
89330
89572
|
const entry = artifactEntry(key2);
|
|
89331
|
-
const hashed = files.map((file) => ({ ...file, hash:
|
|
89573
|
+
const hashed = files.map((file) => ({ ...file, hash: import_node_crypto6.default.createHash("sha256").update(file.data).digest("hex") }));
|
|
89332
89574
|
const byHash = new Map(hashed.map((file) => [file.hash, file.data]));
|
|
89333
|
-
const manifest = hashed.map(({ path:
|
|
89575
|
+
const manifest = hashed.map(({ path: path22, hash }) => ({ path: path22, hash }));
|
|
89334
89576
|
const version2 = (visibility) => ({ title: inspected.title, payload: inspected.payload, files: manifest, project, ...visibility ? { visibility } : {} });
|
|
89335
89577
|
const create3 = () => createRecord2(ref, requested ?? entry.visibility ?? "private");
|
|
89336
89578
|
const upload = async (id2, hashes) => {
|
|
@@ -89553,7 +89795,7 @@ function createCloudRoutes(options) {
|
|
|
89553
89795
|
|
|
89554
89796
|
// src/server/comment-names.ts
|
|
89555
89797
|
var import_node_child_process = require("node:child_process");
|
|
89556
|
-
var
|
|
89798
|
+
var import_node_fs19 = __toESM(require("node:fs"), 1);
|
|
89557
89799
|
|
|
89558
89800
|
// src/server/agent.ts
|
|
89559
89801
|
var NAMES = {
|
|
@@ -89634,7 +89876,7 @@ function commentNames({ agentFile, projectDir, cloud }) {
|
|
|
89634
89876
|
},
|
|
89635
89877
|
agent: () => {
|
|
89636
89878
|
try {
|
|
89637
|
-
return detectAgent(JSON.parse(
|
|
89879
|
+
return detectAgent(JSON.parse(import_node_fs19.default.readFileSync(agentFile, "utf8")));
|
|
89638
89880
|
} catch {
|
|
89639
89881
|
return void 0;
|
|
89640
89882
|
}
|
|
@@ -89662,8 +89904,8 @@ function viewerPage(template, page) {
|
|
|
89662
89904
|
}
|
|
89663
89905
|
|
|
89664
89906
|
// src/server/auto-publish.ts
|
|
89665
|
-
var
|
|
89666
|
-
var
|
|
89907
|
+
var import_node_crypto7 = __toESM(require("node:crypto"), 1);
|
|
89908
|
+
var import_node_fs20 = __toESM(require("node:fs"), 1);
|
|
89667
89909
|
var SIGNED_OUT_MESSAGE = "auto-publish paused: the Ryugi Cloud sign-in expired";
|
|
89668
89910
|
function isNotice(value) {
|
|
89669
89911
|
if (typeof value !== "object" || value === null) return false;
|
|
@@ -89673,7 +89915,7 @@ function isNotice(value) {
|
|
|
89673
89915
|
function readAutoPublishState(file) {
|
|
89674
89916
|
let raw = {};
|
|
89675
89917
|
try {
|
|
89676
|
-
const parsed = JSON.parse(
|
|
89918
|
+
const parsed = JSON.parse(import_node_fs20.default.readFileSync(file, "utf8"));
|
|
89677
89919
|
if (typeof parsed === "object" && parsed !== null) raw = parsed;
|
|
89678
89920
|
} catch {
|
|
89679
89921
|
}
|
|
@@ -89693,7 +89935,7 @@ function createAutoPublisher(options) {
|
|
|
89693
89935
|
const remarked = /* @__PURE__ */ new Set();
|
|
89694
89936
|
const save = () => writeJsonAtomic(options.stateFile, { dirty: [...dirty], notice, paused });
|
|
89695
89937
|
const raise = (kind, message) => {
|
|
89696
|
-
if (notice?.kind !== kind) notice = { id:
|
|
89938
|
+
if (notice?.kind !== kind) notice = { id: import_node_crypto7.default.randomUUID(), kind, message };
|
|
89697
89939
|
};
|
|
89698
89940
|
const run2 = async () => {
|
|
89699
89941
|
if (!options.enabled() || dirty.size === 0) return;
|
|
@@ -89753,7 +89995,7 @@ function createAutoPublisher(options) {
|
|
|
89753
89995
|
}
|
|
89754
89996
|
|
|
89755
89997
|
// src/server/artifact-file.ts
|
|
89756
|
-
var
|
|
89998
|
+
var import_node_fs21 = __toESM(require("node:fs"), 1);
|
|
89757
89999
|
var RESOLVE = { artboard: resolveBoardFile, document: resolveDocumentAsset, html: resolveHtmlFile };
|
|
89758
90000
|
var isArtifactPage = (type, relative) => type === "html" ? relative === "index.html" : relative.endsWith(".html");
|
|
89759
90001
|
function readArtifactFile(dir, type, relative, uiRuntimeUrl) {
|
|
@@ -89762,7 +90004,7 @@ function readArtifactFile(dir, type, relative, uiRuntimeUrl) {
|
|
|
89762
90004
|
if (!target) return null;
|
|
89763
90005
|
let data;
|
|
89764
90006
|
try {
|
|
89765
|
-
data =
|
|
90007
|
+
data = import_node_fs21.default.readFileSync(target);
|
|
89766
90008
|
} catch {
|
|
89767
90009
|
return null;
|
|
89768
90010
|
}
|
|
@@ -89772,25 +90014,25 @@ function readArtifactFile(dir, type, relative, uiRuntimeUrl) {
|
|
|
89772
90014
|
}
|
|
89773
90015
|
|
|
89774
90016
|
// src/server/watch.ts
|
|
89775
|
-
var
|
|
89776
|
-
var
|
|
89777
|
-
var toPosix = (file) => file.split(
|
|
90017
|
+
var import_node_fs22 = __toESM(require("node:fs"), 1);
|
|
90018
|
+
var import_node_path19 = __toESM(require("node:path"), 1);
|
|
90019
|
+
var toPosix = (file) => file.split(import_node_path19.default.sep).join("/");
|
|
89778
90020
|
var ignored = (file) => file === ".state" || file.startsWith(".state/");
|
|
89779
90021
|
function snapshot(root, dir = root, out = /* @__PURE__ */ new Map()) {
|
|
89780
90022
|
let entries2;
|
|
89781
90023
|
try {
|
|
89782
|
-
entries2 =
|
|
90024
|
+
entries2 = import_node_fs22.default.readdirSync(dir, { withFileTypes: true });
|
|
89783
90025
|
} catch {
|
|
89784
90026
|
return out;
|
|
89785
90027
|
}
|
|
89786
90028
|
for (const entry of entries2) {
|
|
89787
|
-
const full =
|
|
89788
|
-
const rel = toPosix(
|
|
90029
|
+
const full = import_node_path19.default.join(dir, entry.name);
|
|
90030
|
+
const rel = toPosix(import_node_path19.default.relative(root, full));
|
|
89789
90031
|
if (ignored(rel)) continue;
|
|
89790
90032
|
if (entry.isDirectory()) snapshot(root, full, out);
|
|
89791
90033
|
else {
|
|
89792
90034
|
try {
|
|
89793
|
-
out.set(rel,
|
|
90035
|
+
out.set(rel, import_node_fs22.default.statSync(full).mtimeMs);
|
|
89794
90036
|
} catch {
|
|
89795
90037
|
}
|
|
89796
90038
|
}
|
|
@@ -89823,7 +90065,7 @@ function watchTree(root, onChange, debounceMs = 120, backupPollMs = 1e3) {
|
|
|
89823
90065
|
}, debounceMs);
|
|
89824
90066
|
};
|
|
89825
90067
|
try {
|
|
89826
|
-
const watcher =
|
|
90068
|
+
const watcher = import_node_fs22.default.watch(root, { recursive: true }, (_event, filename) => {
|
|
89827
90069
|
if (filename) queue([toPosix(filename.toString())]);
|
|
89828
90070
|
});
|
|
89829
90071
|
watcher.on("error", () => {
|
|
@@ -89873,6 +90115,8 @@ var API_PREVIEW_ROUTE = /^\/api\/preview\/([^/]+)\/([^/]+)$/;
|
|
|
89873
90115
|
var API_DOCUMENT_ROUTE = /^\/api\/document\/([^/]+)\/(state|update|comments)$/;
|
|
89874
90116
|
var MAX_COMMENT_OP = 64 * 1024;
|
|
89875
90117
|
var API_AGENT_COMMENTS_ROUTE = /^\/api\/agent\/document\/([^/]+)\/comments$/;
|
|
90118
|
+
var API_BOARD_COMMENTS_ROUTE = /^\/api\/artboard\/([^/]+)\/comments$/;
|
|
90119
|
+
var API_AGENT_BOARD_COMMENTS_ROUTE = /^\/api\/agent\/artboard\/([^/]+)\/comments$/;
|
|
89876
90120
|
var MAX_DOCUMENT_UPDATE = 8 * 1024 * 1024;
|
|
89877
90121
|
var MAX_RELAY_FILE = 8 * 1024 * 1024;
|
|
89878
90122
|
var MAX_RUNTIME_MESSAGE = 2048;
|
|
@@ -89891,17 +90135,17 @@ function titleOf(payload, ref) {
|
|
|
89891
90135
|
return payload.canvas?.title || ref.id;
|
|
89892
90136
|
}
|
|
89893
90137
|
async function startArtifactsServer(options) {
|
|
89894
|
-
const root =
|
|
89895
|
-
const viewerDir =
|
|
89896
|
-
const runtimeDir = options.runtimeDir ?
|
|
89897
|
-
const stateDir =
|
|
89898
|
-
|
|
89899
|
-
|
|
90138
|
+
const root = import_node_path20.default.resolve(options.root);
|
|
90139
|
+
const viewerDir = import_node_path20.default.resolve(options.viewerDir);
|
|
90140
|
+
const runtimeDir = options.runtimeDir ? import_node_path20.default.resolve(options.runtimeDir) : null;
|
|
90141
|
+
const stateDir = import_node_path20.default.join(root, ".state");
|
|
90142
|
+
import_node_fs23.default.mkdirSync(stateDir, { recursive: true, mode: 448 });
|
|
90143
|
+
import_node_fs23.default.writeFileSync(import_node_path20.default.join(stateDir, ".gitignore"), "*\n");
|
|
89900
90144
|
if (options.configFile) ensureConfig(options.configFile);
|
|
89901
|
-
const portFile =
|
|
89902
|
-
const tokenFile =
|
|
90145
|
+
const portFile = import_node_path20.default.join(stateDir, ".last-port");
|
|
90146
|
+
const tokenFile = import_node_path20.default.join(stateDir, ".last-token");
|
|
89903
90147
|
const token = readPersisted(tokenFile) || randomToken();
|
|
89904
|
-
|
|
90148
|
+
import_node_fs23.default.writeFileSync(tokenFile, `${token}
|
|
89905
90149
|
`, { mode: 384 });
|
|
89906
90150
|
const contentToken = randomToken();
|
|
89907
90151
|
const runtimeWarnings = /* @__PURE__ */ new Map();
|
|
@@ -89931,7 +90175,8 @@ async function startArtifactsServer(options) {
|
|
|
89931
90175
|
direct.emit(message.artifact, message);
|
|
89932
90176
|
};
|
|
89933
90177
|
const avatars = createAvatars(options.fetch);
|
|
89934
|
-
const names = commentNames({ agentFile:
|
|
90178
|
+
const names = commentNames({ agentFile: import_node_path20.default.join(stateDir, "agent"), projectDir: import_node_path20.default.resolve(root, "../.."), cloud: options.cloud });
|
|
90179
|
+
const boardComments = createBoardCommentRegistry({ root, stateDir, broadcast, names });
|
|
89935
90180
|
const documents = createDocumentRegistry({
|
|
89936
90181
|
root,
|
|
89937
90182
|
stateDir,
|
|
@@ -89969,8 +90214,8 @@ async function startArtifactsServer(options) {
|
|
|
89969
90214
|
}
|
|
89970
90215
|
return { dir, title, reasons, payload: published };
|
|
89971
90216
|
};
|
|
89972
|
-
const cloud = options.cloud && options.configFile ? createCloudRoutes({ ...options.cloud, configFile: options.configFile, project:
|
|
89973
|
-
const autoPublisher = cloud ? createAutoPublisher({ stateFile:
|
|
90217
|
+
const cloud = options.cloud && options.configFile ? createCloudRoutes({ ...options.cloud, configFile: options.configFile, project: import_node_path20.default.basename(import_node_path20.default.resolve(root, "../..")), port: () => port, inspect }) : null;
|
|
90218
|
+
const autoPublisher = cloud ? createAutoPublisher({ stateFile: import_node_path20.default.join(stateDir, "auto-publish.json"), enabled: cloud.autoPublishEnabled, token: cloud.token, publish: cloud.autoPublish }) : null;
|
|
89974
90219
|
const sameOrigin = (req) => {
|
|
89975
90220
|
const origin2 = req.headers.origin;
|
|
89976
90221
|
const host = req.headers.host ?? "";
|
|
@@ -90049,7 +90294,7 @@ async function startArtifactsServer(options) {
|
|
|
90049
90294
|
};
|
|
90050
90295
|
const blockIdsOf = async (id2, dir) => {
|
|
90051
90296
|
await (await documents.open(id2))?.flush();
|
|
90052
|
-
const state = parseDocument2(
|
|
90297
|
+
const state = parseDocument2(import_node_fs23.default.readFileSync(import_node_path20.default.join(dir, "doc.xml"), "utf8"));
|
|
90053
90298
|
return new Set(state.root.children.flatMap((block) => block.$?.blockId ? [block.$.blockId] : []));
|
|
90054
90299
|
};
|
|
90055
90300
|
const serveAgentComments = async (req, res, id2) => {
|
|
@@ -90089,6 +90334,55 @@ async function startArtifactsServer(options) {
|
|
|
90089
90334
|
sendJson(res, 400, { error: err.message });
|
|
90090
90335
|
}
|
|
90091
90336
|
};
|
|
90337
|
+
const serveBoardComments = async (req, res, id2) => {
|
|
90338
|
+
if (req.method !== "POST" || !sameOrigin(req)) {
|
|
90339
|
+
send(res, 403, "Forbidden");
|
|
90340
|
+
return;
|
|
90341
|
+
}
|
|
90342
|
+
if (!resolveArtifactDir(root, "artboard", id2)) {
|
|
90343
|
+
sendJson(res, 404, { error: `artboard/${id2} not found` });
|
|
90344
|
+
return;
|
|
90345
|
+
}
|
|
90346
|
+
const op = asBoardHumanOp(await readCommentBody(req));
|
|
90347
|
+
if (!op) {
|
|
90348
|
+
sendJson(res, 400, { error: "not a comment op" });
|
|
90349
|
+
return;
|
|
90350
|
+
}
|
|
90351
|
+
sendJson(res, 200, boardComments.apply(id2, op));
|
|
90352
|
+
};
|
|
90353
|
+
const serveAgentBoardComments = async (req, res, id2) => {
|
|
90354
|
+
const dir = resolveArtifactDir(root, "artboard", id2);
|
|
90355
|
+
if (!dir) {
|
|
90356
|
+
sendJson(res, 404, { error: `artboard/${id2} not found` });
|
|
90357
|
+
return;
|
|
90358
|
+
}
|
|
90359
|
+
const body = await readCommentBody(req);
|
|
90360
|
+
const fields = typeof body === "object" && body !== null ? body : {};
|
|
90361
|
+
const agent = typeof fields.agent === "string" && fields.agent.length > 0 && fields.agent.length <= 100 ? fields.agent : void 0;
|
|
90362
|
+
if (fields.op === "list") {
|
|
90363
|
+
sendJson(res, 200, { type: "comments", artifact: `artboard/${id2}`, threads: boardComments.list(id2, agent ?? "Agent", fields.all === true) });
|
|
90364
|
+
return;
|
|
90365
|
+
}
|
|
90366
|
+
const shorthand = agentAddOnBoard(body, boardSpecs(dir));
|
|
90367
|
+
if (shorthand && "error" in shorthand) {
|
|
90368
|
+
sendJson(res, 400, { error: `${shorthand.error} in artboard/${id2}` });
|
|
90369
|
+
return;
|
|
90370
|
+
}
|
|
90371
|
+
const op = shorthand ?? asBoardAgentOp(body);
|
|
90372
|
+
if (!op) {
|
|
90373
|
+
sendJson(res, 400, { error: "not an agent comment op: use list, add {anchor: {page, board, x, y}, text}, reply {threadId, text} or resolve {threadId}; text must not be empty" });
|
|
90374
|
+
return;
|
|
90375
|
+
}
|
|
90376
|
+
if (op.op === "add" && op.anchor.board && !(op.anchor.board in boardFiles(dir))) {
|
|
90377
|
+
sendJson(res, 400, { error: `no board ${op.anchor.board} in artboard/${id2}` });
|
|
90378
|
+
return;
|
|
90379
|
+
}
|
|
90380
|
+
try {
|
|
90381
|
+
sendJson(res, 200, boardComments.applyAgent(id2, op, agent));
|
|
90382
|
+
} catch (err) {
|
|
90383
|
+
sendJson(res, 400, { error: err.message });
|
|
90384
|
+
}
|
|
90385
|
+
};
|
|
90092
90386
|
const isAuthorized = (req, keyFromQuery) => keyFromQuery !== null && safeEqual(keyFromQuery, token) || safeEqual(parseCookies(req.headers.cookie)[cookieName] ?? "", token);
|
|
90093
90387
|
const serveContent = (res, rest) => {
|
|
90094
90388
|
if (rest.startsWith("runtime/")) {
|
|
@@ -90129,7 +90423,7 @@ async function startArtifactsServer(options) {
|
|
|
90129
90423
|
sendFile(res, target, headers);
|
|
90130
90424
|
return;
|
|
90131
90425
|
}
|
|
90132
|
-
|
|
90426
|
+
import_node_fs23.default.readFile(target, "utf8", (err, source) => {
|
|
90133
90427
|
if (err) send(res, 404, "Not found");
|
|
90134
90428
|
else {
|
|
90135
90429
|
const uiRuntimeUrl = runtimeDir ? `${contentPrefix}runtime/ryugi-ui.js` : void 0;
|
|
@@ -90140,6 +90434,7 @@ async function startArtifactsServer(options) {
|
|
|
90140
90434
|
const artifactMeta = (ref, dir, contentOrigin = "") => ({
|
|
90141
90435
|
...readArtifact(dir, ref, runtimeOf(ref, dir)),
|
|
90142
90436
|
...ref.type !== "html" ? { agent: names.agent() } : {},
|
|
90437
|
+
...ref.type === "artboard" ? { comments: boardComments.comments(ref.id), staleThreads: boardComments.stale(ref.id) } : {},
|
|
90143
90438
|
contentBase: `${contentOrigin}${contentPrefix}${ref.type}/${ref.id}/`
|
|
90144
90439
|
});
|
|
90145
90440
|
const serveArtifactApi = (res, type, id2) => {
|
|
@@ -90158,7 +90453,7 @@ async function startArtifactsServer(options) {
|
|
|
90158
90453
|
title: titleOf(readArtifact(entry.dir, entry), entry),
|
|
90159
90454
|
updatedAt: latestMtime(entry.dir)
|
|
90160
90455
|
}));
|
|
90161
|
-
sendJson(res, 200, { project:
|
|
90456
|
+
sendJson(res, 200, { project: import_node_path20.default.basename(import_node_path20.default.dirname(import_node_path20.default.dirname(root))), artifacts: summaries, warnings });
|
|
90162
90457
|
};
|
|
90163
90458
|
function onClientText(socket, text2) {
|
|
90164
90459
|
let message;
|
|
@@ -90220,7 +90515,7 @@ async function startArtifactsServer(options) {
|
|
|
90220
90515
|
return;
|
|
90221
90516
|
}
|
|
90222
90517
|
if (pathname === "/robots.txt") {
|
|
90223
|
-
sendFile(res,
|
|
90518
|
+
sendFile(res, import_node_path20.default.join(viewerDir, "robots.txt"));
|
|
90224
90519
|
return;
|
|
90225
90520
|
}
|
|
90226
90521
|
if (pathname.startsWith("/c/")) {
|
|
@@ -90302,6 +90597,24 @@ async function startArtifactsServer(options) {
|
|
|
90302
90597
|
});
|
|
90303
90598
|
return;
|
|
90304
90599
|
}
|
|
90600
|
+
const agentBoardMatch = API_AGENT_BOARD_COMMENTS_ROUTE.exec(pathname);
|
|
90601
|
+
if (agentBoardMatch) {
|
|
90602
|
+
if (req.method !== "POST" || key2 === null || !safeEqual(key2, token)) {
|
|
90603
|
+
send(res, 403, "Forbidden: agent calls need ?key=");
|
|
90604
|
+
return;
|
|
90605
|
+
}
|
|
90606
|
+
void serveAgentBoardComments(req, res, agentBoardMatch[1]).catch((err) => {
|
|
90607
|
+
if (!res.headersSent) send(res, 500, `Artifacts error: ${err.message}`);
|
|
90608
|
+
});
|
|
90609
|
+
return;
|
|
90610
|
+
}
|
|
90611
|
+
const boardCommentsMatch = API_BOARD_COMMENTS_ROUTE.exec(pathname);
|
|
90612
|
+
if (boardCommentsMatch) {
|
|
90613
|
+
void serveBoardComments(req, res, boardCommentsMatch[1]).catch((err) => {
|
|
90614
|
+
if (!res.headersSent) send(res, 500, `Artifacts error: ${err.message}`);
|
|
90615
|
+
});
|
|
90616
|
+
return;
|
|
90617
|
+
}
|
|
90305
90618
|
const documentMatch = API_DOCUMENT_ROUTE.exec(pathname);
|
|
90306
90619
|
if (documentMatch) {
|
|
90307
90620
|
void serveDocumentApi(req, res, documentMatch[1], documentMatch[2]).catch((err) => {
|
|
@@ -90317,7 +90630,7 @@ async function startArtifactsServer(options) {
|
|
|
90317
90630
|
if (SHELL_ROUTE.test(pathname) || PREVIEW_ROUTE.test(pathname) || pathname === "/index.html") {
|
|
90318
90631
|
const ref = artifactKeyOf(pathname.replace(/^\/(?:preview\/)?/, "").replace(/\/$/, ""));
|
|
90319
90632
|
const dir = ref && resolveArtifactDir(root, ref.type, ref.id);
|
|
90320
|
-
const project =
|
|
90633
|
+
const project = import_node_path20.default.basename(import_node_path20.default.dirname(import_node_path20.default.dirname(root)));
|
|
90321
90634
|
const title = ref ? dir ? titleOf(readArtifact(dir, ref), ref) : ref.id : `${project} \xB7 Artifacts`;
|
|
90322
90635
|
const description = ref ? `\u5728 ${project} \u9879\u76EE\u4E2D\u67E5\u770B ${title}\uFF0C\u8FD9\u662F\u4E00\u4E2A ${ref.type === "artboard" ? "Artboard" : ref.type === "document" ? "Document" : "HTML"} Artifact\u3002` : `\u6D4F\u89C8 ${project} \u9879\u76EE\u7684\u5168\u90E8 Artboard\u3001Document \u548C HTML Artifact\uFF0C\u9884\u89C8\u771F\u5B9E\u5185\u5BB9\uFF0C\u6309\u7C7B\u578B\u3001\u540D\u79F0\u548C\u66F4\u65B0\u65F6\u95F4\u67E5\u627E\u4F5C\u54C1\u3002`;
|
|
90323
90636
|
const canonical = `http://${urlHostForHttp(options.urlHost)}:${port}/${ref ? `${ref.type}/${ref.id}` : ""}`;
|
|
@@ -90326,7 +90639,7 @@ async function startArtifactsServer(options) {
|
|
|
90326
90639
|
"Content-Security-Policy": PREVIEW_ROUTE.test(pathname) ? VIEWER_CSP.replace("frame-ancestors 'none'", "frame-ancestors 'self'") : VIEWER_CSP
|
|
90327
90640
|
};
|
|
90328
90641
|
if (key2 !== null) headers["Set-Cookie"] = `${cookieName}=${token}; HttpOnly; SameSite=Strict; Path=/`;
|
|
90329
|
-
void
|
|
90642
|
+
void import_node_fs23.default.promises.readFile(import_node_path20.default.join(viewerDir, "index.html"), "utf8").then((template) => send(res, 200, viewerPage(template, { title, description, url: canonical }), headers)).catch((err) => send(res, err.code === "ENOENT" ? 404 : 500, "Viewer unavailable"));
|
|
90330
90643
|
return;
|
|
90331
90644
|
}
|
|
90332
90645
|
const target = resolveInside(viewerDir, pathname.slice(1));
|
|
@@ -90385,7 +90698,7 @@ async function startArtifactsServer(options) {
|
|
|
90385
90698
|
port = await listen(server, options.host, 0);
|
|
90386
90699
|
}
|
|
90387
90700
|
cookieName = `ryugi_artifacts_${port}`;
|
|
90388
|
-
|
|
90701
|
+
import_node_fs23.default.writeFileSync(portFile, `${port}
|
|
90389
90702
|
`, { mode: 384 });
|
|
90390
90703
|
const origin = `http://${urlHostForHttp(options.urlHost)}:${port}`;
|
|
90391
90704
|
const url = `${origin}/?key=${token}`;
|
|
@@ -90402,7 +90715,7 @@ async function startArtifactsServer(options) {
|
|
|
90402
90715
|
return payload;
|
|
90403
90716
|
};
|
|
90404
90717
|
const refreshState = (ref, dir) => {
|
|
90405
|
-
signatures.set(`${ref.type}/${ref.id}`, artifactSignature(dir));
|
|
90718
|
+
signatures.set(`${ref.type}/${ref.id}`, artifactSignature(dir, ref.type));
|
|
90406
90719
|
return writeState(ref, dir);
|
|
90407
90720
|
};
|
|
90408
90721
|
const initialChanges = [];
|
|
@@ -90411,7 +90724,7 @@ async function startArtifactsServer(options) {
|
|
|
90411
90724
|
initialChanges.push({ ref: entry, payload, files: [] });
|
|
90412
90725
|
if (entry.type === "document") void documents.open(entry.id);
|
|
90413
90726
|
}
|
|
90414
|
-
writeJsonAtomic(
|
|
90727
|
+
writeJsonAtomic(import_node_path20.default.join(stateDir, "server-info"), { type: "server-started", url, port, root });
|
|
90415
90728
|
const relayViewers = /* @__PURE__ */ new Map();
|
|
90416
90729
|
const servedArtifacts = () => {
|
|
90417
90730
|
const served = /* @__PURE__ */ new Map();
|
|
@@ -90444,6 +90757,11 @@ async function startArtifactsServer(options) {
|
|
|
90444
90757
|
if (typeof request.message === "object" && request.message !== null) acceptReport({ ...request.message, artifact: key2 });
|
|
90445
90758
|
return null;
|
|
90446
90759
|
}
|
|
90760
|
+
if (request.op === "comment" && ref.type === "artboard") {
|
|
90761
|
+
const op = JSON.stringify(request.comment ?? null).length <= MAX_COMMENT_OP ? asBoardHumanOp(request.comment) : null;
|
|
90762
|
+
if (!op) throw new Error("not a comment op");
|
|
90763
|
+
return boardComments.apply(ref.id, op);
|
|
90764
|
+
}
|
|
90447
90765
|
if ((request.op === "state" || request.op === "update" || request.op === "comment") && ref.type !== "document") throw new Error(`${key2} is not a document`);
|
|
90448
90766
|
if (request.op === "state" || request.op === "update") {
|
|
90449
90767
|
const session = await documents.open(ref.id);
|
|
@@ -90508,7 +90826,9 @@ async function startArtifactsServer(options) {
|
|
|
90508
90826
|
}
|
|
90509
90827
|
if (ref.type === "document" && (changed.includes("doc.xml") || changed.length === 0)) documents.fileChanged(ref.id);
|
|
90510
90828
|
if (ref.type === "document" && changed.includes("comments.json")) documents.commentsChanged(ref.id);
|
|
90511
|
-
if (
|
|
90829
|
+
if (ref.type === "artboard" && changed.includes("comments.json")) boardComments.sync(ref.id);
|
|
90830
|
+
if (ref.type === "artboard" && (changed.some((file) => file !== "comments.json") || changed.length === 0)) boardComments.boardsChanged(ref.id);
|
|
90831
|
+
if (signatures.get(key2) === artifactSignature(dir, ref.type)) continue;
|
|
90512
90832
|
autoPublisher?.changed(key2);
|
|
90513
90833
|
runtimeWarnings.delete(key2);
|
|
90514
90834
|
const payload = refreshState(ref, dir);
|
|
@@ -90552,7 +90872,7 @@ async function startArtifactsServer(options) {
|
|
|
90552
90872
|
}
|
|
90553
90873
|
|
|
90554
90874
|
// src/server/lifecycle.ts
|
|
90555
|
-
var
|
|
90875
|
+
var import_node_fs24 = __toESM(require("node:fs"), 1);
|
|
90556
90876
|
var DEFAULT_IDLE_TIMEOUT_MS = 4 * 60 * 60 * 1e3;
|
|
90557
90877
|
var DEFAULT_LIFECYCLE_CHECK_MS = 60 * 1e3;
|
|
90558
90878
|
var SERVER_ID_ARG = "--artifacts-server-id=";
|
|
@@ -90584,7 +90904,7 @@ function parseEnv(env, argv = []) {
|
|
|
90584
90904
|
function readOwners(file) {
|
|
90585
90905
|
let text2;
|
|
90586
90906
|
try {
|
|
90587
|
-
text2 =
|
|
90907
|
+
text2 = import_node_fs24.default.readFileSync(file, "utf8");
|
|
90588
90908
|
} catch {
|
|
90589
90909
|
return [];
|
|
90590
90910
|
}
|
|
@@ -90647,20 +90967,20 @@ function openReady(payload) {
|
|
|
90647
90967
|
}
|
|
90648
90968
|
|
|
90649
90969
|
// package.json
|
|
90650
|
-
var version = "1.
|
|
90970
|
+
var version = "1.16.0";
|
|
90651
90971
|
|
|
90652
90972
|
// src/server/main.ts
|
|
90653
90973
|
async function main() {
|
|
90654
90974
|
const config = parseEnv(process.env, process.argv.slice(2));
|
|
90655
|
-
const root =
|
|
90656
|
-
const stateDir =
|
|
90975
|
+
const root = import_node_path21.default.resolve(config.root);
|
|
90976
|
+
const stateDir = import_node_path21.default.join(root, ".state");
|
|
90657
90977
|
const server = await startArtifactsServer({
|
|
90658
90978
|
root,
|
|
90659
|
-
viewerDir:
|
|
90660
|
-
runtimeDir:
|
|
90979
|
+
viewerDir: import_node_path21.default.join(__dirname, "viewer"),
|
|
90980
|
+
runtimeDir: import_node_path21.default.join(__dirname, "runtime"),
|
|
90661
90981
|
host: config.host,
|
|
90662
90982
|
urlHost: config.urlHost,
|
|
90663
|
-
configFile:
|
|
90983
|
+
configFile: import_node_path21.default.join(import_node_path21.default.dirname(root), "config.json"),
|
|
90664
90984
|
cloud: { origin: config.cloudOrigin, credentialsFile: credentialsFile(process.env, process.platform, import_node_os.default.homedir()) },
|
|
90665
90985
|
relay: { url: `${config.cloudOrigin.replace(/^http/, "ws")}/api/relay/host`, version }
|
|
90666
90986
|
});
|
|
@@ -90690,12 +91010,12 @@ async function main() {
|
|
|
90690
91010
|
if (stopping) return;
|
|
90691
91011
|
stopping = true;
|
|
90692
91012
|
console.log(JSON.stringify({ type: "server-stopped", reason }));
|
|
90693
|
-
|
|
90694
|
-
writeJsonAtomic(
|
|
91013
|
+
import_node_fs25.default.rmSync(import_node_path21.default.join(stateDir, "server-info"), { force: true });
|
|
91014
|
+
writeJsonAtomic(import_node_path21.default.join(stateDir, "server-stopped"), { reason, timestamp: Date.now() });
|
|
90695
91015
|
await server.close();
|
|
90696
91016
|
process.exit(0);
|
|
90697
91017
|
};
|
|
90698
|
-
const ownersFile =
|
|
91018
|
+
const ownersFile = import_node_path21.default.join(stateDir, "owners");
|
|
90699
91019
|
const timer = setInterval(() => {
|
|
90700
91020
|
const owners = readOwners(ownersFile);
|
|
90701
91021
|
const reason = shutdownReason({
|
|
@@ -90709,7 +91029,7 @@ async function main() {
|
|
|
90709
91029
|
timer.unref();
|
|
90710
91030
|
process.on("SIGTERM", () => void shutdown("SIGTERM"));
|
|
90711
91031
|
process.on("SIGINT", () => void shutdown("SIGINT"));
|
|
90712
|
-
|
|
91032
|
+
import_node_fs25.default.rmSync(import_node_path21.default.join(stateDir, "server-stopped"), { force: true });
|
|
90713
91033
|
console.log(JSON.stringify({ type: "server-started", url: server.url, port: server.port, root }));
|
|
90714
91034
|
}
|
|
90715
91035
|
main().catch((err) => {
|