@nextsparkjs/core 0.1.0-beta.92 → 0.1.0-beta.94

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 (341) hide show
  1. package/dist/components/dashboard/block-editor/array-field.d.ts.map +1 -1
  2. package/dist/components/dashboard/block-editor/array-field.js +55 -3
  3. package/dist/components/dashboard/block-editor/dynamic-form.d.ts.map +1 -1
  4. package/dist/components/dashboard/block-editor/dynamic-form.js +82 -2
  5. package/dist/components/dashboard/navigation/DynamicNavigation.d.ts.map +1 -1
  6. package/dist/components/dashboard/navigation/DynamicNavigation.js +7 -1
  7. package/dist/components/devtools/scheduled-actions/actions-table.d.ts +1 -0
  8. package/dist/components/devtools/scheduled-actions/actions-table.d.ts.map +1 -1
  9. package/dist/components/devtools/scheduled-actions/actions-table.js +182 -46
  10. package/dist/components/devtools/scheduled-actions/types.d.ts +1 -0
  11. package/dist/components/devtools/scheduled-actions/types.d.ts.map +1 -1
  12. package/dist/components/media/MediaCard.d.ts +23 -0
  13. package/dist/components/media/MediaCard.d.ts.map +1 -0
  14. package/dist/components/media/MediaCard.js +154 -0
  15. package/dist/components/media/MediaDetailPanel.d.ts +17 -0
  16. package/dist/components/media/MediaDetailPanel.d.ts.map +1 -0
  17. package/dist/components/media/MediaDetailPanel.js +331 -0
  18. package/dist/components/media/MediaGrid.d.ts +26 -0
  19. package/dist/components/media/MediaGrid.d.ts.map +1 -0
  20. package/dist/components/media/MediaGrid.js +77 -0
  21. package/dist/components/media/MediaLibrary.d.ts +20 -0
  22. package/dist/components/media/MediaLibrary.d.ts.map +1 -0
  23. package/dist/components/media/MediaLibrary.js +229 -0
  24. package/dist/components/media/MediaList.d.ts +24 -0
  25. package/dist/components/media/MediaList.d.ts.map +1 -0
  26. package/dist/components/media/MediaList.js +181 -0
  27. package/dist/components/media/MediaSelector.d.ts +19 -0
  28. package/dist/components/media/MediaSelector.d.ts.map +1 -0
  29. package/dist/components/media/MediaSelector.js +145 -0
  30. package/dist/components/media/MediaTagFilter.d.ts +16 -0
  31. package/dist/components/media/MediaTagFilter.d.ts.map +1 -0
  32. package/dist/components/media/MediaTagFilter.js +122 -0
  33. package/dist/components/media/MediaToolbar.d.ts +25 -0
  34. package/dist/components/media/MediaToolbar.d.ts.map +1 -0
  35. package/dist/components/media/MediaToolbar.js +136 -0
  36. package/dist/components/media/MediaUploadZone.d.ts +19 -0
  37. package/dist/components/media/MediaUploadZone.d.ts.map +1 -0
  38. package/dist/components/media/MediaUploadZone.js +248 -0
  39. package/dist/components/media/index.d.ts +15 -0
  40. package/dist/components/media/index.d.ts.map +1 -0
  41. package/dist/components/media/index.js +20 -0
  42. package/dist/contexts/TeamContext.js +1 -1
  43. package/dist/hooks/index.d.ts +2 -0
  44. package/dist/hooks/index.d.ts.map +1 -1
  45. package/dist/hooks/index.js +2 -0
  46. package/dist/hooks/useEnsureUserMetadata.d.ts +4 -0
  47. package/dist/hooks/useEnsureUserMetadata.d.ts.map +1 -1
  48. package/dist/hooks/useEnsureUserMetadata.js +85 -60
  49. package/dist/hooks/useEntityMutations.d.ts.map +1 -1
  50. package/dist/hooks/useEntityMutations.js +5 -9
  51. package/dist/hooks/useMedia.d.ts +56 -0
  52. package/dist/hooks/useMedia.d.ts.map +1 -0
  53. package/dist/hooks/useMedia.js +181 -0
  54. package/dist/hooks/useMediaUpload.d.ts +27 -0
  55. package/dist/hooks/useMediaUpload.d.ts.map +1 -0
  56. package/dist/hooks/useMediaUpload.js +36 -0
  57. package/dist/hooks/useUserSettings.d.ts +5 -4
  58. package/dist/hooks/useUserSettings.d.ts.map +1 -1
  59. package/dist/hooks/useUserSettings.js +42 -40
  60. package/dist/index.d.ts +1 -1
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/index.js +2 -3
  63. package/dist/lib/api/auth/dual-auth.d.ts +6 -2
  64. package/dist/lib/api/auth/dual-auth.d.ts.map +1 -1
  65. package/dist/lib/api/auth/dual-auth.js +5 -9
  66. package/dist/lib/api/entity/generic-handler.d.ts.map +1 -1
  67. package/dist/lib/api/entity/generic-handler.js +3 -3
  68. package/dist/lib/config/app.config.d.ts.map +1 -1
  69. package/dist/lib/config/app.config.js +37 -0
  70. package/dist/lib/config/config-sync.d.ts +1 -0
  71. package/dist/lib/config/config-sync.d.ts.map +1 -1
  72. package/dist/lib/config/config-sync.js +2 -0
  73. package/dist/lib/config/types.d.ts +29 -0
  74. package/dist/lib/config/types.d.ts.map +1 -1
  75. package/dist/lib/media/schemas.d.ts +39 -0
  76. package/dist/lib/media/schemas.d.ts.map +1 -0
  77. package/dist/lib/media/schemas.js +32 -0
  78. package/dist/lib/media/types.d.ts +69 -0
  79. package/dist/lib/media/types.d.ts.map +1 -0
  80. package/dist/lib/media/types.js +0 -0
  81. package/dist/lib/media/utils.d.ts +26 -0
  82. package/dist/lib/media/utils.d.ts.map +1 -0
  83. package/dist/lib/media/utils.js +33 -0
  84. package/dist/lib/rate-limit-redis.d.ts.map +1 -1
  85. package/dist/lib/rate-limit-redis.js +13 -4
  86. package/dist/lib/scheduled-actions/initializer.d.ts +6 -3
  87. package/dist/lib/scheduled-actions/initializer.d.ts.map +1 -1
  88. package/dist/lib/scheduled-actions/initializer.js +11 -6
  89. package/dist/lib/scheduled-actions/processor.d.ts +20 -4
  90. package/dist/lib/scheduled-actions/processor.d.ts.map +1 -1
  91. package/dist/lib/scheduled-actions/processor.js +128 -34
  92. package/dist/lib/scheduled-actions/registry.d.ts +3 -0
  93. package/dist/lib/scheduled-actions/registry.d.ts.map +1 -1
  94. package/dist/lib/scheduled-actions/registry.js +2 -1
  95. package/dist/lib/scheduled-actions/scheduler.d.ts +1 -1
  96. package/dist/lib/scheduled-actions/scheduler.d.ts.map +1 -1
  97. package/dist/lib/scheduled-actions/scheduler.js +76 -38
  98. package/dist/lib/scheduled-actions/types.d.ts +73 -0
  99. package/dist/lib/scheduled-actions/types.d.ts.map +1 -1
  100. package/dist/lib/selectors/core-selectors.d.ts +102 -0
  101. package/dist/lib/selectors/core-selectors.d.ts.map +1 -1
  102. package/dist/lib/selectors/core-selectors.js +3 -1
  103. package/dist/lib/selectors/domains/block-editor.selectors.d.ts +8 -0
  104. package/dist/lib/selectors/domains/block-editor.selectors.d.ts.map +1 -1
  105. package/dist/lib/selectors/domains/block-editor.selectors.js +9 -0
  106. package/dist/lib/selectors/domains/devtools.selectors.d.ts +6 -0
  107. package/dist/lib/selectors/domains/devtools.selectors.d.ts.map +1 -1
  108. package/dist/lib/selectors/domains/devtools.selectors.js +6 -0
  109. package/dist/lib/selectors/domains/index.d.ts +1 -0
  110. package/dist/lib/selectors/domains/index.d.ts.map +1 -1
  111. package/dist/lib/selectors/domains/index.js +2 -0
  112. package/dist/lib/selectors/domains/media.selectors.d.ts +96 -0
  113. package/dist/lib/selectors/domains/media.selectors.d.ts.map +1 -0
  114. package/dist/lib/selectors/domains/media.selectors.js +103 -0
  115. package/dist/lib/selectors/selectors.d.ts +204 -0
  116. package/dist/lib/selectors/selectors.d.ts.map +1 -1
  117. package/dist/lib/services/index.d.ts +2 -0
  118. package/dist/lib/services/index.d.ts.map +1 -1
  119. package/dist/lib/services/index.js +2 -0
  120. package/dist/lib/services/media.service.d.ts +158 -0
  121. package/dist/lib/services/media.service.d.ts.map +1 -0
  122. package/dist/lib/services/media.service.js +410 -0
  123. package/dist/messages/de/devtools.json +16 -0
  124. package/dist/messages/de/index.d.ts +16 -0
  125. package/dist/messages/de/index.d.ts.map +1 -1
  126. package/dist/messages/en/admin.json +4 -1
  127. package/dist/messages/en/devtools.json +16 -0
  128. package/dist/messages/en/index.d.ts +167 -0
  129. package/dist/messages/en/index.d.ts.map +1 -1
  130. package/dist/messages/en/index.js +2 -0
  131. package/dist/messages/en/index.ts +2 -0
  132. package/dist/messages/en/media.json +147 -0
  133. package/dist/messages/en/navigation.json +1 -0
  134. package/dist/messages/es/admin.json +4 -1
  135. package/dist/messages/es/devtools.json +16 -0
  136. package/dist/messages/es/index.d.ts +167 -0
  137. package/dist/messages/es/index.d.ts.map +1 -1
  138. package/dist/messages/es/index.js +2 -0
  139. package/dist/messages/es/index.ts +2 -0
  140. package/dist/messages/es/media.json +147 -0
  141. package/dist/messages/es/navigation.json +1 -0
  142. package/dist/messages/fr/devtools.json +16 -0
  143. package/dist/messages/fr/index.d.ts +16 -0
  144. package/dist/messages/fr/index.d.ts.map +1 -1
  145. package/dist/messages/it/devtools.json +16 -0
  146. package/dist/messages/it/index.d.ts +16 -0
  147. package/dist/messages/it/index.d.ts.map +1 -1
  148. package/dist/messages/pt/devtools.json +16 -0
  149. package/dist/messages/pt/index.d.ts +16 -0
  150. package/dist/messages/pt/index.d.ts.map +1 -1
  151. package/dist/migrations/017_scheduled_actions_table.sql +21 -0
  152. package/dist/migrations/021_media.sql +154 -0
  153. package/dist/migrations/090_sample_data.sql +53 -0
  154. package/dist/styles/classes.json +36 -3
  155. package/dist/styles/ui.css +1 -1
  156. package/dist/templates/app/api/devtools/config/entities/route.ts +18 -11
  157. package/dist/templates/app/api/devtools/config/theme/route.ts +5 -4
  158. package/dist/templates/app/api/devtools/tests/[...path]/route.ts +6 -5
  159. package/dist/templates/app/api/devtools/tests/route.ts +5 -4
  160. package/dist/templates/app/api/health/route.ts +6 -4
  161. package/dist/templates/app/api/internal/user-metadata/route.ts +3 -2
  162. package/dist/templates/app/api/superadmin/subscriptions/route.ts +5 -6
  163. package/dist/templates/app/api/superadmin/teams/[teamId]/route.ts +6 -7
  164. package/dist/templates/app/api/superadmin/teams/route.ts +5 -6
  165. package/dist/templates/app/api/superadmin/users/[userId]/route.ts +11 -16
  166. package/dist/templates/app/api/superadmin/users/route.ts +9 -10
  167. package/dist/templates/app/api/user/delete-account/route.ts +3 -2
  168. package/dist/templates/app/api/user/plan-flags/route.ts +11 -24
  169. package/dist/templates/app/api/user/profile/route.ts +7 -6
  170. package/dist/templates/app/api/v1/[entity]/[id]/child/[childType]/[childId]/route.ts +16 -18
  171. package/dist/templates/app/api/v1/[entity]/[id]/child/[childType]/route.ts +17 -19
  172. package/dist/templates/app/api/v1/[entity]/[id]/route.ts +10 -12
  173. package/dist/templates/app/api/v1/[entity]/route.ts +9 -11
  174. package/dist/templates/app/api/v1/api-keys/[id]/route.ts +9 -8
  175. package/dist/templates/app/api/v1/api-keys/route.ts +7 -6
  176. package/dist/templates/app/api/v1/auth/signup-with-invite/route.ts +3 -2
  177. package/dist/templates/app/api/v1/billing/cancel/route.ts +15 -14
  178. package/dist/templates/app/api/v1/billing/change-plan/route.ts +10 -9
  179. package/dist/templates/app/api/v1/billing/check-action/route.ts +8 -7
  180. package/dist/templates/app/api/v1/billing/checkout/route.ts +10 -9
  181. package/dist/templates/app/api/v1/billing/plans/route.ts +5 -4
  182. package/dist/templates/app/api/v1/billing/portal/route.ts +9 -8
  183. package/dist/templates/app/api/v1/blocks/[slug]/route.ts +4 -3
  184. package/dist/templates/app/api/v1/blocks/route.ts +3 -2
  185. package/dist/templates/app/api/v1/blocks/validate/route.ts +5 -3
  186. package/dist/templates/app/api/v1/cron/process/route.ts +4 -6
  187. package/dist/templates/app/api/v1/devtools/blocks/route.ts +3 -2
  188. package/dist/templates/app/api/v1/devtools/docs/route.ts +3 -2
  189. package/dist/templates/app/api/v1/devtools/features/route.ts +3 -2
  190. package/dist/templates/app/api/v1/devtools/flows/route.ts +3 -2
  191. package/dist/templates/app/api/v1/devtools/scheduled-actions/route.ts +125 -3
  192. package/dist/templates/app/api/v1/devtools/scheduled-actions/run/route.ts +110 -0
  193. package/dist/templates/app/api/v1/devtools/testing/route.ts +3 -2
  194. package/dist/templates/app/api/v1/media/[id]/route.ts +144 -0
  195. package/dist/templates/app/api/v1/media/[id]/tags/route.ts +154 -0
  196. package/dist/templates/app/api/v1/media/check-duplicates/route.ts +56 -0
  197. package/dist/templates/app/api/v1/media/route.ts +56 -0
  198. package/dist/templates/app/api/v1/media/upload/route.ts +157 -33
  199. package/dist/templates/app/api/v1/media-tags/route.ts +65 -0
  200. package/dist/templates/app/api/v1/plugin/[...path]/route.ts +16 -15
  201. package/dist/templates/app/api/v1/plugin/route.ts +3 -2
  202. package/dist/templates/app/api/v1/post-categories/[id]/route.ts +10 -9
  203. package/dist/templates/app/api/v1/post-categories/route.ts +5 -4
  204. package/dist/templates/app/api/v1/team-invitations/[token]/accept/route.ts +3 -3
  205. package/dist/templates/app/api/v1/team-invitations/[token]/decline/route.ts +3 -3
  206. package/dist/templates/app/api/v1/team-invitations/[token]/route.ts +3 -2
  207. package/dist/templates/app/api/v1/team-invitations/route.ts +3 -2
  208. package/dist/templates/app/api/v1/teams/[teamId]/invitations/route.ts +5 -4
  209. package/dist/templates/app/api/v1/teams/[teamId]/invoices/[invoiceNumber]/route.ts +3 -2
  210. package/dist/templates/app/api/v1/teams/[teamId]/invoices/route.ts +3 -2
  211. package/dist/templates/app/api/v1/teams/[teamId]/members/[memberId]/route.ts +5 -4
  212. package/dist/templates/app/api/v1/teams/[teamId]/members/route.ts +5 -5
  213. package/dist/templates/app/api/v1/teams/[teamId]/route.ts +31 -58
  214. package/dist/templates/app/api/v1/teams/[teamId]/subscription/route.ts +3 -2
  215. package/dist/templates/app/api/v1/teams/[teamId]/usage/[limitSlug]/route.ts +5 -4
  216. package/dist/templates/app/api/v1/teams/route.ts +18 -17
  217. package/dist/templates/app/api/v1/teams/switch/route.ts +3 -2
  218. package/dist/templates/app/api/v1/theme/[...path]/route.ts +16 -15
  219. package/dist/templates/app/api/v1/theme/route.ts +3 -2
  220. package/dist/templates/app/api/v1/users/[id]/meta/[key]/route.ts +7 -6
  221. package/dist/templates/app/api/v1/users/[id]/route.ts +9 -8
  222. package/dist/templates/app/api/v1/users/route.ts +7 -6
  223. package/dist/templates/app/dashboard/(main)/media/page.tsx +607 -0
  224. package/dist/templates/contents/themes/starter/messages/de/dev.json +106 -0
  225. package/dist/templates/contents/themes/starter/messages/de/index.ts +2 -0
  226. package/dist/templates/contents/themes/starter/messages/en/dev.json +106 -0
  227. package/dist/templates/contents/themes/starter/messages/en/index.ts +2 -0
  228. package/dist/templates/contents/themes/starter/messages/es/dev.json +106 -0
  229. package/dist/templates/contents/themes/starter/messages/es/index.ts +2 -0
  230. package/dist/templates/contents/themes/starter/messages/fr/dev.json +106 -0
  231. package/dist/templates/contents/themes/starter/messages/fr/index.ts +2 -0
  232. package/dist/templates/contents/themes/starter/messages/it/dev.json +106 -0
  233. package/dist/templates/contents/themes/starter/messages/it/index.ts +2 -0
  234. package/dist/templates/contents/themes/starter/messages/pt/dev.json +106 -0
  235. package/dist/templates/contents/themes/starter/messages/pt/index.ts +2 -0
  236. package/dist/templates/contents/themes/starter/styles/globals.css +14 -0
  237. package/dist/templates/instrumentation.ts +33 -0
  238. package/dist/types/blocks.d.ts +1 -1
  239. package/dist/types/blocks.d.ts.map +1 -1
  240. package/migrations/017_scheduled_actions_table.sql +21 -0
  241. package/migrations/021_media.sql +154 -0
  242. package/migrations/090_sample_data.sql +53 -0
  243. package/package.json +3 -2
  244. package/scripts/build/registry/config.mjs +41 -0
  245. package/scripts/build/registry/discovery/templates.mjs +0 -1
  246. package/scripts/build/registry/generators/entity-registry.mjs +16 -6
  247. package/scripts/build/registry/generators/route-handlers.mjs +8 -2
  248. package/scripts/build/registry/generators/template-registry.mjs +16 -4
  249. package/scripts/build/registry/post-build/route-cleanup.mjs +0 -1
  250. package/scripts/build/registry/validate-env.test.mjs +92 -0
  251. package/scripts/build/registry.mjs +18 -1
  252. package/scripts/deploy/vercel-deploy.mjs +1 -1
  253. package/templates/app/api/devtools/config/entities/route.ts +18 -11
  254. package/templates/app/api/devtools/config/theme/route.ts +5 -4
  255. package/templates/app/api/devtools/tests/[...path]/route.ts +6 -5
  256. package/templates/app/api/devtools/tests/route.ts +5 -4
  257. package/templates/app/api/health/route.ts +6 -4
  258. package/templates/app/api/internal/user-metadata/route.ts +3 -2
  259. package/templates/app/api/superadmin/subscriptions/route.ts +5 -6
  260. package/templates/app/api/superadmin/teams/[teamId]/route.ts +6 -7
  261. package/templates/app/api/superadmin/teams/route.ts +5 -6
  262. package/templates/app/api/superadmin/users/[userId]/route.ts +11 -16
  263. package/templates/app/api/superadmin/users/route.ts +9 -10
  264. package/templates/app/api/user/delete-account/route.ts +3 -2
  265. package/templates/app/api/user/plan-flags/route.ts +11 -24
  266. package/templates/app/api/user/profile/route.ts +7 -6
  267. package/templates/app/api/v1/[entity]/[id]/child/[childType]/[childId]/route.ts +16 -18
  268. package/templates/app/api/v1/[entity]/[id]/child/[childType]/route.ts +17 -19
  269. package/templates/app/api/v1/[entity]/[id]/route.ts +10 -12
  270. package/templates/app/api/v1/[entity]/route.ts +9 -11
  271. package/templates/app/api/v1/api-keys/[id]/route.ts +9 -8
  272. package/templates/app/api/v1/api-keys/route.ts +7 -6
  273. package/templates/app/api/v1/auth/signup-with-invite/route.ts +3 -2
  274. package/templates/app/api/v1/billing/cancel/route.ts +15 -14
  275. package/templates/app/api/v1/billing/change-plan/route.ts +10 -9
  276. package/templates/app/api/v1/billing/check-action/route.ts +8 -7
  277. package/templates/app/api/v1/billing/checkout/route.ts +10 -9
  278. package/templates/app/api/v1/billing/plans/route.ts +5 -4
  279. package/templates/app/api/v1/billing/portal/route.ts +9 -8
  280. package/templates/app/api/v1/blocks/[slug]/route.ts +4 -3
  281. package/templates/app/api/v1/blocks/route.ts +3 -2
  282. package/templates/app/api/v1/blocks/validate/route.ts +5 -3
  283. package/templates/app/api/v1/cron/process/route.ts +4 -6
  284. package/templates/app/api/v1/devtools/blocks/route.ts +3 -2
  285. package/templates/app/api/v1/devtools/docs/route.ts +3 -2
  286. package/templates/app/api/v1/devtools/features/route.ts +3 -2
  287. package/templates/app/api/v1/devtools/flows/route.ts +3 -2
  288. package/templates/app/api/v1/devtools/scheduled-actions/route.ts +125 -3
  289. package/templates/app/api/v1/devtools/scheduled-actions/run/route.ts +110 -0
  290. package/templates/app/api/v1/devtools/testing/route.ts +3 -2
  291. package/templates/app/api/v1/media/[id]/route.ts +144 -0
  292. package/templates/app/api/v1/media/[id]/tags/route.ts +154 -0
  293. package/templates/app/api/v1/media/check-duplicates/route.ts +56 -0
  294. package/templates/app/api/v1/media/route.ts +56 -0
  295. package/templates/app/api/v1/media/upload/route.ts +157 -33
  296. package/templates/app/api/v1/media-tags/route.ts +65 -0
  297. package/templates/app/api/v1/plugin/[...path]/route.ts +16 -15
  298. package/templates/app/api/v1/plugin/route.ts +3 -2
  299. package/templates/app/api/v1/post-categories/[id]/route.ts +10 -9
  300. package/templates/app/api/v1/post-categories/route.ts +5 -4
  301. package/templates/app/api/v1/team-invitations/[token]/accept/route.ts +3 -3
  302. package/templates/app/api/v1/team-invitations/[token]/decline/route.ts +3 -3
  303. package/templates/app/api/v1/team-invitations/[token]/route.ts +3 -2
  304. package/templates/app/api/v1/team-invitations/route.ts +3 -2
  305. package/templates/app/api/v1/teams/[teamId]/invitations/route.ts +5 -4
  306. package/templates/app/api/v1/teams/[teamId]/invoices/[invoiceNumber]/route.ts +3 -2
  307. package/templates/app/api/v1/teams/[teamId]/invoices/route.ts +3 -2
  308. package/templates/app/api/v1/teams/[teamId]/members/[memberId]/route.ts +5 -4
  309. package/templates/app/api/v1/teams/[teamId]/members/route.ts +5 -5
  310. package/templates/app/api/v1/teams/[teamId]/route.ts +31 -58
  311. package/templates/app/api/v1/teams/[teamId]/subscription/route.ts +3 -2
  312. package/templates/app/api/v1/teams/[teamId]/usage/[limitSlug]/route.ts +5 -4
  313. package/templates/app/api/v1/teams/route.ts +18 -17
  314. package/templates/app/api/v1/teams/switch/route.ts +3 -2
  315. package/templates/app/api/v1/theme/[...path]/route.ts +16 -15
  316. package/templates/app/api/v1/theme/route.ts +3 -2
  317. package/templates/app/api/v1/users/[id]/meta/[key]/route.ts +7 -6
  318. package/templates/app/api/v1/users/[id]/route.ts +9 -8
  319. package/templates/app/api/v1/users/route.ts +7 -6
  320. package/templates/app/dashboard/(main)/media/page.tsx +607 -0
  321. package/templates/contents/themes/starter/messages/de/dev.json +106 -0
  322. package/templates/contents/themes/starter/messages/de/index.ts +2 -0
  323. package/templates/contents/themes/starter/messages/en/dev.json +106 -0
  324. package/templates/contents/themes/starter/messages/en/index.ts +2 -0
  325. package/templates/contents/themes/starter/messages/es/dev.json +106 -0
  326. package/templates/contents/themes/starter/messages/es/index.ts +2 -0
  327. package/templates/contents/themes/starter/messages/fr/dev.json +106 -0
  328. package/templates/contents/themes/starter/messages/fr/index.ts +2 -0
  329. package/templates/contents/themes/starter/messages/it/dev.json +106 -0
  330. package/templates/contents/themes/starter/messages/it/index.ts +2 -0
  331. package/templates/contents/themes/starter/messages/pt/dev.json +106 -0
  332. package/templates/contents/themes/starter/messages/pt/index.ts +2 -0
  333. package/templates/contents/themes/starter/styles/globals.css +14 -0
  334. package/templates/instrumentation.ts +33 -0
  335. package/dist/presets/plugin/.env.example.template +0 -19
  336. package/dist/presets/plugin/entities/.gitkeep +0 -18
  337. package/dist/presets/theme/blocks/.gitkeep +0 -17
  338. package/dist/presets/theme/public/brand/.gitkeep +0 -8
  339. package/dist/presets/theme/tests/cypress/.gitkeep +0 -10
  340. package/dist/templates/contents/plugins/starter/plugin/.env.example.template +0 -19
  341. package/templates/contents/plugins/starter/plugin/.env.example.template +0 -19
