@proofkit/cli 1.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 (317) hide show
  1. package/CHANGELOG.md +120 -0
  2. package/LICENSE.md +21 -0
  3. package/README.md +19 -0
  4. package/dist/acorn-AKFTBDM6.js +15 -0
  5. package/dist/angular-BOQ6FHSU.js +2 -0
  6. package/dist/babel-ZTOORN7K.js +15 -0
  7. package/dist/chunk-4LISTI44.js +1 -0
  8. package/dist/estree-KOJPX4S6.js +36 -0
  9. package/dist/flow-RCI44GYZ.js +19 -0
  10. package/dist/glimmer-GV5EF5E4.js +30 -0
  11. package/dist/graphql-YXQNPQWM.js +29 -0
  12. package/dist/html-ZAJTRROK.js +22 -0
  13. package/dist/index.js +300 -0
  14. package/dist/markdown-Q75DTQI7.js +63 -0
  15. package/dist/meriyah-32K7GBV5.js +4 -0
  16. package/dist/postcss-WWYO4PGL.js +54 -0
  17. package/dist/typescript-M6N7JDNQ.js +20 -0
  18. package/dist/yaml-LY7PNAYV.js +161 -0
  19. package/index.d.ts +19 -0
  20. package/package.json +122 -0
  21. package/template/extras/_cursor/conditional-rules/nextjs-framework.mdc +51 -0
  22. package/template/extras/_cursor/conditional-rules/npm.mdc +60 -0
  23. package/template/extras/_cursor/conditional-rules/pnpm.mdc +65 -0
  24. package/template/extras/_cursor/conditional-rules/yarn.mdc +60 -0
  25. package/template/extras/_cursor/rules/cursor-rules.mdc +88 -0
  26. package/template/extras/_cursor/rules/filemaker-api.mdc +176 -0
  27. package/template/extras/_cursor/rules/troubleshooting-patterns.mdc +240 -0
  28. package/template/extras/_cursor/rules/ui-components.mdc +57 -0
  29. package/template/extras/config/_eslint.js +27 -0
  30. package/template/extras/config/_prettier.config.js +6 -0
  31. package/template/extras/config/drizzle-config-mysql.ts +12 -0
  32. package/template/extras/config/drizzle-config-postgres.ts +12 -0
  33. package/template/extras/config/drizzle-config-sqlite.ts +12 -0
  34. package/template/extras/config/fmschema.config.mjs +9 -0
  35. package/template/extras/config/get-query-client.ts +6 -0
  36. package/template/extras/config/postcss.config.cjs +7 -0
  37. package/template/extras/config/query-provider-vite.tsx +19 -0
  38. package/template/extras/config/query-provider.tsx +21 -0
  39. package/template/extras/emailProviders/none/email.tsx +24 -0
  40. package/template/extras/emailProviders/plunk/email.tsx +26 -0
  41. package/template/extras/emailProviders/plunk/service.ts +4 -0
  42. package/template/extras/emailProviders/resend/email.tsx +23 -0
  43. package/template/extras/emailProviders/resend/service.ts +4 -0
  44. package/template/extras/fmaddon-auth/app/(main)/auth/profile/actions.ts +93 -0
  45. package/template/extras/fmaddon-auth/app/(main)/auth/profile/page.tsx +27 -0
  46. package/template/extras/fmaddon-auth/app/(main)/auth/profile/profile-form.tsx +56 -0
  47. package/template/extras/fmaddon-auth/app/(main)/auth/profile/reset-password-form.tsx +110 -0
  48. package/template/extras/fmaddon-auth/app/(main)/auth/profile/schema.ts +19 -0
  49. package/template/extras/fmaddon-auth/app/auth/forgot-password/actions.ts +37 -0
  50. package/template/extras/fmaddon-auth/app/auth/forgot-password/forgot-form.tsx +41 -0
  51. package/template/extras/fmaddon-auth/app/auth/forgot-password/page.tsx +21 -0
  52. package/template/extras/fmaddon-auth/app/auth/forgot-password/schema.ts +5 -0
  53. package/template/extras/fmaddon-auth/app/auth/login/actions.ts +34 -0
  54. package/template/extras/fmaddon-auth/app/auth/login/login-form.tsx +64 -0
  55. package/template/extras/fmaddon-auth/app/auth/login/page.tsx +26 -0
  56. package/template/extras/fmaddon-auth/app/auth/login/schema.ts +6 -0
  57. package/template/extras/fmaddon-auth/app/auth/reset-password/actions.ts +50 -0
  58. package/template/extras/fmaddon-auth/app/auth/reset-password/page.tsx +32 -0
  59. package/template/extras/fmaddon-auth/app/auth/reset-password/reset-password-form.tsx +59 -0
  60. package/template/extras/fmaddon-auth/app/auth/reset-password/schema.ts +14 -0
  61. package/template/extras/fmaddon-auth/app/auth/reset-password/verify-email/actions.ts +45 -0
  62. package/template/extras/fmaddon-auth/app/auth/reset-password/verify-email/page.tsx +32 -0
  63. package/template/extras/fmaddon-auth/app/auth/reset-password/verify-email/schema.ts +5 -0
  64. package/template/extras/fmaddon-auth/app/auth/reset-password/verify-email/verify-email-form.tsx +48 -0
  65. package/template/extras/fmaddon-auth/app/auth/signup/actions.ts +49 -0
  66. package/template/extras/fmaddon-auth/app/auth/signup/page.tsx +26 -0
  67. package/template/extras/fmaddon-auth/app/auth/signup/schema.ts +12 -0
  68. package/template/extras/fmaddon-auth/app/auth/signup/signup-form.tsx +67 -0
  69. package/template/extras/fmaddon-auth/app/auth/verify-email/actions.ts +110 -0
  70. package/template/extras/fmaddon-auth/app/auth/verify-email/email-verification-form.tsx +45 -0
  71. package/template/extras/fmaddon-auth/app/auth/verify-email/page.tsx +38 -0
  72. package/template/extras/fmaddon-auth/app/auth/verify-email/resend-button.tsx +35 -0
  73. package/template/extras/fmaddon-auth/app/auth/verify-email/schema.ts +5 -0
  74. package/template/extras/fmaddon-auth/components/auth/actions.ts +16 -0
  75. package/template/extras/fmaddon-auth/components/auth/protect.tsx +17 -0
  76. package/template/extras/fmaddon-auth/components/auth/redirect.tsx +26 -0
  77. package/template/extras/fmaddon-auth/components/auth/use-user.ts +59 -0
  78. package/template/extras/fmaddon-auth/components/auth/user-menu.tsx +51 -0
  79. package/template/extras/fmaddon-auth/emails/auth-code.tsx +156 -0
  80. package/template/extras/fmaddon-auth/middleware.ts +45 -0
  81. package/template/extras/fmaddon-auth/server/auth/utils/email-verification.ts +136 -0
  82. package/template/extras/fmaddon-auth/server/auth/utils/encryption.ts +51 -0
  83. package/template/extras/fmaddon-auth/server/auth/utils/index.ts +16 -0
  84. package/template/extras/fmaddon-auth/server/auth/utils/password-reset.ts +152 -0
  85. package/template/extras/fmaddon-auth/server/auth/utils/password.ts +67 -0
  86. package/template/extras/fmaddon-auth/server/auth/utils/redirect.ts +8 -0
  87. package/template/extras/fmaddon-auth/server/auth/utils/session.ts +192 -0
  88. package/template/extras/fmaddon-auth/server/auth/utils/user.ts +147 -0
  89. package/template/extras/prisma/schema/base-planetscale.prisma +24 -0
  90. package/template/extras/prisma/schema/base.prisma +20 -0
  91. package/template/extras/prisma/schema/with-auth-planetscale.prisma +77 -0
  92. package/template/extras/prisma/schema/with-auth.prisma +74 -0
  93. package/template/extras/src/app/_components/post-tw.tsx +50 -0
  94. package/template/extras/src/app/_components/post.tsx +54 -0
  95. package/template/extras/src/app/api/auth/[...nextauth]/route.ts +4 -0
  96. package/template/extras/src/app/api/trpc/[trpc]/route.ts +34 -0
  97. package/template/extras/src/app/clerk-auth/layout.tsx +10 -0
  98. package/template/extras/src/app/clerk-auth/signin/[[...sign-in]]/page.tsx +5 -0
  99. package/template/extras/src/app/clerk-auth/signup/[[...sign-up]]/page.tsx +5 -0
  100. package/template/extras/src/app/layout/base.tsx +34 -0
  101. package/template/extras/src/app/layout/main-shell.tsx +37 -0
  102. package/template/extras/src/app/layout/with-trpc-tw.tsx +24 -0
  103. package/template/extras/src/app/layout/with-trpc.tsx +24 -0
  104. package/template/extras/src/app/layout/with-tw.tsx +20 -0
  105. package/template/extras/src/app/next-auth/layout.tsx +22 -0
  106. package/template/extras/src/app/next-auth/signin/page.tsx +82 -0
  107. package/template/extras/src/app/next-auth/signup/action.ts +24 -0
  108. package/template/extras/src/app/next-auth/signup/page.tsx +40 -0
  109. package/template/extras/src/app/next-auth/signup/validation.ts +12 -0
  110. package/template/extras/src/app/page/base.tsx +6 -0
  111. package/template/extras/src/app/page/with-auth-trpc-tw.tsx +67 -0
  112. package/template/extras/src/app/page/with-auth-trpc.tsx +68 -0
  113. package/template/extras/src/app/page/with-trpc-tw.tsx +53 -0
  114. package/template/extras/src/app/page/with-trpc.tsx +54 -0
  115. package/template/extras/src/app/page/with-tw.tsx +37 -0
  116. package/template/extras/src/components/clerk-auth/clerk-provider.tsx +18 -0
  117. package/template/extras/src/components/clerk-auth/user-menu-mobile.tsx +36 -0
  118. package/template/extras/src/components/clerk-auth/user-menu.tsx +24 -0
  119. package/template/extras/src/components/next-auth/next-auth-provider.tsx +14 -0
  120. package/template/extras/src/components/next-auth/user-menu-mobile.tsx +31 -0
  121. package/template/extras/src/components/next-auth/user-menu.tsx +38 -0
  122. package/template/extras/src/env/with-auth.ts +31 -0
  123. package/template/extras/src/env/with-clerk.ts +20 -0
  124. package/template/extras/src/index.module.css +177 -0
  125. package/template/extras/src/middleware/clerk.ts +20 -0
  126. package/template/extras/src/middleware/next-auth.ts +5 -0
  127. package/template/extras/src/pages/_app/base.tsx +14 -0
  128. package/template/extras/src/pages/_app/with-auth-trpc-tw.tsx +23 -0
  129. package/template/extras/src/pages/_app/with-auth-trpc.tsx +23 -0
  130. package/template/extras/src/pages/_app/with-auth-tw.tsx +21 -0
  131. package/template/extras/src/pages/_app/with-auth.tsx +21 -0
  132. package/template/extras/src/pages/_app/with-trpc-tw.tsx +16 -0
  133. package/template/extras/src/pages/_app/with-trpc.tsx +16 -0
  134. package/template/extras/src/pages/_app/with-tw.tsx +14 -0
  135. package/template/extras/src/pages/api/auth/[...nextauth].ts +5 -0
  136. package/template/extras/src/pages/api/trpc/[trpc].ts +19 -0
  137. package/template/extras/src/pages/index/base.tsx +47 -0
  138. package/template/extras/src/pages/index/with-auth-trpc-tw.tsx +80 -0
  139. package/template/extras/src/pages/index/with-auth-trpc.tsx +81 -0
  140. package/template/extras/src/pages/index/with-trpc-tw.tsx +52 -0
  141. package/template/extras/src/pages/index/with-trpc.tsx +53 -0
  142. package/template/extras/src/pages/index/with-tw.tsx +45 -0
  143. package/template/extras/src/server/api/root.ts +23 -0
  144. package/template/extras/src/server/api/routers/post/base.ts +40 -0
  145. package/template/extras/src/server/api/routers/post/with-auth-drizzle.ts +39 -0
  146. package/template/extras/src/server/api/routers/post/with-auth-prisma.ts +41 -0
  147. package/template/extras/src/server/api/routers/post/with-auth.ts +37 -0
  148. package/template/extras/src/server/api/routers/post/with-drizzle.ts +30 -0
  149. package/template/extras/src/server/api/routers/post/with-prisma.ts +31 -0
  150. package/template/extras/src/server/api/trpc-app/base.ts +103 -0
  151. package/template/extras/src/server/api/trpc-app/with-auth-db.ts +133 -0
  152. package/template/extras/src/server/api/trpc-app/with-auth.ts +130 -0
  153. package/template/extras/src/server/api/trpc-app/with-db.ts +106 -0
  154. package/template/extras/src/server/api/trpc-pages/base.ts +122 -0
  155. package/template/extras/src/server/api/trpc-pages/with-auth-db.ts +160 -0
  156. package/template/extras/src/server/api/trpc-pages/with-auth.ts +158 -0
  157. package/template/extras/src/server/api/trpc-pages/with-db.ts +125 -0
  158. package/template/extras/src/server/data/users.ts +23 -0
  159. package/template/extras/src/server/db/db-prisma-planetscale.ts +22 -0
  160. package/template/extras/src/server/db/db-prisma.ts +17 -0
  161. package/template/extras/src/server/db/index-drizzle/with-mysql.ts +18 -0
  162. package/template/extras/src/server/db/index-drizzle/with-planetscale.ts +7 -0
  163. package/template/extras/src/server/db/index-drizzle/with-postgres.ts +18 -0
  164. package/template/extras/src/server/db/index-drizzle/with-sqlite.ts +19 -0
  165. package/template/extras/src/server/db/schema-drizzle/base-mysql.ts +34 -0
  166. package/template/extras/src/server/db/schema-drizzle/base-planetscale.ts +34 -0
  167. package/template/extras/src/server/db/schema-drizzle/base-postgres.ts +36 -0
  168. package/template/extras/src/server/db/schema-drizzle/base-sqlite.ts +30 -0
  169. package/template/extras/src/server/db/schema-drizzle/with-auth-mysql.ts +123 -0
  170. package/template/extras/src/server/db/schema-drizzle/with-auth-planetscale.ts +117 -0
  171. package/template/extras/src/server/db/schema-drizzle/with-auth-postgres.ts +130 -0
  172. package/template/extras/src/server/db/schema-drizzle/with-auth-sqlite.ts +116 -0
  173. package/template/extras/src/server/next-auth/base.ts +111 -0
  174. package/template/extras/src/server/next-auth/password.ts +13 -0
  175. package/template/extras/src/server/next-auth/with-drizzle.ts +83 -0
  176. package/template/extras/src/server/next-auth/with-prisma.ts +72 -0
  177. package/template/extras/src/trpc/query-client.ts +25 -0
  178. package/template/extras/src/trpc/react.tsx +76 -0
  179. package/template/extras/src/trpc/server.ts +30 -0
  180. package/template/extras/src/utils/api.ts +68 -0
  181. package/template/extras/start-database/mysql.sh +54 -0
  182. package/template/extras/start-database/postgres.sh +55 -0
  183. package/template/fm-addon/ProofKitAuth/de.xml +518 -0
  184. package/template/fm-addon/ProofKitAuth/en.xml +518 -0
  185. package/template/fm-addon/ProofKitAuth/es.xml +518 -0
  186. package/template/fm-addon/ProofKitAuth/fr.xml +518 -0
  187. package/template/fm-addon/ProofKitAuth/icon.png +0 -0
  188. package/template/fm-addon/ProofKitAuth/icon@2x.png +0 -0
  189. package/template/fm-addon/ProofKitAuth/info.json +11 -0
  190. package/template/fm-addon/ProofKitAuth/info_de.json +18 -0
  191. package/template/fm-addon/ProofKitAuth/info_en.json +8 -0
  192. package/template/fm-addon/ProofKitAuth/info_es.json +18 -0
  193. package/template/fm-addon/ProofKitAuth/info_fr.json +18 -0
  194. package/template/fm-addon/ProofKitAuth/info_it.json +18 -0
  195. package/template/fm-addon/ProofKitAuth/info_ja.json +18 -0
  196. package/template/fm-addon/ProofKitAuth/info_ko.json +18 -0
  197. package/template/fm-addon/ProofKitAuth/info_nl.json +18 -0
  198. package/template/fm-addon/ProofKitAuth/info_pt.json +18 -0
  199. package/template/fm-addon/ProofKitAuth/info_sv.json +18 -0
  200. package/template/fm-addon/ProofKitAuth/info_zh.json +18 -0
  201. package/template/fm-addon/ProofKitAuth/it.xml +518 -0
  202. package/template/fm-addon/ProofKitAuth/ja.xml +518 -0
  203. package/template/fm-addon/ProofKitAuth/ko.xml +518 -0
  204. package/template/fm-addon/ProofKitAuth/nl.xml +518 -0
  205. package/template/fm-addon/ProofKitAuth/preview.png +0 -0
  206. package/template/fm-addon/ProofKitAuth/pt.xml +518 -0
  207. package/template/fm-addon/ProofKitAuth/sv.xml +518 -0
  208. package/template/fm-addon/ProofKitAuth/template.xml +0 -0
  209. package/template/fm-addon/ProofKitAuth/zh.xml +518 -0
  210. package/template/fm-addon/ProofKitWV/de.xml +896 -0
  211. package/template/fm-addon/ProofKitWV/en.xml +896 -0
  212. package/template/fm-addon/ProofKitWV/es.xml +896 -0
  213. package/template/fm-addon/ProofKitWV/fr.xml +896 -0
  214. package/template/fm-addon/ProofKitWV/icon.png +0 -0
  215. package/template/fm-addon/ProofKitWV/icon@2x.png +0 -0
  216. package/template/fm-addon/ProofKitWV/info.json +11 -0
  217. package/template/fm-addon/ProofKitWV/info_de.json +18 -0
  218. package/template/fm-addon/ProofKitWV/info_en.json +11 -0
  219. package/template/fm-addon/ProofKitWV/info_es.json +18 -0
  220. package/template/fm-addon/ProofKitWV/info_fr.json +18 -0
  221. package/template/fm-addon/ProofKitWV/info_it.json +18 -0
  222. package/template/fm-addon/ProofKitWV/info_ja.json +18 -0
  223. package/template/fm-addon/ProofKitWV/info_ko.json +18 -0
  224. package/template/fm-addon/ProofKitWV/info_nl.json +18 -0
  225. package/template/fm-addon/ProofKitWV/info_pt.json +18 -0
  226. package/template/fm-addon/ProofKitWV/info_sv.json +18 -0
  227. package/template/fm-addon/ProofKitWV/info_zh.json +18 -0
  228. package/template/fm-addon/ProofKitWV/it.xml +896 -0
  229. package/template/fm-addon/ProofKitWV/ja.xml +896 -0
  230. package/template/fm-addon/ProofKitWV/ko.xml +896 -0
  231. package/template/fm-addon/ProofKitWV/nl.xml +896 -0
  232. package/template/fm-addon/ProofKitWV/preview.png +0 -0
  233. package/template/fm-addon/ProofKitWV/pt.xml +896 -0
  234. package/template/fm-addon/ProofKitWV/records_de.xml +0 -0
  235. package/template/fm-addon/ProofKitWV/records_en.xml +0 -0
  236. package/template/fm-addon/ProofKitWV/records_es.xml +0 -0
  237. package/template/fm-addon/ProofKitWV/records_fr.xml +0 -0
  238. package/template/fm-addon/ProofKitWV/records_it.xml +0 -0
  239. package/template/fm-addon/ProofKitWV/records_ja.xml +0 -0
  240. package/template/fm-addon/ProofKitWV/records_ko.xml +0 -0
  241. package/template/fm-addon/ProofKitWV/records_nl.xml +0 -0
  242. package/template/fm-addon/ProofKitWV/records_pt.xml +0 -0
  243. package/template/fm-addon/ProofKitWV/records_sv.xml +0 -0
  244. package/template/fm-addon/ProofKitWV/records_zh.xml +0 -0
  245. package/template/fm-addon/ProofKitWV/sv.xml +896 -0
  246. package/template/fm-addon/ProofKitWV/template.xml +0 -0
  247. package/template/fm-addon/ProofKitWV/zh.xml +896 -0
  248. package/template/nextjs/README.md +27 -0
  249. package/template/nextjs/_gitignore +37 -0
  250. package/template/nextjs/next.config.ts +12 -0
  251. package/template/nextjs/package.json +50 -0
  252. package/template/nextjs/postcss.config.cjs +14 -0
  253. package/template/nextjs/proofkit.json +1 -0
  254. package/template/nextjs/public/favicon.ico +0 -0
  255. package/template/nextjs/public/proofkit.png +0 -0
  256. package/template/nextjs/src/app/(main)/layout.tsx +6 -0
  257. package/template/nextjs/src/app/(main)/page.tsx +90 -0
  258. package/template/nextjs/src/app/layout.tsx +39 -0
  259. package/template/nextjs/src/app/navigation.tsx +12 -0
  260. package/template/nextjs/src/components/AppLogo.tsx +6 -0
  261. package/template/nextjs/src/components/AppShell/internal/AppShell.tsx +21 -0
  262. package/template/nextjs/src/components/AppShell/internal/Header.module.css +40 -0
  263. package/template/nextjs/src/components/AppShell/internal/Header.tsx +34 -0
  264. package/template/nextjs/src/components/AppShell/internal/HeaderMobileMenu.tsx +27 -0
  265. package/template/nextjs/src/components/AppShell/internal/HeaderNavLink.tsx +31 -0
  266. package/template/nextjs/src/components/AppShell/internal/config.ts +1 -0
  267. package/template/nextjs/src/components/AppShell/slot-header-center.tsx +13 -0
  268. package/template/nextjs/src/components/AppShell/slot-header-left.tsx +23 -0
  269. package/template/nextjs/src/components/AppShell/slot-header-mobile-content.tsx +43 -0
  270. package/template/nextjs/src/components/AppShell/slot-header-right.tsx +26 -0
  271. package/template/nextjs/src/config/env.ts +13 -0
  272. package/template/nextjs/src/config/theme/globals.css +1 -0
  273. package/template/nextjs/src/config/theme/mantine-theme.ts +22 -0
  274. package/template/nextjs/src/server/safe-action.ts +3 -0
  275. package/template/nextjs/src/utils/notification-helpers.ts +32 -0
  276. package/template/nextjs/tsconfig.json +40 -0
  277. package/template/pages/nextjs/blank/page.tsx +5 -0
  278. package/template/pages/nextjs/table/page.tsx +17 -0
  279. package/template/pages/nextjs/table/table.tsx +18 -0
  280. package/template/pages/nextjs/table-edit/actions.ts +23 -0
  281. package/template/pages/nextjs/table-edit/page.tsx +28 -0
  282. package/template/pages/nextjs/table-edit/schema.ts +4 -0
  283. package/template/pages/nextjs/table-edit/table.tsx +43 -0
  284. package/template/pages/nextjs/table-infinite/actions.ts +62 -0
  285. package/template/pages/nextjs/table-infinite/page.tsx +11 -0
  286. package/template/pages/nextjs/table-infinite/query.ts +44 -0
  287. package/template/pages/nextjs/table-infinite/table.tsx +107 -0
  288. package/template/pages/nextjs/table-infinite-edit/actions.ts +84 -0
  289. package/template/pages/nextjs/table-infinite-edit/page.tsx +23 -0
  290. package/template/pages/nextjs/table-infinite-edit/query.ts +81 -0
  291. package/template/pages/nextjs/table-infinite-edit/schema.ts +4 -0
  292. package/template/pages/nextjs/table-infinite-edit/table.tsx +130 -0
  293. package/template/pages/vite-wv/blank/index.tsx +0 -0
  294. package/template/pages/vite-wv/table/index.tsx +34 -0
  295. package/template/pages/vite-wv/table-edit/index.tsx +72 -0
  296. package/template/vite-wv/.vscode/settings.json +11 -0
  297. package/template/vite-wv/_gitignore +18 -0
  298. package/template/vite-wv/index.html +13 -0
  299. package/template/vite-wv/package.json +52 -0
  300. package/template/vite-wv/pnpm-lock.yaml +2294 -0
  301. package/template/vite-wv/postcss.config.cjs +14 -0
  302. package/template/vite-wv/proofkit.json +1 -0
  303. package/template/vite-wv/scripts/launch-fm.sh +3 -0
  304. package/template/vite-wv/scripts/upload.js +21 -0
  305. package/template/vite-wv/src/components/AppLogo.tsx +5 -0
  306. package/template/vite-wv/src/components/full-screen-loader.tsx +9 -0
  307. package/template/vite-wv/src/config/env.ts +16 -0
  308. package/template/vite-wv/src/config/theme/globals.css +1 -0
  309. package/template/vite-wv/src/config/theme/mantine-theme.ts +22 -0
  310. package/template/vite-wv/src/main.tsx +42 -0
  311. package/template/vite-wv/src/routeTree.gen.ts +111 -0
  312. package/template/vite-wv/src/routes/__root.tsx +21 -0
  313. package/template/vite-wv/src/routes/index.tsx +63 -0
  314. package/template/vite-wv/src/routes/secondary.tsx +28 -0
  315. package/template/vite-wv/src/utils/notification-helpers.ts +32 -0
  316. package/template/vite-wv/tsconfig.json +14 -0
  317. package/template/vite-wv/vite.config.ts +18 -0
