@dynamik-dev/refdocs 0.1.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 +109 -0
- package/dist/src/chunker.d.ts +9 -0
- package/dist/src/chunker.d.ts.map +1 -0
- package/dist/src/chunker.js +205 -0
- package/dist/src/chunker.js.map +1 -0
- package/dist/src/config.d.ts +8 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +77 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +124 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/indexer.d.ts +9 -0
- package/dist/src/indexer.d.ts.map +1 -0
- package/dist/src/indexer.js +58 -0
- package/dist/src/indexer.js.map +1 -0
- package/dist/src/search.d.ts +11 -0
- package/dist/src/search.d.ts.map +1 -0
- package/dist/src/search.js +63 -0
- package/dist/src/search.js.map +1 -0
- package/dist/src/types.d.ts +39 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/dist/tests/chunker.test.d.ts +2 -0
- package/dist/tests/chunker.test.d.ts.map +1 -0
- package/dist/tests/chunker.test.js +245 -0
- package/dist/tests/chunker.test.js.map +1 -0
- package/dist/tests/cli.test.d.ts +2 -0
- package/dist/tests/cli.test.d.ts.map +1 -0
- package/dist/tests/cli.test.js +166 -0
- package/dist/tests/cli.test.js.map +1 -0
- package/dist/tests/config.test.d.ts +2 -0
- package/dist/tests/config.test.d.ts.map +1 -0
- package/dist/tests/config.test.js +94 -0
- package/dist/tests/config.test.js.map +1 -0
- package/dist/tests/indexer.test.d.ts +2 -0
- package/dist/tests/indexer.test.d.ts.map +1 -0
- package/dist/tests/indexer.test.js +109 -0
- package/dist/tests/indexer.test.js.map +1 -0
- package/dist/tests/search.test.d.ts +2 -0
- package/dist/tests/search.test.d.ts.map +1 -0
- package/dist/tests/search.test.js +160 -0
- package/dist/tests/search.test.js.map +1 -0
- package/package.json +39 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"indexer.js","sourceRoot":"","sources":["../../src/indexer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import MiniSearch from "minisearch";
|
|
2
|
+
import type { Chunk, RefdocsConfig, SearchOptions, SearchResult } from "./types.js";
|
|
3
|
+
export declare function createSearchIndex(config: RefdocsConfig): MiniSearch<Chunk>;
|
|
4
|
+
export declare function indexChunks(index: MiniSearch<Chunk>, chunks: Chunk[]): void;
|
|
5
|
+
export declare function serializeIndex(index: MiniSearch<Chunk>, chunks: Chunk[]): string;
|
|
6
|
+
export declare function loadIndex(json: string, config: RefdocsConfig): {
|
|
7
|
+
index: MiniSearch<Chunk>;
|
|
8
|
+
chunks: Chunk[];
|
|
9
|
+
};
|
|
10
|
+
export declare function search(index: MiniSearch<Chunk>, query: string, options: SearchOptions): SearchResult[];
|
|
11
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/search.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,YAAY,CAAC;AAEpC,OAAO,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAWpF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,GAAG,UAAU,CAAC,KAAK,CAAC,CAU1E;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAE3E;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAQhF;AAED,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,aAAa,GACpB;IAAE,KAAK,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;IAAC,MAAM,EAAE,KAAK,EAAE,CAAA;CAAE,CAoB/C;AAED,wBAAgB,MAAM,CACpB,KAAK,EAAE,UAAU,CAAC,KAAK,CAAC,EACxB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,aAAa,GACrB,YAAY,EAAE,CAqBhB"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import MiniSearch from "minisearch";
|
|
2
|
+
import picomatch from "picomatch";
|
|
3
|
+
const INDEX_VERSION = 1;
|
|
4
|
+
export function createSearchIndex(config) {
|
|
5
|
+
return new MiniSearch({
|
|
6
|
+
fields: ["title", "headings", "body"],
|
|
7
|
+
storeFields: ["id", "file", "title", "headings", "body", "startLine", "endLine", "tokenEstimate"],
|
|
8
|
+
searchOptions: {
|
|
9
|
+
boost: config.boostFields,
|
|
10
|
+
fuzzy: 0.2,
|
|
11
|
+
prefix: true,
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
export function indexChunks(index, chunks) {
|
|
16
|
+
index.addAll(chunks);
|
|
17
|
+
}
|
|
18
|
+
export function serializeIndex(index, chunks) {
|
|
19
|
+
const data = {
|
|
20
|
+
version: INDEX_VERSION,
|
|
21
|
+
createdAt: new Date().toISOString(),
|
|
22
|
+
miniSearchIndex: JSON.stringify(index),
|
|
23
|
+
chunks,
|
|
24
|
+
};
|
|
25
|
+
return JSON.stringify(data);
|
|
26
|
+
}
|
|
27
|
+
export function loadIndex(json, config) {
|
|
28
|
+
const data = JSON.parse(json);
|
|
29
|
+
if (data.version !== INDEX_VERSION) {
|
|
30
|
+
throw new Error(`Index version mismatch (found v${data.version}, expected v${INDEX_VERSION}). Run \`refdocs index\` to rebuild.`);
|
|
31
|
+
}
|
|
32
|
+
const index = MiniSearch.loadJSON(data.miniSearchIndex, {
|
|
33
|
+
fields: ["title", "headings", "body"],
|
|
34
|
+
storeFields: ["id", "file", "title", "headings", "body", "startLine", "endLine", "tokenEstimate"],
|
|
35
|
+
searchOptions: {
|
|
36
|
+
boost: config.boostFields,
|
|
37
|
+
fuzzy: 0.2,
|
|
38
|
+
prefix: true,
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
return { index, chunks: data.chunks };
|
|
42
|
+
}
|
|
43
|
+
export function search(index, query, options) {
|
|
44
|
+
let results = index.search(query);
|
|
45
|
+
if (options.fileFilter) {
|
|
46
|
+
const isMatch = picomatch(options.fileFilter);
|
|
47
|
+
results = results.filter((r) => {
|
|
48
|
+
const file = r.file;
|
|
49
|
+
return isMatch(file);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return results.slice(0, options.maxResults).map((r) => {
|
|
53
|
+
const stored = r;
|
|
54
|
+
return {
|
|
55
|
+
score: r.score,
|
|
56
|
+
file: stored.file,
|
|
57
|
+
lines: [stored.startLine, stored.endLine],
|
|
58
|
+
headings: stored.headings.split(" > "),
|
|
59
|
+
body: stored.body,
|
|
60
|
+
};
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface RefdocsConfig {
|
|
2
|
+
paths: string[];
|
|
3
|
+
index: string;
|
|
4
|
+
chunkMaxTokens: number;
|
|
5
|
+
chunkMinTokens: number;
|
|
6
|
+
boostFields: {
|
|
7
|
+
title: number;
|
|
8
|
+
headings: number;
|
|
9
|
+
body: number;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export interface Chunk {
|
|
13
|
+
id: string;
|
|
14
|
+
file: string;
|
|
15
|
+
title: string;
|
|
16
|
+
headings: string;
|
|
17
|
+
body: string;
|
|
18
|
+
startLine: number;
|
|
19
|
+
endLine: number;
|
|
20
|
+
tokenEstimate: number;
|
|
21
|
+
}
|
|
22
|
+
export interface SearchResult {
|
|
23
|
+
score: number;
|
|
24
|
+
file: string;
|
|
25
|
+
lines: [number, number];
|
|
26
|
+
headings: string[];
|
|
27
|
+
body: string;
|
|
28
|
+
}
|
|
29
|
+
export interface SearchOptions {
|
|
30
|
+
maxResults: number;
|
|
31
|
+
fileFilter?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface IndexSummary {
|
|
34
|
+
filesIndexed: number;
|
|
35
|
+
chunksCreated: number;
|
|
36
|
+
indexSizeBytes: number;
|
|
37
|
+
elapsedMs: number;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE;QACX,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CACnB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunker.test.d.ts","sourceRoot":"","sources":["../../tests/chunker.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { chunkMarkdown, estimateTokens } from "../src/chunker.js";
|
|
5
|
+
const FIXTURES = join(import.meta.dirname, "fixtures");
|
|
6
|
+
function readFixture(name) {
|
|
7
|
+
return readFileSync(join(FIXTURES, name), "utf-8");
|
|
8
|
+
}
|
|
9
|
+
const defaultOpts = { maxTokens: 800, minTokens: 100 };
|
|
10
|
+
describe("estimateTokens", () => {
|
|
11
|
+
it("estimates tokens as chars / 4 rounded up", () => {
|
|
12
|
+
expect(estimateTokens("")).toBe(0);
|
|
13
|
+
expect(estimateTokens("a")).toBe(1);
|
|
14
|
+
expect(estimateTokens("abcd")).toBe(1);
|
|
15
|
+
expect(estimateTokens("abcde")).toBe(2);
|
|
16
|
+
expect(estimateTokens("a".repeat(100))).toBe(25);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
describe("chunkMarkdown", () => {
|
|
20
|
+
describe("empty file", () => {
|
|
21
|
+
it("returns empty array for empty content", () => {
|
|
22
|
+
expect(chunkMarkdown("", "empty.md", defaultOpts)).toEqual([]);
|
|
23
|
+
});
|
|
24
|
+
it("returns empty array for whitespace-only content", () => {
|
|
25
|
+
expect(chunkMarkdown(" \n\n ", "empty.md", defaultOpts)).toEqual([]);
|
|
26
|
+
});
|
|
27
|
+
it("returns empty array for empty fixture", () => {
|
|
28
|
+
const content = readFixture("empty.md");
|
|
29
|
+
expect(chunkMarkdown(content, "empty.md", defaultOpts)).toEqual([]);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
describe("simple.md — basic heading hierarchy", () => {
|
|
33
|
+
it("creates chunks at h1/h2/h3 boundaries", () => {
|
|
34
|
+
const content = readFixture("simple.md");
|
|
35
|
+
const chunks = chunkMarkdown(content, "simple.md", defaultOpts);
|
|
36
|
+
expect(chunks.length).toBeGreaterThanOrEqual(3);
|
|
37
|
+
});
|
|
38
|
+
it("includes heading breadcrumbs", () => {
|
|
39
|
+
const content = readFixture("simple.md");
|
|
40
|
+
const chunks = chunkMarkdown(content, "simple.md", defaultOpts);
|
|
41
|
+
const configChunk = chunks.find((c) => c.headings.includes("Configuration"));
|
|
42
|
+
expect(configChunk).toBeDefined();
|
|
43
|
+
});
|
|
44
|
+
it("sets file field on all chunks", () => {
|
|
45
|
+
const content = readFixture("simple.md");
|
|
46
|
+
const chunks = chunkMarkdown(content, "simple.md", defaultOpts);
|
|
47
|
+
for (const chunk of chunks) {
|
|
48
|
+
expect(chunk.file).toBe("simple.md");
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
it("assigns unique ids", () => {
|
|
52
|
+
const content = readFixture("simple.md");
|
|
53
|
+
const chunks = chunkMarkdown(content, "simple.md", defaultOpts);
|
|
54
|
+
const ids = chunks.map((c) => c.id);
|
|
55
|
+
expect(new Set(ids).size).toBe(ids.length);
|
|
56
|
+
});
|
|
57
|
+
it("has valid line ranges", () => {
|
|
58
|
+
const content = readFixture("simple.md");
|
|
59
|
+
const chunks = chunkMarkdown(content, "simple.md", defaultOpts);
|
|
60
|
+
for (const chunk of chunks) {
|
|
61
|
+
expect(chunk.startLine).toBeGreaterThan(0);
|
|
62
|
+
expect(chunk.endLine).toBeGreaterThanOrEqual(chunk.startLine);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
it("includes token estimates", () => {
|
|
66
|
+
const content = readFixture("simple.md");
|
|
67
|
+
const chunks = chunkMarkdown(content, "simple.md", defaultOpts);
|
|
68
|
+
for (const chunk of chunks) {
|
|
69
|
+
expect(chunk.tokenEstimate).toBeGreaterThan(0);
|
|
70
|
+
expect(chunk.tokenEstimate).toBe(estimateTokens(chunk.body));
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
describe("no-headings.md — flat text", () => {
|
|
75
|
+
it("creates a single chunk", () => {
|
|
76
|
+
const content = readFixture("no-headings.md");
|
|
77
|
+
const chunks = chunkMarkdown(content, "docs/no-headings.md", defaultOpts);
|
|
78
|
+
expect(chunks).toHaveLength(1);
|
|
79
|
+
});
|
|
80
|
+
it("uses filename as title when no headings", () => {
|
|
81
|
+
const content = readFixture("no-headings.md");
|
|
82
|
+
const chunks = chunkMarkdown(content, "docs/no-headings.md", defaultOpts);
|
|
83
|
+
expect(chunks[0].title).toBe("no-headings");
|
|
84
|
+
});
|
|
85
|
+
it("contains the full body text", () => {
|
|
86
|
+
const content = readFixture("no-headings.md");
|
|
87
|
+
const chunks = chunkMarkdown(content, "no-headings.md", defaultOpts);
|
|
88
|
+
expect(chunks[0].body).toContain("no headings at all");
|
|
89
|
+
expect(chunks[0].body).toContain("bold");
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
describe("large-section.md — oversized section splitting", () => {
|
|
93
|
+
it("splits into multiple chunks", () => {
|
|
94
|
+
const content = readFixture("large-section.md");
|
|
95
|
+
const chunks = chunkMarkdown(content, "large-section.md", defaultOpts);
|
|
96
|
+
expect(chunks.length).toBeGreaterThan(1);
|
|
97
|
+
});
|
|
98
|
+
it("keeps all chunks within maxTokens", () => {
|
|
99
|
+
const content = readFixture("large-section.md");
|
|
100
|
+
const chunks = chunkMarkdown(content, "large-section.md", defaultOpts);
|
|
101
|
+
for (const chunk of chunks) {
|
|
102
|
+
expect(chunk.tokenEstimate).toBeLessThanOrEqual(defaultOpts.maxTokens);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
it("preserves heading breadcrumbs across splits", () => {
|
|
106
|
+
const content = readFixture("large-section.md");
|
|
107
|
+
const chunks = chunkMarkdown(content, "large-section.md", defaultOpts);
|
|
108
|
+
for (const chunk of chunks) {
|
|
109
|
+
expect(chunk.headings).toContain("API Reference");
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
it("covers all body content", () => {
|
|
113
|
+
const content = readFixture("large-section.md");
|
|
114
|
+
const chunks = chunkMarkdown(content, "large-section.md", defaultOpts);
|
|
115
|
+
const combined = chunks.map((c) => c.body).join("\n");
|
|
116
|
+
expect(combined).toContain("createUser");
|
|
117
|
+
expect(combined).toContain("Batch operations");
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
describe("tiny-sections.md — small section merging", () => {
|
|
121
|
+
it("merges sections below minTokens", () => {
|
|
122
|
+
const content = readFixture("tiny-sections.md");
|
|
123
|
+
const chunks = chunkMarkdown(content, "tiny-sections.md", defaultOpts);
|
|
124
|
+
// 7 sections (1 h1, 6 h2) — most are tiny and should merge
|
|
125
|
+
expect(chunks.length).toBeLessThan(7);
|
|
126
|
+
});
|
|
127
|
+
it("preserves content from merged sections", () => {
|
|
128
|
+
const content = readFixture("tiny-sections.md");
|
|
129
|
+
const chunks = chunkMarkdown(content, "tiny-sections.md", defaultOpts);
|
|
130
|
+
const allBodies = chunks.map((c) => c.body).join("\n");
|
|
131
|
+
expect(allBodies).toContain("Enable logging");
|
|
132
|
+
expect(allBodies).toContain("Debug mode");
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
describe("frontmatter.md — YAML front matter stripping", () => {
|
|
136
|
+
it("strips front matter and still chunks correctly", () => {
|
|
137
|
+
const content = readFixture("frontmatter.md");
|
|
138
|
+
const chunks = chunkMarkdown(content, "frontmatter.md", defaultOpts);
|
|
139
|
+
expect(chunks.length).toBeGreaterThanOrEqual(1);
|
|
140
|
+
});
|
|
141
|
+
it("does not include front matter in any chunk body", () => {
|
|
142
|
+
const content = readFixture("frontmatter.md");
|
|
143
|
+
const chunks = chunkMarkdown(content, "frontmatter.md", defaultOpts);
|
|
144
|
+
for (const chunk of chunks) {
|
|
145
|
+
expect(chunk.body).not.toContain("author: John Doe");
|
|
146
|
+
expect(chunk.body).not.toContain("tags:");
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
it("includes actual content after front matter", () => {
|
|
150
|
+
const content = readFixture("frontmatter.md");
|
|
151
|
+
const chunks = chunkMarkdown(content, "frontmatter.md", defaultOpts);
|
|
152
|
+
const allBodies = chunks.map((c) => c.body).join("\n");
|
|
153
|
+
expect(allBodies).toContain("DATABASE_URL");
|
|
154
|
+
const allHeadings = chunks.map((c) => c.headings).join("\n");
|
|
155
|
+
expect(allHeadings).toContain("Environment Variables");
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
describe("code-blocks.md — hash characters in code blocks", () => {
|
|
159
|
+
it("does not split on hash characters inside code blocks", () => {
|
|
160
|
+
const content = readFixture("code-blocks.md");
|
|
161
|
+
const chunks = chunkMarkdown(content, "code-blocks.md", defaultOpts);
|
|
162
|
+
// Should only split on actual headings: h1 "Code Examples", h2 "Python Example",
|
|
163
|
+
// h2 "Bash Example", h2 "Markdown in Code Blocks"
|
|
164
|
+
// Code block contents with # should NOT create extra chunks
|
|
165
|
+
const headingsWithCodeComment = chunks.filter((c) => c.headings.includes("This is a comment in Python"));
|
|
166
|
+
expect(headingsWithCodeComment).toHaveLength(0);
|
|
167
|
+
});
|
|
168
|
+
it("preserves code block content in chunk bodies", () => {
|
|
169
|
+
const content = readFixture("code-blocks.md");
|
|
170
|
+
const chunks = chunkMarkdown(content, "code-blocks.md", defaultOpts);
|
|
171
|
+
const allBodies = chunks.map((c) => c.body).join("\n");
|
|
172
|
+
expect(allBodies).toContain('print("Hello, world!")');
|
|
173
|
+
expect(allBodies).toContain("npm install");
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
describe("heading-jumps.md — non-sequential heading depths", () => {
|
|
177
|
+
it("handles h1 -> h3 jump gracefully", () => {
|
|
178
|
+
const content = readFixture("heading-jumps.md");
|
|
179
|
+
const chunks = chunkMarkdown(content, "heading-jumps.md", defaultOpts);
|
|
180
|
+
const jumpedChunk = chunks.find((c) => c.headings.includes("Jumped to H3"));
|
|
181
|
+
expect(jumpedChunk).toBeDefined();
|
|
182
|
+
});
|
|
183
|
+
it("handles h4+ as body content, not split points", () => {
|
|
184
|
+
const content = readFixture("heading-jumps.md");
|
|
185
|
+
const chunks = chunkMarkdown(content, "heading-jumps.md", defaultOpts);
|
|
186
|
+
// h4 "Deep Jump to H4" should appear in body, not as a separate chunk title
|
|
187
|
+
const h4Chunk = chunks.find((c) => c.title === "Deep Jump to H4");
|
|
188
|
+
expect(h4Chunk).toBeUndefined();
|
|
189
|
+
// But the text should be in some chunk's body
|
|
190
|
+
const allBodies = chunks.map((c) => c.body).join("\n");
|
|
191
|
+
expect(allBodies).toContain("Deep Jump to H4");
|
|
192
|
+
});
|
|
193
|
+
it("builds correct breadcrumbs after depth jump", () => {
|
|
194
|
+
const content = readFixture("heading-jumps.md");
|
|
195
|
+
const chunks = chunkMarkdown(content, "heading-jumps.md", defaultOpts);
|
|
196
|
+
const nestedChunk = chunks.find((c) => c.headings.includes("Nested H3 Under H2"));
|
|
197
|
+
if (nestedChunk) {
|
|
198
|
+
expect(nestedChunk.headings).toContain("Back to H2");
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
describe("custom options", () => {
|
|
203
|
+
it("respects custom maxTokens", () => {
|
|
204
|
+
const content = readFixture("large-section.md");
|
|
205
|
+
const chunks = chunkMarkdown(content, "large-section.md", {
|
|
206
|
+
maxTokens: 200,
|
|
207
|
+
minTokens: 50,
|
|
208
|
+
});
|
|
209
|
+
for (const chunk of chunks) {
|
|
210
|
+
expect(chunk.tokenEstimate).toBeLessThanOrEqual(200);
|
|
211
|
+
}
|
|
212
|
+
expect(chunks.length).toBeGreaterThan(3);
|
|
213
|
+
});
|
|
214
|
+
it("respects large minTokens by merging aggressively", () => {
|
|
215
|
+
const content = readFixture("simple.md");
|
|
216
|
+
const chunksNormal = chunkMarkdown(content, "simple.md", defaultOpts);
|
|
217
|
+
const chunksAggressive = chunkMarkdown(content, "simple.md", {
|
|
218
|
+
maxTokens: 2000,
|
|
219
|
+
minTokens: 500,
|
|
220
|
+
});
|
|
221
|
+
expect(chunksAggressive.length).toBeLessThanOrEqual(chunksNormal.length);
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
describe("edge cases", () => {
|
|
225
|
+
it("handles single heading with no body", () => {
|
|
226
|
+
const chunks = chunkMarkdown("# Title\n", "test.md", defaultOpts);
|
|
227
|
+
// A heading with no body produces an empty body section
|
|
228
|
+
expect(chunks.length).toBeLessThanOrEqual(1);
|
|
229
|
+
});
|
|
230
|
+
it("handles content with only inline formatting", () => {
|
|
231
|
+
const content = "**Bold text** and *italic text* and `code`.";
|
|
232
|
+
const chunks = chunkMarkdown(content, "inline.md", defaultOpts);
|
|
233
|
+
expect(chunks).toHaveLength(1);
|
|
234
|
+
expect(chunks[0].body).toContain("Bold text");
|
|
235
|
+
});
|
|
236
|
+
it("generates sequential chunk ids for same file", () => {
|
|
237
|
+
const content = readFixture("simple.md");
|
|
238
|
+
const chunks = chunkMarkdown(content, "simple.md", defaultOpts);
|
|
239
|
+
chunks.forEach((chunk, i) => {
|
|
240
|
+
expect(chunk.id).toBe(`simple.md:${i}`);
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
//# sourceMappingURL=chunker.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunker.test.js","sourceRoot":"","sources":["../../tests/chunker.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.test.d.ts","sourceRoot":"","sources":["../../tests/cli.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { describe, it, expect, beforeAll, afterAll } from "vitest";
|
|
2
|
+
import { execSync } from "node:child_process";
|
|
3
|
+
import { mkdtempSync, writeFileSync, mkdirSync, rmSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
const CLI = join(import.meta.dirname, "..", "src", "index.ts");
|
|
7
|
+
function run(args, cwd) {
|
|
8
|
+
try {
|
|
9
|
+
const stdout = execSync(`npx tsx ${CLI} ${args}`, {
|
|
10
|
+
cwd,
|
|
11
|
+
encoding: "utf-8",
|
|
12
|
+
timeout: 15000,
|
|
13
|
+
env: { ...process.env, NODE_NO_WARNINGS: "1" },
|
|
14
|
+
});
|
|
15
|
+
return { stdout, stderr: "", exitCode: 0 };
|
|
16
|
+
}
|
|
17
|
+
catch (err) {
|
|
18
|
+
const e = err;
|
|
19
|
+
return {
|
|
20
|
+
stdout: e.stdout || "",
|
|
21
|
+
stderr: e.stderr || "",
|
|
22
|
+
exitCode: e.status || 1,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
describe("CLI", () => {
|
|
27
|
+
let tmpDir;
|
|
28
|
+
beforeAll(() => {
|
|
29
|
+
tmpDir = mkdtempSync(join(tmpdir(), "refdocs-cli-"));
|
|
30
|
+
mkdirSync(join(tmpDir, "docs"), { recursive: true });
|
|
31
|
+
writeFileSync(join(tmpDir, ".refdocs.json"), JSON.stringify({ paths: ["docs"] }));
|
|
32
|
+
writeFileSync(join(tmpDir, "docs", "api.md"), [
|
|
33
|
+
"# API Reference",
|
|
34
|
+
"",
|
|
35
|
+
"The API provides RESTful endpoints for managing resources.",
|
|
36
|
+
"",
|
|
37
|
+
"## Authentication",
|
|
38
|
+
"",
|
|
39
|
+
"Use Bearer tokens for authentication. Include the token in the Authorization header.",
|
|
40
|
+
"Tokens expire after 24 hours. Use the refresh endpoint to obtain a new token.",
|
|
41
|
+
"",
|
|
42
|
+
"## Rate Limiting",
|
|
43
|
+
"",
|
|
44
|
+
"Rate limits are applied per API key. The default limit is 100 requests per minute.",
|
|
45
|
+
"Exceeding the limit returns a 429 status code with a Retry-After header.",
|
|
46
|
+
"",
|
|
47
|
+
].join("\n"));
|
|
48
|
+
writeFileSync(join(tmpDir, "docs", "guide.md"), [
|
|
49
|
+
"# Getting Started",
|
|
50
|
+
"",
|
|
51
|
+
"Welcome to the getting started guide.",
|
|
52
|
+
"",
|
|
53
|
+
"## Installation",
|
|
54
|
+
"",
|
|
55
|
+
"Install the package using npm:",
|
|
56
|
+
"",
|
|
57
|
+
"```bash",
|
|
58
|
+
"npm install my-package",
|
|
59
|
+
"```",
|
|
60
|
+
"",
|
|
61
|
+
"## Configuration",
|
|
62
|
+
"",
|
|
63
|
+
"Create a `.env` file with your database URL and API key.",
|
|
64
|
+
"The following environment variables are supported:",
|
|
65
|
+
"",
|
|
66
|
+
"- `DATABASE_URL` — connection string",
|
|
67
|
+
"- `API_KEY` — your API key",
|
|
68
|
+
"",
|
|
69
|
+
].join("\n"));
|
|
70
|
+
});
|
|
71
|
+
afterAll(() => {
|
|
72
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
73
|
+
});
|
|
74
|
+
describe("refdocs index", () => {
|
|
75
|
+
it("indexes files and prints summary", () => {
|
|
76
|
+
const { stdout, exitCode } = run("index", tmpDir);
|
|
77
|
+
expect(exitCode).toBe(0);
|
|
78
|
+
expect(stdout).toContain("Indexed 2 files");
|
|
79
|
+
expect(stdout).toContain("chunks");
|
|
80
|
+
expect(stdout).toContain("KB");
|
|
81
|
+
expect(stdout).toContain("Done in");
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
describe("refdocs search", () => {
|
|
85
|
+
it("returns relevant results", () => {
|
|
86
|
+
run("index", tmpDir);
|
|
87
|
+
const { stdout, exitCode } = run('search "authentication"', tmpDir);
|
|
88
|
+
expect(exitCode).toBe(0);
|
|
89
|
+
expect(stdout).toContain("Bearer tokens");
|
|
90
|
+
});
|
|
91
|
+
it("shows formatted output with file and line info", () => {
|
|
92
|
+
const { stdout } = run('search "rate limiting"', tmpDir);
|
|
93
|
+
expect(stdout).toMatch(/# \[\d+\] docs\/api\.md:\d+-\d+/);
|
|
94
|
+
});
|
|
95
|
+
it("supports --json flag", () => {
|
|
96
|
+
const { stdout } = run('search --json "authentication"', tmpDir);
|
|
97
|
+
const results = JSON.parse(stdout);
|
|
98
|
+
expect(Array.isArray(results)).toBe(true);
|
|
99
|
+
expect(results.length).toBeGreaterThan(0);
|
|
100
|
+
expect(results[0]).toHaveProperty("score");
|
|
101
|
+
expect(results[0]).toHaveProperty("file");
|
|
102
|
+
expect(results[0]).toHaveProperty("lines");
|
|
103
|
+
expect(results[0]).toHaveProperty("headings");
|
|
104
|
+
expect(results[0]).toHaveProperty("body");
|
|
105
|
+
});
|
|
106
|
+
it("supports --raw flag", () => {
|
|
107
|
+
const { stdout } = run('search --raw "authentication"', tmpDir);
|
|
108
|
+
// Raw output should not contain the metadata header
|
|
109
|
+
expect(stdout).not.toMatch(/^# \[/m);
|
|
110
|
+
expect(stdout).toContain("Bearer tokens");
|
|
111
|
+
});
|
|
112
|
+
it("supports -n flag to limit results", () => {
|
|
113
|
+
const { stdout } = run('search -n 1 --json "api"', tmpDir);
|
|
114
|
+
const results = JSON.parse(stdout);
|
|
115
|
+
expect(results).toHaveLength(1);
|
|
116
|
+
});
|
|
117
|
+
it("supports -f flag to filter by file", () => {
|
|
118
|
+
const { stdout } = run('search -f "docs/guide*" --json "install"', tmpDir);
|
|
119
|
+
const results = JSON.parse(stdout);
|
|
120
|
+
for (const r of results) {
|
|
121
|
+
expect(r.file).toMatch(/^docs\/guide/);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
it("shows message when no results found", () => {
|
|
125
|
+
const { stdout } = run('search "xyznonexistent"', tmpDir);
|
|
126
|
+
expect(stdout).toContain("No results found");
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
describe("refdocs list", () => {
|
|
130
|
+
it("lists indexed files with chunk counts", () => {
|
|
131
|
+
const { stdout, exitCode } = run("list", tmpDir);
|
|
132
|
+
expect(exitCode).toBe(0);
|
|
133
|
+
expect(stdout).toContain("docs/api.md");
|
|
134
|
+
expect(stdout).toContain("docs/guide.md");
|
|
135
|
+
expect(stdout).toContain("chunk");
|
|
136
|
+
expect(stdout).toContain("total");
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
describe("refdocs info", () => {
|
|
140
|
+
it("shows chunks for a specific file", () => {
|
|
141
|
+
const { stdout, exitCode } = run("info docs/api.md", tmpDir);
|
|
142
|
+
expect(exitCode).toBe(0);
|
|
143
|
+
expect(stdout).toContain("docs/api.md");
|
|
144
|
+
expect(stdout).toContain("tokens");
|
|
145
|
+
});
|
|
146
|
+
it("errors for unknown file", () => {
|
|
147
|
+
const { stderr, exitCode } = run("info nonexistent.md", tmpDir);
|
|
148
|
+
expect(exitCode).toBe(1);
|
|
149
|
+
expect(stderr).toContain("No chunks found");
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
describe("error handling", () => {
|
|
153
|
+
it("errors when searching without index", () => {
|
|
154
|
+
const emptyDir = mkdtempSync(join(tmpdir(), "refdocs-empty-"));
|
|
155
|
+
try {
|
|
156
|
+
const { stderr, exitCode } = run('search "test"', emptyDir);
|
|
157
|
+
expect(exitCode).toBe(1);
|
|
158
|
+
expect(stderr).toContain("Index not found");
|
|
159
|
+
}
|
|
160
|
+
finally {
|
|
161
|
+
rmSync(emptyDir, { recursive: true, force: true });
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
//# sourceMappingURL=cli.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.test.js","sourceRoot":"","sources":["../../tests/cli.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;AAE/D,SAAS,GAAG,CAAC,IAAY,EAAE,GAAW;IACpC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,WAAW,GAAG,IAAI,IAAI,EAAE,EAAE;YAChD,GAAG;YACH,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,KAAK;YACd,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,gBAAgB,EAAE,GAAG,EAAE;SAC/C,CAAC,CAAC;QACH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IAC7C,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,GAA4D,CAAC;QACvE,OAAO;YACL,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE;YACtB,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE;YACtB,QAAQ,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC;SACxB,CAAC;IACJ,CAAC;AACH,CAAC;AAED,QAAQ,CAAC,KAAK,EAAE,GAAG,EAAE;IACnB,IAAI,MAAc,CAAC;IAEnB,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC;QACrD,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAErD,aAAa,CACX,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,EAC7B,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CACpC,CAAC;QAEF,aAAa,CACX,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAC9B;YACE,iBAAiB;YACjB,EAAE;YACF,4DAA4D;YAC5D,EAAE;YACF,mBAAmB;YACnB,EAAE;YACF,sFAAsF;YACtF,+EAA+E;YAC/E,EAAE;YACF,kBAAkB;YAClB,EAAE;YACF,oFAAoF;YACpF,0EAA0E;YAC1E,EAAE;SACH,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;QAEF,aAAa,CACX,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAChC;YACE,mBAAmB;YACnB,EAAE;YACF,uCAAuC;YACvC,EAAE;YACF,iBAAiB;YACjB,EAAE;YACF,gCAAgC;YAChC,EAAE;YACF,SAAS;YACT,wBAAwB;YACxB,KAAK;YACL,EAAE;YACF,kBAAkB;YAClB,EAAE;YACF,0DAA0D;YAC1D,oDAAoD;YACpD,EAAE;YACF,sCAAsC;YACtC,4BAA4B;YAC5B,EAAE;SACH,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,GAAG,EAAE;QACZ,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;QAC7B,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;YAC1C,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAClD,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACzB,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;YAC5C,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;YACnC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAC/B,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;QAC9B,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;YAClC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACrB,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC,yBAAyB,EAAE,MAAM,CAAC,CAAC;YACpE,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACzB,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;YACxD,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,wBAAwB,EAAE,MAAM,CAAC,CAAC;YACzD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,iCAAiC,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;YAC9B,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,gCAAgC,EAAE,MAAM,CAAC,CAAC;YACjE,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACnC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1C,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;YAC1C,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;YAC3C,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;YAC1C,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;YAC3C,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;YAC9C,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;YAC7B,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,+BAA+B,EAAE,MAAM,CAAC,CAAC;YAChE,oDAAoD;YACpD,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;YAC3C,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,0BAA0B,EAAE,MAAM,CAAC,CAAC;YAC3D,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACnC,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;YAC5C,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,0CAA0C,EAAE,MAAM,CAAC,CAAC;YAC3E,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACnC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;gBACxB,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;YACzC,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;YAC7C,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,yBAAyB,EAAE,MAAM,CAAC,CAAC;YAC1D,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;QAC5B,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;YAC/C,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACjD,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACzB,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;YACxC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;YAC1C,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YAClC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;QAC5B,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;YAC1C,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC;YAC7D,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACzB,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;YACxC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;YACjC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;YAChE,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACzB,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;QAC9B,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;YAC7C,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;YAC/D,IAAI,CAAC;gBACH,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;gBAC5D,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBACzB,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;YAC9C,CAAC;oBAAS,CAAC;gBACT,MAAM,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACrD,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.test.d.ts","sourceRoot":"","sources":["../../tests/config.test.ts"],"names":[],"mappings":""}
|