@picked/vite-plugin-picked 0.0.1-dev.1785826066660 → 0.0.1-dev.1785972867484

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/esm/index.js CHANGED
@@ -1,28 +1,28 @@
1
1
  import { existsSync as e } from "node:fs";
2
- import { createClientHeaders as t, fetchExperienceContent as n, fetchProject as r } from "@picked/client/plugins/dynamic-experiences";
3
- import { appendFile as i, mkdir as a, readFile as o, writeFile as s } from "node:fs/promises";
4
- import { join as c } from "node:path";
2
+ import { join as t, resolve as n } from "node:path";
3
+ import { createClientHeaders as r, fetchExperienceContent as i, fetchProject as a } from "@picked/client/plugins/dynamic-experiences";
4
+ import { appendFile as o, mkdir as s, readFile as c, writeFile as l } from "node:fs/promises";
5
5
  //#region \0@oxc-project+runtime@0.142.0/helpers/esm/taggedTemplateLiteral.js
6
- function l(e, t) {
6
+ function u(e, t) {
7
7
  return t ||= e.slice(0), Object.freeze(Object.defineProperties(e, { raw: { value: Object.freeze(t) } }));
8
8
  }
9
9
  //#endregion
10
10
  //#region src/launcher.ts
11
- var u;
12
- function d(e) {
11
+ var d;
12
+ function f(e) {
13
13
  let t = JSON.stringify(e), n = e.length > 0 ? e.map((e) => `
14
14
  <div class="feature-row">
15
15
  <label>
16
- <input type="checkbox" data-feature-id="${p(e.id)}" checked>
17
- <span class="feature-name">${f(e.name)}</span>
18
- <span class="feature-id">${f(e.id)}</span>
16
+ <input type="checkbox" data-feature-id="${m(e.id)}" checked>
17
+ <span class="feature-name">${p(e.name)}</span>
18
+ <span class="feature-id">${p(e.id)}</span>
19
19
  </label>
20
- <select data-value-for="${p(e.id)}">
20
+ <select data-value-for="${m(e.id)}">
21
21
  <option value="true" selected>true</option>
22
22
  <option value="false">false</option>
23
23
  </select>
24
24
  </div>`).join("") : "<p class=\"text no-features\">No features configured for this project.</p>";
25
- return String.raw(u ||= l([
25
+ return String.raw(d ||= u([
26
26
  "<!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 <meta name=\"robots\" content=\"noindex, nofollow\">\n <title>Picked</title>\n <style>\n main {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n display: grid;\n align-items: center;\n justify-content: center;\n font-family: monospace;\n color: #4A4A4A\n }\n\n .wrap {\n padding-left: 1.5rem;\n padding-right: 1.5rem;\n max-width: 480px;\n width: 100%;\n }\n\n .title {\n font-size: 1.125rem;\n font-weight: 700;\n margin-bottom: 0;\n }\n\n .text {\n margin-top: .5rem;\n font-size: .875rem\n }\n\n .text a {\n color: #4A4A4A;\n text-decoration: none;\n }\n\n .text a:hover {\n cursor: pointer;\n text-decoration: underline\n }\n\n .preview-form {\n margin-top: 2rem;\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n }\n\n .preview-input {\n padding: 0.5rem;\n border: 1px solid #4A4A4A;\n border-radius: 0;\n font-family: monospace;\n }\n\n .preview-button {\n padding: 0.5rem;\n background: #4A4A4A;\n color: white;\n border: none;\n border-radius: 0;\n cursor: pointer;\n font-family: monospace;\n }\n\n .preview-button:hover {\n opacity: 0.9;\n }\n\n .buttons {\n display: grid;\n gap: 0.5em;\n grid-template-columns: 1fr 1fr;\n }\n\n #copy-status {\n font-size: 1em;\n text-align: right;\n margin-top: 0.5em;\n }\n\n .features-section {\n margin-top: 1.5rem;\n }\n\n .features-label {\n font-weight: 700;\n font-size: .875rem;\n margin-bottom: 0.5rem;\n }\n\n .feature-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 0.5rem;\n padding: 0.25rem 0;\n }\n\n .feature-row label {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n cursor: pointer;\n min-width: 0;\n flex: 1;\n }\n\n .feature-name {\n font-size: .875rem;\n }\n\n .feature-id {\n font-size: .75rem;\n color: #888;\n }\n\n .feature-row select {\n font-family: monospace;\n font-size: .75rem;\n padding: 0.125rem 0.25rem;\n border: 1px solid #4A4A4A;\n border-radius: 0;\n background: white;\n flex-shrink: 0;\n }\n\n .no-features {\n color: #888;\n font-style: italic;\n }\n\n .url-history {\n margin-top: 0.5rem;\n font-size: .75rem;\n }\n\n .url-history-item {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n padding: 0.125rem 0;\n }\n\n .url-history-item button {\n background: none;\n border: none;\n cursor: pointer;\n font-family: monospace;\n font-size: .75rem;\n color: #888;\n padding: 0;\n }\n\n .url-history-item button.url-link {\n color: #4A4A4A;\n text-decoration: none;\n text-align: left;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n flex: 1;\n min-width: 0;\n }\n\n .url-history-item button.url-link:hover {\n text-decoration: underline;\n }\n\n .url-history-item button.url-delete:hover {\n color: #b71c1c;\n }\n\n @media (min-width: 640px) {\n .title {\n font-size: 1.25rem\n }\n\n .text {\n font-size: 1rem\n }\n }\n </style>\n</head>\n<body>\n\n<main>\n <div class=\"wrap\">\n <p class=\"title\">Picked</p>\n <p class=\"text\">\n Learn more at\n <a href=\"https://picked.app\">\n https://picked.app\n </a>\n </p>\n <div class=\"preview-form\">\n <input type=\"text\" id=\"url-input\" pattern=\"^(https?://)?.+\" placeholder=\"Enter preview URL\" required\n class=\"preview-input\">\n <div id=\"url-history\" class=\"url-history\"></div>\n <div class=\"features-section\">\n <p class=\"features-label\">Features</p>\n ",
27
27
  "\n </div>\n <div class=\"buttons\">\n <button type=\"button\" class=\"preview-button\" id=\"copy-btn\">Copy</button>\n <button type=\"button\" class=\"preview-button\" id=\"preview-btn\">Preview</button>\n </div>\n <p class=\"text\" id=\"copy-status\" aria-live=\"polite\" style=\"visibility:hidden;\">\n &nbsp;\n </p>\n </div>\n </div>\n\n <script>\n var FEATURES = ",
28
28
  ";\n var STORAGE_KEY_URL = 'picked-launcher-url';\n var STORAGE_KEY_HISTORY = 'picked-launcher-history';\n var STORAGE_KEY_SELECTIONS = 'picked-launcher-selections';\n\n function getUrlInput() {\n return document.getElementById('url-input');\n }\n\n // URL history\n function getHistory() {\n try {\n var raw = localStorage.getItem(STORAGE_KEY_HISTORY);\n if (!raw) return [];\n var parsed = JSON.parse(raw);\n return Array.isArray(parsed) ? parsed : [];\n } catch (e) {\n return [];\n }\n }\n\n function saveHistory(history) {\n localStorage.setItem(STORAGE_KEY_HISTORY, JSON.stringify(history));\n }\n\n function addToHistory(url) {\n var history = getHistory().filter(function(h) { return h !== url; });\n history.unshift(url);\n if (history.length > 10) history = history.slice(0, 10);\n saveHistory(history);\n renderHistory();\n }\n\n function removeFromHistory(url) {\n var history = getHistory().filter(function(h) { return h !== url; });\n saveHistory(history);\n renderHistory();\n }\n\n function renderHistory() {\n var container = document.getElementById('url-history');\n if (!container) return;\n var history = getHistory();\n if (history.length === 0) {\n container.innerHTML = '';\n return;\n }\n container.innerHTML = history.map(function(url) {\n return '<div class=\"url-history-item\">' +\n '<button type=\"button\" class=\"url-link\" data-history-url=\"' + escapeAttr(url) + '\">' + escapeHtml(url) + '</button>' +\n '<button type=\"button\" class=\"url-delete\" data-history-delete=\"' + escapeAttr(url) + '\">x</button>' +\n '</div>';\n }).join('');\n }\n\n // Feature selection persistence\n function getSelections() {\n try {\n var raw = localStorage.getItem(STORAGE_KEY_SELECTIONS);\n if (!raw) return {};\n var parsed = JSON.parse(raw);\n return typeof parsed === 'object' && parsed !== null ? parsed : {};\n } catch (e) {\n return {};\n }\n }\n\n function saveSelections() {\n var selections = {};\n FEATURES.forEach(function(f) {\n var checkbox = document.querySelector('input[data-feature-id=\"' + f.id + '\"]');\n var select = document.querySelector('select[data-value-for=\"' + f.id + '\"]');\n if (checkbox && select) {\n selections[f.id] = { checked: checkbox.checked, value: select.value };\n }\n });\n localStorage.setItem(STORAGE_KEY_SELECTIONS, JSON.stringify(selections));\n }\n\n function restoreSelections() {\n var selections = getSelections();\n FEATURES.forEach(function(f) {\n var saved = selections[f.id];\n if (!saved) return;\n var checkbox = document.querySelector('input[data-feature-id=\"' + f.id + '\"]');\n var select = document.querySelector('select[data-value-for=\"' + f.id + '\"]');\n if (checkbox) checkbox.checked = saved.checked;\n if (select) select.value = saved.value;\n });\n }\n\n function escapeHtml(str) {\n var div = document.createElement('div');\n div.textContent = str;\n return div.innerHTML;\n }\n\n function escapeAttr(str) {\n return str.replace(/&/g, '&amp;').replace(/\"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n }\n\n function buildTargetUrl(inputValue) {\n var value = inputValue;\n if (!value.startsWith('http://') && !value.startsWith('https://')) {\n value = 'https://' + value;\n }\n var hostname = window.location.hostname;\n var subdomain = hostname.split('.').length > 2 ? hostname.split('.')[0] : '';\n var target = value;\n var sep = target.includes('?') ? '&' : '?';\n if (subdomain) {\n target = target + sep + 'cvly_env=' + encodeURIComponent(subdomain);\n sep = '&';\n }\n FEATURES.forEach(function(f) {\n var checkbox = document.querySelector('input[data-feature-id=\"' + f.id + '\"]');\n var select = document.querySelector('select[data-value-for=\"' + f.id + '\"]');\n if (checkbox && checkbox.checked && select) {\n target = target + sep + 'picked-feature=' + encodeURIComponent(f.id + ':' + select.value);\n sep = '&';\n }\n });\n return target;\n }\n\n function showCopyStatus(message, success) {\n var el = document.getElementById('copy-status');\n if (!el) return;\n el.textContent = message;\n el.style.visibility = 'visible';\n el.style.color = success ? '#2e7d32' : '#b71c1c';\n setTimeout(function() {\n el.style.visibility = 'hidden';\n }, 2000);\n }\n\n // Init\n window.addEventListener('load', function() {\n var input = getUrlInput();\n var savedUrl = localStorage.getItem(STORAGE_KEY_URL);\n if (savedUrl && input) {\n input.value = savedUrl;\n }\n renderHistory();\n restoreSelections();\n });\n\n // Delegate click events\n document.addEventListener('click', function(e) {\n var target = e.target;\n\n // History URL click\n var historyUrl = target.getAttribute('data-history-url');\n if (historyUrl) {\n var input = getUrlInput();\n if (input) input.value = historyUrl;\n return;\n }\n\n // History delete click\n var deleteUrl = target.getAttribute('data-history-delete');\n if (deleteUrl) {\n removeFromHistory(deleteUrl);\n return;\n }\n });\n\n // Feature change persistence\n document.addEventListener('change', function(e) {\n var target = e.target;\n if (target.getAttribute('data-feature-id') || target.getAttribute('data-value-for')) {\n saveSelections();\n }\n });\n\n // Copy button\n document.getElementById('copy-btn').addEventListener('click', function() {\n var input = getUrlInput();\n if (!input || !input.value) return;\n localStorage.setItem(STORAGE_KEY_URL, input.value);\n addToHistory(input.value);\n saveSelections();\n var target = buildTargetUrl(input.value);\n navigator.clipboard.writeText(target).then(function() {\n showCopyStatus('Preview URL copied to clipboard', true);\n });\n });\n\n // Preview button\n document.getElementById('preview-btn').addEventListener('click', function() {\n var input = getUrlInput();\n if (!input || !input.value) return;\n localStorage.setItem(STORAGE_KEY_URL, input.value);\n addToHistory(input.value);\n saveSelections();\n var target = buildTargetUrl(input.value);\n window.location.href = target;\n });\n <\/script>\n</main>\n</body>\n</html>"
@@ -32,46 +32,46 @@ function d(e) {
32
32
  ";\n var STORAGE_KEY_URL = 'picked-launcher-url';\n var STORAGE_KEY_HISTORY = 'picked-launcher-history';\n var STORAGE_KEY_SELECTIONS = 'picked-launcher-selections';\n\n function getUrlInput() {\n return document.getElementById('url-input');\n }\n\n // URL history\n function getHistory() {\n try {\n var raw = localStorage.getItem(STORAGE_KEY_HISTORY);\n if (!raw) return [];\n var parsed = JSON.parse(raw);\n return Array.isArray(parsed) ? parsed : [];\n } catch (e) {\n return [];\n }\n }\n\n function saveHistory(history) {\n localStorage.setItem(STORAGE_KEY_HISTORY, JSON.stringify(history));\n }\n\n function addToHistory(url) {\n var history = getHistory().filter(function(h) { return h !== url; });\n history.unshift(url);\n if (history.length > 10) history = history.slice(0, 10);\n saveHistory(history);\n renderHistory();\n }\n\n function removeFromHistory(url) {\n var history = getHistory().filter(function(h) { return h !== url; });\n saveHistory(history);\n renderHistory();\n }\n\n function renderHistory() {\n var container = document.getElementById('url-history');\n if (!container) return;\n var history = getHistory();\n if (history.length === 0) {\n container.innerHTML = '';\n return;\n }\n container.innerHTML = history.map(function(url) {\n return '<div class=\"url-history-item\">' +\n '<button type=\"button\" class=\"url-link\" data-history-url=\"' + escapeAttr(url) + '\">' + escapeHtml(url) + '</button>' +\n '<button type=\"button\" class=\"url-delete\" data-history-delete=\"' + escapeAttr(url) + '\">x</button>' +\n '</div>';\n }).join('');\n }\n\n // Feature selection persistence\n function getSelections() {\n try {\n var raw = localStorage.getItem(STORAGE_KEY_SELECTIONS);\n if (!raw) return {};\n var parsed = JSON.parse(raw);\n return typeof parsed === 'object' && parsed !== null ? parsed : {};\n } catch (e) {\n return {};\n }\n }\n\n function saveSelections() {\n var selections = {};\n FEATURES.forEach(function(f) {\n var checkbox = document.querySelector('input[data-feature-id=\"' + f.id + '\"]');\n var select = document.querySelector('select[data-value-for=\"' + f.id + '\"]');\n if (checkbox && select) {\n selections[f.id] = { checked: checkbox.checked, value: select.value };\n }\n });\n localStorage.setItem(STORAGE_KEY_SELECTIONS, JSON.stringify(selections));\n }\n\n function restoreSelections() {\n var selections = getSelections();\n FEATURES.forEach(function(f) {\n var saved = selections[f.id];\n if (!saved) return;\n var checkbox = document.querySelector('input[data-feature-id=\"' + f.id + '\"]');\n var select = document.querySelector('select[data-value-for=\"' + f.id + '\"]');\n if (checkbox) checkbox.checked = saved.checked;\n if (select) select.value = saved.value;\n });\n }\n\n function escapeHtml(str) {\n var div = document.createElement('div');\n div.textContent = str;\n return div.innerHTML;\n }\n\n function escapeAttr(str) {\n return str.replace(/&/g, '&amp;').replace(/\"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n }\n\n function buildTargetUrl(inputValue) {\n var value = inputValue;\n if (!value.startsWith('http://') && !value.startsWith('https://')) {\n value = 'https://' + value;\n }\n var hostname = window.location.hostname;\n var subdomain = hostname.split('.').length > 2 ? hostname.split('.')[0] : '';\n var target = value;\n var sep = target.includes('?') ? '&' : '?';\n if (subdomain) {\n target = target + sep + 'cvly_env=' + encodeURIComponent(subdomain);\n sep = '&';\n }\n FEATURES.forEach(function(f) {\n var checkbox = document.querySelector('input[data-feature-id=\"' + f.id + '\"]');\n var select = document.querySelector('select[data-value-for=\"' + f.id + '\"]');\n if (checkbox && checkbox.checked && select) {\n target = target + sep + 'picked-feature=' + encodeURIComponent(f.id + ':' + select.value);\n sep = '&';\n }\n });\n return target;\n }\n\n function showCopyStatus(message, success) {\n var el = document.getElementById('copy-status');\n if (!el) return;\n el.textContent = message;\n el.style.visibility = 'visible';\n el.style.color = success ? '#2e7d32' : '#b71c1c';\n setTimeout(function() {\n el.style.visibility = 'hidden';\n }, 2000);\n }\n\n // Init\n window.addEventListener('load', function() {\n var input = getUrlInput();\n var savedUrl = localStorage.getItem(STORAGE_KEY_URL);\n if (savedUrl && input) {\n input.value = savedUrl;\n }\n renderHistory();\n restoreSelections();\n });\n\n // Delegate click events\n document.addEventListener('click', function(e) {\n var target = e.target;\n\n // History URL click\n var historyUrl = target.getAttribute('data-history-url');\n if (historyUrl) {\n var input = getUrlInput();\n if (input) input.value = historyUrl;\n return;\n }\n\n // History delete click\n var deleteUrl = target.getAttribute('data-history-delete');\n if (deleteUrl) {\n removeFromHistory(deleteUrl);\n return;\n }\n });\n\n // Feature change persistence\n document.addEventListener('change', function(e) {\n var target = e.target;\n if (target.getAttribute('data-feature-id') || target.getAttribute('data-value-for')) {\n saveSelections();\n }\n });\n\n // Copy button\n document.getElementById('copy-btn').addEventListener('click', function() {\n var input = getUrlInput();\n if (!input || !input.value) return;\n localStorage.setItem(STORAGE_KEY_URL, input.value);\n addToHistory(input.value);\n saveSelections();\n var target = buildTargetUrl(input.value);\n navigator.clipboard.writeText(target).then(function() {\n showCopyStatus('Preview URL copied to clipboard', true);\n });\n });\n\n // Preview button\n document.getElementById('preview-btn').addEventListener('click', function() {\n var input = getUrlInput();\n if (!input || !input.value) return;\n localStorage.setItem(STORAGE_KEY_URL, input.value);\n addToHistory(input.value);\n saveSelections();\n var target = buildTargetUrl(input.value);\n window.location.href = target;\n });\n <\/script>\n</main>\n</body>\n</html>"
33
33
  ]), n, t);
34
34
  }
35
- function f(e) {
35
+ function p(e) {
36
36
  return e.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("\"", "&quot;");
37
37
  }
38
- function p(e) {
38
+ function m(e) {
39
39
  return e.replaceAll("&", "&amp;").replaceAll("\"", "&quot;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
40
40
  }
41
41
  //#endregion
42
42
  //#region src/log.ts
43
- var m = "picked", ee = "\x1B[0m";
43
+ var h = "picked", ee = "\x1B[0m";
44
44
  function te() {
45
45
  let e = process.env.NO_COLOR;
46
46
  return e === "1" || e === "true";
47
47
  }
48
- function h(e) {
48
+ function g(e) {
49
49
  return (t) => te() ? t : `${e}${t}${ee}`;
50
50
  }
51
- var g = [
51
+ var _ = [
52
52
  "debug",
53
53
  "info",
54
54
  "warn",
55
55
  "error",
56
56
  "silent"
57
- ], _ = {
57
+ ], v = {
58
58
  debug: {
59
- color: h("\x1B[2m"),
59
+ color: g("\x1B[2m"),
60
60
  log: console.debug,
61
61
  enabled: !1
62
62
  },
63
63
  info: {
64
- color: h("\x1B[36m"),
64
+ color: g("\x1B[36m"),
65
65
  log: console.log,
66
66
  enabled: !0
67
67
  },
68
68
  warn: {
69
- color: h("\x1B[33m"),
69
+ color: g("\x1B[33m"),
70
70
  log: console.warn,
71
71
  enabled: !0
72
72
  },
73
73
  error: {
74
- color: h("\x1B[31m"),
74
+ color: g("\x1B[31m"),
75
75
  log: console.error,
76
76
  enabled: !0
77
77
  },
@@ -80,16 +80,16 @@ var g = [
80
80
  enabled: !1
81
81
  }
82
82
  };
83
- function v(e, t) {
84
- return `${(/* @__PURE__ */ new Date()).toLocaleTimeString()} [${t ? `${m}:${t}` : m}] ${e}`;
83
+ function ne(e, t) {
84
+ return `${(/* @__PURE__ */ new Date()).toLocaleTimeString()} [${t ? `${h}:${t}` : h}] ${e}`;
85
85
  }
86
86
  function y(e, t, n, r) {
87
87
  if (!e.enabled) return;
88
- let i = v(t, r);
88
+ let i = ne(t, r);
89
89
  e.log(e.color ? e.color(i) : i), n !== void 0 && e.log(n);
90
90
  }
91
91
  function b(e) {
92
- let t = _[e], n = /* @__PURE__ */ new Set();
92
+ let t = v[e], n = /* @__PURE__ */ new Set();
93
93
  return Object.assign((e, n, r) => {
94
94
  y(t, e, n, r);
95
95
  }, { once(e, r, i) {
@@ -97,15 +97,15 @@ function b(e) {
97
97
  } });
98
98
  }
99
99
  function x(e) {
100
- let t = g.indexOf(e);
100
+ let t = _.indexOf(e);
101
101
  if (t === -1) {
102
- y(_.error, `invalid log level: ${e}`);
102
+ y(v.error, `invalid log level: ${e}`);
103
103
  return;
104
104
  }
105
- for (let [e, n] of g.entries()) _[n].enabled = e >= t;
105
+ for (let [e, n] of _.entries()) v[n].enabled = e >= t;
106
106
  }
107
- var S = h("\x1B[34m"), C = h("\x1B[36m");
108
- function w() {
107
+ var S = g("\x1B[34m"), C = g("\x1B[36m");
108
+ function re() {
109
109
  let e = [
110
110
  ` ${S("_")} ${C("_")} _ _ _`,
111
111
  `${S("(_)")} ${C("(_)")} _ __(_)__| |_____ __| |`,
@@ -115,8 +115,8 @@ function w() {
115
115
  ];
116
116
  console.log(e.join("\n"));
117
117
  }
118
- var T = {
119
- banner: w,
118
+ var w = {
119
+ banner: re,
120
120
  debug: b("debug"),
121
121
  info: b("info"),
122
122
  warn: b("warn"),
@@ -125,7 +125,7 @@ var T = {
125
125
  };
126
126
  //#endregion
127
127
  //#region src/middleware.ts
128
- function E(e) {
128
+ function T(e) {
129
129
  return (t, n, r) => {
130
130
  if (t.method !== "GET") {
131
131
  r();
@@ -142,27 +142,27 @@ function E(e) {
142
142
  }
143
143
  //#endregion
144
144
  //#region src/gitignore.ts
145
- var D = ".picked/";
146
- async function ne(t, n) {
147
- if (n) return;
148
- let r = c(t, ".gitignore");
149
- if (!e(r)) {
150
- await s(r, `${D}
145
+ var E = ".picked/";
146
+ async function D(n, r) {
147
+ if (r) return;
148
+ let i = t(n, ".gitignore");
149
+ if (!e(i)) {
150
+ await l(i, `${E}
151
151
  `);
152
152
  return;
153
153
  }
154
- let a = await o(r, "utf8");
155
- if (re(a)) return;
156
- let l = `${a.length > 0 && !a.endsWith("\n") ? "\n" : ""}${D}
154
+ let a = await c(i, "utf8");
155
+ if (O(a)) return;
156
+ let s = `${a.length > 0 && !a.endsWith("\n") ? "\n" : ""}${E}
157
157
  `;
158
- await i(r, l);
158
+ await o(i, s);
159
159
  }
160
- function re(e) {
161
- return e.split(/\r?\n/).map((e) => e.trim()).some((e) => e === D || e === ".picked");
160
+ function O(e) {
161
+ return e.split(/\r?\n/).map((e) => e.trim()).some((e) => e === E || e === ".picked");
162
162
  }
163
163
  //#endregion
164
164
  //#region src/retry.ts
165
- var O = 6, k = 5e3;
165
+ var k = 6, ie = 5e3;
166
166
  function A(e) {
167
167
  let t;
168
168
  try {
@@ -172,12 +172,12 @@ function A(e) {
172
172
  }
173
173
  return t === "localhost" || t === "127.0.0.1" || t === "::1" || t === "[::1]" || t !== "api.picked.app" && t.endsWith(".picked.app");
174
174
  }
175
- function j(e) {
175
+ function ae(e) {
176
176
  return new Promise((t) => {
177
177
  setTimeout(t, e);
178
178
  });
179
179
  }
180
- async function M(e, t) {
180
+ async function j(e, t) {
181
181
  let n = null, r = null;
182
182
  try {
183
183
  n = await e();
@@ -185,9 +185,9 @@ async function M(e, t) {
185
185
  r = e;
186
186
  }
187
187
  if (n !== null) return n;
188
- for (let i = 1; i <= O; i++) {
189
- let a = k * 2 ** (i - 1);
190
- t(i, O, a), await j(a), r = null;
188
+ for (let i = 1; i <= k; i++) {
189
+ let a = ie * 2 ** (i - 1);
190
+ t(i, k, a), await ae(a), r = null;
191
191
  try {
192
192
  n = await e();
193
193
  } catch (e) {
@@ -200,102 +200,105 @@ async function M(e, t) {
200
200
  }
201
201
  //#endregion
202
202
  //#region src/util.ts
203
- function N(e) {
203
+ function M(e) {
204
204
  return Array.isArray(e) ? e : [];
205
205
  }
206
206
  //#endregion
207
207
  //#region src/prefetch.ts
208
- var P = 2;
209
- function F(e) {
210
- let t = c(e, ".picked");
208
+ var N = 1;
209
+ function P(e) {
210
+ let n = t(e, ".picked");
211
211
  return {
212
- pickedDir: t,
213
- manifestPath: c(t, "manifest.json"),
214
- projectConfigPath: c(t, "project-config.json"),
215
- experiencesDir: c(t, "experiences")
212
+ pickedDir: n,
213
+ manifestPath: t(n, "manifest.json"),
214
+ projectConfigPath: t(n, "project-config.json"),
215
+ experiencesDir: t(n, "experiences")
216
216
  };
217
217
  }
218
- async function I(t) {
218
+ async function F(t) {
219
219
  if (!e(t)) return null;
220
220
  try {
221
- let e = await o(t, "utf8"), n = JSON.parse(e);
222
- return L(n) ? n : null;
221
+ let e = await c(t, "utf8"), n = JSON.parse(e);
222
+ return I(n) ? n : null;
223
223
  } catch {
224
224
  return null;
225
225
  }
226
226
  }
227
- function L(e) {
227
+ function I(e) {
228
228
  return !(typeof e != "object" || !e || !("version" in e) || typeof e.version != "number" || !("projectVersionId" in e) || typeof e.projectVersionId != "string" || !("workspaceId" in e) || typeof e.workspaceId != "string" || !("experiences" in e) || !Array.isArray(e.experiences));
229
229
  }
230
- function R(e) {
230
+ function L(e) {
231
231
  let t = /* @__PURE__ */ new Set();
232
- for (let n of N(e.steps)) n.layoutContentId && t.add(n.id);
232
+ for (let n of M(e.steps)) n.layoutContentId && t.add(n.id);
233
233
  if (t.size === 0) return [];
234
234
  let n = [];
235
- for (let r of N(e.experiences)) N(r.nodes).some((e) => e.type === "step" && t.has(e.stepId)) && n.push(r.id);
235
+ for (let r of M(e.experiences)) M(r.nodes).some((e) => e.type === "step" && t.has(e.stepId)) && n.push(r.id);
236
236
  return n;
237
237
  }
238
- async function z(e) {
239
- let { apiUrl: t, projectId: n, projectRoot: r, headers: i, reuseWhenUnchanged: o = !0 } = e, l = F(r), u = await V(t, n, i), d = R(u);
240
- if (o) {
241
- let e = await I(l.manifestPath);
242
- if (e && e.version === P && e.projectVersionId === u.versionId && e.workspaceId === u.workspaceId) return {
243
- config: u,
244
- manifest: e,
245
- experienceContentPaths: B(l, d)
246
- };
238
+ async function R(n) {
239
+ let { apiUrl: r, projectId: i, projectRoot: a, headers: o, reuseWhenUnchanged: c = !0 } = n, u = P(a), d = await B(r, i, o), f = L(d);
240
+ if (await s(u.experiencesDir, { recursive: !0 }), await l(u.projectConfigPath, JSON.stringify(d, null, 2)), c) {
241
+ let t = await F(u.manifestPath);
242
+ if (t && t.projectVersionId === d.versionId && t.workspaceId === d.workspaceId) {
243
+ let n = z(u, f);
244
+ if (Object.values(n).every((t) => e(t))) return {
245
+ config: d,
246
+ manifest: t,
247
+ experienceContentPaths: n
248
+ };
249
+ w.info("a manifest-referenced content file is missing; refetching every experience");
250
+ }
247
251
  }
248
- await a(l.experiencesDir, { recursive: !0 }), await s(l.projectConfigPath, JSON.stringify(u, null, 2));
249
- let f = (/* @__PURE__ */ new Date()).toISOString(), p = [];
250
- for (let e of d) {
251
- let r = await H(t, n, e, i), a = c(l.experiencesDir, `${e}.json`);
252
- await s(a, JSON.stringify(r, null, 2)), p.push({
252
+ let p = (/* @__PURE__ */ new Date()).toISOString(), m = [];
253
+ for (let e of f) {
254
+ let n = await V(r, i, e, o), a = t(u.experiencesDir, `${e}.json`);
255
+ await l(a, JSON.stringify(n, null, 2)), m.push({
253
256
  id: e,
254
- fetchedAt: f
257
+ fetchedAt: p
255
258
  });
256
259
  }
257
- let m = {
258
- version: P,
259
- fetchedAt: f,
260
- projectVersionId: u.versionId,
261
- workspaceId: u.workspaceId,
262
- projectId: u.id,
263
- experiences: p
260
+ let h = {
261
+ version: N,
262
+ fetchedAt: p,
263
+ projectVersionId: d.versionId,
264
+ workspaceId: d.workspaceId,
265
+ projectId: d.id,
266
+ experiences: m
264
267
  };
265
- return await s(l.manifestPath, JSON.stringify(m, null, 2)), {
266
- config: u,
267
- manifest: m,
268
- experienceContentPaths: B(l, d)
268
+ return await l(u.manifestPath, JSON.stringify(h, null, 2)), {
269
+ config: d,
270
+ manifest: h,
271
+ experienceContentPaths: z(u, f)
269
272
  };
270
273
  }
271
- function B(e, t) {
272
- let n = {};
273
- for (let r of t) n[r] = c(e.experiencesDir, `${r}.json`);
274
- return n;
274
+ function z(e, n) {
275
+ let r = {};
276
+ for (let i of n) r[i] = t(e.experiencesDir, `${i}.json`);
277
+ return r;
275
278
  }
276
- async function V(e, t, n) {
277
- let i = () => r(e, t, { headers: n }), a;
279
+ async function B(e, t, n) {
280
+ let r = () => a(e, t, { headers: n }), i;
278
281
  try {
279
- a = A(e) ? await M(i, (e, t, n) => {
280
- T.info(`project config not ready, retrying in ${(n / 1e3).toString()}s (${e.toString()}/${t.toString()})`);
281
- }) : await i();
282
+ i = A(e) ? await j(r, (e, t, n) => {
283
+ w.info(`project config not ready, retrying in ${(n / 1e3).toString()}s (${e.toString()}/${t.toString()})`);
284
+ }) : await r();
282
285
  } catch (n) {
283
- throw Error(`[picked] Build-time fetch of project config failed for "${t}" at ${e}: ${U(n)}`);
286
+ throw Error(`[picked] Build-time fetch of project config failed for "${t}" at ${e}: ${H(n)}`);
284
287
  }
285
- if (!a) throw Error(`[picked] Build-time fetch of project config returned no usable response for "${t}" at ${e}. Confirm the API is reachable and the project ID is correct.`);
286
- return a;
288
+ if (!i) throw Error(`[picked] Build-time fetch of project config returned no usable response for "${t}" at ${e}. Confirm the API is reachable and the project ID is correct.`);
289
+ return i;
287
290
  }
288
- async function H(e, t, r, i) {
291
+ async function V(e, t, n, r) {
289
292
  let a;
290
293
  try {
291
- a = await n(e, t, r, { headers: i });
294
+ a = await i(e, t, n, { headers: r });
292
295
  } catch (t) {
293
- throw Error(`[picked] Build-time fetch of content for experience "${r}" failed at ${e}: ${U(t)}`);
296
+ throw Error(`[picked] Build-time fetch of content for experience "${n}" failed at ${e}: ${H(t)}`);
294
297
  }
295
- if (!a) throw Error(`[picked] Build-time fetch of content for experience "${r}" returned no usable response. Confirm the experience id exists and the API is reachable.`);
298
+ if (!a) throw Error(`[picked] Build-time fetch of content for experience "${n}" returned no usable response. Confirm the experience id exists and the API is reachable.`);
296
299
  return a;
297
300
  }
298
- function U(e) {
301
+ function H(e) {
299
302
  if (e instanceof Error) return e.message;
300
303
  if (typeof e == "string") return e;
301
304
  try {
@@ -306,7 +309,7 @@ function U(e) {
306
309
  }
307
310
  //#endregion
308
311
  //#region src/virtual-module/build.ts
309
- function W(e) {
312
+ function U(e) {
310
313
  let { projectConfigPath: t, experienceContentPaths: n, manifestMetadata: r } = e, i = (e) => JSON.stringify(e), a = Object.entries(n).map(([e, t]) => ` ${JSON.stringify(e)}: () => import(${i(t)}).then((m) => m.default ?? m),`).join("\n");
311
314
  return `import projectConfigJson from ${i(t)}
312
315
 
@@ -333,14 +336,14 @@ export const manifestMetadata = ${JSON.stringify(r)}
333
336
  }
334
337
  //#endregion
335
338
  //#region src/virtual-module/dev.ts
336
- function G(e) {
337
- let { apiUrl: t, projectId: n } = e;
338
- return `import { fetchProject, fetchExperienceContent } from '@picked/client/plugins/dynamic-experiences'
339
+ function W(e) {
340
+ let { apiUrl: t, projectId: n, projectConfig: r } = e, i = r ? "import { fetchExperienceContent } from '@picked/client/plugins/dynamic-experiences'" : "import { fetchProject, fetchExperienceContent } from '@picked/client/plugins/dynamic-experiences'", a = r ? `export const projectConfig = ${JSON.stringify(r)}` : "export const projectConfig = await fetchProject(apiUrl, projectId)";
341
+ return `${i}
339
342
 
340
343
  const apiUrl = ${JSON.stringify(t)}
341
344
  const projectId = ${JSON.stringify(n)}
342
345
 
343
- export const projectConfig = await fetchProject(apiUrl, projectId)
346
+ ${a}
344
347
 
345
348
  export async function experienceContent(experience, options) {
346
349
  const id = typeof experience === 'string' ? experience : experience?.id
@@ -358,10 +361,10 @@ export const manifestMetadata = {
358
361
  }
359
362
  //#endregion
360
363
  //#region src/index.ts
361
- var K = 5;
362
- function q(e, t, n) {
364
+ var G = 5;
365
+ function K(e, t, n) {
363
366
  if (t.length === 0) return;
364
- if (t.length > K) {
367
+ if (t.length > G) {
365
368
  console.log(`\n ${e}: ${t.length.toString()} loaded\n`);
366
369
  return;
367
370
  }
@@ -376,10 +379,10 @@ function q(e, t, n) {
376
379
  ""
377
380
  ].join("\n"));
378
381
  }
379
- function J(e, t) {
382
+ function q(e, t) {
380
383
  t.length !== 0 && console.log(`\n ${e}: ${t.length.toString()} loaded\n`);
381
384
  }
382
- var Y = [
385
+ var oe = [
383
386
  {
384
387
  header: "Name",
385
388
  value: (e) => e.name
@@ -400,7 +403,7 @@ var Y = [
400
403
  header: "Ver",
401
404
  value: (e) => `v${e.version.toString()}`
402
405
  }
403
- ], ie = [
406
+ ], se = [
404
407
  {
405
408
  header: "Name",
406
409
  value: (e) => e.name
@@ -421,7 +424,7 @@ var Y = [
421
424
  header: "Targets",
422
425
  value: (e) => e.targets.length.toString()
423
426
  }
424
- ], ae = [
427
+ ], ce = [
425
428
  {
426
429
  header: "Name",
427
430
  value: (e) => e.name
@@ -434,7 +437,7 @@ var Y = [
434
437
  header: "Fields",
435
438
  value: (e) => (e.fieldIds?.length ?? 0).toString()
436
439
  }
437
- ], oe = [
440
+ ], le = [
438
441
  {
439
442
  header: "Name",
440
443
  value: (e) => e.name
@@ -451,86 +454,144 @@ var Y = [
451
454
  header: "Required",
452
455
  value: (e) => e.required ? "yes" : "no"
453
456
  }
454
- ], se = [{
457
+ ], ue = [{
455
458
  header: "Name",
456
459
  value: (e) => e.name
457
460
  }, {
458
461
  header: "Key",
459
462
  value: (e) => e.key
460
463
  }];
461
- function ce() {
462
- return "0.0.1-dev.1785826066660";
463
- }
464
- var X = "https://api.picked.app", Z = "virtual:picked/data", Q = `\0${Z}`;
465
- function le(n) {
466
- let i = n.apiUrl ?? X, a = [], o = process.cwd(), s = "serve", c, l = !1;
464
+ function de() {
465
+ return "0.0.1-dev.1785972867484";
466
+ }
467
+ var J = "https://api.picked.app", Y = "virtual:picked/data", X = `\0${Y}`;
468
+ function Z(e) {
469
+ for (let t of Object.values(e)) if (t.type === "chunk" && t.moduleIds.includes(X)) return t.fileName;
470
+ }
471
+ function fe(e, t) {
472
+ return e === "" || e.endsWith("/") ? `${e}${t}` : `${e}/${t}`;
473
+ }
474
+ var Q = /* @__PURE__ */ new Map();
475
+ function pe(e, t, n) {
476
+ return JSON.stringify([
477
+ e,
478
+ t,
479
+ n
480
+ ]);
481
+ }
482
+ function me(t) {
483
+ let i = t.apiUrl ?? J, o = [], s = process.cwd(), c = "serve", l = "/", u, d, p = null;
467
484
  return {
468
485
  name: "picked",
469
- config: async (u, d) => {
470
- s = d.command, o = process.cwd(), T.banner(), i !== X && T.warn(`using custom API URL: ${i}`);
471
- let f = t("vite-plugin", ce());
472
- if (d.command === "build") {
473
- if (l) return;
474
- l = !0, T.info(`prefetching project config + content for "${n.projectId}"`);
475
- let t = F(o), r = e(t.pickedDir), s = performance.now(), u = await z({
476
- apiUrl: i,
477
- projectId: n.projectId,
478
- projectRoot: o,
479
- headers: f
480
- }), d = (performance.now() - s).toFixed(0);
481
- await ne(o, r);
482
- let p = u.config;
483
- a = N(p.features), $(p, d), c = W({
484
- projectConfigPath: t.projectConfigPath,
485
- experienceContentPaths: u.experienceContentPaths,
486
- manifestMetadata: {
487
- mode: "build",
488
- fetchedAt: u.manifest.fetchedAt,
489
- projectVersionId: u.manifest.projectVersionId,
490
- workspaceId: u.manifest.workspaceId
491
- }
492
- });
493
- } else {
494
- T.info(`fetching project config for "${n.projectId}" (dev)`);
495
- let e = performance.now(), t = () => r(i, n.projectId, { headers: f }), o = A(i) ? await M(t, (e, t, n) => {
496
- T.info(`local API not ready, retrying in ${(n / 1e3).toString()}s (${e.toString()}/${t.toString()})`);
497
- }) : await t(), s = (performance.now() - e).toFixed(0);
498
- o ? (a = N(o.features), $(o, s)) : T.warn(`failed to fetch project config for "${n.projectId}" (${s}ms)`);
486
+ config: async (l, f) => {
487
+ c = f.command, s = l.root === void 0 ? process.cwd() : n(process.cwd(), l.root), w.banner(), i !== J && w.warn(`using custom API URL: ${i}`);
488
+ let m = r("vite-plugin", de());
489
+ if (f.command === "build") {
490
+ let n = pe(i, t.projectId, s);
491
+ u = n;
492
+ let r = Q.get(n);
493
+ r === void 0 && (r = (async () => {
494
+ w.info(`prefetching project config + content for "${t.projectId}"`);
495
+ let n = P(s), r = e(n.pickedDir), a = performance.now(), o = await R({
496
+ apiUrl: i,
497
+ projectId: t.projectId,
498
+ projectRoot: s,
499
+ headers: m
500
+ }), c = (performance.now() - a).toFixed(0);
501
+ await D(s, r);
502
+ let l = o.config;
503
+ return $(l, c), {
504
+ virtualSource: U({
505
+ projectConfigPath: n.projectConfigPath,
506
+ experienceContentPaths: o.experienceContentPaths,
507
+ manifestMetadata: {
508
+ mode: "build",
509
+ fetchedAt: o.manifest.fetchedAt,
510
+ projectVersionId: o.manifest.projectVersionId,
511
+ workspaceId: o.manifest.workspaceId
512
+ }
513
+ }),
514
+ features: M(l.features)
515
+ };
516
+ })(), r.catch(() => Q.delete(n)), Q.set(n, r));
517
+ let a = await r;
518
+ d = a.virtualSource, o = a.features;
519
+ } else if (f.mode === "production") w.debug("skipping the dev project-config fetch for a production serve resolution");
520
+ else {
521
+ w.info(`fetching project config for "${t.projectId}" (dev)`);
522
+ let e = performance.now(), n = () => a(i, t.projectId, { headers: m }), r = A(i) ? await j(n, (e, t, n) => {
523
+ w.info(`local API not ready, retrying in ${(n / 1e3).toString()}s (${e.toString()}/${t.toString()})`);
524
+ }) : await n(), s = (performance.now() - e).toFixed(0);
525
+ p = r, r ? (o = M(r.features), $(r, s)) : w.warn(`failed to fetch project config for "${t.projectId}" (${s}ms)`);
526
+ }
527
+ },
528
+ configResolved(e) {
529
+ l = e.base;
530
+ },
531
+ closeBundle() {
532
+ u !== void 0 && Q.delete(u);
533
+ },
534
+ transformIndexHtml: {
535
+ order: "post",
536
+ handler(e, t) {
537
+ if (t.bundle === void 0) return;
538
+ let n = Z(t.bundle);
539
+ if (n === void 0) return;
540
+ let r = fe(l, n);
541
+ if (!e.includes(`"${r}"`)) return [{
542
+ tag: "link",
543
+ attrs: {
544
+ rel: "modulepreload",
545
+ crossorigin: !0,
546
+ href: r
547
+ },
548
+ injectTo: "head"
549
+ }];
499
550
  }
500
551
  },
501
552
  resolveId(e) {
502
- if (e === Z) return Q;
553
+ if (e === Y) return X;
503
554
  },
504
555
  load(e) {
505
- if (e === Q) return s === "build" ? c : G({
556
+ if (e === X) return c === "build" ? d : W({
506
557
  apiUrl: i,
507
- projectId: n.projectId
558
+ projectId: t.projectId,
559
+ projectConfig: p
508
560
  });
509
561
  },
510
562
  configureServer(e) {
511
- if (n.disableLauncher) return;
512
- e.middlewares.use(E(() => d(a)));
513
- let t = e.printUrls.bind(e);
563
+ if (t.disableLauncher) return;
564
+ e.middlewares.use(T(() => f(o)));
565
+ let n = e.printUrls.bind(e);
514
566
  e.printUrls = () => {
515
- let n = e.resolvedUrls?.local[0];
516
- if (n) {
517
- let e = n.replace(/:(?<port>\d+)\//, (e, t) => `:\x1b[1m${t}\x1b[22m/`);
567
+ let t = e.resolvedUrls?.local[0];
568
+ if (t) {
569
+ let e = t.replace(/:(?<port>\d+)\//, (e, t) => `:\x1b[1m${t}\x1b[22m/`);
518
570
  console.log(` \x1b[32m➜\x1b[0m \x1b[1mPicked\x1b[22m: \x1b[36m${e}\x1b[0m`);
519
571
  }
520
- t();
572
+ n();
521
573
  };
522
574
  },
523
- generateBundle() {
524
- n.disableLauncher || this.emitFile({
525
- type: "asset",
526
- fileName: "index.html",
527
- source: d(a)
528
- });
575
+ generateBundle: {
576
+ order: "post",
577
+ handler(e, n) {
578
+ if (!t.disableLauncher) {
579
+ if ("index.html" in n) {
580
+ w.debug("index.html came from the build; skipping the launcher page");
581
+ return;
582
+ }
583
+ this.emitFile({
584
+ type: "asset",
585
+ fileName: "index.html",
586
+ source: f(o)
587
+ });
588
+ }
589
+ }
529
590
  }
530
591
  };
531
592
  }
532
593
  function $(e, t) {
533
- let n = N(e.features), r = N(e.experiences), i = N(e.steps), a = N(e.fields), o = N(e.conditions), s = N(e.actions), c = JSON.stringify(e).length, l = [
594
+ let n = M(e.features), r = M(e.experiences), i = M(e.steps), a = M(e.fields), o = M(e.conditions), s = M(e.actions), c = JSON.stringify(e).length, l = [
534
595
  `${n.length.toString()} features`,
535
596
  `${r.length.toString()} experiences`,
536
597
  `${i.length.toString()} steps`,
@@ -538,7 +599,7 @@ function $(e, t) {
538
599
  `${o.length.toString()} conditions`,
539
600
  `${s.length.toString()} actions`
540
601
  ].join(", ");
541
- T.info(`fetched config in ${t}ms (${l})`), q("Features", n, Y), q("Experiences", r, ie), q("Steps", i, ae), q("Fields", a, oe), q("Conditions", o, se), J("Actions", s), T.debug(`config size: ${c.toString()} bytes`);
602
+ w.info(`fetched config in ${t}ms (${l})`), K("Features", n, oe), K("Experiences", r, se), K("Steps", i, ce), K("Fields", a, le), K("Conditions", o, ue), q("Actions", s), w.debug(`config size: ${c.toString()} bytes`);
542
603
  }
543
604
  //#endregion
544
- export { le as picked };
605
+ export { me as picked };