@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,203 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { openReadOnly } from '@lorepack/backend-local';
|
|
4
|
+
import { compareFingerprints, discover, fingerprintSources } from '@lorepack/compiler';
|
|
5
|
+
import { count, LORE_DIRECTORY, LoreError, } from '@lorepack/core';
|
|
6
|
+
import { readActiveBuild, readBuildCatalog } from './project.js';
|
|
7
|
+
export async function readStatus(options) {
|
|
8
|
+
const { config } = options;
|
|
9
|
+
const now = options.now ?? (() => new Date());
|
|
10
|
+
const loreDirectory = join(config.projectRoot, LORE_DIRECTORY);
|
|
11
|
+
const discovery = discover({
|
|
12
|
+
config,
|
|
13
|
+
...(options.progress === undefined ? {} : { progress: options.progress }),
|
|
14
|
+
...(options.allowLargeProject === undefined
|
|
15
|
+
? {}
|
|
16
|
+
: { allowLargeProject: options.allowLargeProject }),
|
|
17
|
+
});
|
|
18
|
+
const fingerprint = await fingerprintSources({
|
|
19
|
+
artifacts: discovery.artifacts,
|
|
20
|
+
...(options.progress === undefined ? {} : { progress: options.progress }),
|
|
21
|
+
});
|
|
22
|
+
const active = readActiveBuild(loreDirectory);
|
|
23
|
+
const previous = active === null ? null : readBuildCatalog(loreDirectory, active.buildId);
|
|
24
|
+
if (active === null || previous === null) {
|
|
25
|
+
return {
|
|
26
|
+
formatVersion: 1,
|
|
27
|
+
projectName: config.config.name,
|
|
28
|
+
activeBuildId: null,
|
|
29
|
+
activeBuildAt: null,
|
|
30
|
+
buildAgeSeconds: null,
|
|
31
|
+
sourceState: 'unbuilt',
|
|
32
|
+
decidedBy: 'content-hash',
|
|
33
|
+
artifacts: { total: fingerprint.artifacts.length, added: 0, changed: 0, removed: 0 },
|
|
34
|
+
changes: [],
|
|
35
|
+
warnings: discovery.warnings.length,
|
|
36
|
+
remediation: 'lorepack build',
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
const dirty = compareFingerprints(fingerprint.artifacts, previous.artifactHashes);
|
|
40
|
+
const pathOf = pathResolver(fingerprint.artifacts);
|
|
41
|
+
const createdAt = readBuildCreatedAt(loreDirectory, active.buildId);
|
|
42
|
+
return {
|
|
43
|
+
formatVersion: 1,
|
|
44
|
+
projectName: config.config.name,
|
|
45
|
+
activeBuildId: active.buildId,
|
|
46
|
+
activeBuildAt: createdAt,
|
|
47
|
+
buildAgeSeconds: createdAt === null
|
|
48
|
+
? null
|
|
49
|
+
: Math.max(0, Math.floor((now().getTime() - Date.parse(createdAt)) / 1000)),
|
|
50
|
+
sourceState: dirty.clean ? 'clean' : 'dirty',
|
|
51
|
+
decidedBy: 'content-hash',
|
|
52
|
+
artifacts: {
|
|
53
|
+
total: fingerprint.artifacts.length,
|
|
54
|
+
added: dirty.added.length,
|
|
55
|
+
changed: dirty.changed.length,
|
|
56
|
+
removed: dirty.removed.length,
|
|
57
|
+
},
|
|
58
|
+
changes: [
|
|
59
|
+
...dirty.added.map((id) => ({ path: pathOf(id), change: 'added' })),
|
|
60
|
+
...dirty.changed.map((id) => ({ path: pathOf(id), change: 'changed' })),
|
|
61
|
+
...dirty.removed.map((id) => ({ path: pathOf(id), change: 'removed' })),
|
|
62
|
+
].sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0)),
|
|
63
|
+
warnings: countBuildWarnings(loreDirectory, active.buildId) ?? discovery.warnings.length,
|
|
64
|
+
remediation: dirty.clean ? null : 'lorepack build',
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Freshness for a read-only command: an annotation on the answer, never a precondition
|
|
69
|
+
* for it.
|
|
70
|
+
*
|
|
71
|
+
* Section 4.10 says freshness travels with the result, and it is tempting to read that as
|
|
72
|
+
* "establish it or fail". That reading cost `lorepack search` its usefulness on any project
|
|
73
|
+
* above the file envelope: the build existed and was perfectly queryable, and the query was
|
|
74
|
+
* refused because a guard about the cost of *building* had been consulted first (#147). A
|
|
75
|
+
* read of a sealed build is not entitled to have an opinion about the source tree.
|
|
76
|
+
*
|
|
77
|
+
* So two things differ from `readStatus`:
|
|
78
|
+
*
|
|
79
|
+
* - **The envelope does not apply.** It bounds what Lorepack promises about build
|
|
80
|
+
* performance, not what it will answer from a build it already made.
|
|
81
|
+
* - **Nothing here can fail the command.** A source tree that is enormous, unreadable or
|
|
82
|
+
* gone leaves freshness `unknown`, which is precisely what the contract's third state
|
|
83
|
+
* means, and the caller still gets the build's answer.
|
|
84
|
+
*
|
|
85
|
+
* Invariant 6 applies to the degraded case too: `unknown` says Lorepack does not know, and
|
|
86
|
+
* never that the sources are clean.
|
|
87
|
+
*/
|
|
88
|
+
export async function readFreshness(options) {
|
|
89
|
+
try {
|
|
90
|
+
const status = await readStatus({ ...options, allowLargeProject: true });
|
|
91
|
+
return {
|
|
92
|
+
sourceState: status.sourceState === 'unbuilt' ? 'unknown' : status.sourceState,
|
|
93
|
+
reason: null,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
const degraded = degradedFreshness(error);
|
|
98
|
+
if (degraded === null)
|
|
99
|
+
throw error;
|
|
100
|
+
return degraded;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Which failures are allowed to become `unknown`, and which must still be raised.
|
|
105
|
+
*
|
|
106
|
+
* An allowlist rather than a bare `catch`. Swallowing everything would turn a corrupt
|
|
107
|
+
* state database into the cheerful and false statement "freshness unknown", which is the
|
|
108
|
+
* kind of helpfulness that hides a real defect for a phase or two. These three all mean
|
|
109
|
+
* "something about the source tree stopped us looking", and none of them says anything
|
|
110
|
+
* about whether the build being read is sound.
|
|
111
|
+
*/
|
|
112
|
+
export function degradedFreshness(error) {
|
|
113
|
+
if (!(error instanceof LoreError))
|
|
114
|
+
return null;
|
|
115
|
+
const degradable = new Set([
|
|
116
|
+
'LORE_E_ENVELOPE_EXCEEDED',
|
|
117
|
+
'LORE_E_PATH_ESCAPE',
|
|
118
|
+
'LORE_E_CASE_COLLISION',
|
|
119
|
+
]);
|
|
120
|
+
if (!degradable.has(error.code))
|
|
121
|
+
return null;
|
|
122
|
+
return { sourceState: 'unknown', reason: error.message };
|
|
123
|
+
}
|
|
124
|
+
function pathResolver(artifacts) {
|
|
125
|
+
const byId = new Map(artifacts.map((artifact) => [artifact.artifactId, artifact.relativePath]));
|
|
126
|
+
// A removed artifact is no longer on disk, so its path comes from the id, which carries
|
|
127
|
+
// the source name and the relative path by construction.
|
|
128
|
+
return (artifactId) => byId.get(artifactId) ?? artifactId.split(':').slice(1).join(':');
|
|
129
|
+
}
|
|
130
|
+
function readBuildCreatedAt(loreDirectory, buildId) {
|
|
131
|
+
const statePath = join(loreDirectory, 'state.sqlite');
|
|
132
|
+
if (!existsSync(statePath))
|
|
133
|
+
return null;
|
|
134
|
+
const db = openReadOnly(statePath);
|
|
135
|
+
try {
|
|
136
|
+
const row = db.prepare('SELECT created_at FROM builds WHERE build_id = ?').get(buildId);
|
|
137
|
+
return row?.created_at ?? null;
|
|
138
|
+
}
|
|
139
|
+
finally {
|
|
140
|
+
db.close();
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/** Warnings as the active build recorded them, which is what the AI is actually reading. */
|
|
144
|
+
function countBuildWarnings(loreDirectory, buildId) {
|
|
145
|
+
const path = join(loreDirectory, 'builds', buildId, 'context.sqlite');
|
|
146
|
+
if (!existsSync(path))
|
|
147
|
+
return null;
|
|
148
|
+
const db = openReadOnly(path);
|
|
149
|
+
try {
|
|
150
|
+
const row = db.prepare('SELECT count(*) AS n FROM build_warnings').get();
|
|
151
|
+
return Number(row.n);
|
|
152
|
+
}
|
|
153
|
+
finally {
|
|
154
|
+
db.close();
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
export function renderStatus(status, verbose) {
|
|
158
|
+
const lines = [`Project ${status.projectName}`];
|
|
159
|
+
if (status.activeBuildId === null) {
|
|
160
|
+
lines.push('');
|
|
161
|
+
lines.push('No build yet.');
|
|
162
|
+
lines.push(` ${count(status.artifacts.total, 'source file')} found`);
|
|
163
|
+
lines.push('');
|
|
164
|
+
lines.push('Run `lorepack build` to compile and activate the first build.');
|
|
165
|
+
return lines.join('\n');
|
|
166
|
+
}
|
|
167
|
+
lines.push(`Active build ${status.activeBuildId.slice(0, 17)} (${formatAge(status.buildAgeSeconds)})`);
|
|
168
|
+
lines.push('');
|
|
169
|
+
lines.push(status.sourceState === 'clean'
|
|
170
|
+
? `Sources are clean. ${count(status.artifacts.total, 'artifact')}, decided by content hash.`
|
|
171
|
+
: `Sources are dirty: ${status.artifacts.added} added, ${status.artifacts.changed} changed, ${status.artifacts.removed} removed.`);
|
|
172
|
+
if (verbose && status.changes.length > 0) {
|
|
173
|
+
lines.push('');
|
|
174
|
+
for (const kind of ['added', 'changed', 'removed']) {
|
|
175
|
+
const paths = status.changes.filter((change) => change.change === kind);
|
|
176
|
+
if (paths.length === 0)
|
|
177
|
+
continue;
|
|
178
|
+
lines.push(`${kind}:`);
|
|
179
|
+
for (const change of paths)
|
|
180
|
+
lines.push(` ${change.path}`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
if (status.warnings > 0) {
|
|
184
|
+
lines.push(`${count(status.warnings, 'warning')} in the active build.`);
|
|
185
|
+
}
|
|
186
|
+
if (status.remediation !== null) {
|
|
187
|
+
lines.push('');
|
|
188
|
+
lines.push(`Run \`${status.remediation}\` to make the active context current.`);
|
|
189
|
+
}
|
|
190
|
+
return lines.join('\n');
|
|
191
|
+
}
|
|
192
|
+
function formatAge(seconds) {
|
|
193
|
+
if (seconds === null)
|
|
194
|
+
return 'age unknown';
|
|
195
|
+
if (seconds < 60)
|
|
196
|
+
return `${seconds}s ago`;
|
|
197
|
+
if (seconds < 3600)
|
|
198
|
+
return `${Math.floor(seconds / 60)}m ago`;
|
|
199
|
+
if (seconds < 86400)
|
|
200
|
+
return `${Math.floor(seconds / 3600)}h ago`;
|
|
201
|
+
return `${Math.floor(seconds / 86400)}d ago`;
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/services/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Where `vite build` writes, relative to this module once compiled into `dist/`. */
|
|
2
|
+
export declare function studioRoot(): string;
|
|
3
|
+
export declare function studioIsBuilt(root?: string): boolean;
|
|
4
|
+
export type AssetHandler = (request: Request) => Response | null;
|
|
5
|
+
/**
|
|
6
|
+
* Reads one file per request, or returns null so the caller's typed 404 still applies.
|
|
7
|
+
*
|
|
8
|
+
* Files are read rather than held in memory: this serves one developer on loopback, the
|
|
9
|
+
* whole bundle is a few hundred kilobytes, and the operating system's page cache is better
|
|
10
|
+
* at this than a hand-rolled map would be.
|
|
11
|
+
*/
|
|
12
|
+
export declare function createStudioAssets(root?: string): AssetHandler;
|
|
13
|
+
//# sourceMappingURL=studio-assets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"studio-assets.d.ts","sourceRoot":"","sources":["../../src/services/studio-assets.ts"],"names":[],"mappings":"AA6BA,qFAAqF;AACrF,wBAAgB,UAAU,IAAI,MAAM,CAKnC;AAED,wBAAgB,aAAa,CAAC,IAAI,GAAE,MAAqB,GAAG,OAAO,CAElE;AAED,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,QAAQ,GAAG,IAAI,CAAC;AAEjE;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,MAAqB,GAAG,YAAY,CAqB5E"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
2
|
+
import { dirname, extname, join, normalize, resolve, sep } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
/**
|
|
5
|
+
* Serving Studio's built assets from the package, with no network involved.
|
|
6
|
+
*
|
|
7
|
+
* Architecture 4.3 and 15.1: one process, one port, and the app works with the network
|
|
8
|
+
* disabled. So the assets are files inside the published CLI package, read from disk and
|
|
9
|
+
* handed to the same Hono app that answers `/v1`. There is no CDN, no asset host, and
|
|
10
|
+
* nothing to configure.
|
|
11
|
+
*
|
|
12
|
+
* This lives in the CLI rather than in `@lorepack/runtime` because reading a filesystem is a
|
|
13
|
+
* Node concern and that package also has to compile for a Worker. `createApiApp` takes it as
|
|
14
|
+
* an injected function for exactly that reason.
|
|
15
|
+
*/
|
|
16
|
+
const MEDIA_TYPES = {
|
|
17
|
+
'.html': 'text/html; charset=utf-8',
|
|
18
|
+
'.js': 'text/javascript; charset=utf-8',
|
|
19
|
+
'.css': 'text/css; charset=utf-8',
|
|
20
|
+
'.woff2': 'font/woff2',
|
|
21
|
+
'.svg': 'image/svg+xml',
|
|
22
|
+
'.png': 'image/png',
|
|
23
|
+
'.ico': 'image/x-icon',
|
|
24
|
+
'.json': 'application/json; charset=utf-8',
|
|
25
|
+
'.map': 'application/json; charset=utf-8',
|
|
26
|
+
};
|
|
27
|
+
/** Where `vite build` writes, relative to this module once compiled into `dist/`. */
|
|
28
|
+
export function studioRoot() {
|
|
29
|
+
const moduleDirectory = dirname(fileURLToPath(import.meta.url));
|
|
30
|
+
const bundledPath = resolve(moduleDirectory, '..', 'studio-dist');
|
|
31
|
+
if (existsSync(join(bundledPath, 'index.html')))
|
|
32
|
+
return bundledPath;
|
|
33
|
+
return resolve(moduleDirectory, '..', '..', 'studio-dist');
|
|
34
|
+
}
|
|
35
|
+
export function studioIsBuilt(root = studioRoot()) {
|
|
36
|
+
return existsSync(join(root, 'index.html'));
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Reads one file per request, or returns null so the caller's typed 404 still applies.
|
|
40
|
+
*
|
|
41
|
+
* Files are read rather than held in memory: this serves one developer on loopback, the
|
|
42
|
+
* whole bundle is a few hundred kilobytes, and the operating system's page cache is better
|
|
43
|
+
* at this than a hand-rolled map would be.
|
|
44
|
+
*/
|
|
45
|
+
export function createStudioAssets(root = studioRoot()) {
|
|
46
|
+
const index = join(root, 'index.html');
|
|
47
|
+
return (request) => {
|
|
48
|
+
if (!existsSync(index))
|
|
49
|
+
return null;
|
|
50
|
+
const url = new URL(request.url);
|
|
51
|
+
const decoded = safePath(root, url.pathname);
|
|
52
|
+
// Outside the asset root. Not dangerous so much as meaningless, but it is the one thing
|
|
53
|
+
// a static file server must never get wrong, so it is refused rather than clamped.
|
|
54
|
+
if (decoded === null)
|
|
55
|
+
return null;
|
|
56
|
+
if (decoded !== null && existsSync(decoded) && statSync(decoded).isFile()) {
|
|
57
|
+
return file(decoded);
|
|
58
|
+
}
|
|
59
|
+
// A hash route, so every path that is not a file is the app itself. `/v1` and `/mcp` are
|
|
60
|
+
// registered before this handler and never reach it.
|
|
61
|
+
return file(index);
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function safePath(root, pathname) {
|
|
65
|
+
let decoded;
|
|
66
|
+
try {
|
|
67
|
+
decoded = decodeURIComponent(pathname);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
if (decoded.includes('\0'))
|
|
73
|
+
return null;
|
|
74
|
+
const candidate = normalize(join(root, decoded));
|
|
75
|
+
// `normalize` resolves `..` first, so this comparison is what actually contains the read.
|
|
76
|
+
if (candidate !== root && !candidate.startsWith(root + sep))
|
|
77
|
+
return null;
|
|
78
|
+
return candidate;
|
|
79
|
+
}
|
|
80
|
+
function file(path) {
|
|
81
|
+
const body = readFileSync(path);
|
|
82
|
+
const type = MEDIA_TYPES[extname(path).toLowerCase()] ?? 'application/octet-stream';
|
|
83
|
+
return new Response(new Uint8Array(body), {
|
|
84
|
+
headers: {
|
|
85
|
+
'content-type': type,
|
|
86
|
+
// Vite fingerprints every asset except the entry document, so those are immutable and
|
|
87
|
+
// the document must never be.
|
|
88
|
+
'cache-control': path.endsWith('index.html')
|
|
89
|
+
? 'no-cache'
|
|
90
|
+
: 'public, max-age=31536000, immutable',
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=studio-assets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"studio-assets.js","sourceRoot":"","sources":["../../src/services/studio-assets.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { LoadedConfig } from '@lorepack/core';
|
|
2
|
+
import type { WatchStatus } from './watch.js';
|
|
3
|
+
/**
|
|
4
|
+
* Everything `lorepack doctor` knows, plus what only a running session can know.
|
|
5
|
+
*
|
|
6
|
+
* The checks are not reimplemented here and never will be. `runDoctor` produces the same
|
|
7
|
+
* report the CLI prints, validated against the same published schema
|
|
8
|
+
* (`schemas/doctor-report.json`), and this composes it with three things a one-shot command
|
|
9
|
+
* cannot see: the live watcher, the process serving the request, and which clients are
|
|
10
|
+
* currently wired to this project.
|
|
11
|
+
*
|
|
12
|
+
* Read-only apart from doctor's own temporary in-memory FTS5 probe. Opening a diagnostics
|
|
13
|
+
* page must never be a side effect, which is also why client status reads configuration files
|
|
14
|
+
* rather than spawning anything.
|
|
15
|
+
*/
|
|
16
|
+
export interface DiagnosticsInput {
|
|
17
|
+
readonly config: LoadedConfig;
|
|
18
|
+
readonly host: string;
|
|
19
|
+
/** A function, because the port is chosen by binding and is not known before then. */
|
|
20
|
+
readonly port: () => number;
|
|
21
|
+
readonly startedAt: string;
|
|
22
|
+
/** Present when a watcher is running, which is `lorepack dev` and not `lorepack serve`. */
|
|
23
|
+
readonly watchStatus?: () => WatchStatus;
|
|
24
|
+
}
|
|
25
|
+
export declare function createDiagnosticsEndpoint(input: DiagnosticsInput): () => Promise<unknown>;
|
|
26
|
+
/** Exported for the tests, which assert the endpoint answers for every registered client. */
|
|
27
|
+
export declare const KNOWN_CLIENT_IDS: readonly string[];
|
|
28
|
+
//# sourceMappingURL=studio-diagnostics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"studio-diagnostics.d.ts","sourceRoot":"","sources":["../../src/services/studio-diagnostics.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAgB,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAGjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,sFAAsF;IACtF,QAAQ,CAAC,IAAI,EAAE,MAAM,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,2FAA2F;IAC3F,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,WAAW,CAAC;CAC1C;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAuBzF;AAiED,6FAA6F;AAC7F,eAAO,MAAM,gBAAgB,EAAE,SAAS,MAAM,EAA0C,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { arch, platform, release } from 'node:os';
|
|
2
|
+
import { probeFts5 } from '@lorepack/backend-local';
|
|
3
|
+
import { CLAUDE_CODE_ID, CODEX_ID, createClaudeCodeConnector, createCodexConnector, createVsCodeConnector, SERVER_NAME, VSCODE_ID, } from '@lorepack/connect-clients';
|
|
4
|
+
import { runDoctor } from './doctor.js';
|
|
5
|
+
import { COMPILER_VERSION } from './versions.js';
|
|
6
|
+
export function createDiagnosticsEndpoint(input) {
|
|
7
|
+
return async () => {
|
|
8
|
+
const doctor = await runDoctor({
|
|
9
|
+
cwd: input.config.projectRoot,
|
|
10
|
+
port: input.port(),
|
|
11
|
+
// This process is the one holding that port, so "in use" is the expected answer here
|
|
12
|
+
// rather than a warning about someone else's server.
|
|
13
|
+
portHeldByThisProject: true,
|
|
14
|
+
});
|
|
15
|
+
return {
|
|
16
|
+
doctor,
|
|
17
|
+
environment: environment(),
|
|
18
|
+
session: {
|
|
19
|
+
host: input.host,
|
|
20
|
+
port: input.port(),
|
|
21
|
+
pid: process.pid,
|
|
22
|
+
startedAt: input.startedAt,
|
|
23
|
+
watcher: input.watchStatus?.() ?? null,
|
|
24
|
+
},
|
|
25
|
+
clients: await clients(input.config),
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The facts that describe this machine rather than this project.
|
|
31
|
+
*
|
|
32
|
+
* Duplicated in part by individual doctor checks, and deliberately: a check answers "is this
|
|
33
|
+
* a problem", and these answer "what am I running on", which is the first thing anyone pastes
|
|
34
|
+
* into a bug report.
|
|
35
|
+
*/
|
|
36
|
+
function environment() {
|
|
37
|
+
const probe = probeFts5();
|
|
38
|
+
return {
|
|
39
|
+
node: process.version,
|
|
40
|
+
platform: `${platform()} ${release()}`,
|
|
41
|
+
arch: arch(),
|
|
42
|
+
sqlite: probe.sqliteVersion,
|
|
43
|
+
fts5: probe.available,
|
|
44
|
+
lorepack: COMPILER_VERSION,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Which AI clients are installed, and whether this project is wired into them.
|
|
49
|
+
*
|
|
50
|
+
* Registration is explicit (architecture 4.8), so this list is the list of connectors that
|
|
51
|
+
* exist, not a discovery. It reports paths and booleans and never the contents of a
|
|
52
|
+
* configuration file, which is what keeps a credential in someone's `.claude.json` off this
|
|
53
|
+
* page (section 15.6).
|
|
54
|
+
*/
|
|
55
|
+
async function clients(config) {
|
|
56
|
+
const connectors = [createClaudeCodeConnector(), createCodexConnector(), createVsCodeConnector()];
|
|
57
|
+
const input = {
|
|
58
|
+
projectRoot: config.projectRoot,
|
|
59
|
+
serverName: SERVER_NAME,
|
|
60
|
+
command: {
|
|
61
|
+
executable: 'lorepack',
|
|
62
|
+
args: ['mcp', '--project', config.projectRoot, '--ensure-current'],
|
|
63
|
+
},
|
|
64
|
+
scope: 'project',
|
|
65
|
+
};
|
|
66
|
+
return Promise.all(connectors.map(async (connector) => {
|
|
67
|
+
try {
|
|
68
|
+
return { id: connector.id, title: connector.title, ...(await connector.status(input)) };
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
// A client that cannot be inspected is reported as one, because a Diagnostics page
|
|
72
|
+
// that failed entirely because one adapter threw would hide the nine things that
|
|
73
|
+
// were fine.
|
|
74
|
+
return {
|
|
75
|
+
id: connector.id,
|
|
76
|
+
title: connector.title,
|
|
77
|
+
installed: false,
|
|
78
|
+
supported: false,
|
|
79
|
+
configured: false,
|
|
80
|
+
ownedByLorepack: false,
|
|
81
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
}));
|
|
85
|
+
}
|
|
86
|
+
/** Exported for the tests, which assert the endpoint answers for every registered client. */
|
|
87
|
+
export const KNOWN_CLIENT_IDS = [CLAUDE_CODE_ID, CODEX_ID, VSCODE_ID];
|
|
88
|
+
//# sourceMappingURL=studio-diagnostics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"studio-diagnostics.js","sourceRoot":"","sources":["../../src/services/studio-diagnostics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type BuildExclusion, type BuildWarning, type LoadedConfig } from '@lorepack/core';
|
|
2
|
+
/**
|
|
3
|
+
* The reads Studio needs that are not runtime capabilities.
|
|
4
|
+
*
|
|
5
|
+
* Architecture 13.1 fixes `LoreRuntime` at seven capabilities, and every one of them reads
|
|
6
|
+
* the **active build**. A plan reads the **source tree**, and warnings are a property of a
|
|
7
|
+
* build's manifest rather than a query against its content. Neither belongs in that
|
|
8
|
+
* interface, and adding them would change what every backend has to implement, including the
|
|
9
|
+
* Phase 6 Worker that has no sources to plan against.
|
|
10
|
+
*
|
|
11
|
+
* So they are injected host functions on `createApiApp`, exactly like `currentBuild`. A
|
|
12
|
+
* deployment that cannot answer simply does not register the route.
|
|
13
|
+
*
|
|
14
|
+
* Both call the same code the CLI calls, so `lorepack plan` and Studio can never disagree.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* What a rebuild would change.
|
|
18
|
+
*
|
|
19
|
+
* Progress goes to a bus nobody is subscribed to. The CLI renders a stage table here because
|
|
20
|
+
* a person is watching a terminal; an HTTP caller gets one JSON answer when it is ready, and
|
|
21
|
+
* a half-rendered progress stream would be noise in it.
|
|
22
|
+
*/
|
|
23
|
+
export declare function createPlanEndpoint(config: LoadedConfig): () => Promise<unknown>;
|
|
24
|
+
export interface WarningGroup {
|
|
25
|
+
readonly class: BuildWarning['class'];
|
|
26
|
+
readonly count: number;
|
|
27
|
+
readonly warnings: readonly BuildWarning[];
|
|
28
|
+
}
|
|
29
|
+
export interface WarningSummary {
|
|
30
|
+
readonly buildId: string;
|
|
31
|
+
readonly total: number;
|
|
32
|
+
readonly groups: readonly WarningGroup[];
|
|
33
|
+
/**
|
|
34
|
+
* What ignore rules removed, or `null` for a build made before the record existed.
|
|
35
|
+
*
|
|
36
|
+
* `null` and `[]` are different claims and the interfaces render them differently: one is
|
|
37
|
+
* "this build does not know", the other is "no rule removed anything". Collapsing them
|
|
38
|
+
* would be the same defect this field exists to fix, one level down.
|
|
39
|
+
*/
|
|
40
|
+
readonly exclusions: readonly BuildExclusion[] | null;
|
|
41
|
+
/** Paths removed by a rule, which is not the same number as the number of rules. */
|
|
42
|
+
readonly excludedByRule: number | null;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Everything the build left out, in one answer.
|
|
46
|
+
*
|
|
47
|
+
* Two different things are "not in the build" and a reader looking for a missing document
|
|
48
|
+
* does not know which they have: a file with no parser, which produces a warning, and a file
|
|
49
|
+
* an ignore rule removed, which produces nothing at all until #202. They arrive together so
|
|
50
|
+
* that no client has to fetch two endpoints and decide how to add them up, which is how two
|
|
51
|
+
* surfaces come to count the same thing differently.
|
|
52
|
+
*
|
|
53
|
+
* Grouped on the server for the same reason: a client that receives a flat list has to invent
|
|
54
|
+
* the grouping.
|
|
55
|
+
*/
|
|
56
|
+
export declare function createWarningsEndpoint(read: () => Promise<{
|
|
57
|
+
buildId: string;
|
|
58
|
+
warnings: readonly BuildWarning[];
|
|
59
|
+
exclusions?: readonly BuildExclusion[];
|
|
60
|
+
}>): () => Promise<WarningSummary>;
|
|
61
|
+
//# sourceMappingURL=studio-endpoints.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"studio-endpoints.d.ts","sourceRoot":"","sources":["../../src/services/studio-endpoints.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,YAAY,EAElB,MAAM,gBAAgB,CAAC;AAIxB;;;;;;;;;;;;;GAaG;AAEH;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAmB/E;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAC;CAC5C;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,CAAC;IACzC;;;;;;OAMG;IACH,QAAQ,CAAC,UAAU,EAAE,SAAS,cAAc,EAAE,GAAG,IAAI,CAAC;IACtD,oFAAoF;IACpF,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CACxC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAC;IAClC,UAAU,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;CACxC,CAAC,GACD,MAAM,OAAO,CAAC,cAAc,CAAC,CA8B/B"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { createPlan, readLockfile } from '@lorepack/compiler';
|
|
2
|
+
import { ProgressBus, } from '@lorepack/core';
|
|
3
|
+
import { readPreviousBuild } from './project.js';
|
|
4
|
+
import { lockInputs } from './versions.js';
|
|
5
|
+
/**
|
|
6
|
+
* The reads Studio needs that are not runtime capabilities.
|
|
7
|
+
*
|
|
8
|
+
* Architecture 13.1 fixes `LoreRuntime` at seven capabilities, and every one of them reads
|
|
9
|
+
* the **active build**. A plan reads the **source tree**, and warnings are a property of a
|
|
10
|
+
* build's manifest rather than a query against its content. Neither belongs in that
|
|
11
|
+
* interface, and adding them would change what every backend has to implement, including the
|
|
12
|
+
* Phase 6 Worker that has no sources to plan against.
|
|
13
|
+
*
|
|
14
|
+
* So they are injected host functions on `createApiApp`, exactly like `currentBuild`. A
|
|
15
|
+
* deployment that cannot answer simply does not register the route.
|
|
16
|
+
*
|
|
17
|
+
* Both call the same code the CLI calls, so `lorepack plan` and Studio can never disagree.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* What a rebuild would change.
|
|
21
|
+
*
|
|
22
|
+
* Progress goes to a bus nobody is subscribed to. The CLI renders a stage table here because
|
|
23
|
+
* a person is watching a terminal; an HTTP caller gets one JSON answer when it is ready, and
|
|
24
|
+
* a half-rendered progress stream would be noise in it.
|
|
25
|
+
*/
|
|
26
|
+
export function createPlanEndpoint(config) {
|
|
27
|
+
return async () => {
|
|
28
|
+
// `readPreviousBuild` reads the pointer without opening the state store for writing, so
|
|
29
|
+
// there is no handle to release here and a plan cannot block a build.
|
|
30
|
+
const { previous } = readPreviousBuild(config);
|
|
31
|
+
{
|
|
32
|
+
const { plan } = await createPlan({
|
|
33
|
+
config,
|
|
34
|
+
previous,
|
|
35
|
+
previousLock: readLockfile(config.projectRoot),
|
|
36
|
+
lockInputs: lockInputs(),
|
|
37
|
+
progress: new ProgressBus(),
|
|
38
|
+
// A person asking Studio what a rebuild would change wants an answer, not a refusal
|
|
39
|
+
// about the envelope. The build itself still enforces it.
|
|
40
|
+
allowLargeProject: true,
|
|
41
|
+
});
|
|
42
|
+
return plan;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Everything the build left out, in one answer.
|
|
48
|
+
*
|
|
49
|
+
* Two different things are "not in the build" and a reader looking for a missing document
|
|
50
|
+
* does not know which they have: a file with no parser, which produces a warning, and a file
|
|
51
|
+
* an ignore rule removed, which produces nothing at all until #202. They arrive together so
|
|
52
|
+
* that no client has to fetch two endpoints and decide how to add them up, which is how two
|
|
53
|
+
* surfaces come to count the same thing differently.
|
|
54
|
+
*
|
|
55
|
+
* Grouped on the server for the same reason: a client that receives a flat list has to invent
|
|
56
|
+
* the grouping.
|
|
57
|
+
*/
|
|
58
|
+
export function createWarningsEndpoint(read) {
|
|
59
|
+
return async () => {
|
|
60
|
+
const { buildId, warnings, exclusions } = await read();
|
|
61
|
+
const byClass = new Map();
|
|
62
|
+
for (const warning of warnings) {
|
|
63
|
+
const existing = byClass.get(warning.class);
|
|
64
|
+
if (existing === undefined)
|
|
65
|
+
byClass.set(warning.class, [warning]);
|
|
66
|
+
else
|
|
67
|
+
existing.push(warning);
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
buildId,
|
|
71
|
+
total: warnings.length,
|
|
72
|
+
exclusions: exclusions ?? null,
|
|
73
|
+
excludedByRule: exclusions === undefined
|
|
74
|
+
? null
|
|
75
|
+
: exclusions.reduce((sum, exclusion) => sum + exclusion.count, 0),
|
|
76
|
+
// Sorted by count, then by name, so the display order is stable across requests and
|
|
77
|
+
// the largest group is where the eye lands first.
|
|
78
|
+
groups: [...byClass.entries()]
|
|
79
|
+
.map(([warningClass, group]) => ({
|
|
80
|
+
class: warningClass,
|
|
81
|
+
count: group.length,
|
|
82
|
+
warnings: group,
|
|
83
|
+
}))
|
|
84
|
+
.sort((left, right) => right.count - left.count || left.class.localeCompare(right.class)),
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=studio-endpoints.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"studio-endpoints.js","sourceRoot":"","sources":["../../src/services/studio-endpoints.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAIL,WAAW,GACZ,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C;;;;;;;;;;;;;GAaG;AAEH;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAoB;IACrD,OAAO,KAAK,IAAI,EAAE;QAChB,wFAAwF;QACxF,sEAAsE;QACtE,MAAM,EAAE,QAAQ,EAAE,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAC/C,CAAC;YACC,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,UAAU,CAAC;gBAChC,MAAM;gBACN,QAAQ;gBACR,YAAY,EAAE,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC;gBAC9C,UAAU,EAAE,UAAU,EAAE;gBACxB,QAAQ,EAAE,IAAI,WAAW,EAAE;gBAC3B,oFAAoF;gBACpF,0DAA0D;gBAC1D,iBAAiB,EAAE,IAAI;aACxB,CAAC,CAAC;YACH,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAwBD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,sBAAsB,CACpC,IAIE;IAEF,OAAO,KAAK,IAAI,EAAE;QAChB,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;QAEvD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAyC,CAAC;QACjE,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAC5C,IAAI,QAAQ,KAAK,SAAS;gBAAE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;;gBAC7D,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9B,CAAC;QAED,OAAO;YACL,OAAO;YACP,KAAK,EAAE,QAAQ,CAAC,MAAM;YACtB,UAAU,EAAE,UAAU,IAAI,IAAI;YAC9B,cAAc,EACZ,UAAU,KAAK,SAAS;gBACtB,CAAC,CAAC,IAAI;gBACN,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,GAAG,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC;YACrE,oFAAoF;YACpF,kDAAkD;YAClD,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;iBAC3B,GAAG,CAAC,CAAC,CAAC,YAAY,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC/B,KAAK,EAAE,YAAY;gBACnB,KAAK,EAAE,KAAK,CAAC,MAAM;gBACnB,QAAQ,EAAE,KAAK;aAChB,CAAC,CAAC;iBACF,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;SAC5F,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
|