@squadbase/vantage 0.6.2-dev1.42c4e48 → 0.6.2-dev1.48b34e1

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.
Files changed (292) hide show
  1. package/dist/{build-MFWRPYKW.js → build-U7GO26HR.js} +7 -7
  2. package/dist/{build-MFWRPYKW.js.map → build-U7GO26HR.js.map} +1 -1
  3. package/dist/{check-ZBIH422T.js → check-MRVAIHG5.js} +5 -5
  4. package/dist/{check-ZBIH422T.js.map → check-MRVAIHG5.js.map} +1 -1
  5. package/dist/chunk-2IAPIOPS.js +152 -0
  6. package/dist/chunk-2IAPIOPS.js.map +1 -0
  7. package/dist/{chunk-5ZOP4SQR.js → chunk-2N72FKLB.js} +12 -7
  8. package/dist/chunk-2N72FKLB.js.map +1 -0
  9. package/dist/chunk-57GHR5LN.js +163 -0
  10. package/dist/chunk-57GHR5LN.js.map +1 -0
  11. package/dist/chunk-6OTTGAPO.js +44 -0
  12. package/dist/chunk-6OTTGAPO.js.map +1 -0
  13. package/dist/{chunk-OB6UBJXF.js → chunk-7S52M2SL.js} +127 -36
  14. package/dist/chunk-7S52M2SL.js.map +1 -0
  15. package/dist/{chunk-V3LF7BE7.js → chunk-ANZLVSEP.js} +4 -5
  16. package/dist/chunk-ANZLVSEP.js.map +1 -0
  17. package/dist/{chunk-XQUSGIDG.js → chunk-CKWPK4RO.js} +10 -3
  18. package/dist/chunk-CKWPK4RO.js.map +1 -0
  19. package/dist/chunk-JXFCSF3K.js +673 -0
  20. package/dist/chunk-JXFCSF3K.js.map +1 -0
  21. package/dist/{chunk-PXRX5PEC.js → chunk-PDOBHMUQ.js} +3 -3
  22. package/dist/chunk-PDOBHMUQ.js.map +1 -0
  23. package/dist/{chunk-7DZGJQ3P.js → chunk-PJ4SPXHS.js} +23 -6
  24. package/dist/chunk-PJ4SPXHS.js.map +1 -0
  25. package/dist/chunk-QOXXOFGL.js +7051 -0
  26. package/dist/chunk-QOXXOFGL.js.map +1 -0
  27. package/dist/{chunk-CEXAQQ5W.js → chunk-S5MDTHH7.js} +180 -18
  28. package/dist/chunk-S5MDTHH7.js.map +1 -0
  29. package/dist/{chunk-IBGOCWJB.js → chunk-SDJTTMLK.js} +247 -86
  30. package/dist/chunk-SDJTTMLK.js.map +1 -0
  31. package/dist/{chunk-QEWCYW3I.js → chunk-SHZM3EXB.js} +29 -8
  32. package/dist/chunk-SHZM3EXB.js.map +1 -0
  33. package/dist/{chunk-A2UUGASH.js → chunk-U736PVHY.js} +2 -2
  34. package/dist/chunk-U736PVHY.js.map +1 -0
  35. package/dist/{chunk-JKLLFVEU.js → chunk-UWSQUHX6.js} +4 -99
  36. package/dist/chunk-UWSQUHX6.js.map +1 -0
  37. package/dist/cli.js +6 -6
  38. package/dist/client/index.d.ts +2 -0
  39. package/dist/client/index.js +8 -2
  40. package/dist/client/index.js.map +1 -1
  41. package/dist/components/index.d.ts +1596 -100
  42. package/dist/components/index.js +7 -4
  43. package/dist/delta-text-CvwBGJ95.d.ts +15 -0
  44. package/dist/{dev-DCTOHQ6W.js → dev-O42JFQ64.js} +7 -7
  45. package/dist/{dev-DCTOHQ6W.js.map → dev-O42JFQ64.js.map} +1 -1
  46. package/dist/doc/index.d.ts +215 -2
  47. package/dist/doc/index.js +309 -5
  48. package/dist/doc/index.js.map +1 -1
  49. package/dist/{doctor-5E2VEZPK.js → doctor-YD3XAAOT.js} +5 -5
  50. package/dist/{doctor-5E2VEZPK.js.map → doctor-YD3XAAOT.js.map} +1 -1
  51. package/dist/format-U0cQl069.d.ts +243 -0
  52. package/dist/markdown/index.js +1 -1
  53. package/dist/markdown/index.js.map +1 -1
  54. package/dist/query/index.js +2 -2
  55. package/dist/{routes-3SGAFDMC.js → routes-PVKNT777.js} +4 -4
  56. package/dist/{routes-3SGAFDMC.js.map → routes-PVKNT777.js.map} +1 -1
  57. package/dist/slide/index.d.ts +272 -1
  58. package/dist/slide/index.js +974 -4
  59. package/dist/slide/index.js.map +1 -1
  60. package/dist/table/index.js +11 -8
  61. package/dist/table/index.js.map +1 -1
  62. package/dist/ui/index.d.ts +8 -2
  63. package/dist/ui/index.js +22 -112
  64. package/dist/ui/index.js.map +1 -1
  65. package/dist/{upgrade-DBBE6GIR.js → upgrade-6DT7ADRP.js} +4 -4
  66. package/dist/{upgrade-DBBE6GIR.js.map → upgrade-6DT7ADRP.js.map} +1 -1
  67. package/dist/vite/index.js +3 -3
  68. package/docs/en/agent-skills.md +1 -1
  69. package/docs/en/changelog.md +2 -0
  70. package/docs/en/components.md +42 -17
  71. package/docs/en/doc/delta-text.md +40 -0
  72. package/docs/en/doc/doc-action-items.md +49 -0
  73. package/docs/en/doc/doc-callout.md +38 -0
  74. package/docs/en/doc/doc-data-table.md +60 -0
  75. package/docs/en/doc/doc-executive-summary.md +64 -0
  76. package/docs/en/doc/doc-figure.md +56 -0
  77. package/docs/en/doc/doc-key-findings.md +61 -0
  78. package/docs/en/doc/doc-kpi-scorecard.md +80 -0
  79. package/docs/en/doc/doc-notes-and-sources.md +43 -0
  80. package/docs/en/doc/doc-report-header.md +46 -0
  81. package/docs/en/pages-and-metadata.md +15 -0
  82. package/docs/en/parts/area-chart.md +99 -0
  83. package/docs/en/parts/bar-chart.md +91 -0
  84. package/docs/en/parts/bar-list.md +50 -0
  85. package/docs/en/parts/category-bar.md +37 -0
  86. package/docs/en/parts/chart-frame.md +39 -0
  87. package/docs/en/parts/data-table.md +22 -0
  88. package/docs/en/parts/delta.md +51 -0
  89. package/docs/en/parts/donut-chart.md +72 -0
  90. package/docs/en/parts/format.md +43 -0
  91. package/docs/en/parts/funnel-steps.md +2 -1
  92. package/docs/en/parts/heatmap.md +53 -0
  93. package/docs/en/parts/kpi-card.md +58 -0
  94. package/docs/en/parts/legend.md +35 -0
  95. package/docs/en/parts/line-chart.md +94 -0
  96. package/docs/en/parts/metric-value.md +3 -2
  97. package/docs/en/parts/progress-circle.md +33 -0
  98. package/docs/en/parts/sample-data.md +39 -0
  99. package/docs/en/parts/scatter-chart.md +56 -0
  100. package/docs/en/parts/sparkline.md +1 -1
  101. package/docs/en/parts/tracker.md +36 -0
  102. package/docs/en/parts/trend-indicator.md +17 -1
  103. package/docs/en/parts/updated-at.md +30 -0
  104. package/docs/en/parts/waterfall-chart.md +56 -0
  105. package/docs/en/slide/slide-chart-full.md +48 -0
  106. package/docs/en/slide/slide-chart-insight.md +52 -0
  107. package/docs/en/slide/slide-columns.md +46 -0
  108. package/docs/en/slide/slide-comparison.md +68 -0
  109. package/docs/en/slide/slide-cover.md +39 -0
  110. package/docs/en/slide/slide-exec-summary.md +47 -0
  111. package/docs/en/slide/slide-heading.md +38 -0
  112. package/docs/en/slide/slide-kpi-grid.md +55 -0
  113. package/docs/en/slide/slide-kpi-hero.md +58 -0
  114. package/docs/en/slide/slide-next-actions.md +49 -0
  115. package/docs/en/slide/slide-scorecard-table.md +54 -0
  116. package/docs/en/slide/slide-section.md +44 -0
  117. package/docs/en/slide/slide-source-line.md +34 -0
  118. package/docs/en/ui/alert-dialog.md +42 -0
  119. package/docs/en/ui/avatar.md +31 -0
  120. package/docs/en/ui/combobox.md +74 -0
  121. package/docs/en/ui/drawer.md +41 -0
  122. package/docs/en/ui/empty.md +1 -1
  123. package/docs/en/ui/error-state.md +4 -3
  124. package/docs/en/ui/field.md +42 -0
  125. package/docs/en/ui/hover-card.md +21 -0
  126. package/docs/en/ui/kbd.md +17 -0
  127. package/docs/en/ui/loading.md +1 -1
  128. package/docs/en/ui/pagination.md +36 -0
  129. package/docs/en/ui/radio-group.md +21 -0
  130. package/docs/en/ui/toast.md +44 -0
  131. package/docs/en/ui/toggle-group.md +4 -3
  132. package/docs/en/ui-and-theming.md +1 -1
  133. package/docs/index.json +917 -77
  134. package/docs/ja/agent-skills.md +1 -1
  135. package/docs/ja/changelog.md +2 -0
  136. package/docs/ja/components.md +39 -16
  137. package/docs/ja/doc/delta-text.md +40 -0
  138. package/docs/ja/doc/doc-action-items.md +49 -0
  139. package/docs/ja/doc/doc-callout.md +38 -0
  140. package/docs/ja/doc/doc-data-table.md +60 -0
  141. package/docs/ja/doc/doc-executive-summary.md +64 -0
  142. package/docs/ja/doc/doc-figure.md +56 -0
  143. package/docs/ja/doc/doc-key-findings.md +61 -0
  144. package/docs/ja/doc/doc-kpi-scorecard.md +80 -0
  145. package/docs/ja/doc/doc-notes-and-sources.md +43 -0
  146. package/docs/ja/doc/doc-report-header.md +46 -0
  147. package/docs/ja/page-types/slide.md +1 -0
  148. package/docs/ja/pages-and-metadata.md +15 -0
  149. package/docs/ja/parts/area-chart.md +49 -25
  150. package/docs/ja/parts/bar-chart.md +50 -24
  151. package/docs/ja/parts/bar-list.md +31 -8
  152. package/docs/ja/parts/chart-frame.md +36 -0
  153. package/docs/ja/parts/data-table.md +22 -0
  154. package/docs/ja/parts/delta.md +51 -0
  155. package/docs/ja/parts/donut-chart.md +45 -26
  156. package/docs/ja/parts/format.md +44 -0
  157. package/docs/ja/parts/funnel-steps.md +27 -8
  158. package/docs/ja/parts/heatmap.md +45 -0
  159. package/docs/ja/parts/kpi-card.md +56 -0
  160. package/docs/ja/parts/legend.md +36 -0
  161. package/docs/ja/parts/line-chart.md +48 -22
  162. package/docs/ja/parts/metric-value.md +3 -2
  163. package/docs/ja/parts/sample-data.md +61 -0
  164. package/docs/ja/parts/scatter-chart.md +69 -0
  165. package/docs/ja/parts/sparkline.md +1 -1
  166. package/docs/ja/parts/trend-indicator.md +17 -1
  167. package/docs/ja/parts/updated-at.md +27 -0
  168. package/docs/ja/parts/waterfall-chart.md +61 -0
  169. package/docs/ja/slide/slide-chart-full.md +48 -0
  170. package/docs/ja/slide/slide-chart-insight.md +52 -0
  171. package/docs/ja/slide/slide-columns.md +46 -0
  172. package/docs/ja/slide/slide-comparison.md +68 -0
  173. package/docs/ja/slide/slide-cover.md +39 -0
  174. package/docs/ja/slide/slide-exec-summary.md +47 -0
  175. package/docs/ja/slide/slide-heading.md +38 -0
  176. package/docs/ja/slide/slide-kpi-grid.md +55 -0
  177. package/docs/ja/slide/slide-kpi-hero.md +58 -0
  178. package/docs/ja/slide/slide-next-actions.md +49 -0
  179. package/docs/ja/slide/slide-scorecard-table.md +54 -0
  180. package/docs/ja/slide/slide-section.md +44 -0
  181. package/docs/ja/slide/slide-source-line.md +34 -0
  182. package/docs/ja/ui/empty.md +1 -1
  183. package/docs/ja/ui/error-state.md +4 -3
  184. package/docs/ja/ui/loading.md +1 -1
  185. package/docs/ja/ui/toggle-group.md +4 -3
  186. package/docs/ja/ui-and-theming.md +2 -2
  187. package/package.json +26 -24
  188. package/registry/ui/accordion.tsx +4 -2
  189. package/registry/ui/alert-dialog.tsx +3 -3
  190. package/registry/ui/alert.tsx +3 -1
  191. package/registry/ui/app-shell.tsx +7 -1
  192. package/registry/ui/area-chart.tsx +2852 -166
  193. package/registry/ui/attention-list.tsx +303 -0
  194. package/registry/ui/avatar.tsx +1 -1
  195. package/registry/ui/badge.tsx +3 -1
  196. package/registry/ui/bar-chart.tsx +2851 -166
  197. package/registry/ui/bar-list.tsx +3531 -90
  198. package/registry/ui/box-plot-chart.tsx +3906 -0
  199. package/registry/ui/breadcrumb.tsx +3 -1
  200. package/registry/ui/button.tsx +3 -1
  201. package/registry/ui/calendar.tsx +3 -1
  202. package/registry/ui/card.tsx +4 -2
  203. package/registry/ui/category-bar.tsx +1025 -16
  204. package/registry/ui/chart-frame.tsx +1393 -0
  205. package/registry/ui/checkbox.tsx +3 -1
  206. package/registry/ui/collapsible.tsx +3 -1
  207. package/registry/ui/combobox.tsx +2 -2
  208. package/registry/ui/command.tsx +3 -1
  209. package/registry/ui/dashboard-card.tsx +71 -28
  210. package/registry/ui/data-table.tsx +678 -56
  211. package/registry/ui/date-range-picker.tsx +245 -64
  212. package/registry/ui/delta.tsx +191 -0
  213. package/registry/ui/dialog.tsx +5 -3
  214. package/registry/ui/donut-chart.tsx +2929 -182
  215. package/registry/ui/drawer.tsx +1 -1
  216. package/registry/ui/dropdown-menu.tsx +5 -3
  217. package/registry/ui/echart.tsx +621 -67
  218. package/registry/ui/field.tsx +1 -1
  219. package/registry/ui/filter-bar.tsx +33 -6
  220. package/registry/ui/funnel-steps.tsx +3344 -49
  221. package/registry/ui/heatmap.tsx +1786 -0
  222. package/registry/ui/histogram-chart.tsx +3986 -0
  223. package/registry/ui/hover-card.tsx +2 -2
  224. package/registry/ui/input-group.tsx +3 -1
  225. package/registry/ui/input.tsx +3 -1
  226. package/registry/ui/kbd.tsx +3 -1
  227. package/registry/ui/kpi-card.tsx +704 -0
  228. package/registry/ui/label.tsx +3 -1
  229. package/registry/ui/legend.tsx +3563 -0
  230. package/registry/ui/line-chart.tsx +2852 -160
  231. package/registry/ui/metric-value.tsx +9 -1
  232. package/registry/ui/multi-select.tsx +11 -5
  233. package/registry/ui/page-shell.tsx +106 -51
  234. package/registry/ui/pagination.tsx +3 -1
  235. package/registry/ui/paired-chart.tsx +3827 -0
  236. package/registry/ui/placeholder.tsx +8 -2
  237. package/registry/ui/popover.tsx +4 -2
  238. package/registry/ui/progress-circle.tsx +607 -12
  239. package/registry/ui/progress.tsx +3 -1
  240. package/registry/ui/radio-group.tsx +1 -1
  241. package/registry/ui/sample-data.tsx +86 -0
  242. package/registry/ui/scatter-chart.tsx +4212 -0
  243. package/registry/ui/scroll-area.tsx +3 -2
  244. package/registry/ui/searchable-select.tsx +8 -3
  245. package/registry/ui/section-header.tsx +5 -3
  246. package/registry/ui/segmented-control.tsx +7 -2
  247. package/registry/ui/select.tsx +4 -2
  248. package/registry/ui/separator.tsx +3 -1
  249. package/registry/ui/sheet.tsx +4 -2
  250. package/registry/ui/sidebar.tsx +4 -2
  251. package/registry/ui/skeleton.tsx +4 -2
  252. package/registry/ui/slider.tsx +4 -2
  253. package/registry/ui/sparkline.tsx +84 -9
  254. package/registry/ui/spinner.tsx +3 -1
  255. package/registry/ui/states.tsx +34 -5
  256. package/registry/ui/status-badge.tsx +83 -41
  257. package/registry/ui/switch.tsx +3 -1
  258. package/registry/ui/table.tsx +4 -2
  259. package/registry/ui/tabs.tsx +5 -3
  260. package/registry/ui/textarea.tsx +3 -1
  261. package/registry/ui/toast.tsx +2 -2
  262. package/registry/ui/toggle-group.tsx +3 -1
  263. package/registry/ui/toggle.tsx +3 -1
  264. package/registry/ui/tooltip.tsx +10 -4
  265. package/registry/ui/tracker.tsx +632 -19
  266. package/registry/ui/trend-indicator.tsx +15 -3
  267. package/registry/ui/updated-at.tsx +122 -0
  268. package/registry/ui/waterfall-chart.tsx +4248 -0
  269. package/skills/vantage-design/SKILL.md +60 -52
  270. package/skills/vantage-design/references/extract.md +26 -27
  271. package/skills/vantage-design/references/format.md +12 -172
  272. package/skills/vantage-design/references/presets.md +50 -110
  273. package/skills/vantage-pitfalls/SKILL.md +5 -0
  274. package/skills/vantage-slide/SKILL.md +54 -36
  275. package/templates/AGENTS.md +42 -15
  276. package/templates/agents/doc.md +48 -0
  277. package/templates/agents/page.md +33 -2
  278. package/templates/agents/slide.md +77 -3
  279. package/theme.css +247 -149
  280. package/dist/chunk-5ZOP4SQR.js.map +0 -1
  281. package/dist/chunk-7DZGJQ3P.js.map +0 -1
  282. package/dist/chunk-A2UUGASH.js.map +0 -1
  283. package/dist/chunk-AG6RZ2RR.js +0 -3208
  284. package/dist/chunk-AG6RZ2RR.js.map +0 -1
  285. package/dist/chunk-CEXAQQ5W.js.map +0 -1
  286. package/dist/chunk-IBGOCWJB.js.map +0 -1
  287. package/dist/chunk-JKLLFVEU.js.map +0 -1
  288. package/dist/chunk-OB6UBJXF.js.map +0 -1
  289. package/dist/chunk-PXRX5PEC.js.map +0 -1
  290. package/dist/chunk-QEWCYW3I.js.map +0 -1
  291. package/dist/chunk-V3LF7BE7.js.map +0 -1
  292. package/dist/chunk-XQUSGIDG.js.map +0 -1
