@fecommunity/reactpress 3.7.0 → 4.0.0-beta.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/bin/reactpress-cli-shim.js +2 -6
  2. package/bin/reactpress-theme-client.js +2 -0
  3. package/bin/reactpress.js +1 -380
  4. package/out/.source-fingerprint-cli +1 -0
  5. package/out/bin/reactpress-cli-shim.d.ts +3 -0
  6. package/out/bin/reactpress-cli-shim.d.ts.map +1 -0
  7. package/out/bin/reactpress-cli-shim.js +28 -0
  8. package/out/bin/reactpress-cli-shim.js.map +1 -0
  9. package/out/bin/reactpress-theme-client.d.ts +3 -0
  10. package/out/bin/reactpress-theme-client.d.ts.map +1 -0
  11. package/out/bin/reactpress-theme-client.js +113 -0
  12. package/out/bin/reactpress-theme-client.js.map +1 -0
  13. package/out/bin/reactpress.d.ts +3 -0
  14. package/out/bin/reactpress.d.ts.map +1 -0
  15. package/out/bin/reactpress.js +534 -0
  16. package/out/bin/reactpress.js.map +1 -0
  17. package/out/core/services/config.d.ts +12 -0
  18. package/out/core/services/config.d.ts.map +1 -0
  19. package/out/core/services/config.js +137 -0
  20. package/out/core/services/config.js.map +1 -0
  21. package/out/core/services/database/index.d.ts +17 -0
  22. package/out/core/services/database/index.d.ts.map +1 -0
  23. package/out/core/services/database/index.js +242 -0
  24. package/out/core/services/database/index.js.map +1 -0
  25. package/out/core/services/database/mysql.d.ts +14 -0
  26. package/out/core/services/database/mysql.d.ts.map +1 -0
  27. package/out/core/services/database/mysql.js +82 -0
  28. package/out/core/services/database/mysql.js.map +1 -0
  29. package/out/core/services/database/profile.d.ts +6 -0
  30. package/out/core/services/database/profile.d.ts.map +1 -0
  31. package/out/core/services/database/profile.js +60 -0
  32. package/out/core/services/database/profile.js.map +1 -0
  33. package/out/core/services/database/sqlite.d.ts +10 -0
  34. package/out/core/services/database/sqlite.d.ts.map +1 -0
  35. package/out/core/services/database/sqlite.js +73 -0
  36. package/out/core/services/database/sqlite.js.map +1 -0
  37. package/out/core/services/exec.d.ts +21 -0
  38. package/out/core/services/exec.d.ts.map +1 -0
  39. package/out/core/services/exec.js +56 -0
  40. package/out/core/services/exec.js.map +1 -0
  41. package/out/core/services/init.d.ts +11 -0
  42. package/out/core/services/init.d.ts.map +1 -0
  43. package/out/core/services/init.js +60 -0
  44. package/out/core/services/init.js.map +1 -0
  45. package/out/core/services/local-site.d.ts +24 -0
  46. package/out/core/services/local-site.d.ts.map +1 -0
  47. package/out/core/services/local-site.js +144 -0
  48. package/out/core/services/local-site.js.map +1 -0
  49. package/out/core/utils/cli-context.d.ts +3 -0
  50. package/out/core/utils/cli-context.d.ts.map +1 -0
  51. package/out/core/utils/cli-context.js +12 -0
  52. package/out/core/utils/cli-context.js.map +1 -0
  53. package/out/core/utils/paths.d.ts +20 -0
  54. package/out/core/utils/paths.d.ts.map +1 -0
  55. package/out/core/utils/paths.js +34 -0
  56. package/out/core/utils/paths.js.map +1 -0
  57. package/out/core/utils/platform.d.ts +7 -0
  58. package/out/core/utils/platform.d.ts.map +1 -0
  59. package/out/core/utils/platform.js +28 -0
  60. package/out/core/utils/platform.js.map +1 -0
  61. package/out/core/utils/port.d.ts +4 -0
  62. package/out/core/utils/port.d.ts.map +1 -0
  63. package/out/core/utils/port.js +32 -0
  64. package/out/core/utils/port.js.map +1 -0
  65. package/out/lib/api-dev-runner.d.ts +3 -0
  66. package/out/lib/api-dev-runner.d.ts.map +1 -0
  67. package/{lib → out/lib}/api-dev-runner.js +4 -1
  68. package/out/lib/api-dev-runner.js.map +1 -0
  69. package/out/lib/api-dev.d.ts +2 -0
  70. package/out/lib/api-dev.d.ts.map +1 -0
  71. package/out/lib/api-dev.js +101 -0
  72. package/out/lib/api-dev.js.map +1 -0
  73. package/out/lib/bootstrap.d.ts +18 -0
  74. package/out/lib/bootstrap.d.ts.map +1 -0
  75. package/out/lib/bootstrap.js +93 -0
  76. package/out/lib/bootstrap.js.map +1 -0
  77. package/out/lib/build.d.ts +2 -0
  78. package/out/lib/build.d.ts.map +1 -0
  79. package/out/lib/build.js +191 -0
  80. package/out/lib/build.js.map +1 -0
  81. package/out/lib/db-backup.d.ts +2 -0
  82. package/out/lib/db-backup.d.ts.map +1 -0
  83. package/out/lib/db-backup.js +68 -0
  84. package/out/lib/db-backup.js.map +1 -0
  85. package/out/lib/dev-banner.d.ts +2 -0
  86. package/out/lib/dev-banner.d.ts.map +1 -0
  87. package/out/lib/dev-banner.js +102 -0
  88. package/out/lib/dev-banner.js.map +1 -0
  89. package/out/lib/dev-child-io.d.ts +2 -0
  90. package/out/lib/dev-child-io.d.ts.map +1 -0
  91. package/out/lib/dev-child-io.js +80 -0
  92. package/out/lib/dev-child-io.js.map +1 -0
  93. package/out/lib/dev-log.d.ts +2 -0
  94. package/out/lib/dev-log.d.ts.map +1 -0
  95. package/out/lib/dev-log.js +64 -0
  96. package/out/lib/dev-log.js.map +1 -0
  97. package/out/lib/dev-session.d.ts +2 -0
  98. package/out/lib/dev-session.d.ts.map +1 -0
  99. package/out/lib/dev-session.js +95 -0
  100. package/out/lib/dev-session.js.map +1 -0
  101. package/out/lib/dev.d.ts +2 -0
  102. package/out/lib/dev.d.ts.map +1 -0
  103. package/out/lib/dev.js +906 -0
  104. package/out/lib/dev.js.map +1 -0
  105. package/out/lib/docker.d.ts +2 -0
  106. package/out/lib/docker.d.ts.map +1 -0
  107. package/out/lib/docker.js +398 -0
  108. package/out/lib/docker.js.map +1 -0
  109. package/out/lib/doctor.d.ts +2 -0
  110. package/out/lib/doctor.d.ts.map +1 -0
  111. package/out/lib/doctor.js +260 -0
  112. package/out/lib/doctor.js.map +1 -0
  113. package/out/lib/health-parse.d.ts +5 -0
  114. package/out/lib/health-parse.d.ts.map +1 -0
  115. package/out/lib/health-parse.js +36 -0
  116. package/out/lib/health-parse.js.map +1 -0
  117. package/out/lib/health-parse.test.d.ts +2 -0
  118. package/out/lib/health-parse.test.d.ts.map +1 -0
  119. package/out/lib/health-parse.test.js +19 -0
  120. package/out/lib/health-parse.test.js.map +1 -0
  121. package/out/lib/http.d.ts +2 -0
  122. package/out/lib/http.d.ts.map +1 -0
  123. package/out/lib/http.js +234 -0
  124. package/out/lib/http.js.map +1 -0
  125. package/out/lib/i18n/index.d.ts +2 -0
  126. package/out/lib/i18n/index.d.ts.map +1 -0
  127. package/out/lib/i18n/index.js +29 -0
  128. package/out/lib/i18n/index.js.map +1 -0
  129. package/out/lib/i18n/strings.d.ts +2 -0
  130. package/out/lib/i18n/strings.d.ts.map +1 -0
  131. package/out/lib/i18n/strings.js +1140 -0
  132. package/out/lib/i18n/strings.js.map +1 -0
  133. package/out/lib/lifecycle.d.ts +2 -0
  134. package/out/lib/lifecycle.d.ts.map +1 -0
  135. package/out/lib/lifecycle.js +169 -0
  136. package/out/lib/lifecycle.js.map +1 -0
  137. package/out/lib/nginx.d.ts +2 -0
  138. package/out/lib/nginx.d.ts.map +1 -0
  139. package/out/lib/nginx.js +618 -0
  140. package/out/lib/nginx.js.map +1 -0
  141. package/out/lib/paths.d.ts +2 -0
  142. package/out/lib/paths.d.ts.map +1 -0
  143. package/out/lib/paths.js +106 -0
  144. package/out/lib/paths.js.map +1 -0
  145. package/out/lib/plugin-build.d.ts +2 -0
  146. package/out/lib/plugin-build.d.ts.map +1 -0
  147. package/out/lib/plugin-build.js +104 -0
  148. package/out/lib/plugin-build.js.map +1 -0
  149. package/out/lib/plugin-cli.d.ts +2 -0
  150. package/out/lib/plugin-cli.d.ts.map +1 -0
  151. package/out/lib/plugin-cli.js +142 -0
  152. package/out/lib/plugin-cli.js.map +1 -0
  153. package/out/lib/pm2.d.ts +2 -0
  154. package/out/lib/pm2.d.ts.map +1 -0
  155. package/out/lib/pm2.js +32 -0
  156. package/out/lib/pm2.js.map +1 -0
  157. package/out/lib/ports.d.ts +2 -0
  158. package/out/lib/ports.d.ts.map +1 -0
  159. package/out/lib/ports.js +394 -0
  160. package/out/lib/ports.js.map +1 -0
  161. package/out/lib/process.d.ts +2 -0
  162. package/out/lib/process.d.ts.map +1 -0
  163. package/out/lib/process.js +47 -0
  164. package/out/lib/process.js.map +1 -0
  165. package/out/lib/prod-memory.d.ts +6 -0
  166. package/out/lib/prod-memory.d.ts.map +1 -0
  167. package/out/lib/prod-memory.js +57 -0
  168. package/out/lib/prod-memory.js.map +1 -0
  169. package/out/lib/project-type.d.ts +2 -0
  170. package/out/lib/project-type.d.ts.map +1 -0
  171. package/out/lib/project-type.js +77 -0
  172. package/out/lib/project-type.js.map +1 -0
  173. package/out/lib/publish.d.ts +3 -0
  174. package/out/lib/publish.d.ts.map +1 -0
  175. package/out/lib/publish.js +388 -0
  176. package/out/lib/publish.js.map +1 -0
  177. package/out/lib/remote-dev.d.ts +2 -0
  178. package/out/lib/remote-dev.d.ts.map +1 -0
  179. package/out/lib/remote-dev.js +158 -0
  180. package/out/lib/remote-dev.js.map +1 -0
  181. package/out/lib/root.d.ts +2 -0
  182. package/out/lib/root.d.ts.map +1 -0
  183. package/out/lib/root.js +85 -0
  184. package/out/lib/root.js.map +1 -0
  185. package/out/lib/spawn.d.ts +2 -0
  186. package/out/lib/spawn.d.ts.map +1 -0
  187. package/out/lib/spawn.js +96 -0
  188. package/out/lib/spawn.js.map +1 -0
  189. package/out/lib/status.d.ts +2 -0
  190. package/out/lib/status.d.ts.map +1 -0
  191. package/out/lib/status.js +78 -0
  192. package/out/lib/status.js.map +1 -0
  193. package/out/lib/theme-catalog.d.ts +2 -0
  194. package/out/lib/theme-catalog.d.ts.map +1 -0
  195. package/out/lib/theme-catalog.js +6 -0
  196. package/out/lib/theme-catalog.js.map +1 -0
  197. package/out/lib/theme-cli.d.ts +2 -0
  198. package/out/lib/theme-cli.d.ts.map +1 -0
  199. package/out/lib/theme-cli.js +50 -0
  200. package/out/lib/theme-cli.js.map +1 -0
  201. package/out/lib/theme-dev.d.ts +2 -0
  202. package/out/lib/theme-dev.d.ts.map +1 -0
  203. package/out/lib/theme-dev.js +759 -0
  204. package/out/lib/theme-dev.js.map +1 -0
  205. package/out/lib/theme-env.d.ts +2 -0
  206. package/out/lib/theme-env.d.ts.map +1 -0
  207. package/out/lib/theme-env.js +101 -0
  208. package/out/lib/theme-env.js.map +1 -0
  209. package/out/lib/theme-install.d.ts +2 -0
  210. package/out/lib/theme-install.d.ts.map +1 -0
  211. package/out/lib/theme-install.js +363 -0
  212. package/out/lib/theme-install.js.map +1 -0
  213. package/out/lib/theme-lock.d.ts +2 -0
  214. package/out/lib/theme-lock.d.ts.map +1 -0
  215. package/out/lib/theme-lock.js +70 -0
  216. package/out/lib/theme-lock.js.map +1 -0
  217. package/out/lib/theme-paths.d.ts +2 -0
  218. package/out/lib/theme-paths.d.ts.map +1 -0
  219. package/out/lib/theme-paths.js +73 -0
  220. package/out/lib/theme-paths.js.map +1 -0
  221. package/out/lib/theme-placeholder-cover.d.ts +13 -0
  222. package/out/lib/theme-placeholder-cover.d.ts.map +1 -0
  223. package/out/lib/theme-placeholder-cover.js +95 -0
  224. package/out/lib/theme-placeholder-cover.js.map +1 -0
  225. package/out/lib/theme-preview-frame.d.ts +2 -0
  226. package/out/lib/theme-preview-frame.d.ts.map +1 -0
  227. package/out/lib/theme-preview-frame.js +107 -0
  228. package/out/lib/theme-preview-frame.js.map +1 -0
  229. package/out/lib/theme-preview-pool.d.ts +2 -0
  230. package/out/lib/theme-preview-pool.d.ts.map +1 -0
  231. package/out/lib/theme-preview-pool.js +484 -0
  232. package/out/lib/theme-preview-pool.js.map +1 -0
  233. package/out/lib/theme-preview-proxy.d.ts +2 -0
  234. package/out/lib/theme-preview-proxy.d.ts.map +1 -0
  235. package/out/lib/theme-preview-proxy.js +101 -0
  236. package/out/lib/theme-preview-proxy.js.map +1 -0
  237. package/out/lib/theme-prod.d.ts +2 -0
  238. package/out/lib/theme-prod.d.ts.map +1 -0
  239. package/out/lib/theme-prod.js +400 -0
  240. package/out/lib/theme-prod.js.map +1 -0
  241. package/out/lib/theme-registry.d.ts +2 -0
  242. package/out/lib/theme-registry.d.ts.map +1 -0
  243. package/out/lib/theme-registry.js +135 -0
  244. package/out/lib/theme-registry.js.map +1 -0
  245. package/out/lib/theme-runtime.d.ts +2 -0
  246. package/out/lib/theme-runtime.d.ts.map +1 -0
  247. package/out/lib/theme-runtime.js +344 -0
  248. package/out/lib/theme-runtime.js.map +1 -0
  249. package/out/lib/theme-sources.d.ts +2 -0
  250. package/out/lib/theme-sources.d.ts.map +1 -0
  251. package/out/lib/theme-sources.js +347 -0
  252. package/out/lib/theme-sources.js.map +1 -0
  253. package/out/lib/theme-warmup.d.ts +2 -0
  254. package/out/lib/theme-warmup.d.ts.map +1 -0
  255. package/out/lib/theme-warmup.js +167 -0
  256. package/out/lib/theme-warmup.js.map +1 -0
  257. package/out/lib/toolkit-build.d.ts +2 -0
  258. package/out/lib/toolkit-build.d.ts.map +1 -0
  259. package/out/lib/toolkit-build.js +57 -0
  260. package/out/lib/toolkit-build.js.map +1 -0
  261. package/out/types/config.d.ts +57 -0
  262. package/out/types/config.d.ts.map +1 -0
  263. package/out/types/config.js +3 -0
  264. package/out/types/config.js.map +1 -0
  265. package/out/ui/banner.d.ts +2 -0
  266. package/out/ui/banner.d.ts.map +1 -0
  267. package/out/ui/banner.js +358 -0
  268. package/out/ui/banner.js.map +1 -0
  269. package/out/ui/interactive.d.ts +2 -0
  270. package/out/ui/interactive.d.ts.map +1 -0
  271. package/out/ui/interactive.js +328 -0
  272. package/out/ui/interactive.js.map +1 -0
  273. package/out/ui/theme.d.ts +2 -0
  274. package/out/ui/theme.d.ts.map +1 -0
  275. package/out/ui/theme.js +250 -0
  276. package/out/ui/theme.js.map +1 -0
  277. package/package.json +13 -7
  278. package/server/dist/common/api-messages.d.ts +9 -0
  279. package/server/dist/common/api-messages.js +9 -0
  280. package/server/dist/common/api-messages.js.map +1 -1
  281. package/server/dist/database/typeorm-options.d.ts +3 -0
  282. package/server/dist/database/typeorm-options.js +60 -0
  283. package/server/dist/database/typeorm-options.js.map +1 -0
  284. package/server/dist/modules/api-key/api-key.controller.js.map +1 -1
  285. package/server/dist/modules/api-key/api-key.entity.js.map +1 -1
  286. package/server/dist/modules/api-key/api-key.guard.js +2 -3
  287. package/server/dist/modules/api-key/api-key.guard.js.map +1 -1
  288. package/server/dist/modules/api-key/api-key.module.js.map +1 -1
  289. package/server/dist/modules/api-key/api-key.service.js +1 -1
  290. package/server/dist/modules/api-key/api-key.service.js.map +1 -1
  291. package/server/dist/modules/article/article-revision.entity.js +3 -3
  292. package/server/dist/modules/article/article-revision.entity.js.map +1 -1
  293. package/server/dist/modules/article/article-slug.util.d.ts +2 -0
  294. package/server/dist/modules/article/article-slug.util.js +19 -0
  295. package/server/dist/modules/article/article-slug.util.js.map +1 -0
  296. package/server/dist/modules/article/scheduled-publish.service.js.map +1 -1
  297. package/server/dist/modules/bootstrap/bootstrap.constants.d.ts +20 -0
  298. package/server/dist/modules/bootstrap/bootstrap.constants.js +171 -0
  299. package/server/dist/modules/bootstrap/bootstrap.constants.js.map +1 -0
  300. package/server/dist/modules/bootstrap/bootstrap.service.d.ts +22 -0
  301. package/server/dist/modules/bootstrap/bootstrap.service.js +183 -0
  302. package/server/dist/modules/bootstrap/bootstrap.service.js.map +1 -0
  303. package/server/dist/modules/bootstrap/install-locale.d.ts +2 -0
  304. package/server/dist/modules/bootstrap/install-locale.js +11 -0
  305. package/server/dist/modules/bootstrap/install-locale.js.map +1 -0
  306. package/server/dist/modules/extension/extension.module.d.ts +9 -0
  307. package/server/dist/modules/extension/extension.module.js +50 -0
  308. package/server/dist/modules/extension/extension.module.js.map +1 -0
  309. package/server/dist/modules/extension/plugin-loader.service.d.ts +12 -0
  310. package/server/dist/modules/extension/plugin-loader.service.js +96 -0
  311. package/server/dist/modules/extension/plugin-loader.service.js.map +1 -0
  312. package/server/dist/modules/extension/plugin-registry.bridge.d.ts +3 -0
  313. package/server/dist/modules/extension/plugin-registry.bridge.js +44 -0
  314. package/server/dist/modules/extension/plugin-registry.bridge.js.map +1 -0
  315. package/server/dist/modules/extension/plugin.controller.d.ts +22 -0
  316. package/server/dist/modules/extension/plugin.controller.js +155 -0
  317. package/server/dist/modules/extension/plugin.controller.js.map +1 -0
  318. package/server/dist/modules/extension/plugin.service.d.ts +52 -0
  319. package/server/dist/modules/extension/plugin.service.js +391 -0
  320. package/server/dist/modules/extension/plugin.service.js.map +1 -0
  321. package/server/dist/modules/extension/preview-draft.store.d.ts +13 -0
  322. package/server/dist/modules/extension/preview-draft.store.js +41 -0
  323. package/server/dist/modules/extension/preview-draft.store.js.map +1 -0
  324. package/server/dist/modules/extension/theme-registry.bridge.d.ts +56 -0
  325. package/server/dist/modules/extension/theme-registry.bridge.js +46 -0
  326. package/server/dist/modules/extension/theme-registry.bridge.js.map +1 -0
  327. package/server/dist/modules/extension/theme.controller.d.ts +66 -0
  328. package/server/dist/modules/extension/theme.controller.js +301 -0
  329. package/server/dist/modules/extension/theme.controller.js.map +1 -0
  330. package/server/dist/modules/extension/theme.service.d.ts +140 -0
  331. package/server/dist/modules/extension/theme.service.js +1039 -0
  332. package/server/dist/modules/extension/theme.service.js.map +1 -0
  333. package/server/dist/modules/file/file-optimization.controller.d.ts +12 -0
  334. package/server/dist/modules/file/file-optimization.controller.js +79 -0
  335. package/server/dist/modules/file/file-optimization.controller.js.map +1 -0
  336. package/server/dist/modules/file/file-optimization.service.d.ts +36 -0
  337. package/server/dist/modules/file/file-optimization.service.js +385 -0
  338. package/server/dist/modules/file/file-optimization.service.js.map +1 -0
  339. package/server/dist/modules/file/file-optimization.types.d.ts +66 -0
  340. package/server/dist/modules/file/file-optimization.types.js +5 -0
  341. package/server/dist/modules/file/file-optimization.types.js.map +1 -0
  342. package/server/dist/modules/file/image-optimizer-plugin.guard.d.ts +7 -0
  343. package/server/dist/modules/file/image-optimizer-plugin.guard.js +33 -0
  344. package/server/dist/modules/file/image-optimizer-plugin.guard.js.map +1 -0
  345. package/server/dist/modules/health/health.controller.js +2 -4
  346. package/server/dist/modules/health/health.controller.js.map +1 -1
  347. package/server/dist/modules/health/health.module.js.map +1 -1
  348. package/server/dist/modules/hook/hook.module.d.ts +2 -0
  349. package/server/dist/modules/hook/hook.module.js +22 -0
  350. package/server/dist/modules/hook/hook.module.js.map +1 -0
  351. package/server/dist/modules/hook/hook.service.d.ts +26 -0
  352. package/server/dist/modules/hook/hook.service.js +105 -0
  353. package/server/dist/modules/hook/hook.service.js.map +1 -0
  354. package/server/dist/modules/webhook/webhook.controller.js.map +1 -1
  355. package/server/dist/modules/webhook/webhook.entity.js.map +1 -1
  356. package/server/dist/modules/webhook/webhook.module.js.map +1 -1
  357. package/server/dist/modules/webhook/webhook.service.d.ts +1 -1
  358. package/server/dist/modules/webhook/webhook.service.js +5 -2
  359. package/server/dist/modules/webhook/webhook.service.js.map +1 -1
  360. package/server/dist/public/uploads/2026-05-30/QR3X4UZQ93ZTUPGXCFA9II..png +0 -0
  361. package/server/dist/public/uploads/2026-05-31/BXQV3NX9ZVWHGNOSX9AXD8.webp +0 -0
  362. package/server/dist/public/uploads/2026-05-31/BXQV3NX9ZVWHGNOSX9AXD8_medium.webp +0 -0
  363. package/server/dist/public/uploads/2026-05-31/BXQV3NX9ZVWHGNOSX9AXD8_thumb.webp +0 -0
  364. package/server/dist/public/uploads/2026-05-31/I2SZC0ONA7CF31UM46MN56..jpg +0 -0
  365. package/server/dist/tsconfig.tsbuildinfo +1 -0
  366. package/server/dist/utils/image-processor.util.d.ts +23 -0
  367. package/server/dist/utils/image-processor.util.js +88 -0
  368. package/server/dist/utils/image-processor.util.js.map +1 -0
  369. package/server/dist/utils/local-api-quiet.util.d.ts +1 -0
  370. package/server/dist/utils/local-api-quiet.util.js +8 -0
  371. package/server/dist/utils/local-api-quiet.util.js.map +1 -0
  372. package/server/dist/utils/project-root.util.d.ts +2 -0
  373. package/server/dist/utils/project-root.util.js +42 -0
  374. package/server/dist/utils/project-root.util.js.map +1 -0
  375. package/server/public/uploads/2026-05-30/QR3X4UZQ93ZTUPGXCFA9II..png +0 -0
  376. package/server/public/uploads/2026-05-31/BXQV3NX9ZVWHGNOSX9AXD8.webp +0 -0
  377. package/server/public/uploads/2026-05-31/BXQV3NX9ZVWHGNOSX9AXD8_medium.webp +0 -0
  378. package/server/public/uploads/2026-05-31/BXQV3NX9ZVWHGNOSX9AXD8_thumb.webp +0 -0
  379. package/server/public/uploads/2026-05-31/I2SZC0ONA7CF31UM46MN56..jpg +0 -0
  380. package/templates/config.local.json +13 -0
  381. package/templates/env.local.default +10 -0
  382. package/templates/theme-catalog.json +27 -0
  383. package/lib/api-dev.js +0 -89
  384. package/lib/bootstrap.js +0 -114
  385. package/lib/build.js +0 -162
  386. package/lib/db-backup.js +0 -67
  387. package/lib/dev-banner.js +0 -72
  388. package/lib/dev.js +0 -141
  389. package/lib/docker.js +0 -275
  390. package/lib/doctor.js +0 -266
  391. package/lib/http.js +0 -182
  392. package/lib/i18n/index.js +0 -32
  393. package/lib/i18n/strings.js +0 -846
  394. package/lib/lifecycle.js +0 -190
  395. package/lib/nginx.js +0 -342
  396. package/lib/paths.js +0 -108
  397. package/lib/pm2.js +0 -32
  398. package/lib/process.js +0 -45
  399. package/lib/project-type.js +0 -72
  400. package/lib/publish.js +0 -968
  401. package/lib/root.js +0 -88
  402. package/lib/spawn.js +0 -92
  403. package/lib/status.js +0 -132
  404. package/ui/banner.js +0 -441
  405. package/ui/interactive.js +0 -380
  406. package/ui/theme.js +0 -265
