nextly 0.0.1 → 0.0.2-alpha.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 (268) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +122 -0
  3. package/dist/_dts-chunks/collections-handler.d-DjgO74Wt.d.ts +20540 -0
  4. package/dist/_dts-chunks/config.d-DNwsDnjs.d.ts +2589 -0
  5. package/dist/_dts-chunks/define-component.d-BUgTHmt3.d.ts +1149 -0
  6. package/dist/_dts-chunks/image-processor.d-OO1PmMrv.d.ts +335 -0
  7. package/dist/_dts-chunks/index.d-axCAzZ7m.d.ts +17842 -0
  8. package/dist/_dts-chunks/media.d-DjDOZo4B.d.ts +117 -0
  9. package/dist/_dts-chunks/on-error.d-CHIKWNxd.d.ts +38 -0
  10. package/dist/_dts-chunks/storage.d-BUhQ2we_.d.ts +404 -0
  11. package/dist/actions/index.d.ts +239 -0
  12. package/dist/actions/index.mjs +281 -0
  13. package/dist/api/auth-state.d.ts +5 -0
  14. package/dist/api/auth-state.mjs +131 -0
  15. package/dist/api/collections-schema-detail.d.ts +56 -0
  16. package/dist/api/collections-schema-detail.mjs +244 -0
  17. package/dist/api/collections-schema-export.d.ts +56 -0
  18. package/dist/api/collections-schema-export.mjs +129 -0
  19. package/dist/api/collections-schema.d.ts +59 -0
  20. package/dist/api/collections-schema.mjs +207 -0
  21. package/dist/api/components-detail.d.ts +50 -0
  22. package/dist/api/components-detail.mjs +132 -0
  23. package/dist/api/components.d.ts +69 -0
  24. package/dist/api/components.mjs +144 -0
  25. package/dist/api/email-providers-default.d.ts +40 -0
  26. package/dist/api/email-providers-default.mjs +75 -0
  27. package/dist/api/email-providers-detail.d.ts +81 -0
  28. package/dist/api/email-providers-detail.mjs +109 -0
  29. package/dist/api/email-providers-test.d.ts +43 -0
  30. package/dist/api/email-providers-test.mjs +114 -0
  31. package/dist/api/email-providers.d.ts +69 -0
  32. package/dist/api/email-providers.mjs +110 -0
  33. package/dist/api/email-send-template.d.ts +41 -0
  34. package/dist/api/email-send-template.mjs +58 -0
  35. package/dist/api/email-send.d.ts +42 -0
  36. package/dist/api/email-send.mjs +58 -0
  37. package/dist/api/email-templates-detail.d.ts +74 -0
  38. package/dist/api/email-templates-detail.mjs +112 -0
  39. package/dist/api/email-templates-layout.d.ts +55 -0
  40. package/dist/api/email-templates-layout.mjs +92 -0
  41. package/dist/api/email-templates-preview.d.ts +48 -0
  42. package/dist/api/email-templates-preview.mjs +93 -0
  43. package/dist/api/email-templates.d.ts +61 -0
  44. package/dist/api/email-templates.mjs +118 -0
  45. package/dist/api/health.d.ts +68 -0
  46. package/dist/api/health.mjs +67 -0
  47. package/dist/api/index.d.ts +54 -0
  48. package/dist/api/index.mjs +16 -0
  49. package/dist/api/media-bulk.d.ts +74 -0
  50. package/dist/api/media-bulk.mjs +196 -0
  51. package/dist/api/media-folders.d.ts +112 -0
  52. package/dist/api/media-folders.mjs +187 -0
  53. package/dist/api/media-handlers.d.ts +102 -0
  54. package/dist/api/media-handlers.mjs +437 -0
  55. package/dist/api/media.d.ts +117 -0
  56. package/dist/api/media.mjs +242 -0
  57. package/dist/api/singles-detail.d.ts +87 -0
  58. package/dist/api/singles-detail.mjs +170 -0
  59. package/dist/api/singles-schema-detail.d.ts +54 -0
  60. package/dist/api/singles-schema-detail.mjs +182 -0
  61. package/dist/api/singles.d.ts +34 -0
  62. package/dist/api/singles.mjs +94 -0
  63. package/dist/api/storage-upload-url.d.ts +48 -0
  64. package/dist/api/storage-upload-url.mjs +202 -0
  65. package/dist/api/uploads.d.ts +109 -0
  66. package/dist/api/uploads.mjs +359 -0
  67. package/dist/auth/index.d.ts +425 -0
  68. package/dist/auth/index.mjs +199 -0
  69. package/dist/boot-apply-PQSYLDIN.mjs +7 -0
  70. package/dist/chunk-2OALJTK6.mjs +489 -0
  71. package/dist/chunk-2Q2SX2CS.mjs +365 -0
  72. package/dist/chunk-2TFX4ND3.mjs +13 -0
  73. package/dist/chunk-2TWPDSYD.mjs +87 -0
  74. package/dist/chunk-2W3DVD7S.mjs +647 -0
  75. package/dist/chunk-2ZFKXPQM.mjs +88 -0
  76. package/dist/chunk-3FA7FKAV.mjs +832 -0
  77. package/dist/chunk-3NZ2KMBL.mjs +58 -0
  78. package/dist/chunk-4MJLT6PZ.mjs +0 -0
  79. package/dist/chunk-56WO4WX7.mjs +0 -0
  80. package/dist/chunk-5APFUGAD.mjs +89 -0
  81. package/dist/chunk-5HMZ644B.mjs +108 -0
  82. package/dist/chunk-67GXH6PR.mjs +32 -0
  83. package/dist/chunk-6JNEPWRW.mjs +14368 -0
  84. package/dist/chunk-6NFHQIJD.mjs +45 -0
  85. package/dist/chunk-7P6ASYW6.mjs +9 -0
  86. package/dist/chunk-A3WPLSDT.mjs +1364 -0
  87. package/dist/chunk-AGJ6F2T3.mjs +144 -0
  88. package/dist/chunk-AK6Z23OX.mjs +1464 -0
  89. package/dist/chunk-APKKRD2G.mjs +102 -0
  90. package/dist/chunk-B2GV2BWH.mjs +73 -0
  91. package/dist/chunk-D5HQBNUB.mjs +74 -0
  92. package/dist/chunk-DNNG377Z.mjs +204 -0
  93. package/dist/chunk-DP3G27G5.mjs +135 -0
  94. package/dist/chunk-DV6WVX2Q.mjs +0 -0
  95. package/dist/chunk-DXGGXIUZ.mjs +57 -0
  96. package/dist/chunk-EGXBZCGC.mjs +943 -0
  97. package/dist/chunk-ERCNLX3V.mjs +176 -0
  98. package/dist/chunk-FQULBZ53.mjs +850 -0
  99. package/dist/chunk-G2AA4QLC.mjs +262 -0
  100. package/dist/chunk-GDBJ5JCU.mjs +488 -0
  101. package/dist/chunk-GJNSJU4S.mjs +19 -0
  102. package/dist/chunk-GZ6DCQKC.mjs +69 -0
  103. package/dist/chunk-H26B4FYG.mjs +167 -0
  104. package/dist/chunk-I4JMR3UR.mjs +21 -0
  105. package/dist/chunk-INV7QKLG.mjs +508 -0
  106. package/dist/chunk-IUDOC7N7.mjs +46 -0
  107. package/dist/chunk-IZWPRDC3.mjs +206 -0
  108. package/dist/chunk-KIMNCZGV.mjs +15 -0
  109. package/dist/chunk-L6HW2DA7.mjs +15 -0
  110. package/dist/chunk-LAZXX4HR.mjs +100 -0
  111. package/dist/chunk-LDKCUMHK.mjs +95 -0
  112. package/dist/chunk-LRXMECUA.mjs +0 -0
  113. package/dist/chunk-M52VMPGA.mjs +119 -0
  114. package/dist/chunk-MGUWEEI6.mjs +160 -0
  115. package/dist/chunk-NRUWQ5Z7.mjs +419 -0
  116. package/dist/chunk-NSEFNNU4.mjs +25360 -0
  117. package/dist/chunk-NTHVDFGO.mjs +138 -0
  118. package/dist/chunk-O3QHXMOX.mjs +3166 -0
  119. package/dist/chunk-P7NH2OSC.mjs +2605 -0
  120. package/dist/chunk-PKMABBB5.mjs +184 -0
  121. package/dist/chunk-PWS6XGJK.mjs +76 -0
  122. package/dist/chunk-R6JJQHFC.mjs +20 -0
  123. package/dist/chunk-RJLLGGPG.mjs +0 -0
  124. package/dist/chunk-SBACDPNX.mjs +689 -0
  125. package/dist/chunk-TO5AFLVQ.mjs +124 -0
  126. package/dist/chunk-TS7GHTG2.mjs +5436 -0
  127. package/dist/chunk-UJ2IMJ4W.mjs +133 -0
  128. package/dist/chunk-UOP63Q54.mjs +102 -0
  129. package/dist/chunk-UUOFWCM6.mjs +78 -0
  130. package/dist/chunk-V4EQTOA4.mjs +893 -0
  131. package/dist/chunk-VJ66NCL4.mjs +193 -0
  132. package/dist/chunk-VQJQHVEV.mjs +29 -0
  133. package/dist/chunk-VTJADRO3.mjs +141 -0
  134. package/dist/chunk-VWF3JO32.mjs +0 -0
  135. package/dist/chunk-W4MGXIRR.mjs +27 -0
  136. package/dist/chunk-W5KKPZT5.mjs +1204 -0
  137. package/dist/chunk-WD34YQ6T.mjs +381 -0
  138. package/dist/chunk-WZBYMYVW.mjs +14 -0
  139. package/dist/chunk-X23WKS3Z.mjs +50 -0
  140. package/dist/chunk-X7TXCYYN.mjs +6496 -0
  141. package/dist/chunk-XGI4EMS3.mjs +140 -0
  142. package/dist/chunk-XZKLBMN6.mjs +1153 -0
  143. package/dist/chunk-YB7INWPY.mjs +0 -0
  144. package/dist/chunk-YV4Y7SDL.mjs +83 -0
  145. package/dist/chunk-YZNBLFIW.mjs +1688 -0
  146. package/dist/chunk-YZZCTONM.mjs +263 -0
  147. package/dist/chunk-ZE6A3FYH.mjs +289 -0
  148. package/dist/cli/nextly.mjs +68 -0
  149. package/dist/cli/utils/index.d.ts +449 -0
  150. package/dist/cli/utils/index.mjs +49 -0
  151. package/dist/component-schema-service-5577KVW6.mjs +11 -0
  152. package/dist/config-loader-23YEMC3Z.mjs +23 -0
  153. package/dist/config.d.ts +44 -0
  154. package/dist/config.mjs +109 -0
  155. package/dist/container-ORGFGYSZ.mjs +9 -0
  156. package/dist/database/index.d.ts +12 -0
  157. package/dist/database/index.mjs +40 -0
  158. package/dist/database/seeders/index.d.ts +93 -0
  159. package/dist/database/seeders/index.mjs +47 -0
  160. package/dist/db-sync-demote-LJGKLB3S.mjs +117 -0
  161. package/dist/db-sync-promote-B26VSYQF.mjs +113 -0
  162. package/dist/dev-reload-broadcaster-B73IQ53V.mjs +25 -0
  163. package/dist/dist-M2NOU37V.mjs +19 -0
  164. package/dist/drizzle-kit-lazy-D2M2PXR2.mjs +13 -0
  165. package/dist/dynamic-collection-schema-service-IEXTPIZ7.mjs +8 -0
  166. package/dist/errors/index.d.ts +159 -0
  167. package/dist/errors/index.mjs +10 -0
  168. package/dist/factory-IWMBKUJM.mjs +15 -0
  169. package/dist/first-run-QIVKWJIF.mjs +63 -0
  170. package/dist/fresh-push-NR67DC3R.mjs +8 -0
  171. package/dist/index.d.ts +4175 -0
  172. package/dist/index.mjs +1336 -0
  173. package/dist/local-plugin-PTET4NAT.mjs +7 -0
  174. package/dist/logger-NU46DXNY.mjs +15 -0
  175. package/dist/logger-YE4TC7ZN.mjs +9 -0
  176. package/dist/migration-journal-EP532Y4L.mjs +139 -0
  177. package/dist/migrations/mysql/0000_eager_sentry.sql +174 -0
  178. package/dist/migrations/mysql/0001_soft_giant_girl.sql +27 -0
  179. package/dist/migrations/mysql/0002_media_table.sql +24 -0
  180. package/dist/migrations/mysql/0003_dynamic_singles.sql +37 -0
  181. package/dist/migrations/mysql/0004_dynamic_components.sql +35 -0
  182. package/dist/migrations/mysql/0005_user_management_tables.sql +92 -0
  183. package/dist/migrations/mysql/0006_api_keys.sql +36 -0
  184. package/dist/migrations/mysql/0007_general_settings.sql +20 -0
  185. package/dist/migrations/mysql/0008_site_settings_logo_url.sql +9 -0
  186. package/dist/migrations/mysql/0009_activity_log.sql +30 -0
  187. package/dist/migrations/mysql/0010_site_settings_sidebar.sql +13 -0
  188. package/dist/migrations/mysql/0011_missing_tables_and_columns.sql +54 -0
  189. package/dist/migrations/mysql/0012_image_sizes_and_focal_point.sql +30 -0
  190. package/dist/migrations/mysql/0012_media_folders.sql +43 -0
  191. package/dist/migrations/mysql/0013_user_brute_force_protection.sql +31 -0
  192. package/dist/migrations/mysql/0014_email_template_attachments.sql +12 -0
  193. package/dist/migrations/mysql/0015_media_uploaded_by_nullable.sql +15 -0
  194. package/dist/migrations/mysql/20260429_000000_000_initial_journal.sql +22 -0
  195. package/dist/migrations/mysql/20260501_000000_journal_batch.sql +17 -0
  196. package/dist/migrations/mysql/20260501_000001_audit_log.sql +24 -0
  197. package/dist/migrations/mysql/20260504_000000_nextly_meta.sql +21 -0
  198. package/dist/migrations/mysql/meta/0000_snapshot.json +1005 -0
  199. package/dist/migrations/mysql/meta/0001_snapshot.json +1099 -0
  200. package/dist/migrations/mysql/meta/_journal.json +41 -0
  201. package/dist/migrations/postgresql/0000_misty_king_bedlam.sql +169 -0
  202. package/dist/migrations/postgresql/0001_perpetual_captain_marvel.sql +8 -0
  203. package/dist/migrations/postgresql/0002_sad_spectrum.sql +16 -0
  204. package/dist/migrations/postgresql/0003_hesitant_ultron.sql +17 -0
  205. package/dist/migrations/postgresql/0004_media_table.sql +24 -0
  206. package/dist/migrations/postgresql/0005_media_folders.sql +36 -0
  207. package/dist/migrations/postgresql/0006_dynamic_collections_update.sql +50 -0
  208. package/dist/migrations/postgresql/0007_dynamic_singles.sql +38 -0
  209. package/dist/migrations/postgresql/0008_dynamic_components.sql +37 -0
  210. package/dist/migrations/postgresql/0009_user_management_tables.sql +95 -0
  211. package/dist/migrations/postgresql/0010_api_keys.sql +34 -0
  212. package/dist/migrations/postgresql/0011_general_settings.sql +20 -0
  213. package/dist/migrations/postgresql/0012_site_settings_logo_url.sql +9 -0
  214. package/dist/migrations/postgresql/0013_activity_log.sql +29 -0
  215. package/dist/migrations/postgresql/0014_image_sizes_and_focal_point.sql +33 -0
  216. package/dist/migrations/postgresql/0014_site_settings_sidebar.sql +13 -0
  217. package/dist/migrations/postgresql/0015_user_brute_force_protection.sql +29 -0
  218. package/dist/migrations/postgresql/0016_email_template_attachments.sql +12 -0
  219. package/dist/migrations/postgresql/0017_media_uploaded_by_nullable.sql +15 -0
  220. package/dist/migrations/postgresql/20260429_000000_000_initial_journal.sql +24 -0
  221. package/dist/migrations/postgresql/20260501_000000_journal_batch.sql +17 -0
  222. package/dist/migrations/postgresql/20260501_000001_audit_log.sql +24 -0
  223. package/dist/migrations/postgresql/20260504_000000_nextly_meta.sql +22 -0
  224. package/dist/migrations/postgresql/meta/0000_snapshot.json +1286 -0
  225. package/dist/migrations/postgresql/meta/0001_snapshot.json +1407 -0
  226. package/dist/migrations/postgresql/meta/0002_snapshot.json +1552 -0
  227. package/dist/migrations/postgresql/meta/0003_snapshot.json +1695 -0
  228. package/dist/migrations/postgresql/meta/0010_snapshot.json +2345 -0
  229. package/dist/migrations/postgresql/meta/_journal.json +90 -0
  230. package/dist/migrations/sqlite/0000_api_keys.sql +34 -0
  231. package/dist/migrations/sqlite/0001_general_settings.sql +20 -0
  232. package/dist/migrations/sqlite/0002_site_settings_logo_url.sql +9 -0
  233. package/dist/migrations/sqlite/0003_activity_log.sql +29 -0
  234. package/dist/migrations/sqlite/0004_image_sizes_and_focal_point.sql +29 -0
  235. package/dist/migrations/sqlite/0004_site_settings_sidebar.sql +11 -0
  236. package/dist/migrations/sqlite/0005_user_brute_force_protection.sql +29 -0
  237. package/dist/migrations/sqlite/0006_email_template_attachments.sql +12 -0
  238. package/dist/migrations/sqlite/0007_media_uploaded_by_nullable.sql +111 -0
  239. package/dist/migrations/sqlite/20260429_000000_000_initial_journal.sql +24 -0
  240. package/dist/migrations/sqlite/20260501_000000_journal_batch.sql +19 -0
  241. package/dist/migrations/sqlite/20260501_000001_audit_log.sql +24 -0
  242. package/dist/migrations/sqlite/20260504_000000_nextly_meta.sql +21 -0
  243. package/dist/migrations/sqlite/20260505_000000_user_management_tables.sql +77 -0
  244. package/dist/next.d.ts +57 -0
  245. package/dist/next.mjs +55 -0
  246. package/dist/observability/index.d.ts +87 -0
  247. package/dist/observability/index.mjs +57 -0
  248. package/dist/permissions-3DZZQZMI.mjs +39 -0
  249. package/dist/pipeline-YOML7SWF.mjs +29 -0
  250. package/dist/preview-ZZTR3QGS.mjs +9 -0
  251. package/dist/program-PW6UB2ZC.mjs +5934 -0
  252. package/dist/reconcile-single-tables-7ENVXJGB.mjs +7 -0
  253. package/dist/register-SF6E6FVU.mjs +49 -0
  254. package/dist/reload-config-HWQ4G5MM.mjs +23 -0
  255. package/dist/resolve-single-table-name-JSOMUB3R.mjs +7 -0
  256. package/dist/routeHandler-UNMMJIBM.mjs +77 -0
  257. package/dist/runtime-schema-generator-NRA6A6Z6.mjs +8 -0
  258. package/dist/runtime.d.ts +120 -0
  259. package/dist/runtime.mjs +73 -0
  260. package/dist/schema-hash-FMMG6VPJ.mjs +13 -0
  261. package/dist/schema-registry-EQ36FZDP.mjs +7 -0
  262. package/dist/scripts/load-env.mjs +42 -0
  263. package/dist/storage/index.d.ts +566 -0
  264. package/dist/storage/index.mjs +45 -0
  265. package/dist/super-admin-G5ZK5F4T.mjs +39 -0
  266. package/dist/system-table-service-WGSRVEGT.mjs +17 -0
  267. package/dist/users-7KELGRYJ.mjs +38 -0
  268. package/package.json +308 -9