@@ -0,0 +1,40 @@
1
+ {
2
+ "compilerOptions": {
3
+ "lib": [
4
+ "dom",
5
+ "dom.iterable",
6
+ "esnext"
7
+ ],
8
+ "allowJs": true,
9
+ "skipLibCheck": true,
10
+ "strict": true,
11
+ "noEmit": true,
12
+ "esModuleInterop": true,
13
+ "module": "esnext",
14
+ "moduleResolution": "bundler",
15
+ "resolveJsonModule": true,
16
+ "isolatedModules": true,
17
+ "jsx": "preserve",
18
+ "incremental": true,
19
+ "plugins": [
20
+ {
21
+ "name": "next"
22
+ }
23
+ ],
24
+ "paths": {
25
+ "@/*": [
26
+ "./src/*"
27
+ ]
28
+ },
29
+ "target": "ES2017"
30
+ },
31
+ "include": [
32
+ "next-env.d.ts",
33
+ "**/*.ts",
34
+ "**/*.tsx",
35
+ ".next/types/**/*.ts"
36
+ ],
37
+ "exclude": [
38
+ "node_modules"
39
+ ]
40
+ }
@@ -0,0 +1,5 @@
1
+ import React from "react";
2
+
3
+ export default function BlankPage() {
4
+ return <div>BlankPage</div>;
5
+ }
@@ -0,0 +1,17 @@
1
+ import { __CLIENT_NAME__ } from "@/config/schemas/__SOURCE_NAME__/client";
2
+ import { Stack } from "@mantine/core";
3
+ import React from "react";
4
+
5
+ import TableContent from "./table";
6
+
7
+ export default async function TablePage() {
8
+ // this function is limited to 100 records by default. To load more, see the other table templates from the docs
9
+ const { data } = await __CLIENT_NAME__.list({
10
+ fetch: { next: { revalidate: 60 } }, // only call the database at most once every 60 seconds
11
+ });
12
+ return (
13
+ <Stack>
14
+ <TableContent data={data.map((d) => d.fieldData)} />
15
+ </Stack>
16
+ );
17
+ }
@@ -0,0 +1,18 @@
1
+ "use client";
2
+
3
+ import { __TYPE_NAME__ } from "@/config/schemas/__SOURCE_NAME__/__SCHEMA_NAME__";
4
+ import {
5
+ MantineReactTable,
6
+ MRT_ColumnDef,
7
+ useMantineReactTable,
8
+ } from "mantine-react-table";
9
+ import React from "react";
10
+
11
+ type TData = __TYPE_NAME__;
12
+
13
+ const columns: MRT_ColumnDef<TData>[] = [];
14
+
15
+ export default function MyTable({ data }: { data: TData[] }) {
16
+ const table = useMantineReactTable({ data, columns });
17
+ return <MantineReactTable table={table} />;
18
+ }
@@ -0,0 +1,23 @@
1
+ "use server";
2
+
3
+ import { __CLIENT_NAME__ } from "@/config/schemas/__SOURCE_NAME__/client";
4
+ import { __ZOD_TYPE_NAME__ } from "@/config/schemas/__SOURCE_NAME__/__SCHEMA_NAME__";
5
+ import { __ACTION_CLIENT__ } from "@/server/safe-action";
6
+ import { idFieldName } from "./schema";
7
+
8
+ export const updateRecord = __ACTION_CLIENT__
9
+ .schema(__ZOD_TYPE_NAME__.partial())
10
+ .action(async ({ parsedInput }) => {
11
+ const id = parsedInput[idFieldName];
12
+ delete parsedInput[idFieldName]; // this ensures the id field value is not included in the updated fieldData
13
+ const data = parsedInput;
14
+
15
+ const {
16
+ data: { recordId },
17
+ } = await __CLIENT_NAME__.findOne({ query: { [idFieldName]: `==${id}` } });
18
+
19
+ return await __CLIENT_NAME__.update({
20
+ recordId,
21
+ fieldData: data,
22
+ });
23
+ });
@@ -0,0 +1,28 @@
1
+ import { __CLIENT_NAME__ } from "@/config/schemas/__SOURCE_NAME__/client";
2
+ import { Stack, Text, Code } from "@mantine/core";
3
+ import React from "react";
4
+
5
+ import TableContent from "./table";
6
+ import { idFieldName } from "./schema";
7
+
8
+ export default async function TablePage() {
9
+ // this function is limited to 100 records by default. To load more, see the other table templates from the docs
10
+ const { data } = await __CLIENT_NAME__.list({
11
+ fetch: { next: { revalidate: 60 } }, // only call the database at most once every 60 seconds
12
+ });
13
+ return (
14
+ <Stack>
15
+ <div>
16
+ <Text>
17
+ This table allows editing. Double-click on a cell to edit the value.
18
+ </Text>
19
+ <Text size="sm" c="dimmed">
20
+ NOTE: This feature requires a primary key field on your API layout. If your
21
+ primary key field is not <Code>{idFieldName}</Code>, update the
22
+ <Code>idFieldName</Code> variable in the <Code>schema.ts</Code> file.
23
+ </Text>
24
+ </div>
25
+ <TableContent data={data.map((d) => d.fieldData)} />
26
+ </Stack>
27
+ );
28
+ }
@@ -0,0 +1,4 @@
1
+ import { type __TYPE_NAME__ } from "@/config/schemas/__SOURCE_NAME__/__SCHEMA_NAME__";
2
+
3
+ // TODO: Make sure this variable is properly set to your primary key field
4
+ export const idFieldName: keyof __TYPE_NAME__ = "__FIRST_FIELD_NAME__";
@@ -0,0 +1,43 @@
1
+ "use client";
2
+
3
+ import { type __TYPE_NAME__ } from "@/config/schemas/__SOURCE_NAME__/__SCHEMA_NAME__";
4
+ import {
5
+ MantineReactTable,
6
+ type MRT_Cell,
7
+ type MRT_ColumnDef,
8
+ useMantineReactTable,
9
+ } from "mantine-react-table";
10
+ import React from "react";
11
+ import { updateRecord } from "./actions";
12
+ import { showErrorNotification } from "@/utils/notification-helpers";
13
+ import { idFieldName } from "./schema";
14
+
15
+ type TData = __TYPE_NAME__;
16
+
17
+ const columns: MRT_ColumnDef<TData>[] = [];
18
+
19
+ async function handleSaveCell(cell: MRT_Cell<TData>, value: unknown) {
20
+ const resp = await updateRecord({
21
+ [idFieldName]: cell.row.id,
22
+ [cell.column.id]: value,
23
+ });
24
+ if (!resp?.data) {
25
+ showErrorNotification("Failed to update record");
26
+ }
27
+ }
28
+
29
+ export default function MyTable({ data }: { data: TData[] }) {
30
+ const table = useMantineReactTable({
31
+ data,
32
+ columns,
33
+ enableEditing: true,
34
+ editDisplayMode: "cell",
35
+ getRowId: (row) => row[idFieldName],
36
+ mantineEditTextInputProps: ({ cell }) => ({
37
+ //onBlur is more efficient, but could use onChange instead
38
+ onBlur: (event) => {
39
+ handleSaveCell(cell, event.target.value);
40
+ },
41
+ }),
42
+ }); return <MantineReactTable table={table} />;
43
+ }
@@ -0,0 +1,62 @@
1
+ "use server";
2
+
3
+ import { __TYPE_NAME__ } from "@/config/schemas/__SOURCE_NAME__/__SCHEMA_NAME__";
4
+ import { __CLIENT_NAME__ } from "@/config/schemas/__SOURCE_NAME__/client";
5
+ import { __ACTION_CLIENT__ } from "@/server/safe-action";
6
+ import { ListParams, Query } from "@proofkit/fmdapi/dist/client-types.js";
7
+ import dayjs from "dayjs";
8
+ import { z } from "zod/v4";
9
+
10
+ const limit = 50; // raise or lower this number depending on how your layout performs
11
+ export const fetchData = __ACTION_CLIENT__
12
+ .schema(
13
+ z.object({
14
+ offset: z.number().catch(0),
15
+ sorting: z.array(
16
+ z.object({ id: z.string(), desc: z.boolean().default(false) })
17
+ ),
18
+ columnFilters: z.array(z.object({ id: z.string(), value: z.unknown() })),
19
+ })
20
+ )
21
+ .action(async ({ parsedInput: { offset, sorting, columnFilters } }) => {
22
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
23
+ const getOptions: ListParams<__TYPE_NAME__, any> & {
24
+ query: Query<__TYPE_NAME__>[];
25
+ } = {
26
+ limit,
27
+ offset,
28
+ query: [{ ["__FIRST_FIELD_NAME__"]: "*" }],
29
+ };
30
+
31
+ if (sorting.length > 0) {
32
+ getOptions.sort = sorting.map(({ id, desc }) => ({
33
+ fieldName: id as keyof __TYPE_NAME__,
34
+ sortOrder: desc ? "descend" : "ascend",
35
+ }));
36
+ }
37
+
38
+ if (columnFilters.length > 0) {
39
+ getOptions.query = columnFilters
40
+ .map(({ id, value }) => {
41
+ if (typeof value === "string") {
42
+ return {
43
+ [id]: value,
44
+ };
45
+ } else if (typeof value === "object" && value instanceof Date) {
46
+ return {
47
+ [id]: dayjs(value).format("YYYY+MM+DD"),
48
+ };
49
+ }
50
+ return null;
51
+ })
52
+ .filter(Boolean) as Query<any>[];
53
+ }
54
+
55
+ const data = await __CLIENT_NAME__.find(getOptions);
56
+
57
+ return {
58
+ data: data.data,
59
+ hasNextPage: data.dataInfo.foundCount > limit + offset,
60
+ totalCount: data.dataInfo.foundCount,
61
+ };
62
+ });
@@ -0,0 +1,11 @@
1
+ import { Stack } from "@mantine/core";
2
+
3
+ import MyTable from "./table";
4
+
5
+ export default async function TablePage() {
6
+ return (
7
+ <Stack>
8
+ <MyTable />
9
+ </Stack>
10
+ );
11
+ }
@@ -0,0 +1,44 @@
1
+ "use client";
2
+
3
+ import { useInfiniteQuery } from "@tanstack/react-query";
4
+ import { fetchData } from "./actions";
5
+ import { useMemo } from "react";
6
+ import type {
7
+ MRT_SortingState,
8
+ MRT_ColumnFiltersState,
9
+ } from "mantine-react-table";
10
+
11
+ export function useAllData({
12
+ sorting,
13
+ columnFilters,
14
+ }: {
15
+ sorting: MRT_SortingState;
16
+ columnFilters: MRT_ColumnFiltersState;
17
+ }) {
18
+ // useInfiniteQuery is used to help with automatic pagination
19
+ const qr = useInfiniteQuery({
20
+ queryKey: ["all-__SCHEMA_NAME__", sorting, columnFilters],
21
+ queryFn: async ({ pageParam: offset }) => {
22
+ const result = await fetchData({ offset, sorting, columnFilters });
23
+ if (!result) throw new Error(`Failed to fetch __SCHEMA_NAME__`);
24
+ if (!result.data) throw new Error(`No data found for __SCHEMA_NAME__`);
25
+ return result?.data;
26
+ },
27
+ retry: false,
28
+ initialPageParam: 0,
29
+ getNextPageParam: (lastPage, pages) =>
30
+ lastPage.hasNextPage
31
+ ? pages.flatMap((page) => page.data).length
32
+ : undefined,
33
+ });
34
+
35
+ const flatData = useMemo(
36
+ () =>
37
+ qr.data?.pages.flatMap((page) => page.data).map((o) => o.fieldData) ?? [],
38
+ [qr.data]
39
+ );
40
+ const totalFetched = flatData.length;
41
+ const totalDBRowCount = qr.data?.pages?.[0]?.totalCount ?? 0;
42
+
43
+ return { ...qr, data: flatData, totalDBRowCount, totalFetched };
44
+ }
@@ -0,0 +1,107 @@
1
+ "use client";
2
+
3
+ import { __TYPE_NAME__ } from "@/config/schemas/__SOURCE_NAME__/__SCHEMA_NAME__";
4
+ import {
5
+ createMRTColumnHelper,
6
+ MantineReactTable,
7
+ MRT_ColumnDef,
8
+ MRT_ColumnFiltersState,
9
+ MRT_RowVirtualizer,
10
+ MRT_SortingState,
11
+ useMantineReactTable,
12
+ } from "mantine-react-table";
13
+ import React, {
14
+ type UIEvent,
15
+ useCallback,
16
+ useEffect,
17
+ useRef,
18
+ useState,
19
+ } from "react";
20
+ import { useAllData } from "./query";
21
+ import { Text } from "@mantine/core";
22
+
23
+ type TData = __TYPE_NAME__;
24
+
25
+ const columns: MRT_ColumnDef<TData>[] = [];
26
+
27
+ export default function MyTable() {
28
+ const tableContainerRef = useRef<HTMLDivElement>(null);
29
+ const rowVirtualizerInstanceRef =
30
+ useRef<MRT_RowVirtualizer<HTMLDivElement, HTMLTableRowElement>>(null);
31
+
32
+ const [sorting, setSorting] = useState<MRT_SortingState>([]);
33
+ const [columnFilters, setColumnFilters] = useState<MRT_ColumnFiltersState>(
34
+ []
35
+ );
36
+
37
+ const {
38
+ data,
39
+ totalDBRowCount,
40
+ totalFetched,
41
+ isLoading,
42
+ isFetching,
43
+ fetchNextPage,
44
+ } = useAllData({ sorting, columnFilters });
45
+
46
+ const table = useMantineReactTable({
47
+ data,
48
+ columns,
49
+ rowCount: totalDBRowCount,
50
+ enableRowVirtualization: true, // only render the rows that are visible on screen to improve performance
51
+ state: { isLoading, sorting, showProgressBars: isFetching, columnFilters },
52
+ enableGlobalFilter: false, // doesn't work as easily with server-side filters, it's better to filter the specific columns
53
+ onSortingChange: setSorting,
54
+ onColumnFiltersChange: setColumnFilters,
55
+ enablePagination: false, // hide pagination buttons
56
+ enableStickyHeader: true,
57
+ mantineBottomToolbarProps: { style: { alignItems: "center" } },
58
+ renderBottomToolbarCustomActions: () =>
59
+ !isLoading ? (
60
+ <Text px="sm">
61
+ Fetched {totalFetched} of {totalDBRowCount}
62
+ </Text>
63
+ ) : null,
64
+ mantineTableContainerProps: ({ table }) => {
65
+ return {
66
+ h: table.getState().isFullScreen
67
+ ? "100%"
68
+ : `calc(100vh - var(--app-shell-header-height) - 10rem)`, // may need to adjust this height if you have more elements on your page
69
+ ref: tableContainerRef,
70
+ onScroll: (
71
+ event: UIEvent<HTMLDivElement> //add an event listener to the table container element
72
+ ) => fetchMoreOnBottomReached(event.target as HTMLDivElement),
73
+ };
74
+ },
75
+ });
76
+
77
+ // called on scroll and possibly on mount to fetch more data as the user scrolls and reaches bottom of table
78
+ const fetchMoreOnBottomReached = useCallback(
79
+ (containerRefElement?: HTMLDivElement | null) => {
80
+ if (containerRefElement) {
81
+ const { scrollHeight, scrollTop, clientHeight } = containerRefElement;
82
+ // once the user has scrolled within 400px of the bottom of the table, fetch more data
83
+ if (
84
+ scrollHeight - scrollTop - clientHeight < 400 &&
85
+ !isFetching &&
86
+ totalFetched < totalDBRowCount
87
+ ) {
88
+ void fetchNextPage();
89
+ }
90
+ }
91
+ },
92
+ [fetchNextPage, isFetching, totalFetched, totalDBRowCount]
93
+ );
94
+
95
+ // scroll to top of table when sorting or filters change
96
+ useEffect(() => {
97
+ if (rowVirtualizerInstanceRef.current) {
98
+ try {
99
+ rowVirtualizerInstanceRef.current.scrollToIndex(0);
100
+ } catch (e) {
101
+ console.error(e);
102
+ }
103
+ }
104
+ }, [sorting, columnFilters]);
105
+
106
+ return <MantineReactTable table={table} />;
107
+ }
@@ -0,0 +1,84 @@
1
+ "use server";
2
+
3
+ import {
4
+ __TYPE_NAME__,
5
+ __ZOD_TYPE_NAME__,
6
+ } from "@/config/schemas/__SOURCE_NAME__/__SCHEMA_NAME__";
7
+ import { __CLIENT_NAME__ } from "@/config/schemas/__SOURCE_NAME__/client";
8
+ import { __ACTION_CLIENT__ } from "@/server/safe-action";
9
+ import { ListParams, Query } from "@proofkit/fmdapi/dist/client-types.js";
10
+ import dayjs from "dayjs";
11
+ import { z } from "zod/v4";
12
+
13
+ import { idFieldName } from "./schema";
14
+
15
+ const limit = 50; // raise or lower this number depending on how your layout performs
16
+ export const fetchData = __ACTION_CLIENT__
17
+ .schema(
18
+ z.object({
19
+ offset: z.number().catch(0),
20
+ sorting: z.array(
21
+ z.object({ id: z.string(), desc: z.boolean().default(false) })
22
+ ),
23
+ columnFilters: z.array(z.object({ id: z.string(), value: z.unknown() })),
24
+ })
25
+ )
26
+ .action(async ({ parsedInput: { offset, sorting, columnFilters } }) => {
27
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
+ const getOptions: ListParams<__TYPE_NAME__, any> & {
29
+ query: Query<__TYPE_NAME__>[];
30
+ } = {
31
+ limit,
32
+ offset,
33
+ query: [{ ["__FIRST_FIELD_NAME__"]: "*" }],
34
+ };
35
+
36
+ if (sorting.length > 0) {
37
+ getOptions.sort = sorting.map(({ id, desc }) => ({
38
+ fieldName: id as keyof __TYPE_NAME__,
39
+ sortOrder: desc ? "descend" : "ascend",
40
+ }));
41
+ }
42
+
43
+ if (columnFilters.length > 0) {
44
+ getOptions.query = columnFilters
45
+ .map(({ id, value }) => {
46
+ if (typeof value === "string") {
47
+ return {
48
+ [id]: value,
49
+ };
50
+ } else if (typeof value === "object" && value instanceof Date) {
51
+ return {
52
+ [id]: dayjs(value).format("YYYY+MM+DD"),
53
+ };
54
+ }
55
+ return null;
56
+ })
57
+ .filter(Boolean) as Query<any>[];
58
+ }
59
+
60
+ const data = await __CLIENT_NAME__.find(getOptions);
61
+
62
+ return {
63
+ data: data.data,
64
+ hasNextPage: data.dataInfo.foundCount > limit + offset,
65
+ totalCount: data.dataInfo.foundCount,
66
+ };
67
+ });
68
+
69
+ export const updateRecord = __ACTION_CLIENT__
70
+ .schema(__ZOD_TYPE_NAME__.partial())
71
+ .action(async ({ parsedInput }) => {
72
+ const id = parsedInput[idFieldName];
73
+ delete parsedInput[idFieldName]; // this ensures the id field value is not included in the updated fieldData
74
+ const data = parsedInput;
75
+
76
+ const {
77
+ data: { recordId },
78
+ } = await __CLIENT_NAME__.findOne({ query: { [idFieldName]: `==${id}` } });
79
+
80
+ return await __CLIENT_NAME__.update({
81
+ recordId,
82
+ fieldData: data,
83
+ });
84
+ });
@@ -0,0 +1,23 @@
1
+ import { Stack, Text, Code } from "@mantine/core";
2
+ import React from "react";
3
+
4
+ import TableContent from "./table";
5
+ import { idFieldName } from "./schema";
6
+
7
+ export default async function TablePage() {
8
+ return (
9
+ <Stack>
10
+ <div>
11
+ <Text>
12
+ This table allows editing. Double-click on a cell to edit the value.
13
+ </Text>
14
+ <Text size="sm" c="dimmed">
15
+ NOTE: This feature requires a primary key field on your API layout. If your
16
+ primary key field is not <Code>{idFieldName}</Code>, update the
17
+ <Code>idFieldName</Code> variable in the <Code>schema.ts</Code> file.
18
+ </Text>
19
+ </div>
20
+ <TableContent />
21
+ </Stack>
22
+ );
23
+ }
@@ -0,0 +1,81 @@
1
+ "use client";
2
+
3
+ import { showErrorNotification } from "@/utils/notification-helpers";
4
+ import {
5
+ useInfiniteQuery,
6
+ useMutation,
7
+ useQueryClient,
8
+ } from "@tanstack/react-query";
9
+ import type {
10
+ MRT_ColumnFiltersState,
11
+ MRT_SortingState,
12
+ } from "mantine-react-table";
13
+ import { useMemo } from "react";
14
+
15
+ import { fetchData, updateRecord } from "./actions";
16
+ import { idFieldName } from "./schema";
17
+
18
+ export function useAllData({
19
+ sorting,
20
+ columnFilters,
21
+ }: {
22
+ sorting: MRT_SortingState;
23
+ columnFilters: MRT_ColumnFiltersState;
24
+ }) {
25
+ const queryKey = ["all-__SCHEMA_NAME__", sorting, columnFilters];
26
+ // useInfiniteQuery is used to help with automatic pagination
27
+ const qr = useInfiniteQuery({
28
+ queryKey,
29
+ queryFn: async ({ pageParam: offset }) => {
30
+ const result = await fetchData({ offset, sorting, columnFilters });
31
+ if (!result) throw new Error(`Failed to fetch __SCHEMA_NAME__`);
32
+ if (!result.data) throw new Error(`No data found for __SCHEMA_NAME__`);
33
+ return result?.data;
34
+ },
35
+ retry: false,
36
+ initialPageParam: 0,
37
+ getNextPageParam: (lastPage, pages) =>
38
+ lastPage.hasNextPage
39
+ ? pages.flatMap((page) => page.data).length
40
+ : undefined,
41
+ });
42
+
43
+ const flatData = useMemo(
44
+ () =>
45
+ qr.data?.pages.flatMap((page) => page.data).map((o) => o.fieldData) ?? [],
46
+ [qr.data]
47
+ );
48
+ const totalFetched = flatData.length;
49
+ const totalDBRowCount = qr.data?.pages?.[0]?.totalCount ?? 0;
50
+
51
+ const queryClient = useQueryClient();
52
+
53
+ const updateRecordMutation = useMutation({
54
+ mutationFn: updateRecord,
55
+ onMutate: async (newRecord) => {
56
+ // Cancel any outgoing refetches
57
+ await queryClient.cancelQueries({ queryKey });
58
+
59
+ // Optimistically update to the new value
60
+ queryClient.setQueryData<typeof qr.data>(queryKey, (old) => {
61
+ if (!old) return old;
62
+ return {
63
+ ...old,
64
+ pages: old.pages.map((page) => ({
65
+ ...page,
66
+ data: page.data.map((row) =>
67
+ row.fieldData[idFieldName] === newRecord[idFieldName]
68
+ ? { ...row, fieldData: { ...row.fieldData, ...newRecord } }
69
+ : row,
70
+ ),
71
+ })),
72
+ };
73
+ });
74
+ },
75
+ onError: () => {
76
+ showErrorNotification("Failed to update record");
77
+ },
78
+ });
79
+
80
+ return { ...qr, data: flatData, totalDBRowCount, totalFetched, updateRecord: updateRecordMutation.mutate };
81
+ }
@@ -0,0 +1,4 @@
1
+ import { type __TYPE_NAME__ } from "@/config/schemas/__SOURCE_NAME__/__SCHEMA_NAME__";
2
+
3
+ // TODO: Make sure this variable is properly set to your primary key field
4
+ export const idFieldName: keyof __TYPE_NAME__ = "__FIRST_FIELD_NAME__";