@wix/web50-cli 0.1.2 → 0.1.3

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.
@@ -0,0 +1,488 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.generateEmbedDocs = generateEmbedDocs;
5
+ function escapeHtml(s) {
6
+ return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
7
+ }
8
+ function codeBlock(code) {
9
+ return `<div class="code-block"><pre>${escapeHtml(code)}</pre><button class="copy-btn" onclick="copyCode(this)">Copy</button></div>`;
10
+ }
11
+ function section(title, description, code) {
12
+ return `
13
+ <div class="card">
14
+ <h2>${title}</h2>
15
+ ${description ? `<p>${description}</p>` : ''}
16
+ ${codeBlock(code)}
17
+ </div>`;
18
+ }
19
+ function attrRow(attr, type, required, description, defaultVal) {
20
+ const badge = required ? `<span class="badge required">required</span>` : `<span class="badge optional">optional</span>`;
21
+ const def = defaultVal ? `<br><span class="default">Default: <code>${defaultVal}</code></span>` : '';
22
+ return `<tr>
23
+ <td><code>${attr}</code> ${badge}</td>
24
+ <td>${type}</td>
25
+ <td>${description}${def}</td>
26
+ </tr>`;
27
+ }
28
+ function generateEmbedDocs(clientId) {
29
+ // ── Web5 App snippets ──────────────────────────────────────────────────────
30
+
31
+ const web5AppLoader = `<script
32
+ src="https://www.wix.com/embed/v1/component.js"
33
+ data-client-id="${clientId}">
34
+ </script>`;
35
+ const web5AppAutoInit = `<!-- 1. Add a container -->
36
+ <div id="web5-app" style="width:100%; height:100vh;"></div>
37
+
38
+ <!-- 2. Add prerequisites (React 18 + FedOps) -->
39
+ <script src="https://static.parastorage.com/unpkg/react@18.2.0/umd/react.production.min.js"></script>
40
+ <script src="https://static.parastorage.com/unpkg/react-dom@18.2.0/umd/react-dom.production.min.js"></script>
41
+ <script src="https://static.parastorage.com/unpkg-semver/fedops-logger@5/fedops-logger.bundle.min.js"></script>
42
+
43
+ <!-- 3. Load the embed script -->
44
+ <script
45
+ src="https://static.parastorage.com/services/embed-web50/1.0.0/embed-web50.iife.js"
46
+ data-target="#web5-app"
47
+ data-client-id="${clientId}">
48
+ </script>`;
49
+ const web5AppManual = `<div id="web5-app" style="width:100%; height:100vh;"></div>
50
+
51
+ <script src="https://static.parastorage.com/unpkg/react@18.2.0/umd/react.production.min.js"></script>
52
+ <script src="https://static.parastorage.com/unpkg/react-dom@18.2.0/umd/react-dom.production.min.js"></script>
53
+ <script src="https://static.parastorage.com/unpkg-semver/fedops-logger@5/fedops-logger.bundle.min.js"></script>
54
+
55
+ <!-- Load with data-manual to suppress auto-init -->
56
+ <script
57
+ src="https://static.parastorage.com/services/embed-web50/1.0.0/embed-web50.iife.js"
58
+ data-manual>
59
+ </script>
60
+
61
+ <script>
62
+ Web5App.init({
63
+ target: '#web5-app',
64
+ clientId: '${clientId}',
65
+ mode: 'markdown_v2',
66
+ });
67
+ </script>`;
68
+ const web5AppQuestion = `<div id="web5-app" style="width:100%; height:100vh;"></div>
69
+
70
+ <script src="https://static.parastorage.com/unpkg-semver/fedops-logger@5/fedops-logger.bundle.min.js"></script>
71
+ <script
72
+ src="https://static.parastorage.com/services/embed-web50/1.0.0/embed-web50.iife.js"
73
+ data-target="#web5-app"
74
+ data-client-id="${clientId}"
75
+ data-initial-question="How can I improve my SEO?">
76
+ </script>`;
77
+ const web5AppBootstrap = `<div id="web5-app" style="width:100%; height:100vh;"></div>
78
+
79
+ <script src="https://static.parastorage.com/unpkg-semver/fedops-logger@5/fedops-logger.bundle.min.js"></script>
80
+ <!-- Bootstrap loader — resolves the latest bundle automatically -->
81
+ <script
82
+ src="https://static.parastorage.com/services/embed-web50/1.0.0/bootstrap.js"
83
+ data-target="#web5-app"
84
+ data-client-id="${clientId}">
85
+ </script>`;
86
+ const web5AppApiRef = `Web5App.init({
87
+ target: string, // CSS selector for container (required)
88
+ clientId: string, // Your OAuth client ID (required)
89
+ mode?: string, // 'markdown_v2' (default)
90
+ initialQuestion?: string, // Pre-fill first message
91
+ version?: string, // Pin a specific bundle version
92
+ });`;
93
+
94
+ // ── Input Widget snippets ─────────────────────────────────────────────────
95
+
96
+ const inputLoader = `<script
97
+ src="https://www.wix.com/embed/v1/component.js"
98
+ data-client-id="${clientId}">
99
+ </script>`;
100
+ const inputAutoInit = `<!-- The script reads data-* attributes and renders automatically -->
101
+ <script
102
+ src="https://static.parastorage.com/services/embed-input/1.0.0/embed-input.iife.js"
103
+ data-client-id="${clientId}"
104
+ data-placeholder="Ask me anything...">
105
+ </script>`;
106
+ const inputManual = `<!-- Load with data-manual to suppress auto-init -->
107
+ <script
108
+ src="https://static.parastorage.com/services/embed-input/1.0.0/embed-input.iife.js"
109
+ data-manual>
110
+ </script>
111
+
112
+ <script>
113
+ Web5Input.init({
114
+ clientId: '${clientId}',
115
+ placeholder: 'Ask me anything...',
116
+ });
117
+ </script>`;
118
+ const inputCustomChips = `<script
119
+ src="https://static.parastorage.com/services/embed-input/1.0.0/embed-input.iife.js"
120
+ data-manual>
121
+ </script>
122
+
123
+ <script>
124
+ Web5Input.init({
125
+ clientId: '${clientId}',
126
+ placeholder: 'How can I help?',
127
+ suggestions: ['Manage billing', 'SEO tips', 'Connect domain'],
128
+ });
129
+ </script>`;
130
+ const inputRequireParam = `<!-- Widget only renders when ?my-gate appears in the URL -->
131
+ <script
132
+ src="https://static.parastorage.com/services/embed-input/1.0.0/embed-input.iife.js"
133
+ data-client-id="${clientId}"
134
+ data-require-param="my-gate"
135
+ data-placeholder="Ask me anything...">
136
+ </script>`;
137
+ const inputExcludePaths = `<!-- Widget is hidden on /web5 and /admin -->
138
+ <script
139
+ src="https://static.parastorage.com/services/embed-input/1.0.0/embed-input.iife.js"
140
+ data-client-id="${clientId}"
141
+ data-exclude-paths="/web5,/admin"
142
+ data-placeholder="Ask me anything...">
143
+ </script>`;
144
+ const inputApiRef = `Web5Input.init({
145
+ clientId: string, // Your OAuth client ID (required)
146
+ placeholder?: string, // Input placeholder text
147
+ suggestions?: string[], // Custom chip suggestions shown above the input
148
+ requireParam?: string, // URL query param that must be present to render
149
+ excludePaths?: string[], // Pathname prefixes where the widget is hidden
150
+ });`;
151
+
152
+ // ── Assemble page ─────────────────────────────────────────────────────────
153
+
154
+ return `<!DOCTYPE html>
155
+ <html lang="en">
156
+ <head>
157
+ <meta charset="UTF-8" />
158
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
159
+ <title>Web5 Embed Documentation</title>
160
+ <style>
161
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
162
+
163
+ body {
164
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
165
+ background: #f0f2f5;
166
+ color: #1f2937;
167
+ min-height: 100vh;
168
+ }
169
+
170
+ /* ── Header ── */
171
+ .header {
172
+ background: #fff;
173
+ border-bottom: 1px solid #e5e7eb;
174
+ padding: 16px 32px;
175
+ display: flex;
176
+ align-items: baseline;
177
+ gap: 16px;
178
+ }
179
+ .header h1 {
180
+ font-size: 1.2rem;
181
+ font-weight: 700;
182
+ color: #111827;
183
+ }
184
+ .client-id-badge {
185
+ font-family: 'SFMono-Regular', Consolas, monospace;
186
+ font-size: 0.78rem;
187
+ color: #6b7280;
188
+ background: #f3f4f6;
189
+ border: 1px solid #e5e7eb;
190
+ border-radius: 4px;
191
+ padding: 2px 8px;
192
+ }
193
+ .client-id-badge span {
194
+ color: #0060e6;
195
+ font-weight: 600;
196
+ }
197
+
198
+ /* ── Tab bar ── */
199
+ .tabs {
200
+ background: #fff;
201
+ border-bottom: 2px solid #e5e7eb;
202
+ padding: 0 32px;
203
+ display: flex;
204
+ gap: 0;
205
+ }
206
+ .tab-btn {
207
+ padding: 14px 24px;
208
+ border: none;
209
+ background: none;
210
+ font-size: 0.9rem;
211
+ color: #6b7280;
212
+ cursor: pointer;
213
+ border-bottom: 3px solid transparent;
214
+ margin-bottom: -2px;
215
+ transition: color 0.15s, border-color 0.15s;
216
+ font-weight: 500;
217
+ }
218
+ .tab-btn:hover:not(.active) { color: #374151; background: #f9fafb; }
219
+ .tab-btn.active { color: #0060e6; border-bottom-color: #0060e6; }
220
+
221
+ /* ── Tab panels ── */
222
+ .tab-panel { display: none; padding: 32px; max-width: 860px; margin: 0 auto; }
223
+ .tab-panel.active { display: block; }
224
+
225
+ /* ── Section cards ── */
226
+ .card {
227
+ background: #fff;
228
+ border: 1px solid #e5e7eb;
229
+ border-radius: 10px;
230
+ padding: 24px;
231
+ margin-bottom: 20px;
232
+ }
233
+ .card h2 {
234
+ font-size: 1rem;
235
+ font-weight: 600;
236
+ color: #111827;
237
+ margin-bottom: 8px;
238
+ }
239
+ .card > p {
240
+ font-size: 0.875rem;
241
+ color: #6b7280;
242
+ line-height: 1.65;
243
+ margin-bottom: 14px;
244
+ }
245
+ .card > p code {
246
+ background: #f3f4f6;
247
+ border: 1px solid #e5e7eb;
248
+ border-radius: 3px;
249
+ padding: 1px 5px;
250
+ font-size: 0.82rem;
251
+ font-family: 'SFMono-Regular', Consolas, monospace;
252
+ color: #374151;
253
+ }
254
+
255
+ /* ── Code blocks ── */
256
+ .code-block {
257
+ position: relative;
258
+ background: #1a1d23;
259
+ border-radius: 8px;
260
+ overflow: hidden;
261
+ }
262
+ .code-block pre {
263
+ padding: 16px 20px;
264
+ padding-right: 70px;
265
+ font-family: 'SFMono-Regular', Consolas, 'Courier New', monospace;
266
+ font-size: 0.8rem;
267
+ line-height: 1.65;
268
+ color: #abb2bf;
269
+ overflow-x: auto;
270
+ white-space: pre;
271
+ }
272
+ .copy-btn {
273
+ position: absolute;
274
+ top: 10px;
275
+ right: 10px;
276
+ background: #2d3139;
277
+ color: #9ca3af;
278
+ border: 1px solid #3d4451;
279
+ border-radius: 5px;
280
+ padding: 5px 12px;
281
+ font-size: 0.75rem;
282
+ cursor: pointer;
283
+ transition: background 0.15s, color 0.15s, border-color 0.15s;
284
+ white-space: nowrap;
285
+ }
286
+ .copy-btn:hover { background: #383d47; color: #e5e7eb; }
287
+ .copy-btn.copied {
288
+ background: #14532d;
289
+ color: #86efac;
290
+ border-color: #16a34a;
291
+ }
292
+
293
+ /* ── Attribute reference tables ── */
294
+ .attr-table {
295
+ width: 100%;
296
+ border-collapse: collapse;
297
+ font-size: 0.83rem;
298
+ margin-top: 4px;
299
+ }
300
+ .attr-table th {
301
+ text-align: left;
302
+ padding: 9px 12px;
303
+ background: #f9fafb;
304
+ border: 1px solid #e5e7eb;
305
+ font-weight: 600;
306
+ color: #374151;
307
+ }
308
+ .attr-table td {
309
+ padding: 9px 12px;
310
+ border: 1px solid #e5e7eb;
311
+ vertical-align: top;
312
+ color: #4b5563;
313
+ line-height: 1.5;
314
+ }
315
+ .attr-table td:first-child {
316
+ font-family: 'SFMono-Regular', Consolas, monospace;
317
+ font-size: 0.8rem;
318
+ white-space: nowrap;
319
+ }
320
+ .attr-table td:first-child code {
321
+ color: #0060e6;
322
+ }
323
+ .attr-table td .default { font-size: 0.8rem; color: #9ca3af; }
324
+ .attr-table td .default code {
325
+ background: #f3f4f6;
326
+ border: 1px solid #e5e7eb;
327
+ border-radius: 3px;
328
+ padding: 0 4px;
329
+ font-size: 0.78rem;
330
+ font-family: 'SFMono-Regular', Consolas, monospace;
331
+ }
332
+ .badge {
333
+ display: inline-block;
334
+ font-size: 0.68rem;
335
+ font-weight: 600;
336
+ padding: 1px 6px;
337
+ border-radius: 3px;
338
+ vertical-align: middle;
339
+ margin-left: 5px;
340
+ letter-spacing: 0.02em;
341
+ }
342
+ .badge.required { background: #fef2f2; color: #b91c1c; border: 1px solid #fecaca; }
343
+ .badge.optional { background: #f0fdf4; color: #15803d; border: 1px solid #bbf7d0; }
344
+
345
+ /* ── Section divider label ── */
346
+ .section-label {
347
+ font-size: 0.72rem;
348
+ font-weight: 700;
349
+ text-transform: uppercase;
350
+ letter-spacing: 0.08em;
351
+ color: #9ca3af;
352
+ margin: 28px 0 12px;
353
+ }
354
+ </style>
355
+ </head>
356
+ <body>
357
+
358
+ <div class="header">
359
+ <h1>Web5 Embed Documentation</h1>
360
+ <div class="client-id-badge">client-id: <span>${escapeHtml(clientId)}</span></div>
361
+ </div>
362
+
363
+ <div class="tabs">
364
+ <button class="tab-btn active" data-tab="tab-web5app" onclick="showTab('tab-web5app')">Web5 App</button>
365
+ <button class="tab-btn" data-tab="tab-input" onclick="showTab('tab-input')">Input Widget</button>
366
+ </div>
367
+
368
+ <!-- ════════════════════════════ Tab 1: Web5 App ════════════════════════════ -->
369
+ <div class="tab-panel active" id="tab-web5app">
370
+
371
+ <p class="section-label">Quick start</p>
372
+
373
+ ${section('Loader Script', 'Add this to your <code>&lt;head&gt;</code> or before <code>&lt;/body&gt;</code>. Your <code>data-client-id</code> is pre-filled.', web5AppLoader)}
374
+
375
+ <p class="section-label">Initialization methods</p>
376
+
377
+ ${section('Auto-init via script tag', 'The script reads <code>data-*</code> attributes and mounts automatically into the target element.', web5AppAutoInit)}
378
+
379
+ ${section('Manual programmatic init', 'Load the script with <code>data-manual</code> to suppress auto-init, then call <code>Web5App.init()</code> when ready.', web5AppManual)}
380
+
381
+ ${section('With initial question', 'Pre-fill the first conversation message on load using <code>data-initial-question</code>.', web5AppQuestion)}
382
+
383
+ ${section('Bootstrap loader (auto-resolves version)', 'Use the bootstrap script to always load the latest stable bundle without pinning a version.', web5AppBootstrap)}
384
+
385
+ <p class="section-label">Reference</p>
386
+
387
+ <div class="card">
388
+ <h2>Config API</h2>
389
+ <p>Options for <code>Web5App.init()</code> and their <code>data-*</code> attribute equivalents.</p>
390
+ ${codeBlock(web5AppApiRef)}
391
+ <br>
392
+ <table class="attr-table">
393
+ <thead>
394
+ <tr><th>Attribute / Option</th><th>Type</th><th>Description</th></tr>
395
+ </thead>
396
+ <tbody>
397
+ ${attrRow('data-client-id / clientId', 'string', true, 'Your OAuth app client ID')}
398
+ ${attrRow('data-target / target', 'string', true, 'CSS selector for the container element')}
399
+ ${attrRow('data-initial-question / initialQuestion', 'string', false, 'Pre-fills the first conversation message')}
400
+ ${attrRow('data-mode / mode', 'string', false, 'Rendering mode', 'markdown_v2')}
401
+ ${attrRow('version', 'string', false, 'Pin a specific bundle version (emergency override)')}
402
+ </tbody>
403
+ </table>
404
+ </div>
405
+
406
+ </div>
407
+
408
+ <!-- ════════════════════════════ Tab 2: Input Widget ════════════════════════════ -->
409
+ <div class="tab-panel" id="tab-input">
410
+
411
+ <p class="section-label">Quick start</p>
412
+
413
+ ${section('Loader Script', 'Add this to your <code>&lt;head&gt;</code> or before <code>&lt;/body&gt;</code>. Your <code>data-client-id</code> is pre-filled.', inputLoader)}
414
+
415
+ <p class="section-label">Initialization methods</p>
416
+
417
+ ${section('Auto-init via script tag', 'The widget reads <code>data-*</code> attributes and renders automatically as a fixed bar at the bottom of the viewport.', inputAutoInit)}
418
+
419
+ ${section('Manual programmatic init', 'Load with <code>data-manual</code>, then call <code>Web5Input.init()</code> at the right moment in your app lifecycle.', inputManual)}
420
+
421
+ ${section('Custom chip suggestions', 'Pass your own <code>suggestions</code> array. These replace the default fetched chips entirely.', inputCustomChips)}
422
+
423
+ <p class="section-label">Guards &amp; visibility</p>
424
+
425
+ ${section('Conditional init with <code>data-require-param</code>', 'The widget only renders when the specified URL query parameter is present in the page URL. Useful for A/B tests or feature gates.', inputRequireParam)}
426
+
427
+ ${section('Hide on specific paths with <code>data-exclude-paths</code>', 'Provide a comma-separated list of pathname prefixes. The widget will not render on any matching path.', inputExcludePaths)}
428
+
429
+ <p class="section-label">Reference</p>
430
+
431
+ <div class="card">
432
+ <h2>Config API</h2>
433
+ <p>Options for <code>Web5Input.init()</code> and their <code>data-*</code> attribute equivalents.</p>
434
+ ${codeBlock(inputApiRef)}
435
+ <br>
436
+ <table class="attr-table">
437
+ <thead>
438
+ <tr><th>Attribute / Option</th><th>Type</th><th>Description</th></tr>
439
+ </thead>
440
+ <tbody>
441
+ ${attrRow('data-client-id / clientId', 'string', true, 'Your OAuth app client ID')}
442
+ ${attrRow('data-placeholder / placeholder', 'string', false, 'Input placeholder text', '"Ask me anything..."')}
443
+ ${attrRow('data-suggestions / suggestions', 'string | string[]', false, 'Comma-separated string or array of chip labels shown above the input')}
444
+ ${attrRow('data-require-param / requireParam', 'string', false, 'URL query param that must be present for the widget to render')}
445
+ ${attrRow('data-exclude-paths / excludePaths', 'string | string[]', false, 'Pathname prefixes where the widget is hidden', '"/web5"')}
446
+ </tbody>
447
+ </table>
448
+ </div>
449
+
450
+ </div>
451
+
452
+ <script>
453
+ function showTab(id) {
454
+ document.querySelectorAll('.tab-btn').forEach(function(b) {
455
+ b.classList.toggle('active', b.dataset.tab === id);
456
+ });
457
+ document.querySelectorAll('.tab-panel').forEach(function(p) {
458
+ p.classList.toggle('active', p.id === id);
459
+ });
460
+ }
461
+
462
+ async function copyCode(btn) {
463
+ var code = btn.closest('.code-block').querySelector('pre').textContent;
464
+ try {
465
+ await navigator.clipboard.writeText(code);
466
+ } catch (_) {
467
+ var ta = document.createElement('textarea');
468
+ ta.value = code;
469
+ ta.style.cssText = 'position:fixed;opacity:0;top:0;left:0';
470
+ document.body.appendChild(ta);
471
+ ta.select();
472
+ document.execCommand('copy');
473
+ document.body.removeChild(ta);
474
+ }
475
+ var orig = btn.textContent;
476
+ btn.textContent = 'Copied!';
477
+ btn.classList.add('copied');
478
+ setTimeout(function() {
479
+ btn.textContent = orig;
480
+ btn.classList.remove('copied');
481
+ }, 1800);
482
+ }
483
+ </script>
484
+
485
+ </body>
486
+ </html>`;
487
+ }
488
+ //# sourceMappingURL=embedDocs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["escapeHtml","s","replace","codeBlock","code","section","title","description","attrRow","attr","type","required","defaultVal","badge","def","generateEmbedDocs","clientId","web5AppLoader","web5AppAutoInit","web5AppManual","web5AppQuestion","web5AppBootstrap","web5AppApiRef","inputLoader","inputAutoInit","inputManual","inputCustomChips","inputRequireParam","inputExcludePaths","inputApiRef"],"sources":["../../../src/templates/embedDocs.ts"],"sourcesContent":["function escapeHtml(s: string): string {\n return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n}\n\nfunction codeBlock(code: string): string {\n return `<div class=\"code-block\"><pre>${escapeHtml(code)}</pre><button class=\"copy-btn\" onclick=\"copyCode(this)\">Copy</button></div>`;\n}\n\nfunction section(title: string, description: string, code: string): string {\n return `\n <div class=\"card\">\n <h2>${title}</h2>\n ${description ? `<p>${description}</p>` : ''}\n ${codeBlock(code)}\n </div>`;\n}\n\nfunction attrRow(\n attr: string,\n type: string,\n required: boolean,\n description: string,\n defaultVal?: string,\n): string {\n const badge = required\n ? `<span class=\"badge required\">required</span>`\n : `<span class=\"badge optional\">optional</span>`;\n const def = defaultVal ? `<br><span class=\"default\">Default: <code>${defaultVal}</code></span>` : '';\n return `<tr>\n <td><code>${attr}</code> ${badge}</td>\n <td>${type}</td>\n <td>${description}${def}</td>\n </tr>`;\n}\n\nexport function generateEmbedDocs(clientId: string): string {\n // ── Web5 App snippets ──────────────────────────────────────────────────────\n\n const web5AppLoader = `<script\n src=\"https://www.wix.com/embed/v1/component.js\"\n data-client-id=\"${clientId}\">\n</script>`;\n\n const web5AppAutoInit = `<!-- 1. Add a container -->\n<div id=\"web5-app\" style=\"width:100%; height:100vh;\"></div>\n\n<!-- 2. Add prerequisites (React 18 + FedOps) -->\n<script src=\"https://static.parastorage.com/unpkg/react@18.2.0/umd/react.production.min.js\"></script>\n<script src=\"https://static.parastorage.com/unpkg/react-dom@18.2.0/umd/react-dom.production.min.js\"></script>\n<script src=\"https://static.parastorage.com/unpkg-semver/fedops-logger@5/fedops-logger.bundle.min.js\"></script>\n\n<!-- 3. Load the embed script -->\n<script\n src=\"https://static.parastorage.com/services/embed-web50/1.0.0/embed-web50.iife.js\"\n data-target=\"#web5-app\"\n data-client-id=\"${clientId}\">\n</script>`;\n\n const web5AppManual = `<div id=\"web5-app\" style=\"width:100%; height:100vh;\"></div>\n\n<script src=\"https://static.parastorage.com/unpkg/react@18.2.0/umd/react.production.min.js\"></script>\n<script src=\"https://static.parastorage.com/unpkg/react-dom@18.2.0/umd/react-dom.production.min.js\"></script>\n<script src=\"https://static.parastorage.com/unpkg-semver/fedops-logger@5/fedops-logger.bundle.min.js\"></script>\n\n<!-- Load with data-manual to suppress auto-init -->\n<script\n src=\"https://static.parastorage.com/services/embed-web50/1.0.0/embed-web50.iife.js\"\n data-manual>\n</script>\n\n<script>\n Web5App.init({\n target: '#web5-app',\n clientId: '${clientId}',\n mode: 'markdown_v2',\n });\n</script>`;\n\n const web5AppQuestion = `<div id=\"web5-app\" style=\"width:100%; height:100vh;\"></div>\n\n<script src=\"https://static.parastorage.com/unpkg-semver/fedops-logger@5/fedops-logger.bundle.min.js\"></script>\n<script\n src=\"https://static.parastorage.com/services/embed-web50/1.0.0/embed-web50.iife.js\"\n data-target=\"#web5-app\"\n data-client-id=\"${clientId}\"\n data-initial-question=\"How can I improve my SEO?\">\n</script>`;\n\n const web5AppBootstrap = `<div id=\"web5-app\" style=\"width:100%; height:100vh;\"></div>\n\n<script src=\"https://static.parastorage.com/unpkg-semver/fedops-logger@5/fedops-logger.bundle.min.js\"></script>\n<!-- Bootstrap loader — resolves the latest bundle automatically -->\n<script\n src=\"https://static.parastorage.com/services/embed-web50/1.0.0/bootstrap.js\"\n data-target=\"#web5-app\"\n data-client-id=\"${clientId}\">\n</script>`;\n\n const web5AppApiRef = `Web5App.init({\n target: string, // CSS selector for container (required)\n clientId: string, // Your OAuth client ID (required)\n mode?: string, // 'markdown_v2' (default)\n initialQuestion?: string, // Pre-fill first message\n version?: string, // Pin a specific bundle version\n});`;\n\n // ── Input Widget snippets ─────────────────────────────────────────────────\n\n const inputLoader = `<script\n src=\"https://www.wix.com/embed/v1/component.js\"\n data-client-id=\"${clientId}\">\n</script>`;\n\n const inputAutoInit = `<!-- The script reads data-* attributes and renders automatically -->\n<script\n src=\"https://static.parastorage.com/services/embed-input/1.0.0/embed-input.iife.js\"\n data-client-id=\"${clientId}\"\n data-placeholder=\"Ask me anything...\">\n</script>`;\n\n const inputManual = `<!-- Load with data-manual to suppress auto-init -->\n<script\n src=\"https://static.parastorage.com/services/embed-input/1.0.0/embed-input.iife.js\"\n data-manual>\n</script>\n\n<script>\n Web5Input.init({\n clientId: '${clientId}',\n placeholder: 'Ask me anything...',\n });\n</script>`;\n\n const inputCustomChips = `<script\n src=\"https://static.parastorage.com/services/embed-input/1.0.0/embed-input.iife.js\"\n data-manual>\n</script>\n\n<script>\n Web5Input.init({\n clientId: '${clientId}',\n placeholder: 'How can I help?',\n suggestions: ['Manage billing', 'SEO tips', 'Connect domain'],\n });\n</script>`;\n\n const inputRequireParam = `<!-- Widget only renders when ?my-gate appears in the URL -->\n<script\n src=\"https://static.parastorage.com/services/embed-input/1.0.0/embed-input.iife.js\"\n data-client-id=\"${clientId}\"\n data-require-param=\"my-gate\"\n data-placeholder=\"Ask me anything...\">\n</script>`;\n\n const inputExcludePaths = `<!-- Widget is hidden on /web5 and /admin -->\n<script\n src=\"https://static.parastorage.com/services/embed-input/1.0.0/embed-input.iife.js\"\n data-client-id=\"${clientId}\"\n data-exclude-paths=\"/web5,/admin\"\n data-placeholder=\"Ask me anything...\">\n</script>`;\n\n const inputApiRef = `Web5Input.init({\n clientId: string, // Your OAuth client ID (required)\n placeholder?: string, // Input placeholder text\n suggestions?: string[], // Custom chip suggestions shown above the input\n requireParam?: string, // URL query param that must be present to render\n excludePaths?: string[], // Pathname prefixes where the widget is hidden\n});`;\n\n // ── Assemble page ─────────────────────────────────────────────────────────\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>Web5 Embed Documentation</title>\n <style>\n *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\n\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n background: #f0f2f5;\n color: #1f2937;\n min-height: 100vh;\n }\n\n /* ── Header ── */\n .header {\n background: #fff;\n border-bottom: 1px solid #e5e7eb;\n padding: 16px 32px;\n display: flex;\n align-items: baseline;\n gap: 16px;\n }\n .header h1 {\n font-size: 1.2rem;\n font-weight: 700;\n color: #111827;\n }\n .client-id-badge {\n font-family: 'SFMono-Regular', Consolas, monospace;\n font-size: 0.78rem;\n color: #6b7280;\n background: #f3f4f6;\n border: 1px solid #e5e7eb;\n border-radius: 4px;\n padding: 2px 8px;\n }\n .client-id-badge span {\n color: #0060e6;\n font-weight: 600;\n }\n\n /* ── Tab bar ── */\n .tabs {\n background: #fff;\n border-bottom: 2px solid #e5e7eb;\n padding: 0 32px;\n display: flex;\n gap: 0;\n }\n .tab-btn {\n padding: 14px 24px;\n border: none;\n background: none;\n font-size: 0.9rem;\n color: #6b7280;\n cursor: pointer;\n border-bottom: 3px solid transparent;\n margin-bottom: -2px;\n transition: color 0.15s, border-color 0.15s;\n font-weight: 500;\n }\n .tab-btn:hover:not(.active) { color: #374151; background: #f9fafb; }\n .tab-btn.active { color: #0060e6; border-bottom-color: #0060e6; }\n\n /* ── Tab panels ── */\n .tab-panel { display: none; padding: 32px; max-width: 860px; margin: 0 auto; }\n .tab-panel.active { display: block; }\n\n /* ── Section cards ── */\n .card {\n background: #fff;\n border: 1px solid #e5e7eb;\n border-radius: 10px;\n padding: 24px;\n margin-bottom: 20px;\n }\n .card h2 {\n font-size: 1rem;\n font-weight: 600;\n color: #111827;\n margin-bottom: 8px;\n }\n .card > p {\n font-size: 0.875rem;\n color: #6b7280;\n line-height: 1.65;\n margin-bottom: 14px;\n }\n .card > p code {\n background: #f3f4f6;\n border: 1px solid #e5e7eb;\n border-radius: 3px;\n padding: 1px 5px;\n font-size: 0.82rem;\n font-family: 'SFMono-Regular', Consolas, monospace;\n color: #374151;\n }\n\n /* ── Code blocks ── */\n .code-block {\n position: relative;\n background: #1a1d23;\n border-radius: 8px;\n overflow: hidden;\n }\n .code-block pre {\n padding: 16px 20px;\n padding-right: 70px;\n font-family: 'SFMono-Regular', Consolas, 'Courier New', monospace;\n font-size: 0.8rem;\n line-height: 1.65;\n color: #abb2bf;\n overflow-x: auto;\n white-space: pre;\n }\n .copy-btn {\n position: absolute;\n top: 10px;\n right: 10px;\n background: #2d3139;\n color: #9ca3af;\n border: 1px solid #3d4451;\n border-radius: 5px;\n padding: 5px 12px;\n font-size: 0.75rem;\n cursor: pointer;\n transition: background 0.15s, color 0.15s, border-color 0.15s;\n white-space: nowrap;\n }\n .copy-btn:hover { background: #383d47; color: #e5e7eb; }\n .copy-btn.copied {\n background: #14532d;\n color: #86efac;\n border-color: #16a34a;\n }\n\n /* ── Attribute reference tables ── */\n .attr-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 0.83rem;\n margin-top: 4px;\n }\n .attr-table th {\n text-align: left;\n padding: 9px 12px;\n background: #f9fafb;\n border: 1px solid #e5e7eb;\n font-weight: 600;\n color: #374151;\n }\n .attr-table td {\n padding: 9px 12px;\n border: 1px solid #e5e7eb;\n vertical-align: top;\n color: #4b5563;\n line-height: 1.5;\n }\n .attr-table td:first-child {\n font-family: 'SFMono-Regular', Consolas, monospace;\n font-size: 0.8rem;\n white-space: nowrap;\n }\n .attr-table td:first-child code {\n color: #0060e6;\n }\n .attr-table td .default { font-size: 0.8rem; color: #9ca3af; }\n .attr-table td .default code {\n background: #f3f4f6;\n border: 1px solid #e5e7eb;\n border-radius: 3px;\n padding: 0 4px;\n font-size: 0.78rem;\n font-family: 'SFMono-Regular', Consolas, monospace;\n }\n .badge {\n display: inline-block;\n font-size: 0.68rem;\n font-weight: 600;\n padding: 1px 6px;\n border-radius: 3px;\n vertical-align: middle;\n margin-left: 5px;\n letter-spacing: 0.02em;\n }\n .badge.required { background: #fef2f2; color: #b91c1c; border: 1px solid #fecaca; }\n .badge.optional { background: #f0fdf4; color: #15803d; border: 1px solid #bbf7d0; }\n\n /* ── Section divider label ── */\n .section-label {\n font-size: 0.72rem;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n color: #9ca3af;\n margin: 28px 0 12px;\n }\n </style>\n</head>\n<body>\n\n <div class=\"header\">\n <h1>Web5 Embed Documentation</h1>\n <div class=\"client-id-badge\">client-id: <span>${escapeHtml(clientId)}</span></div>\n </div>\n\n <div class=\"tabs\">\n <button class=\"tab-btn active\" data-tab=\"tab-web5app\" onclick=\"showTab('tab-web5app')\">Web5 App</button>\n <button class=\"tab-btn\" data-tab=\"tab-input\" onclick=\"showTab('tab-input')\">Input Widget</button>\n </div>\n\n <!-- ════════════════════════════ Tab 1: Web5 App ════════════════════════════ -->\n <div class=\"tab-panel active\" id=\"tab-web5app\">\n\n <p class=\"section-label\">Quick start</p>\n\n ${section(\n 'Loader Script',\n 'Add this to your <code>&lt;head&gt;</code> or before <code>&lt;/body&gt;</code>. Your <code>data-client-id</code> is pre-filled.',\n web5AppLoader,\n )}\n\n <p class=\"section-label\">Initialization methods</p>\n\n ${section(\n 'Auto-init via script tag',\n 'The script reads <code>data-*</code> attributes and mounts automatically into the target element.',\n web5AppAutoInit,\n )}\n\n ${section(\n 'Manual programmatic init',\n 'Load the script with <code>data-manual</code> to suppress auto-init, then call <code>Web5App.init()</code> when ready.',\n web5AppManual,\n )}\n\n ${section(\n 'With initial question',\n 'Pre-fill the first conversation message on load using <code>data-initial-question</code>.',\n web5AppQuestion,\n )}\n\n ${section(\n 'Bootstrap loader (auto-resolves version)',\n 'Use the bootstrap script to always load the latest stable bundle without pinning a version.',\n web5AppBootstrap,\n )}\n\n <p class=\"section-label\">Reference</p>\n\n <div class=\"card\">\n <h2>Config API</h2>\n <p>Options for <code>Web5App.init()</code> and their <code>data-*</code> attribute equivalents.</p>\n ${codeBlock(web5AppApiRef)}\n <br>\n <table class=\"attr-table\">\n <thead>\n <tr><th>Attribute / Option</th><th>Type</th><th>Description</th></tr>\n </thead>\n <tbody>\n ${attrRow('data-client-id / clientId', 'string', true, 'Your OAuth app client ID')}\n ${attrRow('data-target / target', 'string', true, 'CSS selector for the container element')}\n ${attrRow('data-initial-question / initialQuestion', 'string', false, 'Pre-fills the first conversation message')}\n ${attrRow('data-mode / mode', 'string', false, 'Rendering mode', 'markdown_v2')}\n ${attrRow('version', 'string', false, 'Pin a specific bundle version (emergency override)')}\n </tbody>\n </table>\n </div>\n\n </div>\n\n <!-- ════════════════════════════ Tab 2: Input Widget ════════════════════════════ -->\n <div class=\"tab-panel\" id=\"tab-input\">\n\n <p class=\"section-label\">Quick start</p>\n\n ${section(\n 'Loader Script',\n 'Add this to your <code>&lt;head&gt;</code> or before <code>&lt;/body&gt;</code>. Your <code>data-client-id</code> is pre-filled.',\n inputLoader,\n )}\n\n <p class=\"section-label\">Initialization methods</p>\n\n ${section(\n 'Auto-init via script tag',\n 'The widget reads <code>data-*</code> attributes and renders automatically as a fixed bar at the bottom of the viewport.',\n inputAutoInit,\n )}\n\n ${section(\n 'Manual programmatic init',\n 'Load with <code>data-manual</code>, then call <code>Web5Input.init()</code> at the right moment in your app lifecycle.',\n inputManual,\n )}\n\n ${section(\n 'Custom chip suggestions',\n 'Pass your own <code>suggestions</code> array. These replace the default fetched chips entirely.',\n inputCustomChips,\n )}\n\n <p class=\"section-label\">Guards &amp; visibility</p>\n\n ${section(\n 'Conditional init with <code>data-require-param</code>',\n 'The widget only renders when the specified URL query parameter is present in the page URL. Useful for A/B tests or feature gates.',\n inputRequireParam,\n )}\n\n ${section(\n 'Hide on specific paths with <code>data-exclude-paths</code>',\n 'Provide a comma-separated list of pathname prefixes. The widget will not render on any matching path.',\n inputExcludePaths,\n )}\n\n <p class=\"section-label\">Reference</p>\n\n <div class=\"card\">\n <h2>Config API</h2>\n <p>Options for <code>Web5Input.init()</code> and their <code>data-*</code> attribute equivalents.</p>\n ${codeBlock(inputApiRef)}\n <br>\n <table class=\"attr-table\">\n <thead>\n <tr><th>Attribute / Option</th><th>Type</th><th>Description</th></tr>\n </thead>\n <tbody>\n ${attrRow('data-client-id / clientId', 'string', true, 'Your OAuth app client ID')}\n ${attrRow('data-placeholder / placeholder', 'string', false, 'Input placeholder text', '\"Ask me anything...\"')}\n ${attrRow('data-suggestions / suggestions', 'string | string[]', false, 'Comma-separated string or array of chip labels shown above the input')}\n ${attrRow('data-require-param / requireParam', 'string', false, 'URL query param that must be present for the widget to render')}\n ${attrRow('data-exclude-paths / excludePaths', 'string | string[]', false, 'Pathname prefixes where the widget is hidden', '\"/web5\"')}\n </tbody>\n </table>\n </div>\n\n </div>\n\n <script>\n function showTab(id) {\n document.querySelectorAll('.tab-btn').forEach(function(b) {\n b.classList.toggle('active', b.dataset.tab === id);\n });\n document.querySelectorAll('.tab-panel').forEach(function(p) {\n p.classList.toggle('active', p.id === id);\n });\n }\n\n async function copyCode(btn) {\n var code = btn.closest('.code-block').querySelector('pre').textContent;\n try {\n await navigator.clipboard.writeText(code);\n } catch (_) {\n var ta = document.createElement('textarea');\n ta.value = code;\n ta.style.cssText = 'position:fixed;opacity:0;top:0;left:0';\n document.body.appendChild(ta);\n ta.select();\n document.execCommand('copy');\n document.body.removeChild(ta);\n }\n var orig = btn.textContent;\n btn.textContent = 'Copied!';\n btn.classList.add('copied');\n setTimeout(function() {\n btn.textContent = orig;\n btn.classList.remove('copied');\n }, 1800);\n }\n </script>\n\n</body>\n</html>`;\n}\n"],"mappings":";;;;AAAA,SAASA,UAAUA,CAACC,CAAS,EAAU;EACrC,OAAOA,CAAC,CAACC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAACA,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAACA,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;AAC7E;AAEA,SAASC,SAASA,CAACC,IAAY,EAAU;EACvC,OAAO,gCAAgCJ,UAAU,CAACI,IAAI,CAAC,6EAA6E;AACtI;AAEA,SAASC,OAAOA,CAACC,KAAa,EAAEC,WAAmB,EAAEH,IAAY,EAAU;EACzE,OAAO;AACT;AACA,YAAYE,KAAK;AACjB,QAAQC,WAAW,GAAG,MAAMA,WAAW,MAAM,GAAG,EAAE;AAClD,QAAQJ,SAAS,CAACC,IAAI,CAAC;AACvB,WAAW;AACX;AAEA,SAASI,OAAOA,CACdC,IAAY,EACZC,IAAY,EACZC,QAAiB,EACjBJ,WAAmB,EACnBK,UAAmB,EACX;EACR,MAAMC,KAAK,GAAGF,QAAQ,GAClB,8CAA8C,GAC9C,8CAA8C;EAClD,MAAMG,GAAG,GAAGF,UAAU,GAAG,4CAA4CA,UAAU,gBAAgB,GAAG,EAAE;EACpG,OAAO;AACT,kBAAkBH,IAAI,WAAWI,KAAK;AACtC,YAAYH,IAAI;AAChB,YAAYH,WAAW,GAAGO,GAAG;AAC7B,UAAU;AACV;AAEO,SAASC,iBAAiBA,CAACC,QAAgB,EAAU;EAC1D;;EAEA,MAAMC,aAAa,GAAG;AACxB;AACA,oBAAoBD,QAAQ;AAC5B,UAAU;EAER,MAAME,eAAe,GAAG;AAC1B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oBAAoBF,QAAQ;AAC5B,UAAU;EAER,MAAMG,aAAa,GAAG;AACxB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiBH,QAAQ;AACzB;AACA;AACA,UAAU;EAER,MAAMI,eAAe,GAAG;AAC1B;AACA;AACA;AACA;AACA;AACA,oBAAoBJ,QAAQ;AAC5B;AACA,UAAU;EAER,MAAMK,gBAAgB,GAAG;AAC3B;AACA;AACA;AACA;AACA;AACA;AACA,oBAAoBL,QAAQ;AAC5B,UAAU;EAER,MAAMM,aAAa,GAAG;AACxB;AACA;AACA;AACA;AACA;AACA,IAAI;;EAEF;;EAEA,MAAMC,WAAW,GAAG;AACtB;AACA,oBAAoBP,QAAQ;AAC5B,UAAU;EAER,MAAMQ,aAAa,GAAG;AACxB;AACA;AACA,oBAAoBR,QAAQ;AAC5B;AACA,UAAU;EAER,MAAMS,WAAW,GAAG;AACtB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiBT,QAAQ;AACzB;AACA;AACA,UAAU;EAER,MAAMU,gBAAgB,GAAG;AAC3B;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiBV,QAAQ;AACzB;AACA;AACA;AACA,UAAU;EAER,MAAMW,iBAAiB,GAAG;AAC5B;AACA;AACA,oBAAoBX,QAAQ;AAC5B;AACA;AACA,UAAU;EAER,MAAMY,iBAAiB,GAAG;AAC5B;AACA;AACA,oBAAoBZ,QAAQ;AAC5B;AACA;AACA,UAAU;EAER,MAAMa,WAAW,GAAG;AACtB;AACA;AACA;AACA;AACA;AACA,IAAI;;EAEF;;EAEA,OAAO;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oDAAoD7B,UAAU,CAACgB,QAAQ,CAAC;AACxE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMX,OAAO,CACP,eAAe,EACf,kIAAkI,EAClIY,aACF,CAAC;AACL;AACA;AACA;AACA,MAAMZ,OAAO,CACP,0BAA0B,EAC1B,mGAAmG,EACnGa,eACF,CAAC;AACL;AACA,MAAMb,OAAO,CACP,0BAA0B,EAC1B,wHAAwH,EACxHc,aACF,CAAC;AACL;AACA,MAAMd,OAAO,CACP,uBAAuB,EACvB,2FAA2F,EAC3Fe,eACF,CAAC;AACL;AACA,MAAMf,OAAO,CACP,0CAA0C,EAC1C,6FAA6F,EAC7FgB,gBACF,CAAC;AACL;AACA;AACA;AACA;AACA;AACA;AACA,QAAQlB,SAAS,CAACmB,aAAa,CAAC;AAChC;AACA;AACA;AACA;AACA;AACA;AACA,YAAYd,OAAO,CAAC,2BAA2B,EAAE,QAAQ,EAAE,IAAI,EAAE,0BAA0B,CAAC;AAC5F,YAAYA,OAAO,CAAC,sBAAsB,EAAE,QAAQ,EAAE,IAAI,EAAE,wCAAwC,CAAC;AACrG,YAAYA,OAAO,CAAC,yCAAyC,EAAE,QAAQ,EAAE,KAAK,EAAE,0CAA0C,CAAC;AAC3H,YAAYA,OAAO,CAAC,kBAAkB,EAAE,QAAQ,EAAE,KAAK,EAAE,gBAAgB,EAAE,aAAa,CAAC;AACzF,YAAYA,OAAO,CAAC,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,oDAAoD,CAAC;AACrG;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMH,OAAO,CACP,eAAe,EACf,kIAAkI,EAClIkB,WACF,CAAC;AACL;AACA;AACA;AACA,MAAMlB,OAAO,CACP,0BAA0B,EAC1B,yHAAyH,EACzHmB,aACF,CAAC;AACL;AACA,MAAMnB,OAAO,CACP,0BAA0B,EAC1B,wHAAwH,EACxHoB,WACF,CAAC;AACL;AACA,MAAMpB,OAAO,CACP,yBAAyB,EACzB,iGAAiG,EACjGqB,gBACF,CAAC;AACL;AACA;AACA;AACA,MAAMrB,OAAO,CACP,uDAAuD,EACvD,mIAAmI,EACnIsB,iBACF,CAAC;AACL;AACA,MAAMtB,OAAO,CACP,6DAA6D,EAC7D,uGAAuG,EACvGuB,iBACF,CAAC;AACL;AACA;AACA;AACA;AACA;AACA;AACA,QAAQzB,SAAS,CAAC0B,WAAW,CAAC;AAC9B;AACA;AACA;AACA;AACA;AACA;AACA,YAAYrB,OAAO,CAAC,2BAA2B,EAAE,QAAQ,EAAE,IAAI,EAAE,0BAA0B,CAAC;AAC5F,YAAYA,OAAO,CAAC,gCAAgC,EAAE,QAAQ,EAAE,KAAK,EAAE,wBAAwB,EAAE,sBAAsB,CAAC;AACxH,YAAYA,OAAO,CAAC,gCAAgC,EAAE,mBAAmB,EAAE,KAAK,EAAE,sEAAsE,CAAC;AACzJ,YAAYA,OAAO,CAAC,mCAAmC,EAAE,QAAQ,EAAE,KAAK,EAAE,+DAA+D,CAAC;AAC1I,YAAYA,OAAO,CAAC,mCAAmC,EAAE,mBAAmB,EAAE,KAAK,EAAE,8CAA8C,EAAE,SAAS,CAAC;AAC/I;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ;AACR","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"names":["fs","_interopRequireWildcard","require","path","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","readConfig","root","configPath","join","JSON","parse","readFileSync","writeConfig","config","writeFileSync","stringify","findProjectRoot","startDir","current","parent","dirname","existsSync","getProjectMsid","process","cwd","msid","trim"],"sources":["../../../src/utils/project.ts"],"sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\n\nexport interface Web5Config {\n $schema?: string;\n packageName?: string;\n displayName?: string;\n msid?: string;\n clientId?: string;\n platformType?: 'Content' | 'Ecommerce';\n [key: string]: unknown;\n}\n\nexport function readConfig(root: string): Web5Config {\n const configPath = path.join(root, 'web5.config.json');\n return JSON.parse(fs.readFileSync(configPath, 'utf8')) as Web5Config;\n}\n\nexport function writeConfig(root: string, config: Web5Config): void {\n const configPath = path.join(root, 'web5.config.json');\n fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\\n', 'utf8');\n}\n\n/**\n * Walk up from startDir until we find a directory containing web5.config.json.\n * Returns that directory, or null if none found.\n */\nexport function findProjectRoot(startDir: string): string | null {\n let current = startDir;\n let parent = path.dirname(current);\n while (current !== parent) {\n if (fs.existsSync(path.join(current, 'web5.config.json'))) {\n return current;\n }\n current = parent;\n parent = path.dirname(current);\n }\n if (fs.existsSync(path.join(current, 'web5.config.json'))) {\n return current;\n }\n return null;\n}\n\nexport function getProjectMsid(\n startDir: string = process.cwd(),\n): string | null {\n const root = findProjectRoot(startDir);\n if (!root) {\n return null;\n }\n const config = readConfig(root);\n const msid = config.msid;\n if (!msid || typeof msid !== 'string' || msid.trim() === '') {\n return null;\n }\n return msid.trim();\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["fs","_interopRequireWildcard","require","path","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","readConfig","root","configPath","join","JSON","parse","readFileSync","writeConfig","config","writeFileSync","stringify","findProjectRoot","startDir","current","parent","dirname","existsSync","getProjectMsid","process","cwd","msid","trim"],"sources":["../../../src/utils/project.ts"],"sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\n\nexport interface Web5Config {\n $schema?: string;\n packageName?: string;\n displayName?: string;\n msid?: string;\n clientId?: string;\n platformType?: 'Content' | 'Ecommerce';\n allowedDomains?: string[];\n [key: string]: unknown;\n}\n\nexport function readConfig(root: string): Web5Config {\n const configPath = path.join(root, 'web5.config.json');\n return JSON.parse(fs.readFileSync(configPath, 'utf8')) as Web5Config;\n}\n\nexport function writeConfig(root: string, config: Web5Config): void {\n const configPath = path.join(root, 'web5.config.json');\n fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\\n', 'utf8');\n}\n\n/**\n * Walk up from startDir until we find a directory containing web5.config.json.\n * Returns that directory, or null if none found.\n */\nexport function findProjectRoot(startDir: string): string | null {\n let current = startDir;\n let parent = path.dirname(current);\n while (current !== parent) {\n if (fs.existsSync(path.join(current, 'web5.config.json'))) {\n return current;\n }\n current = parent;\n parent = path.dirname(current);\n }\n if (fs.existsSync(path.join(current, 'web5.config.json'))) {\n return current;\n }\n return null;\n}\n\nexport function getProjectMsid(\n startDir: string = process.cwd(),\n): string | null {\n const root = findProjectRoot(startDir);\n if (!root) {\n return null;\n }\n const config = readConfig(root);\n const msid = config.msid;\n if (!msid || typeof msid !== 'string' || msid.trim() === '') {\n return null;\n }\n return msid.trim();\n}\n"],"mappings":"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","ignoreList":[]}
@@ -111,9 +111,9 @@ async function createWeb5Site(accessToken, name) {
111
111
  log(`Error body: ${body}`);
112
112
  throw new Error(`Failed to create site: ${res.status} ${res.statusText} — ${body}`);
113
113
  }
114
- const site = await res.json();
115
- log(`Create site response:`, JSON.stringify(site, null, 2));
116
- return site;
114
+ const body = await res.json();
115
+ log(`Create site response:`, JSON.stringify(body, null, 2));
116
+ return body.site;
117
117
  }
118
118
  async function promptCreateSite(accessToken, inquirer) {
119
119
  const {
@@ -122,7 +122,13 @@ async function promptCreateSite(accessToken, inquirer) {
122
122
  type: 'input',
123
123
  name: 'siteName',
124
124
  message: 'Enter a name for your new web5 site:',
125
- validate: v => v.trim().length > 0 || 'Name is required'
125
+ validate: v => {
126
+ const trimmed = v.trim();
127
+ if (trimmed.length === 0) return 'Name is required';
128
+ if (trimmed.length > 20) return 'Name must be 20 characters or less';
129
+ if (!/^[a-z0-9_]+$/.test(trimmed)) return 'Name must contain only lowercase letters, numbers, and underscores';
130
+ return true;
131
+ }
126
132
  }]);
127
133
  const spin = spinner('Creating new site...');
128
134
  const newSite = await createWeb5Site(accessToken, siteName.trim());