@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.
Files changed (98) hide show
  1. package/bin/seolful-next.mjs +4 -0
  2. package/dist/api.d.ts +4 -0
  3. package/dist/api.d.ts.map +1 -0
  4. package/dist/api.js +43 -0
  5. package/dist/api.js.map +1 -0
  6. package/dist/cli/handshake.d.ts +17 -0
  7. package/dist/cli/handshake.d.ts.map +1 -0
  8. package/dist/cli/handshake.js +30 -0
  9. package/dist/cli/handshake.js.map +1 -0
  10. package/dist/cli/init.d.ts +2 -0
  11. package/dist/cli/init.d.ts.map +1 -0
  12. package/dist/cli/init.js +173 -0
  13. package/dist/cli/init.js.map +1 -0
  14. package/dist/cli/scaffold.d.ts +6 -0
  15. package/dist/cli/scaffold.d.ts.map +1 -0
  16. package/dist/cli/scaffold.js +101 -0
  17. package/dist/cli/scaffold.js.map +1 -0
  18. package/dist/config.d.ts +5 -0
  19. package/dist/config.d.ts.map +1 -0
  20. package/dist/config.js +44 -0
  21. package/dist/config.js.map +1 -0
  22. package/dist/crawler/analyze.d.ts +18 -0
  23. package/dist/crawler/analyze.d.ts.map +1 -0
  24. package/dist/crawler/analyze.js +114 -0
  25. package/dist/crawler/analyze.js.map +1 -0
  26. package/dist/crawler/crawl-service.d.ts +10 -0
  27. package/dist/crawler/crawl-service.d.ts.map +1 -0
  28. package/dist/crawler/crawl-service.js +79 -0
  29. package/dist/crawler/crawl-service.js.map +1 -0
  30. package/dist/crawler/discover.d.ts +5 -0
  31. package/dist/crawler/discover.d.ts.map +1 -0
  32. package/dist/crawler/discover.js +49 -0
  33. package/dist/crawler/discover.js.map +1 -0
  34. package/dist/handlers/audit-data.d.ts +3 -0
  35. package/dist/handlers/audit-data.d.ts.map +1 -0
  36. package/dist/handlers/audit-data.js +46 -0
  37. package/dist/handlers/audit-data.js.map +1 -0
  38. package/dist/handlers/crawl.d.ts +2 -0
  39. package/dist/handlers/crawl.d.ts.map +1 -0
  40. package/dist/handlers/crawl.js +11 -0
  41. package/dist/handlers/crawl.js.map +1 -0
  42. package/dist/handlers/demote-h1.d.ts +3 -0
  43. package/dist/handlers/demote-h1.d.ts.map +1 -0
  44. package/dist/handlers/demote-h1.js +28 -0
  45. package/dist/handlers/demote-h1.js.map +1 -0
  46. package/dist/handlers/update-ai-visibility.d.ts +3 -0
  47. package/dist/handlers/update-ai-visibility.d.ts.map +1 -0
  48. package/dist/handlers/update-ai-visibility.js +38 -0
  49. package/dist/handlers/update-ai-visibility.js.map +1 -0
  50. package/dist/handlers/update-seo.d.ts +3 -0
  51. package/dist/handlers/update-seo.d.ts.map +1 -0
  52. package/dist/handlers/update-seo.js +65 -0
  53. package/dist/handlers/update-seo.js.map +1 -0
  54. package/dist/helpers/generate-metadata.d.ts +3 -0
  55. package/dist/helpers/generate-metadata.d.ts.map +1 -0
  56. package/dist/helpers/generate-metadata.js +15 -0
  57. package/dist/helpers/generate-metadata.js.map +1 -0
  58. package/dist/helpers/get-page-seo.d.ts +3 -0
  59. package/dist/helpers/get-page-seo.d.ts.map +1 -0
  60. package/dist/helpers/get-page-seo.js +10 -0
  61. package/dist/helpers/get-page-seo.js.map +1 -0
  62. package/dist/helpers/seolful-h1.d.ts +10 -0
  63. package/dist/helpers/seolful-h1.d.ts.map +1 -0
  64. package/dist/helpers/seolful-h1.js +11 -0
  65. package/dist/helpers/seolful-h1.js.map +1 -0
  66. package/dist/helpers/seolful-image.d.ts +8 -0
  67. package/dist/helpers/seolful-image.d.ts.map +1 -0
  68. package/dist/helpers/seolful-image.js +8 -0
  69. package/dist/helpers/seolful-image.js.map +1 -0
  70. package/dist/helpers/seolful-schema.d.ts +6 -0
  71. package/dist/helpers/seolful-schema.d.ts.map +1 -0
  72. package/dist/helpers/seolful-schema.js +10 -0
  73. package/dist/helpers/seolful-schema.js.map +1 -0
  74. package/dist/index.d.ts +11 -0
  75. package/dist/index.d.ts.map +1 -0
  76. package/dist/index.js +13 -0
  77. package/dist/index.js.map +1 -0
  78. package/dist/middleware/validate-token.d.ts +8 -0
  79. package/dist/middleware/validate-token.d.ts.map +1 -0
  80. package/dist/middleware/validate-token.js +29 -0
  81. package/dist/middleware/validate-token.js.map +1 -0
  82. package/dist/storage/file-adapter.d.ts +24 -0
  83. package/dist/storage/file-adapter.d.ts.map +1 -0
  84. package/dist/storage/file-adapter.js +118 -0
  85. package/dist/storage/file-adapter.js.map +1 -0
  86. package/dist/storage/index.d.ts +4 -0
  87. package/dist/storage/index.d.ts.map +1 -0
  88. package/dist/storage/index.js +13 -0
  89. package/dist/storage/index.js.map +1 -0
  90. package/dist/storage/types.d.ts +2 -0
  91. package/dist/storage/types.d.ts.map +1 -0
  92. package/dist/storage/types.js +2 -0
  93. package/dist/storage/types.js.map +1 -0
  94. package/dist/types.d.ts +60 -0
  95. package/dist/types.d.ts.map +1 -0
  96. package/dist/types.js +35 -0
  97. package/dist/types.js.map +1 -0
  98. package/package.json +61 -0
