lapikit 0.0.0-insiders.09c4e21 → 0.0.0-insiders.0a8aed3

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 (304) hide show
  1. package/README.md +9 -9
  2. package/bin/helpers.js +251 -0
  3. package/bin/hooks.js +318 -0
  4. package/bin/index.js +119 -20
  5. package/dist/@types/actions.d.ts +19 -0
  6. package/dist/@types/animations.d.ts +7 -0
  7. package/dist/@types/components.d.ts +35 -0
  8. package/dist/@types/core.d.ts +3 -0
  9. package/dist/@types/dom.d.ts +8 -0
  10. package/dist/@types/events.d.ts +4 -0
  11. package/dist/@types/index.d.ts +7 -0
  12. package/dist/@types/index.js +7 -0
  13. package/dist/@types/props.d.ts +16 -0
  14. package/dist/animations/index.d.ts +1 -0
  15. package/dist/animations/index.js +1 -0
  16. package/dist/animations/ripple.d.ts +5 -0
  17. package/dist/animations/ripple.js +138 -0
  18. package/dist/assets/icon.svg +1 -0
  19. package/dist/components/accordion/accordion.svelte +210 -20
  20. package/dist/components/accordion/accordion.svelte.d.ts +1 -1
  21. package/dist/components/accordion/{types.d.ts → accordion.types.d.ts} +19 -16
  22. package/dist/components/accordion/modules/accordion-item.svelte +197 -56
  23. package/dist/components/accordion/modules/accordion-item.svelte.d.ts +1 -1
  24. package/dist/components/alert/alert.svelte +285 -56
  25. package/dist/components/alert/alert.svelte.d.ts +1 -1
  26. package/dist/components/alert/alert.types.d.ts +22 -0
  27. package/dist/components/app/app.svelte +231 -67
  28. package/dist/components/app/app.svelte.d.ts +1 -1
  29. package/dist/components/app/app.types.d.ts +4 -0
  30. package/dist/components/appbar/appbar.svelte +226 -20
  31. package/dist/components/appbar/appbar.svelte.d.ts +1 -1
  32. package/dist/components/appbar/appbar.types.d.ts +15 -0
  33. package/dist/components/aspect-ratio/aspect-ratio.svelte +93 -17
  34. package/dist/components/aspect-ratio/aspect-ratio.svelte.d.ts +2 -2
  35. package/dist/components/aspect-ratio/aspect-ratio.types.d.ts +12 -0
  36. package/dist/components/avatar/avatar.svelte +188 -31
  37. package/dist/components/avatar/avatar.svelte.d.ts +1 -1
  38. package/dist/components/avatar/avatar.types.d.ts +10 -0
  39. package/dist/components/btn/btn.svelte +484 -0
  40. package/dist/components/btn/btn.svelte.d.ts +4 -0
  41. package/dist/components/btn/btn.types.d.ts +28 -0
  42. package/dist/components/card/card.svelte +252 -45
  43. package/dist/components/card/card.svelte.d.ts +1 -1
  44. package/dist/components/card/card.types.d.ts +38 -0
  45. package/dist/components/card/modules/card-actions.svelte +29 -0
  46. package/dist/components/card/modules/card-actions.svelte.d.ts +4 -0
  47. package/dist/components/card/modules/card-container.svelte +27 -0
  48. package/dist/components/card/modules/card-container.svelte.d.ts +4 -0
  49. package/dist/components/card/modules/card-content.svelte +38 -0
  50. package/dist/components/card/modules/card-content.svelte.d.ts +4 -0
  51. package/dist/components/card/modules/card-media.svelte +28 -0
  52. package/dist/components/card/modules/card-media.svelte.d.ts +4 -0
  53. package/dist/components/card/modules/card-title.svelte +41 -0
  54. package/dist/components/card/modules/card-title.svelte.d.ts +4 -0
  55. package/dist/components/chip/chip.svelte +451 -113
  56. package/dist/components/chip/chip.svelte.d.ts +2 -2
  57. package/dist/components/chip/chip.types.d.ts +28 -0
  58. package/dist/components/dialog/dialog.svelte +246 -43
  59. package/dist/components/dialog/dialog.svelte.d.ts +1 -1
  60. package/dist/components/dialog/dialog.types.d.ts +18 -0
  61. package/dist/components/dropdown/dropdown.svelte +196 -66
  62. package/dist/components/dropdown/dropdown.svelte.d.ts +2 -2
  63. package/dist/components/dropdown/{types.d.ts → dropdown.types.d.ts} +11 -15
  64. package/dist/components/field/field.svelte +474 -0
  65. package/dist/components/field/field.svelte.d.ts +4 -0
  66. package/dist/components/field/field.types.d.ts +46 -0
  67. package/dist/components/icon/icon.svelte +137 -40
  68. package/dist/components/icon/icon.svelte.d.ts +1 -1
  69. package/dist/components/icon/icon.types.d.ts +17 -0
  70. package/dist/components/index.d.ts +32 -22
  71. package/dist/components/index.js +28 -22
  72. package/dist/components/list/list.svelte +209 -26
  73. package/dist/components/list/list.svelte.d.ts +1 -1
  74. package/dist/components/list/list.types.d.ts +27 -0
  75. package/dist/components/list/modules/list-item.svelte +156 -54
  76. package/dist/components/list/modules/list-item.svelte.d.ts +1 -1
  77. package/dist/{stores/components.d.ts → components/modal/modal.d.ts} +1 -2
  78. package/dist/{stores/components.js → components/modal/modal.js} +1 -1
  79. package/dist/components/modal/modal.svelte +277 -46
  80. package/dist/components/modal/modal.svelte.d.ts +1 -1
  81. package/dist/components/modal/modal.types.d.ts +20 -0
  82. package/dist/components/popover/popover.svelte +153 -47
  83. package/dist/components/popover/popover.svelte.d.ts +2 -2
  84. package/dist/components/popover/{types.d.ts → popover.types.d.ts} +8 -13
  85. package/dist/components/separator/separator.svelte +68 -23
  86. package/dist/components/separator/separator.svelte.d.ts +2 -2
  87. package/dist/components/separator/separator.types.d.ts +11 -0
  88. package/dist/components/spacer/spacer.svelte +21 -3
  89. package/dist/components/spacer/spacer.svelte.d.ts +1 -1
  90. package/dist/components/spacer/{types.d.ts → spacer.types.d.ts} +1 -1
  91. package/dist/components/textfield/textfield.svelte +116 -169
  92. package/dist/components/textfield/textfield.svelte.d.ts +1 -1
  93. package/dist/components/textfield/textfield.types.d.ts +20 -0
  94. package/dist/components/textfield/textfield.types.js +1 -0
  95. package/dist/components/toolbar/toolbar.svelte +238 -25
  96. package/dist/components/toolbar/toolbar.svelte.d.ts +1 -1
  97. package/dist/components/toolbar/toolbar.types.d.ts +17 -0
  98. package/dist/components/toolbar/toolbar.types.js +1 -0
  99. package/dist/components/tooltip/tooltip.svelte +243 -75
  100. package/dist/components/tooltip/tooltip.svelte.d.ts +2 -2
  101. package/dist/components/tooltip/tooltip.types.d.ts +17 -0
  102. package/dist/components/tooltip/tooltip.types.js +1 -0
  103. package/dist/constants.d.ts +12 -0
  104. package/dist/constants.js +43 -0
  105. package/dist/directives.d.ts +14 -0
  106. package/dist/directives.js +128 -0
  107. package/dist/entry-bundler.d.ts +3 -11
  108. package/dist/entry-bundler.js +2 -104
  109. package/dist/escaping.d.ts +2 -0
  110. package/dist/escaping.js +157 -0
  111. package/dist/framework.d.ts +11 -0
  112. package/dist/framework.js +131 -0
  113. package/dist/{actions → hooks}/accordion.svelte.d.ts +1 -5
  114. package/dist/{actions/index.d.ts → hooks/actions.d.ts} +1 -1
  115. package/dist/{actions/index.js → hooks/actions.js} +1 -1
  116. package/dist/hooks/themes.svelte.d.ts +12 -0
  117. package/dist/hooks/themes.svelte.js +125 -0
  118. package/dist/html-mapped.d.ts +12 -0
  119. package/dist/html-mapped.js +24 -0
  120. package/dist/labs/index.d.ts +1 -0
  121. package/dist/labs/index.js +2 -0
  122. package/dist/labs/sheet/sheet.svelte +271 -0
  123. package/dist/labs/sheet/sheet.svelte.d.ts +4 -0
  124. package/dist/labs/sheet/sheet.types.d.ts +16 -0
  125. package/dist/labs/sheet/sheet.types.js +1 -0
  126. package/dist/utils/color.d.ts +4 -0
  127. package/dist/utils/color.js +41 -0
  128. package/dist/utils/components.d.ts +60 -0
  129. package/dist/utils/components.js +186 -0
  130. package/dist/utils/directives.d.ts +20 -0
  131. package/dist/utils/directives.js +64 -0
  132. package/dist/utils/floating.d.ts +58 -0
  133. package/dist/utils/floating.js +131 -0
  134. package/dist/utils/index.d.ts +4 -0
  135. package/dist/utils/index.js +4 -0
  136. package/dist/{internal/helpers → utils}/outside.d.ts +2 -5
  137. package/dist/{internal/helpers → utils}/outside.js +5 -0
  138. package/package.json +38 -39
  139. package/bin/configuration.js +0 -303
  140. package/bin/helper.js +0 -59
  141. package/bin/presets.js +0 -26
  142. package/bin/prompts.js +0 -67
  143. package/dist/actions/use-theme.d.ts +0 -1
  144. package/dist/actions/use-theme.js +0 -18
  145. package/dist/assets/icons/arrow-down.svelte +0 -12
  146. package/dist/assets/icons/arrow-down.svelte.d.ts +0 -18
  147. package/dist/assets/icons/arrow-up.svelte +0 -12
  148. package/dist/assets/icons/arrow-up.svelte.d.ts +0 -18
  149. package/dist/assets/icons/close-fill.svelte +0 -12
  150. package/dist/assets/icons/close-fill.svelte.d.ts +0 -18
  151. package/dist/assets/icons/loading-fill.svelte +0 -31
  152. package/dist/assets/icons/loading-fill.svelte.d.ts +0 -18
  153. package/dist/components/accordion/accordion.css +0 -36
  154. package/dist/components/accordion/modules/accordion-item.css +0 -68
  155. package/dist/components/alert/alert.css +0 -130
  156. package/dist/components/alert/types.d.ts +0 -28
  157. package/dist/components/app/app.css +0 -26
  158. package/dist/components/app/types.d.ts +0 -10
  159. package/dist/components/appbar/appbar.css +0 -38
  160. package/dist/components/appbar/types.d.ts +0 -15
  161. package/dist/components/aspect-ratio/aspect-ratio.css +0 -19
  162. package/dist/components/aspect-ratio/types.d.ts +0 -5
  163. package/dist/components/avatar/avatar.css +0 -102
  164. package/dist/components/avatar/types.d.ts +0 -22
  165. package/dist/components/button/button.css +0 -240
  166. package/dist/components/button/button.svelte +0 -102
  167. package/dist/components/button/button.svelte.d.ts +0 -4
  168. package/dist/components/button/types.d.ts +0 -29
  169. package/dist/components/card/card.css +0 -105
  170. package/dist/components/card/types.d.ts +0 -20
  171. package/dist/components/chip/chip.css +0 -224
  172. package/dist/components/chip/types.d.ts +0 -32
  173. package/dist/components/dialog/dialog.css +0 -129
  174. package/dist/components/dialog/types.d.ts +0 -24
  175. package/dist/components/dropdown/dropdown.css +0 -13
  176. package/dist/components/icon/icon.css +0 -78
  177. package/dist/components/icon/types.d.ts +0 -16
  178. package/dist/components/list/list.css +0 -149
  179. package/dist/components/list/modules/list-item.css +0 -67
  180. package/dist/components/list/types.d.ts +0 -33
  181. package/dist/components/modal/modal.css +0 -137
  182. package/dist/components/modal/types.d.ts +0 -26
  183. package/dist/components/popover/popover.css +0 -13
  184. package/dist/components/separator/separator.css +0 -42
  185. package/dist/components/separator/types.d.ts +0 -15
  186. package/dist/components/spacer/spacer.css +0 -3
  187. package/dist/components/textfield/textfield.css +0 -298
  188. package/dist/components/textfield/types.d.ts +0 -37
  189. package/dist/components/toolbar/toolbar.css +0 -106
  190. package/dist/components/toolbar/types.d.ts +0 -27
  191. package/dist/components/tooltip/tooltip.css +0 -116
  192. package/dist/components/tooltip/types.d.ts +0 -23
  193. package/dist/index.d.ts +0 -3
  194. package/dist/index.js +0 -24
  195. package/dist/internal/config/presets.d.ts +0 -149
  196. package/dist/internal/config/presets.js +0 -169
  197. package/dist/internal/config/variables.d.ts +0 -3
  198. package/dist/internal/config/variables.js +0 -3
  199. package/dist/internal/core/actions/assets.svelte.d.ts +0 -8
  200. package/dist/internal/core/actions/assets.svelte.js +0 -54
  201. package/dist/internal/core/actions/dropdown.svelte.d.ts +0 -7
  202. package/dist/internal/core/actions/dropdown.svelte.js +0 -148
  203. package/dist/internal/core/actions/popover.svelte.d.ts +0 -7
  204. package/dist/internal/core/actions/popover.svelte.js +0 -134
  205. package/dist/internal/core/actions/tooltip.svelte.d.ts +0 -7
  206. package/dist/internal/core/actions/tooltip.svelte.js +0 -131
  207. package/dist/internal/core/animations/ripple.d.ts +0 -12
  208. package/dist/internal/core/animations/ripple.js +0 -93
  209. package/dist/internal/core/bin/ansi.d.ts +0 -40
  210. package/dist/internal/core/bin/ansi.js +0 -44
  211. package/dist/internal/core/bin/terminal.d.ts +0 -1
  212. package/dist/internal/core/bin/terminal.js +0 -12
  213. package/dist/internal/core/css.d.ts +0 -1
  214. package/dist/internal/core/css.js +0 -16
  215. package/dist/internal/core/formatter/component.d.ts +0 -5
  216. package/dist/internal/core/formatter/component.js +0 -60
  217. package/dist/internal/core/formatter/device.d.ts +0 -5
  218. package/dist/internal/core/formatter/device.js +0 -66
  219. package/dist/internal/core/formatter/index.d.ts +0 -7
  220. package/dist/internal/core/formatter/index.js +0 -35
  221. package/dist/internal/core/formatter/style.d.ts +0 -4
  222. package/dist/internal/core/formatter/style.js +0 -15
  223. package/dist/internal/core/formatter/theme.d.ts +0 -5
  224. package/dist/internal/core/formatter/theme.js +0 -44
  225. package/dist/internal/core/formatter/typography.d.ts +0 -5
  226. package/dist/internal/core/formatter/typography.js +0 -12
  227. package/dist/internal/core/minify.d.ts +0 -1
  228. package/dist/internal/core/minify.js +0 -10
  229. package/dist/internal/core/standard-colors.d.ts +0 -75
  230. package/dist/internal/core/standard-colors.js +0 -75
  231. package/dist/internal/core/x11-colors.d.ts +0 -4
  232. package/dist/internal/core/x11-colors.js +0 -151
  233. package/dist/internal/helpers/colors.d.ts +0 -1
  234. package/dist/internal/helpers/colors.js +0 -50
  235. package/dist/internal/helpers/convert.d.ts +0 -1
  236. package/dist/internal/helpers/convert.js +0 -17
  237. package/dist/internal/helpers/deep-merge.d.ts +0 -44
  238. package/dist/internal/helpers/deep-merge.js +0 -80
  239. package/dist/internal/helpers/parser.d.ts +0 -10
  240. package/dist/internal/helpers/parser.js +0 -93
  241. package/dist/internal/helpers/scroll.d.ts +0 -1
  242. package/dist/internal/helpers/scroll.js +0 -5
  243. package/dist/internal/plugins/vite.d.ts +0 -8
  244. package/dist/internal/plugins/vite.js +0 -33
  245. package/dist/internal/types/components.d.ts +0 -14
  246. package/dist/internal/types/configuration.d.ts +0 -63
  247. package/dist/internal/types/index.d.ts +0 -2
  248. package/dist/internal/types/index.js +0 -2
  249. package/dist/labs/compiler/mapped-code.d.ts +0 -26
  250. package/dist/labs/compiler/mapped-code.js +0 -77
  251. package/dist/labs/compiler/types/dom.d.ts +0 -2
  252. package/dist/labs/compiler/types/index.d.ts +0 -1
  253. package/dist/labs/components/btn/btn.svelte +0 -44
  254. package/dist/labs/components/btn/btn.svelte.d.ts +0 -7
  255. package/dist/labs/components/index.d.ts +0 -1
  256. package/dist/labs/components/index.js +0 -2
  257. package/dist/labs/utils/components.d.ts +0 -22
  258. package/dist/labs/utils/components.js +0 -86
  259. package/dist/labs/utils/index.d.ts +0 -1
  260. package/dist/labs/utils/index.js +0 -1
  261. package/dist/labs/utils/types/index.d.ts +0 -13
  262. package/dist/stores/breakpoints.d.ts +0 -6
  263. package/dist/stores/breakpoints.js +0 -14
  264. package/dist/stores/devices.d.ts +0 -6
  265. package/dist/stores/devices.js +0 -9
  266. package/dist/stores/index.d.ts +0 -5
  267. package/dist/stores/index.js +0 -5
  268. package/dist/stores/themes.d.ts +0 -2
  269. package/dist/stores/themes.js +0 -4
  270. package/dist/stores/viewport.d.ts +0 -7
  271. package/dist/stores/viewport.js +0 -7
  272. package/dist/styles/animation.css +0 -33
  273. package/dist/styles/keyframes.css +0 -30
  274. package/dist/styles/reset.css +0 -133
  275. package/dist/styles.css +0 -0
  276. package/dist/styles.css.d.ts +0 -4
  277. package/dist/themes.css +0 -0
  278. package/dist/themes.css.d.ts +0 -4
  279. /package/dist/{components/accordion/types.js → @types/actions.js} +0 -0
  280. /package/dist/{components/alert/types.js → @types/animations.js} +0 -0
  281. /package/dist/{internal/types → @types}/components.js +0 -0
  282. /package/dist/{components/app/types.js → @types/core.js} +0 -0
  283. /package/dist/{labs/compiler/types → @types}/dom.js +0 -0
  284. /package/dist/{components/appbar/types.js → @types/events.js} +0 -0
  285. /package/dist/{components/aspect-ratio/types.js → @types/props.js} +0 -0
  286. /package/dist/components/{avatar/types.js → accordion/accordion.types.js} +0 -0
  287. /package/dist/components/{button/types.js → alert/alert.types.js} +0 -0
  288. /package/dist/components/{card/types.js → app/app.types.js} +0 -0
  289. /package/dist/components/{chip/types.js → appbar/appbar.types.js} +0 -0
  290. /package/dist/components/{dialog/types.js → aspect-ratio/aspect-ratio.types.js} +0 -0
  291. /package/dist/components/{dropdown/types.js → avatar/avatar.types.js} +0 -0
  292. /package/dist/components/{icon/types.js → btn/btn.types.js} +0 -0
  293. /package/dist/components/{list/types.js → card/card.types.js} +0 -0
  294. /package/dist/components/{modal/types.js → chip/chip.types.js} +0 -0
  295. /package/dist/components/{popover/types.js → dialog/dialog.types.js} +0 -0
  296. /package/dist/components/{separator/types.js → dropdown/dropdown.types.js} +0 -0
  297. /package/dist/components/{spacer/types.js → field/field.types.js} +0 -0
  298. /package/dist/components/{textfield/types.js → icon/icon.types.js} +0 -0
  299. /package/dist/components/{toolbar/types.js → list/list.types.js} +0 -0
  300. /package/dist/components/{tooltip/types.js → modal/modal.types.js} +0 -0
  301. /package/dist/{internal/types/configuration.js → components/popover/popover.types.js} +0 -0
  302. /package/dist/{labs/compiler/types/index.js → components/separator/separator.types.js} +0 -0
  303. /package/dist/{labs/utils/types/index.js → components/spacer/spacer.types.js} +0 -0
  304. /package/dist/{actions → hooks}/accordion.svelte.js +0 -0
