nextjs-cms 0.9.22 → 0.9.23

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 (185) hide show
  1. package/README.md +65 -13
  2. package/dist/api/actions/files.d.ts +30 -0
  3. package/dist/api/actions/files.d.ts.map +1 -0
  4. package/dist/api/actions/files.js +234 -0
  5. package/dist/api/actions/index.d.ts +4 -0
  6. package/dist/api/actions/index.d.ts.map +1 -0
  7. package/dist/api/actions/index.js +3 -0
  8. package/dist/api/actions/pages.d.ts +297 -0
  9. package/dist/api/actions/pages.d.ts.map +1 -0
  10. package/dist/api/actions/pages.js +1215 -0
  11. package/dist/api/actions/privileges.d.ts +25 -0
  12. package/dist/api/actions/privileges.d.ts.map +1 -0
  13. package/dist/api/actions/privileges.js +98 -0
  14. package/dist/api/client/index.d.ts +4 -0
  15. package/dist/api/client/index.d.ts.map +1 -0
  16. package/dist/api/client/index.js +3 -0
  17. package/dist/api/client.d.ts +30 -0
  18. package/dist/api/client.d.ts.map +1 -0
  19. package/dist/api/client.js +82 -0
  20. package/dist/api/index.d.ts +1 -938
  21. package/dist/api/index.d.ts.map +1 -1
  22. package/dist/api/index.js +0 -13
  23. package/dist/api/plugin/index.d.ts +7 -0
  24. package/dist/api/plugin/index.d.ts.map +1 -0
  25. package/dist/api/plugin/index.js +5 -0
  26. package/dist/api/root.d.ts +18 -1844
  27. package/dist/api/root.d.ts.map +1 -1
  28. package/dist/api/root.js +18 -83
  29. package/dist/api/server/index.d.ts +8 -0
  30. package/dist/api/server/index.d.ts.map +1 -0
  31. package/dist/api/server/index.js +3 -0
  32. package/dist/api/server.d.ts +2748 -0
  33. package/dist/api/server.d.ts.map +1 -0
  34. package/dist/api/server.js +100 -0
  35. package/dist/api/trpc/client.d.ts +19 -3
  36. package/dist/api/trpc/client.d.ts.map +1 -1
  37. package/dist/api/trpc/client.js +55 -1
  38. package/dist/api/trpc/query-client.d.ts +3 -1
  39. package/dist/api/trpc/query-client.d.ts.map +1 -1
  40. package/dist/api/trpc/query-client.js +25 -20
  41. package/dist/api/trpc/root.d.ts +906 -0
  42. package/dist/api/trpc/root.d.ts.map +1 -0
  43. package/dist/api/trpc/root.js +47 -0
  44. package/dist/api/trpc/routers/accountSettings.d.ts +66 -0
  45. package/dist/api/trpc/routers/accountSettings.d.ts.map +1 -0
  46. package/dist/api/trpc/routers/accountSettings.js +200 -0
  47. package/dist/api/trpc/routers/admins.d.ts +112 -0
  48. package/dist/api/trpc/routers/admins.d.ts.map +1 -0
  49. package/dist/api/trpc/routers/admins.js +331 -0
  50. package/dist/api/trpc/routers/auth.d.ts +54 -0
  51. package/dist/api/trpc/routers/auth.d.ts.map +1 -0
  52. package/dist/api/trpc/routers/auth.js +50 -0
  53. package/dist/api/trpc/routers/categorySection.d.ts +105 -0
  54. package/dist/api/trpc/routers/categorySection.d.ts.map +1 -0
  55. package/dist/api/trpc/routers/categorySection.js +49 -0
  56. package/dist/api/trpc/routers/config.d.ts +48 -0
  57. package/dist/api/trpc/routers/config.d.ts.map +1 -0
  58. package/dist/api/trpc/routers/config.js +18 -0
  59. package/dist/api/trpc/routers/cpanel.d.ts +82 -0
  60. package/dist/api/trpc/routers/cpanel.d.ts.map +1 -0
  61. package/dist/api/trpc/routers/cpanel.js +216 -0
  62. package/dist/api/trpc/routers/fields.d.ts +35 -0
  63. package/dist/api/trpc/routers/fields.d.ts.map +1 -0
  64. package/dist/api/trpc/routers/fields.js +81 -0
  65. package/dist/api/trpc/routers/files.d.ts +34 -0
  66. package/dist/api/trpc/routers/files.d.ts.map +1 -0
  67. package/dist/api/trpc/routers/files.js +14 -0
  68. package/dist/api/trpc/routers/gallery.d.ts +35 -0
  69. package/dist/api/trpc/routers/gallery.d.ts.map +1 -0
  70. package/dist/api/trpc/routers/gallery.js +92 -0
  71. package/dist/api/trpc/routers/hasItemsSection.d.ts +194 -0
  72. package/dist/api/trpc/routers/hasItemsSection.d.ts.map +1 -0
  73. package/dist/api/trpc/routers/hasItemsSection.js +86 -0
  74. package/dist/api/trpc/routers/logs.d.ts +59 -0
  75. package/dist/api/trpc/routers/logs.d.ts.map +1 -0
  76. package/dist/api/trpc/routers/logs.js +79 -0
  77. package/dist/api/trpc/routers/navigation.d.ts +65 -0
  78. package/dist/api/trpc/routers/navigation.d.ts.map +1 -0
  79. package/dist/api/trpc/routers/navigation.js +11 -0
  80. package/dist/api/trpc/routers/simpleSection.d.ts +93 -0
  81. package/dist/api/trpc/routers/simpleSection.d.ts.map +1 -0
  82. package/dist/api/trpc/routers/simpleSection.js +54 -0
  83. package/dist/api/trpc/server.d.ts +2789 -5
  84. package/dist/api/trpc/server.d.ts.map +1 -1
  85. package/dist/api/trpc/server.js +91 -52
  86. package/dist/api/trpc/trpc.d.ts +111 -0
  87. package/dist/api/trpc/trpc.d.ts.map +1 -0
  88. package/dist/api/trpc/trpc.js +99 -0
  89. package/dist/api/trpc/utils/async-caller-proxy.d.ts +2 -0
  90. package/dist/api/trpc/utils/async-caller-proxy.d.ts.map +1 -0
  91. package/dist/api/trpc/utils/async-caller-proxy.js +38 -0
  92. package/dist/api/trpc/utils/refresh-token-link.d.ts +6 -0
  93. package/dist/api/trpc/utils/refresh-token-link.d.ts.map +1 -0
  94. package/dist/api/trpc/utils/refresh-token-link.js +81 -0
  95. package/dist/api/trpc/utils/router-types.d.ts +7 -0
  96. package/dist/api/trpc/utils/router-types.d.ts.map +1 -0
  97. package/dist/api/trpc/utils/router-types.js +0 -0
  98. package/dist/api/use-axios-private.d.ts +6 -0
  99. package/dist/api/use-axios-private.d.ts.map +1 -0
  100. package/dist/api/use-axios-private.js +57 -0
  101. package/dist/api/utils/async-caller-proxy.d.ts +2 -0
  102. package/dist/api/utils/async-caller-proxy.d.ts.map +1 -0
  103. package/dist/api/utils/async-caller-proxy.js +36 -0
  104. package/dist/api/utils/lazy-caller-proxy.d.ts +2 -0
  105. package/dist/api/utils/lazy-caller-proxy.d.ts.map +1 -0
  106. package/dist/api/utils/lazy-caller-proxy.js +36 -0
  107. package/dist/api/utils/router-types.d.ts +7 -0
  108. package/dist/api/utils/router-types.d.ts.map +1 -0
  109. package/dist/api/utils/router-types.js +0 -0
  110. package/dist/auth/hooks/index.d.ts +1 -2
  111. package/dist/auth/hooks/index.d.ts.map +1 -1
  112. package/dist/auth/hooks/index.js +1 -2
  113. package/dist/auth/react.d.ts +1 -2
  114. package/dist/auth/react.d.ts.map +1 -1
  115. package/dist/auth/react.js +1 -2
  116. package/dist/auth/trpc.d.ts +1 -1
  117. package/dist/auth/trpc.d.ts.map +1 -1
  118. package/dist/auth/trpc.js +0 -1
  119. package/dist/cli/lib/fix-master-admin.d.ts.map +1 -1
  120. package/dist/cli/lib/fix-master-admin.js +12 -25
  121. package/dist/cli/lib/update-sections.d.ts.map +1 -1
  122. package/dist/cli/lib/update-sections.js +29 -24
  123. package/dist/core/config/config-loader.d.ts +23 -7
  124. package/dist/core/config/config-loader.d.ts.map +1 -1
  125. package/dist/core/config/config-loader.js +26 -9
  126. package/dist/core/fields/select.d.ts +1 -1
  127. package/dist/core/sections/category.d.ts +44 -44
  128. package/dist/core/sections/hasItems.d.ts +44 -44
  129. package/dist/core/sections/section.d.ts +23 -23
  130. package/dist/core/sections/simple.d.ts +8 -8
  131. package/dist/core/types/index.d.ts +17 -0
  132. package/dist/core/types/index.d.ts.map +1 -1
  133. package/dist/index.d.ts +0 -1
  134. package/dist/index.d.ts.map +1 -1
  135. package/dist/index.js +0 -1
  136. package/dist/plugins/client.d.ts +19 -0
  137. package/dist/plugins/client.d.ts.map +1 -0
  138. package/dist/plugins/client.js +24 -0
  139. package/dist/plugins/define.d.ts +4 -0
  140. package/dist/plugins/define.d.ts.map +1 -0
  141. package/dist/plugins/define.js +3 -0
  142. package/dist/plugins/derive.d.ts +32 -0
  143. package/dist/plugins/derive.d.ts.map +1 -0
  144. package/dist/plugins/derive.js +77 -0
  145. package/dist/plugins/loader.d.ts +51 -7
  146. package/dist/plugins/loader.d.ts.map +1 -1
  147. package/dist/plugins/loader.js +111 -51
  148. package/dist/plugins/manifest.d.ts +28 -0
  149. package/dist/plugins/manifest.d.ts.map +1 -0
  150. package/dist/plugins/manifest.js +83 -0
  151. package/dist/plugins/prefetch.d.ts +16 -0
  152. package/dist/plugins/prefetch.d.ts.map +1 -0
  153. package/dist/plugins/prefetch.js +40 -0
  154. package/dist/plugins/registry.d.ts +22 -0
  155. package/dist/plugins/registry.d.ts.map +1 -0
  156. package/dist/plugins/registry.js +25 -0
  157. package/dist/plugins/server.d.ts +2 -0
  158. package/dist/plugins/server.d.ts.map +1 -1
  159. package/dist/plugins/server.js +2 -0
  160. package/dist/plugins/types.d.ts +9 -0
  161. package/dist/plugins/types.d.ts.map +1 -0
  162. package/dist/plugins/types.js +0 -0
  163. package/dist/translations/base/en.d.ts +1 -0
  164. package/dist/translations/base/en.d.ts.map +1 -1
  165. package/dist/translations/base/en.js +1 -0
  166. package/dist/translations/client.d.ts +16 -4
  167. package/dist/translations/client.d.ts.map +1 -1
  168. package/dist/translations/server.d.ts +16 -4
  169. package/dist/translations/server.d.ts.map +1 -1
  170. package/dist/utils/console-log.d.ts +18 -0
  171. package/dist/utils/console-log.d.ts.map +1 -0
  172. package/dist/utils/console-log.js +28 -0
  173. package/dist/utils/index.d.ts +1 -0
  174. package/dist/utils/index.d.ts.map +1 -1
  175. package/dist/utils/index.js +1 -0
  176. package/dist/utils/log.d.ts +18 -0
  177. package/dist/utils/log.d.ts.map +1 -0
  178. package/dist/utils/log.js +28 -0
  179. package/dist/validators/index.d.ts +1 -0
  180. package/dist/validators/index.d.ts.map +1 -1
  181. package/dist/validators/index.js +1 -0
  182. package/dist/validators/tags.d.ts +4 -0
  183. package/dist/validators/tags.d.ts.map +1 -0
  184. package/dist/validators/tags.js +8 -0
  185. package/package.json +34 -16
