nextblogkit 0.6.2 → 0.7.1
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.md +83 -21
- package/dist/admin/index.cjs +366 -10
- package/dist/admin/index.cjs.map +1 -1
- package/dist/admin/index.d.cts +7 -3
- package/dist/admin/index.d.ts +7 -3
- package/dist/admin/index.js +365 -11
- package/dist/admin/index.js.map +1 -1
- package/dist/api/categories.cjs +32 -32
- package/dist/api/categories.cjs.map +1 -1
- package/dist/api/categories.d.cts +1 -1
- package/dist/api/categories.d.ts +1 -1
- package/dist/api/categories.js +6 -6
- package/dist/api/categories.js.map +1 -1
- package/dist/api/media.cjs +37 -30
- package/dist/api/media.cjs.map +1 -1
- package/dist/api/media.d.cts +1 -1
- package/dist/api/media.d.ts +1 -1
- package/dist/api/media.js +13 -6
- package/dist/api/media.js.map +1 -1
- package/dist/api/posts.cjs +39 -39
- package/dist/api/posts.cjs.map +1 -1
- package/dist/api/posts.d.cts +1 -1
- package/dist/api/posts.d.ts +1 -1
- package/dist/api/posts.js +6 -6
- package/dist/api/posts.js.map +1 -1
- package/dist/api/rss.cjs +3 -3
- package/dist/api/rss.js +2 -2
- package/dist/api/settings.cjs +13 -13
- package/dist/api/settings.cjs.map +1 -1
- package/dist/api/settings.d.cts +1 -1
- package/dist/api/settings.d.ts +1 -1
- package/dist/api/settings.js +5 -5
- package/dist/api/settings.js.map +1 -1
- package/dist/api/sitemap.cjs +3 -3
- package/dist/api/sitemap.js +2 -2
- package/dist/api/tokens.cjs +56 -0
- package/dist/api/tokens.cjs.map +1 -0
- package/dist/api/tokens.d.cts +22 -0
- package/dist/api/tokens.d.ts +22 -0
- package/dist/api/tokens.js +52 -0
- package/dist/api/tokens.js.map +1 -0
- package/dist/{chunk-6HKMZOI4.cjs → chunk-3BKPNOES.cjs} +8 -7
- package/dist/chunk-3BKPNOES.cjs.map +1 -0
- package/dist/{chunk-N5MKAD7J.cjs → chunk-DR7QNI32.cjs} +6 -2
- package/dist/chunk-DR7QNI32.cjs.map +1 -0
- package/dist/{chunk-QE4VLQYN.cjs → chunk-F47RPOTU.cjs} +13 -10
- package/dist/chunk-F47RPOTU.cjs.map +1 -0
- package/dist/{chunk-64HUVJOZ.js → chunk-JI2RK6KX.js} +80 -13
- package/dist/chunk-JI2RK6KX.js.map +1 -0
- package/dist/{chunk-R6MO3QIP.js → chunk-NSR7NYSB.js} +6 -5
- package/dist/chunk-NSR7NYSB.js.map +1 -0
- package/dist/{chunk-4PY224XM.js → chunk-O3XES5O2.js} +6 -3
- package/dist/chunk-O3XES5O2.js.map +1 -0
- package/dist/{chunk-4NKOJYWJ.js → chunk-OOUJYUGP.js} +8 -7
- package/dist/chunk-OOUJYUGP.js.map +1 -0
- package/dist/{chunk-A2S32RZN.js → chunk-OWWWTTUT.js} +8 -3
- package/dist/chunk-OWWWTTUT.js.map +1 -0
- package/dist/{chunk-E2QLTHKN.cjs → chunk-QBZLGBHQ.cjs} +11 -10
- package/dist/chunk-QBZLGBHQ.cjs.map +1 -0
- package/dist/{chunk-ZP5XRVVH.cjs → chunk-SUJT6LWH.cjs} +12 -7
- package/dist/chunk-SUJT6LWH.cjs.map +1 -0
- package/dist/{chunk-JM7QRXXK.js → chunk-TVHY4BR2.js} +10 -7
- package/dist/chunk-TVHY4BR2.js.map +1 -0
- package/dist/{chunk-JLPJKNRZ.js → chunk-UMIBGO4S.js} +18 -5
- package/dist/chunk-UMIBGO4S.js.map +1 -0
- package/dist/{chunk-U2ROR6AY.cjs → chunk-VWKVU3SE.cjs} +86 -12
- package/dist/chunk-VWKVU3SE.cjs.map +1 -0
- package/dist/{chunk-KDZER3PU.cjs → chunk-YTJQ426D.cjs} +19 -5
- package/dist/chunk-YTJQ426D.cjs.map +1 -0
- package/dist/cli/index.cjs +90 -19
- package/dist/components/index.cjs +3 -2
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.d.cts +2 -1
- package/dist/components/index.d.ts +2 -1
- package/dist/components/index.js +3 -2
- package/dist/components/index.js.map +1 -1
- package/dist/db-OUSQPM53.js +3 -0
- package/dist/db-OUSQPM53.js.map +1 -0
- package/dist/db-RFY6O5UE.cjs +108 -0
- package/dist/db-RFY6O5UE.cjs.map +1 -0
- package/dist/editor/index.cjs +1 -0
- package/dist/editor/index.cjs.map +1 -1
- package/dist/editor/index.js +1 -0
- package/dist/editor/index.js.map +1 -1
- package/dist/{index-vjlZDWNr.d.cts → index-Bk8gOqBq.d.cts} +25 -21
- package/dist/{index-Cgzphklp.d.ts → index-DsnG2kdW.d.ts} +25 -21
- package/dist/index.cjs +47 -47
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +5 -5
- package/dist/lib/index.cjs +39 -35
- package/dist/lib/index.d.cts +2 -2
- package/dist/lib/index.d.ts +2 -2
- package/dist/lib/index.js +5 -5
- package/dist/{types-CBEEBR4A.d.ts → types-Cu515Egx.d.cts} +16 -1
- package/dist/{types-CBEEBR4A.d.cts → types-Cu515Egx.d.ts} +16 -1
- package/package.json +1 -1
- package/dist/chunk-4NKOJYWJ.js.map +0 -1
- package/dist/chunk-4PY224XM.js.map +0 -1
- package/dist/chunk-64HUVJOZ.js.map +0 -1
- package/dist/chunk-6HKMZOI4.cjs.map +0 -1
- package/dist/chunk-A2S32RZN.js.map +0 -1
- package/dist/chunk-E2QLTHKN.cjs.map +0 -1
- package/dist/chunk-JLPJKNRZ.js.map +0 -1
- package/dist/chunk-JM7QRXXK.js.map +0 -1
- package/dist/chunk-KDZER3PU.cjs.map +0 -1
- package/dist/chunk-N5MKAD7J.cjs.map +0 -1
- package/dist/chunk-QE4VLQYN.cjs.map +0 -1
- package/dist/chunk-R6MO3QIP.js.map +0 -1
- package/dist/chunk-U2ROR6AY.cjs.map +0 -1
- package/dist/chunk-ZP5XRVVH.cjs.map +0 -1
package/dist/api/categories.cjs
CHANGED
|
@@ -1,76 +1,76 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
3
|
+
var chunkDR7QNI32_cjs = require('../chunk-DR7QNI32.cjs');
|
|
4
|
+
var chunkYTJQ426D_cjs = require('../chunk-YTJQ426D.cjs');
|
|
5
|
+
var chunkVWKVU3SE_cjs = require('../chunk-VWKVU3SE.cjs');
|
|
6
6
|
|
|
7
7
|
// src/api/categories.ts
|
|
8
8
|
async function GET(request) {
|
|
9
9
|
try {
|
|
10
|
-
const params =
|
|
10
|
+
const params = chunkYTJQ426D_cjs.getSearchParams(request);
|
|
11
11
|
if (params.slug) {
|
|
12
|
-
const category = await
|
|
13
|
-
if (!category) return
|
|
14
|
-
return
|
|
12
|
+
const category = await chunkVWKVU3SE_cjs.getCategoryBySlug(params.slug);
|
|
13
|
+
if (!category) return chunkYTJQ426D_cjs.jsonError("NOT_FOUND", "Category not found", 404);
|
|
14
|
+
return chunkYTJQ426D_cjs.jsonSuccess(category);
|
|
15
15
|
}
|
|
16
|
-
const categories = await
|
|
17
|
-
return
|
|
16
|
+
const categories = await chunkVWKVU3SE_cjs.listCategories();
|
|
17
|
+
return chunkYTJQ426D_cjs.jsonSuccess(categories);
|
|
18
18
|
} catch (error) {
|
|
19
19
|
console.error("[nextblogkit] GET /categories error:", error);
|
|
20
|
-
return
|
|
20
|
+
return chunkYTJQ426D_cjs.jsonError("INTERNAL_ERROR", "Failed to fetch categories", 500);
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
async function POST(request) {
|
|
24
24
|
try {
|
|
25
|
-
const authError =
|
|
25
|
+
const authError = await chunkYTJQ426D_cjs.requireAuth(request);
|
|
26
26
|
if (authError) return authError;
|
|
27
27
|
const body = await request.json();
|
|
28
|
-
const parsed =
|
|
28
|
+
const parsed = chunkDR7QNI32_cjs.CreateCategorySchema.safeParse(body);
|
|
29
29
|
if (!parsed.success) {
|
|
30
30
|
const errors = parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`);
|
|
31
|
-
return
|
|
31
|
+
return chunkYTJQ426D_cjs.jsonError("VALIDATION_ERROR", errors.join("; "));
|
|
32
32
|
}
|
|
33
|
-
const category = await
|
|
34
|
-
return
|
|
33
|
+
const category = await chunkVWKVU3SE_cjs.createCategory(parsed.data);
|
|
34
|
+
return chunkYTJQ426D_cjs.jsonSuccess(category, void 0, 201);
|
|
35
35
|
} catch (error) {
|
|
36
36
|
console.error("[nextblogkit] POST /categories error:", error);
|
|
37
|
-
return
|
|
37
|
+
return chunkYTJQ426D_cjs.jsonError("INTERNAL_ERROR", "Failed to create category", 500);
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
async function PUT(request) {
|
|
41
41
|
try {
|
|
42
|
-
const authError =
|
|
42
|
+
const authError = await chunkYTJQ426D_cjs.requireAuth(request);
|
|
43
43
|
if (authError) return authError;
|
|
44
|
-
const params =
|
|
44
|
+
const params = chunkYTJQ426D_cjs.getSearchParams(request);
|
|
45
45
|
const id = params.id;
|
|
46
|
-
if (!id) return
|
|
46
|
+
if (!id) return chunkYTJQ426D_cjs.jsonError("MISSING_ID", "Category ID is required");
|
|
47
47
|
const body = await request.json();
|
|
48
|
-
const parsed =
|
|
48
|
+
const parsed = chunkDR7QNI32_cjs.UpdateCategorySchema.safeParse(body);
|
|
49
49
|
if (!parsed.success) {
|
|
50
50
|
const errors = parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`);
|
|
51
|
-
return
|
|
51
|
+
return chunkYTJQ426D_cjs.jsonError("VALIDATION_ERROR", errors.join("; "));
|
|
52
52
|
}
|
|
53
|
-
const category = await
|
|
54
|
-
if (!category) return
|
|
55
|
-
return
|
|
53
|
+
const category = await chunkVWKVU3SE_cjs.updateCategory(id, parsed.data);
|
|
54
|
+
if (!category) return chunkYTJQ426D_cjs.jsonError("NOT_FOUND", "Category not found", 404);
|
|
55
|
+
return chunkYTJQ426D_cjs.jsonSuccess(category);
|
|
56
56
|
} catch (error) {
|
|
57
57
|
console.error("[nextblogkit] PUT /categories error:", error);
|
|
58
|
-
return
|
|
58
|
+
return chunkYTJQ426D_cjs.jsonError("INTERNAL_ERROR", "Failed to update category", 500);
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
async function DELETE(request) {
|
|
62
62
|
try {
|
|
63
|
-
const authError =
|
|
63
|
+
const authError = await chunkYTJQ426D_cjs.requireAuth(request);
|
|
64
64
|
if (authError) return authError;
|
|
65
|
-
const params =
|
|
65
|
+
const params = chunkYTJQ426D_cjs.getSearchParams(request);
|
|
66
66
|
const id = params.id;
|
|
67
|
-
if (!id) return
|
|
68
|
-
const deleted = await
|
|
69
|
-
if (!deleted) return
|
|
70
|
-
return
|
|
67
|
+
if (!id) return chunkYTJQ426D_cjs.jsonError("MISSING_ID", "Category ID is required");
|
|
68
|
+
const deleted = await chunkVWKVU3SE_cjs.deleteCategory(id);
|
|
69
|
+
if (!deleted) return chunkYTJQ426D_cjs.jsonError("NOT_FOUND", "Category not found", 404);
|
|
70
|
+
return chunkYTJQ426D_cjs.jsonSuccess({ deleted: true });
|
|
71
71
|
} catch (error) {
|
|
72
72
|
console.error("[nextblogkit] DELETE /categories error:", error);
|
|
73
|
-
return
|
|
73
|
+
return chunkYTJQ426D_cjs.jsonError("INTERNAL_ERROR", "Failed to delete category", 500);
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/api/categories.ts"],"names":["getSearchParams","getCategoryBySlug","jsonError","jsonSuccess","listCategories","requireAuth","CreateCategorySchema","createCategory","UpdateCategorySchema","updateCategory","deleteCategory"],"mappings":";;;;;;;AAUA,eAAsB,IAAI,OAAA,EAAkB;AAC1C,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAASA,kCAAgB,OAAO,CAAA;AAEtC,IAAA,IAAI,OAAO,IAAA,EAAM;AACf,MAAA,MAAM,QAAA,GAAW,MAAMC,mCAAA,CAAkB,MAAA,CAAO,IAAI,CAAA;AACpD,MAAA,IAAI,CAAC,QAAA,EAAU,OAAOC,2BAAA,CAAU,WAAA,EAAa,sBAAsB,GAAG,CAAA;AACtE,MAAA,OAAOC,8BAAY,QAAQ,CAAA;AAAA,IAC7B;AAEA,IAAA,MAAM,UAAA,GAAa,MAAMC,gCAAA,EAAe;AACxC,IAAA,OAAOD,8BAAY,UAAU,CAAA;AAAA,EAC/B,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,wCAAwC,KAAK,CAAA;AAC3D,IAAA,OAAOD,2BAAA,CAAU,gBAAA,EAAkB,4BAAA,EAA8B,GAAG,CAAA;AAAA,EACtE;AACF;AAEA,eAAsB,KAAK,OAAA,EAAkB;AAC3C,EAAA,IAAI;AACF,IAAA,MAAM,SAAA,
|
|
1
|
+
{"version":3,"sources":["../../src/api/categories.ts"],"names":["getSearchParams","getCategoryBySlug","jsonError","jsonSuccess","listCategories","requireAuth","CreateCategorySchema","createCategory","UpdateCategorySchema","updateCategory","deleteCategory"],"mappings":"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","file":"categories.cjs","sourcesContent":["import {\n listCategories,\n getCategoryBySlug,\n createCategory,\n updateCategory,\n deleteCategory,\n} from '../lib/db';\nimport { CreateCategorySchema, UpdateCategorySchema } from '../lib/types';\nimport { jsonSuccess, jsonError, requireAuth, getSearchParams } from './middleware';\n\nexport async function GET(request: Request) {\n try {\n const params = getSearchParams(request);\n\n if (params.slug) {\n const category = await getCategoryBySlug(params.slug);\n if (!category) return jsonError('NOT_FOUND', 'Category not found', 404);\n return jsonSuccess(category);\n }\n\n const categories = await listCategories();\n return jsonSuccess(categories);\n } catch (error) {\n console.error('[nextblogkit] GET /categories error:', error);\n return jsonError('INTERNAL_ERROR', 'Failed to fetch categories', 500);\n }\n}\n\nexport async function POST(request: Request) {\n try {\n const authError = await requireAuth(request);\n if (authError) return authError;\n\n const body = await request.json();\n const parsed = CreateCategorySchema.safeParse(body);\n\n if (!parsed.success) {\n const errors = parsed.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`);\n return jsonError('VALIDATION_ERROR', errors.join('; '));\n }\n\n const category = await createCategory(parsed.data);\n return jsonSuccess(category, undefined, 201);\n } catch (error) {\n console.error('[nextblogkit] POST /categories error:', error);\n return jsonError('INTERNAL_ERROR', 'Failed to create category', 500);\n }\n}\n\nexport async function PUT(request: Request) {\n try {\n const authError = await requireAuth(request);\n if (authError) return authError;\n\n const params = getSearchParams(request);\n const id = params.id;\n if (!id) return jsonError('MISSING_ID', 'Category ID is required');\n\n const body = await request.json();\n const parsed = UpdateCategorySchema.safeParse(body);\n\n if (!parsed.success) {\n const errors = parsed.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`);\n return jsonError('VALIDATION_ERROR', errors.join('; '));\n }\n\n const category = await updateCategory(id, parsed.data);\n if (!category) return jsonError('NOT_FOUND', 'Category not found', 404);\n\n return jsonSuccess(category);\n } catch (error) {\n console.error('[nextblogkit] PUT /categories error:', error);\n return jsonError('INTERNAL_ERROR', 'Failed to update category', 500);\n }\n}\n\nexport async function DELETE(request: Request) {\n try {\n const authError = await requireAuth(request);\n if (authError) return authError;\n\n const params = getSearchParams(request);\n const id = params.id;\n if (!id) return jsonError('MISSING_ID', 'Category ID is required');\n\n const deleted = await deleteCategory(id);\n if (!deleted) return jsonError('NOT_FOUND', 'Category not found', 404);\n\n return jsonSuccess({ deleted: true });\n } catch (error) {\n console.error('[nextblogkit] DELETE /categories error:', error);\n return jsonError('INTERNAL_ERROR', 'Failed to delete category', 500);\n }\n}\n"]}
|
package/dist/api/categories.d.ts
CHANGED
package/dist/api/categories.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { CreateCategorySchema, UpdateCategorySchema } from '../chunk-
|
|
2
|
-
import { getSearchParams, jsonError, jsonSuccess, requireAuth } from '../chunk-
|
|
3
|
-
import { getCategoryBySlug, listCategories, createCategory, updateCategory, deleteCategory } from '../chunk-
|
|
1
|
+
import { CreateCategorySchema, UpdateCategorySchema } from '../chunk-O3XES5O2.js';
|
|
2
|
+
import { getSearchParams, jsonError, jsonSuccess, requireAuth } from '../chunk-UMIBGO4S.js';
|
|
3
|
+
import { getCategoryBySlug, listCategories, createCategory, updateCategory, deleteCategory } from '../chunk-JI2RK6KX.js';
|
|
4
4
|
|
|
5
5
|
// src/api/categories.ts
|
|
6
6
|
async function GET(request) {
|
|
@@ -20,7 +20,7 @@ async function GET(request) {
|
|
|
20
20
|
}
|
|
21
21
|
async function POST(request) {
|
|
22
22
|
try {
|
|
23
|
-
const authError = requireAuth(request);
|
|
23
|
+
const authError = await requireAuth(request);
|
|
24
24
|
if (authError) return authError;
|
|
25
25
|
const body = await request.json();
|
|
26
26
|
const parsed = CreateCategorySchema.safeParse(body);
|
|
@@ -37,7 +37,7 @@ async function POST(request) {
|
|
|
37
37
|
}
|
|
38
38
|
async function PUT(request) {
|
|
39
39
|
try {
|
|
40
|
-
const authError = requireAuth(request);
|
|
40
|
+
const authError = await requireAuth(request);
|
|
41
41
|
if (authError) return authError;
|
|
42
42
|
const params = getSearchParams(request);
|
|
43
43
|
const id = params.id;
|
|
@@ -58,7 +58,7 @@ async function PUT(request) {
|
|
|
58
58
|
}
|
|
59
59
|
async function DELETE(request) {
|
|
60
60
|
try {
|
|
61
|
-
const authError = requireAuth(request);
|
|
61
|
+
const authError = await requireAuth(request);
|
|
62
62
|
if (authError) return authError;
|
|
63
63
|
const params = getSearchParams(request);
|
|
64
64
|
const id = params.id;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/api/categories.ts"],"names":[],"mappings":";;;;;AAUA,eAAsB,IAAI,OAAA,EAAkB;AAC1C,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,gBAAgB,OAAO,CAAA;AAEtC,IAAA,IAAI,OAAO,IAAA,EAAM;AACf,MAAA,MAAM,QAAA,GAAW,MAAM,iBAAA,CAAkB,MAAA,CAAO,IAAI,CAAA;AACpD,MAAA,IAAI,CAAC,QAAA,EAAU,OAAO,SAAA,CAAU,WAAA,EAAa,sBAAsB,GAAG,CAAA;AACtE,MAAA,OAAO,YAAY,QAAQ,CAAA;AAAA,IAC7B;AAEA,IAAA,MAAM,UAAA,GAAa,MAAM,cAAA,EAAe;AACxC,IAAA,OAAO,YAAY,UAAU,CAAA;AAAA,EAC/B,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,wCAAwC,KAAK,CAAA;AAC3D,IAAA,OAAO,SAAA,CAAU,gBAAA,EAAkB,4BAAA,EAA8B,GAAG,CAAA;AAAA,EACtE;AACF;AAEA,eAAsB,KAAK,OAAA,EAAkB;AAC3C,EAAA,IAAI;AACF,IAAA,MAAM,SAAA,GAAY,
|
|
1
|
+
{"version":3,"sources":["../../src/api/categories.ts"],"names":[],"mappings":"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","file":"categories.js","sourcesContent":["import {\n listCategories,\n getCategoryBySlug,\n createCategory,\n updateCategory,\n deleteCategory,\n} from '../lib/db';\nimport { CreateCategorySchema, UpdateCategorySchema } from '../lib/types';\nimport { jsonSuccess, jsonError, requireAuth, getSearchParams } from './middleware';\n\nexport async function GET(request: Request) {\n try {\n const params = getSearchParams(request);\n\n if (params.slug) {\n const category = await getCategoryBySlug(params.slug);\n if (!category) return jsonError('NOT_FOUND', 'Category not found', 404);\n return jsonSuccess(category);\n }\n\n const categories = await listCategories();\n return jsonSuccess(categories);\n } catch (error) {\n console.error('[nextblogkit] GET /categories error:', error);\n return jsonError('INTERNAL_ERROR', 'Failed to fetch categories', 500);\n }\n}\n\nexport async function POST(request: Request) {\n try {\n const authError = await requireAuth(request);\n if (authError) return authError;\n\n const body = await request.json();\n const parsed = CreateCategorySchema.safeParse(body);\n\n if (!parsed.success) {\n const errors = parsed.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`);\n return jsonError('VALIDATION_ERROR', errors.join('; '));\n }\n\n const category = await createCategory(parsed.data);\n return jsonSuccess(category, undefined, 201);\n } catch (error) {\n console.error('[nextblogkit] POST /categories error:', error);\n return jsonError('INTERNAL_ERROR', 'Failed to create category', 500);\n }\n}\n\nexport async function PUT(request: Request) {\n try {\n const authError = await requireAuth(request);\n if (authError) return authError;\n\n const params = getSearchParams(request);\n const id = params.id;\n if (!id) return jsonError('MISSING_ID', 'Category ID is required');\n\n const body = await request.json();\n const parsed = UpdateCategorySchema.safeParse(body);\n\n if (!parsed.success) {\n const errors = parsed.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`);\n return jsonError('VALIDATION_ERROR', errors.join('; '));\n }\n\n const category = await updateCategory(id, parsed.data);\n if (!category) return jsonError('NOT_FOUND', 'Category not found', 404);\n\n return jsonSuccess(category);\n } catch (error) {\n console.error('[nextblogkit] PUT /categories error:', error);\n return jsonError('INTERNAL_ERROR', 'Failed to update category', 500);\n }\n}\n\nexport async function DELETE(request: Request) {\n try {\n const authError = await requireAuth(request);\n if (authError) return authError;\n\n const params = getSearchParams(request);\n const id = params.id;\n if (!id) return jsonError('MISSING_ID', 'Category ID is required');\n\n const deleted = await deleteCategory(id);\n if (!deleted) return jsonError('NOT_FOUND', 'Category not found', 404);\n\n return jsonSuccess({ deleted: true });\n } catch (error) {\n console.error('[nextblogkit] DELETE /categories error:', error);\n return jsonError('INTERNAL_ERROR', 'Failed to delete category', 500);\n }\n}\n"]}
|
package/dist/api/media.cjs
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
3
|
+
var chunkSUJT6LWH_cjs = require('../chunk-SUJT6LWH.cjs');
|
|
4
|
+
var chunkYTJQ426D_cjs = require('../chunk-YTJQ426D.cjs');
|
|
5
|
+
var chunkVWKVU3SE_cjs = require('../chunk-VWKVU3SE.cjs');
|
|
6
6
|
|
|
7
7
|
// src/api/media.ts
|
|
8
8
|
async function GET(request) {
|
|
9
9
|
try {
|
|
10
|
-
const authError =
|
|
10
|
+
const authError = await chunkYTJQ426D_cjs.requireAuth(request);
|
|
11
11
|
if (authError) return authError;
|
|
12
|
-
const params =
|
|
13
|
-
const result = await
|
|
14
|
-
page:
|
|
15
|
-
limit:
|
|
12
|
+
const params = chunkYTJQ426D_cjs.getSearchParams(request);
|
|
13
|
+
const result = await chunkVWKVU3SE_cjs.listMedia({
|
|
14
|
+
page: chunkYTJQ426D_cjs.parseIntParam(params.page, 1),
|
|
15
|
+
limit: chunkYTJQ426D_cjs.parseIntParam(params.limit, 20),
|
|
16
16
|
mimeType: params.mimeType
|
|
17
17
|
});
|
|
18
|
-
const page =
|
|
19
|
-
const limit =
|
|
20
|
-
return
|
|
18
|
+
const page = chunkYTJQ426D_cjs.parseIntParam(params.page, 1);
|
|
19
|
+
const limit = chunkYTJQ426D_cjs.parseIntParam(params.limit, 20);
|
|
20
|
+
return chunkYTJQ426D_cjs.jsonSuccess(result.media, {
|
|
21
21
|
page,
|
|
22
22
|
limit,
|
|
23
23
|
total: result.total,
|
|
@@ -25,22 +25,29 @@ async function GET(request) {
|
|
|
25
25
|
});
|
|
26
26
|
} catch (error) {
|
|
27
27
|
console.error("[nextblogkit] GET /media error:", error);
|
|
28
|
-
return
|
|
28
|
+
return chunkYTJQ426D_cjs.jsonError("INTERNAL_ERROR", "Failed to fetch media", 500);
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
async function POST(request) {
|
|
32
32
|
try {
|
|
33
|
-
const authError =
|
|
33
|
+
const authError = await chunkYTJQ426D_cjs.requireAuth(request);
|
|
34
34
|
if (authError) return authError;
|
|
35
35
|
const formData = await request.formData();
|
|
36
36
|
const file = formData.get("file");
|
|
37
37
|
if (!file) {
|
|
38
|
-
return
|
|
38
|
+
return chunkYTJQ426D_cjs.jsonError("MISSING_FILE", "File is required");
|
|
39
39
|
}
|
|
40
|
-
|
|
40
|
+
if (!chunkVWKVU3SE_cjs.isR2Configured()) {
|
|
41
|
+
return chunkYTJQ426D_cjs.jsonError(
|
|
42
|
+
"STORAGE_NOT_CONFIGURED",
|
|
43
|
+
"Image upload requires Cloudflare R2. Set R2 environment variables to enable uploads.",
|
|
44
|
+
503
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
const env = chunkVWKVU3SE_cjs.getEnvConfig();
|
|
41
48
|
const maxSize = 10 * 1024 * 1024;
|
|
42
49
|
if (file.size > maxSize) {
|
|
43
|
-
return
|
|
50
|
+
return chunkYTJQ426D_cjs.jsonError("FILE_TOO_LARGE", "File must be under 10MB");
|
|
44
51
|
}
|
|
45
52
|
const allowedTypes = [
|
|
46
53
|
"image/jpeg",
|
|
@@ -51,23 +58,23 @@ async function POST(request) {
|
|
|
51
58
|
"image/avif"
|
|
52
59
|
];
|
|
53
60
|
if (!allowedTypes.includes(file.type)) {
|
|
54
|
-
return
|
|
61
|
+
return chunkYTJQ426D_cjs.jsonError("INVALID_TYPE", `Allowed types: ${allowedTypes.join(", ")}`);
|
|
55
62
|
}
|
|
56
63
|
const buffer = Buffer.from(await file.arrayBuffer());
|
|
57
|
-
const storage = new
|
|
64
|
+
const storage = new chunkSUJT6LWH_cjs.R2StorageProvider();
|
|
58
65
|
const isImage = file.type.startsWith("image/") && file.type !== "image/svg+xml";
|
|
59
66
|
let uploadResult;
|
|
60
67
|
let width;
|
|
61
68
|
let height;
|
|
62
69
|
if (isImage) {
|
|
63
|
-
const processed = await
|
|
70
|
+
const processed = await chunkSUJT6LWH_cjs.processImage(buffer, file.name, storage);
|
|
64
71
|
uploadResult = processed.original;
|
|
65
72
|
width = processed.width;
|
|
66
73
|
height = processed.height;
|
|
67
74
|
} else {
|
|
68
75
|
uploadResult = await storage.upload(buffer, file.name, file.type);
|
|
69
76
|
}
|
|
70
|
-
const media = await
|
|
77
|
+
const media = await chunkVWKVU3SE_cjs.createMedia({
|
|
71
78
|
filename: uploadResult.key.split("/").pop() || file.name,
|
|
72
79
|
originalName: file.name,
|
|
73
80
|
mimeType: uploadResult.contentType,
|
|
@@ -80,29 +87,29 @@ async function POST(request) {
|
|
|
80
87
|
caption: formData.get("caption") || "",
|
|
81
88
|
createdAt: /* @__PURE__ */ new Date()
|
|
82
89
|
});
|
|
83
|
-
return
|
|
90
|
+
return chunkYTJQ426D_cjs.jsonSuccess(media, void 0, 201);
|
|
84
91
|
} catch (error) {
|
|
85
92
|
console.error("[nextblogkit] POST /media error:", error);
|
|
86
|
-
return
|
|
93
|
+
return chunkYTJQ426D_cjs.jsonError("INTERNAL_ERROR", "Failed to upload media", 500);
|
|
87
94
|
}
|
|
88
95
|
}
|
|
89
96
|
async function DELETE(request) {
|
|
90
97
|
try {
|
|
91
|
-
const authError =
|
|
98
|
+
const authError = await chunkYTJQ426D_cjs.requireAuth(request);
|
|
92
99
|
if (authError) return authError;
|
|
93
|
-
const params =
|
|
100
|
+
const params = chunkYTJQ426D_cjs.getSearchParams(request);
|
|
94
101
|
const id = params.id;
|
|
95
|
-
if (!id) return
|
|
96
|
-
const media = await
|
|
97
|
-
if (!media) return
|
|
98
|
-
const storage = new
|
|
102
|
+
if (!id) return chunkYTJQ426D_cjs.jsonError("MISSING_ID", "Media ID is required");
|
|
103
|
+
const media = await chunkVWKVU3SE_cjs.deleteMedia(id);
|
|
104
|
+
if (!media) return chunkYTJQ426D_cjs.jsonError("NOT_FOUND", "Media not found", 404);
|
|
105
|
+
const storage = new chunkSUJT6LWH_cjs.R2StorageProvider();
|
|
99
106
|
await storage.delete(media.r2Key).catch((err) => {
|
|
100
107
|
console.error("[nextblogkit] Failed to delete from R2:", err);
|
|
101
108
|
});
|
|
102
|
-
return
|
|
109
|
+
return chunkYTJQ426D_cjs.jsonSuccess({ deleted: true });
|
|
103
110
|
} catch (error) {
|
|
104
111
|
console.error("[nextblogkit] DELETE /media error:", error);
|
|
105
|
-
return
|
|
112
|
+
return chunkYTJQ426D_cjs.jsonError("INTERNAL_ERROR", "Failed to delete media", 500);
|
|
106
113
|
}
|
|
107
114
|
}
|
|
108
115
|
|
package/dist/api/media.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/api/media.ts"],"names":["requireAuth","getSearchParams","listMedia","parseIntParam","jsonSuccess","jsonError","getEnvConfig","R2StorageProvider","processImage","createMedia","deleteMedia"],"mappings":";;;;;;;AAYA,eAAsB,IAAI,OAAA,EAAkB;AAC1C,EAAA,IAAI;AACF,IAAA,MAAM,SAAA,
|
|
1
|
+
{"version":3,"sources":["../../src/api/media.ts"],"names":["requireAuth","getSearchParams","listMedia","parseIntParam","jsonSuccess","jsonError","isR2Configured","getEnvConfig","R2StorageProvider","processImage","createMedia","deleteMedia"],"mappings":"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","file":"media.cjs","sourcesContent":["import { createMedia, deleteMedia, listMedia } from '../lib/db';\nimport { R2StorageProvider } from '../lib/storage';\nimport { processImage } from '../lib/image';\nimport { getEnvConfig, isR2Configured } from '../lib/config';\nimport {\n jsonSuccess,\n jsonError,\n requireAuth,\n getSearchParams,\n parseIntParam,\n} from './middleware';\n\nexport async function GET(request: Request) {\n try {\n const authError = await requireAuth(request);\n if (authError) return authError;\n\n const params = getSearchParams(request);\n const result = await listMedia({\n page: parseIntParam(params.page, 1),\n limit: parseIntParam(params.limit, 20),\n mimeType: params.mimeType,\n });\n\n const page = parseIntParam(params.page, 1);\n const limit = parseIntParam(params.limit, 20);\n\n return jsonSuccess(result.media, {\n page,\n limit,\n total: result.total,\n totalPages: Math.ceil(result.total / limit),\n });\n } catch (error) {\n console.error('[nextblogkit] GET /media error:', error);\n return jsonError('INTERNAL_ERROR', 'Failed to fetch media', 500);\n }\n}\n\nexport async function POST(request: Request) {\n try {\n const authError = await requireAuth(request);\n if (authError) return authError;\n\n const formData = await request.formData();\n const file = formData.get('file') as File | null;\n\n if (!file) {\n return jsonError('MISSING_FILE', 'File is required');\n }\n\n if (!isR2Configured()) {\n return jsonError(\n 'STORAGE_NOT_CONFIGURED',\n 'Image upload requires Cloudflare R2. Set R2 environment variables to enable uploads.',\n 503\n );\n }\n\n const env = getEnvConfig();\n const maxSize = 10 * 1024 * 1024; // 10MB\n if (file.size > maxSize) {\n return jsonError('FILE_TOO_LARGE', 'File must be under 10MB');\n }\n\n const allowedTypes = [\n 'image/jpeg',\n 'image/png',\n 'image/gif',\n 'image/webp',\n 'image/svg+xml',\n 'image/avif',\n ];\n if (!allowedTypes.includes(file.type)) {\n return jsonError('INVALID_TYPE', `Allowed types: ${allowedTypes.join(', ')}`);\n }\n\n const buffer = Buffer.from(await file.arrayBuffer());\n const storage = new R2StorageProvider();\n\n const isImage = file.type.startsWith('image/') && file.type !== 'image/svg+xml';\n let uploadResult;\n let width: number | undefined;\n let height: number | undefined;\n\n if (isImage) {\n const processed = await processImage(buffer, file.name, storage);\n uploadResult = processed.original;\n width = processed.width;\n height = processed.height;\n } else {\n uploadResult = await storage.upload(buffer, file.name, file.type);\n }\n\n const media = await createMedia({\n filename: uploadResult.key.split('/').pop() || file.name,\n originalName: file.name,\n mimeType: uploadResult.contentType,\n size: uploadResult.size,\n width,\n height,\n r2Key: uploadResult.key,\n url: uploadResult.url,\n alt: (formData.get('alt') as string) || '',\n caption: (formData.get('caption') as string) || '',\n createdAt: new Date(),\n });\n\n return jsonSuccess(media, undefined, 201);\n } catch (error) {\n console.error('[nextblogkit] POST /media error:', error);\n return jsonError('INTERNAL_ERROR', 'Failed to upload media', 500);\n }\n}\n\nexport async function DELETE(request: Request) {\n try {\n const authError = await requireAuth(request);\n if (authError) return authError;\n\n const params = getSearchParams(request);\n const id = params.id;\n if (!id) return jsonError('MISSING_ID', 'Media ID is required');\n\n const media = await deleteMedia(id);\n if (!media) return jsonError('NOT_FOUND', 'Media not found', 404);\n\n // Delete from R2\n const storage = new R2StorageProvider();\n await storage.delete(media.r2Key).catch((err) => {\n console.error('[nextblogkit] Failed to delete from R2:', err);\n });\n\n return jsonSuccess({ deleted: true });\n } catch (error) {\n console.error('[nextblogkit] DELETE /media error:', error);\n return jsonError('INTERNAL_ERROR', 'Failed to delete media', 500);\n }\n}\n"]}
|
package/dist/api/media.d.cts
CHANGED
package/dist/api/media.d.ts
CHANGED
package/dist/api/media.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { R2StorageProvider, processImage } from '../chunk-
|
|
2
|
-
import { requireAuth, getSearchParams, parseIntParam, jsonSuccess, jsonError } from '../chunk-
|
|
3
|
-
import { listMedia, getEnvConfig, createMedia, deleteMedia } from '../chunk-
|
|
1
|
+
import { R2StorageProvider, processImage } from '../chunk-OWWWTTUT.js';
|
|
2
|
+
import { requireAuth, getSearchParams, parseIntParam, jsonSuccess, jsonError } from '../chunk-UMIBGO4S.js';
|
|
3
|
+
import { listMedia, isR2Configured, getEnvConfig, createMedia, deleteMedia } from '../chunk-JI2RK6KX.js';
|
|
4
4
|
|
|
5
5
|
// src/api/media.ts
|
|
6
6
|
async function GET(request) {
|
|
7
7
|
try {
|
|
8
|
-
const authError = requireAuth(request);
|
|
8
|
+
const authError = await requireAuth(request);
|
|
9
9
|
if (authError) return authError;
|
|
10
10
|
const params = getSearchParams(request);
|
|
11
11
|
const result = await listMedia({
|
|
@@ -28,13 +28,20 @@ async function GET(request) {
|
|
|
28
28
|
}
|
|
29
29
|
async function POST(request) {
|
|
30
30
|
try {
|
|
31
|
-
const authError = requireAuth(request);
|
|
31
|
+
const authError = await requireAuth(request);
|
|
32
32
|
if (authError) return authError;
|
|
33
33
|
const formData = await request.formData();
|
|
34
34
|
const file = formData.get("file");
|
|
35
35
|
if (!file) {
|
|
36
36
|
return jsonError("MISSING_FILE", "File is required");
|
|
37
37
|
}
|
|
38
|
+
if (!isR2Configured()) {
|
|
39
|
+
return jsonError(
|
|
40
|
+
"STORAGE_NOT_CONFIGURED",
|
|
41
|
+
"Image upload requires Cloudflare R2. Set R2 environment variables to enable uploads.",
|
|
42
|
+
503
|
|
43
|
+
);
|
|
44
|
+
}
|
|
38
45
|
const env = getEnvConfig();
|
|
39
46
|
const maxSize = 10 * 1024 * 1024;
|
|
40
47
|
if (file.size > maxSize) {
|
|
@@ -86,7 +93,7 @@ async function POST(request) {
|
|
|
86
93
|
}
|
|
87
94
|
async function DELETE(request) {
|
|
88
95
|
try {
|
|
89
|
-
const authError = requireAuth(request);
|
|
96
|
+
const authError = await requireAuth(request);
|
|
90
97
|
if (authError) return authError;
|
|
91
98
|
const params = getSearchParams(request);
|
|
92
99
|
const id = params.id;
|
package/dist/api/media.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/api/media.ts"],"names":[],"mappings":";;;;;AAYA,eAAsB,IAAI,OAAA,EAAkB;AAC1C,EAAA,IAAI;AACF,IAAA,MAAM,SAAA,GAAY,
|
|
1
|
+
{"version":3,"sources":["../../src/api/media.ts"],"names":[],"mappings":"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","file":"media.js","sourcesContent":["import { createMedia, deleteMedia, listMedia } from '../lib/db';\nimport { R2StorageProvider } from '../lib/storage';\nimport { processImage } from '../lib/image';\nimport { getEnvConfig, isR2Configured } from '../lib/config';\nimport {\n jsonSuccess,\n jsonError,\n requireAuth,\n getSearchParams,\n parseIntParam,\n} from './middleware';\n\nexport async function GET(request: Request) {\n try {\n const authError = await requireAuth(request);\n if (authError) return authError;\n\n const params = getSearchParams(request);\n const result = await listMedia({\n page: parseIntParam(params.page, 1),\n limit: parseIntParam(params.limit, 20),\n mimeType: params.mimeType,\n });\n\n const page = parseIntParam(params.page, 1);\n const limit = parseIntParam(params.limit, 20);\n\n return jsonSuccess(result.media, {\n page,\n limit,\n total: result.total,\n totalPages: Math.ceil(result.total / limit),\n });\n } catch (error) {\n console.error('[nextblogkit] GET /media error:', error);\n return jsonError('INTERNAL_ERROR', 'Failed to fetch media', 500);\n }\n}\n\nexport async function POST(request: Request) {\n try {\n const authError = await requireAuth(request);\n if (authError) return authError;\n\n const formData = await request.formData();\n const file = formData.get('file') as File | null;\n\n if (!file) {\n return jsonError('MISSING_FILE', 'File is required');\n }\n\n if (!isR2Configured()) {\n return jsonError(\n 'STORAGE_NOT_CONFIGURED',\n 'Image upload requires Cloudflare R2. Set R2 environment variables to enable uploads.',\n 503\n );\n }\n\n const env = getEnvConfig();\n const maxSize = 10 * 1024 * 1024; // 10MB\n if (file.size > maxSize) {\n return jsonError('FILE_TOO_LARGE', 'File must be under 10MB');\n }\n\n const allowedTypes = [\n 'image/jpeg',\n 'image/png',\n 'image/gif',\n 'image/webp',\n 'image/svg+xml',\n 'image/avif',\n ];\n if (!allowedTypes.includes(file.type)) {\n return jsonError('INVALID_TYPE', `Allowed types: ${allowedTypes.join(', ')}`);\n }\n\n const buffer = Buffer.from(await file.arrayBuffer());\n const storage = new R2StorageProvider();\n\n const isImage = file.type.startsWith('image/') && file.type !== 'image/svg+xml';\n let uploadResult;\n let width: number | undefined;\n let height: number | undefined;\n\n if (isImage) {\n const processed = await processImage(buffer, file.name, storage);\n uploadResult = processed.original;\n width = processed.width;\n height = processed.height;\n } else {\n uploadResult = await storage.upload(buffer, file.name, file.type);\n }\n\n const media = await createMedia({\n filename: uploadResult.key.split('/').pop() || file.name,\n originalName: file.name,\n mimeType: uploadResult.contentType,\n size: uploadResult.size,\n width,\n height,\n r2Key: uploadResult.key,\n url: uploadResult.url,\n alt: (formData.get('alt') as string) || '',\n caption: (formData.get('caption') as string) || '',\n createdAt: new Date(),\n });\n\n return jsonSuccess(media, undefined, 201);\n } catch (error) {\n console.error('[nextblogkit] POST /media error:', error);\n return jsonError('INTERNAL_ERROR', 'Failed to upload media', 500);\n }\n}\n\nexport async function DELETE(request: Request) {\n try {\n const authError = await requireAuth(request);\n if (authError) return authError;\n\n const params = getSearchParams(request);\n const id = params.id;\n if (!id) return jsonError('MISSING_ID', 'Media ID is required');\n\n const media = await deleteMedia(id);\n if (!media) return jsonError('NOT_FOUND', 'Media not found', 404);\n\n // Delete from R2\n const storage = new R2StorageProvider();\n await storage.delete(media.r2Key).catch((err) => {\n console.error('[nextblogkit] Failed to delete from R2:', err);\n });\n\n return jsonSuccess({ deleted: true });\n } catch (error) {\n console.error('[nextblogkit] DELETE /media error:', error);\n return jsonError('INTERNAL_ERROR', 'Failed to delete media', 500);\n }\n}\n"]}
|