@lukoweb/apitogo 0.1.54 → 0.1.56

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 (45) hide show
  1. package/dist/cli/cli.js +831 -398
  2. package/dist/declarations/config/default-landing-content.d.ts +2 -0
  3. package/dist/declarations/config/landing-manifest.d.ts +82 -0
  4. package/dist/declarations/config/local-manifest.d.ts +82 -0
  5. package/dist/declarations/config/resolve-modules.d.ts +3 -1
  6. package/dist/declarations/config/validators/ModulesSchema.d.ts +259 -0
  7. package/dist/declarations/config/validators/ZudokuConfig.d.ts +57 -0
  8. package/dist/declarations/lib/authentication/header-nav-filter.d.ts +4 -0
  9. package/dist/declarations/lib/authentication/providers/dev-portal-auth-pages.d.ts +5 -5
  10. package/dist/declarations/lib/authentication/providers/dev-portal-utils.d.ts +1 -0
  11. package/dist/declarations/lib/components/HeaderAuthActions.d.ts +3 -0
  12. package/dist/declarations/lib/components/SiteTitle.d.ts +6 -0
  13. package/dist/declarations/lib/components/ThemeSwitch.d.ts +3 -1
  14. package/dist/declarations/lib/components/TopNavigation.d.ts +1 -1
  15. package/dist/declarations/lib/core/ZudokuContext.d.ts +1 -0
  16. package/dist/flat-config.d.ts +95 -38
  17. package/package.json +1 -1
  18. package/src/app/main.css +2 -2
  19. package/src/config/apitogo-config-core.ts +13 -0
  20. package/src/config/apitogo-config-loader.browser.ts +17 -0
  21. package/src/config/build-apitogo-config.ts +13 -4
  22. package/src/config/default-landing-content.ts +154 -0
  23. package/src/config/landing-manifest.ts +11 -0
  24. package/src/config/landing-openapi-showcase.ts +115 -0
  25. package/src/config/loader.ts +17 -3
  26. package/src/config/local-manifest.ts +114 -10
  27. package/src/config/resolve-modules.ts +121 -32
  28. package/src/config/validators/ModulesSchema.ts +109 -0
  29. package/src/config/validators/ZudokuConfig.ts +1 -0
  30. package/src/lib/authentication/auth-header-nav.ts +5 -15
  31. package/src/lib/authentication/header-nav-filter.ts +36 -0
  32. package/src/lib/authentication/providers/dev-portal-auth-pages.tsx +95 -35
  33. package/src/lib/authentication/providers/dev-portal-utils.ts +26 -7
  34. package/src/lib/authentication/providers/dev-portal.tsx +18 -8
  35. package/src/lib/components/Header.tsx +49 -39
  36. package/src/lib/components/HeaderAuthActions.tsx +36 -0
  37. package/src/lib/components/HeaderNavigation.tsx +11 -9
  38. package/src/lib/components/MobileTopNavigation.tsx +43 -24
  39. package/src/lib/components/SiteTitle.tsx +20 -0
  40. package/src/lib/components/ThemeSwitch.tsx +36 -2
  41. package/src/lib/components/TopNavigation.tsx +20 -33
  42. package/src/lib/core/ZudokuContext.ts +1 -0
  43. package/src/vite/config.ts +21 -0
  44. package/src/vite/plugin-auth.ts +4 -1
  45. package/src/vite/plugin-config.ts +39 -4
package/dist/cli/cli.js CHANGED
@@ -64,39 +64,25 @@ function applyAuthenticationHeaderNav(config2) {
64
64
  }
65
65
  const authNavEnabled = config2.__meta?.authenticationEnabled === true;
66
66
  const navigation = config2.header?.navigation ?? [];
67
- if (!authNavEnabled) {
68
- const filtered = withoutLoginNavigation(navigation);
69
- if (filtered.length === navigation.length) {
70
- return config2;
71
- }
72
- return {
73
- ...config2,
74
- header: {
75
- ...config2.header,
76
- navigation: filtered
77
- }
78
- };
67
+ if (authNavEnabled) {
68
+ return config2;
79
69
  }
80
- if (navigation.some((item) => "to" in item && item.to === LOGIN_NAV_PATH)) {
70
+ const filtered = withoutLoginNavigation(navigation);
71
+ if (filtered.length === navigation.length) {
81
72
  return config2;
82
73
  }
83
74
  return {
84
75
  ...config2,
85
76
  header: {
86
77
  ...config2.header,
87
- navigation: [...navigation, LOGIN_HEADER_NAV_ITEM]
78
+ navigation: filtered
88
79
  }
89
80
  };
90
81
  }
91
- var LOGIN_NAV_PATH, LOGIN_HEADER_NAV_ITEM;
82
+ var LOGIN_NAV_PATH;
92
83
  var init_auth_header_nav = __esm({
93
84
  "src/lib/authentication/auth-header-nav.ts"() {
94
85
  LOGIN_NAV_PATH = "/signin";
95
- LOGIN_HEADER_NAV_ITEM = {
96
- label: "Login",
97
- to: LOGIN_NAV_PATH,
98
- display: "anon"
99
- };
100
86
  }
101
87
  });
102
88
 
@@ -508,6 +494,17 @@ function deriveManifestFields(config2) {
508
494
  }
509
495
  continue;
510
496
  }
497
+ if (key === "landing") {
498
+ const modules = asRecord(normalized.modules);
499
+ const landing = asRecord(modules?.landing);
500
+ if (landing?.content || landing?.enabled !== void 0) {
501
+ manifest.landing = {
502
+ enabled: typeof landing.enabled === "boolean" ? landing.enabled : void 0,
503
+ content: landing.content
504
+ };
505
+ }
506
+ continue;
507
+ }
511
508
  if (normalized[key] !== void 0) {
512
509
  manifest[key] = normalized[key];
513
510
  }
@@ -525,7 +522,28 @@ function extractManifest(config2) {
525
522
  const manifest = deriveManifestFields(config2);
526
523
  return Object.keys(manifest).length > 0 ? manifest : null;
527
524
  }
528
- var APITOGO_CONFIG_FILENAME, ENV_PREFIX, DERIVED_MANIFEST_KEYS;
525
+ function extractSiteConfig(config2) {
526
+ if (!config2 || typeof config2 !== "object") {
527
+ return {};
528
+ }
529
+ const normalized = normalizeApitogoConfig(config2);
530
+ const siteConfig = {};
531
+ for (const key of SITE_CONFIG_KEYS) {
532
+ if (normalized[key] !== void 0) {
533
+ siteConfig[key] = normalized[key];
534
+ }
535
+ }
536
+ if (normalized.authentication !== void 0) {
537
+ siteConfig.authentication = normalized.authentication;
538
+ }
539
+ const modulesDocs = asRecord(asRecord(normalized.modules)?.docs);
540
+ if (modulesDocs) {
541
+ const { enabled: _enabled, ...docsConfig } = modulesDocs;
542
+ siteConfig.docs = docsConfig;
543
+ }
544
+ return siteConfig;
545
+ }
546
+ var APITOGO_CONFIG_FILENAME, ENV_PREFIX, DERIVED_MANIFEST_KEYS, SITE_CONFIG_KEYS;
529
547
  var init_apitogo_config_core = __esm({
530
548
  "src/config/apitogo-config-core.ts"() {
531
549
  APITOGO_CONFIG_FILENAME = "apitogo.config.json";
@@ -538,7 +556,25 @@ var init_apitogo_config_core = __esm({
538
556
  "plans",
539
557
  "backend",
540
558
  "gateway",
541
- "projectId"
559
+ "projectId",
560
+ "landing"
561
+ ];
562
+ SITE_CONFIG_KEYS = [
563
+ "site",
564
+ "metadata",
565
+ "modules",
566
+ "navigation",
567
+ "apis",
568
+ "redirects",
569
+ "theme",
570
+ "search",
571
+ "llms",
572
+ "protectedRoutes",
573
+ "slots",
574
+ "mdx",
575
+ "catalogs",
576
+ "versions",
577
+ "options"
542
578
  ];
543
579
  }
544
580
  });
@@ -571,18 +607,287 @@ var init_apitogo_config_loader = __esm({
571
607
  }
572
608
  });
573
609
 
610
+ // src/config/build-apitogo-config.ts
611
+ function mergeOptionalRecord(...records) {
612
+ const merged = Object.assign({}, ...records.filter(Boolean));
613
+ return Object.keys(merged).length > 0 ? merged : void 0;
614
+ }
615
+ function buildApitogoConfig({
616
+ plugins,
617
+ plans: _legacyPlans,
618
+ ...jsonOverrides
619
+ } = {}) {
620
+ const jsonConfig = normalizeApitogoConfig({
621
+ ...jsonOverrides,
622
+ ..._legacyPlans !== void 0 ? { plans: _legacyPlans } : {}
623
+ });
624
+ const siteConfig = extractSiteConfig(jsonConfig);
625
+ const { plans: _rootPlans, ...restOverrides } = jsonOverrides;
626
+ const authentication = mergeOptionalRecord(
627
+ siteConfig.authentication,
628
+ jsonOverrides.authentication
629
+ );
630
+ return {
631
+ ...siteConfig,
632
+ ...restOverrides,
633
+ plugins,
634
+ ...authentication ? { authentication } : {},
635
+ site: {
636
+ ...siteConfig.site,
637
+ ...jsonOverrides.site
638
+ },
639
+ metadata: {
640
+ ...siteConfig.metadata,
641
+ ...jsonOverrides.metadata
642
+ },
643
+ docs: {
644
+ ...siteConfig.docs,
645
+ ...jsonOverrides.docs
646
+ },
647
+ modules: {
648
+ ...jsonConfig.modules,
649
+ ...jsonOverrides.modules
650
+ }
651
+ };
652
+ }
653
+ var init_build_apitogo_config = __esm({
654
+ "src/config/build-apitogo-config.ts"() {
655
+ init_apitogo_config_core();
656
+ }
657
+ });
658
+
574
659
  // src/config/file-exists.ts
575
660
  import { stat } from "node:fs/promises";
576
661
  var fileExists;
