looply-cli 0.5.11 → 0.5.13
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/.src-hash +1 -1
- package/dist/bin.d.ts.map +1 -1
- package/dist/bin.js +16 -0
- package/dist/bin.js.map +1 -1
- package/dist/branch-delivery-wiring.d.ts +7 -2
- package/dist/branch-delivery-wiring.d.ts.map +1 -1
- package/dist/branch-delivery-wiring.js +79 -12
- package/dist/branch-delivery-wiring.js.map +1 -1
- package/dist/branch-delivery.d.ts +23 -3
- package/dist/branch-delivery.d.ts.map +1 -1
- package/dist/branch-delivery.js +40 -2
- package/dist/branch-delivery.js.map +1 -1
- package/dist/coordinator-state.d.ts.map +1 -1
- package/dist/coordinator-state.js +2 -0
- package/dist/coordinator-state.js.map +1 -1
- package/dist/daemon-cmd.d.ts.map +1 -1
- package/dist/daemon-cmd.js +23 -1
- package/dist/daemon-cmd.js.map +1 -1
- package/dist/delivery-rules.d.ts +11 -0
- package/dist/delivery-rules.d.ts.map +1 -1
- package/dist/delivery-rules.js +34 -1
- package/dist/delivery-rules.js.map +1 -1
- package/dist/github-api.d.ts +2 -0
- package/dist/github-api.d.ts.map +1 -1
- package/dist/github-api.js +3 -0
- package/dist/github-api.js.map +1 -1
- package/dist/goal-gap.d.ts +9 -0
- package/dist/goal-gap.d.ts.map +1 -1
- package/dist/goal-gap.js +9 -0
- package/dist/goal-gap.js.map +1 -1
- package/dist/machine-run-slots.d.ts +10 -2
- package/dist/machine-run-slots.d.ts.map +1 -1
- package/dist/machine-run-slots.js +15 -4
- package/dist/machine-run-slots.js.map +1 -1
- package/dist/maintenance-cmd.d.ts +44 -0
- package/dist/maintenance-cmd.d.ts.map +1 -0
- package/dist/maintenance-cmd.js +132 -0
- package/dist/maintenance-cmd.js.map +1 -0
- package/dist/maintenance-facts.d.ts +52 -0
- package/dist/maintenance-facts.d.ts.map +1 -0
- package/dist/maintenance-facts.js +256 -0
- package/dist/maintenance-facts.js.map +1 -0
- package/dist/maintenance-tick.d.ts +51 -0
- package/dist/maintenance-tick.d.ts.map +1 -0
- package/dist/maintenance-tick.js +156 -0
- package/dist/maintenance-tick.js.map +1 -0
- package/dist/mcp-main.js +3 -0
- package/dist/mcp-main.js.map +1 -1
- package/dist/mcp-server.d.ts +5 -0
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +14 -1
- package/dist/mcp-server.js.map +1 -1
- package/dist/model-transport.d.ts.map +1 -1
- package/dist/model-transport.js +4 -0
- package/dist/model-transport.js.map +1 -1
- package/dist/run-cmd.d.ts.map +1 -1
- package/dist/run-cmd.js +18 -1
- package/dist/run-cmd.js.map +1 -1
- package/dist/run-launcher.d.ts +3 -0
- package/dist/run-launcher.d.ts.map +1 -1
- package/dist/run-launcher.js +3 -2
- package/dist/run-launcher.js.map +1 -1
- package/dist/screenshot-tool.d.ts +45 -0
- package/dist/screenshot-tool.d.ts.map +1 -0
- package/dist/screenshot-tool.js +49 -0
- package/dist/screenshot-tool.js.map +1 -0
- package/dist/server-client.d.ts +39 -0
- package/dist/server-client.d.ts.map +1 -1
- package/dist/server-client.js +21 -0
- package/dist/server-client.js.map +1 -1
- package/dist/visual-proof-browser.d.ts +184 -0
- package/dist/visual-proof-browser.d.ts.map +1 -0
- package/dist/visual-proof-browser.js +267 -0
- package/dist/visual-proof-browser.js.map +1 -0
- package/dist/visual-proof-cmd.d.ts +24 -0
- package/dist/visual-proof-cmd.d.ts.map +1 -0
- package/dist/visual-proof-cmd.js +144 -0
- package/dist/visual-proof-cmd.js.map +1 -0
- package/dist/visual-proof-config.d.ts +151 -0
- package/dist/visual-proof-config.d.ts.map +1 -0
- package/dist/visual-proof-config.js +381 -0
- package/dist/visual-proof-config.js.map +1 -0
- package/dist/visual-proof-publish.d.ts +77 -0
- package/dist/visual-proof-publish.d.ts.map +1 -0
- package/dist/visual-proof-publish.js +211 -0
- package/dist/visual-proof-publish.js.map +1 -0
- package/dist/visual-proof-run.d.ts +73 -0
- package/dist/visual-proof-run.d.ts.map +1 -0
- package/dist/visual-proof-run.js +153 -0
- package/dist/visual-proof-run.js.map +1 -0
- package/dist/visual-proof-scope.d.ts +41 -0
- package/dist/visual-proof-scope.d.ts.map +1 -0
- package/dist/visual-proof-scope.js +205 -0
- package/dist/visual-proof-scope.js.map +1 -0
- package/dist/visual-proof-serve.d.ts +11 -0
- package/dist/visual-proof-serve.d.ts.map +1 -0
- package/dist/visual-proof-serve.js +100 -0
- package/dist/visual-proof-serve.js.map +1 -0
- package/dist/visual-proof-store.d.ts +76 -0
- package/dist/visual-proof-store.d.ts.map +1 -0
- package/dist/visual-proof-store.js +117 -0
- package/dist/visual-proof-store.js.map +1 -0
- package/dist/visual-proof.d.ts +87 -0
- package/dist/visual-proof.d.ts.map +1 -0
- package/dist/visual-proof.js +343 -0
- package/dist/visual-proof.js.map +1 -0
- package/package.json +5 -2
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DISABLED = exports.DEFAULT_MAX_MB = exports.DEFAULT_MAX_ROUTES = exports.DEFAULT_VIEWPORTS = exports.VisualProofConfigError = void 0;
|
|
4
|
+
exports.repoPath = repoPath;
|
|
5
|
+
exports.fixtureRef = fixtureRef;
|
|
6
|
+
exports.parseVisualProof = parseVisualProof;
|
|
7
|
+
exports.readVisualProofConfig = readVisualProofConfig;
|
|
8
|
+
exports.readFixture = readFixture;
|
|
9
|
+
exports.readJsonFile = readJsonFile;
|
|
10
|
+
const node_fs_1 = require("node:fs");
|
|
11
|
+
const node_path_1 = require("node:path");
|
|
12
|
+
const yaml_1 = require("yaml");
|
|
13
|
+
/**
|
|
14
|
+
* `visual_proof:` IN `.looply/config.yaml` — HOW LOOPLY SHOWS A UI CHANGE.
|
|
15
|
+
*
|
|
16
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
17
|
+
* A ticket that changes what a screen looks like was judged by its unit tests
|
|
18
|
+
* alone (TAB-B-61, the cramped sidebar). This section tells Looply how to build
|
|
19
|
+
* the app, serve it, sign in with the project's OWN test data and which screens
|
|
20
|
+
* to capture, so a finished UI change carries before/after screenshots.
|
|
21
|
+
*
|
|
22
|
+
* visual_proof:
|
|
23
|
+
* enabled: true
|
|
24
|
+
* max_routes: 4 # screens per goal (default 4)
|
|
25
|
+
* max_mb: 2048 # all screenshots kept on this machine (default 2048)
|
|
26
|
+
* apps:
|
|
27
|
+
* - name: admin
|
|
28
|
+
* when: ["admin/**"] # changed files that make this app's proof run
|
|
29
|
+
* build: "cd admin && node node_modules/vite/bin/vite.js build" # in the sandbox, offline
|
|
30
|
+
* static: admin/dist # Looply serves this folder itself
|
|
31
|
+
* mount: /admin/ # the URL path the app expects (Vite `base`)
|
|
32
|
+
* storage: { tabsy.activeCompanyId: cmp_demo } # set before every page
|
|
33
|
+
* dark: { storage: { tabsy.theme: dark } } # else prefers-color-scheme
|
|
34
|
+
* rtl: { storage: { tabsy.lang: ar } } # absent: no RTL capture
|
|
35
|
+
* login:
|
|
36
|
+
* storage:
|
|
37
|
+
* tabsy.access: { from: admin/src/test/fixtures.ts, match: "access: '([^']+)'" }
|
|
38
|
+
* api:
|
|
39
|
+
* fallback: { status: 200, json: [] }
|
|
40
|
+
* routes:
|
|
41
|
+
* - { path: /api/v1/companies/selectable, file: admin/src/test/companies.json }
|
|
42
|
+
* router: admin/src/App.tsx # to infer screens from changed pages
|
|
43
|
+
* routes:
|
|
44
|
+
* - { path: dashboard, name: Dashboard }
|
|
45
|
+
*
|
|
46
|
+
* 🔴 NO PROJECT CODE RUNS OUTSIDE THE SANDBOX. `build` runs where every gate runs
|
|
47
|
+
* (the AppContainer, no network). Looply serves the built files with its own
|
|
48
|
+
* static server; the app's code then runs only inside the browser, and every
|
|
49
|
+
* request that is not to that server is answered from `api` or refused — the
|
|
50
|
+
* page is offline by construction. A dev-server command (`vite dev`, `next
|
|
51
|
+
* start`) is NOT supported: a contained process cannot be reached on loopback.
|
|
52
|
+
*
|
|
53
|
+
* 🔴 SIGN-IN USES THE PROJECT'S OWN TEST DATA, NEVER A REAL ACCOUNT. Every value
|
|
54
|
+
* under `login` is READ from a file in the repository whose path says it is a
|
|
55
|
+
* seed, fixture, mock or test file; a literal written here is refused, so a real
|
|
56
|
+
* password can never be typed into this file and work.
|
|
57
|
+
*/
|
|
58
|
+
class VisualProofConfigError extends Error {
|
|
59
|
+
key;
|
|
60
|
+
constructor(key, message) {
|
|
61
|
+
super(`config: ${key} — ${message}`);
|
|
62
|
+
this.key = key;
|
|
63
|
+
this.name = 'VisualProofConfigError';
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
exports.VisualProofConfigError = VisualProofConfigError;
|
|
67
|
+
exports.DEFAULT_VIEWPORTS = [
|
|
68
|
+
{ name: 'desktop', width: 1280, height: 800 },
|
|
69
|
+
{ name: 'phone', width: 390, height: 844 },
|
|
70
|
+
];
|
|
71
|
+
exports.DEFAULT_MAX_ROUTES = 4;
|
|
72
|
+
exports.DEFAULT_MAX_MB = 2048;
|
|
73
|
+
exports.DISABLED = { enabled: false, maxRoutes: exports.DEFAULT_MAX_ROUTES, maxMb: exports.DEFAULT_MAX_MB, viewports: exports.DEFAULT_VIEWPORTS, themes: ['light', 'dark'], apps: [] };
|
|
74
|
+
const isObj = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
75
|
+
/** Only names a person would recognise as test data. */
|
|
76
|
+
const FIXTURE_PATH = /(^|[\\/._-])(seeds?|fixtures?|mocks?|tests?|__tests__|specs?|examples?|demo|e2e|stories|storybook|qa)([\\/._-]|$)/i;
|
|
77
|
+
function onlyKeys(o, path, allowed) {
|
|
78
|
+
for (const k of Object.keys(o)) {
|
|
79
|
+
if (!allowed.includes(k))
|
|
80
|
+
throw new VisualProofConfigError(`${path}.${k}`, `is not a setting here (${allowed.join(', ')})`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function text(o, key, path) {
|
|
84
|
+
const v = o[key];
|
|
85
|
+
if (typeof v !== 'string' || v.trim() === '')
|
|
86
|
+
throw new VisualProofConfigError(`${path}.${key}`, 'must be a non-empty string');
|
|
87
|
+
return v.trim();
|
|
88
|
+
}
|
|
89
|
+
function optText(o, key, path) {
|
|
90
|
+
return o[key] === undefined || o[key] === null ? null : text(o, key, path);
|
|
91
|
+
}
|
|
92
|
+
function count(o, key, path, fallback, min, max) {
|
|
93
|
+
const v = o[key];
|
|
94
|
+
if (v === undefined)
|
|
95
|
+
return fallback;
|
|
96
|
+
if (typeof v !== 'number' || !Number.isInteger(v) || v < min || v > max)
|
|
97
|
+
throw new VisualProofConfigError(`${path}.${key}`, `must be a whole number from ${min} to ${max}`);
|
|
98
|
+
return v;
|
|
99
|
+
}
|
|
100
|
+
function globs(o, key, path) {
|
|
101
|
+
const v = o[key];
|
|
102
|
+
if (v === undefined)
|
|
103
|
+
return [];
|
|
104
|
+
const list = typeof v === 'string' ? [v] : v;
|
|
105
|
+
if (!Array.isArray(list) || list.some((x) => typeof x !== 'string' || x.trim() === ''))
|
|
106
|
+
throw new VisualProofConfigError(`${path}.${key}`, 'must be a glob or a list of globs');
|
|
107
|
+
return list.map((g) => g.trim());
|
|
108
|
+
}
|
|
109
|
+
/** A repository-relative path that stays inside the repository. */
|
|
110
|
+
function repoPath(p, path) {
|
|
111
|
+
const n = (0, node_path_1.normalize)(p.replace(/\\/g, '/'));
|
|
112
|
+
if ((0, node_path_1.isAbsolute)(p) || /^[A-Za-z]:/.test(p) || n === '..' || n.startsWith(`..${node_path_1.sep}`) || n.startsWith('../')) {
|
|
113
|
+
throw new VisualProofConfigError(path, `"${p}" must be a path inside the repository`);
|
|
114
|
+
}
|
|
115
|
+
return p.replace(/\\/g, '/').replace(/^\.\//, '');
|
|
116
|
+
}
|
|
117
|
+
function plainStorage(raw, path) {
|
|
118
|
+
if (raw === undefined || raw === null)
|
|
119
|
+
return {};
|
|
120
|
+
if (!isObj(raw))
|
|
121
|
+
throw new VisualProofConfigError(path, 'must be a map of key to value');
|
|
122
|
+
const out = {};
|
|
123
|
+
for (const [k, v] of Object.entries(raw)) {
|
|
124
|
+
if (typeof v !== 'string' && typeof v !== 'number' && typeof v !== 'boolean')
|
|
125
|
+
throw new VisualProofConfigError(`${path}.${k}`, 'must be a plain value');
|
|
126
|
+
out[k] = String(v);
|
|
127
|
+
}
|
|
128
|
+
return out;
|
|
129
|
+
}
|
|
130
|
+
function variant(raw, path) {
|
|
131
|
+
if (raw === undefined || raw === null)
|
|
132
|
+
return null;
|
|
133
|
+
if (!isObj(raw))
|
|
134
|
+
throw new VisualProofConfigError(path, 'must be a mapping with `storage`');
|
|
135
|
+
onlyKeys(raw, path, ['storage']);
|
|
136
|
+
return { storage: plainStorage(raw['storage'], `${path}.storage`) };
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* 🔴 A SIGN-IN VALUE IS A POINTER INTO A TEST FILE, NEVER THE VALUE ITSELF.
|
|
140
|
+
*/
|
|
141
|
+
function fixtureRef(raw, path) {
|
|
142
|
+
if (typeof raw === 'string' || typeof raw === 'number') {
|
|
143
|
+
throw new VisualProofConfigError(path, 'sign-in values are read from the project’s own seed or fixture files ({ from: <file>, key | match }), never written here');
|
|
144
|
+
}
|
|
145
|
+
if (!isObj(raw))
|
|
146
|
+
throw new VisualProofConfigError(path, 'must be { from: <file>, key | match }');
|
|
147
|
+
onlyKeys(raw, path, ['from', 'key', 'match']);
|
|
148
|
+
const from = repoPath(text(raw, 'from', path), `${path}.from`);
|
|
149
|
+
if (!FIXTURE_PATH.test(from)) {
|
|
150
|
+
throw new VisualProofConfigError(`${path}.from`, `"${from}" is not a seed, fixture, mock or test file; sign-in data comes only from those`);
|
|
151
|
+
}
|
|
152
|
+
const key = optText(raw, 'key', path);
|
|
153
|
+
const match = optText(raw, 'match', path);
|
|
154
|
+
if (key !== null && match !== null)
|
|
155
|
+
throw new VisualProofConfigError(path, 'takes `key` or `match`, not both');
|
|
156
|
+
if (match !== null) {
|
|
157
|
+
try {
|
|
158
|
+
new RegExp(match);
|
|
159
|
+
}
|
|
160
|
+
catch (e) {
|
|
161
|
+
throw new VisualProofConfigError(`${path}.match`, `is not a regular expression: ${e.message}`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return { from, ...(key === null ? {} : { key }), ...(match === null ? {} : { match }) };
|
|
165
|
+
}
|
|
166
|
+
function parseLogin(raw, path) {
|
|
167
|
+
if (raw === undefined || raw === null)
|
|
168
|
+
return { storage: {}, form: null };
|
|
169
|
+
if (!isObj(raw))
|
|
170
|
+
throw new VisualProofConfigError(path, 'must be a mapping (storage, form)');
|
|
171
|
+
onlyKeys(raw, path, ['storage', 'form']);
|
|
172
|
+
const storage = {};
|
|
173
|
+
if (raw['storage'] !== undefined) {
|
|
174
|
+
if (!isObj(raw['storage']))
|
|
175
|
+
throw new VisualProofConfigError(`${path}.storage`, 'must be a map of key to { from, key | match }');
|
|
176
|
+
for (const [k, v] of Object.entries(raw['storage']))
|
|
177
|
+
storage[k] = fixtureRef(v, `${path}.storage.${k}`);
|
|
178
|
+
}
|
|
179
|
+
let form = null;
|
|
180
|
+
const f = raw['form'];
|
|
181
|
+
if (f !== undefined && f !== null) {
|
|
182
|
+
if (!isObj(f))
|
|
183
|
+
throw new VisualProofConfigError(`${path}.form`, 'must be a mapping (path, fields, submit, wait_for)');
|
|
184
|
+
onlyKeys(f, `${path}.form`, ['path', 'fields', 'submit', 'wait_for']);
|
|
185
|
+
if (!isObj(f['fields']) || Object.keys(f['fields']).length === 0)
|
|
186
|
+
throw new VisualProofConfigError(`${path}.form.fields`, 'must map at least one selector to { from, key | match }');
|
|
187
|
+
const fields = {};
|
|
188
|
+
for (const [sel, v] of Object.entries(f['fields']))
|
|
189
|
+
fields[sel] = fixtureRef(v, `${path}.form.fields.${sel}`);
|
|
190
|
+
const waitFor = optText(f, 'wait_for', `${path}.form`);
|
|
191
|
+
form = { path: text(f, 'path', `${path}.form`), fields, submit: text(f, 'submit', `${path}.form`), ...(waitFor === null ? {} : { waitFor }) };
|
|
192
|
+
}
|
|
193
|
+
return { storage, form };
|
|
194
|
+
}
|
|
195
|
+
function status(o, path, fallback) {
|
|
196
|
+
return count(o, 'status', path, fallback, 100, 599);
|
|
197
|
+
}
|
|
198
|
+
function parseApi(raw, path) {
|
|
199
|
+
if (raw === undefined || raw === null)
|
|
200
|
+
return { routes: [], fallback: { status: 404 } };
|
|
201
|
+
if (!isObj(raw))
|
|
202
|
+
throw new VisualProofConfigError(path, 'must be a mapping (routes, fallback)');
|
|
203
|
+
onlyKeys(raw, path, ['routes', 'fallback']);
|
|
204
|
+
const routes = [];
|
|
205
|
+
const list = raw['routes'] ?? [];
|
|
206
|
+
if (!Array.isArray(list))
|
|
207
|
+
throw new VisualProofConfigError(`${path}.routes`, 'must be a list');
|
|
208
|
+
list.forEach((r, i) => {
|
|
209
|
+
const p = `${path}.routes[${i}]`;
|
|
210
|
+
if (!isObj(r))
|
|
211
|
+
throw new VisualProofConfigError(p, 'must be { path, json | file, status?, method? }');
|
|
212
|
+
onlyKeys(r, p, ['path', 'json', 'file', 'status', 'method']);
|
|
213
|
+
const urlPath = text(r, 'path', p);
|
|
214
|
+
if (!urlPath.startsWith('/'))
|
|
215
|
+
throw new VisualProofConfigError(`${p}.path`, 'must start with /');
|
|
216
|
+
if (r['json'] !== undefined && r['file'] !== undefined)
|
|
217
|
+
throw new VisualProofConfigError(p, 'takes `json` or `file`, not both');
|
|
218
|
+
const method = optText(r, 'method', p);
|
|
219
|
+
routes.push({
|
|
220
|
+
path: urlPath,
|
|
221
|
+
status: status(r, p, 200),
|
|
222
|
+
...(method === null ? {} : { method: method.toUpperCase() }),
|
|
223
|
+
...(r['json'] === undefined ? {} : { json: r['json'] }),
|
|
224
|
+
...(r['file'] === undefined ? {} : { file: repoPath(text(r, 'file', p), `${p}.file`) }),
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
let fallback = { status: 404 };
|
|
228
|
+
if (raw['fallback'] !== undefined && raw['fallback'] !== null) {
|
|
229
|
+
const fb = raw['fallback'];
|
|
230
|
+
if (!isObj(fb))
|
|
231
|
+
throw new VisualProofConfigError(`${path}.fallback`, 'must be { status, json? }');
|
|
232
|
+
onlyKeys(fb, `${path}.fallback`, ['status', 'json']);
|
|
233
|
+
fallback = { status: status(fb, `${path}.fallback`, 200), ...(fb['json'] === undefined ? {} : { json: fb['json'] }) };
|
|
234
|
+
}
|
|
235
|
+
return { routes, fallback };
|
|
236
|
+
}
|
|
237
|
+
function parseRoutes(raw, path) {
|
|
238
|
+
if (raw === undefined || raw === null)
|
|
239
|
+
return [];
|
|
240
|
+
if (!Array.isArray(raw))
|
|
241
|
+
throw new VisualProofConfigError(path, 'must be a list of { path, name?, when? }');
|
|
242
|
+
return raw.map((r, i) => {
|
|
243
|
+
const p = `${path}[${i}]`;
|
|
244
|
+
if (typeof r === 'string')
|
|
245
|
+
return { path: r.replace(/^\/+/, ''), name: r.replace(/^\/+/, '') || 'home', when: [] };
|
|
246
|
+
if (!isObj(r))
|
|
247
|
+
throw new VisualProofConfigError(p, 'must be a path or { path, name?, when? }');
|
|
248
|
+
onlyKeys(r, p, ['path', 'name', 'when']);
|
|
249
|
+
const rp = typeof r['path'] === 'string' ? r['path'].trim().replace(/^\/+/, '') : '';
|
|
250
|
+
if (typeof r['path'] !== 'string')
|
|
251
|
+
throw new VisualProofConfigError(`${p}.path`, 'must be a string ("" for the app’s root)');
|
|
252
|
+
return { path: rp, name: optText(r, 'name', p) ?? (rp || 'home'), when: globs(r, 'when', p) };
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
function parseApp(raw, path) {
|
|
256
|
+
if (!isObj(raw))
|
|
257
|
+
throw new VisualProofConfigError(path, 'must be a mapping');
|
|
258
|
+
onlyKeys(raw, path, ['name', 'when', 'build', 'carry', 'timeout_s', 'static', 'serve', 'mount', 'spa', 'storage', 'light', 'dark', 'rtl', 'login', 'api', 'router', 'routes', 'wait_for']);
|
|
259
|
+
if (raw['serve'] !== undefined) {
|
|
260
|
+
throw new VisualProofConfigError(`${path}.serve`, 'is not supported: a server started in the sandbox cannot be reached from outside it. Build the app (`build`) and name the built folder (`static`); Looply serves it');
|
|
261
|
+
}
|
|
262
|
+
const mountRaw = optText(raw, 'mount', path) ?? '/';
|
|
263
|
+
const mount = `/${mountRaw.replace(/^\/+|\/+$/g, '')}/`.replace(/^\/\/$/, '/');
|
|
264
|
+
const spa = raw['spa'] === undefined ? true : raw['spa'];
|
|
265
|
+
if (typeof spa !== 'boolean')
|
|
266
|
+
throw new VisualProofConfigError(`${path}.spa`, 'must be true or false');
|
|
267
|
+
const router = optText(raw, 'router', path);
|
|
268
|
+
return {
|
|
269
|
+
name: text(raw, 'name', path),
|
|
270
|
+
when: globs(raw, 'when', path),
|
|
271
|
+
build: optText(raw, 'build', path),
|
|
272
|
+
carry: raw['carry'] === undefined ? null : globs(raw, 'carry', path).map((c) => repoPath(c, `${path}.carry`)),
|
|
273
|
+
timeoutS: count(raw, 'timeout_s', path, 600, 10, 3600),
|
|
274
|
+
static: repoPath(text(raw, 'static', path), `${path}.static`),
|
|
275
|
+
mount,
|
|
276
|
+
spa,
|
|
277
|
+
storage: plainStorage(raw['storage'], `${path}.storage`),
|
|
278
|
+
light: variant(raw['light'], `${path}.light`),
|
|
279
|
+
dark: variant(raw['dark'], `${path}.dark`),
|
|
280
|
+
rtl: variant(raw['rtl'], `${path}.rtl`),
|
|
281
|
+
login: parseLogin(raw['login'], `${path}.login`),
|
|
282
|
+
api: parseApi(raw['api'], `${path}.api`),
|
|
283
|
+
router: router === null ? null : repoPath(router, `${path}.router`),
|
|
284
|
+
routes: parseRoutes(raw['routes'], `${path}.routes`),
|
|
285
|
+
waitFor: optText(raw, 'wait_for', path),
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
function parseViewports(raw, path) {
|
|
289
|
+
if (raw === undefined || raw === null)
|
|
290
|
+
return [...exports.DEFAULT_VIEWPORTS];
|
|
291
|
+
if (!isObj(raw) || Object.keys(raw).length === 0)
|
|
292
|
+
throw new VisualProofConfigError(path, 'must map a name to [width, height]');
|
|
293
|
+
return Object.entries(raw).map(([name, v]) => {
|
|
294
|
+
if (!Array.isArray(v) || v.length !== 2 || v.some((n) => typeof n !== 'number' || !Number.isInteger(n) || n < 240 || n > 3840)) {
|
|
295
|
+
throw new VisualProofConfigError(`${path}.${name}`, 'must be [width, height] in pixels (240–3840)');
|
|
296
|
+
}
|
|
297
|
+
if (!/^[a-z][a-z0-9-]{0,19}$/.test(name))
|
|
298
|
+
throw new VisualProofConfigError(`${path}.${name}`, 'must be a short lowercase name');
|
|
299
|
+
return { name, width: v[0], height: v[1] };
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
/** The `visual_proof:` section as written, or DISABLED when absent. Throws on anything malformed. */
|
|
303
|
+
function parseVisualProof(raw) {
|
|
304
|
+
if (raw === undefined || raw === null)
|
|
305
|
+
return exports.DISABLED;
|
|
306
|
+
if (!isObj(raw))
|
|
307
|
+
throw new VisualProofConfigError('visual_proof', 'must be a mapping');
|
|
308
|
+
onlyKeys(raw, 'visual_proof', ['enabled', 'max_routes', 'max_mb', 'viewports', 'themes', 'apps']);
|
|
309
|
+
const enabled = raw['enabled'] === undefined ? true : raw['enabled'];
|
|
310
|
+
if (typeof enabled !== 'boolean')
|
|
311
|
+
throw new VisualProofConfigError('visual_proof.enabled', 'must be true or false');
|
|
312
|
+
let themes = ['light', 'dark'];
|
|
313
|
+
if (raw['themes'] !== undefined) {
|
|
314
|
+
const t = raw['themes'];
|
|
315
|
+
if (!Array.isArray(t) || t.length === 0 || t.some((x) => x !== 'light' && x !== 'dark'))
|
|
316
|
+
throw new VisualProofConfigError('visual_proof.themes', 'must list light and/or dark');
|
|
317
|
+
themes = [...new Set(t)];
|
|
318
|
+
}
|
|
319
|
+
const appsRaw = raw['apps'];
|
|
320
|
+
if (!Array.isArray(appsRaw) || appsRaw.length === 0)
|
|
321
|
+
throw new VisualProofConfigError('visual_proof.apps', 'must list at least one app');
|
|
322
|
+
const apps = appsRaw.map((a, i) => parseApp(a, `visual_proof.apps[${i}]`));
|
|
323
|
+
const names = new Set();
|
|
324
|
+
for (const a of apps) {
|
|
325
|
+
if (names.has(a.name))
|
|
326
|
+
throw new VisualProofConfigError('visual_proof.apps', `"${a.name}" is named twice`);
|
|
327
|
+
names.add(a.name);
|
|
328
|
+
}
|
|
329
|
+
return {
|
|
330
|
+
enabled,
|
|
331
|
+
maxRoutes: count(raw, 'max_routes', 'visual_proof', exports.DEFAULT_MAX_ROUTES, 1, 12),
|
|
332
|
+
maxMb: count(raw, 'max_mb', 'visual_proof', exports.DEFAULT_MAX_MB, 50, 100_000),
|
|
333
|
+
viewports: parseViewports(raw['viewports'], 'visual_proof.viewports'),
|
|
334
|
+
themes,
|
|
335
|
+
apps,
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
/** Read `visual_proof:` from the project's `.looply/config.yaml`; DISABLED when the file or section is absent. */
|
|
339
|
+
function readVisualProofConfig(projectDir) {
|
|
340
|
+
const file = (0, node_path_1.join)(projectDir, '.looply', 'config.yaml');
|
|
341
|
+
if (!(0, node_fs_1.existsSync)(file))
|
|
342
|
+
return exports.DISABLED;
|
|
343
|
+
const raw = (0, yaml_1.parse)((0, node_fs_1.readFileSync)(file, 'utf8'));
|
|
344
|
+
return parseVisualProof(isObj(raw) ? raw['visual_proof'] : undefined);
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Resolve a fixture pointer to its value, reading the file from the first root that has it
|
|
348
|
+
* (the checkout, then the project's main folder — a machine checkout may not carry it).
|
|
349
|
+
*/
|
|
350
|
+
function readFixture(ref, roots) {
|
|
351
|
+
const file = roots.map((r) => (0, node_path_1.join)(r, ref.from)).find((p) => (0, node_fs_1.existsSync)(p));
|
|
352
|
+
if (file === undefined)
|
|
353
|
+
throw new Error(`the fixture file ${ref.from} is not in the repository`);
|
|
354
|
+
const body = (0, node_fs_1.readFileSync)(file, 'utf8');
|
|
355
|
+
if (ref.match !== undefined) {
|
|
356
|
+
const m = new RegExp(ref.match).exec(body);
|
|
357
|
+
if (m === null || m[1] === undefined)
|
|
358
|
+
throw new Error(`nothing in ${ref.from} matches ${ref.match}`);
|
|
359
|
+
return m[1];
|
|
360
|
+
}
|
|
361
|
+
if (ref.key !== undefined) {
|
|
362
|
+
let v = JSON.parse(body);
|
|
363
|
+
for (const part of ref.key.split('.')) {
|
|
364
|
+
if (v === null || typeof v !== 'object')
|
|
365
|
+
throw new Error(`${ref.from} has no ${ref.key}`);
|
|
366
|
+
v = v[part];
|
|
367
|
+
}
|
|
368
|
+
if (v === undefined || v === null || typeof v === 'object')
|
|
369
|
+
throw new Error(`${ref.from} ${ref.key} is not a plain value`);
|
|
370
|
+
return String(v);
|
|
371
|
+
}
|
|
372
|
+
return body.trim();
|
|
373
|
+
}
|
|
374
|
+
/** A JSON body file from the repository (checkout first, then the project folder). */
|
|
375
|
+
function readJsonFile(path, roots) {
|
|
376
|
+
const file = roots.map((r) => (0, node_path_1.join)(r, path)).find((p) => (0, node_fs_1.existsSync)(p));
|
|
377
|
+
if (file === undefined)
|
|
378
|
+
throw new Error(`the API fixture ${path} is not in the repository`);
|
|
379
|
+
return JSON.parse((0, node_fs_1.readFileSync)(file, 'utf8'));
|
|
380
|
+
}
|
|
381
|
+
//# sourceMappingURL=visual-proof-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visual-proof-config.js","sourceRoot":"","sources":["../src/visual-proof-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { type VisualProofUpload } from '@looply/core';
|
|
2
|
+
import type { GitExec, GitExecResult } from './git-driver';
|
|
3
|
+
import type { GitHubApi } from './github-api';
|
|
4
|
+
import type { ProofManifest } from './visual-proof-store';
|
|
5
|
+
/**
|
|
6
|
+
* WHERE A PERSON SEES THE SCREENSHOTS: THE TICKET AND THE PULL REQUEST.
|
|
7
|
+
*
|
|
8
|
+
* 1. the contact sheets are uploaded to the goal on the Looply server, where
|
|
9
|
+
* AutoRyn lists them from the goal's evidence and attaches them to the ticket;
|
|
10
|
+
* 2. they are committed — images only, never code — to their own branch
|
|
11
|
+
* `looply-proof/<goal>/<head sha>` on origin, built with git's plumbing so the
|
|
12
|
+
* checkout's files, index and HEAD are never touched, and pushed under
|
|
13
|
+
* `unsafeProofPushArgv` (origin only, that branch shape only, never forced);
|
|
14
|
+
* 3. one comment on the pull request shows them, linked from that branch, so
|
|
15
|
+
* they are visible exactly to whoever can see the repository.
|
|
16
|
+
*
|
|
17
|
+
* Each step is recorded in the capture's `published.json` and is not repeated.
|
|
18
|
+
* Nothing here throws: a step that cannot happen says why, and delivery carries on.
|
|
19
|
+
*/
|
|
20
|
+
export declare const PUBLISHED = "published.json";
|
|
21
|
+
export interface PublishedRecord {
|
|
22
|
+
uploadedAt?: string;
|
|
23
|
+
branch?: string;
|
|
24
|
+
commit?: string;
|
|
25
|
+
commentedOn?: number[];
|
|
26
|
+
}
|
|
27
|
+
export interface PublishInput {
|
|
28
|
+
readonly goalId: string;
|
|
29
|
+
readonly capture: {
|
|
30
|
+
readonly dir: string;
|
|
31
|
+
readonly manifest: ProofManifest;
|
|
32
|
+
};
|
|
33
|
+
readonly pull: {
|
|
34
|
+
readonly number: number;
|
|
35
|
+
readonly url: string;
|
|
36
|
+
} | null;
|
|
37
|
+
readonly github: {
|
|
38
|
+
readonly owner: string;
|
|
39
|
+
readonly repo: string;
|
|
40
|
+
readonly api: GitHubApi;
|
|
41
|
+
} | null;
|
|
42
|
+
}
|
|
43
|
+
export interface PublishDeps {
|
|
44
|
+
readonly git: GitExec;
|
|
45
|
+
/** git with extra environment — a private index file and the commit's author. */
|
|
46
|
+
gitEnv(args: readonly string[], env: Record<string, string>): Promise<GitExecResult>;
|
|
47
|
+
/** Upload to the goal on the server; null when this machine cannot speak for the project. */
|
|
48
|
+
readonly upload: ((goalId: string, upload: VisualProofUpload) => Promise<void>) | null;
|
|
49
|
+
now(): number;
|
|
50
|
+
log(line: string): void;
|
|
51
|
+
}
|
|
52
|
+
export interface PublishOutcome {
|
|
53
|
+
readonly uploaded: boolean;
|
|
54
|
+
readonly branch: string | null;
|
|
55
|
+
readonly commented: boolean;
|
|
56
|
+
readonly notes: readonly string[];
|
|
57
|
+
}
|
|
58
|
+
/** The sheets that fit the upload rule, largest set first in the manifest's order. */
|
|
59
|
+
export declare function sheetsToSend(capture: PublishInput['capture']): Array<{
|
|
60
|
+
name: string;
|
|
61
|
+
label: string;
|
|
62
|
+
file: string;
|
|
63
|
+
bytes: number;
|
|
64
|
+
}>;
|
|
65
|
+
/** The pull request comment: every sheet, inline, from the screenshots branch. */
|
|
66
|
+
export declare function proofComment(input: {
|
|
67
|
+
manifest: ProofManifest;
|
|
68
|
+
images: Array<{
|
|
69
|
+
label: string;
|
|
70
|
+
url: string;
|
|
71
|
+
}>;
|
|
72
|
+
branch: string;
|
|
73
|
+
}): string;
|
|
74
|
+
export declare function publishVisualProof(input: PublishInput, deps: PublishDeps): Promise<PublishOutcome>;
|
|
75
|
+
/** git in `cwd` with extra environment, hidden, never prompting — never by bare name. */
|
|
76
|
+
export declare function nodeGitEnv(cwd: string): PublishDeps['gitEnv'];
|
|
77
|
+
//# sourceMappingURL=visual-proof-publish.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visual-proof-publish.d.ts","sourceRoot":"","sources":["../src/visual-proof-publish.ts"],"names":[],"mappings":"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"}
|