@prismshadow/penguin-server 0.2.16 → 0.2.17

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.
Files changed (108) hide show
  1. package/README.md +1 -1
  2. package/dist/api/types.d.ts +233 -47
  3. package/dist/api/types.js +9 -3
  4. package/dist/auth-token.js +1 -1
  5. package/dist/{chunk-HMTT2PX4.js → chunk-2LZDP26O.js} +8 -5
  6. package/dist/chunk-2LZDP26O.js.map +1 -0
  7. package/dist/{chunk-LPPVGHYD.js → chunk-BL4U7GYY.js} +2 -2
  8. package/dist/chunk-BL4U7GYY.js.map +1 -0
  9. package/dist/chunk-GGIINEEK.js +3401 -0
  10. package/dist/chunk-GGIINEEK.js.map +1 -0
  11. package/dist/chunk-HDBZRVA5.js +29 -0
  12. package/dist/chunk-HDBZRVA5.js.map +1 -0
  13. package/dist/{chunk-3SFJKLQU.js → chunk-HPOHMZCH.js} +679 -559
  14. package/dist/chunk-HPOHMZCH.js.map +1 -0
  15. package/dist/{chunk-QFV3ERQO.js → chunk-OQZDL3TR.js} +2 -2
  16. package/dist/hmr/manifest.js +1 -1
  17. package/dist/index.js +7701 -4814
  18. package/dist/index.js.map +1 -1
  19. package/dist/machine-status.js +2 -2
  20. package/dist/model-catalog.d.ts +610 -0
  21. package/dist/model-catalog.js +108 -0
  22. package/dist/model-catalog.js.map +1 -0
  23. package/dist/plugin/index.d.ts +113 -58
  24. package/dist/reset-admin-password.js +1 -1
  25. package/dist/version-report.js +2 -2
  26. package/package.json +14 -9
  27. package/web-dist/assets/{abnfDiagram-VCTEODGH-0AKFiyig.js → abnfDiagram-VCTEODGH-DMzkb4l4.js} +1 -1
  28. package/web-dist/assets/{addon-clipboard-BovFnNVg.js → addon-clipboard-BtD2BVSi.js} +1 -1
  29. package/web-dist/assets/{addon-fit-B1npgxQk.js → addon-fit-Dr6HWsi_.js} +1 -1
  30. package/web-dist/assets/{addon-web-links-D88QHj7A.js → addon-web-links-VEE3YLzQ.js} +1 -1
  31. package/web-dist/assets/{arc-Beox1Cgf.js → arc-CvMPOU_B.js} +1 -1
  32. package/web-dist/assets/{architectureDiagram-5GKGNRK7-CC1sLMY1.js → architectureDiagram-5GKGNRK7-Bk65mIBz.js} +1 -1
  33. package/web-dist/assets/{blockDiagram-I7D4REHJ-B8BY1PkZ.js → blockDiagram-I7D4REHJ-D54-XSNs.js} +1 -1
  34. package/web-dist/assets/{c4Diagram-7LVT6UL2-yjY0BkxQ.js → c4Diagram-7LVT6UL2-Dm954LSt.js} +1 -1
  35. package/web-dist/assets/channel-CVHI75kz.js +1 -0
  36. package/web-dist/assets/{chunk-2Q5K7J3B-DdgIvETg.js → chunk-2Q5K7J3B-D_LJ_7Cn.js} +1 -1
  37. package/web-dist/assets/{chunk-5VM5RSS4-BE38k1Rs.js → chunk-5VM5RSS4-B8RI4tl3.js} +1 -1
  38. package/web-dist/assets/{chunk-F27PBJKO-D4YXmaqQ.js → chunk-F27PBJKO-aVSYH9JV.js} +1 -1
  39. package/web-dist/assets/{chunk-IMKFNOWR-CyJFdThc.js → chunk-IMKFNOWR-DnkdWeq2.js} +1 -1
  40. package/web-dist/assets/{chunk-JWPE2WC7-BAM_oEUU.js → chunk-JWPE2WC7-C2pJzKuW.js} +1 -1
  41. package/web-dist/assets/{chunk-POPQ4Y6H-BP3D0FVi.js → chunk-POPQ4Y6H-Bx7Iikzx.js} +1 -1
  42. package/web-dist/assets/{chunk-SVP7TREG-Clk8PdKZ.js → chunk-SVP7TREG-qJC2SMqr.js} +1 -1
  43. package/web-dist/assets/{chunk-TICWLB2K-EvWPnEGg.js → chunk-TICWLB2K-Crl_BgKI.js} +1 -1
  44. package/web-dist/assets/{chunk-XXDRQBXY-6p5D0UB1.js → chunk-XXDRQBXY-BFFemuGm.js} +1 -1
  45. package/web-dist/assets/classDiagram-ZZMXUADV-CBdzAPFu.js +1 -0
  46. package/web-dist/assets/classDiagram-v2-VYDZK3BY-CBdzAPFu.js +1 -0
  47. package/web-dist/assets/{cose-bilkent-JH36ORCC-bpkI-tLJ.js → cose-bilkent-JH36ORCC-Bmh2Kx7h.js} +1 -1
  48. package/web-dist/assets/{cynefin-OW5HDTMX-srLaqJ4e.js → cynefin-OW5HDTMX-BveNWnUV.js} +1 -1
  49. package/web-dist/assets/{cynefinDiagram-5FMLGOSQ-BPfpHSPc.js → cynefinDiagram-5FMLGOSQ-85itazbJ.js} +1 -1
  50. package/web-dist/assets/{dagre-GXQ25YYZ-C4fF5-j7.js → dagre-GXQ25YYZ-DIZT-KY_.js} +1 -1
  51. package/web-dist/assets/{diagram-S7CK7UJ4-BzBLb_9-.js → diagram-S7CK7UJ4-Dum-g63f.js} +1 -1
  52. package/web-dist/assets/{diagram-UQ7AKVKN-BJuJ1o_T.js → diagram-UQ7AKVKN-DallMKJl.js} +1 -1
  53. package/web-dist/assets/{diagram-VSXAHHWV-DFelN9i9.js → diagram-VSXAHHWV-DWELqxfN.js} +1 -1
  54. package/web-dist/assets/{diagram-VX7I27RA-BgrEoPyp.js → diagram-VX7I27RA-BNs0gB9E.js} +1 -1
  55. package/web-dist/assets/{diagram-Z3DM3KII-C71KiMiX.js → diagram-Z3DM3KII-C9mF9xAd.js} +1 -1
  56. package/web-dist/assets/{ebnfDiagram-PWID7BFC-EYteyp1b.js → ebnfDiagram-PWID7BFC-D_Diy9HH.js} +1 -1
  57. package/web-dist/assets/{erDiagram-RLTQ6QDP-B6n6-sz6.js → erDiagram-RLTQ6QDP-4QTS5VIh.js} +1 -1
  58. package/web-dist/assets/{flowDiagram-HODETNUW-BtoMTdyT.js → flowDiagram-HODETNUW-CliTRrtV.js} +1 -1
  59. package/web-dist/assets/{ganttDiagram-EL5Y4UJY-CbOAa3vS.js → ganttDiagram-EL5Y4UJY-DCRd-Ss4.js} +1 -1
  60. package/web-dist/assets/{gitGraphDiagram-WWUBYQGX-B7-8sszH.js → gitGraphDiagram-WWUBYQGX-CTz13GjS.js} +1 -1
  61. package/web-dist/assets/highlighter-BScH1Ud3.js +2 -0
  62. package/web-dist/assets/{highlighter-core-CMXoD8ze.js → highlighter-core-DKz8Z6-I.js} +1 -1
  63. package/web-dist/assets/{highlighter.worker-D6D9fPma.js → highlighter.worker-CKF6ok1g.js} +1 -1
  64. package/web-dist/assets/index-BUvJ5Ctt.js +1299 -0
  65. package/web-dist/assets/index-DRj7nvPY.css +1 -0
  66. package/web-dist/assets/{infoDiagram-27XIBGKW-BBjf6pkP.js → infoDiagram-27XIBGKW-DNfTEPAV.js} +1 -1
  67. package/web-dist/assets/{ishikawaDiagram-5VMMS53U-BBSvCv45.js → ishikawaDiagram-5VMMS53U-B7aCjjG1.js} +1 -1
  68. package/web-dist/assets/{journeyDiagram-3NMN7TZE-CuHHl5zk.js → journeyDiagram-3NMN7TZE-COmDALVr.js} +1 -1
  69. package/web-dist/assets/{kanban-definition-UXKFOSKX-DJyP4Myw.js → kanban-definition-UXKFOSKX-BzUfPINh.js} +1 -1
  70. package/web-dist/assets/{layout-Bqqhdwtt.js → layout-BwzuPU4M.js} +1 -1
  71. package/web-dist/assets/{linear-BZfUSIf8.js → linear-WPZTYjz3.js} +1 -1
  72. package/web-dist/assets/mermaid.core-zKzlwpkw.js +310 -0
  73. package/web-dist/assets/{mindmap-definition-YA3MSWOX-BtyMD4wz.js → mindmap-definition-YA3MSWOX-DCRg7eAx.js} +1 -1
  74. package/web-dist/assets/{pegDiagram-XKGWAZYB-BUF_GJ0B.js → pegDiagram-XKGWAZYB-DyphzDLU.js} +1 -1
  75. package/web-dist/assets/{pieDiagram-E7YTZNPT-nweubbsU.js → pieDiagram-E7YTZNPT-BI5DueGA.js} +1 -1
  76. package/web-dist/assets/powershell-DXrKVo3G.js +1 -0
  77. package/web-dist/assets/powershell-Dpen1YoG.js +1 -0
  78. package/web-dist/assets/{quadrantDiagram-AXDQQJYC-B_r4Wkxy.js → quadrantDiagram-AXDQQJYC-GZxSMY2Z.js} +1 -1
  79. package/web-dist/assets/{railroadDiagram-O6MQD6OU-Dn7nm0MX.js → railroadDiagram-O6MQD6OU-DEFCigBf.js} +1 -1
  80. package/web-dist/assets/{requirementDiagram-BXWQKSXE-DaagYJ49.js → requirementDiagram-BXWQKSXE-Br0thc4j.js} +1 -1
  81. package/web-dist/assets/{sankeyDiagram-P5KCCOFB-CqEX6H-B.js → sankeyDiagram-P5KCCOFB-DYf0pY67.js} +1 -1
  82. package/web-dist/assets/{sequenceDiagram-WJ2MYXX4-BzLfQO55.js → sequenceDiagram-WJ2MYXX4-1EFMboX4.js} +1 -1
  83. package/web-dist/assets/{sizeCapture-INFHLROL-BcUuVH2L.js → sizeCapture-INFHLROL-BuOFv-5q.js} +1 -1
  84. package/web-dist/assets/{stateDiagram-D77RDMKH-BO3LWLvT.js → stateDiagram-D77RDMKH-Bg3H1tjX.js} +1 -1
  85. package/web-dist/assets/stateDiagram-v2-MP3YSRHH-DfaDaPAd.js +1 -0
  86. package/web-dist/assets/{swimlanes-42K2YHIH-etP_hkIB.js → swimlanes-42K2YHIH-BuOa6Osb.js} +1 -1
  87. package/web-dist/assets/swimlanesDiagram-VR7AAH4N-BopAC7b8.js +8 -0
  88. package/web-dist/assets/{timeline-definition-24CTP7MA-CTLt2XCT.js → timeline-definition-24CTP7MA-BDekfdDT.js} +1 -1
  89. package/web-dist/assets/{vennDiagram-4TSXK5OY-DPO6ZSvH.js → vennDiagram-4TSXK5OY-DnC09UI4.js} +1 -1
  90. package/web-dist/assets/{wardleyDiagram-VM6X3IG4-DFofGg8b.js → wardleyDiagram-VM6X3IG4-BXKvxuZQ.js} +1 -1
  91. package/web-dist/assets/{xterm-RdyTuaAH.js → xterm-oY4DYg5s.js} +1 -1
  92. package/web-dist/assets/{xychartDiagram-S5SC5T6Z-Bgtb34Gu.js → xychartDiagram-S5SC5T6Z-DdDC1VLb.js} +1 -1
  93. package/web-dist/index.html +6 -5
  94. package/dist/chunk-3SFJKLQU.js.map +0 -1
  95. package/dist/chunk-HMTT2PX4.js.map +0 -1
  96. package/dist/chunk-LPPVGHYD.js.map +0 -1
  97. package/dist/chunk-W7JNIJ25.js +0 -19
  98. package/dist/chunk-W7JNIJ25.js.map +0 -1
  99. package/web-dist/assets/channel-mfsAVJLE.js +0 -1
  100. package/web-dist/assets/classDiagram-ZZMXUADV-BPVO1m8i.js +0 -1
  101. package/web-dist/assets/classDiagram-v2-VYDZK3BY-BPVO1m8i.js +0 -1
  102. package/web-dist/assets/highlighter-Bj5l2XH_.js +0 -2
  103. package/web-dist/assets/index-BOCqRT4e.css +0 -1
  104. package/web-dist/assets/index-BrMpjp2s.js +0 -1286
  105. package/web-dist/assets/mermaid.core-BlUspEsI.js +0 -310
  106. package/web-dist/assets/stateDiagram-v2-MP3YSRHH-B-EuucjM.js +0 -1
  107. package/web-dist/assets/swimlanesDiagram-VR7AAH4N-0JbFdDbQ.js +0 -8
  108. /package/dist/{chunk-QFV3ERQO.js.map → chunk-OQZDL3TR.js.map} +0 -0
