@picked/vite-plugin-picked 0.0.1-dev.1772493269328 → 0.0.1-dev.1773363643396

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/index.js CHANGED
@@ -1,4 +1,438 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const m=require("@picked/client/plugins/dynamic-experiences");function v(e){const t=JSON.stringify(e);return`<!DOCTYPE html>
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const m=require("@picked/client/plugins/dynamic-experiences");var h=Object.freeze,R=Object.defineProperty,I=(e,t)=>h(R(e,"raw",{value:h(t||e.slice())})),y;function b(e){const t=JSON.stringify(e),r=e.length>0?e.map(n=>`
2
+ <div class="feature-row">
3
+ <label>
4
+ <input type="checkbox" data-feature-id="${S(n.key)}" checked>
5
+ <span class="feature-name">${w(n.name)}</span>
6
+ <span class="feature-id">${w(n.key)}</span>
7
+ </label>
8
+ <select data-value-for="${S(n.key)}">
9
+ <option value="true" selected>true</option>
10
+ <option value="false">false</option>
11
+ </select>
12
+ </div>`).join(""):'<p class="text no-features">No features configured for this project.</p>';return String.raw(y||(y=I([`<!DOCTYPE html>
13
+ <html lang="en">
14
+ <head>
15
+ <meta charset="UTF-8">
16
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
17
+ <meta name="robots" content="noindex, nofollow">
18
+ <title>Picked</title>
19
+ <style>
20
+ main {
21
+ position: fixed;
22
+ top: 0;
23
+ right: 0;
24
+ bottom: 0;
25
+ left: 0;
26
+ display: grid;
27
+ align-items: center;
28
+ justify-content: center;
29
+ font-family: monospace;
30
+ color: #4A4A4A
31
+ }
32
+
33
+ .wrap {
34
+ padding-left: 1.5rem;
35
+ padding-right: 1.5rem;
36
+ max-width: 480px;
37
+ width: 100%;
38
+ }
39
+
40
+ .title {
41
+ font-size: 1.125rem;
42
+ font-weight: 700;
43
+ margin-bottom: 0;
44
+ }
45
+
46
+ .text {
47
+ margin-top: .5rem;
48
+ font-size: .875rem
49
+ }
50
+
51
+ .text a {
52
+ color: #4A4A4A;
53
+ text-decoration: none;
54
+ }
55
+
56
+ .text a:hover {
57
+ cursor: pointer;
58
+ text-decoration: underline
59
+ }
60
+
61
+ .preview-form {
62
+ margin-top: 2rem;
63
+ display: flex;
64
+ flex-direction: column;
65
+ gap: 0.5rem;
66
+ }
67
+
68
+ .preview-input {
69
+ padding: 0.5rem;
70
+ border: 1px solid #4A4A4A;
71
+ border-radius: 0;
72
+ font-family: monospace;
73
+ }
74
+
75
+ .preview-button {
76
+ padding: 0.5rem;
77
+ background: #4A4A4A;
78
+ color: white;
79
+ border: none;
80
+ border-radius: 0;
81
+ cursor: pointer;
82
+ font-family: monospace;
83
+ }
84
+
85
+ .preview-button:hover {
86
+ opacity: 0.9;
87
+ }
88
+
89
+ .buttons {
90
+ display: grid;
91
+ gap: 0.5em;
92
+ grid-template-columns: 1fr 1fr;
93
+ }
94
+
95
+ #copy-status {
96
+ font-size: 1em;
97
+ text-align: right;
98
+ margin-top: 0.5em;
99
+ }
100
+
101
+ .features-section {
102
+ margin-top: 1.5rem;
103
+ }
104
+
105
+ .features-label {
106
+ font-weight: 700;
107
+ font-size: .875rem;
108
+ margin-bottom: 0.5rem;
109
+ }
110
+
111
+ .feature-row {
112
+ display: flex;
113
+ align-items: center;
114
+ justify-content: space-between;
115
+ gap: 0.5rem;
116
+ padding: 0.25rem 0;
117
+ }
118
+
119
+ .feature-row label {
120
+ display: flex;
121
+ align-items: center;
122
+ gap: 0.5rem;
123
+ cursor: pointer;
124
+ min-width: 0;
125
+ flex: 1;
126
+ }
127
+
128
+ .feature-name {
129
+ font-size: .875rem;
130
+ }
131
+
132
+ .feature-id {
133
+ font-size: .75rem;
134
+ color: #888;
135
+ }
136
+
137
+ .feature-row select {
138
+ font-family: monospace;
139
+ font-size: .75rem;
140
+ padding: 0.125rem 0.25rem;
141
+ border: 1px solid #4A4A4A;
142
+ border-radius: 0;
143
+ background: white;
144
+ flex-shrink: 0;
145
+ }
146
+
147
+ .no-features {
148
+ color: #888;
149
+ font-style: italic;
150
+ }
151
+
152
+ .url-history {
153
+ margin-top: 0.5rem;
154
+ font-size: .75rem;
155
+ }
156
+
157
+ .url-history-item {
158
+ display: flex;
159
+ align-items: center;
160
+ gap: 0.25rem;
161
+ padding: 0.125rem 0;
162
+ }
163
+
164
+ .url-history-item button {
165
+ background: none;
166
+ border: none;
167
+ cursor: pointer;
168
+ font-family: monospace;
169
+ font-size: .75rem;
170
+ color: #888;
171
+ padding: 0;
172
+ }
173
+
174
+ .url-history-item button.url-link {
175
+ color: #4A4A4A;
176
+ text-decoration: none;
177
+ text-align: left;
178
+ overflow: hidden;
179
+ text-overflow: ellipsis;
180
+ white-space: nowrap;
181
+ flex: 1;
182
+ min-width: 0;
183
+ }
184
+
185
+ .url-history-item button.url-link:hover {
186
+ text-decoration: underline;
187
+ }
188
+
189
+ .url-history-item button.url-delete:hover {
190
+ color: #b71c1c;
191
+ }
192
+
193
+ @media (min-width: 640px) {
194
+ .title {
195
+ font-size: 1.25rem
196
+ }
197
+
198
+ .text {
199
+ font-size: 1rem
200
+ }
201
+ }
202
+ </style>
203
+ </head>
204
+ <body>
205
+
206
+ <main>
207
+ <div class="wrap">
208
+ <p class="title">Picked</p>
209
+ <p class="text">
210
+ Learn more at
211
+ <a href="https://picked.app">
212
+ https://picked.app
213
+ </a>
214
+ </p>
215
+ <div class="preview-form">
216
+ <input type="text" id="url-input" pattern="^(https?://)?.+" placeholder="Enter preview URL" required
217
+ class="preview-input">
218
+ <div id="url-history" class="url-history"></div>
219
+ <div class="features-section">
220
+ <p class="features-label">Features</p>
221
+ `,`
222
+ </div>
223
+ <div class="buttons">
224
+ <button type="button" class="preview-button" id="copy-btn">Copy</button>
225
+ <button type="button" class="preview-button" id="preview-btn">Preview</button>
226
+ </div>
227
+ <p class="text" id="copy-status" aria-live="polite" style="visibility:hidden;">
228
+ &nbsp;
229
+ </p>
230
+ </div>
231
+ </div>
232
+
233
+ <script>
234
+ var FEATURES = `,`;
235
+ var STORAGE_KEY_URL = 'picked-launcher-url';
236
+ var STORAGE_KEY_HISTORY = 'picked-launcher-history';
237
+ var STORAGE_KEY_SELECTIONS = 'picked-launcher-selections';
238
+
239
+ function getUrlInput() {
240
+ return document.getElementById('url-input');
241
+ }
242
+
243
+ // URL history
244
+ function getHistory() {
245
+ try {
246
+ var raw = localStorage.getItem(STORAGE_KEY_HISTORY);
247
+ if (!raw) return [];
248
+ var parsed = JSON.parse(raw);
249
+ return Array.isArray(parsed) ? parsed : [];
250
+ } catch (e) {
251
+ return [];
252
+ }
253
+ }
254
+
255
+ function saveHistory(history) {
256
+ localStorage.setItem(STORAGE_KEY_HISTORY, JSON.stringify(history));
257
+ }
258
+
259
+ function addToHistory(url) {
260
+ var history = getHistory().filter(function(h) { return h !== url; });
261
+ history.unshift(url);
262
+ if (history.length > 10) history = history.slice(0, 10);
263
+ saveHistory(history);
264
+ renderHistory();
265
+ }
266
+
267
+ function removeFromHistory(url) {
268
+ var history = getHistory().filter(function(h) { return h !== url; });
269
+ saveHistory(history);
270
+ renderHistory();
271
+ }
272
+
273
+ function renderHistory() {
274
+ var container = document.getElementById('url-history');
275
+ if (!container) return;
276
+ var history = getHistory();
277
+ if (history.length === 0) {
278
+ container.innerHTML = '';
279
+ return;
280
+ }
281
+ container.innerHTML = history.map(function(url) {
282
+ return '<div class="url-history-item">' +
283
+ '<button type="button" class="url-link" data-history-url="' + escapeAttr(url) + '">' + escapeHtml(url) + '</button>' +
284
+ '<button type="button" class="url-delete" data-history-delete="' + escapeAttr(url) + '">x</button>' +
285
+ '</div>';
286
+ }).join('');
287
+ }
288
+
289
+ // Feature selection persistence
290
+ function getSelections() {
291
+ try {
292
+ var raw = localStorage.getItem(STORAGE_KEY_SELECTIONS);
293
+ if (!raw) return {};
294
+ var parsed = JSON.parse(raw);
295
+ return typeof parsed === 'object' && parsed !== null ? parsed : {};
296
+ } catch (e) {
297
+ return {};
298
+ }
299
+ }
300
+
301
+ function saveSelections() {
302
+ var selections = {};
303
+ FEATURES.forEach(function(f) {
304
+ var checkbox = document.querySelector('input[data-feature-id="' + f.key + '"]');
305
+ var select = document.querySelector('select[data-value-for="' + f.key + '"]');
306
+ if (checkbox && select) {
307
+ selections[f.key] = { checked: checkbox.checked, value: select.value };
308
+ }
309
+ });
310
+ localStorage.setItem(STORAGE_KEY_SELECTIONS, JSON.stringify(selections));
311
+ }
312
+
313
+ function restoreSelections() {
314
+ var selections = getSelections();
315
+ FEATURES.forEach(function(f) {
316
+ var saved = selections[f.key];
317
+ if (!saved) return;
318
+ var checkbox = document.querySelector('input[data-feature-id="' + f.key + '"]');
319
+ var select = document.querySelector('select[data-value-for="' + f.key + '"]');
320
+ if (checkbox) checkbox.checked = saved.checked;
321
+ if (select) select.value = saved.value;
322
+ });
323
+ }
324
+
325
+ function escapeHtml(str) {
326
+ var div = document.createElement('div');
327
+ div.textContent = str;
328
+ return div.innerHTML;
329
+ }
330
+
331
+ function escapeAttr(str) {
332
+ return str.replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
333
+ }
334
+
335
+ function buildTargetUrl(inputValue) {
336
+ var value = inputValue;
337
+ if (!value.startsWith('http://') && !value.startsWith('https://')) {
338
+ value = 'https://' + value;
339
+ }
340
+ var hostname = window.location.hostname;
341
+ var subdomain = hostname.split('.').length > 2 ? hostname.split('.')[0] : '';
342
+ var target = value;
343
+ var sep = target.includes('?') ? '&' : '?';
344
+ if (subdomain) {
345
+ target = target + sep + 'cvly_env=' + encodeURIComponent(subdomain);
346
+ sep = '&';
347
+ }
348
+ FEATURES.forEach(function(f) {
349
+ var checkbox = document.querySelector('input[data-feature-id="' + f.key + '"]');
350
+ var select = document.querySelector('select[data-value-for="' + f.key + '"]');
351
+ if (checkbox && checkbox.checked && select) {
352
+ target = target + sep + 'picked-feature=' + encodeURIComponent(f.key + ':' + select.value);
353
+ sep = '&';
354
+ }
355
+ });
356
+ return target;
357
+ }
358
+
359
+ function showCopyStatus(message, success) {
360
+ var el = document.getElementById('copy-status');
361
+ if (!el) return;
362
+ el.textContent = message;
363
+ el.style.visibility = 'visible';
364
+ el.style.color = success ? '#2e7d32' : '#b71c1c';
365
+ setTimeout(function() {
366
+ el.style.visibility = 'hidden';
367
+ }, 2000);
368
+ }
369
+
370
+ // Init
371
+ window.addEventListener('load', function() {
372
+ var input = getUrlInput();
373
+ var savedUrl = localStorage.getItem(STORAGE_KEY_URL);
374
+ if (savedUrl && input) {
375
+ input.value = savedUrl;
376
+ }
377
+ renderHistory();
378
+ restoreSelections();
379
+ });
380
+
381
+ // Delegate click events
382
+ document.addEventListener('click', function(e) {
383
+ var target = e.target;
384
+
385
+ // History URL click
386
+ var historyUrl = target.getAttribute('data-history-url');
387
+ if (historyUrl) {
388
+ var input = getUrlInput();
389
+ if (input) input.value = historyUrl;
390
+ return;
391
+ }
392
+
393
+ // History delete click
394
+ var deleteUrl = target.getAttribute('data-history-delete');
395
+ if (deleteUrl) {
396
+ removeFromHistory(deleteUrl);
397
+ return;
398
+ }
399
+ });
400
+
401
+ // Feature change persistence
402
+ document.addEventListener('change', function(e) {
403
+ var target = e.target;
404
+ if (target.getAttribute('data-feature-id') || target.getAttribute('data-value-for')) {
405
+ saveSelections();
406
+ }
407
+ });
408
+
409
+ // Copy button
410
+ document.getElementById('copy-btn').addEventListener('click', function() {
411
+ var input = getUrlInput();
412
+ if (!input || !input.value) return;
413
+ localStorage.setItem(STORAGE_KEY_URL, input.value);
414
+ addToHistory(input.value);
415
+ saveSelections();
416
+ var target = buildTargetUrl(input.value);
417
+ navigator.clipboard.writeText(target).then(function() {
418
+ showCopyStatus('Preview URL copied to clipboard', true);
419
+ });
420
+ });
421
+
422
+ // Preview button
423
+ document.getElementById('preview-btn').addEventListener('click', function() {
424
+ var input = getUrlInput();
425
+ if (!input || !input.value) return;
426
+ localStorage.setItem(STORAGE_KEY_URL, input.value);
427
+ addToHistory(input.value);
428
+ saveSelections();
429
+ var target = buildTargetUrl(input.value);
430
+ window.location.href = target;
431
+ });
432
+ <\/script>
433
+ </main>
434
+ </body>
435
+ </html>`],[`<!DOCTYPE html>
2
436
  <html lang="en">
