kennel 0.2.45 → 0.2.46
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/core/api-client.js +34 -1
- package/dist/core/runtime.js +189 -129
- package/dist/package/preview.js +217 -141
- package/package.json +2 -2
- package/web/assets/{abnfDiagram-VRR7QNED-D8mHNUwf.js → abnfDiagram-VRR7QNED-BOm3iBSE.js} +1 -1
- package/web/assets/{arc-DORR-Lbn.js → arc-D_zfnjJW.js} +1 -1
- package/web/assets/{architectureDiagram-ZJ3FMSHR-CnmL2DAX.js → architectureDiagram-ZJ3FMSHR-CTXAbDtC.js} +1 -1
- package/web/assets/{ask-tray-KUTWZ4MV-VQJJAsDn.js → ask-tray-CT6DQRTC-DfTc3bnC.js} +1 -1
- package/web/assets/{blockDiagram-677ZJIJ3-_SWUT5nP.js → blockDiagram-677ZJIJ3-CcPWOAKO.js} +1 -1
- package/web/assets/{c4Diagram-LMCZKHZV-r7ghc180.js → c4Diagram-LMCZKHZV-B_eNO2-f.js} +1 -1
- package/web/assets/channel-Dlb_u_Yk.js +1 -0
- package/web/assets/{chunk-2Q5K7J3B-D_LeMwFJ.js → chunk-2Q5K7J3B-BtQX_f5i.js} +1 -1
- package/web/assets/{chunk-32BRIVSS-AeVZw1It.js → chunk-32BRIVSS-BBtfsm8_.js} +1 -1
- package/web/assets/{chunk-5VM5RSS4-Bp_epQ8r.js → chunk-5VM5RSS4-CG0bf9ML.js} +1 -1
- package/web/assets/{chunk-EX3LRPZG-Dz4n-DeM.js → chunk-EX3LRPZG-DS2H7ilP.js} +1 -1
- package/web/assets/{chunk-JWPE2WC7-B0MQp8TQ.js → chunk-JWPE2WC7-CGLMMKkr.js} +1 -1
- package/web/assets/{chunk-MOJQB5TN-Bkomqk1x.js → chunk-MOJQB5TN-C76lqDkU.js} +1 -1
- package/web/assets/{chunk-RYQCIY6F-B0F7WMyE.js → chunk-RYQCIY6F-ZY-EzC5l.js} +1 -1
- package/web/assets/{chunk-V7JOEXUC-BDifU9oY.js → chunk-V7JOEXUC-sBv90hIh.js} +1 -1
- package/web/assets/{chunk-VR4S4FIN-Bgd4HCG_.js → chunk-VR4S4FIN-jW9aFTp3.js} +1 -1
- package/web/assets/{chunk-XXDRQBXY-BK8FhRs4.js → chunk-XXDRQBXY-FPtE6zce.js} +1 -1
- package/web/assets/classDiagram-OUVF2IWQ-CinFzRGQ.js +1 -0
- package/web/assets/classDiagram-v2-EOCWNBFH-CinFzRGQ.js +1 -0
- package/web/assets/{client-5Q4VI7ZT-BkTtFalV.js → client-5Q4VI7ZT-DYH5SwVp.js} +1 -1
- package/web/assets/{cose-bilkent-JH36ORCC-Dm3k2U47.js → cose-bilkent-JH36ORCC-NdJGLzeJ.js} +1 -1
- package/web/assets/{cynefin-VYW2F7L2-DCnilF1f.js → cynefin-VYW2F7L2-D-o_obcW.js} +1 -1
- package/web/assets/{cynefinDiagram-TSTJHNR4-BrulEEQ9.js → cynefinDiagram-TSTJHNR4-RA4QYrtB.js} +1 -1
- package/web/assets/{dagre-VKFMJZFB-Dda61i4h.js → dagre-VKFMJZFB-Bq4DfO16.js} +1 -1
- package/web/assets/{diagram-FQU43EPY-sTmDEDMM.js → diagram-FQU43EPY-bPnACaba.js} +1 -1
- package/web/assets/{diagram-G47NLZAW-d-KQnPrm.js → diagram-G47NLZAW-cPca5hvp.js} +1 -1
- package/web/assets/{diagram-NH7WQ7WH-DcRxa_ps.js → diagram-NH7WQ7WH-DHyP34H8.js} +1 -1
- package/web/assets/{diagram-OA4YK3LP-CYzWtWvV.js → diagram-OA4YK3LP-hVk7mHu1.js} +1 -1
- package/web/assets/{diagram-WEI45ONY-FI3V_N07.js → diagram-WEI45ONY-Cd3AEJO3.js} +1 -1
- package/web/assets/{document-view-TGFRNHKS-VSJS3BGw.js → document-view-VX2ZTQM5-CDdtofzz.js} +8 -8
- package/web/assets/{ebnfDiagram-CCIWWBDH-DcvVmQhu.js → ebnfDiagram-CCIWWBDH-BxtDx2MR.js} +1 -1
- package/web/assets/{entity-search-page-RIYQYIJJ-Bed3y-5Q.js → entity-search-page-RIYQYIJJ-IvZzjXvt.js} +1 -1
- package/web/assets/{erDiagram-Q63AITRT-DI5DBlBp.js → erDiagram-Q63AITRT-CtdOkrpo.js} +1 -1
- package/web/assets/{flowDiagram-23GEKE2U-Bz1AbRxB.js → flowDiagram-23GEKE2U-BDHfaJo6.js} +1 -1
- package/web/assets/{ganttDiagram-NO4QXBWP-ChKlhxeo.js → ganttDiagram-NO4QXBWP-BhV7JFJA.js} +1 -1
- package/web/assets/{gitGraphDiagram-IHSO6WYX-BtTqLSyY.js → gitGraphDiagram-IHSO6WYX-BVRBRDVk.js} +1 -1
- package/web/assets/index-BxCXNDe6.css +1 -0
- package/web/assets/{index-CDAH4UPU.js → index-Cl-kcrk3.js} +191 -182
- package/web/assets/{infoDiagram-FWYZ7A6U-COpIz9uZ.js → infoDiagram-FWYZ7A6U-BKuFQe6t.js} +1 -1
- package/web/assets/{ishikawaDiagram-FXEZZL3T-CB7Bdsfr.js → ishikawaDiagram-FXEZZL3T-lNbhlHEo.js} +1 -1
- package/web/assets/{journeyDiagram-5HDEW3XC-BMytnJBE.js → journeyDiagram-5HDEW3XC-CoGf_pSm.js} +1 -1
- package/web/assets/{kanban-definition-HUTT4EX6-BFS4G0g-.js → kanban-definition-HUTT4EX6-Cgp0WGrq.js} +1 -1
- package/web/assets/{linear-DMUO2qBp.js → linear-B3UMk7TK.js} +1 -1
- package/web/assets/{linked-session-header-7BUTWROP-DzEcA4Fq.js → linked-session-header-7BUTWROP-Coqn-Dz0.js} +1 -1
- package/web/assets/{mermaid.core-BAj-Ltr-.js → mermaid.core-6bZ5bkAq.js} +4 -4
- package/web/assets/{mindmap-definition-LN4V7U3C-CjymOEvH.js → mindmap-definition-LN4V7U3C-BowQNgIG.js} +1 -1
- package/web/assets/{pegDiagram-2B236MQR-D64jiUPu.js → pegDiagram-2B236MQR-DrhWFvfI.js} +1 -1
- package/web/assets/{pieDiagram-ENE6RG2P-CCbI5U6o.js → pieDiagram-ENE6RG2P-DNOg53mu.js} +1 -1
- package/web/assets/{plugin-host-modules-D7pHtNJn.js → plugin-host-modules-NvyHieUX.js} +26 -26
- package/web/assets/{project-search-page-O6YRLDGU-1bPrifgb.js → project-search-page-O6YRLDGU-CFA4lf0c.js} +1 -1
- package/web/assets/{quadrantDiagram-ABIIQ3AL-B7dN_Kn5.js → quadrantDiagram-ABIIQ3AL-BOJ4UGbk.js} +1 -1
- package/web/assets/{railroadDiagram-RFXS5EU6-BPjAzqcL.js → railroadDiagram-RFXS5EU6-_UJ9_AEC.js} +1 -1
- package/web/assets/{requirementDiagram-TGXJPOKE-BFhnnUWa.js → requirementDiagram-TGXJPOKE-BFa61FSa.js} +1 -1
- package/web/assets/{sankeyDiagram-HTMAVEWB-W2UguUjW.js → sankeyDiagram-HTMAVEWB-V1J9w6jl.js} +1 -1
- package/web/assets/{selection-popup-ABYH3A27-DsiLbG7S.js → selection-popup-ZX4VUZ3A-Duh9LSP2.js} +1 -1
- package/web/assets/{sequenceDiagram-DBY2YBRQ-DcOakOD4.js → sequenceDiagram-DBY2YBRQ-xdS7JpTx.js} +1 -1
- package/web/assets/{sizeCapture-X5ZJPWSS-D3N248Z6.js → sizeCapture-X5ZJPWSS-DBULLaws.js} +1 -1
- package/web/assets/{stateDiagram-2N3HPSRC-Cir3yiDe.js → stateDiagram-2N3HPSRC-DfBpQAQb.js} +1 -1
- package/web/assets/{stateDiagram-v2-6OUMAXLB-BwL0KYLn.js → stateDiagram-v2-6OUMAXLB-C-dC_PIX.js} +1 -1
- package/web/assets/{swimlanes-5IMT3BWC-Dhq7FmZr.js → swimlanes-5IMT3BWC-L-RTYuhP.js} +2 -2
- package/web/assets/swimlanesDiagram-G3AALYLV-BErklojq.js +8 -0
- package/web/assets/{timeline-definition-FHXFAJF6-CMa1wjsI.js → timeline-definition-FHXFAJF6-CAEbvdzk.js} +1 -1
- package/web/assets/{vennDiagram-L72KCM5P-DvglazwQ.js → vennDiagram-L72KCM5P-J10bFP8c.js} +1 -1
- package/web/assets/{wardleyDiagram-EHGQE667-DcogrL32.js → wardleyDiagram-EHGQE667-Bm0goK-9.js} +1 -1
- package/web/assets/{xychartDiagram-FW5EYKEG-BlsDcr_U.js → xychartDiagram-FW5EYKEG-BAH4TTVb.js} +1 -1
- package/web/index.html +2 -2
- package/web/assets/channel-r9-1szjb.js +0 -1
- package/web/assets/classDiagram-OUVF2IWQ-L_jmDmNd.js +0 -1
- package/web/assets/classDiagram-v2-EOCWNBFH-L_jmDmNd.js +0 -1
- package/web/assets/index-Di6pguZz.css +0 -1
- package/web/assets/swimlanesDiagram-G3AALYLV-D4q-nPpB.js +0 -8
package/dist/package/preview.js
CHANGED
|
@@ -5655,7 +5655,7 @@ var init_contract2 = __esm(() => {
|
|
|
5655
5655
|
});
|
|
5656
5656
|
|
|
5657
5657
|
// packages/api/src/contracts/schemas.ts
|
|
5658
|
-
var items = (item) => object({ items: array(item) }), icon, file, project, session, collectionSummary2, workspace, plugin, plugins, folder, assets, folderMetadataSchema, collection, metadataSchemas, metadataQuerySchema, documentEditSchema, document2, documentSchema, entity, projectSearchItemSchema, pathQuery, emptyQuery, routes;
|
|
5658
|
+
var items = (item) => object({ items: array(item) }), icon, file, project, session, collectionSummary2, workspace, plugin, plugins, folder, assets, folderMetadataSchema, collection, metadataSchemas, metadataQuerySchema, deleteNoteSchema, documentEditSchema, document2, documentSchema, entity, projectSearchItemSchema, pathQuery, emptyQuery, routes;
|
|
5659
5659
|
var init_schemas3 = __esm(() => {
|
|
5660
5660
|
init_contract2();
|
|
5661
5661
|
init_zod();
|
|
@@ -5767,6 +5767,10 @@ var init_schemas3 = __esm(() => {
|
|
|
5767
5767
|
sort: _enum(["alpha", "recent"]).optional(),
|
|
5768
5768
|
schema: string2().optional()
|
|
5769
5769
|
});
|
|
5770
|
+
deleteNoteSchema = object({
|
|
5771
|
+
folder: string2(),
|
|
5772
|
+
path: string2()
|
|
5773
|
+
});
|
|
5770
5774
|
documentEditSchema = object({
|
|
5771
5775
|
folder: string2(),
|
|
5772
5776
|
path: string2(),
|
|
@@ -5826,7 +5830,11 @@ var init_schemas3 = __esm(() => {
|
|
|
5826
5830
|
path: "/api/health",
|
|
5827
5831
|
method: "get",
|
|
5828
5832
|
query: emptyQuery,
|
|
5829
|
-
response: object({
|
|
5833
|
+
response: object({
|
|
5834
|
+
viewer: string2(),
|
|
5835
|
+
root: string2(),
|
|
5836
|
+
kernelKey: string2()
|
|
5837
|
+
})
|
|
5830
5838
|
},
|
|
5831
5839
|
capabilities: {
|
|
5832
5840
|
path: "/api/capabilities",
|
|
@@ -5914,6 +5922,13 @@ var init_schemas3 = __esm(() => {
|
|
|
5914
5922
|
path: "/api/open-path",
|
|
5915
5923
|
method: "get",
|
|
5916
5924
|
query: object({ path: string2() })
|
|
5925
|
+
},
|
|
5926
|
+
deleteNote: {
|
|
5927
|
+
path: "/api/delete-note",
|
|
5928
|
+
method: "post",
|
|
5929
|
+
query: emptyQuery,
|
|
5930
|
+
body: deleteNoteSchema,
|
|
5931
|
+
response: object({ deleted: literal(true) })
|
|
5917
5932
|
}
|
|
5918
5933
|
};
|
|
5919
5934
|
});
|
|
@@ -6030,6 +6045,16 @@ function createKennelClient(options = {}) {
|
|
|
6030
6045
|
parseAs: "text"
|
|
6031
6046
|
});
|
|
6032
6047
|
},
|
|
6048
|
+
async deleteNote(body, input = {}) {
|
|
6049
|
+
const response = await (options.fetch ?? globalThis.fetch)(new URL(routes.deleteNote.path, baseUrl), {
|
|
6050
|
+
method: "POST",
|
|
6051
|
+
headers: { "Content-Type": "application/json" },
|
|
6052
|
+
body: JSON.stringify(deleteNoteSchema.parse(body)),
|
|
6053
|
+
signal: input.signal
|
|
6054
|
+
});
|
|
6055
|
+
if (!response.ok)
|
|
6056
|
+
throw await expectedError(response);
|
|
6057
|
+
},
|
|
6033
6058
|
async openFolder(path, input = {}) {
|
|
6034
6059
|
await transport.POST(routes.openFolder.path, {
|
|
6035
6060
|
params: { query: { path } },
|
|
@@ -38593,6 +38618,43 @@ var init_entity_folder = __esm(() => {
|
|
|
38593
38618
|
]);
|
|
38594
38619
|
});
|
|
38595
38620
|
|
|
38621
|
+
// packages/api/src/server/api/delete-note.ts
|
|
38622
|
+
import { realpath as realpath5, stat as stat5, unlink as unlink2 } from "node:fs/promises";
|
|
38623
|
+
import { extname as extname3, isAbsolute as isAbsolute5, relative as relative9, resolve as resolve9, sep as sep5 } from "node:path";
|
|
38624
|
+
async function containedTarget(path, folder) {
|
|
38625
|
+
const target = await realpath5(resolve9(folder, path));
|
|
38626
|
+
const local = relative9(folder, target);
|
|
38627
|
+
if (!local || local === ".." || local.startsWith(`..${sep5}`) || isAbsolute5(local))
|
|
38628
|
+
throw apiError("forbidden", "The note must be inside its folder.");
|
|
38629
|
+
return target;
|
|
38630
|
+
}
|
|
38631
|
+
var markdownExtensions2, deleteNoteRoute;
|
|
38632
|
+
var init_delete_note = __esm(() => {
|
|
38633
|
+
init_schemas3();
|
|
38634
|
+
init_endpoint();
|
|
38635
|
+
markdownExtensions2 = new Set([".md", ".markdown"]);
|
|
38636
|
+
deleteNoteRoute = {
|
|
38637
|
+
method: "POST",
|
|
38638
|
+
maxBodyBytes: 4 * 1024,
|
|
38639
|
+
async handle({ body, context, response }) {
|
|
38640
|
+
const parsed = deleteNoteSchema.safeParse(parseJsonBody(body));
|
|
38641
|
+
if (!parsed.success)
|
|
38642
|
+
throw apiError("bad-request", "Invalid delete request.");
|
|
38643
|
+
const folder = context.authorize(parsed.data.folder);
|
|
38644
|
+
if (!markdownExtensions2.has(extname3(parsed.data.path).toLowerCase()))
|
|
38645
|
+
throw apiError("bad-request", "Only Markdown notes can be deleted.");
|
|
38646
|
+
const target = await containedTarget(parsed.data.path, folder);
|
|
38647
|
+
const details = await stat5(target).catch(() => {
|
|
38648
|
+
return;
|
|
38649
|
+
});
|
|
38650
|
+
if (!details?.isFile() || details.nlink !== 1)
|
|
38651
|
+
throw apiError("forbidden", "Only regular, unlinked files can be deleted.");
|
|
38652
|
+
await unlink2(target);
|
|
38653
|
+
jsonResponse(response, 200, routes.deleteNote.response.parse({ deleted: true }));
|
|
38654
|
+
}
|
|
38655
|
+
};
|
|
38656
|
+
});
|
|
38657
|
+
|
|
38596
38658
|
// packages/api/src/shared/selection.ts
|
|
38597
38659
|
function replaceSelection(content, start, end, replacement) {
|
|
38598
38660
|
if (!Number.isInteger(start) || !Number.isInteger(end) || start < 0 || end <= start || end > content.length)
|
|
@@ -38604,30 +38666,30 @@ function replaceSelection(content, start, end, replacement) {
|
|
|
38604
38666
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
38605
38667
|
import {
|
|
38606
38668
|
readFile as readFile7,
|
|
38607
|
-
realpath as
|
|
38669
|
+
realpath as realpath6,
|
|
38608
38670
|
rename as rename3,
|
|
38609
|
-
stat as
|
|
38610
|
-
unlink as
|
|
38671
|
+
stat as stat6,
|
|
38672
|
+
unlink as unlink3,
|
|
38611
38673
|
writeFile as writeFile4
|
|
38612
38674
|
} from "node:fs/promises";
|
|
38613
38675
|
import {
|
|
38614
38676
|
dirname as dirname8,
|
|
38615
|
-
extname as
|
|
38616
|
-
isAbsolute as
|
|
38617
|
-
relative as
|
|
38618
|
-
resolve as
|
|
38619
|
-
sep as
|
|
38677
|
+
extname as extname4,
|
|
38678
|
+
isAbsolute as isAbsolute6,
|
|
38679
|
+
relative as relative10,
|
|
38680
|
+
resolve as resolve10,
|
|
38681
|
+
sep as sep6
|
|
38620
38682
|
} from "node:path";
|
|
38621
38683
|
async function editDocument(folder, input) {
|
|
38622
38684
|
const { path, original, start, end, replacement } = input;
|
|
38623
38685
|
if (typeof path !== "string" || typeof original !== "string" || typeof replacement !== "string" || typeof start !== "number" || typeof end !== "number")
|
|
38624
38686
|
throw apiError("bad-request", "Invalid document edit.");
|
|
38625
|
-
if (![".md", ".markdown"].includes(
|
|
38687
|
+
if (![".md", ".markdown"].includes(extname4(path).toLowerCase()))
|
|
38626
38688
|
throw apiError("bad-request", "Only Markdown notes can be edited.");
|
|
38627
|
-
const root = await
|
|
38628
|
-
const target = await
|
|
38629
|
-
const local =
|
|
38630
|
-
if (!local || local === ".." || local.startsWith(`..${
|
|
38689
|
+
const root = await realpath6(folder);
|
|
38690
|
+
const target = await realpath6(resolve10(root, path));
|
|
38691
|
+
const local = relative10(root, target);
|
|
38692
|
+
if (!local || local === ".." || local.startsWith(`..${sep6}`) || isAbsolute6(local))
|
|
38631
38693
|
throw apiError("forbidden", "The document must be inside its folder.");
|
|
38632
38694
|
let content;
|
|
38633
38695
|
try {
|
|
@@ -38637,12 +38699,12 @@ async function editDocument(folder, input) {
|
|
|
38637
38699
|
}
|
|
38638
38700
|
const previous = pending.get(target) ?? Promise.resolve();
|
|
38639
38701
|
const operation = previous.catch(() => {}).then(async () => {
|
|
38640
|
-
const details = await
|
|
38702
|
+
const details = await stat6(target);
|
|
38641
38703
|
if (!details.isFile() || details.nlink !== 1)
|
|
38642
38704
|
throw apiError("forbidden", "Only regular, unlinked files can be edited.");
|
|
38643
38705
|
if (await readFile7(target, "utf8") !== original)
|
|
38644
38706
|
throw apiError("conflict", "This note changed on disk. Close this preview, reload the note, and try again.");
|
|
38645
|
-
const temporary =
|
|
38707
|
+
const temporary = resolve10(dirname8(target), `.kennel-edit-${randomUUID3()}.tmp`);
|
|
38646
38708
|
try {
|
|
38647
38709
|
await writeFile4(temporary, content, {
|
|
38648
38710
|
flag: "wx",
|
|
@@ -38652,7 +38714,7 @@ async function editDocument(folder, input) {
|
|
|
38652
38714
|
throw apiError("conflict", "This note changed on disk. Reload before applying an edit.");
|
|
38653
38715
|
await rename3(temporary, target);
|
|
38654
38716
|
} finally {
|
|
38655
|
-
await
|
|
38717
|
+
await unlink3(temporary).catch(() => {});
|
|
38656
38718
|
}
|
|
38657
38719
|
return content;
|
|
38658
38720
|
});
|
|
@@ -38678,7 +38740,7 @@ var init_document_edit = __esm(() => {
|
|
|
38678
38740
|
throw apiError("bad-request", "Invalid document edit.");
|
|
38679
38741
|
const input = parsed.data;
|
|
38680
38742
|
const folder = context.authorize(input.folder);
|
|
38681
|
-
if (context.lockedFile && (typeof input.path !== "string" || await
|
|
38743
|
+
if (context.lockedFile && (typeof input.path !== "string" || await realpath6(resolve10(folder, input.path)) !== context.lockedFile))
|
|
38682
38744
|
throw apiError("forbidden", "Only the selected document can be edited.");
|
|
38683
38745
|
await editDocument(folder, input);
|
|
38684
38746
|
jsonResponse(response, 200, routes.documentEdit.response.parse({ saved: true }));
|
|
@@ -38688,7 +38750,7 @@ var init_document_edit = __esm(() => {
|
|
|
38688
38750
|
|
|
38689
38751
|
// packages/api/src/server/api/create-agent-file.ts
|
|
38690
38752
|
import { writeFile as writeFile5 } from "node:fs/promises";
|
|
38691
|
-
import { resolve as
|
|
38753
|
+
import { resolve as resolve11 } from "node:path";
|
|
38692
38754
|
var createAgentFileRoute;
|
|
38693
38755
|
var init_create_agent_file = __esm(() => {
|
|
38694
38756
|
init_endpoint();
|
|
@@ -38702,7 +38764,7 @@ var init_create_agent_file = __esm(() => {
|
|
|
38702
38764
|
} catch (error) {
|
|
38703
38765
|
throw apiError("not-found", error instanceof Error ? error.message : "Folder not found");
|
|
38704
38766
|
}
|
|
38705
|
-
const target =
|
|
38767
|
+
const target = resolve11(folder, "AGENTS.md");
|
|
38706
38768
|
try {
|
|
38707
38769
|
await writeFile5(target, "", { flag: "wx" });
|
|
38708
38770
|
} catch (error) {
|
|
@@ -38768,8 +38830,8 @@ var init_folder_favicon = __esm(() => {
|
|
|
38768
38830
|
|
|
38769
38831
|
// packages/api/src/server/folder-icons.ts
|
|
38770
38832
|
import { createHash as createHash4 } from "node:crypto";
|
|
38771
|
-
import { readFile as readFile9, stat as
|
|
38772
|
-
import { extname as
|
|
38833
|
+
import { readFile as readFile9, stat as stat7 } from "node:fs/promises";
|
|
38834
|
+
import { extname as extname5 } from "node:path";
|
|
38773
38835
|
import { discoverFolderIcon } from "@raggle-ai/local";
|
|
38774
38836
|
function assetKey(value) {
|
|
38775
38837
|
return createHash4("sha256").update(value).digest("hex");
|
|
@@ -38786,8 +38848,8 @@ function iconUrl(folder, hash, mediaType) {
|
|
|
38786
38848
|
}
|
|
38787
38849
|
async function folderIcon(folder, assets, assetFiles, fallback) {
|
|
38788
38850
|
const icon = discoverFolderIcon(folder);
|
|
38789
|
-
const mediaType = icon ? iconTypes.get(
|
|
38790
|
-
const details = icon && mediaType ? await
|
|
38851
|
+
const mediaType = icon ? iconTypes.get(extname5(icon).toLowerCase()) : null;
|
|
38852
|
+
const details = icon && mediaType ? await stat7(icon).catch(() => {
|
|
38791
38853
|
return;
|
|
38792
38854
|
}) : undefined;
|
|
38793
38855
|
if (!icon || !mediaType || !details?.size || details.size > maxIconBytes2) {
|
|
@@ -38809,10 +38871,10 @@ async function searchIconDataUrl(icon) {
|
|
|
38809
38871
|
return;
|
|
38810
38872
|
if (icon.startsWith("data:"))
|
|
38811
38873
|
return icon;
|
|
38812
|
-
const mediaType = searchIconTypes.get(
|
|
38874
|
+
const mediaType = searchIconTypes.get(extname5(icon).toLowerCase());
|
|
38813
38875
|
if (!mediaType)
|
|
38814
38876
|
return;
|
|
38815
|
-
const details = await
|
|
38877
|
+
const details = await stat7(icon).catch(() => {
|
|
38816
38878
|
return;
|
|
38817
38879
|
});
|
|
38818
38880
|
if (!details?.size || details.size > maxSearchIconBytes)
|
|
@@ -38886,18 +38948,18 @@ var init_folder_icons = __esm(() => {
|
|
|
38886
38948
|
|
|
38887
38949
|
// packages/knl/src/folder-guard.ts
|
|
38888
38950
|
import { existsSync as existsSync4, realpathSync as realpathSync2 } from "node:fs";
|
|
38889
|
-
import { realpath as
|
|
38890
|
-
import { dirname as dirname9, resolve as
|
|
38951
|
+
import { realpath as realpath7 } from "node:fs/promises";
|
|
38952
|
+
import { dirname as dirname9, resolve as resolve12, sep as sep7 } from "node:path";
|
|
38891
38953
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
38892
38954
|
async function knlRealRoot(owner) {
|
|
38893
|
-
const expected =
|
|
38894
|
-
const real = await
|
|
38955
|
+
const expected = resolve12(await realpath7(owner), "knl");
|
|
38956
|
+
const real = await realpath7(resolve12(owner, "knl"));
|
|
38895
38957
|
if (real !== expected)
|
|
38896
38958
|
throw new Error("knl/ must be a folder, not a link to another place.");
|
|
38897
38959
|
return real;
|
|
38898
38960
|
}
|
|
38899
38961
|
async function knlReadRoots(owner) {
|
|
38900
|
-
const packages = await Promise.all(knlHostPackageFolders.map((folder) =>
|
|
38962
|
+
const packages = await Promise.all(knlHostPackageFolders.map((folder) => realpath7(folder).catch(() => {
|
|
38901
38963
|
return;
|
|
38902
38964
|
})));
|
|
38903
38965
|
return [
|
|
@@ -38910,9 +38972,9 @@ function isKnlReadable(file, roots) {
|
|
|
38910
38972
|
try {
|
|
38911
38973
|
real = realpathSync2(file);
|
|
38912
38974
|
} catch {
|
|
38913
|
-
real =
|
|
38975
|
+
real = resolve12(file);
|
|
38914
38976
|
}
|
|
38915
|
-
return roots.some((root) => real === root || real.startsWith(`${root}${
|
|
38977
|
+
return roots.some((root) => real === root || real.startsWith(`${root}${sep7}`));
|
|
38916
38978
|
}
|
|
38917
38979
|
function knlReadError(file) {
|
|
38918
38980
|
return `KNL pages can only use files in knl/ and installed packages: ${file}`;
|
|
@@ -38928,7 +38990,7 @@ var init_folder_guard = __esm(() => {
|
|
|
38928
38990
|
const folders = [];
|
|
38929
38991
|
let current = knlHostResolveDir;
|
|
38930
38992
|
while (true) {
|
|
38931
|
-
const nodeModules =
|
|
38993
|
+
const nodeModules = resolve12(current, "node_modules");
|
|
38932
38994
|
if (existsSync4(nodeModules))
|
|
38933
38995
|
folders.push(nodeModules);
|
|
38934
38996
|
const parent = dirname9(current);
|
|
@@ -38942,7 +39004,7 @@ var init_folder_guard = __esm(() => {
|
|
|
38942
39004
|
// packages/knl/src/tailwind.ts
|
|
38943
39005
|
import { readFile as readFile10 } from "node:fs/promises";
|
|
38944
39006
|
import { createRequire as createRequire2 } from "node:module";
|
|
38945
|
-
import { dirname as dirname10, resolve as
|
|
39007
|
+
import { dirname as dirname10, resolve as resolve13 } from "node:path";
|
|
38946
39008
|
import { compile } from "@tailwindcss/node";
|
|
38947
39009
|
import { Scanner } from "@tailwindcss/oxide";
|
|
38948
39010
|
function starterKnlStyles() {
|
|
@@ -38984,7 +39046,7 @@ async function compileKnlCss(js, stylesheet, roots) {
|
|
|
38984
39046
|
continue;
|
|
38985
39047
|
const fixed = source.pattern.split("/");
|
|
38986
39048
|
const glob = fixed.findIndex((part) => /[*?[{]/.test(part));
|
|
38987
|
-
assertKnlReadable(
|
|
39049
|
+
assertKnlReadable(resolve13(source.base, fixed.slice(0, glob < 0 ? undefined : glob).join("/")), roots);
|
|
38988
39050
|
}
|
|
38989
39051
|
const scanner = new Scanner({ sources });
|
|
38990
39052
|
const candidates = [
|
|
@@ -39000,31 +39062,31 @@ var init_tailwind = __esm(() => {
|
|
|
39000
39062
|
});
|
|
39001
39063
|
|
|
39002
39064
|
// packages/knl/src/knl.ts
|
|
39003
|
-
import { readdir as readdir5, stat as
|
|
39004
|
-
import { basename as basename6, dirname as dirname11, relative as
|
|
39065
|
+
import { readdir as readdir5, stat as stat8 } from "node:fs/promises";
|
|
39066
|
+
import { basename as basename6, dirname as dirname11, relative as relative11, resolve as resolve14, sep as sep8 } from "node:path";
|
|
39005
39067
|
import * as esbuild from "esbuild";
|
|
39006
39068
|
function sourceFor(file, knlRoot, scanRoot, owner) {
|
|
39007
39069
|
const id = toModuleId(file, knlRoot);
|
|
39008
39070
|
return {
|
|
39009
39071
|
id,
|
|
39010
39072
|
file,
|
|
39011
|
-
relative:
|
|
39073
|
+
relative: relative11(scanRoot, file).split(sep8).join("/"),
|
|
39012
39074
|
folder: dirname11(file),
|
|
39013
39075
|
owner
|
|
39014
39076
|
};
|
|
39015
39077
|
}
|
|
39016
39078
|
function toModuleId(file, knlRoot) {
|
|
39017
|
-
const relativeKnl =
|
|
39079
|
+
const relativeKnl = relative11(knlRoot, file).split(sep8).join("/");
|
|
39018
39080
|
return relativeKnl.replace(/\/?index\.(tsx|ts)$/, "") || "index";
|
|
39019
39081
|
}
|
|
39020
39082
|
async function collectKnlSources(scanRoot, owner) {
|
|
39021
|
-
const knlRoot =
|
|
39083
|
+
const knlRoot = resolve14(scanRoot, KNK_FOLDER);
|
|
39022
39084
|
const knlEntries = await readdir5(knlRoot, { withFileTypes: true }).catch(() => []);
|
|
39023
39085
|
const sources = [];
|
|
39024
39086
|
const addModule = async (folder) => {
|
|
39025
39087
|
for (const candidate of MODULE_FILES) {
|
|
39026
|
-
const file =
|
|
39027
|
-
if (await
|
|
39088
|
+
const file = resolve14(folder, candidate);
|
|
39089
|
+
if (await stat8(file).then((d) => d.isFile()).catch(() => false)) {
|
|
39028
39090
|
sources.push(sourceFor(file, knlRoot, scanRoot, owner));
|
|
39029
39091
|
return;
|
|
39030
39092
|
}
|
|
@@ -39036,7 +39098,7 @@ async function collectKnlSources(scanRoot, owner) {
|
|
|
39036
39098
|
continue;
|
|
39037
39099
|
if (entry.name.startsWith(".") || entry.name === "node_modules")
|
|
39038
39100
|
continue;
|
|
39039
|
-
await addModule(
|
|
39101
|
+
await addModule(resolve14(knlRoot, entry.name));
|
|
39040
39102
|
}
|
|
39041
39103
|
return sources.sort((left, right) => {
|
|
39042
39104
|
const rank = (left.id === "index" ? 0 : 1) - (right.id === "index" ? 0 : 1);
|
|
@@ -39055,10 +39117,10 @@ async function loadKnlSources(viewRoot, linkedFolders = []) {
|
|
|
39055
39117
|
return { sources };
|
|
39056
39118
|
}
|
|
39057
39119
|
function knlNodePaths(knlRoot) {
|
|
39058
|
-
return [
|
|
39120
|
+
return [resolve14(knlRoot, "node_modules"), ...knlHostPackageFolders];
|
|
39059
39121
|
}
|
|
39060
39122
|
async function compileKnlSource(source) {
|
|
39061
|
-
const sourceBytes = (await
|
|
39123
|
+
const sourceBytes = (await stat8(source.file)).size;
|
|
39062
39124
|
const tooLarge = (bytes, what) => ({
|
|
39063
39125
|
id: source.id,
|
|
39064
39126
|
relative: source.relative,
|
|
@@ -39074,10 +39136,10 @@ async function compileKnlSource(source) {
|
|
|
39074
39136
|
if (sourceBytes > MAX_SOURCE_BYTES)
|
|
39075
39137
|
return tooLarge(sourceBytes, "source");
|
|
39076
39138
|
const cached = compileCache.get(source.file);
|
|
39077
|
-
const unchanged = cached && (await Promise.all(cached.dependencies.map(async ({ file, mtimeMs }) => (await
|
|
39139
|
+
const unchanged = cached && (await Promise.all(cached.dependencies.map(async ({ file, mtimeMs }) => (await stat8(file).catch(() => {
|
|
39078
39140
|
return;
|
|
39079
39141
|
}))?.mtimeMs === mtimeMs))).every(Boolean);
|
|
39080
|
-
const knlRoot =
|
|
39142
|
+
const knlRoot = resolve14(source.owner, KNK_FOLDER);
|
|
39081
39143
|
let issuePath = source.relative;
|
|
39082
39144
|
try {
|
|
39083
39145
|
const nodePaths = knlNodePaths(knlRoot);
|
|
@@ -39118,12 +39180,12 @@ globalThis.__knlMount = (container, context, onError) => {
|
|
|
39118
39180
|
});
|
|
39119
39181
|
js = result.outputFiles?.[0]?.text ?? "";
|
|
39120
39182
|
const files = new Set([
|
|
39121
|
-
|
|
39122
|
-
...Object.keys(result.metafile.inputs).map((file) =>
|
|
39183
|
+
resolve14(knlRoot, "package.json"),
|
|
39184
|
+
...Object.keys(result.metafile.inputs).map((file) => resolve14(source.folder, file)).filter((file) => file !== `${source.file}.mount.ts`)
|
|
39123
39185
|
]);
|
|
39124
39186
|
const dependencies = await Promise.all([...files].map(async (file) => ({
|
|
39125
39187
|
file,
|
|
39126
|
-
mtimeMs: (await
|
|
39188
|
+
mtimeMs: (await stat8(file).catch(() => {
|
|
39127
39189
|
return;
|
|
39128
39190
|
}))?.mtimeMs
|
|
39129
39191
|
})));
|
|
@@ -39132,8 +39194,8 @@ globalThis.__knlMount = (container, context, onError) => {
|
|
|
39132
39194
|
if (compileCache.size > MAX_CACHED_MODULES)
|
|
39133
39195
|
compileCache.delete(compileCache.keys().next().value);
|
|
39134
39196
|
}
|
|
39135
|
-
const stylesheet =
|
|
39136
|
-
issuePath =
|
|
39197
|
+
const stylesheet = resolve14(knlRoot, "style.css");
|
|
39198
|
+
issuePath = relative11(source.owner, stylesheet).split(sep8).join("/");
|
|
39137
39199
|
const css = await compileKnlCss(js, stylesheet, roots);
|
|
39138
39200
|
issuePath = source.relative;
|
|
39139
39201
|
if (js.length + css.length > MAX_JS_BYTES) {
|
|
@@ -39192,7 +39254,7 @@ function knlBuildIssues(error, relativePath, source) {
|
|
|
39192
39254
|
const failures = error?.errors;
|
|
39193
39255
|
if (Array.isArray(failures) && failures.length > 0) {
|
|
39194
39256
|
const first = failures[0];
|
|
39195
|
-
const file = first?.location?.file ?
|
|
39257
|
+
const file = first?.location?.file ? relative11(source.owner, resolve14(source.folder, first.location.file)).split(sep8).join("/") : relativePath;
|
|
39196
39258
|
const location = first?.location ? `${file}:${first.location.line ?? "?"}` : relativePath;
|
|
39197
39259
|
return [
|
|
39198
39260
|
{ path: location, message: first?.text ?? "Module failed to compile." }
|
|
@@ -39241,13 +39303,13 @@ var init_manifest = __esm(() => {
|
|
|
39241
39303
|
});
|
|
39242
39304
|
|
|
39243
39305
|
// packages/knl/src/server.ts
|
|
39244
|
-
import { stat as
|
|
39306
|
+
import { stat as stat9 } from "node:fs/promises";
|
|
39245
39307
|
import { join as join5 } from "node:path";
|
|
39246
39308
|
function createKnlPlugin() {
|
|
39247
39309
|
return {
|
|
39248
39310
|
...knlManifest,
|
|
39249
39311
|
async detect(context) {
|
|
39250
|
-
const hasKnlFolder = await
|
|
39312
|
+
const hasKnlFolder = await stat9(join5(context.folder, KNK_FOLDER)).then((entry) => entry.isDirectory()).catch(() => false);
|
|
39251
39313
|
if (!hasKnlFolder)
|
|
39252
39314
|
return { status: "unavailable" };
|
|
39253
39315
|
const { sources } = await loadKnlSources(context.folder, context.linkedFolders ?? []);
|
|
@@ -39353,14 +39415,14 @@ var init_manifest2 = __esm(() => {
|
|
|
39353
39415
|
});
|
|
39354
39416
|
|
|
39355
39417
|
// packages/notes/src/server.ts
|
|
39356
|
-
import { readdir as readdir6, realpath as
|
|
39418
|
+
import { readdir as readdir6, realpath as realpath8, stat as stat10 } from "node:fs/promises";
|
|
39357
39419
|
import {
|
|
39358
39420
|
basename as basename7,
|
|
39359
|
-
extname as
|
|
39360
|
-
isAbsolute as
|
|
39361
|
-
relative as
|
|
39362
|
-
resolve as
|
|
39363
|
-
sep as
|
|
39421
|
+
extname as extname6,
|
|
39422
|
+
isAbsolute as isAbsolute7,
|
|
39423
|
+
relative as relative12,
|
|
39424
|
+
resolve as resolve15,
|
|
39425
|
+
sep as sep9
|
|
39364
39426
|
} from "node:path";
|
|
39365
39427
|
async function listMarkdownFiles(folder) {
|
|
39366
39428
|
const files = [];
|
|
@@ -39369,21 +39431,21 @@ async function listMarkdownFiles(folder) {
|
|
|
39369
39431
|
for (const entry of entries) {
|
|
39370
39432
|
if (entry.name === "node_modules" || entry.name.startsWith("."))
|
|
39371
39433
|
continue;
|
|
39372
|
-
const path =
|
|
39434
|
+
const path = resolve15(current, entry.name);
|
|
39373
39435
|
if (entry.isDirectory()) {
|
|
39374
39436
|
await visit(path);
|
|
39375
39437
|
continue;
|
|
39376
39438
|
}
|
|
39377
|
-
if (!entry.isFile() || !
|
|
39439
|
+
if (!entry.isFile() || !markdownExtensions3.has(extname6(entry.name))) {
|
|
39378
39440
|
continue;
|
|
39379
39441
|
}
|
|
39380
|
-
const details = await
|
|
39442
|
+
const details = await stat10(path).catch(() => {
|
|
39381
39443
|
return;
|
|
39382
39444
|
});
|
|
39383
39445
|
files.push({
|
|
39384
39446
|
activityAt: details?.mtimeMs ?? 0,
|
|
39385
|
-
name: basename7(entry.name,
|
|
39386
|
-
relativePath:
|
|
39447
|
+
name: basename7(entry.name, extname6(entry.name)),
|
|
39448
|
+
relativePath: relative12(folder, path).split(sep9).join("/")
|
|
39387
39449
|
});
|
|
39388
39450
|
}
|
|
39389
39451
|
};
|
|
@@ -39391,8 +39453,8 @@ async function listMarkdownFiles(folder) {
|
|
|
39391
39453
|
return files.sort((left, right) => right.activityAt - left.activityAt);
|
|
39392
39454
|
}
|
|
39393
39455
|
function inside5(path, root) {
|
|
39394
|
-
const local =
|
|
39395
|
-
return local === "" || !local.startsWith("..") && !
|
|
39456
|
+
const local = relative12(root, path);
|
|
39457
|
+
return local === "" || !local.startsWith("..") && !isAbsolute7(local);
|
|
39396
39458
|
}
|
|
39397
39459
|
async function withoutManaged(groups, managedRoots) {
|
|
39398
39460
|
if (!managedRoots.length)
|
|
@@ -39403,7 +39465,7 @@ async function withoutManaged(groups, managedRoots) {
|
|
|
39403
39465
|
return { ...group, files: [] };
|
|
39404
39466
|
}
|
|
39405
39467
|
const files = await Promise.all(group.files.map(async (file) => {
|
|
39406
|
-
const real = await canonical(
|
|
39468
|
+
const real = await canonical(resolve15(group.folder, file.relativePath));
|
|
39407
39469
|
return roots.some((root) => inside5(real, root)) ? undefined : file;
|
|
39408
39470
|
}));
|
|
39409
39471
|
return { ...group, files: files.filter((file) => file !== undefined) };
|
|
@@ -39453,7 +39515,7 @@ async function notesLlmSections({
|
|
|
39453
39515
|
continue;
|
|
39454
39516
|
seen.add(identity);
|
|
39455
39517
|
const files = await listMarkdownFiles(source);
|
|
39456
|
-
const paths = files.map((file) =>
|
|
39518
|
+
const paths = files.map((file) => resolve15(source, file.relativePath));
|
|
39457
39519
|
groups.push({ folder: source, paths });
|
|
39458
39520
|
files.forEach((file, index) => notes.push({ activityAt: file.activityAt, path: paths[index] }));
|
|
39459
39521
|
}
|
|
@@ -39497,17 +39559,17 @@ function createNotesPlugin() {
|
|
|
39497
39559
|
llm: notesLlmSections
|
|
39498
39560
|
};
|
|
39499
39561
|
}
|
|
39500
|
-
var
|
|
39562
|
+
var markdownExtensions3, llmNoteLimit = 20, canonical = (path) => realpath8(path).catch(() => path);
|
|
39501
39563
|
var init_server4 = __esm(() => {
|
|
39502
39564
|
init_manifest2();
|
|
39503
|
-
|
|
39565
|
+
markdownExtensions3 = new Set([".md", ".markdown"]);
|
|
39504
39566
|
});
|
|
39505
39567
|
|
|
39506
39568
|
// packages/api/src/server/plugins.ts
|
|
39507
39569
|
import { pathToFileURL } from "node:url";
|
|
39508
39570
|
import { existsSync as existsSync5 } from "node:fs";
|
|
39509
|
-
import { mkdir as mkdir4, readFile as readFile11, stat as
|
|
39510
|
-
import { dirname as dirname12, resolve as
|
|
39571
|
+
import { mkdir as mkdir4, readFile as readFile11, stat as stat11, writeFile as writeFile6 } from "node:fs/promises";
|
|
39572
|
+
import { dirname as dirname12, resolve as resolve16, sep as sep10 } from "node:path";
|
|
39511
39573
|
function configuredFolderServerRegistry(registry, resolvedConfig) {
|
|
39512
39574
|
const disabled = new Set(resolvedConfig.plugins.disable);
|
|
39513
39575
|
const orderedIds = resolvedConfig.plugins.order.filter((id) => registry.has(id) && !disabled.has(id));
|
|
@@ -39532,8 +39594,8 @@ function parsePluginRegistryConfig(content) {
|
|
|
39532
39594
|
}
|
|
39533
39595
|
async function nearestKennelConfig(folder) {
|
|
39534
39596
|
for (let current = folder;; current = dirname12(current)) {
|
|
39535
|
-
const candidate =
|
|
39536
|
-
const details = await
|
|
39597
|
+
const candidate = resolve16(current, "kennel.json");
|
|
39598
|
+
const details = await stat11(candidate).catch(() => {
|
|
39537
39599
|
return;
|
|
39538
39600
|
});
|
|
39539
39601
|
if (details?.isFile())
|
|
@@ -39595,7 +39657,7 @@ async function folderServerRegistryAsync() {
|
|
|
39595
39657
|
...server,
|
|
39596
39658
|
async detect(context) {
|
|
39597
39659
|
const detection = await server.detect(context);
|
|
39598
|
-
if (detection.status === "unavailable" && existsSync5(
|
|
39660
|
+
if (detection.status === "unavailable" && existsSync5(resolve16(context.folder, entry.trigger))) {
|
|
39599
39661
|
return { status: "available" };
|
|
39600
39662
|
}
|
|
39601
39663
|
return detection;
|
|
@@ -39864,27 +39926,27 @@ var init_project_discovery = __esm(() => {
|
|
|
39864
39926
|
// packages/api/src/server/folder-metadata-plugin.ts
|
|
39865
39927
|
import { createHash as createHash5 } from "node:crypto";
|
|
39866
39928
|
import { realpathSync as realpathSync3 } from "node:fs";
|
|
39867
|
-
import { readdir as readdir7, readFile as readFile12, realpath as
|
|
39929
|
+
import { readdir as readdir7, readFile as readFile12, realpath as realpath9, stat as stat12 } from "node:fs/promises";
|
|
39868
39930
|
import { homedir as homedir4 } from "node:os";
|
|
39869
39931
|
import {
|
|
39870
39932
|
basename as basename8,
|
|
39871
39933
|
dirname as dirname14,
|
|
39872
|
-
extname as
|
|
39873
|
-
isAbsolute as
|
|
39874
|
-
relative as
|
|
39875
|
-
resolve as
|
|
39876
|
-
sep as
|
|
39934
|
+
extname as extname7,
|
|
39935
|
+
isAbsolute as isAbsolute8,
|
|
39936
|
+
relative as relative14,
|
|
39937
|
+
resolve as resolve17,
|
|
39938
|
+
sep as sep11
|
|
39877
39939
|
} from "node:path";
|
|
39878
39940
|
import { execFile as execFile6 } from "node:child_process";
|
|
39879
39941
|
import local from "@raggle-ai/local";
|
|
39880
39942
|
function metadataFile(path, root) {
|
|
39881
|
-
const candidate =
|
|
39882
|
-
if (!candidate || candidate.startsWith("..") ||
|
|
39943
|
+
const candidate = relative14(root, path);
|
|
39944
|
+
if (!candidate || candidate.startsWith("..") || isAbsolute8(candidate))
|
|
39883
39945
|
return false;
|
|
39884
|
-
const parts = candidate.split(
|
|
39946
|
+
const parts = candidate.split(sep11);
|
|
39885
39947
|
if (parts.some((part) => part === "node_modules"))
|
|
39886
39948
|
return false;
|
|
39887
|
-
return metadataExtensions.has(
|
|
39949
|
+
return metadataExtensions.has(extname7(candidate).toLowerCase());
|
|
39888
39950
|
}
|
|
39889
39951
|
async function configuredAiInputModule(folder) {
|
|
39890
39952
|
const config = folderWorkspace(folder).config;
|
|
@@ -39892,11 +39954,11 @@ async function configuredAiInputModule(folder) {
|
|
|
39892
39954
|
return typeof module === "string" && module.trim() ? module.trim() : null;
|
|
39893
39955
|
}
|
|
39894
39956
|
function folderPath(value, root, lockedRoot) {
|
|
39895
|
-
const folder = realpathSync3(
|
|
39957
|
+
const folder = realpathSync3(resolve17(value ?? root));
|
|
39896
39958
|
if (!lockedRoot)
|
|
39897
39959
|
return folder;
|
|
39898
|
-
const path =
|
|
39899
|
-
if (!path || !path.startsWith("..") && !
|
|
39960
|
+
const path = relative14(lockedRoot, folder);
|
|
39961
|
+
if (!path || !path.startsWith("..") && !isAbsolute8(path))
|
|
39900
39962
|
return folder;
|
|
39901
39963
|
throw new Error(`Folder is outside the viewer root: ${folder}`);
|
|
39902
39964
|
}
|
|
@@ -39965,9 +40027,9 @@ function isMachineRoot(folder) {
|
|
|
39965
40027
|
async function shallowMetadata(folder) {
|
|
39966
40028
|
const entries = await readdir7(folder, { withFileTypes: true });
|
|
39967
40029
|
const visible = entries.filter((entry) => !entry.name.startsWith(".") && entry.name !== "node_modules");
|
|
39968
|
-
const files = await Promise.all(visible.filter((entry) => entry.isFile() && [".markdown", ".md"].includes(
|
|
39969
|
-
const path =
|
|
39970
|
-
const details = await
|
|
40030
|
+
const files = await Promise.all(visible.filter((entry) => entry.isFile() && [".markdown", ".md"].includes(extname7(entry.name).toLowerCase())).map(async (entry) => {
|
|
40031
|
+
const path = resolve17(folder, entry.name);
|
|
40032
|
+
const details = await stat12(path);
|
|
39971
40033
|
const content = await readFile12(path, "utf8").catch(() => "");
|
|
39972
40034
|
const title = markdownMetadata(content).title;
|
|
39973
40035
|
return {
|
|
@@ -39981,10 +40043,10 @@ async function shallowMetadata(folder) {
|
|
|
39981
40043
|
};
|
|
39982
40044
|
}));
|
|
39983
40045
|
const projects = visible.filter((entry) => entry.isDirectory()).map((entry) => ({
|
|
39984
|
-
id: createHash5("sha1").update(
|
|
40046
|
+
id: createHash5("sha1").update(resolve17(folder, entry.name)).digest("hex"),
|
|
39985
40047
|
name: entry.name,
|
|
39986
40048
|
relativePath: entry.name,
|
|
39987
|
-
worktree:
|
|
40049
|
+
worktree: resolve17(folder, entry.name)
|
|
39988
40050
|
})).sort((left, right) => left.name.localeCompare(right.name));
|
|
39989
40051
|
return {
|
|
39990
40052
|
changes: { items: [] },
|
|
@@ -40011,7 +40073,7 @@ async function loadFolderData(folder) {
|
|
|
40011
40073
|
id: project.id,
|
|
40012
40074
|
worktree: project.worktree,
|
|
40013
40075
|
name: project.name ?? basename8(project.worktree),
|
|
40014
|
-
relativePath:
|
|
40076
|
+
relativePath: relative14(folder, project.worktree)
|
|
40015
40077
|
}))
|
|
40016
40078
|
}
|
|
40017
40079
|
};
|
|
@@ -40019,10 +40081,10 @@ async function loadFolderData(folder) {
|
|
|
40019
40081
|
async function notesFiles(folder, files, origin) {
|
|
40020
40082
|
return {
|
|
40021
40083
|
items: await Promise.all(files.map(async (file) => {
|
|
40022
|
-
const path = file.path ?? (file.relativePath ?
|
|
40084
|
+
const path = file.path ?? (file.relativePath ? resolve17(folder, file.relativePath) : undefined);
|
|
40023
40085
|
if (!path)
|
|
40024
40086
|
return origin ? { ...file, folder: origin } : file;
|
|
40025
|
-
const content = [".markdown", ".md"].includes(
|
|
40087
|
+
const content = [".markdown", ".md"].includes(extname7(path).toLowerCase()) ? await readFile12(path, "utf8").catch(() => "") : "";
|
|
40026
40088
|
const title = content ? markdownMetadata(content).title : undefined;
|
|
40027
40089
|
return {
|
|
40028
40090
|
...file,
|
|
@@ -40047,8 +40109,8 @@ async function managedNotesFiles(directory) {
|
|
|
40047
40109
|
}));
|
|
40048
40110
|
}
|
|
40049
40111
|
function insideFolder(path, root) {
|
|
40050
|
-
const local =
|
|
40051
|
-
return local === "" || !local.startsWith("..") && !
|
|
40112
|
+
const local = relative14(root, path);
|
|
40113
|
+
return local === "" || !local.startsWith("..") && !isAbsolute8(local);
|
|
40052
40114
|
}
|
|
40053
40115
|
async function withoutManagedFiles(items, managedRoot) {
|
|
40054
40116
|
if (!managedRoot)
|
|
@@ -40079,16 +40141,16 @@ async function localProjectSearchCache(cache) {
|
|
|
40079
40141
|
function mediaTarget(folder, file, lockedTarget) {
|
|
40080
40142
|
if (!file)
|
|
40081
40143
|
return;
|
|
40082
|
-
const rootReal = realpathSync3(
|
|
40083
|
-
const path =
|
|
40144
|
+
const rootReal = realpathSync3(resolve17(folder));
|
|
40145
|
+
const path = resolve17(folder, file);
|
|
40084
40146
|
let pathReal;
|
|
40085
40147
|
try {
|
|
40086
40148
|
pathReal = realpathSync3(path);
|
|
40087
40149
|
} catch {
|
|
40088
40150
|
return;
|
|
40089
40151
|
}
|
|
40090
|
-
const rel =
|
|
40091
|
-
if (rel.startsWith("..") ||
|
|
40152
|
+
const rel = relative14(rootReal, pathReal);
|
|
40153
|
+
if (rel.startsWith("..") || isAbsolute8(rel))
|
|
40092
40154
|
return;
|
|
40093
40155
|
if (lockedTarget && pathReal !== lockedTarget)
|
|
40094
40156
|
return;
|
|
@@ -40127,16 +40189,16 @@ function documentError(response) {
|
|
|
40127
40189
|
function documentTarget(folder, file, lockedTarget) {
|
|
40128
40190
|
if (!file)
|
|
40129
40191
|
return;
|
|
40130
|
-
const rootReal = realpathSync3(
|
|
40131
|
-
const path =
|
|
40192
|
+
const rootReal = realpathSync3(resolve17(folder));
|
|
40193
|
+
const path = resolve17(folder, file);
|
|
40132
40194
|
let pathReal;
|
|
40133
40195
|
try {
|
|
40134
40196
|
pathReal = realpathSync3(path);
|
|
40135
40197
|
} catch {
|
|
40136
40198
|
return;
|
|
40137
40199
|
}
|
|
40138
|
-
const rel =
|
|
40139
|
-
if (rel.startsWith("..") ||
|
|
40200
|
+
const rel = relative14(rootReal, pathReal);
|
|
40201
|
+
if (rel.startsWith("..") || isAbsolute8(rel))
|
|
40140
40202
|
return;
|
|
40141
40203
|
if (lockedTarget && pathReal !== lockedTarget)
|
|
40142
40204
|
return;
|
|
@@ -40274,7 +40336,7 @@ function createFolderApi({
|
|
|
40274
40336
|
if (!folder)
|
|
40275
40337
|
return;
|
|
40276
40338
|
server.emit({
|
|
40277
|
-
data: { path:
|
|
40339
|
+
data: { path: relative14(folder, path) },
|
|
40278
40340
|
event: "kennel:metadata-changed",
|
|
40279
40341
|
type: "custom"
|
|
40280
40342
|
});
|
|
@@ -40429,12 +40491,12 @@ function createFolderApi({
|
|
|
40429
40491
|
}
|
|
40430
40492
|
if (url.pathname === "/api/documents") {
|
|
40431
40493
|
const folder = folderPath(url.searchParams.get("path"), root, lockedRoot);
|
|
40432
|
-
const target = lockedTarget ? documentTarget(folder,
|
|
40494
|
+
const target = lockedTarget ? documentTarget(folder, relative14(folder, lockedTarget), lockedTarget) : undefined;
|
|
40433
40495
|
const dataset = lockedTarget ? {
|
|
40434
40496
|
root: folder,
|
|
40435
40497
|
documents: target ? [
|
|
40436
40498
|
{
|
|
40437
|
-
path:
|
|
40499
|
+
path: relative14(folder, target.path),
|
|
40438
40500
|
kind: target.kind,
|
|
40439
40501
|
content: previewTextKind(target.kind) ? await readFile12(target.path, "utf8") : ""
|
|
40440
40502
|
}
|
|
@@ -40452,7 +40514,7 @@ function createFolderApi({
|
|
|
40452
40514
|
documentError(response);
|
|
40453
40515
|
return;
|
|
40454
40516
|
}
|
|
40455
|
-
const details = await
|
|
40517
|
+
const details = await stat12(target.path);
|
|
40456
40518
|
if (!details.isFile()) {
|
|
40457
40519
|
documentError(response);
|
|
40458
40520
|
return;
|
|
@@ -40468,12 +40530,12 @@ function createFolderApi({
|
|
|
40468
40530
|
sendContract(response, url, {
|
|
40469
40531
|
content,
|
|
40470
40532
|
kind: target.kind,
|
|
40471
|
-
path:
|
|
40533
|
+
path: relative14(target.root, target.path),
|
|
40472
40534
|
root: folder,
|
|
40473
40535
|
...previewTextKind(target.kind) ? {} : {
|
|
40474
40536
|
rawUrl: `/api/raw?${new URLSearchParams({
|
|
40475
40537
|
path: folder,
|
|
40476
|
-
file:
|
|
40538
|
+
file: relative14(target.root, target.path)
|
|
40477
40539
|
})}`
|
|
40478
40540
|
}
|
|
40479
40541
|
}, {
|
|
@@ -40493,7 +40555,7 @@ function createFolderApi({
|
|
|
40493
40555
|
documentError(response);
|
|
40494
40556
|
return;
|
|
40495
40557
|
}
|
|
40496
|
-
const details = await
|
|
40558
|
+
const details = await stat12(target.path);
|
|
40497
40559
|
if (!details.isFile()) {
|
|
40498
40560
|
documentError(response);
|
|
40499
40561
|
return;
|
|
@@ -40531,7 +40593,7 @@ function createFolderApi({
|
|
|
40531
40593
|
documentError(response);
|
|
40532
40594
|
return;
|
|
40533
40595
|
}
|
|
40534
|
-
const details = await
|
|
40596
|
+
const details = await stat12(target.path);
|
|
40535
40597
|
if (!details.isFile()) {
|
|
40536
40598
|
documentError(response);
|
|
40537
40599
|
return;
|
|
@@ -40652,6 +40714,19 @@ function createFolderApi({
|
|
|
40652
40714
|
}))
|
|
40653
40715
|
return;
|
|
40654
40716
|
}
|
|
40717
|
+
if (url.pathname === "/api/delete-note") {
|
|
40718
|
+
if (remote) {
|
|
40719
|
+
response.writeHead(403, {
|
|
40720
|
+
"Content-Type": "text/plain; charset=utf-8"
|
|
40721
|
+
});
|
|
40722
|
+
response.end("Host actions are disabled for remote access");
|
|
40723
|
+
return;
|
|
40724
|
+
}
|
|
40725
|
+
await runApiRoute(request, response, url, deleteNoteRoute, {
|
|
40726
|
+
authorize: (folder) => folderPath(folder, root, lockedRoot)
|
|
40727
|
+
});
|
|
40728
|
+
return;
|
|
40729
|
+
}
|
|
40655
40730
|
if (url.pathname === "/api/create-agent-file") {
|
|
40656
40731
|
if (remote) {
|
|
40657
40732
|
response.writeHead(403, {
|
|
@@ -40706,7 +40781,7 @@ function createFolderApi({
|
|
|
40706
40781
|
workspace.breadcrumbs = await workspaceBreadcrumbIcons(workspace.breadcrumbs ?? [], assetFiles);
|
|
40707
40782
|
const files = [
|
|
40708
40783
|
workspace.configPath,
|
|
40709
|
-
|
|
40784
|
+
resolve17(workspace.root, "raggle.json")
|
|
40710
40785
|
].filter((path) => Boolean(path));
|
|
40711
40786
|
for (const path of files)
|
|
40712
40787
|
contexts.add(path);
|
|
@@ -40847,7 +40922,7 @@ function createFolderApi({
|
|
|
40847
40922
|
}
|
|
40848
40923
|
};
|
|
40849
40924
|
}
|
|
40850
|
-
var applyProjectFavorites, buildProjectCatalog, buildProjectSearchIndex, catalogProjectToLocalProject, discoverProjectIcon, discoverProjectsUnderFolder, listLocalMarkdownFiles, projectRepositoryAccessory, projectSubtitle, projectTitle, readRaggleUserSettings, gitRemoteUrl, githubRepositoryPath, repositoryDisplayName, searchProjectIndex, sortProjectList, projectSearchCacheMs = 5000, metadataExtensions, loopbackServerHosts, canonicalPath = (path) =>
|
|
40925
|
+
var applyProjectFavorites, buildProjectCatalog, buildProjectSearchIndex, catalogProjectToLocalProject, discoverProjectIcon, discoverProjectsUnderFolder, listLocalMarkdownFiles, projectRepositoryAccessory, projectSubtitle, projectTitle, readRaggleUserSettings, gitRemoteUrl, githubRepositoryPath, repositoryDisplayName, searchProjectIndex, sortProjectList, projectSearchCacheMs = 5000, metadataExtensions, loopbackServerHosts, canonicalPath = (path) => realpath9(path).catch(() => path);
|
|
40851
40926
|
var init_folder_metadata_plugin = __esm(() => {
|
|
40852
40927
|
init_contracts();
|
|
40853
40928
|
init_markdown();
|
|
@@ -40859,6 +40934,7 @@ var init_folder_metadata_plugin = __esm(() => {
|
|
|
40859
40934
|
init_server2();
|
|
40860
40935
|
init_store();
|
|
40861
40936
|
init_entity_folder();
|
|
40937
|
+
init_delete_note();
|
|
40862
40938
|
init_document_edit();
|
|
40863
40939
|
init_create_agent_file();
|
|
40864
40940
|
init_open_path();
|
|
@@ -40911,36 +40987,36 @@ var init_folder_metadata_plugin = __esm(() => {
|
|
|
40911
40987
|
import {
|
|
40912
40988
|
createServer
|
|
40913
40989
|
} from "node:http";
|
|
40914
|
-
import { readFile as readFile13, realpath as
|
|
40915
|
-
import { extname as
|
|
40990
|
+
import { readFile as readFile13, realpath as realpath10, stat as stat13 } from "node:fs/promises";
|
|
40991
|
+
import { extname as extname8, isAbsolute as isAbsolute9, relative as relative15, resolve as resolve18 } from "node:path";
|
|
40916
40992
|
async function sendFile(request, response, directory, pathname, fallback) {
|
|
40917
|
-
const root = await
|
|
40993
|
+
const root = await realpath10(directory);
|
|
40918
40994
|
const inside = (path) => {
|
|
40919
|
-
const local =
|
|
40920
|
-
return local !== ".." && !local.startsWith("../") && !
|
|
40995
|
+
const local = relative15(root, path);
|
|
40996
|
+
return local !== ".." && !local.startsWith("../") && !isAbsolute9(local);
|
|
40921
40997
|
};
|
|
40922
|
-
let target =
|
|
40998
|
+
let target = resolve18(root, `.${decodeURIComponent(pathname)}`);
|
|
40923
40999
|
if (!inside(target)) {
|
|
40924
41000
|
response.writeHead(403);
|
|
40925
41001
|
response.end();
|
|
40926
41002
|
return;
|
|
40927
41003
|
}
|
|
40928
|
-
if (!(await
|
|
41004
|
+
if (!(await stat13(target).catch(() => null))?.isFile()) {
|
|
40929
41005
|
if (!fallback) {
|
|
40930
41006
|
response.writeHead(404);
|
|
40931
41007
|
response.end();
|
|
40932
41008
|
return;
|
|
40933
41009
|
}
|
|
40934
|
-
target =
|
|
41010
|
+
target = resolve18(root, fallback);
|
|
40935
41011
|
}
|
|
40936
|
-
target = await
|
|
41012
|
+
target = await realpath10(target);
|
|
40937
41013
|
if (!inside(target)) {
|
|
40938
41014
|
response.writeHead(403);
|
|
40939
41015
|
response.end();
|
|
40940
41016
|
return;
|
|
40941
41017
|
}
|
|
40942
41018
|
response.writeHead(200, {
|
|
40943
|
-
"Content-Type": contentTypes[
|
|
41019
|
+
"Content-Type": contentTypes[extname8(target)] ?? "application/octet-stream",
|
|
40944
41020
|
"X-Content-Type-Options": "nosniff"
|
|
40945
41021
|
});
|
|
40946
41022
|
response.end(request.method === "HEAD" ? undefined : await readFile13(target));
|
|
@@ -41116,7 +41192,7 @@ var init_server5 = __esm(() => {
|
|
|
41116
41192
|
});
|
|
41117
41193
|
|
|
41118
41194
|
// packages/preview/src/share.ts
|
|
41119
|
-
import { dirname as dirname16, resolve as
|
|
41195
|
+
import { dirname as dirname16, resolve as resolve20, join as join7 } from "node:path";
|
|
41120
41196
|
import { homedir as homedir5 } from "node:os";
|
|
41121
41197
|
import { readFileSync as readFileSync2 } from "node:fs";
|
|
41122
41198
|
import { existsSync as existsSync8, realpathSync as realpathSync5 } from "node:fs";
|
|
@@ -41129,7 +41205,7 @@ init_runtime();
|
|
|
41129
41205
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
41130
41206
|
import { existsSync as existsSync7, realpathSync as realpathSync4, statSync as statSync3 } from "node:fs";
|
|
41131
41207
|
import { createServer as createServer2 } from "node:net";
|
|
41132
|
-
import { dirname as dirname15, isAbsolute as
|
|
41208
|
+
import { dirname as dirname15, isAbsolute as isAbsolute10, relative as relative16, resolve as resolve19 } from "node:path";
|
|
41133
41209
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
41134
41210
|
var loopbackHosts = new Set([
|
|
41135
41211
|
"127.0.0.1",
|
|
@@ -41215,7 +41291,7 @@ function splitViewerArgs(input) {
|
|
|
41215
41291
|
}
|
|
41216
41292
|
if (arg.startsWith("-"))
|
|
41217
41293
|
throw new Error(`Unknown viewer option: ${arg}`);
|
|
41218
|
-
const candidate =
|
|
41294
|
+
const candidate = resolve19(arg);
|
|
41219
41295
|
const isDirectory = existsSync7(candidate) && statSync3(candidate).isDirectory();
|
|
41220
41296
|
if (isDirectory) {
|
|
41221
41297
|
if (hasRoot)
|
|
@@ -41263,7 +41339,7 @@ function popUrl(host, port, options) {
|
|
|
41263
41339
|
const scheme = options.tailscale ? "https" : "http";
|
|
41264
41340
|
const authority = options.tailscale ? host : `${host}:${port}`;
|
|
41265
41341
|
return folderUrl(`${scheme}://${authority}/`, options.root, {
|
|
41266
|
-
document: options.target ?
|
|
41342
|
+
document: options.target ? relative16(options.root, options.target) : undefined,
|
|
41267
41343
|
watch: options.watch
|
|
41268
41344
|
}).href;
|
|
41269
41345
|
}
|
|
@@ -41273,8 +41349,8 @@ function viewerPortWasExplicit(input) {
|
|
|
41273
41349
|
function isSameOrDescendant(parent, child) {
|
|
41274
41350
|
const parentReal = realpathSync4(parent);
|
|
41275
41351
|
const childReal = realpathSync4(child);
|
|
41276
|
-
const childRelative =
|
|
41277
|
-
return childRelative === "" || !childRelative.startsWith("..") && !
|
|
41352
|
+
const childRelative = relative16(parentReal, childReal);
|
|
41353
|
+
return childRelative === "" || !childRelative.startsWith("..") && !isAbsolute10(childRelative);
|
|
41278
41354
|
}
|
|
41279
41355
|
async function runningViewer(url) {
|
|
41280
41356
|
try {
|
|
@@ -41335,8 +41411,8 @@ async function viewer(input) {
|
|
|
41335
41411
|
await hotViewer(options);
|
|
41336
41412
|
return;
|
|
41337
41413
|
}
|
|
41338
|
-
const web =
|
|
41339
|
-
if (!existsSync7(
|
|
41414
|
+
const web = resolve19(dirname15(fileURLToPath4(import.meta.url)), "../../web");
|
|
41415
|
+
if (!existsSync7(resolve19(web, "index.html"))) {
|
|
41340
41416
|
throw new Error(`Kennel web app not found. Run the CLI build first.`);
|
|
41341
41417
|
}
|
|
41342
41418
|
const remote = options.tailscale || !isLoopbackHost(options.host);
|
|
@@ -41551,7 +41627,7 @@ function splitShareArgs(input) {
|
|
|
41551
41627
|
if (folder && !existsSync8(folder)) {
|
|
41552
41628
|
throw new Error(`Folder not found: ${folder}`);
|
|
41553
41629
|
}
|
|
41554
|
-
options.folder = folder ?
|
|
41630
|
+
options.folder = folder ? resolve20(folder) : undefined;
|
|
41555
41631
|
return options;
|
|
41556
41632
|
}
|
|
41557
41633
|
async function runningViewerRoot(port = plainViewerPort) {
|
|
@@ -41579,8 +41655,8 @@ async function startPreviewShare(target) {
|
|
|
41579
41655
|
configuredPassword = config.linkSharing?.password === true;
|
|
41580
41656
|
} catch {}
|
|
41581
41657
|
const password = target.password ?? configuredPassword;
|
|
41582
|
-
const web =
|
|
41583
|
-
if (!existsSync8(
|
|
41658
|
+
const web = resolve20(dirname16(fileURLToPath5(import.meta.url)), "../../web");
|
|
41659
|
+
if (!existsSync8(resolve20(web, "index.html"))) {
|
|
41584
41660
|
throw new Error("Kennel web app not found. Run the CLI build first.");
|
|
41585
41661
|
}
|
|
41586
41662
|
const host = await tailscaleHostname();
|