@ethlete/cli 2.1.0-next.7 → 2.1.0-next.9
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/CHANGELOG.md +24 -0
- package/README.md +35 -0
- package/design/define-call.ts +92 -0
- package/design/web/env.d.ts +11 -0
- package/design/web/frame.html +17 -0
- package/design/web/frame.ts +38 -0
- package/design/web/host.css +494 -0
- package/design/web/host.ts +445 -0
- package/design/web/index.html +11 -0
- package/package.json +12 -1
- package/src/index.js +25 -0
- package/src/index.js.map +1 -1
- package/src/lib/config/diagnose.js +9 -0
- package/src/lib/config/diagnose.js.map +1 -1
- package/src/lib/config/local-config.d.ts +2 -0
- package/src/lib/config/local-config.js +6 -1
- package/src/lib/config/local-config.js.map +1 -1
- package/src/lib/design/calls-tsconfig.d.ts +6 -0
- package/src/lib/design/calls-tsconfig.js +37 -0
- package/src/lib/design/calls-tsconfig.js.map +1 -0
- package/src/lib/design/check.d.ts +11 -0
- package/src/lib/design/check.js +192 -0
- package/src/lib/design/check.js.map +1 -0
- package/src/lib/design/design-command.d.ts +10 -0
- package/src/lib/design/design-command.js +32 -0
- package/src/lib/design/design-command.js.map +1 -0
- package/src/lib/design/index.d.ts +5 -0
- package/src/lib/design/index.js +9 -0
- package/src/lib/design/index.js.map +1 -0
- package/src/lib/design/paths.d.ts +24 -0
- package/src/lib/design/paths.js +31 -0
- package/src/lib/design/paths.js.map +1 -0
- package/src/lib/design/serve.d.ts +7 -0
- package/src/lib/design/serve.js +144 -0
- package/src/lib/design/serve.js.map +1 -0
- package/src/lib/doctor/doctor-command.d.ts +3 -1
- package/src/lib/doctor/doctor-command.js +5 -5
- package/src/lib/doctor/doctor-command.js.map +1 -1
- package/src/lib/index.d.ts +2 -0
- package/src/lib/index.js +2 -0
- package/src/lib/index.js.map +1 -1
- package/src/lib/release.js +21 -3
- package/src/lib/release.js.map +1 -1
- package/src/lib/update/ai.d.ts +30 -0
- package/src/lib/update/ai.js +44 -0
- package/src/lib/update/ai.js.map +1 -0
- package/src/lib/update/args.d.ts +21 -0
- package/src/lib/update/args.js +89 -0
- package/src/lib/update/args.js.map +1 -0
- package/src/lib/update/index.d.ts +12 -0
- package/src/lib/update/index.js +16 -0
- package/src/lib/update/index.js.map +1 -0
- package/src/lib/update/migration-manifest.d.ts +40 -0
- package/src/lib/update/migration-manifest.js +137 -0
- package/src/lib/update/migration-manifest.js.map +1 -0
- package/src/lib/update/package-manager.d.ts +23 -0
- package/src/lib/update/package-manager.js +47 -0
- package/src/lib/update/package-manager.js.map +1 -0
- package/src/lib/update/packages.d.ts +65 -0
- package/src/lib/update/packages.js +147 -0
- package/src/lib/update/packages.js.map +1 -0
- package/src/lib/update/pending.d.ts +21 -0
- package/src/lib/update/pending.js +41 -0
- package/src/lib/update/pending.js.map +1 -0
- package/src/lib/update/plan.d.ts +51 -0
- package/src/lib/update/plan.js +101 -0
- package/src/lib/update/plan.js.map +1 -0
- package/src/lib/update/registry.d.ts +31 -0
- package/src/lib/update/registry.js +54 -0
- package/src/lib/update/registry.js.map +1 -0
- package/src/lib/update/run-migrations.d.ts +44 -0
- package/src/lib/update/run-migrations.js +73 -0
- package/src/lib/update/run-migrations.js.map +1 -0
- package/src/lib/update/semver.d.ts +19 -0
- package/src/lib/update/semver.js +79 -0
- package/src/lib/update/semver.js.map +1 -0
- package/src/lib/update/tasks.d.ts +58 -0
- package/src/lib/update/tasks.js +174 -0
- package/src/lib/update/tasks.js.map +1 -0
- package/src/lib/update/update-command.d.ts +12 -0
- package/src/lib/update/update-command.js +304 -0
- package/src/lib/update/update-command.js.map +1 -0
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
import type { Call, CallOption, CallRound } from '@design-explore';
|
|
2
|
+
import { calls, defaultCall } from 'virtual:design-explore';
|
|
3
|
+
import './host.css';
|
|
4
|
+
|
|
5
|
+
/** The contact sheet draws about five 1100px frames per screen at this scale. */
|
|
6
|
+
const SHEET_SCALE = 0.32;
|
|
7
|
+
|
|
8
|
+
const params = new URLSearchParams(location.search);
|
|
9
|
+
const slugs = Object.keys(calls);
|
|
10
|
+
const asked = params.get('call') ?? '';
|
|
11
|
+
const landing = defaultCall && slugs.includes(defaultCall) ? defaultCall : (slugs.at(-1) ?? '');
|
|
12
|
+
const slug = slugs.includes(asked) ? asked : landing;
|
|
13
|
+
const view = params.get('view') === 'sheet' ? 'sheet' : 'rounds';
|
|
14
|
+
const opened = new Set((params.get('open') ?? '').split(',').filter(Boolean));
|
|
15
|
+
const picked = (params.get('pick') ?? '').split(',').filter(Boolean);
|
|
16
|
+
|
|
17
|
+
const esc = (text: string) => text.replace(/[&<>]/g, (c) => ({ '&': '&', '<': '<', '>': '>' })[c] ?? c);
|
|
18
|
+
|
|
19
|
+
const link = (next: Record<string, string | null>) => {
|
|
20
|
+
const url = new URLSearchParams(params);
|
|
21
|
+
for (const [name, value] of Object.entries(next)) {
|
|
22
|
+
if (value === null) url.delete(name);
|
|
23
|
+
else url.set(name, value);
|
|
24
|
+
}
|
|
25
|
+
return `?${url}`;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const listLink = (name: string, list: string[], key: string) => {
|
|
29
|
+
const next = list.includes(key) ? list.filter((entry) => entry !== key) : [...list, key];
|
|
30
|
+
return link({ [name]: next.length > 0 ? next.join(',') : null });
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const toggleOpen = (key: string) => listLink('open', [...opened], key);
|
|
34
|
+
const togglePick = (key: string) => listLink('pick', picked, key);
|
|
35
|
+
|
|
36
|
+
type Band = { key: string | null; number: number; round: CallRound | null; options: CallOption[] };
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The options are the call. A band exists because an option names it, never because `rounds`
|
|
40
|
+
* declares it, so an option added without its round entry still gets a band, a heading and a
|
|
41
|
+
* menu row - all three say the bare key until somebody writes the prose.
|
|
42
|
+
*/
|
|
43
|
+
const bandsOf = (call: Call): Band[] => {
|
|
44
|
+
const declared = new Map((call.rounds ?? []).map((round) => [round.key, round]));
|
|
45
|
+
const bands = new Map<string, Band>();
|
|
46
|
+
|
|
47
|
+
for (const option of call.options) {
|
|
48
|
+
const key = option.round ?? '';
|
|
49
|
+
const band = bands.get(key) ?? { key: key || null, number: 0, round: declared.get(key) ?? null, options: [] };
|
|
50
|
+
band.options.push(option);
|
|
51
|
+
bands.set(key, band);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let number = 0;
|
|
55
|
+
for (const band of bands.values()) if (band.key) band.number = ++number;
|
|
56
|
+
|
|
57
|
+
return [...bands.values()];
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/** Prose that no option claims is stale prose, and it is the one thing the options cannot show. */
|
|
61
|
+
const problemsOf = (call: Call, bands: Band[]) => {
|
|
62
|
+
const keys = (call.rounds ?? []).map((round) => round.key);
|
|
63
|
+
const drawn = new Set(bands.map((band) => band.key));
|
|
64
|
+
|
|
65
|
+
return [
|
|
66
|
+
...[...new Set(keys.filter((key, index) => keys.indexOf(key) !== index))].map(
|
|
67
|
+
(key) => `two rounds share the key "${key}"`,
|
|
68
|
+
),
|
|
69
|
+
...keys.filter((key) => !drawn.has(key)).map((key) => `round "${key}" has no options`),
|
|
70
|
+
];
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* A call is resolved once every round has ruled and at least one round has a winner. Its rounds
|
|
75
|
+
* then draw nothing, because each winner is the one before it plus a change, so the last of them
|
|
76
|
+
* already holds all the others.
|
|
77
|
+
*/
|
|
78
|
+
const chainOf = (bands: Band[]) => {
|
|
79
|
+
const named = bands.filter((band) => band.key);
|
|
80
|
+
const ruled = named.length > 1 && named.every((band) => band.options.every((option) => option.verdict));
|
|
81
|
+
const chain = named
|
|
82
|
+
.map((band) => band.options.find((option) => option.verdict === 'chosen'))
|
|
83
|
+
.filter((option): option is CallOption => !!option);
|
|
84
|
+
|
|
85
|
+
return ruled && chain.length > 0 ? chain : [];
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/** A call's folder path is its place in the tree, so the sidebar nests on the path segments. */
|
|
89
|
+
const tree = (bands: Band[]) => {
|
|
90
|
+
const groups = new Map<string, string[]>();
|
|
91
|
+
for (const s of slugs) {
|
|
92
|
+
const parts = s.split('/');
|
|
93
|
+
const group = parts.slice(0, -1).join(' / ');
|
|
94
|
+
groups.set(group, [...(groups.get(group) ?? []), s]);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const named = bands.filter((band) => band.key);
|
|
98
|
+
|
|
99
|
+
const rounds = (s: string) =>
|
|
100
|
+
s !== slug || view === 'sheet' || named.length < 2
|
|
101
|
+
? ''
|
|
102
|
+
: `<div class="nav-rounds">${named
|
|
103
|
+
.map(
|
|
104
|
+
(band) =>
|
|
105
|
+
`<a href="#round-${esc(band.key ?? '')}">${band.number} · ${esc(band.round?.title ?? band.key ?? '')}</a>`,
|
|
106
|
+
)
|
|
107
|
+
.join('')}</div>`;
|
|
108
|
+
|
|
109
|
+
return [...groups]
|
|
110
|
+
.map(
|
|
111
|
+
([group, members]) => `
|
|
112
|
+
<section>
|
|
113
|
+
${group ? `<h3>${esc(group)}</h3>` : ''}
|
|
114
|
+
${members
|
|
115
|
+
.map(
|
|
116
|
+
(s) =>
|
|
117
|
+
`<a href="${link({ call: s, open: null, pick: null })}" ${s === slug ? 'aria-current="page"' : ''}>${esc(
|
|
118
|
+
s.split('/').at(-1) ?? s,
|
|
119
|
+
)}</a>${rounds(s)}`,
|
|
120
|
+
)
|
|
121
|
+
.join('')}
|
|
122
|
+
</section>`,
|
|
123
|
+
)
|
|
124
|
+
.join('');
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const load = slug ? calls[slug] : undefined;
|
|
128
|
+
|
|
129
|
+
if (!load) {
|
|
130
|
+
document.body.innerHTML = `<p class="empty">No call under .ethlete/design/calls.</p>`;
|
|
131
|
+
} else {
|
|
132
|
+
const call: Call = (await load()).default;
|
|
133
|
+
const bands = bandsOf(call);
|
|
134
|
+
const chain = chainOf(bands);
|
|
135
|
+
const result = chain.at(-1);
|
|
136
|
+
const isView = call.options.length === 1 && !call.options[0]?.claim;
|
|
137
|
+
const geometry = `--frame-width:${call.frameWidth}px`;
|
|
138
|
+
|
|
139
|
+
const frame = (option: CallOption) => `
|
|
140
|
+
<iframe
|
|
141
|
+
src="frame.html?call=${encodeURIComponent(slug)}&option=${encodeURIComponent(option.key)}"
|
|
142
|
+
data-option="${esc(option.key)}"
|
|
143
|
+
title="${esc(option.name)}"
|
|
144
|
+
style="width:${call.frameWidth}px"
|
|
145
|
+
></iframe>`;
|
|
146
|
+
|
|
147
|
+
const column = (option: CallOption) => `
|
|
148
|
+
<div class="column" data-verdict="${option.verdict ?? 'open'}" ${picked.includes(option.key) ? 'data-picked' : ''}>
|
|
149
|
+
${
|
|
150
|
+
isView
|
|
151
|
+
? ''
|
|
152
|
+
: `<h3>
|
|
153
|
+
<a href="${togglePick(option.key)}">${esc(option.name)}</a>
|
|
154
|
+
<span class="tag">${option.verdict ?? 'open'}</span>
|
|
155
|
+
</h3>`
|
|
156
|
+
}
|
|
157
|
+
<div class="stage">${frame(option)}</div>
|
|
158
|
+
${option.claim ? `<p class="claim">${esc(option.claim)}</p>` : ''}
|
|
159
|
+
${option.cost ? `<p class="cost">${esc(option.cost)}</p>` : ''}
|
|
160
|
+
</div>`;
|
|
161
|
+
|
|
162
|
+
const grid = (options: CallOption[]) =>
|
|
163
|
+
options.length === 0
|
|
164
|
+
? ''
|
|
165
|
+
: `<div class="grid" style="${geometry}" ${isView ? 'data-view' : ''}>${options.map(column).join('')}</div>`;
|
|
166
|
+
|
|
167
|
+
const rows = (options: CallOption[]) =>
|
|
168
|
+
options.length === 0
|
|
169
|
+
? ''
|
|
170
|
+
: `<ul class="folded">${options
|
|
171
|
+
.map(
|
|
172
|
+
(option) =>
|
|
173
|
+
`<li data-verdict="${option.verdict ?? 'open'}"><a href="${togglePick(option.key)}">${esc(
|
|
174
|
+
option.name,
|
|
175
|
+
)}</a><span class="tag">${option.verdict ?? 'open'}</span></li>`,
|
|
176
|
+
)
|
|
177
|
+
.join('')}</ul>`;
|
|
178
|
+
|
|
179
|
+
const band = ({ key, number, round, options }: Band) => {
|
|
180
|
+
const settled = options.every((option) => option.verdict);
|
|
181
|
+
const open = !key || !settled || opened.has(key);
|
|
182
|
+
const drawn = open ? options : chain.length > 0 ? [] : options.filter((option) => option.verdict === 'chosen');
|
|
183
|
+
const folded = options.filter((option) => !drawn.includes(option));
|
|
184
|
+
|
|
185
|
+
const head = !key
|
|
186
|
+
? ''
|
|
187
|
+
: `<div class="round-head">
|
|
188
|
+
<span class="eyebrow">Round ${number}${settled ? ' · settled' : ''}</span>
|
|
189
|
+
<h2>${esc(round?.title ?? key)}</h2>
|
|
190
|
+
${round?.note ? `<p>${esc(round.note)}</p>` : ''}
|
|
191
|
+
${
|
|
192
|
+
settled
|
|
193
|
+
? `<a class="fold" href="${toggleOpen(key)}">${
|
|
194
|
+
open ? `Fold ${options.length} options away` : `Show all ${options.length} options`
|
|
195
|
+
}</a>`
|
|
196
|
+
: ''
|
|
197
|
+
}
|
|
198
|
+
</div>`;
|
|
199
|
+
|
|
200
|
+
return `
|
|
201
|
+
<section class="round" ${key ? `id="round-${esc(key)}"` : ''}>
|
|
202
|
+
${head}
|
|
203
|
+
${grid(drawn)}
|
|
204
|
+
${rows(folded)}
|
|
205
|
+
</section>`;
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
/** Each step is the one before it plus a change, so the arrow is the order they were drawn in. */
|
|
209
|
+
const trail = () =>
|
|
210
|
+
chain
|
|
211
|
+
.map((option) => {
|
|
212
|
+
const band = bands.find((entry) => entry.options.includes(option));
|
|
213
|
+
const target = band?.key ? `${toggleOpen(band.key)}#round-${band.key}` : togglePick(option.key);
|
|
214
|
+
return `<a href="${esc(target)}" ${option === result ? 'aria-current="step"' : ''}>${esc(
|
|
215
|
+
option.key.toUpperCase(),
|
|
216
|
+
)}</a>`;
|
|
217
|
+
})
|
|
218
|
+
.join('<span class="arrow">→</span>');
|
|
219
|
+
|
|
220
|
+
const resultBand = () =>
|
|
221
|
+
!result
|
|
222
|
+
? ''
|
|
223
|
+
: `<section class="round result">
|
|
224
|
+
<div class="round-head">
|
|
225
|
+
<span class="eyebrow">Result</span>
|
|
226
|
+
<h2>${esc(result.name)}</h2>
|
|
227
|
+
${result.claim ? `<p>${esc(result.claim)}</p>` : ''}
|
|
228
|
+
<div class="trail">${trail()}</div>
|
|
229
|
+
</div>
|
|
230
|
+
<div class="grid" style="${geometry}">
|
|
231
|
+
<div class="column" data-verdict="chosen">
|
|
232
|
+
<div class="stage">${frame(result)}</div>
|
|
233
|
+
${result.cost ? `<p class="cost">${esc(result.cost)}</p>` : ''}
|
|
234
|
+
</div>
|
|
235
|
+
</div>
|
|
236
|
+
</section>`;
|
|
237
|
+
|
|
238
|
+
const tray = () => {
|
|
239
|
+
const options = picked
|
|
240
|
+
.map((key) => call.options.find((option) => option.key === key))
|
|
241
|
+
.filter((option): option is CallOption => !!option);
|
|
242
|
+
if (options.length === 0) return '';
|
|
243
|
+
|
|
244
|
+
const two = options.length === 2;
|
|
245
|
+
|
|
246
|
+
return `
|
|
247
|
+
<section class="round tray">
|
|
248
|
+
<div class="round-head">
|
|
249
|
+
<span class="eyebrow">Compare · ${options.length}</span>
|
|
250
|
+
<h2>${options.map((option) => esc(option.name)).join(' · ')}</h2>
|
|
251
|
+
<div class="switch">
|
|
252
|
+
${options
|
|
253
|
+
.map((option, index) => `<button data-step="${index}">${esc(option.key.toUpperCase())}</button>`)
|
|
254
|
+
.join('')}
|
|
255
|
+
<span class="hint">${
|
|
256
|
+
two ? 'click or space to blink · arrows to wipe' : 'click or space for the next one'
|
|
257
|
+
}</span>
|
|
258
|
+
</div>
|
|
259
|
+
<a class="fold" href="${link({ pick: null })}">Clear the comparison</a>
|
|
260
|
+
</div>
|
|
261
|
+
<div class="overlay" data-two="${two}" style="width:${call.frameWidth}px">
|
|
262
|
+
${options.map(frame).join('')}
|
|
263
|
+
<div class="seam"></div>
|
|
264
|
+
</div>
|
|
265
|
+
</section>`;
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
const sheet = () => `
|
|
269
|
+
<div class="grid sheet" style="${geometry};--de-scale:${SHEET_SCALE}">
|
|
270
|
+
${call.options
|
|
271
|
+
.map(
|
|
272
|
+
(option) => `
|
|
273
|
+
<a class="thumb" href="${togglePick(option.key)}" data-verdict="${option.verdict ?? 'open'}" ${
|
|
274
|
+
picked.includes(option.key) ? 'data-picked' : ''
|
|
275
|
+
}>
|
|
276
|
+
<div class="thumb-frame">${frame(option)}</div>
|
|
277
|
+
<span class="thumb-name">${esc(option.name)}</span>
|
|
278
|
+
</a>`,
|
|
279
|
+
)
|
|
280
|
+
.join('')}
|
|
281
|
+
</div>`;
|
|
282
|
+
|
|
283
|
+
const views = () =>
|
|
284
|
+
isView
|
|
285
|
+
? ''
|
|
286
|
+
: `<div class="views">
|
|
287
|
+
<a href="${link({ view: null })}" ${view === 'rounds' ? 'aria-current="page"' : ''}>rounds</a>
|
|
288
|
+
<a href="${link({ view: 'sheet' })}" ${view === 'sheet' ? 'aria-current="page"' : ''}>all ${
|
|
289
|
+
call.options.length
|
|
290
|
+
}</a>
|
|
291
|
+
</div>`;
|
|
292
|
+
|
|
293
|
+
document.body.innerHTML = `
|
|
294
|
+
<nav>${tree(bands)}</nav>
|
|
295
|
+
<main>
|
|
296
|
+
<header>
|
|
297
|
+
<span class="eyebrow">${esc(call.eyebrow)}</span>
|
|
298
|
+
<h1>${esc(call.headline)}</h1>
|
|
299
|
+
<p>${esc(call.intro)}</p>
|
|
300
|
+
${views()}
|
|
301
|
+
</header>
|
|
302
|
+
${problemsOf(call, bands)
|
|
303
|
+
.map((problem) => `<p class="problem">design-explore: ${esc(problem)}</p>`)
|
|
304
|
+
.join('')}
|
|
305
|
+
${tray()}
|
|
306
|
+
${view === 'sheet' ? sheet() : `${resultBand()}${bands.map(band).join('')}`}
|
|
307
|
+
</main>`;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* A frame reports its height late, so the page grows under the reader for a second or two after
|
|
312
|
+
* load. The scroll is put back on every one of those reports, until the reader scrolls or the
|
|
313
|
+
* frames go quiet, because a single restore lands on a page that is still the wrong height.
|
|
314
|
+
*/
|
|
315
|
+
const scrollKey = `design-explore:scroll:${slug}:${view}`;
|
|
316
|
+
|
|
317
|
+
history.scrollRestoration = 'manual';
|
|
318
|
+
|
|
319
|
+
let restoring = true;
|
|
320
|
+
const target = Number(sessionStorage.getItem(scrollKey) ?? 0);
|
|
321
|
+
|
|
322
|
+
const stopRestore = () => {
|
|
323
|
+
restoring = false;
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
if (target > 0 && !location.hash) {
|
|
327
|
+
for (const event of ['wheel', 'touchstart', 'keydown', 'pointerdown'] as const) {
|
|
328
|
+
addEventListener(event, stopRestore, { once: true, passive: true });
|
|
329
|
+
}
|
|
330
|
+
setTimeout(stopRestore, 3000);
|
|
331
|
+
scrollTo(0, target);
|
|
332
|
+
} else {
|
|
333
|
+
restoring = false;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
addEventListener(
|
|
337
|
+
'scroll',
|
|
338
|
+
() => {
|
|
339
|
+
if (!restoring) sessionStorage.setItem(scrollKey, String(Math.round(scrollY)));
|
|
340
|
+
},
|
|
341
|
+
{ passive: true },
|
|
342
|
+
);
|
|
343
|
+
|
|
344
|
+
const heights = new Map<string, number>();
|
|
345
|
+
|
|
346
|
+
/** The overlay is as tall as its tallest pick, so no frame is cut and none of them move. */
|
|
347
|
+
const size = () => {
|
|
348
|
+
for (const frame of document.querySelectorAll<HTMLIFrameElement>('iframe[data-option]')) {
|
|
349
|
+
const height = heights.get(frame.dataset.option ?? '');
|
|
350
|
+
if (!height) continue;
|
|
351
|
+
|
|
352
|
+
frame.style.height = `${height}px`;
|
|
353
|
+
|
|
354
|
+
const box = frame.parentElement;
|
|
355
|
+
if (box?.classList.contains('thumb-frame')) box.style.height = `${Math.ceil(height * SHEET_SCALE)}px`;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const overlay = document.querySelector<HTMLElement>('.overlay');
|
|
359
|
+
if (!overlay) return;
|
|
360
|
+
|
|
361
|
+
const tallest = [...overlay.querySelectorAll<HTMLIFrameElement>('iframe')]
|
|
362
|
+
.map((frame) => heights.get(frame.dataset.option ?? '') ?? 0)
|
|
363
|
+
.reduce((a, b) => Math.max(a, b), 0);
|
|
364
|
+
|
|
365
|
+
if (tallest > 0) overlay.style.height = `${tallest}px`;
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
addEventListener('message', (event) => {
|
|
369
|
+
const data = event.data as { type?: string; option?: string; height?: number };
|
|
370
|
+
if (data?.type !== 'design-explore:height' || !data.height || !data.option) return;
|
|
371
|
+
|
|
372
|
+
heights.set(data.option, data.height);
|
|
373
|
+
size();
|
|
374
|
+
|
|
375
|
+
if (restoring) scrollTo(0, target);
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Two drawings that differ by a few pixels can only be told apart in one place, so the picks are
|
|
380
|
+
* stacked at full size and the reader switches between them. Two picks also get a wipe: the
|
|
381
|
+
* second one is clipped from the left, so dragging the seam turns one into the other.
|
|
382
|
+
*/
|
|
383
|
+
const overlay = document.querySelector<HTMLElement>('.overlay');
|
|
384
|
+
|
|
385
|
+
if (overlay) {
|
|
386
|
+
const frames = [...overlay.querySelectorAll<HTMLIFrameElement>('iframe')];
|
|
387
|
+
const steps = [...document.querySelectorAll<HTMLButtonElement>('.switch button')];
|
|
388
|
+
const seam = overlay.querySelector<HTMLElement>('.seam');
|
|
389
|
+
const two = overlay.dataset.two === 'true';
|
|
390
|
+
|
|
391
|
+
let wipe = 50;
|
|
392
|
+
let active = 0;
|
|
393
|
+
|
|
394
|
+
const paint = () => {
|
|
395
|
+
frames.forEach((frame, index) => {
|
|
396
|
+
if (two && index === 1) {
|
|
397
|
+
frame.style.clipPath = `inset(0 0 0 ${wipe}%)`;
|
|
398
|
+
frame.style.opacity = '1';
|
|
399
|
+
} else if (two) {
|
|
400
|
+
frame.style.opacity = '1';
|
|
401
|
+
} else {
|
|
402
|
+
frame.style.opacity = index === active ? '1' : '0';
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
if (seam) {
|
|
407
|
+
seam.style.left = `${wipe}%`;
|
|
408
|
+
seam.hidden = !two || wipe === 0 || wipe === 100;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
const shown = two ? (wipe > 50 ? 0 : 1) : active;
|
|
412
|
+
steps.forEach((step, index) => step.toggleAttribute('aria-current', index === shown));
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
const next = () => {
|
|
416
|
+
if (two) wipe = wipe > 50 ? 0 : 100;
|
|
417
|
+
else active = (active + 1) % frames.length;
|
|
418
|
+
paint();
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
const go = (index: number) => {
|
|
422
|
+
if (two) wipe = index === 0 ? 100 : 0;
|
|
423
|
+
else active = index;
|
|
424
|
+
paint();
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
steps.forEach((step, index) => step.addEventListener('click', () => go(index)));
|
|
428
|
+
overlay.addEventListener('click', next);
|
|
429
|
+
|
|
430
|
+
addEventListener('keydown', (event) => {
|
|
431
|
+
if (event.target !== document.body) return;
|
|
432
|
+
|
|
433
|
+
if (event.key === ' ') next();
|
|
434
|
+
else if (two && event.key === 'ArrowLeft') wipe = Math.max(0, wipe - 5);
|
|
435
|
+
else if (two && event.key === 'ArrowRight') wipe = Math.min(100, wipe + 5);
|
|
436
|
+
else if (!two && event.key === 'ArrowLeft') active = (active - 1 + frames.length) % frames.length;
|
|
437
|
+
else if (!two && event.key === 'ArrowRight') active = (active + 1) % frames.length;
|
|
438
|
+
else return;
|
|
439
|
+
|
|
440
|
+
event.preventDefault();
|
|
441
|
+
paint();
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
paint();
|
|
445
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>Design explore</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<script type="module" src="./host.ts"></script>
|
|
10
|
+
</body>
|
|
11
|
+
</html>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ethlete/cli",
|
|
3
|
-
"version": "2.1.0-next.
|
|
3
|
+
"version": "2.1.0-next.9",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -8,8 +8,19 @@
|
|
|
8
8
|
"bin": {
|
|
9
9
|
"et": "./src/index.js"
|
|
10
10
|
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@tailwindcss/postcss": "4.3.3",
|
|
13
|
+
"typescript": "6.0.3",
|
|
14
|
+
"vite": "8.1.5"
|
|
15
|
+
},
|
|
11
16
|
"peerDependencies": {
|
|
17
|
+
"playwright": "1.61.1",
|
|
12
18
|
"tslib": "2.8.1"
|
|
13
19
|
},
|
|
20
|
+
"peerDependenciesMeta": {
|
|
21
|
+
"playwright": {
|
|
22
|
+
"optional": true
|
|
23
|
+
}
|
|
24
|
+
},
|
|
14
25
|
"types": "./src/index.d.ts"
|
|
15
26
|
}
|
package/src/index.js
CHANGED
|
@@ -25,6 +25,19 @@ const USAGE_ROWS = [
|
|
|
25
25
|
args: '',
|
|
26
26
|
lines: ["Check this machine's ethlete.config.local.json, container engine", 'and every API checkout'],
|
|
27
27
|
},
|
|
28
|
+
{
|
|
29
|
+
subcommand: 'design',
|
|
30
|
+
args: ' [checkout]',
|
|
31
|
+
lines: [
|
|
32
|
+
"Serve the design page of a checkout's .ethlete/design folder,",
|
|
33
|
+
'or run `design check` to find out why a call does not render',
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
subcommand: 'update',
|
|
38
|
+
args: ' [packages...]',
|
|
39
|
+
lines: ['Move the @ethlete/* packages to a newer version and run the', 'migrations those versions ship'],
|
|
40
|
+
},
|
|
28
41
|
];
|
|
29
42
|
const usage = (root) => {
|
|
30
43
|
const rows = USAGE_ROWS.map((row) => (Object.assign(Object.assign({}, row), { command: `${(0, lib_1.repoInvocation)({ root, subcommand: row.subcommand })}${row.args}` })));
|
|
@@ -55,6 +68,18 @@ const cli = (args) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
|
|
|
55
68
|
argv: args.slice(1),
|
|
56
69
|
invocation: (0, lib_1.repoInvocation)({ root: process.cwd(), subcommand: 'auth' }),
|
|
57
70
|
});
|
|
71
|
+
case 'design':
|
|
72
|
+
return (0, lib_1.designCommand)({
|
|
73
|
+
root: process.cwd(),
|
|
74
|
+
argv: args.slice(1),
|
|
75
|
+
invocation: (0, lib_1.repoInvocation)({ root: process.cwd(), subcommand: 'design' }),
|
|
76
|
+
});
|
|
77
|
+
case 'update':
|
|
78
|
+
return (0, lib_1.updateCommand)({
|
|
79
|
+
root: process.cwd(),
|
|
80
|
+
argv: args.slice(1),
|
|
81
|
+
invocation: (0, lib_1.repoInvocation)({ root: process.cwd(), subcommand: 'update' }),
|
|
82
|
+
});
|
|
58
83
|
case 'doctor':
|
|
59
84
|
// Every fix it names is an `et api` command, so it needs that script rather than its own.
|
|
60
85
|
return (0, lib_1.doctorCommand)({
|
package/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/cli/src/index.ts"],"names":[],"mappings":";;;AAAA,+
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/cli/src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -59,12 +59,21 @@ const describeApiRepoBranches = (options) => {
|
|
|
59
59
|
? []
|
|
60
60
|
: [`${fileName} has an invalid "apiRepoBranches.${app}" value — use a non-empty branch name.`]);
|
|
61
61
|
};
|
|
62
|
+
const describeUpdateAgentCommand = (options) => {
|
|
63
|
+
const { value, fileName } = options;
|
|
64
|
+
if (value === undefined)
|
|
65
|
+
return [];
|
|
66
|
+
return typeof value === 'string' && value.trim().length > 0
|
|
67
|
+
? []
|
|
68
|
+
: [`${fileName} has an invalid "updateAgentCommand" value — use the command that hands a prompt to an agent.`];
|
|
69
|
+
};
|
|
62
70
|
const describeValues = (options) => {
|
|
63
71
|
const { root, config, fileName } = options;
|
|
64
72
|
return [
|
|
65
73
|
...describeSdkSourcePath({ root, value: config.sdkSourcePath, fileName }),
|
|
66
74
|
...describeApiRepoPaths({ root, value: config.apiRepoPaths, fileName }),
|
|
67
75
|
...describeApiRepoBranches({ value: config.apiRepoBranches, fileName }),
|
|
76
|
+
...describeUpdateAgentCommand({ value: config.updateAgentCommand, fileName }),
|
|
68
77
|
];
|
|
69
78
|
};
|
|
70
79
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnose.js","sourceRoot":"","sources":["../../../../../../libs/cli/src/lib/config/diagnose.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"diagnose.js","sourceRoot":"","sources":["../../../../../../libs/cli/src/lib/config/diagnose.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,6 +15,8 @@ export type LocalConfig = {
|
|
|
15
15
|
apiRepoPaths?: Record<string, string>;
|
|
16
16
|
/** Branch that represents each API's deployed state, keyed by app name. `"*"` matches any app. */
|
|
17
17
|
apiRepoBranches?: Record<string, string>;
|
|
18
|
+
/** Command `et update --ai` hands an assisted migration task to, for example `claude -p`. */
|
|
19
|
+
updateAgentCommand?: string;
|
|
18
20
|
};
|
|
19
21
|
export declare const LOCAL_CONFIG_KEYS: (keyof LocalConfig)[];
|
|
20
22
|
export type LocalConfigFileState = {
|
|
@@ -9,7 +9,12 @@ exports.LOCAL_CONFIG_FILE_NAME = 'ethlete.config.local.json';
|
|
|
9
9
|
* fallback so an existing checkout keeps working, and reported so the developer can move them.
|
|
10
10
|
*/
|
|
11
11
|
exports.LEGACY_LOCAL_CONFIG_FILE_NAME = 'ethlete-agents.config.local.json';
|
|
12
|
-
exports.LOCAL_CONFIG_KEYS = [
|
|
12
|
+
exports.LOCAL_CONFIG_KEYS = [
|
|
13
|
+
'sdkSourcePath',
|
|
14
|
+
'apiRepoPaths',
|
|
15
|
+
'apiRepoBranches',
|
|
16
|
+
'updateAgentCommand',
|
|
17
|
+
];
|
|
13
18
|
/** Reads one config file, keeping "not there" apart from "there but broken" for `et doctor`. */
|
|
14
19
|
const readLocalConfigFile = (path) => {
|
|
15
20
|
if (!(0, fs_1.existsSync)(path))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-config.js","sourceRoot":"","sources":["../../../../../../libs/cli/src/lib/config/local-config.ts"],"names":[],"mappings":";;;AAAA,2BAA8C;AAC9C,+BAAiD;AAEpC,QAAA,sBAAsB,GAAG,2BAA2B,CAAC;AAElE;;;GAGG;AACU,QAAA,6BAA6B,GAAG,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"local-config.js","sourceRoot":"","sources":["../../../../../../libs/cli/src/lib/config/local-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Writes the tsconfig that types a checkout's calls, and answers with its path. A call file
|
|
3
|
+
* imports `@design-explore`, which only this package can resolve, so no repository can write
|
|
4
|
+
* this config for itself.
|
|
5
|
+
*/
|
|
6
|
+
export declare const writeCallsTsconfig: (target: string) => string;
|