@@ -1,16 +1,17 @@
1
- import { generateArtifacts, setDraftArtifacts } from './chunk-QEWCYW3I.js';
1
+ import { API_CHANGE_EVENT, generateArtifacts, setDraftArtifacts, restoreClientEntry } from './chunk-SHZM3EXB.js';
2
+ import { extractAppLang } from './chunk-S5MDTHH7.js';
2
3
  import { scanProject, resolvePageRoot, stripExt, splitPageVariant, fileToSegments, displayPath } from './chunk-RNTDBX6S.js';
3
4
  import { corsMiddleware, matchApiRoute, dispatchApi, sortApiRoutes } from './chunk-46QI6GFC.js';
4
5
  import { VANTAGE_DIR, NON_ROUTE_DIRS, FILE_PAGE_EXTENSIONS, PAGE_EXTENSIONS, RESERVED_PAGE_NAMES } from './chunk-C2CX6GLX.js';
5
6
  import fs3 from 'fs';
6
- import path5 from 'path';
7
+ import path6 from 'path';
7
8
  import react from '@vitejs/plugin-react';
8
9
  import tailwindcss from '@tailwindcss/vite';
9
10
  import { Hono } from 'hono';
10
11
  import { getRequestListener } from '@hono/node-server';
11
12
  import { createHash, timingSafeEqual } from 'crypto';
