@seo-console/package 1.1.2 → 1.2.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/dist/index.mjs CHANGED
@@ -3578,82 +3578,6 @@ function ValidationDashboard() {
3578
3578
  ] });
3579
3579
  }
3580
3580
 
3581
- // src/lib/route-discovery.ts
3582
- import { join } from "path";
3583
- import { glob } from "glob";
3584
- async function discoverNextJSRoutes(appDir = "app", rootDir = process.cwd()) {
3585
- const routes = [];
3586
- const appPath = join(rootDir, appDir);
3587
- try {
3588
- const pageFiles = await glob("**/page.tsx", {
3589
- cwd: appPath,
3590
- absolute: false,
3591
- ignore: ["**/node_modules/**", "**/.next/**"]
3592
- });
3593
- for (const file of pageFiles) {
3594
- const route = fileToRoute(file, appDir);
3595
- if (route) {
3596
- routes.push(route);
3597
- }
3598
- }
3599
- } catch (error) {
3600
- console.error("Error discovering routes:", error);
3601
- }
3602
- return routes;
3603
- }
3604
- function fileToRoute(filePath, appDir) {
3605
- let routePath = filePath.replace(/^app\//, "").replace(/\/page\.tsx$/, "").replace(/\/page$/, "");
3606
- if (routePath === "page" || routePath === "") {
3607
- routePath = "/";
3608
- } else {
3609
- routePath = "/" + routePath;
3610
- }
3611
- const segments = routePath.split("/").filter(Boolean);
3612
- const params = [];
3613
- let isDynamic = false;
3614
- let isCatchAll = false;
3615
- for (const segment of segments) {
3616
- if (segment.startsWith("[...") && segment.endsWith("]")) {
3617
- const param = segment.slice(4, -1);
3618
- params.push(param);
3619
- isDynamic = true;
3620
- isCatchAll = true;
3621
- } else if (segment.startsWith("[") && segment.endsWith("]")) {
3622
- const param = segment.slice(1, -1);
3623
- params.push(param);
3624
- isDynamic = true;
3625
- }
3626
- }
3627
- return {
3628
- routePath,
3629
- filePath: join(appDir, filePath),
3630
- isDynamic,
3631
- isCatchAll,
3632
- params
3633
- };
3634
- }
3635
- function generateExamplePaths(route, count = 3) {
3636
- if (!route.isDynamic) {
3637
- return [route.routePath];
3638
- }
3639
- const examples = [];
3640
- const segments = route.routePath.split("/").filter(Boolean);
3641
- for (let i = 0; i < count; i++) {
3642
- let examplePath = "";
3643
- for (const segment of segments) {
3644
- if (segment.startsWith("[...")) {
3645
- examplePath += `/example-${i}-part-1/example-${i}-part-2`;
3646
- } else if (segment.startsWith("[")) {
3647
- examplePath += `/example-${i}`;
3648
- } else {
3649
- examplePath += `/${segment}`;
3650
- }
3651
- }
3652
- examples.push(examplePath || "/");
3653
- }
3654
- return examples;
3655
- }
3656
-
3657
3581
  // src/lib/metadata-extractor.ts
3658
3582
  import * as cheerio from "cheerio";
3659
3583
  function extractMetadataFromHTML(html, baseUrl) {
@@ -3682,23 +3606,6 @@ function extractMetadataFromHTML(html, baseUrl) {
3682
3606
  }
3683
3607
  return metadata;
3684
3608
  }
3685
- async function extractMetadataFromURL(url) {
3686
- try {
3687
- const response = await fetch(url, {
3688
- headers: {
3689
- "User-Agent": "SEO-Console/1.0"
3690
- }
3691
- });
3692
- if (!response.ok) {
3693
- throw new Error(`Failed to fetch ${url}: ${response.statusText}`);
3694
- }
3695
- const html = await response.text();
3696
- return extractMetadataFromHTML(html, url);
3697
- } catch (error) {
3698
- console.error(`Error extracting metadata from ${url}:`, error);
3699
- return {};
3700
- }
3701
- }
3702
3609
  function metadataToSEORecord(metadata, routePath, userId = "extracted") {
3703
3610
  return {
3704
3611
  userId,
@@ -3716,20 +3623,6 @@ function metadataToSEORecord(metadata, routePath, userId = "extracted") {
3716
3623
  validationStatus: "pending"
3717
3624
  };
3718
3625
  }
3719
- async function crawlSiteForSEO(baseUrl, routes) {
3720
- const results = /* @__PURE__ */ new Map();
3721
- for (const route of routes) {
3722
- const url = new URL(route, baseUrl).toString();
3723
- try {
3724
- const metadata = await extractMetadataFromURL(url);
3725
- results.set(route, metadata);
3726
- await new Promise((resolve) => setTimeout(resolve, 100));
3727
- } catch (error) {
3728
- console.error(`Failed to crawl ${url}:`, error);
3729
- }
3730
- }
3731
- return results;
3732
- }
3733
3626
 
3734
3627
  // src/lib/sitemap-generator.ts
3735
3628
  function generateSitemapXML(options) {
@@ -3871,119 +3764,8 @@ function extractSitemapFromRobotsTxt(content) {
3871
3764
 
3872
3765
  // src/lib/storage/file-storage.ts
3873
3766
  import { promises as fs } from "fs";
3874
- var FileStorage = class {
3875
- constructor(filePath = "seo-records.json") {
3876
- this.records = [];
3877
- this.initialized = false;
3878
- this.filePath = filePath;
3879
- }
3880
- async ensureInitialized() {
3881
- if (this.initialized) return;
3882
- try {
3883
- const data = await fs.readFile(this.filePath, "utf-8");
3884
- this.records = JSON.parse(data);
3885
- } catch (error) {
3886
- if (error.code === "ENOENT") {
3887
- this.records = [];
3888
- await this.save();
3889
- } else {
3890
- throw error;
3891
- }
3892
- }
3893
- this.initialized = true;
3894
- }
3895
- async save() {
3896
- await fs.writeFile(this.filePath, JSON.stringify(this.records, null, 2), "utf-8");
3897
- }
3898
- async isAvailable() {
3899
- try {
3900
- const dir = this.filePath.includes("/") ? this.filePath.substring(0, this.filePath.lastIndexOf("/")) : ".";
3901
- await fs.access(dir);
3902
- return true;
3903
- } catch {
3904
- return false;
3905
- }
3906
- }
3907
- async getRecords() {
3908
- await this.ensureInitialized();
3909
- return [...this.records];
3910
- }
3911
- async getRecordById(id) {
3912
- await this.ensureInitialized();
3913
- return this.records.find((r) => r.id === id) || null;
3914
- }
3915
- async getRecordByRoute(routePath) {
3916
- await this.ensureInitialized();
3917
- return this.records.find((r) => r.routePath === routePath) || null;
3918
- }
3919
- async createRecord(record) {
3920
- await this.ensureInitialized();
3921
- const newRecord = {
3922
- id: typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`,
3923
- userId: "file-user",
3924
- // File storage doesn't need user IDs
3925
- routePath: record.routePath,
3926
- title: record.title,
3927
- description: record.description,
3928
- keywords: record.keywords,
3929
- ogTitle: record.ogTitle,
3930
- ogDescription: record.ogDescription,
3931
- ogImageUrl: record.ogImageUrl,
3932
- ogImageWidth: record.ogImageWidth,
3933
- ogImageHeight: record.ogImageHeight,
3934
- ogType: record.ogType,
3935
- ogUrl: record.ogUrl,
3936
- ogSiteName: record.ogSiteName,
3937
- twitterCard: record.twitterCard,
3938
- twitterTitle: record.twitterTitle,
3939
- twitterDescription: record.twitterDescription,
3940
- twitterImageUrl: record.twitterImageUrl,
3941
- twitterSite: record.twitterSite,
3942
- twitterCreator: record.twitterCreator,
3943
- canonicalUrl: record.canonicalUrl,
3944
- robots: record.robots,
3945
- author: record.author,
3946
- publishedTime: record.publishedTime,
3947
- modifiedTime: record.modifiedTime,
3948
- structuredData: record.structuredData,
3949
- validationStatus: "pending",
3950
- lastValidatedAt: void 0,
3951
- validationErrors: void 0
3952
- };
3953
- this.records.push(newRecord);
3954
- await this.save();
3955
- return newRecord;
3956
- }
3957
- async updateRecord(record) {
3958
- await this.ensureInitialized();
3959
- const index = this.records.findIndex((r) => r.id === record.id);
3960
- if (index === -1) {
3961
- throw new Error(`SEO record with id ${record.id} not found`);
3962
- }
3963
- const updated = {
3964
- ...this.records[index],
3965
- ...record
3966
- };
3967
- this.records[index] = updated;
3968
- await this.save();
3969
- return updated;
3970
- }
3971
- async deleteRecord(id) {
3972
- await this.ensureInitialized();
3973
- const index = this.records.findIndex((r) => r.id === id);
3974
- if (index === -1) {
3975
- throw new Error(`SEO record with id ${id} not found`);
3976
- }
3977
- this.records.splice(index, 1);
3978
- await this.save();
3979
- }
3980
- };
3981
3767
 
3982
3768
  // src/lib/storage/storage-factory.ts
3983
- function createStorageAdapter(config) {
3984
- const filePath = config?.filePath || process.env.SEO_CONSOLE_STORAGE_PATH || "seo-records.json";
3985
- return new FileStorage(filePath);
3986
- }
3987
3769
  function detectStorageConfig() {
3988
3770
  return {
3989
3771
  type: "file",
@@ -3998,22 +3780,16 @@ export {
3998
3780
  CardFooter,
3999
3781
  CardHeader,
4000
3782
  CardTitle,
4001
- FileStorage,
4002
3783
  Input,
4003
3784
  OGImagePreview,
4004
3785
  SEORecordForm,
4005
3786
  SEORecordList,
4006
3787
  Spinner,
4007
3788
  ValidationDashboard,
4008
- crawlSiteForSEO,
4009
3789
  createSEORecordSchema,
4010
- createStorageAdapter,
4011
3790
  detectStorageConfig,
4012
- discoverNextJSRoutes,
4013
3791
  extractMetadataFromHTML,
4014
- extractMetadataFromURL,
4015
3792
  extractSitemapFromRobotsTxt,
4016
- generateExamplePaths,
4017
3793
  generateRobotsTxt,
4018
3794
  generateSitemapFromRecords,
4019
3795
  generateSitemapXML,