577
662
  var init_file_exists = __esm({
578
663
  "src/config/file-exists.ts"() {
579
- fileExists = (path39) => stat(path39).then(() => true).catch(() => false);
664
+ fileExists = (path40) => stat(path40).then(() => true).catch(() => false);
665
+ }
666
+ });
667
+
668
+ // src/config/validators/ModulesSchema.ts
669
+ import { z as z3 } from "zod";
670
+ var ModuleToggleSchema, DocsModuleSchema, LandingLinkSchema, LandingFeatureSchema, LandingCodeExampleSchema, LandingHeroSchema, LandingFeaturesSectionSchema, LandingTickerItemSchema, LandingTickerSchema, LandingTrustSchema, LandingApiShowcaseItemSchema, LandingApiShowcaseSchema, LandingPricingCtaSchema, LandingContentSchema, DashboardContentSchema, ProfileContentSchema, PlanTierSchema, PlansContentSchema, SubmodulePageFields, LandingModuleSchema, UserManagementModuleSchema, ApiKeysModuleSchema, PlanCatalogItemSchema, PlansModuleSchema, DashboardModuleSchema, UserPanelModuleSchema, ModulesSchema;
671
+ var init_ModulesSchema = __esm({
672
+ "src/config/validators/ModulesSchema.ts"() {
673
+ ModuleToggleSchema = z3.object({
674
+ enabled: z3.boolean().describe("Whether this module is active in the application.")
675
+ }).partial();
676
+ DocsModuleSchema = ModuleToggleSchema.extend({
677
+ files: z3.union([z3.string(), z3.array(z3.string())]).optional(),
678
+ publishMarkdown: z3.boolean().optional(),
679
+ defaultOptions: z3.object({
680
+ toc: z3.boolean(),
681
+ copyPage: z3.boolean().optional(),
682
+ disablePager: z3.boolean(),
683
+ showLastModified: z3.boolean(),
684
+ suggestEdit: z3.object({
685
+ url: z3.string(),
686
+ text: z3.string().optional()
687
+ }).optional()
688
+ }).partial().optional(),
689
+ llms: z3.object({
690
+ llmsTxt: z3.boolean().optional(),
691
+ llmsTxtFull: z3.boolean().optional(),
692
+ includeProtected: z3.boolean().optional()
693
+ }).optional()
694
+ });
695
+ LandingLinkSchema = z3.object({
696
+ label: z3.string(),
697
+ href: z3.string()
698
+ });
699
+ LandingFeatureSchema = z3.object({
700
+ title: z3.string(),
701
+ description: z3.string(),
702
+ icon: z3.string().optional()
703
+ });
704
+ LandingCodeExampleSchema = z3.object({
705
+ filename: z3.string().optional(),
706
+ language: z3.string().optional(),
707
+ code: z3.string()
708
+ }).optional();
709
+ LandingHeroSchema = z3.object({
710
+ title: z3.string().optional(),
711
+ titleAccent: z3.string().optional().describe("Accent-colored word or phrase shown on a new line after the title."),
712
+ subtitle: z3.string().optional(),
713
+ description: z3.string().optional(),
714
+ badge: z3.string().optional(),
715
+ highlights: z3.array(z3.string()).optional(),
716
+ codeExample: LandingCodeExampleSchema
717
+ }).optional();
718
+ LandingFeaturesSectionSchema = z3.object({
719
+ label: z3.string().optional(),
720
+ title: z3.string().optional(),
721
+ description: z3.string().optional()
722
+ }).optional();
723
+ LandingTickerItemSchema = z3.object({
724
+ label: z3.string(),
725
+ value: z3.string(),
726
+ change: z3.string().optional()
727
+ });
728
+ LandingTickerSchema = z3.object({
729
+ enabled: z3.boolean().optional(),
730
+ items: z3.array(LandingTickerItemSchema).optional()
731
+ }).optional();
732
+ LandingTrustSchema = z3.object({
733
+ enabled: z3.boolean().optional(),
734
+ title: z3.string().optional(),
735
+ logos: z3.array(z3.string()).optional()
736
+ }).optional();
737
+ LandingApiShowcaseItemSchema = z3.object({
738
+ name: z3.string(),
739
+ path: z3.string(),
740
+ icon: z3.string().optional(),
741
+ latency: z3.string().optional(),
742
+ summary: z3.string().optional()
743
+ });
744
+ LandingApiShowcaseSchema = z3.object({
745
+ enabled: z3.boolean().optional(),
746
+ title: z3.string().optional(),
747
+ subtitle: z3.string().optional(),
748
+ browseAllHref: z3.string().optional(),
749
+ browseAllLabel: z3.string().optional(),
750
+ autoFromOpenApi: z3.boolean().optional(),
751
+ items: z3.array(LandingApiShowcaseItemSchema).optional()
752
+ }).optional();
753
+ LandingPricingCtaSchema = z3.object({
754
+ enabled: z3.boolean().optional(),
755
+ title: z3.string().optional(),
756
+ description: z3.string().optional(),
757
+ primaryAction: LandingLinkSchema.optional(),
758
+ secondaryAction: LandingLinkSchema.optional()
759
+ }).optional();
760
+ LandingContentSchema = z3.object({
761
+ hero: LandingHeroSchema,
762
+ featuresSection: LandingFeaturesSectionSchema,
763
+ features: z3.array(LandingFeatureSchema).optional(),
764
+ primaryAction: LandingLinkSchema.optional(),
765
+ secondaryAction: LandingLinkSchema.optional(),
766
+ ticker: LandingTickerSchema,
767
+ trust: LandingTrustSchema,
768
+ apiShowcase: LandingApiShowcaseSchema,
769
+ pricingCta: LandingPricingCtaSchema,
770
+ showPoweredBy: z3.boolean().optional()
771
+ }).optional();
772
+ DashboardContentSchema = z3.object({
773
+ title: z3.string().optional(),
774
+ subtitle: z3.string().optional(),
775
+ description: z3.string().optional(),
776
+ quickLinks: z3.array(LandingLinkSchema).optional()
777
+ }).optional();
778
+ ProfileContentSchema = z3.object({
779
+ title: z3.string().optional(),
780
+ description: z3.string().optional()
781
+ }).optional();
782
+ PlanTierSchema = z3.object({
783
+ name: z3.string(),
784
+ price: z3.string().optional(),
785
+ description: z3.string().optional()
786
+ });
787
+ PlansContentSchema = z3.object({
788
+ title: z3.string().optional(),
789
+ description: z3.string().optional(),
790
+ tiers: z3.array(PlanTierSchema).optional()
791
+ }).optional();
792
+ SubmodulePageFields = {
793
+ page: z3.string().optional().describe(
794
+ "Path to a custom page component file, relative to the project root."
795
+ ),
796
+ component: z3.custom().optional().describe("Custom React component for this sub-module page.")
797
+ };
798
+ LandingModuleSchema = ModuleToggleSchema.extend({
799
+ path: z3.string().default("/").describe("Route path for the landing page."),
800
+ component: z3.custom().optional().describe("Custom React component for the landing page."),
801
+ page: z3.string().optional().describe(
802
+ "Path to a custom landing page component file, relative to the project root."
803
+ ),
804
+ layout: z3.enum(["default", "landing", "none"]).default("landing").describe(
805
+ "Layout wrapper: landing (header + footer), default (docs layout), or none."
806
+ ),
807
+ content: LandingContentSchema.describe(
808
+ "Default landing page content when no custom component is provided."
809
+ ),
810
+ useDefaults: z3.boolean().optional().describe(
811
+ "When true, merge DEFAULT_LANDING_CONTENT for unset sections. When false or omitted, only configured sections are shown."
812
+ )
813
+ });
814
+ UserManagementModuleSchema = ModuleToggleSchema.extend({
815
+ routes: z3.object({
816
+ login: z3.string().default("/signin"),
817
+ register: z3.string().default("/signup"),
818
+ profile: z3.string().default("profile"),
819
+ logout: z3.string().default("/signout")
820
+ }).partial().optional(),
821
+ page: SubmodulePageFields.page,
822
+ component: SubmodulePageFields.component,
823
+ content: ProfileContentSchema.describe(
824
+ "Default profile page content when no custom component is provided."
825
+ )
826
+ });
827
+ ApiKeysModuleSchema = ModuleToggleSchema.extend({
828
+ path: z3.string().default("settings/api-keys").describe("Route path for API key management.")
829
+ });
830
+ PlanCatalogItemSchema = z3.object({
831
+ sku: z3.string(),
832
+ displayName: z3.string(),
833
+ priceAmount: z3.number().default(0),
834
+ priceCurrency: z3.string().optional(),
835
+ billingPeriod: z3.string().optional(),
836
+ limitsJson: z3.string().optional(),
837
+ includedActionKeys: z3.array(z3.string()).optional()
838
+ });
839
+ PlansModuleSchema = ModuleToggleSchema.extend({
840
+ path: z3.string().default("plans").describe("Route path for plans and subscription management."),
841
+ page: SubmodulePageFields.page,
842
+ component: SubmodulePageFields.component,
843
+ content: PlansContentSchema.describe(
844
+ "Default plans page content when no custom component is provided."
845
+ ),
846
+ items: z3.array(PlanCatalogItemSchema).optional().describe(
847
+ "Gateway plan catalog for /pricing preview and publish (canonical storage)."
848
+ )
849
+ });
850
+ DashboardModuleSchema = ModuleToggleSchema.extend({
851
+ path: z3.string().default("dashboard").describe("Route path for the user dashboard."),
852
+ page: SubmodulePageFields.page,
853
+ component: SubmodulePageFields.component,
854
+ content: DashboardContentSchema.describe(
855
+ "Default dashboard page content when no custom component is provided."
856
+ )
857
+ });
858
+ UserPanelModuleSchema = ModuleToggleSchema.extend({
859
+ basePath: z3.string().default("/account").describe("Base path prefix for user panel routes."),
860
+ dashboard: DashboardModuleSchema.optional(),
861
+ userManagement: UserManagementModuleSchema.optional(),
862
+ apiKeys: ApiKeysModuleSchema.optional(),
863
+ plans: PlansModuleSchema.optional()
864
+ });
865
+ ModulesSchema = z3.object({
866
+ docs: DocsModuleSchema.optional().describe(
867
+ "Documentation module \u2014 MD/MDX pages and OpenAPI reference."
868
+ ),
869
+ landing: LandingModuleSchema.optional().describe(
870
+ "Landing page module \u2014 marketing or home page."
871
+ ),
872
+ userPanel: UserPanelModuleSchema.optional().describe(
873
+ "User panel module \u2014 authenticated user area with sub-modules."
874
+ )
875
+ }).optional();
876
+ }
877
+ });
878
+
879
+ // src/config/landing-manifest.ts
880
+ var LandingManifestContentSchema;
881
+ var init_landing_manifest = __esm({
882
+ "src/config/landing-manifest.ts"() {
883
+ init_ModulesSchema();
884
+ LandingManifestContentSchema = LandingContentSchema;
580
885
  }
581
886
  });
582
887
 
583
888
  // src/config/local-manifest.ts
584
889
  import path3 from "node:path";
585
- import { z as z3 } from "zod";
890
+ import { z as z4 } from "zod";
586
891
  function isPricingEnabled(manifest) {
587
892
  return manifest?.pricing?.enabled === true;
588
893
  }
