@lorepack/cli 0.0.0-stage → 0.1.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -0
- package/dist/commands/activate.d.ts +20 -0
- package/dist/commands/activate.d.ts.map +1 -0
- package/dist/commands/activate.js +171 -0
- package/dist/commands/activate.js.map +1 -0
- package/dist/commands/build.d.ts +3 -0
- package/dist/commands/build.d.ts.map +1 -0
- package/dist/commands/build.js +53 -0
- package/dist/commands/build.js.map +1 -0
- package/dist/commands/config.d.ts +14 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +109 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/connect.d.ts +5 -0
- package/dist/commands/connect.d.ts.map +1 -0
- package/dist/commands/connect.js +196 -0
- package/dist/commands/connect.js.map +1 -0
- package/dist/commands/deploy.d.ts +14 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +248 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/dev.d.ts +25 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +227 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/commands/diff.d.ts +3 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +75 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/doctor.d.ts +14 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +96 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/export.d.ts +3 -0
- package/dist/commands/export.d.ts.map +1 -0
- package/dist/commands/export.js +126 -0
- package/dist/commands/export.js.map +1 -0
- package/dist/commands/index.d.ts +8 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +51 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +95 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/inspect.d.ts +15 -0
- package/dist/commands/inspect.d.ts.map +1 -0
- package/dist/commands/inspect.js +527 -0
- package/dist/commands/inspect.js.map +1 -0
- package/dist/commands/mcp.d.ts +12 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +219 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/pack.d.ts +9 -0
- package/dist/commands/pack.d.ts.map +1 -0
- package/dist/commands/pack.js +57 -0
- package/dist/commands/pack.js.map +1 -0
- package/dist/commands/plan.d.ts +3 -0
- package/dist/commands/plan.d.ts.map +1 -0
- package/dist/commands/plan.js +44 -0
- package/dist/commands/plan.js.map +1 -0
- package/dist/commands/prune.d.ts +7 -0
- package/dist/commands/prune.d.ts.map +1 -0
- package/dist/commands/prune.js +341 -0
- package/dist/commands/prune.js.map +1 -0
- package/dist/commands/search.d.ts +3 -0
- package/dist/commands/search.d.ts.map +1 -0
- package/dist/commands/search.js +84 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/serve.d.ts +20 -0
- package/dist/commands/serve.d.ts.map +1 -0
- package/dist/commands/serve.js +66 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +27 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/target.d.ts +71 -0
- package/dist/commands/target.d.ts.map +1 -0
- package/dist/commands/target.js +945 -0
- package/dist/commands/target.js.map +1 -0
- package/dist/entry.d.ts +3 -0
- package/dist/entry.d.ts.map +1 -0
- package/dist/entry.js +19 -0
- package/dist/entry.js.map +1 -0
- package/dist/framework/context.d.ts +49 -0
- package/dist/framework/context.d.ts.map +1 -0
- package/dist/framework/context.js +47 -0
- package/dist/framework/context.js.map +1 -0
- package/dist/framework/exit.d.ts +36 -0
- package/dist/framework/exit.d.ts.map +1 -0
- package/dist/framework/exit.js +57 -0
- package/dist/framework/exit.js.map +1 -0
- package/dist/framework/metadata.d.ts +38 -0
- package/dist/framework/metadata.d.ts.map +1 -0
- package/dist/framework/metadata.js +47 -0
- package/dist/framework/metadata.js.map +1 -0
- package/dist/framework/program.d.ts +47 -0
- package/dist/framework/program.d.ts.map +1 -0
- package/dist/framework/program.js +189 -0
- package/dist/framework/program.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/migrations/README.md +7 -0
- package/dist/migrations/build/0001_catalog.sql +85 -0
- package/dist/migrations/build/0002_tables.sql +43 -0
- package/dist/migrations/build/0003_table-cell-range.sql +13 -0
- package/dist/migrations/build/0004_chunk-page.sql +11 -0
- package/dist/migrations/state/0001_state.sql +40 -0
- package/dist/public-entry.js +38563 -0
- package/dist/public-entry.js.map +7 -0
- package/dist/public-index.js +36428 -0
- package/dist/public-index.js.map +7 -0
- package/dist/services/build.d.ts +48 -0
- package/dist/services/build.d.ts.map +1 -0
- package/dist/services/build.js +499 -0
- package/dist/services/build.js.map +1 -0
- package/dist/services/builds.d.ts +40 -0
- package/dist/services/builds.d.ts.map +1 -0
- package/dist/services/builds.js +184 -0
- package/dist/services/builds.js.map +1 -0
- package/dist/services/cancellation.d.ts +27 -0
- package/dist/services/cancellation.d.ts.map +1 -0
- package/dist/services/cancellation.js +41 -0
- package/dist/services/cancellation.js.map +1 -0
- package/dist/services/cloudflare-target.d.ts +38 -0
- package/dist/services/cloudflare-target.d.ts.map +1 -0
- package/dist/services/cloudflare-target.js +471 -0
- package/dist/services/cloudflare-target.js.map +1 -0
- package/dist/services/comparer.d.ts +15 -0
- package/dist/services/comparer.d.ts.map +1 -0
- package/dist/services/comparer.js +43 -0
- package/dist/services/comparer.js.map +1 -0
- package/dist/services/config-resolve.d.ts +60 -0
- package/dist/services/config-resolve.d.ts.map +1 -0
- package/dist/services/config-resolve.js +178 -0
- package/dist/services/config-resolve.js.map +1 -0
- package/dist/services/deploy.d.ts +70 -0
- package/dist/services/deploy.d.ts.map +1 -0
- package/dist/services/deploy.js +260 -0
- package/dist/services/deploy.js.map +1 -0
- package/dist/services/dev-session.d.ts +52 -0
- package/dist/services/dev-session.d.ts.map +1 -0
- package/dist/services/dev-session.js +102 -0
- package/dist/services/dev-session.js.map +1 -0
- package/dist/services/doctor.d.ts +35 -0
- package/dist/services/doctor.d.ts.map +1 -0
- package/dist/services/doctor.js +389 -0
- package/dist/services/doctor.js.map +1 -0
- package/dist/services/export.d.ts +20 -0
- package/dist/services/export.d.ts.map +1 -0
- package/dist/services/export.js +129 -0
- package/dist/services/export.js.map +1 -0
- package/dist/services/init.d.ts +46 -0
- package/dist/services/init.d.ts.map +1 -0
- package/dist/services/init.js +231 -0
- package/dist/services/init.js.map +1 -0
- package/dist/services/packing.d.ts +25 -0
- package/dist/services/packing.d.ts.map +1 -0
- package/dist/services/packing.js +69 -0
- package/dist/services/packing.js.map +1 -0
- package/dist/services/parse-cache.d.ts +47 -0
- package/dist/services/parse-cache.d.ts.map +1 -0
- package/dist/services/parse-cache.js +65 -0
- package/dist/services/parse-cache.js.map +1 -0
- package/dist/services/project.d.ts +49 -0
- package/dist/services/project.d.ts.map +1 -0
- package/dist/services/project.js +119 -0
- package/dist/services/project.js.map +1 -0
- package/dist/services/remote-prune.d.ts +7 -0
- package/dist/services/remote-prune.d.ts.map +1 -0
- package/dist/services/remote-prune.js +34 -0
- package/dist/services/remote-prune.js.map +1 -0
- package/dist/services/retention.d.ts +20 -0
- package/dist/services/retention.d.ts.map +1 -0
- package/dist/services/retention.js +106 -0
- package/dist/services/retention.js.map +1 -0
- package/dist/services/revalidate.d.ts +36 -0
- package/dist/services/revalidate.d.ts.map +1 -0
- package/dist/services/revalidate.js +73 -0
- package/dist/services/revalidate.js.map +1 -0
- package/dist/services/search.d.ts +25 -0
- package/dist/services/search.d.ts.map +1 -0
- package/dist/services/search.js +88 -0
- package/dist/services/search.js.map +1 -0
- package/dist/services/serving.d.ts +70 -0
- package/dist/services/serving.d.ts.map +1 -0
- package/dist/services/serving.js +240 -0
- package/dist/services/serving.js.map +1 -0
- package/dist/services/status.d.ts +54 -0
- package/dist/services/status.d.ts.map +1 -0
- package/dist/services/status.js +203 -0
- package/dist/services/status.js.map +1 -0
- package/dist/services/studio-assets.d.ts +13 -0
- package/dist/services/studio-assets.d.ts.map +1 -0
- package/dist/services/studio-assets.js +94 -0
- package/dist/services/studio-assets.js.map +1 -0
- package/dist/services/studio-diagnostics.d.ts +28 -0
- package/dist/services/studio-diagnostics.d.ts.map +1 -0
- package/dist/services/studio-diagnostics.js +88 -0
- package/dist/services/studio-diagnostics.js.map +1 -0
- package/dist/services/studio-endpoints.d.ts +61 -0
- package/dist/services/studio-endpoints.d.ts.map +1 -0
- package/dist/services/studio-endpoints.js +88 -0
- package/dist/services/studio-endpoints.js.map +1 -0
- package/dist/services/studio-mutations.d.ts +32 -0
- package/dist/services/studio-mutations.d.ts.map +1 -0
- package/dist/services/studio-mutations.js +149 -0
- package/dist/services/studio-mutations.js.map +1 -0
- package/dist/services/versions.d.ts +38 -0
- package/dist/services/versions.d.ts.map +1 -0
- package/dist/services/versions.js +46 -0
- package/dist/services/versions.js.map +1 -0
- package/dist/services/watch.d.ts +103 -0
- package/dist/services/watch.d.ts.map +1 -0
- package/dist/services/watch.js +420 -0
- package/dist/services/watch.js.map +1 -0
- package/package.json +73 -4
- package/studio-dist/assets/ibm-plex-mono-latin-400-normal-Dm_PoFIZ.woff2 +0 -0
- package/studio-dist/assets/ibm-plex-mono-latin-500-normal-C_OblDzq.woff2 +0 -0
- package/studio-dist/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
- package/studio-dist/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
- package/studio-dist/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
- package/studio-dist/assets/index-BuAYbQVX.js +66 -0
- package/studio-dist/assets/index-C_3XEUt4.css +1 -0
- package/studio-dist/index.html +30 -0
- package/README.md +0 -3
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { count } from '@lorepack/core';
|
|
2
|
+
export function renderBundleMarkdown(bundle, options) {
|
|
3
|
+
const lines = [];
|
|
4
|
+
lines.push(`# Context for: ${bundle.task}`, '');
|
|
5
|
+
lines.push(`Project **${options.projectName}**, build \`${bundle.buildId}\`.`);
|
|
6
|
+
lines.push(`Profile **${bundle.profile}**, budget ${count(bundle.budget, 'estimated token')}, of which ${count(bundle.estimatedTokens, 'estimated token')} used.`);
|
|
7
|
+
if (options.sourceState === 'dirty') {
|
|
8
|
+
lines.push('');
|
|
9
|
+
lines.push('> The sources have changed since this build was compiled, so this context is behind them. Run `lorepack build` and export again for current context.');
|
|
10
|
+
}
|
|
11
|
+
else if (options.sourceState === 'unknown') {
|
|
12
|
+
lines.push('');
|
|
13
|
+
lines.push('> Freshness could not be established, so this context may be behind the sources.');
|
|
14
|
+
}
|
|
15
|
+
lines.push('');
|
|
16
|
+
lines.push('Every passage below is quoted from a document in this project, with the file and source coordinate it came from. Lorepack selected and bounded them; it did not write or summarise anything, and it makes no claim about which document is correct.');
|
|
17
|
+
lines.push(`Search considered up to ${count(bundle.candidateLimit, 'candidate')} using ${bundle.candidateMatchMode}-term matching${bundle.candidateLimitHit ? ', and the candidate limit was reached' : ''}.`);
|
|
18
|
+
lines.push('');
|
|
19
|
+
const included = [...bundle.overview, ...bundle.selected];
|
|
20
|
+
if (included.length > 0) {
|
|
21
|
+
lines.push('## Context', '');
|
|
22
|
+
// Grouped by source, which is how a reader navigates it: one heading per document,
|
|
23
|
+
// passages in the order the assembler chose them.
|
|
24
|
+
for (const [path, items] of groupBySource(included)) {
|
|
25
|
+
lines.push(`### ${path}`, '');
|
|
26
|
+
for (const item of items) {
|
|
27
|
+
const heading = item.headingPath.length === 0 ? '' : `${item.headingPath.join(' > ')}, `;
|
|
28
|
+
const labels = item.labels.length === 0 ? '' : ` [${item.labels.join(', ')}]`;
|
|
29
|
+
lines.push(`**${heading}${lineRange(item.locator)}**${labels}`, '');
|
|
30
|
+
lines.push(item.text.trim(), '');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (bundle.alternatives.length > 0) {
|
|
35
|
+
lines.push('## Alternative relevant sources', '');
|
|
36
|
+
lines.push('These matched the task and were held back by their declared status. They are listed, not judged.', '');
|
|
37
|
+
for (const item of bundle.alternatives) {
|
|
38
|
+
const labels = item.labels.length === 0 ? '' : ` [${item.labels.join(', ')}]`;
|
|
39
|
+
lines.push(`- \`${item.locator.relativePath}\` ${lineRange(item.locator)}${labels}`);
|
|
40
|
+
}
|
|
41
|
+
lines.push('');
|
|
42
|
+
}
|
|
43
|
+
if (bundle.tables.length > 0) {
|
|
44
|
+
lines.push('## Tables', '');
|
|
45
|
+
for (const table of bundle.tables)
|
|
46
|
+
lines.push(`- ${table.name} (\`${table.tableId}\`)`);
|
|
47
|
+
lines.push('');
|
|
48
|
+
}
|
|
49
|
+
lines.push('## Citations', '');
|
|
50
|
+
for (const citation of bundle.citations) {
|
|
51
|
+
lines.push(`- \`${citation.relativePath}\` ${lineRange(citation)}`);
|
|
52
|
+
}
|
|
53
|
+
lines.push('');
|
|
54
|
+
lines.push('## What was left out', '');
|
|
55
|
+
if (bundle.omitted.length === 0) {
|
|
56
|
+
lines.push('Nothing from the candidates considered was omitted.', '');
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
lines.push(`${count(bundle.omitted.length, 'passage')} considered candidates did not fit, grouped by reason. The report covers the candidates considered above.`, '');
|
|
60
|
+
for (const [reason, items] of groupByReason(bundle.omitted)) {
|
|
61
|
+
lines.push(`**${describeReason(reason)}** (${count(items.length, 'passage')})`, '');
|
|
62
|
+
for (const item of items.slice(0, 20)) {
|
|
63
|
+
lines.push(`- \`${item.locator.relativePath}\` ${lineRange(item.locator)}, about ${count(item.estimatedTokens, 'token')}`);
|
|
64
|
+
}
|
|
65
|
+
if (items.length > 20)
|
|
66
|
+
lines.push(`- and ${count(items.length - 20, 'more passage')}`);
|
|
67
|
+
lines.push('');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
lines.push('## Getting more', '');
|
|
71
|
+
lines.push('To widen this context, raise the budget or name a profile with a larger one:', '');
|
|
72
|
+
lines.push('```bash', options.moreCommand, '```', '');
|
|
73
|
+
lines.push(`Token counts are conservative estimates from a deterministic counter, not a model tokenizer. Treat them as a bound, not a measurement.`);
|
|
74
|
+
return `${lines.join('\n').trimEnd()}\n`;
|
|
75
|
+
}
|
|
76
|
+
function groupBySource(items) {
|
|
77
|
+
const groups = new Map();
|
|
78
|
+
for (const item of items) {
|
|
79
|
+
const path = item.locator.relativePath;
|
|
80
|
+
const bucket = groups.get(path);
|
|
81
|
+
if (bucket === undefined)
|
|
82
|
+
groups.set(path, [item]);
|
|
83
|
+
else
|
|
84
|
+
bucket.push(item);
|
|
85
|
+
}
|
|
86
|
+
return [...groups.entries()];
|
|
87
|
+
}
|
|
88
|
+
function groupByReason(items) {
|
|
89
|
+
const groups = new Map();
|
|
90
|
+
for (const item of items) {
|
|
91
|
+
const bucket = groups.get(item.reason);
|
|
92
|
+
if (bucket === undefined)
|
|
93
|
+
groups.set(item.reason, [item]);
|
|
94
|
+
else
|
|
95
|
+
bucket.push(item);
|
|
96
|
+
}
|
|
97
|
+
// Sorted so the same bundle always renders the same file, which is what lets a person
|
|
98
|
+
// diff two exports and see what changed rather than what moved.
|
|
99
|
+
return [...groups.entries()].sort(([left], [right]) => (left < right ? -1 : 1));
|
|
100
|
+
}
|
|
101
|
+
function describeReason(reason) {
|
|
102
|
+
switch (reason) {
|
|
103
|
+
case 'budget':
|
|
104
|
+
return 'Did not fit in the budget';
|
|
105
|
+
case 'duplicate':
|
|
106
|
+
return 'Near-duplicate of a passage above';
|
|
107
|
+
case 'diversity':
|
|
108
|
+
return 'One document may not fill the whole bundle';
|
|
109
|
+
case 'superseded':
|
|
110
|
+
return 'Superseded by another document';
|
|
111
|
+
case 'archived':
|
|
112
|
+
return 'Archived';
|
|
113
|
+
default:
|
|
114
|
+
return 'Filtered out';
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function lineRange(locator) {
|
|
118
|
+
if (locator.page !== undefined)
|
|
119
|
+
return `page ${locator.page}`;
|
|
120
|
+
if (locator.sheet !== undefined || locator.cellRange !== undefined) {
|
|
121
|
+
return [locator.sheet, locator.cellRange].filter(Boolean).join(' ');
|
|
122
|
+
}
|
|
123
|
+
if (locator.lineStart === undefined)
|
|
124
|
+
return '';
|
|
125
|
+
return locator.lineEnd === undefined || locator.lineEnd === locator.lineStart
|
|
126
|
+
? `line ${locator.lineStart}`
|
|
127
|
+
: `lines ${locator.lineStart}-${locator.lineEnd}`;
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=export.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export.js","sourceRoot":"","sources":["../../src/services/export.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export declare const GITIGNORE_FILENAME: '.gitignore';
|
|
2
|
+
export interface InitPlan {
|
|
3
|
+
readonly projectRoot: string;
|
|
4
|
+
/** Project-relative POSIX paths this run would create or modify. */
|
|
5
|
+
readonly creates: readonly string[];
|
|
6
|
+
readonly modifies: readonly string[];
|
|
7
|
+
readonly unchanged: readonly string[];
|
|
8
|
+
readonly projectName: string;
|
|
9
|
+
readonly sources: readonly string[];
|
|
10
|
+
readonly secretShaped: readonly string[];
|
|
11
|
+
readonly alreadyInitialized: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* What `--force` would rewrite. Reporting "already initialized" without this leaves the
|
|
14
|
+
* user to guess what the escape hatch does, which is exactly when they reach for it.
|
|
15
|
+
*/
|
|
16
|
+
readonly forceWouldChange: readonly string[];
|
|
17
|
+
/** True when the existing config differs from what this run would generate. */
|
|
18
|
+
readonly configDiffers: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface InitResult extends InitPlan {
|
|
21
|
+
readonly written: readonly string[];
|
|
22
|
+
}
|
|
23
|
+
export interface InitOptions {
|
|
24
|
+
readonly directory: string;
|
|
25
|
+
readonly force?: boolean;
|
|
26
|
+
/** Reports what would change without touching the filesystem. */
|
|
27
|
+
readonly dryRun?: boolean;
|
|
28
|
+
}
|
|
29
|
+
/** Slugified directory name. Collisions are not this tool's problem in v0.1. */
|
|
30
|
+
export declare function projectNameFrom(directory: string): string;
|
|
31
|
+
export declare function renderConfig(name: string, sources: readonly string[]): string;
|
|
32
|
+
export declare function renderIgnore(): string;
|
|
33
|
+
/**
|
|
34
|
+
* Files whose names suggest credentials. Architecture section 19.2 is explicit that this
|
|
35
|
+
* is a guardrail rather than a secret scanner, so contents are never read.
|
|
36
|
+
*/
|
|
37
|
+
export declare function findSecretShaped(root: string, limit?: number): string[];
|
|
38
|
+
export declare function planInit(options: InitOptions): InitPlan;
|
|
39
|
+
/**
|
|
40
|
+
* Writes the project files. Grouped so a failure leaves nothing half-created: content is
|
|
41
|
+
* prepared first, and only then written, each one atomically.
|
|
42
|
+
*/
|
|
43
|
+
export declare function runInit(options: InitOptions): InitResult;
|
|
44
|
+
/** Guards against initializing inside an existing project by accident. */
|
|
45
|
+
export declare function enclosingProject(directory: string): string | null;
|
|
46
|
+
//# sourceMappingURL=init.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/services/init.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,kBAAkB,EAAG,YAAqB,CAAC;AAGxD,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,oEAAoE;IACpE,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAC;IACrC;;;OAGG;IACH,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7C,+EAA+E;IAC/E,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;CACjC;AAED,MAAM,WAAW,UAAW,SAAQ,QAAQ;IAC1C,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,iEAAiE;IACjE,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,gFAAgF;AAChF,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAWzD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAI7E;AAED,wBAAgB,YAAY,IAAI,MAAM,CAWrC;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,SAAO,GAAG,MAAM,EAAE,CAoCrE;AA2BD,wBAAgB,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,QAAQ,CA8DvD;AA6BD;;;GAGG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,UAAU,CAuCxD;AAED,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGjE"}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
2
|
+
import { join, relative, sep } from 'node:path';
|
|
3
|
+
import { ALWAYS_EXCLUDE, CONFIG_FILENAME, configSchema, findProjectRoot, IGNORE_FILENAME, LORE_DIRECTORY, LoreError, SECRET_SHAPED, toPosix, writeFileAtomic, } from '@lorepack/core';
|
|
4
|
+
export const GITIGNORE_FILENAME = '.gitignore';
|
|
5
|
+
const GITIGNORE_ENTRY = `${LORE_DIRECTORY}/`;
|
|
6
|
+
/** Slugified directory name. Collisions are not this tool's problem in v0.1. */
|
|
7
|
+
export function projectNameFrom(directory) {
|
|
8
|
+
const base = directory
|
|
9
|
+
.split(/[\\/]+/)
|
|
10
|
+
.filter(Boolean)
|
|
11
|
+
.at(-1) ?? 'project';
|
|
12
|
+
const cleaned = base
|
|
13
|
+
.normalize('NFC')
|
|
14
|
+
.replace(/[^a-zA-Z0-9 ._-]+/g, '-')
|
|
15
|
+
.replace(/^[-\s]+|[-\s]+$/g, '');
|
|
16
|
+
return cleaned === '' ? 'project' : cleaned;
|
|
17
|
+
}
|
|
18
|
+
export function renderConfig(name, sources) {
|
|
19
|
+
const lines = ['version: 1', `name: ${name}`, '', 'sources:'];
|
|
20
|
+
for (const source of sources)
|
|
21
|
+
lines.push(` - ${source}`);
|
|
22
|
+
return `${lines.join('\n')}\n`;
|
|
23
|
+
}
|
|
24
|
+
export function renderIgnore() {
|
|
25
|
+
return [
|
|
26
|
+
'# Paths Lorepack never reads. Patterns are gitignore-style.',
|
|
27
|
+
'# Everything here is excluded before this file is consulted; it is listed so the',
|
|
28
|
+
'# defaults are visible and can be extended.',
|
|
29
|
+
'',
|
|
30
|
+
...ALWAYS_EXCLUDE.map((pattern) => `${pattern}`),
|
|
31
|
+
'',
|
|
32
|
+
'# Add your own exclusions below.',
|
|
33
|
+
'',
|
|
34
|
+
].join('\n');
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Files whose names suggest credentials. Architecture section 19.2 is explicit that this
|
|
38
|
+
* is a guardrail rather than a secret scanner, so contents are never read.
|
|
39
|
+
*/
|
|
40
|
+
export function findSecretShaped(root, limit = 5000) {
|
|
41
|
+
const matchers = SECRET_SHAPED.map(toRegExp);
|
|
42
|
+
const found = [];
|
|
43
|
+
let visited = 0;
|
|
44
|
+
const walk = (directory) => {
|
|
45
|
+
if (visited > limit)
|
|
46
|
+
return;
|
|
47
|
+
let entries;
|
|
48
|
+
try {
|
|
49
|
+
entries = readdirSync(directory);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
for (const entry of entries.sort()) {
|
|
55
|
+
if (visited > limit)
|
|
56
|
+
return;
|
|
57
|
+
visited += 1;
|
|
58
|
+
if (entry === '.git' || entry === 'node_modules' || entry === LORE_DIRECTORY)
|
|
59
|
+
continue;
|
|
60
|
+
const full = join(directory, entry);
|
|
61
|
+
let stats;
|
|
62
|
+
try {
|
|
63
|
+
stats = statSync(full);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (stats.isDirectory()) {
|
|
69
|
+
walk(full);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if (matchers.some((matcher) => matcher.test(entry))) {
|
|
73
|
+
found.push(toPosix(relative(root, full).split(sep).join('/')));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
walk(root);
|
|
78
|
+
return found.sort();
|
|
79
|
+
}
|
|
80
|
+
function toRegExp(pattern) {
|
|
81
|
+
const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*');
|
|
82
|
+
return new RegExp(`^${escaped}$`, 'i');
|
|
83
|
+
}
|
|
84
|
+
function gitignoreNeedsEntry(path) {
|
|
85
|
+
if (!existsSync(path))
|
|
86
|
+
return true;
|
|
87
|
+
const contents = readFileSync(path, 'utf8');
|
|
88
|
+
return !contents
|
|
89
|
+
.split(/\r?\n/)
|
|
90
|
+
.map((line) => line.trim())
|
|
91
|
+
.some((line) => line === GITIGNORE_ENTRY || line === LORE_DIRECTORY);
|
|
92
|
+
}
|
|
93
|
+
/** Preserves the file's existing line ending style rather than imposing one. */
|
|
94
|
+
function appendGitignoreEntry(path) {
|
|
95
|
+
if (!existsSync(path)) {
|
|
96
|
+
return `# Lorepack build state. Commit lore.yaml, lore.lock and .loreignore instead.\n${GITIGNORE_ENTRY}\n`;
|
|
97
|
+
}
|
|
98
|
+
const contents = readFileSync(path, 'utf8');
|
|
99
|
+
const newline = contents.includes('\r\n') ? '\r\n' : '\n';
|
|
100
|
+
const separator = contents.length === 0 || contents.endsWith(newline) ? '' : newline;
|
|
101
|
+
return `${contents}${separator}${newline}# Lorepack build state${newline}${GITIGNORE_ENTRY}${newline}`;
|
|
102
|
+
}
|
|
103
|
+
export function planInit(options) {
|
|
104
|
+
const root = options.directory;
|
|
105
|
+
if (!existsSync(root)) {
|
|
106
|
+
throw new LoreError('LORE_E_INVALID_ARGUMENT', `${toPosix(root)} does not exist.`, {
|
|
107
|
+
remediation: 'Create the directory first, or point `lorepack init` at an existing one.',
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
if (!statSync(root).isDirectory()) {
|
|
111
|
+
throw new LoreError('LORE_E_INVALID_ARGUMENT', `${toPosix(root)} is not a directory.`, {
|
|
112
|
+
remediation: 'Point `lorepack init` at a directory containing your documents.',
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
const configPath = join(root, CONFIG_FILENAME);
|
|
116
|
+
const ignorePath = join(root, IGNORE_FILENAME);
|
|
117
|
+
const gitignorePath = join(root, GITIGNORE_FILENAME);
|
|
118
|
+
const creates = [];
|
|
119
|
+
const modifies = [];
|
|
120
|
+
const unchanged = [];
|
|
121
|
+
const configExists = existsSync(configPath);
|
|
122
|
+
if (!configExists)
|
|
123
|
+
creates.push(CONFIG_FILENAME);
|
|
124
|
+
else if (options.force === true)
|
|
125
|
+
modifies.push(CONFIG_FILENAME);
|
|
126
|
+
else
|
|
127
|
+
unchanged.push(CONFIG_FILENAME);
|
|
128
|
+
if (!existsSync(ignorePath))
|
|
129
|
+
creates.push(IGNORE_FILENAME);
|
|
130
|
+
else if (options.force === true)
|
|
131
|
+
modifies.push(IGNORE_FILENAME);
|
|
132
|
+
else
|
|
133
|
+
unchanged.push(IGNORE_FILENAME);
|
|
134
|
+
if (gitignoreNeedsEntry(gitignorePath)) {
|
|
135
|
+
if (existsSync(gitignorePath))
|
|
136
|
+
modifies.push(GITIGNORE_FILENAME);
|
|
137
|
+
else
|
|
138
|
+
creates.push(GITIGNORE_FILENAME);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
unchanged.push(GITIGNORE_FILENAME);
|
|
142
|
+
}
|
|
143
|
+
// An existing config keeps its name, so re-running never silently renames a project.
|
|
144
|
+
const projectName = configExists && options.force !== true ? existingName(configPath, root) : projectNameFrom(root);
|
|
145
|
+
const generated = renderConfig(projectNameFrom(root), ['.']);
|
|
146
|
+
const configDiffers = configExists && safeRead(configPath) !== generated;
|
|
147
|
+
const forceWouldChange = configExists && options.force !== true
|
|
148
|
+
? [CONFIG_FILENAME, IGNORE_FILENAME].filter((name) => existsSync(join(root, name)))
|
|
149
|
+
: [];
|
|
150
|
+
return {
|
|
151
|
+
forceWouldChange,
|
|
152
|
+
configDiffers,
|
|
153
|
+
projectRoot: root,
|
|
154
|
+
creates,
|
|
155
|
+
modifies,
|
|
156
|
+
unchanged,
|
|
157
|
+
projectName,
|
|
158
|
+
sources: ['.'],
|
|
159
|
+
secretShaped: findSecretShaped(root),
|
|
160
|
+
alreadyInitialized: configExists,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function safeRead(path) {
|
|
164
|
+
try {
|
|
165
|
+
return readFileSync(path, 'utf8');
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
function existingName(configPath, root) {
|
|
172
|
+
try {
|
|
173
|
+
const parsed = configSchema.partial().safeParse(Object.fromEntries(readFileSync(configPath, 'utf8')
|
|
174
|
+
.split(/\r?\n/)
|
|
175
|
+
.flatMap((line) => {
|
|
176
|
+
const match = /^name:\s*(.+)$/.exec(line.trim());
|
|
177
|
+
return match?.[1] === undefined ? [] : [['name', match[1].trim()]];
|
|
178
|
+
})));
|
|
179
|
+
if (parsed.success && typeof parsed.data.name === 'string')
|
|
180
|
+
return parsed.data.name;
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
// Fall through: a config we cannot read is reported by loadConfig, not here.
|
|
184
|
+
}
|
|
185
|
+
return projectNameFrom(root);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Writes the project files. Grouped so a failure leaves nothing half-created: content is
|
|
189
|
+
* prepared first, and only then written, each one atomically.
|
|
190
|
+
*/
|
|
191
|
+
export function runInit(options) {
|
|
192
|
+
const plan = planInit(options);
|
|
193
|
+
if (options.dryRun === true)
|
|
194
|
+
return { ...plan, written: [] };
|
|
195
|
+
const root = plan.projectRoot;
|
|
196
|
+
const pending = [];
|
|
197
|
+
const wants = (name) => plan.creates.includes(name) || plan.modifies.includes(name);
|
|
198
|
+
if (wants(CONFIG_FILENAME)) {
|
|
199
|
+
pending.push({
|
|
200
|
+
relativePath: CONFIG_FILENAME,
|
|
201
|
+
path: join(root, CONFIG_FILENAME),
|
|
202
|
+
contents: renderConfig(plan.projectName, plan.sources),
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
if (wants(IGNORE_FILENAME)) {
|
|
206
|
+
pending.push({
|
|
207
|
+
relativePath: IGNORE_FILENAME,
|
|
208
|
+
path: join(root, IGNORE_FILENAME),
|
|
209
|
+
contents: renderIgnore(),
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
if (wants(GITIGNORE_FILENAME)) {
|
|
213
|
+
pending.push({
|
|
214
|
+
relativePath: GITIGNORE_FILENAME,
|
|
215
|
+
path: join(root, GITIGNORE_FILENAME),
|
|
216
|
+
contents: appendGitignoreEntry(join(root, GITIGNORE_FILENAME)),
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
const written = [];
|
|
220
|
+
for (const file of pending) {
|
|
221
|
+
writeFileAtomic(file.path, file.contents);
|
|
222
|
+
written.push(file.relativePath);
|
|
223
|
+
}
|
|
224
|
+
return { ...plan, written };
|
|
225
|
+
}
|
|
226
|
+
/** Guards against initializing inside an existing project by accident. */
|
|
227
|
+
export function enclosingProject(directory) {
|
|
228
|
+
const found = findProjectRoot(directory);
|
|
229
|
+
return found === null || found === directory ? null : found;
|
|
230
|
+
}
|
|
231
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/services/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type BuildId, type LoadedConfig } from '@lorepack/core';
|
|
2
|
+
/**
|
|
3
|
+
* Writing a `.lorepack` archive, in the one place both `lorepack pack` and Studio call.
|
|
4
|
+
*
|
|
5
|
+
* Extracted from the command when Studio grew a pack button (#68). Two implementations of an
|
|
6
|
+
* archive format is how a file packed from a browser ends up subtly different from one packed
|
|
7
|
+
* in a terminal, and the difference would only be discovered by whoever tried to open it.
|
|
8
|
+
*/
|
|
9
|
+
export interface PackResult {
|
|
10
|
+
readonly buildId: BuildId;
|
|
11
|
+
readonly archive: string;
|
|
12
|
+
/** Members written, including the checksum index. */
|
|
13
|
+
readonly members: number;
|
|
14
|
+
readonly includeOriginals: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface PackOptions {
|
|
17
|
+
/** Build id or unique prefix. The active build when omitted. */
|
|
18
|
+
readonly build?: string | undefined;
|
|
19
|
+
/** Where to write. Defaults into the project root, named for the project and the build. */
|
|
20
|
+
readonly out?: string | undefined;
|
|
21
|
+
/** Base for a relative `out`. The process cwd for the CLI, the project root for Studio. */
|
|
22
|
+
readonly relativeTo?: string | undefined;
|
|
23
|
+
}
|
|
24
|
+
export declare function packBuild(config: LoadedConfig, options: PackOptions): Promise<PackResult>;
|
|
25
|
+
//# sourceMappingURL=packing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packing.d.ts","sourceRoot":"","sources":["../../src/services/packing.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,OAAO,EAAkB,KAAK,YAAY,EAAa,MAAM,gBAAgB,CAAC;AAG5F;;;;;;GAMG;AAEH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,qDAAqD;IACrD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;CACpC;AAED,MAAM,WAAW,WAAW;IAC1B,gEAAgE;IAChE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,2FAA2F;IAC3F,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,2FAA2F;IAC3F,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1C;AAED,wBAAsB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAsD/F"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { join, resolve } from 'node:path';
|
|
2
|
+
import { collectBuildMembers, collectObjects, collectOriginals, openReadOnly, writeArchive, } from '@lorepack/backend-local';
|
|
3
|
+
import { LORE_DIRECTORY, LoreError } from '@lorepack/core';
|
|
4
|
+
import { buildDirectory, openStateStore, resolveBuildId } from './builds.js';
|
|
5
|
+
export async function packBuild(config, options) {
|
|
6
|
+
const loreDirectory = join(config.projectRoot, LORE_DIRECTORY);
|
|
7
|
+
const state = openStateStore(loreDirectory);
|
|
8
|
+
try {
|
|
9
|
+
const builds = state.listBuilds();
|
|
10
|
+
const active = state.current();
|
|
11
|
+
const buildId = options.build === undefined
|
|
12
|
+
? activeOrFail(active?.buildId)
|
|
13
|
+
: resolveBuildId(builds, options.build);
|
|
14
|
+
const summary = builds.find((build) => build.buildId === buildId);
|
|
15
|
+
if (summary?.state !== 'verified' && summary?.state !== 'active') {
|
|
16
|
+
throw new LoreError('LORE_E_BUILD_VALIDATION', `Build ${buildId} is ${summary?.state ?? 'unknown'}, and only a verified build can be packed.`, {
|
|
17
|
+
remediation: 'Run `lorepack build` to produce a verified build.',
|
|
18
|
+
subject: buildId,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
const directory = buildDirectory(loreDirectory, buildId);
|
|
22
|
+
const { objectHashes, sourcePaths } = readReferences(directory);
|
|
23
|
+
const members = collectBuildMembers(directory, collectObjects(join(loreDirectory, 'objects'), objectHashes));
|
|
24
|
+
// Originals are excluded by default (section 11.2): an archive is a build, not a copy of
|
|
25
|
+
// someone's document folder, and shipping binaries by default would be a surprise the
|
|
26
|
+
// user did not ask for.
|
|
27
|
+
if (config.effective.includeOriginals) {
|
|
28
|
+
members.push(...collectOriginals(config.projectRoot, sourcePaths));
|
|
29
|
+
}
|
|
30
|
+
const destination = options.out === undefined
|
|
31
|
+
? join(config.projectRoot, `${config.config.name}-${buildId.slice(0, 17)}.lorepack`)
|
|
32
|
+
: resolve(options.relativeTo ?? config.projectRoot, options.out);
|
|
33
|
+
await writeArchive(destination, members);
|
|
34
|
+
return {
|
|
35
|
+
buildId,
|
|
36
|
+
archive: destination,
|
|
37
|
+
members: members.length + 1,
|
|
38
|
+
includeOriginals: config.effective.includeOriginals,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
state.close();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function activeOrFail(buildId) {
|
|
46
|
+
if (buildId === undefined) {
|
|
47
|
+
throw new LoreError('LORE_E_BUILD_NOT_FOUND', 'This project has no active build to pack.', {
|
|
48
|
+
remediation: 'Run `lorepack build`, or name a build.',
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
return buildId;
|
|
52
|
+
}
|
|
53
|
+
/** The objects and source paths a build references, read from the build itself. */
|
|
54
|
+
function readReferences(directory) {
|
|
55
|
+
const db = openReadOnly(join(directory, 'context.sqlite'));
|
|
56
|
+
try {
|
|
57
|
+
const rows = db
|
|
58
|
+
.prepare('SELECT object_hash AS objectHash, relative_path AS relativePath FROM artifacts')
|
|
59
|
+
.all();
|
|
60
|
+
return {
|
|
61
|
+
objectHashes: rows.map((row) => row.objectHash),
|
|
62
|
+
sourcePaths: rows.map((row) => row.relativePath),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
db.close();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=packing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packing.js","sourceRoot":"","sources":["../../src/services/packing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Chunk } from '@lorepack/compiler';
|
|
2
|
+
import type { Artifact, LoreNode, ParsedTable, ParserWarning } from '@lorepack/core';
|
|
3
|
+
/**
|
|
4
|
+
* The parse cache behind incremental builds.
|
|
5
|
+
*
|
|
6
|
+
* Keyed by `cacheKey` (architecture section 12.3), which covers content, parser identity,
|
|
7
|
+
* normalization version and the configuration that affects output. That is what makes a
|
|
8
|
+
* hit safe: anything that could change the parsed result changes the key, so a stale entry
|
|
9
|
+
* is unreachable rather than merely unlikely.
|
|
10
|
+
*
|
|
11
|
+
* The cache is an optimisation and nothing more. A corrupt, truncated or unreadable entry
|
|
12
|
+
* is treated as a miss, never as an error: a build must never fail because of a cache.
|
|
13
|
+
*/
|
|
14
|
+
export interface CachedParse {
|
|
15
|
+
readonly artifact: Artifact;
|
|
16
|
+
readonly nodes: readonly LoreNode[];
|
|
17
|
+
readonly chunks: readonly Chunk[];
|
|
18
|
+
readonly objectHash: string;
|
|
19
|
+
/**
|
|
20
|
+
* Typed tables, when the artifact produced any.
|
|
21
|
+
*
|
|
22
|
+
* Present on a fresh parse and never on a cached one, because a table-bearing parse is
|
|
23
|
+
* not written to the cache at all: the rows would be hundreds of megabytes of JSON to
|
|
24
|
+
* avoid a re-read of a file the build already has. Since nothing is written, nothing can
|
|
25
|
+
* be read back with its tables missing, which is the failure mode that would matter.
|
|
26
|
+
*/
|
|
27
|
+
readonly tables?: readonly ParsedTable[];
|
|
28
|
+
/**
|
|
29
|
+
* What the parser said about this artifact, cached alongside it.
|
|
30
|
+
*
|
|
31
|
+
* Unlike table rows these are cheap, and dropping them would make a build's warnings depend
|
|
32
|
+
* on whether the cache happened to be warm: the first build would name a flattened Word
|
|
33
|
+
* style and the second would not (#223). A warning that appears only sometimes is worse
|
|
34
|
+
* than one that never appears, because it teaches a reader that silence means nothing.
|
|
35
|
+
*/
|
|
36
|
+
readonly warnings?: readonly ParserWarning[];
|
|
37
|
+
}
|
|
38
|
+
export declare class ParseCache {
|
|
39
|
+
#private;
|
|
40
|
+
constructor(directory: string);
|
|
41
|
+
get hits(): number;
|
|
42
|
+
get misses(): number;
|
|
43
|
+
get(key: string): CachedParse | null;
|
|
44
|
+
put(key: string, value: CachedParse): void;
|
|
45
|
+
clear(): void;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=parse-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-cache.d.ts","sourceRoot":"","sources":["../../src/services/parse-cache.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGrF;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B;;;;;;;OAOG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;IACzC;;;;;;;OAOG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;CAC9C;AASD,qBAAa,UAAU;;IAKrB,YAAY,SAAS,EAAE,MAAM,EAE5B;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAyBnC;IAED,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CASzC;IAED,KAAK,IAAI,IAAI,CAEZ;CAOF"}
|