@lark-apaas/coding-template-nestjs-react-fullstack 0.1.0-alpha.1

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 (250) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +41 -0
  3. package/hooks/after-install.mjs +3 -0
  4. package/hooks/after-render.mjs +3 -0
  5. package/hooks/before-render.mjs +3 -0
  6. package/package.json +36 -0
  7. package/template/.codebase/pipelines/ci.yaml +34 -0
  8. package/template/.codebase/pipelines/coco-code-review.yaml +21 -0
  9. package/template/.prettierrc +8 -0
  10. package/template/.spark_project +16 -0
  11. package/template/.stylelintrc.js +12 -0
  12. package/template/_env.local +38 -0
  13. package/template/_gitignore +64 -0
  14. package/template/_npmrc +1 -0
  15. package/template/client/index.html +23 -0
  16. package/template/client/public/favicon.svg +40 -0
  17. package/template/client/src/api/index.ts +19 -0
  18. package/template/client/src/app.tsx +22 -0
  19. package/template/client/src/components/Layout.tsx +11 -0
  20. package/template/client/src/components/business-ui/README.md +519 -0
  21. package/template/client/src/components/business-ui/api/chats/queries.ts +39 -0
  22. package/template/client/src/components/business-ui/api/chats/service.ts +29 -0
  23. package/template/client/src/components/business-ui/api/departments/queries.ts +42 -0
  24. package/template/client/src/components/business-ui/api/departments/service.ts +18 -0
  25. package/template/client/src/components/business-ui/api/files/service.ts +28 -0
  26. package/template/client/src/components/business-ui/api/user-profiles/queries.ts +42 -0
  27. package/template/client/src/components/business-ui/api/user-profiles/service.ts +23 -0
  28. package/template/client/src/components/business-ui/api/users/queries.ts +34 -0
  29. package/template/client/src/components/business-ui/api/users/service.ts +40 -0
  30. package/template/client/src/components/business-ui/chat-select/README.md +128 -0
  31. package/template/client/src/components/business-ui/chat-select/chat-item.tsx +85 -0
  32. package/template/client/src/components/business-ui/chat-select/chat-select-tag.tsx +83 -0
  33. package/template/client/src/components/business-ui/chat-select/chat-select.tsx +197 -0
  34. package/template/client/src/components/business-ui/chat-select/index.tsx +12 -0
  35. package/template/client/src/components/business-ui/chat-select/types.ts +102 -0
  36. package/template/client/src/components/business-ui/chat-select/use-chat-value.ts +180 -0
  37. package/template/client/src/components/business-ui/chat-select/utils.ts +81 -0
  38. package/template/client/src/components/business-ui/department-select/department-item.tsx +55 -0
  39. package/template/client/src/components/business-ui/department-select/department-select-field.tsx +86 -0
  40. package/template/client/src/components/business-ui/department-select/department-select-tag.tsx +56 -0
  41. package/template/client/src/components/business-ui/department-select/department-select.tsx +168 -0
  42. package/template/client/src/components/business-ui/department-select/icon-department.tsx +22 -0
  43. package/template/client/src/components/business-ui/department-select/index.tsx +7 -0
  44. package/template/client/src/components/business-ui/department-select/types.ts +15 -0
  45. package/template/client/src/components/business-ui/department-select/utils.ts +17 -0
  46. package/template/client/src/components/business-ui/entity-combobox/base-combobox-content.tsx +35 -0
  47. package/template/client/src/components/business-ui/entity-combobox/base-combobox-empty.tsx +28 -0
  48. package/template/client/src/components/business-ui/entity-combobox/base-combobox-error.tsx +35 -0
  49. package/template/client/src/components/business-ui/entity-combobox/base-combobox-item.tsx +55 -0
  50. package/template/client/src/components/business-ui/entity-combobox/base-combobox-list.tsx +174 -0
  51. package/template/client/src/components/business-ui/entity-combobox/base-combobox-loading.tsx +19 -0
  52. package/template/client/src/components/business-ui/entity-combobox/base-combobox-search.tsx +31 -0
  53. package/template/client/src/components/business-ui/entity-combobox/base-combobox-trigger.tsx +281 -0
  54. package/template/client/src/components/business-ui/entity-combobox/base-combobox.tsx +132 -0
  55. package/template/client/src/components/business-ui/entity-combobox/context.tsx +19 -0
  56. package/template/client/src/components/business-ui/entity-combobox/entity-combobox.tsx +145 -0
  57. package/template/client/src/components/business-ui/entity-combobox/highlight-text.tsx +52 -0
  58. package/template/client/src/components/business-ui/entity-combobox/hooks.tsx +21 -0
  59. package/template/client/src/components/business-ui/entity-combobox/index.tsx +31 -0
  60. package/template/client/src/components/business-ui/entity-combobox/item-pill.tsx +179 -0
  61. package/template/client/src/components/business-ui/entity-combobox/popover-wrapper.tsx +149 -0
  62. package/template/client/src/components/business-ui/entity-combobox/search-trigger.tsx +262 -0
  63. package/template/client/src/components/business-ui/entity-combobox/shared-types.ts +296 -0
  64. package/template/client/src/components/business-ui/entity-combobox/size-variants.tsx +322 -0
  65. package/template/client/src/components/business-ui/entity-combobox/types.ts +246 -0
  66. package/template/client/src/components/business-ui/entity-combobox/use-fetch-data.tsx +81 -0
  67. package/template/client/src/components/business-ui/entity-combobox/use-infinite-scroll.tsx +99 -0
  68. package/template/client/src/components/business-ui/entity-combobox/use-popover-outside-click.tsx +32 -0
  69. package/template/client/src/components/business-ui/form/checkbox-field.tsx +83 -0
  70. package/template/client/src/components/business-ui/form/context.tsx +38 -0
  71. package/template/client/src/components/business-ui/form/field-layout.tsx +91 -0
  72. package/template/client/src/components/business-ui/form/form.tsx +54 -0
  73. package/template/client/src/components/business-ui/form/hooks/form-context.tsx +4 -0
  74. package/template/client/src/components/business-ui/form/hooks/form-utils.ts +23 -0
  75. package/template/client/src/components/business-ui/form/hooks/form.tsx +40 -0
  76. package/template/client/src/components/business-ui/form/index.tsx +4 -0
  77. package/template/client/src/components/business-ui/form/input-field.tsx +74 -0
  78. package/template/client/src/components/business-ui/form/radio-group-field.tsx +138 -0
  79. package/template/client/src/components/business-ui/form/select-field.tsx +155 -0
  80. package/template/client/src/components/business-ui/form/switch-field.tsx +66 -0
  81. package/template/client/src/components/business-ui/form/textarea-field.tsx +72 -0
  82. package/template/client/src/components/business-ui/form/types.ts +32 -0
  83. package/template/client/src/components/business-ui/tiptap-editor/README.md +324 -0
  84. package/template/client/src/components/business-ui/tiptap-editor/components/attachment-toolbar-button.tsx +74 -0
  85. package/template/client/src/components/business-ui/tiptap-editor/components/blockquote-toolbar-button.tsx +41 -0
  86. package/template/client/src/components/business-ui/tiptap-editor/components/code-block-toolbar-button.tsx +41 -0
  87. package/template/client/src/components/business-ui/tiptap-editor/components/color-highlight-toolbar-button.tsx +141 -0
  88. package/template/client/src/components/business-ui/tiptap-editor/components/heading-toolbar-button.tsx +99 -0
  89. package/template/client/src/components/business-ui/tiptap-editor/components/horizontal-rule-toolbar-button.tsx +39 -0
  90. package/template/client/src/components/business-ui/tiptap-editor/components/image-upload-toolbar-button.tsx +65 -0
  91. package/template/client/src/components/business-ui/tiptap-editor/components/link-edit-form.tsx +127 -0
  92. package/template/client/src/components/business-ui/tiptap-editor/components/link-hover-toolbar.tsx +380 -0
  93. package/template/client/src/components/business-ui/tiptap-editor/components/link-toolbar-button.tsx +96 -0
  94. package/template/client/src/components/business-ui/tiptap-editor/components/list-toolbar-button.tsx +75 -0
  95. package/template/client/src/components/business-ui/tiptap-editor/components/mark-toolbar-button.tsx +118 -0
  96. package/template/client/src/components/business-ui/tiptap-editor/components/text-align-toolbar-button.tsx +84 -0
  97. package/template/client/src/components/business-ui/tiptap-editor/components/undo-redo-toolbar-button.tsx +54 -0
  98. package/template/client/src/components/business-ui/tiptap-editor/extensions/attachment.tsx +539 -0
  99. package/template/client/src/components/business-ui/tiptap-editor/extensions/code-block-shiki.tsx +236 -0
  100. package/template/client/src/components/business-ui/tiptap-editor/extensions/complete-kit.ts +260 -0
  101. package/template/client/src/components/business-ui/tiptap-editor/extensions/image.tsx +456 -0
  102. package/template/client/src/components/business-ui/tiptap-editor/hooks/use-tiptap-editor.ts +47 -0
  103. package/template/client/src/components/business-ui/tiptap-editor/index.ts +38 -0
  104. package/template/client/src/components/business-ui/tiptap-editor/tiptap-editor-complete.tsx +112 -0
  105. package/template/client/src/components/business-ui/tiptap-editor/tiptap-editor.tsx +169 -0
  106. package/template/client/src/components/business-ui/types/user.ts +74 -0
  107. package/template/client/src/components/business-ui/user-display/index.tsx +2 -0
  108. package/template/client/src/components/business-ui/user-display/overflow-tooltip-text.tsx +90 -0
  109. package/template/client/src/components/business-ui/user-display/type.ts +27 -0
  110. package/template/client/src/components/business-ui/user-display/user-display.tsx +99 -0
  111. package/template/client/src/components/business-ui/user-display/user-with-avatar.tsx +158 -0
  112. package/template/client/src/components/business-ui/user-display/utils.ts +37 -0
  113. package/template/client/src/components/business-ui/user-profile/error-image.tsx +302 -0
  114. package/template/client/src/components/business-ui/user-profile/user-external-script.ts +73 -0
  115. package/template/client/src/components/business-ui/user-profile/user-profile.tsx +370 -0
  116. package/template/client/src/components/business-ui/user-select/index.tsx +28 -0
  117. package/template/client/src/components/business-ui/user-select/types.ts +109 -0
  118. package/template/client/src/components/business-ui/user-select/use-user-value.ts +160 -0
  119. package/template/client/src/components/business-ui/user-select/user-item.tsx +98 -0
  120. package/template/client/src/components/business-ui/user-select/user-pill.tsx +140 -0
  121. package/template/client/src/components/business-ui/user-select/user-select-tag.tsx +82 -0
  122. package/template/client/src/components/business-ui/user-select/user-select.tsx +359 -0
  123. package/template/client/src/components/business-ui/user-select/utils.tsx +188 -0
  124. package/template/client/src/components/business-ui/utils/user.ts +72 -0
  125. package/template/client/src/components/ui/README.md +134 -0
  126. package/template/client/src/components/ui/accordion.tsx +66 -0
  127. package/template/client/src/components/ui/alert-dialog.tsx +157 -0
  128. package/template/client/src/components/ui/alert.tsx +71 -0
  129. package/template/client/src/components/ui/aspect-ratio.tsx +11 -0
  130. package/template/client/src/components/ui/avatar.tsx +53 -0
  131. package/template/client/src/components/ui/badge.tsx +42 -0
  132. package/template/client/src/components/ui/breadcrumb.tsx +109 -0
  133. package/template/client/src/components/ui/button-group.tsx +83 -0
  134. package/template/client/src/components/ui/button.tsx +69 -0
  135. package/template/client/src/components/ui/calendar.tsx +213 -0
  136. package/template/client/src/components/ui/card.tsx +82 -0
  137. package/template/client/src/components/ui/carousel.tsx +241 -0
  138. package/template/client/src/components/ui/chart.tsx +357 -0
  139. package/template/client/src/components/ui/checkbox.tsx +32 -0
  140. package/template/client/src/components/ui/collapsible.tsx +33 -0
  141. package/template/client/src/components/ui/command.tsx +208 -0
  142. package/template/client/src/components/ui/context-menu.tsx +324 -0
  143. package/template/client/src/components/ui/dialog.tsx +143 -0
  144. package/template/client/src/components/ui/drawer.tsx +135 -0
  145. package/template/client/src/components/ui/dropdown-menu.tsx +329 -0
  146. package/template/client/src/components/ui/empty.tsx +104 -0
  147. package/template/client/src/components/ui/field.tsx +248 -0
  148. package/template/client/src/components/ui/form.tsx +167 -0
  149. package/template/client/src/components/ui/hover-card.tsx +44 -0
  150. package/template/client/src/components/ui/icons/file-ae-colorful-icon.tsx +21 -0
  151. package/template/client/src/components/ui/icons/file-ai-colorful-icon.tsx +36 -0
  152. package/template/client/src/components/ui/icons/file-android-colorful-icon.tsx +33 -0
  153. package/template/client/src/components/ui/icons/file-audio-colorful-icon.tsx +21 -0
  154. package/template/client/src/components/ui/icons/file-code-colorful-icon.tsx +28 -0
  155. package/template/client/src/components/ui/icons/file-csv-colorful-icon.tsx +21 -0
  156. package/template/client/src/components/ui/icons/file-eml-colorful-icon.tsx +29 -0
  157. package/template/client/src/components/ui/icons/file-ios-colorful-icon.tsx +25 -0
  158. package/template/client/src/components/ui/icons/file-keynote-colorful-icon.tsx +29 -0
  159. package/template/client/src/components/ui/icons/file-pages-colorful-icon.tsx +29 -0
  160. package/template/client/src/components/ui/icons/file-ps-colorful-icon.tsx +21 -0
  161. package/template/client/src/components/ui/icons/file-sketch-colorful-icon.tsx +21 -0
  162. package/template/client/src/components/ui/icons/file-slide-colorful-icon.tsx +21 -0
  163. package/template/client/src/components/ui/icons/file-vcf-colorful-icon.tsx +29 -0
  164. package/template/client/src/components/ui/icons/file-wiki-excel-colorful-icon.tsx +23 -0
  165. package/template/client/src/components/ui/icons/file-wiki-image-colorful-icon.tsx +27 -0
  166. package/template/client/src/components/ui/icons/file-wiki-pdf-colorful-icon.tsx +20 -0
  167. package/template/client/src/components/ui/icons/file-wiki-ppt-colorful-icon.tsx +21 -0
  168. package/template/client/src/components/ui/icons/file-wiki-text-colorful-icon.tsx +12 -0
  169. package/template/client/src/components/ui/icons/file-wiki-unknown-colorful-icon.tsx +14 -0
  170. package/template/client/src/components/ui/icons/file-wiki-video-colorful-icon.tsx +23 -0
  171. package/template/client/src/components/ui/icons/file-wiki-word-colorful-icon.tsx +38 -0
  172. package/template/client/src/components/ui/icons/file-wiki-zip-colorful-icon.tsx +21 -0
  173. package/template/client/src/components/ui/image.tsx +183 -0
  174. package/template/client/src/components/ui/input-group.tsx +166 -0
  175. package/template/client/src/components/ui/input-otp.tsx +77 -0
  176. package/template/client/src/components/ui/input.tsx +21 -0
  177. package/template/client/src/components/ui/item.tsx +193 -0
  178. package/template/client/src/components/ui/kbd.tsx +28 -0
  179. package/template/client/src/components/ui/label.tsx +24 -0
  180. package/template/client/src/components/ui/menubar.tsx +348 -0
  181. package/template/client/src/components/ui/native-select.tsx +48 -0
  182. package/template/client/src/components/ui/navigation-menu.tsx +168 -0
  183. package/template/client/src/components/ui/pagination.tsx +127 -0
  184. package/template/client/src/components/ui/popover.tsx +48 -0
  185. package/template/client/src/components/ui/progress.tsx +31 -0
  186. package/template/client/src/components/ui/radio-group.tsx +45 -0
  187. package/template/client/src/components/ui/resizable.tsx +56 -0
  188. package/template/client/src/components/ui/scroll-area.tsx +58 -0
  189. package/template/client/src/components/ui/select.tsx +243 -0
  190. package/template/client/src/components/ui/separator.tsx +28 -0
  191. package/template/client/src/components/ui/sheet.tsx +139 -0
  192. package/template/client/src/components/ui/sidebar.tsx +727 -0
  193. package/template/client/src/components/ui/skeleton.tsx +13 -0
  194. package/template/client/src/components/ui/slider.tsx +87 -0
  195. package/template/client/src/components/ui/sonner.tsx +67 -0
  196. package/template/client/src/components/ui/spinner.tsx +16 -0
  197. package/template/client/src/components/ui/streamdown.tsx +186 -0
  198. package/template/client/src/components/ui/switch.tsx +31 -0
  199. package/template/client/src/components/ui/table.tsx +116 -0
  200. package/template/client/src/components/ui/tabs.tsx +66 -0
  201. package/template/client/src/components/ui/textarea.tsx +18 -0
  202. package/template/client/src/components/ui/toggle-group.tsx +83 -0
  203. package/template/client/src/components/ui/toggle.tsx +47 -0
  204. package/template/client/src/components/ui/tooltip.tsx +61 -0
  205. package/template/client/src/hooks/use-example.ts +52 -0
  206. package/template/client/src/hooks/use-mobile.ts +19 -0
  207. package/template/client/src/index.css +7 -0
  208. package/template/client/src/index.tsx +36 -0
  209. package/template/client/src/lib/shiki.ts +92 -0
  210. package/template/client/src/lib/utils.ts +6 -0
  211. package/template/client/src/pages/ExamplePage/ExamplePage.tsx +37 -0
  212. package/template/client/src/pages/NotFound/NotFound.tsx +11 -0
  213. package/template/client/src/tailwind-theme.css +257 -0
  214. package/template/client/src/types/common.ts +34 -0
  215. package/template/client/src/types/global.d.ts +53 -0
  216. package/template/client/src/types/index.ts +4 -0
  217. package/template/client/src/typography.css +41 -0
  218. package/template/client/src/utils/img-resources/avatar-placeholders.ts +12 -0
  219. package/template/client/src/utils/img-resources/banner-placeholders.ts +29 -0
  220. package/template/client/src/utils/img-resources/cover-placeholders.ts +47 -0
  221. package/template/components.json +21 -0
  222. package/template/eslint.config.js +50 -0
  223. package/template/nest-cli.json +25 -0
  224. package/template/package-lock.json +29195 -0
  225. package/template/package.json +202 -0
  226. package/template/postcss.config.js +10 -0
  227. package/template/scripts/build.sh +120 -0
  228. package/template/scripts/dev.js +295 -0
  229. package/template/scripts/dev.sh +2 -0
  230. package/template/scripts/lint.js +150 -0
  231. package/template/scripts/prune-smart.js +281 -0
  232. package/template/scripts/run.sh +5 -0
  233. package/template/server/app.module.ts +27 -0
  234. package/template/server/common/constants/api_response_code.ts +54 -0
  235. package/template/server/common/filters/exception.filter.ts +78 -0
  236. package/template/server/common/interfaces/api_response.interface.ts +21 -0
  237. package/template/server/common/interfaces/exception.interface.ts +19 -0
  238. package/template/server/database/schema.ts +90 -0
  239. package/template/server/main.ts +31 -0
  240. package/template/server/modules/hello/hello.controller.ts +16 -0
  241. package/template/server/modules/hello/hello.module.ts +10 -0
  242. package/template/server/modules/hello/hello.service.ts +28 -0
  243. package/template/server/modules/view/view.controller.ts +17 -0
  244. package/template/server/modules/view/view.module.ts +8 -0
  245. package/template/shared/api.interface.ts +1 -0
  246. package/template/tailwind.config.ts +9 -0
  247. package/template/tsconfig.app.json +23 -0
  248. package/template/tsconfig.json +8 -0
  249. package/template/tsconfig.node.json +16 -0
  250. package/template/vite.config.ts +10 -0