@@ -0,0 +1,239 @@
1
+ import { M as Media } from '../_dts-chunks/media.d-DjDOZo4B.d.ts';
2
+ import { O as OnErrorHook } from '../_dts-chunks/on-error.d-CHIKWNxd.d.ts';
3
+ import { PublicData } from '../errors/index.d.ts';
4
+ import 'zod';
5
+
6
+ /**
7
+ * Media Upload Server Action
8
+ *
9
+ * Next.js 16 Server Action for uploading media files.
10
+ * Provides a simpler alternative to API routes for small files (<5MB).
11
+ *
12
+ * ## Features
13
+ *
14
+ * - Server-side file upload (no client-side FormData serialization)
15
+ * - Automatic cache revalidation (revalidatePath)
16
+ * - Type-safe with Zod validation
17
+ * - Authentication support (when configured)
18
+ * - Error handling with user-friendly messages
19
+ *
20
+ * ## Usage
21
+ *
22
+ * ### In Consumer's Next.js App
23
+ *
24
+ * ```typescript
25
+ * // app/actions/media.ts
26
+ * 'use server';
27
+ *
28
+ * import { uploadMediaAction } from 'nextly/actions/upload-media';
29
+ * import { getUserId } from './auth'; // Your auth implementation
30
+ *
31
+ * export async function uploadMedia(formData: FormData) {
32
+ * const userId = await getUserId();
33
+ * return uploadMediaAction(formData, { uploadedBy: userId });
34
+ * }
35
+ * ```
36
+ *
37
+ * ### In Client Component
38
+ *
39
+ * ```tsx
40
+ * 'use client';
41
+ *
42
+ * import { uploadMedia } from './actions/media';
43
+ *
44
+ * function UploadForm() {
45
+ * async function handleSubmit(formData: FormData) {
46
+ * const result = await uploadMedia(formData);
47
+ * if (result.success) {
48
+ * toast.success('Uploaded!');
49
+ * } else {
50
+ * toast.error(result.error);
51
+ * }
52
+ * }
53
+ *
54
+ * return <form action={handleSubmit}>...</form>;
55
+ * }
56
+ * ```
57
+ *
58
+ * ## Authentication
59
+ *
60
+ * This action is **auth-agnostic** by design. The `uploadedBy` parameter
61
+ * must be provided by the consumer's authentication implementation.
62
+ *
63
+ * Examples:
64
+ * - Nextly: `const result = await getSession(request, secret); uploadedBy: result.user?.id`
65
+ * - Clerk: `const { userId } = auth(); uploadedBy: userId`
66
+ * - Custom: `const user = await getUser(); uploadedBy: user.id`
67
+ *
68
+ * ## Limitations
69
+ *
70
+ * - **No upload progress**: Server Actions don't support progress events
71
+ * - **Recommended for small files only** (<5MB)
72
+ * - **For large files**: Use API route with XMLHttpRequest
73
+ *
74
+ * @see packages/db/src/api/media.ts - API route with progress support
75
+ * @see MEDIA-MANAGEMENT-EXTENDED-PLAN.md - Phase 6 implementation details
76
+ */
77
+
78
+ /**
79
+ * Server Action options
80
+ */
81
+ interface UploadMediaActionOptions {
82
+ /**
83
+ * User ID who is uploading the file (required)
84
+ * Must be obtained from your auth system
85
+ */
86
+ uploadedBy: string;
87
+ /**
88
+ * Path to revalidate after successful upload
89
+ * @default '/admin/media'
90
+ */
91
+ revalidatePath?: string;
92
+ }
93
+ /**
94
+ * Server Action result
95
+ */
96
+ interface UploadMediaActionResult {
97
+ success: boolean;
98
+ data?: Media;
99
+ error?: string;
100
+ statusCode?: number;
101
+ }
102
+ /**
103
+ * Upload media file via Server Action
104
+ *
105
+ * Uploads a file to storage and creates a database record.
106
+ * Automatically generates thumbnails for images.
107
+ *
108
+ * @param formData - FormData containing the file
109
+ * @param options - Upload options (uploadedBy, revalidatePath)
110
+ * @returns Upload result with media data or error
111
+ *
112
+ * @example Basic usage
113
+ * ```typescript
114
+ * 'use server';
115
+ *
116
+ * export async function uploadFile(formData: FormData) {
117
+ * const userId = await getUserId(); // Your auth function
118
+ * return uploadMediaAction(formData, { uploadedBy: userId });
119
+ * }
120
+ * ```
121
+ *
122
+ * @example With custom revalidation path
123
+ * ```typescript
124
+ * return uploadMediaAction(formData, {
125
+ * uploadedBy: userId,
126
+ * revalidatePath: '/dashboard/gallery',
127
+ * });
128
+ * ```
129
+ */
130
+ declare function uploadMediaAction(formData: FormData, options: UploadMediaActionOptions): Promise<UploadMediaActionResult>;
131
+ /**
132
+ * Delete media file via Server Action
133
+ *
134
+ * Deletes a file from storage and removes the database record.
135
+ *
136
+ * @param mediaId - ID of media to delete
137
+ * @param options - Options (revalidatePath)
138
+ * @returns Deletion result
139
+ *
140
+ * @example
141
+ * ```typescript
142
+ * 'use server';
143
+ *
144
+ * export async function deleteFile(mediaId: string) {
145
+ * return deleteMediaAction(mediaId);
146
+ * }
147
+ * ```
148
+ */
149
+ declare function deleteMediaAction(mediaId: string, options?: {
150
+ revalidatePath?: string;
151
+ }): Promise<{
152
+ success: boolean;
153
+ error?: string;
154
+ statusCode?: number;
155
+ }>;
156
+ /**
157
+ * Update media metadata via Server Action
158
+ *
159
+ * Updates altText, caption, tags, or other metadata fields.
160
+ *
161
+ * @param mediaId - ID of media to update
162
+ * @param updates - Metadata updates
163
+ * @param options - Options (revalidatePath)
164
+ * @returns Update result
165
+ *
166
+ * @example
167
+ * ```typescript
168
+ * 'use server';
169
+ *
170
+ * export async function updateFile(
171
+ * mediaId: string,
172
+ * updates: { altText?: string; caption?: string; tags?: string[] }
173
+ * ) {
174
+ * return updateMediaAction(mediaId, updates);
175
+ * }
176
+ * ```
177
+ */
178
+ declare function updateMediaAction(mediaId: string, updates: {
179
+ filename?: string;
180
+ altText?: string;
181
+ caption?: string;
182
+ tags?: string[];
183
+ }, options?: {
184
+ revalidatePath?: string;
185
+ }): Promise<{
186
+ success: boolean;
187
+ data?: Media;
188
+ error?: string;
189
+ statusCode?: number;
190
+ }>;
191
+
192
+ /**
193
+ * Wire shape returned by Server Actions wrapped with `withAction`.
194
+ *
195
+ * The `error` block matches the canonical HTTP wire-format error block
196
+ * (modulo the discriminator), so developers learn one shape regardless of
197
+ * whether they consume a Route Handler or a Server Action.
198
+ */
199
+ type ActionError = {
200
+ code: string;
201
+ message: string;
202
+ messageKey?: string;
203
+ data?: PublicData;
204
+ requestId: string;
205
+ };
206
+ /**
207
+ * Result of a Server Action: either `{ ok: true, data }` on success or
208
+ * `{ ok: false, error }` on failure. The `ok` discriminator narrows
209
+ * cleanly via `if (result.ok)` so consumers get type-safe access to either
210
+ * branch.
211
+ */
212
+ type ActionResult<T> = {
213
+ ok: true;
214
+ data: T;
215
+ } | {
216
+ ok: false;
217
+ error: ActionError;
218
+ };
219
+
220
+ type WithActionOptions = {
221
+ /** Per-call observability hook. Fired before the global hook. */
222
+ onError?: OnErrorHook;
223
+ };
224
+ /**
225
+ * Server Action boundary wrapper. Mirrors `withErrorHandler` but returns a
226
+ * typed `ActionResult<T>` instead of a `Response`, working around Next.js's
227
+ * production error-digesting (which strips thrown error messages).
228
+ *
229
+ * Generic over `TArgs` so it transparently supports both direct-call
230
+ * actions (`(id: string)`) and form-binding actions
231
+ * (`(prevState, formData)`) consumed by `useActionState`.
232
+ *
233
+ * Sentinel errors (`redirect`, `notFound`, dynamic-API bailouts) are passed
234
+ * through `unstable_rethrow` first so navigation works as expected.
235
+ */
236
+ declare function withAction<TArgs extends unknown[], TResult>(fn: (...args: TArgs) => Promise<TResult>, options?: WithActionOptions): (...args: TArgs) => Promise<ActionResult<TResult>>;
237
+
238
+ export { deleteMediaAction, updateMediaAction, uploadMediaAction, withAction };
239
+ export type { ActionError, ActionResult, UploadMediaActionOptions, UploadMediaActionResult };
@@ -0,0 +1,281 @@
1
+ import {
2
+ generateRequestId
3
+ } from "../chunk-67GXH6PR.mjs";
4
+ import {
5
+ getGlobalOnError
6
+ } from "../chunk-2TFX4ND3.mjs";
7
+ import {
8
+ getNextlyLogger
9
+ } from "../chunk-W4MGXIRR.mjs";
10
+ import {
11
+ ServiceContainer,
12
+ UploadMediaInputSchema
13
+ } from "../chunk-NSEFNNU4.mjs";
14
+ import "../chunk-3FA7FKAV.mjs";
15
+ import "../chunk-AGJ6F2T3.mjs";
16
+ import "../chunk-KIMNCZGV.mjs";
17
+ import "../chunk-AK6Z23OX.mjs";
18
+ import "../chunk-INV7QKLG.mjs";
19
+ import "../chunk-GZ6DCQKC.mjs";
20
+ import "../chunk-SBACDPNX.mjs";
21
+ import "../chunk-RJLLGGPG.mjs";
22
+ import "../chunk-V4EQTOA4.mjs";
23
+ import "../chunk-I4JMR3UR.mjs";
24
+ import "../chunk-XZKLBMN6.mjs";
25
+ import "../chunk-IZWPRDC3.mjs";
26
+ import "../chunk-DNNG377Z.mjs";
27
+ import "../chunk-5HMZ644B.mjs";
28
+ import "../chunk-W5KKPZT5.mjs";
29
+ import "../chunk-56WO4WX7.mjs";
30
+ import "../chunk-2W3DVD7S.mjs";
31
+ import "../chunk-TS7GHTG2.mjs";
32
+ import "../chunk-H26B4FYG.mjs";
33
+ import "../chunk-DP3G27G5.mjs";
34
+ import "../chunk-DV6WVX2Q.mjs";
35
+ import "../chunk-UJ2IMJ4W.mjs";
36
+ import "../chunk-EGXBZCGC.mjs";
37
+ import "../chunk-G2AA4QLC.mjs";
38
+ import "../chunk-4MJLT6PZ.mjs";
39
+ import "../chunk-IUDOC7N7.mjs";
40
+ import "../chunk-LAZXX4HR.mjs";
41
+ import {
42
+ container
43
+ } from "../chunk-D5HQBNUB.mjs";
44
+ import {
45
+ NextlyError,
46
+ isDbError
47
+ } from "../chunk-NRUWQ5Z7.mjs";
48
+ import "../chunk-VTJADRO3.mjs";
49
+ import "../chunk-5APFUGAD.mjs";
50
+ import "../chunk-7P6ASYW6.mjs";
51
+
52
+ // src/actions/upload-media.ts
53
+ import { createRequire } from "module";
54
+ var cachedRevalidatePath = null;
55
+ function getRevalidatePath() {
56
+ if (cachedRevalidatePath) return cachedRevalidatePath;
57
+ const require2 = createRequire(import.meta.url);
58
+ const mod = require2("next/cache");
59
+ cachedRevalidatePath = mod.revalidatePath;
60
+ return cachedRevalidatePath;
61
+ }
62
+ function getServices() {
63
+ const adapter = container.get("adapter");
64
+ return new ServiceContainer(adapter);
65
+ }
66
+ async function uploadMediaAction(formData, options) {
67
+ try {
68
+ const file = formData.get("file");
69
+ if (!file) {
70
+ return {
71
+ success: false,
72
+ error: "No file provided",
73
+ statusCode: 400
74
+ };
75
+ }
76
+ if (!(file instanceof File)) {
77
+ return {
78
+ success: false,
79
+ error: "Invalid file",
80
+ statusCode: 400
81
+ };
82
+ }
83
+ const arrayBuffer = await file.arrayBuffer();
84
+ const buffer = Buffer.from(arrayBuffer);
85
+ const parseResult = UploadMediaInputSchema.safeParse({
86
+ file: buffer,
87
+ filename: file.name,
88
+ mimeType: file.type,
89
+ size: file.size,
90
+ uploadedBy: options.uploadedBy
91
+ });
92
+ if (!parseResult.success) {
93
+ const errors = parseResult.error.issues;
94
+ const firstError = errors[0];
95
+ return {
96
+ success: false,
97
+ error: firstError?.message || "Invalid file data",
98
+ statusCode: 400
99
+ };
100
+ }
101
+ const services = getServices();
102
+ const result = await services.media.uploadMedia(parseResult.data);
103
+ if (result.success && result.data) {
104
+ const pathToRevalidate = options.revalidatePath || "/admin/media";
105
+ getRevalidatePath()(pathToRevalidate);
106
+ return {
107
+ success: true,
108
+ data: result.data,
109
+ statusCode: result.statusCode
110
+ };
111
+ }
112
+ return {
113
+ success: false,
114
+ error: result.message || "Upload failed",
115
+ statusCode: result.statusCode
116
+ };
117
+ } catch (error) {
118
+ console.error("[uploadMediaAction] Unexpected error:", error);
119
+ return {
120
+ success: false,
121
+ error: error instanceof Error ? error.message : "An unexpected error occurred",
122
+ statusCode: 500
123
+ };
124
+ }
125
+ }
126
+ async function deleteMediaAction(mediaId, options) {
127
+ try {
128
+ if (!mediaId || typeof mediaId !== "string") {
129
+ return {
130
+ success: false,
131
+ error: "Invalid media ID",
132
+ statusCode: 400
133
+ };
134
+ }
135
+ const services = getServices();
136
+ const result = await services.media.deleteMedia(mediaId);
137
+ if (result.success) {
138
+ const pathToRevalidate = options?.revalidatePath || "/admin/media";
139
+ getRevalidatePath()(pathToRevalidate);
140
+ return {
141
+ success: true,
142
+ statusCode: result.statusCode
143
+ };
144
+ }
145
+ return {
146
+ success: false,
147
+ error: result.message || "Delete failed",
148
+ statusCode: result.statusCode
149
+ };
150
+ } catch (error) {
151
+ console.error("[deleteMediaAction] Unexpected error:", error);
152
+ return {
153
+ success: false,
154
+ error: error instanceof Error ? error.message : "An unexpected error occurred",
155
+ statusCode: 500
156
+ };
157
+ }
158
+ }
159
+ async function updateMediaAction(mediaId, updates, options) {
160
+ try {
161
+ if (!mediaId || typeof mediaId !== "string") {
162
+ return {
163
+ success: false,
164
+ error: "Invalid media ID",
165
+ statusCode: 400
166
+ };
167
+ }
168
+ const services = getServices();
169
+ const result = await services.media.updateMedia(mediaId, updates);
170
+ if (result.success && result.data) {
171
+ const pathToRevalidate = options?.revalidatePath || "/admin/media";
172
+ getRevalidatePath()(pathToRevalidate);
173
+ return {
174
+ success: true,
175
+ data: result.data,
176
+ statusCode: result.statusCode
177
+ };
178
+ }
179
+ return {
180
+ success: false,
181
+ error: result.message || "Update failed",
182
+ statusCode: result.statusCode
183
+ };
184
+ } catch (error) {
185
+ console.error("[updateMediaAction] Unexpected error:", error);
186
+ return {
187
+ success: false,
188
+ error: error instanceof Error ? error.message : "An unexpected error occurred",
189
+ statusCode: 500
190
+ };
191
+ }
192
+ }
193
+
194
+ // src/actions/with-action.ts
195
+ import { createRequire as createRequire2 } from "module";
196
+ var cachedHeaders = null;
197
+ var cachedUnstableRethrow = null;
198
+ function getHeaders() {
199
+ if (cachedHeaders) return cachedHeaders;
200
+ const require2 = createRequire2(import.meta.url);
201
+ const mod = require2("next/headers");
202
+ cachedHeaders = mod.headers;
203
+ return cachedHeaders;
204
+ }
205
+ function getUnstableRethrow() {
206
+ if (cachedUnstableRethrow) return cachedUnstableRethrow;
207
+ const require2 = createRequire2(import.meta.url);
208
+ const mod = require2("next/navigation");
209
+ cachedUnstableRethrow = mod.unstable_rethrow;
210
+ return cachedUnstableRethrow;
211
+ }
212
+ async function readOrGenerateRequestIdFromHeaders() {
213
+ try {
214
+ const headers = getHeaders();
215
+ const h = await headers();
216
+ return h.get("x-request-id") ?? h.get("x-vercel-id") ?? h.get("cf-ray") ?? generateRequestId();
217
+ } catch {
218
+ return generateRequestId();
219
+ }
220
+ }
221
+ function withAction(fn, options) {
222
+ return async (...args) => {
223
+ const requestId = await readOrGenerateRequestIdFromHeaders();
224
+ try {
225
+ const data = await fn(...args);
226
+ return { ok: true, data };
227
+ } catch (err) {
228
+ getUnstableRethrow()(err);
229
+ let nextlyErr;
230
+ if (NextlyError.is(err)) {
231
+ nextlyErr = err;
232
+ } else if (isDbError(err)) {
233
+ getNextlyLogger().warn({
234
+ kind: "stray-db-error-converted",
235
+ requestId,
236
+ dbKind: err.kind
237
+ });
238
+ nextlyErr = NextlyError.fromDatabaseError(err);
239
+ } else {
240
+ nextlyErr = NextlyError.internal({ cause: err });
241
+ }
242
+ getNextlyLogger().error({
243
+ kind: "server-action-error",
244
+ ...nextlyErr.toLogJSON(requestId)
245
+ });
246
+ const ctx = { kind: "server-action", requestId };
247
+ if (options?.onError) {
248
+ try {
249
+ await options.onError(nextlyErr, ctx);
250
+ } catch (hookErr) {
251
+ getNextlyLogger().warn({
252
+ kind: "onError-hook-failed",
253
+ layer: "per-call",
254
+ requestId,
255
+ err: String(hookErr)
256
+ });
257
+ }
258
+ }
259
+ const globalHook = getGlobalOnError();
260
+ if (globalHook) {
261
+ try {
262
+ await globalHook(nextlyErr, ctx);
263
+ } catch (hookErr) {
264
+ getNextlyLogger().warn({
265
+ kind: "onError-hook-failed",
266
+ layer: "global",
267
+ requestId,
268
+ err: String(hookErr)
269
+ });
270
+ }
271
+ }
272
+ return { ok: false, error: nextlyErr.toResponseJSON(requestId) };
273
+ }
274
+ };
275
+ }
276
+ export {
277
+ deleteMediaAction,
278
+ updateMediaAction,
279
+ uploadMediaAction,
280
+ withAction
281
+ };
@@ -0,0 +1,5 @@
1
+ import { NextRequest } from 'next/server';
2
+
3
+ declare const GET: (request: NextRequest) => Promise<Response>;
4
+
5
+ export { GET };
@@ -0,0 +1,131 @@
1
+ import {
2
+ readAccessTokenCookie,
3
+ verifyAccessToken
4
+ } from "../chunk-2ZFKXPQM.mjs";
5
+ import {
6
+ withErrorHandler
7
+ } from "../chunk-TO5AFLVQ.mjs";
8
+ import {
9
+ getCachedNextly
10
+ } from "../chunk-P7NH2OSC.mjs";
11
+ import "../chunk-2OALJTK6.mjs";
12
+ import "../chunk-VJ66NCL4.mjs";
13
+ import "../chunk-R6JJQHFC.mjs";
14
+ import "../chunk-X23WKS3Z.mjs";
15
+ import "../chunk-X7TXCYYN.mjs";
16
+ import "../chunk-YZNBLFIW.mjs";
17
+ import "../chunk-FQULBZ53.mjs";
18
+ import "../chunk-67GXH6PR.mjs";
19
+ import "../chunk-2TFX4ND3.mjs";
20
+ import "../chunk-W4MGXIRR.mjs";
21
+ import "../chunk-NSEFNNU4.mjs";
22
+ import "../chunk-3FA7FKAV.mjs";
23
+ import "../chunk-AGJ6F2T3.mjs";
24
+ import "../chunk-KIMNCZGV.mjs";
25
+ import "../chunk-AK6Z23OX.mjs";
26
+ import "../chunk-INV7QKLG.mjs";
27
+ import "../chunk-GZ6DCQKC.mjs";
28
+ import "../chunk-SBACDPNX.mjs";
29
+ import "../chunk-RJLLGGPG.mjs";
30
+ import "../chunk-V4EQTOA4.mjs";
31
+ import "../chunk-I4JMR3UR.mjs";
32
+ import "../chunk-XZKLBMN6.mjs";
33
+ import "../chunk-IZWPRDC3.mjs";
34
+ import "../chunk-DNNG377Z.mjs";
35
+ import "../chunk-5HMZ644B.mjs";
36
+ import "../chunk-W5KKPZT5.mjs";
37
+ import "../chunk-56WO4WX7.mjs";
38
+ import "../chunk-2W3DVD7S.mjs";
39
+ import {
40
+ getDialectTables
41
+ } from "../chunk-TS7GHTG2.mjs";
42
+ import "../chunk-H26B4FYG.mjs";
43
+ import "../chunk-DP3G27G5.mjs";
44
+ import "../chunk-DV6WVX2Q.mjs";
45
+ import {
46
+ env
47
+ } from "../chunk-UJ2IMJ4W.mjs";
48
+ import "../chunk-EGXBZCGC.mjs";
49
+ import "../chunk-G2AA4QLC.mjs";
50
+ import "../chunk-4MJLT6PZ.mjs";
51
+ import {
52
+ respondData
53
+ } from "../chunk-IUDOC7N7.mjs";
54
+ import "../chunk-LAZXX4HR.mjs";
55
+ import "../chunk-D5HQBNUB.mjs";
56
+ import {
57
+ NextlyError
58
+ } from "../chunk-NRUWQ5Z7.mjs";
59
+ import "../chunk-VTJADRO3.mjs";
60
+ import "../chunk-5APFUGAD.mjs";
61
+ import "../chunk-7P6ASYW6.mjs";
62
+
63
+ // src/api/auth-state.ts
64
+ import { eq } from "drizzle-orm";
65
+ var GET = withErrorHandler(async (request) => {
66
+ const secret = env.NEXTLY_SECRET ?? "";
67
+ if (!secret) {
68
+ throw NextlyError.authRequired({
69
+ logContext: { reason: "no-secret-configured" }
70
+ });
71
+ }
72
+ const token = readAccessTokenCookie(request);
73
+ if (!token) {
74
+ throw NextlyError.authRequired({ logContext: { reason: "no_token" } });
75
+ }
76
+ const verifyResult = await verifyAccessToken(token, secret);
77
+ if (!verifyResult.valid) {
78
+ throw NextlyError.authRequired({
79
+ logContext: { reason: verifyResult.reason }
80
+ });
81
+ }
82
+ const claims = verifyResult.payload;
83
+ const userId = claims.sub;
84
+ const issuedAt = typeof claims.iat === "number" ? new Date(claims.iat * 1e3) : /* @__PURE__ */ new Date(0);
85
+ const expiresAt = typeof claims.exp === "number" ? new Date(claims.exp * 1e3) : /* @__PURE__ */ new Date(0);
86
+ if (!userId) {
87
+ throw NextlyError.authRequired({
88
+ logContext: { reason: "claims-missing-sub" }
89
+ });
90
+ }
91
+ const nextly = await getCachedNextly();
92
+ const db = nextly.adapter.getDrizzle();
93
+ const tables = getDialectTables();
94
+ const rows = await db.select({
95
+ id: tables.users.id,
96
+ email: tables.users.email,
97
+ name: tables.users.name,
98
+ emailVerified: tables.users.emailVerified,
99
+ isActive: tables.users.isActive,
100
+ lockedUntil: tables.users.lockedUntil
101
+ }).from(tables.users).where(eq(tables.users.id, userId)).limit(1);
102
+ const user = rows[0];
103
+ if (!user) {
104
+ throw NextlyError.authRequired({
105
+ logContext: { reason: "session-user-missing", userId }
106
+ });
107
+ }
108
+ const now = /* @__PURE__ */ new Date();
109
+ const account = {
110
+ verified: Boolean(user.emailVerified),
111
+ locked: Boolean(user.lockedUntil && user.lockedUntil > now),
112
+ disabled: !user.isActive,
113
+ // The schema does not yet track these as first-class fields; expose
114
+ // safe defaults until they land. (Spec §19 follow-up.)
115
+ passwordResetRequired: false,
116
+ mustChangePasswordReason: null
117
+ };
118
+ const payload = {
119
+ authenticated: true,
120
+ user: { id: user.id, email: user.email, name: user.name },
121
+ account,
122
+ session: {
123
+ issuedAt: issuedAt.toISOString(),
124
+ expiresAt: expiresAt.toISOString()
125
+ }
126
+ };
127
+ return respondData(payload);
128
+ });
129
+ export {
130
+ GET
131
+ };
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Collection Schema Detail API Route Handlers for Next.js
3
+ *
4
+ * These route handlers can be re-exported in your Next.js application to provide
5
+ * individual collection management endpoints at /api/collections/schema/[slug].
6
+ *
7
+ * Services are auto-initialized on first request using environment variables:
8
+ * - DB_DIALECT: Database dialect ("postgresql" | "mysql" | "sqlite")
9
+ * - DATABASE_URL: Database connection string
10
+ *
11
+ * Locked code-first collections surface as canonical FORBIDDEN: the registry
12
+ * throws `NextlyError.forbidden` with the `collection-locked` reason in
13
+ * `logContext`.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * // In your Next.js app: app/api/collections/schema/[slug]/route.ts
18
+ * export { GET, PATCH, DELETE } from 'nextly/api/collections-schema-detail';
19
+ * ```
20
+ *
21
+ * @module api/collections-schema-detail
22
+ */
23
+ /**
24
+ * Context object for dynamic route handlers.
25
+ * Next.js 15+ requires params to be a Promise.
26
+ */
27
+ interface RouteContext {
28
+ params: Promise<{
29
+ slug: string;
30
+ }>;
31
+ }
32
+ /**
33
+ * GET handler for retrieving a single collection by slug.
34
+ *
35
+ * Requires authentication and read permission for the collection. The
36
+ * registry throws `NOT_FOUND` if no collection matches the slug.
37
+ */
38
+ declare const GET: (request: Request, context: RouteContext) => Promise<Response>;
39
+ /**
40
+ * PATCH handler for updating a collection.
41
+ *
42
+ * Requires `manage-settings` (or super-admin). The registry throws
43
+ * `NextlyError.forbidden` with `reason: "collection-locked"` if the
44
+ * collection is locked (code-first collections cannot be modified via API).
45
+ */
46
+ declare const PATCH: (request: Request, context: RouteContext) => Promise<Response>;
47
+ /**
48
+ * DELETE handler for removing a collection.
49
+ *
50
+ * Requires `manage-settings` (or super-admin). The registry throws
51
+ * `NextlyError.forbidden` with `reason: "collection-locked-delete"` if the
52
+ * collection is locked (code-first collections cannot be deleted via API).
53
+ */
54
+ declare const DELETE: (request: Request, context: RouteContext) => Promise<Response>;
55
+
56
+ export { DELETE, GET, PATCH };