@seo-console/package 1.0.3 → 1.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.md CHANGED
@@ -12,7 +12,7 @@ npm install @seo-console/package
12
12
 
13
13
  ### Step 1: Configure Storage (Optional)
14
14
 
15
- The package uses **file storage by default** (no database required). SEO records are stored in `seo-records.json`.
15
+ The package uses **file storage** (no database required). SEO records are stored in `seo-records.json` in your project root.
16
16
 
17
17
  To customize the storage location, add to your `.env.local`:
18
18
 
@@ -20,40 +20,39 @@ To customize the storage location, add to your `.env.local`:
20
20
  SEO_CONSOLE_STORAGE_PATH=./data/seo-records.json
21
21
  ```
22
22
 
23
- **Optional:** If you prefer Supabase, set these environment variables:
23
+ That's it! No database setup needed.
24
24
 
25
- ```env
26
- NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
27
- NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
28
- ```
29
-
30
- The package will automatically detect and use Supabase if these are set.
25
+ ### Step 2: Create API Routes (REQUIRED - This is why you're getting 404 errors!)
31
26
 
32
- ### Step 2: Create API Routes
27
+ **⚠️ 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.
33
28
 
34
- Create the following API route in your Next.js app:
35
-
36
- **`app/api/seo-records/route.ts`:**
29
+ **Create `app/api/seo-records/route.ts`:**
37
30
 
38
31
  ```typescript
39
32
  import { NextRequest, NextResponse } from "next/server";
40
- import {
41
- getSEORecords,
42
- getSEORecordByRoute,
43
- createSEORecord,
44
- updateSEORecord,
45
- deleteSEORecord
46
- } from "@seo-console/package/server";
33
+ import { detectStorageConfig, createStorageAdapter } from "@seo-console/package";
34
+ import { createSEORecordSchema } from "@seo-console/package/server";
47
35
 
48
36
  // GET - Fetch all SEO records