package/README.md CHANGED
@@ -175,18 +175,70 @@ export default categorySection({
175
175
  })
176
176
  ```
177
177
 
178
- ## API Reference
179
-
180
- ### Core Modules
181
-
182
- #### API (`nextjs-cms/api`)
183
- - **appRouter**: Main tRPC router with all CMS endpoints
184
- - **createCaller**: Server-side API caller factory
185
- - **createTRPCContext**: Context factory for tRPC requests
186
-
187
- #### Authentication (`nextjs-cms/auth`)
188
- - **JWT Management**: Token creation, verification, and refresh
189
- - **React Hooks**: `useAxiosPrivate`, `useRefreshToken`
178
+ ## API Reference
179
+
180
+ ### Extending tRPC
181
+
182
+ Create an app-owned tRPC server entrypoint so custom routers are included in the final `AppRouter` type:
183
+
184
+ ```typescript
185
+ // app/_trpc/server.ts
186
+ import 'server-only'
187
+
188
+ import { createTRPCRouter } from 'nextjs-cms/api/server'
189
+ import { dashboardRouter } from './routers/dashboard'
190
+
191
+ export const trpc = createTRPCRouter({
192
+ routers: {
193
+ dashboard: dashboardRouter,
194
+ },
195
+ })
196
+
197
+ export type AppRouter = typeof trpc.appRouter
198
+ export const { api, HydrateClient } = trpc
199
+ ```
200
+
201
+ Create the matching client entrypoint:
202
+
203
+ ```typescript
204
+ // app/_trpc/client.tsx
205
+ 'use client'
206
+
207
+ import { createNextjsCmsClient } from 'nextjs-cms/api/client'
208
+ import type { AppRouter } from './server'
209
+
210
+ export const { trpc, NextjsCmsProvider } = createNextjsCmsClient<AppRouter>()
211
+ ```
212
+
213
+ Export final app router inference helpers from the app:
214
+
215
+ ```typescript
216
+ // app/_trpc/types.ts
217
+ import type { inferRouterInputs, inferRouterOutputs } from '@trpc/server'
218
+ import type { AppRouter } from './server'
219
+
220
+ export type RouterInputs = inferRouterInputs<AppRouter>
221
+ export type RouterOutputs = inferRouterOutputs<AppRouter>
222
+ ```
223
+
224
+ Mount the handler from the app-owned router:
225
+
226
+ ```typescript
227
+ // app/api/trpc/[trpc]/route.ts
228
+ import { trpc } from '@/app/_trpc/server'
229
+
230
+ export const { GET, POST } = trpc.handler
231
+ ```
232
+
233
+ ### Core Modules
234
+
235
+ #### API
236
+ - **Server runtime**: `createTRPCRouter`, procedures, and `createTRPCContext` from `nextjs-cms/api/server`
237
+ - **Client runtime**: `createNextjsCmsClient` and `useAxiosPrivate` from `nextjs-cms/api/client`
238
+
239
+ #### Authentication (`nextjs-cms/auth`)
240
+ - **JWT Management**: Token creation, verification, and refresh
241
+ - **React Hooks**: `useSession`, `useRefreshToken`
190
242
  - **Server Actions**: Authentication utilities for server components
191
243
 
192
244
  #### Core (`nextjs-cms/core`)
@@ -288,4 +340,4 @@ Contributions are welcome! Please read our contributing guidelines and submit pu
288
340
 
289
341
  ## License
290
342
 
291
- MIT License - see LICENSE file for details.
343
+ MIT License - see LICENSE file for details.
@@ -0,0 +1,30 @@
1
+ import 'server-only';
2
+ import type { Session } from '../../auth/index.js';
3
+ export declare const getDocument: (session: Session, input: {
4
+ name: string;
5
+ sectionName: string;
6
+ fieldName: string;
7
+ }) => Promise<{
8
+ base64: string;
9
+ mimeType: string;
10
+ }>;
11
+ export declare const getPhoto: (input: {
12
+ name: string;
13
+ folder: string;
14
+ isThumb?: boolean;
15
+ }) => Promise<string>;
16
+ export declare function streamPhoto(input: {
17
+ name: string;
18
+ folder: string;
19
+ isThumb?: boolean;
20
+ }): Promise<ReadableStream<Uint8Array<ArrayBufferLike>>>;
21
+ export declare const getVideo: (session: Session, input: {
22
+ name: string;
23
+ sectionName: string;
24
+ fieldName: string;
25
+ }) => Promise<never>;
26
+ export declare const streamFile: (path: string, options?: {
27
+ start?: number;
28
+ end?: number;
29
+ }) => Promise<ReadableStream<Uint8Array>>;
30
+ //# sourceMappingURL=files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../../src/api/actions/files.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AAWpB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAOlD,eAAO,MAAM,WAAW,GACpB,SAAS,OAAO,EAChB,OAAO;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE;;;EA4GlE,CAAA;AA2DD,eAAO,MAAM,QAAQ,GAAU,OAAO;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,oBAgDxF,CAAA;AAGD,wBAAsB,WAAW,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,wDAyB3F;AAGD,eAAO,MAAM,QAAQ,GAAU,SAAS,OAAO,EAAE,OAAO;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,mBAE/G,CAAA;AAGD,eAAO,MAAM,UAAU,GACnB,MAAM,MAAM,EACZ,UAAU;IACN,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,GAAG,CAAC,EAAE,MAAM,CAAA;CACf,KACF,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAGpC,CAAA"}
@@ -0,0 +1,234 @@
1
+ import 'server-only';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import { Readable } from 'stream';
5
+ import { TRPCError } from '@trpc/server';
6
+ import { fileTypeFromBuffer } from 'file-type';
7
+ import { readChunk } from 'read-chunk';
8
+ import sharp from 'sharp';
9
+ import through2 from 'through2';
10
+ import { getCMSConfig } from '../../core/config/index.js';
11
+ import { SectionFactory } from '../../core/factories/index.js';
12
+ import getString from '../../translations/index.js';
13
+ import { sanitizeFileName, sanitizeFolderOrFileName } from '../../utils/index.js';
14
+ export const getDocument = async (session, input) => {
15
+ const { name, sectionName, fieldName } = input;
16
+ // Sanitize the inputs
17
+ const sanitizedFolder = sanitizeFolderOrFileName(sectionName);
18
+ const sanitizedName = sanitizeFileName(name);
19
+ /**
20
+ * Check the section and the field name, and get the allowed extensions,
21
+ * while also checking if the user has access to the section
22
+ */
23
+ const section = await SectionFactory.getSectionForAdmin({
24
+ name: sanitizedFolder,
25
+ admin: { id: session.user.id },
26
+ });
27
+ /**
28
+ * If the check fails, throw an error
29
+ */
30
+ if (!section?.name) {
31
+ throw new TRPCError({
32
+ code: 'BAD_REQUEST',
33
+ message: getString('invalidFilePath', session.user.language),
34
+ });
35
+ }
36
+ const fieldConfig = section.fields.find((field) => field.name === fieldName);
37
+ if (!fieldConfig || typeof fieldConfig.build !== 'function') {
38
+ throw new TRPCError({
39
+ code: 'BAD_REQUEST',
40
+ message: getString('invalidRequest', session.user.language),
41
+ });
42
+ }
43
+ const field = fieldConfig.build();
44
+ /**
45
+ * If field is not found, throw an error
46
+ */
47
+ if (!field || !field.name || !field.extensions || field.extensions.length === 0) {
48
+ throw new TRPCError({
49
+ code: 'BAD_REQUEST',
50
+ message: getString('invalidRequest', session.user.language),
51
+ });
52
+ }
53
+ /**
54
+ * Split the allowed extensions into an array
55
+ */
56
+ const uploadsFolder = (await getCMSConfig()).media.upload.path;
57
+ const documentAllowedExtensions = field.extensions;
58
+ const dir = '.documents';
59
+ const pathToFile = path.join(uploadsFolder, dir, sanitizedFolder, sanitizedName);
60
+ /**
61
+ * First, check if the file exists
62
+ */
63
+ if (!fs.existsSync(pathToFile)) {
64
+ throw new TRPCError({
65
+ code: 'BAD_REQUEST',
66
+ message: getString('fileNotFound', session.user.language),
67
+ });
68
+ }
69
+ /**
70
+ * Read the first 4100 bytes of the file
71
+ */
72
+ const chunkBuffer = await readChunk(pathToFile, { length: 4100 });
73
+ /**
74
+ * Get the file type from the buffer
75
+ */
76
+ const fileType = await fileTypeFromBuffer(chunkBuffer);
77
+ /**
78
+ * If the file type is invalid, return an error
79
+ */
80
+ if (!fileType) {
81
+ throw new TRPCError({
82
+ code: 'BAD_REQUEST',
83
+ message: getString('invalidFileType', session.user.language),
84
+ });
85
+ }
86
+ /**
87
+ * Check if the file type is allowed
88
+ */
89
+ if (!documentAllowedExtensions.includes(fileType.ext)) {
90
+ throw new TRPCError({
91
+ code: 'BAD_REQUEST',
92
+ message: getString('invalidFileType', session.user.language),
93
+ });
94
+ }
95
+ /**
96
+ * Convert the image to webp format and return a buffer
97
+ */
98
+ const buffer = fs.readFileSync(pathToFile);
99
+ /**
100
+ * Create a base64 string from the buffer
101
+ */
102
+ const base64 = buffer.toString('base64');
103
+ /**
104
+ * Return the base64 string with the mime type
105
+ */
106
+ return {
107
+ base64: `data:${fileType.mime};base64,${base64}`,
108
+ mimeType: fileType.mime,
109
+ };
110
+ };
111
+ /**
112
+ * Helper function with proper cleanup for converting Node.js stream to Web ReadableStream
113
+ * Uses pull()-based reading for proper backpressure support.
114
+ * @param nodeStream
115
+ * @param sharpInstance
116
+ */
117
+ function nodeStreamToWebStream(nodeStream, sharpInstance) {
118
+ return new ReadableStream({
119
+ start() {
120
+ // Start paused — let pull() drive reading
121
+ if ('pause' in nodeStream && typeof nodeStream.pause === 'function') {
122
+ nodeStream.pause();
123
+ }
124
+ },
125
+ pull(controller) {
126
+ return new Promise((resolve, reject) => {
127
+ const onData = (chunk) => {
128
+ controller.enqueue(new Uint8Array(chunk));
129
+ if ('pause' in nodeStream && typeof nodeStream.pause === 'function') {
130
+ nodeStream.pause();
131
+ }
132
+ nodeStream.removeListener('data', onData);
133
+ nodeStream.removeListener('error', onError);
134
+ resolve();
135
+ };
136
+ const onError = (err) => {
137
+ controller.error(err);
138
+ nodeStream.removeListener('data', onData);
139
+ reject(err);
140
+ };
141
+ nodeStream.on('data', onData);
142
+ nodeStream.on('error', onError);
143
+ nodeStream.once('end', () => {
144
+ controller.close();
145
+ resolve();
146
+ });
147
+ if ('resume' in nodeStream && typeof nodeStream.resume === 'function') {
148
+ nodeStream.resume();
149
+ }
150
+ });
151
+ },
152
+ cancel() {
153
+ // Proper cleanup sequence
154
+ sharpInstance.destroy();
155
+ nodeStream.removeAllListeners();
156
+ if ('destroy' in nodeStream && typeof nodeStream.destroy === 'function') {
157
+ nodeStream.destroy();
158
+ }
159
+ },
160
+ });
161
+ }
162
+ export const getPhoto = async (input) => {
163
+ const { name, folder, isThumb } = input;
164
+ // Sanitize the inputs
165
+ const sanitizedFolder = sanitizeFolderOrFileName(folder);
166
+ const sanitizedName = sanitizeFileName(name);
167
+ /**
168
+ * Check the folder name matches a section name in the database
169
+ * Notice: Maybe we don't need this check because making an sql call for each image is maybe expensive
170
+ */
171
+ /*const sectionQuery = await db
172
+ .select()
173
+ .from(SectionsTable)
174
+ .where(eq(SectionsTable.sectionName, sanitizedFolder))
175
+ .limit(1)
176
+
177
+ if (sectionQuery.length === 0) {
178
+ throw new Error('Invalid folder name')
179
+ }*/
180
+ const uploadsFolder = (await getCMSConfig()).media.upload.path;
181
+ const dir = isThumb ? '.thumbs' : '.photos';
182
+ const pathToFile = path.join(uploadsFolder, dir, sanitizedFolder, sanitizedName);
183
+ /**
184
+ * Disable caching for the image to avoid unlink issues when removing the image
185
+ */
186
+ sharp.cache({ files: 0 });
187
+ sharp.cache(false);
188
+ /**
189
+ * Convert the image to webp format and return a buffer
190
+ */
191
+ const sharpInstance = sharp(pathToFile);
192
+ let webpBuffer = await sharpInstance // Load the image
193
+ .toFormat('webp') // Re-encode the image to webp
194
+ .withExif({}) // Strip the exif data
195
+ .toBuffer(); // Return a buffer
196
+ /**
197
+ * Destroy the sharp instance to free it from memory
198
+ */
199
+ const base64String = webpBuffer.toString('base64');
200
+ sharpInstance.destroy();
201
+ /**
202
+ * Return the base64 string with the mime type
203
+ */
204
+ return `data:image/webp;base64,${base64String}`;
205
+ };
206
+ export async function streamPhoto(input) {
207
+ const { name, folder, isThumb } = input;
208
+ // Sanitize the inputs
209
+ const sanitizedFolder = sanitizeFolderOrFileName(folder);
210
+ const sanitizedName = sanitizeFileName(name);
211
+ const dir = isThumb ? '.thumbs' : '.photos';
212
+ const uploadsFolder = (await getCMSConfig()).media.upload.path;
213
+ const pathToFile = path.join(uploadsFolder, dir, sanitizedFolder, sanitizedName);
214
+ /**
215
+ * Disable caching for the image to avoid unlink issues when removing the image
216
+ */
217
+ sharp.cache({ files: 0 });
218
+ sharp.cache(false);
219
+ // Process all images through Sharp
220
+ const processedImage = sharp(pathToFile).toFormat('webp').withExif({});
221
+ /**
222
+ * Convert Node.js stream to Web ReadableStream
223
+ * Also, add through2 for proper streaming
224
+ */
225
+ const nodeStream = processedImage.pipe(through2());
226
+ return nodeStreamToWebStream(nodeStream, processedImage);
227
+ }
228
+ export const getVideo = async (session, input) => {
229
+ throw new Error(getString('useVideoApiRoute', session.user.language));
230
+ };
231
+ export const streamFile = async (path, options) => {
232
+ const stream = fs.createReadStream(path, options);
233
+ return Readable.toWeb(stream);
234
+ };
@@ -0,0 +1,4 @@
1
+ import 'server-only';
2
+ export { streamFile, getPhoto } from './files.js';
3
+ export { getAdminPrivileges } from './privileges.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/api/actions/index.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AAEpB,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA"}
@@ -0,0 +1,3 @@
1
+ import 'server-only';
2
+ export { streamFile, getPhoto } from './files.js';
3
+ export { getAdminPrivileges } from './privileges.js';