@@ -50,12 +50,13 @@ var MachinesRepo = class {
50
50
  installedAt: null,
51
51
  sessionPid: null,
52
52
  remotePort: null,
53
- platform: null
53
+ platform: null,
54
+ adoptedAt: null
54
55
  },
55
56
  ...patch
56
57
  };
57
58
  this.db.prepare(
58
- "INSERT OR REPLACE INTO machines (address, machine_id, version, installed_at, session_pid, remote_port, platform) VALUES (?, ?, ?, ?, ?, ?, ?)"
59
+ "INSERT OR REPLACE INTO machines (address, machine_id, version, installed_at, session_pid, remote_port, platform, adopted_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
59
60
  ).run(
60
61
  address,
61
62
  next.machineId,
@@ -63,7 +64,8 @@ var MachinesRepo = class {
63
64
  next.installedAt,
64
65
  next.sessionPid,
65
66
  next.remotePort,
66
- next.platform
67
+ next.platform,
68
+ next.adoptedAt
67
69
  );
68
70
  }
69
71
  /** The addresses a Project uses, or null when it has never had a list written for it. */
@@ -83,11 +85,12 @@ function toRow(row) {
83
85
  installedAt: row.installed_at ?? null,
84
86
  sessionPid: row.session_pid ?? null,
85
87
  remotePort: row.remote_port ?? null,
86
- platform: row.platform ?? null
88
+ platform: row.platform ?? null,
89
+ adoptedAt: row.adopted_at ?? null
87
90
  };