3
437
  <head>
4
438
  <meta charset="UTF-8">
@@ -207,18 +641,7 @@
207
641
  <div id="url-history" class="url-history"></div>
208
642
  <div class="features-section">
209
643
  <p class="features-label">Features</p>
210
- ${e.length>0?e.map(r=>`
211
- <div class="feature-row">
212
- <label>
213
- <input type="checkbox" data-feature-id="${b(r.id)}" checked>
214
- <span class="feature-name">${y(r.name)}</span>
215
- <span class="feature-id">${y(r.id)}</span>
216
- </label>
217
- <select data-value-for="${b(r.id)}">
218
- <option value="true" selected>true</option>
219
- <option value="false">false</option>
220
- </select>
221
- </div>`).join(""):'<p class="text no-features">No features configured for this project.</p>'}
644
+ `,`
222
645
  </div>
223
646
  <div class="buttons">
224
647
  <button type="button" class="preview-button" id="copy-btn">Copy</button>
@@ -231,7 +654,7 @@
231
654
  </div>
232
655
 
233
656
  <script>
234
- var FEATURES = ${t};
657
+ var FEATURES = `,`;
235
658
  var STORAGE_KEY_URL = 'picked-launcher-url';
236
659
  var STORAGE_KEY_HISTORY = 'picked-launcher-history';
