@dbx-tools/cli 0.9.139 → 0.9.140
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -14
- package/index.ts +2 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.js +3 -2
- package/lib/src/brand/cli.js +4 -2
- package/lib/src/brand/export.d.ts +2 -0
- package/lib/src/brand/export.js +8 -1
- package/lib/src/brand/index.d.ts +1 -0
- package/lib/src/brand/index.js +2 -1
- package/lib/src/brand/options.d.ts +2 -1
- package/lib/src/brand/options.js +7 -3
- package/lib/src/brand/run.js +22 -3
- package/lib/src/brand/showcase.d.ts +8 -0
- package/lib/src/brand/showcase.js +333 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +22 -22
- package/src/brand/cli.ts +3 -1
- package/src/brand/export.ts +9 -0
- package/src/brand/index.ts +1 -0
- package/src/brand/options.ts +8 -2
- package/src/brand/run.ts +23 -1
- package/src/brand/showcase.ts +344 -0
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-contained HTML presentation for an exported brand package.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { stringUtils } from "@dbx-tools/shared-core";
|
|
7
|
+
function safeAsset(value) {
|
|
8
|
+
if (!value)
|
|
9
|
+
return undefined;
|
|
10
|
+
if (/^(?:data:image\/|https:\/\/)/i.test(value))
|
|
11
|
+
return value;
|
|
12
|
+
return /^\.{0,2}\//.test(value) ? value : undefined;
|
|
13
|
+
}
|
|
14
|
+
function safeWebsite(value) {
|
|
15
|
+
return value && /^https:\/\//i.test(value) ? value : undefined;
|
|
16
|
+
}
|
|
17
|
+
function safeFontFamily(value) {
|
|
18
|
+
return /^[\w\s'",.-]+$/.test(value) ? value : "ui-sans-serif, system-ui, sans-serif";
|
|
19
|
+
}
|
|
20
|
+
function listItems(values) {
|
|
21
|
+
return values.map((value) => `<li>${stringUtils.escapeHtml(value)}</li>`).join("");
|
|
22
|
+
}
|
|
23
|
+
/** Render one responsive brand presentation with desktop and mobile mockups. */
|
|
24
|
+
export function renderBrandShowcase(brandPackage) {
|
|
25
|
+
const { brand, visualReferences } = brandPackage;
|
|
26
|
+
const html = stringUtils.escapeHtml;
|
|
27
|
+
const logo = safeAsset(brand.assets.logo.light) ?? safeAsset(brand.assets.icon.light);
|
|
28
|
+
const icon = safeAsset(brand.assets.icon.light);
|
|
29
|
+
const website = safeWebsite(brand.links.website);
|
|
30
|
+
const screenshots = visualReferences
|
|
31
|
+
.flatMap((reference) => reference.images.flatMap((image) => image.localPath
|
|
32
|
+
? [{ appName: reference.appName, platform: reference.platform, path: image.localPath }]
|
|
33
|
+
: []))
|
|
34
|
+
.slice(0, 4);
|
|
35
|
+
const identityMark = logo
|
|
36
|
+
? `<img src="${html(logo)}" alt="${html(brand.name)} logo">`
|
|
37
|
+
: `<span class="wordmark">${html(brand.shortName)}</span>`;
|
|
38
|
+
const compactMark = icon
|
|
39
|
+
? `<img src="${html(icon)}" alt="" aria-hidden="true">`
|
|
40
|
+
: `<span class="compact-wordmark">${html(brand.shortName.slice(0, 2))}</span>`;
|
|
41
|
+
const action = website
|
|
42
|
+
? `<a class="button" href="${html(website)}">Visit website</a>`
|
|
43
|
+
: `<span class="button">Explore the brand</span>`;
|
|
44
|
+
const gallery = screenshots.length
|
|
45
|
+
? `
|
|
46
|
+
<section class="references" aria-labelledby="references-title">
|
|
47
|
+
<div class="section-heading">
|
|
48
|
+
<h2 id="references-title">Visual references</h2>
|
|
49
|
+
<p>Supplemental mobile references used during research.</p>
|
|
50
|
+
</div>
|
|
51
|
+
<div class="reference-grid">
|
|
52
|
+
${screenshots
|
|
53
|
+
.map(({ appName, path, platform }) => `
|
|
54
|
+
<figure>
|
|
55
|
+
<img src="${html(path)}" alt="${html(appName)} ${html(platform)} reference">
|
|
56
|
+
<figcaption>${html(appName)} / ${html(platform)}</figcaption>
|
|
57
|
+
</figure>
|
|
58
|
+
`)
|
|
59
|
+
.join("")}
|
|
60
|
+
</div>
|
|
61
|
+
</section>
|
|
62
|
+
`
|
|
63
|
+
: "";
|
|
64
|
+
const headline = brand.tagline ?? brand.name;
|
|
65
|
+
// prettier-ignore
|
|
66
|
+
return stringUtils.dedent(
|
|
67
|
+
// ============================================================================
|
|
68
|
+
/*html*/ `
|
|
69
|
+
<!doctype html>
|
|
70
|
+
<html lang="en">
|
|
71
|
+
<head>
|
|
72
|
+
<meta charset="utf-8">
|
|
73
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
74
|
+
<title>${html(brand.name)} brand presentation</title>
|
|
75
|
+
<style>
|
|
76
|
+
:root {
|
|
77
|
+
color-scheme: light;
|
|
78
|
+
--primary: ${brand.colors.primary};
|
|
79
|
+
--primary-hover: ${brand.colors.primaryHover};
|
|
80
|
+
--accent: ${brand.colors.accent};
|
|
81
|
+
--foreground: ${brand.colors.foreground};
|
|
82
|
+
--background: ${brand.colors.background};
|
|
83
|
+
--surface: ${brand.colors.surface};
|
|
84
|
+
--muted: ${brand.colors.muted};
|
|
85
|
+
--border: ${brand.colors.border};
|
|
86
|
+
--sans: ${safeFontFamily(brand.typography.sans)};
|
|
87
|
+
--mono: ${safeFontFamily(brand.typography.mono)};
|
|
88
|
+
}
|
|
89
|
+
* { box-sizing: border-box; }
|
|
90
|
+
body {
|
|
91
|
+
margin: 0;
|
|
92
|
+
background: var(--background);
|
|
93
|
+
color: var(--foreground);
|
|
94
|
+
font-family: var(--sans);
|
|
95
|
+
}
|
|
96
|
+
a { color: inherit; }
|
|
97
|
+
img { display: block; max-width: 100%; }
|
|
98
|
+
main { margin: 0 auto; max-width: 1240px; padding: 0 32px 72px; }
|
|
99
|
+
.masthead {
|
|
100
|
+
align-items: center;
|
|
101
|
+
border-bottom: 1px solid var(--border);
|
|
102
|
+
display: flex;
|
|
103
|
+
justify-content: space-between;
|
|
104
|
+
min-height: 88px;
|
|
105
|
+
}
|
|
106
|
+
.masthead img { max-height: 42px; max-width: 210px; }
|
|
107
|
+
.wordmark { font-size: 24px; font-weight: 750; letter-spacing: -0.04em; }
|
|
108
|
+
.meta { color: var(--muted); font-family: var(--mono); font-size: 12px; }
|
|
109
|
+
.identity {
|
|
110
|
+
display: grid;
|
|
111
|
+
gap: 48px;
|
|
112
|
+
grid-template-columns: minmax(0, 1.4fr) minmax(260px, 0.6fr);
|
|
113
|
+
padding: 72px 0 64px;
|
|
114
|
+
}
|
|
115
|
+
.identity h1 {
|
|
116
|
+
font-size: clamp(48px, 8vw, 104px);
|
|
117
|
+
letter-spacing: -0.065em;
|
|
118
|
+
line-height: 0.92;
|
|
119
|
+
margin: 0;
|
|
120
|
+
max-width: 850px;
|
|
121
|
+
}
|
|
122
|
+
.identity-copy { align-self: end; }
|
|
123
|
+
.identity-copy p { color: var(--muted); font-size: 17px; line-height: 1.65; margin: 0 0 28px; }
|
|
124
|
+
.button {
|
|
125
|
+
background: var(--primary);
|
|
126
|
+
border-radius: 999px;
|
|
127
|
+
color: var(--background);
|
|
128
|
+
display: inline-flex;
|
|
129
|
+
font-weight: 700;
|
|
130
|
+
padding: 12px 20px;
|
|
131
|
+
text-decoration: none;
|
|
132
|
+
}
|
|
133
|
+
.showcase {
|
|
134
|
+
background: var(--surface);
|
|
135
|
+
border: 1px solid var(--border);
|
|
136
|
+
border-radius: 28px;
|
|
137
|
+
overflow: hidden;
|
|
138
|
+
padding: 38px;
|
|
139
|
+
}
|
|
140
|
+
.section-heading { align-items: end; display: flex; gap: 24px; justify-content: space-between; margin-bottom: 28px; }
|
|
141
|
+
.section-heading h2 { font-size: 30px; letter-spacing: -0.035em; margin: 0; }
|
|
142
|
+
.section-heading p { color: var(--muted); margin: 0; max-width: 460px; text-align: right; }
|
|
143
|
+
.devices { align-items: end; display: grid; gap: 28px; grid-template-columns: minmax(0, 1fr) 280px; }
|
|
144
|
+
.browser, .phone {
|
|
145
|
+
background: var(--background);
|
|
146
|
+
border: 1px solid color-mix(in srgb, var(--foreground) 18%, transparent);
|
|
147
|
+
box-shadow: 0 24px 70px color-mix(in srgb, var(--foreground) 13%, transparent);
|
|
148
|
+
overflow: hidden;
|
|
149
|
+
}
|
|
150
|
+
.browser { border-radius: 18px; }
|
|
151
|
+
.browser-bar { align-items: center; background: var(--foreground); display: flex; gap: 7px; height: 38px; padding: 0 16px; }
|
|
152
|
+
.browser-bar i { background: var(--accent); border-radius: 50%; display: block; height: 7px; opacity: 0.8; width: 7px; }
|
|
153
|
+
.browser-nav, .phone-nav { align-items: center; display: flex; justify-content: space-between; padding: 20px 24px; }
|
|
154
|
+
.browser-nav img { max-height: 30px; max-width: 150px; }
|
|
155
|
+
.nav-links { color: var(--muted); display: flex; font-size: 12px; gap: 22px; }
|
|
156
|
+
.mock-hero { display: grid; gap: 28px; grid-template-columns: 1.1fr 0.9fr; min-height: 350px; padding: 44px; }
|
|
157
|
+
.mock-copy { align-self: center; }
|
|
158
|
+
.mock-copy h3 { font-size: clamp(34px, 5vw, 64px); letter-spacing: -0.055em; line-height: 0.98; margin: 0 0 22px; }
|
|
159
|
+
.mock-copy p { color: var(--muted); line-height: 1.55; margin: 0 0 24px; max-width: 520px; }
|
|
160
|
+
.mock-visual {
|
|
161
|
+
align-content: end;
|
|
162
|
+
background: var(--primary);
|
|
163
|
+
border-radius: 20px;
|
|
164
|
+
color: var(--background);
|
|
165
|
+
display: grid;
|
|
166
|
+
min-height: 250px;
|
|
167
|
+
overflow: hidden;
|
|
168
|
+
padding: 28px;
|
|
169
|
+
position: relative;
|
|
170
|
+
}
|
|
171
|
+
.mock-visual::before {
|
|
172
|
+
background: var(--accent);
|
|
173
|
+
border-radius: 50%;
|
|
174
|
+
content: "";
|
|
175
|
+
height: 210px;
|
|
176
|
+
position: absolute;
|
|
177
|
+
right: -70px;
|
|
178
|
+
top: -80px;
|
|
179
|
+
width: 210px;
|
|
180
|
+
}
|
|
181
|
+
.mock-visual strong { font-size: 22px; line-height: 1.15; max-width: 220px; position: relative; }
|
|
182
|
+
.phone { border: 8px solid var(--foreground); border-radius: 34px; }
|
|
183
|
+
.phone-screen { min-height: 540px; }
|
|
184
|
+
.phone-nav { padding: 18px; }
|
|
185
|
+
.phone-nav img { height: 30px; max-width: 112px; object-fit: contain; object-position: left center; }
|
|
186
|
+
.phone-mark img { height: 30px; width: 30px; }
|
|
187
|
+
.compact-wordmark { font-weight: 800; }
|
|
188
|
+
.phone-copy { padding: 34px 22px 24px; }
|
|
189
|
+
.phone-copy h3 { font-size: 38px; letter-spacing: -0.05em; line-height: 0.98; margin: 0 0 18px; }
|
|
190
|
+
.phone-copy p { color: var(--muted); font-size: 14px; line-height: 1.55; margin: 0; }
|
|
191
|
+
.phone-accent { background: var(--accent); height: 120px; margin: 18px 22px 22px; }
|
|
192
|
+
.system {
|
|
193
|
+
display: grid;
|
|
194
|
+
gap: 48px;
|
|
195
|
+
grid-template-columns: 1fr 1fr;
|
|
196
|
+
padding: 72px 0;
|
|
197
|
+
}
|
|
198
|
+
.palette { display: grid; grid-template-columns: repeat(4, 1fr); min-height: 250px; }
|
|
199
|
+
.swatch { align-items: end; display: flex; padding: 16px; }
|
|
200
|
+
.swatch span { background: var(--background); color: var(--foreground); font-family: var(--mono); font-size: 11px; padding: 5px 7px; }
|
|
201
|
+
.type-specimen { border-top: 1px solid var(--border); padding-top: 24px; }
|
|
202
|
+
.type-specimen strong { display: block; font-size: clamp(44px, 6vw, 76px); letter-spacing: -0.05em; line-height: 0.95; }
|
|
203
|
+
.type-specimen code { color: var(--muted); display: block; font-family: var(--mono); margin-top: 20px; }
|
|
204
|
+
.voice { border-top: 1px solid var(--border); display: grid; gap: 32px; grid-template-columns: 1fr 1fr; padding: 36px 0; }
|
|
205
|
+
.voice h2 { font-size: 30px; letter-spacing: -0.035em; margin: 0; }
|
|
206
|
+
.voice h3 { font-size: 14px; margin: 0 0 12px; }
|
|
207
|
+
.voice ul { color: var(--muted); line-height: 1.6; margin: 0; padding-left: 18px; }
|
|
208
|
+
.references { border-top: 1px solid var(--border); padding-top: 56px; }
|
|
209
|
+
.reference-grid { display: grid; gap: 18px; grid-template-columns: repeat(4, 1fr); }
|
|
210
|
+
figure { margin: 0; }
|
|
211
|
+
figure img { aspect-ratio: 9 / 16; background: var(--surface); border: 1px solid var(--border); object-fit: contain; width: 100%; }
|
|
212
|
+
figcaption { color: var(--muted); font-size: 11px; margin-top: 8px; }
|
|
213
|
+
@media (max-width: 860px) {
|
|
214
|
+
main { padding: 0 18px 48px; }
|
|
215
|
+
.identity, .system { grid-template-columns: 1fr; }
|
|
216
|
+
.identity { gap: 28px; padding: 52px 0 44px; }
|
|
217
|
+
.showcase { border-radius: 20px; padding: 20px; }
|
|
218
|
+
.devices { grid-template-columns: 1fr; }
|
|
219
|
+
.phone { margin: 0 auto; max-width: 320px; width: 100%; }
|
|
220
|
+
.reference-grid { grid-template-columns: repeat(2, 1fr); }
|
|
221
|
+
}
|
|
222
|
+
@media (max-width: 560px) {
|
|
223
|
+
.masthead { min-height: 72px; }
|
|
224
|
+
.identity h1 { font-size: 52px; }
|
|
225
|
+
.section-heading { align-items: start; flex-direction: column; }
|
|
226
|
+
.section-heading p { text-align: left; }
|
|
227
|
+
.mock-hero { grid-template-columns: 1fr; padding: 24px; }
|
|
228
|
+
.mock-visual { min-height: 190px; }
|
|
229
|
+
.nav-links { display: none; }
|
|
230
|
+
.palette { grid-template-columns: 1fr 1fr; }
|
|
231
|
+
.voice { grid-template-columns: 1fr; }
|
|
232
|
+
}
|
|
233
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
234
|
+
.button { transition: background-color 160ms ease, transform 160ms ease; }
|
|
235
|
+
.button:hover { background: var(--primary-hover); transform: translateY(-1px); }
|
|
236
|
+
}
|
|
237
|
+
.button:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
|
|
238
|
+
</style>
|
|
239
|
+
</head>
|
|
240
|
+
<body>
|
|
241
|
+
<main>
|
|
242
|
+
<header class="masthead">
|
|
243
|
+
${identityMark}
|
|
244
|
+
<span class="meta">Brand system / ${html(brand.schemaVersion)}</span>
|
|
245
|
+
</header>
|
|
246
|
+
|
|
247
|
+
<section class="identity" aria-labelledby="brand-name">
|
|
248
|
+
<h1 id="brand-name">${html(brand.name)}</h1>
|
|
249
|
+
<div class="identity-copy">
|
|
250
|
+
<p>${html(brand.description)}</p>
|
|
251
|
+
${action}
|
|
252
|
+
</div>
|
|
253
|
+
</section>
|
|
254
|
+
|
|
255
|
+
<section class="showcase" aria-labelledby="mockup-title">
|
|
256
|
+
<div class="section-heading">
|
|
257
|
+
<h2 id="mockup-title">Website mockups</h2>
|
|
258
|
+
<p>One responsive direction shown at desktop and mobile sizes.</p>
|
|
259
|
+
</div>
|
|
260
|
+
<div class="devices">
|
|
261
|
+
<article class="browser" aria-label="Desktop website mockup">
|
|
262
|
+
<div class="browser-bar"><i></i><i></i><i></i></div>
|
|
263
|
+
<div class="browser-nav">
|
|
264
|
+
${identityMark}
|
|
265
|
+
<div class="nav-links"><span>Overview</span><span>Product</span><span>Resources</span></div>
|
|
266
|
+
</div>
|
|
267
|
+
<div class="mock-hero">
|
|
268
|
+
<div class="mock-copy">
|
|
269
|
+
<h3>${html(headline)}</h3>
|
|
270
|
+
<p>${html(brand.description)}</p>
|
|
271
|
+
${action}
|
|
272
|
+
</div>
|
|
273
|
+
<div class="mock-visual">
|
|
274
|
+
<strong>${html(brand.voice.principles[0] ?? brand.name)}</strong>
|
|
275
|
+
</div>
|
|
276
|
+
</div>
|
|
277
|
+
</article>
|
|
278
|
+
|
|
279
|
+
<article class="phone" aria-label="Mobile website mockup">
|
|
280
|
+
<div class="phone-screen">
|
|
281
|
+
<div class="phone-nav">
|
|
282
|
+
<span class="phone-mark">${compactMark}</span>
|
|
283
|
+
<span class="meta">Menu</span>
|
|
284
|
+
</div>
|
|
285
|
+
<div class="phone-copy">
|
|
286
|
+
<h3>${html(headline)}</h3>
|
|
287
|
+
<p>${html(brand.description)}</p>
|
|
288
|
+
</div>
|
|
289
|
+
<div class="phone-accent"></div>
|
|
290
|
+
</div>
|
|
291
|
+
</article>
|
|
292
|
+
</div>
|
|
293
|
+
</section>
|
|
294
|
+
|
|
295
|
+
<section class="system" aria-label="Brand system">
|
|
296
|
+
<div>
|
|
297
|
+
<div class="section-heading"><h2>Core palette</h2></div>
|
|
298
|
+
<div class="palette">
|
|
299
|
+
<div class="swatch" style="background: var(--primary)"><span>${brand.colors.primary}</span></div>
|
|
300
|
+
<div class="swatch" style="background: var(--accent)"><span>${brand.colors.accent}</span></div>
|
|
301
|
+
<div class="swatch" style="background: var(--surface)"><span>${brand.colors.surface}</span></div>
|
|
302
|
+
<div class="swatch" style="background: var(--foreground)"><span>${brand.colors.foreground}</span></div>
|
|
303
|
+
</div>
|
|
304
|
+
</div>
|
|
305
|
+
<div>
|
|
306
|
+
<div class="section-heading"><h2>Typography</h2></div>
|
|
307
|
+
<div class="type-specimen">
|
|
308
|
+
<strong>Aa 01</strong>
|
|
309
|
+
<code>${html(brand.typography.sans)}</code>
|
|
310
|
+
</div>
|
|
311
|
+
</div>
|
|
312
|
+
</section>
|
|
313
|
+
|
|
314
|
+
<section class="voice" aria-labelledby="voice-title">
|
|
315
|
+
<div>
|
|
316
|
+
<h2 id="voice-title">Voice</h2>
|
|
317
|
+
<p class="meta">${html(brand.voice.tone.join(", "))}</p>
|
|
318
|
+
</div>
|
|
319
|
+
<div>
|
|
320
|
+
<h3>Principles</h3>
|
|
321
|
+
<ul>${listItems(brand.voice.principles)}</ul>
|
|
322
|
+
</div>
|
|
323
|
+
</section>
|
|
324
|
+
|
|
325
|
+
${gallery}
|
|
326
|
+
</main>
|
|
327
|
+
</body>
|
|
328
|
+
</html>
|
|
329
|
+
`
|
|
330
|
+
// ============================================================================
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2hvd2Nhc2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYnJhbmQvc2hvd2Nhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7R0FJRztBQUVILE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUdyRCxTQUFTLFNBQVMsQ0FBQyxLQUF5QjtJQUMxQyxJQUFJLENBQUMsS0FBSztRQUFFLE9BQU8sU0FBUyxDQUFDO0lBQzdCLElBQUksK0JBQStCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQztRQUFFLE9BQU8sS0FBSyxDQUFDO0lBQzlELE9BQU8sWUFBWSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7QUFDdEQsQ0FBQztBQUVELFNBQVMsV0FBVyxDQUFDLEtBQXlCO0lBQzVDLE9BQU8sS0FBSyxJQUFJLGNBQWMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBQ2pFLENBQUM7QUFFRCxTQUFTLGNBQWMsQ0FBQyxLQUFhO0lBQ25DLE9BQU8sZ0JBQWdCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLHNDQUFzQyxDQUFDO0FBQ3ZGLENBQUM7QUFFRCxTQUFTLFNBQVMsQ0FBQyxNQUF5QjtJQUMxQyxPQUFPLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLE9BQU8sV0FBVyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ3JGLENBQUM7QUFFRCxnRkFBZ0Y7QUFDaEYsTUFBTSxVQUFVLG1CQUFtQixDQUFDLFlBQTBCO0lBQzVELE1BQU0sRUFBRSxLQUFLLEVBQUUs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S0FBSyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUM7Ozs7Ozs7O2dDQVFuQixJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDOzs7O29CQUk3QyxTQUFTLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUM7Ozs7WUFJekMsT0FBTzs7OztLQUlkO0lBQ0QsK0VBQStFO0tBQ2hGLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBTZWxmLWNvbnRhaW5lZCBIVE1MIHByZXNlbnRhdGlvbiBmb3IgYW4gZXhwb3J0ZWQgYnJhbmQgcGFja2FnZS5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHsgc3RyaW5nVXRpbHMgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHR5cGUgeyBCcmFuZFBhY2thZ2UgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtZ2VuZXJhdG9yXCI7XG5cbmZ1bmN0aW9uIHNhZmVBc3NldCh2YWx1ZTogc3RyaW5nIHwgdW5kZWZpbmVkKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgaWYgKCF2YWx1ZSkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgaWYgKC9eKD86ZGF0YTppbWFnZVxcL3xodHRwczpcXC9cXC8pL2kudGVzdCh2YWx1ZSkpIHJldHVybiB2YWx1ZTtcbiAgcmV0dXJuIC9eXFwuezAsMn1cXC8vLnRlc3QodmFsdWUpID8gdmFsdWUgOiB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIHNhZmVXZWJzaXRlKHZhbHVlOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICByZXR1cm4gdmFsdWUgJiYgL15odHRwczpcXC9cXC8vaS50ZXN0KHZhbHVlKSA/IHZhbHVlIDogdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiBzYWZlRm9udEZhbWlseSh2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIC9eW1xcd1xccydcIiwuLV0rJC8udGVzdCh2YWx1ZSkgPyB2YWx1ZSA6IFwidWktc2Fucy1zZXJpZiwgc3lzdGVtLXVpLCBzYW5zLXNlcmlmXCI7XG59XG5cbmZ1bmN0aW9uIGxpc3RJdGVtcyh2YWx1ZXM6IHJlYWRvbmx5IHN0cmluZ1tdKTogc3RyaW5nIHtcbiAgcmV0dXJuIHZhbHVlcy5tYXAoKHZhbHVlKSA9PiBgPGxpPiR7c3RyaW5nVXRpbHMuZXNjYXBlSHRtbCh2YWx1ZSl9PC9saT5gKS5qb2luKFwiXCIpO1xufVxuXG4vKiogUmVuZGVyIG9uZSByZXNwb25zaXZlIGJyYW5kIHByZXNlbnRhdGlvbiB3aXRoIGRlc2t0b3AgYW5kIG1vYmlsZSBtb2NrdXBzLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlbmRlckJyYW5kU2hvd2Nhc2UoYnJhbmRQYWNrYWdlOiBCcmFuZFBhY2thZ2UpOiBzdHJpbmcge1xuICBjb25zdCB7IGJyYW5kLCB2aXN1YWxSZWZlcmVuY2VzIH0gPSBicmFuZFBhY2thZ2U7XG4gIGNvbnN0IGh0bWwgPSBzdHJpbmdVdGlscy5lc2NhcGVIdG1sO1xuICBjb25zdCBsb2dvID0gc2FmZUFzc2V0KGJyYW5kLmFzc2V0cy5sb2dvLmxpZ2h0KSA/PyBzYWZlQXNzZXQoYnJhbmQuYXNzZXRzLmljb24ubGlnaHQpO1xuICBjb25zdCBpY29uID0gc2FmZUFzc2V0KGJyYW5kLmFzc2V0cy5pY29uLmxpZ2h0KTtcbiAgY29uc3Qgd2Vic2l0ZSA9IHNhZmVXZWJzaXRlKGJyYW5kLmxpbmtzLndlYnNpdGUpO1xuICBjb25zdCBzY3JlZW5zaG90cyA9IHZpc3VhbFJlZmVyZW5jZXNcbiAgICAuZmxhdE1hcCgocmVmZXJlbmNlKSA9PlxuICAgICAgcmVmZXJlbmNlLmltYWdlcy5mbGF0TWFwKChpbWFnZSkgPT5cbiAgICAgICAgaW1hZ2UubG9jYWxQYXRoXG4gICAgICAgICAgPyBbeyBhcHBOYW1lOiByZWZlcmVuY2UuYXBwTmFtZSwgcGxhdGZvcm06IHJlZmVyZW5jZS5wbGF0Zm9ybSwgcGF0aDogaW1hZ2UubG9jYWxQYXRoIH1dXG4gICAgICAgICAgOiBbXSxcbiAgICAgICksXG4gICAgKVxuICAgIC5zbGljZSgwLCA0KTtcbiAgY29uc3QgaWRlbnRpdHlNYXJrID0gbG9nb1xuICAgID8gYDxpbWcgc3JjPVwiJHtodG1sKGxvZ28pfVwiIGFsdD1cIiR7aHRtbChicmFuZC5uYW1lKX0gbG9nb1wiPmBcbiAgICA6IGA8c3BhbiBjbGFzcz1cIndvcmRtYXJrXCI+JHtodG1sKGJyYW5kLnNob3J0TmFtZSl9PC9zcGFuPmA7XG4gIGNvbnN0IGNvbXBhY3RNYXJrID0gaWNvblxuICAgID8gYDxpbWcgc3JjPVwiJHtodG1sKGljb24pfVwiIGFsdD1cIlwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPmBcbiAgICA6IGA8c3BhbiBjbGFzcz1cImNvbXBhY3Qtd29yZG1hcmtcIj4ke2h0bWwoYnJhbmQuc2hvcnROYW1lLnNsaWNlKDAsIDIpKX08L3NwYW4+YDtcbiAgY29uc3QgYWN0aW9uID0gd2Vic2l0ZVxuICAgID8gYDxhIGNsYXNzPVwiYnV0dG9uXCIgaHJlZj1cIiR7aHRtbCh3ZWJzaXRlKX1cIj5WaXNpdCB3ZWJzaXRlPC9hPmBcbiAgICA6IGA8c3BhbiBjbGFzcz1cImJ1dHRvblwiPkV4cGxvcmUgdGhlIGJyYW5kPC9zcGFuPmA7XG4gIGNvbnN0IGdhbGxlcnkgPSBzY3JlZW5zaG90cy5sZW5ndGhcbiAgICA/IGBcbiAgICAgIDxzZWN0aW9uIGNsYXNzPVwicmVmZXJlbmNlc1wiIGFyaWEtbGFiZWxsZWRieT1cInJlZmVyZW5jZXMtdGl0bGVcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInNlY3Rpb24taGVhZGluZ1wiPlxuICAgICAgICAgIDxoMiBpZD1cInJlZmVyZW5jZXMtdGl0bGVcIj5WaXN1YWwgcmVmZXJlbmNlczwvaDI+XG4gICAgICAgICAgPHA+U3VwcGxlbWVudGFsIG1vYmlsZSByZWZlcmVuY2VzIHVzZWQgZHVyaW5nIHJlc2VhcmNoLjwvcD5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJyZWZlcmVuY2UtZ3JpZFwiPlxuICAgICAgICAgICR7c2NyZWVuc2hvdHNcbiAgICAgICAgICAgIC5tYXAoXG4gICAgICAgICAgICAgICh7IGFwcE5hbWUsIHBhdGgsIHBsYXRmb3JtIH0pID0+IGBcbiAgICAgICAgICAgICAgICA8ZmlndXJlPlxuICAgICAgICAgICAgICAgICAgPGltZyBzcmM9XCIke2h0bWwocGF0aCl9XCIgYWx0PVwiJHtodG1sKGFwcE5hbWUpfSAke2h0bWwocGxhdGZvcm0pfSByZWZlcmVuY2VcIj5cbiAgICAgICAgICAgICAgICAgIDxmaWdjYXB0aW9uPiR7aHRtbChhcHBOYW1lKX0gLyAke2h0bWwocGxhdGZvcm0pfTwvZmlnY2FwdGlvbj5cbiAgICAgICAgICAgICAgICA8L2ZpZ3VyZT5cbiAgICAgICAgICAgICAgYCxcbiAgICAgICAgICAgIClcbiAgICAgICAgICAgIC5qb2luKFwiXCIpfVxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvc2VjdGlvbj5cbiAgICBgXG4gICAgOiBcIlwiO1xuICBjb25zdCBoZWFkbGluZSA9IGJyYW5kLnRhZ2xpbmUgPz8gYnJhbmQubmFtZTtcblxuICAvLyBwcmV0dGllci1pZ25vcmVcbiAgcmV0dXJuIHN0cmluZ1V0aWxzLmRlZGVudChcbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLypodG1sKi9gXG4gICAgPCFkb2N0eXBlIGh0bWw+XG4gICAgPGh0bWwgbGFuZz1cImVuXCI+XG4gICAgICA8aGVhZD5cbiAgICAgICAgPG1ldGEgY2hhcnNldD1cInV0Zi04XCI+XG4gICAgICAgIDxtZXRhIG5hbWU9XCJ2aWV3cG9ydFwiIGNvbnRlbnQ9XCJ3aWR0aD1kZXZpY2Utd2lkdGgsIGluaXRpYWwtc2NhbGU9MVwiPlxuICAgICAgICA8dGl0bGU+JHtodG1sKGJyYW5kLm5hbWUpfSBicmFuZCBwcmVzZW50YXRpb248L3RpdGxlPlxuICAgICAgICA8c3R5bGU+XG4gICAgICAgICAgOnJvb3Qge1xuICAgICAgICAgICAgY29sb3Itc2NoZW1lOiBsaWdodDtcbiAgICAgICAgICAgIC0tcHJpbWFyeTogJHticmFuZC5jb2xvcnMucHJpbWFyeX07XG4gICAgICAgICAgICAtLXByaW1hcnktaG92ZXI6ICR7YnJhbmQuY29sb3JzLnByaW1hcnlIb3Zlcn07XG4gICAgICAgICAgICAtLWFjY2VudDogJHticmFuZC5jb2xvcnMuYWNjZW50fTtcbiAgICAgICAgICAgIC0tZm9yZWdyb3VuZDogJHticmFuZC5jb2xvcnMuZm9yZWdyb3VuZH07XG4gICAgICAgICAgICAtLWJhY2tncm91bmQ6ICR7YnJhbmQuY29sb3JzLmJhY2tncm91bmR9O1xuICAgICAgICAgICAgLS1zdXJmYWNlOiAke2JyYW5kLmNvbG9ycy5zdXJmYWNlfTtcbiAgICAgICAgICAgIC0tbXV0ZWQ6ICR7YnJhbmQuY29sb3JzLm11dGVkfTtcbiAgICAgICAgICAgIC0tYm9yZGVyOiAke2JyYW5kLmNvbG9ycy5ib3JkZXJ9O1xuICAgICAgICAgICAgLS1zYW5zOiAke3NhZmVGb250RmFtaWx5KGJyYW5kLnR5cG9ncmFwaHkuc2Fucyl9O1xuICAgICAgICAgICAgLS1tb25vOiAke3NhZmVGb250RmFtaWx5KGJyYW5kLnR5cG9ncmFwaHkubW9ubyl9O1xuICAgICAgICAgIH1cbiAgICAgICAgICAqIHsgYm94LXNpemluZzogYm9yZGVyLWJveDsgfVxuICAgICAgICAgIGJvZHkge1xuICAgICAgICAgICAgbWFyZ2luOiAwO1xuICAgICAgICAgICAgYmFja2dyb3VuZDogdmFyKC0tYmFja2dyb3VuZCk7XG4gICAgICAgICAgICBjb2xvcjogdmFyKC0tZm9yZWdyb3VuZCk7XG4gICAgICAgICAgICBmb250LWZhbWlseTogdmFyKC0tc2Fucyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGEgeyBjb2xvcjogaW5oZXJpdDsgfVxuICAgICAgICAgIGltZyB7IGRpc3BsYXk6IGJsb2NrOyBtYXgtd2lkdGg6IDEwMCU7IH1cbiAgICAgICAgICBtYWluIHsgbWFyZ2luOiAwIGF1dG87IG1heC13aWR0aDogMTI0MHB4OyBwYWRkaW5nOiAwIDMycHggNzJweDsgfVxuICAgICAgICAgIC5tYXN0aGVhZCB7XG4gICAgICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgICAgICAgICAgYm9yZGVyLWJvdHRvbTogMXB4IHNvbGlkIHZhcigtLWJvcmRlcik7XG4gICAgICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICAgICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xuICAgICAgICAgICAgbWluLWhlaWdodDogODhweDtcbiAgICAgICAgICB9XG4gICAgICAgICAgLm1hc3RoZWFkIGltZyB7IG1heC1oZWlnaHQ6IDQycHg7IG1heC13aWR0aDogMjEwcHg7IH1cbiAgICAgICAgICAud29yZG1hcmsgeyBmb250LXNpemU6IDI0cHg7IGZvbnQtd2VpZ2h0OiA3NTA7IGxldHRlci1zcGFjaW5nOiAtMC4wNGVtOyB9XG4gICAgICAgICAgLm1ldGEgeyBjb2xvcjogdmFyKC0tbXV0ZWQpOyBmb250LWZhbWlseTogdmFyKC0tbW9ubyk7IGZvbnQtc2l6ZTogMTJweDsgfVxuICAgICAgICAgIC5pZGVudGl0eSB7XG4gICAgICAgICAgICBkaXNwbGF5OiBncmlkO1xuICAgICAgICAgICAgZ2FwOiA0OHB4O1xuICAgICAgICAgICAgZ3JpZC10ZW1wbGF0ZS1jb2x1bW5zOiBtaW5tYXgoMCwgMS40ZnIpIG1pbm1heCgyNjBweCwgMC42ZnIpO1xuICAgICAgICAgICAgcGFkZGluZzogNzJweCAwIDY0cHg7XG4gICAgICAgICAgfVxuICAgICAgICAgIC5pZGVudGl0eSBoMSB7XG4gICAgICAgICAgICBmb250LXNpemU6IGNsYW1wKDQ4cHgsIDh2dywgMTA0cHgpO1xuICAgICAgICAgICAgbGV0dGVyLXNwYWNpbmc6IC0wLjA2NWVtO1xuICAgICAgICAgICAgbGluZS1oZWlnaHQ6IDAuOTI7XG4gICAgICAgICAgICBtYXJnaW46IDA7XG4gICAgICAgICAgICBtYXgtd2lkdGg6IDg1MHB4O1xuICAgICAgICAgIH1cbiAgICAgICAgICAuaWRlbnRpdHktY29weSB7IGFsaWduLXNlbGY6IGVuZDsgfVxuICAgICAgICAgIC5pZGVudGl0eS1jb3B5IHAgeyBjb2xvcjogdmFyKC0tbXV0ZWQpOyBmb250LXNpemU6IDE3cHg7IGxpbmUtaGVpZ2h0OiAxLjY1OyBtYXJnaW46IDAgMCAyOHB4OyB9XG4gICAgICAgICAgLmJ1dHRvbiB7XG4gICAgICAgICAgICBiYWNrZ3JvdW5kOiB2YXIoLS1wcmltYXJ5KTtcbiAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6IDk5OXB4O1xuICAgICAgICAgICAgY29sb3I6IHZhcigtLWJhY2tncm91bmQpO1xuICAgICAgICAgICAgZGlzcGxheTogaW5saW5lLWZsZXg7XG4gICAgICAgICAgICBmb250LXdlaWdodDogNzAwO1xuICAgICAgICAgICAgcGFkZGluZzogMTJweCAyMHB4O1xuICAgICAgICAgICAgdGV4dC1kZWNvcmF0aW9uOiBub25lO1xuICAgICAgICAgIH1cbiAgICAgICAgICAuc2hvd2Nhc2Uge1xuICAgICAgICAgICAgYmFja2dyb3VuZDogdmFyKC0tc3VyZmFjZSk7XG4gICAgICAgICAgICBib3JkZXI6IDFweCBzb2xpZCB2YXIoLS1ib3JkZXIpO1xuICAgICAgICAgICAgYm9yZGVyLXJhZGl1czogMjhweDtcbiAgICAgICAgICAgIG92ZXJmbG93OiBoaWRkZW47XG4gICAgICAgICAgICBwYWRkaW5nOiAzOHB4O1xuICAgICAgICAgIH1cbiAgICAgICAgICAuc2VjdGlvbi1oZWFkaW5nIHsgYWxpZ24taXRlbXM6IGVuZDsgZGlzcGxheTogZmxleDsgZ2FwOiAyNHB4OyBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47IG1hcmdpbi1ib3R0b206IDI4cHg7IH1cbiAgICAgICAgICAuc2VjdGlvbi1oZWFkaW5nIGgyIHsgZm9udC1zaXplOiAzMHB4OyBsZXR0ZXItc3BhY2luZzogLTAuMDM1ZW07IG1hcmdpbjogMDsgfVxuICAgICAgICAgIC5zZWN0aW9uLWhlYWRpbmcgcCB7IGNvbG9yOiB2YXIoLS1tdXRlZCk7IG1hcmdpbjogMDsgbWF4LXdpZHRoOiA0NjBweDsgdGV4dC1hbGlnbjogcmlnaHQ7IH1cbiAgICAgICAgICAuZGV2aWNlcyB7IGFsaWduLWl0ZW1zOiBlbmQ7IGRpc3BsYXk6IGdyaWQ7IGdhcDogMjhweDsgZ3JpZC10ZW1wbGF0ZS1jb2x1bW5zOiBtaW5tYXgoMCwgMWZyKSAyODBweDsgfVxuICAgICAgICAgIC5icm93c2VyLCAucGhvbmUge1xuICAgICAgICAgICAgYmFja2dyb3VuZDogdmFyKC0tYmFja2dyb3VuZCk7XG4gICAgICAgICAgICBib3JkZXI6IDFweCBzb2xpZCBjb2xvci1taXgoaW4gc3JnYiwgdmFyKC0tZm9yZWdyb3VuZCkgMTglLCB0cmFuc3BhcmVudCk7XG4gICAgICAgICAgICBib3gtc2hhZG93OiAwIDI0cHggNzBweCBjb2xvci1taXgoaW4gc3JnYiwgdmFyKC0tZm9yZWdyb3VuZCkgMTMlLCB0cmFuc3BhcmVudCk7XG4gICAgICAgICAgICBvdmVyZmxvdzogaGlkZGVuO1xuICAgICAgICAgIH1cbiAgICAgICAgICAuYnJvd3NlciB7IGJvcmRlci1yYWRpdXM6IDE4cHg7IH1cbiAgICAgICAgICAuYnJvd3Nlci1iYXIgeyBhbGlnbi1pdGVtczogY2VudGVyOyBiYWNrZ3JvdW5kOiB2YXIoLS1mb3JlZ3JvdW5kKTsgZGlzcGxheTogZmxleDsgZ2FwOiA3cHg7IGhlaWdodDogMzhweDsgcGFkZGluZzogMCAxNnB4OyB9XG4gICAgICAgICAgLmJyb3dzZXItYmFyIGkgeyBiYWNrZ3JvdW5kOiB2YXIoLS1hY2NlbnQpOyBib3JkZXItcmFkaXVzOiA1MCU7IGRpc3BsYXk6IGJsb2NrOyBoZWlnaHQ6IDdweDsgb3BhY2l0eTogMC44OyB3aWR0aDogN3B4OyB9XG4gICAgICAgICAgLmJyb3dzZXItbmF2LCAucGhvbmUtbmF2IHsgYWxpZ24taXRlbXM6IGNlbnRlcjsgZGlzcGxheTogZmxleDsganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuOyBwYWRkaW5nOiAyMHB4IDI0cHg7IH1cbiAgICAgICAgICAuYnJvd3Nlci1uYXYgaW1nIHsgbWF4LWhlaWdodDogMzBweDsgbWF4LXdpZHRoOiAxNTBweDsgfVxuICAgICAgICAgIC5uYXYtbGlua3MgeyBjb2xvcjogdmFyKC0tbXV0ZWQpOyBkaXNwbGF5OiBmbGV4OyBmb250LXNpemU6IDEycHg7IGdhcDogMjJweDsgfVxuICAgICAgICAgIC5tb2NrLWhlcm8geyBkaXNwbGF5OiBncmlkOyBnYXA6IDI4cHg7IGdyaWQtdGVtcGxhdGUtY29sdW1uczogMS4xZnIgMC45ZnI7IG1pbi1oZWlnaHQ6IDM1MHB4OyBwYWRkaW5nOiA0NHB4OyB9XG4gICAgICAgICAgLm1vY2stY29weSB7IGFsaWduLXNlbGY6IGNlbnRlcjsgfVxuICAgICAgICAgIC5tb2NrLWNvcHkgaDMgeyBmb250LXNpemU6IGNsYW1wKDM0cHgsIDV2dywgNjRweCk7IGxldHRlci1zcGFjaW5nOiAtMC4wNTVlbTsgbGluZS1oZWlnaHQ6IDAuOTg7IG1hcmdpbjogMCAwIDIycHg7IH1cbiAgICAgICAgICAubW9jay1jb3B5IHAgeyBjb2xvcjogdmFyKC0tbXV0ZWQpOyBsaW5lLWhlaWdodDogMS41NTsgbWFyZ2luOiAwIDAgMjRweDsgbWF4LXdpZHRoOiA1MjBweDsgfVxuICAgICAgICAgIC5tb2NrLXZpc3VhbCB7XG4gICAgICAgICAgICBhbGlnbi1jb250ZW50OiBlbmQ7XG4gICAgICAgICAgICBiYWNrZ3JvdW5kOiB2YXIoLS1wcmltYXJ5KTtcbiAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6IDIwcHg7XG4gICAgICAgICAgICBjb2xvcjogdmFyKC0tYmFja2dyb3VuZCk7XG4gICAgICAgICAgICBkaXNwbGF5OiBncmlkO1xuICAgICAgICAgICAgbWluLWhlaWdodDogMjUwcHg7XG4gICAgICAgICAgICBvdmVyZmxvdzogaGlkZGVuO1xuICAgICAgICAgICAgcGFkZGluZzogMjhweDtcbiAgICAgICAgICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLm1vY2stdmlzdWFsOjpiZWZvcmUge1xuICAgICAgICAgICAgYmFja2dyb3VuZDogdmFyKC0tYWNjZW50KTtcbiAgICAgICAgICAgIGJvcmRlci1yYWRpdXM6IDUwJTtcbiAgICAgICAgICAgIGNvbnRlbnQ6IFwiXCI7XG4gICAgICAgICAgICBoZWlnaHQ6IDIxMHB4O1xuICAgICAgICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgICAgICAgcmlnaHQ6IC03MHB4O1xuICAgICAgICAgICAgdG9wOiAtODBweDtcbiAgICAgICAgICAgIHdpZHRoOiAyMTBweDtcbiAgICAgICAgICB9XG4gICAgICAgICAgLm1vY2stdmlzdWFsIHN0cm9uZyB7IGZvbnQtc2l6ZTogMjJweDsgbGluZS1oZWlnaHQ6IDEuMTU7IG1heC13aWR0aDogMjIwcHg7IHBvc2l0aW9uOiByZWxhdGl2ZTsgfVxuICAgICAgICAgIC5waG9uZSB7IGJvcmRlcjogOHB4IHNvbGlkIHZhcigtLWZvcmVncm91bmQpOyBib3JkZXItcmFkaXVzOiAzNHB4OyB9XG4gICAgICAgICAgLnBob25lLXNjcmVlbiB7IG1pbi1oZWlnaHQ6IDU0MHB4OyB9XG4gICAgICAgICAgLnBob25lLW5hdiB7IHBhZGRpbmc6IDE4cHg7IH1cbiAgICAgICAgICAucGhvbmUtbmF2IGltZyB7IGhlaWdodDogMzBweDsgbWF4LXdpZHRoOiAxMTJweDsgb2JqZWN0LWZpdDogY29udGFpbjsgb2JqZWN0LXBvc2l0aW9uOiBsZWZ0IGNlbnRlcjsgfVxuICAgICAgICAgIC5waG9uZS1tYXJrIGltZyB7IGhlaWdodDogMzBweDsgd2lkdGg6IDMwcHg7IH1cbiAgICAgICAgICAuY29tcGFjdC13b3JkbWFyayB7IGZvbnQtd2VpZ2h0OiA4MDA7IH1cbiAgICAgICAgICAucGhvbmUtY29weSB7IHBhZGRpbmc6IDM0cHggMjJweCAyNHB4OyB9XG4gICAgICAgICAgLnBob25lLWNvcHkgaDMgeyBmb250LXNpemU6IDM4cHg7IGxldHRlci1zcGFjaW5nOiAtMC4wNWVtOyBsaW5lLWhlaWdodDogMC45ODsgbWFyZ2luOiAwIDAgMThweDsgfVxuICAgICAgICAgIC5waG9uZS1jb3B5IHAgeyBjb2xvcjogdmFyKC0tbXV0ZWQpOyBmb250LXNpemU6IDE0cHg7IGxpbmUtaGVpZ2h0OiAxLjU1OyBtYXJnaW46IDA7IH1cbiAgICAgICAgICAucGhvbmUtYWNjZW50IHsgYmFja2dyb3VuZDogdmFyKC0tYWNjZW50KTsgaGVpZ2h0OiAxMjBweDsgbWFyZ2luOiAxOHB4IDIycHggMjJweDsgfVxuICAgICAgICAgIC5zeXN0ZW0ge1xuICAgICAgICAgICAgZGlzcGxheTogZ3JpZDtcbiAgICAgICAgICAgIGdhcDogNDhweDtcbiAgICAgICAgICAgIGdyaWQtdGVtcGxhdGUtY29sdW1uczogMWZyIDFmcjtcbiAgICAgICAgICAgIHBhZGRpbmc6IDcycHggMDtcbiAgICAgICAgICB9XG4gICAgICAgICAgLnBhbGV0dGUgeyBkaXNwbGF5OiBncmlkOyBncmlkLXRlbXBsYXRlLWNvbHVtbnM6IHJlcGVhdCg0LCAxZnIpOyBtaW4taGVpZ2h0OiAyNTBweDsgfVxuICAgICAgICAgIC5zd2F0Y2ggeyBhbGlnbi1pdGVtczogZW5kOyBkaXNwbGF5OiBmbGV4OyBwYWRkaW5nOiAxNnB4OyB9XG4gICAgICAgICAgLnN3YXRjaCBzcGFuIHsgYmFja2dyb3VuZDogdmFyKC0tYmFja2dyb3VuZCk7IGNvbG9yOiB2YXIoLS1mb3JlZ3JvdW5kKTsgZm9udC1mYW1pbHk6IHZhcigtLW1vbm8pOyBmb250LXNpemU6IDExcHg7IHBhZGRpbmc6IDVweCA3cHg7IH1cbiAgICAgICAgICAudHlwZS1zcGVjaW1lbiB7IGJvcmRlci10b3A6IDFweCBzb2xpZCB2YXIoLS1ib3JkZXIpOyBwYWRkaW5nLXRvcDogMjRweDsgfVxuICAgICAgICAgIC50eXBlLXNwZWNpbWVuIHN0cm9uZyB7IGRpc3BsYXk6IGJsb2NrOyBmb250LXNpemU6IGNsYW1wKDQ0cHgsIDZ2dywgNzZweCk7IGxldHRlci1zcGFjaW5nOiAtMC4wNWVtOyBsaW5lLWhlaWdodDogMC45NTsgfVxuICAgICAgICAgIC50eXBlLXNwZWNpbWVuIGNvZGUgeyBjb2xvcjogdmFyKC0tbXV0ZWQpOyBkaXNwbGF5OiBibG9jazsgZm9udC1mYW1pbHk6IHZhcigtLW1vbm8pOyBtYXJnaW4tdG9wOiAyMHB4OyB9XG4gICAgICAgICAgLnZvaWNlIHsgYm9yZGVyLXRvcDogMXB4IHNvbGlkIHZhcigtLWJvcmRlcik7IGRpc3BsYXk6IGdyaWQ7IGdhcDogMzJweDsgZ3JpZC10ZW1wbGF0ZS1jb2x1bW5zOiAxZnIgMWZyOyBwYWRkaW5nOiAzNnB4IDA7IH1cbiAgICAgICAgICAudm9pY2UgaDIgeyBmb250LXNpemU6IDMwcHg7IGxldHRlci1zcGFjaW5nOiAtMC4wMzVlbTsgbWFyZ2luOiAwOyB9XG4gICAgICAgICAgLnZvaWNlIGgzIHsgZm9udC1zaXplOiAxNHB4OyBtYXJnaW46IDAgMCAxMnB4OyB9XG4gICAgICAgICAgLnZvaWNlIHVsIHsgY29sb3I6IHZhcigtLW11dGVkKTsgbGluZS1oZWlnaHQ6IDEuNjsgbWFyZ2luOiAwOyBwYWRkaW5nLWxlZnQ6IDE4cHg7IH1cbiAgICAgICAgICAucmVmZXJlbmNlcyB7IGJvcmRlci10b3A6IDFweCBzb2xpZCB2YXIoLS1ib3JkZXIpOyBwYWRkaW5nLXRvcDogNTZweDsgfVxuICAgICAgICAgIC5yZWZlcmVuY2UtZ3JpZCB7IGRpc3BsYXk6IGdyaWQ7IGdhcDogMThweDsgZ3JpZC10ZW1wbGF0ZS1jb2x1bW5zOiByZXBlYXQoNCwgMWZyKTsgfVxuICAgICAgICAgIGZpZ3VyZSB7IG1hcmdpbjogMDsgfVxuICAgICAgICAgIGZpZ3VyZSBpbWcgeyBhc3BlY3QtcmF0aW86IDkgLyAxNjsgYmFja2dyb3VuZDogdmFyKC0tc3VyZmFjZSk7IGJvcmRlcjogMXB4IHNvbGlkIHZhcigtLWJvcmRlcik7IG9iamVjdC1maXQ6IGNvbnRhaW47IHdpZHRoOiAxMDAlOyB9XG4gICAgICAgICAgZmlnY2FwdGlvbiB7IGNvbG9yOiB2YXIoLS1tdXRlZCk7IGZvbnQtc2l6ZTogMTFweDsgbWFyZ2luLXRvcDogOHB4OyB9XG4gICAgICAgICAgQG1lZGlhIChtYXgtd2lkdGg6IDg2MHB4KSB7XG4gICAgICAgICAgICBtYWluIHsgcGFkZGluZzogMCAxOHB4IDQ4cHg7IH1cbiAgICAgICAgICAgIC5pZGVudGl0eSwgLnN5c3RlbSB7IGdyaWQtdGVtcGxhdGUtY29sdW1uczogMWZyOyB9XG4gICAgICAgICAgICAuaWRlbnRpdHkgeyBnYXA6IDI4cHg7IHBhZGRpbmc6IDUycHggMCA0NHB4OyB9XG4gICAgICAgICAgICAuc2hvd2Nhc2UgeyBib3JkZXItcmFkaXVzOiAyMHB4OyBwYWRkaW5nOiAyMHB4OyB9XG4gICAgICAgICAgICAuZGV2aWNlcyB7IGdyaWQtdGVtcGxhdGUtY29sdW1uczogMWZyOyB9XG4gICAgICAgICAgICAucGhvbmUgeyBtYXJnaW46IDAgYXV0bzsgbWF4LXdpZHRoOiAzMjBweDsgd2lkdGg6IDEwMCU7IH1cbiAgICAgICAgICAgIC5yZWZlcmVuY2UtZ3JpZCB7IGdyaWQtdGVtcGxhdGUtY29sdW1uczogcmVwZWF0KDIsIDFmcik7IH1cbiAgICAgICAgICB9XG4gICAgICAgICAgQG1lZGlhIChtYXgtd2lkdGg6IDU2MHB4KSB7XG4gICAgICAgICAgICAubWFzdGhlYWQgeyBtaW4taGVpZ2h0OiA3MnB4OyB9XG4gICAgICAgICAgICAuaWRlbnRpdHkgaDEgeyBmb250LXNpemU6IDUycHg7IH1cbiAgICAgICAgICAgIC5zZWN0aW9uLWhlYWRpbmcgeyBhbGlnbi1pdGVtczogc3RhcnQ7IGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47IH1cbiAgICAgICAgICAgIC5zZWN0aW9uLWhlYWRpbmcgcCB7IHRleHQtYWxpZ246IGxlZnQ7IH1cbiAgICAgICAgICAgIC5tb2NrLWhlcm8geyBncmlkLXRlbXBsYXRlLWNvbHVtbnM6IDFmcjsgcGFkZGluZzogMjRweDsgfVxuICAgICAgICAgICAgLm1vY2stdmlzdWFsIHsgbWluLWhlaWdodDogMTkwcHg7IH1cbiAgICAgICAgICAgIC5uYXYtbGlua3MgeyBkaXNwbGF5OiBub25lOyB9XG4gICAgICAgICAgICAucGFsZXR0ZSB7IGdyaWQtdGVtcGxhdGUtY29sdW1uczogMWZyIDFmcjsgfVxuICAgICAgICAgICAgLnZvaWNlIHsgZ3JpZC10ZW1wbGF0ZS1jb2x1bW5zOiAxZnI7IH1cbiAgICAgICAgICB9XG4gICAgICAgICAgQG1lZGlhIChwcmVmZXJzLXJlZHVjZWQtbW90aW9uOiBuby1wcmVmZXJlbmNlKSB7XG4gICAgICAgICAgICAuYnV0dG9uIHsgdHJhbnNpdGlvbjogYmFja2dyb3VuZC1jb2xvciAxNjBtcyBlYXNlLCB0cmFuc2Zvcm0gMTYwbXMgZWFzZTsgfVxuICAgICAgICAgICAgLmJ1dHRvbjpob3ZlciB7IGJhY2tncm91bmQ6IHZhcigtLXByaW1hcnktaG92ZXIpOyB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoLTFweCk7IH1cbiAgICAgICAgICB9XG4gICAgICAgICAgLmJ1dHRvbjpmb2N1cy12aXNpYmxlIHsgb3V0bGluZTogM3B4IHNvbGlkIHZhcigtLWFjY2VudCk7IG91dGxpbmUtb2Zmc2V0OiAzcHg7IH1cbiAgICAgICAgPC9zdHlsZT5cbiAgICAgIDwvaGVhZD5cbiAgICAgIDxib2R5PlxuICAgICAgICA8bWFpbj5cbiAgICAgICAgICA8aGVhZGVyIGNsYXNzPVwibWFzdGhlYWRcIj5cbiAgICAgICAgICAgICR7aWRlbnRpdHlNYXJrfVxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJtZXRhXCI+QnJhbmQgc3lzdGVtIC8gJHtodG1sKGJyYW5kLnNjaGVtYVZlcnNpb24pfTwvc3Bhbj5cbiAgICAgICAgICA8L2hlYWRlcj5cblxuICAgICAgICAgIDxzZWN0aW9uIGNsYXNzPVwiaWRlbnRpdHlcIiBhcmlhLWxhYmVsbGVkYnk9XCJicmFuZC1uYW1lXCI+XG4gICAgICAgICAgICA8aDEgaWQ9XCJicmFuZC1uYW1lXCI+JHtodG1sKGJyYW5kLm5hbWUpfTwvaDE+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiaWRlbnRpdHktY29weVwiPlxuICAgICAgICAgICAgICA8cD4ke2h0bWwoYnJhbmQuZGVzY3JpcHRpb24pfTwvcD5cbiAgICAgICAgICAgICAgJHthY3Rpb259XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L3NlY3Rpb24+XG5cbiAgICAgICAgICA8c2VjdGlvbiBjbGFzcz1cInNob3djYXNlXCIgYXJpYS1sYWJlbGxlZGJ5PVwibW9ja3VwLXRpdGxlXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwic2VjdGlvbi1oZWFkaW5nXCI+XG4gICAgICAgICAgICAgIDxoMiBpZD1cIm1vY2t1cC10aXRsZVwiPldlYnNpdGUgbW9ja3VwczwvaDI+XG4gICAgICAgICAgICAgIDxwPk9uZSByZXNwb25zaXZlIGRpcmVjdGlvbiBzaG93biBhdCBkZXNrdG9wIGFuZCBtb2JpbGUgc2l6ZXMuPC9wPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZGV2aWNlc1wiPlxuICAgICAgICAgICAgICA8YXJ0aWNsZSBjbGFzcz1cImJyb3dzZXJcIiBhcmlhLWxhYmVsPVwiRGVza3RvcCB3ZWJzaXRlIG1vY2t1cFwiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJicm93c2VyLWJhclwiPjxpPjwvaT48aT48L2k+PGk+PC9pPjwvZGl2PlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJicm93c2VyLW5hdlwiPlxuICAgICAgICAgICAgICAgICAgJHtpZGVudGl0eU1hcmt9XG4gICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibmF2LWxpbmtzXCI+PHNwYW4+T3ZlcnZpZXc8L3NwYW4+PHNwYW4+UHJvZHVjdDwvc3Bhbj48c3Bhbj5SZXNvdXJjZXM8L3NwYW4+PC9kaXY+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1vY2staGVyb1wiPlxuICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1vY2stY29weVwiPlxuICAgICAgICAgICAgICAgICAgICA8aDM+JHtodG1sKGhlYWRsaW5lKX08L2gzPlxuICAgICAgICAgICAgICAgICAgICA8cD4ke2h0bWwoYnJhbmQuZGVzY3JpcHRpb24pfTwvcD5cbiAgICAgICAgICAgICAgICAgICAgJHthY3Rpb259XG4gICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtb2NrLXZpc3VhbFwiPlxuICAgICAgICAgICAgICAgICAgICA8c3Ryb25nPiR7aHRtbChicmFuZC52b2ljZS5wcmluY2lwbGVzWzBdID8/IGJyYW5kLm5hbWUpfTwvc3Ryb25nPlxuICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIDwvYXJ0aWNsZT5cblxuICAgICAgICAgICAgICA8YXJ0aWNsZSBjbGFzcz1cInBob25lXCIgYXJpYS1sYWJlbD1cIk1vYmlsZSB3ZWJzaXRlIG1vY2t1cFwiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJwaG9uZS1zY3JlZW5cIj5cbiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJwaG9uZS1uYXZcIj5cbiAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJwaG9uZS1tYXJrXCI+JHtjb21wYWN0TWFya308L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwibWV0YVwiPk1lbnU8L3NwYW4+XG4gICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJwaG9uZS1jb3B5XCI+XG4gICAgICAgICAgICAgICAgICAgIDxoMz4ke2h0bWwoaGVhZGxpbmUpfTwvaDM+XG4gICAgICAgICAgICAgICAgICAgIDxwPiR7aHRtbChicmFuZC5kZXNjcmlwdGlvbil9PC9wPlxuICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwicGhvbmUtYWNjZW50XCI+PC9kaXY+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIDwvYXJ0aWNsZT5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvc2VjdGlvbj5cblxuICAgICAgICAgIDxzZWN0aW9uIGNsYXNzPVwic3lzdGVtXCIgYXJpYS1sYWJlbD1cIkJyYW5kIHN5c3RlbVwiPlxuICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInNlY3Rpb24taGVhZGluZ1wiPjxoMj5Db3JlIHBhbGV0dGU8L2gyPjwvZGl2PlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwicGFsZXR0ZVwiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzd2F0Y2hcIiBzdHlsZT1cImJhY2tncm91bmQ6IHZhcigtLXByaW1hcnkpXCI+PHNwYW4+JHticmFuZC5jb2xvcnMucHJpbWFyeX08L3NwYW4+PC9kaXY+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInN3YXRjaFwiIHN0eWxlPVwiYmFja2dyb3VuZDogdmFyKC0tYWNjZW50KVwiPjxzcGFuPiR7YnJhbmQuY29sb3JzLmFjY2VudH08L3NwYW4+PC9kaXY+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInN3YXRjaFwiIHN0eWxlPVwiYmFja2dyb3VuZDogdmFyKC0tc3VyZmFjZSlcIj48c3Bhbj4ke2JyYW5kLmNvbG9ycy5zdXJmYWNlfTwvc3Bhbj48L2Rpdj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3dhdGNoXCIgc3R5bGU9XCJiYWNrZ3JvdW5kOiB2YXIoLS1mb3JlZ3JvdW5kKVwiPjxzcGFuPiR7YnJhbmQuY29sb3JzLmZvcmVncm91bmR9PC9zcGFuPjwvZGl2PlxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInNlY3Rpb24taGVhZGluZ1wiPjxoMj5UeXBvZ3JhcGh5PC9oMj48L2Rpdj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInR5cGUtc3BlY2ltZW5cIj5cbiAgICAgICAgICAgICAgICA8c3Ryb25nPkFhIDAxPC9zdHJvbmc+XG4gICAgICAgICAgICAgICAgPGNvZGU+JHtodG1sKGJyYW5kLnR5cG9ncmFwaHkuc2Fucyl9PC9jb2RlPlxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvc2VjdGlvbj5cblxuICAgICAgICAgIDxzZWN0aW9uIGNsYXNzPVwidm9pY2VcIiBhcmlhLWxhYmVsbGVkYnk9XCJ2b2ljZS10aXRsZVwiPlxuICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgPGgyIGlkPVwidm9pY2UtdGl0bGVcIj5Wb2ljZTwvaDI+XG4gICAgICAgICAgICAgIDxwIGNsYXNzPVwibWV0YVwiPiR7aHRtbChicmFuZC52b2ljZS50b25lLmpvaW4oXCIsIFwiKSl9PC9wPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8ZGl2PlxuICAgICAgICAgICAgICA8aDM+UHJpbmNpcGxlczwvaDM+XG4gICAgICAgICAgICAgIDx1bD4ke2xpc3RJdGVtcyhicmFuZC52b2ljZS5wcmluY2lwbGVzKX08L3VsPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9zZWN0aW9uPlxuXG4gICAgICAgICAgJHtnYWxsZXJ5fVxuICAgICAgICA8L21haW4+XG4gICAgICA8L2JvZHk+XG4gICAgPC9odG1sPlxuICAgIGBcbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICk7XG59XG4iXX0=
|
package/lib/tsconfig.tsbuildinfo
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../src/bootstrap.ts","../src/bun.ts","../src/cli.ts","../src/root.ts","../src/appkit/cli.ts","../src/appkit/env-export.ts","../src/appkit/index.ts","../src/auth/cli.ts","../src/auth/index.ts","../src/auth/options.ts","../src/brand/cli.ts","../src/brand/export.ts","../src/brand/index.ts","../src/brand/options.ts","../src/brand/run.ts","../src/genie-code/cli.ts","../src/genie-code/config.ts","../src/genie-code/index.ts","../src/genie-code/install.ts","../src/genie-code/options.ts","../src/genie-code/runner.ts","../src/genie-code/runtime.ts","../src/graphiti/cli.ts","../src/graphiti/index.ts","../src/graphiti/options.ts","../src/lakebase-proxy/cancellation.ts","../src/lakebase-proxy/cli.ts","../src/lakebase-proxy/index.ts","../src/lakebase-proxy/options.ts","../src/lakebase-proxy/protocol.ts","../src/lakebase-proxy/proxy.ts","../src/model-gateway/cli.ts","../src/model-gateway/index.ts","../src/model-gateway/server.ts","../src/tunnel/app.ts","../src/tunnel/cli.ts","../src/tunnel/index.ts","../src/tunnel/options.ts","../src/tunnel/proxy.ts","../index.ts","../bin/dbx-genie.ts","../bin/dbx-graphiti.ts","../bin/dbx-lakebase-proxy.ts","../bin/dbx-model-gateway.ts","../bin/dbx-tools.ts"],"version":"5.9.3"}
|
|
1
|
+
{"root":["../src/bootstrap.ts","../src/bun.ts","../src/cli.ts","../src/root.ts","../src/appkit/cli.ts","../src/appkit/env-export.ts","../src/appkit/index.ts","../src/auth/cli.ts","../src/auth/index.ts","../src/auth/options.ts","../src/brand/cli.ts","../src/brand/export.ts","../src/brand/index.ts","../src/brand/options.ts","../src/brand/run.ts","../src/brand/showcase.ts","../src/genie-code/cli.ts","../src/genie-code/config.ts","../src/genie-code/index.ts","../src/genie-code/install.ts","../src/genie-code/options.ts","../src/genie-code/runner.ts","../src/genie-code/runtime.ts","../src/graphiti/cli.ts","../src/graphiti/index.ts","../src/graphiti/options.ts","../src/lakebase-proxy/cancellation.ts","../src/lakebase-proxy/cli.ts","../src/lakebase-proxy/index.ts","../src/lakebase-proxy/options.ts","../src/lakebase-proxy/protocol.ts","../src/lakebase-proxy/proxy.ts","../src/model-gateway/cli.ts","../src/model-gateway/index.ts","../src/model-gateway/server.ts","../src/tunnel/app.ts","../src/tunnel/cli.ts","../src/tunnel/index.ts","../src/tunnel/options.ts","../src/tunnel/proxy.ts","../index.ts","../bin/dbx-genie.ts","../bin/dbx-graphiti.ts","../bin/dbx-lakebase-proxy.ts","../bin/dbx-model-gateway.ts","../bin/dbx-tools.ts"],"version":"5.9.3"}
|
package/package.json
CHANGED
|
@@ -34,27 +34,27 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@clack/prompts": "^1.7.0",
|
|
36
36
|
"@databricks/appkit": "0.81.0",
|
|
37
|
-
"@dbx-tools/appkit": "^0.9.
|
|
38
|
-
"@dbx-tools/appkit-generator": "^0.9.
|
|
39
|
-
"@dbx-tools/appkit-memory": "^0.9.
|
|
40
|
-
"@dbx-tools/appkit-model-gateway": "^0.9.
|
|
41
|
-
"@dbx-tools/appkit-web-search": "^0.9.
|
|
42
|
-
"@dbx-tools/auth": "^0.9.
|
|
43
|
-
"@dbx-tools/auth-gate": "^0.9.
|
|
44
|
-
"@dbx-tools/cli-args": "^0.9.
|
|
45
|
-
"@dbx-tools/cli-service": "^0.9.
|
|
46
|
-
"@dbx-tools/core": "^0.9.
|
|
47
|
-
"@dbx-tools/databricks": "^0.9.
|
|
48
|
-
"@dbx-tools/email": "^0.9.
|
|
49
|
-
"@dbx-tools/lakebase": "^0.9.
|
|
50
|
-
"@dbx-tools/postgres": "^0.9.
|
|
51
|
-
"@dbx-tools/shared-auth": "^0.9.
|
|
52
|
-
"@dbx-tools/shared-core": "^0.9.
|
|
53
|
-
"@dbx-tools/shared-email": "^0.9.
|
|
54
|
-
"@dbx-tools/shared-generator": "^0.9.
|
|
55
|
-
"@dbx-tools/shared-genie-code": "^0.9.
|
|
56
|
-
"@dbx-tools/shared-model-gateway": "^0.9.
|
|
57
|
-
"@dbx-tools/tunnel": "^0.9.
|
|
37
|
+
"@dbx-tools/appkit": "^0.9.140",
|
|
38
|
+
"@dbx-tools/appkit-generator": "^0.9.140",
|
|
39
|
+
"@dbx-tools/appkit-memory": "^0.9.140",
|
|
40
|
+
"@dbx-tools/appkit-model-gateway": "^0.9.140",
|
|
41
|
+
"@dbx-tools/appkit-web-search": "^0.9.140",
|
|
42
|
+
"@dbx-tools/auth": "^0.9.140",
|
|
43
|
+
"@dbx-tools/auth-gate": "^0.9.140",
|
|
44
|
+
"@dbx-tools/cli-args": "^0.9.140",
|
|
45
|
+
"@dbx-tools/cli-service": "^0.9.140",
|
|
46
|
+
"@dbx-tools/core": "^0.9.140",
|
|
47
|
+
"@dbx-tools/databricks": "^0.9.140",
|
|
48
|
+
"@dbx-tools/email": "^0.9.140",
|
|
49
|
+
"@dbx-tools/lakebase": "^0.9.140",
|
|
50
|
+
"@dbx-tools/postgres": "^0.9.140",
|
|
51
|
+
"@dbx-tools/shared-auth": "^0.9.140",
|
|
52
|
+
"@dbx-tools/shared-core": "^0.9.140",
|
|
53
|
+
"@dbx-tools/shared-email": "^0.9.140",
|
|
54
|
+
"@dbx-tools/shared-generator": "^0.9.140",
|
|
55
|
+
"@dbx-tools/shared-genie-code": "^0.9.140",
|
|
56
|
+
"@dbx-tools/shared-model-gateway": "^0.9.140",
|
|
57
|
+
"@dbx-tools/tunnel": "^0.9.140",
|
|
58
58
|
"commander": "^15.0.0",
|
|
59
59
|
"concurrently": "^10.0.3",
|
|
60
60
|
"get-port": "^7.1.0",
|
|
@@ -178,7 +178,7 @@
|
|
|
178
178
|
"./package.json": "./package.json"
|
|
179
179
|
}
|
|
180
180
|
},
|
|
181
|
-
"version": "0.9.
|
|
181
|
+
"version": "0.9.140",
|
|
182
182
|
"types": "./lib/index.d.ts",
|
|
183
183
|
"dbxToolsConfig": {
|
|
184
184
|
"tags": [
|
package/src/brand/cli.ts
CHANGED
|
@@ -39,12 +39,14 @@ export function buildProgram(name = "dbx brand", dependencies: BrandCliDependenc
|
|
|
39
39
|
const options = parseArgs(program, BrandExportOptionsSchema);
|
|
40
40
|
const result = await runExport(prompt, options, {
|
|
41
41
|
onProgress(event) {
|
|
42
|
-
writeProgress(
|
|
42
|
+
writeProgress(event.message);
|
|
43
43
|
},
|
|
44
44
|
});
|
|
45
45
|
writeResult({
|
|
46
|
+
root: result.outputDirectory,
|
|
46
47
|
brand: result.brandYamlPath,
|
|
47
48
|
manifest: result.manifestPath,
|
|
49
|
+
...(result.showcasePath ? { showcase: result.showcasePath } : {}),
|
|
48
50
|
references: result.referenceCount,
|
|
49
51
|
});
|
|
50
52
|
});
|
package/src/brand/export.ts
CHANGED
|
@@ -10,6 +10,7 @@ import type { BrandResearch } from "@dbx-tools/appkit-generator";
|
|
|
10
10
|
import type { BrandPackage } from "@dbx-tools/shared-generator";
|
|
11
11
|
import { BrandPackageSchema } from "@dbx-tools/shared-generator";
|
|
12
12
|
import { stringify } from "yaml";
|
|
13
|
+
import { renderBrandShowcase } from "./showcase.ts";
|
|
13
14
|
|
|
14
15
|
/** Inputs required to write a generated brand package. */
|
|
15
16
|
export interface WriteBrandPackageOptions {
|
|
@@ -17,6 +18,7 @@ export interface WriteBrandPackageOptions {
|
|
|
17
18
|
readonly prompt: string;
|
|
18
19
|
readonly brandPackage: BrandPackage;
|
|
19
20
|
readonly research: BrandResearch;
|
|
21
|
+
readonly showcase?: boolean;
|
|
20
22
|
readonly force?: boolean;
|
|
21
23
|
}
|
|
22
24
|
|
|
@@ -25,6 +27,7 @@ export interface WrittenBrandPackage {
|
|
|
25
27
|
readonly outputDirectory: string;
|
|
26
28
|
readonly brandYamlPath: string;
|
|
27
29
|
readonly manifestPath: string;
|
|
30
|
+
readonly showcasePath?: string;
|
|
28
31
|
readonly referenceCount: number;
|
|
29
32
|
}
|
|
30
33
|
|
|
@@ -86,12 +89,14 @@ export async function writeBrandPackage(
|
|
|
86
89
|
): Promise<WrittenBrandPackage> {
|
|
87
90
|
const outputDirectory = path.resolve(options.outputDirectory);
|
|
88
91
|
const brandYamlPath = path.join(outputDirectory, "brand.yaml");
|
|
92
|
+
const showcasePath = path.join(outputDirectory, "showcase.html");
|
|
89
93
|
const packageExists = await fileExists(brandYamlPath);
|
|
90
94
|
if (packageExists && !options.force) {
|
|
91
95
|
throw new Error(`Brand package already exists at ${brandYamlPath}; pass --force to replace it`);
|
|
92
96
|
}
|
|
93
97
|
if (options.force) {
|
|
94
98
|
await rm(path.join(outputDirectory, "references"), { recursive: true, force: true });
|
|
99
|
+
await rm(showcasePath, { force: true });
|
|
95
100
|
}
|
|
96
101
|
|
|
97
102
|
const visualReferences = structuredClone(options.brandPackage.visualReferences);
|
|
@@ -134,11 +139,15 @@ export async function writeBrandPackage(
|
|
|
134
139
|
2,
|
|
135
140
|
)}\n`,
|
|
136
141
|
);
|
|
142
|
+
if (options.showcase) {
|
|
143
|
+
await writeAtomic(showcasePath, renderBrandShowcase(brandPackage));
|
|
144
|
+
}
|
|
137
145
|
|
|
138
146
|
return {
|
|
139
147
|
outputDirectory,
|
|
140
148
|
brandYamlPath,
|
|
141
149
|
manifestPath,
|
|
150
|
+
...(options.showcase ? { showcasePath } : {}),
|
|
142
151
|
referenceCount,
|
|
143
152
|
};
|
|
144
153
|
}
|
package/src/brand/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ export * as cli from "./cli.ts";
|
|
|
6
6
|
export * as exportModule from "./export.ts";
|
|
7
7
|
export * as options from "./options.ts";
|
|
8
8
|
export * as run from "./run.ts";
|
|
9
|
+
export * as showcase from "./showcase.ts";
|
|
9
10
|
export type { BrandCliDependencies } from "./cli.ts";
|
|
10
11
|
export type { WriteBrandPackageOptions, WrittenBrandPackage } from "./export.ts";
|
|
11
12
|
export { BrandExportOptionsSchema } from "./options.ts";
|
package/src/brand/options.ts
CHANGED
|
@@ -17,8 +17,10 @@ export const BrandExportOptionsSchema = z
|
|
|
17
17
|
.string()
|
|
18
18
|
.trim()
|
|
19
19
|
.min(1)
|
|
20
|
-
.
|
|
21
|
-
.describe(
|
|
20
|
+
.optional()
|
|
21
|
+
.describe(
|
|
22
|
+
"Persistent output directory for brand.yaml, showcase, provenance, and visual references. Omit for a temporary directory.",
|
|
23
|
+
),
|
|
22
24
|
model: z
|
|
23
25
|
.string()
|
|
24
26
|
.trim()
|
|
@@ -39,6 +41,10 @@ export const BrandExportOptionsSchema = z
|
|
|
39
41
|
.max(20_000)
|
|
40
42
|
.default(8_000)
|
|
41
43
|
.describe("Maximum characters retained from each source page."),
|
|
44
|
+
showcase: z
|
|
45
|
+
.boolean()
|
|
46
|
+
.default(true)
|
|
47
|
+
.describe("Responsive HTML brand presentation and website mockups."),
|
|
42
48
|
force: z.boolean().default(false).describe("Replace files in an existing output directory."),
|
|
43
49
|
})
|
|
44
50
|
.strict()
|
package/src/brand/run.ts
CHANGED
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { mkdtemp } from "node:fs/promises";
|
|
8
|
+
import { tmpdir } from "node:os";
|
|
9
|
+
import path from "node:path";
|
|
7
10
|
import type { BrandResearch } from "@dbx-tools/appkit-generator";
|
|
8
11
|
import { generateBrandPackage } from "@dbx-tools/appkit-generator/generate";
|
|
9
12
|
import {
|
|
@@ -14,6 +17,7 @@ import {
|
|
|
14
17
|
import { createWebSearchRuntime } from "@dbx-tools/appkit-web-search/runtime";
|
|
15
18
|
import { runWebSearch } from "@dbx-tools/appkit-web-search/search";
|
|
16
19
|
import { createWorkspaceClient } from "@dbx-tools/databricks/workspace-client";
|
|
20
|
+
import { object } from "@dbx-tools/shared-core";
|
|
17
21
|
import type { BrandGenerationProgressEvent } from "@dbx-tools/shared-generator";
|
|
18
22
|
|
|
19
23
|
import { writeBrandPackage, type WrittenBrandPackage } from "./export.ts";
|
|
@@ -59,6 +63,21 @@ export async function exportBrandFromPrompt(
|
|
|
59
63
|
...(options.profile ? { cacheIdentity: `profile:${options.profile}` } : {}),
|
|
60
64
|
},
|
|
61
65
|
signal,
|
|
66
|
+
async (event) => {
|
|
67
|
+
if (!object.isRecord(event)) return;
|
|
68
|
+
const status = typeof event.status === "string" ? event.status : undefined;
|
|
69
|
+
const eventMessage =
|
|
70
|
+
typeof event.message === "string" ? event.message.trim() : undefined;
|
|
71
|
+
const detail = typeof event.detail === "string" ? event.detail.trim() : undefined;
|
|
72
|
+
await callbacks.onProgress?.({
|
|
73
|
+
type: "progress",
|
|
74
|
+
stage: "search",
|
|
75
|
+
message:
|
|
76
|
+
status === "search" && eventMessage
|
|
77
|
+
? `Web search: ${eventMessage}`
|
|
78
|
+
: `Web search complete${detail ? `: ${detail}` : ""}`,
|
|
79
|
+
});
|
|
80
|
+
},
|
|
62
81
|
),
|
|
63
82
|
fetch: (request, signal) => runWebFetch(request, runtime, signal),
|
|
64
83
|
fetchAssetPage: (request, signal) => runWebAssetPageFetch(request, runtime, signal),
|
|
@@ -75,11 +94,14 @@ export async function exportBrandFromPrompt(
|
|
|
75
94
|
},
|
|
76
95
|
);
|
|
77
96
|
if (!research) throw new Error("Brand generation completed without research provenance");
|
|
97
|
+
const outputDirectory =
|
|
98
|
+
options.output ?? (await mkdtemp(path.join(tmpdir(), "dbx-tools-brand-")));
|
|
78
99
|
return writeBrandPackage({
|
|
79
|
-
outputDirectory
|
|
100
|
+
outputDirectory,
|
|
80
101
|
prompt,
|
|
81
102
|
brandPackage,
|
|
82
103
|
research,
|
|
104
|
+
showcase: options.showcase,
|
|
83
105
|
force: options.force,
|
|
84
106
|
});
|
|
85
107
|
}
|