kirograph 1.0.0 → 1.2.1
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/README.md +4 -2
- package/dist/architecture/manifest/python.js +2 -2
- package/dist/architecture/manifest/python.js.map +2 -2
- package/dist/bin/commands/help.js +3 -1
- package/dist/bin/commands/help.js.map +2 -2
- package/dist/bin/commands/memory.js +29 -9
- package/dist/bin/commands/memory.js.map +2 -2
- package/dist/bin/commands/reachability.js +7 -2
- package/dist/bin/commands/reachability.js.map +2 -2
- package/dist/bin/commands/vulns.js +16 -1
- package/dist/bin/commands/vulns.js.map +2 -2
- package/dist/bin/commands/wiki.js +59 -2
- package/dist/bin/commands/wiki.js.map +2 -2
- package/dist/bin/installer/steering.js +9 -0
- package/dist/bin/installer/steering.js.map +2 -2
- package/dist/bin/kirograph.js +1 -1
- package/dist/config.js +12 -0
- package/dist/config.js.map +2 -2
- package/dist/db/memory-schema.sql +2 -1
- package/dist/extraction/extractor.js +46 -41
- package/dist/extraction/extractor.js.map +2 -2
- package/dist/extraction/notebook.js +15 -7
- package/dist/extraction/notebook.js.map +2 -2
- package/dist/jev/client.js +99 -0
- package/dist/jev/client.js.map +7 -0
- package/dist/jev/types.js +17 -0
- package/dist/jev/types.js.map +7 -0
- package/dist/mcp/handlers/memory.js +15 -8
- package/dist/mcp/handlers/memory.js.map +2 -2
- package/dist/mcp/handlers/security.js +5 -3
- package/dist/mcp/handlers/security.js.map +2 -2
- package/dist/mcp/handlers/wiki.js +4 -2
- package/dist/mcp/handlers/wiki.js.map +2 -2
- package/dist/mcp/tools.js +3 -2
- package/dist/mcp/tools.js.map +2 -2
- package/dist/memory/database.js +17 -4
- package/dist/memory/database.js.map +2 -2
- package/dist/memory/index.js +31 -2
- package/dist/memory/index.js.map +3 -3
- package/dist/memory/relation-jev.js +59 -0
- package/dist/memory/relation-jev.js.map +7 -0
- package/dist/memory/schema.js +92 -0
- package/dist/memory/schema.js.map +7 -0
- package/dist/memory/types.js.map +1 -1
- package/dist/patterns/loader.js +2 -146
- package/dist/patterns/loader.js.map +3 -3
- package/dist/security/auth-detection-jev.js +47 -0
- package/dist/security/auth-detection-jev.js.map +7 -0
- package/dist/security/manifest/adapter.js +17 -3
- package/dist/security/manifest/adapter.js.map +3 -3
- package/dist/security/manifest/plugins/cargo.js +23 -0
- package/dist/security/manifest/plugins/cargo.js.map +2 -2
- package/dist/security/manifest/plugins/composer.js +12 -0
- package/dist/security/manifest/plugins/composer.js.map +2 -2
- package/dist/security/manifest/plugins/gradle.js +12 -0
- package/dist/security/manifest/plugins/gradle.js.map +2 -2
- package/dist/security/manifest/plugins/hex.js +12 -0
- package/dist/security/manifest/plugins/hex.js.map +2 -2
- package/dist/security/manifest/plugins/maven.js +101 -4
- package/dist/security/manifest/plugins/maven.js.map +2 -2
- package/dist/security/manifest/plugins/npm.js +117 -2
- package/dist/security/manifest/plugins/npm.js.map +2 -2
- package/dist/security/manifest/plugins/nuget.js +13 -0
- package/dist/security/manifest/plugins/nuget.js.map +2 -2
- package/dist/security/manifest/plugins/pubspec.js +12 -0
- package/dist/security/manifest/plugins/pubspec.js.map +2 -2
- package/dist/security/manifest/plugins/pyproject.js +12 -0
- package/dist/security/manifest/plugins/pyproject.js.map +2 -2
- package/dist/security/manifest/plugins/rubygems.js +12 -0
- package/dist/security/manifest/plugins/rubygems.js.map +2 -2
- package/dist/security/pipeline.js +1 -1
- package/dist/security/pipeline.js.map +2 -2
- package/dist/security/reachability.js +54 -5
- package/dist/security/reachability.js.map +3 -3
- package/dist/security/types.js.map +1 -1
- package/dist/security/vuln/client.js +45 -1
- package/dist/security/vuln/client.js.map +2 -2
- package/dist/security/vuln/osv-adapter.js +45 -1
- package/dist/security/vuln/osv-adapter.js.map +2 -2
- package/dist/shared/json-schema.js +136 -0
- package/dist/shared/json-schema.js.map +7 -0
- package/dist/shared/yaml.js +174 -0
- package/dist/shared/yaml.js.map +7 -0
- package/dist/wiki/contradiction-jev.js +49 -0
- package/dist/wiki/contradiction-jev.js.map +7 -0
- package/dist/wiki/index.js +16 -1
- package/dist/wiki/index.js.map +2 -2
- package/dist/wiki/ingest.js +2 -0
- package/dist/wiki/ingest.js.map +2 -2
- package/dist/wiki/links.js +53 -0
- package/dist/wiki/links.js.map +7 -0
- package/dist/wiki/lint.js +17 -7
- package/dist/wiki/lint.js.map +2 -2
- package/dist/wiki/rename.js +103 -0
- package/dist/wiki/rename.js.map +7 -0
- package/dist/wiki/typed-pages.js +67 -0
- package/dist/wiki/typed-pages.js.map +7 -0
- package/dist/wiki/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var rename_exports = {};
|
|
30
|
+
__export(rename_exports, {
|
|
31
|
+
renamePage: () => renamePage
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(rename_exports);
|
|
34
|
+
var fs = __toESM(require("fs"));
|
|
35
|
+
var path = __toESM(require("path"));
|
|
36
|
+
var import_ingest = require("./ingest");
|
|
37
|
+
var import_links = require("./links");
|
|
38
|
+
function escapeRegExp(s) {
|
|
39
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
40
|
+
}
|
|
41
|
+
function renamePage(wikiDir, wikiDb, fromSlug, toSlug) {
|
|
42
|
+
if (fromSlug === toSlug) {
|
|
43
|
+
throw new Error("New slug is the same as the current slug");
|
|
44
|
+
}
|
|
45
|
+
const page = wikiDb.getPage(fromSlug);
|
|
46
|
+
if (!page) {
|
|
47
|
+
throw new Error(`Wiki page "${fromSlug}" not found`);
|
|
48
|
+
}
|
|
49
|
+
if (wikiDb.getPage(toSlug)) {
|
|
50
|
+
throw new Error(`Wiki page "${toSlug}" already exists \u2014 pick a different slug or delete it first`);
|
|
51
|
+
}
|
|
52
|
+
const fromPath = path.join(wikiDir, (0, import_ingest.slugToFilePath)(fromSlug));
|
|
53
|
+
const toPath = path.join(wikiDir, (0, import_ingest.slugToFilePath)(toSlug));
|
|
54
|
+
if (!fs.existsSync(fromPath)) {
|
|
55
|
+
throw new Error(`File for "${fromSlug}" not found on disk at ${fromPath} \u2014 run \`kirograph wiki reindex\` to resync`);
|
|
56
|
+
}
|
|
57
|
+
if (fs.existsSync(toPath)) {
|
|
58
|
+
throw new Error(`Target file already exists at ${toPath}`);
|
|
59
|
+
}
|
|
60
|
+
fs.mkdirSync(path.dirname(toPath), { recursive: true });
|
|
61
|
+
fs.renameSync(fromPath, toPath);
|
|
62
|
+
removeIfEmpty(path.dirname(fromPath), wikiDir);
|
|
63
|
+
wikiDb.deletePage(fromSlug);
|
|
64
|
+
wikiDb.upsertPage({
|
|
65
|
+
slug: toSlug,
|
|
66
|
+
title: page.title,
|
|
67
|
+
content: fs.readFileSync(toPath, "utf8"),
|
|
68
|
+
filePath: path.relative(wikiDir, toPath),
|
|
69
|
+
sourceCount: page.sourceCount
|
|
70
|
+
});
|
|
71
|
+
const linkRe = new RegExp(`\\[\\[\\s*${escapeRegExp(fromSlug)}\\s*\\]\\]`, "g");
|
|
72
|
+
const linksUpdated = [];
|
|
73
|
+
for (const p of wikiDb.listPages()) {
|
|
74
|
+
if (!(0, import_links.extractLinks)(p.content).includes(fromSlug)) continue;
|
|
75
|
+
const absPath = path.join(wikiDir, (0, import_ingest.slugToFilePath)(p.slug));
|
|
76
|
+
const current = fs.readFileSync(absPath, "utf8");
|
|
77
|
+
const rewritten = current.replace(linkRe, `[[${toSlug}]]`);
|
|
78
|
+
if (rewritten === current) continue;
|
|
79
|
+
fs.writeFileSync(absPath, rewritten, "utf8");
|
|
80
|
+
wikiDb.upsertPage({
|
|
81
|
+
slug: p.slug,
|
|
82
|
+
title: p.title,
|
|
83
|
+
content: rewritten,
|
|
84
|
+
filePath: p.filePath,
|
|
85
|
+
sourceCount: 0
|
|
86
|
+
});
|
|
87
|
+
if (p.slug !== toSlug) linksUpdated.push(p.slug);
|
|
88
|
+
}
|
|
89
|
+
(0, import_ingest.updateManifest)(wikiDir, wikiDb);
|
|
90
|
+
return { from: fromSlug, to: toSlug, linksUpdated };
|
|
91
|
+
}
|
|
92
|
+
function removeIfEmpty(dir, wikiDir) {
|
|
93
|
+
if (path.resolve(dir) === path.resolve(wikiDir)) return;
|
|
94
|
+
try {
|
|
95
|
+
if (fs.readdirSync(dir).length === 0) fs.rmdirSync(dir);
|
|
96
|
+
} catch {
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
100
|
+
0 && (module.exports = {
|
|
101
|
+
renamePage
|
|
102
|
+
});
|
|
103
|
+
//# sourceMappingURL=rename.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/wiki/rename.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * KiroGraph Wiki \u2014 Rename\n *\n * Renames a page's slug: moves its file on disk and rewrites every\n * `[[oldSlug]]` reference across the wiki (including the page's own\n * content, for hub pages that link to themselves) to `[[newSlug]]`.\n * The IWE-inspired \"rename with automatic link updates\" refactor, ported\n * to the CLI rather than an LSP rename action.\n */\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport type { WikiDatabase } from './database';\nimport { slugToFilePath, updateManifest } from './ingest';\nimport { extractLinks } from './links';\n\nexport interface RenamePageResult {\n from: string;\n to: string;\n /** Other pages whose [[from]] links were rewritten to [[to]]. */\n linksUpdated: string[];\n}\n\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nexport function renamePage(\n wikiDir: string,\n wikiDb: WikiDatabase,\n fromSlug: string,\n toSlug: string,\n): RenamePageResult {\n if (fromSlug === toSlug) {\n throw new Error('New slug is the same as the current slug');\n }\n\n const page = wikiDb.getPage(fromSlug);\n if (!page) {\n throw new Error(`Wiki page \"${fromSlug}\" not found`);\n }\n if (wikiDb.getPage(toSlug)) {\n throw new Error(`Wiki page \"${toSlug}\" already exists \u2014 pick a different slug or delete it first`);\n }\n\n const fromPath = path.join(wikiDir, slugToFilePath(fromSlug));\n const toPath = path.join(wikiDir, slugToFilePath(toSlug));\n if (!fs.existsSync(fromPath)) {\n throw new Error(`File for \"${fromSlug}\" not found on disk at ${fromPath} \u2014 run \\`kirograph wiki reindex\\` to resync`);\n }\n if (fs.existsSync(toPath)) {\n throw new Error(`Target file already exists at ${toPath}`);\n }\n\n // Move the file\n fs.mkdirSync(path.dirname(toPath), { recursive: true });\n fs.renameSync(fromPath, toPath);\n removeIfEmpty(path.dirname(fromPath), wikiDir);\n\n // Reindex: drop the old slug, insert the new one under the moved path.\n wikiDb.deletePage(fromSlug);\n wikiDb.upsertPage({\n slug: toSlug,\n title: page.title,\n content: fs.readFileSync(toPath, 'utf8'),\n filePath: path.relative(wikiDir, toPath),\n sourceCount: page.sourceCount,\n });\n\n // Rewrite every [[fromSlug]] reference across the wiki \u2014 including the\n // renamed page's own content, in case it links to itself (hub pages).\n const linkRe = new RegExp(`\\\\[\\\\[\\\\s*${escapeRegExp(fromSlug)}\\\\s*\\\\]\\\\]`, 'g');\n const linksUpdated: string[] = [];\n\n for (const p of wikiDb.listPages()) {\n if (!extractLinks(p.content).includes(fromSlug)) continue;\n\n const absPath = path.join(wikiDir, slugToFilePath(p.slug));\n const current = fs.readFileSync(absPath, 'utf8');\n const rewritten = current.replace(linkRe, `[[${toSlug}]]`);\n if (rewritten === current) continue;\n\n fs.writeFileSync(absPath, rewritten, 'utf8');\n wikiDb.upsertPage({\n slug: p.slug,\n title: p.title,\n content: rewritten,\n filePath: p.filePath,\n sourceCount: 0,\n });\n if (p.slug !== toSlug) linksUpdated.push(p.slug);\n }\n\n updateManifest(wikiDir, wikiDb);\n\n return { from: fromSlug, to: toSlug, linksUpdated };\n}\n\n/** Best-effort cleanup of a now-empty directory left behind by a nested-slug move. Never removes wikiDir itself. */\nfunction removeIfEmpty(dir: string, wikiDir: string): void {\n if (path.resolve(dir) === path.resolve(wikiDir)) return;\n try {\n if (fs.readdirSync(dir).length === 0) fs.rmdirSync(dir);\n } catch {\n // Not empty, doesn't exist, or a permissions issue \u2014 leave it.\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AASA,SAAoB;AACpB,WAAsB;AAEtB,oBAA+C;AAC/C,mBAA6B;AAS7B,SAAS,aAAa,GAAmB;AACvC,SAAO,EAAE,QAAQ,uBAAuB,MAAM;AAChD;AAEO,SAAS,WACd,SACA,QACA,UACA,QACkB;AAClB,MAAI,aAAa,QAAQ;AACvB,UAAM,IAAI,MAAM,0CAA0C;AAAA,EAC5D;AAEA,QAAM,OAAO,OAAO,QAAQ,QAAQ;AACpC,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,MAAM,cAAc,QAAQ,aAAa;AAAA,EACrD;AACA,MAAI,OAAO,QAAQ,MAAM,GAAG;AAC1B,UAAM,IAAI,MAAM,cAAc,MAAM,kEAA6D;AAAA,EACnG;AAEA,QAAM,WAAW,KAAK,KAAK,aAAS,8BAAe,QAAQ,CAAC;AAC5D,QAAM,SAAS,KAAK,KAAK,aAAS,8BAAe,MAAM,CAAC;AACxD,MAAI,CAAC,GAAG,WAAW,QAAQ,GAAG;AAC5B,UAAM,IAAI,MAAM,aAAa,QAAQ,0BAA0B,QAAQ,kDAA6C;AAAA,EACtH;AACA,MAAI,GAAG,WAAW,MAAM,GAAG;AACzB,UAAM,IAAI,MAAM,iCAAiC,MAAM,EAAE;AAAA,EAC3D;AAGA,KAAG,UAAU,KAAK,QAAQ,MAAM,GAAG,EAAE,WAAW,KAAK,CAAC;AACtD,KAAG,WAAW,UAAU,MAAM;AAC9B,gBAAc,KAAK,QAAQ,QAAQ,GAAG,OAAO;AAG7C,SAAO,WAAW,QAAQ;AAC1B,SAAO,WAAW;AAAA,IAChB,MAAM;AAAA,IACN,OAAO,KAAK;AAAA,IACZ,SAAS,GAAG,aAAa,QAAQ,MAAM;AAAA,IACvC,UAAU,KAAK,SAAS,SAAS,MAAM;AAAA,IACvC,aAAa,KAAK;AAAA,EACpB,CAAC;AAID,QAAM,SAAS,IAAI,OAAO,aAAa,aAAa,QAAQ,CAAC,cAAc,GAAG;AAC9E,QAAM,eAAyB,CAAC;AAEhC,aAAW,KAAK,OAAO,UAAU,GAAG;AAClC,QAAI,KAAC,2BAAa,EAAE,OAAO,EAAE,SAAS,QAAQ,EAAG;AAEjD,UAAM,UAAU,KAAK,KAAK,aAAS,8BAAe,EAAE,IAAI,CAAC;AACzD,UAAM,UAAU,GAAG,aAAa,SAAS,MAAM;AAC/C,UAAM,YAAY,QAAQ,QAAQ,QAAQ,KAAK,MAAM,IAAI;AACzD,QAAI,cAAc,QAAS;AAE3B,OAAG,cAAc,SAAS,WAAW,MAAM;AAC3C,WAAO,WAAW;AAAA,MAChB,MAAM,EAAE;AAAA,MACR,OAAO,EAAE;AAAA,MACT,SAAS;AAAA,MACT,UAAU,EAAE;AAAA,MACZ,aAAa;AAAA,IACf,CAAC;AACD,QAAI,EAAE,SAAS,OAAQ,cAAa,KAAK,EAAE,IAAI;AAAA,EACjD;AAEA,oCAAe,SAAS,MAAM;AAE9B,SAAO,EAAE,MAAM,UAAU,IAAI,QAAQ,aAAa;AACpD;AAGA,SAAS,cAAc,KAAa,SAAuB;AACzD,MAAI,KAAK,QAAQ,GAAG,MAAM,KAAK,QAAQ,OAAO,EAAG;AACjD,MAAI;AACF,QAAI,GAAG,YAAY,GAAG,EAAE,WAAW,EAAG,IAAG,UAAU,GAAG;AAAA,EACxD,QAAQ;AAAA,EAER;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var typed_pages_exports = {};
|
|
30
|
+
__export(typed_pages_exports, {
|
|
31
|
+
parseFrontmatter: () => parseFrontmatter,
|
|
32
|
+
validatePageSchema: () => validatePageSchema
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(typed_pages_exports);
|
|
35
|
+
var path = __toESM(require("path"));
|
|
36
|
+
var import_yaml = require("../shared/yaml");
|
|
37
|
+
var import_json_schema = require("../shared/json-schema");
|
|
38
|
+
const FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
|
|
39
|
+
function parseFrontmatter(content) {
|
|
40
|
+
const match = FRONTMATTER_RE.exec(content);
|
|
41
|
+
if (!match) return { fields: {}, body: content };
|
|
42
|
+
const parsed = (0, import_yaml.parseYaml)(match[1]);
|
|
43
|
+
const { _type, ...fields } = parsed;
|
|
44
|
+
return {
|
|
45
|
+
type: typeof _type === "string" ? _type : void 0,
|
|
46
|
+
fields,
|
|
47
|
+
body: content.slice(match[0].length)
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function validatePageSchema(fields, type, wikiSchemasDir) {
|
|
51
|
+
const schemaPath = path.join(wikiSchemasDir, `${type}.schema.json`);
|
|
52
|
+
let schema;
|
|
53
|
+
try {
|
|
54
|
+
schema = (0, import_json_schema.loadJsonSchema)(schemaPath);
|
|
55
|
+
} catch (err) {
|
|
56
|
+
if (err instanceof import_json_schema.SchemaLoadError) return [err.message];
|
|
57
|
+
throw err;
|
|
58
|
+
}
|
|
59
|
+
if (!schema) return [];
|
|
60
|
+
return (0, import_json_schema.validateAgainstSchema)(fields, schema);
|
|
61
|
+
}
|
|
62
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
63
|
+
0 && (module.exports = {
|
|
64
|
+
parseFrontmatter,
|
|
65
|
+
validatePageSchema
|
|
66
|
+
});
|
|
67
|
+
//# sourceMappingURL=typed-pages.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/wiki/typed-pages.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * KiroGraph Wiki \u2014 Typed pages (opt-in, config `wikiTypedPages`)\n *\n * A wiki page may optionally start with a YAML frontmatter block declaring\n * `_type: <type>` plus arbitrary structured fields. When wikiTypedPages is\n * enabled, `wiki lint` validates those fields against a JSON Schema\n * registered at `.kirograph/wiki-schemas/<type>.schema.json`. Pages with no\n * frontmatter, or a `_type` with no schema registered, are never validated \u2014\n * this is purely additive on top of the existing prose-only wiki pages.\n */\nimport * as path from 'path';\nimport { parseYaml } from '../shared/yaml';\nimport { loadJsonSchema, validateAgainstSchema, SchemaLoadError } from '../shared/json-schema';\n\nexport interface ParsedFrontmatter {\n /** The declared `_type`, if any. */\n type?: string;\n /** All other frontmatter fields (`_type` excluded). */\n fields: Record<string, unknown>;\n /** Page content with the frontmatter block stripped. */\n body: string;\n}\n\nconst FRONTMATTER_RE = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?/;\n\n/**\n * Parse a leading `---\\n...\\n---\\n` YAML frontmatter block, if present.\n * Returns `{ fields: {}, body: content }` unchanged when there's no\n * frontmatter block at the very start of the content.\n */\nexport function parseFrontmatter(content: string): ParsedFrontmatter {\n const match = FRONTMATTER_RE.exec(content);\n if (!match) return { fields: {}, body: content };\n\n const parsed = parseYaml(match[1]);\n const { _type, ...fields } = parsed as Record<string, unknown> & { _type?: unknown };\n\n return {\n type: typeof _type === 'string' ? _type : undefined,\n fields,\n body: content.slice(match[0].length),\n };\n}\n\n/**\n * Validate `fields` against `.kirograph/wiki-schemas/<type>.schema.json`.\n * Returns one message per violation. Returns [] when no schema is\n * registered for `type` \u2014 schemas are opt-in per type, not required.\n */\nexport function validatePageSchema(fields: Record<string, unknown>, type: string, wikiSchemasDir: string): string[] {\n const schemaPath = path.join(wikiSchemasDir, `${type}.schema.json`);\n\n let schema;\n try {\n schema = loadJsonSchema(schemaPath);\n } catch (err) {\n if (err instanceof SchemaLoadError) return [err.message];\n throw err;\n }\n if (!schema) return [];\n\n return validateAgainstSchema(fields, schema);\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUA,WAAsB;AACtB,kBAA0B;AAC1B,yBAAuE;AAWvE,MAAM,iBAAiB;AAOhB,SAAS,iBAAiB,SAAoC;AACnE,QAAM,QAAQ,eAAe,KAAK,OAAO;AACzC,MAAI,CAAC,MAAO,QAAO,EAAE,QAAQ,CAAC,GAAG,MAAM,QAAQ;AAE/C,QAAM,aAAS,uBAAU,MAAM,CAAC,CAAC;AACjC,QAAM,EAAE,OAAO,GAAG,OAAO,IAAI;AAE7B,SAAO;AAAA,IACL,MAAM,OAAO,UAAU,WAAW,QAAQ;AAAA,IAC1C;AAAA,IACA,MAAM,QAAQ,MAAM,MAAM,CAAC,EAAE,MAAM;AAAA,EACrC;AACF;AAOO,SAAS,mBAAmB,QAAiC,MAAc,gBAAkC;AAClH,QAAM,aAAa,KAAK,KAAK,gBAAgB,GAAG,IAAI,cAAc;AAElE,MAAI;AACJ,MAAI;AACF,iBAAS,mCAAe,UAAU;AAAA,EACpC,SAAS,KAAK;AACZ,QAAI,eAAe,mCAAiB,QAAO,CAAC,IAAI,OAAO;AACvD,UAAM;AAAA,EACR;AACA,MAAI,CAAC,OAAQ,QAAO,CAAC;AAErB,aAAO,0CAAsB,QAAQ,MAAM;AAC7C;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/wiki/types.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/wiki/types.ts"],
|
|
4
|
-
"sourcesContent": ["// \u2500\u2500 WikiPage \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface WikiPage {\n slug: string;\n title: string;\n content: string;\n filePath: string;\n updatedAt: number;\n sourceCount: number;\n}\n\nexport interface ScoredWikiPage {\n page: WikiPage;\n score: number;\n}\n\n// \u2500\u2500 WIKI_DIFF types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport type DiffAction = 'upsert' | 'create' | 'append';\nexport type DiffMode = 'replace' | 'append';\n\nexport interface WikiDiffEntry {\n action: DiffAction;\n page: string; // slug\n title?: string; // required for action=create\n section?: string; // target section heading (e.g. \"Decisions\")\n mode?: DiffMode; // for action=upsert: replace section or append to it\n content: string; // markdown content to write\n}\n\nexport interface WikiDiffConflict {\n page: string;\n section: string;\n existing: string;\n incoming: string;\n source: string;\n existingDate?: string; // ISO date string\n incomingDate?: string; // ISO date string\n}\n\nexport interface WikiDiff {\n entries: WikiDiffEntry[];\n conflicts: WikiDiffConflict[];\n rawDiff: string;\n}\n\n// \u2500\u2500 Lint \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport type LintIssueKind = 'contradiction' | 'orphan' | 'stale' | 'broken_link';\n\nexport interface WikiLintIssue {\n kind: LintIssueKind;\n slug: string;\n detail: string;\n relatedSlug?: string;\n}\n\n// \u2500\u2500 Stats \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface WikiStats {\n pageCount: number;\n totalSources: number;\n oldestPage: number | null;\n newestPage: number | null;\n}\n"],
|
|
4
|
+
"sourcesContent": ["// \u2500\u2500 WikiPage \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface WikiPage {\n slug: string;\n title: string;\n content: string;\n filePath: string;\n updatedAt: number;\n sourceCount: number;\n}\n\nexport interface ScoredWikiPage {\n page: WikiPage;\n score: number;\n}\n\n// \u2500\u2500 WIKI_DIFF types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport type DiffAction = 'upsert' | 'create' | 'append';\nexport type DiffMode = 'replace' | 'append';\n\nexport interface WikiDiffEntry {\n action: DiffAction;\n page: string; // slug\n title?: string; // required for action=create\n section?: string; // target section heading (e.g. \"Decisions\")\n mode?: DiffMode; // for action=upsert: replace section or append to it\n content: string; // markdown content to write\n}\n\nexport interface WikiDiffConflict {\n page: string;\n section: string;\n existing: string;\n incoming: string;\n source: string;\n existingDate?: string; // ISO date string\n incomingDate?: string; // ISO date string\n}\n\nexport interface WikiDiff {\n entries: WikiDiffEntry[];\n conflicts: WikiDiffConflict[];\n rawDiff: string;\n}\n\n// \u2500\u2500 Lint \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport type LintIssueKind = 'contradiction' | 'orphan' | 'stale' | 'broken_link' | 'schema_error';\n\nexport interface WikiLintIssue {\n kind: LintIssueKind;\n slug: string;\n detail: string;\n relatedSlug?: string;\n}\n\n// \u2500\u2500 Stats \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface WikiStats {\n pageCount: number;\n totalSources: number;\n oldestPage: number | null;\n newestPage: number | null;\n}\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;;AAAA;AAAA;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED