@seo-console/package 1.0.3 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +111 -38
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -29,31 +29,37 @@ NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
29
29
 
30
30
  The package will automatically detect and use Supabase if these are set.
31
31
 
32
- ### Step 2: Create API Routes
32
+ ### Step 2: Create API Routes (REQUIRED - This is why you're getting 404 errors!)
33
33
 
34
- Create the following API route in your Next.js app:
34
+ **⚠️ CRITICAL:** The package does NOT include API routes. You MUST create them in your Next.js app. The 404 error you're seeing means the API route doesn't exist yet.
35
35
 
36
- **`app/api/seo-records/route.ts`:**
36
+ **Create `app/api/seo-records/route.ts`:**
37
37
 
38
38
  ```typescript
39
39
  import { NextRequest, NextResponse } from "next/server";
40
- import {
41
- getSEORecords,
42
- getSEORecordByRoute,
43
- createSEORecord,
44
- updateSEORecord,
45
- deleteSEORecord
46
- } from "@seo-console/package/server";
40
+ import { detectStorageConfig, createStorageAdapter } from "@seo-console/package";
41
+ import { createSEORecordSchema } from "@seo-console/package/server";
47
42
 
48
43
  // GET - Fetch all SEO records
49
44
  export async function GET() {
50
45
  try {
51
- const result = await getSEORecords();
52
- if (!result.success) {
53
- return NextResponse.json({ error: result.error?.message }, { status: 500 });
46
+ // Auto-detect storage type (file or Supabase)
47
+ const config = detectStorageConfig();
48
+ const storage = createStorageAdapter(config);
49
+
50
+ // Check if storage is available
51
+ const isAvailable = await storage.isAvailable();
52
+ if (!isAvailable) {
53
+ return NextResponse.json(
54
+ { error: "Storage not available" },
55
+ { status: 500 }
56
+ );
54
57
  }
55
- return NextResponse.json({ data: result.data || [] });
58
+
59
+ const records = await storage.getRecords();
60
+ return NextResponse.json({ data: records || [] });
56
61
  } catch (error) {
62
+ console.error("Error fetching SEO records:", error);
57
63
  return NextResponse.json(
58
64
  { error: error instanceof Error ? error.message : "Failed to fetch records" },
59
65
  { status: 500 }
@@ -65,48 +71,111 @@ export async function GET() {
65
71
  export async function POST(request: NextRequest) {
66
72
  try {
67
73
  const body = await request.json();
68
- const result = await createSEORecord(body);
69
- if (!result.success) {
70
- return NextResponse.json({ error: result.error?.message }, { status: 500 });
74
+
75
+ // Validate the request body
76
+ const validated = createSEORecordSchema.parse(body);
77
+
78
+ // Auto-detect storage type
79
+ const config = detectStorageConfig();
80
+ const storage = createStorageAdapter(config);
81
+
82
+ const record = await storage.createRecord(validated);
83
+ return NextResponse.json({ data: record }, { status: 201 });
84
+ } catch (error) {
85
+ console.error("Error creating SEO record:", error);
86
+ if (error instanceof Error) {
87
+ return NextResponse.json(
88
+ { error: error.message },
89
+ { status: 400 }
90
+ );
71
91
  }
72
- return NextResponse.json({ data: result.data });
92
+ return NextResponse.json(
93
+ { error: "Invalid request" },
94
+ { status: 400 }
95
+ );
96
+ }
97
+ }
98
+ ```
99
+
100
+ **Create `app/api/seo-records/[id]/route.ts`:**
101
+
102
+ ```typescript
103
+ import { NextRequest, NextResponse } from "next/server";
104
+ import { detectStorageConfig, createStorageAdapter } from "@seo-console/package";
105
+ import { updateSEORecordSchema } from "@seo-console/package/server";
106
+
107
+ interface RouteParams {
108
+ params: Promise<{ id: string }>;
109
+ }
110
+
111
+ // GET - Get a single SEO record
112
+ export async function GET(
113
+ request: NextRequest,
114
+ { params }: RouteParams
115
+ ) {
116
+ try {
117
+ const { id } = await params;
118
+ const config = detectStorageConfig();
119
+ const storage = createStorageAdapter(config);
120
+
121
+ const record = await storage.getRecordById(id);
122
+
123
+ if (!record) {
124
+ return NextResponse.json(
125
+ { error: "Record not found" },
126
+ { status: 404 }
127
+ );
128
+ }
129
+
130
+ return NextResponse.json({ data: record });
73
131
  } catch (error) {
74
132
  return NextResponse.json(
75
- { error: error instanceof Error ? error.message : "Failed to create record" },
133
+ { error: error instanceof Error ? error.message : "Failed to fetch record" },
76
134
  { status: 500 }
77
135
  );
78
136
  }
79
137
  }
80
138
 
81
- // PUT - Update an existing SEO record
82
- export async function PUT(request: NextRequest) {
139
+ // PATCH - Update an SEO record
140
+ export async function PATCH(
141
+ request: NextRequest,
142
+ { params }: RouteParams
143
+ ) {
83
144
  try {
145
+ const { id } = await params;
84
146
  const body = await request.json();
85
- const result = await updateSEORecord(body);
86
- if (!result.success) {
87
- return NextResponse.json({ error: result.error?.message }, { status: 500 });
88
- }
89
- return NextResponse.json({ data: result.data });
147
+
148
+ const validated = updateSEORecordSchema.parse({ ...body, id });
149
+ const config = detectStorageConfig();
150
+ const storage = createStorageAdapter(config);
151
+
152
+ const record = await storage.updateRecord(validated);
153
+ return NextResponse.json({ data: record });
90
154
  } catch (error) {
155
+ if (error instanceof Error) {
156
+ return NextResponse.json(
157
+ { error: error.message },
158
+ { status: 400 }
159
+ );
160
+ }
91
161
  return NextResponse.json(
92
- { error: error instanceof Error ? error.message : "Failed to update record" },
93
- { status: 500 }
162
+ { error: "Invalid request" },
163
+ { status: 400 }
94
164
  );
95
165
  }
96
166
  }
97
167
 
98
168
  // DELETE - Delete an SEO record
99
- export async function DELETE(request: NextRequest) {
169
+ export async function DELETE(
170
+ request: NextRequest,
171
+ { params }: RouteParams
172
+ ) {
100
173
  try {
101
- const { searchParams } = new URL(request.url);
102
- const id = searchParams.get("id");
103
- if (!id) {
104
- return NextResponse.json({ error: "ID is required" }, { status: 400 });
105
- }
106
- const result = await deleteSEORecord(id);
107
- if (!result.success) {
108
- return NextResponse.json({ error: result.error?.message }, { status: 500 });
109
- }
174
+ const { id } = await params;
175
+ const config = detectStorageConfig();
176
+ const storage = createStorageAdapter(config);
177
+
178
+ await storage.deleteRecord(id);
110
179
  return NextResponse.json({ success: true });
111
180
  } catch (error) {
112
181
  return NextResponse.json(
@@ -117,6 +186,10 @@ export async function DELETE(request: NextRequest) {
117
186
  }
118
187
  ```
119
188
 
189
+ > **Important:** These API routes use the storage adapter system, which automatically works with:
190
+ > - **File storage** (default) - if no Supabase credentials are set
191
+ > - **Supabase** - if `NEXT_PUBLIC_SUPABASE_URL` and `NEXT_PUBLIC_SUPABASE_ANON_KEY` are set
192
+
120
193
  ### Step 3: Add Admin Pages
121
194
 
122
195
  Create the admin SEO section in your Next.js app. This will be accessible as a new tab in your admin area.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seo-console/package",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "SEO validation and management system for Next.js applications",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",