@@ -671,222 +976,226 @@ var BillingPeriodSchema, ManifestPlanInputSchema, DevPortalLocalManifestSchema;
671
976
  var init_local_manifest = __esm({
672
977
  "src/config/local-manifest.ts"() {
673
978
  init_apitogo_config_loader();
674
- BillingPeriodSchema = z3.enum(["month", "year", "monthly", "annual"]);
675
- ManifestPlanInputSchema = z3.object({
676
- sku: z3.string().min(1),
677
- displayName: z3.string().min(1),
678
- priceAmount: z3.number().default(0),
679
- priceCurrency: z3.string().optional(),
979
+ init_landing_manifest();
980
+ BillingPeriodSchema = z4.enum(["month", "year", "monthly", "annual"]);
981
+ ManifestPlanInputSchema = z4.object({
982
+ sku: z4.string().min(1),
983
+ displayName: z4.string().min(1),
984
+ priceAmount: z4.number().default(0),
985
+ priceCurrency: z4.string().optional(),
680
986
  billingPeriod: BillingPeriodSchema.optional(),
681
- limitsJson: z3.string().optional(),
682
- includedActionKeys: z3.array(z3.string()).optional()
987
+ limitsJson: z4.string().optional(),
988
+ includedActionKeys: z4.array(z4.string()).optional()
683
989
  });
684
- DevPortalLocalManifestSchema = z3.object({
685
- siteName: z3.string().optional(),
686
- branding: z3.object({
687
- title: z3.string().optional(),
688
- logoUrl: z3.string().optional()
990
+ DevPortalLocalManifestSchema = z4.object({
991
+ siteName: z4.string().optional(),
992
+ branding: z4.object({
993
+ title: z4.string().optional(),
994
+ logoUrl: z4.string().optional()
689
995
  }).optional(),
690
- pricing: z3.object({
691
- enabled: z3.boolean().optional()
996
+ pricing: z4.object({
997
+ enabled: z4.boolean().optional()
692
998
  }).optional(),
693
- authentication: z3.object({
694
- enabled: z3.boolean().optional(),
695
- apiBaseUrl: z3.string().optional(),
696
- native: z3.object({
697
- enabled: z3.boolean().optional()
999
+ authentication: z4.object({
1000
+ enabled: z4.boolean().optional(),
1001
+ apiBaseUrl: z4.string().optional(),
1002
+ native: z4.object({
1003
+ enabled: z4.boolean().optional()
698
1004
  }).optional(),
699
- email: z3.object({
700
- provider: z3.string().optional(),
701
- from: z3.string().optional()
1005
+ email: z4.object({
1006
+ provider: z4.string().optional(),
1007
+ from: z4.string().optional()
702
1008
  }).optional(),
703
- providers: z3.array(
704
- z3.object({
705
- id: z3.string().min(1),
706
- displayName: z3.string().optional(),
707
- authority: z3.string().optional(),
708
- clientId: z3.string().optional(),
709
- scopes: z3.string().optional()
1009
+ providers: z4.array(
1010
+ z4.object({
1011
+ id: z4.string().min(1),
1012
+ displayName: z4.string().optional(),
1013
+ authority: z4.string().optional(),
1014
+ clientId: z4.string().optional(),
1015
+ scopes: z4.string().optional()
710
1016
  })
711
1017
  ).optional()
712
1018
  }).optional(),
713
- plans: z3.array(ManifestPlanInputSchema).optional(),
714
- backend: z3.object({
715
- sourceDirectory: z3.string().optional(),
716
- publishDirectory: z3.string().optional(),
717
- openApiPath: z3.string().optional(),
718
- runtime: z3.string().optional(),
719
- runtimeVersion: z3.string().optional(),
720
- deployed: z3.boolean().optional()
1019
+ plans: z4.array(ManifestPlanInputSchema).optional(),
1020
+ backend: z4.object({
1021
+ sourceDirectory: z4.string().optional(),
1022
+ publishDirectory: z4.string().optional(),
1023
+ openApiPath: z4.string().optional(),
1024
+ runtime: z4.string().optional(),
1025
+ runtimeVersion: z4.string().optional(),
1026
+ deployed: z4.boolean().optional()
721
1027
  }).optional(),
722
- gateway: z3.object({
723
- authMode: z3.enum(["platformManagedEntra", "bringYourOwnOidc"]).optional(),
724
- oidcMetadataUrl: z3.string().optional(),
725
- oidcAllowedIssuers: z3.array(z3.string()).optional(),
726
- oidcAudiences: z3.array(z3.string()).optional(),
727
- limitsJson: z3.string().optional(),
728
- publicHealthActionKey: z3.string().optional()
1028
+ gateway: z4.object({
1029
+ authMode: z4.enum(["platformManagedEntra", "bringYourOwnOidc"]).optional(),
1030
+ oidcMetadataUrl: z4.string().optional(),
1031
+ oidcAllowedIssuers: z4.array(z4.string()).optional(),
1032
+ oidcAudiences: z4.array(z4.string()).optional(),
1033
+ limitsJson: z4.string().optional(),
1034
+ publicHealthActionKey: z4.string().optional()
729
1035
  }).optional(),
730
- projectId: z3.string().optional()
1036
+ projectId: z4.string().optional(),
1037
+ landing: z4.object({
1038
+ enabled: z4.boolean().optional(),
1039
+ content: LandingManifestContentSchema
1040
+ }).optional()
731
1041
  });
732
1042
  }
733
1043
  });
734
1044
 
735
- // src/config/validators/ModulesSchema.ts
736
- import { z as z4 } from "zod";
737
- var ModuleToggleSchema, DocsModuleSchema, LandingLinkSchema, LandingFeatureSchema, LandingHeroSchema, LandingContentSchema, DashboardContentSchema, ProfileContentSchema, PlanTierSchema, PlansContentSchema, SubmodulePageFields, LandingModuleSchema, UserManagementModuleSchema, ApiKeysModuleSchema, PlanCatalogItemSchema, PlansModuleSchema, DashboardModuleSchema, UserPanelModuleSchema, ModulesSchema;
738
- var init_ModulesSchema = __esm({
739
- "src/config/validators/ModulesSchema.ts"() {
740
- ModuleToggleSchema = z4.object({
741
- enabled: z4.boolean().describe("Whether this module is active in the application.")
742
- }).partial();
743
- DocsModuleSchema = ModuleToggleSchema.extend({
744
- files: z4.union([z4.string(), z4.array(z4.string())]).optional(),
745
- publishMarkdown: z4.boolean().optional(),
746
- defaultOptions: z4.object({
747
- toc: z4.boolean(),
748
- copyPage: z4.boolean().optional(),
749
- disablePager: z4.boolean(),
750
- showLastModified: z4.boolean(),
751
- suggestEdit: z4.object({
752
- url: z4.string(),
753
- text: z4.string().optional()
754
- }).optional()
755
- }).partial().optional(),
756
- llms: z4.object({
757
- llmsTxt: z4.boolean().optional(),
758
- llmsTxtFull: z4.boolean().optional(),
759
- includeProtected: z4.boolean().optional()
760
- }).optional()
761
- });
762
- LandingLinkSchema = z4.object({
763
- label: z4.string(),
764
- href: z4.string()
765
- });
766
- LandingFeatureSchema = z4.object({
767
- title: z4.string(),
768
- description: z4.string()
769
- });
770
- LandingHeroSchema = z4.object({
771
- title: z4.string().optional(),
772
- subtitle: z4.string().optional(),
773
- description: z4.string().optional()
774
- }).optional();
775
- LandingContentSchema = z4.object({
776
- hero: LandingHeroSchema,
777
- features: z4.array(LandingFeatureSchema).optional(),
778
- primaryAction: LandingLinkSchema.optional(),
779
- secondaryAction: LandingLinkSchema.optional(),
780
- showPoweredBy: z4.boolean().optional()
781
- }).optional();
782
- DashboardContentSchema = z4.object({
783
- title: z4.string().optional(),
784
- subtitle: z4.string().optional(),
785
- description: z4.string().optional(),
786
- quickLinks: z4.array(LandingLinkSchema).optional()
787
- }).optional();
788
- ProfileContentSchema = z4.object({
789
- title: z4.string().optional(),
790
- description: z4.string().optional()
791
- }).optional();
792
- PlanTierSchema = z4.object({
793
- name: z4.string(),
794
- price: z4.string().optional(),
795
- description: z4.string().optional()
796
- });
797
- PlansContentSchema = z4.object({
798
- title: z4.string().optional(),
799
- description: z4.string().optional(),
800
- tiers: z4.array(PlanTierSchema).optional()
801
- }).optional();
802
- SubmodulePageFields = {
803
- page: z4.string().optional().describe(
804
- "Path to a custom page component file, relative to the project root."
805
- ),
806
- component: z4.custom().optional().describe("Custom React component for this sub-module page.")
1045
+ // src/config/default-landing-content.ts
1046
+ var DEFAULT_LANDING_CONTENT;
1047
+ var init_default_landing_content = __esm({
1048
+ "src/config/default-landing-content.ts"() {
1049
+ DEFAULT_LANDING_CONTENT = {
1050
+ hero: {
1051
+ badge: "99.98% uptime",
1052
+ subtitle: "Production-ready APIs, one endpoint away",
1053
+ title: "Developer APIs that ship",
1054
+ titleAccent: "today.",
1055
+ description: "Documentation, interactive API reference, auth, and billing \u2014 sub-40ms responses, one API key, generous free tier.",
1056
+ highlights: ["No credit card", "10k requests free", "SDKs for 6 languages"],
1057
+ codeExample: {
1058
+ filename: "example.sh",
1059
+ language: "bash",
1060
+ code: `$ curl https://api.example.com/v1/items \\
1061
+ -H "Authorization: Bearer YOUR_API_KEY" \\
1062
+ -d "limit=10"
1063
+
1064
+ {
1065
+ "items": [
1066
+ { "id": "item_1", "name": "Widget", "status": "active" },
1067
+ { "id": "item_2", "name": "Gadget", "status": "active" }
1068
+ ]
1069
+ } // 28ms`
1070
+ }
1071
+ },
1072
+ primaryAction: { label: "Get your API key", href: "/register" },
1073
+ secondaryAction: { label: "Read the docs", href: "/introduction" },
1074
+ ticker: {
1075
+ items: [
1076
+ { label: "GET", value: "/v1/items", change: "28ms" },
1077
+ { label: "POST", value: "/v1/items", change: "34ms" },
1078
+ { label: "GET", value: "/v1/users", change: "19ms" },
1079
+ { label: "PATCH", value: "/v1/users/{id}", change: "41ms" },
1080
+ { label: "GET", value: "/v1/health", change: "16ms" },
1081
+ { label: "DELETE", value: "/v1/items/{id}", change: "22ms" },
1082
+ { label: "GET", value: "/v1/search", change: "47ms" },
1083
+ { label: "POST", value: "/v1/auth/token", change: "52ms" }
1084
+ ]
1085
+ },
1086
+ trust: {
1087
+ title: "Trusted by teams shipping production APIs",
1088
+ logos: ["Acme Corp", "BuildFast", "DataFlow", "ShipKit", "DevStack", "LaunchPad"]
1089
+ },
1090
+ featuresSection: {
1091
+ label: "// why us",
1092
+ title: "Everything you need to build on your API",
1093
+ description: "Skip the infra. We handle docs, auth, keys, and billing so you can focus on your product."
1094
+ },
1095
+ features: [
1096
+ {
1097
+ icon: "gauge",
1098
+ title: "Sub-40ms responses",
1099
+ description: "Edge-cached and globally distributed, so your app feels instant anywhere."
1100
+ },
1101
+ {
1102
+ icon: "radio",
1103
+ title: "Real-time streams",
1104
+ description: "WebSocket feeds with automatic reconnection for live data and events."
1105
+ },
1106
+ {
1107
+ icon: "blocks",
1108
+ title: "Unified schema",
1109
+ description: "One consistent API design \u2014 no per-endpoint glue code or custom adapters."
1110
+ },
1111
+ {
1112
+ icon: "shield-check",
1113
+ title: "99.98% uptime",
1114
+ description: "Redundant infra with a public status page and an SLA on paid plans."
1115
+ },
1116
+ {
1117
+ icon: "code",
1118
+ title: "SDKs for 6 languages",
1119
+ description: "Typed clients for JS, Python, Go, Rust, Ruby and PHP. Copy, paste, ship."
1120
+ },
1121
+ {
1122
+ icon: "webhook",
1123
+ title: "Webhooks & alerts",
1124
+ description: "Push events and threshold alerts straight to your endpoints."
1125
+ }
1126
+ ],
1127
+ apiShowcase: {
1128
+ title: "Production APIs. One key.",
1129
+ browseAllLabel: "Browse all APIs",
1130
+ browseAllHref: "/api",
1131
+ autoFromOpenApi: true,
1132
+ items: [
1133
+ {
1134
+ name: "List resources",
1135
+ path: "/v1/items",
1136
+ icon: "boxes",
1137
+ latency: "28ms"
1138
+ },
1139
+ {
1140
+ name: "Create resource",
1141
+ path: "/v1/items",
1142
+ icon: "badge-dollar-sign",
1143
+ latency: "34ms"
1144
+ },
1145
+ {
1146
+ name: "Get resource",
1147
+ path: "/v1/items/{id}",
1148
+ icon: "layers",
1149
+ latency: "19ms"
1150
+ },
1151
+ {
1152
+ name: "Search",
1153
+ path: "/v1/search",
1154
+ icon: "arrow-left-right",
1155
+ latency: "41ms"
1156
+ },
1157
+ {
1158
+ name: "User profile",
1159
+ path: "/v1/users/me",
1160
+ icon: "wallet",
1161
+ latency: "52ms"
1162
+ },
1163
+ {
1164
+ name: "Health check",
1165
+ path: "/v1/health",
1166
+ icon: "activity",
1167
+ latency: "16ms"
1168
+ },
1169
+ {
1170
+ name: "Metadata",
1171
+ path: "/v1/meta",
1172
+ icon: "coins",
1173
+ latency: "22ms"
1174
+ },
1175
+ {
1176
+ name: "Rate limits",
1177
+ path: "/v1/limits",
1178
+ icon: "gauge",
1179
+ latency: "16ms"
1180
+ }
1181
+ ]
1182
+ },
1183
+ pricingCta: {
1184
+ title: "Start free. Scale when you do.",
1185
+ description: "10,000 requests a month, free forever. Upgrade only when your app takes off.",
1186
+ primaryAction: { label: "Create free account", href: "/register" },
1187
+ secondaryAction: { label: "See pricing", href: "/pricing" }
1188
+ },
1189
+ showPoweredBy: true
807
1190
  };
808
- LandingModuleSchema = ModuleToggleSchema.extend({
809
- path: z4.string().default("/").describe("Route path for the landing page."),
810
- component: z4.custom().optional().describe("Custom React component for the landing page."),
811
- page: z4.string().optional().describe(
812
- "Path to a custom landing page component file, relative to the project root."
813
- ),
814
- layout: z4.enum(["default", "landing", "none"]).default("landing").describe(
815
- "Layout wrapper: landing (header + footer), default (docs layout), or none."
816
- ),
817
- content: LandingContentSchema.describe(
818
- "Default landing page content when no custom component is provided."
819
- )
820
- });
821
- UserManagementModuleSchema = ModuleToggleSchema.extend({
822
- routes: z4.object({
823
- login: z4.string().default("/signin"),
824
- register: z4.string().default("/signup"),
825
- profile: z4.string().default("profile"),
826
- logout: z4.string().default("/signout")
827
- }).partial().optional(),
828
- page: SubmodulePageFields.page,
829
- component: SubmodulePageFields.component,
830
- content: ProfileContentSchema.describe(
831
- "Default profile page content when no custom component is provided."
832
- )
833
- });
834
- ApiKeysModuleSchema = ModuleToggleSchema.extend({
835
- path: z4.string().default("settings/api-keys").describe("Route path for API key management.")
836
- });
837
- PlanCatalogItemSchema = z4.object({
838
- sku: z4.string(),
839
- displayName: z4.string(),
840
- priceAmount: z4.number().default(0),
841
- priceCurrency: z4.string().optional(),
842
- billingPeriod: z4.string().optional(),
843
- limitsJson: z4.string().optional(),
844
- includedActionKeys: z4.array(z4.string()).optional()
845
- });
846
- PlansModuleSchema = ModuleToggleSchema.extend({
847
- path: z4.string().default("plans").describe("Route path for plans and subscription management."),
848
- page: SubmodulePageFields.page,
849
- component: SubmodulePageFields.component,
850
- content: PlansContentSchema.describe(
851
- "Default plans page content when no custom component is provided."
852
- ),
853
- items: z4.array(PlanCatalogItemSchema).optional().describe(
854
- "Gateway plan catalog for /pricing preview and publish (canonical storage)."
855
- )
856
- });
857
- DashboardModuleSchema = ModuleToggleSchema.extend({
858
- path: z4.string().default("dashboard").describe("Route path for the user dashboard."),
859
- page: SubmodulePageFields.page,
860
- component: SubmodulePageFields.component,
861
- content: DashboardContentSchema.describe(
862
- "Default dashboard page content when no custom component is provided."
863
- )
864
- });
865
- UserPanelModuleSchema = ModuleToggleSchema.extend({
866
- basePath: z4.string().default("/account").describe("Base path prefix for user panel routes."),
867
- dashboard: DashboardModuleSchema.optional(),
868
- userManagement: UserManagementModuleSchema.optional(),
869
- apiKeys: ApiKeysModuleSchema.optional(),
870
- plans: PlansModuleSchema.optional()
871
- });
872
- ModulesSchema = z4.object({
873
- docs: DocsModuleSchema.optional().describe(
874
- "Documentation module \u2014 MD/MDX pages and OpenAPI reference."
875
- ),
876
- landing: LandingModuleSchema.optional().describe(
877
- "Landing page module \u2014 marketing or home page."
878
- ),
879
- userPanel: UserPanelModuleSchema.optional().describe(
880
- "User panel module \u2014 authenticated user area with sub-modules."
881
- )
882
- }).optional();
883
1191
  }
884
1192
  });
885
1193
 
886
1194
  // src/config/resolve-modules.ts
887
- var hasExplicitModules, joinPanelPath, DEFAULT_LANDING_FEATURES, resolveLandingContent, DEFAULT_DASHBOARD_QUICK_LINKS, resolveDashboardContent, resolveProfileContent, resolvePlansContent, resolveModulesConfig;
1195
+ var hasExplicitModules, joinPanelPath, mergeLandingSection, buildDefaultLandingContent, resolveLandingContent, DEFAULT_DASHBOARD_QUICK_LINKS, resolveDashboardContent, resolveProfileContent, resolvePlansContent, resolveModulesConfig;
888
1196
  var init_resolve_modules = __esm({
889
1197
  "src/config/resolve-modules.ts"() {
1198
+ init_default_landing_content();
890
1199
  init_ModulesSchema();
891
1200
  hasExplicitModules = (config2) => config2.modules !== void 0;
892
1201
  joinPanelPath = (basePath, routePath) => {
@@ -900,38 +1209,97 @@ var init_resolve_modules = __esm({
900
1209
  }
901
1210
  return `/${`${base}/${route}`.replace(/^\/+/, "")}`;
902
1211
  };
903
- DEFAULT_LANDING_FEATURES = [
904
- {
905
- title: "Documentation",
906
- description: "Write guides and references in Markdown or MDX with full navigation and search."
907
- },
908
- {
909
- title: "API Reference",
910
- description: "Publish interactive OpenAPI docs with a built-in playground and code samples."
911
- },
912
- {
913
- title: "Developer Portal",
914
- description: "Extend with landing pages, authentication, API keys, and subscription modules."
1212
+ mergeLandingSection = (defaults, override) => {
1213
+ if (override?.enabled === false) {
1214
+ return void 0;
915
1215
  }
916
- ];
917
- resolveLandingContent = (config2, content) => {
1216
+ if (!defaults && !override) {
1217
+ return void 0;
1218
+ }
1219
+ return { ...defaults, ...override };
1220
+ };
1221
+ buildDefaultLandingContent = (config2) => {
918
1222
  const siteTitle = config2.metadata?.applicationName ?? config2.site?.title ?? "APIToGo";
919
1223
  return {
1224
+ ...DEFAULT_LANDING_CONTENT,
920
1225
  hero: {
921
- title: content?.hero?.title ?? siteTitle,
922
- subtitle: content?.hero?.subtitle ?? "Developer portal",
923
- description: content?.hero?.description ?? config2.metadata?.description ?? "Ship beautiful API documentation and developer experiences with APIToGo."
1226
+ ...DEFAULT_LANDING_CONTENT.hero,
1227
+ title: `${siteTitle} APIs that ship`
924
1228
  },
925
- features: content?.features ?? DEFAULT_LANDING_FEATURES,
926
- primaryAction: content?.primaryAction ?? {
927
- label: "Get started",
928
- href: "/introduction"
1229
+ primaryAction: {
1230
+ ...DEFAULT_LANDING_CONTENT.primaryAction,
1231
+ href: "/introduction",
1232
+ label: "Get started"
929
1233
  },
930
- secondaryAction: content?.secondaryAction ?? {
931
- label: "API Reference",
932
- href: "/api"
1234
+ secondaryAction: {
1235
+ ...DEFAULT_LANDING_CONTENT.secondaryAction,
1236
+ href: "/api",
1237
+ label: "API Reference"
933
1238
  },
934
- showPoweredBy: content?.showPoweredBy
1239
+ pricingCta: DEFAULT_LANDING_CONTENT.pricingCta ? {
1240
+ ...DEFAULT_LANDING_CONTENT.pricingCta,
1241
+ primaryAction: {
1242
+ label: "Get started",
1243
+ href: "/introduction"
1244
+ },
1245
+ secondaryAction: {
1246
+ label: "See pricing",
1247
+ href: "/pricing"
1248
+ }
1249
+ } : void 0
1250
+ };
1251
+ };
1252
+ resolveLandingContent = (config2, content, options) => {
1253
+ const siteTitle = config2.metadata?.applicationName ?? config2.site?.title ?? "APIToGo";
1254
+ if (options?.useDefaults === true) {
1255
+ const defaults = buildDefaultLandingContent(config2);
1256
+ return {
1257
+ hero: {
1258
+ ...defaults.hero,
1259
+ ...content?.hero,
1260
+ title: content?.hero?.title ?? defaults.hero?.title,
1261
+ description: content?.hero?.description ?? config2.metadata?.description ?? defaults.hero?.description,
1262
+ codeExample: content?.hero?.codeExample ?? defaults.hero?.codeExample,
1263
+ titleAccent: content?.hero?.titleAccent ?? (content?.hero?.title ? void 0 : defaults.hero?.titleAccent)
1264
+ },
1265
+ featuresSection: mergeLandingSection(
1266
+ defaults.featuresSection,
1267
+ content?.featuresSection
1268
+ ),
1269
+ features: content?.features ?? defaults.features,
1270
+ primaryAction: content?.primaryAction ?? defaults.primaryAction,
1271
+ secondaryAction: content?.secondaryAction ?? defaults.secondaryAction,
1272
+ showPoweredBy: content?.showPoweredBy ?? defaults.showPoweredBy,
1273
+ ticker: mergeLandingSection(defaults.ticker, content?.ticker),
1274
+ trust: mergeLandingSection(defaults.trust, content?.trust),
1275
+ apiShowcase: mergeLandingSection(
1276
+ defaults.apiShowcase,
1277
+ content?.apiShowcase
1278
+ ),
1279
+ pricingCta: mergeLandingSection(defaults.pricingCta, content?.pricingCta)
1280
+ };
1281
+ }
1282
+ const hasContent = content !== void 0 && Object.keys(content).length > 0;
1283
+ if (!hasContent) {
1284
+ return {
1285
+ hero: { title: siteTitle },
1286
+ showPoweredBy: true
1287
+ };
1288
+ }
1289
+ return {
1290
+ hero: {
1291
+ ...content.hero,
1292
+ title: content.hero?.title ?? siteTitle
1293
+ },
1294
+ featuresSection: content.featuresSection ? mergeLandingSection(void 0, content.featuresSection) : void 0,
1295
+ features: content.features,
1296
+ primaryAction: content.primaryAction,
1297
+ secondaryAction: content.secondaryAction,
1298
+ showPoweredBy: content.showPoweredBy ?? true,
1299
+ ticker: content.ticker ? mergeLandingSection(void 0, content.ticker) : void 0,
1300
+ trust: content.trust ? mergeLandingSection(void 0, content.trust) : void 0,
1301
+ apiShowcase: content.apiShowcase ? mergeLandingSection(void 0, content.apiShowcase) : void 0,
1302
+ pricingCta: content.pricingCta ? mergeLandingSection(void 0, content.pricingCta) : void 0
935
1303
  };
936
1304
  };
937
1305
  DEFAULT_DASHBOARD_QUICK_LINKS = [
@@ -986,7 +1354,9 @@ var init_resolve_modules = __esm({
986
1354
  path: landingModule?.path ?? "/",
987
1355
  component: landingModule?.component,
988
1356
  layout: landingModule?.layout ?? "landing",
989
- content: resolveLandingContent(config2, landingModule?.content)
1357
+ content: resolveLandingContent(config2, landingModule?.content, {
1358
+ useDefaults: landingModule?.useDefaults === true
1359
+ })
990
1360
  },
991
1361
  userPanel: {
992
1362
  enabled: userPanelEnabled,
@@ -4234,6 +4604,7 @@ var init_ZudokuConfig = __esm({
4234
4604
  });
4235
4605
  SiteSchema = z9.object({
4236
4606
  title: z9.string(),
4607
+ showTitleInHeader: z9.boolean().optional(),
4237
4608
  logoUrl: z9.string(),
4238
4609
  dir: z9.enum(["ltr", "rtl"]).optional(),
4239
4610
  logo: LogoSchema,
@@ -4378,7 +4749,17 @@ async function loadZudokuConfigWithMeta(rootDir) {
4378
4749
  perEnvironmentStartEndDuringDev: true
4379
4750
  }
4380
4751
  });
4381
- const config2 = module.default;
4752
+ const importedConfig = module.default;
4753
+ let config2;
4754
+ try {
4755
+ const fileConfig = loadApitogoConfig(rootDir);
4756
+ config2 = buildApitogoConfig({
4757
+ ...fileConfig,
4758
+ plugins: importedConfig.plugins
4759
+ });
4760
+ } catch {
4761
+ config2 = importedConfig;
4762
+ }
4382
4763
  validateConfig(config2, configPath);
4383
4764
  const configWithMetadata = {
4384
4765
  ...config2,
@@ -4389,7 +4770,7 @@ async function loadZudokuConfigWithMeta(rootDir) {
4389
4770
  dependencies,
4390
4771
  configPath
4391
4772
  },
4392
- __resolvedModules: resolveModulesConfig(config2)
4773
+ __resolvedModules: resolveModulesConfig(config2, { rootDir })
4393
4774
  };
4394
4775
  return configWithMetadata;
4395
4776
  }
@@ -4499,7 +4880,9 @@ async function loadZudokuConfig(configEnv, rootDir) {
4499
4880
  ...transformedConfig.__meta,
4500
4881
  ...configWithManifestMeta.__meta
4501
4882
  },
4502
- __resolvedModules: resolveModulesConfig(transformedConfig)
4883
+ __resolvedModules: resolveModulesConfig(transformedConfig, {
4884
+ rootDir: transformedConfig.__meta.rootDir
4885
+ })
4503
4886
  };
4504
4887
  if (!process.env.APITOGO_JSON_ONLY) {
4505
4888
  logger.info(
@@ -4527,6 +4910,7 @@ var init_loader = __esm({
4527
4910
  init_transform_config();
4528
4911
  init_invariant();
4529
4912
  init_apitogo_config_loader();
4913
+ init_build_apitogo_config();
4530
4914
  init_file_exists();
4531
4915
  init_local_manifest();
4532
4916
  init_resolve_modules();
@@ -4566,7 +4950,7 @@ __export(llms_exports, {
4566
4950
  generateLlmsTxtFiles: () => generateLlmsTxtFiles
4567
4951
  });
4568
4952
  import { writeFile as writeFile4 } from "node:fs/promises";
4569
- import path26 from "node:path";
4953
+ import path27 from "node:path";
4570
4954
  import colors6 from "picocolors";
4571
4955
  async function generateLlmsTxtFiles({
4572
4956
  markdownFileInfos,
@@ -4601,7 +4985,7 @@ async function generateLlmsTxtFiles({
4601
4985
  }
4602
4986
  }
4603
4987
  const llmsTxt2 = llmsTxtParts.join("\n");
4604
- await writeFile4(path26.join(baseOutputDir, "llms.txt"), llmsTxt2, "utf-8");
4988
+ await writeFile4(path27.join(baseOutputDir, "llms.txt"), llmsTxt2, "utf-8");
4605
4989
  if (process.env.APITOGO_JSON_ONLY !== "1") {
4606
4990
  console.log(colors6.blue("\u2713 generated llms.txt"));
4607
4991
  }
@@ -4629,7 +5013,7 @@ ${info.content}
4629
5013
  }
4630
5014
  const llmsFull = llmsFullParts.join("\n");
4631
5015
  await writeFile4(
4632
- path26.join(baseOutputDir, "llms-full.txt"),
5016
+ path27.join(baseOutputDir, "llms-full.txt"),
4633
5017
  llmsFull,
4634
5018
  "utf-8"
4635
5019
  );
@@ -4650,11 +5034,11 @@ import { hideBin } from "yargs/helpers";
4650
5034
  import yargs from "yargs/yargs";
4651
5035
 
4652
5036
  // src/cli/build/handler.ts
4653
- import path30 from "node:path";
5037
+ import path31 from "node:path";
4654
5038
 
4655
5039
  // src/vite/build.ts
4656
5040
  import { mkdir as mkdir5, readFile as readFile3, rename, rm as rm2, writeFile as writeFile5 } from "node:fs/promises";
4657
- import path28 from "node:path";
5041
+ import path29 from "node:path";
4658
5042
  import { build as esbuild } from "esbuild";
4659
5043
  import { build as viteBuild, mergeConfig as mergeConfig3 } from "vite";
4660
5044
 
@@ -4790,7 +5174,7 @@ init_invariant();
4790
5174
  init_joinUrl();
4791
5175
 
4792
5176
  // src/vite/config.ts
4793
- import path23 from "node:path";
5177
+ import path24 from "node:path";
4794
5178
  import dotenv from "dotenv";
4795
5179
  import colors4 from "picocolors";
4796
5180
  import {
@@ -4801,7 +5185,7 @@ import {
4801
5185
  // package.json
4802
5186
  var package_default = {
4803
5187
  name: "@lukoweb/apitogo",
4804
- version: "0.1.54",
5188
+ version: "0.1.56",
4805
5189
  type: "module",
4806
5190
  sideEffects: [
4807
5191
  "**/*.css",
@@ -5570,14 +5954,14 @@ var flattenAllOf = (schema2) => {
5570
5954
  };
5571
5955
 
5572
5956
  // src/lib/util/traverse.ts
5573
- var traverse = (specification, transform, path39 = []) => {
5574
- const transformed = transform(specification, path39);
5957
+ var traverse = (specification, transform, path40 = []) => {
5958
+ const transformed = transform(specification, path40);
5575
5959
  if (typeof transformed !== "object" || transformed === null) {
5576
5960
  return transformed;
5577
5961
  }
5578
5962
  const result = Array.isArray(transformed) ? [] : {};
5579
5963
  for (const [key, value] of Object.entries(transformed)) {
5580
- const currentPath = [...path39, key];
5964
+ const currentPath = [...path40, key];
5581
5965
  if (Array.isArray(value)) {
5582
5966
  result[key] = value.map(
5583
5967
  (item, index) => typeof item === "object" && item != null ? traverse(item, transform, [...currentPath, index.toString()]) : item
@@ -5605,9 +5989,9 @@ var resolveLocalRef = (schema2, ref) => {
5605
5989
  if (schemaCache?.has(ref)) {
5606
5990
  return schemaCache.get(ref);
5607
5991
  }
5608
- const path39 = ref.split("/").slice(1);
5992
+ const path40 = ref.split("/").slice(1);
5609
5993
  let current = schema2;
5610
- for (const segment of path39) {
5994
+ for (const segment of path40) {
5611
5995
  if (!current || typeof current !== "object") {
5612
5996
  current = null;
5613
5997
  }
@@ -5626,7 +6010,7 @@ var dereference = async (schema2, resolvers = []) => {
5626
6010
  }
5627
6011
  const cloned = structuredClone(schema2);
5628
6012
  const visited = /* @__PURE__ */ new Set();
5629
- const resolve = async (current, path39) => {
6013
+ const resolve = async (current, path40) => {
5630
6014
  if (isIndexableObject(current)) {
5631
6015
  if (visited.has(current)) {
5632
6016
  return CIRCULAR_REF;
@@ -5634,7 +6018,7 @@ var dereference = async (schema2, resolvers = []) => {
5634
6018
  visited.add(current);
5635
6019
  if (Array.isArray(current)) {
5636
6020
  for (let index = 0; index < current.length; index++) {
5637
- current[index] = await resolve(current[index], `${path39}/${index}`);
6021
+ current[index] = await resolve(current[index], `${path40}/${index}`);
5638
6022
  }
5639
6023
  } else {
5640
6024
  if ("$ref" in current && typeof current.$ref === "string") {
@@ -5645,13 +6029,13 @@ var dereference = async (schema2, resolvers = []) => {
5645
6029
  for (const resolver of resolvers) {
5646
6030
  const resolved = await resolver($ref);
5647
6031
  if (resolved) {
5648
- result2 = await resolve(resolved, path39);
6032
+ result2 = await resolve(resolved, path40);
5649
6033
  break;
5650
6034
  }
5651
6035
  }
5652
6036
  if (result2 === void 0) {
5653
6037
  const resolved = await resolveLocalRef(cloned, $ref);
5654
- result2 = await resolve(resolved, path39);
6038
+ result2 = await resolve(resolved, path40);
5655
6039
  }
5656
6040
  if (hasSiblings) {
5657
6041
  if (result2 === CIRCULAR_REF) {
@@ -5664,7 +6048,7 @@ var dereference = async (schema2, resolvers = []) => {
5664
6048
  return result2;
5665
6049
  }
5666
6050
  for (const key in current) {
5667
- current[key] = await resolve(current[key], `${path39}/${key}`);
6051
+ current[key] = await resolve(current[key], `${path40}/${key}`);
5668
6052
  }
5669
6053
  }
5670
6054
  visited.delete(current);
@@ -5703,9 +6087,9 @@ var upgradeSchema = (schema2) => {
5703
6087
  }
5704
6088
  return sub;
5705
6089
  });
5706
- schema2 = traverse(schema2, (sub, path39) => {
6090
+ schema2 = traverse(schema2, (sub, path40) => {
5707
6091
  if (sub.example !== void 0) {
5708
- if (isSchemaPath(path39 ?? [])) {
6092
+ if (isSchemaPath(path40 ?? [])) {
5709
6093
  sub.examples = [sub.example];
5710
6094
  } else {
5711
6095
  sub.examples = {
@@ -5718,11 +6102,11 @@ var upgradeSchema = (schema2) => {
5718
6102
  }
5719
6103
  return sub;
5720
6104
  });
5721
- schema2 = traverse(schema2, (schema3, path39) => {
6105
+ schema2 = traverse(schema2, (schema3, path40) => {
5722
6106
  if (schema3.type === "object" && schema3.properties !== void 0) {
5723
- const parentPath = path39?.slice(0, -1);
6107
+ const parentPath = path40?.slice(0, -1);
5724
6108
  const isMultipart = parentPath?.some((segment, index) => {
5725
- return segment === "content" && path39?.[index + 1] === "multipart/form-data";
6109
+ return segment === "content" && path40?.[index + 1] === "multipart/form-data";
5726
6110
  });
5727
6111
  if (isMultipart) {
5728
6112
  const entries = Object.entries(schema3.properties);
@@ -5736,8 +6120,8 @@ var upgradeSchema = (schema2) => {
5736
6120
  }
5737
6121
  return schema3;
5738
6122
  });
5739
- schema2 = traverse(schema2, (schema3, path39) => {
5740
- if (path39?.includes("content") && path39.includes("application/octet-stream")) {
6123
+ schema2 = traverse(schema2, (schema3, path40) => {
6124
+ if (path40?.includes("content") && path40.includes("application/octet-stream")) {
5741
6125
  return {};
5742
6126
  }
5743
6127
  if (schema3.type === "string" && schema3.format === "binary") {
@@ -5763,11 +6147,11 @@ var upgradeSchema = (schema2) => {
5763
6147
  }
5764
6148
  return sub;
5765
6149
  });
5766
- schema2 = traverse(schema2, (schema3, path39) => {
6150
+ schema2 = traverse(schema2, (schema3, path40) => {
5767
6151
  if (schema3.type === "string" && schema3.format === "byte") {
5768
- const parentPath = path39?.slice(0, -1);
6152
+ const parentPath = path40?.slice(0, -1);
5769
6153
  const contentMediaType = parentPath?.find(
5770
- (_, index) => path39?.[index - 1] === "content"
6154
+ (_, index) => path40?.[index - 1] === "content"
5771
6155
  );
5772
6156
  return {
5773
6157
  type: "string",
@@ -5779,7 +6163,7 @@ var upgradeSchema = (schema2) => {
5779
6163
  });
5780
6164
  return schema2;
5781
6165
  };
5782
- function isSchemaPath(path39) {
6166
+ function isSchemaPath(path40) {
5783
6167
  const schemaLocations = [
5784
6168
  ["components", "schemas"],
5785
6169
  "properties",
@@ -5792,10 +6176,10 @@ function isSchemaPath(path39) {
5792
6176
  ];
5793
6177
  return schemaLocations.some((location) => {
5794
6178
  if (Array.isArray(location)) {
5795
- return location.every((segment, index) => path39[index] === segment);
6179
+ return location.every((segment, index) => path40[index] === segment);
5796
6180
  }
5797
- return path39.includes(location);
5798
- }) || path39.includes("schema") || path39.some((segment) => segment.endsWith("Schema"));
6181
+ return path40.includes(location);
6182
+ }) || path40.includes("schema") || path40.some((segment) => segment.endsWith("Schema"));
5799
6183
  }
5800
6184
 
5801
6185
  // src/lib/oas/parser/index.ts
@@ -5877,13 +6261,13 @@ var OPENAPI_PROPS = /* @__PURE__ */ new Set([
5877
6261
  "anyOf",
5878
6262
  "oneOf"
5879
6263
  ]);
5880
- var handleCircularRefs = (obj, currentPath = /* @__PURE__ */ new WeakSet(), refs = /* @__PURE__ */ new WeakMap(), path39 = [], currentRefPaths = /* @__PURE__ */ new Set()) => {
6264
+ var handleCircularRefs = (obj, currentPath = /* @__PURE__ */ new WeakSet(), refs = /* @__PURE__ */ new WeakMap(), path40 = [], currentRefPaths = /* @__PURE__ */ new Set()) => {
5881
6265
  if (obj === null || typeof obj !== "object") return obj;
5882
6266
  const refPath = obj.__$ref;
5883
6267
  const isCircular = currentPath.has(obj) || typeof refPath === "string" && currentRefPaths.has(refPath);
5884
6268
  if (isCircular) {
5885
6269
  if (typeof refPath === "string") return SCHEMA_REF_PREFIX + refPath;
5886
- const circularProp = path39.find((p) => !OPENAPI_PROPS.has(p)) || path39[0];
6270
+ const circularProp = path40.find((p) => !OPENAPI_PROPS.has(p)) || path40[0];
5887
6271
  return [CIRCULAR_REF, circularProp].filter(Boolean).join(":");
5888
6272
  }
5889
6273
  if (refs.has(obj)) return refs.get(obj);
@@ -5893,7 +6277,7 @@ var handleCircularRefs = (obj, currentPath = /* @__PURE__ */ new WeakSet(), refs
5893
6277
  value,
5894
6278
  currentPath,
5895
6279
  refs,
5896
- [...path39, key],
6280
+ [...path40, key],
5897
6281
  currentRefPaths
5898
6282
  );
5899
6283
  const result = Array.isArray(obj) ? obj.map((item, i) => recurse(item, i.toString())) : Object.fromEntries(
@@ -5928,7 +6312,7 @@ var resolveExtensions = (obj) => Object.fromEntries(
5928
6312
  var getAllTags = (schema2) => {
5929
6313
  const rootTags = schema2.tags ?? [];
5930
6314
  const operations = Object.values(schema2.paths ?? {}).flatMap(
5931
- (path39) => HttpMethods.map((k) => path39?.[k]).filter((op) => op != null)
6315
+ (path40) => HttpMethods.map((k) => path40?.[k]).filter((op) => op != null)
5932
6316
  );
5933
6317
  const operationTags = new Set(operations.flatMap((op) => op.tags ?? []));
5934
6318
  const hasUntaggedOperations = operations.some(
@@ -5983,7 +6367,7 @@ var getAllSlugs = (ops, schemaTags = []) => {
5983
6367
  var getOperationSlugKey = (op) => [op.path, op.method, op.operationId, op.summary].filter(Boolean).join("-");
5984
6368
  var getAllOperations = (paths) => {
5985
6369
  const operations = Object.entries(paths ?? {}).flatMap(
5986
- ([path39, value]) => HttpMethods.flatMap((method) => {
6370
+ ([path40, value]) => HttpMethods.flatMap((method) => {
5987
6371
  if (!value?.[method]) return [];
5988
6372
  const operation = value[method];
5989
6373
  const pathParameters = value.parameters ?? [];
@@ -6003,7 +6387,7 @@ var getAllOperations = (paths) => {
6003
6387
  return {
6004
6388
  ...operation,
6005
6389
  method,
6006
- path: path39,
6390
+ path: path40,
6007
6391
  parameters,
6008
6392
  servers,
6009
6393
  tags: operation.tags ?? []
@@ -6361,8 +6745,8 @@ var Schema = builder.objectRef("Schema").implement({
6361
6745
  }),
6362
6746
  paths: t.field({
6363
6747
  type: [PathItem],
6364
- resolve: (root) => Object.entries(root.paths ?? {}).map(([path39, value]) => ({
6365
- path: path39,
6748
+ resolve: (root) => Object.entries(root.paths ?? {}).map(([path40, value]) => ({
6749
+ path: path40,
6366
6750
  // biome-ignore lint/style/noNonNullAssertion: value is guaranteed to be defined
6367
6751
  methods: Object.keys(value)
6368
6752
  }))
@@ -6509,7 +6893,7 @@ init_joinUrl();
6509
6893
 
6510
6894
  // src/vite/api/schema-codegen.ts
6511
6895
  var unescapeJsonPointer = (uri) => decodeURIComponent(uri.replace(/~1/g, "/").replace(/~0/g, "~"));
6512
- var getSegmentsFromPath = (path39) => path39.split("/").slice(1).map(unescapeJsonPointer);
6896
+ var getSegmentsFromPath = (path40) => path40.split("/").slice(1).map(unescapeJsonPointer);
6513
6897
  var createLocalRefMap = (obj) => {
6514
6898
  const refMap = /* @__PURE__ */ new Map();
6515
6899
  const siblingsMap = /* @__PURE__ */ new Map();
@@ -6540,16 +6924,16 @@ var replaceMarkers = (code, mergedRefs) => code.replace(/"__refMap:(.*?)"/g, '__
6540
6924
  /"__refMap\+Siblings:(.*?)"/g,
6541
6925
  (_, key) => mergedRefs.get(key) ?? `__refMap["${key}"]`
6542
6926
  );
6543
- var lookup = (schema2, path39, filePath) => {
6544
- const parts = getSegmentsFromPath(path39);
6927
+ var lookup = (schema2, path40, filePath) => {
6928
+ const parts = getSegmentsFromPath(path40);
6545
6929
  let val = schema2;
6546
6930
  for (const part of parts) {
6547
6931
  while (val.$ref?.startsWith("#/")) {
6548
- val = val.$ref === path39 ? val : lookup(schema2, val.$ref, filePath);
6932
+ val = val.$ref === path40 ? val : lookup(schema2, val.$ref, filePath);
6549
6933
  }
6550
6934
  if (val[part] === void 0) {
6551
6935
  throw new Error(
6552
- `Error in ${filePath ?? "code generation"}: Could not find path segment ${part} in path: ${path39}`
6936
+ `Error in ${filePath ?? "code generation"}: Could not find path segment ${part} in path: ${path40}`
6553
6937
  );
6554
6938
  }
6555
6939
  val = val[part];
@@ -6794,8 +7178,8 @@ var SchemaManager = class {
6794
7178
  }
6795
7179
  }
6796
7180
  };
6797
- getLatestSchema = (path39) => this.processedSchemas[path39]?.at(0);
6798
- getSchemasForPath = (path39) => this.processedSchemas[path39];
7181
+ getLatestSchema = (path40) => this.processedSchemas[path40]?.at(0);
7182
+ getSchemasForPath = (path40) => this.processedSchemas[path40];
6799
7183
  getSchemaImports = () => Object.values(this.processedSchemas).flat().filter((s) => s.importKey);
6800
7184
  getUrlToFilePathMap = () => {
6801
7185
  const map = /* @__PURE__ */ new Map();
@@ -7410,7 +7794,7 @@ var viteAuthPlugin = () => {
7410
7794
  async load(id) {
7411
7795
  if (id === resolvedVirtualModuleId5) {
7412
7796
  const config2 = getCurrentConfig();
7413
- if (!config2.authentication || config2.__meta.mode === "standalone") {
7797
+ if (!config2.authentication?.type || config2.__meta.mode === "standalone") {
7414
7798
  return `export const configuredAuthProvider = undefined;`;
7415
7799
  }
7416
7800
  return [
@@ -7466,17 +7850,43 @@ var viteAliasPlugin = () => {
7466
7850
  var plugin_component_default = viteAliasPlugin;
7467
7851
 
7468
7852
  // src/vite/plugin-config.ts
7853
+ init_package_json();
7469
7854
  init_loader();
7855
+ import path16 from "node:path";
7470
7856
  import { normalizePath } from "vite";
7471
7857
  var virtualModuleId3 = "virtual:zudoku-config";
7472
7858
  var resolvedVirtualModuleId3 = `\0${virtualModuleId3}`;
7859
+ var browserConfigLoaderPath = path16.join(
7860
+ getZudokuRootDir(),
7861
+ "src/config/apitogo-config-loader.browser.ts"
7862
+ );
7863
+ function serializeClientConfig(config2) {
7864
+ const {
7865
+ plugins: _plugins,
7866
+ __meta: _meta,
7867
+ __resolvedModules,
7868
+ ...rest
7869
+ } = config2;
7870
+ return JSON.stringify(
7871
+ { ...rest, __resolvedModules },
7872
+ (_key, value) => typeof value === "function" ? void 0 : value
7873
+ );
7874
+ }
7473
7875
  var viteConfigPlugin = () => {
7474
7876
  let viteConfig;
7475
7877
  return {
7476
7878
  name: "zudoku-config-plugin",
7477
- resolveId(id) {
7478
- if (id !== virtualModuleId3) return;
7479
- return resolvedVirtualModuleId3;
7879
+ resolveId(source, _importer, options) {
7880
+ if (source === virtualModuleId3) {
7881
+ return resolvedVirtualModuleId3;
7882
+ }
7883
+ if (!source.includes("apitogo-config-loader.node")) {
7884
+ return;
7885
+ }
7886
+ const isServerEnvironment = options?.ssr === true || this.environment?.config?.consumer === "server";
7887
+ if (!isServerEnvironment) {
7888
+ return browserConfigLoaderPath;
7889
+ }
7480
7890
  },
7481
7891
  configResolved(resolvedConfig) {
7482
7892
  viteConfig = resolvedConfig;
@@ -7504,8 +7914,11 @@ var viteConfigPlugin = () => {
7504
7914
  import rawConfig from "${normalizePath(configPath)}";
7505
7915
  import { runPluginTransformConfig } from "@lukoweb/apitogo/plugins";
7506
7916
 
7917
+ const embeddedConfig = ${serializeClientConfig(loadedConfig)};
7918
+
7507
7919
  const config = await runPluginTransformConfig({
7508
- ...rawConfig,
7920
+ ...embeddedConfig,
7921
+ plugins: rawConfig?.plugins ?? embeddedConfig.plugins ?? [],
7509
7922
  __meta: ${JSON.stringify(clientMeta)},
7510
7923
  });
7511
7924
  export default config;
@@ -7610,7 +8023,7 @@ var viteDocMetadataPlugin = () => ({
7610
8023
 
7611
8024
  // src/vite/plugin-docs.ts
7612
8025
  init_loader();
7613
- import path16 from "node:path";
8026
+ import path17 from "node:path";
7614
8027
  import { glob as glob3 } from "glob";
7615
8028
  import globParent from "glob-parent";
7616
8029
  init_ZudokuConfig();
@@ -7679,7 +8092,7 @@ var globMarkdownFiles = async (config2, options = { absolute: false }) => {
7679
8092
  if (process.env.NODE_ENV !== "development") {
7680
8093
  const draftStatuses = await Promise.all(
7681
8094
  globbedFiles.map(async (file) => {
7682
- const absolutePath = path16.resolve(config2.__meta.rootDir, file);
8095
+ const absolutePath = path17.resolve(config2.__meta.rootDir, file);
7683
8096
  const { data } = await readFrontmatter(absolutePath);
7684
8097
  return { file, isDraft: data.draft === true };
7685
8098
  })
@@ -7692,9 +8105,9 @@ var globMarkdownFiles = async (config2, options = { absolute: false }) => {
7692
8105
  if (draftFiles.has(file)) {
7693
8106
  continue;
7694
8107
  }
7695
- const relativePath = path16.posix.relative(parent, file);
8108
+ const relativePath = path17.posix.relative(parent, file);
7696
8109
  const routePath = ensureLeadingSlash(relativePath.replace(/\.mdx?$/, ""));
7697
- const filePath = options.absolute ? path16.resolve(config2.__meta.rootDir, file) : file;
8110
+ const filePath = options.absolute ? path17.resolve(config2.__meta.rootDir, file) : file;
7698
8111
  fileMapping[routePath] = filePath;
7699
8112
  }
7700
8113
  }
@@ -7758,7 +8171,7 @@ var viteDocsPlugin = () => {
7758
8171
  const globbedDocuments = {};
7759
8172
  for (const [routePath, file] of Object.entries(fileMapping)) {
7760
8173
  const importPath = ensureLeadingSlash(
7761
- path16.posix.join(globImportBasePath, file)
8174
+ path17.posix.join(globImportBasePath, file)
7762
8175
  );
7763
8176
  globbedDocuments[routePath] = importPath;
7764
8177
  }
@@ -7784,7 +8197,7 @@ var plugin_docs_default = viteDocsPlugin;
7784
8197
  // src/vite/plugin-local-manifest.ts
7785
8198
  init_apitogo_config_loader();
7786
8199
  init_local_manifest();
7787
- import path17 from "node:path";
8200
+ import path18 from "node:path";
7788
8201
  var APITOGO_LOCAL_MANIFEST_VIRTUAL_ID = "virtual:apitogo-local-manifest";
7789
8202
  var resolvedVirtualModuleId4 = `\0${APITOGO_LOCAL_MANIFEST_VIRTUAL_ID}`;
7790
8203
  var viteLocalManifestPlugin = () => {
@@ -7834,8 +8247,8 @@ var viteLocalManifestPlugin = () => {
7834
8247
  server.watcher.add(watchPath);
7835
8248
  }
7836
8249
  server.watcher.on("change", async (changedPath) => {
7837
- const resolvedChanged = path17.resolve(changedPath);
7838
- if (!watchPaths.some((p) => path17.resolve(p) === resolvedChanged)) {
8250
+ const resolvedChanged = path18.resolve(changedPath);
8251
+ if (!watchPaths.some((p) => path18.resolve(p) === resolvedChanged)) {
7839
8252
  return;
7840
8253
  }
7841
8254
  const module = server.moduleGraph.getModuleById(
@@ -7862,7 +8275,7 @@ init_loader();
7862
8275
  init_ProtectedRoutesSchema();
7863
8276
  init_joinUrl();
7864
8277
  import { mkdir as mkdir2, writeFile as writeFile2 } from "node:fs/promises";
7865
- import path18 from "node:path";
8278
+ import path19 from "node:path";
7866
8279
  import { matchPath } from "react-router";
7867
8280
  var processMarkdownFile = async (filePath) => {
7868
8281
  const { content: markdownContent, data: frontmatter } = await readFrontmatter(filePath);
@@ -7950,7 +8363,7 @@ var viteMarkdownExportPlugin = () => {
7950
8363
  if (process.env.NODE_ENV !== "production" || Object.keys(markdownFiles).length === 0 || !needsMdFiles) {
7951
8364
  return;
7952
8365
  }
7953
- const distDir = path18.join(
8366
+ const distDir = path19.join(
7954
8367
  config2.__meta.rootDir,
7955
8368
  "dist",
7956
8369
  config2.basePath ?? ""
@@ -7971,15 +8384,15 @@ var viteMarkdownExportPlugin = () => {
7971
8384
  content: finalMarkdown
7972
8385
  });
7973
8386
  const segments = routePath === "/" ? ["index"] : routePath.split("/").filter(Boolean);
7974
- const outputPath = `${path18.join(distDir, ...segments)}.md`;
7975
- await mkdir2(path18.dirname(outputPath), { recursive: true });
8387
+ const outputPath = `${path19.join(distDir, ...segments)}.md`;
8388
+ await mkdir2(path19.dirname(outputPath), { recursive: true });
7976
8389
  await writeFile2(outputPath, finalMarkdown, "utf-8");
7977
8390
  } catch (error) {
7978
8391
  console.warn(`Failed to export markdown for ${routePath}:`, error);
7979
8392
  }
7980
8393
  }
7981
8394
  if (config2.docs?.llms?.llmsTxt || config2.docs?.llms?.llmsTxtFull) {
7982
- const markdownInfoPath = path18.join(
8395
+ const markdownInfoPath = path19.join(
7983
8396
  config2.__meta.rootDir,
7984
8397
  "node_modules/.apitogo/markdown-info.json"
7985
8398
  );
@@ -8131,9 +8544,9 @@ var remarkCodeTabs = () => (tree) => {
8131
8544
  };
8132
8545
 
8133
8546
  // src/vite/mdx/remark-inject-filepath.ts
8134
- import path19 from "node:path";
8547
+ import path20 from "node:path";
8135
8548
  var remarkInjectFilepath = (rootDir) => (tree, vfile) => {
8136
- const relativePath = path19.relative(rootDir, vfile.path).split(path19.sep).join(path19.posix.sep);
8549
+ const relativePath = path20.relative(rootDir, vfile.path).split(path20.sep).join(path20.posix.sep);
8137
8550
  tree.children.unshift(exportMdxjsConst("__filepath", relativePath));
8138
8551
  };
8139
8552
 
@@ -8220,18 +8633,18 @@ var remarkLastModified = () => {
8220
8633
  };
8221
8634
 
8222
8635
  // src/vite/mdx/remark-link-rewrite.ts
8223
- import path20 from "node:path";
8636
+ import path21 from "node:path";
8224
8637
  import { visit as visit5 } from "unist-util-visit";
8225
8638
  var remarkLinkRewrite = (basePath = "") => (tree) => {
8226
8639
  visit5(tree, "link", (node) => {
8227
8640
  if (!node.url) return;
8228
8641
  if (node.url.startsWith("http") || node.url.startsWith("mailto:")) return;
8229
8642
  node.url = node.url.replace(/\\/g, "/");
8230
- const base = path20.posix.join(basePath);
8643
+ const base = path21.posix.join(basePath);
8231
8644
  if (basePath && node.url.startsWith(base)) {
8232
8645
  node.url = node.url.slice(base.length);
8233
8646
  } else if (!node.url.startsWith("/") && !node.url.startsWith("#")) {
8234
- node.url = path20.posix.join("..", node.url);
8647
+ node.url = path21.posix.join("..", node.url);
8235
8648
  }
8236
8649
  node.url = node.url.replace(/\.mdx?(#.*)?$/, "$1");
8237
8650
  });
@@ -8451,11 +8864,11 @@ var plugin_mdx_default = viteMdxPlugin;
8451
8864
 
8452
8865
  // src/vite/plugin-modules.ts
8453
8866
  init_loader();
8454
- import path21 from "node:path";
8867
+ import path22 from "node:path";
8455
8868
  import { normalizePath as normalizePath2 } from "vite";
8456
- var getLandingModuleImport = (moduleDir, mode) => mode === "internal" ? normalizePath2(path21.join(moduleDir, "../module-landing/src/index.tsx")) : "@lukoweb/apitogo-module-landing";
8457
- var getUserPanelModuleImport = (moduleDir, mode) => mode === "internal" ? normalizePath2(path21.join(moduleDir, "../module-user-panel/src/index.tsx")) : "@lukoweb/apitogo-module-user-panel";
8458
- var resolveProjectPageImport = (rootDir, pagePath) => normalizePath2(path21.resolve(rootDir, pagePath));
8869
+ var getLandingModuleImport = (moduleDir, mode) => mode === "internal" ? normalizePath2(path22.join(moduleDir, "../module-landing/src/index.tsx")) : "@lukoweb/apitogo-module-landing";
8870
+ var getUserPanelModuleImport = (moduleDir, mode) => mode === "internal" ? normalizePath2(path22.join(moduleDir, "../module-user-panel/src/index.tsx")) : "@lukoweb/apitogo-module-user-panel";
8871
+ var resolveProjectPageImport = (rootDir, pagePath) => normalizePath2(path22.resolve(rootDir, pagePath));
8459
8872
  var viteModulesPlugin = () => {
8460
8873
  const virtualModuleId4 = "virtual:zudoku-modules-plugin";
8461
8874
  const resolvedVirtualModuleId5 = `\0${virtualModuleId4}`;
@@ -8576,7 +8989,7 @@ var plugin_modules_default = viteModulesPlugin;
8576
8989
 
8577
8990
  // src/vite/plugin-search.ts
8578
8991
  init_loader();
8579
- import path22 from "node:path";
8992
+ import path23 from "node:path";
8580
8993
  var viteSearchPlugin = () => {
8581
8994
  const virtualModuleId4 = "virtual:zudoku-search-plugin";
8582
8995
  const resolvedVirtualModuleId5 = `\0${virtualModuleId4}`;
@@ -8594,7 +9007,7 @@ var viteSearchPlugin = () => {
8594
9007
  return resolvedVirtualModuleId5;
8595
9008
  }
8596
9009
  if (id === "/pagefind/pagefind.js" && resolvedViteConfig?.publicDir) {
8597
- return path22.join(resolvedViteConfig.publicDir, "pagefind/pagefind.js");
9010
+ return path23.join(resolvedViteConfig.publicDir, "pagefind/pagefind.js");
8598
9011
  }
8599
9012
  },
8600
9013
  async load(id) {
@@ -8733,13 +9146,17 @@ function vitePlugin() {
8733
9146
  }
8734
9147
 
8735
9148
  // src/vite/config.ts
9149
+ var browserConfigLoaderPath2 = path24.join(
9150
+ getZudokuRootDir(),
9151
+ "src/config/apitogo-config-loader.browser.ts"
9152
+ );
8736
9153
  var resolveMergedPublicDir = (rootDir, merged) => {
8737
9154
  if (merged.publicDir === false) return void 0;
8738
9155
  const rel = typeof merged.publicDir === "string" ? merged.publicDir : "public";
8739
- return path23.resolve(rootDir, rel);
9156
+ return path24.resolve(rootDir, rel);
8740
9157
  };
8741
- var getAppClientEntryPath = () => path23.posix.join(getZudokuRootDir(), "src/app/entry.client.tsx");
8742
- var getAppServerEntryPath = () => path23.posix.join(getZudokuRootDir(), "src/app/entry.server.tsx");
9158
+ var getAppClientEntryPath = () => path24.posix.join(getZudokuRootDir(), "src/app/entry.client.tsx");
9159
+ var getAppServerEntryPath = () => path24.posix.join(getZudokuRootDir(), "src/app/entry.server.tsx");
8743
9160
  var hasLoggedCdnInfo = false;
8744
9161
  var MEDIA_REGEX = /\.(a?png|jpe?g|gif|bmp|svg|webp|tiff|ico|webm|ogg|mp3|wav|m4a|avif|mp4)/i;
8745
9162
  var defineEnvVars = (vars) => Object.fromEntries(
@@ -8769,7 +9186,7 @@ async function getViteConfig(dir, configEnv) {
8769
9186
  );
8770
9187
  if (ZuploEnv.isZuplo) {
8771
9188
  dotenv.config({
8772
- path: path23.resolve(config2.__meta.rootDir, "../.env.zuplo"),
9189
+ path: path24.resolve(config2.__meta.rootDir, "../.env.zuplo"),
8773
9190
  quiet: true
8774
9191
  });
8775
9192
  }
@@ -8790,6 +9207,22 @@ async function getViteConfig(dir, configEnv) {
8790
9207
  "@mdx-js/react": import.meta.resolve("@mdx-js/react")
8791
9208
  }
8792
9209
  },
9210
+ environments: {
9211
+ client: {
9212
+ resolve: {
9213
+ alias: {
9214
+ [path24.join(
9215
+ getZudokuRootDir(),
9216
+ "src/config/apitogo-config-loader.node.ts"
9217
+ )]: browserConfigLoaderPath2,
9218
+ [path24.join(
9219
+ getZudokuRootDir(),
9220
+ "src/config/apitogo-config-loader.node.js"
9221
+ )]: browserConfigLoaderPath2
9222
+ }
9223
+ }
9224
+ }
9225
+ },
8793
9226
  define: {
8794
9227
  "process.env.ZUDOKU_VERSION": JSON.stringify(package_default.version),
8795
9228
  "process.env.IS_ZUPLO": ZuploEnv.isZuplo,
@@ -8828,8 +9261,8 @@ async function getViteConfig(dir, configEnv) {
8828
9261
  ssr: configEnv.isSsrBuild,
8829
9262
  sourcemap: true,
8830
9263
  target: "es2022",
8831
- outDir: path23.resolve(
8832
- path23.join(
9264
+ outDir: path24.resolve(
9265
+ path24.join(
8833
9266
  dir,
8834
9267
  "dist",
8835
9268
  config2.basePath ?? "",
@@ -8848,7 +9281,7 @@ async function getViteConfig(dir, configEnv) {
8848
9281
  },
8849
9282
  experimental: {
8850
9283
  renderBuiltUrl(filename) {
8851
- if (cdnUrl?.base && [".js", ".css"].includes(path23.extname(filename))) {
9284
+ if (cdnUrl?.base && [".js", ".css"].includes(path24.extname(filename))) {
8852
9285
  return joinUrl(cdnUrl.base, filename);
8853
9286
  }
8854
9287
  if (cdnUrl?.media && MEDIA_REGEX.test(filename)) {
@@ -8861,7 +9294,7 @@ async function getViteConfig(dir, configEnv) {
8861
9294
  esbuildOptions: {
8862
9295
  target: "es2022"
8863
9296
  },
8864
- entries: [path23.posix.join(getZudokuRootDir(), "src/{app,lib}/**")],
9297
+ entries: [path24.posix.join(getZudokuRootDir(), "src/{app,lib}/**")],
8865
9298
  exclude: [
8866
9299
  "@lukoweb/apitogo",
8867
9300
  "@lukoweb/apitogo-plugin-dev-portal-billing"
@@ -8967,7 +9400,7 @@ init_package_json();
8967
9400
  init_joinUrl();
8968
9401
  import assert from "node:assert";
8969
9402
  import { cp, mkdir as mkdir3, writeFile as writeFile3 } from "node:fs/promises";
8970
- import path24 from "node:path";
9403
+ import path25 from "node:path";
8971
9404
  var pkgJson = getZudokuPackageJson();
8972
9405
  function generateOutput({
8973
9406
  config: config2,
@@ -9024,9 +9457,9 @@ async function writeOutput(dir, {
9024
9457
  rewrites
9025
9458
  }) {
9026
9459
  const output = generateOutput({ config: config2, redirects, rewrites });
9027
- const outputDir = process.env.VERCEL ? path24.join(dir, ".vercel/output") : path24.join(dir, "dist/.output");
9460
+ const outputDir = process.env.VERCEL ? path25.join(dir, ".vercel/output") : path25.join(dir, "dist/.output");
9028
9461
  await mkdir3(outputDir, { recursive: true });
9029
- const outputFile = path24.join(outputDir, "config.json");
9462
+ const outputFile = path25.join(outputDir, "config.json");
9030
9463
  await writeFile3(outputFile, JSON.stringify(output, null, 2), "utf-8");
9031
9464
  if (process.env.VERCEL) {
9032
9465
  console.log("Wrote Vercel output to", outputDir);
@@ -9038,7 +9471,7 @@ init_logger();
9038
9471
  init_file_exists();
9039
9472
  import { readFile as readFile2, rm } from "node:fs/promises";
9040
9473
  import os from "node:os";
9041
- import path27 from "node:path";
9474
+ import path28 from "node:path";
9042
9475
  import { pathToFileURL } from "node:url";
9043
9476
  import { createIndex } from "pagefind";
9044
9477
  import colors7 from "picocolors";
@@ -9080,7 +9513,7 @@ function throttle(fn) {
9080
9513
  init_joinUrl();
9081
9514
  import { createWriteStream, existsSync as existsSync2 } from "node:fs";
9082
9515
  import { mkdir as mkdir4 } from "node:fs/promises";
9083
- import path25 from "node:path";
9516
+ import path26 from "node:path";
9084
9517
  import colors5 from "picocolors";
9085
9518
  import { SitemapStream } from "sitemap";
9086
9519
  async function generateSitemap({
@@ -9094,11 +9527,11 @@ async function generateSitemap({
9094
9527
  return;
9095
9528
  }
9096
9529
  const sitemap = new SitemapStream({ hostname: config2.siteUrl });
9097
- const outputDir = path25.resolve(baseOutputDir, config2.outDir ?? "");
9530
+ const outputDir = path26.resolve(baseOutputDir, config2.outDir ?? "");
9098
9531
  if (!existsSync2(outputDir)) {
9099
9532
  await mkdir4(outputDir, { recursive: true });
9100
9533
  }
9101
- const sitemapOutputPath = path25.join(outputDir, "sitemap.xml");
9534
+ const sitemapOutputPath = path26.join(outputDir, "sitemap.xml");
9102
9535
  const writeStream = createWriteStream(sitemapOutputPath);
9103
9536
  sitemap.pipe(writeStream);
9104
9537
  let lastmod;
@@ -9128,14 +9561,14 @@ async function generateSitemap({
9128
9561
 
9129
9562
  // src/vite/prerender/utils.ts
9130
9563
  init_joinUrl();
9131
- var resolveRoutePath = (path39) => {
9132
- const segments = path39.split("/");
9564
+ var resolveRoutePath = (path40) => {
9565
+ const segments = path40.split("/");
9133
9566
  if (segments.some((s) => s.startsWith(":") && !s.endsWith("?"))) {
9134
9567
  return void 0;
9135
9568
  }
9136
9569
  return segments.filter((s) => !s.startsWith(":")).join("/") || void 0;
9137
9570
  };
9138
- var isSkipped = (path39) => path39.includes("*") || /^\d+$/.test(path39);
9571
+ var isSkipped = (path40) => path40.includes("*") || /^\d+$/.test(path40);
9139
9572
  var resolveRoutes = (routes, parentPath = "") => routes.flatMap((route) => {
9140
9573
  if (route.path && isSkipped(route.path)) return [];
9141
9574
  const routePath = route.path ? resolveRoutePath(route.path) : void 0;
@@ -9184,12 +9617,12 @@ var prerender = async ({
9184
9617
  serverConfigFilename,
9185
9618
  writeRedirects = true
9186
9619
  }) => {
9187
- const distDir = path27.join(dir, "dist", basePath);
9620
+ const distDir = path28.join(dir, "dist", basePath);
9188
9621
  const serverConfigPath = pathToFileURL(
9189
- path27.join(distDir, "server", serverConfigFilename)
9622
+ path28.join(distDir, "server", serverConfigFilename)
9190
9623
  ).href;
9191
9624
  const entryServerPath = pathToFileURL(
9192
- path27.join(distDir, "server/entry.server.js")
9625
+ path28.join(distDir, "server/entry.server.js")
9193
9626
  ).href;
9194
9627
  const rawConfig = await import(serverConfigPath).then(
9195
9628
  (m) => m.default
@@ -9274,7 +9707,7 @@ var prerender = async ({
9274
9707
  })
9275
9708
  );
9276
9709
  const pagefindWriteResult = await pagefindIndex?.writeFiles({
9277
- outputPath: path27.join(distDir, "pagefind")
9710
+ outputPath: path28.join(distDir, "pagefind")
9278
9711
  });
9279
9712
  const seconds = ((performance.now() - start) / 1e3).toFixed(1);
9280
9713
  const message = `\u2713 finished prerendering ${paths.length} routes in ${seconds} seconds using ${maxThreads} workers`;
@@ -9306,7 +9739,7 @@ var prerender = async ({
9306
9739
  const { generateLlmsTxtFiles: generateLlmsTxtFiles2 } = await Promise.resolve().then(() => (init_llms(), llms_exports));
9307
9740
  const docsConfig = DocsConfigSchema2.parse(config2.docs);
9308
9741
  const llmsConfig = docsConfig.llms ?? {};
9309
- const markdownInfoPath = path27.join(
9742
+ const markdownInfoPath = path28.join(
9310
9743
  dir,
9311
9744
  "node_modules/.apitogo/markdown-info.json"
9312
9745
  );
@@ -9397,7 +9830,7 @@ async function runBuild(options) {
9397
9830
  html,
9398
9831
  basePath: config2.basePath
9399
9832
  });
9400
- await rm2(path28.join(clientOutDir, "index.html"), { force: true });
9833
+ await rm2(path29.join(clientOutDir, "index.html"), { force: true });
9401
9834
  } else {
9402
9835
  await runPrerender({
9403
9836
  dir,
@@ -9421,7 +9854,7 @@ var runPrerender = async (options) => {
9421
9854
  serverConfigFilename,
9422
9855
  writeRedirects: process.env.VERCEL === void 0
9423
9856
  });
9424
- const indexHtml = path28.join(clientOutDir, "index.html");
9857
+ const indexHtml = path29.join(clientOutDir, "index.html");
9425
9858
  if (!workerResults.find((r) => r.outputPath === indexHtml)) {
9426
9859
  await writeFile5(indexHtml, html, "utf-8");
9427
9860
  }
@@ -9431,15 +9864,15 @@ var runPrerender = async (options) => {
9431
9864
  for (const statusPage of statusPages) {
9432
9865
  await rename(
9433
9866
  statusPage,
9434
- path28.join(dir, DIST_DIR, path28.basename(statusPage))
9867
+ path29.join(dir, DIST_DIR, path29.basename(statusPage))
9435
9868
  );
9436
9869
  }
9437
9870
  await rm2(serverOutDir, { recursive: true, force: true });
9438
9871
  if (process.env.VERCEL) {
9439
- await mkdir5(path28.join(dir, ".vercel/output/static"), { recursive: true });
9872
+ await mkdir5(path29.join(dir, ".vercel/output/static"), { recursive: true });
9440
9873
  await rename(
9441
- path28.join(dir, DIST_DIR),
9442
- path28.join(dir, ".vercel/output/static")
9874
+ path29.join(dir, DIST_DIR),
9875
+ path29.join(dir, ".vercel/output/static")
9443
9876
  );
9444
9877
  }
9445
9878
  await writeOutput(dir, {
@@ -9449,7 +9882,7 @@ var runPrerender = async (options) => {
9449
9882
  });
9450
9883
  if (ZuploEnv.isZuplo && issuer) {
9451
9884
  await writeFile5(
9452
- path28.join(dir, DIST_DIR, ".output/zuplo.json"),
9885
+ path29.join(dir, DIST_DIR, ".output/zuplo.json"),
9453
9886
  JSON.stringify({ issuer }, null, 2),
9454
9887
  "utf-8"
9455
9888
  );
@@ -9461,10 +9894,10 @@ var runPrerender = async (options) => {
9461
9894
  };
9462
9895
  var bundleSSREntry = async (options) => {
9463
9896
  const { dir, adapter, serverOutDir, serverConfigFilename, html, basePath } = options;
9464
- const tempEntryPath = path28.join(dir, "__ssr-entry.ts");
9897
+ const tempEntryPath = path29.join(dir, "__ssr-entry.ts");
9465
9898
  const packageRoot = getZudokuRootDir();
9466
9899
  const templateContent = await readFile3(
9467
- path28.join(packageRoot, "src/vite/ssr-templates", `${adapter}.ts`),
9900
+ path29.join(packageRoot, "src/vite/ssr-templates", `${adapter}.ts`),
9468
9901
  "utf-8"
9469
9902
  );
9470
9903
  const entryContent = templateContent.replace('"__TEMPLATE__"', JSON.stringify(html)).replace('"__CONFIG_FILE__"', JSON.stringify(`./${serverConfigFilename}`)).replace(
@@ -9479,9 +9912,9 @@ var bundleSSREntry = async (options) => {
9479
9912
  platform: adapter === "node" ? "node" : "neutral",
9480
9913
  target: "es2022",
9481
9914
  format: "esm",
9482
- outfile: path28.join(serverOutDir, "entry.js"),
9915
+ outfile: path29.join(serverOutDir, "entry.js"),
9483
9916
  external: ["./entry.server.js", `./${serverConfigFilename}`],
9484
- nodePaths: [path28.join(packageRoot, "node_modules")],
9917
+ nodePaths: [path29.join(packageRoot, "node_modules")],
9485
9918
  banner: { js: "// Bundled SSR entry" }
9486
9919
  });
9487
9920
  } finally {
@@ -9536,11 +9969,11 @@ function textOrJson(text) {
9536
9969
  init_package_json();
9537
9970
 
9538
9971
  // src/cli/preview/handler.ts
9539
- import path29 from "node:path";
9972
+ import path30 from "node:path";
9540
9973
  import { preview as vitePreview } from "vite";
9541
9974
  var DEFAULT_PREVIEW_PORT = 4e3;
9542
9975
  async function preview(argv) {
9543
- const dir = path29.resolve(process.cwd(), argv.dir);
9976
+ const dir = path30.resolve(process.cwd(), argv.dir);
9544
9977
  const viteConfig = await getViteConfig(dir, {
9545
9978
  command: "serve",
9546
9979
  mode: "production",
@@ -9581,7 +10014,7 @@ async function build(argv) {
9581
10014
  printDiagnosticsToConsole("");
9582
10015
  printDiagnosticsToConsole("");
9583
10016
  }
9584
- const dir = path30.resolve(process.cwd(), argv.dir);
10017
+ const dir = path31.resolve(process.cwd(), argv.dir);
9585
10018
  try {
9586
10019
  await runBuild({
9587
10020
  dir,
@@ -9741,7 +10174,7 @@ var build_default = {
9741
10174
  // src/cli/configure-github-workflow/handler.ts
9742
10175
  import { constants } from "node:fs";
9743
10176
  import { access, mkdir as mkdir6, writeFile as writeFile6 } from "node:fs/promises";
9744
- import path31 from "node:path";
10177
+ import path32 from "node:path";
9745
10178
  var APITOGO_DEPLOY_WORKFLOW_YAML = `name: Build and Deploy
9746
10179
 
9747
10180
  on:
@@ -9852,9 +10285,9 @@ jobs:
9852
10285
  run: apitogo deploy --deployment-token="$APITOGO_TOKEN" --json-only
9853
10286
  `;
9854
10287
  async function configureGithubWorkflow(argv) {
9855
- const dir = path31.resolve(process.cwd(), argv.dir);
9856
- const workflowDir = path31.join(dir, ".github", "workflows");
9857
- const workflowPath = path31.join(workflowDir, "apitogo-deploy.yml");
10288
+ const dir = path32.resolve(process.cwd(), argv.dir);
10289
+ const workflowDir = path32.join(dir, ".github", "workflows");
10290
+ const workflowPath = path32.join(workflowDir, "apitogo-deploy.yml");
9858
10291
  try {
9859
10292
  try {
9860
10293
  await access(workflowPath, constants.F_OK);
@@ -9927,14 +10360,14 @@ function applyJsonOnlyDeployQuietMode() {
9927
10360
 
9928
10361
  // src/cli/deploy/handler.ts
9929
10362
  import { access as access2, readFile as readFile4 } from "node:fs/promises";
9930
- import path32 from "node:path";
10363
+ import path33 from "node:path";
9931
10364
  import { create as createTar } from "tar";
9932
10365
  var DEPLOY_ENDPOINT = "https://deploy-server-dotnet2-b3fkcaaraydbckfe.canadacentral-01.azurewebsites.net/deploy";
9933
10366
  var ARCHIVE_NAME = "dist.tgz";
9934
10367
  var createDeploymentArchive = async (dir) => {
9935
- const distDir = path32.join(dir, "dist");
10368
+ const distDir = path33.join(dir, "dist");
9936
10369
  await access2(distDir);
9937
- const archivePath = path32.join(dir, ARCHIVE_NAME);
10370
+ const archivePath = path33.join(dir, ARCHIVE_NAME);
9938
10371
  await createTar(
9939
10372
  {
9940
10373
  cwd: dir,
@@ -9948,7 +10381,7 @@ var createDeploymentArchive = async (dir) => {
9948
10381
  };
9949
10382
  async function deploy(argv) {
9950
10383
  await build({ ...argv, preview: void 0 });
9951
- const dir = path32.resolve(process.cwd(), argv.dir);
10384
+ const dir = path33.resolve(process.cwd(), argv.dir);
9952
10385
  const deploymentToken = argv.deploymentToken?.trim() || process.env.npm_config_deployment_token?.trim();
9953
10386
  const env = argv.env?.trim() || process.env.npm_config_env?.trim() || "production";
9954
10387
  try {
@@ -9961,7 +10394,7 @@ async function deploy(argv) {
9961
10394
  const archivePath = await createDeploymentArchive(dir);
9962
10395
  if (!isJsonOnlyDeployEnv()) {
9963
10396
  printDiagnosticsToConsole(
9964
- `Uploading ${path32.basename(archivePath)} to ${env}...`
10397
+ `Uploading ${path33.basename(archivePath)} to ${env}...`
9965
10398
  );
9966
10399
  }
9967
10400
  const archiveBuffer = await readFile4(archivePath);
@@ -9969,7 +10402,7 @@ async function deploy(argv) {
9969
10402
  formData.append(
9970
10403
  "file",
9971
10404
  new Blob([archiveBuffer], { type: "application/gzip" }),
9972
- path32.basename(archivePath)
10405
+ path33.basename(archivePath)
9973
10406
  );
9974
10407
  formData.append("deploymentToken", deploymentToken);
9975
10408
  formData.append("env", env);
@@ -10054,14 +10487,14 @@ var deploy_default = {
10054
10487
 
10055
10488
  // src/cli/dev/handler.ts
10056
10489
  init_joinUrl();
10057
- import path35 from "node:path";
10490
+ import path36 from "node:path";
10058
10491
 
10059
10492
  // src/vite/dev-server.ts
10060
10493
  init_logger();
10061
10494
  import fs4 from "node:fs/promises";
10062
10495
  import http from "node:http";
10063
10496
  import https from "node:https";
10064
- import path34 from "node:path";
10497
+ import path35 from "node:path";
10065
10498
  import { createHttpTerminator } from "http-terminator";
10066
10499
  import {
10067
10500
  createServer as createViteServer,
@@ -10094,7 +10527,7 @@ init_loader();
10094
10527
  // src/vite/pagefind-dev-index.ts
10095
10528
  init_invariant();
10096
10529
  init_joinUrl();
10097
- import path33 from "node:path";
10530
+ import path34 from "node:path";
10098
10531
  import { createIndex as createIndex2 } from "pagefind";
10099
10532
  import { isRunnableDevEnvironment } from "vite";
10100
10533
  async function* buildPagefindDevIndex(vite, config2) {
@@ -10147,7 +10580,7 @@ async function* buildPagefindDevIndex(vite, config2) {
10147
10580
  path: urlPath
10148
10581
  };
10149
10582
  }
10150
- const outputPath = path33.join(vite.config.publicDir, "pagefind");
10583
+ const outputPath = path34.join(vite.config.publicDir, "pagefind");
10151
10584
  await pagefindIndex.writeFiles({ outputPath });
10152
10585
  yield { type: "complete", success: true, indexed };
10153
10586
  }
@@ -10166,9 +10599,9 @@ var DevServer = class {
10166
10599
  this.protocol = "https";
10167
10600
  const { dir } = this.options;
10168
10601
  const [key, cert, ca] = await Promise.all([
10169
- fs4.readFile(path34.resolve(dir, config2.https.key)),
10170
- fs4.readFile(path34.resolve(dir, config2.https.cert)),
10171
- config2.https.ca ? fs4.readFile(path34.resolve(dir, config2.https.ca)) : void 0
10602
+ fs4.readFile(path35.resolve(dir, config2.https.key)),
10603
+ fs4.readFile(path35.resolve(dir, config2.https.cert)),
10604
+ config2.https.ca ? fs4.readFile(path35.resolve(dir, config2.https.ca)) : void 0
10172
10605
  ]);
10173
10606
  return https.createServer({ key, cert, ca });
10174
10607
  }
@@ -10185,7 +10618,7 @@ var DevServer = class {
10185
10618
  );
10186
10619
  const server = await this.createNodeServer(config2);
10187
10620
  if (config2.search?.type === "pagefind" && viteConfig.publicDir !== false) {
10188
- const publicRoot = path34.resolve(
10621
+ const publicRoot = path35.resolve(
10189
10622
  this.options.dir,
10190
10623
  typeof viteConfig.publicDir === "string" ? viteConfig.publicDir : "public"
10191
10624
  );
@@ -10202,7 +10635,7 @@ var DevServer = class {
10202
10635
  // built-in transform middleware which would treat the path as a static asset.
10203
10636
  name: "apitogo:entry-client",
10204
10637
  configureServer(server2) {
10205
- const entryPath = path34.posix.join(
10638
+ const entryPath = path35.posix.join(
10206
10639
  server2.config.base,
10207
10640
  "/__z/entry.client.tsx"
10208
10641
  );
@@ -10367,7 +10800,7 @@ init_package_json();
10367
10800
  async function dev(argv) {
10368
10801
  const packageJson2 = getZudokuPackageJson();
10369
10802
  process.env.NODE_ENV = "development";
10370
- const dir = path35.resolve(process.cwd(), argv.dir);
10803
+ const dir = path36.resolve(process.cwd(), argv.dir);
10371
10804
  const server = new DevServer({
10372
10805
  dir,
10373
10806
  argPort: argv.port,
@@ -10452,14 +10885,14 @@ var dev_default = {
10452
10885
  // src/cli/make-config/handler.ts
10453
10886
  import { constants as constants3 } from "node:fs";
10454
10887
  import { access as access4, mkdir as mkdir7, readFile as readFile6, writeFile as writeFile8 } from "node:fs/promises";
10455
- import path37 from "node:path";
10888
+ import path38 from "node:path";
10456
10889
  import { glob as glob5 } from "glob";
10457
10890
 
10458
10891
  // src/cli/make-config/scaffold-project.ts
10459
10892
  init_package_json();
10460
10893
  import { constants as constants2 } from "node:fs";
10461
10894
  import { access as access3, readFile as readFile5, writeFile as writeFile7 } from "node:fs/promises";
10462
- import path36 from "node:path";
10895
+ import path37 from "node:path";
10463
10896
  import { glob as glob4 } from "glob";
10464
10897
  var OPENAPI_GLOBS = [
10465
10898
  "apis/openapi.json",
@@ -10519,9 +10952,9 @@ var findMatchingCurly = (source, startIndex) => {
10519
10952
  }
10520
10953
  throw new Error("Could not find matching closing brace for object.");
10521
10954
  };
10522
- var toPosix = (p) => p.split(path36.sep).join("/");
10955
+ var toPosix = (p) => p.split(path37.sep).join("/");
10523
10956
  var sanitizePackageName = (dir) => {
10524
- const base = path36.basename(path36.resolve(dir));
10957
+ const base = path37.basename(path37.resolve(dir));
10525
10958
  const s = base.toLowerCase().replace(/[^a-z0-9-_.]/g, "-").replace(/^-+|-+$/g, "");
10526
10959
  return s || "apitogo-site";
10527
10960
  };
@@ -10531,7 +10964,7 @@ var apitogoVersionRange = () => {
10531
10964
  };
10532
10965
  async function findOpenApiSpecPath(dir) {
10533
10966
  for (const rel of OPENAPI_GLOBS) {
10534
- const full = path36.join(dir, rel);
10967
+ const full = path37.join(dir, rel);
10535
10968
  try {
10536
10969
  await access3(full, constants2.R_OK);
10537
10970
  return toPosix(rel);
@@ -10546,7 +10979,7 @@ async function findOpenApiSpecPath(dir) {
10546
10979
  return extra[0] ? toPosix(extra[0]) : null;
10547
10980
  }
10548
10981
  async function ensurePackageJson(dir) {
10549
- const pkgPath = path36.join(dir, "package.json");
10982
+ const pkgPath = path37.join(dir, "package.json");
10550
10983
  const apitogoVer = apitogoVersionRange();
10551
10984
  const baseDeps = {
10552
10985
  react: ">=19.0.0",
@@ -10609,7 +11042,7 @@ async function ensurePackageJson(dir) {
10609
11042
  return false;
10610
11043
  }
10611
11044
  async function ensureTsconfigJson(dir) {
10612
- const tsPath = path36.join(dir, "tsconfig.json");
11045
+ const tsPath = path37.join(dir, "tsconfig.json");
10613
11046
  try {
10614
11047
  await access3(tsPath, constants2.R_OK);
10615
11048
  return false;
@@ -10691,7 +11124,7 @@ var CONFIG_FILENAMES = [
10691
11124
  ];
10692
11125
  var DEFAULT_NEW_CONFIG_FILENAME = "apitogo.config.tsx";
10693
11126
  var createTreeNode = () => ({ docs: [], children: /* @__PURE__ */ new Map() });
10694
- var toPosixPath2 = (value) => value.split(path37.sep).join(path37.posix.sep);
11127
+ var toPosixPath2 = (value) => value.split(path38.sep).join(path38.posix.sep);
10695
11128
  var toRoutePath = (relativeFile, pagesDir) => {
10696
11129
  const relativeNoExt = relativeFile.replace(/\.mdx?$/, "");
10697
11130
  const withoutPagesPrefix = relativeNoExt.replace(
@@ -10936,7 +11369,7 @@ export default config;
10936
11369
  `;
10937
11370
  };
10938
11371
  var ensureApitogoDeployWorkflow = async (dir) => {
10939
- const workflowPath = path37.join(
11372
+ const workflowPath = path38.join(
10940
11373
  dir,
10941
11374
  ".github",
10942
11375
  "workflows",
@@ -10947,13 +11380,13 @@ var ensureApitogoDeployWorkflow = async (dir) => {
10947
11380
  return false;
10948
11381
  } catch {
10949
11382
  }
10950
- await mkdir7(path37.join(dir, ".github", "workflows"), { recursive: true });
11383
+ await mkdir7(path38.join(dir, ".github", "workflows"), { recursive: true });
10951
11384
  await writeFile8(workflowPath, APITOGO_DEPLOY_WORKFLOW_YAML, "utf8");
10952
11385
  return true;
10953
11386
  };
10954
11387
  var findExistingConfigPath = async (dir) => {
10955
11388
  for (const filename of CONFIG_FILENAMES) {
10956
- const fullPath = path37.join(dir, filename);
11389
+ const fullPath = path38.join(dir, filename);
10957
11390
  try {
10958
11391
  await readFile6(fullPath, "utf8");
10959
11392
  return fullPath;
@@ -10963,7 +11396,7 @@ var findExistingConfigPath = async (dir) => {
10963
11396
  return null;
10964
11397
  };
10965
11398
  async function makeConfig(argv) {
10966
- const dir = path37.resolve(process.cwd(), argv.dir);
11399
+ const dir = path38.resolve(process.cwd(), argv.dir);
10967
11400
  const pagesDir = toPosixPath2(
10968
11401
  argv.pagesDir.replace(/^[./]+/, "").replace(/\/+$/, "")
10969
11402
  );
@@ -10982,7 +11415,7 @@ async function makeConfig(argv) {
10982
11415
  let configPath = await findExistingConfigPath(dir);
10983
11416
  let createdNew = false;
10984
11417
  if (!configPath) {
10985
- configPath = path37.join(dir, DEFAULT_NEW_CONFIG_FILENAME);
11418
+ configPath = path38.join(dir, DEFAULT_NEW_CONFIG_FILENAME);
10986
11419
  await writeFile8(
10987
11420
  configPath,
10988
11421
  buildNewConfigContents(pagesDir, openApiSpecPath),
@@ -11023,7 +11456,7 @@ async function makeConfig(argv) {
11023
11456
  await writeFile8(configPath, withRedirects, "utf8");
11024
11457
  const action = createdNew ? "Initialized" : "Updated";
11025
11458
  printResultToConsole(
11026
- `${action} ${path37.basename(configPath)} from ${pagesDir}/ (navigation and redirects; other top-level settings preserved unless newly scaffolded).`
11459
+ `${action} ${path38.basename(configPath)} from ${pagesDir}/ (navigation and redirects; other top-level settings preserved unless newly scaffolded).`
11027
11460
  );
11028
11461
  const createdWorkflow = await ensureApitogoDeployWorkflow(dir);
11029
11462
  if (createdWorkflow) {
@@ -11216,12 +11649,12 @@ function box(message, {
11216
11649
 
11217
11650
  // src/cli/common/xdg/lib.ts
11218
11651
  import { homedir } from "node:os";
11219
- import path38 from "node:path";
11652
+ import path39 from "node:path";
11220
11653
  function defineDirectoryWithFallback(xdgName, fallback) {
11221
11654
  if (process.env[xdgName]) {
11222
11655
  return process.env[xdgName];
11223
11656
  } else {
11224
- return path38.join(homedir(), fallback);
11657
+ return path39.join(homedir(), fallback);
11225
11658
  }
11226
11659
  }
11227
11660
  var XDG_CONFIG_HOME = defineDirectoryWithFallback(
@@ -11236,15 +11669,15 @@ var XDG_STATE_HOME = defineDirectoryWithFallback(
11236
11669
  "XDG_DATA_HOME",
11237
11670
  ".local/state"
11238
11671
  );
11239
- var ZUDOKU_XDG_CONFIG_HOME = path38.join(
11672
+ var ZUDOKU_XDG_CONFIG_HOME = path39.join(
11240
11673
  XDG_CONFIG_HOME,
11241
11674
  CLI_XDG_FOLDER_NAME
11242
11675
  );
11243
- var ZUDOKU_XDG_DATA_HOME = path38.join(
11676
+ var ZUDOKU_XDG_DATA_HOME = path39.join(
11244
11677
  XDG_DATA_HOME,
11245
11678
  CLI_XDG_FOLDER_NAME
11246
11679
  );
11247
- var ZUDOKU_XDG_STATE_HOME = path38.join(
11680
+ var ZUDOKU_XDG_STATE_HOME = path39.join(
11248
11681
  XDG_STATE_HOME,
11249
11682
  CLI_XDG_FOLDER_NAME
11250
11683
  );