@nextsparkjs/core 0.1.0-beta.195 → 0.1.0-beta.197

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 (283) hide show
  1. package/README.md +2 -0
  2. package/dist/components/auth/forms/SignupForm.d.ts.map +1 -1
  3. package/dist/components/auth/forms/SignupForm.js +55 -45
  4. package/dist/components/billing/InvoicesPagination.js +2 -2
  5. package/dist/components/dashboard/block-editor/config-panel.d.ts.map +1 -1
  6. package/dist/components/dashboard/block-editor/config-panel.js +3 -2
  7. package/dist/components/dashboard/block-editor/entity-fields-sidebar.d.ts.map +1 -1
  8. package/dist/components/dashboard/block-editor/entity-fields-sidebar.js +3 -2
  9. package/dist/components/dashboard/navigation/DynamicNavigation.js +2 -2
  10. package/dist/components/settings/layouts/SettingsSidebar.d.ts.map +1 -1
  11. package/dist/components/settings/layouts/SettingsSidebar.js +0 -1
  12. package/dist/components/teams/CreateTeamButton.js +2 -2
  13. package/dist/components/teams/CreateTeamDialog.js +1 -1
  14. package/dist/components/teams/InviteMemberButton.js +3 -3
  15. package/dist/components/teams/InviteMemberDialog.js +1 -1
  16. package/dist/components/teams/TeamPendingInvitations.js +2 -2
  17. package/dist/components/users/tables/UsersTable.d.ts.map +1 -1
  18. package/dist/components/users/tables/UsersTable.js +3 -4
  19. package/dist/hooks/useAuthReadiness.d.ts +1 -0
  20. package/dist/hooks/useAuthReadiness.d.ts.map +1 -1
  21. package/dist/hooks/useAuthReadiness.js +3 -1
  22. package/dist/lib/actions/entity.actions.js +2 -2
  23. package/dist/lib/actions/team.actions.js +2 -2
  24. package/dist/lib/actions/user.actions.js +4 -4
  25. package/dist/lib/api/api-error.d.ts +2 -0
  26. package/dist/lib/api/api-error.d.ts.map +1 -1
  27. package/dist/lib/api/api-error.js +3 -1
  28. package/dist/lib/api/auth/dual-auth.d.ts +2 -1
  29. package/dist/lib/api/auth/dual-auth.d.ts.map +1 -1
  30. package/dist/lib/api/auth/dual-auth.js +25 -6
  31. package/dist/lib/api/auth/scope-policy.d.ts +6 -3
  32. package/dist/lib/api/auth/scope-policy.d.ts.map +1 -1
  33. package/dist/lib/api/auth.d.ts.map +1 -1
  34. package/dist/lib/api/auth.js +7 -0
  35. package/dist/lib/api/cors-response.d.ts +3 -2
  36. package/dist/lib/api/cors-response.d.ts.map +1 -1
  37. package/dist/lib/api/cors-response.js +8 -6
  38. package/dist/lib/api/entity/generic-handler.d.ts.map +1 -1
  39. package/dist/lib/api/entity/generic-handler.js +66 -15
  40. package/dist/lib/api/entity-handler.js +2 -2
  41. package/dist/lib/api/helpers.d.ts.map +1 -1
  42. package/dist/lib/api/helpers.js +9 -24
  43. package/dist/lib/api/permission-middleware.d.ts.map +1 -1
  44. package/dist/lib/api/permission-middleware.js +0 -2
  45. package/dist/lib/api/post-categories.d.ts +29 -0
  46. package/dist/lib/api/post-categories.d.ts.map +1 -0
  47. package/dist/lib/api/post-categories.js +33 -0
  48. package/dist/lib/api/rate-limit.d.ts +8 -0
  49. package/dist/lib/api/rate-limit.d.ts.map +1 -1
  50. package/dist/lib/api/rate-limit.js +34 -3
  51. package/dist/lib/api/request-origin.d.ts.map +1 -1
  52. package/dist/lib/api/request-origin.js +1 -1
  53. package/dist/lib/auth/auth-methods.d.ts +5 -2
  54. package/dist/lib/auth/auth-methods.d.ts.map +1 -1
  55. package/dist/lib/auth/auth-methods.js +4 -2
  56. package/dist/lib/auth/authorization-session.d.ts +14 -0
  57. package/dist/lib/auth/authorization-session.d.ts.map +1 -0
  58. package/dist/lib/auth/authorization-session.js +10 -0
  59. package/dist/lib/auth/request-session.d.ts +5 -0
  60. package/dist/lib/auth/request-session.d.ts.map +1 -1
  61. package/dist/lib/auth/request-session.js +3 -0
  62. package/dist/lib/auth/runtime-readiness.d.ts +7 -4
  63. package/dist/lib/auth/runtime-readiness.d.ts.map +1 -1
  64. package/dist/lib/auth/runtime-readiness.js +9 -6
  65. package/dist/lib/auth/sample-accounts.d.ts +18 -0
  66. package/dist/lib/auth/sample-accounts.d.ts.map +1 -0
  67. package/dist/lib/auth/sample-accounts.js +25 -0
  68. package/dist/lib/auth/suspension.d.ts +22 -0
  69. package/dist/lib/auth/suspension.d.ts.map +1 -0
  70. package/dist/lib/auth/suspension.js +43 -0
  71. package/dist/lib/auth.d.ts.map +1 -1
  72. package/dist/lib/auth.js +20 -17
  73. package/dist/lib/cache/public-entity-cache.d.ts +21 -0
  74. package/dist/lib/cache/public-entity-cache.d.ts.map +1 -0
  75. package/dist/lib/cache/public-entity-cache.js +25 -0
  76. package/dist/lib/config/app.config.d.ts.map +1 -1
  77. package/dist/lib/config/app.config.js +6 -7
  78. package/dist/lib/config/types.d.ts +8 -6
  79. package/dist/lib/config/types.d.ts.map +1 -1
  80. package/dist/lib/db-pool.d.ts +31 -0
  81. package/dist/lib/db-pool.d.ts.map +1 -0
  82. package/dist/lib/db-pool.js +75 -0
  83. package/dist/lib/db.d.ts +1 -1
  84. package/dist/lib/db.d.ts.map +1 -1
  85. package/dist/lib/db.js +11 -14
  86. package/dist/lib/entities/api-generator.js +5 -5
  87. package/dist/lib/entities/entity-hooks.d.ts.map +1 -1
  88. package/dist/lib/entities/entity-hooks.js +4 -0
  89. package/dist/lib/mcp/errors.d.ts +2 -0
  90. package/dist/lib/mcp/errors.d.ts.map +1 -1
  91. package/dist/lib/mcp/errors.js +3 -1
  92. package/dist/lib/mcp/index.d.ts +1 -1
  93. package/dist/lib/mcp/index.d.ts.map +1 -1
  94. package/dist/lib/mcp/index.js +2 -1
  95. package/dist/lib/oauth/token-refresh.d.ts.map +1 -1
  96. package/dist/lib/oauth/token-refresh.js +3 -6
  97. package/dist/lib/permissions/check.d.ts +9 -0
  98. package/dist/lib/permissions/check.d.ts.map +1 -1
  99. package/dist/lib/permissions/check.js +11 -1
  100. package/dist/lib/services/generic-entity.service.d.ts.map +1 -1
  101. package/dist/lib/services/generic-entity.service.js +41 -7
  102. package/dist/lib/services/transactional-meta.service.d.ts.map +1 -1
  103. package/dist/lib/services/transactional-meta.service.js +7 -8
  104. package/dist/lib/teams/actions.d.ts.map +1 -1
  105. package/dist/lib/teams/actions.js +0 -1
  106. package/dist/lib/validation.d.ts +5 -0
  107. package/dist/lib/validation.d.ts.map +1 -1
  108. package/dist/lib/validation.js +2 -0
  109. package/dist/messages/de/billing.json +12 -1
  110. package/dist/messages/de/common.json +2 -0
  111. package/dist/messages/de/docs.json +1 -0
  112. package/dist/messages/de/features.json +16 -4
  113. package/dist/messages/de/home.json +5 -0
  114. package/dist/messages/de/index.d.ts +68 -25
  115. package/dist/messages/de/index.d.ts.map +1 -1
  116. package/dist/messages/de/index.js +2 -0
  117. package/dist/messages/de/index.ts +2 -0
  118. package/dist/messages/de/settings.json +1 -0
  119. package/dist/messages/de/teams.json +3 -18
  120. package/dist/messages/en/billing.json +1 -1
  121. package/dist/messages/en/common.json +2 -0
  122. package/dist/messages/en/docs.json +1 -0
  123. package/dist/messages/en/features.json +16 -4
  124. package/dist/messages/en/home.json +5 -0
  125. package/dist/messages/en/index.d.ts +58 -25
  126. package/dist/messages/en/index.d.ts.map +1 -1
  127. package/dist/messages/en/index.js +2 -0
  128. package/dist/messages/en/index.ts +2 -0
  129. package/dist/messages/en/settings.json +1 -0
  130. package/dist/messages/en/teams.json +3 -18
  131. package/dist/messages/es/billing.json +1 -1
  132. package/dist/messages/es/common.json +2 -0
  133. package/dist/messages/es/docs.json +1 -0
  134. package/dist/messages/es/features.json +16 -4
  135. package/dist/messages/es/home.json +5 -0
  136. package/dist/messages/es/index.d.ts +41 -8
  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/settings.json +1 -0
  141. package/dist/messages/es/teams.json +3 -0
  142. package/dist/messages/fr/billing.json +12 -1
  143. package/dist/messages/fr/common.json +2 -0
  144. package/dist/messages/fr/docs.json +1 -0
  145. package/dist/messages/fr/features.json +16 -4
  146. package/dist/messages/fr/home.json +5 -0
  147. package/dist/messages/fr/index.d.ts +68 -25
  148. package/dist/messages/fr/index.d.ts.map +1 -1
  149. package/dist/messages/fr/index.js +2 -0
  150. package/dist/messages/fr/index.ts +2 -0
  151. package/dist/messages/fr/settings.json +1 -0
  152. package/dist/messages/fr/teams.json +3 -18
  153. package/dist/messages/it/billing.json +12 -1
  154. package/dist/messages/it/common.json +2 -0
  155. package/dist/messages/it/docs.json +1 -0
  156. package/dist/messages/it/features.json +16 -4
  157. package/dist/messages/it/home.json +5 -0
  158. package/dist/messages/it/index.d.ts +68 -25
  159. package/dist/messages/it/index.d.ts.map +1 -1
  160. package/dist/messages/it/index.js +2 -0
  161. package/dist/messages/it/index.ts +2 -0
  162. package/dist/messages/it/settings.json +1 -0
  163. package/dist/messages/it/teams.json +3 -18
  164. package/dist/messages/pt/billing.json +12 -1
  165. package/dist/messages/pt/common.json +2 -0
  166. package/dist/messages/pt/docs.json +1 -0
  167. package/dist/messages/pt/features.json +16 -4
  168. package/dist/messages/pt/home.json +5 -0
  169. package/dist/messages/pt/index.d.ts +68 -25
  170. package/dist/messages/pt/index.d.ts.map +1 -1
  171. package/dist/messages/pt/index.js +2 -0
  172. package/dist/messages/pt/index.ts +2 -0
  173. package/dist/messages/pt/settings.json +1 -0
  174. package/dist/messages/pt/teams.json +3 -18
  175. package/dist/migrations/029_sample_accounts_outside_development.sql +55 -0
  176. package/dist/migrations/030_taxonomies_team_writes.sql +29 -0
  177. package/dist/migrations/031_users_role_suspended.sql +41 -0
  178. package/dist/migrations/090_sample_data.sql +10 -0
  179. package/dist/routes/(auth)/signup/page.cc.d.ts +3 -1
  180. package/dist/routes/(auth)/signup/page.cc.d.ts.map +1 -1
  181. package/dist/routes/(auth)/signup/page.cc.js +2 -2
  182. package/dist/routes/(auth)/signup/page.d.ts +3 -1
  183. package/dist/routes/(auth)/signup/page.d.ts.map +1 -1
  184. package/dist/routes/(auth)/signup/page.js +4 -3
  185. package/dist/routes/_internal/area-access.js +2 -2
  186. package/dist/routes/_internal/entity-permission-layout.d.ts.map +1 -1
  187. package/dist/routes/_internal/entity-permission-layout.js +0 -7
  188. package/dist/routes/api/devtools/config/entities/route.js +2 -2
  189. package/dist/routes/api/devtools/config/theme/route.js +2 -2
  190. package/dist/routes/api/devtools/tests/[...path]/route.js +2 -2
  191. package/dist/routes/api/devtools/tests/route.js +2 -2
  192. package/dist/routes/api/mcp/route.d.ts.map +1 -1
  193. package/dist/routes/api/mcp/route.js +7 -1
  194. package/dist/routes/api/superadmin/subscriptions/route.js +2 -2
  195. package/dist/routes/api/superadmin/teams/[teamId]/route.js +2 -2
  196. package/dist/routes/api/superadmin/teams/route.js +2 -2
  197. package/dist/routes/api/superadmin/users/[userId]/route.d.ts +5 -3
  198. package/dist/routes/api/superadmin/users/[userId]/route.d.ts.map +1 -1
  199. package/dist/routes/api/superadmin/users/[userId]/route.js +46 -23
  200. package/dist/routes/api/superadmin/users/route.js +2 -2
  201. package/dist/routes/api/user/delete-account/route.d.ts.map +1 -1
  202. package/dist/routes/api/user/delete-account/route.js +2 -3
  203. package/dist/routes/api/user/plan-flags/route.d.ts.map +1 -1
  204. package/dist/routes/api/user/plan-flags/route.js +5 -5
  205. package/dist/routes/api/user/profile/route.js +3 -3
  206. package/dist/routes/api/v1/auth/signup-with-invite/route.d.ts.map +1 -1
  207. package/dist/routes/api/v1/auth/signup-with-invite/route.js +80 -44
  208. package/dist/routes/api/v1/media/upload/route.d.ts +2 -1
  209. package/dist/routes/api/v1/media/upload/route.d.ts.map +1 -1
  210. package/dist/routes/api/v1/media/upload/route.js +10 -2
  211. package/dist/routes/api/v1/post-categories/[id]/route.d.ts.map +1 -1
  212. package/dist/routes/api/v1/post-categories/[id]/route.js +39 -34
  213. package/dist/routes/api/v1/post-categories/route.d.ts.map +1 -1
  214. package/dist/routes/api/v1/post-categories/route.js +18 -14
  215. package/dist/routes/api/v1/team-invitations/route.d.ts.map +1 -1
  216. package/dist/routes/api/v1/team-invitations/route.js +12 -5
  217. package/dist/routes/api/v1/teams/[teamId]/members/route.d.ts.map +1 -1
  218. package/dist/routes/api/v1/teams/[teamId]/members/route.js +12 -10
  219. package/dist/routes/api/v1/teams/switch/route.d.ts.map +1 -1
  220. package/dist/routes/api/v1/teams/switch/route.js +4 -1
  221. package/dist/routes/dashboard/settings/password/page.d.ts.map +1 -1
  222. package/dist/routes/dashboard/settings/password/page.js +10 -12
  223. package/dist/routes/devtools/config/page.js +1 -1
  224. package/dist/routes/devtools/page.js +1 -1
  225. package/dist/routes/devtools/scheduled-actions/page.js +1 -1
  226. package/dist/routes/devtools/tests/[[...path]]/page.js +1 -1
  227. package/dist/routes/superadmin/users/page.js +2 -2
  228. package/dist/templates/ci-workflows/github/cypress-regression.yml +1 -1
  229. package/dist/templates/ci-workflows/github/cypress-smoke.yml +2 -1
  230. package/dist/templates/next.config.mjs +11 -31
  231. package/dist/templates/projects/blog/package.json +1 -1
  232. package/dist/templates/projects/crm/package.json +1 -1
  233. package/dist/templates/projects/productivity/package.json +1 -1
  234. package/dist/templates/projects/starter/README.md +2 -0
  235. package/dist/templates/projects/starter/config/app.config.ts +8 -0
  236. package/dist/templates/projects/starter/docs/public/01-overview/01-introduction.md +2 -0
  237. package/dist/templates/projects/starter/templates/dashboard/analytics/layout.tsx +14 -0
  238. package/dist/templates/proxy.ts +18 -8
  239. package/dist/templates/public/uploads/README.md +5 -94
  240. package/migrations/029_sample_accounts_outside_development.sql +55 -0
  241. package/migrations/030_taxonomies_team_writes.sql +29 -0
  242. package/migrations/031_users_role_suspended.sql +41 -0
  243. package/migrations/090_sample_data.sql +10 -0
  244. package/package.json +3 -3
  245. package/scripts/build/registry/__tests__/build-output.test.mjs +1 -1
  246. package/scripts/build/registry/__tests__/project-mode-root-first.test.mjs +6 -6
  247. package/scripts/build/registry/__tests__/write-places.test.mjs +1 -1
  248. package/scripts/build/registry/contracts/__tests__/contracts-wire.test.mjs +1 -1
  249. package/scripts/build/registry/contracts/__tests__/contracts.test.mjs +1 -1
  250. package/scripts/build/registry/host/README.md +2 -2
  251. package/scripts/build/registry/host/__tests__/facade-emitter.test.mjs +14 -13
  252. package/scripts/build/registry/host/__tests__/host-mode.test.mjs +1 -1
  253. package/scripts/build/registry/host/__tests__/host-project-composition.test.mjs +1 -1
  254. package/scripts/build/registry/host/__tests__/host-project.test.mjs +2 -2
  255. package/scripts/build/registry/host/__tests__/host-proxy-areas.test.mjs +99 -1
  256. package/scripts/build/registry/host/__tests__/host-robustness.test.mjs +1 -1
  257. package/scripts/build/registry/host/facade-emitter.mjs +1 -1
  258. package/scripts/build/registry/host/next-route-exports.json +2 -2
  259. package/scripts/build/registry/host/proxy-areas.mjs +92 -2
  260. package/scripts/db/run-migrations.mjs +30 -10
  261. package/scripts/db/sample-data.mjs +44 -0
  262. package/scripts/db/verify-theme-migrations.mjs +7 -1
  263. package/templates/ci-workflows/github/cypress-regression.yml +1 -1
  264. package/templates/ci-workflows/github/cypress-smoke.yml +2 -1
  265. package/templates/next.config.mjs +11 -31
  266. package/templates/projects/blog/package.json +1 -1
  267. package/templates/projects/crm/package.json +1 -1
  268. package/templates/projects/productivity/package.json +1 -1
  269. package/templates/projects/starter/README.md +2 -0
  270. package/templates/projects/starter/config/app.config.ts +8 -0
  271. package/templates/projects/starter/docs/public/01-overview/01-introduction.md +2 -0
  272. package/templates/projects/starter/templates/dashboard/analytics/layout.tsx +14 -0
  273. package/templates/proxy.ts +18 -8
  274. package/templates/public/uploads/README.md +5 -94
  275. package/tests/jest/__mocks__/@nextsparkjs/registries/api-presets-registry.ts +2 -0
  276. package/tests/jest/__mocks__/@nextsparkjs/registries/mcp-registry.ts +2 -0
  277. package/tests/jest/__mocks__/@nextsparkjs/registries/permissions-registry.ts +5 -4
  278. package/dist/templates/projects/starter/public/brand/.gitkeep +0 -0
  279. package/dist/templates/public/uploads/.gitignore +0 -6
  280. package/dist/templates/public/uploads/temp/.gitkeep +0 -1
  281. package/templates/projects/starter/public/brand/.gitkeep +0 -0
  282. package/templates/public/uploads/.gitignore +0 -6
  283. package/templates/public/uploads/temp/.gitkeep +0 -1