@@ -0,0 +1,10 @@
1
+ interface CrawlResult {
2
+ crawled: number;
3
+ failed: number;
4
+ total: number;
5
+ firstError: string | null;
6
+ discoveryMethod: string;
7
+ }
8
+ export declare function crawlSite(): Promise<CrawlResult>;
9
+ export {};
10
+ //# sourceMappingURL=crawl-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crawl-service.d.ts","sourceRoot":"","sources":["../../src/crawler/crawl-service.ts"],"names":[],"mappings":"AASA,UAAU,WAAW;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,eAAe,EAAE,MAAM,CAAA;CACxB;AAMD,wBAAsB,SAAS,IAAI,OAAO,CAAC,WAAW,CAAC,CAmBtD"}
@@ -0,0 +1,79 @@
1
+ import { getConfig } from '../config.js';
2
+ import { getStorage } from '../storage/index.js';
3
+ import { discoverUrls } from './discover.js';
4
+ import { analyzePage } from './analyze.js';
5
+ const LOCK_TTL_MS = 300_000; // 5 minutes
6
+ const BATCH_SIZE = 20;
7
+ function sleep(ms) {
8
+ return new Promise((resolve) => setTimeout(resolve, ms));
9
+ }
10
+ export async function crawlSite() {
11
+ const storage = getStorage();
12
+ const locked = await storage.acquireLock('crawling', LOCK_TTL_MS);
13
+ if (!locked) {
14
+ return {
15
+ crawled: 0,
16
+ failed: 0,
17
+ total: 0,
18
+ firstError: 'A crawl is already in progress.',
19
+ discoveryMethod: 'skipped',
20
+ };
21
+ }
22
+ try {
23
+ return await doCrawl();
24
+ }
25
+ finally {
26
+ await storage.releaseLock('crawling');
27
+ }
28
+ }
29
+ async function doCrawl() {
30
+ const config = getConfig();
31
+ const storage = getStorage();
32
+ const delayMs = config.crawl?.delayMs ?? 300;
33
+ const timeout = (config.crawl?.timeout ?? 10) * 1000;
34
+ const { urls, method } = await discoverUrls();
35
+ const total = urls.length;
36
+ let crawled = 0;
37
+ let failed = 0;
38
+ let firstError = null;
39
+ const batch = [];
40
+ for (const url of urls) {
41
+ try {
42
+ const response = await fetch(url, { signal: AbortSignal.timeout(timeout) });
43
+ if (!response.ok) {
44
+ throw new Error(`HTTP ${response.status}`);
45
+ }
46
+ const html = await response.text();
47
+ const analysis = analyzePage(url, html);
48
+ batch.push({
49
+ ...analysis,
50
+ demoteH1: false,
51
+ crawledAt: new Date().toISOString(),
52
+ });
53
+ crawled++;
54
+ }
55
+ catch (e) {
56
+ const message = e instanceof Error ? e.message : String(e);
57
+ firstError ??= message;
58
+ failed++;
59
+ }
60
+ if (batch.length >= BATCH_SIZE) {
61
+ await storage.upsertPages(batch);
62
+ batch.length = 0;
63
+ }
64
+ if (delayMs > 0) {
65
+ await sleep(delayMs);
66
+ }
67
+ }
68
+ if (batch.length > 0) {
69
+ await storage.upsertPages(batch);
70
+ }
71
+ return {
72
+ crawled,
73
+ failed,
74
+ total,
75
+ firstError,
76
+ discoveryMethod: method,
77
+ };
78
+ }
79
+ //# sourceMappingURL=crawl-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crawl-service.js","sourceRoot":"","sources":["../../src/crawler/crawl-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare function discoverUrls(): Promise<{
2
+ urls: string[];
3
+ method: string;
4
+ }>;
5
+ //# sourceMappingURL=discover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover.d.ts","sourceRoot":"","sources":["../../src/crawler/discover.ts"],"names":[],"mappings":"AAEA,wBAAsB,YAAY,IAAI,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAkBhF"}
@@ -0,0 +1,49 @@
1
+ import { getConfig } from '../config.js';
2
+ export async function discoverUrls() {
3
+ const config = getConfig();
4
+ const siteUrl = config.siteUrl.replace(/\/$/, '');
5
+ const explicit = config.crawl?.urls ?? [];
6
+ if (explicit.length > 0) {
7
+ return { urls: explicit, method: 'config list' };
8
+ }
9
+ if (config.crawl?.useSitemap !== false) {
10
+ const sitemapUrl = config.crawl?.sitemapUrl ?? `${siteUrl}/sitemap.xml`;
11
+ const urls = await parseSitemap(sitemapUrl);
12
+ if (urls.length > 0) {
13
+ return { urls, method: 'sitemap.xml' };
14
+ }
15
+ }
16
+ return { urls: [siteUrl + '/'], method: 'root only' };
17
+ }
18
+ async function parseSitemap(url, depth = 0) {
19
+ if (depth > 3)
20
+ return [];
21
+ try {
22
+ const response = await fetch(url, { signal: AbortSignal.timeout(10_000) });
23
+ if (!response.ok)
24
+ return [];
25
+ const body = await response.text();
26
+ const urls = [];
27
+ // Extract <loc> from <url> entries
28
+ const locMatches = body.matchAll(/<url>\s*<loc>([^<]+)<\/loc>/gs);
29
+ for (const match of locMatches) {
30
+ const loc = match[1].trim();
31
+ if (loc)
32
+ urls.push(loc);
33
+ }
34
+ // Handle sitemap index — <sitemap><loc>...</loc></sitemap>
35
+ const sitemapMatches = body.matchAll(/<sitemap>\s*<loc>([^<]+)<\/loc>/gs);
36
+ for (const match of sitemapMatches) {
37
+ const loc = match[1].trim();
38
+ if (loc) {
39
+ const childUrls = await parseSitemap(loc, depth + 1);
40
+ urls.push(...childUrls);
41
+ }
42
+ }
43
+ return [...new Set(urls)];
44
+ }
45
+ catch {
46
+ return [];
47
+ }
48
+ }
49
+ //# sourceMappingURL=discover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover.js","sourceRoot":"","sources":["../../src/crawler/discover.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAExC,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAC1B,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IAEjD,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,EAAE,IAAI,IAAI,EAAE,CAAA;IACzC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,CAAA;IAClD,CAAC;IAED,IAAI,MAAM,CAAC,KAAK,EAAE,UAAU,KAAK,KAAK,EAAE,CAAC;QACvC,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,EAAE,UAAU,IAAI,GAAG,OAAO,cAAc,CAAA;QACvE,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,UAAU,CAAC,CAAA;QAC3C,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,CAAA;QACxC,CAAC;IACH,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,CAAC,OAAO,GAAG,GAAG,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAA;AACvD,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,GAAW,EAAE,KAAK,GAAG,CAAC;IAChD,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,EAAE,CAAA;IAExB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QAC1E,IAAI,CAAC,QAAQ,CAAC,EAAE;YAAE,OAAO,EAAE,CAAA;QAE3B,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;QAClC,MAAM,IAAI,GAAa,EAAE,CAAA;QAEzB,mCAAmC;QACnC,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,+BAA+B,CAAC,CAAA;QACjE,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;YAC/B,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;YAC3B,IAAI,GAAG;gBAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACzB,CAAC;QAED,2DAA2D;QAC3D,MAAM,cAAc,GAAG,IAAI,CAAC,QAAQ,CAAC,mCAAmC,CAAC,CAAA;QACzE,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;YACnC,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;YAC3B,IAAI,GAAG,EAAE,CAAC;gBACR,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE,KAAK,GAAG,CAAC,CAAC,CAAA;gBACpD,IAAI,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAA;YACzB,CAAC;QACH,CAAC;QAED,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAA;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { NextRequest } from 'next/server';
2
+ export declare function auditDataHandler(request: NextRequest): Promise<Response>;
3
+ //# sourceMappingURL=audit-data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-data.d.ts","sourceRoot":"","sources":["../../src/handlers/audit-data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAMzC,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CA6C9E"}
@@ -0,0 +1,46 @@
1
+ import { getStorage } from '../storage/index.js';
2
+ import { getPageRole } from '../types.js';
3
+ const PER_PAGE = 75;
4
+ export async function auditDataHandler(request) {
5
+ const url = new URL(request.url);
6
+ const page = Math.max(1, Number(url.searchParams.get('page') ?? 1));
7
+ const storage = getStorage();
8
+ const { data, total } = await storage.getAllPages(page, PER_PAGE);
9
+ const lastPage = Math.max(1, Math.ceil(total / PER_PAGE));
10
+ const items = data.map((p) => {
11
+ const missingAltImages = (p.imageAlts ?? []).filter((img) => img.missing);
12
+ return {
13
+ url: p.url,
14
+ post_id: p.id,
15
+ title: p.title,
16
+ meta_description: p.metaDescription,
17
+ page_role: getPageRole(p),
18
+ h1_in_content: p.h1Count > 1,
19
+ h1_text: p.h1Count > 1 ? p.h1Secondary : null,
20
+ word_count: p.wordCount,
21
+ images_missing_alt: missingAltImages.map((img) => ({ src: img.src })),
22
+ internal_links: p.internalLinkCount,
23
+ structured_data: p.structuredData ?? [],
24
+ is_noindexed: p.noindex,
25
+ canonical_url: p.canonicalUrl,
26
+ page_builder: null,
27
+ };
28
+ });
29
+ let connectorVersion = null;
30
+ try {
31
+ const pkg = await import('../../package.json', { with: { type: 'json' } });
32
+ connectorVersion = pkg.default.version;
33
+ }
34
+ catch {
35
+ // ignore
36
+ }
37
+ return Response.json({
38
+ data: items,
39
+ current_page: page,
40
+ last_page: lastPage,
41
+ per_page: PER_PAGE,
42
+ total,
43
+ connector_version: connectorVersion,
44
+ });
45
+ }
46
+ //# sourceMappingURL=audit-data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-data.js","sourceRoot":"","sources":["../../src/handlers/audit-data.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAEzC,MAAM,QAAQ,GAAG,EAAE,CAAA;AAEnB,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAAoB;IACzD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IAChC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAEnE,MAAM,OAAO,GAAG,UAAU,EAAE,CAAA;IAC5B,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;IACjE,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAA;IAEzD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAC3B,MAAM,gBAAgB,GAAG,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;QAEzE,OAAO;YACL,GAAG,EAAE,CAAC,CAAC,GAAG;YACV,OAAO,EAAE,CAAC,CAAC,EAAE;YACb,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,gBAAgB,EAAE,CAAC,CAAC,eAAe;YACnC,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;YACzB,aAAa,EAAE,CAAC,CAAC,OAAO,GAAG,CAAC;YAC5B,OAAO,EAAE,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI;YAC7C,UAAU,EAAE,CAAC,CAAC,SAAS;YACvB,kBAAkB,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;YACrE,cAAc,EAAE,CAAC,CAAC,iBAAiB;YACnC,eAAe,EAAE,CAAC,CAAC,cAAc,IAAI,EAAE;YACvC,YAAY,EAAE,CAAC,CAAC,OAAO;YACvB,aAAa,EAAE,CAAC,CAAC,YAAY;YAC7B,YAAY,EAAE,IAAI;SACnB,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,IAAI,gBAAgB,GAAkB,IAAI,CAAA;IAC1C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,oBAAoB,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,CAAA;QAC1E,gBAAgB,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,CAAA;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,SAAS;IACX,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,CAAC;QACnB,IAAI,EAAE,KAAK;QACX,YAAY,EAAE,IAAI;QAClB,SAAS,EAAE,QAAQ;QACnB,QAAQ,EAAE,QAAQ;QAClB,KAAK;QACL,iBAAiB,EAAE,gBAAgB;KACpC,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function crawlHandler(): Promise<Response>;
2
+ //# sourceMappingURL=crawl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crawl.d.ts","sourceRoot":"","sources":["../../src/handlers/crawl.ts"],"names":[],"mappings":"AAEA,wBAAsB,YAAY,IAAI,OAAO,CAAC,QAAQ,CAAC,CAStD"}
@@ -0,0 +1,11 @@
1
+ import { crawlSite } from '../crawler/crawl-service.js';
2
+ export async function crawlHandler() {
3
+ const result = await crawlSite();
4
+ return Response.json({
5
+ status: 'success',
6
+ crawled: result.crawled,
7
+ failed: result.failed,
8
+ total: result.total,
9
+ });
10
+ }
11
+ //# sourceMappingURL=crawl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crawl.js","sourceRoot":"","sources":["../../src/handlers/crawl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAA;AAEvD,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAA;IAEhC,OAAO,QAAQ,CAAC,IAAI,CAAC;QACnB,MAAM,EAAE,SAAS;QACjB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,KAAK,EAAE,MAAM,CAAC,KAAK;KACpB,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { NextRequest } from 'next/server';
2
+ export declare function demoteH1Handler(request: NextRequest): Promise<Response>;
3
+ //# sourceMappingURL=demote-h1.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"demote-h1.d.ts","sourceRoot":"","sources":["../../src/handlers/demote-h1.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAGzC,wBAAsB,eAAe,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CA8B7E"}
@@ -0,0 +1,28 @@
1
+ import { getStorage } from '../storage/index.js';
2
+ export async function demoteH1Handler(request) {
3
+ const data = (await request.json());
4
+ if (!data.post_id || typeof data.post_id !== 'number') {
5
+ return Response.json({ error: 'post_id is required' }, { status: 422 });
6
+ }
7
+ const storage = getStorage();
8
+ const page = await storage.getPageById(data.post_id);
9
+ if (!page) {
10
+ return Response.json({ error: 'Page not found' }, { status: 404 });
11
+ }
12
+ page.demoteH1 = true;
13
+ const { id: _, ...pageWithoutId } = page;
14
+ await storage.upsertPage(pageWithoutId);
15
+ try {
16
+ const { revalidatePath } = await import('next/cache');
17
+ const pathname = new URL(page.url).pathname;
18
+ revalidatePath(pathname);
19
+ }
20
+ catch {
21
+ // revalidatePath may not be available outside Next.js runtime
22
+ }
23
+ return Response.json({
24
+ status: 'success',
25
+ fields_updated: ['h1'],
26
+ });
27
+ }
28
+ //# sourceMappingURL=demote-h1.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"demote-h1.js","sourceRoot":"","sources":["../../src/handlers/demote-h1.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAEhD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAAoB;IACxD,MAAM,IAAI,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,EAAE,CAA4B,CAAA;IAE9D,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QACtD,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;IACzE,CAAC;IAED,MAAM,OAAO,GAAG,UAAU,EAAE,CAAA;IAC5B,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAEpD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;IACpE,CAAC;IAED,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAA;IACpB,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,aAAa,EAAE,GAAG,IAAI,CAAA;IACxC,MAAM,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAA;IAEvC,IAAI,CAAC;QACH,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAA;QACrD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAA;QAC3C,cAAc,CAAC,QAAQ,CAAC,CAAA;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,8DAA8D;IAChE,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,CAAC;QACnB,MAAM,EAAE,SAAS;QACjB,cAAc,EAAE,CAAC,IAAI,CAAC;KACvB,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { NextRequest } from 'next/server';
2
+ export declare function aiVisibilityHandler(request: NextRequest): Promise<Response>;
3
+ //# sourceMappingURL=update-ai-visibility.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-ai-visibility.d.ts","sourceRoot":"","sources":["../../src/handlers/update-ai-visibility.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAKzC,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAqCjF"}
@@ -0,0 +1,38 @@
1
+ import { writeFileSync, existsSync, mkdirSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { getStorage } from '../storage/index.js';
4
+ export async function aiVisibilityHandler(request) {
5
+ const data = (await request.json());
6
+ const updated = [];
7
+ if (data.llms_txt_content !== undefined) {
8
+ const publicDir = join(process.cwd(), 'public');
9
+ if (!existsSync(publicDir))
10
+ mkdirSync(publicDir, { recursive: true });
11
+ writeFileSync(join(publicDir, 'llms.txt'), String(data.llms_txt_content));
12
+ updated.push('llms_txt_content');
13
+ }
14
+ if (data.schema_jsonld !== undefined && data.post_id !== undefined) {
15
+ const storage = getStorage();
16
+ const page = await storage.getPageById(Number(data.post_id));
17
+ if (!page) {
18
+ return Response.json({ error: 'Page not found' }, { status: 404 });
19
+ }
20
+ page.structuredData = Array.isArray(data.schema_jsonld) ? data.schema_jsonld : [data.schema_jsonld];
21
+ const { id: _, ...pageWithoutId } = page;
22
+ await storage.upsertPage(pageWithoutId);
23
+ updated.push('schema_jsonld');
24
+ try {
25
+ const { revalidatePath } = await import('next/cache');
26
+ const pathname = new URL(page.url).pathname;
27
+ revalidatePath(pathname);
28
+ }
29
+ catch {
30
+ // revalidatePath may not be available outside Next.js runtime
31
+ }
32
+ }
33
+ return Response.json({
34
+ status: 'success',
35
+ fields_updated: updated,
36
+ });
37
+ }
38
+ //# sourceMappingURL=update-ai-visibility.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-ai-visibility.js","sourceRoot":"","sources":["../../src/handlers/update-ai-visibility.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAEhD,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,OAAoB;IAC5D,MAAM,IAAI,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,EAAE,CAA4B,CAAA;IAC9D,MAAM,OAAO,GAAa,EAAE,CAAA;IAE5B,IAAI,IAAI,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;QACxC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,CAAA;QAC/C,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QACrE,aAAa,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAA;QACzE,OAAO,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAA;IAClC,CAAC;IAED,IAAI,IAAI,CAAC,aAAa,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QACnE,MAAM,OAAO,GAAG,UAAU,EAAE,CAAA;QAC5B,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;QAE5D,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;QACpE,CAAC;QAED,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,aAAyB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,aAAuB,CAAC,CAAA;QACzH,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,aAAa,EAAE,GAAG,IAAI,CAAA;QACxC,MAAM,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAA;QACvC,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;QAE7B,IAAI,CAAC;YACH,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAA;YACrD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAA;YAC3C,cAAc,CAAC,QAAQ,CAAC,CAAA;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,8DAA8D;QAChE,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,CAAC;QACnB,MAAM,EAAE,SAAS;QACjB,cAAc,EAAE,OAAO;KACxB,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { NextRequest } from 'next/server';
2
+ export declare function updateSeoHandler(request: NextRequest): Promise<Response>;
3
+ //# sourceMappingURL=update-seo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-seo.d.ts","sourceRoot":"","sources":["../../src/handlers/update-seo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAqBzC,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAuD9E"}
@@ -0,0 +1,65 @@
1
+ import { getStorage } from '../storage/index.js';
2
+ const LABEL_PREFIXES = [
3
+ 'Meta Description:', 'Meta description:',
4
+ 'Title Tag:', 'Title tag:', 'Title:',
5
+ 'New Title:', 'New Meta Description:',
6
+ 'Revised Title:', 'Revised Meta Description:',
7
+ 'Updated Title:', 'Updated Meta Description:',
8
+ 'H1:', 'H1 Heading:', 'Alt Text:', 'Alt text:',
9
+ ];
10
+ function stripLabelPrefix(value) {
11
+ for (const prefix of LABEL_PREFIXES) {
12
+ if (value.startsWith(prefix)) {
13
+ return value.slice(prefix.length).trim();
14
+ }
15
+ }
16
+ return value;
17
+ }
18
+ export async function updateSeoHandler(request) {
19
+ const data = (await request.json());
20
+ if (!data.post_id || typeof data.post_id !== 'number') {
21
+ return Response.json({ error: 'post_id is required' }, { status: 422 });
22
+ }
23
+ const storage = getStorage();
24
+ const page = await storage.getPageById(data.post_id);
25
+ if (!page) {
26
+ return Response.json({ error: 'Page not found' }, { status: 404 });
27
+ }
28
+ const updated = [];
29
+ if (data.meta_title !== undefined) {
30
+ page.title = stripLabelPrefix(String(data.meta_title));
31
+ updated.push('meta_title');
32
+ }
33
+ if (data.meta_description !== undefined) {
34
+ page.metaDescription = stripLabelPrefix(String(data.meta_description));
35
+ updated.push('meta_description');
36
+ }
37
+ if (data.image_src !== undefined && data.image_alt !== undefined) {
38
+ const alts = page.imageAlts ?? [];
39
+ for (const img of alts) {
40
+ if (img.src === data.image_src) {
41
+ img.alt = String(data.image_alt);
42
+ img.missing = false;
43
+ break;
44
+ }
45
+ }
46
+ page.imageAlts = alts;
47
+ updated.push('image_alt');
48
+ }
49
+ const { id: _, ...pageWithoutId } = page;
50
+ await storage.upsertPage(pageWithoutId);
51
+ // Trigger ISR revalidation
52
+ try {
53
+ const { revalidatePath } = await import('next/cache');
54
+ const pathname = new URL(page.url).pathname;
55
+ revalidatePath(pathname);
56
+ }
57
+ catch {
58
+ // revalidatePath may not be available outside Next.js runtime
59
+ }
60
+ return Response.json({
61
+ status: 'success',
62
+ fields_updated: updated,
63
+ });
64
+ }
65
+ //# sourceMappingURL=update-seo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-seo.js","sourceRoot":"","sources":["../../src/handlers/update-seo.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Metadata } from 'next';
2
+ export declare function withSeolfulMetadata(pathname: string, base: Metadata): Promise<Metadata>;
3
+ //# sourceMappingURL=generate-metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-metadata.d.ts","sourceRoot":"","sources":["../../src/helpers/generate-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAA;AAGpC,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,QAAQ,GACb,OAAO,CAAC,QAAQ,CAAC,CAenB"}
@@ -0,0 +1,15 @@
1
+ import { getPageSeo } from './get-page-seo.js';
2
+ export async function withSeolfulMetadata(pathname, base) {
3
+ const seo = await getPageSeo(pathname);
4
+ if (!seo)
5
+ return base;
6
+ const merged = { ...base };
7
+ if (seo.title) {
8
+ merged.title = seo.title;
9
+ }
10
+ if (seo.metaDescription) {
11
+ merged.description = seo.metaDescription;
12
+ }
13
+ return merged;
14
+ }
15
+ //# sourceMappingURL=generate-metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-metadata.js","sourceRoot":"","sources":["../../src/helpers/generate-metadata.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,QAAgB,EAChB,IAAc;IAEd,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAA;IACtC,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAA;IAErB,MAAM,MAAM,GAAa,EAAE,GAAG,IAAI,EAAE,CAAA;IAEpC,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;QACd,MAAM,CAAC,KAAK,GAAG,GAAG,CAAC,KAAK,CAAA;IAC1B,CAAC;IAED,IAAI,GAAG,CAAC,eAAe,EAAE,CAAC;QACxB,MAAM,CAAC,WAAW,GAAG,GAAG,CAAC,eAAe,CAAA;IAC1C,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { SeoPage } from '../types.js';
2
+ export declare function getPageSeo(pathname: string): Promise<SeoPage | null>;
3
+ //# sourceMappingURL=get-page-seo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-page-seo.d.ts","sourceRoot":"","sources":["../../src/helpers/get-page-seo.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAE1C,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAO1E"}
@@ -0,0 +1,10 @@
1
+ import { getStorage } from '../storage/index.js';
2
+ import { getConfig } from '../config.js';
3
+ export async function getPageSeo(pathname) {
4
+ const config = getConfig();
5
+ const siteUrl = config.siteUrl.replace(/\/$/, '');
6
+ const fullUrl = siteUrl + pathname;
7
+ const storage = getStorage();
8
+ return storage.getPageByUrl(fullUrl);
9
+ }
10
+ //# sourceMappingURL=get-page-seo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-page-seo.js","sourceRoot":"","sources":["../../src/helpers/get-page-seo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAGxC,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAgB;IAC/C,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAC1B,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IACjD,MAAM,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAA;IAElC,MAAM,OAAO,GAAG,UAAU,EAAE,CAAA;IAC5B,OAAO,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,CAAA;AACtC,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { ReactNode } from 'react';
2
+ interface SeolfulH1Props {
3
+ pathname: string;
4
+ children: ReactNode;
5
+ className?: string;
6
+ isSecondary?: boolean;
7
+ }
8
+ export declare function SeolfulH1({ pathname, children, className, isSecondary, }: SeolfulH1Props): Promise<import("react").JSX.Element>;
9
+ export {};
10
+ //# sourceMappingURL=seolful-h1.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seolful-h1.d.ts","sourceRoot":"","sources":["../../src/helpers/seolful-h1.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,UAAU,cAAc;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,SAAS,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAED,wBAAsB,SAAS,CAAC,EAC9B,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,WAAmB,GACpB,EAAE,cAAc,wCAShB"}
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { getPageSeo } from './get-page-seo.js';
3
+ export async function SeolfulH1({ pathname, children, className, isSecondary = false, }) {
4
+ const seo = await getPageSeo(pathname);
5
+ const shouldDemote = isSecondary && seo?.demoteH1;
6
+ if (shouldDemote) {
7
+ return _jsx("h2", { className: className, children: children });
8
+ }
9
+ return _jsx("h1", { className: className, children: children });
10
+ }
11
+ //# sourceMappingURL=seolful-h1.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seolful-h1.js","sourceRoot":"","sources":["../../src/helpers/seolful-h1.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAU9C,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,EAC9B,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,WAAW,GAAG,KAAK,GACJ;IACf,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAA;IACtC,MAAM,YAAY,GAAG,WAAW,IAAI,GAAG,EAAE,QAAQ,CAAA;IAEjD,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,aAAI,SAAS,EAAE,SAAS,YAAG,QAAQ,GAAM,CAAA;IAClD,CAAC;IAED,OAAO,aAAI,SAAS,EAAE,SAAS,YAAG,QAAQ,GAAM,CAAA;AAClD,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { type ImageProps } from 'next/image';
2
+ import type { ImageAlt } from '../types.js';
3
+ type SeolfulImageProps = ImageProps & {
4
+ seolfulAlts?: ImageAlt[];
5
+ };
6
+ export declare function SeolfulImage({ src, seolfulAlts, alt, ...props }: SeolfulImageProps): import("react").JSX.Element;
7
+ export {};
8
+ //# sourceMappingURL=seolful-image.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seolful-image.d.ts","sourceRoot":"","sources":["../../src/helpers/seolful-image.tsx"],"names":[],"mappings":"AAEA,OAAc,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAA;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAE3C,KAAK,iBAAiB,GAAG,UAAU,GAAG;IACpC,WAAW,CAAC,EAAE,QAAQ,EAAE,CAAA;CACzB,CAAA;AAED,wBAAgB,YAAY,CAAC,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,GAAG,KAAK,EAAE,EAAE,iBAAiB,+BAGlF"}
@@ -0,0 +1,8 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import Image from 'next/image';
4
+ export function SeolfulImage({ src, seolfulAlts, alt, ...props }) {
5
+ const resolved = seolfulAlts?.find((a) => a.src === String(src))?.alt ?? alt;
6
+ return _jsx(Image, { src: src, alt: resolved ?? '', ...props });
7
+ }
8
+ //# sourceMappingURL=seolful-image.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seolful-image.js","sourceRoot":"","sources":["../../src/helpers/seolful-image.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,KAA0B,MAAM,YAAY,CAAA;AAOnD,MAAM,UAAU,YAAY,CAAC,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,GAAG,KAAK,EAAqB;IACjF,MAAM,QAAQ,GAAG,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,IAAI,GAAG,CAAA;IAC5E,OAAO,KAAC,KAAK,IAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,IAAI,EAAE,KAAM,KAAK,GAAI,CAAA;AAC5D,CAAC"}
@@ -0,0 +1,6 @@
1
+ interface SeolfulSchemaProps {
2
+ pathname: string;
3
+ }
4
+ export declare function SeolfulSchema({ pathname }: SeolfulSchemaProps): Promise<import("react").JSX.Element | null>;
5
+ export {};
6
+ //# sourceMappingURL=seolful-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seolful-schema.d.ts","sourceRoot":"","sources":["../../src/helpers/seolful-schema.tsx"],"names":[],"mappings":"AAEA,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,wBAAsB,aAAa,CAAC,EAAE,QAAQ,EAAE,EAAE,kBAAkB,+CAiBnE"}
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { getPageSeo } from './get-page-seo.js';
3
+ export async function SeolfulSchema({ pathname }) {
4
+ const seo = await getPageSeo(pathname);
5
+ const schemas = seo?.structuredData ?? [];
6
+ if (schemas.length === 0)
7
+ return null;
8
+ return (_jsx(_Fragment, { children: schemas.map((schema, i) => (_jsx("script", { type: "application/ld+json", dangerouslySetInnerHTML: { __html: JSON.stringify(schema) } }, i))) }));
9
+ }
10
+ //# sourceMappingURL=seolful-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seolful-schema.js","sourceRoot":"","sources":["../../src/helpers/seolful-schema.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAM9C,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,EAAE,QAAQ,EAAsB;IAClE,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAA;IACtC,MAAM,OAAO,GAAG,GAAG,EAAE,cAAc,IAAI,EAAE,CAAA;IAEzC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IAErC,OAAO,CACL,4BACG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,CAC1B,iBAEE,IAAI,EAAC,qBAAqB,EAC1B,uBAAuB,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,IAFtD,CAAC,CAGN,CACH,CAAC,GACD,CACJ,CAAA;AACH,CAAC"}
@@ -0,0 +1,11 @@
1
+ export type { SeolfulConfig, SeolfulConnection, SeoPage, ImageAlt, StorageAdapter, } from './types.js';
2
+ export { getPageRole } from './types.js';
3
+ export { getConfig, getStorageDir, clearConfigCache } from './config.js';
4
+ export { getStorage, setStorage } from './storage/index.js';
5
+ export { FileAdapter } from './storage/file-adapter.js';
6
+ export { getPageSeo } from './helpers/get-page-seo.js';
7
+ export { withSeolfulMetadata } from './helpers/generate-metadata.js';
8
+ export { SeolfulImage } from './helpers/seolful-image.js';
9
+ export { SeolfulSchema } from './helpers/seolful-schema.js';
10
+ export { SeolfulH1 } from './helpers/seolful-h1.js';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,OAAO,EACP,QAAQ,EACR,cAAc,GACf,MAAM,YAAY,CAAA;AAEnB,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAGxC,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAGxE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAGvD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ export { getPageRole } from './types.js';
2
+ // Config
3
+ export { getConfig, getStorageDir, clearConfigCache } from './config.js';
4
+ // Storage
5
+ export { getStorage, setStorage } from './storage/index.js';
6
+ export { FileAdapter } from './storage/file-adapter.js';
7
+ // Helpers — user-facing
8
+ export { getPageSeo } from './helpers/get-page-seo.js';
9
+ export { withSeolfulMetadata } from './helpers/generate-metadata.js';
10
+ export { SeolfulImage } from './helpers/seolful-image.js';
11
+ export { SeolfulSchema } from './helpers/seolful-schema.js';
12
+ export { SeolfulH1 } from './helpers/seolful-h1.js';
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAExC,SAAS;AACT,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAExE,UAAU;AACV,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAEvD,wBAAwB;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA"}
@@ -0,0 +1,8 @@
1
+ export declare function validateToken(headers: Headers): Promise<{
2
+ valid: true;
3
+ } | {
4
+ valid: false;
5
+ status: number;
6
+ error: string;
7
+ }>;
8
+ //# sourceMappingURL=validate-token.d.ts.map