package/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <a href="https://lapikit.dev">
2
- <img src="https://raw.githubusercontent.com/Nycolaide/lapikit/main/.github/lapikit.svg" alt="Lapikit Logo" width="125">
2
+ <img src="https://raw.githubusercontent.com/lapikit/lapikit.dev/main/.github/lapikit.svg" alt="Lapikit Logo" width="125">
3
3
  </a>
4
4
 
5
5
  # Lapikit - Svelte components library
@@ -8,10 +8,10 @@
8
8
  [![][subscribe-to-instagram]](https://www.instagram.com/lapikit/)
9
9
  [![][join-discord-lapikit]](https://discord.gg/gn9ZGtDtK4)
10
10
 
11
- [![][version]](https://github.com/nycolaide/lapikit/releases?q=lapikit&expanded=true)
11
+ [![][version]](https://github.com/lapikit/lapikit/releases?q=lapikit&expanded=true)
12
12
  [![][installs]](https://www.npmjs.com/package/lapikit)
13
13
  [![][installs-this-month]](https://www.npmjs.com/package/lapikit)
14
- [![][license]](https://github.com/nycolaide/lapikit/blob/main/LICENSE)
14
+ [![][license]](https://github.com/lapikit/lapikit/blob/main/LICENSE)
15
15
  [![][discord]](https://discord.gg/gn9ZGtDtK4)
16
16
 
17
17
  Lapikit is a comprehensive Svelte components library that provides developers with a wide range of pre-built, customizable UI components to streamline the development process. Whether you're building a simple website or a complex web application, Lapikit has the tools you need to create beautiful and functional user interfaces with ease.
@@ -71,7 +71,7 @@ Lapikit has created to help Svelte developers save time and effort when building
71
71
 
72
72
  ## 💖Community
73
73
 
74
- Join our growing community on [Discord](https://discord.gg/gn9ZGtDtK4) and [GitHub Discussions](https://github.com/nycolaide/lapikit/discussions) where we discuss and collaborate on all things Lapikit. Don't be shy, jump right in and be part of the discussion!
74
+ Join our growing community on [Discord](https://discord.gg/gn9ZGtDtK4) and [GitHub Discussions](https://github.com/lapikit/lapikit/discussions) where we discuss and collaborate on all things Lapikit. Don't be shy, jump right in and be part of the discussion!
75
75
 
76
76
  ## 💁‍♂️Contributing
77
77
 
@@ -84,9 +84,9 @@ Be part of the next revolution in code editing by contributing to the project. T
84
84
 
85
85
  ## 📄License
86
86
 
87
- Licensed under the [MIT license](https://github.com/nycolaide/lapikit/blob/main/LICENSE).
87
+ Licensed under the [MIT license](https://github.com/lapikit/lapikit/blob/main/LICENSE).
88
88
 
89
- Copyright © 2025 Nycolaide
89
+ Copyright © 2025 - 2026 Nycolaide
90
90
 
91
91
  ## 🪧We support these projects
92
92
 
@@ -96,12 +96,12 @@ We are proud supporters of the open-source community and contribute to several p
96
96
  <tr>
97
97
  <td>
98
98
  <a href="https://www.w3.org/">
99
- <img src="https://raw.githubusercontent.com/Nycolaide/lapikit/main/.github/w3c.svg" alt="W3C" width="75">
99
+ <img src="https://raw.githubusercontent.com/lapikit/lapikit.dev/main/.github/w3c.svg" alt="W3C" width="75">
100
100
  </a>
101
101
  </td>
102
102
  <td>
103
103
  <a href="https://humanstxt.org/">
104
- <img src="https://raw.githubusercontent.com/Nycolaide/lapikit/main/.github/humans.png" alt="Humans.txt" width="115">
104
+ <img src="https://raw.githubusercontent.com/lapikit/lapikit.dev/main/.github/humans.png" alt="Humans.txt" width="115">
105
105
  </a>
106
106
  </td>
107
107
  </tr>
@@ -111,7 +111,7 @@ We are proud supporters of the open-source community and contribute to several p
111
111
  [join-discord-lapikit]: https://img.shields.io/badge/Join%20the%20community-black.svg?style=for-the-badge&logo=Discord
112
112
  [subscribe-to-instagram]: https://img.shields.io/badge/Follow%20@Lapikit-black.svg?style=for-the-badge&logo=Instagram
113
113
  [version]: https://img.shields.io/npm/v/lapikit.svg?label=Version&color=f58142
114
- [license]: https://badgen.net/github/license/nycolaide/lapikit?label=License&color=cc5640
114
+ [license]: https://badgen.net/github/license/lapikit/lapikit?label=License&color=cc5640
115
115
  [installs]: https://badgen.net/npm/dt/lapikit?label=NPM%20installs&color=40ba12
116
116
  [installs-this-month]: https://badgen.net/npm/dm/lapikit?label=NPM%20installs&color=40ba12
117
117
  [discord]: https://img.shields.io/discord/1383879204671721492?color=5865F2&label=Discord&logo=discord&logoColor=white
package/bin/helpers.js ADDED
@@ -0,0 +1,251 @@
1
+ import readline from 'node:readline/promises';
2
+ import { emitKeypressEvents, moveCursor, cursorTo, clearLine } from 'node:readline';
3
+
4
+ const color = {
5
+ red: (text) => `\x1b[31m${text}\x1b[0m`,
6
+ green: (text) => `\x1b[32m${text}\x1b[0m`,
7
+ yellow: (text) => `\x1b[33m${text}\x1b[0m`,
8
+ blue: (text) => `\x1b[34m${text}\x1b[0m`,
9
+ purple: (text) => `\x1b[35m${text}\x1b[0m`,
10
+ cyan: (text) => `\x1b[36m${text}\x1b[0m`
11
+ };
12
+
13
+ const variant = {
14
+ bold: (text) => `\x1b[1m${text}\x1b[0m`,
15
+ underline: (text) => `\x1b[4m${text}\x1b[0m`,
16
+ inverse: (text) => `\x1b[7m${text}\x1b[0m`
17
+ };
18
+
19
+ const bold = {
20
+ red: (text) => `\x1b[1m\x1b[31m${text}\x1b[0m`,
21
+ green: (text) => `\x1b[1m\x1b[32m${text}\x1b[0m`,
22
+ yellow: (text) => `\x1b[1m\x1b[33m${text}\x1b[0m`,
23
+ blue: (text) => `\x1b[1m\x1b[34m${text}\x1b[0m`,
24
+ purple: (text) => `\x1b[1m\x1b[35m${text}\x1b[0m`,
25
+ cyan: (text) => `\x1b[1m\x1b[36m${text}\x1b[0m`
26
+ };
27
+
28
+ const inverse = {
29
+ red: (text) => `\x1b[7m\x1b[31m${text}\x1b[0m`,
30
+ green: (text) => `\x1b[7m\x1b[32m${text}\x1b[0m`,
31
+ yellow: (text) => `\x1b[7m\x1b[33m${text}\x1b[0m`,
32
+ blue: (text) => `\x1b[7m\x1b[34m${text}\x1b[0m`,
33
+ purple: (text) => `\x1b[7m\x1b[35m${text}\x1b[0m`,
34
+ cyan: (text) => `\x1b[7m\x1b[36m${text}\x1b[0m`
35
+ };
36
+
37
+ const underline = {
38
+ red: (text) => `\x1b[4m\x1b[31m${text}\x1b[0m`,
39
+ green: (text) => `\x1b[4m\x1b[32m${text}\x1b[0m`,
40
+ yellow: (text) => `\x1b[4m\x1b[33m${text}\x1b[0m`,
41
+ blue: (text) => `\x1b[4m\x1b[34m${text}\x1b[0m`,
42
+ purple: (text) => `\x1b[4m\x1b[35m${text}\x1b[0m`,
43
+ cyan: (text) => `\x1b[4m\x1b[36m${text}\x1b[0m`
44
+ };
45
+
46
+ export const ansi = {
47
+ color,
48
+ variant,
49
+ bold,
50
+ inverse,
51
+ underline
52
+ };
53
+
54
+ export const terminal = (type = 'info', msg) => {
55
+ const name = ansi.color.cyan('lapikit');
56
+
57
+ if (type === 'error') console.error(name, ansi.bold.red('[error]'), msg);
58
+ else if (type === 'warn') console.warn(name, ansi.bold.yellow('[warn]'), msg);
59
+ else if (type === 'success') console.warn(name, ansi.bold.green('[success]'), msg);
60
+ else if (type === 'none') console.log(msg);
61
+ else console.log(name, ansi.bold.blue('[info]'), msg);
62
+ };
63
+
64
+ export function createRL() {
65
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
66
+
67
+ rl.on('SIGINT', () => {
68
+ if (process.stdin.isTTY) process.stdin.setRawMode(false);
69
+ console.log('\n');
70
+ terminal('warn', 'installation canceled.');
71
+ process.exit(0);
72
+ });
73
+
74
+ return rl;
75
+ }
76
+
77
+ export async function toggle(rl, message, initial = true) {
78
+ const hint = initial ? 'Y/n' : 'y/N';
79
+ const answer = (await rl.question(`${message} (${hint}): `)).trim().toLowerCase();
80
+ if (answer === '') return initial;
81
+ return answer === 'y';
82
+ }
83
+
84
+ export async function text(rl, message, initial = '', validate) {
85
+ while (true) {
86
+ const hint = initial ? ` (${initial})` : '';
87
+ const answer = (await rl.question(`${message}${hint}: `)).trim();
88
+ const value = answer === '' ? initial : answer;
89
+ if (validate) {
90
+ const result = validate(value);
91
+ if (result !== true) {
92
+ terminal('warn', result);
93
+ continue;
94
+ }
95
+ }
96
+ return value;
97
+ }
98
+ }
99
+
100
+ async function selectFallback(rl, message, choices) {
101
+ console.log(`\n${message}`);
102
+ choices.forEach((c, i) => console.log(` ${i + 1}. ${c.title}`));
103
+
104
+ while (true) {
105
+ const answer = (await rl.question(`Choice (1): `)).trim();
106
+ const index = answer === '' ? 0 : parseInt(answer, 10) - 1;
107
+ if (index >= 0 && index < choices.length) return choices[index].value;
108
+ terminal('warn', `Please enter a number between 1 and ${choices.length}`);
109
+ }
110
+ }
111
+
112
+ async function multiselectFallback(rl, message, choices) {
113
+ console.log(`\n${message}`);
114
+ choices.forEach((c, i) => console.log(` ${i + 1}. ${c.title}`));
115
+ console.log(` (enter numbers separated by commas, e.g. 1,2 - leave empty for none)`);
116
+
117
+ while (true) {
118
+ const answer = (await rl.question(`Choice: `)).trim();
119
+ if (answer === '') return [];
120
+
121
+ const indexes = answer.split(',').map((part) => parseInt(part.trim(), 10) - 1);
122
+ const valid = indexes.every((index) => index >= 0 && index < choices.length);
123
+ if (valid) return [...new Set(indexes)].map((index) => choices[index].value);
124
+
125
+ terminal('warn', `Please enter numbers between 1 and ${choices.length}, separated by commas`);
126
+ }
127
+ }
128
+
129
+ async function interactiveList(rl, message, hint, choices, renderLine, onKey) {
130
+ console.log(`\n${message}`);
131
+ console.log(ansi.color.cyan(` (${hint})`));
132
+ choices.forEach((_, i) => console.log(renderLine(i)));
133
+
134
+ const { stdin } = process;
135
+ rl.pause();
136
+ const wasRaw = stdin.isRaw;
137
+ emitKeypressEvents(stdin, rl);
138
+ stdin.setRawMode(true);
139
+ stdin.resume();
140
+
141
+ return new Promise((resolve) => {
142
+ const redrawLine = (index) => {
143
+ const rowsUp = choices.length - index;
144
+ moveCursor(process.stdout, 0, -rowsUp);
145
+ cursorTo(process.stdout, 0);
146
+ clearLine(process.stdout, 1);
147
+ process.stdout.write(renderLine(index));
148
+ moveCursor(process.stdout, 0, rowsUp);
149
+ cursorTo(process.stdout, 0);
150
+ };
151
+
152
+ const cleanup = () => {
153
+ stdin.removeListener('keypress', onKeypress);
154
+ stdin.setRawMode(wasRaw);
155
+ rl.resume();
156
+ };
157
+
158
+ const onKeypress = (str, key) => {
159
+ if (key.ctrl && key.name === 'c') {
160
+ cleanup();
161
+ process.stdout.write('\n');
162
+ terminal('warn', 'installation canceled.');
163
+ process.exit(130);
164
+ }
165
+ onKey(key, redrawLine, (value) => {
166
+ cleanup();
167
+ console.log('');
168
+ resolve(value);
169
+ });
170
+ };
171
+
172
+ stdin.on('keypress', onKeypress);
173
+ });
174
+ }
175
+
176
+ export async function select(rl, message, choices) {
177
+ const { stdin } = process;
178
+ if (!stdin.isTTY || typeof stdin.setRawMode !== 'function') {
179
+ return selectFallback(rl, message, choices);
180
+ }
181
+
182
+ let cursor = 0;
183
+ const renderLine = (index) => {
184
+ const radio = index === cursor ? ansi.color.green('(●)') : '( )';
185
+ const pointer = index === cursor ? ansi.color.cyan('❯') : ' ';
186
+ return `${pointer} ${radio} ${choices[index].title}`;
187
+ };
188
+
189
+ return interactiveList(
190
+ rl,
191
+ message,
192
+ '↑/↓ move, enter to confirm',
193
+ choices,
194
+ renderLine,
195
+ (key, redrawLine, resolve) => {
196
+ const previousCursor = cursor;
197
+ if (key.name === 'up') {
198
+ cursor = (cursor - 1 + choices.length) % choices.length;
199
+ redrawLine(previousCursor);
200
+ redrawLine(cursor);
201
+ } else if (key.name === 'down') {
202
+ cursor = (cursor + 1) % choices.length;
203
+ redrawLine(previousCursor);
204
+ redrawLine(cursor);
205
+ } else if (key.name === 'return') {
206
+ resolve(choices[cursor].value);
207
+ }
208
+ }
209
+ );
210
+ }
211
+
212
+ export async function multiselect(rl, message, choices) {
213
+ const { stdin } = process;
214
+ if (!stdin.isTTY || typeof stdin.setRawMode !== 'function') {
215
+ return multiselectFallback(rl, message, choices);
216
+ }
217
+
218
+ const selected = new Set();
219
+ let cursor = 0;
220
+ const renderLine = (index) => {
221
+ const checked = selected.has(index) ? ansi.color.green('[x]') : '[ ]';
222
+ const pointer = index === cursor ? ansi.color.cyan('❯') : ' ';
223
+ return `${pointer} ${checked} ${choices[index].title}`;
224
+ };
225
+
226
+ return interactiveList(
227
+ rl,
228
+ message,
229
+ '↑/↓ move, space to select, enter to confirm',
230
+ choices,
231
+ renderLine,
232
+ (key, redrawLine, resolve) => {
233
+ const previousCursor = cursor;
234
+ if (key.name === 'up') {
235
+ cursor = (cursor - 1 + choices.length) % choices.length;
236
+ redrawLine(previousCursor);
237
+ redrawLine(cursor);
238
+ } else if (key.name === 'down') {
239
+ cursor = (cursor + 1) % choices.length;
240
+ redrawLine(previousCursor);
241
+ redrawLine(cursor);
242
+ } else if (key.name === 'space') {
243
+ if (selected.has(cursor)) selected.delete(cursor);
244
+ else selected.add(cursor);
245
+ redrawLine(cursor);
246
+ } else if (key.name === 'return') {
247
+ resolve([...selected].sort((a, b) => a - b).map((index) => choices[index].value));
248
+ }
249
+ }
250
+ );
251
+ }
package/bin/hooks.js ADDED
@@ -0,0 +1,318 @@
1
+ #!/usr/bin/env node
2
+ import { promises as fs } from 'node:fs';
3
+ import path from 'node:path';
4
+ import { spawn } from 'node:child_process';
5
+ import { terminal } from './helpers.js';
6
+
7
+ const INSTALL_ARGS = {
8
+ npm: ['install', '--save-dev'],
9
+ yarn: ['add', '-D'],
10
+ pnpm: ['add', '--save-dev'],
11
+ bun: ['add', '-D']
12
+ };
13
+
14
+ export function installDependency(pkgManager, packageName, cwd) {
15
+ const args = INSTALL_ARGS[pkgManager];
16
+ if (!args) throw new Error(`Unsupported package manager: ${pkgManager}`);
17
+ return new Promise((resolve, reject) => {
18
+ const child = spawn(pkgManager, [...args, packageName], {
19
+ cwd,
20
+ stdio: 'inherit',
21
+ shell: process.platform === 'win32'
22
+ });
23
+ child.on('error', reject);
24
+ child.on('close', (code) =>
25
+ code === 0 ? resolve() : reject(new Error(`${pkgManager} exited with code ${code}`))
26
+ );
27
+ });
28
+ }
29
+
30
+ function findMatchingDelimiter(content, openIndex, openChar, closeChar) {
31
+ let depth = 0;
32
+ for (let i = openIndex; i < content.length; i++) {
33
+ const ch = content[i];
34
+ if (ch === '"' || ch === "'" || ch === '`') {
35
+ i = skipString(content, i);
36
+ continue;
37
+ }
38
+ if (ch === openChar) depth++;
39
+ else if (ch === closeChar) {
40
+ depth--;
41
+ if (depth === 0) return i;
42
+ }
43
+ }
44
+ return -1;
45
+ }
46
+
47
+ function skipString(source, start) {
48
+ const quote = source[start];
49
+ for (let i = start + 1; i < source.length; i++) {
50
+ if (source[i] === '\\') {
51
+ i++;
52
+ continue;
53
+ }
54
+ if (source[i] === quote) return i;
55
+ }
56
+ return source.length - 1;
57
+ }
58
+
59
+ function insertImportLine(content, importLine) {
60
+ const lines = content.split('\n');
61
+ let importInsertIndex = 0;
62
+ for (let i = 0; i < lines.length; i++) {
63
+ if (lines[i].trim().startsWith('import ')) importInsertIndex = i + 1;
64
+ }
65
+ lines.splice(importInsertIndex, 0, importLine);
66
+ return lines.join('\n');
67
+ }
68
+
69
+ function buildPreprocessCall(pluginKeys = []) {
70
+ if (!pluginKeys.length) return `lapikitPreprocess()`;
71
+ const plugins = pluginKeys.map((key) => `'${key}'`).join(', ');
72
+ return `lapikitPreprocess({ plugins: [${plugins}] })`;
73
+ }
74
+
75
+ function mergeExistingPreprocessCall(content, pluginKeys) {
76
+ if (!pluginKeys.length) return null;
77
+
78
+ const callMatch = content.match(/lapikitPreprocess\s*\(\s*(\{[\s\S]*?\})?\s*\)/);
79
+ if (!callMatch) return null;
80
+
81
+ const [fullMatch, optionsSource] = callMatch;
82
+ const pluginsMatch = optionsSource?.match(/plugins\s*:\s*\[([^\]]*)\]/);
83
+ const existingKeys = pluginsMatch
84
+ ? [...pluginsMatch[1].matchAll(/'([^']+)'|"([^"]+)"/g)].map((m) => m[1] ?? m[2])
85
+ : [];
86
+
87
+ const merged = [...new Set([...existingKeys, ...pluginKeys])];
88
+ if (merged.length === existingKeys.length) return null;
89
+
90
+ const newCall = buildPreprocessCall(merged);
91
+ return (
92
+ content.slice(0, callMatch.index) + newCall + content.slice(callMatch.index + fullMatch.length)
93
+ );
94
+ }
95
+
96
+ function findValueEnd(source, start) {
97
+ let depth = 0;
98
+ for (let i = start; i < source.length; i++) {
99
+ const ch = source[i];
100
+ if (ch === '"' || ch === "'" || ch === '`') {
101
+ i = skipString(source, i);
102
+ continue;
103
+ }
104
+ if (ch === '(' || ch === '[' || ch === '{') depth++;
105
+ else if (ch === ')' || ch === ']' || ch === '}') {
106
+ if (depth === 0) return i;
107
+ depth--;
108
+ } else if (ch === ',' && depth === 0) return i;
109
+ }
110
+ return source.length;
111
+ }
112
+
113
+ function injectPreprocessEntry(objectSource, pluginKeys = []) {
114
+ const call = buildPreprocessCall(pluginKeys);
115
+
116
+ const keyMatch = objectSource.match(/preprocess\s*:\s*/);
117
+ if (!keyMatch) {
118
+ return objectSource.replace('{', `{\n\t\t\tpreprocess: [${call}],`);
119
+ }
120
+ const valueStart = keyMatch.index + keyMatch[0].length;
121
+
122
+ if (objectSource[valueStart] === '[') {
123
+ const openBracketIndex = valueStart;
124
+ const closeBracketIndex = findMatchingDelimiter(objectSource, openBracketIndex, '[', ']');
125
+ const inner = objectSource.slice(openBracketIndex + 1, closeBracketIndex);
126
+ const trimmed = inner.trim();
127
+
128
+ let newInner;
129
+ if (!trimmed) {
130
+ newInner = call;
131
+ } else if (inner.includes('\n')) {
132
+ const firstItemMatch = inner.match(/\n(\s*)\S/);
133
+ const indent = firstItemMatch ? firstItemMatch[1] : '\t\t';
134
+ const closingMatch = inner.match(/\n(\s*)$/);
135
+ const closingIndent = closingMatch ? closingMatch[1] : '\t';
136
+ const innerTrimmed = inner.trimEnd();
137
+ const sep = innerTrimmed.endsWith(',') ? '' : ',';
138
+ newInner = `${innerTrimmed}${sep}\n${indent}${call}\n${closingIndent}`;
139
+ } else {
140
+ const sep = trimmed.endsWith(',') ? ' ' : ', ';
141
+ newInner = `${trimmed}${sep}${call}`;
142
+ }
143
+ return (
144
+ objectSource.slice(0, openBracketIndex + 1) + newInner + objectSource.slice(closeBracketIndex)
145
+ );
146
+ }
147
+
148
+ const valueEnd = findValueEnd(objectSource, valueStart);
149
+ const expr = objectSource.slice(valueStart, valueEnd).trim();
150
+ return objectSource.slice(0, valueStart) + `[${expr}, ${call}]` + objectSource.slice(valueEnd);
151
+ }
152
+
153
+ export async function findSvelteConfigFile(projectPath) {
154
+ for (const ext of ['js', 'mjs', 'cjs', 'ts']) {
155
+ const file = path.join(projectPath, `svelte.config.${ext}`);
156
+ try {
157
+ await fs.access(file);
158
+ return file;
159
+ } catch {
160
+ // lapikit other step
161
+ }
162
+ }
163
+ throw new Error('No svelte.config file found');
164
+ }
165
+
166
+ export async function addLiliPreprocess(svelteConfigFile, pluginKeys = []) {
167
+ let content = await fs.readFile(svelteConfigFile, 'utf-8');
168
+ const lapikitImport = `import { lapikitPreprocess } from 'lapikit/preprocess';`;
169
+
170
+ if (content.includes(`from 'lapikit/preprocess'`)) {
171
+ const updated = mergeExistingPreprocessCall(content, pluginKeys);
172
+ if (!updated) {
173
+ terminal('warn', `lapikitPreprocess already imported in ${svelteConfigFile}`);
174
+ return;
175
+ }
176
+ await fs.writeFile(svelteConfigFile, updated);
177
+ terminal('success', `lapikitPreprocess plugins updated in ${svelteConfigFile}`);
178
+ return;
179
+ }
180
+
181
+ const match = content.match(/(?:const\s+\w+\s*=\s*|export\s+default\s*)(\{)/);
182
+ if (!match) {
183
+ throw new Error(`Could not find the exported config object in ${svelteConfigFile}`);
184
+ }
185
+
186
+ const openBraceIndex = match.index + match[0].length - 1;
187
+ const closeBraceIndex = findMatchingDelimiter(content, openBraceIndex, '{', '}');
188
+ if (closeBraceIndex === -1) {
189
+ throw new Error(`Could not parse the config object in ${svelteConfigFile}`);
190
+ }
191
+
192
+ const objectSource = content.slice(openBraceIndex, closeBraceIndex + 1);
193
+ const updatedObject = injectPreprocessEntry(objectSource, pluginKeys);
194
+ content = content.slice(0, openBraceIndex) + updatedObject + content.slice(closeBraceIndex + 1);
195
+ content = insertImportLine(content, lapikitImport);
196
+
197
+ await fs.writeFile(svelteConfigFile, content);
198
+ terminal('success', `lapikitPreprocess added to ${svelteConfigFile}`);
199
+ }
200
+
201
+ export async function findViteConfigFile(projectPath) {
202
+ for (const ext of ['ts', 'js', 'mjs', 'cjs']) {
203
+ const file = path.join(projectPath, `vite.config.${ext}`);
204
+ try {
205
+ await fs.access(file);
206
+ return file;
207
+ } catch {
208
+ // lapikit other step
209
+ }
210
+ }
211
+ return null;
212
+ }
213
+
214
+ function findSveltekitPluginCall(content) {
215
+ const match = content.match(/sveltekit\s*\(\s*\{/);
216
+ if (!match) return null;
217
+
218
+ const openBraceIndex = match.index + match[0].length - 1;
219
+ const closeBraceIndex = findMatchingDelimiter(content, openBraceIndex, '{', '}');
220
+ if (closeBraceIndex === -1) return null;
221
+
222
+ return { openBraceIndex, closeBraceIndex };
223
+ }
224
+
225
+ export async function addLiliPreprocessToViteConfig(viteConfigFile, pluginKeys = []) {
226
+ let content = await fs.readFile(viteConfigFile, 'utf-8');
227
+ const lapikitImport = `import { lapikitPreprocess } from 'lapikit/preprocess';`;
228
+
229
+ if (content.includes(`from 'lapikit/preprocess'`)) {
230
+ const updated = mergeExistingPreprocessCall(content, pluginKeys);
231
+ if (!updated) {
232
+ terminal('warn', `lapikitPreprocess already imported in ${viteConfigFile}`);
233
+ return;
234
+ }
235
+ await fs.writeFile(viteConfigFile, updated);
236
+ terminal('success', `lapikitPreprocess plugins updated in ${viteConfigFile}`);
237
+ return;
238
+ }
239
+
240
+ const pluginCall = findSveltekitPluginCall(content);
241
+ if (!pluginCall) {
242
+ throw new Error(`Could not find a sveltekit({ ... }) plugin call in ${viteConfigFile}`);
243
+ }
244
+
245
+ const { openBraceIndex, closeBraceIndex } = pluginCall;
246
+ const objectSource = content.slice(openBraceIndex, closeBraceIndex + 1);
247
+ const updatedObject = injectPreprocessEntry(objectSource, pluginKeys);
248
+ content = content.slice(0, openBraceIndex) + updatedObject + content.slice(closeBraceIndex + 1);
249
+ content = insertImportLine(content, lapikitImport);
250
+
251
+ await fs.writeFile(viteConfigFile, content);
252
+ terminal('success', `lapikitPreprocess added to ${viteConfigFile}`);
253
+ }
254
+
255
+ // Since SvelteKit 2.62, Svelte/preprocess config can be passed directly to the
256
+ // sveltekit() vite plugin instead of svelte.config.js — when it is, svelte.config.js
257
+ // is ignored, so the vite.config plugin call takes priority when both exist.
258
+ export async function resolveSveltePreprocessTarget(projectPath) {
259
+ const viteConfigFile = await findViteConfigFile(projectPath);
260
+ if (viteConfigFile) {
261
+ const content = await fs.readFile(viteConfigFile, 'utf-8');
262
+ if (findSveltekitPluginCall(content)) {
263
+ return { file: viteConfigFile, add: addLiliPreprocessToViteConfig };
264
+ }
265
+ }
266
+
267
+ try {
268
+ const svelteConfigFile = await findSvelteConfigFile(projectPath);
269
+ return { file: svelteConfigFile, add: addLiliPreprocess };
270
+ } catch {
271
+ throw new Error(
272
+ 'No svelte.config file found, and no sveltekit({ ... }) plugin config found in vite.config.(js|ts) ' +
273
+ "Add lapikitPreprocess() manually: import { lapikitPreprocess } from 'lapikit/preprocess'; " +
274
+ 'then add it to your preprocess array.'
275
+ );
276
+ }
277
+ }
278
+
279
+ export async function findEslintConfigFile(projectPath) {
280
+ for (const ext of ['js', 'mjs', 'cjs', 'ts']) {
281
+ const file = path.join(projectPath, `eslint.config.${ext}`);
282
+ try {
283
+ await fs.access(file);
284
+ return file;
285
+ } catch {
286
+ // lapikit other step
287
+ }
288
+ }
289
+ throw new Error('No eslint.config.js file found');
290
+ }
291
+
292
+ export async function addLapikitEslintConfig(eslintConfigFile) {
293
+ let content = await fs.readFile(eslintConfigFile, 'utf-8');
294
+ const lapikitImport = `import lapikitConfig from 'eslint-config-lapikit';`;
295
+
296
+ if (content.includes(`from 'eslint-config-lapikit'`)) {
297
+ terminal('warn', `eslint-config-lapikit already imported in ${eslintConfigFile}`);
298
+ return;
299
+ }
300
+
301
+ content = insertImportLine(content, lapikitImport);
302
+
303
+ // Matches `export default [...]` as well as wrapped forms like
304
+ // `export default defineConfig([...])`, `export default defineConfig(a, b)`
305
+ // (rest-args form, no array) and member-expression wrappers like
306
+ // `export default ts.config(...)`.
307
+ const exportArrayPattern = /export\s+default\s*(?:\[|[\w.]+\s*\()/;
308
+ if (!exportArrayPattern.test(content)) {
309
+ throw new Error(
310
+ `Could not find "export default [...]" in ${eslintConfigFile}. Please add "...lapikitConfig" manually.`
311
+ );
312
+ }
313
+
314
+ content = content.replace(exportArrayPattern, (m) => `${m}\n\t...lapikitConfig,`);
315
+
316
+ await fs.writeFile(eslintConfigFile, content);
317
+ terminal('success', `eslint-config-lapikit added to ${eslintConfigFile}`);
318
+ }