@seolful/nextjs-connector 1.0.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/bin/seolful-next.mjs +4 -0
- package/dist/api.d.ts +4 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +43 -0
- package/dist/api.js.map +1 -0
- package/dist/cli/handshake.d.ts +17 -0
- package/dist/cli/handshake.d.ts.map +1 -0
- package/dist/cli/handshake.js +30 -0
- package/dist/cli/handshake.js.map +1 -0
- package/dist/cli/init.d.ts +2 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +173 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/scaffold.d.ts +6 -0
- package/dist/cli/scaffold.d.ts.map +1 -0
- package/dist/cli/scaffold.js +101 -0
- package/dist/cli/scaffold.js.map +1 -0
- package/dist/config.d.ts +5 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +44 -0
- package/dist/config.js.map +1 -0
- package/dist/crawler/analyze.d.ts +18 -0
- package/dist/crawler/analyze.d.ts.map +1 -0
- package/dist/crawler/analyze.js +114 -0
- package/dist/crawler/analyze.js.map +1 -0
- package/dist/crawler/crawl-service.d.ts +10 -0
- package/dist/crawler/crawl-service.d.ts.map +1 -0
- package/dist/crawler/crawl-service.js +79 -0
- package/dist/crawler/crawl-service.js.map +1 -0
- package/dist/crawler/discover.d.ts +5 -0
- package/dist/crawler/discover.d.ts.map +1 -0
- package/dist/crawler/discover.js +49 -0
- package/dist/crawler/discover.js.map +1 -0
- package/dist/handlers/audit-data.d.ts +3 -0
- package/dist/handlers/audit-data.d.ts.map +1 -0
- package/dist/handlers/audit-data.js +46 -0
- package/dist/handlers/audit-data.js.map +1 -0
- package/dist/handlers/crawl.d.ts +2 -0
- package/dist/handlers/crawl.d.ts.map +1 -0
- package/dist/handlers/crawl.js +11 -0
- package/dist/handlers/crawl.js.map +1 -0
- package/dist/handlers/demote-h1.d.ts +3 -0
- package/dist/handlers/demote-h1.d.ts.map +1 -0
- package/dist/handlers/demote-h1.js +28 -0
- package/dist/handlers/demote-h1.js.map +1 -0
- package/dist/handlers/update-ai-visibility.d.ts +3 -0
- package/dist/handlers/update-ai-visibility.d.ts.map +1 -0
- package/dist/handlers/update-ai-visibility.js +38 -0
- package/dist/handlers/update-ai-visibility.js.map +1 -0
- package/dist/handlers/update-seo.d.ts +3 -0
- package/dist/handlers/update-seo.d.ts.map +1 -0
- package/dist/handlers/update-seo.js +65 -0
- package/dist/handlers/update-seo.js.map +1 -0
- package/dist/helpers/generate-metadata.d.ts +3 -0
- package/dist/helpers/generate-metadata.d.ts.map +1 -0
- package/dist/helpers/generate-metadata.js +15 -0
- package/dist/helpers/generate-metadata.js.map +1 -0
- package/dist/helpers/get-page-seo.d.ts +3 -0
- package/dist/helpers/get-page-seo.d.ts.map +1 -0
- package/dist/helpers/get-page-seo.js +10 -0
- package/dist/helpers/get-page-seo.js.map +1 -0
- package/dist/helpers/seolful-h1.d.ts +10 -0
- package/dist/helpers/seolful-h1.d.ts.map +1 -0
- package/dist/helpers/seolful-h1.js +11 -0
- package/dist/helpers/seolful-h1.js.map +1 -0
- package/dist/helpers/seolful-image.d.ts +8 -0
- package/dist/helpers/seolful-image.d.ts.map +1 -0
- package/dist/helpers/seolful-image.js +8 -0
- package/dist/helpers/seolful-image.js.map +1 -0
- package/dist/helpers/seolful-schema.d.ts +6 -0
- package/dist/helpers/seolful-schema.d.ts.map +1 -0
- package/dist/helpers/seolful-schema.js +10 -0
- package/dist/helpers/seolful-schema.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/validate-token.d.ts +8 -0
- package/dist/middleware/validate-token.d.ts.map +1 -0
- package/dist/middleware/validate-token.js +29 -0
- package/dist/middleware/validate-token.js.map +1 -0
- package/dist/storage/file-adapter.d.ts +24 -0
- package/dist/storage/file-adapter.d.ts.map +1 -0
- package/dist/storage/file-adapter.js +118 -0
- package/dist/storage/file-adapter.js.map +1 -0
- package/dist/storage/index.d.ts +4 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +13 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/types.d.ts +2 -0
- package/dist/storage/types.d.ts.map +1 -0
- package/dist/storage/types.js +2 -0
- package/dist/storage/types.js.map +1 -0
- package/dist/types.d.ts +60 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +35 -0
- package/dist/types.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-token.d.ts","sourceRoot":"","sources":["../../src/middleware/validate-token.ts"],"names":[],"mappings":"AAGA,wBAAsB,aAAa,CACjC,OAAO,EAAE,OAAO,GACf,OAAO,CAAC;IAAE,KAAK,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CA+B5E"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import bcrypt from 'bcryptjs';
|
|
2
|
+
import { getStorage } from '../storage/index.js';
|
|
3
|
+
export async function validateToken(headers) {
|
|
4
|
+
const token = headers.get('x-seolful-token');
|
|
5
|
+
const clientId = headers.get('x-seolful-client-id');
|
|
6
|
+
if (!token || !clientId) {
|
|
7
|
+
return { valid: false, status: 401, error: 'Unauthorized' };
|
|
8
|
+
}
|
|
9
|
+
// In Vercel/serverless, env vars are the source of truth for auth
|
|
10
|
+
const envClientId = process.env.SEOLFUL_CLIENT_ID;
|
|
11
|
+
const envToken = process.env.SEOLFUL_TOKEN;
|
|
12
|
+
if (envClientId && envToken) {
|
|
13
|
+
if (clientId === envClientId && token === envToken) {
|
|
14
|
+
return { valid: true };
|
|
15
|
+
}
|
|
16
|
+
return { valid: false, status: 401, error: 'Unauthorized' };
|
|
17
|
+
}
|
|
18
|
+
const storage = getStorage();
|
|
19
|
+
const connection = await storage.getConnection();
|
|
20
|
+
if (!connection || connection.clientId !== clientId) {
|
|
21
|
+
return { valid: false, status: 401, error: 'Unauthorized' };
|
|
22
|
+
}
|
|
23
|
+
const match = await bcrypt.compare(token, connection.tokenHash);
|
|
24
|
+
if (!match) {
|
|
25
|
+
return { valid: false, status: 401, error: 'Unauthorized' };
|
|
26
|
+
}
|
|
27
|
+
return { valid: true };
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=validate-token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-token.js","sourceRoot":"","sources":["../../src/middleware/validate-token.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,UAAU,CAAA;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAEhD,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAAgB;IAEhB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAA;IAC5C,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAA;IAEnD,IAAI,CAAC,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC;QACxB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,cAAc,EAAE,CAAA;IAC7D,CAAC;IAED,kEAAkE;IAClE,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAA;IACjD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAA;IAC1C,IAAI,WAAW,IAAI,QAAQ,EAAE,CAAC;QAC5B,IAAI,QAAQ,KAAK,WAAW,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;YACnD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAA;QACxB,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,cAAc,EAAE,CAAA;IAC7D,CAAC;IAED,MAAM,OAAO,GAAG,UAAU,EAAE,CAAA;IAC5B,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,aAAa,EAAE,CAAA;IAEhD,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACpD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,cAAc,EAAE,CAAA;IAC7D,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,UAAU,CAAC,SAAS,CAAC,CAAA;IAC/D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,cAAc,EAAE,CAAA;IAC7D,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAA;AACxB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { StorageAdapter, SeolfulConnection, SeoPage } from '../types.js';
|
|
2
|
+
export declare class FileAdapter implements StorageAdapter {
|
|
3
|
+
private dir;
|
|
4
|
+
constructor(storageDir: string);
|
|
5
|
+
private path;
|
|
6
|
+
private readJson;
|
|
7
|
+
private writeJson;
|
|
8
|
+
getConnection(): Promise<SeolfulConnection | null>;
|
|
9
|
+
saveConnection(conn: SeolfulConnection): Promise<void>;
|
|
10
|
+
deleteConnection(): Promise<void>;
|
|
11
|
+
private loadPages;
|
|
12
|
+
private savePages;
|
|
13
|
+
getPageByUrl(url: string): Promise<SeoPage | null>;
|
|
14
|
+
getPageById(id: number): Promise<SeoPage | null>;
|
|
15
|
+
getAllPages(page: number, perPage: number): Promise<{
|
|
16
|
+
data: SeoPage[];
|
|
17
|
+
total: number;
|
|
18
|
+
}>;
|
|
19
|
+
upsertPage(page: Omit<SeoPage, 'id'>): Promise<SeoPage>;
|
|
20
|
+
upsertPages(pages: Array<Omit<SeoPage, 'id'>>): Promise<void>;
|
|
21
|
+
acquireLock(key: string, ttlMs: number): Promise<boolean>;
|
|
22
|
+
releaseLock(key: string): Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=file-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-adapter.d.ts","sourceRoot":"","sources":["../../src/storage/file-adapter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAW7E,qBAAa,WAAY,YAAW,cAAc;IAChD,OAAO,CAAC,GAAG,CAAQ;gBAEP,UAAU,EAAE,MAAM;IAO9B,OAAO,CAAC,IAAI;IAIZ,OAAO,CAAC,QAAQ;IAUhB,OAAO,CAAC,SAAS;IAWX,aAAa,IAAI,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAMlD,cAAc,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAItD,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAOvC,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,SAAS;IAIX,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAKlD,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAKhD,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IASvF,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IAiBvD,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB7D,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAazD,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAK9C"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, renameSync, unlinkSync } from 'node:fs';
|
|
2
|
+
import { join, dirname } from 'node:path';
|
|
3
|
+
import { randomUUID } from 'node:crypto';
|
|
4
|
+
export class FileAdapter {
|
|
5
|
+
dir;
|
|
6
|
+
constructor(storageDir) {
|
|
7
|
+
this.dir = storageDir;
|
|
8
|
+
if (!existsSync(this.dir)) {
|
|
9
|
+
mkdirSync(this.dir, { recursive: true });
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
path(file) {
|
|
13
|
+
return join(this.dir, file);
|
|
14
|
+
}
|
|
15
|
+
readJson(file, fallback) {
|
|
16
|
+
const p = this.path(file);
|
|
17
|
+
if (!existsSync(p))
|
|
18
|
+
return fallback;
|
|
19
|
+
try {
|
|
20
|
+
return JSON.parse(readFileSync(p, 'utf8'));
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return fallback;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
writeJson(file, data) {
|
|
27
|
+
const p = this.path(file);
|
|
28
|
+
const dir = dirname(p);
|
|
29
|
+
if (!existsSync(dir))
|
|
30
|
+
mkdirSync(dir, { recursive: true });
|
|
31
|
+
const tmp = p + '.' + randomUUID() + '.tmp';
|
|
32
|
+
writeFileSync(tmp, JSON.stringify(data, null, 2));
|
|
33
|
+
renameSync(tmp, p);
|
|
34
|
+
}
|
|
35
|
+
// -- Connection --
|
|
36
|
+
async getConnection() {
|
|
37
|
+
const conn = this.readJson('connection.json', null);
|
|
38
|
+
if (!conn?.clientId)
|
|
39
|
+
return null;
|
|
40
|
+
return conn;
|
|
41
|
+
}
|
|
42
|
+
async saveConnection(conn) {
|
|
43
|
+
this.writeJson('connection.json', conn);
|
|
44
|
+
}
|
|
45
|
+
async deleteConnection() {
|
|
46
|
+
const p = this.path('connection.json');
|
|
47
|
+
if (existsSync(p))
|
|
48
|
+
unlinkSync(p);
|
|
49
|
+
}
|
|
50
|
+
// -- Pages --
|
|
51
|
+
loadPages() {
|
|
52
|
+
return this.readJson('pages.json', { nextId: 1, pages: [] });
|
|
53
|
+
}
|
|
54
|
+
savePages(store) {
|
|
55
|
+
this.writeJson('pages.json', store);
|
|
56
|
+
}
|
|
57
|
+
async getPageByUrl(url) {
|
|
58
|
+
const store = this.loadPages();
|
|
59
|
+
return store.pages.find((p) => p.url === url) ?? null;
|
|
60
|
+
}
|
|
61
|
+
async getPageById(id) {
|
|
62
|
+
const store = this.loadPages();
|
|
63
|
+
return store.pages.find((p) => p.id === id) ?? null;
|
|
64
|
+
}
|
|
65
|
+
async getAllPages(page, perPage) {
|
|
66
|
+
const store = this.loadPages();
|
|
67
|
+
const start = (page - 1) * perPage;
|
|
68
|
+
return {
|
|
69
|
+
data: store.pages.slice(start, start + perPage),
|
|
70
|
+
total: store.pages.length,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
async upsertPage(page) {
|
|
74
|
+
const store = this.loadPages();
|
|
75
|
+
const idx = store.pages.findIndex((p) => p.url === page.url);
|
|
76
|
+
if (idx >= 0) {
|
|
77
|
+
const existing = store.pages[idx];
|
|
78
|
+
store.pages[idx] = { ...existing, ...page, id: existing.id };
|
|
79
|
+
this.savePages(store);
|
|
80
|
+
return store.pages[idx];
|
|
81
|
+
}
|
|
82
|
+
const newPage = { ...page, id: store.nextId++ };
|
|
83
|
+
store.pages.push(newPage);
|
|
84
|
+
this.savePages(store);
|
|
85
|
+
return newPage;
|
|
86
|
+
}
|
|
87
|
+
async upsertPages(pages) {
|
|
88
|
+
const store = this.loadPages();
|
|
89
|
+
for (const page of pages) {
|
|
90
|
+
const idx = store.pages.findIndex((p) => p.url === page.url);
|
|
91
|
+
if (idx >= 0) {
|
|
92
|
+
const existing = store.pages[idx];
|
|
93
|
+
store.pages[idx] = { ...existing, ...page, id: existing.id };
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
store.pages.push({ ...page, id: store.nextId++ });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
this.savePages(store);
|
|
100
|
+
}
|
|
101
|
+
// -- Locks --
|
|
102
|
+
async acquireLock(key, ttlMs) {
|
|
103
|
+
const locks = this.readJson('locks.json', {});
|
|
104
|
+
const existing = locks[key];
|
|
105
|
+
if (existing && existing.expiresAt > Date.now()) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
locks[key] = { expiresAt: Date.now() + ttlMs };
|
|
109
|
+
this.writeJson('locks.json', locks);
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
async releaseLock(key) {
|
|
113
|
+
const locks = this.readJson('locks.json', {});
|
|
114
|
+
delete locks[key];
|
|
115
|
+
this.writeJson('locks.json', locks);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=file-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-adapter.js","sourceRoot":"","sources":["../../src/storage/file-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAIjD,wBAAgB,UAAU,IAAI,cAAc,CAK3C;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAExD"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { getStorageDir } from '../config.js';
|
|
2
|
+
import { FileAdapter } from './file-adapter.js';
|
|
3
|
+
let instance = null;
|
|
4
|
+
export function getStorage() {
|
|
5
|
+
if (!instance) {
|
|
6
|
+
instance = new FileAdapter(getStorageDir());
|
|
7
|
+
}
|
|
8
|
+
return instance;
|
|
9
|
+
}
|
|
10
|
+
export function setStorage(adapter) {
|
|
11
|
+
instance = adapter;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAG/C,IAAI,QAAQ,GAA0B,IAAI,CAAA;AAE1C,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,QAAQ,GAAG,IAAI,WAAW,CAAC,aAAa,EAAE,CAAC,CAAA;IAC7C,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,OAAuB;IAChD,QAAQ,GAAG,OAAO,CAAA;AACpB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/storage/types.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/storage/types.ts"],"names":[],"mappings":""}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export interface SeolfulConfig {
|
|
2
|
+
appUrl: string;
|
|
3
|
+
siteUrl: string;
|
|
4
|
+
siteName: string;
|
|
5
|
+
connectionKey?: string;
|
|
6
|
+
storageDir?: string;
|
|
7
|
+
crawl?: {
|
|
8
|
+
urls?: string[];
|
|
9
|
+
sitemapUrl?: string;
|
|
10
|
+
useSitemap?: boolean;
|
|
11
|
+
delayMs?: number;
|
|
12
|
+
timeout?: number;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export interface SeolfulConnection {
|
|
16
|
+
clientId: string;
|
|
17
|
+
tokenHash: string;
|
|
18
|
+
siteUrl: string;
|
|
19
|
+
connectedAt: string;
|
|
20
|
+
}
|
|
21
|
+
export interface ImageAlt {
|
|
22
|
+
src: string;
|
|
23
|
+
alt: string;
|
|
24
|
+
missing: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface SeoPage {
|
|
27
|
+
id: number;
|
|
28
|
+
url: string;
|
|
29
|
+
slug: string;
|
|
30
|
+
title: string | null;
|
|
31
|
+
metaDescription: string | null;
|
|
32
|
+
h1: string | null;
|
|
33
|
+
h1Count: number;
|
|
34
|
+
h1Secondary: string | null;
|
|
35
|
+
demoteH1: boolean;
|
|
36
|
+
wordCount: number;
|
|
37
|
+
imageAlts: ImageAlt[];
|
|
38
|
+
internalLinkCount: number;
|
|
39
|
+
structuredData: object[];
|
|
40
|
+
noindex: boolean;
|
|
41
|
+
canonicalUrl: string | null;
|
|
42
|
+
crawledAt: string | null;
|
|
43
|
+
}
|
|
44
|
+
export interface StorageAdapter {
|
|
45
|
+
getConnection(): Promise<SeolfulConnection | null>;
|
|
46
|
+
saveConnection(conn: SeolfulConnection): Promise<void>;
|
|
47
|
+
deleteConnection(): Promise<void>;
|
|
48
|
+
getPageByUrl(url: string): Promise<SeoPage | null>;
|
|
49
|
+
getPageById(id: number): Promise<SeoPage | null>;
|
|
50
|
+
getAllPages(page: number, perPage: number): Promise<{
|
|
51
|
+
data: SeoPage[];
|
|
52
|
+
total: number;
|
|
53
|
+
}>;
|
|
54
|
+
upsertPage(page: Omit<SeoPage, 'id'>): Promise<SeoPage>;
|
|
55
|
+
upsertPages(pages: Array<Omit<SeoPage, 'id'>>): Promise<void>;
|
|
56
|
+
acquireLock(key: string, ttlMs: number): Promise<boolean>;
|
|
57
|
+
releaseLock(key: string): Promise<void>;
|
|
58
|
+
}
|
|
59
|
+
export declare function getPageRole(page: SeoPage): 'content' | 'legal' | 'utility';
|
|
60
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE;QACN,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;QACf,UAAU,CAAC,EAAE,MAAM,CAAA;QACnB,UAAU,CAAC,EAAE,OAAO,CAAA;QACpB,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,OAAO,CAAC,EAAE,MAAM,CAAA;KACjB,CAAA;CACF;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAA;IACV,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,EAAE,EAAE,MAAM,GAAG,IAAI,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,QAAQ,EAAE,OAAO,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,QAAQ,EAAE,CAAA;IACrB,iBAAiB,EAAE,MAAM,CAAA;IACzB,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,OAAO,EAAE,OAAO,CAAA;IAChB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,aAAa,IAAI,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAA;IAClD,cAAc,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACtD,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IAEjC,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAA;IAClD,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAA;IAChD,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACvF,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACvD,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAE7D,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACzD,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACxC;AAyBD,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAW1E"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const LEGAL_EXACT = new Set([
|
|
2
|
+
'privacy', 'terms', 'tos', 'cookie', 'cookies', 'disclaimer',
|
|
3
|
+
'legal', 'refund', 'copyright', 'cancellation',
|
|
4
|
+
]);
|
|
5
|
+
const LEGAL_SUBSTRING = [
|
|
6
|
+
'privacy-policy', 'cookie-policy', 'terms-of-service', 'terms-and-conditions',
|
|
7
|
+
'return-policy', 'refund-policy', 'cancellation-policy',
|
|
8
|
+
'gdpr', 'dmca', 'accessibility',
|
|
9
|
+
];
|
|
10
|
+
const UTILITY_EXACT = new Set([
|
|
11
|
+
'contact', 'contact-us', 'about', 'about-us', 'faq', 'faqs', 'search', 'sitemap',
|
|
12
|
+
]);
|
|
13
|
+
const UTILITY_SUBSTRING = [
|
|
14
|
+
'cart', 'checkout', 'my-account', 'wishlist', 'order-received',
|
|
15
|
+
'login', 'log-in', 'register', 'sign-in', 'sign-up', 'signup',
|
|
16
|
+
'lost-password', 'reset-password', 'forgot-password',
|
|
17
|
+
'thank-you', 'thankyou',
|
|
18
|
+
'coming-soon', 'maintenance', '404',
|
|
19
|
+
];
|
|
20
|
+
export function getPageRole(page) {
|
|
21
|
+
const slug = (page.slug ?? '').toLowerCase().replace(/^\/|\/$/g, '');
|
|
22
|
+
const lastSegment = slug.split('/').pop() ?? '';
|
|
23
|
+
if (LEGAL_EXACT.has(lastSegment))
|
|
24
|
+
return 'legal';
|
|
25
|
+
if (LEGAL_SUBSTRING.some((p) => lastSegment.includes(p)))
|
|
26
|
+
return 'legal';
|
|
27
|
+
if (UTILITY_EXACT.has(lastSegment))
|
|
28
|
+
return 'utility';
|
|
29
|
+
if (UTILITY_SUBSTRING.some((p) => lastSegment.includes(p)))
|
|
30
|
+
return 'utility';
|
|
31
|
+
if ((page.wordCount ?? 0) < 50)
|
|
32
|
+
return 'utility';
|
|
33
|
+
return 'content';
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AA8DA,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC;IAC1B,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY;IAC5D,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc;CAC/C,CAAC,CAAA;AAEF,MAAM,eAAe,GAAG;IACtB,gBAAgB,EAAE,eAAe,EAAE,kBAAkB,EAAE,sBAAsB;IAC7E,eAAe,EAAE,eAAe,EAAE,qBAAqB;IACvD,MAAM,EAAE,MAAM,EAAE,eAAe;CAChC,CAAA;AAED,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC;IAC5B,SAAS,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS;CACjF,CAAC,CAAA;AAEF,MAAM,iBAAiB,GAAG;IACxB,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,gBAAgB;IAC9D,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ;IAC7D,eAAe,EAAE,gBAAgB,EAAE,iBAAiB;IACpD,WAAW,EAAE,UAAU;IACvB,aAAa,EAAE,aAAa,EAAE,KAAK;CACpC,CAAA;AAED,MAAM,UAAU,WAAW,CAAC,IAAa;IACvC,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;IACpE,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAA;IAE/C,IAAI,WAAW,CAAC,GAAG,CAAC,WAAW,CAAC;QAAE,OAAO,OAAO,CAAA;IAChD,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAAE,OAAO,OAAO,CAAA;IACxE,IAAI,aAAa,CAAC,GAAG,CAAC,WAAW,CAAC;QAAE,OAAO,SAAS,CAAA;IACpD,IAAI,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAAE,OAAO,SAAS,CAAA;IAC5E,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC,GAAG,EAAE;QAAE,OAAO,SAAS,CAAA;IAEhD,OAAO,SAAS,CAAA;AAClB,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@seolful/nextjs-connector",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Seolful SEO connector for Next.js — self-sufficient site auditing, fix publishing, and metadata injection",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./api": {
|
|
14
|
+
"types": "./dist/api.d.ts",
|
|
15
|
+
"import": "./dist/api.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"bin": {
|
|
19
|
+
"seolful-next": "./bin/seolful-next.mjs"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist/",
|
|
23
|
+
"bin/"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsc",
|
|
27
|
+
"dev": "tsc --watch"
|
|
28
|
+
},
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=18"
|
|
31
|
+
},
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"next": ">=14.0.0",
|
|
34
|
+
"react": ">=18.0.0"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"bcryptjs": "^2.4.3",
|
|
38
|
+
"node-html-parser": "^6.1.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/bcryptjs": "^2.4.6",
|
|
42
|
+
"@types/node": "^20",
|
|
43
|
+
"@types/react": "^19",
|
|
44
|
+
"next": "^15.0.0",
|
|
45
|
+
"react": "^19.0.0",
|
|
46
|
+
"typescript": "^5"
|
|
47
|
+
},
|
|
48
|
+
"keywords": [
|
|
49
|
+
"seolful",
|
|
50
|
+
"seo",
|
|
51
|
+
"nextjs",
|
|
52
|
+
"next",
|
|
53
|
+
"audit",
|
|
54
|
+
"metadata",
|
|
55
|
+
"connector"
|
|
56
|
+
],
|
|
57
|
+
"license": "MIT",
|
|
58
|
+
"publishConfig": {
|
|
59
|
+
"access": "public"
|
|
60
|
+
}
|
|
61
|
+
}
|