88
91
  }
89
92
 
90
93
  export {
91
94
  MachinesRepo
92
95
  };
93
- //# sourceMappingURL=chunk-HMTT2PX4.js.map
96
+ //# sourceMappingURL=chunk-2LZDP26O.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/db/repos/machines.ts"],"sourcesContent":["/**\n * What this server remembers about machines: its own identity, one row per machine it has\n * installed on or reached (what is installed there, the session held to it), and which\n * machines each Project uses. All in web.db, so a hot swap or a restart reads back exactly\n * what the last generation wrote — the JSON file this replaces could not survive a schema\n * change, and nothing else this server remembers lives outside the database.\n */\nimport type { DatabaseSync } from \"node:sqlite\";\nimport { randomBytes } from \"node:crypto\";\n\nexport interface MachineRow {\n /** `ssh:<alias>` */\n address: string;\n /** That machine's own id, once heard. */\n machineId: string | null;\n /** What this server last installed there; null when it never has. */\n version: string | null;\n installedAt: string | null;\n /**\n * Non-null while a connection to it is HELD: the pid of the session as of the last connect.\n * A record of intent, not a handle — a restart or a hot push re-holds every machine with one,\n * and a disconnect clears it. It is never used to kill anything: a pid read back from a file\n * may by then be anyone's.\n */\n sessionPid: number | null;\n /** The port its server was bound to over there, as of the last connect. */\n remotePort: number | null;\n /** What the install found the machine to be; null until one has. The status probe speaks that dialect. */\n platform: \"linux\" | \"darwin\" | \"win32\" | null;\n /**\n * When this server adopted the machine: when it first recorded it at this address, again when\n * the address answers with another machine's id. The Sessions that machine held before then\n * read as CLI tasks through this server (runtime/session-sources.ts). Null for a machine\n * recorded before the time was kept, which never gets one and which the rule leaves alone.\n */\n adoptedAt: string | null;\n}\n\n/** Everything but the address may be patched; absent fields keep their value. */\ntype MachinePatch = Partial<Omit<MachineRow, \"address\">>;\n\n/**\n * 12 random bytes as base64url: 16 characters a person can read in a tooltip, 96 bits\n * against ids minted on machines that never coordinate.\n */\nconst MACHINE_ID_BYTES = 12;\n\nexport class MachinesRepo {\n constructor(private readonly db: DatabaseSync) {}\n\n /**\n * This server's own id if one has been minted, WITHOUT minting one — `penguin server\n * status` runs on a data root whose server may never have started, and must not create an\n * identity as a side effect of the question.\n */\n peekOwnId(): string | null {\n const row = this.db.prepare(\"SELECT machine_id FROM machine WHERE singleton = 1\").get();\n return row ? (row.machine_id as string) : null;\n }\n\n /** This server's own id, minted on first call and stable ever after. */\n ownId(): string {\n const existing = this.peekOwnId();\n if (existing !== null) return existing;\n const minted = randomBytes(MACHINE_ID_BYTES).toString(\"base64url\");\n this.db.prepare(\"INSERT INTO machine (singleton, machine_id) VALUES (1, ?)\").run(minted);\n return minted;\n }\n\n get(address: string): MachineRow | null {\n const row = this.db.prepare(\"SELECT * FROM machines WHERE address = ?\").get(address);\n return row === undefined ? null : toRow(row);\n }\n\n /**\n * Every row answering to a machine's own id — two aliases for one host are two rows with\n * one id. Newest install first, then by address, so the order is the same every time; which\n * of them to speak through is the service's to decide (it knows which has a session).\n */\n byMachineId(machineId: string): MachineRow[] {\n return this.db\n .prepare(\n \"SELECT * FROM machines WHERE machine_id = ? ORDER BY installed_at DESC, address ASC\",\n )\n .all(machineId)\n .map(toRow);\n }\n\n all(): MachineRow[] {\n return this.db.prepare(\"SELECT * FROM machines\").all().map(toRow);\n }\n\n /** Writes the fields given, creating the row when there is none. */\n patch(address: string, patch: MachinePatch): void {\n const next: MachineRow = {\n ...(this.get(address) ?? {\n address,\n machineId: null,\n version: null,\n installedAt: null,\n sessionPid: null,\n remotePort: null,\n platform: null,\n adoptedAt: null,\n }),\n ...patch,\n };\n this.db\n .prepare(\n \"INSERT OR REPLACE INTO machines (address, machine_id, version, installed_at, session_pid, remote_port, platform, adopted_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)\",\n )\n .run(\n address,\n next.machineId,\n next.version,\n next.installedAt,\n next.sessionPid,\n next.remotePort,\n next.platform,\n next.adoptedAt,\n );\n }\n\n /** The addresses a Project uses, or null when it has never had a list written for it. */\n members(projectId: string): string[] | null {\n const row = this.db\n .prepare(\"SELECT addresses FROM machine_project WHERE project_id = ?\")\n .get(projectId);\n return row ? (JSON.parse(row.addresses as string) as string[]) : null;\n }\n\n setMembers(projectId: string, addresses: string[]): void {\n this.db\n .prepare(\"INSERT OR REPLACE INTO machine_project (project_id, addresses) VALUES (?, ?)\")\n .run(projectId, JSON.stringify(addresses));\n }\n}\n\nfunction toRow(row: Record<string, unknown>): MachineRow {\n return {\n address: row.address as string,\n machineId: (row.machine_id as string | null) ?? null,\n version: (row.version as string | null) ?? null,\n installedAt: (row.installed_at as string | null) ?? null,\n sessionPid: (row.session_pid as number | null) ?? null,\n remotePort: (row.remote_port as number | null) ?? null,\n platform: (row.platform as MachineRow[\"platform\"]) ?? null,\n adoptedAt: (row.adopted_at as string | null) ?? null,\n };\n}\n"],"mappings":";AAQA,SAAS,mBAAmB;AAqC5B,IAAM,mBAAmB;AAElB,IAAM,eAAN,MAAmB;AAAA,EACxB,YAA6B,IAAkB;AAAlB;AAAA,EAAmB;AAAA,EAAnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO7B,YAA2B;AACzB,UAAM,MAAM,KAAK,GAAG,QAAQ,oDAAoD,EAAE,IAAI;AACtF,WAAO,MAAO,IAAI,aAAwB;AAAA,EAC5C;AAAA;AAAA,EAGA,QAAgB;AACd,UAAM,WAAW,KAAK,UAAU;AAChC,QAAI,aAAa,KAAM,QAAO;AAC9B,UAAM,SAAS,YAAY,gBAAgB,EAAE,SAAS,WAAW;AACjE,SAAK,GAAG,QAAQ,2DAA2D,EAAE,IAAI,MAAM;AACvF,WAAO;AAAA,EACT;AAAA,EAEA,IAAI,SAAoC;AACtC,UAAM,MAAM,KAAK,GAAG,QAAQ,0CAA0C,EAAE,IAAI,OAAO;AACnF,WAAO,QAAQ,SAAY,OAAO,MAAM,GAAG;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YAAY,WAAiC;AAC3C,WAAO,KAAK,GACT;AAAA,MACC;AAAA,IACF,EACC,IAAI,SAAS,EACb,IAAI,KAAK;AAAA,EACd;AAAA,EAEA,MAAoB;AAClB,WAAO,KAAK,GAAG,QAAQ,wBAAwB,EAAE,IAAI,EAAE,IAAI,KAAK;AAAA,EAClE;AAAA;AAAA,EAGA,MAAM,SAAiB,OAA2B;AAChD,UAAM,OAAmB;AAAA,MACvB,GAAI,KAAK,IAAI,OAAO,KAAK;AAAA,QACvB;AAAA,QACA,WAAW;AAAA,QACX,SAAS;AAAA,QACT,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,WAAW;AAAA,MACb;AAAA,MACA,GAAG;AAAA,IACL;AACA,SAAK,GACF;AAAA,MACC;AAAA,IACF,EACC;AAAA,MACC;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAAA,EACJ;AAAA;AAAA,EAGA,QAAQ,WAAoC;AAC1C,UAAM,MAAM,KAAK,GACd,QAAQ,4DAA4D,EACpE,IAAI,SAAS;AAChB,WAAO,MAAO,KAAK,MAAM,IAAI,SAAmB,IAAiB;AAAA,EACnE;AAAA,EAEA,WAAW,WAAmB,WAA2B;AACvD,SAAK,GACF,QAAQ,8EAA8E,EACtF,IAAI,WAAW,KAAK,UAAU,SAAS,CAAC;AAAA,EAC7C;AACF;AAEA,SAAS,MAAM,KAA0C;AACvD,SAAO;AAAA,IACL,SAAS,IAAI;AAAA,IACb,WAAY,IAAI,cAAgC;AAAA,IAChD,SAAU,IAAI,WAA6B;AAAA,IAC3C,aAAc,IAAI,gBAAkC;AAAA,IACpD,YAAa,IAAI,eAAiC;AAAA,IAClD,YAAa,IAAI,eAAiC;AAAA,IAClD,UAAW,IAAI,YAAuC;AAAA,IACtD,WAAY,IAAI,cAAgC;AAAA,EAClD;AACF;","names":[]}
@@ -1,4 +1,4 @@
1
- // ../../node_modules/.pnpm/@prismshadow+penguin-hmr@file+packages+hmr_supports-color@10.2.2_ws@8.21.0/node_modules/@prismshadow/penguin-hmr/dist/chunk-HC5WPFTZ.js
1
+ // ../../node_modules/.pnpm/@prismshadow+penguin-hmr@file+packages+hmr_supports-color@10.2.2_ws@8.21.0_zod@4.6.7/node_modules/@prismshadow/penguin-hmr/dist/chunk-HC5WPFTZ.js
2
2
  import fs from "fs";