49
37
  export async function GET() {
50
38
  try {
51
- const result = await getSEORecords();
52
- if (!result.success) {
53
- return NextResponse.json({ error: result.error?.message }, { status: 500 });
39
+ // Get file storage adapter
40
+ const config = detectStorageConfig();
41
+ const storage = createStorageAdapter(config);
42
+
43
+ // Check if storage is available
44
+ const isAvailable = await storage.isAvailable();
45
+ if (!isAvailable) {
46
+ return NextResponse.json(
47
+ { error: "Storage not available" },
48
+ { status: 500 }
49
+ );
54
50
  }
55
- return NextResponse.json({ data: result.data || [] });
51
+
52
+ const records = await storage.getRecords();
53
+ return NextResponse.json({ data: records || [] });
56
54
  } catch (error) {
55
+ console.error("Error fetching SEO records:", error);
57
56
  return NextResponse.json(
58
57
  { error: error instanceof Error ? error.message : "Failed to fetch records" },
59
58
  { status: 500 }
@@ -65,48 +64,111 @@ export async function GET() {
65
64
  export async function POST(request: NextRequest) {
66
65
  try {
67
66
  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 });
67
+
68
+ // Validate the request body
69
+ const validated = createSEORecordSchema.parse(body);
70
+
71
+ // Auto-detect storage type
72
+ const config = detectStorageConfig();
73
+ const storage = createStorageAdapter(config);
74
+
75
+ const record = await storage.createRecord(validated);
76
+ return NextResponse.json({ data: record }, { status: 201 });
77
+ } catch (error) {
78
+ console.error("Error creating SEO record:", error);
79
+ if (error instanceof Error) {
80
+ return NextResponse.json(
81
+ { error: error.message },
82
+ { status: 400 }
83
+ );
84
+ }
85
+ return NextResponse.json(
86
+ { error: "Invalid request" },
87
+ { status: 400 }
88
+ );
89
+ }
90
+ }
91
+ ```
92
+
93
+ **Create `app/api/seo-records/[id]/route.ts`:**
94
+
95
+ ```typescript
96
+ import { NextRequest, NextResponse } from "next/server";
97
+ import { detectStorageConfig, createStorageAdapter } from "@seo-console/package";
98
+ import { updateSEORecordSchema } from "@seo-console/package/server";
99
+
100
+ interface RouteParams {
101
+ params: Promise<{ id: string }>;
102
+ }
103
+
104
+ // GET - Get a single SEO record
105
+ export async function GET(
106
+ request: NextRequest,
107
+ { params }: RouteParams
108
+ ) {
109
+ try {
110
+ const { id } = await params;
111
+ const config = detectStorageConfig();
112
+ const storage = createStorageAdapter(config);
113
+
114
+ const record = await storage.getRecordById(id);
115
+
116
+ if (!record) {
117
+ return NextResponse.json(
118
+ { error: "Record not found" },
119
+ { status: 404 }
120
+ );
71
121
  }
72
- return NextResponse.json({ data: result.data });
122
+
123
+ return NextResponse.json({ data: record });
73
124
  } catch (error) {
74
125
  return NextResponse.json(
75
- { error: error instanceof Error ? error.message : "Failed to create record" },
126
+ { error: error instanceof Error ? error.message : "Failed to fetch record" },
76
127
  { status: 500 }
77
128
  );
78
129
  }
79
130
  }
80
131
 
81
- // PUT - Update an existing SEO record
82
- export async function PUT(request: NextRequest) {
132
+ // PATCH - Update an SEO record
133
+ export async function PATCH(
134
+ request: NextRequest,
135
+ { params }: RouteParams
136
+ ) {
83
137
  try {
138
+ const { id } = await params;
84
139
  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 });
140
+
141
+ const validated = updateSEORecordSchema.parse({ ...body, id });
142
+ const config = detectStorageConfig();
143
+ const storage = createStorageAdapter(config);
144
+
145
+ const record = await storage.updateRecord(validated);
146
+ return NextResponse.json({ data: record });
90
147
  } catch (error) {
148
+ if (error instanceof Error) {
149
+ return NextResponse.json(
150
+ { error: error.message },
151
+ { status: 400 }
152
+ );
153
+ }
91
154
  return NextResponse.json(
92
- { error: error instanceof Error ? error.message : "Failed to update record" },
93
- { status: 500 }
155
+ { error: "Invalid request" },
156
+ { status: 400 }
94
157
  );
95
158
  }
96
159
  }
97
160
 
98
161
  // DELETE - Delete an SEO record
99
- export async function DELETE(request: NextRequest) {
162
+ export async function DELETE(
163
+ request: NextRequest,
164
+ { params }: RouteParams
165
+ ) {
100
166
  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
- }
167
+ const { id } = await params;
168
+ const config = detectStorageConfig();
169
+ const storage = createStorageAdapter(config);
170
+
171
+ await storage.deleteRecord(id);
110
172
  return NextResponse.json({ success: true });
111
173
  } catch (error) {
112
174
  return NextResponse.json(
@@ -117,6 +179,8 @@ export async function DELETE(request: NextRequest) {
117
179
  }
118
180
  ```
119
181
 
182
+ > **Important:** These API routes use file storage. SEO records are stored in `seo-records.json` in your project root (or the path specified in `SEO_CONSOLE_STORAGE_PATH`).
183
+
120
184
  ### Step 3: Add Admin Pages
121
185
 
122
186
  Create the admin SEO section in your Next.js app. This will be accessible as a new tab in your admin area.
@@ -271,15 +335,28 @@ const metadata = await useGenerateMetadata({
271
335
  });
272
336
  ```
273
337
 
274
- ### Server-Side Functions
338
+ ### Storage Functions
339
+
340
+ ```typescript
341
+ import {
342
+ detectStorageConfig,
343
+ createStorageAdapter
344
+ } from "@seo-console/package";
345
+
346
+ // Get storage adapter (uses file storage)
347
+ const config = detectStorageConfig();
348
+ const storage = createStorageAdapter(config);
349
+
350
+ // Use storage methods
351
+ const records = await storage.getRecords();
352
+ const record = await storage.getRecordByRoute("/about");
353
+ await storage.createRecord({ routePath: "/contact", title: "Contact" });
354
+ ```
355
+
356
+ ### Other Server-Side Functions
275
357
 
276
358
  ```typescript
277
359
  import {
278
- getSEORecords,
279
- getSEORecordByRoute,
280
- createSEORecord,
281
- updateSEORecord,
282
- deleteSEORecord,
283
360
  generateSitemapFromRecords,
284
361
  generateRobotsTxt,
285
362
  discoverNextJSRoutes,
@@ -287,21 +364,14 @@ import {
287
364
  } from "@seo-console/package/server";
288
365
  ```
289
366
 
290
- ## Storage Backends
291
-
292
- ### File Storage (Default)
293
-
294
- - **No database required** - stores data in a JSON file
295
- - **Perfect for small to medium sites** - simple and fast
296
- - **File location**: `seo-records.json` (configurable via `SEO_CONSOLE_STORAGE_PATH`)
297
- - **Automatic**: Works out of the box with no configuration
367
+ ## Storage
298
368
 
299
- ### Supabase Storage (Optional)
369
+ The package uses **file storage** - SEO records are stored in a JSON file (`seo-records.json` by default).
300
370
 
301
- - **Database-backed** - uses Supabase PostgreSQL
302
- - **Better for larger sites** - scalable and supports concurrent access
303
- - **Requires**: Supabase project and migrations
304
- - **Auto-detected**: If `NEXT_PUBLIC_SUPABASE_URL` and `NEXT_PUBLIC_SUPABASE_ANON_KEY` are set
371
+ - **No database required** - works out of the box
372
+ - **Simple and fast** - perfect for most sites
373
+ - **Version controlled** - the JSON file can be committed to git
374
+ - **Configurable** - set `SEO_CONSOLE_STORAGE_PATH` to customize the file location
305
375
 
306
376
  ## License
307
377