@picked/vite-plugin-picked 0.0.72-next.1 → 0.0.72-next.2

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,28 +142,28 @@ 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");
154
+ let a = await c(i, "utf8");
155
155
  if (O(a)) return;
156
- let l = `${a.length > 0 && !a.endsWith("\n") ? "\n" : ""}${D}
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
160
  function O(e) {
161
- return e.split(/\r?\n/).map((e) => e.trim()).some((e) => e === D || e === ".picked");
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 k = 6, A = 5e3;
166
- function j(e) {
165
+ var k = 6, ie = 5e3;
166
+ function A(e) {
167
167
  let t;
168
168
  try {
169
169
  t = new URL(e).hostname;
@@ -172,12 +172,12 @@ function j(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 re(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();
@@ -186,8 +186,8 @@ async function M(e, t) {
186
186
  }
187
187
  if (n !== null) return n;
188
188
  for (let i = 1; i <= k; i++) {
189
- let a = A * 2 ** (i - 1);
190
- t(i, k, a), await re(a), r = null;
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 = 1;
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.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 = j(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 {
@@ -305,10 +308,16 @@ function U(e) {
305
308
  }
306
309
  }
307
310
  //#endregion
311
+ //#region src/virtual-module/api.ts
312
+ function U() {
313
+ return "export const manifestMetadata = {\n mode: 'api',\n fetchedAt: null,\n projectVersionId: null,\n workspaceId: null,\n}\n";
314
+ }
315
+ //#endregion
308
316
  //#region src/virtual-module/build.ts
309
317
  function W(e) {
310
318
  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
- return `import projectConfigJson from ${i(t)}
319
+ return `import { registerPickedBundle } from '@picked/client/plugins/dynamic-experiences'
320
+ import projectConfigJson from ${i(t)}
312
321
 
313
322
  const experienceImporters = {
314
323
  ${a}
@@ -329,18 +338,20 @@ export async function experienceContent(experience, _options) {
329
338
  }
330
339
 
331
340
  export const manifestMetadata = ${JSON.stringify(r)}
341
+
342
+ registerPickedBundle({ projectConfig, experienceContent, manifestMetadata })
332
343
  `;
333
344
  }
334
345
  //#endregion
335
346
  //#region src/virtual-module/dev.ts
336
347
  function G(e) {
337
- let { apiUrl: t, projectId: n } = e;
338
- return `import { fetchProject, fetchExperienceContent } from '@picked/client/plugins/dynamic-experiences'
348
+ let { apiUrl: t, projectId: n, projectConfig: r } = e, i = r ? "import { fetchExperienceContent, registerPickedBundle } 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)", o = r ? "\nregisterPickedBundle({ projectConfig, experienceContent, manifestMetadata })\n" : "";
349
+ return `${i}
339
350
 
340
351
  const apiUrl = ${JSON.stringify(t)}
341
352
  const projectId = ${JSON.stringify(n)}
342
353
 
343
- export const projectConfig = await fetchProject(apiUrl, projectId)
354
+ ${a}
344
355
 
345
356
  export async function experienceContent(experience, options) {
346
357
  const id = typeof experience === 'string' ? experience : experience?.id
@@ -354,7 +365,7 @@ export const manifestMetadata = {
354
365
  projectVersionId: projectConfig?.versionId ?? null,
355
366
  workspaceId: projectConfig?.workspaceId ?? null,
356
367
  }
357
- `;
368
+ ${o}`;
358
369
  }
359
370
  //#endregion
360
371
  //#region src/index.ts
@@ -376,10 +387,10 @@ function q(e, t, n) {
376
387
  ""
377
388
  ].join("\n"));
378
389
  }
