@ethlete/cli 2.0.1-next.2 → 2.1.0-next.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/CHANGELOG.md +95 -0
- package/README.md +173 -6
- 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.d.ts +1 -1
- package/src/index.js +96 -10
- package/src/index.js.map +1 -1
- package/src/lib/api/api-command.d.ts +5 -0
- package/src/lib/api/api-command.js +27 -0
- package/src/lib/api/api-command.js.map +1 -0
- package/src/lib/api/auth-hint.d.ts +16 -0
- package/src/lib/api/auth-hint.js +59 -0
- package/src/lib/api/auth-hint.js.map +1 -0
- package/src/lib/api/clear.d.ts +36 -0
- package/src/lib/api/clear.js +121 -0
- package/src/lib/api/clear.js.map +1 -0
- package/src/lib/api/clone.d.ts +12 -0
- package/src/lib/api/clone.js +24 -0
- package/src/lib/api/clone.js.map +1 -0
- package/src/lib/api/compose.d.ts +46 -0
- package/src/lib/api/compose.js +101 -0
- package/src/lib/api/compose.js.map +1 -0
- package/src/lib/api/definition.d.ts +37 -0
- package/src/lib/api/definition.js +33 -0
- package/src/lib/api/definition.js.map +1 -0
- package/src/lib/api/git.d.ts +25 -0
- package/src/lib/api/git.js +71 -0
- package/src/lib/api/git.js.map +1 -0
- package/src/lib/api/help.d.ts +11 -0
- package/src/lib/api/help.js +72 -0
- package/src/lib/api/help.js.map +1 -0
- package/src/lib/api/index.d.ts +15 -0
- package/src/lib/api/index.js +19 -0
- package/src/lib/api/index.js.map +1 -0
- package/src/lib/api/load-definitions.d.ts +16 -0
- package/src/lib/api/load-definitions.js +22 -0
- package/src/lib/api/load-definitions.js.map +1 -0
- package/src/lib/api/ports.d.ts +13 -0
- package/src/lib/api/ports.js +98 -0
- package/src/lib/api/ports.js.map +1 -0
- package/src/lib/api/resolve-checkout.d.ts +45 -0
- package/src/lib/api/resolve-checkout.js +91 -0
- package/src/lib/api/resolve-checkout.js.map +1 -0
- package/src/lib/api/run.d.ts +10 -0
- package/src/lib/api/run.js +332 -0
- package/src/lib/api/run.js.map +1 -0
- package/src/lib/api/setup.d.ts +15 -0
- package/src/lib/api/setup.js +41 -0
- package/src/lib/api/setup.js.map +1 -0
- package/src/lib/api/state.d.ts +20 -0
- package/src/lib/api/state.js +33 -0
- package/src/lib/api/state.js.map +1 -0
- package/src/lib/api/suggest.d.ts +7 -0
- package/src/lib/api/suggest.js +35 -0
- package/src/lib/api/suggest.js.map +1 -0
- package/src/lib/auth/auth-command.d.ts +11 -0
- package/src/lib/auth/auth-command.js +165 -0
- package/src/lib/auth/auth-command.js.map +1 -0
- package/src/lib/auth/composer-auth.d.ts +30 -0
- package/src/lib/auth/composer-auth.js +70 -0
- package/src/lib/auth/composer-auth.js.map +1 -0
- package/src/lib/auth/composer-repositories.d.ts +5 -0
- package/src/lib/auth/composer-repositories.js +33 -0
- package/src/lib/auth/composer-repositories.js.map +1 -0
- package/src/lib/auth/gitlab-token.d.ts +43 -0
- package/src/lib/auth/gitlab-token.js +72 -0
- package/src/lib/auth/gitlab-token.js.map +1 -0
- package/src/lib/auth/index.d.ts +4 -0
- package/src/lib/auth/index.js +8 -0
- package/src/lib/auth/index.js.map +1 -0
- package/src/lib/config/diagnose.d.ts +7 -0
- package/src/lib/config/diagnose.js +112 -0
- package/src/lib/config/diagnose.js.map +1 -0
- package/src/lib/config/index.d.ts +2 -0
- package/src/lib/config/index.js +6 -0
- package/src/lib/config/index.js.map +1 -0
- package/src/lib/config/local-config.d.ts +46 -0
- package/src/lib/config/local-config.js +57 -0
- package/src/lib/config/local-config.js.map +1 -0
- 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 +7 -0
- package/src/lib/doctor/doctor-command.js +62 -0
- package/src/lib/doctor/doctor-command.js.map +1 -0
- package/src/lib/doctor/index.d.ts +1 -0
- package/src/lib/doctor/index.js +5 -0
- package/src/lib/doctor/index.js.map +1 -0
- package/src/lib/index.d.ts +7 -0
- package/src/lib/index.js +7 -0
- package/src/lib/index.js.map +1 -1
- package/src/lib/invocation.d.ts +9 -0
- package/src/lib/invocation.js +47 -0
- package/src/lib/invocation.js.map +1 -0
- 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
- package/src/lib/utils.d.ts +14 -0
- package/src/lib/utils.js +14 -1
- package/src/lib/utils.js.map +1 -1
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
import type { Call, CallVariant, 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; variants: CallVariant[] };
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The variants are the call. A band exists because a variant names it, never because `rounds`
|
|
40
|
+
* declares it, so a variant 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 variant of call.variants) {
|
|
48
|
+
const key = variant.round ?? '';
|
|
49
|
+
const band = bands.get(key) ?? { key: key || null, number: 0, round: declared.get(key) ?? null, variants: [] };
|
|
50
|
+
band.variants.push(variant);
|
|
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 variant claims is stale prose, and it is the one thing the variants 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 variants`),
|
|
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.variants.every((variant) => variant.verdict));
|
|
81
|
+
const chain = named
|
|
82
|
+
.map((band) => band.variants.find((variant) => variant.verdict === 'chosen'))
|
|
83
|
+
.filter((variant): variant is CallVariant => !!variant);
|
|
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.variants.length === 1 && !call.variants[0]?.claim;
|
|
137
|
+
const geometry = `--frame-width:${call.frameWidth}px`;
|
|
138
|
+
|
|
139
|
+
const frame = (variant: CallVariant) => `
|
|
140
|
+
<iframe
|
|
141
|
+
src="frame.html?call=${encodeURIComponent(slug)}&variant=${encodeURIComponent(variant.key)}"
|
|
142
|
+
data-variant="${esc(variant.key)}"
|
|
143
|
+
title="${esc(variant.name)}"
|
|
144
|
+
style="width:${call.frameWidth}px"
|
|
145
|
+
></iframe>`;
|
|
146
|
+
|
|
147
|
+
const column = (variant: CallVariant) => `
|
|
148
|
+
<div class="column" data-verdict="${variant.verdict ?? 'open'}" ${picked.includes(variant.key) ? 'data-picked' : ''}>
|
|
149
|
+
${
|
|
150
|
+
isView
|
|
151
|
+
? ''
|
|
152
|
+
: `<h3>
|
|
153
|
+
<a href="${togglePick(variant.key)}">${esc(variant.name)}</a>
|
|
154
|
+
<span class="tag">${variant.verdict ?? 'open'}</span>
|
|
155
|
+
</h3>`
|
|
156
|
+
}
|
|
157
|
+
<div class="stage">${frame(variant)}</div>
|
|
158
|
+
${variant.claim ? `<p class="claim">${esc(variant.claim)}</p>` : ''}
|
|
159
|
+
${variant.cost ? `<p class="cost">${esc(variant.cost)}</p>` : ''}
|
|
160
|
+
</div>`;
|
|
161
|
+
|
|
162
|
+
const grid = (variants: CallVariant[]) =>
|
|
163
|
+
variants.length === 0
|
|
164
|
+
? ''
|
|
165
|
+
: `<div class="grid" style="${geometry}" ${isView ? 'data-view' : ''}>${variants.map(column).join('')}</div>`;
|
|
166
|
+
|
|
167
|
+
const rows = (variants: CallVariant[]) =>
|
|
168
|
+
variants.length === 0
|
|
169
|
+
? ''
|
|
170
|
+
: `<ul class="folded">${variants
|
|
171
|
+
.map(
|
|
172
|
+
(variant) =>
|
|
173
|
+
`<li data-verdict="${variant.verdict ?? 'open'}"><a href="${togglePick(variant.key)}">${esc(
|
|
174
|
+
variant.name,
|
|
175
|
+
)}</a><span class="tag">${variant.verdict ?? 'open'}</span></li>`,
|
|
176
|
+
)
|
|
177
|
+
.join('')}</ul>`;
|
|
178
|
+
|
|
179
|
+
const band = ({ key, number, round, variants }: Band) => {
|
|
180
|
+
const settled = variants.every((variant) => variant.verdict);
|
|
181
|
+
const open = !key || !settled || opened.has(key);
|
|
182
|
+
const drawn = open ? variants : chain.length > 0 ? [] : variants.filter((variant) => variant.verdict === 'chosen');
|
|
183
|
+
const folded = variants.filter((variant) => !drawn.includes(variant));
|
|
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 ${variants.length} variants away` : `Show all ${variants.length} variants`
|
|
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((variant) => {
|
|
212
|
+
const band = bands.find((entry) => entry.variants.includes(variant));
|
|
213
|
+
const target = band?.key ? `${toggleOpen(band.key)}#round-${band.key}` : togglePick(variant.key);
|
|
214
|
+
return `<a href="${esc(target)}" ${variant === result ? 'aria-current="step"' : ''}>${esc(
|
|
215
|
+
variant.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 variants = picked
|
|
240
|
+
.map((key) => call.variants.find((variant) => variant.key === key))
|
|
241
|
+
.filter((variant): variant is CallVariant => !!variant);
|
|
242
|
+
if (variants.length === 0) return '';
|
|
243
|
+
|
|
244
|
+
const two = variants.length === 2;
|
|
245
|
+
|
|
246
|
+
return `
|
|
247
|
+
<section class="round tray">
|
|
248
|
+
<div class="round-head">
|
|
249
|
+
<span class="eyebrow">Compare · ${variants.length}</span>
|
|
250
|
+
<h2>${variants.map((variant) => esc(variant.name)).join(' · ')}</h2>
|
|
251
|
+
<div class="switch">
|
|
252
|
+
${variants
|
|
253
|
+
.map((variant, index) => `<button data-step="${index}">${esc(variant.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
|
+
${variants.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.variants
|
|
271
|
+
.map(
|
|
272
|
+
(variant) => `
|
|
273
|
+
<a class="thumb" href="${togglePick(variant.key)}" data-verdict="${variant.verdict ?? 'open'}" ${
|
|
274
|
+
picked.includes(variant.key) ? 'data-picked' : ''
|
|
275
|
+
}>
|
|
276
|
+
<div class="thumb-frame">${frame(variant)}</div>
|
|
277
|
+
<span class="thumb-name">${esc(variant.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.variants.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-variant]')) {
|
|
349
|
+
const height = heights.get(frame.dataset.variant ?? '');
|
|
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.variant ?? '') ?? 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; variant?: string; height?: number };
|
|
370
|
+
if (data?.type !== 'design-explore:height' || !data.height || !data.variant) return;
|
|
371
|
+
|
|
372
|
+
heights.set(data.variant, 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.0
|
|
3
|
+
"version": "2.1.0-next.10",
|
|
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.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export * from './lib';
|
package/src/index.js
CHANGED
|
@@ -2,19 +2,105 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
const lib_1 = require("./lib");
|
|
5
|
+
const USAGE_ROWS = [
|
|
6
|
+
{ subcommand: 'release', args: '', lines: ['Turn pending changesets into a tagged, pushed release commit'] },
|
|
7
|
+
{
|
|
8
|
+
subcommand: 'api',
|
|
9
|
+
args: ' <cmd> <api>',
|
|
10
|
+
lines: [
|
|
11
|
+
"Run an API from this repo's ethlete.apis.js locally",
|
|
12
|
+
"(up, down, logs, shell, setup, plus that API's own exec entries)",
|
|
13
|
+
],
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
subcommand: 'auth',
|
|
17
|
+
args: ' [host] <token>',
|
|
18
|
+
lines: [
|
|
19
|
+
"Write a GitLab token into composer's auth.json, which the",
|
|
20
|
+
'API containers mount, after checking it can download code',
|
|
21
|
+
],
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
subcommand: 'doctor',
|
|
25
|
+
args: '',
|
|
26
|
+
lines: ["Check this machine's ethlete.config.local.json, container engine", 'and every API checkout'],
|
|
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
|
+
},
|
|
41
|
+
];
|
|
42
|
+
const usage = (root) => {
|
|
43
|
+
const rows = USAGE_ROWS.map((row) => (Object.assign(Object.assign({}, row), { command: `${(0, lib_1.repoInvocation)({ root, subcommand: row.subcommand })}${row.args}` })));
|
|
44
|
+
const width = Math.max(...rows.map((row) => row.command.length));
|
|
45
|
+
return [
|
|
46
|
+
'et — Ethlete repo tooling',
|
|
47
|
+
'',
|
|
48
|
+
...rows.flatMap((row) => row.lines.map((line, index) => ` ${(index === 0 ? row.command : '').padEnd(width)} ${line}`)),
|
|
49
|
+
'',
|
|
50
|
+
].join('\n');
|
|
51
|
+
};
|
|
5
52
|
const cli = (args) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
|
|
6
|
-
|
|
7
|
-
switch (cliFunctionArg) {
|
|
53
|
+
switch (args[0]) {
|
|
8
54
|
case 'release':
|
|
9
|
-
|
|
10
|
-
|
|
55
|
+
// `release` reads its flags from a list that was split on "=" before this switch existed.
|
|
56
|
+
// Keep that shape here so its own parsing is untouched.
|
|
57
|
+
yield (0, lib_1.release)(args.join('=').split('='));
|
|
58
|
+
return 0;
|
|
59
|
+
case 'api':
|
|
60
|
+
return (0, lib_1.apiCommand)({
|
|
61
|
+
root: process.cwd(),
|
|
62
|
+
argv: args.slice(1),
|
|
63
|
+
invocation: (0, lib_1.repoInvocation)({ root: process.cwd(), subcommand: 'api' }),
|
|
64
|
+
});
|
|
65
|
+
case 'auth':
|
|
66
|
+
return (0, lib_1.authCommand)({
|
|
67
|
+
root: process.cwd(),
|
|
68
|
+
argv: args.slice(1),
|
|
69
|
+
invocation: (0, lib_1.repoInvocation)({ root: process.cwd(), subcommand: 'auth' }),
|
|
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
|
+
});
|
|
83
|
+
case 'doctor':
|
|
84
|
+
// Every fix it names is an `et api` command, so it needs that script rather than its own.
|
|
85
|
+
return (0, lib_1.doctorCommand)({
|
|
86
|
+
root: process.cwd(),
|
|
87
|
+
apiInvocation: (0, lib_1.repoInvocation)({ root: process.cwd(), subcommand: 'api' }),
|
|
88
|
+
});
|
|
11
89
|
default:
|
|
12
|
-
console.log(
|
|
13
|
-
|
|
90
|
+
console.log(usage(process.cwd()));
|
|
91
|
+
return args[0] === undefined || args[0] === '--help' || args[0] === '-h' ? 0 : 1;
|
|
14
92
|
}
|
|
15
93
|
});
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
94
|
+
tslib_1.__exportStar(require("./lib"), exports);
|
|
95
|
+
// Guarded so the package can also be imported as a library without running the CLI.
|
|
96
|
+
if (require.main === module) {
|
|
97
|
+
cli(process.argv.slice(2))
|
|
98
|
+
.then((code) => {
|
|
99
|
+
process.exitCode = code;
|
|
100
|
+
})
|
|
101
|
+
.catch((error) => {
|
|
102
|
+
console.error(error instanceof Error ? error.message : error);
|
|
103
|
+
process.exitCode = 1;
|
|
104
|
+
});
|
|
105
|
+
}
|
|
20
106
|
//# sourceMappingURL=index.js.map
|
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":";;;AAAA,+BAAsH;AAEtH,MAAM,UAAU,GAAG;IACjB,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,8DAA8D,CAAC,EAAE;IAC5G;QACE,UAAU,EAAE,KAAK;QACjB,IAAI,EAAE,cAAc;QACpB,KAAK,EAAE;YACL,qDAAqD;YACrD,kEAAkE;SACnE;KACF;IACD;QACE,UAAU,EAAE,MAAM;QAClB,IAAI,EAAE,iBAAiB;QACvB,KAAK,EAAE;YACL,2DAA2D;YAC3D,2DAA2D;SAC5D;KACF;IACD;QACE,UAAU,EAAE,QAAQ;QACpB,IAAI,EAAE,EAAE;QACR,KAAK,EAAE,CAAC,kEAAkE,EAAE,wBAAwB,CAAC;KACtG;IACD;QACE,UAAU,EAAE,QAAQ;QACpB,IAAI,EAAE,aAAa;QACnB,KAAK,EAAE;YACL,+DAA+D;YAC/D,8DAA8D;SAC/D;KACF;IACD;QACE,UAAU,EAAE,QAAQ;QACpB,IAAI,EAAE,gBAAgB;QACtB,KAAK,EAAE,CAAC,6DAA6D,EAAE,gCAAgC,CAAC;KACzG;CACF,CAAC;AAEF,MAAM,KAAK,GAAG,CAAC,IAAY,EAAE,EAAE;IAC7B,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,iCAChC,GAAG,KACN,OAAO,EAAE,GAAG,IAAA,oBAAc,EAAC,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,IAC7E,CAAC,CAAC;IACJ,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAEjE,OAAO;QACL,2BAA2B;QAC3B,EAAE;QACF,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CACtB,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAC/F;QACD,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,GAAG,GAAG,CAAO,IAAc,EAAmB,EAAE;IACpD,QAAQ,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAChB,KAAK,SAAS;YACZ,0FAA0F;YAC1F,wDAAwD;YACxD,MAAM,IAAA,aAAO,EAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;YAEzC,OAAO,CAAC,CAAC;QAEX,KAAK,KAAK;YACR,OAAO,IAAA,gBAAU,EAAC;gBAChB,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE;gBACnB,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;gBACnB,UAAU,EAAE,IAAA,oBAAc,EAAC,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;aACvE,CAAC,CAAC;QAEL,KAAK,MAAM;YACT,OAAO,IAAA,iBAAW,EAAC;gBACjB,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE;gBACnB,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;gBACnB,UAAU,EAAE,IAAA,oBAAc,EAAC,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;aACxE,CAAC,CAAC;QAEL,KAAK,QAAQ;YACX,OAAO,IAAA,mBAAa,EAAC;gBACnB,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE;gBACnB,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;gBACnB,UAAU,EAAE,IAAA,oBAAc,EAAC,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC;aAC1E,CAAC,CAAC;QAEL,KAAK,QAAQ;YACX,OAAO,IAAA,mBAAa,EAAC;gBACnB,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE;gBACnB,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;gBACnB,UAAU,EAAE,IAAA,oBAAc,EAAC,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC;aAC1E,CAAC,CAAC;QAEL,KAAK,QAAQ;YACX,0FAA0F;YAC1F,OAAO,IAAA,mBAAa,EAAC;gBACnB,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE;gBACnB,aAAa,EAAE,IAAA,oBAAc,EAAC,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;aAC1E,CAAC,CAAC;QAEL;YACE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YAElC,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrF,CAAC;AACH,CAAC,CAAA,CAAC;AAEF,gDAAsB;AAEtB,oFAAoF;AACpF,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;IAC5B,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SACvB,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;QACb,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAC1B,CAAC,CAAC;SACD,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;QACxB,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC9D,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.apiCommand = void 0;
|
|
4
|
+
const load_definitions_1 = require("./load-definitions");
|
|
5
|
+
const run_1 = require("./run");
|
|
6
|
+
const apiCommand = ({ root, argv, invocation }) => {
|
|
7
|
+
const { found, apis } = (0, load_definitions_1.loadApiDefinitions)(root);
|
|
8
|
+
if (!found) {
|
|
9
|
+
console.error(`No API definitions found. Create ${load_definitions_1.API_DEFINITIONS_FILE_NAMES[0]} in the repo root:\n\n` +
|
|
10
|
+
` const { sshKeyPath } = require('@ethlete/cli');\n\n` +
|
|
11
|
+
` module.exports = {\n` +
|
|
12
|
+
` hub: {\n` +
|
|
13
|
+
` composeDir: 'development',\n` +
|
|
14
|
+
` services: ['app', 'database'],\n` +
|
|
15
|
+
` execService: 'app',\n` +
|
|
16
|
+
` port: 8040,\n` +
|
|
17
|
+
` envFile: '.env',\n` +
|
|
18
|
+
` setupCommand: 'make setup',\n` +
|
|
19
|
+
` exec: { install: ['composer', 'install'] },\n` +
|
|
20
|
+
` },\n` +
|
|
21
|
+
` };`);
|
|
22
|
+
return 1;
|
|
23
|
+
}
|
|
24
|
+
return (0, run_1.runApiCommand)({ apis, argv, root, invocation });
|
|
25
|
+
};
|
|
26
|
+
exports.apiCommand = apiCommand;
|
|
27
|
+
//# sourceMappingURL=api-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-command.js","sourceRoot":"","sources":["../../../../../../libs/cli/src/lib/api/api-command.ts"],"names":[],"mappings":";;;AAAA,yDAAoF;AACpF,+BAAsC;AAE/B,MAAM,UAAU,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAyD,EAAE,EAAE;IAC9G,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,IAAA,qCAAkB,EAAC,IAAI,CAAC,CAAC;IAEjD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CACX,oCAAoC,6CAA0B,CAAC,CAAC,CAAC,wBAAwB;YACvF,uDAAuD;YACvD,wBAAwB;YACxB,cAAc;YACd,oCAAoC;YACpC,wCAAwC;YACxC,6BAA6B;YAC7B,qBAAqB;YACrB,0BAA0B;YAC1B,qCAAqC;YACrC,qDAAqD;YACrD,UAAU;YACV,MAAM,CACT,CAAC;QAEF,OAAO,CAAC,CAAC;IACX,CAAC;IAED,OAAO,IAAA,mBAAa,EAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;AACzD,CAAC,CAAC;AAxBW,QAAA,UAAU,cAwBrB"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A private dependency that will not download is the most common way these commands fail, and git
|
|
3
|
+
* and the package managers report it as a bare 403 or a public-key error. This says what to check.
|
|
4
|
+
*/
|
|
5
|
+
export declare const printPrivateDependencyHint: (options: {
|
|
6
|
+
repoHost?: string;
|
|
7
|
+
}) => void;
|
|
8
|
+
/** The host of a git url, for naming it in the hint. Undefined when the url has no host. */
|
|
9
|
+
export declare const gitUrlHost: (repoUrl: string) => string | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* The host a user names on the command line, which is often pasted as a url: `https://git.example.com/`
|
|
12
|
+
* holds the same host as `git.example.com`. Undefined when there is no host name in it at all.
|
|
13
|
+
*/
|
|
14
|
+
export declare const gitHostFromInput: (value: string) => string | undefined;
|
|
15
|
+
/** The `group/project` part of a git url, for addressing the project in a host's own API. */
|
|
16
|
+
export declare const gitUrlProjectPath: (repoUrl: string) => string | undefined;
|