12
13
  import { createRequire } from 'module';
13
- import { pathToFileURL } from 'url';
14
+ import { pathToFileURL, fileURLToPath } from 'url';
14
15
 
15
16
  // @squadbase/vantage — generated build. Do not edit.
16
17
  function createApiDevMiddleware(opts) {
@@ -50,8 +51,8 @@ function createApiDevMiddleware(opts) {
50
51
  const listener = getRequestListener(app.fetch);
51
52
  return (req, res, next) => {
52
53
  const url = req.url ?? "/";
53
- const path6 = url.split("?")[0];
54
- if (path6 === "/api" || path6.startsWith("/api/")) {
54
+ const path7 = url.split("?")[0];
55
+ if (path7 === "/api" || path7.startsWith("/api/")) {
55
56
  Promise.resolve(listener(req, res)).catch((err) => {
56
57
  console.error("[vantage] API middleware failure:", err);
57
58
  if (!res.headersSent) {
@@ -126,7 +127,7 @@ var BorrowedVersions = class {
126
127
  var loaded;
127
128
  async function loadTypeScript(root) {
128
129
  try {
129
- const entry = createRequire(path5.join(path5.resolve(root), "package.json")).resolve("typescript");
130
+ const entry = createRequire(path6.join(path6.resolve(root), "package.json")).resolve("typescript");
130
131
  const mod = await import(pathToFileURL(entry).href);
131
132
  const compiler = mod.default ?? mod;
132
133
  if (typeof compiler.createSourceFile !== "function") return null;
@@ -220,6 +221,7 @@ function boundNames(sf) {
220
221
  else if (ts.isImportEqualsDeclaration(node)) names.add(node.name.text);
221
222
  else if (ts.isVariableDeclaration(node) || ts.isParameter(node) || ts.isBindingElement(node))
222
223
  bindingNames(node.name, names);
224
+ else if (ts.isTypeParameterDeclaration(node)) names.add(node.name.text);
223
225
  else if ((ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) || ts.isClassDeclaration(node) || ts.isClassExpression(node) || ts.isEnumDeclaration(node)) && node.name)
224
226
  names.add(node.name.text);
225
227
  ts.forEachChild(node, visit);
@@ -415,11 +417,11 @@ function needsBreak(head) {
415
417
  const lastLine = head.slice(head.lastIndexOf("\n") + 1);
416
418
  return lastLine.includes("//");
417
419
  }
418
- function isPageModule(path6, pageDir = "") {
419
- return /\.tsx$/i.test(path6) && isPagePath(path6, pageDir);
420
+ function isPageModule(path7, pageDir = "") {
421
+ return /\.tsx$/i.test(path7) && isPagePath(path7, pageDir);
420
422
  }
421
- function isPagePath(path6, pageDir) {
422
- let rel = path6.replace(/\\/g, "/");
423
+ function isPagePath(path7, pageDir) {
424
+ let rel = path7.replace(/\\/g, "/");
423
425
  if (pageDir !== "") {
424
426
  if (!rel.startsWith(`${pageDir}/`)) return false;
425
427
  rel = rel.slice(pageDir.length + 1);
@@ -427,8 +429,8 @@ function isPagePath(path6, pageDir) {
427
429
  const dirs = rel.split("/").slice(0, -1);
428
430
  return dirs.every((d) => d !== "" && !d.startsWith(".") && !NON_ROUTE_DIRS.has(d));
429
431
  }
430
- function parsesWithExport(code, path6, kind, needDefault, needExport) {
431
- const sf = ts.createSourceFile(path6, code, ts.ScriptTarget.Latest, false, kind);
432
+ function parsesWithExport(code, path7, kind, needDefault, needExport) {
433
+ const sf = ts.createSourceFile(path7, code, ts.ScriptTarget.Latest, false, kind);
432
434
  const diagnostics = sf.parseDiagnostics;
433
435
  if (diagnostics && diagnostics.length > 0) return false;
434
436
  const exports = !needExport || sf.statements.some((s) => {
@@ -438,7 +440,7 @@ function parsesWithExport(code, path6, kind, needDefault, needExport) {
438
440
  const flags = ts.getCombinedModifierFlags(s);
439
441
  return needDefault ? (flags & ts.ModifierFlags.ExportDefault) === ts.ModifierFlags.ExportDefault : (flags & ts.ModifierFlags.Export) !== 0;
440
442
  });
441
- return exports && bodilessFunctions(code, path6).length === 0;
443
+ return exports && bodilessFunctions(code, path7).length === 0;
442
444
  }
443
445
  var ID_START = /[A-Za-z_$]/;
444
446
  var ID_PART = /[A-Za-z0-9_$]/;
@@ -641,20 +643,20 @@ function getDraftRoutes(server) {
641
643
  return instances.get(server);
642
644
  }
643
645
  function createDraftRoutes(server, _model) {
644
- const root = path5.resolve(server.config.root);
645
- const vantageDir = path5.join(root, VANTAGE_DIR);
646
+ const root = path6.resolve(server.config.root);
647
+ const vantageDir = path6.join(root, VANTAGE_DIR);
646
648
  const pages = /* @__PURE__ */ new Map();
647
649
  const committed = /* @__PURE__ */ new Map();
648
650
  setDraftArtifacts(root, { hmr: true, pages: [] });
649
651
  generateArtifacts({ root, model: scanProject(root) });
650
652
  const toRel = (file) => {
651
- const abs = path5.isAbsolute(file) ? file : path5.resolve(root, file);
652
- return path5.relative(root, abs).split(path5.sep).join("/");
653
+ const abs = path6.isAbsolute(file) ? file : path6.resolve(root, file);
654
+ return path6.relative(root, abs).split(path6.sep).join("/");
653
655
  };
654
656
  const describe = (rel) => {
655
- if (rel === "" || rel.startsWith("../") || path5.isAbsolute(rel)) return null;
657
+ if (rel === "" || rel.startsWith("../") || path6.isAbsolute(rel)) return null;
656
658
  const pageRoot = resolvePageRoot(root);
657
- const fromPageRoot = pageRoot.dir === "" ? rel : path5.posix.relative(pageRoot.dir, rel);
659
+ const fromPageRoot = pageRoot.dir === "" ? rel : path6.posix.relative(pageRoot.dir, rel);
658
660
  if (fromPageRoot.startsWith("../") || fromPageRoot === "") return null;
659
661
  const parts = fromPageRoot.split("/");
660
662
  if (parts.some((s) => NON_ROUTE_DIRS.has(s) || s.startsWith("."))) return null;
@@ -668,10 +670,10 @@ function createDraftRoutes(server, _model) {
668
670
  const relNoExt = stripExt(fromPageRoot, PAGE_EXTENSIONS);
669
671
  const forSegments = variant ? relNoExt.slice(0, -(variant.length + 1)) : relNoExt;
670
672
  const segments = fileToSegments(forSegments);
671
- const dir = path5.posix.dirname(fromPageRoot);
673
+ const dir = path6.posix.dirname(fromPageRoot);
672
674
  return {
673
675
  file: rel,
674
- absFile: path5.join(root, ...rel.split("/")),
676
+ absFile: path6.join(root, ...rel.split("/")),
675
677
  routePath: displayPath(segments),
676
678
  segments,
677
679
  dir: dir === "." ? "" : dir,
@@ -700,7 +702,7 @@ function createDraftRoutes(server, _model) {
700
702
  const container = server.environments?.client?.pluginContainer;
701
703
  if (!container) return true;
702
704
  try {
703
- const importer = path5.join(vantageDir, "route-tree.gen.ts");
705
+ const importer = path6.join(vantageDir, "route-tree.gen.ts");
704
706
  return await container.resolveId(`../${rel}`, importer) != null;
705
707
  } catch {
706
708
  return false;
@@ -802,12 +804,12 @@ function usedComponents(sf) {
802
804
  return used;
803
805
  }
804
806
  function draftTailwind(root) {
805
- const dir = path5.join(root, VANTAGE_DIR, "draft-tailwind");
806
- const runtimeCss = path5.join(root, VANTAGE_DIR, "runtime.css");
807
- const mirrorOf = (file) => path5.join(dir, path5.relative(root, file).split(path5.sep).join("__"));
807
+ const dir = path6.join(root, VANTAGE_DIR, "draft-tailwind");
808
+ const runtimeCss = path6.join(root, VANTAGE_DIR, "runtime.css");
809
+ const mirrorOf = (file) => path6.join(dir, path6.relative(root, file).split(path6.sep).join("__"));
808
810
  return {
809
811
  stylesheet: runtimeCss,
810
- owns: (file) => file.startsWith(dir + path5.sep),
812
+ owns: (file) => file.startsWith(dir + path6.sep),
811
813
  reset() {
812
814
  fs3.rmSync(dir, { recursive: true, force: true });
813
815
  fs3.mkdirSync(dir, { recursive: true });
@@ -916,11 +918,12 @@ var DRAFT_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mts", ".mjs"];
916
918
  var DRAFTABLE_EXTENSIONS = [".ts", ".tsx"];
917
919
  var MAX_BODY_BYTES = 1024 * 1024;
918
920
  var DRAFT_IDLE_DISCARD_MS = 6e4;
921
+ var MAX_HANDOVER_RETRIES = 10;
919
922
  var ROLLBACK_DEBOUNCE_MS = 150;
920
923
  var PREV_QUERY = "vantage-draft-prev";
921
924
  var SKELETON_PREFIX = "\0vantage-draft-skeleton:";
922
925
  function draftPreviewPlugin(options) {
923
- const root = path5.resolve(options.root);
926
+ const root = path6.resolve(options.root);
924
927
  const token = options.token ?? process.env.VANTAGE_DRAFT_TOKEN;
925
928
  const createRoutes = options.createRoutes ?? createDraftRoutes;
926
929
  const idleDiscardMs = options.idleDiscardMs ?? DRAFT_IDLE_DISCARD_MS;
@@ -935,6 +938,7 @@ function draftPreviewPlugin(options) {
935
938
  const lastSeq = /* @__PURE__ */ new Map();
936
939
  const idleTimers = /* @__PURE__ */ new Map();
937
940
  const rolledBackAt = /* @__PURE__ */ new Map();
941
+ const handovers = /* @__PURE__ */ new Map();
938
942
  const skeletons = /* @__PURE__ */ new Map();
939
943
  const borrowed = new BorrowedVersions(PREV_QUERY);
940
944
  let lastApplied;
@@ -950,7 +954,7 @@ function draftPreviewPlugin(options) {
950
954
  const isDraftRequest = (req) => !req.final && !req.discard;
951
955
  const SUPERSEDED = { applied: false, reason: "superseded" };
952
956
  const submit = (req) => new Promise((resolve, reject) => {
953
- const key = typeof req.path === "string" && req.path !== "" ? path5.resolve(root, req.path) : void 0;
957
+ const key = typeof req.path === "string" && req.path !== "" ? path6.resolve(root, req.path) : void 0;
954
958
  if (key !== void 0) {
955
959
  if (!isDraftRequest(req)) {
956
960
  for (let i = waiting.length - 1; i >= 0; i--) {
@@ -984,7 +988,7 @@ function draftPreviewPlugin(options) {
984
988
  }
985
989
  });
986
990
  });
987
- const relOf = (file) => path5.relative(root, file).split(path5.sep).join("/");
991
+ const relOf = (file) => path6.relative(root, file).split(path6.sep).join("/");
988
992
  const shown = (file) => drafts.get(file)?.at(-1);
989
993
  const diskText = (file) => {
990
994
  try {
@@ -996,10 +1000,10 @@ function draftPreviewPlugin(options) {
996
1000
  const candidatesOf = (base) => [
997
1001
  base,
998
1002
  ...DRAFT_EXTENSIONS.map((ext) => base + ext),
999
- ...DRAFT_EXTENSIONS.map((ext) => path5.join(base, "index" + ext))
1003
+ ...DRAFT_EXTENSIONS.map((ext) => path6.join(base, "index" + ext))
1000
1004
  ];
1001
1005
  const skeletonId = (base) => {
1002
- const ext = path5.extname(base);
1006
+ const ext = path6.extname(base);
1003
1007
  return SKELETON_PREFIX + (DRAFT_EXTENSIONS.includes(ext) ? base.slice(0, -ext.length) : base);
1004
1008
  };
1005
1009
  const isWritten = (base) => candidatesOf(base).some((c) => newFiles.has(c) || fs3.existsSync(c));
@@ -1007,9 +1011,9 @@ function draftPreviewPlugin(options) {
1007
1011
  const grown = [];
1008
1012
  const before = /* @__PURE__ */ new Map();
1009
1013
  for (const [specifier, names] of relativeImports(source, rel)) {
1010
- const ext = path5.extname(specifier);
1014
+ const ext = path6.extname(specifier);
1011
1015
  if (ext !== "" && !DRAFT_EXTENSIONS.includes(ext)) continue;
1012
- const base = path5.resolve(path5.dirname(file), specifier);
1016
+ const base = path6.resolve(path6.dirname(file), specifier);
1013
1017
  if (isWritten(base)) continue;
1014
1018
  const id = skeletonId(base);
1015
1019
  const known = skeletons.get(id);
@@ -1033,13 +1037,13 @@ function draftPreviewPlugin(options) {
1033
1037
  };
1034
1038
  const resolveTarget = (rel) => {
1035
1039
  if (typeof rel !== "string" || rel === "") return "path is required";
1036
- const file = path5.resolve(root, rel);
1037
- const relPath = path5.relative(root, file);
1038
- if (relPath === "" || relPath.startsWith("..") || path5.isAbsolute(relPath)) return "path is outside the project";
1039
- const segments = relPath.split(path5.sep);
1040
+ const file = path6.resolve(root, rel);
1041
+ const relPath = path6.relative(root, file);
1042
+ if (relPath === "" || relPath.startsWith("..") || path6.isAbsolute(relPath)) return "path is outside the project";
1043
+ const segments = relPath.split(path6.sep);
1040
1044
  if (segments[0] === "server") return "server/ is not previewed";
1041
1045
  if (segments.some((s) => s === "node_modules" || s.startsWith("."))) return "path is not a project source";
1042
- if (!DRAFTABLE_EXTENSIONS.includes(path5.extname(file))) return "only .ts and .tsx script modules are previewed";
1046
+ if (!DRAFTABLE_EXTENSIONS.includes(path6.extname(file))) return "only .ts and .tsx script modules are previewed";
1043
1047
  const exists = fs3.existsSync(file);
1044
1048
  if (exists && fs3.statSync(file).isDirectory()) return "path is a directory";
1045
1049
  if (exists && !isInside(fs3.realpathSync(root), fs3.realpathSync(file))) return "path is outside the project";
@@ -1077,6 +1081,7 @@ function draftPreviewPlugin(options) {
1077
1081
  const forget = async (file, opts) => {
1078
1082
  drafts.delete(file);
1079
1083
  rolledBackAt.delete(file);
1084
+ handovers.delete(file);
1080
1085
  borrowed.drop(file);
1081
1086
  tailwind.remove(file);
1082
1087
  newFiles.delete(file);
@@ -1111,7 +1116,27 @@ function draftPreviewPlugin(options) {
1111
1116
  if (drafts.has(target.file)) touchIdle(target);
1112
1117
  return result;
1113
1118
  };
1114
- const finalize = async ({ file }) => {
1119
+ const diskTransforms = async ({ file, url }) => {
1120
+ const history = drafts.get(file);
1121
+ if (history === void 0) return void 0;
1122
+ drafts.delete(file);
1123
+ invalidate(file);
1124
+ try {
1125
+ await server.environments.client.transformRequest(url);
1126
+ return void 0;
1127
+ } catch (err) {
1128
+ drafts.set(file, history);
1129
+ invalidate(file);
1130
+ return firstLine(err);
1131
+ }
1132
+ };
1133
+ const keepDraft = (target, reason) => {
1134
+ handovers.set(target.file, { target, retries: handovers.get(target.file)?.retries ?? 0 });
1135
+ touchIdle(target);
1136
+ return { applied: false, reason: `disk version does not transform yet: ${reason}` };
1137
+ };
1138
+ const finalize = async (target) => {
1139
+ const { file } = target;
1115
1140
  if (!fs3.existsSync(file)) {
1116
1141
  const had = drafts.has(file);
1117
1142
  await forget(file, { committed: false });
@@ -1119,6 +1144,8 @@ function draftPreviewPlugin(options) {
1119
1144
  notifyState();
1120
1145
  return { applied: false, reason: had ? "file was not written" : "file does not exist" };
1121
1146
  }
1147
+ const broken = await diskTransforms(target);
1148
+ if (broken !== void 0) return keepDraft(target, broken);
1122
1149
  await forget(file, { committed: true });
1123
1150
  notifyState();
1124
1151
  invalidate(file);
@@ -1126,7 +1153,8 @@ function draftPreviewPlugin(options) {
1126
1153
  await refreshSkeletons([], file);
1127
1154
  return { applied: true };
1128
1155
  };
1129
- const discard = async ({ file }) => {
1156
+ const discard = async (target) => {
1157
+ const { file } = target;
1130
1158
  if (!drafts.has(file)) return { applied: false, reason: "no draft" };
1131
1159
  await forget(file, { committed: false });
1132
1160
  notifyState();
@@ -1134,9 +1162,21 @@ function draftPreviewPlugin(options) {
1134
1162
  if (fs3.existsSync(file)) await pushUpdate(file);
1135
1163
  return { applied: true };
1136
1164
  };
1165
+ const retryHandovers = () => {
1166
+ for (const [file, pending] of [...handovers]) {
1167
+ void enqueue(async () => {
1168
+ if (handovers.get(file) !== pending || !drafts.has(file)) return;
1169
+ pending.retries++;
1170
+ if (pending.retries > MAX_HANDOVER_RETRIES) await discard(pending.target);
1171
+ else await finalize(pending.target);
1172
+ }).catch(() => {
1173
+ });
1174
+ }
1175
+ };
1137
1176
  const draft = async (target, req) => {
1138
1177
  const { file, rel, url, exists } = target;
1139
1178
  if (typeof req.content !== "string") return { applied: false, reason: "content is required" };
1179
+ handovers.delete(file);
1140
1180
  const pageDir = options.getModel().pageDir;
1141
1181
  const previous = shown(file);
1142
1182
  const base = previous?.served ?? diskText(file);
@@ -1260,7 +1300,7 @@ function draftPreviewPlugin(options) {
1260
1300
  };
1261
1301
  const locate = (name) => {
1262
1302
  const clean = name.split("?")[0];
1263
- const candidates = [path5.resolve(root, clean.replace(/^\//, "")), clean];
1303
+ const candidates = [path6.resolve(root, clean.replace(/^\//, "")), clean];
1264
1304
  return candidates.find((c) => drafts.has(c));
1265
1305
  };
1266
1306
  const authorized = (req) => {
@@ -1344,8 +1384,8 @@ function draftPreviewPlugin(options) {
1344
1384
  if (newFiles.size === 0 && skeletons.size === 0) return null;
1345
1385
  const clean = source.split("?")[0];
1346
1386
  let base;
1347
- if (clean.startsWith("/")) base = clean.startsWith(root + "/") ? clean : path5.join(root, clean);
1348
- else if (clean.startsWith(".") && importer) base = path5.resolve(path5.dirname(importer.split("?")[0]), clean);
1387
+ if (clean.startsWith("/")) base = clean.startsWith(root + "/") ? clean : path6.join(root, clean);
1388
+ else if (clean.startsWith(".") && importer) base = path6.resolve(path6.dirname(importer.split("?")[0]), clean);
1349
1389
  else return null;
1350
1390
  const written = candidatesOf(base);
1351
1391
  const draftFile = written.find((c) => newFiles.has(c));
@@ -1373,6 +1413,11 @@ function draftPreviewPlugin(options) {
1373
1413
  // The borrowed versions share the drafted file but are not what changed.
1374
1414
  hotUpdate({ modules, file }) {
1375
1415
  if (tailwind?.owns(file)) return [];
1416
+ if (enabled && handovers.size > 0) retryHandovers();
1417
+ if (enabled && file === path6.join(root, VANTAGE_DIR, "client-entry.tsx")) {
1418
+ restoreClientEntry(root);
1419
+ return [];
1420
+ }
1376
1421
  const kept = modules.filter(
1377
1422
  (mod) => mod.id !== null && !mod.url.includes(`${PREV_QUERY}=`) && (!drafted.has(file) || reachable(mod))
1378
1423
  );
@@ -1408,8 +1453,8 @@ function stubExports(source, expected, prevUrl, fileName) {
1408
1453
  ` : source;
1409
1454
  }
1410
1455
  function isInside(dir, file) {
1411
- const rel = path5.relative(dir, file);
1412
- return rel !== ".." && !rel.startsWith(".." + path5.sep) && !path5.isAbsolute(rel);
1456
+ const rel = path6.relative(dir, file);
1457
+ return rel !== ".." && !rel.startsWith(".." + path6.sep) && !path6.isAbsolute(rel);
1413
1458
  }
1414
1459
  var REFUSED_PATH = /^path is a directory$/;
1415
1460
  function isDynamicRoute(route) {
@@ -1455,6 +1500,119 @@ function firstLine(err) {
1455
1500
  const message = err instanceof Error ? err.message : String(err);
1456
1501
  return message.split("\n").find((l) => l.trim() !== "")?.trim() ?? "transform failed";
1457
1502
  }
1503
+ var PACKAGE_NAME = "@squadbase/vantage";
1504
+ var NOT_PREBUNDLED = /* @__PURE__ */ new Set([
1505
+ "./server",
1506
+ "./server/node",
1507
+ "./vite",
1508
+ "./theme.css",
1509
+ "./package.json",
1510
+ "./markdown",
1511
+ "./table",
1512
+ "./slide",
1513
+ "./doc"
1514
+ ]);
1515
+ function ownPackageDir() {
1516
+ let dir = path6.dirname(fileURLToPath(import.meta.url));
1517
+ for (; ; ) {
1518
+ const manifest = path6.join(dir, "package.json");
1519
+ if (fs3.existsSync(manifest)) {
1520
+ try {
1521
+ if (JSON.parse(fs3.readFileSync(manifest, "utf8")).name === PACKAGE_NAME) return dir;
1522
+ } catch {
1523
+ }
1524
+ }
1525
+ const parent = path6.dirname(dir);
1526
+ if (parent === dir) return null;
1527
+ dir = parent;
1528
+ }
1529
+ }
1530
+ function packageName(spec) {
1531
+ const parts = spec.split("/");
1532
+ return spec.startsWith("@") ? parts.slice(0, 2).join("/") : parts[0];
1533
+ }
1534
+ function findPackageDir(fromDir, pkg) {
1535
+ let dir = fromDir;
1536
+ for (; ; ) {
1537
+ const candidate = path6.join(dir, "node_modules", pkg);
1538
+ if (fs3.existsSync(candidate)) return candidate;
1539
+ const parent = path6.dirname(dir);
1540
+ if (parent === dir) return null;
1541
+ dir = parent;
1542
+ }
1543
+ }
1544
+ function resolvesFrom(root, spec) {
1545
+ const pkg = packageName(spec);
1546
+ const dir = findPackageDir(root, pkg);
1547
+ if (!dir) return false;
1548
+ const sub = spec.slice(pkg.length);
1549
+ if (sub === "") return true;
1550
+ let exportsField;
1551
+ try {
1552
+ exportsField = JSON.parse(fs3.readFileSync(path6.join(dir, "package.json"), "utf8")).exports;
1553
+ } catch {
1554
+ return false;
1555
+ }
1556
+ if (exportsField && typeof exportsField === "object" && !Array.isArray(exportsField)) {
1557
+ const keys = Object.keys(exportsField);
1558
+ if (!keys.some((k) => k.startsWith("."))) return false;
1559
+ const wanted = `.${sub}`;
1560
+ return keys.some((key) => {
1561
+ if (key === wanted) return true;
1562
+ const star = key.indexOf("*");
1563
+ if (star < 0) return false;
1564
+ return wanted.startsWith(key.slice(0, star)) && wanted.endsWith(key.slice(star + 1));
1565
+ });
1566
+ }
1567
+ const file = path6.join(dir, sub);
1568
+ return [file, `${file}.js`, `${file}.mjs`, path6.join(file, "index.js")].some((f) => fs3.existsSync(f));
1569
+ }
1570
+ function isInstalled(root) {
1571
+ const dir = findPackageDir(root, PACKAGE_NAME);
1572
+ if (!dir) return false;
1573
+ try {
1574
+ return fs3.realpathSync(dir).split(path6.sep).includes("node_modules");
1575
+ } catch {
1576
+ return false;
1577
+ }
1578
+ }
1579
+ function frameworkSubpaths(exportsField) {
1580
+ return Object.keys(exportsField).filter((key) => key.startsWith(".") && !key.includes("*") && !NOT_PREBUNDLED.has(key)).map((key) => key === "." ? PACKAGE_NAME : `${PACKAGE_NAME}${key.slice(1)}`);
1581
+ }
1582
+ function bareImports(source) {
1583
+ const out = /* @__PURE__ */ new Set();
1584
+ const re = /(?:^|[\n;])\s*(?:import|export)\s+(type\s)?(?:[^'";]*?\sfrom\s*)?['"]([^'"\n]+)['"]/g;
1585
+ for (const m of source.matchAll(re)) {
1586
+ const [, typeOnly, spec] = m;
1587
+ if (typeOnly || !spec || /^(\.|\/|node:|@\/|~|#)/.test(spec)) continue;
1588
+ out.add(spec);
1589
+ }
1590
+ return [...out];
1591
+ }
1592
+ function registryDeps(registryDir) {
1593
+ if (!fs3.existsSync(registryDir)) return [];
1594
+ const out = /* @__PURE__ */ new Set();
1595
+ for (const name of fs3.readdirSync(registryDir)) {
1596
+ if (!/\.(tsx?|jsx?)$/.test(name)) continue;
1597
+ for (const spec of bareImports(fs3.readFileSync(path6.join(registryDir, name), "utf8"))) {
1598
+ if (packageName(spec) !== PACKAGE_NAME) out.add(spec);
1599
+ }
1600
+ }
1601
+ return [...out].sort();
1602
+ }
1603
+ function derivedDeps(root) {
1604
+ const pkgDir = ownPackageDir();
1605
+ if (!pkgDir) return [];
1606
+ const out = registryDeps(path6.join(pkgDir, "registry", "ui"));
1607
+ if (isInstalled(root)) {
1608
+ try {
1609
+ const manifest = JSON.parse(fs3.readFileSync(path6.join(pkgDir, "package.json"), "utf8"));
1610
+ if (manifest.exports && typeof manifest.exports === "object") out.push(...frameworkSubpaths(manifest.exports));
1611
+ } catch {
1612
+ }
1613
+ }
1614
+ return out;
1615
+ }
1458
1616
 
1459
1617
  // src/vite/index.ts
1460
1618
  var DEDUPE = ["react", "react-dom", "@tanstack/react-router", "@tanstack/react-query"];
@@ -1498,22 +1656,9 @@ var KIT_DEPS = [
1498
1656
  "@base-ui/react/tooltip",
1499
1657
  "@base-ui/react/use-render"
1500
1658
  ];
1501
- function packageName(spec) {
1502
- const parts = spec.split("/");
1503
- return spec.startsWith("@") ? parts.slice(0, 2).join("/") : parts[0];
1504
- }
1505
- function hasPackage(fromDir, pkg) {
1506
- let dir = fromDir;
1507
- for (; ; ) {
1508
- if (fs3.existsSync(path5.join(dir, "node_modules", pkg))) return true;
1509
- const parent = path5.dirname(dir);
1510
- if (parent === dir) return false;
1511
- dir = parent;
1512
- }
1513
- }
1514
1659
  function optimizeInclude(root, extra) {
1515
- return [...RUNTIME_DEPS, ...KIT_DEPS, ...extra].filter(
1516
- (spec) => hasPackage(root, packageName(spec))
1660
+ return [.../* @__PURE__ */ new Set([...RUNTIME_DEPS, ...KIT_DEPS, ...derivedDeps(root), ...extra])].filter(
1661
+ (spec) => resolvesFrom(root, spec)
1517
1662
  );
1518
1663
  }
1519
1664
  var FILE_PAGE_DEPS = ["papaparse", "read-excel-file/browser"];
@@ -1525,9 +1670,9 @@ function conditionalDeps(model) {
1525
1670
  ];
1526
1671
  }
1527
1672
  function underPageRoot(pageRoot, file) {
1528
- const rel = path5.relative(pageRoot, file);
1673
+ const rel = path6.relative(pageRoot, file);
1529
1674
  if (rel.startsWith("..")) return false;
1530
- const segments = rel.split(path5.sep);
1675
+ const segments = rel.split(path6.sep);
1531
1676
  return !segments.some((s) => NON_ROUTE_DIRS.has(s) || s.startsWith(".") && s !== "..");
1532
1677
  }
1533
1678
  function isPageModuleFile(pageRoot, file) {
@@ -1541,22 +1686,24 @@ function isFilePageFile(pageRoot, file) {
1541
1686
  return underPageRoot(pageRoot, file) && FILE_PAGE_EXTENSIONS.some((ext) => lower.endsWith(ext));
1542
1687
  }
1543
1688
  function isApiFile(root, file) {
1544
- const rel = path5.relative(root, file);
1545
- return rel.startsWith(`server${path5.sep}api${path5.sep}`) && /\.(ts|tsx|js)$/.test(file) && !file.endsWith(".d.ts");
1689
+ const rel = path6.relative(root, file);
1690
+ return rel.startsWith(`server${path6.sep}api${path6.sep}`) && /\.(ts|tsx|js)$/.test(file) && !file.endsWith(".d.ts");
1546
1691
  }
1547
1692
  function isServerFile(root, file) {
1548
- const rel = path5.relative(root, file);
1549
- return rel === "server" || rel.startsWith(`server${path5.sep}`);
1693
+ const rel = path6.relative(root, file);
1694
+ return rel === "server" || rel.startsWith(`server${path6.sep}`);
1550
1695
  }
1551
1696
  function vantagePlugin(options) {
1552
- const root = path5.resolve(options.root);
1553
- const vantageDir = path5.join(root, VANTAGE_DIR);
1697
+ const root = path6.resolve(options.root);
1698
+ const vantageDir = path6.join(root, VANTAGE_DIR);
1554
1699
  let model = options.model ?? scanProject(root);
1555
1700
  let generated = Boolean(options.artifactsWritten);
1556
1701
  let shellHtml = null;
1557
- const pageRoot = () => model.pageDir === "" ? root : path5.join(root, model.pageDir);
1702
+ const pageRoot = () => model.pageDir === "" ? root : path6.join(root, model.pageDir);
1703
+ let appLang = extractAppLang(model);
1558
1704
  const emit = () => {
1559
1705
  generateArtifacts({ root, model });
1706
+ appLang = extractAppLang(model);
1560
1707
  generated = true;
1561
1708
  shellHtml = null;
1562
1709
  };
@@ -1588,10 +1735,10 @@ function vantagePlugin(options) {
1588
1735
  forwardConsole: { unhandledErrors: true, logLevels: ["warn", "error"] }
1589
1736
  },
1590
1737
  build: {
1591
- outDir: path5.join(root, "dist", "client"),
1738
+ outDir: path6.join(root, "dist", "client"),
1592
1739
  emptyOutDir: true,
1593
1740
  rollupOptions: {
1594
- input: path5.join(vantageDir, "index.html")
1741
+ input: path6.join(vantageDir, "index.html")
1595
1742
  }
1596
1743
  }
1597
1744
  };
@@ -1608,17 +1755,17 @@ function vantagePlugin(options) {
1608
1755
  if (!importer) return null;
1609
1756
  const imp = importer.split("?")[0];
1610
1757
  if (!imp.startsWith(root)) return null;
1611
- const relImp = path5.relative(root, imp);
1612
- if (relImp.startsWith(`server${path5.sep}`) || relImp.startsWith(VANTAGE_DIR) || relImp.includes("node_modules")) {
1758
+ const relImp = path6.relative(root, imp);
1759
+ if (relImp.startsWith(`server${path6.sep}`) || relImp.startsWith(VANTAGE_DIR) || relImp.includes("node_modules")) {
1613
1760
  return null;
1614
1761
  }
1615
1762
  let target = null;
1616
- if (source.startsWith(".")) target = path5.resolve(path5.dirname(imp), source);
1617
- else if (source.startsWith("/")) target = path5.join(root, source.slice(1));
1618
- else if (source === "server" || source.startsWith("server/")) target = path5.join(root, source);
1763
+ if (source.startsWith(".")) target = path6.resolve(path6.dirname(imp), source);
1764
+ else if (source.startsWith("/")) target = path6.join(root, source.slice(1));
1765
+ else if (source === "server" || source.startsWith("server/")) target = path6.join(root, source);
1619
1766
  if (!target) return null;
1620
- const relTarget = path5.relative(root, target);
1621
- if (relTarget === "server" || relTarget.startsWith(`server${path5.sep}`)) {
1767
+ const relTarget = path6.relative(root, target);
1768
+ if (relTarget === "server" || relTarget.startsWith(`server${path6.sep}`)) {
1622
1769
  this.error(
1623
1770
  `Client module "${relImp}" imports from server/ ("${source}"). server/ code must never reach the client bundle \u2014 move shared code to lib/.`
1624
1771
  );
@@ -1650,21 +1797,30 @@ function vantagePlugin(options) {
1650
1797
  if (model.hasServer) return apiMw(req, res, next);
1651
1798
  return next();
1652
1799
  });
1653
- const isStylesFile = (file) => path5.relative(pageRoot(), file) === "styles.css";
1800
+ const isStylesFile = (file) => path6.relative(pageRoot(), file) === "styles.css";
1654
1801
  const rootMoved = () => resolvePageRoot(root).dir !== model.pageDir;
1802
+ const notifyApiChange = (file) => {
1803
+ if (!isApiFile(root, file)) return;
1804
+ server.ws.send({ type: "custom", event: API_CHANGE_EVENT, data: { paths: [path6.relative(root, file)] } });
1805
+ };
1655
1806
  const onStructural = (file) => {
1656
1807
  const moved = rootMoved();
1657
- if (moved || isRoutedFile(pageRoot(), file) || isApiFile(root, file) || isStylesFile(file)) {
1808
+ const clientFacing = moved || isRoutedFile(pageRoot(), file) || isStylesFile(file);
1809
+ if (clientFacing || isApiFile(root, file)) {
1658
1810
  regenerate();
1811
+ if (!clientFacing) {
1812
+ notifyApiChange(file);
1813
+ return;
1814
+ }
1659
1815
  if (!moved && getDraftRoutes(server)?.isSuppressed(file)) return;
1660
1816
  server.ws.send({ type: "full-reload" });
1661
1817
  }
1662
1818
  };
1663
1819
  const isRouteDir = (dir) => {
1664
1820
  if (isServerFile(root, dir)) return true;
1665
- const rel = path5.relative(pageRoot(), dir);
1821
+ const rel = path6.relative(pageRoot(), dir);
1666
1822
  if (rel === "" || rel.startsWith("..")) return false;
1667
- return !rel.split(path5.sep).some((s) => NON_ROUTE_DIRS.has(s) || s.startsWith("."));
1823
+ return !rel.split(path6.sep).some((s) => NON_ROUTE_DIRS.has(s) || s.startsWith("."));
1668
1824
  };
1669
1825
  server.watcher.on("add", onStructural);
1670
1826
  server.watcher.on("unlink", onStructural);
@@ -1674,22 +1830,27 @@ function vantagePlugin(options) {
1674
1830
  server.watcher.on("unlinkDir", (dir) => {
1675
1831
  if (!rootMoved() && !isRouteDir(dir)) return;
1676
1832
  regenerate();
1677
- server.ws.send({ type: "full-reload" });
1833
+ if (!isServerFile(root, dir)) server.ws.send({ type: "full-reload" });
1678
1834
  });
1679
1835
  server.watcher.on("change", (file) => {
1680
1836
  if (isServerFile(root, file)) {
1681
1837
  const mods = server.moduleGraph.getModulesByFile(file);
1682
1838
  if (mods) for (const m of mods) server.moduleGraph.invalidateModule(m);
1839
+ notifyApiChange(file);
1683
1840
  return;
1684
1841
  }
1685
1842
  if (isFilePageFile(pageRoot(), file)) server.ws.send({ type: "full-reload" });
1843
+ if (model.layouts.some((l) => l.dir === "" && l.absFile === file) && extractAppLang(model) !== appLang) {
1844
+ emit();
1845
+ server.ws.send({ type: "full-reload" });
1846
+ }
1686
1847
  });
1687
1848
  return () => {
1688
1849
  server.middlewares.use(async (req, res, next) => {
1689
1850
  if (req.method !== "GET" && req.method !== "HEAD") return next();
1690
1851
  try {
1691
1852
  if (shellHtml === null) {
1692
- const raw = fs3.readFileSync(path5.join(vantageDir, "index.html"), "utf8");
1853
+ const raw = fs3.readFileSync(path6.join(vantageDir, "index.html"), "utf8");
1693
1854
  const shellUrl = `/${VANTAGE_DIR}/index.html`;
1694
1855
  shellHtml = await server.transformIndexHtml(shellUrl, raw, req.originalUrl);
1695
1856
  }
@@ -1712,5 +1873,5 @@ function vantagePlugin(options) {
1712
1873
  }
1713
1874
 
1714
1875
  export { vantagePlugin };
1715
- //# sourceMappingURL=chunk-IBGOCWJB.js.map
1716
- //# sourceMappingURL=chunk-IBGOCWJB.js.map
1876
+ //# sourceMappingURL=chunk-SDJTTMLK.js.map
1877
+ //# sourceMappingURL=chunk-SDJTTMLK.js.map