@elastic/isomer-studio 0.0.0 → 0.4.0

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 (406) hide show
  1. package/LICENSE.txt +93 -0
  2. package/NOTICE.txt +17329 -0
  3. package/README.md +64 -0
  4. package/THIRD_PARTY_LICENSES.md +404 -0
  5. package/bin/isomer-studio.js +10 -0
  6. package/dist/app/assets/codicon-5T574S7B.ttf +0 -0
  7. package/dist/app/assets/editor.worker.js +11 -0
  8. package/dist/app/assets/esbuild.wasm +0 -0
  9. package/dist/app/assets/json.worker.js +47 -0
  10. package/dist/app/assets/slack.css +1 -0
  11. package/dist/app/assets/studio.css +11 -0
  12. package/dist/app/assets/ts.worker.js +37029 -0
  13. package/dist/app/index.html +16 -0
  14. package/dist/apps/app_host.d.ts +8 -0
  15. package/dist/apps/app_host.d.ts.map +1 -0
  16. package/dist/apps/app_host.js +73 -0
  17. package/dist/apps/app_host.js.map +1 -0
  18. package/dist/browser/dev_host.d.ts +5 -0
  19. package/dist/browser/dev_host.d.ts.map +1 -0
  20. package/dist/browser/dev_host.js +46 -0
  21. package/dist/browser/dev_host.js.map +1 -0
  22. package/dist/browser/mount.d.ts +16 -0
  23. package/dist/browser/mount.d.ts.map +1 -0
  24. package/dist/browser/mount.js +37 -0
  25. package/dist/browser/mount.js.map +1 -0
  26. package/dist/browser/static_host.d.ts +5 -0
  27. package/dist/browser/static_host.d.ts.map +1 -0
  28. package/dist/browser/static_host.js +55 -0
  29. package/dist/browser/static_host.js.map +1 -0
  30. package/dist/chrome/accent.d.ts +14 -0
  31. package/dist/chrome/accent.d.ts.map +1 -0
  32. package/dist/chrome/accent.js +31 -0
  33. package/dist/chrome/accent.js.map +1 -0
  34. package/dist/chrome/app_pages.d.ts +13 -0
  35. package/dist/chrome/app_pages.d.ts.map +1 -0
  36. package/dist/chrome/app_pages.js +33 -0
  37. package/dist/chrome/app_pages.js.map +1 -0
  38. package/dist/chrome/color_mode.d.ts +10 -0
  39. package/dist/chrome/color_mode.d.ts.map +1 -0
  40. package/dist/chrome/color_mode.js +45 -0
  41. package/dist/chrome/color_mode.js.map +1 -0
  42. package/dist/chrome/dev_tint.d.ts +7 -0
  43. package/dist/chrome/dev_tint.d.ts.map +1 -0
  44. package/dist/chrome/dev_tint.js +31 -0
  45. package/dist/chrome/dev_tint.js.map +1 -0
  46. package/dist/chrome/header.d.ts +20 -0
  47. package/dist/chrome/header.d.ts.map +1 -0
  48. package/dist/chrome/header.js +124 -0
  49. package/dist/chrome/header.js.map +1 -0
  50. package/dist/chrome/icon_data_uri.d.ts +12 -0
  51. package/dist/chrome/icon_data_uri.d.ts.map +1 -0
  52. package/dist/chrome/icon_data_uri.js +21 -0
  53. package/dist/chrome/icon_data_uri.js.map +1 -0
  54. package/dist/chrome/isomer_mark.d.ts +17 -0
  55. package/dist/chrome/isomer_mark.d.ts.map +1 -0
  56. package/dist/chrome/isomer_mark.js +46 -0
  57. package/dist/chrome/isomer_mark.js.map +1 -0
  58. package/dist/chrome/nav.d.ts +22 -0
  59. package/dist/chrome/nav.d.ts.map +1 -0
  60. package/dist/chrome/nav.js +306 -0
  61. package/dist/chrome/nav.js.map +1 -0
  62. package/dist/chrome/nav_groups.d.ts +6 -0
  63. package/dist/chrome/nav_groups.d.ts.map +1 -0
  64. package/dist/chrome/nav_groups.js +48 -0
  65. package/dist/chrome/nav_groups.js.map +1 -0
  66. package/dist/chrome/nav_sections.d.ts +29 -0
  67. package/dist/chrome/nav_sections.d.ts.map +1 -0
  68. package/dist/chrome/nav_sections.js +55 -0
  69. package/dist/chrome/nav_sections.js.map +1 -0
  70. package/dist/chrome/oklch.d.ts +10 -0
  71. package/dist/chrome/oklch.d.ts.map +1 -0
  72. package/dist/chrome/oklch.js +61 -0
  73. package/dist/chrome/oklch.js.map +1 -0
  74. package/dist/chrome/primitive_glyph.d.ts +14 -0
  75. package/dist/chrome/primitive_glyph.d.ts.map +1 -0
  76. package/dist/chrome/primitive_glyph.js +48 -0
  77. package/dist/chrome/primitive_glyph.js.map +1 -0
  78. package/dist/chrome/primitive_heading.d.ts +14 -0
  79. package/dist/chrome/primitive_heading.d.ts.map +1 -0
  80. package/dist/chrome/primitive_heading.js +32 -0
  81. package/dist/chrome/primitive_heading.js.map +1 -0
  82. package/dist/chrome/primitive_peek.d.ts +8 -0
  83. package/dist/chrome/primitive_peek.d.ts.map +1 -0
  84. package/dist/chrome/primitive_peek.js +51 -0
  85. package/dist/chrome/primitive_peek.js.map +1 -0
  86. package/dist/chrome/primitive_search.d.ts +9 -0
  87. package/dist/chrome/primitive_search.d.ts.map +1 -0
  88. package/dist/chrome/primitive_search.js +93 -0
  89. package/dist/chrome/primitive_search.js.map +1 -0
  90. package/dist/chrome/route.d.ts +48 -0
  91. package/dist/chrome/route.d.ts.map +1 -0
  92. package/dist/chrome/route.js +136 -0
  93. package/dist/chrome/route.js.map +1 -0
  94. package/dist/cli/args.d.ts +39 -0
  95. package/dist/cli/args.d.ts.map +1 -0
  96. package/dist/cli/args.js +171 -0
  97. package/dist/cli/args.js.map +1 -0
  98. package/dist/cli/run.d.ts +15 -0
  99. package/dist/cli/run.d.ts.map +1 -0
  100. package/dist/cli/run.js +113 -0
  101. package/dist/cli/run.js.map +1 -0
  102. package/dist/cli.d.ts +2 -0
  103. package/dist/cli.d.ts.map +1 -0
  104. package/dist/cli.js +22 -0
  105. package/dist/cli.js.map +1 -0
  106. package/dist/config.d.ts +118 -0
  107. package/dist/config.d.ts.map +1 -0
  108. package/dist/config.js +11 -0
  109. package/dist/config.js.map +1 -0
  110. package/dist/dev/code_editor.d.ts +10 -0
  111. package/dist/dev/code_editor.d.ts.map +1 -0
  112. package/dist/dev/code_editor.js +22 -0
  113. package/dist/dev/code_editor.js.map +1 -0
  114. package/dist/dev/dev_view.d.ts +9 -0
  115. package/dist/dev/dev_view.d.ts.map +1 -0
  116. package/dist/dev/dev_view.js +65 -0
  117. package/dist/dev/dev_view.js.map +1 -0
  118. package/dist/dev/editor_panel.d.ts +17 -0
  119. package/dist/dev/editor_panel.d.ts.map +1 -0
  120. package/dist/dev/editor_panel.js +51 -0
  121. package/dist/dev/editor_panel.js.map +1 -0
  122. package/dist/dev/monaco_editor.d.ts +15 -0
  123. package/dist/dev/monaco_editor.d.ts.map +1 -0
  124. package/dist/dev/monaco_editor.js +159 -0
  125. package/dist/dev/monaco_editor.js.map +1 -0
  126. package/dist/dev/preview_panel.d.ts +10 -0
  127. package/dist/dev/preview_panel.d.ts.map +1 -0
  128. package/dist/dev/preview_panel.js +45 -0
  129. package/dist/dev/preview_panel.js.map +1 -0
  130. package/dist/dev/prop_reference.d.ts +9 -0
  131. package/dist/dev/prop_reference.d.ts.map +1 -0
  132. package/dist/dev/prop_reference.js +134 -0
  133. package/dist/dev/prop_reference.js.map +1 -0
  134. package/dist/dev/tsx_language.d.ts +10 -0
  135. package/dist/dev/tsx_language.d.ts.map +1 -0
  136. package/dist/dev/tsx_language.js +283 -0
  137. package/dist/dev/tsx_language.js.map +1 -0
  138. package/dist/dev/use_editor.d.ts +23 -0
  139. package/dist/dev/use_editor.d.ts.map +1 -0
  140. package/dist/dev/use_editor.js +124 -0
  141. package/dist/dev/use_editor.js.map +1 -0
  142. package/dist/docs/docs_view.d.ts +10 -0
  143. package/dist/docs/docs_view.d.ts.map +1 -0
  144. package/dist/docs/docs_view.js +80 -0
  145. package/dist/docs/docs_view.js.map +1 -0
  146. package/dist/docs/example_source.d.ts +7 -0
  147. package/dist/docs/example_source.d.ts.map +1 -0
  148. package/dist/docs/example_source.js +56 -0
  149. package/dist/docs/example_source.js.map +1 -0
  150. package/dist/docs/examples_panel.d.ts +10 -0
  151. package/dist/docs/examples_panel.d.ts.map +1 -0
  152. package/dist/docs/examples_panel.js +51 -0
  153. package/dist/docs/examples_panel.js.map +1 -0
  154. package/dist/docs/gallery_view.d.ts +9 -0
  155. package/dist/docs/gallery_view.d.ts.map +1 -0
  156. package/dist/docs/gallery_view.js +98 -0
  157. package/dist/docs/gallery_view.js.map +1 -0
  158. package/dist/docs/inline_code.d.ts +11 -0
  159. package/dist/docs/inline_code.d.ts.map +1 -0
  160. package/dist/docs/inline_code.js +24 -0
  161. package/dist/docs/inline_code.js.map +1 -0
  162. package/dist/docs/on_this_page.d.ts +17 -0
  163. package/dist/docs/on_this_page.d.ts.map +1 -0
  164. package/dist/docs/on_this_page.js +77 -0
  165. package/dist/docs/on_this_page.js.map +1 -0
  166. package/dist/docs/props_table.d.ts +14 -0
  167. package/dist/docs/props_table.d.ts.map +1 -0
  168. package/dist/docs/props_table.js +34 -0
  169. package/dist/docs/props_table.js.map +1 -0
  170. package/dist/home/apps_section.d.ts +6 -0
  171. package/dist/home/apps_section.d.ts.map +1 -0
  172. package/dist/home/apps_section.js +44 -0
  173. package/dist/home/apps_section.js.map +1 -0
  174. package/dist/home/featured_strip.d.ts +12 -0
  175. package/dist/home/featured_strip.d.ts.map +1 -0
  176. package/dist/home/featured_strip.js +176 -0
  177. package/dist/home/featured_strip.js.map +1 -0
  178. package/dist/home/home_view.d.ts +11 -0
  179. package/dist/home/home_view.d.ts.map +1 -0
  180. package/dist/home/home_view.js +261 -0
  181. package/dist/home/home_view.js.map +1 -0
  182. package/dist/home/links.d.ts +8 -0
  183. package/dist/home/links.d.ts.map +1 -0
  184. package/dist/home/links.js +14 -0
  185. package/dist/home/links.js.map +1 -0
  186. package/dist/home/loaded_panel.d.ts +6 -0
  187. package/dist/home/loaded_panel.d.ts.map +1 -0
  188. package/dist/home/loaded_panel.js +116 -0
  189. package/dist/home/loaded_panel.js.map +1 -0
  190. package/dist/home/surface_chart.d.ts +6 -0
  191. package/dist/home/surface_chart.d.ts.map +1 -0
  192. package/dist/home/surface_chart.js +263 -0
  193. package/dist/home/surface_chart.js.map +1 -0
  194. package/dist/home/tokens.d.ts +49 -0
  195. package/dist/home/tokens.d.ts.map +1 -0
  196. package/dist/home/tokens.js +171 -0
  197. package/dist/home/tokens.js.map +1 -0
  198. package/dist/index.d.ts +6 -0
  199. package/dist/index.d.ts.map +1 -0
  200. package/dist/index.js +9 -0
  201. package/dist/index.js.map +1 -0
  202. package/dist/model/app_problems.d.ts +4 -0
  203. package/dist/model/app_problems.d.ts.map +1 -0
  204. package/dist/model/app_problems.js +90 -0
  205. package/dist/model/app_problems.js.map +1 -0
  206. package/dist/model/authoring_types.d.ts +23 -0
  207. package/dist/model/authoring_types.d.ts.map +1 -0
  208. package/dist/model/authoring_types.js +35 -0
  209. package/dist/model/authoring_types.js.map +1 -0
  210. package/dist/model/compile_jsx.d.ts +19 -0
  211. package/dist/model/compile_jsx.d.ts.map +1 -0
  212. package/dist/model/compile_jsx.js +55 -0
  213. package/dist/model/compile_jsx.js.map +1 -0
  214. package/dist/model/compose_example.d.ts +9 -0
  215. package/dist/model/compose_example.d.ts.map +1 -0
  216. package/dist/model/compose_example.js +24 -0
  217. package/dist/model/compose_example.js.map +1 -0
  218. package/dist/model/composition_key.d.ts +6 -0
  219. package/dist/model/composition_key.d.ts.map +1 -0
  220. package/dist/model/composition_key.js +26 -0
  221. package/dist/model/composition_key.js.map +1 -0
  222. package/dist/model/describe_runtime.d.ts +33 -0
  223. package/dist/model/describe_runtime.d.ts.map +1 -0
  224. package/dist/model/describe_runtime.js +77 -0
  225. package/dist/model/describe_runtime.js.map +1 -0
  226. package/dist/model/featured.d.ts +11 -0
  227. package/dist/model/featured.d.ts.map +1 -0
  228. package/dist/model/featured.js +70 -0
  229. package/dist/model/featured.js.map +1 -0
  230. package/dist/model/jsx_transform.d.ts +10 -0
  231. package/dist/model/jsx_transform.d.ts.map +1 -0
  232. package/dist/model/jsx_transform.js +31 -0
  233. package/dist/model/jsx_transform.js.map +1 -0
  234. package/dist/model/png_manifest.d.ts +23 -0
  235. package/dist/model/png_manifest.d.ts.map +1 -0
  236. package/dist/model/png_manifest.js +26 -0
  237. package/dist/model/png_manifest.js.map +1 -0
  238. package/dist/model/read_examples.d.ts +12 -0
  239. package/dist/model/read_examples.d.ts.map +1 -0
  240. package/dist/model/read_examples.js +43 -0
  241. package/dist/model/read_examples.js.map +1 -0
  242. package/dist/model/search.d.ts +4 -0
  243. package/dist/model/search.d.ts.map +1 -0
  244. package/dist/model/search.js +29 -0
  245. package/dist/model/search.js.map +1 -0
  246. package/dist/model/sha256.d.ts +3 -0
  247. package/dist/model/sha256.d.ts.map +1 -0
  248. package/dist/model/sha256.js +72 -0
  249. package/dist/model/sha256.js.map +1 -0
  250. package/dist/model/slack_limits.d.ts +9 -0
  251. package/dist/model/slack_limits.d.ts.map +1 -0
  252. package/dist/model/slack_limits.js +213 -0
  253. package/dist/model/slack_limits.js.map +1 -0
  254. package/dist/node/app_bundle.d.ts +45 -0
  255. package/dist/node/app_bundle.d.ts.map +1 -0
  256. package/dist/node/app_bundle.js +212 -0
  257. package/dist/node/app_bundle.js.map +1 -0
  258. package/dist/node/build_site.d.ts +28 -0
  259. package/dist/node/build_site.d.ts.map +1 -0
  260. package/dist/node/build_site.js +90 -0
  261. package/dist/node/build_site.js.map +1 -0
  262. package/dist/node/check.d.ts +40 -0
  263. package/dist/node/check.d.ts.map +1 -0
  264. package/dist/node/check.js +162 -0
  265. package/dist/node/check.js.map +1 -0
  266. package/dist/node/dev_bundle.d.ts +21 -0
  267. package/dist/node/dev_bundle.d.ts.map +1 -0
  268. package/dist/node/dev_bundle.js +121 -0
  269. package/dist/node/dev_bundle.js.map +1 -0
  270. package/dist/node/dev_server.d.ts +16 -0
  271. package/dist/node/dev_server.d.ts.map +1 -0
  272. package/dist/node/dev_server.js +291 -0
  273. package/dist/node/dev_server.js.map +1 -0
  274. package/dist/node/init_config.d.ts +30 -0
  275. package/dist/node/init_config.d.ts.map +1 -0
  276. package/dist/node/init_config.js +158 -0
  277. package/dist/node/init_config.js.map +1 -0
  278. package/dist/node/load_config.d.ts +34 -0
  279. package/dist/node/load_config.d.ts.map +1 -0
  280. package/dist/node/load_config.js +246 -0
  281. package/dist/node/load_config.js.map +1 -0
  282. package/dist/node/project_resolution.d.ts +17 -0
  283. package/dist/node/project_resolution.d.ts.map +1 -0
  284. package/dist/node/project_resolution.js +66 -0
  285. package/dist/node/project_resolution.js.map +1 -0
  286. package/dist/node/rasterize.d.ts +23 -0
  287. package/dist/node/rasterize.d.ts.map +1 -0
  288. package/dist/node/rasterize.js +79 -0
  289. package/dist/node/rasterize.js.map +1 -0
  290. package/dist/node/report.d.ts +8 -0
  291. package/dist/node/report.d.ts.map +1 -0
  292. package/dist/node/report.js +57 -0
  293. package/dist/node/report.js.map +1 -0
  294. package/dist/node/resolve_hooks.d.ts +16 -0
  295. package/dist/node/resolve_hooks.d.ts.map +1 -0
  296. package/dist/node/resolve_hooks.js +104 -0
  297. package/dist/node/resolve_hooks.js.map +1 -0
  298. package/dist/studio.d.ts +4 -0
  299. package/dist/studio.d.ts.map +1 -0
  300. package/dist/studio.js +188 -0
  301. package/dist/studio.js.map +1 -0
  302. package/dist/studio_context.d.ts +27 -0
  303. package/dist/studio_context.d.ts.map +1 -0
  304. package/dist/studio_context.js +17 -0
  305. package/dist/studio_context.js.map +1 -0
  306. package/dist/surfaces/adopt_stylesheet.d.ts +7 -0
  307. package/dist/surfaces/adopt_stylesheet.d.ts.map +1 -0
  308. package/dist/surfaces/adopt_stylesheet.js +64 -0
  309. package/dist/surfaces/adopt_stylesheet.js.map +1 -0
  310. package/dist/surfaces/app_preview.d.ts +4 -0
  311. package/dist/surfaces/app_preview.d.ts.map +1 -0
  312. package/dist/surfaces/app_preview.js +28 -0
  313. package/dist/surfaces/app_preview.js.map +1 -0
  314. package/dist/surfaces/app_surface.d.ts +9 -0
  315. package/dist/surfaces/app_surface.d.ts.map +1 -0
  316. package/dist/surfaces/app_surface.js +27 -0
  317. package/dist/surfaces/app_surface.js.map +1 -0
  318. package/dist/surfaces/applicable_enhancements.d.ts +4 -0
  319. package/dist/surfaces/applicable_enhancements.d.ts.map +1 -0
  320. package/dist/surfaces/applicable_enhancements.js +16 -0
  321. package/dist/surfaces/applicable_enhancements.js.map +1 -0
  322. package/dist/surfaces/enhancement_select.d.ts +10 -0
  323. package/dist/surfaces/enhancement_select.d.ts.map +1 -0
  324. package/dist/surfaces/enhancement_select.js +28 -0
  325. package/dist/surfaces/enhancement_select.js.map +1 -0
  326. package/dist/surfaces/example_picker.d.ts +11 -0
  327. package/dist/surfaces/example_picker.d.ts.map +1 -0
  328. package/dist/surfaces/example_picker.js +44 -0
  329. package/dist/surfaces/example_picker.js.map +1 -0
  330. package/dist/surfaces/format_source.d.ts +4 -0
  331. package/dist/surfaces/format_source.d.ts.map +1 -0
  332. package/dist/surfaces/format_source.js +30 -0
  333. package/dist/surfaces/format_source.js.map +1 -0
  334. package/dist/surfaces/html_surface.d.ts +14 -0
  335. package/dist/surfaces/html_surface.d.ts.map +1 -0
  336. package/dist/surfaces/html_surface.js +122 -0
  337. package/dist/surfaces/html_surface.js.map +1 -0
  338. package/dist/surfaces/png_surface.d.ts +13 -0
  339. package/dist/surfaces/png_surface.d.ts.map +1 -0
  340. package/dist/surfaces/png_surface.js +68 -0
  341. package/dist/surfaces/png_surface.js.map +1 -0
  342. package/dist/surfaces/react_surface.d.ts +11 -0
  343. package/dist/surfaces/react_surface.d.ts.map +1 -0
  344. package/dist/surfaces/react_surface.js +55 -0
  345. package/dist/surfaces/react_surface.js.map +1 -0
  346. package/dist/surfaces/render_output.d.ts +31 -0
  347. package/dist/surfaces/render_output.d.ts.map +1 -0
  348. package/dist/surfaces/render_output.js +119 -0
  349. package/dist/surfaces/render_output.js.map +1 -0
  350. package/dist/surfaces/scaled_preview.d.ts +17 -0
  351. package/dist/surfaces/scaled_preview.d.ts.map +1 -0
  352. package/dist/surfaces/scaled_preview.js +74 -0
  353. package/dist/surfaces/scaled_preview.js.map +1 -0
  354. package/dist/surfaces/shadow_root.d.ts +8 -0
  355. package/dist/surfaces/shadow_root.d.ts.map +1 -0
  356. package/dist/surfaces/shadow_root.js +41 -0
  357. package/dist/surfaces/shadow_root.js.map +1 -0
  358. package/dist/surfaces/slack_surface.d.ts +12 -0
  359. package/dist/surfaces/slack_surface.d.ts.map +1 -0
  360. package/dist/surfaces/slack_surface.js +27 -0
  361. package/dist/surfaces/slack_surface.js.map +1 -0
  362. package/dist/surfaces/snapshot_surface.d.ts +6 -0
  363. package/dist/surfaces/snapshot_surface.d.ts.map +1 -0
  364. package/dist/surfaces/snapshot_surface.js +5 -0
  365. package/dist/surfaces/snapshot_surface.js.map +1 -0
  366. package/dist/surfaces/surface_board.d.ts +19 -0
  367. package/dist/surfaces/surface_board.d.ts.map +1 -0
  368. package/dist/surfaces/surface_board.js +128 -0
  369. package/dist/surfaces/surface_board.js.map +1 -0
  370. package/dist/surfaces/surface_frame.d.ts +8 -0
  371. package/dist/surfaces/surface_frame.d.ts.map +1 -0
  372. package/dist/surfaces/surface_frame.js +4 -0
  373. package/dist/surfaces/surface_frame.js.map +1 -0
  374. package/dist/surfaces/surface_logos.d.ts +9 -0
  375. package/dist/surfaces/surface_logos.d.ts.map +1 -0
  376. package/dist/surfaces/surface_logos.js +21 -0
  377. package/dist/surfaces/surface_logos.js.map +1 -0
  378. package/dist/surfaces/surface_preview.d.ts +32 -0
  379. package/dist/surfaces/surface_preview.d.ts.map +1 -0
  380. package/dist/surfaces/surface_preview.js +66 -0
  381. package/dist/surfaces/surface_preview.js.map +1 -0
  382. package/dist/surfaces/surface_select.d.ts +34 -0
  383. package/dist/surfaces/surface_select.d.ts.map +1 -0
  384. package/dist/surfaces/surface_select.js +119 -0
  385. package/dist/surfaces/surface_select.js.map +1 -0
  386. package/dist/surfaces/text_surfaces.d.ts +14 -0
  387. package/dist/surfaces/text_surfaces.d.ts.map +1 -0
  388. package/dist/surfaces/text_surfaces.js +31 -0
  389. package/dist/surfaces/text_surfaces.js.map +1 -0
  390. package/dist/surfaces/zoom_select.d.ts +9 -0
  391. package/dist/surfaces/zoom_select.d.ts.map +1 -0
  392. package/dist/surfaces/zoom_select.js +32 -0
  393. package/dist/surfaces/zoom_select.js.map +1 -0
  394. package/dist/types.d.ts +32 -0
  395. package/dist/types.d.ts.map +1 -0
  396. package/dist/types.js +9 -0
  397. package/dist/types.js.map +1 -0
  398. package/docs/ci.md +55 -0
  399. package/docs/commands.md +167 -0
  400. package/docs/config.md +192 -0
  401. package/docs/images/home.png +0 -0
  402. package/docs/images/reference.png +0 -0
  403. package/docs/images/workbench.png +0 -0
  404. package/docs/index.md +96 -0
  405. package/docs/toc.yml +10 -0
  406. package/package.json +89 -5