379
- function J(e, t) {
390
+ function oe(e, t) {
380
391
  t.length !== 0 && console.log(`\n ${e}: ${t.length.toString()} loaded\n`);
381
392
  }
382
- var Y = [
393
+ var se = [
383
394
  {
384
395
  header: "Name",
385
396
  value: (e) => e.name
@@ -400,7 +411,7 @@ var Y = [
400
411
  header: "Ver",
401
412
  value: (e) => `v${e.version.toString()}`
402
413
  }
403
- ], ie = [
414
+ ], ce = [
404
415
  {
405
416
  header: "Name",
406
417
  value: (e) => e.name
@@ -421,7 +432,7 @@ var Y = [
421
432
  header: "Targets",
422
433
  value: (e) => e.targets.length.toString()
423
434
  }
424
- ], ae = [
435
+ ], le = [
425
436
  {
426
437
  header: "Name",
427
438
  value: (e) => e.name
@@ -434,7 +445,7 @@ var Y = [
434
445
  header: "Fields",
435
446
  value: (e) => (e.fieldIds?.length ?? 0).toString()
436
447
  }
437
- ], oe = [
448
+ ], ue = [
438
449
  {
439
450
  header: "Name",
440
451
  value: (e) => e.name
@@ -451,86 +462,145 @@ var Y = [
451
462
  header: "Required",
452
463
  value: (e) => e.required ? "yes" : "no"
453
464
  }
454
- ], se = [{
465
+ ], de = [{
455
466
  header: "Name",
456
467
  value: (e) => e.name
457
468
  }, {
458
469
  header: "Key",
459
470
  value: (e) => e.key
460
471
  }];
461
- function ce() {
462
- return "0.0.72-next.1";
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;
472
+ function J() {
473
+ return "0.0.72-next.2";
474
+ }
475
+ var Y = "https://api.picked.app", X = "virtual:picked/data", Z = `\0${X}`;
476
+ function fe(e) {
477
+ for (let t of Object.values(e)) if (t.type === "chunk" && t.moduleIds.includes(Z)) return t.fileName;
478
+ }
479
+ function pe(e, t) {
480
+ return e === "" || e.endsWith("/") ? `${e}${t}` : `${e}/${t}`;
481
+ }
482
+ var Q = /* @__PURE__ */ new Map();
483
+ function me(e, t, n) {
484
+ return JSON.stringify([
485
+ e,
486
+ t,
487
+ n
488
+ ]);
489
+ }
490
+ function he(t) {
491
+ let i = t.apiUrl ?? Y, o = t.mode ?? "bundle", s = [], c = process.cwd(), l = "serve", u = "/", d, p, m = null;
467
492
  return {
468
493
  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 = j(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)`);
494
+ config: async (u, f) => {
495
+ l = f.command, c = u.root === void 0 ? process.cwd() : n(process.cwd(), u.root), w.banner(), i !== Y && w.warn(`using custom API URL: ${i}`);
496
+ let h = r("vite-plugin", J());
497
+ if (o === "api") w.debug("mode is 'api': skipping the project-config prefetch");
498
+ else if (f.command === "build") {
499
+ let n = me(i, t.projectId, c);
500
+ d = n;
501
+ let r = Q.get(n);
502
+ r === void 0 && (r = (async () => {
503
+ w.info(`prefetching project config + content for "${t.projectId}"`);
504
+ let n = P(c), r = e(n.pickedDir), a = performance.now(), o = await R({
505
+ apiUrl: i,
506
+ projectId: t.projectId,
507
+ projectRoot: c,
508
+ headers: h
509
+ }), s = (performance.now() - a).toFixed(0);
510
+ await D(c, r);
511
+ let l = o.config;
512
+ return $(l, s), {
513
+ virtualSource: W({
514
+ projectConfigPath: n.projectConfigPath,
515
+ experienceContentPaths: o.experienceContentPaths,
516
+ manifestMetadata: {
517
+ mode: "build",
518
+ fetchedAt: o.manifest.fetchedAt,
519
+ projectVersionId: o.manifest.projectVersionId,
520
+ workspaceId: o.manifest.workspaceId
521
+ }
522
+ }),
523
+ features: M(l.features)
524
+ };
525
+ })(), r.catch(() => Q.delete(n)), Q.set(n, r));
526
+ let a = await r;
527
+ p = a.virtualSource, s = a.features;
528
+ } else if (f.mode === "production") w.debug("skipping the dev project-config fetch for a production serve resolution");
529
+ else {
530
+ w.info(`fetching project config for "${t.projectId}" (dev)`);
531
+ let e = performance.now(), n = () => a(i, t.projectId, { headers: h }), r = A(i) ? await j(n, (e, t, n) => {
532
+ w.info(`local API not ready, retrying in ${(n / 1e3).toString()}s (${e.toString()}/${t.toString()})`);
533
+ }) : await n(), o = (performance.now() - e).toFixed(0);
534
+ m = r, r ? (s = M(r.features), $(r, o)) : w.warn(`failed to fetch project config for "${t.projectId}" (${o}ms)`);
535
+ }
536
+ },
537
+ configResolved(e) {
538
+ u = e.base;
539
+ },
540
+ closeBundle() {
541
+ d !== void 0 && Q.delete(d);
542
+ },
543
+ transformIndexHtml: {
544
+ order: "post",
545
+ handler(e, t) {
546
+ if (o === "api" || t.bundle === void 0) return;
547
+ let n = fe(t.bundle);
548
+ if (n === void 0) return;
549
+ let r = pe(u, n);
550
+ if (!e.includes(`"${r}"`)) return [{
551
+ tag: "link",
552
+ attrs: {
553
+ rel: "modulepreload",
554
+ crossorigin: !0,
555
+ href: r
556
+ },
557
+ injectTo: "head"
558
+ }];
499
559
  }
500
560
  },
501
561
  resolveId(e) {
502
- if (e === Z) return Q;
562
+ if (e === X) return Z;
503
563
  },
504
564
  load(e) {
505
- if (e === Q) return s === "build" ? c : G({
565
+ if (e === Z) return o === "api" ? U() : l === "build" ? p : G({
506
566
  apiUrl: i,
507
- projectId: n.projectId
567
+ projectId: t.projectId,
568
+ projectConfig: m
508
569
  });
509
570
  },
510
571
  configureServer(e) {
511
- if (n.disableLauncher) return;
512
- e.middlewares.use(E(() => d(a)));
513
- let t = e.printUrls.bind(e);
572
+ if (t.disableLauncher) return;
573
+ e.middlewares.use(T(() => f(s)));
574
+ let n = e.printUrls.bind(e);
514
575
  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/`);
576
+ let t = e.resolvedUrls?.local[0];
577
+ if (t) {
578
+ let e = t.replace(/:(?<port>\d+)\//, (e, t) => `:\x1b[1m${t}\x1b[22m/`);
518
579
  console.log(` \x1b[32m➜\x1b[0m \x1b[1mPicked\x1b[22m: \x1b[36m${e}\x1b[0m`);
519
580
  }
520
- t();
581
+ n();
521
582
  };
522
583
  },
523
- generateBundle() {
524
- n.disableLauncher || this.emitFile({
525
- type: "asset",
526
- fileName: "index.html",
527
- source: d(a)
528
- });
584
+ generateBundle: {
585
+ order: "post",
586
+ handler(e, n) {
587
+ if (!t.disableLauncher) {
588
+ if ("index.html" in n) {
589
+ w.debug("index.html came from the build; skipping the launcher page");
590
+ return;
591
+ }
592
+ this.emitFile({
593
+ type: "asset",
594
+ fileName: "index.html",
595
+ source: f(s)
596
+ });
597
+ }
598
+ }
529
599
  }
530
600
  };
531
601
  }
532
602
  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 = [
603
+ 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
604
  `${n.length.toString()} features`,
535
605
  `${r.length.toString()} experiences`,
536
606
  `${i.length.toString()} steps`,
@@ -538,7 +608,7 @@ function $(e, t) {
538
608
  `${o.length.toString()} conditions`,
539
609
  `${s.length.toString()} actions`
540
610
  ].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`);
611
+ w.info(`fetched config in ${t}ms (${l})`), q("Features", n, se), q("Experiences", r, ce), q("Steps", i, le), q("Fields", a, ue), q("Conditions", o, de), oe("Actions", s), w.debug(`config size: ${c.toString()} bytes`);
542
612
  }
543
613
  //#endregion
544
- export { le as picked };
614
+ export { he as picked };