@@ -0,0 +1,110 @@
1
+ /**
2
+ * DevTools Scheduled Actions Run API
3
+ *
4
+ * POST /api/v1/devtools/scheduled-actions/run
5
+ *
6
+ * Executes a pending action immediately.
7
+ * Requires superadmin or developer user role.
8
+ */
9
+
10
+ import { NextRequest, NextResponse } from 'next/server'
11
+ import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
12
+ import {
13
+ canAccessDevtoolsApi,
14
+ createDevtoolsAccessDeniedResponse,
15
+ createDevtoolsUnauthorizedResponse,
16
+ } from '@nextsparkjs/core/lib/api/auth/devtools-auth'
17
+ import { queryWithRLS } from '@nextsparkjs/core/lib/db'
18
+ import type { ScheduledAction } from '@nextsparkjs/core/lib/scheduled-actions/types'
19
+ import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
20
+ import { executeAction } from '@nextsparkjs/core/lib/scheduled-actions/processor'
21
+
22
+ export const POST = withRateLimitTier(async (request: NextRequest) => {
23
+ // Authenticate request
24
+ const authResult = await authenticateRequest(request)
25
+
26
+ if (!authResult.success) {
27
+ return createDevtoolsUnauthorizedResponse()
28
+ }
29
+
30
+ // Check DevTools access permission
31
+ if (!canAccessDevtoolsApi(authResult)) {
32
+ return createDevtoolsAccessDeniedResponse()
33
+ }
34
+
35
+ // Parse request body
36
+ const body = await request.json()
37
+ const { actionId } = body
38
+
39
+ if (!actionId) {
40
+ return NextResponse.json({
41
+ success: false,
42
+ error: 'actionId is required'
43
+ }, { status: 400 })
44
+ }
45
+
46
+ // Fetch the pending action
47
+ const actions = await queryWithRLS<ScheduledAction>(
48
+ `SELECT
49
+ id,
50
+ "actionType",
51
+ status,
52
+ payload,
53
+ "teamId",
54
+ "scheduledAt",
55
+ attempts,
56
+ "maxRetries",
57
+ "recurringInterval",
58
+ "recurrenceType",
59
+ "lockGroup"
60
+ FROM "scheduled_actions"
61
+ WHERE id = $1`,
62
+ [actionId],
63
+ null
64
+ )
65
+
66
+ if (actions.length === 0) {
67
+ return NextResponse.json({
68
+ success: false,
69
+ error: 'Action not found'
70
+ }, { status: 404 })
71
+ }
72
+
73
+ const action = actions[0]
74
+
75
+ // Only allow running pending actions
76
+ if (action.status !== 'pending') {
77
+ return NextResponse.json({
78
+ success: false,
79
+ error: 'Only pending actions can be executed'
80
+ }, { status: 400 })
81
+ }
82
+
83
+ try {
84
+ // Execute the action immediately
85
+ await executeAction(action)
86
+
87
+ return NextResponse.json({
88
+ success: true,
89
+ data: {
90
+ executed: true
91
+ }
92
+ })
93
+ } catch (error) {
94
+ console.error('[DevTools] Failed to execute action:', error)
95
+ return NextResponse.json({
96
+ success: false,
97
+ error: error instanceof Error ? error.message : 'Failed to execute action'
98
+ }, { status: 500 })
99
+ }
100
+ }, 'write');
101
+
102
+ export async function OPTIONS() {
103
+ return new NextResponse(null, {
104
+ status: 204,
105
+ headers: {
106
+ 'Access-Control-Allow-Methods': 'POST, OPTIONS',
107
+ 'Access-Control-Allow-Headers': 'Content-Type, Authorization, x-api-key',
108
+ },
109
+ })
110
+ }
@@ -20,8 +20,9 @@ import {
20
20
  FEATURE_REGISTRY,
21
21
  FLOW_REGISTRY,
22
22
  } from '@nextsparkjs/registries/testing-registry'