@@ -0,0 +1,202 @@
1
+ {
2
+ "name": "fullstack-nestjs-template",
3
+ "version": "2.2.5",
4
+ "private": true,
5
+ "flags": {
6
+ "supportBusinessUser": true,
7
+ "supportScrollReveal": true,
8
+ "supportTiptapAndStreamdown": true,
9
+ "customToaster": true
10
+ },
11
+ "scripts": {
12
+ "dev": "npm run upgrade && ./scripts/dev.sh",
13
+ "dev:server": "NODE_ENV=development nest start --watch",
14
+ "dev:client": "NODE_ENV=development vite --config vite.config.ts",
15
+ "gen:db-schema": "npx -y @lark-apaas/db-schema-sync@latest --output server/database/schema.ts --export-custom-types",
16
+ "gen:openapi": "echo 'UNSUPPORTED, SKIP'",
17
+ "build": "./scripts/build.sh",
18
+ "build:prod": "npm run build:server && npm run build:client",
19
+ "build:server": "NODE_ENV=production nest build",
20
+ "build:client": "NODE_ENV=production vite build --config vite.config.ts",
21
+ "start": "NODE_ENV=production node main.js",
22
+ "test": "jest",
23
+ "test:watch": "jest --watch",
24
+ "test:e2e": "jest --config test/e2e/jest.config.js",
25
+ "eslint": "eslint . --quiet",
26
+ "stylelint": "stylelint client/src/**/*.css --quiet",
27
+ "type:check": "concurrently -n \"server,client\" -c \"blue,green\" \"npm run type:check:server\" \"npm run type:check:client\"",
28
+ "type:check:client": "tsc --noEmit --project tsconfig.app.json",
29
+ "type:check:server": "tsc --noEmit --project tsconfig.node.json",
30
+ "lint": "node ./scripts/lint.js",
31
+ "format": "prettier --write \"{server,client,test}/**/*.{js,ts,tsx,json,md}\"",
32
+ "upgrade": "fullstack-cli sync --disable-gen-openapi"
33
+ },
34
+ "dependencies": {
35
+ "@lark-apaas/fullstack-nestjs-core": "^1.1.22",
36
+ "@nestjs/axios": "^4.0.1",
37
+ "@nestjs/common": "^10.4.20",
38
+ "@nestjs/config": "^3.3.0",
39
+ "@nestjs/core": "^10.4.20",
40
+ "@nestjs/platform-express": "^10.4.20",
41
+ "@nestjs/swagger": "^7.4.2",
42
+ "@tanstack/react-form": "^1.27.6",
43
+ "@tanstack/react-query": "^5.90.12",
44
+ "axios": "^1.12.2",
45
+ "class-transformer": "^0.5.1",
46
+ "class-validator": "^0.14.2",
47
+ "crypto-js": "^4.2.0",
48
+ "dayjs": "^1.11.15",
49
+ "dotenv": "^17.2.2",
50
+ "drizzle-orm": "0.44.6",
51
+ "hbs": "^4.2.0",
52
+ "reflect-metadata": "^0.1.14",
53
+ "tslib": "^2.8.1"
54
+ },
55
+ "devDependencies": {
56
+ "@dnd-kit/core": "^6.3.1",
57
+ "@dnd-kit/modifiers": "^9.0.0",
58
+ "@dnd-kit/sortable": "^10.0.0",
59
+ "@headlessui/react": "^2.2.9",
60
+ "@heroicons/react": "^2.2.0",
61
+ "@hookform/resolvers": "^5.2.2",
62
+ "@lark-apaas/client-toolkit": "^1.2.31",
63
+ "@lark-apaas/fullstack-presets": "^1.1.0",
64
+ "@lark-apaas/fullstack-vite-preset": "^1.0.1",
65
+ "@nestjs/cli": "^10.4.9",
66
+ "@nestjs/testing": "^10.4.20",
67
+ "@radix-ui/react-accordion": "^1.2.12",
68
+ "@radix-ui/react-alert-dialog": "^1.1.15",
69
+ "@radix-ui/react-aspect-ratio": "^1.1.7",
70
+ "@radix-ui/react-avatar": "^1.1.10",
71
+ "@radix-ui/react-checkbox": "^1.3.3",
72
+ "@radix-ui/react-collapsible": "^1.1.12",
73
+ "@radix-ui/react-context-menu": "^2.2.16",
74
+ "@radix-ui/react-dialog": "^1.1.15",
75
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
76
+ "@radix-ui/react-hover-card": "^1.1.15",
77
+ "@radix-ui/react-label": "^2.1.7",
78
+ "@radix-ui/react-menubar": "^1.1.16",
79
+ "@radix-ui/react-navigation-menu": "^1.2.14",
80
+ "@radix-ui/react-popover": "^1.1.15",
81
+ "@radix-ui/react-progress": "^1.1.7",
82
+ "@radix-ui/react-radio-group": "^1.3.8",
83
+ "@radix-ui/react-scroll-area": "^1.2.10",
84
+ "@radix-ui/react-select": "^2.2.6",
85
+ "@radix-ui/react-separator": "^1.1.7",
86
+ "@radix-ui/react-slider": "^1.3.6",
87
+ "@radix-ui/react-slot": "^1.2.3",
88
+ "@radix-ui/react-switch": "^1.2.6",
89
+ "@radix-ui/react-tabs": "^1.1.13",
90
+ "@radix-ui/react-toggle": "^1.1.10",
91
+ "@radix-ui/react-toggle-group": "^1.1.11",
92
+ "@radix-ui/react-tooltip": "^1.2.8",
93
+ "@reduxjs/toolkit": "^2.9.0",
94
+ "@shikijs/langs": "^3.21.0",
95
+ "@shikijs/themes": "^3.21.0",
96
+ "@tailwindcss/postcss": "^4.1.13",
97
+ "@tailwindcss/typography": "^0.5.19",
98
+ "@tiptap/core": "^3.14.0",
99
+ "@tiptap/extension-code-block": "^3.15.3",
100
+ "@tiptap/extension-code-block-lowlight": "^3.14.0",
101
+ "@tiptap/extension-color": "^3.14.0",
102
+ "@tiptap/extension-highlight": "^3.14.0",
103
+ "@tiptap/extension-image": "^3.14.0",
104
+ "@tiptap/extension-link": "^3.14.0",
105
+ "@tiptap/extension-placeholder": "^3.14.0",
106
+ "@tiptap/extension-task-item": "^3.15.3",
107
+ "@tiptap/extension-task-list": "^3.15.3",
108
+ "@tiptap/extension-text-align": "^3.14.0",
109
+ "@tiptap/extension-text-style": "^3.14.0",
110
+ "@tiptap/extension-underline": "^3.14.0",
111
+ "@tiptap/pm": "^3.15.3",
112
+ "@tiptap/react": "^3.14.0",
113
+ "@tiptap/starter-kit": "^3.14.0",
114
+ "@types/crypto-js": "^4.2.2",
115
+ "@types/express": "^5.0.3",
116
+ "@types/hbs": "^4.0.5",
117
+ "@types/jest": "^29.5.14",
118
+ "@types/node": "^22.18.6",
119
+ "@types/react": "^19.2.0",
120
+ "@types/react-dom": "^19.2.0",
121
+ "autoprefixer": "^10.4.21",
122
+ "class-variance-authority": "^0.7.1",
123
+ "clsx": "~2.0.1",
124
+ "cmdk": "^1.1.1",
125
+ "cobe": "^0.6.5",
126
+ "concurrently": "^9.2.1",
127
+ "css-loader": "^7.1.2",
128
+ "date-fns": "^4.1.0",
129
+ "echarts": "~5.6.0",
130
+ "echarts-for-react": "~3.0.2",
131
+ "embla-carousel-react": "^8.6.0",
132
+ "es-toolkit": "^1.43.0",
133
+ "eslint": "^9.35.0",
134
+ "eslint-config-prettier": "^9.1.2",
135
+ "form-data": "^4.0.4",
136
+ "framer-motion": "~11.13.5",
137
+ "gsap": "^3.13.0",
138
+ "html2canvas": "^1.4.1",
139
+ "input-otp": "^1.4.2",
140
+ "jest": "^29.7.0",
141
+ "js-base64": "^3.7.8",
142
+ "jspdf": "^3.0.3",
143
+ "lodash": "^4.17.21",
144
+ "lucide-react": "^0.554.0",
145
+ "nanoid": "^5.1.6",
146
+ "next-themes": "^0.4.6",
147
+ "pinyin-pro": "^3.27.0",
148
+ "postcss": "^8.5.6",
149
+ "postcss-import": "^16.1.1",
150
+ "postcss-loader": "^8.2.0",
151
+ "prettier": "^3.6.2",
152
+ "qrcode.react": "^4.2.0",
153
+ "radix-ui": "^1.4.3",
154
+ "react": "^19.2.0",
155
+ "react-countup": "^6.5.3",
156
+ "react-day-picker": "^9.11.1",
157
+ "react-dom": "^19.2.0",
158
+ "react-dropzone": "^14.3.5",
159
+ "react-error-boundary": "^6.0.0",
160
+ "react-hook-form": "^7.65.0",
161
+ "react-redux": "^9.2.0",
162
+ "react-refresh": "^0.17.0",
163
+ "react-resizable-panels": "^3.0.6",
164
+ "react-router-dom": "^6.30.1",
165
+ "recharts": "^2.15.4",
166
+ "rxjs": "^7.8.2",
167
+ "shiki": "^3.21.0",
168
+ "sonner": "^2.0.7",
169
+ "streamdown": "^1.6.10",
170
+ "style-loader": "^4.0.0",
171
+ "stylelint": "^16.11.0",
172
+ "tailwind-merge": "~3.4.0",
173
+ "tailwindcss": "^4.1.13",
174
+ "ts-jest": "^29.4.3",
175
+ "ts-node": "^10.9.2",
176
+ "tw-animate-css": "^1.3.8",
177
+ "typescript": "^5.9.2",
178
+ "typescript-eslint": "^8.44.0",
179
+ "uuid": "11.0.5",
180
+ "vaul": "^1.1.2",
181
+ "vite": "^7.3.1",
182
+ "xlsx": "^0.18.5",
183
+ "xlsx-js-style": "^1.2.0",
184
+ "zod": "^3.25.76",
185
+ "zustand": "~5.0.8"
186
+ },
187
+ "overrides": {
188
+ "dayjs": "^1.11.15"
189
+ },
190
+ "jest": {
191
+ "preset": "ts-jest",
192
+ "testEnvironment": "node",
193
+ "testMatch": [
194
+ "<rootDir>/server/**/*.spec.ts",
195
+ "<rootDir>/test/unit/**/*.spec.ts"
196
+ ]
197
+ },
198
+ "engines": {
199
+ "node": ">=22.0.0",
200
+ "npm": ">=10.0.0"
201
+ }
202
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @type {import('postcss-load-config').Config}
3
+ */
4
+ module.exports = {
5
+ plugins: {
6
+ 'postcss-import': {},
7
+ '@tailwindcss/postcss': {},
8
+ autoprefixer: {}
9
+ },
10
+ }
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env bash
2
+ # This file is auto-generated by @lark-apaas/fullstack-cli
3
+ set -euo pipefail
4
+
5
+ ROOT_DIR="$(pwd)"
6
+ OUT_DIR="$ROOT_DIR/dist/server"
7
+
8
+ # 记录总开始时间
9
+ TOTAL_START=$(node -e "console.log(Date.now())")
10
+
11
+ # 打印耗时的辅助函数
12
+ print_time() {
13
+ local start=$1
14
+ local end=$(node -e "console.log(Date.now())")
15
+ local elapsed=$((end - start))
16
+ local seconds=$((elapsed / 1000))
17
+ local ms=$((elapsed % 1000))
18
+ echo " ⏱️ 耗时: ${seconds}.$(printf "%03d" $ms)s"
19
+ }
20
+
21
+ # ==================== 步骤 0 ====================
22
+ echo "🗑️ [0/5] 安装插件"
23
+ STEP_START=$(node -e "console.log(Date.now())")
24
+ npx fullstack-cli action-plugin init
25
+ print_time $STEP_START
26
+ echo ""
27
+
28
+ # ==================== 步骤 1 ====================
29
+ echo "📝 [1/5] 更新 openapi 代码"
30
+ STEP_START=$(node -e "console.log(Date.now())")
31
+ npm run gen:openapi
32
+ print_time $STEP_START
33
+ echo ""
34
+
35
+ # ==================== 步骤 2 ====================
36
+ echo "🗑️ [2/5] 清理 dist 目录"
37
+ STEP_START=$(node -e "console.log(Date.now())")
38
+ rm -rf "$ROOT_DIR/dist"
39
+ print_time $STEP_START
40
+ echo ""
41
+
42
+ # ==================== 步骤 3 ====================
43
+ echo "🔨 [3/5] 并行构建 server 和 client"
44
+ STEP_START=$(node -e "console.log(Date.now())")
45
+
46
+ # 并行构建
47
+ echo " ├─ 启动 server 构建..."
48
+ npm run build:server > /tmp/build-server.log 2>&1 &
49
+ SERVER_PID=$!
50
+
51
+ echo " ├─ 启动 client 构建..."
52
+ npm run build:client > /tmp/build-client.log 2>&1 &
53
+ CLIENT_PID=$!
54
+
55
+ # 等待两个构建完成
56
+ SERVER_EXIT=0
57
+ CLIENT_EXIT=0
58
+
59
+ wait $SERVER_PID || SERVER_EXIT=$?
60
+ wait $CLIENT_PID || CLIENT_EXIT=$?
61
+
62
+ # 检查构建结果
63
+ if [ $SERVER_EXIT -ne 0 ]; then
64
+ echo " ❌ Server 构建失败"
65
+ cat /tmp/build-server.log
66
+ exit 1
67
+ fi
68
+
69
+ if [ $CLIENT_EXIT -ne 0 ]; then
70
+ echo " ❌ Client 构建失败"
71
+ cat /tmp/build-client.log
72
+ exit 1
73
+ fi
74
+
75
+ echo " ✅ Server 构建完成"
76
+ echo " ✅ Client 构建完成"
77
+ print_time $STEP_START
78
+ echo ""
79
+
80
+ # ==================== 步骤 4 ====================
81
+ echo "📦 [4/5] 准备 server 依赖产物"
82
+ STEP_START=$(node -e "console.log(Date.now())")
83
+
84
+ mkdir -p "$OUT_DIR/dist/client"
85
+
86
+ # 拷贝 HTML
87
+ cp "$ROOT_DIR/dist/client/"*.html "$OUT_DIR/dist/client/" || true
88
+
89
+ # 拷贝 run.sh 文件
90
+ cp "$ROOT_DIR/scripts/run.sh" "$OUT_DIR/"
91
+
92
+ # 清理无用文件
93
+ rm -rf "$ROOT_DIR/dist/scripts"
94
+ rm -rf "$ROOT_DIR/dist/tsconfig.node.tsbuildinfo"
95
+
96
+ print_time $STEP_START
97
+ echo ""
98
+
99
+ # ==================== 步骤 5 ====================
100
+ echo "✂️ [5/5] 智能依赖裁剪"
101
+ STEP_START=$(node -e "console.log(Date.now())")
102
+
103
+ # 分析实际依赖、复制并裁剪 node_modules、生成精简的 package.json
104
+ node "$ROOT_DIR/scripts/prune-smart.js"
105
+
106
+ print_time $STEP_START
107
+ echo ""
108
+
109
+ # 总耗时
110
+ echo "构建完成"
111
+ print_time $TOTAL_START
112
+
113
+ # 输出产物信息
114
+ DIST_SIZE=$(du -sh "$OUT_DIR" | cut -f1)
115
+ NODE_MODULES_SIZE=$(du -sh "$OUT_DIR/node_modules" | cut -f1)
116
+ echo ""
117
+ echo "📊 构建产物统计:"
118
+ echo " 总大小: $DIST_SIZE"
119
+ echo " node_modules: $NODE_MODULES_SIZE"
120
+ echo ""
@@ -0,0 +1,295 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+ const { spawn, execSync } = require('child_process');
7
+ const readline = require('readline');
8
+
9
+ // ── Project root ──────────────────────────────────────────────────────────────
10
+ const PROJECT_ROOT = path.resolve(__dirname, '..');
11
+ process.chdir(PROJECT_ROOT);
12
+
13
+ // ── Load .env ─────────────────────────────────────────────────────────────────
14
+ function loadEnv() {
15
+ const envPath = path.join(PROJECT_ROOT, '.env');
16
+ if (!fs.existsSync(envPath)) return;
17
+ const lines = fs.readFileSync(envPath, 'utf8').split('\n');
18
+ for (const line of lines) {
19
+ const trimmed = line.trim();
20
+ if (!trimmed || trimmed.startsWith('#')) continue;
21
+ const eqIdx = trimmed.indexOf('=');
22
+ if (eqIdx === -1) continue;
23
+ const key = trimmed.slice(0, eqIdx).trim();
24
+ const value = trimmed.slice(eqIdx + 1).trim();
25
+ if (!(key in process.env)) {
26
+ process.env[key] = value;
27
+ }
28
+ }
29
+ }
30
+ loadEnv();
31
+
32
+ // ── Configuration ─────────────────────────────────────────────────────────────
33
+ const LOG_DIR = process.env.LOG_DIR || 'logs';
34
+ const MAX_RESTART_COUNT = process.env.MAX_RESTART_COUNT != null && process.env.MAX_RESTART_COUNT !== ''
35
+ ? parseInt(process.env.MAX_RESTART_COUNT, 10)
36
+ : Infinity;
37
+ const RESTART_DELAY = parseInt(process.env.RESTART_DELAY, 10) || 2;
38
+ const MAX_DELAY = 8;
39
+ const SERVER_PORT = process.env.SERVER_PORT || '3000';
40
+ const CLIENT_DEV_PORT = process.env.CLIENT_DEV_PORT || '8080';
41
+
42
+ fs.mkdirSync(LOG_DIR, { recursive: true });
43
+
44
+ // ── Logging infrastructure ────────────────────────────────────────────────────
45
+ const devStdLogPath = path.join(LOG_DIR, 'dev.std.log');
46
+ const devLogPath = path.join(LOG_DIR, 'dev.log');
47
+ const devStdLogFd = fs.openSync(devStdLogPath, 'a');
48
+ const devLogFd = fs.openSync(devLogPath, 'a');
49
+
50
+ function timestamp() {
51
+ const now = new Date();
52
+ return (
53
+ now.getFullYear() + '-' +
54
+ String(now.getMonth() + 1).padStart(2, '0') + '-' +
55
+ String(now.getDate()).padStart(2, '0') + ' ' +
56
+ String(now.getHours()).padStart(2, '0') + ':' +
57
+ String(now.getMinutes()).padStart(2, '0') + ':' +
58
+ String(now.getSeconds()).padStart(2, '0')
59
+ );
60
+ }
61
+
62
+ /** Write to terminal + dev.std.log */
63
+ function writeOutput(msg) {
64
+ try { process.stdout.write(msg); } catch {}
65
+ try { fs.writeSync(devStdLogFd, msg); } catch {}
66
+ }
67
+
68
+ /** Structured event log → terminal + dev.std.log + dev.log */
69
+ function logEvent(level, name, message) {
70
+ const msg = `[${timestamp()}] [${level}] [${name}] ${message}\n`;
71
+ writeOutput(msg);
72
+ try { fs.writeSync(devLogFd, msg); } catch {}
73
+ }
74
+
75
+ // ── Process group management ──────────────────────────────────────────────────
76
+ function killProcessGroup(pid, signal) {
77
+ try {
78
+ process.kill(-pid, signal);
79
+ } catch {}
80
+ }
81
+
82
+ function killOrphansByPort(port) {
83
+ try {
84
+ const pids = execSync(`lsof -ti :${port}`, { encoding: 'utf8', timeout: 5000 }).trim();
85
+ if (pids) {
86
+ const pidList = pids.split('\n').filter(Boolean);
87
+ for (const p of pidList) {
88
+ try { process.kill(parseInt(p, 10), 'SIGKILL'); } catch {}
89
+ }
90
+ return pidList;
91
+ }
92
+ } catch {}
93
+ return [];
94
+ }
95
+
96
+ // ── Process supervision ───────────────────────────────────────────────────────
97
+ let stopping = false;
98
+ const managedProcesses = []; // { name, pid, child }
99
+
100
+ function sleep(ms) {
101
+ return new Promise((resolve) => setTimeout(resolve, ms));
102
+ }
103
+
104
+ /**
105
+ * Start and supervise a process with auto-restart and log piping.
106
+ * Returns a promise that resolves when the process loop ends.
107
+ */
108
+ function startProcess({ name, command, args, cleanupPort }) {
109
+ const logFilePath = path.join(LOG_DIR, `${name}.std.log`);
110
+ const logFd = fs.openSync(logFilePath, 'a');
111
+
112
+ const entry = { name, pid: null, child: null };
113
+ managedProcesses.push(entry);
114
+
115
+ const run = async () => {
116
+ let restartCount = 0;
117
+
118
+ while (!stopping) {
119
+ const child = spawn(command, args, {
120
+ detached: true,
121
+ stdio: ['ignore', 'pipe', 'pipe'],
122
+ shell: true,
123
+ cwd: PROJECT_ROOT,
124
+ env: { ...process.env },
125
+ });
126
+
127
+ entry.pid = child.pid;
128
+ entry.child = child;
129
+
130
+ const startTime = Date.now();
131
+ logEvent('INFO', name, `Process started (PGID: ${child.pid}): ${command} ${args.join(' ')}`);
132
+
133
+ // Pipe stdout and stderr through readline for timestamped logging
134
+ const pipeLines = (stream) => {
135
+ const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });
136
+ rl.on('line', (line) => {
137
+ const msg = `[${timestamp()}] [${name}] ${line}\n`;
138
+ try { fs.writeSync(logFd, msg); } catch {}
139
+ writeOutput(msg);
140
+ });
141
+ };
142
+ if (child.stdout) pipeLines(child.stdout);
143
+ if (child.stderr) pipeLines(child.stderr);
144
+
145
+ // Wait for the direct child to exit.
146
+ // NOTE: must use 'exit', not 'close'. With shell:true, grandchild processes
147
+ // (e.g. nest's server) inherit stdout pipes. 'close' won't fire until ALL
148
+ // pipe holders exit, causing dev.js to hang when npm/nest dies but server survives.
149
+ const exitCode = await new Promise((resolve) => {
150
+ child.on('exit', (code) => resolve(code ?? 1));
151
+ child.on('error', () => resolve(1));
152
+ });
153
+
154
+ // Kill the entire process group
155
+ if (entry.pid) {
156
+ killProcessGroup(entry.pid, 'SIGTERM');
157
+ await sleep(2000);
158
+ killProcessGroup(entry.pid, 'SIGKILL');
159
+ }
160
+ entry.pid = null;
161
+ entry.child = null;
162
+
163
+ // Port cleanup fallback
164
+ if (cleanupPort) {
165
+ const orphans = killOrphansByPort(cleanupPort);
166
+ if (orphans.length > 0) {
167
+ logEvent('WARN', name, `Killed orphan processes on port ${cleanupPort}: ${orphans.join(' ')}`);
168
+ await sleep(500);
169
+ }
170
+ }
171
+
172
+ if (stopping) break;
173
+
174
+ const runDuration = (Date.now() - startTime) / 1000;
175
+ if (runDuration >= 60) {
176
+ restartCount = 0;
177
+ logEvent('INFO', name, `Ran for ${Math.round(runDuration)}s, resetting restart counter`);
178
+ } else {
179
+ restartCount++;
180
+ }
181
+ if (restartCount >= MAX_RESTART_COUNT) {
182
+ logEvent('ERROR', name, `Max restart count (${MAX_RESTART_COUNT}) reached, giving up`);
183
+ break;
184
+ }
185
+
186
+ const delay = Math.min(RESTART_DELAY * (1 << Math.max(0, restartCount - 1)), MAX_DELAY);
187
+ logEvent('WARN', name, `Process exited with code ${exitCode}, restarting (${restartCount}/${MAX_RESTART_COUNT}) in ${delay}s...`);
188
+ await sleep(delay * 1000);
189
+ }
190
+
191
+ try { fs.closeSync(logFd); } catch {}
192
+ };
193
+
194
+ return run();
195
+ }
196
+
197
+ // ── Cleanup ───────────────────────────────────────────────────────────────────
198
+ let cleanupDone = false;
199
+
200
+ async function cleanup() {
201
+ if (cleanupDone) return;
202
+ cleanupDone = true;
203
+ stopping = true;
204
+
205
+ logEvent('INFO', 'main', 'Shutting down all processes...');
206
+
207
+ // Kill all managed process groups
208
+ for (const entry of managedProcesses) {
209
+ if (entry.pid) {
210
+ logEvent('INFO', 'main', `Stopping process group (PGID: ${entry.pid})`);
211
+ killProcessGroup(entry.pid, 'SIGTERM');
212
+ }
213
+ }
214
+
215
+ // Wait for graceful shutdown
216
+ await sleep(2000);
217
+
218
+ // Force kill any remaining
219
+ for (const entry of managedProcesses) {
220
+ if (entry.pid) {
221
+ logEvent('WARN', 'main', `Force killing process group (PGID: ${entry.pid})`);
222
+ killProcessGroup(entry.pid, 'SIGKILL');
223
+ }
224
+ }
225
+
226
+ // Port cleanup fallback
227
+ killOrphansByPort(SERVER_PORT);
228
+ killOrphansByPort(CLIENT_DEV_PORT);
229
+
230
+ logEvent('INFO', 'main', 'All processes stopped');
231
+
232
+ try { fs.closeSync(devStdLogFd); } catch {}
233
+ try { fs.closeSync(devLogFd); } catch {}
234
+
235
+ process.exit(0);
236
+ }
237
+
238
+ process.on('SIGTERM', cleanup);
239
+ process.on('SIGINT', cleanup);
240
+ process.on('SIGHUP', cleanup);
241
+
242
+ // Stale dist makes nest --watch skip missing files; watcher won't self-heal.
243
+ function cleanStaleDist() {
244
+ const distPath = path.join(PROJECT_ROOT, 'dist');
245
+ if (fs.existsSync(distPath)) {
246
+ fs.rmSync(distPath, { recursive: true, force: true });
247
+ logEvent('INFO', 'main', 'Cleaned dist/ to force full rebuild');
248
+ }
249
+ }
250
+
251
+ // ── Main ──────────────────────────────────────────────────────────────────────
252
+ async function main() {
253
+ logEvent('INFO', 'main', '========== Dev session started ==========');
254
+
255
+ cleanStaleDist();
256
+
257
+ // Initialize action plugins
258
+ writeOutput('\n🔌 Initializing action plugins...\n');
259
+ try {
260
+ execSync('fullstack-cli action-plugin init', { cwd: PROJECT_ROOT, stdio: 'inherit' });
261
+ writeOutput('✅ Action plugins initialized\n\n');
262
+ } catch {
263
+ writeOutput('⚠️ Action plugin initialization failed, continuing anyway...\n\n');
264
+ }
265
+
266
+ // Start server and client
267
+ const serverPromise = startProcess({
268
+ name: 'server',
269
+ command: 'npm',
270
+ args: ['run', 'dev:server'],
271
+ cleanupPort: SERVER_PORT,
272
+ });
273
+
274
+ const clientPromise = startProcess({
275
+ name: 'client',
276
+ command: 'npm',
277
+ args: ['run', 'dev:client'],
278
+ cleanupPort: CLIENT_DEV_PORT,
279
+ });
280
+
281
+ writeOutput(`📋 Dev processes running. Press Ctrl+C to stop.\n`);
282
+ writeOutput(`📄 Logs: ${devStdLogPath}\n\n`);
283
+
284
+ // Wait for both (they loop until stopping or max restarts)
285
+ await Promise.all([serverPromise, clientPromise]);
286
+
287
+ if (!cleanupDone) {
288
+ await cleanup();
289
+ }
290
+ }
291
+
292
+ main().catch((err) => {
293
+ console.error('Fatal error:', err);
294
+ process.exit(1);
295
+ });
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env bash
2
+ exec node "$(dirname "$0")/dev.js" "$@"