237
660
  var STORAGE_KEY_SELECTIONS = 'picked-launcher-selections';
@@ -301,10 +724,10 @@
301
724
  function saveSelections() {
302
725
  var selections = {};
303
726
  FEATURES.forEach(function(f) {
304
- var checkbox = document.querySelector('input[data-feature-id="' + f.id + '"]');
305
- var select = document.querySelector('select[data-value-for="' + f.id + '"]');
727
+ var checkbox = document.querySelector('input[data-feature-id="' + f.key + '"]');
728
+ var select = document.querySelector('select[data-value-for="' + f.key + '"]');
306
729
  if (checkbox && select) {
307
- selections[f.id] = { checked: checkbox.checked, value: select.value };
730
+ selections[f.key] = { checked: checkbox.checked, value: select.value };
308
731
  }
309
732
  });
310
733
  localStorage.setItem(STORAGE_KEY_SELECTIONS, JSON.stringify(selections));
@@ -313,10 +736,10 @@
313
736
  function restoreSelections() {
314
737
  var selections = getSelections();
315
738
  FEATURES.forEach(function(f) {
316
- var saved = selections[f.id];
739
+ var saved = selections[f.key];
317
740
  if (!saved) return;
318
- var checkbox = document.querySelector('input[data-feature-id="' + f.id + '"]');
319
- var select = document.querySelector('select[data-value-for="' + f.id + '"]');
741
+ var checkbox = document.querySelector('input[data-feature-id="' + f.key + '"]');
742
+ var select = document.querySelector('select[data-value-for="' + f.key + '"]');
320
743
  if (checkbox) checkbox.checked = saved.checked;
321
744
  if (select) select.value = saved.value;
322
745
  });
@@ -346,10 +769,10 @@
346
769
  sep = '&';
347
770
  }
348
771
  FEATURES.forEach(function(f) {
349
- var checkbox = document.querySelector('input[data-feature-id="' + f.id + '"]');
350
- var select = document.querySelector('select[data-value-for="' + f.id + '"]');
772
+ var checkbox = document.querySelector('input[data-feature-id="' + f.key + '"]');
773
+ var select = document.querySelector('select[data-value-for="' + f.key + '"]');
351
774
  if (checkbox && checkbox.checked && select) {
352
- target = target + sep + 'picked-feature=' + encodeURIComponent(f.id + ':' + select.value);
775
+ target = target + sep + 'picked-feature=' + encodeURIComponent(f.key + ':' + select.value);
353
776
  sep = '&';
354
777
  }
355
778
  });
@@ -432,7 +855,7 @@
432
855
  <\/script>
433
856
  </main>
434
857
  </body>
435
- </html>`}function y(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function b(e){return e.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}const _="picked",T="\x1B[0m";function k(){const e=process.env.NO_COLOR;return e==="1"||e==="true"}function c(e){return t=>k()?t:`${e}${t}${T}`}const w=["debug","info","warn","error","silent"],g={debug:{color:c("\x1B[2m"),log:console.debug,enabled:!1},info:{color:c("\x1B[36m"),log:console.log,enabled:!0},warn:{color:c("\x1B[33m"),log:console.warn,enabled:!0},error:{color:c("\x1B[31m"),log:console.error,enabled:!0},silent:{log:()=>{},enabled:!1}};function U(e,t){const n=new Date().toLocaleTimeString(),r=t?`${_}:${t}`:_;return`${n} [${r}] ${e}`}function h(e,t,n,r){if(!e.enabled)return;const i=U(t,r);e.log(e.color?e.color(i):i),n!==void 0&&e.log(n)}function p(e){const t=g[e],n=new Set;return Object.assign((r,i,o)=>{h(t,r,i,o)},{once(r,i,o){!t.enabled||n.has(r)||(n.add(r),h(t,r,i,o))}})}function R(e){const t=w.indexOf(e);if(t===-1){h(g.error,`invalid log level: ${e}`);return}for(const[n,r]of w.entries())g[r].enabled=n>=t}const l=c("\x1B[34m"),S=c("\x1B[36m");function L(){const e=[` ${l("_")} ${S("_")} _ _ _`,`${l("(_)")} ${S("(_)")} _ __(_)__| |_____ __| |`,` ${l("_")} ${l("_")} | '_ \\ / _| / / -_) _\` |`,`${l("(_)")} ${l("(_)")} | .__/_\\__|_\\_\\___\\__,_|`,` |_|
858
+ </html>`])),r,t)}function w(e){return e.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;")}function S(e){return e.replaceAll("&","&amp;").replaceAll('"',"&quot;").replaceAll("<","&lt;").replaceAll(">","&gt;")}const E="picked",L="\x1B[0m";function O(){const e=process.env.NO_COLOR;return e==="1"||e==="true"}function c(e){return t=>O()?t:`${e}${t}${L}`}const x=["debug","info","warn","error","silent"],v={debug:{color:c("\x1B[2m"),log:console.debug,enabled:!1},info:{color:c("\x1B[36m"),log:console.log,enabled:!0},warn:{color:c("\x1B[33m"),log:console.warn,enabled:!0},error:{color:c("\x1B[31m"),log:console.error,enabled:!0},silent:{log:()=>{},enabled:!1}};function H(e,t){const r=new Date().toLocaleTimeString(),n=t?`${E}:${t}`:E;return`${r} [${n}] ${e}`}function g(e,t,r,n){if(!e.enabled)return;const o=H(t,n);e.log(e.color?e.color(o):o),r!==void 0&&e.log(r)}function p(e){const t=v[e],r=new Set;return Object.assign((n,o,i)=>{g(t,n,o,i)},{once(n,o,i){!t.enabled||r.has(n)||(r.add(n),g(t,n,o,i))}})}function $(e){const t=x.indexOf(e);if(t===-1){g(v.error,`invalid log level: ${e}`);return}for(const[r,n]of x.entries())v[n].enabled=r>=t}const s=c("\x1B[34m"),_=c("\x1B[36m");function C(){const e=[` ${s("_")} ${_("_")} _ _ _`,`${s("(_)")} ${_("(_)")} _ __(_)__| |_____ __| |`,` ${s("_")} ${s("_")} | '_ \\ / _| / / -_) _\` |`,`${s("(_)")} ${s("(_)")} | .__/_\\__|_\\_\\___\\__,_|`,` |_|
436
859
  `];console.log(e.join(`
437
- `))}const s={banner:L,debug:p("debug"),info:p("info"),warn:p("warn"),error:p("error"),setLevel:R};function I(e){return(t,n,r)=>{if(t.method!=="GET"){r();return}const o=(t.url??"").split("?")[0];if(o!=="/"&&o!=="/index.html"){r();return}const a=e();n.setHeader("Content-Type","text/html"),n.statusCode=200,n.end(a)}}function O(e){if(e.length===0)return;const t=Math.max(4,...e.map(a=>a.name.length)),n=Math.max(2,...e.map(a=>a.id.length)),r=` ${"Name".padEnd(t)} ${"ID".padEnd(n)} Status Weight Ver`,i=` ${"─".repeat(t)} ${"─".repeat(n)} ──────── ────── ───`,o=e.map(a=>{const d=a.enabled?"\x1B[32m enabled\x1B[0m":"\x1B[2mdisabled\x1B[0m",u=`${a.weight.toString()}%`.padStart(6),f=`v${a.version.toString()}`;return` ${a.name.padEnd(t)} ${a.id.padEnd(n)} ${d} ${u} ${f}`});console.log([""," Features:","",r,i,...o,""].join(`
438
- `))}function H(e){try{const t=new URL(e).hostname;return t==="localhost"||t==="127.0.0.1"||t==="::1"}catch{return!1}}function B(e){return new Promise(t=>{setTimeout(t,e)})}async function C(e,t,n){const r=await m.fetchProject(e,t,{headers:n});if(r||!H(e))return r;for(let i=1;i<=x;i++){s.info(`local API not ready, retrying in ${(A/1e3).toString()}s (${i.toString()}/${x.toString()})`),await B(A);const o=await m.fetchProject(e,t,{headers:n});if(o)return o}return null}function P(){return"0.0.1-dev.1772493269328"}const E="https://api.picked.app",F="__PICKED_PROJECT_CONFIG__",x=5,A=2e3;function Y(e){const t=e.apiUrl??E;let n=[];return{name:"picked",config:async()=>{s.banner(),s.info(`fetching project config for "${e.projectId}"`),t!==E&&s.warn(`using custom API URL: ${t}`);const r=m.createClientHeaders("vite-plugin",P()),i=performance.now(),o=await C(t,e.projectId,r),a=(performance.now()-i).toFixed(0);if(!o){s.warn(`failed to fetch project config for "${e.projectId}" (${a}ms)`);return}n=o.features;const d=o.features.length,u=o.features.filter($=>$.enabled).length,f=JSON.stringify(o).length;return s.info(`fetched ${d.toString()} features (${u.toString()} enabled) for "${e.projectId}" in ${a}ms`),O(o.features),s.debug(`config size: ${f.toString()} bytes`),{define:{[F]:JSON.stringify(o)}}},configureServer(r){if(e.disableLauncher)return;r.middlewares.use(I(()=>v(n)));const i=r.printUrls.bind(r);r.printUrls=()=>{const o=r.resolvedUrls?.local[0];if(o){const a=o.replace(/:(?<port>\d+)\//,(d,u)=>`:\x1B[1m${u}\x1B[22m/`);console.log(` \x1B[32m➜\x1B[0m \x1B[1mPicked\x1B[22m: \x1B[36m${a}\x1B[0m`)}i()}},generateBundle(){e.disableLauncher||this.emitFile({type:"asset",fileName:"index.html",source:v(n)})}}}exports.picked=Y;
860
+ `))}const l={banner:C,debug:p("debug"),info:p("info"),warn:p("warn"),error:p("error"),setLevel:$};function Y(e){return(t,r,n)=>{if(t.method!=="GET"){n();return}const i=(t.url??"").split("?")[0];if(i!=="/"&&i!=="/index.html"){n();return}const a=e();r.setHeader("Content-Type","text/html"),r.statusCode=200,r.end(a)}}function B(e){if(e.length===0)return;const t=Math.max(4,...e.map(a=>a.name.length)),r=Math.max(3,...e.map(a=>a.key.length)),n=` ${"Name".padEnd(t)} ${"Key".padEnd(r)} Status Weight Ver`,o=` ${"─".repeat(t)} ${"─".repeat(r)} ──────── ────── ───`,i=e.map(a=>{const d=a.enabled?"\x1B[32m enabled\x1B[0m":"\x1B[2mdisabled\x1B[0m",u=`${a.weight.toString()}%`.padStart(6),f=`v${a.version.toString()}`;return` ${a.name.padEnd(t)} ${a.key.padEnd(r)} ${d} ${u} ${f}`});console.log([""," Features:","",n,o,...i,""].join(`
861
+ `))}function F(e){try{const t=new URL(e).hostname;return t==="localhost"||t==="127.0.0.1"||t==="::1"}catch{return!1}}function P(e){return new Promise(t=>{setTimeout(t,e)})}async function z(e,t,r){const n=await m.fetchProject(e,t,{headers:r});if(n||!F(e))return n;for(let o=1;o<=A;o++){l.info(`local API not ready, retrying in ${(T/1e3).toString()}s (${o.toString()}/${A.toString()})`),await P(T);const i=await m.fetchProject(e,t,{headers:r});if(i)return i}return null}function N(){return"0.0.1-dev.1773363643396"}const k="https://api.picked.app",j="__PICKED_PROJECT_CONFIG__",A=5,T=2e3;function K(e){const t=e.apiUrl??k;let r=[];return{name:"picked",config:async()=>{l.banner(),l.info(`fetching project config for "${e.projectId}"`),t!==k&&l.warn(`using custom API URL: ${t}`);const n=m.createClientHeaders("vite-plugin",N()),o=performance.now(),i=await z(t,e.projectId,n),a=(performance.now()-o).toFixed(0);if(!i){l.warn(`failed to fetch project config for "${e.projectId}" (${a}ms)`);return}r=i.features;const d=i.features.length,u=i.features.filter(U=>U.enabled).length,f=JSON.stringify(i).length;return l.info(`fetched ${d.toString()} features (${u.toString()} enabled) for "${e.projectId}" in ${a}ms`),B(i.features),l.debug(`config size: ${f.toString()} bytes`),{define:{[j]:JSON.stringify(i)}}},configureServer(n){if(e.disableLauncher)return;n.middlewares.use(Y(()=>b(r)));const o=n.printUrls.bind(n);n.printUrls=()=>{const i=n.resolvedUrls?.local[0];if(i){const a=i.replace(/:(?<port>\d+)\//,(d,u)=>`:\x1B[1m${u}\x1B[22m/`);console.log(` \x1B[32m➜\x1B[0m \x1B[1mPicked\x1B[22m: \x1B[36m${a}\x1B[0m`)}o()}},generateBundle(){e.disableLauncher||this.emitFile({type:"asset",fileName:"index.html",source:b(r)})}}}exports.picked=K;
package/dist/esm/index.js CHANGED
@@ -1,7 +1,444 @@
1
- import { createClientHeaders as T, fetchProject as h } from "@picked/client/plugins/dynamic-experiences";
2
- function v(e) {
3
- const t = JSON.stringify(e);
4
- return `<!DOCTYPE html>
1
+ import { createClientHeaders as R, fetchProject as g } from "@picked/client/plugins/dynamic-experiences";
2
+ var h = Object.freeze, I = Object.defineProperty, L = (e, t) => h(I(e, "raw", { value: h(t || e.slice()) })), y;
3
+ function b(e) {
4
+ const t = JSON.stringify(e), r = e.length > 0 ? e.map(
5
+ (n) => `
6
+ <div class="feature-row">
7
+ <label>
8
+ <input type="checkbox" data-feature-id="${S(n.key)}" checked>
9
+ <span class="feature-name">${w(n.name)}</span>
10
+ <span class="feature-id">${w(n.key)}</span>
11
+ </label>
12
+ <select data-value-for="${S(n.key)}">
13
+ <option value="true" selected>true</option>
14
+ <option value="false">false</option>
15
+ </select>
16
+ </div>`
17
+ ).join("") : '<p class="text no-features">No features configured for this project.</p>';
18
+ return String.raw(y || (y = L([`<!DOCTYPE html>
19
+ <html lang="en">
20
+ <head>
21
+ <meta charset="UTF-8">
22
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
23
+ <meta name="robots" content="noindex, nofollow">
24
+ <title>Picked</title>
25
+ <style>
26
+ main {
27
+ position: fixed;
28
+ top: 0;
29
+ right: 0;
30
+ bottom: 0;
31
+ left: 0;
32
+ display: grid;
33
+ align-items: center;
34
+ justify-content: center;
35
+ font-family: monospace;
36
+ color: #4A4A4A
37
+ }
38
+
39
+ .wrap {
40
+ padding-left: 1.5rem;
41
+ padding-right: 1.5rem;
42
+ max-width: 480px;
43
+ width: 100%;
44
+ }
45
+
46
+ .title {
47
+ font-size: 1.125rem;
48
+ font-weight: 700;
49
+ margin-bottom: 0;
50
+ }
51
+
52
+ .text {
53
+ margin-top: .5rem;
54
+ font-size: .875rem
55
+ }
56
+
57
+ .text a {
58
+ color: #4A4A4A;
59
+ text-decoration: none;
60
+ }
61
+
62
+ .text a:hover {
63
+ cursor: pointer;
64
+ text-decoration: underline
65
+ }
66
+
67
+ .preview-form {
68
+ margin-top: 2rem;
69
+ display: flex;
70
+ flex-direction: column;
71
+ gap: 0.5rem;
72
+ }
73
+
74
+ .preview-input {
75
+ padding: 0.5rem;
76
+ border: 1px solid #4A4A4A;
77
+ border-radius: 0;
78
+ font-family: monospace;
79
+ }
80
+
81
+ .preview-button {
82
+ padding: 0.5rem;
83
+ background: #4A4A4A;
84
+ color: white;
85
+ border: none;
86
+ border-radius: 0;
87
+ cursor: pointer;
88
+ font-family: monospace;
89
+ }
90
+
91
+ .preview-button:hover {
92
+ opacity: 0.9;
93
+ }
94
+
95
+ .buttons {
96
+ display: grid;
97
+ gap: 0.5em;
98
+ grid-template-columns: 1fr 1fr;
99
+ }
100
+
101
+ #copy-status {
102
+ font-size: 1em;
103
+ text-align: right;
104
+ margin-top: 0.5em;
105
+ }
106
+
107
+ .features-section {
108
+ margin-top: 1.5rem;
109
+ }
110
+
111
+ .features-label {
112
+ font-weight: 700;
113
+ font-size: .875rem;
114
+ margin-bottom: 0.5rem;
115
+ }
116
+
117
+ .feature-row {
118
+ display: flex;
119
+ align-items: center;
120
+ justify-content: space-between;
121
+ gap: 0.5rem;
122
+ padding: 0.25rem 0;
123
+ }
124
+
125
+ .feature-row label {
126
+ display: flex;
127
+ align-items: center;
128
+ gap: 0.5rem;
129
+ cursor: pointer;
130
+ min-width: 0;
131
+ flex: 1;
132
+ }
133
+
134
+ .feature-name {
135
+ font-size: .875rem;
136
+ }
137
+
138
+ .feature-id {
139
+ font-size: .75rem;
140
+ color: #888;
141
+ }
142
+
143
+ .feature-row select {
144
+ font-family: monospace;
145
+ font-size: .75rem;
146
+ padding: 0.125rem 0.25rem;
147
+ border: 1px solid #4A4A4A;
148
+ border-radius: 0;
149
+ background: white;
150
+ flex-shrink: 0;
151
+ }
152
+
153
+ .no-features {
154
+ color: #888;
155
+ font-style: italic;
156
+ }
157
+
158
+ .url-history {
159
+ margin-top: 0.5rem;
160
+ font-size: .75rem;
161
+ }
162
+
163
+ .url-history-item {
164
+ display: flex;
165
+ align-items: center;
166
+ gap: 0.25rem;
167
+ padding: 0.125rem 0;
168
+ }
169
+
170
+ .url-history-item button {
171
+ background: none;
172
+ border: none;
173
+ cursor: pointer;
174
+ font-family: monospace;
175
+ font-size: .75rem;
176
+ color: #888;
177
+ padding: 0;
178
+ }
179
+
180
+ .url-history-item button.url-link {
181
+ color: #4A4A4A;
182
+ text-decoration: none;
183
+ text-align: left;
184
+ overflow: hidden;
185
+ text-overflow: ellipsis;
186
+ white-space: nowrap;
187
+ flex: 1;
188
+ min-width: 0;
189
+ }
190
+
191
+ .url-history-item button.url-link:hover {
192
+ text-decoration: underline;
193
+ }
194
+
195
+ .url-history-item button.url-delete:hover {
196
+ color: #b71c1c;
197
+ }
198
+
199
+ @media (min-width: 640px) {
200
+ .title {
201
+ font-size: 1.25rem
202
+ }
203
+
204
+ .text {
205
+ font-size: 1rem
206
+ }
207
+ }
208
+ </style>
209
+ </head>
210
+ <body>
211
+
212
+ <main>
213
+ <div class="wrap">
214
+ <p class="title">Picked</p>
215
+ <p class="text">
216
+ Learn more at
217
+ <a href="https://picked.app">
218
+ https://picked.app
219
+ </a>
220
+ </p>
221
+ <div class="preview-form">
222
+ <input type="text" id="url-input" pattern="^(https?://)?.+" placeholder="Enter preview URL" required
223
+ class="preview-input">
224
+ <div id="url-history" class="url-history"></div>
225
+ <div class="features-section">
226
+ <p class="features-label">Features</p>
227
+ `, `
228
+ </div>
229
+ <div class="buttons">
230
+ <button type="button" class="preview-button" id="copy-btn">Copy</button>
231
+ <button type="button" class="preview-button" id="preview-btn">Preview</button>
232
+ </div>
233
+ <p class="text" id="copy-status" aria-live="polite" style="visibility:hidden;">
234
+ &nbsp;
235
+ </p>
236
+ </div>
237
+ </div>
238
+
239
+ <script>
240
+ var FEATURES = `, `;
241
+ var STORAGE_KEY_URL = 'picked-launcher-url';
242
+ var STORAGE_KEY_HISTORY = 'picked-launcher-history';
243
+ var STORAGE_KEY_SELECTIONS = 'picked-launcher-selections';
244
+
245
+ function getUrlInput() {
246
+ return document.getElementById('url-input');
247
+ }
248
+
249
+ // URL history
250
+ function getHistory() {
251
+ try {
252
+ var raw = localStorage.getItem(STORAGE_KEY_HISTORY);
253
+ if (!raw) return [];
254
+ var parsed = JSON.parse(raw);
255
+ return Array.isArray(parsed) ? parsed : [];
256
+ } catch (e) {
257
+ return [];
258
+ }
259
+ }
260
+
261
+ function saveHistory(history) {
262
+ localStorage.setItem(STORAGE_KEY_HISTORY, JSON.stringify(history));
263
+ }
264
+
265
+ function addToHistory(url) {
266
+ var history = getHistory().filter(function(h) { return h !== url; });
267
+ history.unshift(url);
268
+ if (history.length > 10) history = history.slice(0, 10);
269
+ saveHistory(history);
270
+ renderHistory();
271
+ }
272
+
273
+ function removeFromHistory(url) {
274
+ var history = getHistory().filter(function(h) { return h !== url; });
275
+ saveHistory(history);
276
+ renderHistory();
277
+ }
278
+
279
+ function renderHistory() {
280
+ var container = document.getElementById('url-history');
281
+ if (!container) return;
282
+ var history = getHistory();
283
+ if (history.length === 0) {
284
+ container.innerHTML = '';
285
+ return;
286
+ }
287
+ container.innerHTML = history.map(function(url) {
288
+ return '<div class="url-history-item">' +
289
+ '<button type="button" class="url-link" data-history-url="' + escapeAttr(url) + '">' + escapeHtml(url) + '</button>' +
290
+ '<button type="button" class="url-delete" data-history-delete="' + escapeAttr(url) + '">x</button>' +
291
+ '</div>';
292
+ }).join('');
293
+ }
294
+
295
+ // Feature selection persistence
296
+ function getSelections() {
297
+ try {
298
+ var raw = localStorage.getItem(STORAGE_KEY_SELECTIONS);
299
+ if (!raw) return {};
300
+ var parsed = JSON.parse(raw);
301
+ return typeof parsed === 'object' && parsed !== null ? parsed : {};
302
+ } catch (e) {
303
+ return {};
304
+ }
305
+ }
306
+
307
+ function saveSelections() {
308
+ var selections = {};
309
+ FEATURES.forEach(function(f) {
310
+ var checkbox = document.querySelector('input[data-feature-id="' + f.key + '"]');
311
+ var select = document.querySelector('select[data-value-for="' + f.key + '"]');
312
+ if (checkbox && select) {
313
+ selections[f.key] = { checked: checkbox.checked, value: select.value };
314
+ }
315
+ });
316
+ localStorage.setItem(STORAGE_KEY_SELECTIONS, JSON.stringify(selections));
317
+ }
318
+
319
+ function restoreSelections() {
320
+ var selections = getSelections();
321
+ FEATURES.forEach(function(f) {
322
+ var saved = selections[f.key];
323
+ if (!saved) return;
324
+ var checkbox = document.querySelector('input[data-feature-id="' + f.key + '"]');
325
+ var select = document.querySelector('select[data-value-for="' + f.key + '"]');
326
+ if (checkbox) checkbox.checked = saved.checked;
327
+ if (select) select.value = saved.value;
328
+ });
329
+ }
330
+
331
+ function escapeHtml(str) {
332
+ var div = document.createElement('div');
333
+ div.textContent = str;
334
+ return div.innerHTML;
335
+ }
336
+
337
+ function escapeAttr(str) {
338
+ return str.replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
339
+ }
340
+
341
+ function buildTargetUrl(inputValue) {
342
+ var value = inputValue;
343
+ if (!value.startsWith('http://') && !value.startsWith('https://')) {
344
+ value = 'https://' + value;
345
+ }
346
+ var hostname = window.location.hostname;
347
+ var subdomain = hostname.split('.').length > 2 ? hostname.split('.')[0] : '';
348
+ var target = value;
349
+ var sep = target.includes('?') ? '&' : '?';
350
+ if (subdomain) {
351
+ target = target + sep + 'cvly_env=' + encodeURIComponent(subdomain);
352
+ sep = '&';
353
+ }
354
+ FEATURES.forEach(function(f) {
355
+ var checkbox = document.querySelector('input[data-feature-id="' + f.key + '"]');
356
+ var select = document.querySelector('select[data-value-for="' + f.key + '"]');
357
+ if (checkbox && checkbox.checked && select) {
358
+ target = target + sep + 'picked-feature=' + encodeURIComponent(f.key + ':' + select.value);
359
+ sep = '&';
360
+ }
361
+ });
362
+ return target;
363
+ }
364
+
365
+ function showCopyStatus(message, success) {
366
+ var el = document.getElementById('copy-status');
367
+ if (!el) return;
368
+ el.textContent = message;
369
+ el.style.visibility = 'visible';
370
+ el.style.color = success ? '#2e7d32' : '#b71c1c';
371
+ setTimeout(function() {
372
+ el.style.visibility = 'hidden';
373
+ }, 2000);
374
+ }
375
+
376
+ // Init
377
+ window.addEventListener('load', function() {
378
+ var input = getUrlInput();
379
+ var savedUrl = localStorage.getItem(STORAGE_KEY_URL);
380
+ if (savedUrl && input) {
381
+ input.value = savedUrl;
382
+ }
383
+ renderHistory();
384
+ restoreSelections();
385
+ });
386
+
387
+ // Delegate click events
388
+ document.addEventListener('click', function(e) {
389
+ var target = e.target;
390
+
391
+ // History URL click
392
+ var historyUrl = target.getAttribute('data-history-url');
393
+ if (historyUrl) {
394
+ var input = getUrlInput();
395
+ if (input) input.value = historyUrl;
396
+ return;
397
+ }
398
+
399
+ // History delete click
400
+ var deleteUrl = target.getAttribute('data-history-delete');
401
+ if (deleteUrl) {
402
+ removeFromHistory(deleteUrl);
403
+ return;
404
+ }
405
+ });
406
+
407
+ // Feature change persistence
408
+ document.addEventListener('change', function(e) {
409
+ var target = e.target;
410
+ if (target.getAttribute('data-feature-id') || target.getAttribute('data-value-for')) {
411
+ saveSelections();
412
+ }
413
+ });
414
+
415
+ // Copy button
416
+ document.getElementById('copy-btn').addEventListener('click', function() {
417
+ var input = getUrlInput();
418
+ if (!input || !input.value) return;
419
+ localStorage.setItem(STORAGE_KEY_URL, input.value);
420
+ addToHistory(input.value);
421
+ saveSelections();
422
+ var target = buildTargetUrl(input.value);
423
+ navigator.clipboard.writeText(target).then(function() {
424
+ showCopyStatus('Preview URL copied to clipboard', true);
425
+ });
426
+ });
427
+
428
+ // Preview button
429
+ document.getElementById('preview-btn').addEventListener('click', function() {
430
+ var input = getUrlInput();
431
+ if (!input || !input.value) return;
432
+ localStorage.setItem(STORAGE_KEY_URL, input.value);
433
+ addToHistory(input.value);
434
+ saveSelections();
435
+ var target = buildTargetUrl(input.value);
436
+ window.location.href = target;
437
+ });
438
+ <\/script>
439
+ </main>
440
+ </body>
441
+ </html>`], [`<!DOCTYPE html>
5
442
  <html lang="en">
6
443
  <head>
7
444
  <meta charset="UTF-8">
@@ -210,20 +647,7 @@ function v(e) {
210
647
  <div id="url-history" class="url-history"></div>
211
648
  <div class="features-section">
212
649
  <p class="features-label">Features</p>
213
- ${e.length > 0 ? e.map(
214
- (r) => `
215
- <div class="feature-row">
216
- <label>
217
- <input type="checkbox" data-feature-id="${b(r.id)}" checked>
218
- <span class="feature-name">${y(r.name)}</span>
219
- <span class="feature-id">${y(r.id)}</span>
220
- </label>
221
- <select data-value-for="${b(r.id)}">
222
- <option value="true" selected>true</option>
223
- <option value="false">false</option>
224
- </select>
225
- </div>`
226
- ).join("") : '<p class="text no-features">No features configured for this project.</p>'}
650
+ `, `
227
651
  </div>
228
652
  <div class="buttons">
229
653
  <button type="button" class="preview-button" id="copy-btn">Copy</button>
@@ -236,7 +660,7 @@ function v(e) {
236
660
  </div>
237
661
 
238
662
  <script>
239
- var FEATURES = ${t};
663
+ var FEATURES = `, `;
240
664
  var STORAGE_KEY_URL = 'picked-launcher-url';
241
665
  var STORAGE_KEY_HISTORY = 'picked-launcher-history';
242
666
  var STORAGE_KEY_SELECTIONS = 'picked-launcher-selections';
@@ -306,10 +730,10 @@ function v(e) {
306
730
  function saveSelections() {
307
731
  var selections = {};
308
732
  FEATURES.forEach(function(f) {
309
- var checkbox = document.querySelector('input[data-feature-id="' + f.id + '"]');
310
- var select = document.querySelector('select[data-value-for="' + f.id + '"]');
733
+ var checkbox = document.querySelector('input[data-feature-id="' + f.key + '"]');
734
+ var select = document.querySelector('select[data-value-for="' + f.key + '"]');
311
735
  if (checkbox && select) {
312
- selections[f.id] = { checked: checkbox.checked, value: select.value };
736
+ selections[f.key] = { checked: checkbox.checked, value: select.value };
313
737
  }
314
738
  });
315
739
  localStorage.setItem(STORAGE_KEY_SELECTIONS, JSON.stringify(selections));
@@ -318,10 +742,10 @@ function v(e) {
318
742
  function restoreSelections() {
319
743
  var selections = getSelections();
320
744
  FEATURES.forEach(function(f) {
321
- var saved = selections[f.id];
745
+ var saved = selections[f.key];
322
746
  if (!saved) return;
323
- var checkbox = document.querySelector('input[data-feature-id="' + f.id + '"]');
324
- var select = document.querySelector('select[data-value-for="' + f.id + '"]');
747
+ var checkbox = document.querySelector('input[data-feature-id="' + f.key + '"]');
748
+ var select = document.querySelector('select[data-value-for="' + f.key + '"]');
325
749
  if (checkbox) checkbox.checked = saved.checked;
326
750
  if (select) select.value = saved.value;
327
751
  });
@@ -351,10 +775,10 @@ function v(e) {
351
775
  sep = '&';
352
776
  }
353
777
  FEATURES.forEach(function(f) {
354
- var checkbox = document.querySelector('input[data-feature-id="' + f.id + '"]');
355
- var select = document.querySelector('select[data-value-for="' + f.id + '"]');
778
+ var checkbox = document.querySelector('input[data-feature-id="' + f.key + '"]');
779
+ var select = document.querySelector('select[data-value-for="' + f.key + '"]');
356
780
  if (checkbox && checkbox.checked && select) {
357
- target = target + sep + 'picked-feature=' + encodeURIComponent(f.id + ':' + select.value);
781
+ target = target + sep + 'picked-feature=' + encodeURIComponent(f.key + ':' + select.value);
358
782
  sep = '&';
359
783
  }
360
784
  });
@@ -437,23 +861,23 @@ function v(e) {
437
861
  <\/script>
438
862
  </main>
439
863
  </body>
440
- </html>`;
864
+ </html>`])), r, t);
441
865
  }
442
- function y(e) {
443
- return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
866
+ function w(e) {
867
+ return e.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;");
444
868
  }
445
- function b(e) {
446
- return e.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
869
+ function S(e) {
870
+ return e.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
447
871
  }
448
- const _ = "picked", k = "\x1B[0m";
449
- function U() {
872
+ const E = "picked", H = "\x1B[0m";
873
+ function O() {
450
874
  const e = process.env.NO_COLOR;
451
875
  return e === "1" || e === "true";
452
876
  }
453
877
  function c(e) {
454
- return (t) => U() ? t : `${e}${t}${k}`;
878
+ return (t) => O() ? t : `${e}${t}${H}`;
455
879
  }
456
- const w = ["debug", "info", "warn", "error", "silent"], m = {
880
+ const x = ["debug", "info", "warn", "error", "silent"], m = {
457
881
  debug: {
458
882
  color: c("\x1B[2m"),
459
883
  log: console.debug,
@@ -480,43 +904,43 @@ const w = ["debug", "info", "warn", "error", "silent"], m = {
480
904
  enabled: !1
481
905
  }
482
906
  };
483
- function R(e, t) {
484
- const n = (/* @__PURE__ */ new Date()).toLocaleTimeString(), r = t ? `${_}:${t}` : _;
485
- return `${n} [${r}] ${e}`;
907
+ function $(e, t) {
908
+ const r = (/* @__PURE__ */ new Date()).toLocaleTimeString(), n = t ? `${E}:${t}` : E;
909
+ return `${r} [${n}] ${e}`;
486
910
  }
487
- function g(e, t, n, r) {
911
+ function v(e, t, r, n) {
488
912
  if (!e.enabled)
489
913
  return;
490
- const i = R(t, r);
491
- e.log(e.color ? e.color(i) : i), n !== void 0 && e.log(n);
914
+ const o = $(t, n);
915
+ e.log(e.color ? e.color(o) : o), r !== void 0 && e.log(r);
492
916
  }
493
917
  function p(e) {
494
- const t = m[e], n = /* @__PURE__ */ new Set();
918
+ const t = m[e], r = /* @__PURE__ */ new Set();
495
919
  return Object.assign(
496
- (r, i, o) => {
497
- g(t, r, i, o);
920
+ (n, o, i) => {
921
+ v(t, n, o, i);
498
922
  },
499
923
  {
500
- once(r, i, o) {
501
- !t.enabled || n.has(r) || (n.add(r), g(t, r, i, o));
924
+ once(n, o, i) {
925
+ !t.enabled || r.has(n) || (r.add(n), v(t, n, o, i));
502
926
  }
503
927
  }
504
928
  );
505
929
  }
506
- function L(e) {
507
- const t = w.indexOf(e);
930
+ function C(e) {
931
+ const t = x.indexOf(e);
508
932
  if (t === -1) {
509
- g(m.error, `invalid log level: ${e}`);
933
+ v(m.error, `invalid log level: ${e}`);
510
934
  return;
511
935
  }
512
- for (const [n, r] of w.entries())
513
- m[r].enabled = n >= t;
936
+ for (const [r, n] of x.entries())
937
+ m[n].enabled = r >= t;
514
938
  }
515
- const s = c("\x1B[34m"), S = c("\x1B[36m");
516
- function I() {
939
+ const s = c("\x1B[34m"), _ = c("\x1B[36m");
940
+ function Y() {
517
941
  const e = [
518
- ` ${s("_")} ${S("_")} _ _ _`,
519
- `${s("(_)")} ${S("(_)")} _ __(_)__| |_____ __| |`,
942
+ ` ${s("_")} ${_("_")} _ _ _`,
943
+ `${s("(_)")} ${_("(_)")} _ __(_)__| |_____ __| |`,
520
944
  ` ${s("_")} ${s("_")} | '_ \\ / _| / / -_) _\` |`,
521
945
  `${s("(_)")} ${s("(_)")} | .__/_\\__|_\\_\\___\\__,_|`,
522
946
  ` |_|
@@ -526,39 +950,39 @@ function I() {
526
950
  `));
527
951
  }
528
952
  const l = {
529
- banner: I,
953
+ banner: Y,
530
954
  debug: p("debug"),
531
955
  info: p("info"),
532
956
  warn: p("warn"),
533
957
  error: p("error"),
534
- setLevel: L
958
+ setLevel: C
535
959
  };
536
- function O(e) {
537
- return (t, n, r) => {
960
+ function B(e) {
961
+ return (t, r, n) => {
538
962
  if (t.method !== "GET") {
539
- r();
963
+ n();
540
964
  return;
541
965
  }
542
- const o = (t.url ?? "").split("?")[0];
543
- if (o !== "/" && o !== "/index.html") {
544
- r();
966
+ const i = (t.url ?? "").split("?")[0];
967
+ if (i !== "/" && i !== "/index.html") {
968
+ n();
545
969
  return;
546
970
  }
547
971
  const a = e();
548
- n.setHeader("Content-Type", "text/html"), n.statusCode = 200, n.end(a);
972
+ r.setHeader("Content-Type", "text/html"), r.statusCode = 200, r.end(a);
549
973
  };
550
974
  }
551
- function H(e) {
975
+ function F(e) {
552
976
  if (e.length === 0)
553
977
  return;
554
- const t = Math.max(4, ...e.map((a) => a.name.length)), n = Math.max(2, ...e.map((a) => a.id.length)), r = ` ${"Name".padEnd(t)} ${"ID".padEnd(n)} Status Weight Ver`, i = ` ${"─".repeat(t)} ${"─".repeat(n)} ──────── ────── ───`, o = e.map((a) => {
978
+ const t = Math.max(4, ...e.map((a) => a.name.length)), r = Math.max(3, ...e.map((a) => a.key.length)), n = ` ${"Name".padEnd(t)} ${"Key".padEnd(r)} Status Weight Ver`, o = ` ${"─".repeat(t)} ${"─".repeat(r)} ──────── ────── ───`, i = e.map((a) => {
555
979
  const d = a.enabled ? "\x1B[32m enabled\x1B[0m" : "\x1B[2mdisabled\x1B[0m", u = `${a.weight.toString()}%`.padStart(6), f = `v${a.version.toString()}`;
556
- return ` ${a.name.padEnd(t)} ${a.id.padEnd(n)} ${d} ${u} ${f}`;
980
+ return ` ${a.name.padEnd(t)} ${a.key.padEnd(r)} ${d} ${u} ${f}`;
557
981
  });
558
- console.log(["", " Features:", "", r, i, ...o, ""].join(`
982
+ console.log(["", " Features:", "", n, o, ...i, ""].join(`
559
983
  `));
560
984
  }
561
- function B(e) {
985
+ function z(e) {
562
986
  try {
563
987
  const t = new URL(e).hostname;
564
988
  return t === "localhost" || t === "127.0.0.1" || t === "::1";
@@ -566,76 +990,76 @@ function B(e) {
566
990
  return !1;
567
991
  }
568
992
  }
569
- function C(e) {
993
+ function P(e) {
570
994
  return new Promise((t) => {
571
995
  setTimeout(t, e);
572
996
  });
573
997
  }
574
- async function F(e, t, n) {
575
- const r = await h(e, t, { headers: n });
576
- if (r || !B(e))
577
- return r;
578
- for (let i = 1; i <= E; i++) {
998
+ async function N(e, t, r) {
999
+ const n = await g(e, t, { headers: r });
1000
+ if (n || !z(e))
1001
+ return n;
1002
+ for (let o = 1; o <= A; o++) {
579
1003
  l.info(
580
- `local API not ready, retrying in ${(A / 1e3).toString()}s (${i.toString()}/${E.toString()})`
581
- ), await C(A);
582
- const o = await h(e, t, { headers: n });
583
- if (o)
584
- return o;
1004
+ `local API not ready, retrying in ${(T / 1e3).toString()}s (${o.toString()}/${A.toString()})`
1005
+ ), await P(T);
1006
+ const i = await g(e, t, { headers: r });
1007
+ if (i)
1008
+ return i;
585
1009
  }
586
1010
  return null;
587
1011
  }
588
- function P() {
589
- return "0.0.1-dev.1772493269328";
1012
+ function K() {
1013
+ return "0.0.1-dev.1773363643396";
590
1014
  }
591
- const x = "https://api.picked.app", Y = "__PICKED_PROJECT_CONFIG__", E = 5, A = 2e3;
592
- function j(e) {
593
- const t = e.apiUrl ?? x;
594
- let n = [];
1015
+ const k = "https://api.picked.app", G = "__PICKED_PROJECT_CONFIG__", A = 5, T = 2e3;
1016
+ function q(e) {
1017
+ const t = e.apiUrl ?? k;
1018
+ let r = [];
595
1019
  return {
596
1020
  name: "picked",
597
1021
  config: async () => {
598
- l.banner(), l.info(`fetching project config for "${e.projectId}"`), t !== x && l.warn(`using custom API URL: ${t}`);
599
- const r = T("vite-plugin", P()), i = performance.now(), o = await F(t, e.projectId, r), a = (performance.now() - i).toFixed(0);
600
- if (!o) {
1022
+ l.banner(), l.info(`fetching project config for "${e.projectId}"`), t !== k && l.warn(`using custom API URL: ${t}`);
1023
+ const n = R("vite-plugin", K()), o = performance.now(), i = await N(t, e.projectId, n), a = (performance.now() - o).toFixed(0);
1024
+ if (!i) {
601
1025
  l.warn(`failed to fetch project config for "${e.projectId}" (${a}ms)`);
602
1026
  return;
603
1027
  }
604
- n = o.features;
605
- const d = o.features.length, u = o.features.filter(($) => $.enabled).length, f = JSON.stringify(o).length;
1028
+ r = i.features;
1029
+ const d = i.features.length, u = i.features.filter((U) => U.enabled).length, f = JSON.stringify(i).length;
606
1030
  return l.info(
607
1031
  `fetched ${d.toString()} features (${u.toString()} enabled) for "${e.projectId}" in ${a}ms`
608
- ), H(o.features), l.debug(`config size: ${f.toString()} bytes`), {
1032
+ ), F(i.features), l.debug(`config size: ${f.toString()} bytes`), {
609
1033
  define: {
610
- [Y]: JSON.stringify(o)
1034
+ [G]: JSON.stringify(i)
611
1035
  }
612
1036
  };
613
1037
  },
614
- configureServer(r) {
1038
+ configureServer(n) {
615
1039
  if (e.disableLauncher) return;
616
- r.middlewares.use(O(() => v(n)));
617
- const i = r.printUrls.bind(r);
618
- r.printUrls = () => {
619
- const o = r.resolvedUrls?.local[0];
620
- if (o) {
621
- const a = o.replace(
1040
+ n.middlewares.use(B(() => b(r)));
1041
+ const o = n.printUrls.bind(n);
1042
+ n.printUrls = () => {
1043
+ const i = n.resolvedUrls?.local[0];
1044
+ if (i) {
1045
+ const a = i.replace(
622
1046
  /:(?<port>\d+)\//,
623
1047
  (d, u) => `:\x1B[1m${u}\x1B[22m/`
624
1048
  );
625
1049
  console.log(` \x1B[32m➜\x1B[0m \x1B[1mPicked\x1B[22m: \x1B[36m${a}\x1B[0m`);
626
1050
  }
627
- i();
1051
+ o();
628
1052
  };
629
1053
  },
630
1054
  generateBundle() {
631
1055
  e.disableLauncher || this.emitFile({
632
1056
  type: "asset",
633
1057
  fileName: "index.html",
634
- source: v(n)
1058
+ source: b(r)
635
1059
  });
636
1060
  }
637
1061
  };
638
1062
  }
639
1063
  export {
640
- j as picked
1064
+ q as picked
641
1065
  };
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@picked/vite-plugin-picked",
3
3
  "description": "Vite plugin for build-time config injection",
4
- "version": "0.0.1-dev.1772493269328",
4
+ "version": "0.0.1-dev.1773363643396",
5
5
  "dependencies": {
6
- "@picked/client": "0.0.1-dev.1772493269328"
6
+ "@picked/client": "0.0.1-dev.1773363643396"
7
7
  },
8
8
  "devDependencies": {
9
9
  "@repo/eslint-config": "workspace:*",
@@ -56,7 +56,7 @@
56
56
  "dev": "vite build --watch",
57
57
  "jscpd": "jscpd src",
58
58
  "knip": "knip",
59
- "lint": "eslint .",
59
+ "lint": "if [ \"$AGENT\" = \"true\" ]; then echo \"[AGENT HINT] Prefer running lint on specific files from the repo root: node scripts/lint-files.js <files>\"; fi && eslint .",
60
60
  "lint-files": "eslint",
61
61
  "lint:format": "eslint . --fix",
62
62
  "lint:report": "eslint . -o './.reports/eslint.json' -f json || true",