@reshotdev/screenshot 0.0.1-beta.2 → 0.0.1-beta.20
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/LICENSE +1 -1
- package/README.md +138 -47
- package/package.json +27 -16
- package/src/commands/auth.js +159 -30
- package/src/commands/capture-dom.js +50 -0
- package/src/commands/certify.js +62 -0
- package/src/commands/compose.js +220 -0
- package/src/commands/doctor-release.js +74 -0
- package/src/commands/doctor-target.js +108 -0
- package/src/commands/drifts.js +16 -69
- package/src/commands/import-tests.js +13 -13
- package/src/commands/init.js +16 -277
- package/src/commands/publish.js +484 -257
- package/src/commands/pull.js +302 -35
- package/src/commands/refresh.js +166 -0
- package/src/commands/run.js +292 -12
- package/src/commands/setup-wizard.js +348 -496
- package/src/commands/status.js +334 -126
- package/src/commands/sync.js +28 -236
- package/src/commands/ui.js +1 -1
- package/src/commands/variation.js +194 -0
- package/src/commands/verify-publish.js +46 -0
- package/src/index.js +383 -118
- package/src/lib/api-client.js +172 -60
- package/src/lib/auto-update/refresh.js +598 -0
- package/src/lib/auto-update/scene-runtime.compose.tsx +73 -0
- package/src/lib/auto-update/spec.js +89 -0
- package/src/lib/capture-engine.js +179 -9
- package/src/lib/capture-script-runner.js +639 -214
- package/src/lib/certification.js +887 -0
- package/src/lib/compose-context.js +156 -0
- package/src/lib/compose-pack.js +42 -0
- package/src/lib/compose-runtime.js +34 -0
- package/src/lib/compose-upload.js +142 -0
- package/src/lib/config.js +186 -81
- package/src/lib/dom-capture.js +64 -0
- package/src/lib/ensure-browser.js +147 -0
- package/src/lib/output-path-template.js +3 -3
- package/src/lib/record-cdp.js +288 -16
- package/src/lib/record-clip.js +83 -3
- package/src/lib/record-config.js +1 -5
- package/src/lib/release-doctor.js +321 -0
- package/src/lib/resolve-targets.js +60 -0
- package/src/lib/run-manifest.js +148 -0
- package/src/lib/standalone-mode.js +1 -1
- package/src/lib/storage-providers.js +5 -5
- package/src/lib/style-engine.js +5 -5
- package/src/lib/target-contract.js +292 -0
- package/src/lib/ui-api-helpers.js +118 -0
- package/src/lib/ui-api.js +31 -824
- package/src/lib/ui-asset-cleanup.js +62 -0
- package/src/lib/ui-output-versions.js +165 -0
- package/src/lib/ui-recorder-routes.js +341 -0
- package/src/lib/ui-scenario-metadata.js +161 -0
- package/vendor/compose/dist/auto-update.cjs +5544 -0
- package/vendor/compose/dist/auto-update.mjs +5518 -0
- package/vendor/compose/dist/capture.cjs +1450 -0
- package/vendor/compose/dist/capture.mjs +1416 -0
- package/vendor/compose/dist/eligibility.cjs +5331 -0
- package/vendor/compose/dist/eligibility.mjs +5313 -0
- package/vendor/compose/dist/index.cjs +2046 -0
- package/vendor/compose/dist/index.mjs +1997 -0
- package/vendor/compose/dist/jsx-dev-runtime.cjs +55 -0
- package/vendor/compose/dist/jsx-dev-runtime.mjs +27 -0
- package/vendor/compose/dist/jsx-runtime.cjs +58 -0
- package/vendor/compose/dist/jsx-runtime.mjs +31 -0
- package/vendor/compose/dist/render.cjs +558 -0
- package/vendor/compose/dist/render.mjs +515 -0
- package/vendor/compose/dist/verify-cli.cjs +3806 -0
- package/vendor/compose/dist/verify-cli.mjs +3812 -0
- package/vendor/compose/dist/verify.cjs +3880 -0
- package/vendor/compose/dist/verify.mjs +3858 -0
- package/web/manager/dist/assets/index-D0S2otug.js +507 -0
- package/web/manager/dist/index.html +1 -1
- package/src/commands/ci-run.js +0 -123
- package/src/commands/ci-setup.js +0 -288
- package/src/commands/ingest.js +0 -458
- package/src/commands/setup.js +0 -137
- package/src/commands/validate-docs.js +0 -529
- package/src/lib/playwright-runner.js +0 -252
- package/web/manager/dist/assets/index--ZgioErz.js +0 -507
package/src/commands/status.js
CHANGED
|
@@ -1,20 +1,46 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* status - Check
|
|
3
|
+
* status - Check project status, sync jobs, and drift queue
|
|
4
4
|
*
|
|
5
5
|
* Displays:
|
|
6
6
|
* - Current project configuration
|
|
7
7
|
* - Recent sync jobs with status
|
|
8
8
|
* - Drift queue summary
|
|
9
|
-
* - Pending actions
|
|
10
9
|
*
|
|
11
|
-
* Usage: reshot status [--jobs] [--drifts] [--json]
|
|
10
|
+
* Usage: reshot status [--jobs] [--drifts] [--config] [--json]
|
|
12
11
|
*/
|
|
13
12
|
|
|
14
13
|
const chalk = require("chalk");
|
|
15
14
|
const config = require("../lib/config");
|
|
16
15
|
const apiClient = require("../lib/api-client");
|
|
17
16
|
|
|
17
|
+
function createIssue(scope, level, message, details = {}) {
|
|
18
|
+
return {
|
|
19
|
+
scope,
|
|
20
|
+
level,
|
|
21
|
+
message,
|
|
22
|
+
...details,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function summarizeConfig(reshotConfig) {
|
|
27
|
+
return {
|
|
28
|
+
baseUrl: reshotConfig.baseUrl || null,
|
|
29
|
+
viewport: reshotConfig.viewport || null,
|
|
30
|
+
assetDir: reshotConfig.assetDir || ".reshot/output",
|
|
31
|
+
scenarioCount: reshotConfig.scenarios?.length || 0,
|
|
32
|
+
traceDir: reshotConfig.visuals?.traceDir || null,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function readSettingsSafe() {
|
|
37
|
+
try {
|
|
38
|
+
return config.readSettings();
|
|
39
|
+
} catch (error) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
18
44
|
/**
|
|
19
45
|
* Format timestamp for display
|
|
20
46
|
*/
|
|
@@ -86,33 +112,275 @@ function formatDriftType(type) {
|
|
|
86
112
|
}
|
|
87
113
|
|
|
88
114
|
/**
|
|
89
|
-
*
|
|
115
|
+
* Display project configuration summary
|
|
90
116
|
*/
|
|
91
|
-
async function displayConfig(
|
|
117
|
+
async function displayConfig(configSummary) {
|
|
92
118
|
console.log(chalk.bold("\n📋 Project Configuration\n"));
|
|
93
119
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
120
|
+
console.log(chalk.gray(" Base URL: ") + chalk.white(configSummary.baseUrl || "(not set)"));
|
|
121
|
+
console.log(chalk.gray(" Viewport: ") + chalk.white(
|
|
122
|
+
configSummary.viewport
|
|
123
|
+
? `${configSummary.viewport.width}×${configSummary.viewport.height}`
|
|
124
|
+
: "(default)"
|
|
125
|
+
));
|
|
126
|
+
console.log(chalk.gray(" Asset Dir: ") + chalk.white(configSummary.assetDir || ".reshot/output"));
|
|
127
|
+
|
|
128
|
+
console.log(chalk.gray(" Scenarios: ") + chalk.white(`${configSummary.scenarioCount || 0} defined`));
|
|
129
|
+
|
|
130
|
+
if (configSummary.traceDir) {
|
|
131
|
+
console.log(chalk.gray(" Trace Dir: ") + chalk.white(configSummary.traceDir));
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function renderJobs(jobs) {
|
|
136
|
+
if (jobs.length === 0) {
|
|
137
|
+
console.log(chalk.gray(" No sync jobs found."));
|
|
138
|
+
console.log(chalk.gray(" Run `reshot sync` to upload traces."));
|
|
98
139
|
return;
|
|
99
140
|
}
|
|
100
141
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
142
|
+
for (const job of jobs) {
|
|
143
|
+
console.log(
|
|
144
|
+
` ${formatJobStatus(job.status)} ` +
|
|
145
|
+
chalk.gray(`${job.id.slice(0, 8)} `) +
|
|
146
|
+
chalk.white(`${job.branch || "unknown"}@${(job.commitHash || "").slice(0, 7)} `) +
|
|
147
|
+
chalk.gray(formatTime(job.createdAt)),
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
if (job.driftCount > 0) {
|
|
151
|
+
console.log(chalk.gray(` └─ ${job.driftCount} drift(s) detected`));
|
|
152
|
+
}
|
|
153
|
+
if (job.errorMessage) {
|
|
154
|
+
console.log(chalk.red(` └─ Error: ${job.errorMessage}`));
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function renderDrifts(drifts, stats, projectId, limit = 10) {
|
|
160
|
+
if (stats.total > 0) {
|
|
161
|
+
console.log(
|
|
162
|
+
chalk.gray(" Summary: ") +
|
|
163
|
+
chalk.yellow(`${stats.pending || 0} pending`) + ", " +
|
|
164
|
+
chalk.green(`${stats.approved || 0} approved`) + ", " +
|
|
165
|
+
chalk.red(`${stats.rejected || 0} rejected`) + ", " +
|
|
166
|
+
chalk.gray(`${stats.ignored || 0} ignored`),
|
|
167
|
+
);
|
|
168
|
+
console.log();
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (drifts.length === 0) {
|
|
172
|
+
console.log(chalk.green(" ✓ No pending drifts!"));
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const displayed = drifts.slice(0, limit);
|
|
177
|
+
for (const drift of displayed) {
|
|
178
|
+
console.log(
|
|
179
|
+
` ${formatDriftType(drift.driftType)} ` +
|
|
180
|
+
chalk.white(drift.journeyKey) + " " +
|
|
181
|
+
chalk.gray(`(${Math.round(drift.confidenceScore * 100)}% confidence)`),
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (drifts.length > limit) {
|
|
186
|
+
console.log(chalk.gray(`\n ... and ${drifts.length - limit} more.`));
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
console.log();
|
|
190
|
+
console.log(
|
|
191
|
+
chalk.gray(" View in dashboard: ") +
|
|
192
|
+
chalk.blue(`https://reshot.dev/app/projects/${projectId}/visuals`),
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
async function fetchJobsData(apiKey, projectId, limit = 5) {
|
|
197
|
+
try {
|
|
198
|
+
const response = await apiClient.getSyncJobs(apiKey, projectId, { limit });
|
|
199
|
+
return {
|
|
200
|
+
jobs: response.jobs || response.data?.jobs || [],
|
|
201
|
+
error: null,
|
|
202
|
+
};
|
|
203
|
+
} catch (error) {
|
|
204
|
+
return {
|
|
205
|
+
jobs: [],
|
|
206
|
+
error: {
|
|
207
|
+
message: error.message,
|
|
208
|
+
kind: error.reshot?.kind || null,
|
|
209
|
+
status: error.reshot?.status || error.response?.status || null,
|
|
210
|
+
},
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
async function fetchDriftsData(apiKey, projectId) {
|
|
216
|
+
try {
|
|
217
|
+
const response = await apiClient.getDrifts(apiKey, projectId, {
|
|
218
|
+
status: "pending",
|
|
219
|
+
});
|
|
220
|
+
return {
|
|
221
|
+
drifts: response.drifts || [],
|
|
222
|
+
stats: response.stats || {},
|
|
223
|
+
error: null,
|
|
224
|
+
};
|
|
225
|
+
} catch (error) {
|
|
226
|
+
return {
|
|
227
|
+
drifts: [],
|
|
228
|
+
stats: {},
|
|
229
|
+
error: {
|
|
230
|
+
message: error.message,
|
|
231
|
+
kind: error.reshot?.kind || null,
|
|
232
|
+
status: error.reshot?.status || error.response?.status || null,
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
async function buildStatusReport(options = {}) {
|
|
239
|
+
const report = {
|
|
240
|
+
generatedAt: new Date().toISOString(),
|
|
241
|
+
ok: true,
|
|
242
|
+
projectId: null,
|
|
243
|
+
mode: config.getModeInfo(),
|
|
244
|
+
config: {
|
|
245
|
+
exists: false,
|
|
246
|
+
summary: null,
|
|
247
|
+
validation: {
|
|
248
|
+
valid: false,
|
|
249
|
+
errors: [],
|
|
250
|
+
warnings: [],
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
auth: {
|
|
254
|
+
hasApiKey: false,
|
|
255
|
+
hasProjectId: false,
|
|
256
|
+
},
|
|
257
|
+
jobs: {
|
|
258
|
+
items: [],
|
|
259
|
+
error: null,
|
|
260
|
+
},
|
|
261
|
+
drifts: {
|
|
262
|
+
items: [],
|
|
263
|
+
stats: {},
|
|
264
|
+
error: null,
|
|
265
|
+
},
|
|
266
|
+
issues: [],
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
let reshotConfig = null;
|
|
270
|
+
try {
|
|
271
|
+
reshotConfig = config.readConfigLenient();
|
|
272
|
+
report.config.exists = true;
|
|
273
|
+
report.config.summary = summarizeConfig(reshotConfig);
|
|
274
|
+
} catch (error) {
|
|
275
|
+
report.issues.push(
|
|
276
|
+
createIssue(
|
|
277
|
+
"config",
|
|
278
|
+
"error",
|
|
279
|
+
"reshot.config.json not found. Run `reshot init` or `reshot setup` first.",
|
|
280
|
+
{ detail: error.message },
|
|
281
|
+
),
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (report.config.exists) {
|
|
286
|
+
report.config.validation = config.validateConfig();
|
|
287
|
+
for (const errorMessage of report.config.validation.errors) {
|
|
288
|
+
report.issues.push(createIssue("config", "error", errorMessage));
|
|
289
|
+
}
|
|
290
|
+
for (const warningMessage of report.config.validation.warnings) {
|
|
291
|
+
report.issues.push(createIssue("config", "warning", warningMessage));
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const settings = readSettingsSafe();
|
|
296
|
+
const apiKey = process.env.RESHOT_API_KEY || settings?.apiKey || null;
|
|
297
|
+
const projectId =
|
|
298
|
+
process.env.RESHOT_PROJECT_ID ||
|
|
299
|
+
settings?.projectId ||
|
|
300
|
+
reshotConfig?._metadata?.projectId ||
|
|
301
|
+
null;
|
|
302
|
+
|
|
303
|
+
report.projectId = projectId;
|
|
304
|
+
report.auth.hasApiKey = Boolean(apiKey);
|
|
305
|
+
report.auth.hasProjectId = Boolean(projectId);
|
|
306
|
+
|
|
307
|
+
// Loudly warn when the linked session (settings.json) and the committed
|
|
308
|
+
// config (reshot.config.json) disagree on the project — settings.json wins,
|
|
309
|
+
// so an edited/stale config projectId would otherwise be silently ignored.
|
|
310
|
+
const configProjectId =
|
|
311
|
+
reshotConfig?.projectId || reshotConfig?._metadata?.projectId || null;
|
|
312
|
+
if (
|
|
313
|
+
projectId &&
|
|
314
|
+
configProjectId &&
|
|
315
|
+
configProjectId !== projectId &&
|
|
316
|
+
!process.env.RESHOT_PROJECT_ID
|
|
317
|
+
) {
|
|
318
|
+
report.issues.push(
|
|
319
|
+
createIssue(
|
|
320
|
+
"config",
|
|
321
|
+
"warning",
|
|
322
|
+
`Project ID mismatch: using ${projectId} (from .reshot/settings.json) but reshot.config.json declares ${configProjectId}. Run \`reshot setup\` to reconcile.`,
|
|
323
|
+
),
|
|
324
|
+
);
|
|
107
325
|
}
|
|
108
|
-
|
|
109
|
-
|
|
326
|
+
|
|
327
|
+
if (!apiKey) {
|
|
328
|
+
report.issues.push(
|
|
329
|
+
createIssue(
|
|
330
|
+
"auth",
|
|
331
|
+
"error",
|
|
332
|
+
"API key not found. Set RESHOT_API_KEY or run `reshot auth`.",
|
|
333
|
+
),
|
|
334
|
+
);
|
|
110
335
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
336
|
+
|
|
337
|
+
if (!projectId) {
|
|
338
|
+
report.issues.push(
|
|
339
|
+
createIssue(
|
|
340
|
+
"auth",
|
|
341
|
+
"error",
|
|
342
|
+
"Project ID not found. Set RESHOT_PROJECT_ID or run `reshot setup`.",
|
|
343
|
+
),
|
|
344
|
+
);
|
|
115
345
|
}
|
|
346
|
+
|
|
347
|
+
if (apiKey && projectId) {
|
|
348
|
+
const [jobsResult, driftsResult] = await Promise.all([
|
|
349
|
+
fetchJobsData(apiKey, projectId, options.limit || 5),
|
|
350
|
+
fetchDriftsData(apiKey, projectId),
|
|
351
|
+
]);
|
|
352
|
+
|
|
353
|
+
report.jobs.items = jobsResult.jobs;
|
|
354
|
+
report.jobs.error = jobsResult.error;
|
|
355
|
+
report.drifts.items = driftsResult.drifts;
|
|
356
|
+
report.drifts.stats = driftsResult.stats;
|
|
357
|
+
report.drifts.error = driftsResult.error;
|
|
358
|
+
|
|
359
|
+
if (jobsResult.error) {
|
|
360
|
+
report.issues.push(
|
|
361
|
+
createIssue(
|
|
362
|
+
"jobs",
|
|
363
|
+
"warning",
|
|
364
|
+
`Could not fetch sync jobs: ${jobsResult.error.message}`,
|
|
365
|
+
jobsResult.error,
|
|
366
|
+
),
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (driftsResult.error) {
|
|
371
|
+
report.issues.push(
|
|
372
|
+
createIssue(
|
|
373
|
+
"drifts",
|
|
374
|
+
"warning",
|
|
375
|
+
`Could not fetch drifts: ${driftsResult.error.message}`,
|
|
376
|
+
driftsResult.error,
|
|
377
|
+
),
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
report.ok = !report.issues.some((issue) => issue.level === "error");
|
|
383
|
+
return report;
|
|
116
384
|
}
|
|
117
385
|
|
|
118
386
|
/**
|
|
@@ -122,32 +390,9 @@ async function displayJobs(apiKey, projectId, limit = 5) {
|
|
|
122
390
|
console.log(chalk.bold("\n📦 Recent Sync Jobs\n"));
|
|
123
391
|
|
|
124
392
|
try {
|
|
125
|
-
// Fetch jobs via API
|
|
126
393
|
const response = await apiClient.getSyncJobs(apiKey, projectId, { limit });
|
|
127
|
-
|
|
128
394
|
const jobs = response.jobs || response.data?.jobs || [];
|
|
129
|
-
|
|
130
|
-
if (jobs.length === 0) {
|
|
131
|
-
console.log(chalk.gray(" No sync jobs found."));
|
|
132
|
-
console.log(chalk.gray(" Run `reshot ingest` to upload traces and docs."));
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
for (const job of jobs) {
|
|
137
|
-
console.log(
|
|
138
|
-
` ${formatJobStatus(job.status)} ` +
|
|
139
|
-
chalk.gray(`${job.id.slice(0, 8)} `) +
|
|
140
|
-
chalk.white(`${job.branch || "unknown"}@${(job.commitHash || "").slice(0, 7)} `) +
|
|
141
|
-
chalk.gray(formatTime(job.createdAt))
|
|
142
|
-
);
|
|
143
|
-
|
|
144
|
-
if (job.driftCount > 0) {
|
|
145
|
-
console.log(chalk.gray(` └─ ${job.driftCount} drift(s) detected`));
|
|
146
|
-
}
|
|
147
|
-
if (job.errorMessage) {
|
|
148
|
-
console.log(chalk.red(` └─ Error: ${job.errorMessage}`));
|
|
149
|
-
}
|
|
150
|
-
}
|
|
395
|
+
renderJobs(jobs);
|
|
151
396
|
} catch (error) {
|
|
152
397
|
console.log(chalk.yellow(" Could not fetch sync jobs: " + error.message));
|
|
153
398
|
console.log(chalk.gray(" This endpoint may not be available yet."));
|
|
@@ -161,48 +406,10 @@ async function displayDrifts(apiKey, projectId, limit = 10) {
|
|
|
161
406
|
console.log(chalk.bold("\n🔄 Drift Queue\n"));
|
|
162
407
|
|
|
163
408
|
try {
|
|
164
|
-
const response = await apiClient.getDrifts(apiKey, projectId, { status: "
|
|
409
|
+
const response = await apiClient.getDrifts(apiKey, projectId, { status: "pending" });
|
|
165
410
|
const drifts = response.drifts || [];
|
|
166
411
|
const stats = response.stats || {};
|
|
167
|
-
|
|
168
|
-
// Show stats summary
|
|
169
|
-
if (stats.total > 0) {
|
|
170
|
-
console.log(
|
|
171
|
-
chalk.gray(" Summary: ") +
|
|
172
|
-
chalk.yellow(`${stats.pending || 0} pending`) + ", " +
|
|
173
|
-
chalk.green(`${stats.approved || 0} approved`) + ", " +
|
|
174
|
-
chalk.red(`${stats.rejected || 0} rejected`) + ", " +
|
|
175
|
-
chalk.gray(`${stats.ignored || 0} ignored`)
|
|
176
|
-
);
|
|
177
|
-
console.log();
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
if (drifts.length === 0) {
|
|
181
|
-
console.log(chalk.green(" ✓ No pending drifts!"));
|
|
182
|
-
console.log(chalk.gray(" Your documentation is in sync with the application."));
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// Show pending drifts
|
|
187
|
-
const displayed = drifts.slice(0, limit);
|
|
188
|
-
for (const drift of displayed) {
|
|
189
|
-
console.log(
|
|
190
|
-
` ${formatDriftType(drift.driftType)} ` +
|
|
191
|
-
chalk.white(drift.journeyKey || drift.docPath) + " " +
|
|
192
|
-
chalk.gray(`(${Math.round(drift.confidenceScore * 100)}% confidence)`)
|
|
193
|
-
);
|
|
194
|
-
|
|
195
|
-
if (drift.docPath) {
|
|
196
|
-
console.log(chalk.gray(` └─ ${drift.docPath}`));
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
if (drifts.length > limit) {
|
|
201
|
-
console.log(chalk.gray(`\n ... and ${drifts.length - limit} more.`));
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
console.log();
|
|
205
|
-
console.log(chalk.gray(" View in dashboard: ") + chalk.blue(`https://reshot.dev/app/projects/${projectId}/docsync`));
|
|
412
|
+
renderDrifts(drifts, stats, projectId, limit);
|
|
206
413
|
} catch (error) {
|
|
207
414
|
console.log(chalk.yellow(" Could not fetch drifts: " + error.message));
|
|
208
415
|
}
|
|
@@ -212,64 +419,65 @@ async function displayDrifts(apiKey, projectId, limit = 10) {
|
|
|
212
419
|
* Main status command
|
|
213
420
|
*/
|
|
214
421
|
async function statusCommand(options = {}) {
|
|
215
|
-
|
|
422
|
+
const report = await buildStatusReport(options);
|
|
216
423
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
process.exit(1);
|
|
424
|
+
if (options.json) {
|
|
425
|
+
console.log(JSON.stringify(report, null, 2));
|
|
426
|
+
if (!report.ok) {
|
|
427
|
+
process.exitCode = 1;
|
|
428
|
+
}
|
|
429
|
+
return report;
|
|
224
430
|
}
|
|
225
431
|
|
|
226
|
-
|
|
227
|
-
const settings = config.readSettings();
|
|
228
|
-
const apiKey = process.env.RESHOT_API_KEY || settings?.apiKey;
|
|
229
|
-
const projectId =
|
|
230
|
-
process.env.RESHOT_PROJECT_ID ||
|
|
231
|
-
settings?.projectId ||
|
|
232
|
-
docSyncConfig._metadata?.projectId;
|
|
432
|
+
console.log(chalk.blue("\n📊 Reshot Status\n"));
|
|
233
433
|
|
|
234
|
-
if (
|
|
235
|
-
console.
|
|
236
|
-
process.exit(1);
|
|
434
|
+
if (report.projectId) {
|
|
435
|
+
console.log(chalk.gray(` Project: ${report.projectId}`));
|
|
237
436
|
}
|
|
238
437
|
|
|
239
|
-
if (!
|
|
240
|
-
|
|
241
|
-
process.exit(1);
|
|
438
|
+
if (report.config.summary && (options.config || (!options.jobs && !options.drifts))) {
|
|
439
|
+
await displayConfig(report.config.summary);
|
|
242
440
|
}
|
|
243
441
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
442
|
+
if (!options.config && (options.jobs || (!options.config && !options.drifts))) {
|
|
443
|
+
console.log(chalk.bold("\n📦 Recent Sync Jobs\n"));
|
|
444
|
+
if (report.jobs.error) {
|
|
445
|
+
console.log(chalk.yellow(" Could not fetch sync jobs: " + report.jobs.error.message));
|
|
446
|
+
console.log(chalk.gray(" This endpoint may not be available yet."));
|
|
447
|
+
} else {
|
|
448
|
+
renderJobs(report.jobs.items);
|
|
449
|
+
}
|
|
249
450
|
}
|
|
250
451
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
452
|
+
if (!options.jobs && (options.drifts || (!options.config && !options.jobs))) {
|
|
453
|
+
console.log(chalk.bold("\n🔄 Drift Queue\n"));
|
|
454
|
+
if (report.drifts.error) {
|
|
455
|
+
console.log(chalk.yellow(" Could not fetch drifts: " + report.drifts.error.message));
|
|
456
|
+
} else {
|
|
457
|
+
renderDrifts(
|
|
458
|
+
report.drifts.items,
|
|
459
|
+
report.drifts.stats,
|
|
460
|
+
report.projectId,
|
|
461
|
+
options.limit || 10,
|
|
462
|
+
);
|
|
463
|
+
}
|
|
254
464
|
}
|
|
255
465
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
466
|
+
if (report.issues.length > 0) {
|
|
467
|
+
console.log(chalk.bold("\n⚠ Issues\n"));
|
|
468
|
+
for (const issue of report.issues) {
|
|
469
|
+
const prefix = issue.level === "error" ? chalk.red(" ✖") : chalk.yellow(" ⚠");
|
|
470
|
+
console.log(`${prefix} [${issue.scope}] ${issue.message}`);
|
|
471
|
+
}
|
|
259
472
|
}
|
|
260
473
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
const response = await apiClient.getDrifts(apiKey, projectId).catch(() => ({}));
|
|
264
|
-
console.log(JSON.stringify({
|
|
265
|
-
projectId,
|
|
266
|
-
config: docSyncConfig.documentation,
|
|
267
|
-
drifts: response.drifts || [],
|
|
268
|
-
stats: response.stats || {},
|
|
269
|
-
}, null, 2));
|
|
474
|
+
if (!report.ok) {
|
|
475
|
+
process.exitCode = 1;
|
|
270
476
|
}
|
|
271
477
|
|
|
272
478
|
console.log();
|
|
479
|
+
return report;
|
|
273
480
|
}
|
|
274
481
|
|
|
275
482
|
module.exports = statusCommand;
|
|
483
|
+
module.exports.buildStatusReport = buildStatusReport;
|