23
+ import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
23
24
 
24
- export async function GET(request: NextRequest) {
25
+ export const GET = withRateLimitTier(async (request: NextRequest) => {
25
26
  // Authenticate request
26
27
  const authResult = await authenticateRequest(request)
27
28
 
@@ -69,7 +70,7 @@ export async function GET(request: NextRequest) {
69
70
  },
70
71
  },
71
72
  })
72
- }
73
+ }, 'read');
73
74
 
74
75
  export async function OPTIONS() {
75
76
  return new NextResponse(null, {
@@ -0,0 +1,144 @@
1
+ import { NextRequest } from 'next/server'
2
+ import { authenticateRequest, hasRequiredScope } from '@nextsparkjs/core/lib/api/auth/dual-auth'
3
+ import { createApiResponse, createApiError } from '@nextsparkjs/core/lib/api/helpers'
4
+ import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
5
+ import { MediaService } from '@nextsparkjs/core/lib/services/media.service'
6
+ import { updateMediaSchema } from '@nextsparkjs/core/lib/media/schemas'
7
+
8
+ /**
9
+ * GET /api/v1/media/:id
10
+ *
11
+ * Get a single media item by ID.
12
+ *
13
+ * Authentication: Requires valid session or API key with media:read scope
14
+ * RLS: Returns only media from teams the user is a member of
15
+ */
16
+ export const GET = withRateLimitTier(async (
17
+ request: NextRequest,
18
+ { params }: { params: Promise<{ id: string }> }
19
+ ) => {
20
+ try {
21
+ // 1. Authenticate
22
+ const authResult = await authenticateRequest(request)
23
+ if (!authResult.success) {
24
+ return createApiError('Unauthorized', 401)
25
+ }
26
+
27
+ // 2. Check permissions
28
+ if (!hasRequiredScope(authResult, 'media:read')) {
29
+ return createApiError('Insufficient permissions', 403)
30
+ }
31
+
32
+ // 3. Get media ID from params
33
+ const { id } = await params
34
+
35
+ // 4. Fetch media with RLS
36
+ const media = await MediaService.getById(id, authResult.user!.id)
37
+
38
+ if (!media) {
39
+ return createApiError('Media not found', 404)
40
+ }
41
+
42
+ return createApiResponse(media)
43
+ } catch (error) {
44
+ console.error('[Media API] Error fetching media:', error)
45
+ return createApiError('Failed to fetch media', 500)
46
+ }
47
+ }, 'read')
48
+
49
+ /**
50
+ * PATCH /api/v1/media/:id
51
+ *
52
+ * Update media metadata (alt text and caption).
53
+ * File properties (url, filename, size, dimensions) are immutable.
54
+ *
55
+ * Request Body:
56
+ * - alt: Alt text for accessibility (max 500 characters, optional)
57
+ * - caption: Caption or description (max 1000 characters, optional)
58
+ *
59
+ * Authentication: Requires valid session or API key with media:write scope
60
+ * RLS: Can only update media from teams the user is a member of
61
+ */
62
+ export const PATCH = withRateLimitTier(async (
63
+ request: NextRequest,
64
+ { params }: { params: Promise<{ id: string }> }
65
+ ) => {
66
+ try {
67
+ // 1. Authenticate
68
+ const authResult = await authenticateRequest(request)
69
+ if (!authResult.success) {
70
+ return createApiError('Unauthorized', 401)
71
+ }
72
+
73
+ // 2. Check permissions
74
+ if (!hasRequiredScope(authResult, 'media:write')) {
75
+ return createApiError('Insufficient permissions', 403)
76
+ }
77
+
78
+ // 3. Get media ID from params
79
+ const { id } = await params
80
+
81
+ // 4. Parse and validate request body
82
+ const body = await request.json()
83
+ const parsed = updateMediaSchema.safeParse(body)
84
+
85
+ if (!parsed.success) {
86
+ return createApiError('Validation failed', 400, {
87
+ errors: parsed.error.issues,
88
+ })
89
+ }
90
+
91
+ // 5. Update media with RLS
92
+ const media = await MediaService.update(id, authResult.user!.id, parsed.data)
93
+
94
+ return createApiResponse(media)
95
+ } catch (error) {
96
+ console.error('[Media API] Error updating media:', error)
97
+ return createApiError(
98
+ error instanceof Error ? error.message : 'Failed to update media',
99
+ 500
100
+ )
101
+ }
102
+ }, 'write')
103
+
104
+ /**
105
+ * DELETE /api/v1/media/:id
106
+ *
107
+ * Soft delete a media item (sets status to 'deleted').
108
+ * The file remains in storage but is hidden from queries.
109
+ *
110
+ * Authentication: Requires valid session or API key with media:delete scope
111
+ * RLS: Can only delete media from teams the user is a member of
112
+ */
113
+ export const DELETE = withRateLimitTier(async (
114
+ request: NextRequest,
115
+ { params }: { params: Promise<{ id: string }> }
116
+ ) => {
117
+ try {
118
+ // 1. Authenticate
119
+ const authResult = await authenticateRequest(request)
120
+ if (!authResult.success) {
121
+ return createApiError('Unauthorized', 401)
122
+ }
123
+
124
+ // 2. Check permissions
125
+ if (!hasRequiredScope(authResult, 'media:delete')) {
126
+ return createApiError('Insufficient permissions', 403)
127
+ }
128
+
129
+ // 3. Get media ID from params
130
+ const { id } = await params
131
+
132
+ // 4. Soft delete media with RLS
133
+ const deleted = await MediaService.softDelete(id, authResult.user!.id)
134
+
135
+ if (!deleted) {
136
+ return createApiError('Media not found', 404)
137
+ }
138
+
139
+ return createApiResponse({ message: 'Media deleted successfully' })
140
+ } catch (error) {
141
+ console.error('[Media API] Error deleting media:', error)
142
+ return createApiError('Failed to delete media', 500)
143
+ }
144
+ }, 'write')
@@ -0,0 +1,154 @@
1
+ import { NextRequest } from 'next/server'
2
+ import { authenticateRequest, hasRequiredScope } from '@nextsparkjs/core/lib/api/auth/dual-auth'
3
+ import { createApiResponse, createApiError } from '@nextsparkjs/core/lib/api/helpers'
4
+ import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
5
+ import { MediaService } from '@nextsparkjs/core/lib/services/media.service'
6
+ import { z } from 'zod'
7
+
8
+ const addTagSchema = z.object({
9
+ tagId: z.string().min(1),
10
+ })
11
+
12
+ const setTagsSchema = z.object({
13
+ tagIds: z.array(z.string().min(1)),
14
+ })
15
+
16
+ /**
17
+ * GET /api/v1/media/{id}/tags
18
+ *
19
+ * Get all tags assigned to a media item.
20
+ */
21
+ export const GET = withRateLimitTier(async (
22
+ request: NextRequest,
23
+ { params }: { params: Promise<{ id: string }> }
24
+ ) => {
25
+ try {
26
+ const authResult = await authenticateRequest(request)
27
+ if (!authResult.success) {
28
+ return createApiError('Unauthorized', 401)
29
+ }
30
+
31
+ if (!hasRequiredScope(authResult, 'media:read')) {
32
+ return createApiError('Insufficient permissions', 403)
33
+ }
34
+
35
+ const { id } = await params
36
+ const tags = await MediaService.getMediaTags(id, authResult.user!.id)
37
+ return createApiResponse(tags)
38
+ } catch (error) {
39
+ console.error('[Media Tags API] Error getting tags:', error)
40
+ return createApiError('Failed to get media tags', 500)
41
+ }
42
+ }, 'read')
43
+
44
+ /**
45
+ * POST /api/v1/media/{id}/tags
46
+ *
47
+ * Add a tag to a media item.
48
+ * Body: { tagId: string }
49
+ */
50
+ export const POST = withRateLimitTier(async (
51
+ request: NextRequest,
52
+ { params }: { params: Promise<{ id: string }> }
53
+ ) => {
54
+ try {
55
+ const authResult = await authenticateRequest(request)
56
+ if (!authResult.success) {
57
+ return createApiError('Unauthorized', 401)
58
+ }
59
+
60
+ if (!hasRequiredScope(authResult, 'media:write')) {
61
+ return createApiError('Insufficient permissions', 403)
62
+ }
63
+
64
+ const { id } = await params
65
+ const body = await request.json()
66
+ const parsed = addTagSchema.safeParse(body)
67
+
68
+ if (!parsed.success) {
69
+ return createApiError('Invalid request body', 400, { errors: parsed.error.issues })
70
+ }
71
+
72
+ await MediaService.addTag(id, parsed.data.tagId, authResult.user!.id)
73
+ const tags = await MediaService.getMediaTags(id, authResult.user!.id)
74
+
75
+ return createApiResponse(tags, undefined, 201)
76
+ } catch (error) {
77
+ console.error('[Media Tags API] Error adding tag:', error)
78
+ return createApiError('Failed to add tag', 500)
79
+ }
80
+ }, 'write')
81
+
82
+ /**
83
+ * PUT /api/v1/media/{id}/tags
84
+ *
85
+ * Replace all tags for a media item.
86
+ * Body: { tagIds: string[] }
87
+ */
88
+ export const PUT = withRateLimitTier(async (
89
+ request: NextRequest,
90
+ { params }: { params: Promise<{ id: string }> }
91
+ ) => {
92
+ try {
93
+ const authResult = await authenticateRequest(request)
94
+ if (!authResult.success) {
95
+ return createApiError('Unauthorized', 401)
96
+ }
97
+
98
+ if (!hasRequiredScope(authResult, 'media:write')) {
99
+ return createApiError('Insufficient permissions', 403)
100
+ }
101
+
102
+ const { id } = await params
103
+ const body = await request.json()
104
+ const parsed = setTagsSchema.safeParse(body)
105
+
106
+ if (!parsed.success) {
107
+ return createApiError('Invalid request body', 400, { errors: parsed.error.issues })
108
+ }
109
+
110
+ await MediaService.setTags(id, parsed.data.tagIds, authResult.user!.id)
111
+ const tags = await MediaService.getMediaTags(id, authResult.user!.id)
112
+
113
+ return createApiResponse(tags)
114
+ } catch (error) {
115
+ console.error('[Media Tags API] Error setting tags:', error)
116
+ return createApiError('Failed to set tags', 500)
117
+ }
118
+ }, 'write')
119
+
120
+ /**
121
+ * DELETE /api/v1/media/{id}/tags
122
+ *
123
+ * Remove a tag from a media item.
124
+ * Query parameter: tagId
125
+ */
126
+ export const DELETE = withRateLimitTier(async (
127
+ request: NextRequest,
128
+ { params }: { params: Promise<{ id: string }> }
129
+ ) => {
130
+ try {
131
+ const authResult = await authenticateRequest(request)
132
+ if (!authResult.success) {
133
+ return createApiError('Unauthorized', 401)
134
+ }
135
+
136
+ if (!hasRequiredScope(authResult, 'media:delete')) {
137
+ return createApiError('Insufficient permissions', 403)
138
+ }
139
+
140
+ const { id } = await params
141
+ const { searchParams } = new URL(request.url)
142
+ const tagId = searchParams.get('tagId')
143
+
144
+ if (!tagId) {
145
+ return createApiError('tagId query parameter is required', 400)
146
+ }
147
+
148
+ await MediaService.removeTag(id, tagId, authResult.user!.id)
149
+ return createApiResponse({ success: true })
150
+ } catch (error) {
151
+ console.error('[Media Tags API] Error removing tag:', error)
152
+ return createApiError('Failed to remove tag', 500)
153
+ }
154
+ }, 'write')
@@ -0,0 +1,56 @@
1
+ import { NextRequest } from 'next/server'
2
+ import { authenticateRequest, hasRequiredScope } from '@nextsparkjs/core/lib/api/auth/dual-auth'
3
+ import { createApiResponse, createApiError } from '@nextsparkjs/core/lib/api/helpers'
4
+ import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
5
+ import { MediaService } from '@nextsparkjs/core/lib/services/media.service'
6
+
7
+ /**
8
+ * POST /api/v1/media/check-duplicates
9
+ *
10
+ * Check if files with the same name+size already exist in the media library.
11
+ * Used by the upload zone to warn users before uploading duplicates.
12
+ *
13
+ * Body: { files: [{ filename: string, fileSize: number }] }
14
+ * Returns: { duplicates: [{ filename, fileSize, existing: Media[] }] }
15
+ */
16
+ export const POST = withRateLimitTier(async (request: NextRequest) => {
17
+ try {
18
+ const authResult = await authenticateRequest(request)
19
+ if (!authResult.success) {
20
+ return createApiError('Unauthorized', 401)
21
+ }
22
+
23
+ if (!hasRequiredScope(authResult, 'media:read')) {
24
+ return createApiError('Insufficient permissions - media:read scope required', 403)
25
+ }
26
+
27
+ const body = await request.json()
28
+ const files = body.files as { filename: string; fileSize: number }[]
29
+
30
+ if (!files || !Array.isArray(files) || files.length === 0) {
31
+ return createApiError('files array is required', 400)
32
+ }
33
+
34
+ const duplicates: { filename: string; fileSize: number; existing: { id: string; url: string; createdAt: string }[] }[] = []
35
+
36
+ for (const file of files) {
37
+ const existing = await MediaService.findDuplicates(
38
+ authResult.user!.id,
39
+ file.filename,
40
+ file.fileSize
41
+ )
42
+ if (existing.length > 0) {
43
+ duplicates.push({
44
+ filename: file.filename,
45
+ fileSize: file.fileSize,
46
+ existing: existing.map(m => ({ id: m.id, url: m.url, createdAt: m.createdAt })),
47
+ })
48
+ }
49
+ }
50
+
51
+ return createApiResponse({ duplicates })
52
+ } catch (error) {
53
+ console.error('Error checking duplicates:', error)
54
+ return createApiError('Failed to check duplicates', 500)
55
+ }
56
+ }, 'read')
@@ -0,0 +1,56 @@
1
+ import { NextRequest } from 'next/server'
2
+ import { authenticateRequest, hasRequiredScope } from '@nextsparkjs/core/lib/api/auth/dual-auth'
3
+ import { createApiResponse, createApiError } from '@nextsparkjs/core/lib/api/helpers'
4
+ import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
5
+ import { MediaService } from '@nextsparkjs/core/lib/services/media.service'
6
+ import { mediaListQuerySchema } from '@nextsparkjs/core/lib/media/schemas'
7
+
8
+ /**
9
+ * GET /api/v1/media
10
+ *
11
+ * List media files with pagination, filtering, and search.
12
+ * Supports filtering by type (image/video), searching by filename, and sorting.
13
+ *
14
+ * Query Parameters:
15
+ * - limit: Number of items per page (default: 20, max: 100)
16
+ * - offset: Number of items to skip (default: 0)
17
+ * - orderBy: Sort field (createdAt|filename|fileSize, default: createdAt)
18
+ * - orderDir: Sort direction (asc|desc, default: desc)
19
+ * - type: Filter by type (image|video|all, default: all)
20
+ * - search: Search by filename (case-insensitive)
21
+ *
22
+ * Authentication: Requires valid session or API key with media:read scope
23
+ * RLS: Returns only media from teams the user is a member of
24
+ */
25
+ export const GET = withRateLimitTier(async (request: NextRequest) => {
26
+ try {
27
+ // 1. Authenticate
28
+ const authResult = await authenticateRequest(request)
29
+ if (!authResult.success) {
30
+ return createApiError('Unauthorized', 401)
31
+ }
32
+
33
+ // 2. Check permissions
34
+ if (!hasRequiredScope(authResult, 'media:read')) {
35
+ return createApiError('Insufficient permissions - media:read scope required', 403)
36
+ }
37
+
38
+ // 3. Parse and validate query parameters
39
+ const { searchParams } = new URL(request.url)
40
+ const parsed = mediaListQuerySchema.safeParse(Object.fromEntries(searchParams))
41
+
42
+ if (!parsed.success) {
43
+ return createApiError('Invalid query parameters', 400, {
44
+ errors: parsed.error.issues,
45
+ })
46
+ }
47
+
48
+ // 4. Query media list with RLS
49
+ const result = await MediaService.list(authResult.user!.id, parsed.data)
50
+
51
+ return createApiResponse(result)
52
+ } catch (error) {
53
+ console.error('[Media API] Error listing media:', error)
54
+ return createApiError('Failed to list media', 500)
55
+ }
56
+ }, 'read')