@yimingliao/cms 0.0.75 → 0.0.77

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.
@@ -468,6 +468,29 @@ var jsonArrayToUi = (data) => {
468
468
  }
469
469
  };
470
470
 
471
+ // src/shared/utils/ensure-array.ts
472
+ function ensureArray(value) {
473
+ if (value == null) return [];
474
+ return Array.isArray(value) ? value : [value];
475
+ }
476
+
477
+ // src/shared/utils/format-date-time.ts
478
+ var dateTimeFormatter = new Intl.DateTimeFormat(void 0, {
479
+ year: "numeric",
480
+ month: "numeric",
481
+ day: "numeric",
482
+ hour: "2-digit",
483
+ minute: "2-digit"
484
+ });
485
+ function formatDateTime(input) {
486
+ if (!input) return "";
487
+ const date = typeof input === "string" ? new Date(input) : input;
488
+ if (Number.isNaN(date.getTime())) {
489
+ return "";
490
+ }
491
+ return dateTimeFormatter.format(date);
492
+ }
493
+
471
494
  // src/shared/units.ts
472
495
  var SIZE = {
473
496
  BYTE: 1,
@@ -478,4 +501,4 @@ var SIZE = {
478
501
  PB: 1024 ** 5
479
502
  };
480
503
 
481
- export { FILE_TYPES, OG_TYPE_ARRAY, SIZE, TWITTER_CARD_ARRAY, classifyFileType, createBuildArticleMetadata, createBuildTranslations, createBuildWebsiteMetadata, datetimeToDb, datetimeToUi, findTranslation, formatFileSize, getMediaInfo, jsonArrayToDb, jsonArrayToUi, mimeToExtension, result, serializeJsonLd };
504
+ export { FILE_TYPES, OG_TYPE_ARRAY, SIZE, TWITTER_CARD_ARRAY, classifyFileType, createBuildArticleMetadata, createBuildTranslations, createBuildWebsiteMetadata, datetimeToDb, datetimeToUi, ensureArray, findTranslation, formatDateTime, formatFileSize, getMediaInfo, jsonArrayToDb, jsonArrayToUi, mimeToExtension, result, serializeJsonLd };
@@ -1,4 +1,4 @@
1
- import { mimeToExtension } from './chunk-N2PRNBP2.js';
1
+ import { mimeToExtension } from './chunk-OAENV763.js';
2
2
  import path from 'path/posix';
3
3
  import { ulid } from 'ulid';
4
4
 
@@ -1,5 +1,8 @@
1
- import { R as Result } from '../types-DHlRoJwv.js';
1
+ import { R as Result, S as SuccessResult, a as ErrorResult } from '../types-DHlRoJwv.js';
2
2
  import { Logger } from 'logry';
3
+ import * as _tanstack_react_query from '@tanstack/react-query';
4
+ import { QueryClient, UseMutationOptions, UseQueryOptions } from '@tanstack/react-query';
5
+ import * as _tanstack_query_core from '@tanstack/query-core';
3
6
 
4
7
  interface FetchContext {
5
8
  input: string;
@@ -27,4 +30,268 @@ declare function createResponseInterceptor({ logger }: {
27
30
  logger: Logger;
28
31
  }): ResponseInterceptor;
29
32
 
30
- export { createRequestInterceptor, createResponseInterceptor, createSmartFetch };
33
+ type ShowToastOption = boolean | {
34
+ success?: boolean;
35
+ error?: boolean;
36
+ };
37
+ declare const handleToast: (result: SuccessResult | ErrorResult, showToast?: ShowToastOption) => void;
38
+
39
+ declare function createUseCommand(queryClient: QueryClient): <P = void, R = unknown>(fn: (params: P) => Promise<Result<R | undefined>>, mutationOptions?: UseMutationOptions<R | undefined, unknown, P> & {
40
+ showToast?: ShowToastOption;
41
+ shouldTrigger?: (payload: P) => (boolean | undefined) | Promise<boolean | undefined>;
42
+ clearAll?: boolean;
43
+ }) => {
44
+ execute: (params: P extends void ? void : P) => Promise<R | undefined>;
45
+ isRedirecting: boolean;
46
+ errors: string[];
47
+ data: undefined;
48
+ variables: undefined;
49
+ error: null;
50
+ isError: false;
51
+ isIdle: true;
52
+ isPending: false;
53
+ isSuccess: false;
54
+ status: "idle";
55
+ mutate: _tanstack_react_query.UseMutateFunction<R | undefined, Error, P, unknown>;
56
+ reset: () => void;
57
+ context: unknown;
58
+ failureCount: number;
59
+ failureReason: Error | null;
60
+ isPaused: boolean;
61
+ submittedAt: number;
62
+ mutateAsync: _tanstack_react_query.UseMutateAsyncFunction<R | undefined, Error, P, unknown>;
63
+ } | {
64
+ execute: (params: P extends void ? void : P) => Promise<R | undefined>;
65
+ isRedirecting: boolean;
66
+ errors: string[];
67
+ data: undefined;
68
+ variables: P;
69
+ error: null;
70
+ isError: false;
71
+ isIdle: false;
72
+ isPending: true;
73
+ isSuccess: false;
74
+ status: "pending";
75
+ mutate: _tanstack_react_query.UseMutateFunction<R | undefined, Error, P, unknown>;
76
+ reset: () => void;
77
+ context: unknown;
78
+ failureCount: number;
79
+ failureReason: Error | null;
80
+ isPaused: boolean;
81
+ submittedAt: number;
82
+ mutateAsync: _tanstack_react_query.UseMutateAsyncFunction<R | undefined, Error, P, unknown>;
83
+ } | {
84
+ execute: (params: P extends void ? void : P) => Promise<R | undefined>;
85
+ isRedirecting: boolean;
86
+ errors: string[];
87
+ data: undefined;
88
+ error: Error;
89
+ variables: P;
90
+ isError: true;
91
+ isIdle: false;
92
+ isPending: false;
93
+ isSuccess: false;
94
+ status: "error";
95
+ mutate: _tanstack_react_query.UseMutateFunction<R | undefined, Error, P, unknown>;
96
+ reset: () => void;
97
+ context: unknown;
98
+ failureCount: number;
99
+ failureReason: Error | null;
100
+ isPaused: boolean;
101
+ submittedAt: number;
102
+ mutateAsync: _tanstack_react_query.UseMutateAsyncFunction<R | undefined, Error, P, unknown>;
103
+ } | {
104
+ execute: (params: P extends void ? void : P) => Promise<R | undefined>;
105
+ isRedirecting: boolean;
106
+ errors: string[];
107
+ data: R | undefined;
108
+ error: null;
109
+ variables: P;
110
+ isError: false;
111
+ isIdle: false;
112
+ isPending: false;
113
+ isSuccess: true;
114
+ status: "success";
115
+ mutate: _tanstack_react_query.UseMutateFunction<R | undefined, Error, P, unknown>;
116
+ reset: () => void;
117
+ context: unknown;
118
+ failureCount: number;
119
+ failureReason: Error | null;
120
+ isPaused: boolean;
121
+ submittedAt: number;
122
+ mutateAsync: _tanstack_react_query.UseMutateAsyncFunction<R | undefined, Error, P, unknown>;
123
+ };
124
+
125
+ declare function createUseQuery(): <P = void, R = unknown, TData = R>(fn: (params?: P) => Promise<Result<R>>, queryKey: readonly unknown[], queryOptions?: Omit<UseQueryOptions<R | undefined, Error, TData, readonly unknown[]>, "queryKey"> & {
126
+ params?: P;
127
+ }) => {
128
+ isNotFound: boolean;
129
+ data: _tanstack_query_core.NoInfer<TData>;
130
+ error: Error;
131
+ isError: true;
132
+ isPending: false;
133
+ isLoading: false;
134
+ isLoadingError: false;
135
+ isRefetchError: true;
136
+ isSuccess: false;
137
+ isPlaceholderData: false;
138
+ status: "error";
139
+ dataUpdatedAt: number;
140
+ errorUpdatedAt: number;
141
+ failureCount: number;
142
+ failureReason: Error | null;
143
+ errorUpdateCount: number;
144
+ isFetched: boolean;
145
+ isFetchedAfterMount: boolean;
146
+ isFetching: boolean;
147
+ isInitialLoading: boolean;
148
+ isPaused: boolean;
149
+ isRefetching: boolean;
150
+ isStale: boolean;
151
+ isEnabled: boolean;
152
+ refetch: (options?: _tanstack_query_core.RefetchOptions) => Promise<_tanstack_query_core.QueryObserverResult<_tanstack_query_core.NoInfer<TData>, Error>>;
153
+ fetchStatus: _tanstack_query_core.FetchStatus;
154
+ promise: Promise<_tanstack_query_core.NoInfer<TData>>;
155
+ } | {
156
+ isNotFound: boolean;
157
+ data: _tanstack_query_core.NoInfer<TData>;
158
+ error: null;
159
+ isError: false;
160
+ isPending: false;
161
+ isLoading: false;
162
+ isLoadingError: false;
163
+ isRefetchError: false;
164
+ isSuccess: true;
165
+ isPlaceholderData: false;
166
+ status: "success";
167
+ dataUpdatedAt: number;
168
+ errorUpdatedAt: number;
169
+ failureCount: number;
170
+ failureReason: Error | null;
171
+ errorUpdateCount: number;
172
+ isFetched: boolean;
173
+ isFetchedAfterMount: boolean;
174
+ isFetching: boolean;
175
+ isInitialLoading: boolean;
176
+ isPaused: boolean;
177
+ isRefetching: boolean;
178
+ isStale: boolean;
179
+ isEnabled: boolean;
180
+ refetch: (options?: _tanstack_query_core.RefetchOptions) => Promise<_tanstack_query_core.QueryObserverResult<_tanstack_query_core.NoInfer<TData>, Error>>;
181
+ fetchStatus: _tanstack_query_core.FetchStatus;
182
+ promise: Promise<_tanstack_query_core.NoInfer<TData>>;
183
+ } | {
184
+ isNotFound: boolean;
185
+ data: undefined;
186
+ error: Error;
187
+ isError: true;
188
+ isPending: false;
189
+ isLoading: false;
190
+ isLoadingError: true;
191
+ isRefetchError: false;
192
+ isSuccess: false;
193
+ isPlaceholderData: false;
194
+ status: "error";
195
+ dataUpdatedAt: number;
196
+ errorUpdatedAt: number;
197
+ failureCount: number;
198
+ failureReason: Error | null;
199
+ errorUpdateCount: number;
200
+ isFetched: boolean;
201
+ isFetchedAfterMount: boolean;
202
+ isFetching: boolean;
203
+ isInitialLoading: boolean;
204
+ isPaused: boolean;
205
+ isRefetching: boolean;
206
+ isStale: boolean;
207
+ isEnabled: boolean;
208
+ refetch: (options?: _tanstack_query_core.RefetchOptions) => Promise<_tanstack_query_core.QueryObserverResult<_tanstack_query_core.NoInfer<TData>, Error>>;
209
+ fetchStatus: _tanstack_query_core.FetchStatus;
210
+ promise: Promise<_tanstack_query_core.NoInfer<TData>>;
211
+ } | {
212
+ isNotFound: boolean;
213
+ data: undefined;
214
+ error: null;
215
+ isError: false;
216
+ isPending: true;
217
+ isLoading: true;
218
+ isLoadingError: false;
219
+ isRefetchError: false;
220
+ isSuccess: false;
221
+ isPlaceholderData: false;
222
+ status: "pending";
223
+ dataUpdatedAt: number;
224
+ errorUpdatedAt: number;
225
+ failureCount: number;
226
+ failureReason: Error | null;
227
+ errorUpdateCount: number;
228
+ isFetched: boolean;
229
+ isFetchedAfterMount: boolean;
230
+ isFetching: boolean;
231
+ isInitialLoading: boolean;
232
+ isPaused: boolean;
233
+ isRefetching: boolean;
234
+ isStale: boolean;
235
+ isEnabled: boolean;
236
+ refetch: (options?: _tanstack_query_core.RefetchOptions) => Promise<_tanstack_query_core.QueryObserverResult<_tanstack_query_core.NoInfer<TData>, Error>>;
237
+ fetchStatus: _tanstack_query_core.FetchStatus;
238
+ promise: Promise<_tanstack_query_core.NoInfer<TData>>;
239
+ } | {
240
+ isNotFound: boolean;
241
+ data: undefined;
242
+ error: null;
243
+ isError: false;
244
+ isPending: true;
245
+ isLoadingError: false;
246
+ isRefetchError: false;
247
+ isSuccess: false;
248
+ isPlaceholderData: false;
249
+ status: "pending";
250
+ dataUpdatedAt: number;
251
+ errorUpdatedAt: number;
252
+ failureCount: number;
253
+ failureReason: Error | null;
254
+ errorUpdateCount: number;
255
+ isFetched: boolean;
256
+ isFetchedAfterMount: boolean;
257
+ isFetching: boolean;
258
+ isLoading: boolean;
259
+ isInitialLoading: boolean;
260
+ isPaused: boolean;
261
+ isRefetching: boolean;
262
+ isStale: boolean;
263
+ isEnabled: boolean;
264
+ refetch: (options?: _tanstack_query_core.RefetchOptions) => Promise<_tanstack_query_core.QueryObserverResult<_tanstack_query_core.NoInfer<TData>, Error>>;
265
+ fetchStatus: _tanstack_query_core.FetchStatus;
266
+ promise: Promise<_tanstack_query_core.NoInfer<TData>>;
267
+ } | {
268
+ isNotFound: boolean;
269
+ data: _tanstack_query_core.NoInfer<TData>;
270
+ isError: false;
271
+ error: null;
272
+ isPending: false;
273
+ isLoading: false;
274
+ isLoadingError: false;
275
+ isRefetchError: false;
276
+ isSuccess: true;
277
+ isPlaceholderData: true;
278
+ status: "success";
279
+ dataUpdatedAt: number;
280
+ errorUpdatedAt: number;
281
+ failureCount: number;
282
+ failureReason: Error | null;
283
+ errorUpdateCount: number;
284
+ isFetched: boolean;
285
+ isFetchedAfterMount: boolean;
286
+ isFetching: boolean;
287
+ isInitialLoading: boolean;
288
+ isPaused: boolean;
289
+ isRefetching: boolean;
290
+ isStale: boolean;
291
+ isEnabled: boolean;
292
+ refetch: (options?: _tanstack_query_core.RefetchOptions) => Promise<_tanstack_query_core.QueryObserverResult<_tanstack_query_core.NoInfer<TData>, Error>>;
293
+ fetchStatus: _tanstack_query_core.FetchStatus;
294
+ promise: Promise<_tanstack_query_core.NoInfer<TData>>;
295
+ };
296
+
297
+ export { type ShowToastOption, createRequestInterceptor, createResponseInterceptor, createSmartFetch, createUseCommand, createUseQuery, handleToast };
@@ -1,4 +1,10 @@
1
- // src/client/infrastructure/smart-fetch/smart-fetch.ts
1
+ import { ensureArray } from '../chunk-OAENV763.js';
2
+ import { toast } from 'sonner';
3
+ import { jsx, jsxs } from 'react/jsx-runtime';
4
+ import { useMutation, useQuery } from '@tanstack/react-query';
5
+ import { useState } from 'react';
6
+
7
+ // src/client/infrastructure/fetch/smart-fetch.ts
2
8
  function createSmartFetch({
3
9
  requestInterceptor,
4
10
  responseInterceptor,
@@ -22,7 +28,7 @@ function createSmartFetch({
22
28
  return smartFetch;
23
29
  }
24
30
 
25
- // src/client/infrastructure/smart-fetch/request-interceptor.ts
31
+ // src/client/infrastructure/fetch/request-interceptor.ts
26
32
  function createRequestInterceptor({ baseUrl }) {
27
33
  const requestInterceptor = (ctx) => {
28
34
  const normalizedBase = baseUrl.replace(/\/+$/, "");
@@ -43,7 +49,7 @@ function createRequestInterceptor({ baseUrl }) {
43
49
  return requestInterceptor;
44
50
  }
45
51
 
46
- // src/client/infrastructure/smart-fetch/response-interceptor.ts
52
+ // src/client/infrastructure/fetch/response-interceptor.ts
47
53
  function createResponseInterceptor({ logger }) {
48
54
  const responseInterceptor = async (response, ctx) => {
49
55
  const duration = Date.now() - (ctx.meta.startTime ?? 0);
@@ -64,5 +70,119 @@ function createResponseInterceptor({ logger }) {
64
70
  };
65
71
  return responseInterceptor;
66
72
  }
73
+ function ErrorDisplay({ errors }) {
74
+ return /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: errors.map((error, index) => {
75
+ let field = error.field ?? "";
76
+ if (field.startsWith("translations")) field = field.slice(15);
77
+ if (field.includes(".") && !Number.isNaN(Number(field.at(-1)))) {
78
+ const [f, i] = field.split(".");
79
+ field = `${f} ${Number(i) + 1}`;
80
+ }
81
+ return /* @__PURE__ */ jsxs("p", { children: [
82
+ /* @__PURE__ */ jsxs("span", { className: "font-bold", children: [
83
+ "(",
84
+ index + 1,
85
+ ")"
86
+ ] }),
87
+ "\xA0",
88
+ /* @__PURE__ */ jsx("span", { className: "font-bold underline underline-offset-2", children: field }),
89
+ "\xA0",
90
+ /* @__PURE__ */ jsx("span", { children: error.message })
91
+ ] }, index);
92
+ }) });
93
+ }
94
+ var createErrorDisplay = (errors) => ErrorDisplay({ errors });
95
+
96
+ // src/client/infrastructure/toast/should-show-toast.ts
97
+ var shouldShowToast = (type, showToast) => {
98
+ if (showToast === void 0) return false;
99
+ if (typeof showToast === "boolean") return showToast;
100
+ return !!showToast[type];
101
+ };
102
+
103
+ // src/client/infrastructure/toast/handle-toast.ts
104
+ var handleToast = (result, showToast) => {
105
+ const normalizedShowToast = typeof showToast === "object" ? {
106
+ success: showToast.success ?? true,
107
+ error: showToast.error ?? true
108
+ } : showToast ?? true;
109
+ if (result.success) {
110
+ const { message } = result;
111
+ if (shouldShowToast("success", normalizedShowToast) && message) {
112
+ toast.success(message);
113
+ }
114
+ } else {
115
+ const { message, errors } = result;
116
+ if (shouldShowToast("error", normalizedShowToast)) {
117
+ if (errors && errors.length > 0) {
118
+ toast.error(createErrorDisplay(errors));
119
+ } else if (message) {
120
+ toast.error(message);
121
+ } else {
122
+ toast.error("Unknown Error");
123
+ }
124
+ }
125
+ }
126
+ };
127
+ function createUseCommand(queryClient) {
128
+ return function useCommand(fn, mutationOptions) {
129
+ const [isRedirecting, setIsRedirecting] = useState(false);
130
+ const [errors, setErrors] = useState([]);
131
+ const { showToast, shouldTrigger, clearAll = true } = mutationOptions || {};
132
+ const mutation = useMutation({
133
+ ...mutationOptions,
134
+ mutationFn: async (params) => {
135
+ const response = await fn(params);
136
+ handleToast(response, showToast);
137
+ if (response.success) {
138
+ setErrors([]);
139
+ if (clearAll) {
140
+ await queryClient.invalidateQueries({
141
+ predicate: (query) => !query.queryKey[0].startsWith("auth")
142
+ });
143
+ }
144
+ return response.data;
145
+ }
146
+ setErrors(
147
+ ensureArray(response.errors).map((e) => e.field).filter((f) => typeof f === "string")
148
+ );
149
+ throw new Error(response.message);
150
+ }
151
+ });
152
+ const execute = (async (params) => {
153
+ try {
154
+ if (shouldTrigger) {
155
+ const shouldProceed = await shouldTrigger(params);
156
+ if (!shouldProceed) {
157
+ setIsRedirecting(false);
158
+ return void 0;
159
+ }
160
+ }
161
+ setIsRedirecting(true);
162
+ return await mutation.mutateAsync(params);
163
+ } catch {
164
+ setIsRedirecting(false);
165
+ return void 0;
166
+ }
167
+ });
168
+ return { ...mutation, execute, isRedirecting, errors };
169
+ };
170
+ }
171
+ function createUseQuery() {
172
+ return function useQuery$1(fn, queryKey, queryOptions) {
173
+ const { params, ...rest } = queryOptions || {};
174
+ const query = useQuery({
175
+ queryKey: params ? [...queryKey, params] : queryKey,
176
+ queryFn: async () => {
177
+ const response = await fn(params);
178
+ if (response.success) return response.data;
179
+ throw new Error(response.message);
180
+ },
181
+ ...rest
182
+ });
183
+ const isNotFound = !query.isPending && !query.data;
184
+ return { ...query, isNotFound };
185
+ };
186
+ }
67
187
 
68
- export { createRequestInterceptor, createResponseInterceptor, createSmartFetch };
188
+ export { createRequestInterceptor, createResponseInterceptor, createSmartFetch, createUseCommand, createUseQuery, handleToast };
package/dist/index.d.ts CHANGED
@@ -96,6 +96,10 @@ declare const jsonArrayToDb: (data?: unknown) => unknown[];
96
96
 
97
97
  declare const jsonArrayToUi: (data?: unknown[]) => string;
98
98
 
99
+ declare function ensureArray<T>(value: T | T[] | null | undefined): T[];
100
+
101
+ declare function formatDateTime(input?: string | Date): string;
102
+
99
103
  declare const SIZE: {
100
104
  readonly BYTE: 1;
101
105
  readonly KB: 1024;
@@ -106,4 +110,4 @@ declare const SIZE: {
106
110
  };
107
111
  type SizeUnit = keyof typeof SIZE;
108
112
 
109
- export { BaseTranslation, ErrorDetail, ErrorResult, type ErrorResultParams, FileCard, FileFull, Folder, FolderFull, OG_TYPE_ARRAY, type OgType, PostFull, ROOT_FOLDER, ROOT_FOLDER_ID, ROOT_FOLDER_NAME, SIMPLE_UPLOAD_FOLDER_KEY, SIMPLE_UPLOAD_FOLDER_NAME, SIZE, type SizeUnit, SuccessResult, type SuccessResultParams, TWITTER_CARD_ARRAY, type TwitterCard, classifyFileType, createBuildArticleMetadata, createBuildTranslations, createBuildWebsiteMetadata, datetimeToDb, datetimeToUi, findTranslation, formatFileSize, getMediaInfo, isFileLocked, isFolderLocked, jsonArrayToDb, jsonArrayToUi, mimeToExtension, result, serializeJsonLd };
113
+ export { BaseTranslation, ErrorDetail, ErrorResult, type ErrorResultParams, FileCard, FileFull, Folder, FolderFull, OG_TYPE_ARRAY, type OgType, PostFull, ROOT_FOLDER, ROOT_FOLDER_ID, ROOT_FOLDER_NAME, SIMPLE_UPLOAD_FOLDER_KEY, SIMPLE_UPLOAD_FOLDER_NAME, SIZE, type SizeUnit, SuccessResult, type SuccessResultParams, TWITTER_CARD_ARRAY, type TwitterCard, classifyFileType, createBuildArticleMetadata, createBuildTranslations, createBuildWebsiteMetadata, datetimeToDb, datetimeToUi, ensureArray, findTranslation, formatDateTime, formatFileSize, getMediaInfo, isFileLocked, isFolderLocked, jsonArrayToDb, jsonArrayToUi, mimeToExtension, result, serializeJsonLd };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
1
  export { ADMIN_ROLES, POST_TYPES, ROOT_FOLDER, ROOT_FOLDER_ID, ROOT_FOLDER_NAME, SIMPLE_UPLOAD_FOLDER_KEY, SIMPLE_UPLOAD_FOLDER_NAME, isFileLocked, isFolderLocked } from './chunk-FUAJWL2N.js';
2
- export { FILE_TYPES, OG_TYPE_ARRAY, SIZE, TWITTER_CARD_ARRAY, classifyFileType, createBuildArticleMetadata, createBuildTranslations, createBuildWebsiteMetadata, datetimeToDb, datetimeToUi, findTranslation, formatFileSize, getMediaInfo, jsonArrayToDb, jsonArrayToUi, mimeToExtension, result, serializeJsonLd } from './chunk-N2PRNBP2.js';
2
+ export { FILE_TYPES, OG_TYPE_ARRAY, SIZE, TWITTER_CARD_ARRAY, classifyFileType, createBuildArticleMetadata, createBuildTranslations, createBuildWebsiteMetadata, datetimeToDb, datetimeToUi, ensureArray, findTranslation, formatDateTime, formatFileSize, getMediaInfo, jsonArrayToDb, jsonArrayToUi, mimeToExtension, result, serializeJsonLd } from './chunk-OAENV763.js';
@@ -1,5 +1,5 @@
1
1
  import { ADMIN_ROLES, isFileLocked, isFolderLocked, ROOT_FOLDER_ID, ROOT_FOLDER } from '../chunk-FUAJWL2N.js';
2
- import { SIZE, result, datetimeToDb, jsonArrayToDb, mimeToExtension, classifyFileType, TWITTER_CARD_ARRAY, OG_TYPE_ARRAY } from '../chunk-N2PRNBP2.js';
2
+ import { SIZE, result, datetimeToDb, jsonArrayToDb, mimeToExtension, classifyFileType, TWITTER_CARD_ARRAY, OG_TYPE_ARRAY } from '../chunk-OAENV763.js';
3
3
  import jwt from 'jsonwebtoken';
4
4
  import argon2 from 'argon2';
5
5
  import crypto, { timingSafeEqual } from 'crypto';
@@ -1,5 +1,5 @@
1
- import { createObjectKey } from '../../chunk-3J5YR2NA.js';
2
- import '../../chunk-N2PRNBP2.js';
1
+ import { createObjectKey } from '../../chunk-XWXG67I4.js';
2
+ import '../../chunk-OAENV763.js';
3
3
  import { PutObjectCommand, DeleteObjectCommand, CopyObjectCommand } from '@aws-sdk/client-s3';
4
4
 
5
5
  function createR2Service({
@@ -1,5 +1,5 @@
1
- import { createObjectKey } from '../../chunk-3J5YR2NA.js';
2
- import '../../chunk-N2PRNBP2.js';
1
+ import { createObjectKey } from '../../chunk-XWXG67I4.js';
2
+ import '../../chunk-OAENV763.js';
3
3
  import path from 'path/posix';
4
4
  import { createPool } from 'generic-pool';
5
5
  import SFTPClient from 'ssh2-sftp-client';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yimingliao/cms",
3
- "version": "0.0.75",
3
+ "version": "0.0.77",
4
4
  "author": "Yiming Liao",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -44,18 +44,21 @@
44
44
  },
45
45
  "dependencies": {
46
46
  "@keyv/redis": "^5.1.6",
47
+ "@types/react": "^19.2.14",
47
48
  "argon2": "^0.44.0",
48
49
  "jsonwebtoken": "^9.0.3",
49
50
  "keyv": "^5.6.0",
50
51
  "logry": "^2.1.6",
51
52
  "mime-types": "^3.0.2",
52
53
  "nodemailer": "^8.0.1",
54
+ "sonner": "^2.0.7",
53
55
  "ulid": "^3.0.2"
54
56
  },
55
57
  "devDependencies": {
56
58
  "@aws-sdk/client-s3": "^3.1004.0",
57
59
  "@eslint/js": "^10.0.1",
58
60
  "@prisma/client": "6.5.0",
61
+ "@tanstack/react-query": "^5.90.21",
59
62
  "@types/jsonwebtoken": "^9.0.10",
60
63
  "@types/mime-types": "^3.0.1",
61
64
  "@types/nodemailer": "^7.0.11",
@@ -73,6 +76,7 @@
73
76
  "knip": "^5.86.0",
74
77
  "next": "^16.1.6",
75
78
  "prisma": "6.5.0",
79
+ "react": "^19.2.4",
76
80
  "tsup": "^8.5.1",
77
81
  "typescript": "^5.9.3",
78
82
  "typescript-eslint": "^8.56.1",