3
3
  import fsp from "fs/promises";
4
4
  import path from "path";
@@ -80,4 +80,4 @@ export {
80
80
  readPushedCli,
81
81
  resolveCliBundlePath
82
82
  };
83
- //# sourceMappingURL=chunk-LPPVGHYD.js.map
83
+ //# sourceMappingURL=chunk-BL4U7GYY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../node_modules/.pnpm/@prismshadow+penguin-hmr@file+packages+hmr_supports-color@10.2.2_ws@8.21.0_zod@4.6.7/node_modules/@prismshadow/penguin-hmr/src/manifest.ts"],"sourcesContent":["/**\n * The harness.json shape (`<root>/hmr/harness.json`) and pure readers over it.\n *\n * Split out of host.ts so a reader never needs a running HmrHost: `penguin` is a\n * separate, short-lived process per invocation (see packages/cli/src/index.ts) — it\n * has no host instance to ask, only the data root's own harness.json on disk.\n * `resolveCliBundlePath` is that reader: a plain disk read, no HTTP, no boot, no\n * in-memory state.\n *\n * ONE atomic version, THREE independent artifacts: `platform`, `cli`, and `web` are\n * always written together by HmrHost's single merged upgrade path (see host.ts's\n * persistVersion), but each is content-addressed and stored on its own — a push to\n * POST /api/hmr/upgrade carries `platform` and `cli` as two separate single-file ESM\n * sources, so `cli.bundle` points at its OWN file, a different sha from\n * `platform.bundle`. They are read back together too (see host.ts's restore): a\n * partial record (e.g. `platform` present but `web` or `cli` missing) is never\n * trusted — the whole version is treated as absent instead of partially applied.\n */\nimport fs from \"node:fs\";\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { HarnessInfo } from \"@prismshadow/penguin-core\";\n\n/**\n * The committed on-disk record: a runtime restart resumes exactly this CODE (platform,\n * cli, web). It carries no STATE — a restart always boots the resumed platform bundle\n * against its own fresh initial context (bundle.context, see host.ts's PlatformBundle),\n * never a document parked from a previous run (see host.ts's module doc for why: a\n * parked doc's live-resource handles die with the process anyway, so resuming one could\n * only ever produce handles that fail to reclaim). Paths are relative to hmrDir\n * (`<root>/hmr`).\n */\n/**\n * Written into an assets directory once every file in it is on disk. Its absence marks a\n * directory whose materialization was interrupted; no asset path can collide with it\n * (assets arrive as `node_modules/...` paths).\n */\nexport const MATERIALIZED = \".materialized\";\n\nexport interface Manifest {\n platform?: { bundle: string };\n /**\n * The CLI's own bundle pointer — its own independent file (a different sha from\n * `platform.bundle`; the two are separately compiled artifacts), kept as its own\n * field so a reader that only wants \"which bundle does the CLI load right now\"\n * never has to reach into `platform` at all.\n */\n cli?: { bundle: string };\n /** One gzip(JSON.stringify({ files })) artifact, restored straight into memory. */\n web?: { manifest: string };\n /**\n * Files the pushed platform needs as REAL files on disk, unpacked under this directory\n * (relative to hmrDir). The web artifact stays in memory because it is only ever served\n * as bytes; an asset is something the platform hands to the OS — a native `.node` the\n * loader must resolve by path, a helper binary it execs — so it has to exist on the\n * filesystem, with its exec bit intact.\n */\n assets?: { dir: string };\n /**\n * Provenance of the push that produced this version, exactly as the pushing client sent\n * it (scripts/deploy.mjs fills it from its own checkout). Recorded, never executed or\n * resolved. Absent for a version pushed without it, and for every version committed\n * before the field existed — which is why every reader treats it as optional.\n */\n source?: { repo: string; revision: string };\n /** When this version was committed to the store (ISO 8601). Absent on older records. */\n pushedAt?: string;\n /**\n * The sha256 of each part this version was pushed as (platform, cli, every web file):\n * the blobs the store keeps alive so the next push need not carry an unchanged one.\n * Absent on older records.\n */\n blobs?: string[];\n}\n\n/** A string field of an untrusted manifest, or null unless it is a non-empty string. */\nfunction str(value: unknown): string | null {\n return typeof value === \"string\" && value.length > 0 ? value : null;\n}\n\n/**\n * What the store has committed, for version reporting: provenance, commit time, and the\n * three artifact pointers. Null when nothing has ever been pushed to this root.\n *\n * Read defensively rather than cast: harness.json is written only by persistVersion, but a\n * truncated or hand-edited file must degrade a `penguin version` to missing fields, never\n * crash it. A record missing every artifact pointer counts as nothing pushed, and so does an\n * unreadable one — the only reader here that deliberately collapses the two, because its\n * caller is a report with nowhere to put a fault. The host says so at boot instead, and\n * `penguin-hmr` says so through readPushedCli.\n */\nexport async function readHarnessInfo(root: string): Promise<HarnessInfo | null> {\n const manifest = await readManifest(root);\n if (manifest === null) return null;\n\n const bundles = {\n platform: str(manifest.platform?.bundle),\n cli: str(manifest.cli?.bundle),\n web: str(manifest.web?.manifest),\n };\n if (bundles.platform === null && bundles.cli === null && bundles.web === null) return null;\n\n const repo = str(manifest.source?.repo);\n const revision = str(manifest.source?.revision);\n return {\n // Both halves or neither: half a provenance names nothing.\n source: repo !== null && revision !== null ? { repo, revision } : null,\n pushedAt: str(manifest.pushedAt),\n bundles,\n };\n}\n\n/**\n * `<root>/hmr/harness.json`, as one of three answers. No file means nothing was ever pushed\n * here; a file that cannot be read or parsed is a fault on a root that DID commit a version,\n * and the two must not arrive as the same value — a reader that acts on \"nothing pushed\"\n * would quietly ignore a version this root still holds.\n */\ntype ManifestRead =\n { kind: \"none\" } | { kind: \"manifest\"; manifest: Manifest } | { kind: \"broken\"; reason: string };\n\nasync function readManifestFile(root: string): Promise<ManifestRead> {\n const file = path.join(root, \"hmr\", \"harness.json\");\n let raw: string;\n try {\n raw = await fsp.readFile(file, \"utf8\");\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return { kind: \"none\" };\n return { kind: \"broken\", reason: `${file} could not be read: ${msg(err)}` };\n }\n try {\n return { kind: \"manifest\", manifest: JSON.parse(raw) as Manifest };\n } catch (err) {\n return { kind: \"broken\", reason: `${file} is not readable JSON: ${msg(err)}` };\n }\n}\n\nfunction msg(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/**\n * Reads and parses `<root>/hmr/harness.json`; null when missing or corrupt. The published\n * `./hmr/manifest` subpath is a contract with installed CLIs, so this keeps its shape;\n * a caller that has to tell the two apart reads it through readPushedCli.\n */\nexport async function readManifest(root: string): Promise<Manifest | null> {\n const read = await readManifestFile(root);\n return read.kind === \"manifest\" ? read.manifest : null;\n}\n\n/**\n * What this root has for the `penguin-hmr` loader. Three answers, never two: a root that\n * pushed no CLI and a root whose record names one it cannot produce are different\n * situations, and collapsing them tells the caller \"nothing pushed\" when the truth is\n * \"the store lost it\".\n */\nexport type PushedCli =\n /** Nothing has pushed a CLI here: a fresh root, or a record with no `cli` entry. */\n | { kind: \"none\" }\n /** The committed CLI bundle, absolute. */\n | { kind: \"bundle\"; file: string }\n /** The record names a CLI this root cannot produce. Says which, so it can be repaired. */\n | { kind: \"broken\"; reason: string };\n\n/**\n * Reads the committed CLI bundle. Never throws: a malformed record is an answer\n * (`broken`), not an exception, because the caller is a CLI entry point that has to print\n * something useful either way.\n *\n * `cli.bundle` is trusted content, written only by persistVersion, but a reader must never\n * let a malformed or malicious value walk it out of the store via `..` segments — an escape\n * is `broken`, like a file the store no longer holds (pruned, see host.ts's pruneStore).\n */\nexport async function readPushedCli(root: string): Promise<PushedCli> {\n const read = await readManifestFile(root);\n if (read.kind === \"none\") return { kind: \"none\" };\n if (read.kind === \"broken\") return { kind: \"broken\", reason: read.reason };\n // No `cli` entry at all is a version that pushed no CLI; an entry that names nothing\n // usable is a record this root cannot act on.\n if (read.manifest.cli === undefined) return { kind: \"none\" };\n const bundle: unknown = read.manifest.cli.bundle;\n if (typeof bundle !== \"string\" || bundle.length === 0) {\n return { kind: \"broken\", reason: \"harness.json has a `cli` entry with no bundle path\" };\n }\n const hmrDir = path.join(root, \"hmr\");\n const abs = path.resolve(hmrDir, bundle);\n if (abs !== hmrDir && !abs.startsWith(hmrDir + path.sep)) {\n return {\n kind: \"broken\",\n reason: `harness.json points \\`cli.bundle\\` outside ${hmrDir}: ${bundle}`,\n };\n }\n if (!fs.existsSync(abs)) {\n return { kind: \"broken\", reason: `the committed CLI bundle is missing from the store: ${abs}` };\n }\n return { kind: \"bundle\", file: abs };\n}\n\n/**\n * The committed CLI bundle's path, or null for anything else. The published `./hmr/manifest`\n * subpath is a contract with installed CLIs, so this keeps its shape; readPushedCli is what\n * says WHY there is no path.\n */\nexport async function resolveCliBundlePath(root: string): Promise<string | null> {\n const cli = await readPushedCli(root);\n return cli.kind === \"bundle\" ? cli.file : null;\n}\n"],"mappings":";AAkBA,OAAO,QAAQ;AACf,OAAO,SAAS;AAChB,OAAO,UAAU;AAiBV,IAAM,eAAe;AAuC5B,SAAS,IAAI,OAA+B;AAC1C,SAAO,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ;AACjE;AAaA,eAAsB,gBAAgB,MAA2C;AAC/E,QAAM,WAAW,MAAM,aAAa,IAAI;AACxC,MAAI,aAAa,KAAM,QAAO;AAE9B,QAAM,UAAU;IACd,UAAU,IAAI,SAAS,UAAU,MAAM;IACvC,KAAK,IAAI,SAAS,KAAK,MAAM;IAC7B,KAAK,IAAI,SAAS,KAAK,QAAQ;EACjC;AACA,MAAI,QAAQ,aAAa,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,KAAM,QAAO;AAEtF,QAAM,OAAO,IAAI,SAAS,QAAQ,IAAI;AACtC,QAAM,WAAW,IAAI,SAAS,QAAQ,QAAQ;AAC9C,SAAO;;IAEL,QAAQ,SAAS,QAAQ,aAAa,OAAO,EAAE,MAAM,SAAS,IAAI;IAClE,UAAU,IAAI,SAAS,QAAQ;IAC/B;EACF;AACF;AAWA,eAAe,iBAAiB,MAAqC;AACnE,QAAM,OAAO,KAAK,KAAK,MAAM,OAAO,cAAc;AAClD,MAAI;AACJ,MAAI;AACF,UAAM,MAAM,IAAI,SAAS,MAAM,MAAM;EACvC,SAAS,KAAK;AACZ,QAAK,IAA8B,SAAS,SAAU,QAAO,EAAE,MAAM,OAAO;AAC5E,WAAO,EAAE,MAAM,UAAU,QAAQ,GAAG,IAAI,uBAAuB,IAAI,GAAG,CAAC,GAAG;EAC5E;AACA,MAAI;AACF,WAAO,EAAE,MAAM,YAAY,UAAU,KAAK,MAAM,GAAG,EAAc;EACnE,SAAS,KAAK;AACZ,WAAO,EAAE,MAAM,UAAU,QAAQ,GAAG,IAAI,0BAA0B,IAAI,GAAG,CAAC,GAAG;EAC/E;AACF;AAEA,SAAS,IAAI,KAAsB;AACjC,SAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AACxD;AAOA,eAAsB,aAAa,MAAwC;AACzE,QAAM,OAAO,MAAM,iBAAiB,IAAI;AACxC,SAAO,KAAK,SAAS,aAAa,KAAK,WAAW;AACpD;AAyBA,eAAsB,cAAc,MAAkC;AACpE,QAAM,OAAO,MAAM,iBAAiB,IAAI;AACxC,MAAI,KAAK,SAAS,OAAQ,QAAO,EAAE,MAAM,OAAO;AAChD,MAAI,KAAK,SAAS,SAAU,QAAO,EAAE,MAAM,UAAU,QAAQ,KAAK,OAAO;AAGzE,MAAI,KAAK,SAAS,QAAQ,OAAW,QAAO,EAAE,MAAM,OAAO;AAC3D,QAAM,SAAkB,KAAK,SAAS,IAAI;AAC1C,MAAI,OAAO,WAAW,YAAY,OAAO,WAAW,GAAG;AACrD,WAAO,EAAE,MAAM,UAAU,QAAQ,qDAAqD;EACxF;AACA,QAAM,SAAS,KAAK,KAAK,MAAM,KAAK;AACpC,QAAM,MAAM,KAAK,QAAQ,QAAQ,MAAM;AACvC,MAAI,QAAQ,UAAU,CAAC,IAAI,WAAW,SAAS,KAAK,GAAG,GAAG;AACxD,WAAO;MACL,MAAM;MACN,QAAQ,8CAA8C,MAAM,KAAK,MAAM;IACzE;EACF;AACA,MAAI,CAAC,GAAG,WAAW,GAAG,GAAG;AACvB,WAAO,EAAE,MAAM,UAAU,QAAQ,uDAAuD,GAAG,GAAG;EAChG;AACA,SAAO,EAAE,MAAM,UAAU,MAAM,IAAI;AACrC;AAOA,eAAsB,qBAAqB,MAAsC;AAC/E,QAAM,MAAM,MAAM,cAAc,IAAI;AACpC,SAAO,IAAI,SAAS,WAAW,IAAI,OAAO;AAC5C;","names":[]}