@withwiz/cms-kit 0.1.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.
- package/README.ko.md +146 -0
- package/README.md +146 -0
- package/dist/chunk-2REYWBQ6.js +32 -0
- package/dist/chunk-2REYWBQ6.js.map +1 -0
- package/dist/chunk-2SYUEQ6J.mjs +17 -0
- package/dist/chunk-2SYUEQ6J.mjs.map +1 -0
- package/dist/chunk-3ILEMZAL.mjs +32 -0
- package/dist/chunk-3ILEMZAL.mjs.map +1 -0
- package/dist/chunk-3Y2TQCHU.mjs +33 -0
- package/dist/chunk-3Y2TQCHU.mjs.map +1 -0
- package/dist/chunk-4LSFAAZW.js +1 -0
- package/dist/chunk-4LSFAAZW.js.map +1 -0
- package/dist/chunk-4W3X7OKF.js +100 -0
- package/dist/chunk-4W3X7OKF.js.map +1 -0
- package/dist/chunk-5JUIMXNF.js +108 -0
- package/dist/chunk-5JUIMXNF.js.map +1 -0
- package/dist/chunk-5RDMODGV.mjs +34 -0
- package/dist/chunk-5RDMODGV.mjs.map +1 -0
- package/dist/chunk-6ES4W2DL.mjs +1 -0
- package/dist/chunk-6ES4W2DL.mjs.map +1 -0
- package/dist/chunk-6EZ3QE5N.js +71 -0
- package/dist/chunk-6EZ3QE5N.js.map +1 -0
- package/dist/chunk-6JFERXNE.mjs +16 -0
- package/dist/chunk-6JFERXNE.mjs.map +1 -0
- package/dist/chunk-7SWW3ZIN.js +17 -0
- package/dist/chunk-7SWW3ZIN.js.map +1 -0
- package/dist/chunk-AXR56AUD.mjs +1 -0
- package/dist/chunk-AXR56AUD.mjs.map +1 -0
- package/dist/chunk-BE7JDL64.js +154 -0
- package/dist/chunk-BE7JDL64.js.map +1 -0
- package/dist/chunk-BHN2SRZC.js +51 -0
- package/dist/chunk-BHN2SRZC.js.map +1 -0
- package/dist/chunk-BJTO5JO5.mjs +11 -0
- package/dist/chunk-BJTO5JO5.mjs.map +1 -0
- package/dist/chunk-BWKKHCDG.mjs +164 -0
- package/dist/chunk-BWKKHCDG.mjs.map +1 -0
- package/dist/chunk-C5WFZJM4.js +218 -0
- package/dist/chunk-C5WFZJM4.js.map +1 -0
- package/dist/chunk-CGVFB23E.mjs +123 -0
- package/dist/chunk-CGVFB23E.mjs.map +1 -0
- package/dist/chunk-D2VDTRXO.js +1 -0
- package/dist/chunk-D2VDTRXO.js.map +1 -0
- package/dist/chunk-D75ADHVM.mjs +181 -0
- package/dist/chunk-D75ADHVM.mjs.map +1 -0
- package/dist/chunk-DCIF4XJL.js +309 -0
- package/dist/chunk-DCIF4XJL.js.map +1 -0
- package/dist/chunk-DGUM43GV.js +11 -0
- package/dist/chunk-DGUM43GV.js.map +1 -0
- package/dist/chunk-DSORCGJK.js +44 -0
- package/dist/chunk-DSORCGJK.js.map +1 -0
- package/dist/chunk-E5YUAOJI.js +27 -0
- package/dist/chunk-E5YUAOJI.js.map +1 -0
- package/dist/chunk-EG6NVPP2.js +164 -0
- package/dist/chunk-EG6NVPP2.js.map +1 -0
- package/dist/chunk-EL7YGOTY.js +1 -0
- package/dist/chunk-EL7YGOTY.js.map +1 -0
- package/dist/chunk-EM4MQEWV.mjs +100 -0
- package/dist/chunk-EM4MQEWV.mjs.map +1 -0
- package/dist/chunk-FCCCG5Z7.mjs +108 -0
- package/dist/chunk-FCCCG5Z7.mjs.map +1 -0
- package/dist/chunk-FEPGJ7WN.mjs +218 -0
- package/dist/chunk-FEPGJ7WN.mjs.map +1 -0
- package/dist/chunk-HXVWBFCN.js +16 -0
- package/dist/chunk-HXVWBFCN.js.map +1 -0
- package/dist/chunk-I5YMTJV6.mjs +51 -0
- package/dist/chunk-I5YMTJV6.mjs.map +1 -0
- package/dist/chunk-IMNWW7Q5.mjs +13 -0
- package/dist/chunk-IMNWW7Q5.mjs.map +1 -0
- package/dist/chunk-J5N76ASB.mjs +114 -0
- package/dist/chunk-J5N76ASB.mjs.map +1 -0
- package/dist/chunk-JBV26CUG.mjs +51 -0
- package/dist/chunk-JBV26CUG.mjs.map +1 -0
- package/dist/chunk-JMWXVXK5.js +53 -0
- package/dist/chunk-JMWXVXK5.js.map +1 -0
- package/dist/chunk-KWKV2GAH.js +60 -0
- package/dist/chunk-KWKV2GAH.js.map +1 -0
- package/dist/chunk-LDFE33ML.mjs +53 -0
- package/dist/chunk-LDFE33ML.mjs.map +1 -0
- package/dist/chunk-LF5LOI7K.mjs +174 -0
- package/dist/chunk-LF5LOI7K.mjs.map +1 -0
- package/dist/chunk-MMKAMH4U.mjs +16 -0
- package/dist/chunk-MMKAMH4U.mjs.map +1 -0
- package/dist/chunk-MUHFEEYW.js +33 -0
- package/dist/chunk-MUHFEEYW.js.map +1 -0
- package/dist/chunk-MUQYK5EO.js +1 -0
- package/dist/chunk-MUQYK5EO.js.map +1 -0
- package/dist/chunk-OBNALAMG.mjs +71 -0
- package/dist/chunk-OBNALAMG.mjs.map +1 -0
- package/dist/chunk-OLEYNPW6.js +25 -0
- package/dist/chunk-OLEYNPW6.js.map +1 -0
- package/dist/chunk-OYJRR3G2.js +123 -0
- package/dist/chunk-OYJRR3G2.js.map +1 -0
- package/dist/chunk-PLVG7AW3.js +16 -0
- package/dist/chunk-PLVG7AW3.js.map +1 -0
- package/dist/chunk-PYD4CES4.js +1 -0
- package/dist/chunk-PYD4CES4.js.map +1 -0
- package/dist/chunk-QACD2U6P.mjs +1 -0
- package/dist/chunk-QACD2U6P.mjs.map +1 -0
- package/dist/chunk-R5GGIVD4.js +10 -0
- package/dist/chunk-R5GGIVD4.js.map +1 -0
- package/dist/chunk-RCK5WCU5.mjs +25 -0
- package/dist/chunk-RCK5WCU5.mjs.map +1 -0
- package/dist/chunk-S6UUSM7S.js +13 -0
- package/dist/chunk-S6UUSM7S.js.map +1 -0
- package/dist/chunk-S7GOXCRM.js +114 -0
- package/dist/chunk-S7GOXCRM.js.map +1 -0
- package/dist/chunk-SMV5D5LO.mjs +28 -0
- package/dist/chunk-SMV5D5LO.mjs.map +1 -0
- package/dist/chunk-T7EVFD4G.mjs +60 -0
- package/dist/chunk-T7EVFD4G.mjs.map +1 -0
- package/dist/chunk-TLH3V4SY.mjs +1 -0
- package/dist/chunk-TLH3V4SY.mjs.map +1 -0
- package/dist/chunk-TUQ2CVAK.mjs +10 -0
- package/dist/chunk-TUQ2CVAK.mjs.map +1 -0
- package/dist/chunk-U6PVJKTB.js +51 -0
- package/dist/chunk-U6PVJKTB.js.map +1 -0
- package/dist/chunk-UXMMEEX4.mjs +27 -0
- package/dist/chunk-UXMMEEX4.mjs.map +1 -0
- package/dist/chunk-VVXNFFKI.mjs +44 -0
- package/dist/chunk-VVXNFFKI.mjs.map +1 -0
- package/dist/chunk-VZZ3RU3Q.js +28 -0
- package/dist/chunk-VZZ3RU3Q.js.map +1 -0
- package/dist/chunk-W4FWIZ2Y.js +34 -0
- package/dist/chunk-W4FWIZ2Y.js.map +1 -0
- package/dist/chunk-YEQFKOWD.mjs +154 -0
- package/dist/chunk-YEQFKOWD.mjs.map +1 -0
- package/dist/chunk-YPBKY4KY.mjs +1 -0
- package/dist/chunk-YPBKY4KY.mjs.map +1 -0
- package/dist/chunk-YY7K5CXX.js +174 -0
- package/dist/chunk-YY7K5CXX.js.map +1 -0
- package/dist/chunk-ZFORODOX.js +181 -0
- package/dist/chunk-ZFORODOX.js.map +1 -0
- package/dist/chunk-ZULSFSDG.mjs +309 -0
- package/dist/chunk-ZULSFSDG.mjs.map +1 -0
- package/dist/components/AdminManagerBase.d.mts +26 -0
- package/dist/components/AdminManagerBase.d.ts +26 -0
- package/dist/components/AdminManagerBase.js +13 -0
- package/dist/components/AdminManagerBase.js.map +1 -0
- package/dist/components/AdminManagerBase.mjs +12 -0
- package/dist/components/AdminManagerBase.mjs.map +1 -0
- package/dist/components/AdminManagerConfig.d.mts +83 -0
- package/dist/components/AdminManagerConfig.d.ts +83 -0
- package/dist/components/AdminManagerConfig.js +2 -0
- package/dist/components/AdminManagerConfig.js.map +1 -0
- package/dist/components/AdminManagerConfig.mjs +2 -0
- package/dist/components/AdminManagerConfig.mjs.map +1 -0
- package/dist/components/AdminShell.d.mts +30 -0
- package/dist/components/AdminShell.d.ts +30 -0
- package/dist/components/AdminShell.js +12 -0
- package/dist/components/AdminShell.js.map +1 -0
- package/dist/components/AdminShell.mjs +11 -0
- package/dist/components/AdminShell.mjs.map +1 -0
- package/dist/components/JsonLd.d.mts +32 -0
- package/dist/components/JsonLd.d.ts +32 -0
- package/dist/components/JsonLd.js +11 -0
- package/dist/components/JsonLd.js.map +1 -0
- package/dist/components/JsonLd.mjs +11 -0
- package/dist/components/JsonLd.mjs.map +1 -0
- package/dist/components/ResizableImage.d.mts +18 -0
- package/dist/components/ResizableImage.d.ts +18 -0
- package/dist/components/ResizableImage.js +10 -0
- package/dist/components/ResizableImage.js.map +1 -0
- package/dist/components/ResizableImage.mjs +9 -0
- package/dist/components/ResizableImage.mjs.map +1 -0
- package/dist/components/ToggleSwitch.d.mts +11 -0
- package/dist/components/ToggleSwitch.d.ts +11 -0
- package/dist/components/ToggleSwitch.js +10 -0
- package/dist/components/ToggleSwitch.js.map +1 -0
- package/dist/components/ToggleSwitch.mjs +9 -0
- package/dist/components/ToggleSwitch.mjs.map +1 -0
- package/dist/components/image-drop-zone.css +115 -0
- package/dist/components/index.d.mts +26 -0
- package/dist/components/index.d.ts +26 -0
- package/dist/components/index.js +35 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/index.mjs +35 -0
- package/dist/components/index.mjs.map +1 -0
- package/dist/components/toggle-switch.css +55 -0
- package/dist/hooks/index.d.mts +45 -0
- package/dist/hooks/index.d.ts +45 -0
- package/dist/hooks/index.js +25 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/index.mjs +25 -0
- package/dist/hooks/index.mjs.map +1 -0
- package/dist/hooks/useImageDropZone.d.mts +37 -0
- package/dist/hooks/useImageDropZone.d.ts +37 -0
- package/dist/hooks/useImageDropZone.js +13 -0
- package/dist/hooks/useImageDropZone.js.map +1 -0
- package/dist/hooks/useImageDropZone.mjs +12 -0
- package/dist/hooks/useImageDropZone.mjs.map +1 -0
- package/dist/hooks/useScrollReveal.d.mts +6 -0
- package/dist/hooks/useScrollReveal.d.ts +6 -0
- package/dist/hooks/useScrollReveal.js +12 -0
- package/dist/hooks/useScrollReveal.js.map +1 -0
- package/dist/hooks/useScrollReveal.mjs +11 -0
- package/dist/hooks/useScrollReveal.mjs.map +1 -0
- package/dist/image-drop-zone.css +115 -0
- package/dist/index-00a40-FQ.d.mts +136 -0
- package/dist/index-00a40-FQ.d.ts +136 -0
- package/dist/index.d.mts +35 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.js +169 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +169 -0
- package/dist/index.mjs.map +1 -0
- package/dist/infrastructure/index.d.mts +4 -0
- package/dist/infrastructure/index.d.ts +4 -0
- package/dist/infrastructure/index.js +20 -0
- package/dist/infrastructure/index.js.map +1 -0
- package/dist/infrastructure/index.mjs +20 -0
- package/dist/infrastructure/index.mjs.map +1 -0
- package/dist/infrastructure/middleware/index.d.mts +3 -0
- package/dist/infrastructure/middleware/index.d.ts +3 -0
- package/dist/infrastructure/middleware/index.js +15 -0
- package/dist/infrastructure/middleware/index.js.map +1 -0
- package/dist/infrastructure/middleware/index.mjs +15 -0
- package/dist/infrastructure/middleware/index.mjs.map +1 -0
- package/dist/infrastructure/middleware/wrappers.d.mts +10 -0
- package/dist/infrastructure/middleware/wrappers.d.ts +10 -0
- package/dist/infrastructure/middleware/wrappers.js +15 -0
- package/dist/infrastructure/middleware/wrappers.js.map +1 -0
- package/dist/infrastructure/middleware/wrappers.mjs +15 -0
- package/dist/infrastructure/middleware/wrappers.mjs.map +1 -0
- package/dist/infrastructure/prisma.d.mts +5 -0
- package/dist/infrastructure/prisma.d.ts +5 -0
- package/dist/infrastructure/prisma.js +12 -0
- package/dist/infrastructure/prisma.js.map +1 -0
- package/dist/infrastructure/prisma.mjs +12 -0
- package/dist/infrastructure/prisma.mjs.map +1 -0
- package/dist/services/index.d.mts +22 -0
- package/dist/services/index.d.ts +22 -0
- package/dist/services/index.js +36 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/index.mjs +36 -0
- package/dist/services/index.mjs.map +1 -0
- package/dist/toggle-switch.css +55 -0
- package/dist/types/common.d.mts +14 -0
- package/dist/types/common.d.ts +14 -0
- package/dist/types/common.js +8 -0
- package/dist/types/common.js.map +1 -0
- package/dist/types/common.mjs +8 -0
- package/dist/types/common.mjs.map +1 -0
- package/dist/types/index.d.mts +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +9 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/index.mjs +9 -0
- package/dist/types/index.mjs.map +1 -0
- package/dist/utils/admin-fetch.d.mts +11 -0
- package/dist/utils/admin-fetch.d.ts +11 -0
- package/dist/utils/admin-fetch.js +13 -0
- package/dist/utils/admin-fetch.js.map +1 -0
- package/dist/utils/admin-fetch.mjs +13 -0
- package/dist/utils/admin-fetch.mjs.map +1 -0
- package/dist/utils/api-helpers.d.mts +20 -0
- package/dist/utils/api-helpers.d.ts +20 -0
- package/dist/utils/api-helpers.js +12 -0
- package/dist/utils/api-helpers.js.map +1 -0
- package/dist/utils/api-helpers.mjs +12 -0
- package/dist/utils/api-helpers.mjs.map +1 -0
- package/dist/utils/date.d.mts +5 -0
- package/dist/utils/date.d.ts +5 -0
- package/dist/utils/date.js +12 -0
- package/dist/utils/date.js.map +1 -0
- package/dist/utils/date.mjs +12 -0
- package/dist/utils/date.mjs.map +1 -0
- package/dist/utils/html-sanitizer.d.mts +56 -0
- package/dist/utils/html-sanitizer.d.ts +56 -0
- package/dist/utils/html-sanitizer.js +11 -0
- package/dist/utils/html-sanitizer.js.map +1 -0
- package/dist/utils/html-sanitizer.mjs +11 -0
- package/dist/utils/html-sanitizer.mjs.map +1 -0
- package/dist/utils/image-variant-utils.d.mts +14 -0
- package/dist/utils/image-variant-utils.d.ts +14 -0
- package/dist/utils/image-variant-utils.js +10 -0
- package/dist/utils/image-variant-utils.js.map +1 -0
- package/dist/utils/image-variant-utils.mjs +10 -0
- package/dist/utils/image-variant-utils.mjs.map +1 -0
- package/dist/utils/image-variants.d.mts +13 -0
- package/dist/utils/image-variants.d.ts +13 -0
- package/dist/utils/image-variants.js +12 -0
- package/dist/utils/image-variants.js.map +1 -0
- package/dist/utils/image-variants.mjs +12 -0
- package/dist/utils/image-variants.mjs.map +1 -0
- package/dist/utils/index.d.mts +88 -0
- package/dist/utils/index.d.ts +88 -0
- package/dist/utils/index.js +92 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/index.mjs +92 -0
- package/dist/utils/index.mjs.map +1 -0
- package/dist/utils/jwt.d.mts +19 -0
- package/dist/utils/jwt.d.ts +19 -0
- package/dist/utils/jwt.js +9 -0
- package/dist/utils/jwt.js.map +1 -0
- package/dist/utils/jwt.mjs +9 -0
- package/dist/utils/jwt.mjs.map +1 -0
- package/dist/utils/r2-helpers.d.mts +9 -0
- package/dist/utils/r2-helpers.d.ts +9 -0
- package/dist/utils/r2-helpers.js +20 -0
- package/dist/utils/r2-helpers.js.map +1 -0
- package/dist/utils/r2-helpers.mjs +20 -0
- package/dist/utils/r2-helpers.mjs.map +1 -0
- package/dist/utils/r2-storage.d.mts +38 -0
- package/dist/utils/r2-storage.d.ts +38 -0
- package/dist/utils/r2-storage.js +17 -0
- package/dist/utils/r2-storage.js.map +1 -0
- package/dist/utils/r2-storage.mjs +17 -0
- package/dist/utils/r2-storage.mjs.map +1 -0
- package/dist/utils/route-params.d.mts +3 -0
- package/dist/utils/route-params.d.ts +3 -0
- package/dist/utils/route-params.js +8 -0
- package/dist/utils/route-params.js.map +1 -0
- package/dist/utils/route-params.mjs +8 -0
- package/dist/utils/route-params.mjs.map +1 -0
- package/dist/validators/index.d.mts +2 -0
- package/dist/validators/index.d.ts +2 -0
- package/dist/validators/index.js +11 -0
- package/dist/validators/index.js.map +1 -0
- package/dist/validators/index.mjs +11 -0
- package/dist/validators/index.mjs.map +1 -0
- package/dist/validators/shared.d.mts +6 -0
- package/dist/validators/shared.d.ts +6 -0
- package/dist/validators/shared.js +10 -0
- package/dist/validators/shared.js.map +1 -0
- package/dist/validators/shared.mjs +10 -0
- package/dist/validators/shared.mjs.map +1 -0
- package/package.json +257 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
|
|
2
|
+
|
|
3
|
+
var _chunkKWKV2GAHjs = require('./chunk-KWKV2GAH.js');
|
|
4
|
+
|
|
5
|
+
// src/hooks/useAdminList.ts
|
|
6
|
+
var _react = require('react');
|
|
7
|
+
function useAdminList(options) {
|
|
8
|
+
const { initialItems, apiPath, defaultSortKey, normalizeItem, defaultFilterValue } = options;
|
|
9
|
+
const [items, setItems] = _react.useState.call(void 0, initialItems);
|
|
10
|
+
const [searchQuery, setSearchQuery] = _react.useState.call(void 0, "");
|
|
11
|
+
const [sortKey, setSortKey] = _react.useState.call(void 0, defaultSortKey);
|
|
12
|
+
const [filterValue, setFilterValue] = _react.useState.call(void 0, _nullishCoalesce(defaultFilterValue, () => ( "all")));
|
|
13
|
+
const fetchList = _react.useCallback.call(void 0,
|
|
14
|
+
async (sort) => {
|
|
15
|
+
try {
|
|
16
|
+
const res = await _chunkKWKV2GAHjs.adminFetch.call(void 0, `${apiPath}?limit=100&sortBy=${sort}`);
|
|
17
|
+
if (res.ok) {
|
|
18
|
+
const json = await res.json();
|
|
19
|
+
if (json.success) {
|
|
20
|
+
setItems(normalizeItem ? json.data.items.map(normalizeItem) : json.data.items);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
} catch (e) {
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
[apiPath]
|
|
27
|
+
);
|
|
28
|
+
const isInitialMount = _react.useRef.call(void 0, true);
|
|
29
|
+
_react.useEffect.call(void 0, () => {
|
|
30
|
+
if (isInitialMount.current) {
|
|
31
|
+
isInitialMount.current = false;
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
fetchList(sortKey);
|
|
35
|
+
}, [sortKey, fetchList]);
|
|
36
|
+
return {
|
|
37
|
+
items,
|
|
38
|
+
setItems,
|
|
39
|
+
searchQuery,
|
|
40
|
+
setSearchQuery,
|
|
41
|
+
sortKey,
|
|
42
|
+
setSortKey,
|
|
43
|
+
filterValue,
|
|
44
|
+
setFilterValue,
|
|
45
|
+
fetchList
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// src/hooks/useAdminForm.ts
|
|
50
|
+
|
|
51
|
+
function useAdminForm(initialForm) {
|
|
52
|
+
const [tab, setTab] = _react.useState.call(void 0, "list");
|
|
53
|
+
const [form, setForm] = _react.useState.call(void 0, initialForm);
|
|
54
|
+
const [selectedId, setSelectedId] = _react.useState.call(void 0, null);
|
|
55
|
+
const [isNew, setIsNew] = _react.useState.call(void 0, false);
|
|
56
|
+
const [saving, setSaving] = _react.useState.call(void 0, false);
|
|
57
|
+
const [loading, setLoading] = _react.useState.call(void 0, false);
|
|
58
|
+
const [mobilePv, setMobilePv] = _react.useState.call(void 0, false);
|
|
59
|
+
const updateField = _react.useCallback.call(void 0, (key, value) => {
|
|
60
|
+
setForm((prev) => prev[key] === value ? prev : { ...prev, [key]: value });
|
|
61
|
+
}, []);
|
|
62
|
+
const addNew = _react.useCallback.call(void 0,
|
|
63
|
+
(emptyForm) => {
|
|
64
|
+
setSelectedId(null);
|
|
65
|
+
setIsNew(true);
|
|
66
|
+
setForm(emptyForm);
|
|
67
|
+
setTab("edit");
|
|
68
|
+
},
|
|
69
|
+
[]
|
|
70
|
+
);
|
|
71
|
+
const startEdit = _react.useCallback.call(void 0, (id, emptyForm) => {
|
|
72
|
+
setSelectedId(id);
|
|
73
|
+
if (emptyForm) setForm(emptyForm);
|
|
74
|
+
setIsNew(false);
|
|
75
|
+
setLoading(true);
|
|
76
|
+
setTab("edit");
|
|
77
|
+
}, []);
|
|
78
|
+
const backToList = _react.useCallback.call(void 0, () => {
|
|
79
|
+
setTab("list");
|
|
80
|
+
setSelectedId(null);
|
|
81
|
+
}, []);
|
|
82
|
+
return {
|
|
83
|
+
tab,
|
|
84
|
+
setTab,
|
|
85
|
+
form,
|
|
86
|
+
setForm,
|
|
87
|
+
updateField,
|
|
88
|
+
selectedId,
|
|
89
|
+
setSelectedId,
|
|
90
|
+
isNew,
|
|
91
|
+
setIsNew,
|
|
92
|
+
saving,
|
|
93
|
+
setSaving,
|
|
94
|
+
loading,
|
|
95
|
+
setLoading,
|
|
96
|
+
mobilePv,
|
|
97
|
+
setMobilePv,
|
|
98
|
+
addNew,
|
|
99
|
+
startEdit,
|
|
100
|
+
backToList
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
exports.useAdminList = useAdminList; exports.useAdminForm = useAdminForm;
|
|
108
|
+
//# sourceMappingURL=chunk-5JUIMXNF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-cms-kit/dist/chunk-5JUIMXNF.js","../src/hooks/useAdminList.ts","../src/hooks/useAdminForm.ts"],"names":["useState","useCallback"],"mappings":"AAAA;AACE;AACF,sDAA4B;AAC5B;AACA;ACFA,8BAAyD;AAWlD,SAAS,YAAA,CACd,OAAA,EACA;AACA,EAAA,MAAM,EAAE,YAAA,EAAc,OAAA,EAAS,cAAA,EAAgB,aAAA,EAAe,mBAAmB,EAAA,EAAI,OAAA;AAErF,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,EAAA,EAAI,6BAAA,YAA0B,CAAA;AACpD,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,EAAA,EAAI,6BAAA,EAAW,CAAA;AACjD,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,EAAA,EAAI,6BAAA,cAA0B,CAAA;AACxD,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,EAAA,EAAI,6BAAA,iBAAS,kBAAA,UAAsB,OAAK,CAAA;AAE1E,EAAA,MAAM,UAAA,EAAY,gCAAA;AAAA,IAChB,MAAA,CAAO,IAAA,EAAA,GAAY;AACjB,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,EAAM,MAAM,yCAAA,CAAW,EAAA;AACjB,QAAA;AACkB,UAAA;AACV,UAAA;AACS,YAAA;AAC3B,UAAA;AACF,QAAA;AACM,MAAA;AAAC,MAAA;AACX,IAAA;AACQ,IAAA;AACV,EAAA;AAEkC,EAAA;AAClB,EAAA;AACc,IAAA;AACD,MAAA;AACzB,MAAA;AACF,IAAA;AACiB,IAAA;AACI,EAAA;AAEhB,EAAA;AACL,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACF,EAAA;AACF;ADXsC;AACA;AE9CnB;AAE4C;AACb,EAAA;AACZ,EAAA;AACAA,EAAAA;AACD,EAAA;AACPA,EAAAA;AACEA,EAAAA;AACEA,EAAAA;AAEoB,EAAA;AACjB,IAAA;AAC9B,EAAA;AAEUC,EAAAA;AACK,IAAA;AACE,MAAA;AACL,MAAA;AACI,MAAA;AACJ,MAAA;AACf,IAAA;AACC,IAAA;AACH,EAAA;AAE2C,EAAA;AACzB,IAAA;AACgB,IAAA;AAClB,IAAA;AACC,IAAA;AACF,IAAA;AACV,EAAA;AAE0B,EAAA;AAChB,IAAA;AACK,IAAA;AACf,EAAA;AAEE,EAAA;AACL,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACF,EAAA;AACF;AF0CsC;AACA;AACA;AACA;AACA","file":"/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-cms-kit/dist/chunk-5JUIMXNF.js","sourcesContent":[null,"'use client';\n\nimport { useState, useCallback, useRef, useEffect } from 'react';\nimport { adminFetch } from '../utils/admin-fetch';\n\ninterface UseAdminListOptions<T, S extends string> {\n initialItems: T[];\n apiPath: string;\n defaultSortKey: S;\n normalizeItem?: (raw: unknown) => T;\n defaultFilterValue?: string;\n}\n\nexport function useAdminList<T, S extends string = string>(\n options: UseAdminListOptions<T, S>,\n) {\n const { initialItems, apiPath, defaultSortKey, normalizeItem, defaultFilterValue } = options;\n\n const [items, setItems] = useState<T[]>(initialItems);\n const [searchQuery, setSearchQuery] = useState('');\n const [sortKey, setSortKey] = useState<S>(defaultSortKey);\n const [filterValue, setFilterValue] = useState(defaultFilterValue ?? 'all');\n\n const fetchList = useCallback(\n async (sort: S) => {\n try {\n const res = await adminFetch(`${apiPath}?limit=100&sortBy=${sort}`);\n if (res.ok) {\n const json = await res.json();\n if (json.success) {\n setItems(normalizeItem ? json.data.items.map(normalizeItem) : json.data.items);\n }\n }\n } catch {}\n },\n [apiPath],\n );\n\n const isInitialMount = useRef(true);\n useEffect(() => {\n if (isInitialMount.current) {\n isInitialMount.current = false;\n return;\n }\n fetchList(sortKey);\n }, [sortKey, fetchList]);\n\n return {\n items,\n setItems,\n searchQuery,\n setSearchQuery,\n sortKey,\n setSortKey,\n filterValue,\n setFilterValue,\n fetchList,\n };\n}\n","'use client';\n\nimport { useState, useCallback } from 'react';\n\nexport function useAdminForm<F extends object>(initialForm: F) {\n const [tab, setTab] = useState<'list' | 'edit'>('list');\n const [form, setForm] = useState<F>(initialForm);\n const [selectedId, setSelectedId] = useState<string | null>(null);\n const [isNew, setIsNew] = useState(false);\n const [saving, setSaving] = useState(false);\n const [loading, setLoading] = useState(false);\n const [mobilePv, setMobilePv] = useState(false);\n\n const updateField = useCallback(<K extends keyof F>(key: K, value: F[K]) => {\n setForm((prev) => (prev[key] === value ? prev : { ...prev, [key]: value }));\n }, []);\n\n const addNew = useCallback(\n (emptyForm: F) => {\n setSelectedId(null);\n setIsNew(true);\n setForm(emptyForm);\n setTab('edit');\n },\n [],\n );\n\n const startEdit = useCallback((id: string, emptyForm?: F) => {\n setSelectedId(id);\n if (emptyForm) setForm(emptyForm);\n setIsNew(false);\n setLoading(true);\n setTab('edit');\n }, []);\n\n const backToList = useCallback(() => {\n setTab('list');\n setSelectedId(null);\n }, []);\n\n return {\n tab,\n setTab,\n form,\n setForm,\n updateField,\n selectedId,\n setSelectedId,\n isNew,\n setIsNew,\n saving,\n setSaving,\n loading,\n setLoading,\n mobilePv,\n setMobilePv,\n addNew,\n startEdit,\n backToList,\n };\n}\n"]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {
|
|
2
|
+
resolveJwtConfig
|
|
3
|
+
} from "./chunk-BWKKHCDG.mjs";
|
|
4
|
+
|
|
5
|
+
// src/utils/jwt.ts
|
|
6
|
+
import { JWTManager } from "@withwiz/toolkit/core/auth/jwt";
|
|
7
|
+
import { logInfo, logError } from "@withwiz/toolkit/core/logger/logger";
|
|
8
|
+
var _jwtManager = null;
|
|
9
|
+
function getJWTManager() {
|
|
10
|
+
if (!_jwtManager) {
|
|
11
|
+
const { secret, accessTokenExpiry, refreshTokenExpiry, algorithm } = resolveJwtConfig();
|
|
12
|
+
_jwtManager = new JWTManager(
|
|
13
|
+
{
|
|
14
|
+
secret,
|
|
15
|
+
accessTokenExpiry,
|
|
16
|
+
refreshTokenExpiry,
|
|
17
|
+
algorithm
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
debug: () => {
|
|
21
|
+
},
|
|
22
|
+
info: (msg, meta) => logInfo(`[JWT] ${msg}`, meta),
|
|
23
|
+
warn: (msg, meta) => logInfo(`[JWT] ${msg}`, meta),
|
|
24
|
+
error: (msg, meta) => logError(`[JWT] ${msg}`, meta)
|
|
25
|
+
}
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
return _jwtManager;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export {
|
|
32
|
+
getJWTManager
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=chunk-5RDMODGV.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/jwt.ts"],"sourcesContent":["import { JWTManager } from '@withwiz/toolkit/core/auth/jwt';\nimport { logInfo, logError } from '@withwiz/toolkit/core/logger/logger';\nimport { resolveJwtConfig } from '../config';\n\nlet _jwtManager: JWTManager | null = null;\n\n/**\n * JWT 매니저 싱글턴 (spec.md §4.6 / §4.3 / Sprint 1 S3).\n *\n * secret/expiry/algorithm 은 §5 config boundary (`resolveJwtConfig`) 를 통해\n * 해석된다: 명시적 주입 > `process.env.JWT_SECRET` 레거시 fallback > (서명\n * 비밀에는 안전한 기본값이 없음 → point-of-use fail-fast).\n *\n * - 비밀 누락: `@withwiz/cms-kit:` 네임스페이스 에러로 즉시 throw (undefined 로\n * 조용히 JWTManager 를 만들지 않는다).\n * - 비밀 취약(<32자, 문서화 정책): `@withwiz/cms-kit:` 네임스페이스 에러로 거부\n * (forgeable 서명 키는 unsafe-no-safe-default).\n * - import 만으로는 절대 throw 하지 않는다 (lazy / point-of-use).\n * 기존의 JWT_SECRET non-null 단정(bang) 직접 접근은 제거되었다.\n */\nexport function getJWTManager(): JWTManager {\n if (!_jwtManager) {\n const { secret, accessTokenExpiry, refreshTokenExpiry, algorithm } =\n resolveJwtConfig();\n _jwtManager = new JWTManager(\n {\n secret,\n accessTokenExpiry,\n refreshTokenExpiry,\n algorithm,\n },\n {\n debug: () => {},\n info: (msg: string, meta?: any) => logInfo(`[JWT] ${msg}`, meta),\n warn: (msg: string, meta?: any) => logInfo(`[JWT] ${msg}`, meta),\n error: (msg: string, meta?: any) => logError(`[JWT] ${msg}`, meta),\n },\n );\n }\n return _jwtManager;\n}\n"],"mappings":";;;;;AAAA,SAAS,kBAAkB;AAC3B,SAAS,SAAS,gBAAgB;AAGlC,IAAI,cAAiC;AAgB9B,SAAS,gBAA4B;AAC1C,MAAI,CAAC,aAAa;AAChB,UAAM,EAAE,QAAQ,mBAAmB,oBAAoB,UAAU,IAC/D,iBAAiB;AACnB,kBAAc,IAAI;AAAA,MAChB;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA;AAAA,QACE,OAAO,MAAM;AAAA,QAAC;AAAA,QACd,MAAM,CAAC,KAAa,SAAe,QAAQ,SAAS,GAAG,IAAI,IAAI;AAAA,QAC/D,MAAM,CAAC,KAAa,SAAe,QAAQ,SAAS,GAAG,IAAI,IAAI;AAAA,QAC/D,OAAO,CAAC,KAAa,SAAe,SAAS,SAAS,GAAG,IAAI,IAAI;AAAA,MACnE;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=chunk-6ES4W2DL.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
|
+
|
|
3
|
+
var _chunkYY7K5CXXjs = require('./chunk-YY7K5CXX.js');
|
|
4
|
+
|
|
5
|
+
// src/components/ImageDropUpload.tsx
|
|
6
|
+
var _react = require('react');
|
|
7
|
+
require('./image-drop-zone.css');
|
|
8
|
+
var _jsxruntime = require('react/jsx-runtime');
|
|
9
|
+
function ImageDropUpload({
|
|
10
|
+
src,
|
|
11
|
+
onUpload,
|
|
12
|
+
onKeyTracked,
|
|
13
|
+
className = "",
|
|
14
|
+
placeholder = "\uD074\uB9AD \uB610\uB294 \uB4DC\uB798\uADF8\uD558\uC5EC \uC774\uBBF8\uC9C0 \uCD94\uAC00"
|
|
15
|
+
}) {
|
|
16
|
+
const inputRef = _react.useRef.call(void 0, null);
|
|
17
|
+
const drop = _chunkYY7K5CXXjs.useImageDropZone.call(void 0, {
|
|
18
|
+
onUpload: (result) => onUpload(result.url, result.key),
|
|
19
|
+
onKeyTracked
|
|
20
|
+
});
|
|
21
|
+
const cls = [
|
|
22
|
+
className,
|
|
23
|
+
src ? "has" : "",
|
|
24
|
+
drop.isDragOver ? "is-drag-over" : "",
|
|
25
|
+
drop.isUploading ? "is-uploading" : "",
|
|
26
|
+
drop.isResizing ? "is-resizing" : ""
|
|
27
|
+
].filter(Boolean).join(" ");
|
|
28
|
+
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
|
|
29
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
30
|
+
"input",
|
|
31
|
+
{
|
|
32
|
+
ref: inputRef,
|
|
33
|
+
type: "file",
|
|
34
|
+
accept: "image/*",
|
|
35
|
+
style: { display: "none" },
|
|
36
|
+
onChange: async (e) => {
|
|
37
|
+
await drop.handleFileInput(e.target.files);
|
|
38
|
+
e.target.value = "";
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
),
|
|
42
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
43
|
+
"div",
|
|
44
|
+
{
|
|
45
|
+
className: cls,
|
|
46
|
+
onClick: () => !drop.isUploading && !drop.isResizing && _optionalChain([inputRef, 'access', _ => _.current, 'optionalAccess', _2 => _2.click, 'call', _3 => _3()]),
|
|
47
|
+
...drop.dragHandlers,
|
|
48
|
+
children: drop.isResizing ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "dz-upload-spinner", children: "\uCD5C\uC801\uD654 \uC911..." }) : drop.isUploading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "dz-upload-spinner", children: "\uC5C5\uB85C\uB4DC \uC911..." }) : drop.isDragOver ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "dz-drag-hint", children: "\uB193\uC73C\uC138\uC694" }) : src ? (
|
|
49
|
+
/* eslint-disable-next-line @next/next/no-img-element */
|
|
50
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src, alt: "", style: { maxWidth: "100%", height: "auto" } })
|
|
51
|
+
) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "dz-placeholder", children: [
|
|
52
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "dz-placeholder-icon", children: "+" }),
|
|
53
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "dz-placeholder-text", children: placeholder }),
|
|
54
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "dz-placeholder-guide", children: [
|
|
55
|
+
"JPG, PNG, WebP, GIF | \uCD5C\uB300 5MB",
|
|
56
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "br", {}),
|
|
57
|
+
"\uCD08\uACFC \uC2DC \uC790\uB3D9 \uC555\uCD95 \xB7 1920px \uC774\uD558\uB85C \uB9AC\uC0AC\uC774\uC988",
|
|
58
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "br", {}),
|
|
59
|
+
"WebP \uBCC0\uD658 \xB7 4\uAC1C \uC0AC\uC774\uC988(lg/md/sm/thumb) \uC790\uB3D9 \uC0DD\uC131"
|
|
60
|
+
] })
|
|
61
|
+
] })
|
|
62
|
+
}
|
|
63
|
+
),
|
|
64
|
+
drop.error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "dz-error", children: drop.error })
|
|
65
|
+
] });
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
exports.ImageDropUpload = ImageDropUpload;
|
|
71
|
+
//# sourceMappingURL=chunk-6EZ3QE5N.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-cms-kit/dist/chunk-6EZ3QE5N.js","../src/components/ImageDropUpload.tsx"],"names":[],"mappings":"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","file":"/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-cms-kit/dist/chunk-6EZ3QE5N.js","sourcesContent":[null,"\"use client\";\n\nimport { useRef } from \"react\";\nimport { useImageDropZone } from \"../hooks/useImageDropZone\";\nimport \"./image-drop-zone.css\";\n\ninterface Props {\n /** Current image URL */\n src: string;\n /** Called with uploaded image URL and key */\n onUpload: (url: string, key: string) => void;\n /** Track uploaded key for orphan cleanup */\n onKeyTracked?: (key: string) => void;\n /** CSS class for the drop zone container */\n className?: string;\n /** Placeholder text when no image */\n placeholder?: string;\n}\n\nexport default function ImageDropUpload({\n src,\n onUpload,\n onKeyTracked,\n className = \"\",\n placeholder = \"클릭 또는 드래그하여 이미지 추가\",\n}: Props) {\n const inputRef = useRef<HTMLInputElement>(null);\n const drop = useImageDropZone({\n onUpload: (result) => onUpload(result.url, result.key),\n onKeyTracked,\n });\n\n const cls = [\n className,\n src ? \"has\" : \"\",\n drop.isDragOver ? \"is-drag-over\" : \"\",\n drop.isUploading ? \"is-uploading\" : \"\",\n drop.isResizing ? \"is-resizing\" : \"\",\n ].filter(Boolean).join(\" \");\n\n return (\n <>\n <input\n ref={inputRef}\n type=\"file\"\n accept=\"image/*\"\n style={{ display: \"none\" }}\n onChange={async (e) => {\n await drop.handleFileInput(e.target.files);\n e.target.value = \"\";\n }}\n />\n <div\n className={cls}\n onClick={() => !drop.isUploading && !drop.isResizing && inputRef.current?.click()}\n {...drop.dragHandlers}\n >\n {drop.isResizing ? (\n <span className=\"dz-upload-spinner\">최적화 중...</span>\n ) : drop.isUploading ? (\n <span className=\"dz-upload-spinner\">업로드 중...</span>\n ) : drop.isDragOver ? (\n <span className=\"dz-drag-hint\">놓으세요</span>\n ) : src ? (\n /* eslint-disable-next-line @next/next/no-img-element */\n <img src={src} alt=\"\" style={{ maxWidth: \"100%\", height: \"auto\" }} />\n ) : (\n <div className=\"dz-placeholder\">\n <div className=\"dz-placeholder-icon\">+</div>\n <div className=\"dz-placeholder-text\">{placeholder}</div>\n <div className=\"dz-placeholder-guide\">\n JPG, PNG, WebP, GIF | 최대 5MB\n <br />\n 초과 시 자동 압축 · 1920px 이하로 리사이즈\n <br />\n WebP 변환 · 4개 사이즈(lg/md/sm/thumb) 자동 생성\n </div>\n </div>\n )}\n </div>\n {drop.error && <div className=\"dz-error\">{drop.error}</div>}\n </>\n );\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// src/services/base-service.ts
|
|
2
|
+
var DEFAULT_PAGE = 1;
|
|
3
|
+
var DEFAULT_LIMIT = 20;
|
|
4
|
+
function parseSortParam(sortBy, allowed, defaultField) {
|
|
5
|
+
const [field, order] = sortBy.split("_");
|
|
6
|
+
const safeField = allowed.includes(field) ? field : defaultField;
|
|
7
|
+
const safeOrder = order === "asc" ? "asc" : "desc";
|
|
8
|
+
return { field: safeField, order: safeOrder };
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export {
|
|
12
|
+
DEFAULT_PAGE,
|
|
13
|
+
DEFAULT_LIMIT,
|
|
14
|
+
parseSortParam
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=chunk-6JFERXNE.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/services/base-service.ts"],"sourcesContent":["import { prisma } from '../infrastructure/prisma';\nimport { buildPaginatedResult, type PaginatedResult } from '../types/common';\nimport { sanitizeHtmlContent } from '../utils/html-sanitizer';\nimport { isR2Enabled } from '../utils/r2-storage';\nimport { collectR2Keys, deleteR2Keys } from '../utils/r2-helpers';\nimport type { SortOrder } from '../types/common';\n\nexport { prisma, buildPaginatedResult, sanitizeHtmlContent, isR2Enabled, collectR2Keys, deleteR2Keys };\nexport type { PaginatedResult, SortOrder };\n\nexport interface ListParams {\n page?: number;\n limit?: number;\n sortBy?: string;\n sortOrder?: SortOrder;\n}\n\nexport const DEFAULT_PAGE = 1;\nexport const DEFAULT_LIMIT = 20;\n\nexport function parseSortParam(\n sortBy: string,\n allowed: string[],\n defaultField: string,\n): { field: string; order: SortOrder } {\n const [field, order] = sortBy.split('_');\n const safeField = allowed.includes(field) ? field : defaultField;\n const safeOrder: SortOrder = order === 'asc' ? 'asc' : 'desc';\n return { field: safeField, order: safeOrder };\n}\n"],"mappings":";AAiBO,IAAM,eAAe;AACrB,IAAM,gBAAgB;AAEtB,SAAS,eACd,QACA,SACA,cACqC;AACrC,QAAM,CAAC,OAAO,KAAK,IAAI,OAAO,MAAM,GAAG;AACvC,QAAM,YAAY,QAAQ,SAAS,KAAK,IAAI,QAAQ;AACpD,QAAM,YAAuB,UAAU,QAAQ,QAAQ;AACvD,SAAO,EAAE,OAAO,WAAW,OAAO,UAAU;AAC9C;","names":[]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/validators/shared.ts
|
|
2
|
+
var _zod = require('zod');
|
|
3
|
+
var slugSchema = _zod.z.string().min(1).max(200).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, "Slug must be URL-safe (lowercase, hyphens only)");
|
|
4
|
+
var safeUrl = _zod.z.url().refine(
|
|
5
|
+
(url) => {
|
|
6
|
+
const lower = url.toLowerCase().replace(/[\t\n\r]/g, "");
|
|
7
|
+
return !lower.startsWith("file:") && !lower.startsWith("javascript:") && !lower.startsWith("data:");
|
|
8
|
+
},
|
|
9
|
+
{ error: "Unsafe URL protocol (file:, javascript:, data: not allowed)" }
|
|
10
|
+
);
|
|
11
|
+
var optionalUrlSchema = safeUrl.optional().or(_zod.z.literal(""));
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
exports.slugSchema = slugSchema; exports.optionalUrlSchema = optionalUrlSchema;
|
|
17
|
+
//# sourceMappingURL=chunk-7SWW3ZIN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-cms-kit/dist/chunk-7SWW3ZIN.js","../src/validators/shared.ts"],"names":[],"mappings":"AAAA;ACAA,0BAAkB;AAEX,IAAM,WAAA,EAAa,MAAA,CACvB,MAAA,CAAO,CAAA,CACP,GAAA,CAAI,CAAC,CAAA,CACL,GAAA,CAAI,GAAG,CAAA,CACP,KAAA,CAAM,4BAAA,EAA8B,iDAAiD,CAAA;AAExF,IAAM,QAAA,EAAU,MAAA,CAAE,GAAA,CAAI,CAAA,CAAE,MAAA;AAAA,EACtB,CAAC,GAAA,EAAA,GAAQ;AACP,IAAA,MAAM,MAAA,EAAQ,GAAA,CAAI,WAAA,CAAY,CAAA,CAAE,OAAA,CAAQ,WAAA,EAAa,EAAE,CAAA;AACvD,IAAA,OAAO,CAAC,KAAA,CAAM,UAAA,CAAW,OAAO,EAAA,GAAK,CAAC,KAAA,CAAM,UAAA,CAAW,aAAa,EAAA,GAAK,CAAC,KAAA,CAAM,UAAA,CAAW,OAAO,CAAA;AAAA,EACpG,CAAA;AAAA,EACA,EAAE,KAAA,EAAO,8DAA8D;AACzE,CAAA;AACO,IAAM,kBAAA,EAAoB,OAAA,CAAQ,QAAA,CAAS,CAAA,CAAE,EAAA,CAAG,MAAA,CAAE,OAAA,CAAQ,EAAE,CAAC,CAAA;ADJpE;AACA;AACE;AACA;AACF,+EAAC","file":"/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-cms-kit/dist/chunk-7SWW3ZIN.js","sourcesContent":[null,"import { z } from 'zod';\n\nexport const slugSchema = z\n .string()\n .min(1)\n .max(200)\n .regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, 'Slug must be URL-safe (lowercase, hyphens only)');\n\nconst safeUrl = z.url().refine(\n (url) => {\n const lower = url.toLowerCase().replace(/[\\t\\n\\r]/g, '');\n return !lower.startsWith('file:') && !lower.startsWith('javascript:') && !lower.startsWith('data:');\n },\n { error: 'Unsafe URL protocol (file:, javascript:, data: not allowed)' },\n);\nexport const optionalUrlSchema = safeUrl.optional().or(z.literal(''));\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=chunk-AXR56AUD.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } }
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
var _chunkEG6NVPP2js = require('./chunk-EG6NVPP2.js');
|
|
6
|
+
|
|
7
|
+
// src/utils/r2-storage.ts
|
|
8
|
+
var _clients3 = require('@aws-sdk/client-s3');
|
|
9
|
+
var _logger = require('@withwiz/toolkit/core/logger/logger');
|
|
10
|
+
function sanitizeStorageKey(key) {
|
|
11
|
+
if (typeof key !== "string" || key.length === 0) {
|
|
12
|
+
throw _chunkEG6NVPP2js.namespacedError.call(void 0,
|
|
13
|
+
`storage key is empty or not a string; refusing to send to storage.`
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
if (key.startsWith("/")) {
|
|
17
|
+
throw _chunkEG6NVPP2js.namespacedError.call(void 0,
|
|
18
|
+
`storage key "${key}" is absolute / leading-slash; it could escape the intended namespace. Use a relative key (e.g. "news/x.jpg").`
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
if (key.includes("\\")) {
|
|
22
|
+
throw _chunkEG6NVPP2js.namespacedError.call(void 0,
|
|
23
|
+
`storage key "${key}" contains a backslash; refusing (namespace-escape risk).`
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
for (let i = 0; i < key.length; i++) {
|
|
27
|
+
if (key.charCodeAt(i) < 32) {
|
|
28
|
+
throw _chunkEG6NVPP2js.namespacedError.call(void 0,
|
|
29
|
+
`storage key contains control characters; refusing (namespace-escape risk).`
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const segments = key.split("/");
|
|
34
|
+
if (segments.some((seg) => seg === ".." || seg === ".")) {
|
|
35
|
+
throw _chunkEG6NVPP2js.namespacedError.call(void 0,
|
|
36
|
+
`storage key "${key}" contains a path-traversal segment ("." / ".."); it could escape the intended namespace.`
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
return key;
|
|
40
|
+
}
|
|
41
|
+
var client = null;
|
|
42
|
+
var clientSnapshot = null;
|
|
43
|
+
function requireR2Credentials() {
|
|
44
|
+
const c = _chunkEG6NVPP2js.resolveR2CredentialsConfig.call(void 0, );
|
|
45
|
+
const missing = [];
|
|
46
|
+
if (!c.accountId) missing.push("accountId");
|
|
47
|
+
if (!c.accessKeyId) missing.push("accessKeyId");
|
|
48
|
+
if (!c.secretAccessKey) missing.push("secretAccessKey");
|
|
49
|
+
if (!c.bucketName) missing.push("bucketName");
|
|
50
|
+
if (missing.length > 0) {
|
|
51
|
+
throw _chunkEG6NVPP2js.namespacedError.call(void 0,
|
|
52
|
+
`R2 credentials are missing: ${missing.join(", ")}. Inject \`setCmsConfig({ storage: { r2: { accountId, accessKeyId, secretAccessKey, bucketName } } })\` or set the legacy R2_ACCOUNT_ID / R2_ACCESS_KEY_ID / R2_SECRET_ACCESS_KEY / R2_BUCKET_NAME environment variables. There is no safe default for storage credentials.`
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
return c;
|
|
56
|
+
}
|
|
57
|
+
function getClient() {
|
|
58
|
+
const c = requireR2Credentials();
|
|
59
|
+
const snapshot = `${c.accountId}|${c.accessKeyId}`;
|
|
60
|
+
if (!client || clientSnapshot !== snapshot) {
|
|
61
|
+
client = new (0, _clients3.S3Client)({
|
|
62
|
+
region: "auto",
|
|
63
|
+
endpoint: `https://${c.accountId}.r2.cloudflarestorage.com`,
|
|
64
|
+
credentials: {
|
|
65
|
+
accessKeyId: c.accessKeyId,
|
|
66
|
+
secretAccessKey: c.secretAccessKey
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
clientSnapshot = snapshot;
|
|
70
|
+
}
|
|
71
|
+
return client;
|
|
72
|
+
}
|
|
73
|
+
function isR2Enabled() {
|
|
74
|
+
const c = _chunkEG6NVPP2js.resolveR2CredentialsConfig.call(void 0, );
|
|
75
|
+
return !!(c.accountId && c.accessKeyId && c.secretAccessKey && c.bucketName);
|
|
76
|
+
}
|
|
77
|
+
function buildPublicUrl(key, bucket) {
|
|
78
|
+
const base = _chunkEG6NVPP2js.resolveR2PublicUrl.call(void 0, );
|
|
79
|
+
return base ? `${base}/${key}` : `https://${bucket}.r2.dev/${key}`;
|
|
80
|
+
}
|
|
81
|
+
async function uploadToR2(key, buffer, contentType) {
|
|
82
|
+
const safeKey = sanitizeStorageKey(key);
|
|
83
|
+
const s3 = getClient();
|
|
84
|
+
const { bucketName: bucket } = requireR2Credentials();
|
|
85
|
+
await s3.send(
|
|
86
|
+
new (0, _clients3.PutObjectCommand)({
|
|
87
|
+
Bucket: bucket,
|
|
88
|
+
Key: safeKey,
|
|
89
|
+
Body: buffer,
|
|
90
|
+
ContentType: contentType
|
|
91
|
+
})
|
|
92
|
+
);
|
|
93
|
+
return { url: buildPublicUrl(safeKey, bucket), key: safeKey, size: buffer.length };
|
|
94
|
+
}
|
|
95
|
+
async function uploadImageWithVariants(originalKey, originalBuffer, originalContentType) {
|
|
96
|
+
const { generateImageVariants } = await Promise.resolve().then(() => _interopRequireWildcard(require("./utils/image-variants.js")));
|
|
97
|
+
const original = await uploadToR2(originalKey, originalBuffer, originalContentType);
|
|
98
|
+
const baseKey = originalKey.replace(/\.[^.]+$/, "");
|
|
99
|
+
const variants = {};
|
|
100
|
+
const variantKeys = [];
|
|
101
|
+
try {
|
|
102
|
+
const imageVariants = await generateImageVariants(originalBuffer, baseKey, originalContentType);
|
|
103
|
+
const { bucketName: bucket } = requireR2Credentials();
|
|
104
|
+
await Promise.all(
|
|
105
|
+
imageVariants.map(async (v) => {
|
|
106
|
+
try {
|
|
107
|
+
await uploadToR2(v.key, v.buffer, v.contentType);
|
|
108
|
+
variants[v.size] = buildPublicUrl(v.key, bucket);
|
|
109
|
+
variantKeys.push(v.key);
|
|
110
|
+
} catch (err) {
|
|
111
|
+
_logger.logError.call(void 0, `[image-variant] Failed to upload variant ${v.key}`, {
|
|
112
|
+
error: err instanceof Error ? err.message : err,
|
|
113
|
+
originalKey,
|
|
114
|
+
size: v.size
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
})
|
|
118
|
+
);
|
|
119
|
+
if (variantKeys.length === 0) {
|
|
120
|
+
_logger.logError.call(void 0, `[image-variant] No variants generated for ${originalKey}`);
|
|
121
|
+
}
|
|
122
|
+
} catch (err) {
|
|
123
|
+
_logger.logError.call(void 0, `[image-variant] Failed to generate variants for ${originalKey}`, {
|
|
124
|
+
error: err instanceof Error ? err.message : err
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
url: original.url,
|
|
129
|
+
key: original.key,
|
|
130
|
+
size: original.size,
|
|
131
|
+
variants,
|
|
132
|
+
variantKeys
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
async function deleteFromR2(key) {
|
|
136
|
+
const safeKey = sanitizeStorageKey(key);
|
|
137
|
+
const s3 = getClient();
|
|
138
|
+
const { bucketName: bucket } = requireR2Credentials();
|
|
139
|
+
await s3.send(
|
|
140
|
+
new (0, _clients3.DeleteObjectCommand)({
|
|
141
|
+
Bucket: bucket,
|
|
142
|
+
Key: safeKey
|
|
143
|
+
})
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
exports.sanitizeStorageKey = sanitizeStorageKey; exports.isR2Enabled = isR2Enabled; exports.uploadToR2 = uploadToR2; exports.uploadImageWithVariants = uploadImageWithVariants; exports.deleteFromR2 = deleteFromR2;
|
|
154
|
+
//# sourceMappingURL=chunk-BE7JDL64.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-cms-kit/dist/chunk-BE7JDL64.js","../src/utils/r2-storage.ts"],"names":[],"mappings":"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","file":"/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-cms-kit/dist/chunk-BE7JDL64.js","sourcesContent":[null,"import { S3Client, PutObjectCommand, DeleteObjectCommand } from '@aws-sdk/client-s3';\nimport { logError, logInfo } from '@withwiz/toolkit/core/logger/logger';\nimport {\n namespacedError,\n resolveR2CredentialsConfig,\n resolveR2PublicUrl,\n} from '../config';\n\n/**\n * storage object key 를 검증/정규화한다 (spec.md §4.6 / Sprint 1 S5).\n *\n * caller/user 파생 key 가 의도된 namespace 를 탈출(path traversal /\n * absolute / prefix-escape)하지 못하도록 한다. 위험 key 는 `@withwiz/cms-kit:`\n * 네임스페이스 에러로 즉시 거부한다. 양성(benign) key 는 *바이트 동일하게*\n * 통과시킨다 (blanket reject 아님 — 정규화로 인한 mangling 없음).\n *\n * 거부 규칙:\n * - 빈 값 / 비문자열\n * - 선행 `/` (절대/leading-slash: `/absolute`, `/news/x.jpg`)\n * - 백슬래시 포함 (`\\` — 윈도우식 절대/우회)\n * - 제어문자 (codepoint < 0x20)\n * - `.` / `..` path 세그먼트 (`../`, `a/../../b`, `news/../../secret`)\n */\nexport function sanitizeStorageKey(key: string): string {\n if (typeof key !== 'string' || key.length === 0) {\n throw namespacedError(\n `storage key is empty or not a string; refusing to send to storage.`,\n );\n }\n if (key.startsWith('/')) {\n throw namespacedError(\n `storage key \"${key}\" is absolute / leading-slash; it could escape the ` +\n `intended namespace. Use a relative key (e.g. \"news/x.jpg\").`,\n );\n }\n if (key.includes('\\\\')) {\n throw namespacedError(\n `storage key \"${key}\" contains a backslash; refusing (namespace-escape risk).`,\n );\n }\n for (let i = 0; i < key.length; i++) {\n if (key.charCodeAt(i) < 0x20) {\n throw namespacedError(\n `storage key contains control characters; refusing (namespace-escape risk).`,\n );\n }\n }\n const segments = key.split('/');\n if (segments.some((seg) => seg === '..' || seg === '.')) {\n throw namespacedError(\n `storage key \"${key}\" contains a path-traversal segment (\".\" / \"..\"); ` +\n `it could escape the intended namespace.`,\n );\n }\n // benign key: byte-identical passthrough.\n return key;\n}\n\nlet client: S3Client | null = null;\n// 자격증명/엔드포인트가 바뀌면 캐시된 S3Client 를 무효화하기 위한 스냅샷.\n// 같은 프로세스 내에서 `setCmsConfig` 가 재호출되거나 R2_* env 가 바뀐 경우\n// 다음 호출에서 새 클라이언트가 만들어진다.\nlet clientSnapshot: string | null = null;\n\nfunction requireR2Credentials(): {\n accountId: string;\n accessKeyId: string;\n secretAccessKey: string;\n bucketName: string;\n} {\n const c = resolveR2CredentialsConfig();\n const missing: string[] = [];\n if (!c.accountId) missing.push('accountId');\n if (!c.accessKeyId) missing.push('accessKeyId');\n if (!c.secretAccessKey) missing.push('secretAccessKey');\n if (!c.bucketName) missing.push('bucketName');\n if (missing.length > 0) {\n throw namespacedError(\n `R2 credentials are missing: ${missing.join(', ')}. ` +\n 'Inject `setCmsConfig({ storage: { r2: { accountId, accessKeyId, secretAccessKey, bucketName } } })` ' +\n 'or set the legacy R2_ACCOUNT_ID / R2_ACCESS_KEY_ID / R2_SECRET_ACCESS_KEY / R2_BUCKET_NAME ' +\n 'environment variables. There is no safe default for storage credentials.',\n );\n }\n return c as {\n accountId: string;\n accessKeyId: string;\n secretAccessKey: string;\n bucketName: string;\n };\n}\n\nfunction getClient(): S3Client {\n const c = requireR2Credentials();\n const snapshot = `${c.accountId}|${c.accessKeyId}`;\n if (!client || clientSnapshot !== snapshot) {\n client = new S3Client({\n region: 'auto',\n endpoint: `https://${c.accountId}.r2.cloudflarestorage.com`,\n credentials: {\n accessKeyId: c.accessKeyId,\n secretAccessKey: c.secretAccessKey,\n },\n });\n clientSnapshot = snapshot;\n }\n return client;\n}\n\nexport function isR2Enabled(): boolean {\n const c = resolveR2CredentialsConfig();\n return !!(c.accountId && c.accessKeyId && c.secretAccessKey && c.bucketName);\n}\n\nfunction buildPublicUrl(key: string, bucket: string): string {\n const base = resolveR2PublicUrl();\n return base ? `${base}/${key}` : `https://${bucket}.r2.dev/${key}`;\n}\n\nexport async function uploadToR2(\n key: string,\n buffer: Buffer,\n contentType: string,\n): Promise<{ url: string; key: string; size: number }> {\n const safeKey = sanitizeStorageKey(key);\n const s3 = getClient();\n const { bucketName: bucket } = requireR2Credentials();\n\n await s3.send(\n new PutObjectCommand({\n Bucket: bucket,\n Key: safeKey,\n Body: buffer,\n ContentType: contentType,\n }),\n );\n\n return { url: buildPublicUrl(safeKey, bucket), key: safeKey, size: buffer.length };\n}\n\nexport interface ImageVariantUrls {\n lg?: string;\n md?: string;\n sm?: string;\n thumb?: string;\n}\n\nexport async function uploadImageWithVariants(\n originalKey: string,\n originalBuffer: Buffer,\n originalContentType: string,\n): Promise<{\n url: string;\n key: string;\n size: number;\n variants: ImageVariantUrls;\n variantKeys: string[];\n}> {\n const { generateImageVariants } = await import('./image-variants');\n\n const original = await uploadToR2(originalKey, originalBuffer, originalContentType);\n\n const baseKey = originalKey.replace(/\\.[^.]+$/, '');\n\n const variants: ImageVariantUrls = {};\n const variantKeys: string[] = [];\n\n try {\n const imageVariants = await generateImageVariants(originalBuffer, baseKey, originalContentType);\n const { bucketName: bucket } = requireR2Credentials();\n\n await Promise.all(\n imageVariants.map(async (v) => {\n try {\n await uploadToR2(v.key, v.buffer, v.contentType);\n variants[v.size] = buildPublicUrl(v.key, bucket);\n variantKeys.push(v.key);\n } catch (err) {\n logError(`[image-variant] Failed to upload variant ${v.key}`, {\n error: err instanceof Error ? err.message : err,\n originalKey,\n size: v.size,\n });\n }\n }),\n );\n\n if (variantKeys.length === 0) {\n logError(`[image-variant] No variants generated for ${originalKey}`);\n }\n } catch (err) {\n logError(`[image-variant] Failed to generate variants for ${originalKey}`, {\n error: err instanceof Error ? err.message : err,\n });\n }\n\n return {\n url: original.url,\n key: original.key,\n size: original.size,\n variants,\n variantKeys,\n };\n}\n\nexport async function deleteFromR2(key: string): Promise<void> {\n const safeKey = sanitizeStorageKey(key);\n const s3 = getClient();\n const { bucketName: bucket } = requireR2Credentials();\n await s3.send(\n new DeleteObjectCommand({\n Bucket: bucket,\n Key: safeKey,\n }),\n );\n}\n"]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/utils/cn.ts
|
|
2
|
+
var _clsx = require('clsx');
|
|
3
|
+
var _tailwindmerge = require('tailwind-merge');
|
|
4
|
+
function cn(...inputs) {
|
|
5
|
+
return _tailwindmerge.twMerge.call(void 0, _clsx.clsx.call(void 0, inputs));
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// src/utils/api-response.ts
|
|
9
|
+
var _server = require('next/server');
|
|
10
|
+
var NextApiResponse = class {
|
|
11
|
+
static success(data, status = 200) {
|
|
12
|
+
return _server.NextResponse.json({ success: true, data }, { status });
|
|
13
|
+
}
|
|
14
|
+
static paginated(items, page, pageSize, total, dataKey = "items") {
|
|
15
|
+
const totalPages = Math.ceil(total / pageSize);
|
|
16
|
+
return this.success({
|
|
17
|
+
[dataKey]: items,
|
|
18
|
+
pagination: { page, pageSize, total, totalPages, hasMore: page < totalPages }
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
static created(data) {
|
|
22
|
+
return this.success(data, 201);
|
|
23
|
+
}
|
|
24
|
+
static noContent() {
|
|
25
|
+
return new (0, _server.NextResponse)(null, { status: 204 });
|
|
26
|
+
}
|
|
27
|
+
static error(message, status = 400, code) {
|
|
28
|
+
return _server.NextResponse.json(
|
|
29
|
+
{ success: false, error: { message, ...code && { code } } },
|
|
30
|
+
{ status }
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
static notFound(message = "Not Found") {
|
|
34
|
+
return this.error(message, 404, "NOT_FOUND");
|
|
35
|
+
}
|
|
36
|
+
static unauthorized(message = "Unauthorized") {
|
|
37
|
+
return this.error(message, 401, "UNAUTHORIZED");
|
|
38
|
+
}
|
|
39
|
+
static forbidden(message = "Forbidden") {
|
|
40
|
+
return this.error(message, 403, "FORBIDDEN");
|
|
41
|
+
}
|
|
42
|
+
static serverError(message = "Internal Server Error") {
|
|
43
|
+
return this.error(message, 500, "INTERNAL_SERVER_ERROR");
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
exports.cn = cn; exports.NextApiResponse = NextApiResponse;
|
|
51
|
+
//# sourceMappingURL=chunk-BHN2SRZC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-cms-kit/dist/chunk-BHN2SRZC.js","../src/utils/cn.ts","../src/utils/api-response.ts"],"names":[],"mappings":"AAAA;ACAA,4BAAsC;AACtC,+CAAwB;AAEjB,SAAS,EAAA,CAAA,GAAM,MAAA,EAAsB;AAC1C,EAAA,OAAO,oCAAA,wBAAQ,MAAW,CAAC,CAAA;AAC7B;ADCA;AACA;AEPA,qCAA6B;AAEtB,IAAM,gBAAA,EAAN,MAAsB;AAAA,EAC3B,OAAO,OAAA,CAAW,IAAA,EAAS,OAAA,EAAiB,GAAA,EAAK;AAC/C,IAAA,OAAO,oBAAA,CAAa,IAAA,CAAK,EAAE,OAAA,EAAS,IAAA,EAAM,KAAK,CAAA,EAAG,EAAE,OAAO,CAAC,CAAA;AAAA,EAC9D;AAAA,EAEA,OAAO,SAAA,CACL,KAAA,EACA,IAAA,EACA,QAAA,EACA,KAAA,EACA,QAAA,EAAkB,OAAA,EAClB;AACA,IAAA,MAAM,WAAA,EAAa,IAAA,CAAK,IAAA,CAAK,MAAA,EAAQ,QAAQ,CAAA;AAC7C,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ;AAAA,MAClB,CAAC,OAAO,CAAA,EAAG,KAAA;AAAA,MACX,UAAA,EAAY,EAAE,IAAA,EAAM,QAAA,EAAU,KAAA,EAAO,UAAA,EAAY,OAAA,EAAS,KAAA,EAAO,WAAW;AAAA,IAC9E,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,OAAO,OAAA,CAAW,IAAA,EAAS;AACzB,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,IAAA,EAAM,GAAG,CAAA;AAAA,EAC/B;AAAA,EAEA,OAAO,SAAA,CAAA,EAAY;AACjB,IAAA,OAAO,IAAI,yBAAA,CAAa,IAAA,EAAM,EAAE,MAAA,EAAQ,IAAI,CAAC,CAAA;AAAA,EAC/C;AAAA,EAEA,OAAO,KAAA,CAAM,OAAA,EAAiB,OAAA,EAAiB,GAAA,EAAK,IAAA,EAAe;AACjE,IAAA,OAAO,oBAAA,CAAa,IAAA;AAAA,MAClB,EAAE,OAAA,EAAS,KAAA,EAAO,KAAA,EAAO,EAAE,OAAA,EAAS,GAAI,KAAA,GAAQ,EAAE,KAAK,EAAG,EAAE,CAAA;AAAA,MAC5D,EAAE,OAAO;AAAA,IACX,CAAA;AAAA,EACF;AAAA,EAEA,OAAO,QAAA,CAAS,QAAA,EAAkB,WAAA,EAAa;AAC7C,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,OAAA,EAAS,GAAA,EAAK,WAAW,CAAA;AAAA,EAC7C;AAAA,EAEA,OAAO,YAAA,CAAa,QAAA,EAAkB,cAAA,EAAgB;AACpD,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,OAAA,EAAS,GAAA,EAAK,cAAc,CAAA;AAAA,EAChD;AAAA,EAEA,OAAO,SAAA,CAAU,QAAA,EAAkB,WAAA,EAAa;AAC9C,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,OAAA,EAAS,GAAA,EAAK,WAAW,CAAA;AAAA,EAC7C;AAAA,EAEA,OAAO,WAAA,CAAY,QAAA,EAAkB,uBAAA,EAAyB;AAC5D,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,OAAA,EAAS,GAAA,EAAK,uBAAuB,CAAA;AAAA,EACzD;AACF,CAAA;AFNA;AACA;AACE;AACA;AACF,2DAAC","file":"/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-cms-kit/dist/chunk-BHN2SRZC.js","sourcesContent":[null,"import { type ClassValue, clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import { NextResponse } from 'next/server';\n\nexport class NextApiResponse {\n static success<T>(data: T, status: number = 200) {\n return NextResponse.json({ success: true, data }, { status });\n }\n\n static paginated<T>(\n items: T[],\n page: number,\n pageSize: number,\n total: number,\n dataKey: string = 'items',\n ) {\n const totalPages = Math.ceil(total / pageSize);\n return this.success({\n [dataKey]: items,\n pagination: { page, pageSize, total, totalPages, hasMore: page < totalPages },\n });\n }\n\n static created<T>(data: T) {\n return this.success(data, 201);\n }\n\n static noContent() {\n return new NextResponse(null, { status: 204 });\n }\n\n static error(message: string, status: number = 400, code?: string) {\n return NextResponse.json(\n { success: false, error: { message, ...(code && { code }) } },\n { status },\n );\n }\n\n static notFound(message: string = 'Not Found') {\n return this.error(message, 404, 'NOT_FOUND');\n }\n\n static unauthorized(message: string = 'Unauthorized') {\n return this.error(message, 401, 'UNAUTHORIZED');\n }\n\n static forbidden(message: string = 'Forbidden') {\n return this.error(message, 403, 'FORBIDDEN');\n }\n\n static serverError(message: string = 'Internal Server Error') {\n return this.error(message, 500, 'INTERNAL_SERVER_ERROR');\n }\n}\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
__require
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=chunk-BJTO5JO5.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|