@@ -1,4 +1,4 @@
1
- import { getTypedSession } from "@nextsparkjs/core/lib/auth";
1
+ import { getAuthorizationSession } from "@nextsparkjs/core/lib/auth/authorization-session";
2
2
  import { NextResponse } from "next/server";
3
3
  import { readFile, stat } from "fs/promises";
4
4
  import { join } from "path";
@@ -7,7 +7,7 @@ import { withRateLimitTier } from "@nextsparkjs/core/lib/api/rate-limit";
7
7
  import { corsPreflight } from "@nextsparkjs/core/lib/api/cors-response";
8
8
  export const GET = withRateLimitTier(async (request, { params }) => {
9
9
  try {
10
- const session = await getTypedSession(request.headers);
10
+ const session = await getAuthorizationSession(request.headers);
11
11
  if (!(session == null ? void 0 : session.user) || session.user.role !== "developer") {
12
12
  return NextResponse.json(
13
13
  {
@@ -1,4 +1,4 @@
1
- import { getTypedSession } from "@nextsparkjs/core/lib/auth";
1
+ import { getAuthorizationSession } from "@nextsparkjs/core/lib/auth/authorization-session";
2
2
  import { NextResponse } from "next/server";
3
3
  import { readdir, stat } from "fs/promises";
4
4
  import { join } from "path";
@@ -35,7 +35,7 @@ async function buildFileTree(dirPath, basePath) {
35
35
  }
36
36
  export const GET = withRateLimitTier(async (request) => {
37
37
  try {
38
- const session = await getTypedSession(request.headers);
38
+ const session = await getAuthorizationSession(request.headers);
39
39
  if (!(session == null ? void 0 : session.user) || session.user.role !== "developer") {
40
40
  return NextResponse.json(
41
41
  {
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../src/routes/api/mcp/route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAOvD,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAA;AAoIvE,eAAO,MAAM,IAAI,iDAA0C,CAAA;AAE3D,wBAAsB,GAAG,IAAI,OAAO,CAAC,YAAY,CAAC,CAKjD;AAED,wBAAsB,MAAM,IAAI,OAAO,CAAC,YAAY,CAAC,CAKpD;AAED,eAAO,MAAM,OAAO,sBAAgB,CAAA"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../src/routes/api/mcp/route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAOvD,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAA;AA2IvE,eAAO,MAAM,IAAI,iDAA0C,CAAA;AAE3D,wBAAsB,GAAG,IAAI,OAAO,CAAC,YAAY,CAAC,CAKjD;AAED,wBAAsB,MAAM,IAAI,OAAO,CAAC,YAAY,CAAC,CAKpD;AAED,eAAO,MAAM,OAAO,sBAAgB,CAAA"}
@@ -7,7 +7,7 @@ import { validateApiKey } from "@nextsparkjs/core/lib/api/auth";
7
7
  import { withRateLimitTier } from "@nextsparkjs/core/lib/api/rate-limit";
8
8
  import { corsPreflight } from "@nextsparkjs/core/lib/api/cors-response";
9
9
  import { setEntityRegistry } from "@nextsparkjs/core/lib/entities/queries";
10
- import { createMcpEngine } from "@nextsparkjs/core/lib/mcp";
10
+ import { createMcpEngine, RATE_LIMIT_MESSAGE } from "@nextsparkjs/core/lib/mcp";
11
11
  import { ENTITY_REGISTRY, ENTITY_METADATA } from "@nextsparkjs/registries/entity-registry";
12
12
  import { MCP_OVERRIDES } from "@nextsparkjs/registries/mcp-registry";
13
13
  import { API_PRESETS_REGISTRY } from "@nextsparkjs/registries/api-presets-registry";
@@ -56,6 +56,12 @@ async function handleMcpPost(request) {
56
56
  return jsonRpcError(403, -32e3, "Origin not allowed");
57
57
  }
58
58
  const authResult = await authenticateRequest(request, { allowAnyScope: true });
59
+ if (authResult.rateLimitResponse) {
60
+ const limited = jsonRpcError(429, -32e3, RATE_LIMIT_MESSAGE);
61
+ const retryAfter = authResult.rateLimitResponse.headers.get("Retry-After");
62
+ if (retryAfter) limited.headers.set("Retry-After", retryAfter);
63
+ return limited;
64
+ }
59
65
  if (!authResult.success || authResult.type !== "api-key" || !authResult.user) {
60
66
  return jsonRpcError(401, -32001, API_KEY_HELP);
61
67
  }
@@ -1,5 +1,5 @@
1
1
  import { NextResponse } from "next/server";
2
- import { getTypedSession } from "@nextsparkjs/core/lib/auth";
2
+ import { getAuthorizationSession } from "@nextsparkjs/core/lib/auth/authorization-session";
3
3
  import { queryWithRLS } from "@nextsparkjs/core/lib/db";
4
4
  import { withRateLimitTier } from "@nextsparkjs/core/lib/api/rate-limit";
5
5
  import { corsPreflight } from "@nextsparkjs/core/lib/api/cors-response";
@@ -7,7 +7,7 @@ import { getBillingGateway } from "@nextsparkjs/core/lib/billing/gateways/factor
7
7
  export const GET = withRateLimitTier(async (request) => {
8
8
  var _a;
9
9
  try {
10
- const session = await getTypedSession(request.headers);
10
+ const session = await getAuthorizationSession(request.headers);
11
11
  if (!(session == null ? void 0 : session.user)) {
12
12
  return NextResponse.json(
13
13
  { error: "Unauthorized - No session found" },
@@ -1,5 +1,5 @@
1
1
  import { NextResponse } from "next/server";
2
- import { getTypedSession } from "@nextsparkjs/core/lib/auth";
2
+ import { getAuthorizationSession } from "@nextsparkjs/core/lib/auth/authorization-session";
3
3
  import { queryWithRLS } from "@nextsparkjs/core/lib/db";
4
4
  import { withRateLimitTier } from "@nextsparkjs/core/lib/api/rate-limit";
5
5
  import { corsPreflight } from "@nextsparkjs/core/lib/api/cors-response";
@@ -8,7 +8,7 @@ export const GET = withRateLimitTier(async (request, { params }) => {
8
8
  var _a;
9
9
  try {
10
10
  const { teamId } = await params;
11
- const session = await getTypedSession(request.headers);
11
+ const session = await getAuthorizationSession(request.headers);
12
12
  if (!(session == null ? void 0 : session.user)) {
13
13
  return NextResponse.json(
14
14
  { error: "Unauthorized - No session found" },
@@ -1,5 +1,5 @@
1
1
  import { NextResponse } from "next/server";
2
- import { getTypedSession } from "@nextsparkjs/core/lib/auth";
2
+ import { getAuthorizationSession } from "@nextsparkjs/core/lib/auth/authorization-session";
3
3
  import { queryWithRLS } from "@nextsparkjs/core/lib/db";
4
4
  import { SYSTEM_ADMIN_TEAM_ID } from "@nextsparkjs/core/lib/api/auth/dual-auth";
5
5
  import { withRateLimitTier } from "@nextsparkjs/core/lib/api/rate-limit";
@@ -7,7 +7,7 @@ import { corsPreflight } from "@nextsparkjs/core/lib/api/cors-response";
7
7
  export const GET = withRateLimitTier(async (request) => {
8
8
  var _a, _b, _c, _d;
9
9
  try {
10
- const session = await getTypedSession(request.headers);
10
+ const session = await getAuthorizationSession(request.headers);
11
11
  if (!(session == null ? void 0 : session.user)) {
12
12
  return NextResponse.json(
13
13
  { error: "Unauthorized - No session found" },
@@ -24,10 +24,12 @@ export declare const GET: (request: NextRequest, args_0: RouteParams) => Promise
24
24
  * Only accessible by superadmin or developer users.
25
25
  *
26
26
  * Actions:
27
- * - change-role: Change user's role (requires 'role' field)
28
- * - suspend: Suspend the user (sets role to 'suspended')
29
- * - unsuspend: Restore user's role to 'member'
27
+ * - change-role: Change user's role (requires 'role' field: member, or developer when a superadmin asks)
28
+ * - suspend: Suspend the user (role 'suspended'), sign out all their sessions and deactivate their API keys
29
+ * - unsuspend: Give a suspended user back the 'member' role (their API keys stay deactivated)
30
30
  * - verify-email: Manually verify user's email
31
+ *
32
+ * Nobody can act on their own account or on a superadmin, so the last superadmin is never suspended.
31
33
  */
32
34
  export declare const PATCH: (request: NextRequest, args_0: RouteParams) => Promise<NextResponse>;
33
35
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../src/routes/api/superadmin/users/[userId]/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIxD,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AA+BxE,UAAU,WAAW;IACnB,MAAM,EAAE,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACrC;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,GAAG,sEA6KJ,CAAC;AAOb;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,KAAK,sEA+JN,CAAC;AAEb;;;;;;;;;;GAUG;AACH,eAAO,MAAM,MAAM,sEAgIP,CAAC;AAEb,eAAO,MAAM,OAAO,sBAAgB,CAAC"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../src/routes/api/superadmin/users/[userId]/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAKxD,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AA+BxE,UAAU,WAAW;IACnB,MAAM,EAAE,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACrC;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,GAAG,sEA6KJ,CAAC;AAOb;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,KAAK,sEAuLN,CAAC;AAEb;;;;;;;;;;GAUG;AACH,eAAO,MAAM,MAAM,sEAgIP,CAAC;AAEb,eAAO,MAAM,OAAO,sBAAgB,CAAC"}
@@ -1,11 +1,12 @@
1
1
  import { NextResponse } from "next/server";
2
- import { getTypedSession } from "@nextsparkjs/core/lib/auth";
2
+ import { getAuthorizationSession } from "@nextsparkjs/core/lib/auth/authorization-session";
3
+ import { suspendUser, unsuspendUser } from "@nextsparkjs/core/lib/auth/suspension";
3
4
  import { queryWithRLS } from "@nextsparkjs/core/lib/db";
4
5
  import { withRateLimitTier } from "@nextsparkjs/core/lib/api/rate-limit";
5
6
  import { corsPreflight } from "@nextsparkjs/core/lib/api/cors-response";
6
7
  export const GET = withRateLimitTier(async (request, { params }) => {
7
8
  try {
8
- const session = await getTypedSession(request.headers);
9
+ const session = await getAuthorizationSession(request.headers);
9
10
  if (!(session == null ? void 0 : session.user)) {
10
11
  return NextResponse.json(
11
12
  { error: "Unauthorized - No session found" },
@@ -137,7 +138,7 @@ export const GET = withRateLimitTier(async (request, { params }) => {
137
138
  }, "strict");
138
139
  export const PATCH = withRateLimitTier(async (request, { params }) => {
139
140
  try {
140
- const session = await getTypedSession(request.headers);
141
+ const session = await getAuthorizationSession(request.headers);
141
142
  if (!(session == null ? void 0 : session.user)) {
142
143
  return NextResponse.json(
143
144
  { error: "Unauthorized - No session found" },
@@ -192,12 +193,24 @@ export const PATCH = withRateLimitTier(async (request, { params }) => {
192
193
  let updateParams = [];
193
194
  switch (action) {
194
195
  case "change-role":
195
- if (!role || !["member", "colaborator", "admin"].includes(role)) {
196
+ if (!role || !["member", "developer"].includes(role)) {
196
197
  return NextResponse.json(
197
- { error: "Invalid role. Must be one of: member, colaborator, admin" },
198
+ { error: "Invalid role. Must be one of: member, developer" },
198
199
  { status: 400 }
199
200
  );
200
201
  }
202
+ if (targetUser.role === "suspended") {
203
+ return NextResponse.json(
204
+ { error: "User is suspended. Use the unsuspend action to restore access, then change the role" },
205
+ { status: 400 }
206
+ );
207
+ }
208
+ if (role === "developer" && session.user.role !== "superadmin") {
209
+ return NextResponse.json(
210
+ { error: "Forbidden - Only a superadmin can grant the developer role" },
211
+ { status: 403 }
212
+ );
213
+ }
201
214
  updateQuery = `
202
215
  UPDATE "users"
203
216
  SET role = $1, "updatedAt" = NOW()
@@ -206,24 +219,34 @@ export const PATCH = withRateLimitTier(async (request, { params }) => {
206
219
  `;
207
220
  updateParams = [role, userId];
208
221
  break;
209
- case "suspend":
210
- updateQuery = `
211
- UPDATE "users"
212
- SET role = 'suspended', "updatedAt" = NOW()
213
- WHERE id = $1
214
- RETURNING id, role
215
- `;
216
- updateParams = [userId];
217
- break;
222
+ case "suspend": {
223
+ const suspended = await suspendUser(userId, session.user.id);
224
+ if (!suspended) {
225
+ return NextResponse.json({ error: "Failed to update user" }, { status: 500 });
226
+ }
227
+ return NextResponse.json({
228
+ success: true,
229
+ action,
230
+ userId,
231
+ message: `User ${action} successful`,
232
+ revoked: suspended,
233
+ metadata: { performedBy: session.user.id, performedAt: (/* @__PURE__ */ new Date()).toISOString(), source: "superadmin-api" }
234
+ });
235
+ }
218
236
  case "unsuspend":
219
- updateQuery = `
220
- UPDATE "users"
221
- SET role = 'member', "updatedAt" = NOW()
222
- WHERE id = $1
223
- RETURNING id, role
224
- `;
225
- updateParams = [userId];
226
- break;
237
+ if (targetUser.role !== "suspended") {
238
+ return NextResponse.json({ error: "User is not suspended" }, { status: 400 });
239
+ }
240
+ if (!await unsuspendUser(userId, session.user.id)) {
241
+ return NextResponse.json({ error: "Failed to update user" }, { status: 500 });
242
+ }
243
+ return NextResponse.json({
244
+ success: true,
245
+ action,
246
+ userId,
247
+ message: `User ${action} successful`,
248
+ metadata: { performedBy: session.user.id, performedAt: (/* @__PURE__ */ new Date()).toISOString(), source: "superadmin-api" }
249
+ });
227
250
  case "verify-email":
228
251
  updateQuery = `
229
252
  UPDATE "users"
@@ -265,7 +288,7 @@ export const PATCH = withRateLimitTier(async (request, { params }) => {
265
288
  }, "strict");
266
289
  export const DELETE = withRateLimitTier(async (request, { params }) => {
267
290
  try {
268
- const session = await getTypedSession(request.headers);
291
+ const session = await getAuthorizationSession(request.headers);
269
292
  if (!(session == null ? void 0 : session.user)) {
270
293
  return NextResponse.json(
271
294
  { error: "Unauthorized - No session found" },
@@ -1,12 +1,12 @@
1
1
  import { NextResponse } from "next/server";
2
- import { getTypedSession } from "@nextsparkjs/core/lib/auth";
2
+ import { getAuthorizationSession } from "@nextsparkjs/core/lib/auth/authorization-session";
3
3
  import { queryWithRLS } from "@nextsparkjs/core/lib/db";
4
4
  import { withRateLimitTier } from "@nextsparkjs/core/lib/api/rate-limit";
5
5
  import { corsPreflight } from "@nextsparkjs/core/lib/api/cors-response";
6
6
  export const GET = withRateLimitTier(async (request) => {
7
7
  var _a, _b, _c;
8
8
  try {
9
- const session = await getTypedSession(request.headers);
9
+ const session = await getAuthorizationSession(request.headers);
10
10
  if (!(session == null ? void 0 : session.user)) {
11
11
  return NextResponse.json(
12
12
  { error: "Unauthorized - No session found" },
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/routes/api/user/delete-account/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGxD,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AAGxE,eAAO,MAAM,MAAM,iDAoDP,CAAC;AAEb,eAAO,MAAM,OAAO,sBAAgB,CAAC"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/routes/api/user/delete-account/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIxD,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AAGxE,eAAO,MAAM,MAAM,iDAkDP,CAAC;AAEb,eAAO,MAAM,OAAO,sBAAgB,CAAC"}
@@ -1,13 +1,12 @@
1
1
  import { NextResponse } from "next/server";
2
2
  import { auth } from "@nextsparkjs/core/lib/auth";
3
+ import { getAuthorizationSession } from "@nextsparkjs/core/lib/auth/authorization-session";
3
4
  import { withRateLimitTier } from "@nextsparkjs/core/lib/api/rate-limit";
4
5
  import { corsPreflight } from "@nextsparkjs/core/lib/api/cors-response";
5
6
  import { UserService } from "@nextsparkjs/core/lib/services";
6
7
  export const DELETE = withRateLimitTier(async (req) => {
7
8
  try {
8
- const session = await auth.api.getSession({
9
- headers: req.headers
10
- });
9
+ const session = await getAuthorizationSession(req.headers);
11
10
  if (!(session == null ? void 0 : session.user)) {
12
11
  return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
13
12
  }
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/routes/api/user/plan-flags/route.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAMvD,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAA;AAavE;;;GAGG;AACH,eAAO,MAAM,GAAG,iDAwDN,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,KAAK,iDAgFP,CAAC;AAEZ;;;GAGG;AACH,eAAO,MAAM,IAAI,iDA4FL,CAAC;AAEb,eAAO,MAAM,OAAO,sBAAgB,CAAA"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/routes/api/user/plan-flags/route.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAMvD,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAA;AAavE;;;GAGG;AACH,eAAO,MAAM,GAAG,iDAyDN,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,KAAK,iDAgFP,CAAC;AAEZ;;;GAGG;AACH,eAAO,MAAM,IAAI,iDA4FL,CAAC;AAEb,eAAO,MAAM,OAAO,sBAAgB,CAAA"}
@@ -1,5 +1,5 @@
1
1
  import { NextResponse } from "next/server";
2
- import { getTypedSession } from "@nextsparkjs/core/lib/auth";
2
+ import { getAuthorizationSession } from "@nextsparkjs/core/lib/auth/authorization-session";
3
3
  import { getUserPlanAndFlags, updateUserPlan, updateUserFlags } from "@nextsparkjs/core/lib/user-data";
4
4
  import * as z from "zod";
5
5
  import { withRateLimitTier } from "@nextsparkjs/core/lib/api/rate-limit";
@@ -14,7 +14,7 @@ const planFlagsUpdateSchema = z.object({
14
14
  });
15
15
  export const GET = withRateLimitTier(async (request) => {
16
16
  try {
17
- const session = await getTypedSession(request.headers);
17
+ const session = await getAuthorizationSession(request.headers);
18
18
  if (!session) {
19
19
  return NextResponse.json(
20
20
  { error: "Authentication required" },
@@ -23,7 +23,7 @@ export const GET = withRateLimitTier(async (request) => {
23
23
  }
24
24
  const { searchParams } = new URL(request.url);
25
25
  const validation = planFlagsQuerySchema.safeParse({
26
- userId: searchParams.get("userId")
26
+ userId: searchParams.get("userId") ?? void 0
27
27
  });
28
28
  if (!validation.success) {
29
29
  return NextResponse.json(
@@ -60,7 +60,7 @@ export const GET = withRateLimitTier(async (request) => {
60
60
  }, "read");
61
61
  export const PATCH = withRateLimitTier(async (request) => {
62
62
  try {
63
- const session = await getTypedSession(request.headers);
63
+ const session = await getAuthorizationSession(request.headers);
64
64
  if (!session) {
65
65
  return NextResponse.json(
66
66
  { error: "Authentication required" },
@@ -125,7 +125,7 @@ export const PATCH = withRateLimitTier(async (request) => {
125
125
  }, "write");
126
126
  export const POST = withRateLimitTier(async (request) => {
127
127
  try {
128
- const session = await getTypedSession(request.headers);
128
+ const session = await getAuthorizationSession(request.headers);
129
129
  if (!session) {
130
130
  return NextResponse.json(
131
131
  { error: "Authentication required" },
@@ -1,5 +1,5 @@
1
1
  import { NextResponse } from "next/server";
2
- import { auth } from "@nextsparkjs/core/lib/auth";
2
+ import { getAuthorizationSession } from "@nextsparkjs/core/lib/auth/authorization-session";
3
3
  import { queryOneWithRLS, mutateWithRLS, queryOne } from "@nextsparkjs/core/lib/db";
4
4
  import { profileSchema } from "@nextsparkjs/core/lib/validation";
5
5
  import { MetaService, MetaValueTooLargeError } from "@nextsparkjs/core/lib/services/meta.service";
@@ -10,7 +10,7 @@ export const GET = withRateLimitTier(async (request) => {
10
10
  const includeMeta = url.searchParams.get("includeMeta") === "true";
11
11
  try {
12
12
  const sessionHeaders = request.headers;
13
- const session = await auth.api.getSession({ headers: sessionHeaders });
13
+ const session = await getAuthorizationSession(sessionHeaders);
14
14
  if (!(session == null ? void 0 : session.user)) {
15
15
  return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
16
16
  }
@@ -44,7 +44,7 @@ export const GET = withRateLimitTier(async (request) => {
44
44
  export const PATCH = withRateLimitTier(async (request) => {
45
45
  try {
46
46
  const sessionHeaders = request.headers;
47
- const session = await auth.api.getSession({ headers: sessionHeaders });
47
+ const session = await getAuthorizationSession(sessionHeaders);
48
48
  if (!(session == null ? void 0 : session.user)) {
49
49
  return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
50
50
  }
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../src/routes/api/v1/auth/signup-with-invite/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAkBvD,wBAAsB,OAAO,CAAC,OAAO,EAAE,WAAW,kCAEjD;AAWD,eAAO,MAAM,IAAI,iDA8NP,CAAA"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../src/routes/api/v1/auth/signup-with-invite/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAkBvD,wBAAsB,OAAO,CAAC,OAAO,EAAE,WAAW,kCAEjD;AAYD,eAAO,MAAM,IAAI,iDAsQP,CAAA"}
@@ -19,20 +19,12 @@ export const POST = withRateLimitTier(withApiLogging(
19
19
  async (req) => {
20
20
  var _a, _b;
21
21
  try {
22
- if (!isPasswordLoginEnabled(AUTH_CONFIG)) {
23
- const response = createApiError(
24
- "Password authentication is unavailable",
25
- 503,
26
- null,
27
- "AUTH_METHOD_UNAVAILABLE"
28
- );
29
- return addCorsHeaders(response, req);
30
- }
22
+ const passwordLogin = isPasswordLoginEnabled(AUTH_CONFIG);
31
23
  const body = await req.json();
32
24
  const { email, password, firstName, lastName, inviteToken } = body;
33
- if (!email || !password || !inviteToken) {
25
+ if (!email || passwordLogin && !password || !inviteToken) {
34
26
  const response = createApiError(
35
- "Email, password, and invitation token are required",
27
+ passwordLogin ? "Email, password, and invitation token are required" : "Email and invitation token are required",
36
28
  400,
37
29
  null,
38
30
  "MISSING_FIELDS"
@@ -44,7 +36,7 @@ export const POST = withRateLimitTier(withApiLogging(
44
36
  const response = createApiError("Invalid email format", 400, null, "INVALID_EMAIL");
45
37
  return addCorsHeaders(response, req);
46
38
  }
47
- if (password.length < 8) {
39
+ if (passwordLogin && password.length < 8) {
48
40
  const response = createApiError(
49
41
  "Password must be at least 8 characters",
50
42
  400,
@@ -86,45 +78,89 @@ export const POST = withRateLimitTier(withApiLogging(
86
78
  const response = createApiError("Invitation has expired", 410, null, "INVITATION_EXPIRED");
87
79
  return addCorsHeaders(response, req);
88
80
  }
89
- const signUpRequest = new Request(`${process.env.NEXT_PUBLIC_APP_URL}${withBasePath("/api/auth/sign-up/email")}`, {
90
- method: "POST",
91
- headers: {
92
- "Content-Type": "application/json"
93
- },
94
- body: JSON.stringify({
95
- email,
96
- password,
97
- name: firstName && lastName ? `${firstName} ${lastName}` : firstName || "",
98
- firstName,
99
- lastName,
100
- language: I18N_CONFIG.defaultLocale
101
- })
102
- });
103
- const signUpResponse = await withSignupContext(
104
- { skipTeamCreation: true, invitedTeamId: invitation.teamId },
105
- () => auth.handler(signUpRequest)
106
- );
107
- if (!signUpResponse.ok) {
108
- const errorData = await signUpResponse.json();
109
- if (((_a = errorData.message) == null ? void 0 : _a.includes("already exists")) || errorData.code === "USER_ALREADY_EXISTS") {
110
- const response2 = createApiError(
81
+ let userId;
82
+ const signupContext = { skipTeamCreation: true, invitedTeamId: invitation.teamId };
83
+ const name = firstName && lastName ? `${firstName} ${lastName}` : firstName || "";
84
+ if (passwordLogin) {
85
+ const signUpRequest = new Request(`${process.env.NEXT_PUBLIC_APP_URL}${withBasePath("/api/auth/sign-up/email")}`, {
86
+ method: "POST",
87
+ headers: {
88
+ "Content-Type": "application/json"
89
+ },
90
+ body: JSON.stringify({
91
+ email,
92
+ password,
93
+ name,
94
+ firstName,
95
+ lastName,
96
+ language: I18N_CONFIG.defaultLocale
97
+ })
98
+ });
99
+ const signUpResponse = await withSignupContext(signupContext, () => auth.handler(signUpRequest));
100
+ if (!signUpResponse.ok) {
101
+ const errorData = await signUpResponse.json();
102
+ if (((_a = errorData.message) == null ? void 0 : _a.includes("already exists")) || errorData.code === "USER_ALREADY_EXISTS") {
103
+ const response2 = createApiError(
104
+ "An account with this email already exists. Please sign in instead.",
105
+ 409,
106
+ null,
107
+ "USER_ALREADY_EXISTS"
108
+ );
109
+ return addCorsHeaders(response2, req);
110
+ }
111
+ const response = createApiError(
112
+ errorData.message || "Failed to create account",
113
+ signUpResponse.status,
114
+ null,
115
+ "SIGNUP_FAILED"
116
+ );
117
+ return addCorsHeaders(response, req);
118
+ }
119
+ const signUpData = await signUpResponse.json();
120
+ userId = (_b = signUpData.user) == null ? void 0 : _b.id;
121
+ } else {
122
+ const { internalAdapter } = await auth.$context;
123
+ if (await internalAdapter.findUserByEmail(email.toLowerCase())) {
124
+ const response = createApiError(
111
125
  "An account with this email already exists. Please sign in instead.",
112
126
  409,
113
127
  null,
114
128
  "USER_ALREADY_EXISTS"
115
129
  );
116
- return addCorsHeaders(response2, req);
130
+ return addCorsHeaders(response, req);
117
131
  }
118
- const response = createApiError(
119
- errorData.message || "Failed to create account",
120
- signUpResponse.status,
121
- null,
122
- "SIGNUP_FAILED"
123
- );
124
- return addCorsHeaders(response, req);
132
+ let user;
133
+ try {
134
+ user = await withSignupContext(signupContext, () => internalAdapter.createUser({
135
+ email: email.toLowerCase(),
136
+ emailVerified: true,
137
+ name,
138
+ firstName,
139
+ lastName,
140
+ language: I18N_CONFIG.defaultLocale
141
+ }));
142
+ } catch (error) {
143
+ const message = error instanceof Error ? error.message : "";
144
+ const refused = /^(DOMAIN_NOT_ALLOWED|SIGNUP_RESTRICTED): (.*)$/s.exec(message);
145
+ if (refused) {
146
+ return addCorsHeaders(createApiError(refused[2], 403, null, refused[1]), req);
147
+ }
148
+ if (error.code === "23505" || /duplicate key/i.test(message)) {
149
+ const response = createApiError(
150
+ "An account with this email already exists. Please sign in instead.",
151
+ 409,
152
+ null,
153
+ "USER_ALREADY_EXISTS"
154
+ );
155
+ return addCorsHeaders(response, req);
156
+ }
157
+ throw error;
158
+ }
159
+ if (!user) {
160
+ return addCorsHeaders(createApiError("Account creation was refused", 403, null, "SIGNUP_FAILED"), req);
161
+ }
162
+ userId = user.id;
125
163
  }
126
- const signUpData = await signUpResponse.json();
127
- const userId = (_b = signUpData.user) == null ? void 0 : _b.id;
128
164
  if (!userId) {
129
165
  const response = createApiError(
130
166
  "Failed to create account - no user ID returned",
@@ -7,7 +7,8 @@ import { corsPreflight } from '@nextsparkjs/core/lib/api/cors-response';
7
7
  * Enhanced version that creates database records for uploaded files.
8
8
  *
9
9
  * Features:
10
- * - Uploads files to Vercel Blob (production) or local storage (development)
10
+ * - Uploads files to Vercel Blob; development without a token falls back to local storage,
11
+ * production without one answers 503 STORAGE_NOT_CONFIGURED
11
12
  * - Creates media records in database for tracking
12
13
  * - Extracts image dimensions automatically
13
14
  * - Returns both legacy URLs array and new media records array
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../src/routes/api/v1/media/upload/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAOzC,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAA;AAkCvE;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,IAAI,uEA0KN,CAAC;AAEZ;;;;GAIG;AACH,eAAO,MAAM,GAAG,uEA0CN,CAAC;AAEX,eAAO,MAAM,OAAO,sBAAgB,CAAA"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../src/routes/api/v1/media/upload/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAOzC,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAA;AA8CvE;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,IAAI,uEA6KN,CAAC;AAEZ;;;;GAIG;AACH,eAAO,MAAM,GAAG,uEA0CN,CAAC;AAEX,eAAO,MAAM,OAAO,sBAAgB,CAAA"}
@@ -15,6 +15,13 @@ const isVercelBlobConfigured = () => {
15
15
  const token = process.env.BLOB_READ_WRITE_TOKEN;
16
16
  return !!token && token.startsWith("vercel_blob_");
17
17
  };
18
+ const localFallbackAllowed = () => process.env.NODE_ENV !== "production";
19
+ const storageNotConfigured = () => createApiError(
20
+ 'Media storage is not configured: set BLOB_READ_WRITE_TOKEN (a Vercel Blob read/write token, starts with "vercel_blob_") to upload files in production.',
21
+ 503,
22
+ { missing: "BLOB_READ_WRITE_TOKEN" },
23
+ API_ERROR_CODES.STORAGE_NOT_CONFIGURED
24
+ );
18
25
  async function uploadToLocalStorageBuffer(buffer, fileName) {
19
26
  const uploadDir = join(process.cwd(), "public", "uploads", "temp");
20
27
  if (!existsSync(uploadDir)) {
@@ -37,6 +44,7 @@ export const POST = withRateLimitTier(async (request) => {
37
44
  if (!await checkPermission(authResult.user.id, teamId, "media.upload")) {
38
45
  return createApiError("Permission denied", 403, void 0, API_ERROR_CODES.PERMISSION_DENIED);
39
46
  }
47
+ if (!isVercelBlobConfigured() && !localFallbackAllowed()) return storageNotConfigured();
40
48
  const formData = await request.formData();
41
49
  const files = Array.from(formData.getAll("files")).filter((value) => value instanceof File);
42
50
  if (files.length === 0) {
@@ -46,7 +54,6 @@ export const POST = withRateLimitTier(async (request) => {
46
54
  const uploadedMedia = [];
47
55
  const useVercelBlob = isVercelBlobConfigured();
48
56
  console.log(`\u{1F4E4} [Media Upload] Storage mode: ${useVercelBlob ? "Vercel Blob" : "Local Storage"}`);
49
- console.log(`\u{1F4E4} [Media Upload] Team context: ${teamId}`);
50
57
  for (const file of files) {
51
58
  if (!file.size) {
52
59
  continue;
@@ -101,6 +108,7 @@ export const POST = withRateLimitTier(async (request) => {
101
108
  uploadedUrl = blob.url;
102
109
  console.log(`\u2705 [Media Upload] Uploaded to Vercel Blob: ${uploadedUrl}`);
103
110
  } catch (blobError) {
111
+ if (!localFallbackAllowed()) throw blobError;
104
112
  console.warn(`\u26A0\uFE0F [Media Upload] Vercel Blob failed, falling back to local storage:`, blobError);
105
113
  uploadedUrl = await uploadToLocalStorageBuffer(fileBuffer, fileName);
106
114
  console.log(`\u2705 [Media Upload] Uploaded to local storage (fallback): ${uploadedUrl}`);
@@ -179,7 +187,7 @@ export const GET = withRateLimitTier(async (request) => {
179
187
  const maxSizeMB = ((_a = MEDIA_CONFIG) == null ? void 0 : _a.maxSizeMB) ?? 10;
180
188
  return createApiResponse({
181
189
  message: "Media upload endpoint is active",
182
- storage: useVercelBlob ? "Vercel Blob" : "Local Storage",
190
+ storage: useVercelBlob ? "Vercel Blob" : localFallbackAllowed() ? "Local Storage" : "Not configured (set BLOB_READ_WRITE_TOKEN)",
183
191
  uploadPath: "uploads/temp/",
184
192
  supportedTypes: ((_b = MEDIA_CONFIG) == null ? void 0 : _b.allowedMimeTypes) ?? ["image/jpeg", "image/png", "image/gif", "image/webp", "video/mp4", "video/webm"],
185
193
  maxFileSize: `${maxSizeMB}MB`,
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../src/routes/api/v1/post-categories/[id]/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAKvD,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAA;AAevE,eAAO,MAAM,GAAG;YAEQ,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;2BAyBrC,CAAC;AAGX,eAAO,MAAM,GAAG;YAEQ,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;2BAwIpC,CAAC;AAGZ,eAAO,MAAM,MAAM;YAEK,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;2BAiEpC,CAAC;AAEZ,eAAO,MAAM,OAAO,sBAAgB,CAAA"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../src/routes/api/v1/post-categories/[id]/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAKvD,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAA;AAiCvE,eAAO,MAAM,GAAG;YAEQ,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;2BA2BrC,CAAC;AAIX,eAAO,MAAM,GAAG;YAEQ,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;2BA+HpC,CAAC;AAIZ,eAAO,MAAM,MAAM;YAEK,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;2BAuDpC,CAAC;AAEZ,eAAO,MAAM,OAAO,sBAAgB,CAAA"}