@@ -0,0 +1,1039 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ var ThemeService_1;
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.ThemeService = void 0;
17
+ const theme_1 = require("../../../../toolkit/dist/theme");
18
+ const theme_2 = require("../../../../toolkit/dist/theme");
19
+ const node_1 = require("../../../../toolkit/dist/theme/node");
20
+ const common_1 = require("@nestjs/common");
21
+ const typeorm_1 = require("@nestjs/typeorm");
22
+ const child_process_1 = require("child_process");
23
+ const fs = require("fs");
24
+ const path = require("path");
25
+ const typeorm_2 = require("typeorm");
26
+ const project_root_util_1 = require("../../utils/project-root.util");
27
+ const setting_service_1 = require("../setting/setting.service");
28
+ const setting_entity_1 = require("../setting/setting.entity");
29
+ const theme_placeholder_cover_js_1 = require("../../../../cli/out/lib/theme-placeholder-cover.js");
30
+ const theme_registry_bridge_1 = require("./theme-registry.bridge");
31
+ const preview_draft_store_1 = require("./preview-draft.store");
32
+ function projectRoot() {
33
+ return (0, project_root_util_1.resolveProjectRoot)();
34
+ }
35
+ function monorepoRoot() {
36
+ return (0, project_root_util_1.resolveMonorepoRoot)();
37
+ }
38
+ function resolveThemeInstallScript() {
39
+ const candidates = [
40
+ path.join(monorepoRoot(), 'cli', 'lib', 'theme-install.js'),
41
+ path.join(projectRoot(), 'cli', 'lib', 'theme-install.js'),
42
+ ];
43
+ for (const candidate of candidates) {
44
+ if (fs.existsSync(candidate))
45
+ return candidate;
46
+ }
47
+ return candidates[0];
48
+ }
49
+ function isResolvableThemeDirEntry(entry, parentDir) {
50
+ if (!entry.isDirectory() && !entry.isSymbolicLink())
51
+ return false;
52
+ try {
53
+ return fs.statSync(path.join(parentDir, entry.name)).isDirectory();
54
+ }
55
+ catch (_a) {
56
+ return false;
57
+ }
58
+ }
59
+ const THEME_ID_RE = /^[a-z0-9][a-z0-9-]*$/i;
60
+ const PREVIEW_POOL_PORTS = [3003];
61
+ const PREVIEW_POOL_MANIFEST = path.join('.reactpress', 'preview-pool.json');
62
+ const THEME_RUNTIME_REL = path.join('.reactpress', 'runtime');
63
+ const LEGACY_THEMES_RUNTIME_REL = path.join('themes', 'runtime');
64
+ const THEMES_RESERVED_SUBDIRS = new Set(['starter', 'bundled', 'core', 'theme-starter']);
65
+ const THEMES_LEGACY_STARTER_SUBDIRS = ['starter', 'bundled', 'core'];
66
+ let ThemeService = ThemeService_1 = class ThemeService {
67
+ constructor(settingRepository, settingService) {
68
+ this.settingRepository = settingRepository;
69
+ this.settingService = settingService;
70
+ }
71
+ themesRoot() {
72
+ return path.join(projectRoot(), 'themes');
73
+ }
74
+ templatesDir() {
75
+ return this.themesRoot();
76
+ }
77
+ runtimeDir() {
78
+ return path.join(projectRoot(), THEME_RUNTIME_REL);
79
+ }
80
+ ensureSiteRuntimeLink(id, sourceDir) {
81
+ const targetDir = path.join(this.runtimeDir(), id);
82
+ fs.mkdirSync(this.runtimeDir(), { recursive: true });
83
+ if (fs.existsSync(targetDir)) {
84
+ return targetDir;
85
+ }
86
+ try {
87
+ fs.symlinkSync(sourceDir, targetDir, 'dir');
88
+ }
89
+ catch (_a) {
90
+ return sourceDir;
91
+ }
92
+ this.ensureRuntimeThemeTsconfigBase();
93
+ return targetDir;
94
+ }
95
+ legacyStarterDirs() {
96
+ return THEMES_LEGACY_STARTER_SUBDIRS.map((name) => path.join(this.themesRoot(), name));
97
+ }
98
+ legacyBundledDir() {
99
+ return path.join(projectRoot(), 'templates');
100
+ }
101
+ applyTemplateAppearanceSchema(manifest) {
102
+ var _a, _b;
103
+ const templatePath = path.join(this.templatesDir(), manifest.id);
104
+ const template = this.readManifest(templatePath);
105
+ if (!template)
106
+ return manifest;
107
+ let next = manifest;
108
+ if ((_b = (_a = template.appearance) === null || _a === void 0 ? void 0 : _a.sections) === null || _b === void 0 ? void 0 : _b.length) {
109
+ next = Object.assign(Object.assign({}, next), { appearance: template.appearance });
110
+ }
111
+ if (template.options) {
112
+ next = Object.assign(Object.assign({}, next), { options: template.options });
113
+ }
114
+ return next;
115
+ }
116
+ readManifest(themeDir) {
117
+ const manifestPath = path.join(themeDir, 'theme.json');
118
+ if (!fs.existsSync(manifestPath))
119
+ return null;
120
+ try {
121
+ const raw = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
122
+ const parsed = (0, theme_2.parseThemeManifest)(raw);
123
+ if (parsed)
124
+ return parsed;
125
+ if (raw && typeof raw.id === 'string') {
126
+ return (0, theme_2.parseThemeManifest)(Object.assign(Object.assign({}, raw), { id: raw.id }));
127
+ }
128
+ const id = path.basename(themeDir);
129
+ return (0, theme_2.parseThemeManifest)(Object.assign({ id, name: id, version: '1.0.0' }, raw));
130
+ }
131
+ catch (_a) {
132
+ return null;
133
+ }
134
+ }
135
+ readNpmThemeLock() {
136
+ var _a;
137
+ const lockPath = path.join(projectRoot(), '.reactpress', 'themes.lock.json');
138
+ if (!fs.existsSync(lockPath))
139
+ return {};
140
+ try {
141
+ const raw = JSON.parse(fs.readFileSync(lockPath, 'utf8'));
142
+ const themes = (_a = raw.themes) !== null && _a !== void 0 ? _a : {};
143
+ const npmOnly = {};
144
+ for (const [id, entry] of Object.entries(themes)) {
145
+ if ((entry === null || entry === void 0 ? void 0 : entry.source) === 'npm' && entry.spec) {
146
+ npmOnly[id] = {
147
+ spec: entry.spec,
148
+ resolvedVersion: entry.resolvedVersion,
149
+ packageName: entry.packageName,
150
+ installedAt: entry.installedAt,
151
+ };
152
+ }
153
+ }
154
+ return npmOnly;
155
+ }
156
+ catch (_b) {
157
+ return {};
158
+ }
159
+ }
160
+ readThemeCatalogFile() {
161
+ return (0, theme_registry_bridge_1.readThemeCatalogEntries)(projectRoot());
162
+ }
163
+ getThemeCatalog() {
164
+ return this.readThemeCatalogFile();
165
+ }
166
+ findCatalogEntry(id) {
167
+ return (0, theme_registry_bridge_1.findThemeCatalogEntry)(id, projectRoot());
168
+ }
169
+ getThemeManifestFromSources(themeId) {
170
+ const dir = this.resolveThemeDir(themeId);
171
+ if (dir) {
172
+ return this.readManifest(dir);
173
+ }
174
+ const catalog = this.findCatalogEntry(themeId);
175
+ if (!catalog)
176
+ return null;
177
+ const manifest = (0, theme_registry_bridge_1.loadThemeRegistry)().catalogEntryToManifest(catalog);
178
+ return manifest ? manifest : null;
179
+ }
180
+ async ensureThemeMaterialized(id) {
181
+ const existing = this.resolveThemeDir(id);
182
+ if (existing)
183
+ return existing;
184
+ const templatePath = path.join(this.templatesDir(), id);
185
+ if (fs.existsSync(templatePath) && !THEMES_RESERVED_SUBDIRS.has(id)) {
186
+ await this.installTheme(id);
187
+ const installed = this.resolveThemeDir(id);
188
+ if (installed)
189
+ return installed;
190
+ }
191
+ const catalog = this.findCatalogEntry(id);
192
+ if (catalog === null || catalog === void 0 ? void 0 : catalog.npm) {
193
+ await this.installThemeFromNpm(catalog.npm);
194
+ const installed = this.resolveThemeDir(id);
195
+ if (installed)
196
+ return installed;
197
+ }
198
+ throw new common_1.NotFoundException(`Theme "${id}" not found`);
199
+ }
200
+ listDirThemes(dir, source, options) {
201
+ if (!fs.existsSync(dir))
202
+ return [];
203
+ const skip = options === null || options === void 0 ? void 0 : options.skipDirNames;
204
+ return fs
205
+ .readdirSync(dir, { withFileTypes: true })
206
+ .filter((d) => isResolvableThemeDirEntry(d, dir) && !(skip && skip.has(d.name)))
207
+ .map((d) => this.readManifest(path.join(dir, d.name)))
208
+ .filter((m) => m !== null);
209
+ }
210
+ async getSettingRow() {
211
+ return this.settingService.getSettingRow();
212
+ }
213
+ parseGlobalSetting(row) {
214
+ if (!row.globalSetting)
215
+ return {};
216
+ try {
217
+ return JSON.parse(row.globalSetting);
218
+ }
219
+ catch (_a) {
220
+ return {};
221
+ }
222
+ }
223
+ async getThemeState() {
224
+ const row = await this.getSettingRow();
225
+ return (0, theme_2.getThemeStateFromGlobalSetting)(this.parseGlobalSetting(row));
226
+ }
227
+ async saveThemeState(patch) {
228
+ const row = await this.getSettingRow();
229
+ const merged = (0, theme_2.mergeThemeStateIntoGlobalSetting)(this.parseGlobalSetting(row), patch);
230
+ row.globalSetting = JSON.stringify(merged);
231
+ await this.settingRepository.save(row);
232
+ return merged.theme;
233
+ }
234
+ listLocalThemes() {
235
+ return this.listBundledThemes();
236
+ }
237
+ listBundledThemes() {
238
+ const { bundled: local } = (0, theme_registry_bridge_1.readThemesPackageMeta)(projectRoot());
239
+ const manifests = [];
240
+ for (const id of local) {
241
+ const manifest = this.readManifest(path.join(this.templatesDir(), id));
242
+ if (manifest)
243
+ manifests.push(manifest);
244
+ }
245
+ return manifests;
246
+ }
247
+ isRegistryLocalTheme(id) {
248
+ const { bundled: local } = (0, theme_registry_bridge_1.readThemesPackageMeta)(projectRoot());
249
+ return local.includes(id);
250
+ }
251
+ hasOfficialTag(tags) {
252
+ return (tags !== null && tags !== void 0 ? tags : []).some((tag) => /^(official|官方)$/i.test(String(tag).trim()));
253
+ }
254
+ resolveThemeOfficial(manifest, catalog) {
255
+ if (this.isRegistryLocalTheme(manifest.id))
256
+ return true;
257
+ if ((catalog === null || catalog === void 0 ? void 0 : catalog.featured) === true)
258
+ return true;
259
+ if (this.hasOfficialTag(manifest.tags))
260
+ return true;
261
+ const catalogEntry = this.findCatalogEntry(manifest.id);
262
+ if ((catalogEntry === null || catalogEntry === void 0 ? void 0 : catalogEntry.featured) === true)
263
+ return true;
264
+ return this.hasOfficialTag(catalogEntry === null || catalogEntry === void 0 ? void 0 : catalogEntry.tags);
265
+ }
266
+ catalogMetaFromEntry(entry) {
267
+ return {
268
+ dependency: entry.dependency,
269
+ npm: entry.npm,
270
+ featured: entry.featured,
271
+ themeUri: entry.themeUri,
272
+ previewUrl: entry.previewUrl,
273
+ };
274
+ }
275
+ async listThemes() {
276
+ const state = await this.getThemeState();
277
+ const installedSet = new Set(state.installedThemes);
278
+ const npmLock = this.readNpmThemeLock();
279
+ const byId = new Map();
280
+ const add = (manifest, source, npm, catalog) => {
281
+ const installed = installedSet.has(manifest.id) || source === 'installed';
282
+ const merged = this.applyTemplateAppearanceSchema(manifest);
283
+ byId.set(merged.id, Object.assign(Object.assign({}, merged), { source,
284
+ installed, active: state.activeTheme === merged.id, official: this.resolveThemeOfficial(merged, catalog), coverUrl: `/api/extension/themes/${merged.id}/cover`, npm,
285
+ catalog }));
286
+ };
287
+ for (const m of this.listLocalThemes()) {
288
+ add(m, 'local');
289
+ }
290
+ for (const m of this.listDirThemes(this.runtimeDir(), 'installed')) {
291
+ const npm = npmLock[m.id];
292
+ const catalogEntry = this.findCatalogEntry(m.id);
293
+ add(m, 'installed', npm, catalogEntry
294
+ ? this.catalogMetaFromEntry(catalogEntry)
295
+ : npm
296
+ ? { npm: npm.spec }
297
+ : undefined);
298
+ }
299
+ for (const entry of this.readThemeCatalogFile()) {
300
+ if (byId.has(entry.id))
301
+ continue;
302
+ add({
303
+ id: entry.id,
304
+ name: entry.name,
305
+ version: entry.version,
306
+ description: entry.description,
307
+ author: entry.author,
308
+ themeUri: entry.themeUri,
309
+ tags: entry.tags,
310
+ requires: entry.requires,
311
+ }, 'npm', undefined, { dependency: entry.dependency, npm: entry.npm, featured: entry.featured, themeUri: entry.themeUri, previewUrl: entry.previewUrl });
312
+ }
313
+ return Array.from(byId.values()).sort((a, b) => a.name.localeCompare(b.name));
314
+ }
315
+ async getTheme(id) {
316
+ const items = await this.listThemes();
317
+ const found = items.find((t) => t.id === id);
318
+ if (!found)
319
+ throw new common_1.NotFoundException(`Theme "${id}" not found`);
320
+ return found;
321
+ }
322
+ async getThemeAdminLocale(themeId, locale) {
323
+ if (!this.isValidThemeId(themeId)) {
324
+ throw new common_1.BadRequestException(`Invalid theme id "${themeId}"`);
325
+ }
326
+ const dirs = this.themeLocaleSearchDirs(themeId);
327
+ if (dirs.length === 0) {
328
+ throw new common_1.NotFoundException(`Theme "${themeId}" not found`);
329
+ }
330
+ const safeLocale = /^[a-z]{2}(?:-[a-z]{2})?$/i.test(locale) ? locale : 'en';
331
+ for (const dir of dirs) {
332
+ const messages = (0, node_1.readThemeAdminLocaleFile)(dir, safeLocale);
333
+ if (messages) {
334
+ return { themeId, locale: safeLocale, messages };
335
+ }
336
+ }
337
+ return { themeId, locale: safeLocale, messages: {} };
338
+ }
339
+ themeLocaleSearchDirs(themeId) {
340
+ const seen = new Set();
341
+ const ordered = [];
342
+ const push = (dir) => {
343
+ if (!dir || seen.has(dir))
344
+ return;
345
+ seen.add(dir);
346
+ ordered.push(dir);
347
+ };
348
+ const template = path.join(this.templatesDir(), themeId);
349
+ if (fs.existsSync(template) &&
350
+ !THEMES_RESERVED_SUBDIRS.has(themeId) &&
351
+ this.isUnderDir(template, this.templatesDir())) {
352
+ push(template);
353
+ }
354
+ push(this.resolveThemeDir(themeId));
355
+ return ordered;
356
+ }
357
+ getThemeManifestForConfig(themeId) {
358
+ const dir = this.resolveThemeDir(themeId);
359
+ if (!dir)
360
+ return null;
361
+ return this.applyTemplateAppearanceSchema(this.readManifest(dir));
362
+ }
363
+ async getThemeConfigurationSchema(themeId) {
364
+ if (!this.isValidThemeId(themeId)) {
365
+ throw new common_1.BadRequestException(`Invalid theme id "${themeId}"`);
366
+ }
367
+ const manifest = this.getThemeManifestForConfig(themeId);
368
+ if (!manifest)
369
+ throw new common_1.NotFoundException(`Theme "${themeId}" not found`);
370
+ const schema = (0, theme_2.getConfigurationSchemaFromManifest)(manifest, themeId);
371
+ return { themeId, schema };
372
+ }
373
+ async getThemeConfiguration(themeId) {
374
+ if (!this.isValidThemeId(themeId)) {
375
+ throw new common_1.BadRequestException(`Invalid theme id "${themeId}"`);
376
+ }
377
+ const manifest = this.getThemeManifestForConfig(themeId);
378
+ if (!manifest)
379
+ throw new common_1.NotFoundException(`Theme "${themeId}" not found`);
380
+ const row = await this.getSettingRow();
381
+ const configuration = (0, theme_2.getMergedThemeConfiguration)(this.parseGlobalSetting(row), themeId, {
382
+ manifest,
383
+ });
384
+ return { themeId, configuration };
385
+ }
386
+ async updateThemeConfiguration(themeId, patch, options) {
387
+ var _a, _b, _c;
388
+ if (!this.isValidThemeId(themeId)) {
389
+ throw new common_1.BadRequestException(`Invalid theme id "${themeId}"`);
390
+ }
391
+ const manifest = this.getThemeManifestForConfig(themeId);
392
+ if (!manifest)
393
+ throw new common_1.NotFoundException(`Theme "${themeId}" not found`);
394
+ const schema = (0, theme_2.getConfigurationSchemaFromManifest)(manifest, themeId);
395
+ if (!schema) {
396
+ throw new common_1.BadRequestException(`Theme "${themeId}" does not declare options schema`);
397
+ }
398
+ const row = await this.getSettingRow();
399
+ const globalRaw = this.parseGlobalSetting(row);
400
+ const locale = (_a = options === null || options === void 0 ? void 0 : options.locale) !== null && _a !== void 0 ? _a : 'zh';
401
+ if (options === null || options === void 0 ? void 0 : options.replace) {
402
+ const seed = (_b = (0, theme_2.getThemeConfigurationSeed)(themeId, locale)) !== null && _b !== void 0 ? _b : (0, theme_2.getMergedThemeConfiguration)(globalRaw, themeId, { locale, manifest });
403
+ const validation = (0, theme_2.validateThemeConfiguration)(schema, seed);
404
+ if (!validation.valid) {
405
+ throw new common_1.BadRequestException((_c = validation.message) !== null && _c !== void 0 ? _c : 'Invalid configuration');
406
+ }
407
+ const mergedGlobal = (0, theme_2.mergeConfigIntoGlobalSetting)(globalRaw, themeId, seed);
408
+ row.globalSetting = JSON.stringify(mergedGlobal);
409
+ await this.settingRepository.save(row);
410
+ return { themeId, configuration: seed };
411
+ }
412
+ const result = (0, theme_2.validateAndMergeThemeConfiguration)(themeId, globalRaw, patch, manifest);
413
+ if (!result.ok) {
414
+ throw new common_1.BadRequestException('message' in result ? result.message : 'Invalid configuration');
415
+ }
416
+ const mergedGlobal = (0, theme_2.mergeConfigIntoGlobalSetting)(globalRaw, themeId, result.config);
417
+ row.globalSetting = JSON.stringify(mergedGlobal);
418
+ await this.settingRepository.save(row);
419
+ return { themeId, configuration: result.config };
420
+ }
421
+ isValidThemeId(id) {
422
+ return typeof id === 'string' && THEME_ID_RE.test(id) && id.length <= 64;
423
+ }
424
+ isUnderDir(target, base) {
425
+ const rel = path.relative(path.resolve(base), path.resolve(target));
426
+ return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));
427
+ }
428
+ isSafeThemeDirRel(themeDirRel) {
429
+ if (themeDirRel == null)
430
+ return true;
431
+ if (themeDirRel.includes('..') || path.isAbsolute(themeDirRel))
432
+ return false;
433
+ if (themeDirRel.startsWith(`${THEME_RUNTIME_REL}/`)) {
434
+ return true;
435
+ }
436
+ if (themeDirRel.startsWith(`${LEGACY_THEMES_RUNTIME_REL}/`)) {
437
+ return true;
438
+ }
439
+ if (themeDirRel.startsWith('themes/') && !themeDirRel.startsWith(`${LEGACY_THEMES_RUNTIME_REL}/`)) {
440
+ const rest = themeDirRel.slice('themes/'.length);
441
+ const top = rest.split('/')[0];
442
+ if (top && !THEMES_RESERVED_SUBDIRS.has(top)) {
443
+ return true;
444
+ }
445
+ }
446
+ const legacyPrefixes = THEMES_LEGACY_STARTER_SUBDIRS.map((name) => `themes/${name}/`);
447
+ if (legacyPrefixes.some((prefix) => themeDirRel.startsWith(prefix))) {
448
+ return true;
449
+ }
450
+ return themeDirRel.startsWith('templates/');
451
+ }
452
+ resolveThemeDir(id) {
453
+ if (!this.isValidThemeId(id))
454
+ return null;
455
+ const runtime = path.join(this.runtimeDir(), id);
456
+ if (fs.existsSync(runtime) && this.isUnderDir(runtime, this.runtimeDir())) {
457
+ return runtime;
458
+ }
459
+ const legacyRuntimeRoot = path.join(projectRoot(), LEGACY_THEMES_RUNTIME_REL);
460
+ const legacyRuntime = path.join(legacyRuntimeRoot, id);
461
+ if (fs.existsSync(legacyRuntime) && this.isUnderDir(legacyRuntime, legacyRuntimeRoot)) {
462
+ return legacyRuntime;
463
+ }
464
+ const template = path.join(this.templatesDir(), id);
465
+ if (fs.existsSync(template) &&
466
+ !THEMES_RESERVED_SUBDIRS.has(id) &&
467
+ this.isUnderDir(template, this.templatesDir())) {
468
+ return template;
469
+ }
470
+ for (const legacyStarter of this.legacyStarterDirs()) {
471
+ const legacy = path.join(legacyStarter, id);
472
+ if (fs.existsSync(legacy) && this.isUnderDir(legacy, legacyStarter)) {
473
+ return legacy;
474
+ }
475
+ }
476
+ const legacyBundled = path.join(this.legacyBundledDir(), id);
477
+ if (fs.existsSync(legacyBundled) && this.isUnderDir(legacyBundled, this.legacyBundledDir())) {
478
+ return legacyBundled;
479
+ }
480
+ const site = projectRoot();
481
+ const mono = monorepoRoot();
482
+ if (mono !== site) {
483
+ const monoRuntime = path.join(mono, THEME_RUNTIME_REL, id);
484
+ if (fs.existsSync(monoRuntime) && fs.statSync(monoRuntime).isDirectory()) {
485
+ return this.ensureSiteRuntimeLink(id, monoRuntime);
486
+ }
487
+ const monoTheme = path.join(mono, 'themes', id);
488
+ if (fs.existsSync(monoTheme) &&
489
+ fs.statSync(monoTheme).isDirectory() &&
490
+ !THEMES_RESERVED_SUBDIRS.has(id)) {
491
+ return monoTheme;
492
+ }
493
+ }
494
+ return null;
495
+ }
496
+ async installTheme(id) {
497
+ if (!this.isValidThemeId(id)) {
498
+ throw new common_1.BadRequestException(`Invalid theme id "${id}"`);
499
+ }
500
+ const templatePath = path.join(this.templatesDir(), id);
501
+ if (!fs.existsSync(templatePath) || THEMES_RESERVED_SUBDIRS.has(id)) {
502
+ const catalog = this.findCatalogEntry(id);
503
+ if (catalog === null || catalog === void 0 ? void 0 : catalog.npm) {
504
+ return this.installThemeFromNpm(catalog.npm);
505
+ }
506
+ throw new common_1.NotFoundException(`Theme template "${id}" not found`);
507
+ }
508
+ const targetDir = path.join(this.runtimeDir(), id);
509
+ fs.mkdirSync(this.runtimeDir(), { recursive: true });
510
+ if (fs.existsSync(targetDir)) {
511
+ this.removeDir(targetDir);
512
+ }
513
+ this.materializeRuntimeTheme(templatePath, targetDir);
514
+ this.ensureRuntimeThemeTsconfigBase();
515
+ const state = await this.getThemeState();
516
+ const installedThemes = state.installedThemes.includes(id)
517
+ ? state.installedThemes
518
+ : [...state.installedThemes, id];
519
+ return this.saveThemeState({ installedThemes });
520
+ }
521
+ async installThemeFromNpm(spec, options) {
522
+ var _a;
523
+ const trimmed = typeof spec === 'string' ? spec.trim() : '';
524
+ if (!trimmed) {
525
+ throw new common_1.BadRequestException('npm spec is required');
526
+ }
527
+ const resolvedSpec = (_a = (0, theme_registry_bridge_1.resolveThemeCatalogInstallSpec)(trimmed, projectRoot())) !== null && _a !== void 0 ? _a : trimmed;
528
+ const installScript = resolveThemeInstallScript();
529
+ if (!fs.existsSync(installScript)) {
530
+ throw new common_1.BadRequestException('Theme npm installer is not available in this deployment');
531
+ }
532
+ let result;
533
+ try {
534
+ const { installThemeFromNpm } = require(installScript);
535
+ result = await installThemeFromNpm(projectRoot(), resolvedSpec, {
536
+ skipDependencies: (options === null || options === void 0 ? void 0 : options.skipDependencies) === true,
537
+ });
538
+ }
539
+ catch (err) {
540
+ const message = err instanceof Error ? err.message : String(err);
541
+ throw new common_1.BadRequestException(message || 'Failed to install theme from npm');
542
+ }
543
+ const state = await this.getThemeState();
544
+ const installedThemes = state.installedThemes.includes(result.themeId)
545
+ ? state.installedThemes
546
+ : [...state.installedThemes, result.themeId];
547
+ const saved = await this.saveThemeState({ installedThemes });
548
+ return Object.assign(Object.assign({}, saved), { themeId: result.themeId, npmSpec: result.npmSpec });
549
+ }
550
+ writeThemeDevManifest(fileName, themeId) {
551
+ if (!this.isValidThemeId(themeId))
552
+ return;
553
+ const themeDir = this.resolveThemeDir(themeId);
554
+ if (!themeDir)
555
+ return;
556
+ const manifestDir = path.join(projectRoot(), '.reactpress');
557
+ const manifestPath = path.join(manifestDir, fileName);
558
+ const themeDirRel = path.relative(projectRoot(), themeDir);
559
+ if (!this.isSafeThemeDirRel(themeDirRel))
560
+ return;
561
+ if (fs.existsSync(manifestPath)) {
562
+ try {
563
+ const existing = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
564
+ if (existing.activeTheme === themeId && existing.themeDir === themeDirRel) {
565
+ return;
566
+ }
567
+ }
568
+ catch (_a) {
569
+ }
570
+ }
571
+ fs.mkdirSync(manifestDir, { recursive: true });
572
+ const payload = {
573
+ activeTheme: themeId,
574
+ themeDir: themeDirRel,
575
+ updatedAt: new Date().toISOString(),
576
+ };
577
+ fs.writeFileSync(manifestPath, JSON.stringify(payload, null, 2), 'utf8');
578
+ }
579
+ syncActiveThemeManifest(themeId) {
580
+ this.writeThemeDevManifest('active-theme.json', themeId);
581
+ }
582
+ ensureRuntimeThemeTsconfigBase() {
583
+ const baseSrc = path.join(projectRoot(), 'tsconfig.base.json');
584
+ if (!fs.existsSync(baseSrc))
585
+ return;
586
+ const runtimeBase = path.join(this.runtimeDir(), 'tsconfig.base.json');
587
+ fs.mkdirSync(this.runtimeDir(), { recursive: true });
588
+ fs.copyFileSync(baseSrc, runtimeBase);
589
+ }
590
+ scheduleProductionClientRestart() {
591
+ if (process.env.NODE_ENV !== 'production')
592
+ return;
593
+ if (process.env.REACTPRESS_SKIP_CLIENT_RESTART === '1')
594
+ return;
595
+ const root = projectRoot();
596
+ const cliBin = path.join(root, 'cli', 'bin', 'reactpress.js');
597
+ if (!fs.existsSync(cliBin))
598
+ return;
599
+ const child = (0, child_process_1.spawn)(process.execPath, [cliBin, 'client', 'restart', '--pm2'], {
600
+ cwd: root,
601
+ detached: true,
602
+ stdio: 'ignore',
603
+ env: Object.assign(Object.assign({}, process.env), { REACTPRESS_ORIGINAL_CWD: root }),
604
+ });
605
+ child.unref();
606
+ }
607
+ syncPreviewThemeManifest(themeId) {
608
+ this.writeThemeDevManifest('preview-theme.json', themeId);
609
+ }
610
+ clearPreviewThemeManifest() {
611
+ const manifestPath = path.join(projectRoot(), '.reactpress', 'preview-theme.json');
612
+ if (fs.existsSync(manifestPath)) {
613
+ fs.unlinkSync(manifestPath);
614
+ }
615
+ }
616
+ readLocalDevActiveThemeId() {
617
+ const manifestPath = path.join(projectRoot(), '.reactpress', 'active-theme.json');
618
+ if (!fs.existsSync(manifestPath))
619
+ return null;
620
+ try {
621
+ const raw = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
622
+ const id = typeof raw.activeTheme === 'string' ? raw.activeTheme.trim() : '';
623
+ return this.isValidThemeId(id) ? id : null;
624
+ }
625
+ catch (_a) {
626
+ return null;
627
+ }
628
+ }
629
+ readPreviewPoolManifest() {
630
+ const poolPath = path.join(projectRoot(), PREVIEW_POOL_MANIFEST);
631
+ if (!fs.existsSync(poolPath))
632
+ return {};
633
+ try {
634
+ const raw = JSON.parse(fs.readFileSync(poolPath, 'utf8'));
635
+ return raw && typeof raw === 'object' ? raw : {};
636
+ }
637
+ catch (_a) {
638
+ return {};
639
+ }
640
+ }
641
+ writePreviewPoolEntry(themeId, port, siteUrl) {
642
+ const poolPath = path.join(projectRoot(), PREVIEW_POOL_MANIFEST);
643
+ const pool = this.readPreviewPoolManifest();
644
+ let previewUrl;
645
+ try {
646
+ const url = new URL(siteUrl);
647
+ url.port = port;
648
+ previewUrl = `${url.origin}/`;
649
+ }
650
+ catch (_a) {
651
+ previewUrl = `http://127.0.0.1:${port}/`;
652
+ }
653
+ pool[themeId] = { port, url: previewUrl, updatedAt: new Date().toISOString() };
654
+ fs.mkdirSync(path.dirname(poolPath), { recursive: true });
655
+ fs.writeFileSync(poolPath, `${JSON.stringify(pool, null, 2)}\n`, 'utf8');
656
+ }
657
+ reservePreviewPortForTheme(themeId, siteUrl) {
658
+ const proxyPort = process.env.REACTPRESS_PREVIEW_PORT || '3003';
659
+ this.writePreviewPoolEntry(themeId, proxyPort, siteUrl);
660
+ return proxyPort;
661
+ }
662
+ resolvePreviewSiteUrl(siteUrl, themeId) {
663
+ if (themeId) {
664
+ const entry = this.readPreviewPoolManifest()[themeId];
665
+ if (typeof (entry === null || entry === void 0 ? void 0 : entry.url) === 'string' && entry.url.startsWith('http')) {
666
+ return entry.url.endsWith('/') ? entry.url : `${entry.url}/`;
667
+ }
668
+ if (entry === null || entry === void 0 ? void 0 : entry.port) {
669
+ try {
670
+ const url = new URL(siteUrl);
671
+ url.port = String(entry.port);
672
+ return `${url.origin}/`;
673
+ }
674
+ catch (_a) {
675
+ return `http://127.0.0.1:${entry.port}/`;
676
+ }
677
+ }
678
+ }
679
+ const previewPort = process.env.REACTPRESS_PREVIEW_PORT || '3003';
680
+ try {
681
+ const url = new URL(siteUrl);
682
+ url.port = previewPort;
683
+ return `${url.origin}/`;
684
+ }
685
+ catch (_b) {
686
+ return `http://127.0.0.1:${previewPort}/`;
687
+ }
688
+ }
689
+ async activateTheme(id) {
690
+ if (!this.isValidThemeId(id)) {
691
+ throw new common_1.BadRequestException(`Invalid theme id "${id}"`);
692
+ }
693
+ await this.ensureThemeMaterialized(id);
694
+ const themeDir = this.resolveThemeDir(id);
695
+ if (!themeDir)
696
+ throw new common_1.NotFoundException(`Theme "${id}" not found`);
697
+ const state = await this.getThemeState();
698
+ const installedThemes = state.installedThemes.includes(id)
699
+ ? state.installedThemes
700
+ : [...state.installedThemes, id];
701
+ const saved = await this.saveThemeState({
702
+ activeTheme: id,
703
+ installedThemes,
704
+ previewThemeId: id,
705
+ });
706
+ this.clearPreviewThemeManifest();
707
+ this.syncActiveThemeManifest(id);
708
+ this.scheduleProductionClientRestart();
709
+ const row = await this.getSettingRow();
710
+ const siteUrl = this.resolveSiteUrlFromRow(row);
711
+ return Object.assign(Object.assign({}, saved), { siteUrl });
712
+ }
713
+ async getActiveThemePublic() {
714
+ const state = await this.getThemeState();
715
+ const themeDir = this.resolveThemeDir(state.activeTheme);
716
+ const row = await this.getSettingRow();
717
+ return {
718
+ activeTheme: state.activeTheme,
719
+ themeDir: themeDir ? path.relative(projectRoot(), themeDir) : null,
720
+ siteUrl: this.resolveSiteUrlFromRow(row),
721
+ };
722
+ }
723
+ async updateThemeMods(themeId, mods) {
724
+ var _a;
725
+ const state = await this.getThemeState();
726
+ const themeMods = Object.assign({}, ((_a = state.mods[themeId]) !== null && _a !== void 0 ? _a : {}));
727
+ for (const [key, value] of Object.entries(mods)) {
728
+ if (value === "") {
729
+ delete themeMods[key];
730
+ }
731
+ else {
732
+ themeMods[key] = value;
733
+ }
734
+ }
735
+ const nextMods = Object.assign(Object.assign({}, state.mods), { [themeId]: themeMods });
736
+ return this.saveThemeState({ mods: nextMods, previewThemeId: themeId });
737
+ }
738
+ async beginPreviewSession(themeId) {
739
+ var _a;
740
+ if (!this.isValidThemeId(themeId)) {
741
+ throw new common_1.BadRequestException(`Invalid theme id "${themeId}"`);
742
+ }
743
+ await this.ensureThemeMaterialized(themeId);
744
+ const themeDir = this.resolveThemeDir(themeId);
745
+ if (!themeDir)
746
+ throw new common_1.NotFoundException(`Theme "${themeId}" not found`);
747
+ const state = await this.getThemeState();
748
+ const saved = await this.saveThemeState({ previewThemeId: themeId });
749
+ const row = await this.getSettingRow();
750
+ const siteUrl = this.resolveSiteUrlFromRow(row);
751
+ const runtimeActiveTheme = (_a = this.readLocalDevActiveThemeId()) !== null && _a !== void 0 ? _a : state.activeTheme;
752
+ if (themeId !== runtimeActiveTheme) {
753
+ this.reservePreviewPortForTheme(themeId, siteUrl);
754
+ this.syncPreviewThemeManifest(themeId);
755
+ }
756
+ else {
757
+ this.clearPreviewThemeManifest();
758
+ }
759
+ return Object.assign(Object.assign({}, saved), { activeTheme: runtimeActiveTheme, siteUrl, previewSiteUrl: themeId !== runtimeActiveTheme ? this.resolvePreviewSiteUrl(siteUrl, themeId) : undefined });
760
+ }
761
+ async endPreviewSession() {
762
+ const state = await this.getThemeState();
763
+ this.clearPreviewThemeManifest();
764
+ const saved = await this.saveThemeState({ previewThemeId: state.activeTheme });
765
+ const row = await this.getSettingRow();
766
+ return Object.assign(Object.assign({}, saved), { siteUrl: this.resolveSiteUrlFromRow(row) });
767
+ }
768
+ getCoverPath(id) {
769
+ const dir = this.resolveThemeDir(id);
770
+ if (!dir)
771
+ return null;
772
+ const candidates = ['cover.png', 'cover.jpg', 'cover.webp', 'cover.jpeg'];
773
+ for (const file of candidates) {
774
+ const full = path.join(dir, file);
775
+ if (fs.existsSync(full))
776
+ return full;
777
+ }
778
+ const manifest = this.readManifest(dir);
779
+ if (manifest === null || manifest === void 0 ? void 0 : manifest.cover) {
780
+ const fromManifest = path.join(dir, manifest.cover);
781
+ if (fs.existsSync(fromManifest))
782
+ return fromManifest;
783
+ }
784
+ return null;
785
+ }
786
+ themeAppearanceDefaults(manifest) {
787
+ var _a, _b, _c;
788
+ const defaults = {};
789
+ for (const section of (_b = (_a = manifest === null || manifest === void 0 ? void 0 : manifest.appearance) === null || _a === void 0 ? void 0 : _a.sections) !== null && _b !== void 0 ? _b : []) {
790
+ for (const setting of (_c = section.settings) !== null && _c !== void 0 ? _c : []) {
791
+ if (setting.default)
792
+ defaults[setting.id] = setting.default;
793
+ }
794
+ }
795
+ return defaults;
796
+ }
797
+ buildPlaceholderCoverSvg(id) {
798
+ var _a;
799
+ const manifest = this.getThemeManifestFromSources(id);
800
+ const defaults = this.themeAppearanceDefaults(manifest);
801
+ return (0, theme_placeholder_cover_js_1.buildThemePlaceholderCoverSvg)({
802
+ id,
803
+ name: (_a = manifest === null || manifest === void 0 ? void 0 : manifest.name) !== null && _a !== void 0 ? _a : id,
804
+ primary: defaults.primaryColor,
805
+ accent: defaults.accentColor,
806
+ version: manifest === null || manifest === void 0 ? void 0 : manifest.version,
807
+ });
808
+ }
809
+ resolveSiteUrlFromRow(row) {
810
+ return (process.env.NGINX_ENTRY_URL ||
811
+ process.env.REACTPRESS_NGINX_ENTRY_URL ||
812
+ (process.env.NGINX_PORT ? `http://localhost:${process.env.NGINX_PORT}` : null) ||
813
+ row.systemUrl ||
814
+ process.env.CLIENT_SITE_URL ||
815
+ 'http://localhost:3001');
816
+ }
817
+ buildPreviewHtml(themeId, mods = {}) {
818
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
819
+ const manifest = this.getThemeManifestFromSources(themeId);
820
+ const name = (_a = manifest === null || manifest === void 0 ? void 0 : manifest.name) !== null && _a !== void 0 ? _a : themeId;
821
+ const primary = (_b = mods.primaryColor) !== null && _b !== void 0 ? _b : '#2271b1';
822
+ const accent = (_c = mods.accentColor) !== null && _c !== void 0 ? _c : '#d63638';
823
+ const bg = (_d = mods.backgroundColor) !== null && _d !== void 0 ? _d : '#f0f0f1';
824
+ const displayTitle = (_e = mods.displayTitle) !== null && _e !== void 0 ? _e : name;
825
+ const displayTagline = (_g = (_f = mods.displayTagline) !== null && _f !== void 0 ? _f : manifest === null || manifest === void 0 ? void 0 : manifest.description) !== null && _g !== void 0 ? _g : 'Theme preview';
826
+ const dark = mods.darkMode === '1' || mods.darkMode === 'true' || mods.darkMode === 'yes';
827
+ const textColor = dark ? '#e8e8e8' : '#1d2327';
828
+ const pageBg = dark ? '#1a1a1a' : bg;
829
+ const bgImage = (_h = mods.backgroundImage) === null || _h === void 0 ? void 0 : _h.trim();
830
+ const extraCss = (_k = (_j = mods.additionalCss) === null || _j === void 0 ? void 0 : _j.trim()) !== null && _k !== void 0 ? _k : '';
831
+ return `<!DOCTYPE html>
832
+ <html lang="zh-CN"${dark ? ' data-rp-dark="true"' : ''}>
833
+ <head>
834
+ <meta charset="utf-8" />
835
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
836
+ <title>${displayTitle} — Preview</title>
837
+ <style>
838
+ :root {
839
+ --rp-primary: ${primary};
840
+ --rp-accent: ${accent};
841
+ --rp-bg: ${pageBg};
842
+ }
843
+ * { box-sizing: border-box; }
844
+ body {
845
+ margin: 0;
846
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
847
+ background: ${bgImage ? `url("${bgImage.replace(/"/g, '\\"')}") center/cover fixed` : 'var(--rp-bg)'};
848
+ color: ${textColor};
849
+ line-height: 1.6;
850
+ }
851
+ ${extraCss}
852
+ .wrap { max-width: 720px; margin: 0 auto; padding: 2rem 1.5rem 4rem; }
853
+ header { border-bottom: 3px solid var(--rp-primary); padding-bottom: 1rem; margin-bottom: 2rem; }
854
+ h1 { color: var(--rp-primary); font-size: 2rem; margin: 0 0 0.25rem; }
855
+ .tagline { color: #646970; margin: 0; }
856
+ h2 { color: var(--rp-accent); margin-top: 2rem; }
857
+ a { color: var(--rp-primary); }
858
+ .card {
859
+ background: #fff;
860
+ border: 1px solid #c3c4c7;
861
+ border-radius: 4px;
862
+ padding: 1.25rem;
863
+ margin-top: 1rem;
864
+ }
865
+ .meta { font-size: 0.875rem; color: #646970; }
866
+ </style>
867
+ </head>
868
+ <body>
869
+ <div class="wrap">
870
+ <header>
871
+ <h1>${displayTitle}</h1>
872
+ <p class="tagline">${displayTagline}</p>
873
+ </header>
874
+ <h2>排版示例</h2>
875
+ <p>这是 <strong>${name}</strong> 主题的实时预览。在左侧自定义器中修改颜色与标题后,此页面会即时更新。</p>
876
+ <h3>标题层级</h3>
877
+ <h4>四级标题</h4>
878
+ <h5>五级标题</h5>
879
+ <h6>六级标题</h6>
880
+ <ul>
881
+ <li>无序列表项</li>
882
+ <li><a href="#">示例链接</a></li>
883
+ </ul>
884
+ <article class="card">
885
+ <h2 style="margin-top:0">Hello world!</h2>
886
+ <p class="meta">发布于 ${new Date().toLocaleDateString('zh-CN')}</p>
887
+ <p>欢迎使用 ReactPress 主题系统。激活主题后,访客站点将使用该主题的 Next.js 模板渲染。</p>
888
+ </article>
889
+ </div>
890
+ </body>
891
+ </html>`;
892
+ }
893
+ async getPreviewMods(themeId, overrideMods) {
894
+ var _a;
895
+ if (overrideMods && Object.keys(overrideMods).length > 0)
896
+ return overrideMods;
897
+ const state = await this.getThemeState();
898
+ return (_a = state.mods[themeId]) !== null && _a !== void 0 ? _a : {};
899
+ }
900
+ createPreviewDraft(payload) {
901
+ const token = (0, preview_draft_store_1.putPreviewDraft)(payload);
902
+ return { token };
903
+ }
904
+ resolvePreviewDraft(token) {
905
+ const draft = (0, preview_draft_store_1.getPreviewDraft)(token);
906
+ if (!draft)
907
+ return null;
908
+ return {
909
+ themeId: draft.themeId,
910
+ mods: draft.mods,
911
+ configuration: draft.configuration,
912
+ };
913
+ }
914
+ resolveFallbackActiveTheme(state) {
915
+ const candidates = [
916
+ state.activeTheme,
917
+ 'hello-world',
918
+ ...state.installedThemes,
919
+ theme_2.defaultSiteThemeState.activeTheme,
920
+ ];
921
+ const seen = new Set();
922
+ for (const id of candidates) {
923
+ if (!id || seen.has(id))
924
+ continue;
925
+ seen.add(id);
926
+ if (this.resolveThemeDir(id))
927
+ return id;
928
+ }
929
+ for (const manifest of this.listBundledThemes()) {
930
+ if (this.resolveThemeDir(manifest.id))
931
+ return manifest.id;
932
+ }
933
+ return null;
934
+ }
935
+ async ensureDefaultTheme() {
936
+ const state = await this.getThemeState();
937
+ let activeTheme = state.activeTheme;
938
+ if (!activeTheme || !this.resolveThemeDir(activeTheme)) {
939
+ const fallback = this.resolveFallbackActiveTheme(state);
940
+ if (fallback) {
941
+ const saved = await this.saveThemeState({
942
+ activeTheme: fallback,
943
+ previewThemeId: fallback,
944
+ installedThemes: state.installedThemes.includes(fallback)
945
+ ? state.installedThemes
946
+ : [...state.installedThemes, fallback],
947
+ });
948
+ activeTheme = saved.activeTheme;
949
+ }
950
+ else if (!activeTheme) {
951
+ const saved = await this.saveThemeState(theme_2.defaultSiteThemeState);
952
+ activeTheme = saved.activeTheme;
953
+ }
954
+ }
955
+ if (this.resolveThemeDir(activeTheme)) {
956
+ this.syncActiveThemeManifest(activeTheme);
957
+ }
958
+ }
959
+ materializeRuntimeTheme(templatePath, targetDir) {
960
+ const forceCopy = process.env.REACTPRESS_THEME_RUNTIME_SYMLINK !== '1' &&
961
+ (process.env.REACTPRESS_THEME_RUNTIME_COPY === '1' || process.env.NODE_ENV === 'production');
962
+ if (!forceCopy) {
963
+ const linkTarget = path.relative(path.dirname(targetDir), templatePath);
964
+ fs.symlinkSync(linkTarget, targetDir, 'dir');
965
+ return;
966
+ }
967
+ this.copyDir(templatePath, targetDir);
968
+ this.linkTemplateNodeModules(templatePath, targetDir);
969
+ }
970
+ copyDir(src, dest) {
971
+ fs.mkdirSync(dest, { recursive: true });
972
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
973
+ if (ThemeService_1.COPY_SKIP_NAMES.has(entry.name))
974
+ continue;
975
+ const from = path.join(src, entry.name);
976
+ const to = path.join(dest, entry.name);
977
+ if (entry.isSymbolicLink()) {
978
+ const link = fs.readlinkSync(from);
979
+ fs.symlinkSync(link, to);
980
+ }
981
+ else if (entry.isDirectory()) {
982
+ this.copyDir(from, to);
983
+ }
984
+ else if (entry.isFile()) {
985
+ fs.copyFileSync(from, to);
986
+ }
987
+ }
988
+ }
989
+ linkTemplateNodeModules(templatePath, targetDir) {
990
+ const srcModules = path.join(templatePath, 'node_modules');
991
+ const destModules = path.join(targetDir, 'node_modules');
992
+ if (!fs.existsSync(srcModules) || fs.existsSync(destModules))
993
+ return;
994
+ const linkTarget = path.relative(targetDir, srcModules);
995
+ const linkType = fs.lstatSync(srcModules).isDirectory() ? 'dir' : 'file';
996
+ fs.symlinkSync(linkTarget, destModules, linkType);
997
+ }
998
+ removeDir(dir) {
999
+ if (!fs.existsSync(dir))
1000
+ return;
1001
+ const stat = fs.lstatSync(dir);
1002
+ if (stat.isSymbolicLink() || !stat.isDirectory()) {
1003
+ fs.unlinkSync(dir);
1004
+ return;
1005
+ }
1006
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
1007
+ const target = path.join(dir, entry.name);
1008
+ if (entry.isSymbolicLink()) {
1009
+ fs.unlinkSync(target);
1010
+ }
1011
+ else if (entry.isDirectory()) {
1012
+ this.removeDir(target);
1013
+ }
1014
+ else {
1015
+ fs.unlinkSync(target);
1016
+ }
1017
+ }
1018
+ fs.rmdirSync(dir);
1019
+ }
1020
+ };
1021
+ ThemeService.COPY_SKIP_NAMES = new Set([
1022
+ 'node_modules',
1023
+ '.next',
1024
+ '.git',
1025
+ 'dist',
1026
+ '.turbo',
1027
+ 'coverage',
1028
+ '.reactpress',
1029
+ '.cache',
1030
+ 'package-lock.json',
1031
+ ]);
1032
+ ThemeService = ThemeService_1 = __decorate([
1033
+ (0, common_1.Injectable)(),
1034
+ __param(0, (0, typeorm_1.InjectRepository)(setting_entity_1.Setting)),
1035
+ __metadata("design:paramtypes", [typeorm_2.Repository,
1036
+ setting_service_1.SettingService])
1037
+ ], ThemeService);
1038
+ exports.ThemeService = ThemeService;
1039
+ //# sourceMappingURL=theme.service.js.map