@@ -0,0 +1,246 @@
1
+ /*
2
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3
+ * or more contributor license agreements. Licensed under the Elastic License
4
+ * 2.0; you may not use this file except in compliance with the Elastic License
5
+ * 2.0.
6
+ */
7
+ import { randomUUID } from 'node:crypto';
8
+ import { existsSync, readFileSync, realpathSync } from 'node:fs';
9
+ import * as nodeModule from 'node:module';
10
+ import { createRequire } from 'node:module';
11
+ import { dirname, join, resolve } from 'node:path';
12
+ import { pathToFileURL } from 'node:url';
13
+ import { register as registerCommonJs } from 'tsx/cjs/api';
14
+ import { register as registerEsm } from 'tsx/esm/api';
15
+ import { appProblems } from '../model/app_problems.js';
16
+ import { featuredProblems, runtimePrimitiveTypes } from '../model/featured.js';
17
+ import { PACKAGE_DIR, RUNS_FROM_SOURCE } from './app_bundle.js';
18
+ import { projectDirectory } from './project_resolution.js';
19
+ import { patchRequire, resolveSync } from './resolve_hooks.js';
20
+ export const DEFAULT_CONFIG_NAMES = [
21
+ 'isomer-studio.config.ts',
22
+ 'isomer-studio.config.tsx',
23
+ 'isomer-studio.config.js',
24
+ ];
25
+ /** The first default config name that exists in `cwd`. */
26
+ export const findDefaultConfig = (cwd) => DEFAULT_CONFIG_NAMES.map((name) => resolve(cwd, name)).find((path) => existsSync(path));
27
+ /** `config` against `cwd`, or the first default name that exists there. */
28
+ export const resolveConfigPath = (cwd, config) => {
29
+ if (config !== undefined) {
30
+ const path = resolve(cwd, config);
31
+ if (!existsSync(path)) {
32
+ throw new Error(`No Studio config at ${path}.`);
33
+ }
34
+ return path;
35
+ }
36
+ const found = findDefaultConfig(cwd);
37
+ if (found === undefined) {
38
+ throw new Error(`No Studio config in ${cwd}. Run \`npx @elastic/isomer-studio init\` to create one, or pass --config.`);
39
+ }
40
+ return found;
41
+ };
42
+ const isRecord = (value) => typeof value === 'object' && value !== null;
43
+ const isStudioConfig = (value) => isRecord(value) &&
44
+ isRecord(value.runtime) &&
45
+ isRecord(value.runtime.surfaces);
46
+ /** The default export, unwrapping the extra `default` a CommonJS build adds. */
47
+ const defaultExport = (namespace) => {
48
+ const outer = isRecord(namespace) ? namespace.default : undefined;
49
+ return isRecord(outer) && !isStudioConfig(outer) ? outer.default : outer;
50
+ };
51
+ const reactDirectory = (from) => {
52
+ try {
53
+ return dirname(realpathSync(createRequire(from).resolve('react/package.json')));
54
+ }
55
+ catch {
56
+ return undefined;
57
+ }
58
+ };
59
+ /** The installed entry of `@elastic/isomer-runtime` as seen from `configPath`; its `exports` hide `package.json`. */
60
+ const runtimeEntry = (configPath) => {
61
+ try {
62
+ return createRequire(configPath).resolve('@elastic/isomer-runtime');
63
+ }
64
+ catch {
65
+ return undefined;
66
+ }
67
+ };
68
+ /** Throws unless the config resolves React 18, which EUI needs, and `@elastic/isomer-runtime` resolves the same copy. */
69
+ export const assertSingleReact = (configPath) => {
70
+ const configReact = reactDirectory(configPath);
71
+ if (configReact === undefined) {
72
+ throw new Error(`React is not installed where the Studio config is: ${configPath}. Install react@18 and react-dom@18.`);
73
+ }
74
+ const { version } = JSON.parse(readFileSync(join(configReact, 'package.json'), 'utf8'));
75
+ if (typeof version !== 'string' || !version.startsWith('18.')) {
76
+ throw new Error(`Isomer Studio needs React 18, which EUI requires; ${configPath} resolves React ${String(version)}.`);
77
+ }
78
+ const entry = runtimeEntry(configPath);
79
+ const runtimeReact = entry === undefined ? undefined : reactDirectory(entry);
80
+ if (runtimeReact !== undefined && runtimeReact !== configReact) {
81
+ throw new Error([
82
+ 'The Studio config and @elastic/isomer-runtime resolve different copies of React:',
83
+ ` config: ${configReact}`,
84
+ ` runtime: ${runtimeReact}`,
85
+ 'Install one React for both, for example by deduplicating your lockfile.',
86
+ ].join('\n'));
87
+ }
88
+ };
89
+ /** Packages an app must share with the Studio for EUI's theme context and Emotion's cache to reach it. */
90
+ const SHARED_WITH_APPS = ['@elastic/eui', '@emotion/react'];
91
+ /** `@elastic/eui`'s peers, which pnpm must resolve alike for the config and the Studio to share one EUI. */
92
+ const EUI_PEERS = [
93
+ 'react',
94
+ 'react-dom',
95
+ '@emotion/react',
96
+ '@emotion/css',
97
+ '@elastic/eui-theme-borealis',
98
+ '@elastic/datemath',
99
+ 'moment',
100
+ ];
101
+ const packageDirectory = (name, from) => {
102
+ try {
103
+ return dirname(realpathSync(createRequire(from).resolve(`${name}/package.json`)));
104
+ }
105
+ catch {
106
+ return undefined;
107
+ }
108
+ };
109
+ const studioVersions = (studioDir) => {
110
+ const { dependencies = {}, peerDependencies = {} } = JSON.parse(readFileSync(join(studioDir, 'package.json'), 'utf8'));
111
+ return { ...peerDependencies, ...dependencies };
112
+ };
113
+ /** Throws when the config would load a different EUI or Emotion from the Studio's, which its apps share; one it cannot resolve at all is fine. */
114
+ export const assertSingleEui = (configPath, studioDir = PACKAGE_DIR) => {
115
+ const studioPackage = join(studioDir, 'package.json');
116
+ const mismatched = SHARED_WITH_APPS.map((name) => ({
117
+ name,
118
+ config: packageDirectory(name, configPath),
119
+ studio: packageDirectory(name, studioPackage),
120
+ })).filter(({ config, studio }) => config !== undefined && config !== studio);
121
+ if (!mismatched.length) {
122
+ return;
123
+ }
124
+ const versions = studioVersions(studioDir);
125
+ const wanted = ['@elastic/eui', ...EUI_PEERS].map((name) => versions[name] === undefined ? name : `${name}@${versions[name]}`);
126
+ throw new Error([
127
+ 'The Studio config and @elastic/isomer-studio resolve different copies of packages that Studio apps share:',
128
+ ...mismatched.flatMap(({ name, config, studio }) => [
129
+ ` ${name}`,
130
+ ` config: ${config}`,
131
+ ` studio: ${studio ?? '(not installed)'}`,
132
+ ]),
133
+ `Install the Studio's versions beside the config, then deduplicate your lockfile: ${wanted.join(', ')}.`,
134
+ ].join('\n'));
135
+ };
136
+ /** The `tsconfig.json` nearest the config, which `tsx` applies to the files it includes. */
137
+ export const nearestTsconfig = (configPath) => {
138
+ for (let dir = dirname(configPath);; dir = dirname(dir)) {
139
+ const candidate = join(dir, 'tsconfig.json');
140
+ if (existsSync(candidate)) {
141
+ return candidate;
142
+ }
143
+ if (dirname(dir) === dir) {
144
+ return undefined;
145
+ }
146
+ }
147
+ };
148
+ /** Registers `tsx`'s CommonJS and ESM hooks under one namespace, as `tsImport` does; the CommonJS hook reads `TSX_TSCONFIG_PATH` as it registers. */
149
+ const registerTsx = (tsconfig) => {
150
+ const previous = process.env.TSX_TSCONFIG_PATH;
151
+ if (tsconfig !== undefined) {
152
+ process.env.TSX_TSCONFIG_PATH = tsconfig;
153
+ }
154
+ try {
155
+ const namespace = randomUUID();
156
+ registerCommonJs({ namespace });
157
+ return registerEsm({
158
+ namespace,
159
+ ...(tsconfig === undefined ? {} : { tsconfig }),
160
+ }).import;
161
+ }
162
+ finally {
163
+ if (previous === undefined) {
164
+ delete process.env.TSX_TSCONFIG_PATH;
165
+ }
166
+ else {
167
+ process.env.TSX_TSCONFIG_PATH = previous;
168
+ }
169
+ }
170
+ };
171
+ /** The Studio config a module namespace default-exports, or an error naming `configPath`. */
172
+ export const studioConfigFrom = (namespace, configPath) => {
173
+ const config = defaultExport(namespace);
174
+ if (!isStudioConfig(config)) {
175
+ throw new Error(`${configPath} must default-export defineStudioConfig({ runtime, ... }).`);
176
+ }
177
+ const problems = appProblems(config.apps);
178
+ if (problems.length) {
179
+ throw new Error([
180
+ `${configPath} has invalid apps:`,
181
+ ...problems.map((line) => ` ${line}`),
182
+ ].join('\n'));
183
+ }
184
+ const featured = featuredProblems(config.featured, runtimePrimitiveTypes(config.runtime));
185
+ if (featured.length) {
186
+ throw new Error([
187
+ `${configPath} has invalid featured primitives:`,
188
+ ...featured.map((line) => ` ${line}`),
189
+ ].join('\n'));
190
+ }
191
+ if (config.apps?.length) {
192
+ assertSingleEui(configPath);
193
+ }
194
+ return config;
195
+ };
196
+ let registeredProject;
197
+ /** Applies the Studio's module resolution to every later `import` in this process; a process serves one project. */
198
+ export const registerProjectResolution = (configPath) => {
199
+ const projectDir = projectDirectory(configPath);
200
+ if (registeredProject !== undefined) {
201
+ if (registeredProject !== projectDir) {
202
+ throw new Error(`Module resolution is registered for ${registeredProject}, not ${projectDir}.`);
203
+ }
204
+ return;
205
+ }
206
+ registeredProject = projectDir;
207
+ const data = { projectDir, studioDir: PACKAGE_DIR };
208
+ // Node 22.15 and later; before it, `register` covers `import` and `patchRequire` covers `require`.
209
+ const { registerHooks } = nodeModule;
210
+ if (registerHooks) {
211
+ registerHooks({ resolve: resolveSync(data) });
212
+ return;
213
+ }
214
+ nodeModule.register(`./resolve_hooks${RUNS_FROM_SOURCE ? '.ts' : '.js'}`, import.meta.url, { data });
215
+ patchRequire(data);
216
+ };
217
+ /**
218
+ * Imports the config and the modules it names into one module graph, compiled with the config's nearest `tsconfig.json`.
219
+ * Each `tsx` namespace is a separate graph, so a package both import would otherwise load twice.
220
+ */
221
+ export const createStudioImporter = (configPath, { loader = 'tsx' } = {}) => {
222
+ if (loader === 'none') {
223
+ return (path) => import(pathToFileURL(path).href);
224
+ }
225
+ let scoped;
226
+ return (path) => {
227
+ scoped ??= registerTsx(nearestTsconfig(configPath));
228
+ return scoped(pathToFileURL(path).href, import.meta.url);
229
+ };
230
+ };
231
+ /** Imports the config's default export in Node; `tsx` compiles TypeScript and leaves resolution to Node. */
232
+ export const loadStudioConfig = async (configPath, { loader, importModule = createStudioImporter(configPath, { loader }), } = {}) => {
233
+ assertSingleReact(configPath);
234
+ return studioConfigFrom(await importModule(configPath), configPath);
235
+ };
236
+ const isRenderToString = (value) => typeof value === 'function';
237
+ /** `react-dom/server`'s `renderToString`, from the config's own React. */
238
+ export const loadRenderToString = (configPath) => {
239
+ const server = createRequire(configPath)('react-dom/server');
240
+ const renderToString = isRecord(server) ? server.renderToString : undefined;
241
+ if (!isRenderToString(renderToString)) {
242
+ throw new Error('react-dom/server has no renderToString.');
243
+ }
244
+ return renderToString;
245
+ };
246
+ //# sourceMappingURL=load_config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load_config.js","sourceRoot":"","sources":["../../src/node/load_config.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one\n * or more contributor license agreements. Licensed under the Elastic License\n * 2.0; you may not use this file except in compliance with the Elastic License\n * 2.0.\n */\n\nimport { randomUUID } from 'node:crypto';\nimport { existsSync, readFileSync, realpathSync } from 'node:fs';\nimport * as nodeModule from 'node:module';\nimport { createRequire } from 'node:module';\nimport { dirname, join, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\nimport type { ReactNode } from 'react';\nimport { register as registerCommonJs } from 'tsx/cjs/api';\nimport type { ScopedImport } from 'tsx/esm/api';\nimport { register as registerEsm } from 'tsx/esm/api';\n\nimport type { StudioConfig } from '../config';\nimport { appProblems } from '../model/app_problems';\nimport { featuredProblems, runtimePrimitiveTypes } from '../model/featured';\n\nimport { PACKAGE_DIR, RUNS_FROM_SOURCE } from './app_bundle';\nimport { projectDirectory } from './project_resolution';\nimport type { ResolveHooksData } from './resolve_hooks';\nimport { patchRequire, resolveSync } from './resolve_hooks';\n\nexport type ConfigLoader = 'none' | 'tsx';\n\nexport const DEFAULT_CONFIG_NAMES = [\n 'isomer-studio.config.ts',\n 'isomer-studio.config.tsx',\n 'isomer-studio.config.js',\n] as const;\n\n/** The first default config name that exists in `cwd`. */\nexport const findDefaultConfig = (cwd: string): string | undefined =>\n DEFAULT_CONFIG_NAMES.map((name) => resolve(cwd, name)).find((path) =>\n existsSync(path)\n );\n\n/** `config` against `cwd`, or the first default name that exists there. */\nexport const resolveConfigPath = (cwd: string, config?: string): string => {\n if (config !== undefined) {\n const path = resolve(cwd, config);\n if (!existsSync(path)) {\n throw new Error(`No Studio config at ${path}.`);\n }\n return path;\n }\n const found = findDefaultConfig(cwd);\n if (found === undefined) {\n throw new Error(\n `No Studio config in ${cwd}. Run \\`npx @elastic/isomer-studio init\\` to create one, or pass --config.`\n );\n }\n return found;\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null;\n\nconst isStudioConfig = (value: unknown): value is StudioConfig =>\n isRecord(value) &&\n isRecord(value.runtime) &&\n isRecord(value.runtime.surfaces);\n\n/** The default export, unwrapping the extra `default` a CommonJS build adds. */\nconst defaultExport = (namespace: unknown): unknown => {\n const outer = isRecord(namespace) ? namespace.default : undefined;\n return isRecord(outer) && !isStudioConfig(outer) ? outer.default : outer;\n};\n\nconst reactDirectory = (from: string): string | undefined => {\n try {\n return dirname(\n realpathSync(createRequire(from).resolve('react/package.json'))\n );\n } catch {\n return undefined;\n }\n};\n\n/** The installed entry of `@elastic/isomer-runtime` as seen from `configPath`; its `exports` hide `package.json`. */\nconst runtimeEntry = (configPath: string): string | undefined => {\n try {\n return createRequire(configPath).resolve('@elastic/isomer-runtime');\n } catch {\n return undefined;\n }\n};\n\n/** Throws unless the config resolves React 18, which EUI needs, and `@elastic/isomer-runtime` resolves the same copy. */\nexport const assertSingleReact = (configPath: string): void => {\n const configReact = reactDirectory(configPath);\n if (configReact === undefined) {\n throw new Error(\n `React is not installed where the Studio config is: ${configPath}. Install react@18 and react-dom@18.`\n );\n }\n const { version } = JSON.parse(\n readFileSync(join(configReact, 'package.json'), 'utf8')\n ) as { version?: unknown };\n if (typeof version !== 'string' || !version.startsWith('18.')) {\n throw new Error(\n `Isomer Studio needs React 18, which EUI requires; ${configPath} resolves React ${String(version)}.`\n );\n }\n const entry = runtimeEntry(configPath);\n const runtimeReact = entry === undefined ? undefined : reactDirectory(entry);\n if (runtimeReact !== undefined && runtimeReact !== configReact) {\n throw new Error(\n [\n 'The Studio config and @elastic/isomer-runtime resolve different copies of React:',\n ` config: ${configReact}`,\n ` runtime: ${runtimeReact}`,\n 'Install one React for both, for example by deduplicating your lockfile.',\n ].join('\\n')\n );\n }\n};\n\n/** Packages an app must share with the Studio for EUI's theme context and Emotion's cache to reach it. */\nconst SHARED_WITH_APPS = ['@elastic/eui', '@emotion/react'] as const;\n\n/** `@elastic/eui`'s peers, which pnpm must resolve alike for the config and the Studio to share one EUI. */\nconst EUI_PEERS = [\n 'react',\n 'react-dom',\n '@emotion/react',\n '@emotion/css',\n '@elastic/eui-theme-borealis',\n '@elastic/datemath',\n 'moment',\n] as const;\n\nconst packageDirectory = (name: string, from: string): string | undefined => {\n try {\n return dirname(\n realpathSync(createRequire(from).resolve(`${name}/package.json`))\n );\n } catch {\n return undefined;\n }\n};\n\nconst studioVersions = (studioDir: string): Record<string, string> => {\n const { dependencies = {}, peerDependencies = {} } = JSON.parse(\n readFileSync(join(studioDir, 'package.json'), 'utf8')\n ) as {\n dependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n };\n return { ...peerDependencies, ...dependencies };\n};\n\n/** Throws when the config would load a different EUI or Emotion from the Studio's, which its apps share; one it cannot resolve at all is fine. */\nexport const assertSingleEui = (\n configPath: string,\n studioDir: string = PACKAGE_DIR\n): void => {\n const studioPackage = join(studioDir, 'package.json');\n const mismatched = SHARED_WITH_APPS.map((name) => ({\n name,\n config: packageDirectory(name, configPath),\n studio: packageDirectory(name, studioPackage),\n })).filter(({ config, studio }) => config !== undefined && config !== studio);\n if (!mismatched.length) {\n return;\n }\n const versions = studioVersions(studioDir);\n const wanted = ['@elastic/eui', ...EUI_PEERS].map((name) =>\n versions[name] === undefined ? name : `${name}@${versions[name]}`\n );\n throw new Error(\n [\n 'The Studio config and @elastic/isomer-studio resolve different copies of packages that Studio apps share:',\n ...mismatched.flatMap(({ name, config, studio }) => [\n ` ${name}`,\n ` config: ${config}`,\n ` studio: ${studio ?? '(not installed)'}`,\n ]),\n `Install the Studio's versions beside the config, then deduplicate your lockfile: ${wanted.join(', ')}.`,\n ].join('\\n')\n );\n};\n\n/** The `tsconfig.json` nearest the config, which `tsx` applies to the files it includes. */\nexport const nearestTsconfig = (configPath: string): string | undefined => {\n for (let dir = dirname(configPath); ; dir = dirname(dir)) {\n const candidate = join(dir, 'tsconfig.json');\n if (existsSync(candidate)) {\n return candidate;\n }\n if (dirname(dir) === dir) {\n return undefined;\n }\n }\n};\n\n/** Registers `tsx`'s CommonJS and ESM hooks under one namespace, as `tsImport` does; the CommonJS hook reads `TSX_TSCONFIG_PATH` as it registers. */\nconst registerTsx = (tsconfig: string | undefined): ScopedImport => {\n const previous = process.env.TSX_TSCONFIG_PATH;\n if (tsconfig !== undefined) {\n process.env.TSX_TSCONFIG_PATH = tsconfig;\n }\n try {\n const namespace = randomUUID();\n registerCommonJs({ namespace });\n return registerEsm({\n namespace,\n ...(tsconfig === undefined ? {} : { tsconfig }),\n }).import;\n } finally {\n if (previous === undefined) {\n delete process.env.TSX_TSCONFIG_PATH;\n } else {\n process.env.TSX_TSCONFIG_PATH = previous;\n }\n }\n};\n\n/** The Studio config a module namespace default-exports, or an error naming `configPath`. */\nexport const studioConfigFrom = (\n namespace: unknown,\n configPath: string\n): StudioConfig => {\n const config = defaultExport(namespace);\n if (!isStudioConfig(config)) {\n throw new Error(\n `${configPath} must default-export defineStudioConfig({ runtime, ... }).`\n );\n }\n const problems = appProblems(config.apps);\n if (problems.length) {\n throw new Error(\n [\n `${configPath} has invalid apps:`,\n ...problems.map((line) => ` ${line}`),\n ].join('\\n')\n );\n }\n const featured = featuredProblems(\n config.featured,\n runtimePrimitiveTypes(config.runtime)\n );\n if (featured.length) {\n throw new Error(\n [\n `${configPath} has invalid featured primitives:`,\n ...featured.map((line) => ` ${line}`),\n ].join('\\n')\n );\n }\n if (config.apps?.length) {\n assertSingleEui(configPath);\n }\n return config;\n};\n\nlet registeredProject: string | undefined;\n\n/** Applies the Studio's module resolution to every later `import` in this process; a process serves one project. */\nexport const registerProjectResolution = (configPath: string): void => {\n const projectDir = projectDirectory(configPath);\n if (registeredProject !== undefined) {\n if (registeredProject !== projectDir) {\n throw new Error(\n `Module resolution is registered for ${registeredProject}, not ${projectDir}.`\n );\n }\n return;\n }\n registeredProject = projectDir;\n const data: ResolveHooksData = { projectDir, studioDir: PACKAGE_DIR };\n // Node 22.15 and later; before it, `register` covers `import` and `patchRequire` covers `require`.\n const { registerHooks }: { registerHooks?: typeof nodeModule.registerHooks } =\n nodeModule;\n if (registerHooks) {\n registerHooks({ resolve: resolveSync(data) });\n return;\n }\n nodeModule.register(\n `./resolve_hooks${RUNS_FROM_SOURCE ? '.ts' : '.js'}`,\n import.meta.url,\n { data }\n );\n patchRequire(data);\n};\n\nexport type StudioModuleImporter = (path: string) => Promise<unknown>;\n\n/**\n * Imports the config and the modules it names into one module graph, compiled with the config's nearest `tsconfig.json`.\n * Each `tsx` namespace is a separate graph, so a package both import would otherwise load twice.\n */\nexport const createStudioImporter = (\n configPath: string,\n { loader = 'tsx' }: { loader?: ConfigLoader | undefined } = {}\n): StudioModuleImporter => {\n if (loader === 'none') {\n return (path) => import(pathToFileURL(path).href);\n }\n let scoped: ScopedImport | undefined;\n return (path) => {\n scoped ??= registerTsx(nearestTsconfig(configPath));\n return scoped(pathToFileURL(path).href, import.meta.url);\n };\n};\n\n/** Imports the config's default export in Node; `tsx` compiles TypeScript and leaves resolution to Node. */\nexport const loadStudioConfig = async (\n configPath: string,\n {\n loader,\n importModule = createStudioImporter(configPath, { loader }),\n }: {\n loader?: ConfigLoader | undefined;\n importModule?: StudioModuleImporter | undefined;\n } = {}\n): Promise<StudioConfig> => {\n assertSingleReact(configPath);\n return studioConfigFrom(await importModule(configPath), configPath);\n};\n\nconst isRenderToString = (\n value: unknown\n): value is (node: ReactNode) => string => typeof value === 'function';\n\n/** `react-dom/server`'s `renderToString`, from the config's own React. */\nexport const loadRenderToString = (\n configPath: string\n): ((node: ReactNode) => string) => {\n const server: unknown = createRequire(configPath)('react-dom/server');\n const renderToString = isRecord(server) ? server.renderToString : undefined;\n if (!isRenderToString(renderToString)) {\n throw new Error('react-dom/server has no renderToString.');\n }\n return renderToString;\n};\n"]}
@@ -0,0 +1,17 @@
1
+ /** Packages a project and the Studio must load one copy of: imported from outside the project, they resolve from it. */
2
+ export declare const SHARED_PACKAGES: readonly ["react", "react-dom", "@elastic/isomer-sdk", "zod"];
3
+ /** Packages a config may import without installing: when the project lacks them, they resolve from the Studio's install. */
4
+ export declare const STUDIO_PACKAGES: readonly ["@elastic/isomer-runtime", "@elastic/isomer-studio"];
5
+ /** The package a bare specifier names, or `undefined` for a relative, absolute or URL specifier. */
6
+ export declare const packageNameOf: (specifier: string) => string | undefined;
7
+ export declare const isSharedSpecifier: (specifier: string) => boolean;
8
+ export declare const isStudioSpecifier: (specifier: string) => boolean;
9
+ /** Whether `path` is `dir` or inside it. */
10
+ export declare const isInside: (dir: string, path: string) => boolean;
11
+ /** The real directory of the `package.json` nearest `path`, else `path`'s directory. */
12
+ export declare const projectDirectory: (path: string) => string;
13
+ /** The `node_modules` directory the Studio is installed in, which also holds what it depends on. */
14
+ export declare const installDirectory: (studioDir: string) => string;
15
+ /** Where a resolver should look for `specifier` first, imported from `importer`: the project for a shared package from outside it, otherwise `undefined`. */
16
+ export declare const sharedResolveDir: (specifier: string, importer: string | undefined, projectDir: string) => string | undefined;
17
+ //# sourceMappingURL=project_resolution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project_resolution.d.ts","sourceRoot":"","sources":["../../src/node/project_resolution.ts"],"names":[],"mappings":"AAUA,wHAAwH;AACxH,eAAO,MAAM,eAAe,+DAKlB,CAAC;AAEX,4HAA4H;AAC5H,eAAO,MAAM,eAAe,gEAGlB,CAAC;AAEX,oGAAoG;AACpG,eAAO,MAAM,aAAa,GAAI,WAAW,MAAM,KAAG,MAAM,GAAG,SAM1D,CAAC;AAOF,eAAO,MAAM,iBAAiB,cALyB,MAAM,YAKN,CAAC;AAExD,eAAO,MAAM,iBAAiB,cAPyB,MAAM,YAON,CAAC;AAExD,4CAA4C;AAC5C,eAAO,MAAM,QAAQ,GAAI,KAAK,MAAM,EAAE,MAAM,MAAM,KAAG,OAGpD,CAAC;AAEF,wFAAwF;AACxF,eAAO,MAAM,gBAAgB,GAAI,MAAM,MAAM,KAAG,MAO/C,CAAC;AAEF,oGAAoG;AACpG,eAAO,MAAM,gBAAgB,GAAI,WAAW,MAAM,KAAG,MAQpD,CAAC;AAEF,6JAA6J;AAC7J,eAAO,MAAM,gBAAgB,GAC3B,WAAW,MAAM,EACjB,UAAU,MAAM,GAAG,SAAS,EAC5B,YAAY,MAAM,KACjB,MAAM,GAAG,SAMG,CAAC"}
@@ -0,0 +1,66 @@
1
+ /*
2
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3
+ * or more contributor license agreements. Licensed under the Elastic License
4
+ * 2.0; you may not use this file except in compliance with the Elastic License
5
+ * 2.0.
6
+ */
7
+ import { existsSync, realpathSync } from 'node:fs';
8
+ import { basename, dirname, isAbsolute, join, relative } from 'node:path';
9
+ /** Packages a project and the Studio must load one copy of: imported from outside the project, they resolve from it. */
10
+ export const SHARED_PACKAGES = [
11
+ 'react',
12
+ 'react-dom',
13
+ '@elastic/isomer-sdk',
14
+ 'zod',
15
+ ];
16
+ /** Packages a config may import without installing: when the project lacks them, they resolve from the Studio's install. */
17
+ export const STUDIO_PACKAGES = [
18
+ '@elastic/isomer-runtime',
19
+ '@elastic/isomer-studio',
20
+ ];
21
+ /** The package a bare specifier names, or `undefined` for a relative, absolute or URL specifier. */
22
+ export const packageNameOf = (specifier) => {
23
+ if (/^[./]|^[a-z][a-z\d+.-]*:/i.test(specifier) || isAbsolute(specifier)) {
24
+ return undefined;
25
+ }
26
+ const [scope = '', name] = specifier.split('/');
27
+ return scope.startsWith('@') ? `${scope}/${name ?? ''}` : scope;
28
+ };
29
+ const names = (list) => (specifier) => {
30
+ const name = packageNameOf(specifier);
31
+ return name !== undefined && list.includes(name);
32
+ };
33
+ export const isSharedSpecifier = names(SHARED_PACKAGES);
34
+ export const isStudioSpecifier = names(STUDIO_PACKAGES);
35
+ /** Whether `path` is `dir` or inside it. */
36
+ export const isInside = (dir, path) => {
37
+ const inside = relative(dir, path);
38
+ return !inside.startsWith('..') && !isAbsolute(inside);
39
+ };
40
+ /** The real directory of the `package.json` nearest `path`, else `path`'s directory. */
41
+ export const projectDirectory = (path) => {
42
+ for (let dir = dirname(path); dirname(dir) !== dir; dir = dirname(dir)) {
43
+ if (existsSync(join(dir, 'package.json'))) {
44
+ return realpathSync(dir);
45
+ }
46
+ }
47
+ return dirname(path);
48
+ };
49
+ /** The `node_modules` directory the Studio is installed in, which also holds what it depends on. */
50
+ export const installDirectory = (studioDir) => {
51
+ const real = realpathSync(studioDir);
52
+ for (let dir = real; dirname(dir) !== dir; dir = dirname(dir)) {
53
+ if (basename(dir) === 'node_modules') {
54
+ return dir;
55
+ }
56
+ }
57
+ return real;
58
+ };
59
+ /** Where a resolver should look for `specifier` first, imported from `importer`: the project for a shared package from outside it, otherwise `undefined`. */
60
+ export const sharedResolveDir = (specifier, importer, projectDir) => importer !== undefined &&
61
+ isAbsolute(importer) &&
62
+ isSharedSpecifier(specifier) &&
63
+ !isInside(projectDir, importer)
64
+ ? projectDir
65
+ : undefined;
66
+ //# sourceMappingURL=project_resolution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project_resolution.js","sourceRoot":"","sources":["../../src/node/project_resolution.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one\n * or more contributor license agreements. Licensed under the Elastic License\n * 2.0; you may not use this file except in compliance with the Elastic License\n * 2.0.\n */\n\nimport { existsSync, realpathSync } from 'node:fs';\nimport { basename, dirname, isAbsolute, join, relative } from 'node:path';\n\n/** Packages a project and the Studio must load one copy of: imported from outside the project, they resolve from it. */\nexport const SHARED_PACKAGES = [\n 'react',\n 'react-dom',\n '@elastic/isomer-sdk',\n 'zod',\n] as const;\n\n/** Packages a config may import without installing: when the project lacks them, they resolve from the Studio's install. */\nexport const STUDIO_PACKAGES = [\n '@elastic/isomer-runtime',\n '@elastic/isomer-studio',\n] as const;\n\n/** The package a bare specifier names, or `undefined` for a relative, absolute or URL specifier. */\nexport const packageNameOf = (specifier: string): string | undefined => {\n if (/^[./]|^[a-z][a-z\\d+.-]*:/i.test(specifier) || isAbsolute(specifier)) {\n return undefined;\n }\n const [scope = '', name] = specifier.split('/');\n return scope.startsWith('@') ? `${scope}/${name ?? ''}` : scope;\n};\n\nconst names = (list: readonly string[]) => (specifier: string) => {\n const name = packageNameOf(specifier);\n return name !== undefined && list.includes(name);\n};\n\nexport const isSharedSpecifier = names(SHARED_PACKAGES);\n\nexport const isStudioSpecifier = names(STUDIO_PACKAGES);\n\n/** Whether `path` is `dir` or inside it. */\nexport const isInside = (dir: string, path: string): boolean => {\n const inside = relative(dir, path);\n return !inside.startsWith('..') && !isAbsolute(inside);\n};\n\n/** The real directory of the `package.json` nearest `path`, else `path`'s directory. */\nexport const projectDirectory = (path: string): string => {\n for (let dir = dirname(path); dirname(dir) !== dir; dir = dirname(dir)) {\n if (existsSync(join(dir, 'package.json'))) {\n return realpathSync(dir);\n }\n }\n return dirname(path);\n};\n\n/** The `node_modules` directory the Studio is installed in, which also holds what it depends on. */\nexport const installDirectory = (studioDir: string): string => {\n const real = realpathSync(studioDir);\n for (let dir = real; dirname(dir) !== dir; dir = dirname(dir)) {\n if (basename(dir) === 'node_modules') {\n return dir;\n }\n }\n return real;\n};\n\n/** Where a resolver should look for `specifier` first, imported from `importer`: the project for a shared package from outside it, otherwise `undefined`. */\nexport const sharedResolveDir = (\n specifier: string,\n importer: string | undefined,\n projectDir: string\n): string | undefined =>\n importer !== undefined &&\n isAbsolute(importer) &&\n isSharedSpecifier(specifier) &&\n !isInside(projectDir, importer)\n ? projectDir\n : undefined;\n"]}
@@ -0,0 +1,23 @@
1
+ import type { FontLoader } from '@elastic/isomer-image-takumi';
2
+ import type { Composition } from '@elastic/isomer-sdk';
3
+ import type { StudioConfig, StudioRuntime } from '../config.js';
4
+ export type NodeRasterizer = (composition: Composition) => Promise<Buffer>;
5
+ export type NodePdfWriter = (compositions: readonly Composition[], options?: {
6
+ title?: string | undefined;
7
+ }) => Promise<Buffer>;
8
+ export interface NodeRenderers {
9
+ png: NodeRasterizer;
10
+ pdf: NodePdfWriter;
11
+ }
12
+ /** Resolves the faces takumi draws text with. */
13
+ export type ImageFonts = () => Promise<readonly FontLoader[]>;
14
+ /** The config's `imageFonts` module, imported once on first use with `importModule`; `undefined` without one. */
15
+ export declare const imageFontsOf: ({ imageFonts }: Pick<StudioConfig, "imageFonts">, configPath: string, importModule: (path: string) => Promise<unknown>) => ImageFonts | undefined;
16
+ /**
17
+ * Draws with takumi, loaded on first use because it is native; `undefined` without a snapshot surface.
18
+ * Images take the frame's own geometry, as the Snapshot preview does. Without `fonts`, a PNG falls back to takumi's built-in face and a PDF can't draw text.
19
+ */
20
+ export declare const createRenderers: (runtime: StudioRuntime, fonts?: ImageFonts) => NodeRenderers | undefined;
21
+ /** {@link createRenderers}' PNGs alone. */
22
+ export declare const createRasterizer: (runtime: StudioRuntime, fonts?: ImageFonts) => NodeRasterizer | undefined;
23
+ //# sourceMappingURL=rasterize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rasterize.d.ts","sourceRoot":"","sources":["../../src/node/rasterize.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAiB,MAAM,8BAA8B,CAAC;AAC9E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG7D,MAAM,MAAM,cAAc,GAAG,CAAC,WAAW,EAAE,WAAW,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAE3E,MAAM,MAAM,aAAa,GAAG,CAC1B,YAAY,EAAE,SAAS,WAAW,EAAE,EACpC,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,KACrC,OAAO,CAAC,MAAM,CAAC,CAAC;AAErB,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,cAAc,CAAC;IACpB,GAAG,EAAE,aAAa,CAAC;CACpB;AAED,iDAAiD;AACjD,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC,CAAC;AAiB9D,iHAAiH;AACjH,eAAO,MAAM,YAAY,GACvB,gBAAgB,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC,EAChD,YAAY,MAAM,EAClB,cAAc,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,KAC/C,UAAU,GAAG,SAqBf,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,eAAe,GAC1B,SAAS,aAAa,EACtB,QAAQ,UAAU,KACjB,aAAa,GAAG,SAsClB,CAAC;AAEF,2CAA2C;AAC3C,eAAO,MAAM,gBAAgB,GAC3B,SAAS,aAAa,EACtB,QAAQ,UAAU,KACjB,cAAc,GAAG,SAAiD,CAAC"}
@@ -0,0 +1,79 @@
1
+ /*
2
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3
+ * or more contributor license agreements. Licensed under the Elastic License
4
+ * 2.0; you may not use this file except in compliance with the Elastic License
5
+ * 2.0.
6
+ */
7
+ import { dirname, resolve } from 'node:path';
8
+ import { PNG_SCALE } from '../types.js';
9
+ const fontsIn = (namespace) => {
10
+ const exported = typeof namespace === 'object' &&
11
+ namespace !== null &&
12
+ 'default' in namespace
13
+ ? namespace.default
14
+ : undefined;
15
+ return Array.isArray(exported) ||
16
+ typeof exported !== 'object' ||
17
+ exported === null ||
18
+ !('default' in exported)
19
+ ? exported
20
+ : exported.default;
21
+ };
22
+ /** The config's `imageFonts` module, imported once on first use with `importModule`; `undefined` without one. */
23
+ export const imageFontsOf = ({ imageFonts }, configPath, importModule) => {
24
+ if (imageFonts === undefined) {
25
+ return undefined;
26
+ }
27
+ const path = resolve(dirname(configPath), imageFonts);
28
+ let fonts;
29
+ return () => (fonts ??= importModule(path)
30
+ .then((namespace) => {
31
+ const exported = fontsIn(namespace);
32
+ if (!Array.isArray(exported)) {
33
+ throw new Error(`${imageFonts} must default-export an array of takumi font loaders.`);
34
+ }
35
+ return exported;
36
+ })
37
+ .catch((error) => {
38
+ fonts = undefined;
39
+ throw error;
40
+ }));
41
+ };
42
+ /**
43
+ * Draws with takumi, loaded on first use because it is native; `undefined` without a snapshot surface.
44
+ * Images take the frame's own geometry, as the Snapshot preview does. Without `fonts`, a PNG falls back to takumi's built-in face and a PDF can't draw text.
45
+ */
46
+ export const createRenderers = (runtime, fonts) => {
47
+ const { snapshot } = runtime.surfaces;
48
+ if (!snapshot) {
49
+ return undefined;
50
+ }
51
+ let backend;
52
+ const loadBackend = () => (backend ??= Promise.all([
53
+ import('@elastic/isomer-image-takumi'),
54
+ fonts?.() ?? [],
55
+ ])
56
+ .then(([{ createTakumiImageBackend }, faces]) => createTakumiImageBackend({ fonts: faces }))
57
+ .catch((error) => {
58
+ backend = undefined;
59
+ throw error;
60
+ }));
61
+ return {
62
+ png: async (composition) => (await loadBackend()).png(snapshot.render(composition, { onValidationError: 'collect' }), { scale: PNG_SCALE }),
63
+ pdf: async (compositions, { title } = {}) => {
64
+ const takumi = await loadBackend();
65
+ const { renderPdf } = await import('@elastic/isomer-image-takumi');
66
+ const drawable = {
67
+ validate: (composition) => runtime.validate(composition),
68
+ surfaces: { snapshot },
69
+ };
70
+ const { pdf } = await renderPdf(drawable, compositions, takumi, {
71
+ ...(title === undefined ? {} : { metadata: { title } }),
72
+ });
73
+ return pdf;
74
+ },
75
+ };
76
+ };
77
+ /** {@link createRenderers}' PNGs alone. */
78
+ export const createRasterizer = (runtime, fonts) => createRenderers(runtime, fonts)?.png;
79
+ //# sourceMappingURL=rasterize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rasterize.js","sourceRoot":"","sources":["../../src/node/rasterize.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one\n * or more contributor license agreements. Licensed under the Elastic License\n * 2.0; you may not use this file except in compliance with the Elastic License\n * 2.0.\n */\n\nimport { dirname, resolve } from 'node:path';\n\nimport type { FontLoader, TakumiBackend } from '@elastic/isomer-image-takumi';\nimport type { Composition } from '@elastic/isomer-sdk';\n\nimport type { StudioConfig, StudioRuntime } from '../config';\nimport { PNG_SCALE } from '../types';\n\nexport type NodeRasterizer = (composition: Composition) => Promise<Buffer>;\n\nexport type NodePdfWriter = (\n compositions: readonly Composition[],\n options?: { title?: string | undefined }\n) => Promise<Buffer>;\n\nexport interface NodeRenderers {\n png: NodeRasterizer;\n pdf: NodePdfWriter;\n}\n\n/** Resolves the faces takumi draws text with. */\nexport type ImageFonts = () => Promise<readonly FontLoader[]>;\n\nconst fontsIn = (namespace: unknown): unknown => {\n const exported =\n typeof namespace === 'object' &&\n namespace !== null &&\n 'default' in namespace\n ? namespace.default\n : undefined;\n return Array.isArray(exported) ||\n typeof exported !== 'object' ||\n exported === null ||\n !('default' in exported)\n ? exported\n : exported.default;\n};\n\n/** The config's `imageFonts` module, imported once on first use with `importModule`; `undefined` without one. */\nexport const imageFontsOf = (\n { imageFonts }: Pick<StudioConfig, 'imageFonts'>,\n configPath: string,\n importModule: (path: string) => Promise<unknown>\n): ImageFonts | undefined => {\n if (imageFonts === undefined) {\n return undefined;\n }\n const path = resolve(dirname(configPath), imageFonts);\n let fonts: Promise<readonly FontLoader[]> | undefined;\n return () =>\n (fonts ??= importModule(path)\n .then((namespace) => {\n const exported = fontsIn(namespace);\n if (!Array.isArray(exported)) {\n throw new Error(\n `${imageFonts} must default-export an array of takumi font loaders.`\n );\n }\n return exported as readonly FontLoader[];\n })\n .catch((error: unknown) => {\n fonts = undefined;\n throw error;\n }));\n};\n\n/**\n * Draws with takumi, loaded on first use because it is native; `undefined` without a snapshot surface.\n * Images take the frame's own geometry, as the Snapshot preview does. Without `fonts`, a PNG falls back to takumi's built-in face and a PDF can't draw text.\n */\nexport const createRenderers = (\n runtime: StudioRuntime,\n fonts?: ImageFonts\n): NodeRenderers | undefined => {\n const { snapshot } = runtime.surfaces;\n if (!snapshot) {\n return undefined;\n }\n let backend: Promise<TakumiBackend> | undefined;\n const loadBackend = () =>\n (backend ??= Promise.all([\n import('@elastic/isomer-image-takumi'),\n fonts?.() ?? [],\n ])\n .then(([{ createTakumiImageBackend }, faces]) =>\n createTakumiImageBackend({ fonts: faces })\n )\n .catch((error: unknown) => {\n backend = undefined;\n throw error;\n }));\n\n return {\n png: async (composition) =>\n (await loadBackend()).png(\n snapshot.render(composition, { onValidationError: 'collect' }),\n { scale: PNG_SCALE }\n ),\n pdf: async (compositions, { title } = {}) => {\n const takumi = await loadBackend();\n const { renderPdf } = await import('@elastic/isomer-image-takumi');\n const drawable = {\n validate: (composition: Composition) => runtime.validate(composition),\n surfaces: { snapshot },\n };\n const { pdf } = await renderPdf(drawable, compositions, takumi, {\n ...(title === undefined ? {} : { metadata: { title } }),\n });\n return pdf;\n },\n };\n};\n\n/** {@link createRenderers}' PNGs alone. */\nexport const createRasterizer = (\n runtime: StudioRuntime,\n fonts?: ImageFonts\n): NodeRasterizer | undefined => createRenderers(runtime, fonts)?.png;\n"]}
@@ -0,0 +1,8 @@
1
+ import type { CheckReport } from './check.js';
2
+ export type ReportFormat = 'json' | 'junit';
3
+ /** One `testsuite` per primitive, one `testcase` per check. */
4
+ export declare const toJunit: ({ title, results, failed, skipped, }: CheckReport) => string;
5
+ export declare const formatReport: (report: CheckReport, format: ReportFormat) => string;
6
+ /** Every failure, then the totals, for the terminal. */
7
+ export declare const summarizeReport: ({ title, apps, results, passed, failed, skipped, }: CheckReport) => string;
8
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/node/report.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,WAAW,EAAe,MAAM,SAAS,CAAC;AAExD,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,OAAO,CAAC;AA6B5C,+DAA+D;AAC/D,eAAO,MAAM,OAAO,GAAI,sCAKrB,WAAW,KAAG,MAmBhB,CAAC;AAEF,eAAO,MAAM,YAAY,GACvB,QAAQ,WAAW,EACnB,QAAQ,YAAY,KACnB,MAC4E,CAAC;AAEhF,wDAAwD;AACxD,eAAO,MAAM,eAAe,GAAI,oDAO7B,WAAW,KAAG,MAUH,CAAC"}
@@ -0,0 +1,57 @@
1
+ /*
2
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3
+ * or more contributor license agreements. Licensed under the Elastic License
4
+ * 2.0; you may not use this file except in compliance with the Elastic License
5
+ * 2.0.
6
+ */
7
+ const XML_ESCAPES = {
8
+ '&': '&amp;',
9
+ '<': '&lt;',
10
+ '>': '&gt;',
11
+ '"': '&quot;',
12
+ "'": '&apos;',
13
+ };
14
+ const escapeXml = (value) => value.replace(/[&<>"']/g, (char) => XML_ESCAPES[char] ?? char);
15
+ const caseName = ({ example, check }) => example === undefined ? check : `${example} › ${check}`;
16
+ const testCase = (result) => {
17
+ const { primitive, status, message = '' } = result;
18
+ const open = ` <testcase classname="${escapeXml(primitive)}" name="${escapeXml(caseName(result))}"`;
19
+ switch (status) {
20
+ case 'passed':
21
+ return `${open} />`;
22
+ case 'skipped':
23
+ return `${open}>\n <skipped message="${escapeXml(message)}" />\n </testcase>`;
24
+ case 'failed':
25
+ return `${open}>\n <failure message="${escapeXml(message.split('\n')[0] ?? '')}">${escapeXml(message)}</failure>\n </testcase>`;
26
+ }
27
+ };
28
+ /** One `testsuite` per primitive, one `testcase` per check. */
29
+ export const toJunit = ({ title, results, failed, skipped, }) => {
30
+ const primitives = [...new Set(results.map(({ primitive }) => primitive))];
31
+ const suites = primitives.map((primitive) => {
32
+ const cases = results.filter((result) => result.primitive === primitive);
33
+ const count = (status) => cases.filter((result) => result.status === status).length;
34
+ return [
35
+ ` <testsuite name="${escapeXml(primitive)}" tests="${cases.length}" failures="${count('failed')}" skipped="${count('skipped')}">`,
36
+ ...cases.map(testCase),
37
+ ' </testsuite>',
38
+ ].join('\n');
39
+ });
40
+ return [
41
+ '<?xml version="1.0" encoding="UTF-8"?>',
42
+ `<testsuites name="${escapeXml(title)}" tests="${results.length}" failures="${failed}" skipped="${skipped}">`,
43
+ ...suites,
44
+ '</testsuites>',
45
+ '',
46
+ ].join('\n');
47
+ };
48
+ export const formatReport = (report, format) => format === 'junit' ? toJunit(report) : `${JSON.stringify(report, null, 2)}\n`;
49
+ /** Every failure, then the totals, for the terminal. */
50
+ export const summarizeReport = ({ title, apps, results, passed, failed, skipped, }) => [
51
+ ...results
52
+ .filter(({ status }) => status === 'failed')
53
+ .map((result) => `✗ ${result.primitive} › ${caseName(result)}\n ${(result.message ?? '').split('\n').join('\n ')}`),
54
+ `${title}: ${passed} passed, ${failed} failed, ${skipped} skipped.${apps ? ` ${apps} ${apps === 1 ? 'app' : 'apps'} listed.` : ''}`,
55
+ '',
56
+ ].join('\n');
57
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/node/report.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one\n * or more contributor license agreements. Licensed under the Elastic License\n * 2.0; you may not use this file except in compliance with the Elastic License\n * 2.0.\n */\n\nimport type { CheckReport, CheckResult } from './check';\n\nexport type ReportFormat = 'json' | 'junit';\n\nconst XML_ESCAPES: Readonly<Record<string, string>> = {\n '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;',\n \"'\": '&apos;',\n};\n\nconst escapeXml = (value: string): string =>\n value.replace(/[&<>\"']/g, (char) => XML_ESCAPES[char] ?? char);\n\nconst caseName = ({ example, check }: CheckResult): string =>\n example === undefined ? check : `${example} › ${check}`;\n\nconst testCase = (result: CheckResult): string => {\n const { primitive, status, message = '' } = result;\n const open = ` <testcase classname=\"${escapeXml(primitive)}\" name=\"${escapeXml(caseName(result))}\"`;\n switch (status) {\n case 'passed':\n return `${open} />`;\n case 'skipped':\n return `${open}>\\n <skipped message=\"${escapeXml(message)}\" />\\n </testcase>`;\n case 'failed':\n return `${open}>\\n <failure message=\"${escapeXml(message.split('\\n')[0] ?? '')}\">${escapeXml(message)}</failure>\\n </testcase>`;\n }\n};\n\n/** One `testsuite` per primitive, one `testcase` per check. */\nexport const toJunit = ({\n title,\n results,\n failed,\n skipped,\n}: CheckReport): string => {\n const primitives = [...new Set(results.map(({ primitive }) => primitive))];\n const suites = primitives.map((primitive) => {\n const cases = results.filter((result) => result.primitive === primitive);\n const count = (status: CheckResult['status']) =>\n cases.filter((result) => result.status === status).length;\n return [\n ` <testsuite name=\"${escapeXml(primitive)}\" tests=\"${cases.length}\" failures=\"${count('failed')}\" skipped=\"${count('skipped')}\">`,\n ...cases.map(testCase),\n ' </testsuite>',\n ].join('\\n');\n });\n return [\n '<?xml version=\"1.0\" encoding=\"UTF-8\"?>',\n `<testsuites name=\"${escapeXml(title)}\" tests=\"${results.length}\" failures=\"${failed}\" skipped=\"${skipped}\">`,\n ...suites,\n '</testsuites>',\n '',\n ].join('\\n');\n};\n\nexport const formatReport = (\n report: CheckReport,\n format: ReportFormat\n): string =>\n format === 'junit' ? toJunit(report) : `${JSON.stringify(report, null, 2)}\\n`;\n\n/** Every failure, then the totals, for the terminal. */\nexport const summarizeReport = ({\n title,\n apps,\n results,\n passed,\n failed,\n skipped,\n}: CheckReport): string =>\n [\n ...results\n .filter(({ status }) => status === 'failed')\n .map(\n (result) =>\n `✗ ${result.primitive} › ${caseName(result)}\\n ${(result.message ?? '').split('\\n').join('\\n ')}`\n ),\n `${title}: ${passed} passed, ${failed} failed, ${skipped} skipped.${apps ? ` ${apps} ${apps === 1 ? 'app' : 'apps'} listed.` : ''}`,\n '',\n ].join('\\n');\n"]}
@@ -0,0 +1,16 @@
1
+ import type { InitializeHook, ResolveHook, ResolveHookSync } from 'node:module';
2
+ /** Node module hooks applying `sharedResolveDir` and the Studio fallback to every `import` and `require`. */
3
+ export interface ResolveHooksData {
4
+ projectDir: string;
5
+ studioDir: string;
6
+ }
7
+ /** Where to resolve `specifier` from, in order; every parent but the last is passed over when it finds nothing. */
8
+ export declare const parentsFor: (specifier: string, parentURL: string | undefined, { projectDir, studioDir }: ResolveHooksData) => (string | undefined)[];
9
+ /** For `module.registerHooks`, which also sees `require`. */
10
+ export declare const resolveSync: (data: ResolveHooksData) => ResolveHookSync;
11
+ /** Applies {@link resolveSync} to `require` on a Node without `registerHooks`, wrapping the resolver as `tsx` does. */
12
+ export declare const patchRequire: (hooksData: ResolveHooksData) => void;
13
+ /** For `module.register`, on a Node without `registerHooks`. */
14
+ export declare const initialize: InitializeHook<ResolveHooksData>;
15
+ export declare const resolve: ResolveHook;
16
+ //# sourceMappingURL=resolve_hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve_hooks.d.ts","sourceRoot":"","sources":["../../src/node/resolve_hooks.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACV,cAAc,EAEd,WAAW,EACX,eAAe,EAChB,MAAM,aAAa,CAAC;AAOrB,6GAA6G;AAC7G,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAKD,mHAAmH;AACnH,eAAO,MAAM,UAAU,GACrB,WAAW,MAAM,EACjB,WAAW,MAAM,GAAG,SAAS,EAC7B,2BAA2B,gBAAgB,KAC1C,CAAC,MAAM,GAAG,SAAS,CAAC,EAUtB,CAAC;AAeF,6DAA6D;AAC7D,eAAO,MAAM,WAAW,GACrB,MAAM,gBAAgB,KAAG,eA6BzB,CAAC;AAYJ,uHAAuH;AACvH,eAAO,MAAM,YAAY,GAAI,WAAW,gBAAgB,KAAG,IAyB1D,CAAC;AAIF,gEAAgE;AAChE,eAAO,MAAM,UAAU,EAAE,cAAc,CAAC,gBAAgB,CAEvD,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,WAiBrB,CAAC"}