@reshotdev/screenshot 0.0.1-beta.1 → 0.0.1-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -7
- package/package.json +9 -2
- package/src/commands/auth.js +108 -26
- package/src/commands/certify.js +62 -0
- package/src/commands/ci-run.js +57 -2
- package/src/commands/ci-setup.js +5 -5
- package/src/commands/doctor-release.js +67 -0
- package/src/commands/doctor-target.js +49 -0
- package/src/commands/drifts.js +5 -70
- package/src/commands/import-tests.js +13 -13
- package/src/commands/ingest.js +10 -10
- package/src/commands/init.js +16 -277
- package/src/commands/publish.js +204 -237
- package/src/commands/pull.js +253 -23
- package/src/commands/run.js +292 -12
- package/src/commands/setup-wizard.js +277 -499
- package/src/commands/setup.js +41 -13
- package/src/commands/status.js +313 -125
- package/src/commands/sync.js +28 -236
- package/src/commands/ui.js +1 -1
- package/src/commands/verify-publish.js +46 -0
- package/src/index.js +194 -94
- package/src/lib/api-client.js +121 -35
- package/src/lib/capture-engine.js +103 -7
- package/src/lib/capture-script-runner.js +305 -58
- package/src/lib/certification.js +865 -0
- package/src/lib/config.js +181 -76
- package/src/lib/record-cdp.js +288 -16
- package/src/lib/record-config.js +1 -1
- package/src/lib/release-doctor.js +313 -0
- package/src/lib/run-manifest.js +103 -0
- package/src/lib/standalone-mode.js +1 -1
- package/src/lib/storage-providers.js +4 -4
- package/src/lib/target-contract.js +292 -0
- package/src/lib/ui-api.js +6 -7
- package/web/manager/dist/assets/{index--ZgioErz.js → index-D2qqcFNN.js} +1 -1
- package/web/manager/dist/index.html +1 -1
- package/src/commands/validate-docs.js +0 -529
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const fs = require("fs-extra");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const config = require("./config");
|
|
6
|
+
const { buildRunPreflightReport } = require("../commands/run");
|
|
7
|
+
const { runDoctorTarget } = require("./certification");
|
|
8
|
+
|
|
9
|
+
const REPORT_DIR = path.join(process.cwd(), ".reshot", "reports");
|
|
10
|
+
const RELEASE_DOCTOR_REPORT_PATH = path.join(REPORT_DIR, "release-doctor.json");
|
|
11
|
+
const DEFAULT_DOCS_ASSET_MAP_MAX_AGE_DAYS = 30;
|
|
12
|
+
const RESHOT_CDN_ORIGIN = "https://cdn.reshot.dev/";
|
|
13
|
+
|
|
14
|
+
function ensureReportDir() {
|
|
15
|
+
fs.ensureDirSync(REPORT_DIR);
|
|
16
|
+
return REPORT_DIR;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function parseScenarioKeys(value) {
|
|
20
|
+
if (!value) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (Array.isArray(value)) {
|
|
25
|
+
return value.map((entry) => String(entry || "").trim()).filter(Boolean);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return String(value)
|
|
29
|
+
.split(",")
|
|
30
|
+
.map((entry) => entry.trim())
|
|
31
|
+
.filter(Boolean);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function resolveDocsAssetMapMaxAgeDays() {
|
|
35
|
+
const parsed = Number.parseInt(
|
|
36
|
+
process.env.RESHOT_DOCS_ASSET_MAP_MAX_AGE_DAYS || String(DEFAULT_DOCS_ASSET_MAP_MAX_AGE_DAYS),
|
|
37
|
+
10,
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
return Number.isFinite(parsed) && parsed >= 0
|
|
41
|
+
? parsed
|
|
42
|
+
: DEFAULT_DOCS_ASSET_MAP_MAX_AGE_DAYS;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function createDocsHealth(options = {}) {
|
|
46
|
+
return {
|
|
47
|
+
checked: false,
|
|
48
|
+
skipped: false,
|
|
49
|
+
ok: false,
|
|
50
|
+
path: null,
|
|
51
|
+
exportedAt: null,
|
|
52
|
+
ageDays: null,
|
|
53
|
+
maxAgeDays: resolveDocsAssetMapMaxAgeDays(),
|
|
54
|
+
summary: {
|
|
55
|
+
visuals: 0,
|
|
56
|
+
assets: 0,
|
|
57
|
+
steps: 0,
|
|
58
|
+
},
|
|
59
|
+
issues: [],
|
|
60
|
+
...options,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function createDocsIssueCollector(summary, issues, groupKey, visualKey, contextKey) {
|
|
65
|
+
return {
|
|
66
|
+
checkEntry(entry) {
|
|
67
|
+
summary.assets += 1;
|
|
68
|
+
|
|
69
|
+
if (!entry || typeof entry !== "object") {
|
|
70
|
+
issues.push(`Asset map entry \"${groupKey}/${visualKey}/${contextKey}\" is invalid.`);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (!entry.type) {
|
|
75
|
+
issues.push(`Asset map entry \"${groupKey}/${visualKey}/${contextKey}\" is missing type.`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (!entry.alt) {
|
|
79
|
+
issues.push(`Asset map entry \"${groupKey}/${visualKey}/${contextKey}\" is missing alt text.`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (entry.src && !String(entry.src).startsWith(RESHOT_CDN_ORIGIN)) {
|
|
83
|
+
issues.push(
|
|
84
|
+
`Asset map entry \"${groupKey}/${visualKey}/${contextKey}\" does not use a direct cdn.reshot.dev URL.`,
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (entry.poster && !String(entry.poster).startsWith(RESHOT_CDN_ORIGIN)) {
|
|
89
|
+
issues.push(
|
|
90
|
+
`Asset map poster \"${groupKey}/${visualKey}/${contextKey}\" does not use a direct cdn.reshot.dev URL.`,
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
for (const step of entry.steps || []) {
|
|
95
|
+
summary.steps += 1;
|
|
96
|
+
if (!step?.src || !String(step.src).startsWith(RESHOT_CDN_ORIGIN)) {
|
|
97
|
+
issues.push(
|
|
98
|
+
`Asset map step \"${groupKey}/${visualKey}/${contextKey}/${step?.step || "unknown"}\" does not use a direct cdn.reshot.dev URL.`,
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function inspectDocsAssetMap(assetMap, options = {}) {
|
|
107
|
+
const maxAgeDays = Number.isFinite(options.maxAgeDays)
|
|
108
|
+
? options.maxAgeDays
|
|
109
|
+
: resolveDocsAssetMapMaxAgeDays();
|
|
110
|
+
const now = options.now || new Date();
|
|
111
|
+
const issues = [];
|
|
112
|
+
const summary = {
|
|
113
|
+
visuals: 0,
|
|
114
|
+
assets: 0,
|
|
115
|
+
steps: 0,
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
if (!assetMap || typeof assetMap !== "object") {
|
|
119
|
+
return createDocsHealth({
|
|
120
|
+
checked: true,
|
|
121
|
+
ok: false,
|
|
122
|
+
maxAgeDays,
|
|
123
|
+
issues: ["Asset map is missing or invalid."],
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const exportedAt = typeof assetMap.meta?.exportedAt === "string"
|
|
128
|
+
? assetMap.meta.exportedAt
|
|
129
|
+
: null;
|
|
130
|
+
const exportedAtMs = exportedAt ? Date.parse(exportedAt) : Number.NaN;
|
|
131
|
+
let ageDays = null;
|
|
132
|
+
|
|
133
|
+
if (!assetMap.meta?.projectId) {
|
|
134
|
+
issues.push("Asset map meta.projectId is missing.");
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (!exportedAt || Number.isNaN(exportedAtMs)) {
|
|
138
|
+
issues.push("Asset map meta.exportedAt is missing or invalid.");
|
|
139
|
+
} else {
|
|
140
|
+
ageDays = Math.max(0, Math.floor((now.getTime() - exportedAtMs) / 86_400_000));
|
|
141
|
+
if (ageDays > maxAgeDays) {
|
|
142
|
+
issues.push(`Asset map is stale: exported ${ageDays} day(s) ago (max ${maxAgeDays}).`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const groups = assetMap.assets && typeof assetMap.assets === "object"
|
|
147
|
+
? Object.entries(assetMap.assets)
|
|
148
|
+
: [];
|
|
149
|
+
if (groups.length === 0) {
|
|
150
|
+
issues.push("Asset map has no assets.");
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
for (const [groupKey, visuals] of groups) {
|
|
154
|
+
if (!visuals || typeof visuals !== "object") {
|
|
155
|
+
issues.push(`Asset map group \"${groupKey}\" is invalid.`);
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
for (const [visualKey, contexts] of Object.entries(visuals)) {
|
|
160
|
+
summary.visuals += 1;
|
|
161
|
+
|
|
162
|
+
if (!contexts || typeof contexts !== "object") {
|
|
163
|
+
issues.push(`Asset map visual \"${groupKey}/${visualKey}\" is invalid.`);
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
for (const [contextKey, entry] of Object.entries(contexts)) {
|
|
168
|
+
createDocsIssueCollector(summary, issues, groupKey, visualKey, contextKey)
|
|
169
|
+
.checkEntry(entry);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (
|
|
175
|
+
typeof assetMap.meta?.totalVisuals === "number" &&
|
|
176
|
+
assetMap.meta.totalVisuals !== summary.visuals
|
|
177
|
+
) {
|
|
178
|
+
issues.push(`Asset map meta.totalVisuals=${assetMap.meta.totalVisuals} but counted ${summary.visuals}.`);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (
|
|
182
|
+
typeof assetMap.meta?.totalAssets === "number" &&
|
|
183
|
+
assetMap.meta.totalAssets !== summary.assets
|
|
184
|
+
) {
|
|
185
|
+
issues.push(`Asset map meta.totalAssets=${assetMap.meta.totalAssets} but counted ${summary.assets}.`);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (
|
|
189
|
+
typeof assetMap.meta?.totalSteps === "number" &&
|
|
190
|
+
assetMap.meta.totalSteps !== summary.steps
|
|
191
|
+
) {
|
|
192
|
+
issues.push(`Asset map meta.totalSteps=${assetMap.meta.totalSteps} but counted ${summary.steps}.`);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return createDocsHealth({
|
|
196
|
+
checked: true,
|
|
197
|
+
ok: issues.length === 0,
|
|
198
|
+
exportedAt,
|
|
199
|
+
ageDays,
|
|
200
|
+
maxAgeDays,
|
|
201
|
+
summary,
|
|
202
|
+
issues,
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function resolveDocsAssetMapCandidates(cwd = process.cwd()) {
|
|
207
|
+
return [
|
|
208
|
+
path.join(cwd, "src", "data", "reshot-assets.json"),
|
|
209
|
+
path.join(cwd, "app", "src", "data", "reshot-assets.json"),
|
|
210
|
+
];
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function inspectDocsAssetMapFile(options = {}) {
|
|
214
|
+
const cwd = options.cwd || process.cwd();
|
|
215
|
+
const candidates = resolveDocsAssetMapCandidates(cwd);
|
|
216
|
+
const assetMapPath = candidates.find((candidate) => fs.existsSync(candidate));
|
|
217
|
+
|
|
218
|
+
if (!assetMapPath) {
|
|
219
|
+
return createDocsHealth({
|
|
220
|
+
checked: false,
|
|
221
|
+
skipped: true,
|
|
222
|
+
ok: true,
|
|
223
|
+
issues: ["No docs asset map found; skipping docs asset verification."],
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
try {
|
|
228
|
+
const assetMap = fs.readJsonSync(assetMapPath);
|
|
229
|
+
return {
|
|
230
|
+
...inspectDocsAssetMap(assetMap, options),
|
|
231
|
+
path: assetMapPath,
|
|
232
|
+
};
|
|
233
|
+
} catch (error) {
|
|
234
|
+
return createDocsHealth({
|
|
235
|
+
checked: true,
|
|
236
|
+
ok: false,
|
|
237
|
+
path: assetMapPath,
|
|
238
|
+
issues: [`Failed to read docs asset map: ${error.message}`],
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
async function runReleaseDoctor(options = {}) {
|
|
244
|
+
ensureReportDir();
|
|
245
|
+
const scenarioKeys = parseScenarioKeys(options.scenarioKeys || options.scenarios);
|
|
246
|
+
const docSyncConfig = config.readConfig();
|
|
247
|
+
const preflight = await buildRunPreflightReport(docSyncConfig, { scenarioKeys });
|
|
248
|
+
const targetDoctor = docSyncConfig.target?.tier === "certified"
|
|
249
|
+
? await runDoctorTarget({ scenarioKeys })
|
|
250
|
+
: {
|
|
251
|
+
skipped: true,
|
|
252
|
+
ok: true,
|
|
253
|
+
target: docSyncConfig.target,
|
|
254
|
+
summary: {
|
|
255
|
+
overallSeverity: "info",
|
|
256
|
+
blockingIssues: [],
|
|
257
|
+
advisories: [],
|
|
258
|
+
info: [{ message: "Target doctor skipped for non-certified target." }],
|
|
259
|
+
},
|
|
260
|
+
};
|
|
261
|
+
const docsAssetMap = inspectDocsAssetMapFile({ cwd: process.cwd() });
|
|
262
|
+
|
|
263
|
+
const blockingIssues = [];
|
|
264
|
+
const advisories = [];
|
|
265
|
+
|
|
266
|
+
for (const error of preflight.errors || []) {
|
|
267
|
+
blockingIssues.push({ scope: "run-preflight", message: error });
|
|
268
|
+
}
|
|
269
|
+
for (const warning of preflight.warnings || []) {
|
|
270
|
+
advisories.push({ scope: "run-preflight", message: warning });
|
|
271
|
+
}
|
|
272
|
+
for (const issue of targetDoctor.summary?.blockingIssues || []) {
|
|
273
|
+
blockingIssues.push({ scope: "target-doctor", ...issue });
|
|
274
|
+
}
|
|
275
|
+
for (const issue of targetDoctor.summary?.advisories || []) {
|
|
276
|
+
advisories.push({ scope: "target-doctor", ...issue });
|
|
277
|
+
}
|
|
278
|
+
if (!docsAssetMap.skipped) {
|
|
279
|
+
for (const issue of docsAssetMap.issues) {
|
|
280
|
+
blockingIssues.push({ scope: "docs-asset-map", message: issue });
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const ok = preflight.ok && targetDoctor.ok && (docsAssetMap.skipped || docsAssetMap.ok);
|
|
285
|
+
const report = {
|
|
286
|
+
type: "ReleaseDoctorReport",
|
|
287
|
+
stage: "doctor-release",
|
|
288
|
+
generatedAt: new Date().toISOString(),
|
|
289
|
+
ok,
|
|
290
|
+
scenarioKeys: scenarioKeys || null,
|
|
291
|
+
target: docSyncConfig.target || null,
|
|
292
|
+
runPreflight: preflight,
|
|
293
|
+
targetDoctor,
|
|
294
|
+
docsAssetMap,
|
|
295
|
+
summary: {
|
|
296
|
+
blockingIssues,
|
|
297
|
+
advisories,
|
|
298
|
+
},
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
await fs.writeJson(RELEASE_DOCTOR_REPORT_PATH, report, { spaces: 2 });
|
|
302
|
+
report.reportPath = RELEASE_DOCTOR_REPORT_PATH;
|
|
303
|
+
return report;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
module.exports = {
|
|
307
|
+
RELEASE_DOCTOR_REPORT_PATH,
|
|
308
|
+
parseScenarioKeys,
|
|
309
|
+
resolveDocsAssetMapCandidates,
|
|
310
|
+
inspectDocsAssetMap,
|
|
311
|
+
inspectDocsAssetMapFile,
|
|
312
|
+
runReleaseDoctor,
|
|
313
|
+
};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const fs = require("fs-extra");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
|
|
6
|
+
const RUN_MANIFEST_DIR = path.join(
|
|
7
|
+
process.cwd(),
|
|
8
|
+
".reshot",
|
|
9
|
+
"manifests",
|
|
10
|
+
"runs",
|
|
11
|
+
);
|
|
12
|
+
const LATEST_RUN_MANIFEST_PATH = path.join(RUN_MANIFEST_DIR, "run-latest.json");
|
|
13
|
+
|
|
14
|
+
function ensureRunManifestDir() {
|
|
15
|
+
fs.ensureDirSync(RUN_MANIFEST_DIR);
|
|
16
|
+
return RUN_MANIFEST_DIR;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function normalizeScenarioResults(results = []) {
|
|
20
|
+
return results.map((result) => ({
|
|
21
|
+
key: result.key || result.scenario || null,
|
|
22
|
+
scenario: result.scenario || result.key || null,
|
|
23
|
+
success: result.success !== false,
|
|
24
|
+
timestamp: result.timestamp || null,
|
|
25
|
+
outputDir: result.outputDir || null,
|
|
26
|
+
variant: result.variant || null,
|
|
27
|
+
assetCount: Array.isArray(result.assets) ? result.assets.length : 0,
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function buildRunManifest(payload = {}) {
|
|
32
|
+
const generatedAt = payload.generatedAt || new Date().toISOString();
|
|
33
|
+
return {
|
|
34
|
+
type: "ReshotRunManifest",
|
|
35
|
+
runId: payload.runId || generatedAt.replace(/[:.]/g, "-"),
|
|
36
|
+
generatedAt,
|
|
37
|
+
success: payload.success !== false,
|
|
38
|
+
outputBaseDir: payload.outputBaseDir || null,
|
|
39
|
+
selectedScenarioKeys: payload.selectedScenarioKeys || [],
|
|
40
|
+
diffEnabled: Boolean(payload.diffEnabled),
|
|
41
|
+
scenarios: normalizeScenarioResults(payload.scenarios || []),
|
|
42
|
+
preflight: payload.preflight || null,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function writeRunManifest(payload = {}) {
|
|
47
|
+
const manifest = buildRunManifest(payload);
|
|
48
|
+
ensureRunManifestDir();
|
|
49
|
+
const manifestPath = path.join(RUN_MANIFEST_DIR, `run-${manifest.runId}.json`);
|
|
50
|
+
fs.writeJsonSync(manifestPath, manifest, { spaces: 2 });
|
|
51
|
+
fs.writeJsonSync(LATEST_RUN_MANIFEST_PATH, manifest, { spaces: 2 });
|
|
52
|
+
return { manifest, manifestPath, latestPath: LATEST_RUN_MANIFEST_PATH };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function readRunManifest(manifestPath) {
|
|
56
|
+
if (!manifestPath || !fs.existsSync(manifestPath)) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return fs.readJsonSync(manifestPath);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function listRunManifestPaths() {
|
|
64
|
+
if (!fs.existsSync(RUN_MANIFEST_DIR)) {
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return fs
|
|
69
|
+
.readdirSync(RUN_MANIFEST_DIR)
|
|
70
|
+
.filter(
|
|
71
|
+
(entry) =>
|
|
72
|
+
/^run-.*\.json$/.test(entry) && entry !== path.basename(LATEST_RUN_MANIFEST_PATH),
|
|
73
|
+
)
|
|
74
|
+
.map((entry) => path.join(RUN_MANIFEST_DIR, entry))
|
|
75
|
+
.sort((left, right) => right.localeCompare(left));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function getLatestSuccessfulRunManifest() {
|
|
79
|
+
const latest = readRunManifest(LATEST_RUN_MANIFEST_PATH);
|
|
80
|
+
if (latest?.success) {
|
|
81
|
+
return latest;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
for (const manifestPath of listRunManifestPaths()) {
|
|
85
|
+
const manifest = readRunManifest(manifestPath);
|
|
86
|
+
if (manifest?.success) {
|
|
87
|
+
return manifest;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
module.exports = {
|
|
95
|
+
RUN_MANIFEST_DIR,
|
|
96
|
+
LATEST_RUN_MANIFEST_PATH,
|
|
97
|
+
buildRunManifest,
|
|
98
|
+
writeRunManifest,
|
|
99
|
+
readRunManifest,
|
|
100
|
+
listRunManifestPaths,
|
|
101
|
+
getLatestSuccessfulRunManifest,
|
|
102
|
+
normalizeScenarioResults,
|
|
103
|
+
};
|
|
@@ -103,7 +103,7 @@ const DEFAULT_STANDALONE_SETTINGS = {
|
|
|
103
103
|
};
|
|
104
104
|
|
|
105
105
|
const SETTINGS_DIR = ".reshot";
|
|
106
|
-
const CONFIG_PATH = "
|
|
106
|
+
const CONFIG_PATH = "reshot.config.json";
|
|
107
107
|
const SETTINGS_PATH = path.join(SETTINGS_DIR, "settings.json");
|
|
108
108
|
|
|
109
109
|
/**
|
|
@@ -114,7 +114,7 @@ ${chalk.cyan('AWS S3 Setup:')}
|
|
|
114
114
|
${chalk.gray('export AWS_SECRET_ACCESS_KEY="your-secret-access-key"')}
|
|
115
115
|
${chalk.gray('export AWS_REGION="us-east-1" # optional, defaults to us-east-1')}
|
|
116
116
|
|
|
117
|
-
3. ${chalk.yellow('Update
|
|
117
|
+
3. ${chalk.yellow('Update reshot.config.json:')}
|
|
118
118
|
${chalk.gray(JSON.stringify({
|
|
119
119
|
storage: {
|
|
120
120
|
type: 's3',
|
|
@@ -143,7 +143,7 @@ ${chalk.cyan('Cloudflare R2 Setup:')}
|
|
|
143
143
|
${chalk.gray('export R2_ACCESS_KEY_ID="your-r2-access-key"')}
|
|
144
144
|
${chalk.gray('export R2_SECRET_ACCESS_KEY="your-r2-secret-key"')}
|
|
145
145
|
|
|
146
|
-
3. ${chalk.yellow('Update
|
|
146
|
+
3. ${chalk.yellow('Update reshot.config.json:')}
|
|
147
147
|
${chalk.gray(JSON.stringify({
|
|
148
148
|
storage: {
|
|
149
149
|
type: 'r2',
|
|
@@ -165,7 +165,7 @@ ${chalk.cyan('Local Storage Setup:')}
|
|
|
165
165
|
|
|
166
166
|
For local testing or self-hosted scenarios:
|
|
167
167
|
|
|
168
|
-
1. ${chalk.yellow('Update
|
|
168
|
+
1. ${chalk.yellow('Update reshot.config.json:')}
|
|
169
169
|
${chalk.gray(JSON.stringify({
|
|
170
170
|
storage: {
|
|
171
171
|
type: 'local',
|
|
@@ -536,7 +536,7 @@ function createStorageProvider(config) {
|
|
|
536
536
|
|
|
537
537
|
/**
|
|
538
538
|
* Determine storage mode from config
|
|
539
|
-
* @param {object} docSyncConfig - The
|
|
539
|
+
* @param {object} docSyncConfig - The reshot.config.json content
|
|
540
540
|
* @returns {'platform'|'byos'}
|
|
541
541
|
*/
|
|
542
542
|
function getStorageMode(docSyncConfig) {
|