@lukoweb/apitogo 0.1.94 → 0.1.96

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/cli.js CHANGED
@@ -10,18 +10,18 @@ var __export = (target, all) => {
10
10
 
11
11
  // src/cli/common/package-json.ts
12
12
  import { readFileSync } from "node:fs";
13
- import path18 from "node:path";
13
+ import path19 from "node:path";
14
14
  import { fileURLToPath } from "node:url";
15
15
  var getPackageJsonPath, getPackageJson, getZudokuPackageJson, getZudokuRootDir;
16
16
  var init_package_json = __esm({
17
17
  "src/cli/common/package-json.ts"() {
18
18
  getPackageJsonPath = (pkg) => fileURLToPath(import.meta.resolve(`${pkg}/package.json`)).replaceAll(
19
- path18.sep,
20
- path18.posix.sep
19
+ path19.sep,
20
+ path19.posix.sep
21
21
  );
22
22
  getPackageJson = (pkgPath) => JSON.parse(readFileSync(pkgPath, "utf-8"));
23
23
  getZudokuPackageJson = () => getPackageJson(getPackageJsonPath("@lukoweb/apitogo"));
24
- getZudokuRootDir = () => path18.dirname(getPackageJsonPath("@lukoweb/apitogo"));
24
+ getZudokuRootDir = () => path19.dirname(getPackageJsonPath("@lukoweb/apitogo"));
25
25
  }
26
26
  });
27
27
 
@@ -654,12 +654,12 @@ var init_apitogo_config_core = __esm({
654
654
 
655
655
  // src/config/apitogo-config-loader.node.ts
656
656
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
657
- import path19 from "node:path";
657
+ import path20 from "node:path";
658
658
  function loadApitogoConfig(rootDir = process.cwd()) {
659
- const configPath = path19.join(path19.resolve(rootDir), APITOGO_CONFIG_FILENAME2);
659
+ const configPath = path20.join(path20.resolve(rootDir), APITOGO_CONFIG_FILENAME2);
660
660
  if (!existsSync2(configPath)) {
661
661
  throw new Error(
662
- `Missing ${APITOGO_CONFIG_FILENAME2} in ${path19.resolve(rootDir)}`
662
+ `Missing ${APITOGO_CONFIG_FILENAME2} in ${path20.resolve(rootDir)}`
663
663
  );
664
664
  }
665
665
  const raw = readFileSync2(configPath, "utf8");
@@ -734,7 +734,7 @@ import { stat } from "node:fs/promises";
734
734
  var fileExists;
735
735
  var init_file_exists = __esm({
736
736
  "src/config/file-exists.ts"() {
737
- fileExists = (path66) => stat(path66).then(() => true).catch(() => false);
737
+ fileExists = (path69) => stat(path69).then(() => true).catch(() => false);
738
738
  }
739
739
  });
740
740
 
@@ -978,7 +978,7 @@ var init_landing_manifest = __esm({
978
978
  });
979
979
 
980
980
  // src/config/local-manifest.ts
981
- import path20 from "node:path";
981
+ import path21 from "node:path";
982
982
  import { z as z4 } from "zod";
983
983
  function isPricingEnabled(manifest) {
984
984
  return manifest?.pricing?.enabled === true;
@@ -1028,8 +1028,8 @@ function resolveManifestEnv(viteMode) {
1028
1028
  return viteMode === "production" ? "production" : "development";
1029
1029
  }
1030
1030
  function manifestPathsForEnv(rootDir, _env) {
1031
- const resolvedRoot = path20.resolve(rootDir);
1032
- const configPath = path20.join(resolvedRoot, APITOGO_CONFIG_FILENAME2);
1031
+ const resolvedRoot = path21.resolve(rootDir);
1032
+ const configPath = path21.join(resolvedRoot, APITOGO_CONFIG_FILENAME2);
1033
1033
  return {
1034
1034
  basePath: configPath,
1035
1035
  overridePath: configPath,
@@ -1705,7 +1705,7 @@ var init_shadcn_registry = __esm({
1705
1705
 
1706
1706
  // src/vite/plugin-theme.ts
1707
1707
  import { createRequire as createRequire2 } from "node:module";
1708
- import path21 from "node:path";
1708
+ import path22 from "node:path";
1709
1709
  import { normalizeTheme } from "shiki";
1710
1710
  var THEME_VARIABLES, uncamelize, processColorValue, generateCss, generateRegistryCss, processCustomCss, MAIN_REPLACE, DEFAULT_THEME_REPLACE, GOOGLE_FONTS, getGoogleFontUrl, processFont, processFontConfig, DEFAULT_FONT_SANS, DEFAULT_FONT_MONO, DEFAULT_FONT_HEADING, processFonts, MODULE_SOURCE_PACKAGES, resolveModuleSourceDirs, virtualModuleId, resolvedVirtualModuleId, viteThemePlugin;
1711
1711
  var init_plugin_theme = __esm({
@@ -1884,7 +1884,7 @@ var init_plugin_theme = __esm({
1884
1884
  resolveModuleSourceDirs = (config2) => {
1885
1885
  if (config2.__meta.mode === "internal") {
1886
1886
  return MODULE_SOURCE_PACKAGES.map(
1887
- (pkg) => path21.join(
1887
+ (pkg) => path22.join(
1888
1888
  config2.__meta.moduleDir,
1889
1889
  "..",
1890
1890
  pkg.replace("@lukoweb/apitogo-", ""),
@@ -1893,12 +1893,12 @@ var init_plugin_theme = __esm({
1893
1893
  );
1894
1894
  }
1895
1895
  const require2 = createRequire2(
1896
- path21.join(config2.__meta.rootDir, "package.json")
1896
+ path22.join(config2.__meta.rootDir, "package.json")
1897
1897
  );
1898
1898
  const dirs = [];
1899
1899
  for (const pkg of MODULE_SOURCE_PACKAGES) {
1900
1900
  try {
1901
- dirs.push(path21.dirname(require2.resolve(pkg)));
1901
+ dirs.push(path22.dirname(require2.resolve(pkg)));
1902
1902
  } catch {
1903
1903
  }
1904
1904
  }
@@ -2024,7 +2024,7 @@ ${rootVars.join("\n")}
2024
2024
  ...config2.__meta.dependencies,
2025
2025
  ...config2.__pluginDirs ?? [],
2026
2026
  ...resolveModuleSourceDirs(config2)
2027
- ].map((file) => path21.relative(path21.dirname(id), file))
2027
+ ].map((file) => path22.relative(path22.dirname(id), file))
2028
2028
  );
2029
2029
  const code = [...files].map((file) => `@source "${file}";`);
2030
2030
  code.push("@theme inline {");
@@ -4866,7 +4866,7 @@ var init_ZudokuConfig = __esm({
4866
4866
 
4867
4867
  // src/config/loader.ts
4868
4868
  import { stat as stat2 } from "node:fs/promises";
4869
- import path22 from "node:path";
4869
+ import path23 from "node:path";
4870
4870
  import colors3 from "picocolors";
4871
4871
  import {
4872
4872
  runnerImport,
@@ -4893,7 +4893,7 @@ function mergeJsonConfigWithRuntimeOverrides(fileConfig, importedConfig) {
4893
4893
  }
4894
4894
  async function getConfigFilePath(rootDir) {
4895
4895
  for (const fileName of zudokuConfigFiles) {
4896
- const filepath = path22.join(rootDir, fileName);
4896
+ const filepath = path23.join(rootDir, fileName);
4897
4897
  if (await fileExists(filepath)) {
4898
4898
  return filepath;
4899
4899
  }
@@ -5126,7 +5126,7 @@ __export(llms_exports, {
5126
5126
  generateLlmsTxtFiles: () => generateLlmsTxtFiles
5127
5127
  });
5128
5128
  import { writeFile as writeFile9 } from "node:fs/promises";
5129
- import path44 from "node:path";
5129
+ import path45 from "node:path";
5130
5130
  import colors7 from "picocolors";
5131
5131
  async function generateLlmsTxtFiles({
5132
5132
  markdownFileInfos,
@@ -5161,7 +5161,7 @@ async function generateLlmsTxtFiles({
5161
5161
  }
5162
5162
  }
5163
5163
  const llmsTxt2 = llmsTxtParts.join("\n");
5164
- await writeFile9(path44.join(baseOutputDir, "llms.txt"), llmsTxt2, "utf-8");
5164
+ await writeFile9(path45.join(baseOutputDir, "llms.txt"), llmsTxt2, "utf-8");
5165
5165
  if (process.env.APITOGO_JSON_ONLY !== "1") {
5166
5166
  console.log(colors7.blue("\u2713 generated llms.txt"));
5167
5167
  }
@@ -5189,7 +5189,7 @@ ${info.content}
5189
5189
  }
5190
5190
  const llmsFull = llmsFullParts.join("\n");
5191
5191
  await writeFile9(
5192
- path44.join(baseOutputDir, "llms-full.txt"),
5192
+ path45.join(baseOutputDir, "llms-full.txt"),
5193
5193
  llmsFull,
5194
5194
  "utf-8"
5195
5195
  );
@@ -5315,7 +5315,7 @@ async function shutdownAnalytics() {
5315
5315
  }
5316
5316
 
5317
5317
  // src/cli/apply/handler.ts
5318
- import path17 from "node:path";
5318
+ import path18 from "node:path";
5319
5319
 
5320
5320
  // src/cli/common/output.ts
5321
5321
  import * as Sentry from "@sentry/node";
@@ -5504,8 +5504,8 @@ var PlatformApiClient = class {
5504
5504
  constructor(config2) {
5505
5505
  this.config = config2;
5506
5506
  }
5507
- url(path66) {
5508
- return `${this.config.apiUrl}${path66.startsWith("/") ? path66 : `/${path66}`}`;
5507
+ url(path69) {
5508
+ return `${this.config.apiUrl}${path69.startsWith("/") ? path69 : `/${path69}`}`;
5509
5509
  }
5510
5510
  headers(extra) {
5511
5511
  return {
@@ -5515,9 +5515,9 @@ var PlatformApiClient = class {
5515
5515
  ...extra
5516
5516
  };
5517
5517
  }
5518
- async request(method, path66, init4) {
5518
+ async request(method, path69, init4) {
5519
5519
  const response = await fetchWithRetry(
5520
- this.url(path66),
5520
+ this.url(path69),
5521
5521
  {
5522
5522
  method,
5523
5523
  ...init4,
@@ -5717,15 +5717,15 @@ var PlatformApiClient = class {
5717
5717
  }
5718
5718
  );
5719
5719
  }
5720
- deleteDevPortalPage(projectId, path66) {
5721
- const query = new URLSearchParams({ path: path66 });
5720
+ deleteDevPortalPage(projectId, path69) {
5721
+ const query = new URLSearchParams({ path: path69 });
5722
5722
  return this.request(
5723
5723
  "DELETE",
5724
5724
  `/api/v1/projects/${projectId}/dev-portal/pages/files?${query.toString()}`
5725
5725
  );
5726
5726
  }
5727
- renameDevPortalPage(projectId, path66, newName) {
5728
- const query = new URLSearchParams({ path: path66 });
5727
+ renameDevPortalPage(projectId, path69, newName) {
5728
+ const query = new URLSearchParams({ path: path69 });
5729
5729
  return this.request(
5730
5730
  "POST",
5731
5731
  `/api/v1/projects/${projectId}/dev-portal/pages/files/rename?${query.toString()}`,
@@ -5896,8 +5896,8 @@ var PlatformApiClient = class {
5896
5896
  }
5897
5897
  };
5898
5898
  async function readFileBytes(filePath) {
5899
- const { readFile: readFile18 } = await import("node:fs/promises");
5900
- const buffer = await readFile18(filePath);
5899
+ const { readFile: readFile20 } = await import("node:fs/promises");
5900
+ const buffer = await readFile20(filePath);
5901
5901
  const arrayBuffer = new ArrayBuffer(buffer.byteLength);
5902
5902
  new Uint8Array(arrayBuffer).set(buffer);
5903
5903
  return arrayBuffer;
@@ -7317,8 +7317,8 @@ function normalizeActionKey(actionKey) {
7317
7317
  const trimmed = actionKey.trim();
7318
7318
  if (trimmed.includes(":")) {
7319
7319
  const [method2, ...pathParts] = trimmed.split(":");
7320
- const path67 = pathParts.join(":").trim();
7321
- return `${method2.toLowerCase()}:${path67.startsWith("/") ? path67 : `/${path67}`}`;
7320
+ const path70 = pathParts.join(":").trim();
7321
+ return `${method2.toLowerCase()}:${path70.startsWith("/") ? path70 : `/${path70}`}`;
7322
7322
  }
7323
7323
  const spaceIndex = trimmed.indexOf(" ");
7324
7324
  if (spaceIndex <= 0) {
@@ -7327,8 +7327,8 @@ function normalizeActionKey(actionKey) {
7327
7327
  );
7328
7328
  }
7329
7329
  const method = trimmed.slice(0, spaceIndex).trim().toLowerCase();
7330
- const path66 = trimmed.slice(spaceIndex + 1).trim();
7331
- return `${method}:${path66.startsWith("/") ? path66 : `/${path66}`}`;
7330
+ const path69 = trimmed.slice(spaceIndex + 1).trim();
7331
+ return `${method}:${path69.startsWith("/") ? path69 : `/${path69}`}`;
7332
7332
  }
7333
7333
  async function applyGatewayPublicRoutes(client, projectId, routes, options) {
7334
7334
  const applied = [];
@@ -8793,10 +8793,14 @@ function formatJobStatusResponse(options) {
8793
8793
  }
8794
8794
 
8795
8795
  // src/cli/platform/helpers/openapi.ts
8796
- import { promises as fs3 } from "node:fs";
8797
- import path9 from "node:path";
8796
+ import { promises as fs4 } from "node:fs";
8797
+ import path10 from "node:path";
8798
8798
  import SwaggerParser from "@apidevtools/swagger-parser";
8799
8799
  import YAML2 from "yaml";
8800
+
8801
+ // src/cli/scaffold/discover-openapi-files.ts
8802
+ import { promises as fs3 } from "node:fs";
8803
+ import path9 from "node:path";
8800
8804
  var OPENAPI_BASENAMES = [
8801
8805
  "openapi.yaml",
8802
8806
  "openapi.yml",
@@ -8805,6 +8809,7 @@ var OPENAPI_BASENAMES = [
8805
8809
  "swagger.yml",
8806
8810
  "swagger.json"
8807
8811
  ];
8812
+ var OPENAPI_NOT_FOUND_SUGGESTION = "No OpenAPI file found near the site (checked parent, sibling folders, and the site directory for openapi.yaml|yml|json / swagger.yaml|yml|json). Ask the user for a path, or offer to draft a starter OpenAPI 3 spec from their API description, write it next to the site (e.g. ../openapi.yaml), then call set_dev_portal_openapi.";
8808
8813
  var SKIP_OPENAPI_SEARCH_DIRS = /* @__PURE__ */ new Set([
8809
8814
  "node_modules",
8810
8815
  ".git",
@@ -8816,28 +8821,34 @@ var SKIP_OPENAPI_SEARCH_DIRS = /* @__PURE__ */ new Set([
8816
8821
  ".cache",
8817
8822
  ".apitogo"
8818
8823
  ]);
8819
- async function discoverNearbyOpenApi(siteDirectory) {
8824
+ async function collectFromDir(dir, searchedDirectories, candidates) {
8825
+ const resolved = path9.resolve(dir);
8826
+ if (searchedDirectories.includes(resolved)) {
8827
+ return;
8828
+ }
8829
+ searchedDirectories.push(resolved);
8830
+ for (const name of OPENAPI_BASENAMES) {
8831
+ const candidate = path9.join(resolved, name);
8832
+ try {
8833
+ await fs3.access(candidate);
8834
+ candidates.push(candidate);
8835
+ } catch {
8836
+ }
8837
+ }
8838
+ }
8839
+ async function collectSiteOpenApiFiles(siteDirectory) {
8840
+ const searchedDirectories = [];
8841
+ const candidates = [];
8842
+ await collectFromDir(siteDirectory, searchedDirectories, candidates);
8843
+ return { candidates: [...new Set(candidates)], searchedDirectories };
8844
+ }
8845
+ async function collectNearbyOpenApiFiles(siteDirectory) {
8820
8846
  const site = path9.resolve(siteDirectory);
8821
8847
  const parent = path9.dirname(site);
8822
8848
  const searchedDirectories = [];
8823
8849
  const candidates = [];
8824
- const collectFromDir = async (dir) => {
8825
- const resolved = path9.resolve(dir);
8826
- if (searchedDirectories.includes(resolved)) {
8827
- return;
8828
- }
8829
- searchedDirectories.push(resolved);
8830
- for (const name of OPENAPI_BASENAMES) {
8831
- const candidate = path9.join(resolved, name);
8832
- try {
8833
- await fs3.access(candidate);
8834
- candidates.push(candidate);
8835
- } catch {
8836
- }
8837
- }
8838
- };
8839
8850
  if (parent && parent !== site) {
8840
- await collectFromDir(parent);
8851
+ await collectFromDir(parent, searchedDirectories, candidates);
8841
8852
  try {
8842
8853
  const entries = await fs3.readdir(parent, { withFileTypes: true });
8843
8854
  for (const entry of entries) {
@@ -8848,15 +8859,75 @@ async function discoverNearbyOpenApi(siteDirectory) {
8848
8859
  if (path9.resolve(sibling) === site) {
8849
8860
  continue;
8850
8861
  }
8851
- await collectFromDir(sibling);
8862
+ await collectFromDir(sibling, searchedDirectories, candidates);
8852
8863
  }
8853
8864
  } catch {
8854
8865
  }
8855
8866
  }
8856
- await collectFromDir(site);
8857
- const unique = [...new Set(candidates)];
8867
+ await collectFromDir(site, searchedDirectories, candidates);
8868
+ return { candidates: [...new Set(candidates)], searchedDirectories };
8869
+ }
8870
+ function parseOpenApiObject(doc) {
8871
+ const openapi = doc.openapi;
8872
+ if (typeof openapi !== "string" || !openapi.startsWith("3.")) {
8873
+ return {
8874
+ valid: false,
8875
+ errors: [`OpenAPI 3.x required; found ${String(openapi ?? "missing")}.`]
8876
+ };
8877
+ }
8878
+ const info = doc.info;
8879
+ return {
8880
+ valid: true,
8881
+ version: openapi,
8882
+ title: info?.title,
8883
+ errors: []
8884
+ };
8885
+ }
8886
+ function liteParseOpenApi(content, filePath) {
8887
+ const ext = path9.extname(filePath).toLowerCase();
8888
+ if (ext === ".json") {
8889
+ try {
8890
+ const parsed = JSON.parse(content);
8891
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
8892
+ return {
8893
+ valid: false,
8894
+ errors: ["OpenAPI document must be a JSON object."]
8895
+ };
8896
+ }
8897
+ return parseOpenApiObject(parsed);
8898
+ } catch (err) {
8899
+ return {
8900
+ valid: false,
8901
+ errors: [
8902
+ `Failed to parse OpenAPI document: ${err instanceof Error ? err.message : String(err)}`
8903
+ ]
8904
+ };
8905
+ }
8906
+ }
8907
+ const versionMatch = content.match(
8908
+ /^\s*openapi:\s*['"]?(3\.\d+(?:\.\d+)?)['"]?/m
8909
+ );
8910
+ if (!versionMatch?.[1]) {
8911
+ return {
8912
+ valid: false,
8913
+ errors: ["OpenAPI 3.x required; missing openapi: 3.x field."]
8914
+ };
8915
+ }
8916
+ const infoBlock = content.match(/^\s*info:\s*\n((?:[ \t].*\n)+)/m);
8917
+ const titleMatch = infoBlock?.[1]?.match(/^\s*title:\s*['"]?(.+?)['"]?\s*$/m);
8918
+ return {
8919
+ valid: true,
8920
+ version: versionMatch[1],
8921
+ title: titleMatch?.[1]?.trim(),
8922
+ errors: []
8923
+ };
8924
+ }
8925
+
8926
+ // src/cli/platform/helpers/openapi.ts
8927
+ async function discoverNearbyOpenApi(siteDirectory) {
8928
+ const { candidates, searchedDirectories } = await collectNearbyOpenApiFiles(siteDirectory);
8858
8929
  const invalidCandidates = [];
8859
- for (const candidate of unique) {
8930
+ for (const candidate of candidates) {
8860
8931
  const validation = await validateOpenApiFile(candidate);
8861
8932
  if (validation.valid) {
8862
8933
  return {
@@ -8864,35 +8935,39 @@ async function discoverNearbyOpenApi(siteDirectory) {
8864
8935
  selectedPath: candidate,
8865
8936
  version: validation.version,
8866
8937
  title: validation.title,
8867
- candidates: unique,
8938
+ candidates,
8868
8939
  searchedDirectories
8869
8940
  };
8870
8941
  }
8871
8942
  invalidCandidates.push({ path: candidate, errors: validation.errors });
8872
8943
  }
8873
8944
  return {
8874
- status: unique.length > 0 ? "invalid" : "not_found",
8875
- candidates: unique,
8945
+ status: candidates.length > 0 ? "invalid" : "not_found",
8946
+ candidates,
8876
8947
  searchedDirectories,
8877
8948
  ...invalidCandidates.length > 0 ? { invalidCandidates } : {}
8878
8949
  };
8879
8950
  }
8880
- var OPENAPI_NOT_FOUND_SUGGESTION = "No OpenAPI file found near the site (checked parent, sibling folders, and the site directory for openapi.yaml|yml|json / swagger.yaml|yml|json). Ask the user for a path, or offer to draft a starter OpenAPI 3 spec from their API description, write it next to the site (e.g. ../openapi.yaml), then call set_dev_portal_openapi.";
8881
8951
  async function validateOpenApiFile(filePath) {
8882
- const resolved = path9.resolve(filePath);
8883
- const content = await fs3.readFile(resolved, "utf8");
8884
- const ext = path9.extname(resolved).toLowerCase();
8952
+ const resolved = path10.resolve(filePath);
8953
+ const content = await fs4.readFile(resolved, "utf8");
8954
+ const ext = path10.extname(resolved).toLowerCase();
8885
8955
  let parsed;
8886
8956
  try {
8887
8957
  parsed = ext === ".json" ? JSON.parse(content) : YAML2.parse(content);
8888
8958
  } catch (err) {
8889
8959
  return {
8890
8960
  valid: false,
8891
- errors: [`Failed to parse OpenAPI document: ${err instanceof Error ? err.message : String(err)}`]
8961
+ errors: [
8962
+ `Failed to parse OpenAPI document: ${err instanceof Error ? err.message : String(err)}`
8963
+ ]
8892
8964
  };
8893
8965
  }
8894
8966
  if (!parsed || typeof parsed !== "object") {
8895
- return { valid: false, errors: ["OpenAPI document must be a JSON or YAML object."] };
8967
+ return {
8968
+ valid: false,
8969
+ errors: ["OpenAPI document must be a JSON or YAML object."]
8970
+ };
8896
8971
  }
8897
8972
  const doc = parsed;
8898
8973
  const openapi = doc.openapi;
@@ -8918,14 +8993,14 @@ async function validateOpenApiFile(filePath) {
8918
8993
  }
8919
8994
 
8920
8995
  // src/cli/platform/helpers/zip.ts
8921
- import { createReadStream as createReadStream2, createWriteStream, promises as fs4 } from "node:fs";
8996
+ import { createReadStream as createReadStream2, createWriteStream, promises as fs5 } from "node:fs";
8922
8997
  import { tmpdir as tmpdir2 } from "node:os";
8923
- import path10 from "node:path";
8998
+ import path11 from "node:path";
8924
8999
  import { ZipArchive } from "archiver";
8925
9000
  async function packageBackendDirectory(sourceDirectory) {
8926
- const resolved = path10.resolve(sourceDirectory);
9001
+ const resolved = path11.resolve(sourceDirectory);
8927
9002
  const files = await collectPackageableFiles(resolved);
8928
- const zipPath = path10.join(
9003
+ const zipPath = path11.join(
8929
9004
  tmpdir2(),
8930
9005
  `apitogo-backend-${Date.now()}-${Math.random().toString(36).slice(2)}.zip`
8931
9006
  );
@@ -8937,15 +9012,15 @@ async function packageBackendDirectory(sourceDirectory) {
8937
9012
  output2.on("error", reject);
8938
9013
  archive.pipe(output2);
8939
9014
  for (const rel of files) {
8940
- archive.append(createReadStream2(path10.join(resolved, rel)), { name: rel.split(path10.sep).join("/") });
9015
+ archive.append(createReadStream2(path11.join(resolved, rel)), { name: rel.split(path11.sep).join("/") });
8941
9016
  }
8942
9017
  void archive.finalize();
8943
9018
  });
8944
- const { size } = await fs4.stat(zipPath);
9019
+ const { size } = await fs5.stat(zipPath);
8945
9020
  return { zipPath, byteSize: size };
8946
9021
  }
8947
9022
  async function cleanupZip(zipPath) {
8948
- await fs4.unlink(zipPath).catch(() => void 0);
9023
+ await fs5.unlink(zipPath).catch(() => void 0);
8949
9024
  }
8950
9025
 
8951
9026
  // src/cli/platform/tools/infrastructure.ts
@@ -10363,13 +10438,13 @@ async function resolveProjectIdForPublish(client, config2, args, wait, progress,
10363
10438
  }
10364
10439
 
10365
10440
  // src/cli/platform/tools/dev-portal.ts
10366
- import { promises as fs6 } from "node:fs";
10367
- import path13 from "node:path";
10441
+ import { promises as fs7 } from "node:fs";
10442
+ import path14 from "node:path";
10368
10443
 
10369
10444
  // src/cli/platform/helpers/tarball.ts
10370
- import { createReadStream as createReadStream3, createWriteStream as createWriteStream2, promises as fs5 } from "node:fs";
10445
+ import { createReadStream as createReadStream3, createWriteStream as createWriteStream2, promises as fs6 } from "node:fs";
10371
10446
  import { tmpdir as tmpdir3 } from "node:os";
10372
- import path11 from "node:path";
10447
+ import path12 from "node:path";
10373
10448
  import { TarArchive } from "archiver";
10374
10449
  var DEV_PORTAL_DEPLOY_ARCHIVE_ROOT = "dist";
10375
10450
  function normalizeArchiveRoot(archiveRoot) {
@@ -10380,10 +10455,10 @@ function normalizeArchiveRoot(archiveRoot) {
10380
10455
  return `${trimmed}/`;
10381
10456
  }
10382
10457
  async function packageDirectoryAsTarGz(sourceDirectory, options) {
10383
- const resolved = path11.resolve(sourceDirectory);
10458
+ const resolved = path12.resolve(sourceDirectory);
10384
10459
  const files = await collectPackageableFiles(resolved);
10385
10460
  const entryPrefix = options?.archiveRoot ? normalizeArchiveRoot(options.archiveRoot) : "";
10386
- const archivePath = path11.join(
10461
+ const archivePath = path12.join(
10387
10462
  tmpdir3(),
10388
10463
  `apitogo-docs-${Date.now()}-${Math.random().toString(36).slice(2)}.tgz`
10389
10464
  );
@@ -10395,16 +10470,16 @@ async function packageDirectoryAsTarGz(sourceDirectory, options) {
10395
10470
  output2.on("error", reject);
10396
10471
  archive.pipe(output2);
10397
10472
  for (const rel of files) {
10398
- const entryName = entryPrefix + rel.split(path11.sep).join("/");
10399
- archive.append(createReadStream3(path11.join(resolved, rel)), { name: entryName });
10473
+ const entryName = entryPrefix + rel.split(path12.sep).join("/");
10474
+ archive.append(createReadStream3(path12.join(resolved, rel)), { name: entryName });
10400
10475
  }
10401
10476
  void archive.finalize();
10402
10477
  });
10403
- const { size } = await fs5.stat(archivePath);
10478
+ const { size } = await fs6.stat(archivePath);
10404
10479
  return { archivePath, byteSize: size };
10405
10480
  }
10406
10481
  async function cleanupArchive(archivePath) {
10407
- await fs5.unlink(archivePath).catch(() => void 0);
10482
+ await fs6.unlink(archivePath).catch(() => void 0);
10408
10483
  }
10409
10484
  function isTarGzPath(filePath) {
10410
10485
  const normalized = filePath.toLowerCase();
@@ -10520,7 +10595,7 @@ async function snapshotBackendUpdateJobIds(client, projectId) {
10520
10595
 
10521
10596
  // src/cli/platform/helpers/dev-portal-site-api-url.ts
10522
10597
  import { readdir as readdir2, readFile as readFile6, writeFile as writeFile5 } from "node:fs/promises";
10523
- import path12 from "node:path";
10598
+ import path13 from "node:path";
10524
10599
  var SITE_API_BASE_URL_ENV_KEY = "VITE_APITOGO_AUTHENTICATION_API_BASE_URL";
10525
10600
  var PLACEHOLDER_HOST_MARKERS = [
10526
10601
  "dp-example.azurecontainerapps.io",
@@ -10538,10 +10613,10 @@ function isPlaceholderDevPortalApiUrl(apiBaseUrl) {
10538
10613
  return PLACEHOLDER_HOST_MARKERS.some((marker) => normalized.includes(marker));
10539
10614
  }
10540
10615
  async function readSiteApiBaseUrl(sourceDirectory) {
10541
- const resolved = path12.resolve(sourceDirectory);
10616
+ const resolved = path13.resolve(sourceDirectory);
10542
10617
  for (const envFile of [".env", ".env.production"]) {
10543
10618
  try {
10544
- const content = await readFile6(path12.join(resolved, envFile), "utf8");
10619
+ const content = await readFile6(path13.join(resolved, envFile), "utf8");
10545
10620
  const lines = [...content.matchAll(ENV_LINE_GLOBAL_RE)];
10546
10621
  if (lines.length === 0) {
10547
10622
  continue;
@@ -10566,11 +10641,11 @@ async function readSiteApiBaseUrl(sourceDirectory) {
10566
10641
  return null;
10567
10642
  }
10568
10643
  async function patchSiteApiBaseUrl(sourceDirectory, apiBaseUrl) {
10569
- const resolved = path12.resolve(sourceDirectory);
10644
+ const resolved = path13.resolve(sourceDirectory);
10570
10645
  const line = `${SITE_API_BASE_URL_ENV_KEY}=${apiBaseUrl}`;
10571
10646
  let patchedExisting = false;
10572
10647
  for (const envFile of [".env.production", ".env"]) {
10573
- const envPath = path12.join(resolved, envFile);
10648
+ const envPath = path13.join(resolved, envFile);
10574
10649
  try {
10575
10650
  const content = await readFile6(envPath, "utf8");
10576
10651
  const withoutAssignments = content.replace(ENV_LINE_GLOBAL_RE, "").replace(/\n{3,}/g, "\n\n").trimEnd();
@@ -10584,7 +10659,7 @@ ${line}
10584
10659
  }
10585
10660
  }
10586
10661
  if (!patchedExisting) {
10587
- await writeFile5(path12.join(resolved, ".env"), `${line}
10662
+ await writeFile5(path13.join(resolved, ".env"), `${line}
10588
10663
  `);
10589
10664
  }
10590
10665
  }
@@ -10592,7 +10667,7 @@ function tryProjectId(explicit, manifestProjectId, config2) {
10592
10667
  return explicit?.trim() || manifestProjectId?.trim() || config2.defaultProjectId?.trim() || void 0;
10593
10668
  }
10594
10669
  async function ensureLiveSiteApiBaseUrlForBuild(_client, config2, args, resolveFromProject) {
10595
- const sourceDirectory = path12.resolve(args.sourceDirectory);
10670
+ const sourceDirectory = path13.resolve(args.sourceDirectory);
10596
10671
  const explicit = args.apiBaseUrl?.trim();
10597
10672
  if (explicit && !isPlaceholderDevPortalApiUrl(explicit)) {
10598
10673
  await patchSiteApiBaseUrl(sourceDirectory, explicit);
@@ -10628,7 +10703,7 @@ async function* walkFiles(root) {
10628
10703
  return;
10629
10704
  }
10630
10705
  for (const entry of entries) {
10631
- const full = path12.join(root, entry.name);
10706
+ const full = path13.join(root, entry.name);
10632
10707
  if (entry.isDirectory()) {
10633
10708
  if (entry.name === "node_modules" || entry.name === ".git") {
10634
10709
  continue;
@@ -10640,8 +10715,8 @@ async function* walkFiles(root) {
10640
10715
  }
10641
10716
  }
10642
10717
  async function assertDeployableDistHasLiveApiBaseUrl(distDirectory, expectedApiBaseUrl) {
10643
- const dist = path12.resolve(distDirectory);
10644
- const siteRoot = path12.dirname(dist);
10718
+ const dist = path13.resolve(distDirectory);
10719
+ const siteRoot = path13.dirname(dist);
10645
10720
  const fromEnv = expectedApiBaseUrl?.trim() || await readSiteApiBaseUrl(siteRoot) || await readSiteApiBaseUrl(dist);
10646
10721
  if (!fromEnv || isPlaceholderDevPortalApiUrl(fromEnv)) {
10647
10722
  throw new Error(
@@ -10896,8 +10971,8 @@ function validateDeployArchiveInput(args) {
10896
10971
  async function resolveDevPortalArchive(args) {
10897
10972
  validateDeployArchiveInput(args);
10898
10973
  if (args.archivePath?.trim()) {
10899
- const archivePath = path13.resolve(args.archivePath.trim());
10900
- const stat4 = await fs6.stat(archivePath).catch(() => null);
10974
+ const archivePath = path14.resolve(args.archivePath.trim());
10975
+ const stat4 = await fs7.stat(archivePath).catch(() => null);
10901
10976
  if (!stat4?.isFile()) {
10902
10977
  throw new Error(`archivePath is not a file: ${archivePath}`);
10903
10978
  }
@@ -10964,12 +11039,12 @@ async function handleDeployDevPortal(client, config2, args, progress) {
10964
11039
  }
10965
11040
 
10966
11041
  // src/cli/platform/tools/dev-portal-site-build.ts
10967
- import path15 from "node:path";
11042
+ import path16 from "node:path";
10968
11043
 
10969
11044
  // src/cli/platform/helpers/npm-build.ts
10970
11045
  import { spawn as spawn2 } from "node:child_process";
10971
11046
  import { access as access3, readFile as readFile7 } from "node:fs/promises";
10972
- import path14 from "node:path";
11047
+ import path15 from "node:path";
10973
11048
  var BUILD_LOG_TAIL_BYTES = 8192;
10974
11049
  var MIN_NODE_MAJOR = 20;
10975
11050
  var NpmBuildError = class extends Error {
@@ -11034,13 +11109,13 @@ function runCommand(command, args, cwd, env) {
11034
11109
  }
11035
11110
  async function runNpmInstall(sourceDirectory, options) {
11036
11111
  assertNodeVersion(options?.nodeVersion);
11037
- const cwd = path14.resolve(sourceDirectory);
11038
- const packageJsonPath = path14.join(cwd, "package.json");
11112
+ const cwd = path15.resolve(sourceDirectory);
11113
+ const packageJsonPath = path15.join(cwd, "package.json");
11039
11114
  if (!await pathExists2(packageJsonPath)) {
11040
11115
  throw new Error(`package.json not found in sourceDirectory: ${cwd}`);
11041
11116
  }
11042
11117
  const startedAt = Date.now();
11043
- const lockPath = path14.join(cwd, "package-lock.json");
11118
+ const lockPath = path15.join(cwd, "package-lock.json");
11044
11119
  const installArgs = await pathExists2(lockPath) ? ["ci"] : ["install"];
11045
11120
  const install = await runCommand("npm", installArgs, cwd);
11046
11121
  const installLog = install.output;
@@ -11058,8 +11133,8 @@ async function runNpmInstall(sourceDirectory, options) {
11058
11133
  }
11059
11134
  async function runNpmBuild(sourceDirectory, options) {
11060
11135
  assertNodeVersion(options?.nodeVersion);
11061
- const cwd = path14.resolve(sourceDirectory);
11062
- const packageJsonPath = path14.join(cwd, "package.json");
11136
+ const cwd = path15.resolve(sourceDirectory);
11137
+ const packageJsonPath = path15.join(cwd, "package.json");
11063
11138
  if (!await pathExists2(packageJsonPath)) {
11064
11139
  throw new Error(`package.json not found in sourceDirectory: ${cwd}`);
11065
11140
  }
@@ -11076,8 +11151,8 @@ async function runNpmBuild(sourceDirectory, options) {
11076
11151
  build2.exitCode
11077
11152
  );
11078
11153
  }
11079
- const distPath = path14.join(cwd, "dist");
11080
- const indexPath = path14.join(distPath, "index.html");
11154
+ const distPath = path15.join(cwd, "dist");
11155
+ const indexPath = path15.join(distPath, "index.html");
11081
11156
  if (!await pathExists2(indexPath)) {
11082
11157
  throw new NpmBuildError(
11083
11158
  `Build completed but dist/index.html was not found at ${indexPath}`,
@@ -11095,7 +11170,7 @@ async function runNpmBuild(sourceDirectory, options) {
11095
11170
  // src/cli/platform/tools/dev-portal-site-build.ts
11096
11171
  async function handleBuildDevPortalSite(client, config2, args, progress) {
11097
11172
  const buildProgress = progress?.child("Build dev portal site");
11098
- const sourceDirectory = path15.resolve(args.sourceDirectory);
11173
+ const sourceDirectory = path16.resolve(args.sourceDirectory);
11099
11174
  await buildProgress?.onStep("Ensuring live portal API URL");
11100
11175
  const apiBaseUrl = await ensureLiveSiteApiBaseUrlForBuild(
11101
11176
  client,
@@ -11175,10 +11250,10 @@ async function handleBuildDevPortalSite(client, config2, args, progress) {
11175
11250
  // src/cli/platform/helpers/dev-portal-site-validation.ts
11176
11251
  import { readFile as readFile8 } from "node:fs/promises";
11177
11252
  import { createRequire } from "node:module";
11178
- import path16 from "node:path";
11253
+ import path17 from "node:path";
11179
11254
  var cachedFallbackTs;
11180
11255
  async function loadTypeScriptForSite(sourceDirectory) {
11181
- const require2 = createRequire(path16.join(path16.resolve(sourceDirectory), "package.json"));
11256
+ const require2 = createRequire(path17.join(path17.resolve(sourceDirectory), "package.json"));
11182
11257
  try {
11183
11258
  return require2("typescript");
11184
11259
  } catch {
@@ -11222,7 +11297,7 @@ async function referencedFileExists(sourceDirectory, reference) {
11222
11297
  if (/^https?:\/\//i.test(reference)) {
11223
11298
  return true;
11224
11299
  }
11225
- return pathExists(path16.resolve(sourceDirectory, reference.replace(/^\.\//, "")));
11300
+ return pathExists(path17.resolve(sourceDirectory, reference.replace(/^\.\//, "")));
11226
11301
  }
11227
11302
  async function validateSiteConfigStructure(config2, sourceDirectory) {
11228
11303
  const errors = [];
@@ -11323,11 +11398,11 @@ var DEFAULT_TSX_CANDIDATES = [
11323
11398
  "landing/LandingPage.tsx"
11324
11399
  ];
11325
11400
  async function validateDevPortalSiteConfig(sourceDirectory, options) {
11326
- const resolvedDir = path16.resolve(sourceDirectory);
11401
+ const resolvedDir = path17.resolve(sourceDirectory);
11327
11402
  const issues = [];
11328
11403
  const checkedFiles = [];
11329
11404
  const skippedChecks = [];
11330
- const jsonPath = path16.join(resolvedDir, APITOGO_CONFIG_FILENAME);
11405
+ const jsonPath = path17.join(resolvedDir, APITOGO_CONFIG_FILENAME);
11331
11406
  if (await pathExists(jsonPath)) {
11332
11407
  checkedFiles.push(APITOGO_CONFIG_FILENAME);
11333
11408
  let parsed;
@@ -11356,7 +11431,7 @@ async function validateDevPortalSiteConfig(sourceDirectory, options) {
11356
11431
  );
11357
11432
  const existingTsxFiles = [];
11358
11433
  for (const relativeFile of tsxFiles) {
11359
- if (await pathExists(path16.join(resolvedDir, relativeFile))) {
11434
+ if (await pathExists(path17.join(resolvedDir, relativeFile))) {
11360
11435
  existingTsxFiles.push(relativeFile);
11361
11436
  }
11362
11437
  }
@@ -11369,7 +11444,7 @@ async function validateDevPortalSiteConfig(sourceDirectory, options) {
11369
11444
  } else {
11370
11445
  for (const relativeFile of existingTsxFiles) {
11371
11446
  checkedFiles.push(relativeFile);
11372
- const content = await readFile8(path16.join(resolvedDir, relativeFile), "utf8");
11447
+ const content = await readFile8(path17.join(resolvedDir, relativeFile), "utf8");
11373
11448
  issues.push(
11374
11449
  ...checkTsxSyntax(ts, relativeFile, content).map((message) => ({
11375
11450
  file: relativeFile,
@@ -11407,8 +11482,8 @@ function normalizeActionKeyFormat(actionKey) {
11407
11482
  const trimmed = actionKey.trim();
11408
11483
  if (trimmed.includes(":")) {
11409
11484
  const [method2, ...pathParts] = trimmed.split(":");
11410
- const path67 = pathParts.join(":").trim();
11411
- return `${method2.toLowerCase()}:${path67.startsWith("/") ? path67 : `/${path67}`}`;
11485
+ const path70 = pathParts.join(":").trim();
11486
+ return `${method2.toLowerCase()}:${path70.startsWith("/") ? path70 : `/${path70}`}`;
11412
11487
  }
11413
11488
  const spaceIndex = trimmed.indexOf(" ");
11414
11489
  if (spaceIndex <= 0) {
@@ -11417,8 +11492,8 @@ function normalizeActionKeyFormat(actionKey) {
11417
11492
  );
11418
11493
  }
11419
11494
  const method = trimmed.slice(0, spaceIndex).trim().toLowerCase();
11420
- const path66 = trimmed.slice(spaceIndex + 1).trim();
11421
- return `${method}:${path66.startsWith("/") ? path66 : `/${path66}`}`;
11495
+ const path69 = trimmed.slice(spaceIndex + 1).trim();
11496
+ return `${method}:${path69.startsWith("/") ? path69 : `/${path69}`}`;
11422
11497
  }
11423
11498
  function normalizePublicRoute(route) {
11424
11499
  const trimmed = route.trim();
@@ -12299,7 +12374,7 @@ function resultLooksFailed(payload) {
12299
12374
  }
12300
12375
  }
12301
12376
  async function apply(argv) {
12302
- const sourceDirectory = path17.resolve(process.cwd(), argv.dir);
12377
+ const sourceDirectory = path18.resolve(process.cwd(), argv.dir);
12303
12378
  const config2 = loadConfig();
12304
12379
  const client = new PlatformApiClient(config2);
12305
12380
  let only;
@@ -12384,11 +12459,11 @@ var apply_default = {
12384
12459
  };
12385
12460
 
12386
12461
  // src/cli/build/handler.ts
12387
- import path48 from "node:path";
12462
+ import path49 from "node:path";
12388
12463
 
12389
12464
  // src/vite/build.ts
12390
12465
  import { mkdir as mkdir9, readFile as readFile11, rename, rm as rm3, writeFile as writeFile10 } from "node:fs/promises";
12391
- import path46 from "node:path";
12466
+ import path47 from "node:path";
12392
12467
  import { build as esbuild } from "esbuild";
12393
12468
  import { build as viteBuild, mergeConfig as mergeConfig3 } from "vite";
12394
12469
 
@@ -12524,7 +12599,7 @@ init_invariant();
12524
12599
  init_joinUrl();
12525
12600
 
12526
12601
  // src/vite/config.ts
12527
- import path41 from "node:path";
12602
+ import path42 from "node:path";
12528
12603
  import dotenv from "dotenv";
12529
12604
  import colors5 from "picocolors";
12530
12605
  import {
@@ -12535,7 +12610,7 @@ import {
12535
12610
  // package.json
12536
12611
  var package_default = {
12537
12612
  name: "@lukoweb/apitogo",
12538
- version: "0.1.94",
12613
+ version: "0.1.96",
12539
12614
  type: "module",
12540
12615
  sideEffects: [
12541
12616
  "**/*.css",
@@ -12965,25 +13040,25 @@ async function loadDevPortalViteDefines(rootDir, mode) {
12965
13040
 
12966
13041
  // src/vite/package-root.ts
12967
13042
  init_file_exists();
12968
- import path23 from "node:path";
13043
+ import path24 from "node:path";
12969
13044
  var findPackageRoot = async (startDir) => {
12970
13045
  let dir = startDir;
12971
- while (dir !== path23.dirname(dir)) {
12972
- if (await fileExists(path23.join(dir, "package.json"))) return dir;
12973
- dir = path23.dirname(dir);
13046
+ while (dir !== path24.dirname(dir)) {
13047
+ if (await fileExists(path24.join(dir, "package.json"))) return dir;
13048
+ dir = path24.dirname(dir);
12974
13049
  }
12975
13050
  };
12976
13051
 
12977
13052
  // src/vite/pagefind-dev-stub.ts
12978
- import fs7 from "node:fs/promises";
12979
- import path24 from "node:path";
13053
+ import fs8 from "node:fs/promises";
13054
+ import path25 from "node:path";
12980
13055
  var NOT_BUILT_YET = 'throw new Error("NOT_BUILT_YET");';
12981
13056
  async function ensurePagefindDevStub(publicDir) {
12982
- const pagefindPath = path24.join(publicDir, "pagefind/pagefind.js");
12983
- const exists = await fs7.stat(pagefindPath).catch(() => false);
13057
+ const pagefindPath = path25.join(publicDir, "pagefind/pagefind.js");
13058
+ const exists = await fs8.stat(pagefindPath).catch(() => false);
12984
13059
  if (!exists) {
12985
- await fs7.mkdir(path24.dirname(pagefindPath), { recursive: true });
12986
- await fs7.writeFile(pagefindPath, NOT_BUILT_YET);
13060
+ await fs8.mkdir(path25.dirname(pagefindPath), { recursive: true });
13061
+ await fs8.writeFile(pagefindPath, NOT_BUILT_YET);
12987
13062
  }
12988
13063
  }
12989
13064
 
@@ -12994,7 +13069,7 @@ import react from "@vitejs/plugin-react";
12994
13069
  // src/vite/css/plugin.ts
12995
13070
  init_loader();
12996
13071
  init_plugin_theme();
12997
- import path25 from "node:path";
13072
+ import path26 from "node:path";
12998
13073
  import { isCSSRequest as isCSSRequest2 } from "vite";
12999
13074
 
13000
13075
  // src/vite/css/collect.ts
@@ -13029,7 +13104,7 @@ var VIRTUAL_ENTRY = "virtual:ssr-css.css";
13029
13104
  function vitePluginSsrCss(pluginOpts) {
13030
13105
  let server;
13031
13106
  const config2 = getCurrentConfig();
13032
- const virtualHref = path25.join(
13107
+ const virtualHref = path26.join(
13033
13108
  config2.basePath ?? "",
13034
13109
  `/@id/__x00__${VIRTUAL_ENTRY}?direct`
13035
13110
  );
@@ -13165,8 +13240,8 @@ var viteApiKeysPlugin = () => {
13165
13240
  var plugin_api_keys_default = viteApiKeysPlugin;
13166
13241
 
13167
13242
  // src/vite/plugin-api.ts
13168
- import fs9 from "node:fs/promises";
13169
- import path31 from "node:path";
13243
+ import fs10 from "node:fs/promises";
13244
+ import path32 from "node:path";
13170
13245
  import { deepEqual as deepEqual2 } from "fast-equals";
13171
13246
  import { runnerImport as runnerImport3 } from "vite";
13172
13247
  init_package_json();
@@ -13175,7 +13250,7 @@ init_loader();
13175
13250
  // src/config/validators/BuildSchema.ts
13176
13251
  init_file_exists();
13177
13252
  init_loader();
13178
- import path26 from "node:path";
13253
+ import path27 from "node:path";
13179
13254
  import { runnerImport as runnerImport2 } from "vite";
13180
13255
  import { z as z10 } from "zod";
13181
13256
  var BuildProcessorSchema = z10.custom((val) => typeof val === "function");
@@ -13204,7 +13279,7 @@ var buildConfigFiles = [
13204
13279
  ];
13205
13280
  async function getBuildConfigFilePath(rootDir) {
13206
13281
  for (const fileName of buildConfigFiles) {
13207
- const filepath = path26.join(rootDir, fileName);
13282
+ const filepath = path27.join(rootDir, fileName);
13208
13283
  if (await fileExists(filepath)) {
13209
13284
  return filepath;
13210
13285
  }
@@ -13313,14 +13388,14 @@ var flattenAllOf = (schema2) => {
13313
13388
  };
13314
13389
 
13315
13390
  // src/lib/util/traverse.ts
13316
- var traverse = (specification, transform, path66 = []) => {
13317
- const transformed = transform(specification, path66);
13391
+ var traverse = (specification, transform, path69 = []) => {
13392
+ const transformed = transform(specification, path69);
13318
13393
  if (typeof transformed !== "object" || transformed === null) {
13319
13394
  return transformed;
13320
13395
  }
13321
13396
  const result = Array.isArray(transformed) ? [] : {};
13322
13397
  for (const [key, value] of Object.entries(transformed)) {
13323
- const currentPath = [...path66, key];
13398
+ const currentPath = [...path69, key];
13324
13399
  if (Array.isArray(value)) {
13325
13400
  result[key] = value.map(
13326
13401
  (item, index) => typeof item === "object" && item != null ? traverse(item, transform, [...currentPath, index.toString()]) : item
@@ -13348,9 +13423,9 @@ var resolveLocalRef = (schema2, ref) => {
13348
13423
  if (schemaCache?.has(ref)) {
13349
13424
  return schemaCache.get(ref);
13350
13425
  }
13351
- const path66 = ref.split("/").slice(1);
13426
+ const path69 = ref.split("/").slice(1);
13352
13427
  let current = schema2;
13353
- for (const segment of path66) {
13428
+ for (const segment of path69) {
13354
13429
  if (!current || typeof current !== "object") {
13355
13430
  current = null;
13356
13431
  }
@@ -13369,7 +13444,7 @@ var dereference = async (schema2, resolvers = []) => {
13369
13444
  }
13370
13445
  const cloned = structuredClone(schema2);
13371
13446
  const visited = /* @__PURE__ */ new Set();
13372
- const resolve = async (current, path66) => {
13447
+ const resolve = async (current, path69) => {
13373
13448
  if (isIndexableObject(current)) {
13374
13449
  if (visited.has(current)) {
13375
13450
  return CIRCULAR_REF;
@@ -13377,7 +13452,7 @@ var dereference = async (schema2, resolvers = []) => {
13377
13452
  visited.add(current);
13378
13453
  if (Array.isArray(current)) {
13379
13454
  for (let index = 0; index < current.length; index++) {
13380
- current[index] = await resolve(current[index], `${path66}/${index}`);
13455
+ current[index] = await resolve(current[index], `${path69}/${index}`);
13381
13456
  }
13382
13457
  } else {
13383
13458
  if ("$ref" in current && typeof current.$ref === "string") {
@@ -13388,13 +13463,13 @@ var dereference = async (schema2, resolvers = []) => {
13388
13463
  for (const resolver of resolvers) {
13389
13464
  const resolved = await resolver($ref);
13390
13465
  if (resolved) {
13391
- result2 = await resolve(resolved, path66);
13466
+ result2 = await resolve(resolved, path69);
13392
13467
  break;
13393
13468
  }
13394
13469
  }
13395
13470
  if (result2 === void 0) {
13396
13471
  const resolved = await resolveLocalRef(cloned, $ref);
13397
- result2 = await resolve(resolved, path66);
13472
+ result2 = await resolve(resolved, path69);
13398
13473
  }
13399
13474
  if (hasSiblings) {
13400
13475
  if (result2 === CIRCULAR_REF) {
@@ -13407,7 +13482,7 @@ var dereference = async (schema2, resolvers = []) => {
13407
13482
  return result2;
13408
13483
  }
13409
13484
  for (const key in current) {
13410
- current[key] = await resolve(current[key], `${path66}/${key}`);
13485
+ current[key] = await resolve(current[key], `${path69}/${key}`);
13411
13486
  }
13412
13487
  }
13413
13488
  visited.delete(current);
@@ -13446,9 +13521,9 @@ var upgradeSchema = (schema2) => {
13446
13521
  }
13447
13522
  return sub;
13448
13523
  });
13449
- schema2 = traverse(schema2, (sub, path66) => {
13524
+ schema2 = traverse(schema2, (sub, path69) => {
13450
13525
  if (sub.example !== void 0) {
13451
- if (isSchemaPath(path66 ?? [])) {
13526
+ if (isSchemaPath(path69 ?? [])) {
13452
13527
  sub.examples = [sub.example];
13453
13528
  } else {
13454
13529
  sub.examples = {
@@ -13461,11 +13536,11 @@ var upgradeSchema = (schema2) => {
13461
13536
  }
13462
13537
  return sub;
13463
13538
  });
13464
- schema2 = traverse(schema2, (schema3, path66) => {
13539
+ schema2 = traverse(schema2, (schema3, path69) => {
13465
13540
  if (schema3.type === "object" && schema3.properties !== void 0) {
13466
- const parentPath = path66?.slice(0, -1);
13541
+ const parentPath = path69?.slice(0, -1);
13467
13542
  const isMultipart = parentPath?.some((segment, index) => {
13468
- return segment === "content" && path66?.[index + 1] === "multipart/form-data";
13543
+ return segment === "content" && path69?.[index + 1] === "multipart/form-data";
13469
13544
  });
13470
13545
  if (isMultipart) {
13471
13546
  const entries = Object.entries(schema3.properties);
@@ -13479,8 +13554,8 @@ var upgradeSchema = (schema2) => {
13479
13554
  }
13480
13555
  return schema3;
13481
13556
  });
13482
- schema2 = traverse(schema2, (schema3, path66) => {
13483
- if (path66?.includes("content") && path66.includes("application/octet-stream")) {
13557
+ schema2 = traverse(schema2, (schema3, path69) => {
13558
+ if (path69?.includes("content") && path69.includes("application/octet-stream")) {
13484
13559
  return {};
13485
13560
  }
13486
13561
  if (schema3.type === "string" && schema3.format === "binary") {
@@ -13506,11 +13581,11 @@ var upgradeSchema = (schema2) => {
13506
13581
  }
13507
13582
  return sub;
13508
13583
  });
13509
- schema2 = traverse(schema2, (schema3, path66) => {
13584
+ schema2 = traverse(schema2, (schema3, path69) => {
13510
13585
  if (schema3.type === "string" && schema3.format === "byte") {
13511
- const parentPath = path66?.slice(0, -1);
13586
+ const parentPath = path69?.slice(0, -1);
13512
13587
  const contentMediaType = parentPath?.find(
13513
- (_, index) => path66?.[index - 1] === "content"
13588
+ (_, index) => path69?.[index - 1] === "content"
13514
13589
  );
13515
13590
  return {
13516
13591
  type: "string",
@@ -13522,7 +13597,7 @@ var upgradeSchema = (schema2) => {
13522
13597
  });
13523
13598
  return schema2;
13524
13599
  };
13525
- function isSchemaPath(path66) {
13600
+ function isSchemaPath(path69) {
13526
13601
  const schemaLocations = [
13527
13602
  ["components", "schemas"],
13528
13603
  "properties",
@@ -13535,10 +13610,10 @@ function isSchemaPath(path66) {
13535
13610
  ];
13536
13611
  return schemaLocations.some((location) => {
13537
13612
  if (Array.isArray(location)) {
13538
- return location.every((segment, index) => path66[index] === segment);
13613
+ return location.every((segment, index) => path69[index] === segment);
13539
13614
  }
13540
- return path66.includes(location);
13541
- }) || path66.includes("schema") || path66.some((segment) => segment.endsWith("Schema"));
13615
+ return path69.includes(location);
13616
+ }) || path69.includes("schema") || path69.some((segment) => segment.endsWith("Schema"));
13542
13617
  }
13543
13618
 
13544
13619
  // src/lib/oas/parser/index.ts
@@ -13620,13 +13695,13 @@ var OPENAPI_PROPS = /* @__PURE__ */ new Set([
13620
13695
  "anyOf",
13621
13696
  "oneOf"
13622
13697
  ]);
13623
- var handleCircularRefs = (obj, currentPath = /* @__PURE__ */ new WeakSet(), refs = /* @__PURE__ */ new WeakMap(), path66 = [], currentRefPaths = /* @__PURE__ */ new Set()) => {
13698
+ var handleCircularRefs = (obj, currentPath = /* @__PURE__ */ new WeakSet(), refs = /* @__PURE__ */ new WeakMap(), path69 = [], currentRefPaths = /* @__PURE__ */ new Set()) => {
13624
13699
  if (obj === null || typeof obj !== "object") return obj;
13625
13700
  const refPath = obj.__$ref;
13626
13701
  const isCircular = currentPath.has(obj) || typeof refPath === "string" && currentRefPaths.has(refPath);
13627
13702
  if (isCircular) {
13628
13703
  if (typeof refPath === "string") return SCHEMA_REF_PREFIX + refPath;
13629
- const circularProp = path66.find((p) => !OPENAPI_PROPS.has(p)) || path66[0];
13704
+ const circularProp = path69.find((p) => !OPENAPI_PROPS.has(p)) || path69[0];
13630
13705
  return [CIRCULAR_REF, circularProp].filter(Boolean).join(":");
13631
13706
  }
13632
13707
  if (refs.has(obj)) return refs.get(obj);
@@ -13636,7 +13711,7 @@ var handleCircularRefs = (obj, currentPath = /* @__PURE__ */ new WeakSet(), refs
13636
13711
  value,
13637
13712
  currentPath,
13638
13713
  refs,
13639
- [...path66, key],
13714
+ [...path69, key],
13640
13715
  currentRefPaths
13641
13716
  );
13642
13717
  const result = Array.isArray(obj) ? obj.map((item, i) => recurse(item, i.toString())) : Object.fromEntries(
@@ -13671,7 +13746,7 @@ var resolveExtensions = (obj) => Object.fromEntries(
13671
13746
  var getAllTags = (schema2) => {
13672
13747
  const rootTags = schema2.tags ?? [];
13673
13748
  const operations = Object.values(schema2.paths ?? {}).flatMap(
13674
- (path66) => HttpMethods.map((k) => path66?.[k]).filter((op) => op != null)
13749
+ (path69) => HttpMethods.map((k) => path69?.[k]).filter((op) => op != null)
13675
13750
  );
13676
13751
  const operationTags = new Set(operations.flatMap((op) => op.tags ?? []));
13677
13752
  const hasUntaggedOperations = operations.some(
@@ -13726,7 +13801,7 @@ var getAllSlugs = (ops, schemaTags = []) => {
13726
13801
  var getOperationSlugKey = (op) => [op.path, op.method, op.operationId, op.summary].filter(Boolean).join("-");
13727
13802
  var getAllOperations = (paths) => {
13728
13803
  const operations = Object.entries(paths ?? {}).flatMap(
13729
- ([path66, value]) => HttpMethods.flatMap((method) => {
13804
+ ([path69, value]) => HttpMethods.flatMap((method) => {
13730
13805
  if (!value?.[method]) return [];
13731
13806
  const operation = value[method];
13732
13807
  const pathParameters = value.parameters ?? [];
@@ -13746,7 +13821,7 @@ var getAllOperations = (paths) => {
13746
13821
  return {
13747
13822
  ...operation,
13748
13823
  method,
13749
- path: path66,
13824
+ path: path69,
13750
13825
  parameters,
13751
13826
  servers,
13752
13827
  tags: operation.tags ?? []
@@ -14104,8 +14179,8 @@ var Schema = builder.objectRef("Schema").implement({
14104
14179
  }),
14105
14180
  paths: t.field({
14106
14181
  type: [PathItem],
14107
- resolve: (root) => Object.entries(root.paths ?? {}).map(([path66, value]) => ({
14108
- path: path66,
14182
+ resolve: (root) => Object.entries(root.paths ?? {}).map(([path69, value]) => ({
14183
+ path: path69,
14109
14184
  // biome-ignore lint/style/noNonNullAssertion: value is guaranteed to be defined
14110
14185
  methods: Object.keys(value)
14111
14186
  }))
@@ -14217,8 +14292,8 @@ function injectApitogoGatewayServer(options) {
14217
14292
  var ensureArray = (value) => Array.isArray(value) ? value : [value];
14218
14293
 
14219
14294
  // src/vite/api/SchemaManager.ts
14220
- import fs8 from "node:fs/promises";
14221
- import path27 from "node:path";
14295
+ import fs9 from "node:fs/promises";
14296
+ import path28 from "node:path";
14222
14297
  import {
14223
14298
  $RefParser as $RefParser2
14224
14299
  } from "@apidevtools/json-schema-ref-parser";
@@ -14270,7 +14345,7 @@ init_joinUrl();
14270
14345
 
14271
14346
  // src/vite/api/schema-codegen.ts
14272
14347
  var unescapeJsonPointer = (uri) => decodeURIComponent(uri.replace(/~1/g, "/").replace(/~0/g, "~"));
14273
- var getSegmentsFromPath = (path66) => path66.split("/").slice(1).map(unescapeJsonPointer);
14348
+ var getSegmentsFromPath = (path69) => path69.split("/").slice(1).map(unescapeJsonPointer);
14274
14349
  var createLocalRefMap = (obj) => {
14275
14350
  const refMap = /* @__PURE__ */ new Map();
14276
14351
  const siblingsMap = /* @__PURE__ */ new Map();
@@ -14301,16 +14376,16 @@ var replaceMarkers = (code, mergedRefs) => code.replace(/"__refMap:(.*?)"/g, '__
14301
14376
  /"__refMap\+Siblings:(.*?)"/g,
14302
14377
  (_, key) => mergedRefs.get(key) ?? `__refMap["${key}"]`
14303
14378
  );
14304
- var lookup2 = (schema2, path66, filePath) => {
14305
- const parts = getSegmentsFromPath(path66);
14379
+ var lookup2 = (schema2, path69, filePath) => {
14380
+ const parts = getSegmentsFromPath(path69);
14306
14381
  let val = schema2;
14307
14382
  for (const part of parts) {
14308
14383
  while (val.$ref?.startsWith("#/")) {
14309
- val = val.$ref === path66 ? val : lookup2(schema2, val.$ref, filePath);
14384
+ val = val.$ref === path69 ? val : lookup2(schema2, val.$ref, filePath);
14310
14385
  }
14311
14386
  if (val[part] === void 0) {
14312
14387
  throw new Error(
14313
- `Error in ${filePath ?? "code generation"}: Could not find path segment ${part} in path: ${path66}`
14388
+ `Error in ${filePath ?? "code generation"}: Could not find path segment ${part} in path: ${path69}`
14314
14389
  );
14315
14390
  }
14316
14391
  val = val[part];
@@ -14408,18 +14483,18 @@ var SchemaManager = class {
14408
14483
  ];
14409
14484
  }
14410
14485
  getPathForFile = (input3, params) => {
14411
- const filePath = path27.resolve(this.config.__meta.rootDir, input3);
14486
+ const filePath = path28.resolve(this.config.__meta.rootDir, input3);
14412
14487
  const apis = ensureArray(this.config.apis ?? []);
14413
14488
  for (const apiConfig of apis) {
14414
14489
  if (!apiConfig || apiConfig.type !== "file" || !apiConfig.path) continue;
14415
14490
  const match = normalizeInputs(apiConfig.input).some(
14416
- (i) => path27.resolve(this.config.__meta.rootDir, i.input) === filePath && deepEqual(i.params, params)
14491
+ (i) => path28.resolve(this.config.__meta.rootDir, i.input) === filePath && deepEqual(i.params, params)
14417
14492
  );
14418
14493
  if (match) return apiConfig.path;
14419
14494
  }
14420
14495
  };
14421
14496
  processSchema = async (input3) => {
14422
- const filePath = path27.resolve(this.config.__meta.rootDir, input3.input);
14497
+ const filePath = path28.resolve(this.config.__meta.rootDir, input3.input);
14423
14498
  const params = input3.params;
14424
14499
  const configuredPath = this.getPathForFile(input3.input, params);
14425
14500
  if (!configuredPath) {
@@ -14455,15 +14530,15 @@ var SchemaManager = class {
14455
14530
  const processedTime = Date.now();
14456
14531
  const code = generateCode(processedSchema, filePath);
14457
14532
  const prefixPath = slugify(configuredPath);
14458
- const processedFilePath = path27.posix.join(
14533
+ const processedFilePath = path28.posix.join(
14459
14534
  this.storeDir,
14460
- `${prefixPath}-${path27.basename(filePath)}${paramsSuffix(params)}.js`
14535
+ `${prefixPath}-${path28.basename(filePath)}${paramsSuffix(params)}.js`
14461
14536
  );
14462
14537
  const importKey = processedFilePath;
14463
- await fs8.writeFile(processedFilePath, code);
14538
+ await fs9.writeFile(processedFilePath, code);
14464
14539
  const processedJsonPath = paramsSuffix(params) ? processedFilePath.replace(/\.js$/, ".json") : "";
14465
14540
  if (processedJsonPath) {
14466
- await fs8.writeFile(
14541
+ await fs9.writeFile(
14467
14542
  processedJsonPath,
14468
14543
  JSON.stringify(processedSchema, null, 2)
14469
14544
  );
@@ -14506,7 +14581,7 @@ var SchemaManager = class {
14506
14581
  };
14507
14582
  getAllTrackedFiles = () => Array.from(this.referencedBy.keys());
14508
14583
  getFilesToReprocess = (changedFile) => {
14509
- const resolvedPath = path27.resolve(this.config.__meta.rootDir, changedFile);
14584
+ const resolvedPath = path28.resolve(this.config.__meta.rootDir, changedFile);
14510
14585
  const referencedBy = this.referencedBy.get(resolvedPath);
14511
14586
  if (!referencedBy) return [];
14512
14587
  const filesToProcess = referencedBy.size === 0 ? [resolvedPath] : Array.from(referencedBy);
@@ -14535,7 +14610,7 @@ var SchemaManager = class {
14535
14610
  version: "",
14536
14611
  path: input3.path ?? "",
14537
14612
  label: input3.label,
14538
- inputPath: path27.resolve(this.config.__meta.rootDir, input3.input),
14613
+ inputPath: path28.resolve(this.config.__meta.rootDir, input3.input),
14539
14614
  params: input3.params,
14540
14615
  importKey: "",
14541
14616
  downloadUrl: "",
@@ -14555,8 +14630,8 @@ var SchemaManager = class {
14555
14630
  }
14556
14631
  }
14557
14632
  };
14558
- getLatestSchema = (path66) => this.processedSchemas[path66]?.at(0);
14559
- getSchemasForPath = (path66) => this.processedSchemas[path66];
14633
+ getLatestSchema = (path69) => this.processedSchemas[path69]?.at(0);
14634
+ getSchemasForPath = (path69) => this.processedSchemas[path69];
14560
14635
  getSchemaImports = () => Object.values(this.processedSchemas).flat().filter((s) => s.importKey);
14561
14636
  getUrlToFilePathMap = () => {
14562
14637
  const map = /* @__PURE__ */ new Map();
@@ -14578,7 +14653,7 @@ var SchemaManager = class {
14578
14653
  };
14579
14654
  createSchemaPath = (inputPath, versionPath, apiPath, params) => {
14580
14655
  const suffix = paramsSuffix(params);
14581
- const extension = suffix ? ".json" : path27.extname(inputPath);
14656
+ const extension = suffix ? ".json" : path28.extname(inputPath);
14582
14657
  return joinUrl(
14583
14658
  this.config.basePath,
14584
14659
  apiPath,
@@ -14601,7 +14676,7 @@ var SchemaManager = class {
14601
14676
  // src/vite/plugin-config-reload.ts
14602
14677
  init_logger();
14603
14678
  init_loader();
14604
- import path30 from "node:path";
14679
+ import path31 from "node:path";
14605
14680
  import colors4 from "picocolors";
14606
14681
 
14607
14682
  // src/vite/plugin-navigation.ts
@@ -14611,7 +14686,7 @@ import { stringify as stringify3 } from "javascript-stringify";
14611
14686
  import { isElement } from "react-is";
14612
14687
 
14613
14688
  // src/config/validators/NavigationSchema.ts
14614
- import path28 from "node:path";
14689
+ import path29 from "node:path";
14615
14690
  import { glob } from "glob";
14616
14691
  import { fromMarkdown } from "mdast-util-from-markdown";
14617
14692
  import { mdxFromMarkdown } from "mdast-util-mdx";
@@ -14662,7 +14737,7 @@ var extractRichH1 = (content) => {
14662
14737
  }
14663
14738
  };
14664
14739
  var isNavigationItem = (item) => item !== void 0;
14665
- var toPosixPath = (filePath) => filePath.split(path28.win32.sep).join(path28.posix.sep);
14740
+ var toPosixPath = (filePath) => filePath.split(path29.win32.sep).join(path29.posix.sep);
14666
14741
  var NavigationResolver = class {
14667
14742
  rootDir;
14668
14743
  globPatterns;
@@ -14795,13 +14870,13 @@ init_invariant();
14795
14870
 
14796
14871
  // src/vite/debug.ts
14797
14872
  import { mkdir as mkdir5, writeFile as writeFile6 } from "node:fs/promises";
14798
- import path29 from "node:path";
14873
+ import path30 from "node:path";
14799
14874
  async function writePluginDebugCode(rootDir, pluginName, code, extension = "js") {
14800
14875
  if (process.env.ZUDOKU_BUILD_DEBUG) {
14801
- const debugDir = path29.join(rootDir, "dist", "debug");
14876
+ const debugDir = path30.join(rootDir, "dist", "debug");
14802
14877
  await mkdir5(debugDir, { recursive: true });
14803
14878
  await writeFile6(
14804
- path29.join(debugDir, `${pluginName}.${extension}`),
14879
+ path30.join(debugDir, `${pluginName}.${extension}`),
14805
14880
  typeof code === "string" ? code : code.join("\n")
14806
14881
  );
14807
14882
  }
@@ -14910,7 +14985,7 @@ var viteConfigReloadPlugin = () => ({
14910
14985
  reload(server);
14911
14986
  logger.info(
14912
14987
  colors4.blue(
14913
- `Config ${path30.basename(currentConfig.__meta.configPath)} changed. Reloading...`
14988
+ `Config ${path31.basename(currentConfig.__meta.configPath)} changed. Reloading...`
14914
14989
  ),
14915
14990
  { timestamp: true }
14916
14991
  );
@@ -14924,11 +14999,11 @@ var viteApiPlugin = async () => {
14924
14999
  const resolvedVirtualModuleId5 = `\0${virtualModuleId4}`;
14925
15000
  const initialConfig = getCurrentConfig();
14926
15001
  const zuploProcessors = ZuploEnv.isZuplo ? await runnerImport3(
14927
- path31.resolve(getZudokuRootDir(), "src/zuplo/with-zuplo-processors.ts")
15002
+ path32.resolve(getZudokuRootDir(), "src/zuplo/with-zuplo-processors.ts")
14928
15003
  ).then((m) => m.module.default(initialConfig.__meta.rootDir)) : [];
14929
15004
  const buildConfig = await getBuildConfig();
14930
15005
  const buildProcessors = buildConfig?.processors ?? [];
14931
- const tmpStoreDir = path31.posix.join(
15006
+ const tmpStoreDir = path32.posix.join(
14932
15007
  initialConfig.__meta.rootDir,
14933
15008
  "node_modules/.apitogo/processed"
14934
15009
  );
@@ -14945,8 +15020,8 @@ var viteApiPlugin = async () => {
14945
15020
  return {
14946
15021
  name: "zudoku-api-plugins",
14947
15022
  async buildStart() {
14948
- await fs9.rm(tmpStoreDir, { recursive: true, force: true });
14949
- await fs9.mkdir(tmpStoreDir, { recursive: true });
15023
+ await fs10.rm(tmpStoreDir, { recursive: true, force: true });
15024
+ await fs10.mkdir(tmpStoreDir, { recursive: true });
14950
15025
  await schemaManager.processAllSchemas();
14951
15026
  schemaManager.getAllTrackedFiles().forEach((file) => this.addWatchFile(file));
14952
15027
  },
@@ -14959,8 +15034,8 @@ var viteApiPlugin = async () => {
14959
15034
  const pathMap = schemaManager.getUrlToFilePathMap();
14960
15035
  const inputPath = pathMap.get(req.url);
14961
15036
  if (!inputPath) return next();
14962
- const content = await fs9.readFile(inputPath, "utf-8");
14963
- const mimeType = path31.extname(inputPath).toLowerCase() === ".json" ? "application/json" : "application/x-yaml";
15037
+ const content = await fs10.readFile(inputPath, "utf-8");
15038
+ const mimeType = path32.extname(inputPath).toLowerCase() === ".json" ? "application/json" : "application/x-yaml";
14964
15039
  res.setHeader("Content-Type", `${mimeType}; charset=utf-8`);
14965
15040
  return res.end(content);
14966
15041
  });
@@ -15147,10 +15222,10 @@ var viteApiPlugin = async () => {
15147
15222
  const pathMap = schemaManager.getUrlToFilePathMap();
15148
15223
  if (process.env.NODE_ENV !== "production") return;
15149
15224
  for (const [urlPath, inputPath] of pathMap) {
15150
- const content = await fs9.readFile(inputPath, "utf-8");
15151
- const outputPath = path31.join(config2.__meta.rootDir, "dist", urlPath);
15152
- await fs9.mkdir(path31.dirname(outputPath), { recursive: true });
15153
- await fs9.writeFile(outputPath, content, "utf-8");
15225
+ const content = await fs10.readFile(inputPath, "utf-8");
15226
+ const outputPath = path32.join(config2.__meta.rootDir, "dist", urlPath);
15227
+ await fs10.mkdir(path32.dirname(outputPath), { recursive: true });
15228
+ await fs10.writeFile(outputPath, content, "utf-8");
15154
15229
  }
15155
15230
  }
15156
15231
  };
@@ -15192,7 +15267,7 @@ var plugin_auth_default = viteAuthPlugin;
15192
15267
 
15193
15268
  // src/vite/plugin-component.ts
15194
15269
  init_loader();
15195
- import path32 from "node:path";
15270
+ import path33 from "node:path";
15196
15271
  var viteAliasPlugin = () => {
15197
15272
  return {
15198
15273
  name: "zudoku-component-plugin",
@@ -15220,7 +15295,7 @@ var viteAliasPlugin = () => {
15220
15295
  ];
15221
15296
  const aliases = replacements.map(([find, replacement]) => ({
15222
15297
  find,
15223
- replacement: path32.posix.join(config2.__meta.moduleDir, replacement)
15298
+ replacement: path33.posix.join(config2.__meta.moduleDir, replacement)
15224
15299
  }));
15225
15300
  return config2.__meta.mode === "internal" || config2.__meta.mode === "standalone" ? { resolve: { alias: aliases } } : void 0;
15226
15301
  }
@@ -15231,11 +15306,11 @@ var plugin_component_default = viteAliasPlugin;
15231
15306
  // src/vite/plugin-config.ts
15232
15307
  init_package_json();
15233
15308
  init_loader();
15234
- import path33 from "node:path";
15309
+ import path34 from "node:path";
15235
15310
  import { normalizePath } from "vite";
15236
15311
  var virtualModuleId3 = "virtual:zudoku-config";
15237
15312
  var resolvedVirtualModuleId3 = `\0${virtualModuleId3}`;
15238
- var browserConfigLoaderPath = path33.join(
15313
+ var browserConfigLoaderPath = path34.join(
15239
15314
  getZudokuRootDir(),
15240
15315
  "src/config/apitogo-config-loader.browser.ts"
15241
15316
  );
@@ -15406,7 +15481,7 @@ var viteDocMetadataPlugin = () => ({
15406
15481
 
15407
15482
  // src/vite/plugin-docs.ts
15408
15483
  init_loader();
15409
- import path34 from "node:path";
15484
+ import path35 from "node:path";
15410
15485
  import { glob as glob3 } from "glob";
15411
15486
  import globParent from "glob-parent";
15412
15487
  init_ZudokuConfig();
@@ -15475,7 +15550,7 @@ var globMarkdownFiles = async (config2, options = { absolute: false }) => {
15475
15550
  if (process.env.NODE_ENV !== "development") {
15476
15551
  const draftStatuses = await Promise.all(
15477
15552
  globbedFiles.map(async (file) => {
15478
- const absolutePath = path34.resolve(config2.__meta.rootDir, file);
15553
+ const absolutePath = path35.resolve(config2.__meta.rootDir, file);
15479
15554
  const { data } = await readFrontmatter(absolutePath);
15480
15555
  return { file, isDraft: data.draft === true };
15481
15556
  })
@@ -15488,9 +15563,9 @@ var globMarkdownFiles = async (config2, options = { absolute: false }) => {
15488
15563
  if (draftFiles.has(file)) {
15489
15564
  continue;
15490
15565
  }
15491
- const relativePath = path34.posix.relative(parent, file);
15566
+ const relativePath = path35.posix.relative(parent, file);
15492
15567
  const routePath = ensureLeadingSlash(relativePath.replace(/\.mdx?$/, ""));
15493
- const filePath = options.absolute ? path34.resolve(config2.__meta.rootDir, file) : file;
15568
+ const filePath = options.absolute ? path35.resolve(config2.__meta.rootDir, file) : file;
15494
15569
  fileMapping[routePath] = filePath;
15495
15570
  }
15496
15571
  }
@@ -15554,7 +15629,7 @@ var viteDocsPlugin = () => {
15554
15629
  const globbedDocuments = {};
15555
15630
  for (const [routePath, file] of Object.entries(fileMapping)) {
15556
15631
  const importPath = ensureLeadingSlash(
15557
- path34.posix.join(globImportBasePath, file)
15632
+ path35.posix.join(globImportBasePath, file)
15558
15633
  );
15559
15634
  globbedDocuments[routePath] = importPath;
15560
15635
  }
@@ -15580,7 +15655,7 @@ var plugin_docs_default = viteDocsPlugin;
15580
15655
  // src/vite/plugin-local-manifest.ts
15581
15656
  init_apitogo_config_loader();
15582
15657
  init_local_manifest();
15583
- import path35 from "node:path";
15658
+ import path36 from "node:path";
15584
15659
  var APITOGO_LOCAL_MANIFEST_VIRTUAL_ID = "virtual:apitogo-local-manifest";
15585
15660
  var resolvedVirtualModuleId4 = `\0${APITOGO_LOCAL_MANIFEST_VIRTUAL_ID}`;
15586
15661
  var viteLocalManifestPlugin = () => {
@@ -15630,8 +15705,8 @@ var viteLocalManifestPlugin = () => {
15630
15705
  server.watcher.add(watchPath);
15631
15706
  }
15632
15707
  server.watcher.on("change", async (changedPath) => {
15633
- const resolvedChanged = path35.resolve(changedPath);
15634
- if (!watchPaths.some((p) => path35.resolve(p) === resolvedChanged)) {
15708
+ const resolvedChanged = path36.resolve(changedPath);
15709
+ if (!watchPaths.some((p) => path36.resolve(p) === resolvedChanged)) {
15635
15710
  return;
15636
15711
  }
15637
15712
  const module = server.moduleGraph.getModuleById(
@@ -15658,7 +15733,7 @@ init_loader();
15658
15733
  init_ProtectedRoutesSchema();
15659
15734
  init_joinUrl();
15660
15735
  import { mkdir as mkdir6, writeFile as writeFile7 } from "node:fs/promises";
15661
- import path36 from "node:path";
15736
+ import path37 from "node:path";
15662
15737
  import { matchPath } from "react-router";
15663
15738
  var processMarkdownFile = async (filePath) => {
15664
15739
  const { content: markdownContent, data: frontmatter } = await readFrontmatter(filePath);
@@ -15746,7 +15821,7 @@ var viteMarkdownExportPlugin = () => {
15746
15821
  if (process.env.NODE_ENV !== "production" || Object.keys(markdownFiles).length === 0 || !needsMdFiles) {
15747
15822
  return;
15748
15823
  }
15749
- const distDir = path36.join(
15824
+ const distDir = path37.join(
15750
15825
  config2.__meta.rootDir,
15751
15826
  "dist",
15752
15827
  config2.basePath ?? ""
@@ -15767,15 +15842,15 @@ var viteMarkdownExportPlugin = () => {
15767
15842
  content: finalMarkdown
15768
15843
  });
15769
15844
  const segments = routePath === "/" ? ["index"] : routePath.split("/").filter(Boolean);
15770
- const outputPath = `${path36.join(distDir, ...segments)}.md`;
15771
- await mkdir6(path36.dirname(outputPath), { recursive: true });
15845
+ const outputPath = `${path37.join(distDir, ...segments)}.md`;
15846
+ await mkdir6(path37.dirname(outputPath), { recursive: true });
15772
15847
  await writeFile7(outputPath, finalMarkdown, "utf-8");
15773
15848
  } catch (error) {
15774
15849
  console.warn(`Failed to export markdown for ${routePath}:`, error);
15775
15850
  }
15776
15851
  }
15777
15852
  if (config2.docs?.llms?.llmsTxt || config2.docs?.llms?.llmsTxtFull) {
15778
- const markdownInfoPath = path36.join(
15853
+ const markdownInfoPath = path37.join(
15779
15854
  config2.__meta.rootDir,
15780
15855
  "node_modules/.apitogo/markdown-info.json"
15781
15856
  );
@@ -15927,9 +16002,9 @@ var remarkCodeTabs = () => (tree) => {
15927
16002
  };
15928
16003
 
15929
16004
  // src/vite/mdx/remark-inject-filepath.ts
15930
- import path37 from "node:path";
16005
+ import path38 from "node:path";
15931
16006
  var remarkInjectFilepath = (rootDir) => (tree, vfile) => {
15932
- const relativePath = path37.relative(rootDir, vfile.path).split(path37.sep).join(path37.posix.sep);
16007
+ const relativePath = path38.relative(rootDir, vfile.path).split(path38.sep).join(path38.posix.sep);
15933
16008
  tree.children.unshift(exportMdxjsConst("__filepath", relativePath));
15934
16009
  };
15935
16010
 
@@ -16016,18 +16091,18 @@ var remarkLastModified = () => {
16016
16091
  };
16017
16092
 
16018
16093
  // src/vite/mdx/remark-link-rewrite.ts
16019
- import path38 from "node:path";
16094
+ import path39 from "node:path";
16020
16095
  import { visit as visit5 } from "unist-util-visit";
16021
16096
  var remarkLinkRewrite = (basePath = "") => (tree) => {
16022
16097
  visit5(tree, "link", (node) => {
16023
16098
  if (!node.url) return;
16024
16099
  if (node.url.startsWith("http") || node.url.startsWith("mailto:")) return;
16025
16100
  node.url = node.url.replace(/\\/g, "/");
16026
- const base = path38.posix.join(basePath);
16101
+ const base = path39.posix.join(basePath);
16027
16102
  if (basePath && node.url.startsWith(base)) {
16028
16103
  node.url = node.url.slice(base.length);
16029
16104
  } else if (!node.url.startsWith("/") && !node.url.startsWith("#")) {
16030
- node.url = path38.posix.join("..", node.url);
16105
+ node.url = path39.posix.join("..", node.url);
16031
16106
  }
16032
16107
  node.url = node.url.replace(/\.mdx?(#.*)?$/, "$1");
16033
16108
  });
@@ -16247,14 +16322,14 @@ var plugin_mdx_default = viteMdxPlugin;
16247
16322
 
16248
16323
  // src/vite/plugin-modules.ts
16249
16324
  init_loader();
16250
- import path39 from "node:path";
16325
+ import path40 from "node:path";
16251
16326
  import { normalizePath as normalizePath2 } from "vite";
16252
- var getLandingModuleImport = (moduleDir, mode) => mode === "internal" ? normalizePath2(path39.join(moduleDir, "../module-landing/src/index.tsx")) : "@lukoweb/apitogo-module-landing";
16253
- var getUserPanelModuleImport = (moduleDir, mode) => mode === "internal" ? normalizePath2(path39.join(moduleDir, "../module-user-panel/src/index.tsx")) : "@lukoweb/apitogo-module-user-panel";
16327
+ var getLandingModuleImport = (moduleDir, mode) => mode === "internal" ? normalizePath2(path40.join(moduleDir, "../module-landing/src/index.tsx")) : "@lukoweb/apitogo-module-landing";
16328
+ var getUserPanelModuleImport = (moduleDir, mode) => mode === "internal" ? normalizePath2(path40.join(moduleDir, "../module-user-panel/src/index.tsx")) : "@lukoweb/apitogo-module-user-panel";
16254
16329
  var getBillingPluginImport = (moduleDir, mode) => mode === "internal" ? normalizePath2(
16255
- path39.join(moduleDir, "../plugin-dev-portal-billing/src/index.ts")
16330
+ path40.join(moduleDir, "../plugin-dev-portal-billing/src/index.ts")
16256
16331
  ) : "@lukoweb/apitogo-plugin-dev-portal-billing";
16257
- var resolveProjectPageImport = (rootDir, pagePath) => normalizePath2(path39.resolve(rootDir, pagePath));
16332
+ var resolveProjectPageImport = (rootDir, pagePath) => normalizePath2(path40.resolve(rootDir, pagePath));
16258
16333
  var viteModulesPlugin = () => {
16259
16334
  const virtualModuleId4 = "virtual:zudoku-modules-plugin";
16260
16335
  const resolvedVirtualModuleId5 = `\0${virtualModuleId4}`;
@@ -16394,7 +16469,7 @@ var plugin_modules_default = viteModulesPlugin;
16394
16469
 
16395
16470
  // src/vite/plugin-search.ts
16396
16471
  init_loader();
16397
- import path40 from "node:path";
16472
+ import path41 from "node:path";
16398
16473
  var viteSearchPlugin = () => {
16399
16474
  const virtualModuleId4 = "virtual:zudoku-search-plugin";
16400
16475
  const resolvedVirtualModuleId5 = `\0${virtualModuleId4}`;
@@ -16412,7 +16487,7 @@ var viteSearchPlugin = () => {
16412
16487
  return resolvedVirtualModuleId5;
16413
16488
  }
16414
16489
  if (id === "/pagefind/pagefind.js" && resolvedViteConfig?.publicDir) {
16415
- return path40.join(resolvedViteConfig.publicDir, "pagefind/pagefind.js");
16490
+ return path41.join(resolvedViteConfig.publicDir, "pagefind/pagefind.js");
16416
16491
  }
16417
16492
  },
16418
16493
  async load(id) {
@@ -16551,17 +16626,17 @@ function vitePlugin() {
16551
16626
  }
16552
16627
 
16553
16628
  // src/vite/config.ts
16554
- var browserConfigLoaderPath2 = path41.join(
16629
+ var browserConfigLoaderPath2 = path42.join(
16555
16630
  getZudokuRootDir(),
16556
16631
  "src/config/apitogo-config-loader.browser.ts"
16557
16632
  );
16558
16633
  var resolveMergedPublicDir = (rootDir, merged) => {
16559
16634
  if (merged.publicDir === false) return void 0;
16560
16635
  const rel = typeof merged.publicDir === "string" ? merged.publicDir : "public";
16561
- return path41.resolve(rootDir, rel);
16636
+ return path42.resolve(rootDir, rel);
16562
16637
  };
16563
- var getAppClientEntryPath = () => path41.posix.join(getZudokuRootDir(), "src/app/entry.client.tsx");
16564
- var getAppServerEntryPath = () => path41.posix.join(getZudokuRootDir(), "src/app/entry.server.tsx");
16638
+ var getAppClientEntryPath = () => path42.posix.join(getZudokuRootDir(), "src/app/entry.client.tsx");
16639
+ var getAppServerEntryPath = () => path42.posix.join(getZudokuRootDir(), "src/app/entry.server.tsx");
16565
16640
  var hasLoggedCdnInfo = false;
16566
16641
  var MEDIA_REGEX = /\.(a?png|jpe?g|gif|bmp|svg|webp|tiff|ico|webm|ogg|mp3|wav|m4a|avif|mp4)/i;
16567
16642
  var defineEnvVars = (vars) => Object.fromEntries(
@@ -16591,7 +16666,7 @@ async function getViteConfig(dir, configEnv) {
16591
16666
  );
16592
16667
  if (ZuploEnv.isZuplo) {
16593
16668
  dotenv.config({
16594
- path: path41.resolve(config2.__meta.rootDir, "../.env.zuplo"),
16669
+ path: path42.resolve(config2.__meta.rootDir, "../.env.zuplo"),
16595
16670
  quiet: true
16596
16671
  });
16597
16672
  }
@@ -16616,11 +16691,11 @@ async function getViteConfig(dir, configEnv) {
16616
16691
  client: {
16617
16692
  resolve: {
16618
16693
  alias: {
16619
- [path41.join(
16694
+ [path42.join(
16620
16695
  getZudokuRootDir(),
16621
16696
  "src/config/apitogo-config-loader.node.ts"
16622
16697
  )]: browserConfigLoaderPath2,
16623
- [path41.join(
16698
+ [path42.join(
16624
16699
  getZudokuRootDir(),
16625
16700
  "src/config/apitogo-config-loader.node.js"
16626
16701
  )]: browserConfigLoaderPath2
@@ -16666,8 +16741,8 @@ async function getViteConfig(dir, configEnv) {
16666
16741
  ssr: configEnv.isSsrBuild,
16667
16742
  sourcemap: true,
16668
16743
  target: "es2022",
16669
- outDir: path41.resolve(
16670
- path41.join(
16744
+ outDir: path42.resolve(
16745
+ path42.join(
16671
16746
  dir,
16672
16747
  "dist",
16673
16748
  config2.basePath ?? "",
@@ -16686,7 +16761,7 @@ async function getViteConfig(dir, configEnv) {
16686
16761
  },
16687
16762
  experimental: {
16688
16763
  renderBuiltUrl(filename) {
16689
- if (cdnUrl?.base && [".js", ".css"].includes(path41.extname(filename))) {
16764
+ if (cdnUrl?.base && [".js", ".css"].includes(path42.extname(filename))) {
16690
16765
  return joinUrl(cdnUrl.base, filename);
16691
16766
  }
16692
16767
  if (cdnUrl?.media && MEDIA_REGEX.test(filename)) {
@@ -16699,7 +16774,7 @@ async function getViteConfig(dir, configEnv) {
16699
16774
  esbuildOptions: {
16700
16775
  target: "es2022"
16701
16776
  },
16702
- entries: [path41.posix.join(getZudokuRootDir(), "src/{app,lib}/**")],
16777
+ entries: [path42.posix.join(getZudokuRootDir(), "src/{app,lib}/**")],
16703
16778
  exclude: [
16704
16779
  "@lukoweb/apitogo",
16705
16780
  "@lukoweb/apitogo-plugin-dev-portal-billing"
@@ -16805,7 +16880,7 @@ init_package_json();
16805
16880
  init_joinUrl();
16806
16881
  import assert from "node:assert";
16807
16882
  import { cp, mkdir as mkdir7, writeFile as writeFile8 } from "node:fs/promises";
16808
- import path42 from "node:path";
16883
+ import path43 from "node:path";
16809
16884
  var pkgJson = getZudokuPackageJson();
16810
16885
  function generateOutput({
16811
16886
  config: config2,
@@ -16862,9 +16937,9 @@ async function writeOutput(dir, {
16862
16937
  rewrites
16863
16938
  }) {
16864
16939
  const output2 = generateOutput({ config: config2, redirects, rewrites });
16865
- const outputDir = process.env.VERCEL ? path42.join(dir, ".vercel/output") : path42.join(dir, "dist/.output");
16940
+ const outputDir = process.env.VERCEL ? path43.join(dir, ".vercel/output") : path43.join(dir, "dist/.output");
16866
16941
  await mkdir7(outputDir, { recursive: true });
16867
- const outputFile = path42.join(outputDir, "config.json");
16942
+ const outputFile = path43.join(outputDir, "config.json");
16868
16943
  await writeFile8(outputFile, JSON.stringify(output2, null, 2), "utf-8");
16869
16944
  if (process.env.VERCEL) {
16870
16945
  console.log("Wrote Vercel output to", outputDir);
@@ -16876,7 +16951,7 @@ init_logger();
16876
16951
  init_file_exists();
16877
16952
  import { readFile as readFile10, rm as rm2 } from "node:fs/promises";
16878
16953
  import os from "node:os";
16879
- import path45 from "node:path";
16954
+ import path46 from "node:path";
16880
16955
  import { pathToFileURL } from "node:url";
16881
16956
  import { createIndex } from "pagefind";
16882
16957
  import colors8 from "picocolors";
@@ -16918,7 +16993,7 @@ function throttle(fn) {
16918
16993
  init_joinUrl();
16919
16994
  import { createWriteStream as createWriteStream3, existsSync as existsSync3 } from "node:fs";
16920
16995
  import { mkdir as mkdir8 } from "node:fs/promises";
16921
- import path43 from "node:path";
16996
+ import path44 from "node:path";
16922
16997
  import colors6 from "picocolors";
16923
16998
  import { SitemapStream } from "sitemap";
16924
16999
  async function generateSitemap({
@@ -16932,11 +17007,11 @@ async function generateSitemap({
16932
17007
  return;
16933
17008
  }
16934
17009
  const sitemap = new SitemapStream({ hostname: config2.siteUrl });
16935
- const outputDir = path43.resolve(baseOutputDir, config2.outDir ?? "");
17010
+ const outputDir = path44.resolve(baseOutputDir, config2.outDir ?? "");
16936
17011
  if (!existsSync3(outputDir)) {
16937
17012
  await mkdir8(outputDir, { recursive: true });
16938
17013
  }
16939
- const sitemapOutputPath = path43.join(outputDir, "sitemap.xml");
17014
+ const sitemapOutputPath = path44.join(outputDir, "sitemap.xml");
16940
17015
  const writeStream = createWriteStream3(sitemapOutputPath);
16941
17016
  sitemap.pipe(writeStream);
16942
17017
  let lastmod;
@@ -16966,14 +17041,14 @@ async function generateSitemap({
16966
17041
 
16967
17042
  // src/vite/prerender/utils.ts
16968
17043
  init_joinUrl();
16969
- var resolveRoutePath = (path66) => {
16970
- const segments = path66.split("/");
17044
+ var resolveRoutePath = (path69) => {
17045
+ const segments = path69.split("/");
16971
17046
  if (segments.some((s) => s.startsWith(":") && !s.endsWith("?"))) {
16972
17047
  return void 0;
16973
17048
  }
16974
17049
  return segments.filter((s) => !s.startsWith(":")).join("/") || void 0;
16975
17050
  };
16976
- var isSkipped = (path66) => path66.includes("*") || /^\d+$/.test(path66);
17051
+ var isSkipped = (path69) => path69.includes("*") || /^\d+$/.test(path69);
16977
17052
  var resolveRoutes = (routes, parentPath = "") => routes.flatMap((route) => {
16978
17053
  if (route.path && isSkipped(route.path)) return [];
16979
17054
  const routePath = route.path ? resolveRoutePath(route.path) : void 0;
@@ -17022,12 +17097,12 @@ var prerender = async ({
17022
17097
  serverConfigFilename,
17023
17098
  writeRedirects = true
17024
17099
  }) => {
17025
- const distDir = path45.join(dir, "dist", basePath);
17100
+ const distDir = path46.join(dir, "dist", basePath);
17026
17101
  const serverConfigPath = pathToFileURL(
17027
- path45.join(distDir, "server", serverConfigFilename)
17102
+ path46.join(distDir, "server", serverConfigFilename)
17028
17103
  ).href;
17029
17104
  const entryServerPath = pathToFileURL(
17030
- path45.join(distDir, "server/entry.server.js")
17105
+ path46.join(distDir, "server/entry.server.js")
17031
17106
  ).href;
17032
17107
  const rawConfig = await import(serverConfigPath).then(
17033
17108
  (m) => m.default
@@ -17112,7 +17187,7 @@ var prerender = async ({
17112
17187
  })
17113
17188
  );
17114
17189
  const pagefindWriteResult = await pagefindIndex?.writeFiles({
17115
- outputPath: path45.join(distDir, "pagefind")
17190
+ outputPath: path46.join(distDir, "pagefind")
17116
17191
  });
17117
17192
  const seconds = ((performance.now() - start) / 1e3).toFixed(1);
17118
17193
  const message = `\u2713 finished prerendering ${paths.length} routes in ${seconds} seconds using ${maxThreads} workers`;
@@ -17144,7 +17219,7 @@ var prerender = async ({
17144
17219
  const { generateLlmsTxtFiles: generateLlmsTxtFiles2 } = await Promise.resolve().then(() => (init_llms(), llms_exports));
17145
17220
  const docsConfig = DocsConfigSchema2.parse(config2.docs);
17146
17221
  const llmsConfig = docsConfig.llms ?? {};
17147
- const markdownInfoPath = path45.join(
17222
+ const markdownInfoPath = path46.join(
17148
17223
  dir,
17149
17224
  "node_modules/.apitogo/markdown-info.json"
17150
17225
  );
@@ -17235,7 +17310,7 @@ async function runBuild(options) {
17235
17310
  html,
17236
17311
  basePath: config2.basePath
17237
17312
  });
17238
- await rm3(path46.join(clientOutDir, "index.html"), { force: true });
17313
+ await rm3(path47.join(clientOutDir, "index.html"), { force: true });
17239
17314
  } else {
17240
17315
  await runPrerender({
17241
17316
  dir,
@@ -17259,7 +17334,7 @@ var runPrerender = async (options) => {
17259
17334
  serverConfigFilename,
17260
17335
  writeRedirects: process.env.VERCEL === void 0
17261
17336
  });
17262
- const indexHtml = path46.join(clientOutDir, "index.html");
17337
+ const indexHtml = path47.join(clientOutDir, "index.html");
17263
17338
  if (!workerResults.find((r) => r.outputPath === indexHtml)) {
17264
17339
  await writeFile10(indexHtml, html, "utf-8");
17265
17340
  }
@@ -17269,15 +17344,15 @@ var runPrerender = async (options) => {
17269
17344
  for (const statusPage of statusPages) {
17270
17345
  await rename(
17271
17346
  statusPage,
17272
- path46.join(dir, DIST_DIR, path46.basename(statusPage))
17347
+ path47.join(dir, DIST_DIR, path47.basename(statusPage))
17273
17348
  );
17274
17349
  }
17275
17350
  await rm3(serverOutDir, { recursive: true, force: true });
17276
17351
  if (process.env.VERCEL) {
17277
- await mkdir9(path46.join(dir, ".vercel/output/static"), { recursive: true });
17352
+ await mkdir9(path47.join(dir, ".vercel/output/static"), { recursive: true });
17278
17353
  await rename(
17279
- path46.join(dir, DIST_DIR),
17280
- path46.join(dir, ".vercel/output/static")
17354
+ path47.join(dir, DIST_DIR),
17355
+ path47.join(dir, ".vercel/output/static")
17281
17356
  );
17282
17357
  }
17283
17358
  await writeOutput(dir, {
@@ -17287,7 +17362,7 @@ var runPrerender = async (options) => {
17287
17362
  });
17288
17363
  if (ZuploEnv.isZuplo && issuer) {
17289
17364
  await writeFile10(
17290
- path46.join(dir, DIST_DIR, ".output/zuplo.json"),
17365
+ path47.join(dir, DIST_DIR, ".output/zuplo.json"),
17291
17366
  JSON.stringify({ issuer }, null, 2),
17292
17367
  "utf-8"
17293
17368
  );
@@ -17299,10 +17374,10 @@ var runPrerender = async (options) => {
17299
17374
  };
17300
17375
  var bundleSSREntry = async (options) => {
17301
17376
  const { dir, adapter, serverOutDir, serverConfigFilename, html, basePath } = options;
17302
- const tempEntryPath = path46.join(dir, "__ssr-entry.ts");
17377
+ const tempEntryPath = path47.join(dir, "__ssr-entry.ts");
17303
17378
  const packageRoot = getZudokuRootDir();
17304
17379
  const templateContent = await readFile11(
17305
- path46.join(packageRoot, "src/vite/ssr-templates", `${adapter}.ts`),
17380
+ path47.join(packageRoot, "src/vite/ssr-templates", `${adapter}.ts`),
17306
17381
  "utf-8"
17307
17382
  );
17308
17383
  const entryContent = templateContent.replace('"__TEMPLATE__"', JSON.stringify(html)).replace('"__CONFIG_FILE__"', JSON.stringify(`./${serverConfigFilename}`)).replace(
@@ -17317,9 +17392,9 @@ var bundleSSREntry = async (options) => {
17317
17392
  platform: adapter === "node" ? "node" : "neutral",
17318
17393
  target: "es2022",
17319
17394
  format: "esm",
17320
- outfile: path46.join(serverOutDir, "entry.js"),
17395
+ outfile: path47.join(serverOutDir, "entry.js"),
17321
17396
  external: ["./entry.server.js", `./${serverConfigFilename}`],
17322
- nodePaths: [path46.join(packageRoot, "node_modules")],
17397
+ nodePaths: [path47.join(packageRoot, "node_modules")],
17323
17398
  banner: { js: "// Bundled SSR entry" }
17324
17399
  });
17325
17400
  } finally {
@@ -17332,11 +17407,11 @@ init_logger();
17332
17407
  init_package_json();
17333
17408
 
17334
17409
  // src/cli/preview/handler.ts
17335
- import path47 from "node:path";
17410
+ import path48 from "node:path";
17336
17411
  import { preview as vitePreview } from "vite";
17337
17412
  var DEFAULT_PREVIEW_PORT = 4e3;
17338
17413
  async function preview(argv) {
17339
- const dir = path47.resolve(process.cwd(), argv.dir);
17414
+ const dir = path48.resolve(process.cwd(), argv.dir);
17340
17415
  const viteConfig = await getViteConfig(dir, {
17341
17416
  command: "serve",
17342
17417
  mode: "production",
@@ -17377,7 +17452,7 @@ async function build(argv) {
17377
17452
  printDiagnosticsToConsole("");
17378
17453
  printDiagnosticsToConsole("");
17379
17454
  }
17380
- const dir = path48.resolve(process.cwd(), argv.dir);
17455
+ const dir = path49.resolve(process.cwd(), argv.dir);
17381
17456
  try {
17382
17457
  await runBuild({
17383
17458
  dir,
@@ -17437,12 +17512,12 @@ var build_default = {
17437
17512
  };
17438
17513
 
17439
17514
  // src/cli/check/handler.ts
17440
- import path50 from "node:path";
17515
+ import path51 from "node:path";
17441
17516
 
17442
17517
  // src/cli/platform/tools/check-publish-readiness.ts
17443
- import path49 from "node:path";
17518
+ import path50 from "node:path";
17444
17519
  async function checkPublishReadiness(client, _config, args) {
17445
- const sourceDirectory = path49.resolve(args.sourceDirectory);
17520
+ const sourceDirectory = path50.resolve(args.sourceDirectory);
17446
17521
  const manifest = await readManifest(sourceDirectory) ?? createScaffoldManifest();
17447
17522
  const emailOptions = await resolveEmailOptionsForPublish(
17448
17523
  client,
@@ -17520,7 +17595,7 @@ async function checkPublishReadiness(client, _config, args) {
17520
17595
 
17521
17596
  // src/cli/check/handler.ts
17522
17597
  async function check(argv) {
17523
- const sourceDirectory = path50.resolve(process.cwd(), argv.dir);
17598
+ const sourceDirectory = path51.resolve(process.cwd(), argv.dir);
17524
17599
  const config2 = loadConfig();
17525
17600
  const client = new PlatformApiClient(config2);
17526
17601
  let result;
@@ -17565,13 +17640,13 @@ var check_default = {
17565
17640
  // src/cli/make-config/handler.ts
17566
17641
  import { constants as constants2 } from "node:fs";
17567
17642
  import { access as access8, mkdir as mkdir12, readFile as readFile16, writeFile as writeFile15 } from "node:fs/promises";
17568
- import path58 from "node:path";
17643
+ import path59 from "node:path";
17569
17644
  import { stdin as input2 } from "node:process";
17570
17645
  import { glob as glob5 } from "glob";
17571
17646
 
17572
17647
  // src/cli/scaffold/dev-portal-config-pages.ts
17573
17648
  import { access as access4, readFile as readFile12, rename as rename2, rm as rm4, writeFile as writeFile11 } from "node:fs/promises";
17574
- import path51 from "node:path";
17649
+ import path52 from "node:path";
17575
17650
  async function writeConfigAtomically(filePath, content) {
17576
17651
  const temporaryPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
17577
17652
  try {
@@ -17584,7 +17659,7 @@ async function writeConfigAtomically(filePath, content) {
17584
17659
  }
17585
17660
  async function resolveApitogoConfigPath(sourceDirectory) {
17586
17661
  for (const filename of ["apitogo.config.tsx", "apitogo.config.jsx"]) {
17587
- const configPath = path51.join(sourceDirectory, filename);
17662
+ const configPath = path52.join(sourceDirectory, filename);
17588
17663
  try {
17589
17664
  await access4(configPath);
17590
17665
  return configPath;
@@ -18321,16 +18396,16 @@ async function wireNewDevPortalPageInConfig(sourceDirectory, slug, label) {
18321
18396
 
18322
18397
  // src/cli/scaffold/wire-openapi.ts
18323
18398
  import { access as access6, readFile as readFile14, writeFile as writeFile13 } from "node:fs/promises";
18324
- import path54 from "node:path";
18399
+ import path55 from "node:path";
18325
18400
 
18326
18401
  // src/cli/scaffold/scaffold-dev-portal-site.ts
18327
18402
  import { mkdir as mkdir10, readFile as readFile13, writeFile as writeFile12 } from "node:fs/promises";
18328
- import path53 from "node:path";
18403
+ import path54 from "node:path";
18329
18404
 
18330
18405
  // src/cli/scaffold/create-apitogo-cli.ts
18331
18406
  import { spawn as spawn3 } from "node:child_process";
18332
18407
  import { access as access5, rm as rm5 } from "node:fs/promises";
18333
- import path52 from "node:path";
18408
+ import path53 from "node:path";
18334
18409
 
18335
18410
  // src/cli/scaffold/apitogo-npm-packages.ts
18336
18411
  var DEFAULT_CREATE_APITOGO_PACKAGE2 = "@lukoweb/create-apitogo@latest";
@@ -18431,9 +18506,9 @@ function resolveDocToolPath(explicit) {
18431
18506
  return value || void 0;
18432
18507
  }
18433
18508
  function splitOutputDirectory(outputDirectory) {
18434
- const resolvedOutputDirectory = path52.resolve(outputDirectory);
18435
- const projectName = path52.basename(resolvedOutputDirectory);
18436
- const parentDirectory = path52.dirname(resolvedOutputDirectory);
18509
+ const resolvedOutputDirectory = path53.resolve(outputDirectory);
18510
+ const projectName = path53.basename(resolvedOutputDirectory);
18511
+ const parentDirectory = path53.dirname(resolvedOutputDirectory);
18437
18512
  if (!projectName || projectName === "." || projectName === "..") {
18438
18513
  throw new Error(
18439
18514
  "outputDirectory must be a named folder (e.g. ./dev-portal-site), not the current directory."
@@ -18451,15 +18526,15 @@ async function pathExists3(filePath) {
18451
18526
  }
18452
18527
  async function directoryHasEntries(dir) {
18453
18528
  try {
18454
- const { readdir: readdir3 } = await import("node:fs/promises");
18455
- const entries = await readdir3(dir);
18529
+ const { readdir: readdir4 } = await import("node:fs/promises");
18530
+ const entries = await readdir4(dir);
18456
18531
  return entries.length > 0;
18457
18532
  } catch {
18458
18533
  return false;
18459
18534
  }
18460
18535
  }
18461
18536
  function resolveLocalCreateApitogoEntry(docToolPath) {
18462
- return path52.resolve(docToolPath, "packages/create-zudoku/dist/index.js");
18537
+ return path53.resolve(docToolPath, "packages/create-zudoku/dist/index.js");
18463
18538
  }
18464
18539
  async function resolveCreateApitogoInvocation(options) {
18465
18540
  const docToolPath = resolveDocToolPath(options.docToolPath);
@@ -18541,7 +18616,7 @@ async function runCreateApitogoDevPortal(options) {
18541
18616
  result.exitCode
18542
18617
  );
18543
18618
  }
18544
- if (!await pathExists3(path52.join(resolvedOutputDirectory, "package.json"))) {
18619
+ if (!await pathExists3(path53.join(resolvedOutputDirectory, "package.json"))) {
18545
18620
  throw new CreateApitogoCliError(
18546
18621
  `create-apitogo completed but package.json was not found at ${resolvedOutputDirectory}`,
18547
18622
  result.output,
@@ -18597,7 +18672,7 @@ function ensureRequiredApitogoModules(pkg, options) {
18597
18672
  ]
18598
18673
  ]) {
18599
18674
  if (options.docToolPath) {
18600
- deps[moduleName] = `file:${path53.join(options.docToolPath, localPath)}`;
18675
+ deps[moduleName] = `file:${path54.join(options.docToolPath, localPath)}`;
18601
18676
  continue;
18602
18677
  }
18603
18678
  deps[moduleName] = `npm:${moduleName}@${moduleAliasVersion}`;
@@ -18626,7 +18701,7 @@ function rewritePackageJson(raw, options) {
18626
18701
  if (!deps) continue;
18627
18702
  for (const [dep, relativePath] of Object.entries(DOC_TOOL_LOCAL_PACKAGE_PATHS)) {
18628
18703
  if (dep in deps) {
18629
- deps[dep] = `file:${path53.join(options.docToolPath, relativePath)}`;
18704
+ deps[dep] = `file:${path54.join(options.docToolPath, relativePath)}`;
18630
18705
  linkedWorkspacePackage = true;
18631
18706
  }
18632
18707
  }
@@ -18723,23 +18798,23 @@ function patchDashboardPageConfig(content) {
18723
18798
  );
18724
18799
  }
18725
18800
  async function ensureAccountPlansPage(outputDirectory) {
18726
- const pagePath = path53.join(outputDirectory, ACCOUNT_PLANS_PAGE_PATH);
18801
+ const pagePath = path54.join(outputDirectory, ACCOUNT_PLANS_PAGE_PATH);
18727
18802
  try {
18728
18803
  await readFile13(pagePath, "utf8");
18729
18804
  return void 0;
18730
18805
  } catch {
18731
- await mkdir10(path53.dirname(pagePath), { recursive: true });
18806
+ await mkdir10(path54.dirname(pagePath), { recursive: true });
18732
18807
  await writeFile12(pagePath, ACCOUNT_PLANS_PAGE);
18733
18808
  return ACCOUNT_PLANS_PAGE_PATH;
18734
18809
  }
18735
18810
  }
18736
18811
  async function ensureDashboardPage(outputDirectory) {
18737
- const pagePath = path53.join(outputDirectory, DASHBOARD_PAGE_PATH);
18812
+ const pagePath = path54.join(outputDirectory, DASHBOARD_PAGE_PATH);
18738
18813
  try {
18739
18814
  await readFile13(pagePath, "utf8");
18740
18815
  return void 0;
18741
18816
  } catch {
18742
- await mkdir10(path53.dirname(pagePath), { recursive: true });
18817
+ await mkdir10(path54.dirname(pagePath), { recursive: true });
18743
18818
  await writeFile12(pagePath, DASHBOARD_PAGE);
18744
18819
  return DASHBOARD_PAGE_PATH;
18745
18820
  }
@@ -18790,7 +18865,7 @@ function patchApitogoConfig(content, options) {
18790
18865
  async function patchScaffoldedSite(outputDirectory, options) {
18791
18866
  const title = options.branding?.title ?? options.siteName;
18792
18867
  const filesWritten = [];
18793
- const packageJsonPath = path53.join(outputDirectory, "package.json");
18868
+ const packageJsonPath = path54.join(outputDirectory, "package.json");
18794
18869
  if (options.patchPackageJson !== false) {
18795
18870
  const packageJson2 = await readFile13(packageJsonPath, "utf8");
18796
18871
  await writeFile12(
@@ -18803,7 +18878,7 @@ async function patchScaffoldedSite(outputDirectory, options) {
18803
18878
  );
18804
18879
  filesWritten.push("package.json");
18805
18880
  }
18806
- const configPath = path53.join(outputDirectory, "apitogo.config.tsx");
18881
+ const configPath = path54.join(outputDirectory, "apitogo.config.tsx");
18807
18882
  const configContent = await readFile13(configPath, "utf8");
18808
18883
  await writeFile12(
18809
18884
  configPath,
@@ -18865,15 +18940,7 @@ async function pathExists4(filePath) {
18865
18940
  }
18866
18941
  }
18867
18942
  async function discoverSiteOpenApi(siteDirectory) {
18868
- const site = path54.resolve(siteDirectory);
18869
- const searchedDirectories = [site];
18870
- const candidates = [];
18871
- for (const name of OPENAPI_BASENAMES) {
18872
- const candidate = path54.join(site, name);
18873
- if (await pathExists4(candidate)) {
18874
- candidates.push(candidate);
18875
- }
18876
- }
18943
+ const { candidates, searchedDirectories } = await collectSiteOpenApiFiles(siteDirectory);
18877
18944
  const invalidCandidates = [];
18878
18945
  for (const candidate of candidates) {
18879
18946
  const validation = await validateOpenApiFile(candidate);
@@ -18906,8 +18973,8 @@ async function discoverOpenApiByMode(siteDirectory, mode) {
18906
18973
  return discoverNearbyOpenApi(siteDirectory);
18907
18974
  }
18908
18975
  async function wireDevPortalOpenApi(sourceDirectory, openApiPath) {
18909
- const resolvedSource = path54.resolve(sourceDirectory);
18910
- const resolvedOpenApi = path54.resolve(openApiPath);
18976
+ const resolvedSource = path55.resolve(sourceDirectory);
18977
+ const resolvedOpenApi = path55.resolve(openApiPath);
18911
18978
  const input3 = toSiteRelativeOpenApiInput(resolvedSource, resolvedOpenApi);
18912
18979
  const validation = await validateOpenApiFile(resolvedOpenApi);
18913
18980
  if (!validation.valid) {
@@ -18932,7 +18999,7 @@ async function wireDevPortalOpenApi(sourceDirectory, openApiPath) {
18932
18999
  "utf8"
18933
19000
  );
18934
19001
  } else {
18935
- const tsxConfigPath = path54.join(resolvedSource, "apitogo.config.tsx");
19002
+ const tsxConfigPath = path55.join(resolvedSource, "apitogo.config.tsx");
18936
19003
  const configContent = await readFile14(tsxConfigPath, "utf8");
18937
19004
  try {
18938
19005
  const patched = patchApitogoConfigOpenApiToFile(configContent, input3);
@@ -19020,10 +19087,10 @@ async function discoverAndWireOpenApi(siteDirectory, mode) {
19020
19087
  // src/cli/make-config/interactive.ts
19021
19088
  import { createInterface } from "node:readline/promises";
19022
19089
  import { stdin as input, stdout as output } from "node:process";
19023
- import path56 from "node:path";
19090
+ import path57 from "node:path";
19024
19091
 
19025
19092
  // src/cli/make-config/json-config.ts
19026
- import path55 from "node:path";
19093
+ import path56 from "node:path";
19027
19094
  var APITOGO_JSON_FILENAME = "apitogo.config.json";
19028
19095
  var DOCUMENTATION_NAV_LABEL2 = "Documentation";
19029
19096
  var API_REFERENCE_PATH = "/api";
@@ -19382,9 +19449,9 @@ function openapiInputForConfig(specRelativePosix) {
19382
19449
  return `./${specRelativePosix}`;
19383
19450
  }
19384
19451
  function toRelativeOpenApiInput(projectDir, inputPath) {
19385
- const resolved = path55.isAbsolute(inputPath) ? inputPath : path55.resolve(projectDir, inputPath);
19386
- const relative = path55.relative(projectDir, resolved);
19387
- const posix = relative.split(path55.sep).join(path55.posix.sep);
19452
+ const resolved = path56.isAbsolute(inputPath) ? inputPath : path56.resolve(projectDir, inputPath);
19453
+ const relative = path56.relative(projectDir, resolved);
19454
+ const posix = relative.split(path56.sep).join(path56.posix.sep);
19388
19455
  if (!posix) {
19389
19456
  throw new Error("OpenAPI path must point to a file.");
19390
19457
  }
@@ -19757,7 +19824,7 @@ async function promptMakeConfigInteractive(options) {
19757
19824
  continue;
19758
19825
  }
19759
19826
  const routePath = `/${slug}`;
19760
- const relativePath = path56.posix.join(options.pagesDir, `${slug}.tsx`);
19827
+ const relativePath = path57.posix.join(options.pagesDir, `${slug}.tsx`);
19761
19828
  const page = {
19762
19829
  slug,
19763
19830
  title: pageTitle.trim(),
@@ -19850,7 +19917,7 @@ export default function ${componentName}() {
19850
19917
  init_package_json();
19851
19918
  import { constants } from "node:fs";
19852
19919
  import { access as access7, mkdir as mkdir11, readFile as readFile15, writeFile as writeFile14 } from "node:fs/promises";
19853
- import path57 from "node:path";
19920
+ import path58 from "node:path";
19854
19921
  import { glob as glob4 } from "glob";
19855
19922
 
19856
19923
  // src/cli/make-config/branding-assets.ts
@@ -19874,9 +19941,9 @@ var OPENAPI_GLOBS = [
19874
19941
  "openapi.yaml",
19875
19942
  "openapi.yml"
19876
19943
  ];
19877
- var toPosix = (p) => p.split(path57.sep).join("/");
19944
+ var toPosix = (p) => p.split(path58.sep).join("/");
19878
19945
  var sanitizePackageName = (dir) => {
19879
- const base = path57.basename(path57.resolve(dir));
19946
+ const base = path58.basename(path58.resolve(dir));
19880
19947
  const s = base.toLowerCase().replace(/[^a-z0-9-_.]/g, "-").replace(/^-+|-+$/g, "");
19881
19948
  return s || "apitogo-site";
19882
19949
  };
@@ -19886,7 +19953,7 @@ var apitogoVersionRange = () => {
19886
19953
  };
19887
19954
  async function findOpenApiSpecPath(dir) {
19888
19955
  for (const rel of OPENAPI_GLOBS) {
19889
- const full = path57.join(dir, rel);
19956
+ const full = path58.join(dir, rel);
19890
19957
  try {
19891
19958
  await access7(full, constants.R_OK);
19892
19959
  return toPosix(rel);
@@ -19901,7 +19968,7 @@ async function findOpenApiSpecPath(dir) {
19901
19968
  return extra[0] ? toPosix(extra[0]) : null;
19902
19969
  }
19903
19970
  async function ensurePackageJson(dir) {
19904
- const pkgPath = path57.join(dir, "package.json");
19971
+ const pkgPath = path58.join(dir, "package.json");
19905
19972
  const apitogoVer = apitogoVersionRange();
19906
19973
  const baseDeps = {
19907
19974
  react: ">=19.0.0",
@@ -19968,7 +20035,7 @@ async function ensurePackageJson(dir) {
19968
20035
  return false;
19969
20036
  }
19970
20037
  async function ensureTsconfigJson(dir) {
19971
- const tsPath = path57.join(dir, "tsconfig.json");
20038
+ const tsPath = path58.join(dir, "tsconfig.json");
19972
20039
  try {
19973
20040
  await access7(tsPath, constants.R_OK);
19974
20041
  return false;
@@ -20017,28 +20084,28 @@ var fileExists2 = async (filePath) => {
20017
20084
  }
20018
20085
  };
20019
20086
  async function ensurePortalStubFiles(dir) {
20020
- const landingPath = path57.join(dir, "landing", "LandingPage.tsx");
20087
+ const landingPath = path58.join(dir, "landing", "LandingPage.tsx");
20021
20088
  if (!await fileExists2(landingPath)) {
20022
- await mkdir11(path57.join(dir, "landing"), { recursive: true });
20089
+ await mkdir11(path58.join(dir, "landing"), { recursive: true });
20023
20090
  await writeFile14(landingPath, LANDING_PAGE_SOURCE, "utf8");
20024
20091
  }
20025
- const plansPath = path57.join(dir, "user-panel", "AccountPlansPage.tsx");
20092
+ const plansPath = path58.join(dir, "user-panel", "AccountPlansPage.tsx");
20026
20093
  if (!await fileExists2(plansPath)) {
20027
- await mkdir11(path57.join(dir, "user-panel"), { recursive: true });
20094
+ await mkdir11(path58.join(dir, "user-panel"), { recursive: true });
20028
20095
  await writeFile14(plansPath, ACCOUNT_PLANS_PAGE_SOURCE, "utf8");
20029
20096
  }
20030
- const dashboardPath = path57.join(dir, "user-panel", "DashboardPage.tsx");
20097
+ const dashboardPath = path58.join(dir, "user-panel", "DashboardPage.tsx");
20031
20098
  if (!await fileExists2(dashboardPath)) {
20032
- await mkdir11(path57.join(dir, "user-panel"), { recursive: true });
20099
+ await mkdir11(path58.join(dir, "user-panel"), { recursive: true });
20033
20100
  await writeFile14(dashboardPath, DASHBOARD_PAGE_SOURCE, "utf8");
20034
20101
  }
20035
20102
  await ensurePublicBrandingFiles(dir);
20036
20103
  }
20037
20104
  async function ensurePublicBrandingFiles(dir) {
20038
- const destDir = path57.join(dir, "public");
20105
+ const destDir = path58.join(dir, "public");
20039
20106
  await mkdir11(destDir, { recursive: true });
20040
20107
  for (const { name, content } of BRANDING_ASSETS) {
20041
- const dest = path57.join(destDir, name);
20108
+ const dest = path58.join(destDir, name);
20042
20109
  if (await fileExists2(dest)) {
20043
20110
  continue;
20044
20111
  }
@@ -20046,7 +20113,7 @@ async function ensurePublicBrandingFiles(dir) {
20046
20113
  }
20047
20114
  }
20048
20115
  async function ensureThinConfigTsx(dir) {
20049
- const tsxPath = path57.join(dir, "apitogo.config.tsx");
20116
+ const tsxPath = path58.join(dir, "apitogo.config.tsx");
20050
20117
  if (await fileExists2(tsxPath)) {
20051
20118
  return false;
20052
20119
  }
@@ -20055,7 +20122,7 @@ async function ensureThinConfigTsx(dir) {
20055
20122
  }
20056
20123
 
20057
20124
  // src/cli/make-config/handler.ts
20058
- var toPosixPath2 = (value) => value.split(path58.sep).join(path58.posix.sep);
20125
+ var toPosixPath2 = (value) => value.split(path59.sep).join(path59.posix.sep);
20059
20126
  var fileExists3 = async (filePath) => {
20060
20127
  try {
20061
20128
  await access8(filePath, constants2.F_OK);
@@ -20113,7 +20180,7 @@ async function persistConfig(config2, ctx) {
20113
20180
  };
20114
20181
  await writeFile15(ctx.jsonPath, `${JSON.stringify(next, null, 2)}
20115
20182
  `, "utf8");
20116
- const tsxPath = path58.join(ctx.dir, "apitogo.config.tsx");
20183
+ const tsxPath = path59.join(ctx.dir, "apitogo.config.tsx");
20117
20184
  if (await fileExists3(tsxPath) && tsxRoutes.length > 0) {
20118
20185
  const tsxSource = await readFile16(tsxPath, "utf8");
20119
20186
  if (isManagedConfigWrapper(tsxSource)) {
@@ -20140,7 +20207,7 @@ function mergeBackendFlag(config2, backend) {
20140
20207
  return next;
20141
20208
  }
20142
20209
  async function makeConfig(argv) {
20143
- const dir = path58.resolve(process.cwd(), argv.dir);
20210
+ const dir = path59.resolve(process.cwd(), argv.dir);
20144
20211
  const pagesDir = toPosixPath2(
20145
20212
  argv.pagesDir.replace(/^[./]+/, "").replace(/\/+$/, "")
20146
20213
  );
@@ -20160,14 +20227,14 @@ async function makeConfig(argv) {
20160
20227
  printDiagnosticsToConsole("Created tsconfig.json.");
20161
20228
  }
20162
20229
  await ensurePortalStubFiles(dir);
20163
- const jsonPath = path58.join(dir, APITOGO_JSON_FILENAME);
20230
+ const jsonPath = path59.join(dir, APITOGO_JSON_FILENAME);
20164
20231
  let createdJson = false;
20165
20232
  let config2;
20166
20233
  if (await fileExists3(jsonPath)) {
20167
20234
  config2 = await readJsonConfig(jsonPath);
20168
20235
  } else {
20169
20236
  config2 = createDefaultApitogoJsonConfig({
20170
- title: titleFromDirectoryName(path58.basename(dir)),
20237
+ title: titleFromDirectoryName(path59.basename(dir)),
20171
20238
  pagesDir
20172
20239
  });
20173
20240
  createdJson = true;
@@ -20216,8 +20283,8 @@ async function makeConfig(argv) {
20216
20283
  return;
20217
20284
  }
20218
20285
  if (action2.kind === "page") {
20219
- const pagePath = path58.join(dir, action2.page.relativePath);
20220
- await mkdir12(path58.dirname(pagePath), { recursive: true });
20286
+ const pagePath = path59.join(dir, action2.page.relativePath);
20287
+ await mkdir12(path59.dirname(pagePath), { recursive: true });
20221
20288
  await writeFile15(
20222
20289
  pagePath,
20223
20290
  buildStarterDocsPageTsx(action2.page.slug, action2.page.title),
@@ -20270,7 +20337,7 @@ async function makeConfig(argv) {
20270
20337
  if (argv.openapi) {
20271
20338
  const wire = await wireDevPortalOpenApi(
20272
20339
  dir,
20273
- path58.resolve(dir, argv.openapi)
20340
+ path59.resolve(dir, argv.openapi)
20274
20341
  );
20275
20342
  if (wire.status !== "succeeded") {
20276
20343
  throw new Error(
@@ -20299,7 +20366,7 @@ async function makeConfig(argv) {
20299
20366
  const slug = normalizePageSlug(argv.pageSlug);
20300
20367
  const pageTemplate = normalizePageTemplate(argv.pageTemplate);
20301
20368
  const relativePagePath = pageComponentRelativePath(slug);
20302
- const filePath = path58.join(dir, relativePagePath);
20369
+ const filePath = path59.join(dir, relativePagePath);
20303
20370
  const isUpdate = argv.pageUpdate === true;
20304
20371
  if (isUpdate) {
20305
20372
  if (!await fileExists3(filePath)) {
@@ -20332,7 +20399,7 @@ async function makeConfig(argv) {
20332
20399
  argv.pageContent,
20333
20400
  pageTemplate
20334
20401
  );
20335
- await mkdir12(path58.dirname(filePath), { recursive: true });
20402
+ await mkdir12(path59.dirname(filePath), { recursive: true });
20336
20403
  await writeFile15(filePath, tsx, "utf8");
20337
20404
  const configResult = await wireNewDevPortalPageInConfig(
20338
20405
  dir,
@@ -20345,7 +20412,7 @@ async function makeConfig(argv) {
20345
20412
  pagePath: relativePagePath,
20346
20413
  pageTemplate,
20347
20414
  configUpdated: configResult.updated,
20348
- configPath: configResult.configPath ? path58.relative(dir, configResult.configPath) : null
20415
+ configPath: configResult.configPath ? path59.relative(dir, configResult.configPath) : null
20349
20416
  };
20350
20417
  changes.push("page_add");
20351
20418
  }
@@ -20499,14 +20566,14 @@ var deploy_default = {
20499
20566
 
20500
20567
  // src/cli/dev/handler.ts
20501
20568
  init_joinUrl();
20502
- import path61 from "node:path";
20569
+ import path62 from "node:path";
20503
20570
 
20504
20571
  // src/vite/dev-server.ts
20505
20572
  init_logger();
20506
- import fs10 from "node:fs/promises";
20573
+ import fs11 from "node:fs/promises";
20507
20574
  import http from "node:http";
20508
20575
  import https from "node:https";
20509
- import path60 from "node:path";
20576
+ import path61 from "node:path";
20510
20577
  import { createHttpTerminator } from "http-terminator";
20511
20578
  import {
20512
20579
  createServer as createViteServer,
@@ -20539,7 +20606,7 @@ init_loader();
20539
20606
  // src/vite/pagefind-dev-index.ts
20540
20607
  init_invariant();
20541
20608
  init_joinUrl();
20542
- import path59 from "node:path";
20609
+ import path60 from "node:path";
20543
20610
  import { createIndex as createIndex2 } from "pagefind";
20544
20611
  import { isRunnableDevEnvironment } from "vite";
20545
20612
  async function* buildPagefindDevIndex(vite, config2) {
@@ -20592,7 +20659,7 @@ async function* buildPagefindDevIndex(vite, config2) {
20592
20659
  path: urlPath
20593
20660
  };
20594
20661
  }
20595
- const outputPath = path59.join(vite.config.publicDir, "pagefind");
20662
+ const outputPath = path60.join(vite.config.publicDir, "pagefind");
20596
20663
  await pagefindIndex.writeFiles({ outputPath });
20597
20664
  yield { type: "complete", success: true, indexed };
20598
20665
  }
@@ -20611,9 +20678,9 @@ var DevServer = class {
20611
20678
  this.protocol = "https";
20612
20679
  const { dir } = this.options;
20613
20680
  const [key, cert, ca] = await Promise.all([
20614
- fs10.readFile(path60.resolve(dir, config2.https.key)),
20615
- fs10.readFile(path60.resolve(dir, config2.https.cert)),
20616
- config2.https.ca ? fs10.readFile(path60.resolve(dir, config2.https.ca)) : void 0
20681
+ fs11.readFile(path61.resolve(dir, config2.https.key)),
20682
+ fs11.readFile(path61.resolve(dir, config2.https.cert)),
20683
+ config2.https.ca ? fs11.readFile(path61.resolve(dir, config2.https.ca)) : void 0
20617
20684
  ]);
20618
20685
  return https.createServer({ key, cert, ca });
20619
20686
  }
@@ -20630,7 +20697,7 @@ var DevServer = class {
20630
20697
  );
20631
20698
  const server = await this.createNodeServer(config2);
20632
20699
  if (config2.search?.type === "pagefind" && viteConfig.publicDir !== false) {
20633
- const publicRoot = path60.resolve(
20700
+ const publicRoot = path61.resolve(
20634
20701
  this.options.dir,
20635
20702
  typeof viteConfig.publicDir === "string" ? viteConfig.publicDir : "public"
20636
20703
  );
@@ -20647,7 +20714,7 @@ var DevServer = class {
20647
20714
  // built-in transform middleware which would treat the path as a static asset.
20648
20715
  name: "apitogo:entry-client",
20649
20716
  configureServer(server2) {
20650
- const entryPath = path60.posix.join(
20717
+ const entryPath = path61.posix.join(
20651
20718
  server2.config.base,
20652
20719
  "/__z/entry.client.tsx"
20653
20720
  );
@@ -20812,7 +20879,7 @@ init_package_json();
20812
20879
  async function dev(argv) {
20813
20880
  const packageJson2 = getZudokuPackageJson();
20814
20881
  process.env.NODE_ENV = "development";
20815
- const dir = path61.resolve(process.cwd(), argv.dir);
20882
+ const dir = path62.resolve(process.cwd(), argv.dir);
20816
20883
  const server = new DevServer({
20817
20884
  dir,
20818
20885
  argPort: argv.port,
@@ -20895,23 +20962,521 @@ var dev_default = {
20895
20962
  };
20896
20963
 
20897
20964
  // src/cli/init/handler.ts
20898
- import path62 from "node:path";
20965
+ import path65 from "node:path";
20966
+
20967
+ // src/cli/scaffold/run-scaffold-discovery.ts
20968
+ import { access as access10, readFile as readFile18, writeFile as writeFile17 } from "node:fs/promises";
20969
+ import path64 from "node:path";
20970
+
20971
+ // src/cli/scaffold/wire-docs.ts
20972
+ import {
20973
+ access as access9,
20974
+ lstat,
20975
+ mkdir as mkdir13,
20976
+ readdir as readdir3,
20977
+ readFile as readFile17,
20978
+ readlink,
20979
+ symlink,
20980
+ writeFile as writeFile16
20981
+ } from "node:fs/promises";
20982
+ import path63 from "node:path";
20983
+ var DOCS_DIR_WHITELIST = [
20984
+ "docs",
20985
+ "documents",
20986
+ "documentation",
20987
+ "doc"
20988
+ ];
20989
+ var SKIP_SEARCH_DIRS = /* @__PURE__ */ new Set([
20990
+ "node_modules",
20991
+ ".git",
20992
+ "dist",
20993
+ "build",
20994
+ ".next",
20995
+ "coverage",
20996
+ ".turbo",
20997
+ ".cache",
20998
+ ".apitogo"
20999
+ ]);
21000
+ var PAGES_DIR = "pages";
21001
+ var CONFIG_FILENAME = "apitogo.config.json";
21002
+ async function pathExists5(filePath) {
21003
+ try {
21004
+ await access9(filePath);
21005
+ return true;
21006
+ } catch {
21007
+ return false;
21008
+ }
21009
+ }
21010
+ async function isDirectory(filePath) {
21011
+ try {
21012
+ const stat4 = await lstat(filePath);
21013
+ return stat4.isDirectory();
21014
+ } catch {
21015
+ return false;
21016
+ }
21017
+ }
21018
+ function toPosix2(value) {
21019
+ return value.split(path63.sep).join(path63.posix.sep);
21020
+ }
21021
+ function isWhitelistedDirName(name) {
21022
+ return DOCS_DIR_WHITELIST.includes(name.toLowerCase());
21023
+ }
21024
+ function isInside(parent, child) {
21025
+ const relative = path63.relative(parent, child);
21026
+ return relative === "" || !relative.startsWith("..") && !path63.isAbsolute(relative);
21027
+ }
21028
+ async function collectMarkdownFiles(dir) {
21029
+ const files = [];
21030
+ let entries;
21031
+ try {
21032
+ entries = await readdir3(dir, { withFileTypes: true });
21033
+ } catch {
21034
+ return files;
21035
+ }
21036
+ for (const entry of entries) {
21037
+ if (entry.name.startsWith(".")) {
21038
+ continue;
21039
+ }
21040
+ const full = path63.join(dir, entry.name);
21041
+ if (entry.isDirectory()) {
21042
+ if (SKIP_SEARCH_DIRS.has(entry.name) || entry.isSymbolicLink()) {
21043
+ continue;
21044
+ }
21045
+ files.push(...await collectMarkdownFiles(full));
21046
+ continue;
21047
+ }
21048
+ if ((entry.isFile() || entry.isSymbolicLink()) && /\.mdx?$/i.test(entry.name)) {
21049
+ files.push(full);
21050
+ }
21051
+ }
21052
+ return files;
21053
+ }
21054
+ async function collectSearchRoots(siteDirectory) {
21055
+ const site = path63.resolve(siteDirectory);
21056
+ const parent = path63.dirname(site);
21057
+ const roots = [];
21058
+ const add = (dir) => {
21059
+ const resolved = path63.resolve(dir);
21060
+ if (!roots.includes(resolved)) {
21061
+ roots.push(resolved);
21062
+ }
21063
+ };
21064
+ if (parent && parent !== site) {
21065
+ add(parent);
21066
+ try {
21067
+ const entries = await readdir3(parent, { withFileTypes: true });
21068
+ for (const entry of entries) {
21069
+ if (!entry.isDirectory() || SKIP_SEARCH_DIRS.has(entry.name)) {
21070
+ continue;
21071
+ }
21072
+ add(path63.join(parent, entry.name));
21073
+ }
21074
+ } catch {
21075
+ }
21076
+ }
21077
+ add(site);
21078
+ return roots;
21079
+ }
21080
+ async function discoverNearbyDocsDirectories(siteDirectory) {
21081
+ const site = path63.resolve(siteDirectory);
21082
+ const sitePages = path63.join(site, PAGES_DIR);
21083
+ const searchedDirectories = await collectSearchRoots(site);
21084
+ const directories = [];
21085
+ const seen = /* @__PURE__ */ new Set();
21086
+ const consider = async (dir) => {
21087
+ const resolved = path63.resolve(dir);
21088
+ if (resolved === site || seen.has(resolved) || isInside(sitePages, resolved)) {
21089
+ return;
21090
+ }
21091
+ if (!await isDirectory(resolved)) {
21092
+ return;
21093
+ }
21094
+ const files = (await collectMarkdownFiles(resolved)).sort(
21095
+ (a, b) => a.localeCompare(b)
21096
+ );
21097
+ if (files.length === 0) {
21098
+ return;
21099
+ }
21100
+ seen.add(resolved);
21101
+ directories.push({ sourceDirectory: resolved, files });
21102
+ };
21103
+ for (const root of searchedDirectories) {
21104
+ if (isWhitelistedDirName(path63.basename(root))) {
21105
+ await consider(root);
21106
+ }
21107
+ try {
21108
+ const entries = await readdir3(root, { withFileTypes: true });
21109
+ for (const entry of entries) {
21110
+ if (!entry.isDirectory() || SKIP_SEARCH_DIRS.has(entry.name)) {
21111
+ continue;
21112
+ }
21113
+ if (!isWhitelistedDirName(entry.name)) {
21114
+ continue;
21115
+ }
21116
+ await consider(path63.join(root, entry.name));
21117
+ }
21118
+ } catch {
21119
+ }
21120
+ }
21121
+ return { directories, searchedDirectories };
21122
+ }
21123
+ function slugifyDirName(name) {
21124
+ return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "docs";
21125
+ }
21126
+ async function allocateLinkName(pagesDir, sourceDirectory, used) {
21127
+ const base = slugifyDirName(path63.basename(sourceDirectory));
21128
+ const parent = slugifyDirName(path63.basename(path63.dirname(sourceDirectory)));
21129
+ const candidates = [base, `${parent}-${base}`];
21130
+ let index = 2;
21131
+ while (true) {
21132
+ const name = candidates.shift() ?? `${base}-${index++}`;
21133
+ if (used.has(name)) {
21134
+ continue;
21135
+ }
21136
+ const target = path63.join(pagesDir, name);
21137
+ if (await pathExists5(target)) {
21138
+ const stat4 = await lstat(target);
21139
+ if (!stat4.isDirectory() || !await isManagedLinkDir(target)) {
21140
+ continue;
21141
+ }
21142
+ }
21143
+ used.add(name);
21144
+ return name;
21145
+ }
21146
+ }
21147
+ async function isManagedLinkDir(dir) {
21148
+ try {
21149
+ const entries = await readdir3(dir, { withFileTypes: true });
21150
+ if (entries.length === 0) {
21151
+ return true;
21152
+ }
21153
+ return entries.every(
21154
+ (entry) => entry.isSymbolicLink() || entry.isDirectory()
21155
+ );
21156
+ } catch {
21157
+ return false;
21158
+ }
21159
+ }
21160
+ async function alreadyLinked(linkPath, sourcePath) {
21161
+ try {
21162
+ const stat4 = await lstat(linkPath);
21163
+ if (!stat4.isSymbolicLink()) {
21164
+ return false;
21165
+ }
21166
+ const current = await readlink(linkPath);
21167
+ const resolved = path63.resolve(path63.dirname(linkPath), current);
21168
+ return resolved === path63.resolve(sourcePath);
21169
+ } catch {
21170
+ return false;
21171
+ }
21172
+ }
21173
+ async function linkMarkdownFile(sourcePath, linkPath) {
21174
+ if (await alreadyLinked(linkPath, sourcePath)) {
21175
+ return "exists";
21176
+ }
21177
+ if (await pathExists5(linkPath)) {
21178
+ return "skipped";
21179
+ }
21180
+ await mkdir13(path63.dirname(linkPath), { recursive: true });
21181
+ const relativeTarget = path63.relative(path63.dirname(linkPath), sourcePath);
21182
+ await symlink(
21183
+ relativeTarget,
21184
+ linkPath,
21185
+ process.platform === "win32" ? "file" : void 0
21186
+ );
21187
+ return "linked";
21188
+ }
21189
+ function isPlainObject4(value) {
21190
+ return value !== null && typeof value === "object" && !Array.isArray(value);
21191
+ }
21192
+ async function applyDocsNavigation(siteDirectory, routes) {
21193
+ if (routes.length === 0) {
21194
+ return;
21195
+ }
21196
+ const configPath = path63.join(siteDirectory, CONFIG_FILENAME);
21197
+ if (!await pathExists5(configPath)) {
21198
+ return;
21199
+ }
21200
+ const raw = await readFile17(configPath, "utf8");
21201
+ const parsed = JSON.parse(raw);
21202
+ if (!isPlainObject4(parsed)) {
21203
+ return;
21204
+ }
21205
+ parsed.navigation = mergeDocumentationNavigation(parsed.navigation, routes, {
21206
+ force: false
21207
+ });
21208
+ await writeFile16(configPath, `${JSON.stringify(parsed, null, 2)}
21209
+ `, "utf8");
21210
+ }
21211
+ async function discoverAndWireDocs(siteDirectory) {
21212
+ const site = path63.resolve(siteDirectory);
21213
+ const pagesDir = path63.join(site, PAGES_DIR);
21214
+ const { directories, searchedDirectories } = await discoverNearbyDocsDirectories(site);
21215
+ if (directories.length === 0) {
21216
+ return {
21217
+ status: "not_found",
21218
+ whitelist: DOCS_DIR_WHITELIST,
21219
+ searchedDirectories,
21220
+ sources: [],
21221
+ fileCount: 0,
21222
+ skippedCount: 0
21223
+ };
21224
+ }
21225
+ await mkdir13(pagesDir, { recursive: true });
21226
+ const usedNames = /* @__PURE__ */ new Set();
21227
+ const sources = [];
21228
+ const routes = [];
21229
+ for (const directory of directories) {
21230
+ const linkName = await allocateLinkName(
21231
+ pagesDir,
21232
+ directory.sourceDirectory,
21233
+ usedNames
21234
+ );
21235
+ const linkDirectory = path63.join(pagesDir, linkName);
21236
+ const linked = [];
21237
+ const skipped = [];
21238
+ for (const sourcePath of directory.files) {
21239
+ const relativeSource = toPosix2(
21240
+ path63.relative(directory.sourceDirectory, sourcePath)
21241
+ );
21242
+ const linkPath = path63.join(linkDirectory, relativeSource);
21243
+ const result = await linkMarkdownFile(sourcePath, linkPath);
21244
+ if (result === "skipped") {
21245
+ skipped.push({
21246
+ sourcePath,
21247
+ reason: "target already exists and is not this source"
21248
+ });
21249
+ continue;
21250
+ }
21251
+ const relativeLink = toPosix2(path63.relative(site, linkPath));
21252
+ const route = toRoutePath(relativeLink, PAGES_DIR);
21253
+ linked.push({ sourcePath, linkPath, route, relativeSource });
21254
+ routes.push(route);
21255
+ }
21256
+ sources.push({
21257
+ sourceDirectory: directory.sourceDirectory,
21258
+ linkDirectory,
21259
+ linkName,
21260
+ files: linked,
21261
+ skipped
21262
+ });
21263
+ }
21264
+ await applyDocsNavigation(site, routes);
21265
+ const fileCount = sources.reduce(
21266
+ (sum, source) => sum + source.files.length,
21267
+ 0
21268
+ );
21269
+ const skippedCount = sources.reduce(
21270
+ (sum, source) => sum + source.skipped.length,
21271
+ 0
21272
+ );
21273
+ const status2 = fileCount === 0 ? "not_found" : skippedCount > 0 ? "partial" : "wired";
21274
+ return {
21275
+ status: status2,
21276
+ whitelist: DOCS_DIR_WHITELIST,
21277
+ searchedDirectories,
21278
+ sources,
21279
+ fileCount,
21280
+ skippedCount
21281
+ };
21282
+ }
21283
+ function siteRelative(siteDirectory, filePath) {
21284
+ const relative = toPosix2(path63.relative(siteDirectory, filePath));
21285
+ if (!relative) {
21286
+ return ".";
21287
+ }
21288
+ if (path63.isAbsolute(relative)) {
21289
+ return toPosix2(filePath);
21290
+ }
21291
+ if (relative.startsWith("..")) {
21292
+ return relative;
21293
+ }
21294
+ return `./${relative}`;
21295
+ }
21296
+ function formatOpenApiDiscoveryLines(siteDirectory, openApiDiscovery) {
21297
+ const status2 = String(openApiDiscovery.status ?? "unknown");
21298
+ if (status2 === "wired") {
21299
+ const input3 = typeof openApiDiscovery.openApiInput === "string" ? openApiDiscovery.openApiInput : typeof openApiDiscovery.openApiPath === "string" ? siteRelative(siteDirectory, openApiDiscovery.openApiPath) : "OpenAPI";
21300
+ const title = typeof openApiDiscovery.openApiTitle === "string" ? ` (${openApiDiscovery.openApiTitle})` : "";
21301
+ const apiPath = typeof openApiDiscovery.apiReferencePath === "string" ? openApiDiscovery.apiReferencePath : "/api";
21302
+ return [`OpenAPI: wired ${input3}${title} \u2192 ${apiPath}`];
21303
+ }
21304
+ if (status2 === "skipped") {
21305
+ return ["OpenAPI: search skipped"];
21306
+ }
21307
+ if (status2 === "invalid" || status2 === "wire_failed") {
21308
+ const error = typeof openApiDiscovery.error === "string" ? `: ${openApiDiscovery.error}` : "";
21309
+ return [`OpenAPI: found a spec but did not wire it${error}`];
21310
+ }
21311
+ return ["OpenAPI: none found nearby"];
21312
+ }
21313
+ function formatDocsDiscoveryLines(siteDirectory, docsDiscovery) {
21314
+ if (docsDiscovery.status === "not_found") {
21315
+ return [
21316
+ `Docs: none found in ${DOCS_DIR_WHITELIST.join("/")}/ folders nearby`
21317
+ ];
21318
+ }
21319
+ const lines = [
21320
+ `Docs: linked ${docsDiscovery.fileCount} markdown file${docsDiscovery.fileCount === 1 ? "" : "s"} (not copied)`
21321
+ ];
21322
+ for (const source of docsDiscovery.sources) {
21323
+ const from = siteRelative(siteDirectory, source.sourceDirectory);
21324
+ const to = siteRelative(siteDirectory, source.linkDirectory);
21325
+ lines.push(` ${from} \u2192 ${to}`);
21326
+ for (const file of source.files) {
21327
+ lines.push(` ${file.relativeSource} \u2192 ${file.route}`);
21328
+ }
21329
+ for (const skipped of source.skipped) {
21330
+ lines.push(
21331
+ ` skipped ${siteRelative(siteDirectory, skipped.sourcePath)}`
21332
+ );
21333
+ }
21334
+ }
21335
+ return lines;
21336
+ }
21337
+ function formatInitDiscoveryReport(siteDirectory, openApiDiscovery, docsDiscovery) {
21338
+ return [
21339
+ ...formatOpenApiDiscoveryLines(siteDirectory, openApiDiscovery),
21340
+ ...formatDocsDiscoveryLines(siteDirectory, docsDiscovery)
21341
+ ];
21342
+ }
21343
+
21344
+ // src/cli/scaffold/run-scaffold-discovery.ts
21345
+ async function pathExists6(filePath) {
21346
+ try {
21347
+ await access10(filePath);
21348
+ return true;
21349
+ } catch {
21350
+ return false;
21351
+ }
21352
+ }
21353
+ async function wireOpenApiIntoJsonConfig(siteDirectory, openApiPath) {
21354
+ const input3 = toSiteRelativeOpenApiInput(siteDirectory, openApiPath);
21355
+ const jsonConfigPath = path64.join(siteDirectory, "apitogo.config.json");
21356
+ const raw = await readFile18(jsonConfigPath, "utf8");
21357
+ const siteConfig = JSON.parse(raw);
21358
+ const updated = applyOpenApiToSiteConfig(siteConfig, {
21359
+ input: input3,
21360
+ apiPath: "api"
21361
+ });
21362
+ const backend = updated.backend && typeof updated.backend === "object" && !Array.isArray(updated.backend) ? { ...updated.backend } : {};
21363
+ updated.backend = { ...backend, openApiPath: input3 };
21364
+ await writeFile17(
21365
+ jsonConfigPath,
21366
+ `${JSON.stringify(updated, null, 2)}
21367
+ `,
21368
+ "utf8"
21369
+ );
21370
+ return { input: input3 };
21371
+ }
21372
+ async function discoverAndWireOpenApiLite(siteDirectory, mode) {
21373
+ if (mode === "none") {
21374
+ return {
21375
+ openApiDiscovery: { status: "skipped", mode },
21376
+ wired: false
21377
+ };
21378
+ }
21379
+ const search = mode === "site" ? await collectSiteOpenApiFiles(siteDirectory) : await collectNearbyOpenApiFiles(siteDirectory);
21380
+ const invalidCandidates = [];
21381
+ let selected;
21382
+ for (const candidate of search.candidates) {
21383
+ const content = await readFile18(candidate, "utf8");
21384
+ const parsed = liteParseOpenApi(content, candidate);
21385
+ if (parsed.valid) {
21386
+ selected = {
21387
+ path: candidate,
21388
+ version: parsed.version,
21389
+ title: parsed.title
21390
+ };
21391
+ break;
21392
+ }
21393
+ invalidCandidates.push({ path: candidate, errors: parsed.errors });
21394
+ }
21395
+ if (!selected) {
21396
+ return {
21397
+ openApiDiscovery: {
21398
+ status: search.candidates.length > 0 ? "invalid" : "not_found",
21399
+ candidates: search.candidates,
21400
+ searchedDirectories: search.searchedDirectories,
21401
+ ...invalidCandidates.length > 0 ? { invalidCandidates } : {},
21402
+ suggestion: OPENAPI_NOT_FOUND_SUGGESTION
21403
+ },
21404
+ wired: false
21405
+ };
21406
+ }
21407
+ const jsonConfigPath = path64.join(siteDirectory, "apitogo.config.json");
21408
+ if (!await pathExists6(jsonConfigPath)) {
21409
+ return {
21410
+ openApiDiscovery: {
21411
+ status: "wire_failed",
21412
+ openApiPath: selected.path,
21413
+ error: "apitogo.config.json not found",
21414
+ candidates: search.candidates,
21415
+ searchedDirectories: search.searchedDirectories,
21416
+ suggestion: OPENAPI_NOT_FOUND_SUGGESTION
21417
+ },
21418
+ wired: false
21419
+ };
21420
+ }
21421
+ try {
21422
+ const { input: input3 } = await wireOpenApiIntoJsonConfig(
21423
+ siteDirectory,
21424
+ selected.path
21425
+ );
21426
+ return {
21427
+ openApiDiscovery: {
21428
+ status: "wired",
21429
+ openApiPath: selected.path,
21430
+ openApiInput: input3,
21431
+ openApiTitle: selected.title ?? null,
21432
+ openApiVersion: selected.version ?? null,
21433
+ apiReferencePath: "/api",
21434
+ candidates: search.candidates,
21435
+ searchedDirectories: search.searchedDirectories
21436
+ },
21437
+ wired: true
21438
+ };
21439
+ } catch (error) {
21440
+ return {
21441
+ openApiDiscovery: {
21442
+ status: "wire_failed",
21443
+ openApiPath: selected.path,
21444
+ error: error instanceof Error ? error.message : String(error),
21445
+ candidates: search.candidates,
21446
+ searchedDirectories: search.searchedDirectories,
21447
+ suggestion: OPENAPI_NOT_FOUND_SUGGESTION
21448
+ },
21449
+ wired: false
21450
+ };
21451
+ }
21452
+ }
21453
+ async function runScaffoldDiscovery(siteDirectory, options) {
21454
+ const openapiSearch = options?.openapiSearch ?? "nearby";
21455
+ const { openApiDiscovery } = await discoverAndWireOpenApiLite(
21456
+ siteDirectory,
21457
+ openapiSearch
21458
+ );
21459
+ const docsDiscovery = await discoverAndWireDocs(siteDirectory);
21460
+ return { openApiDiscovery, docsDiscovery };
21461
+ }
21462
+
21463
+ // src/cli/init/handler.ts
20899
21464
  function slugifyName2(name) {
20900
21465
  return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "dev-portal-site";
20901
21466
  }
20902
21467
  function resolveInitOutputDirectory(dirArg, name) {
20903
- const resolved = path62.resolve(process.cwd(), dirArg);
20904
- const base = path62.basename(resolved);
21468
+ const resolved = path65.resolve(process.cwd(), dirArg);
21469
+ const base = path65.basename(resolved);
20905
21470
  const isDot = dirArg === "." || dirArg === "./" || base === "." || resolved === process.cwd();
20906
21471
  if (isDot) {
20907
21472
  const fromName = name?.trim();
20908
21473
  if (!fromName) {
20909
21474
  throw new Error(
20910
- "apitogo init requires a named directory (e.g. apitogo init my-portal), or pass --name when using `.`."
21475
+ "apitogo init requires a named directory (e.g. apitogo init dev-portal), or pass --name when using `.`."
20911
21476
  );
20912
21477
  }
20913
21478
  return {
20914
- outputDirectory: path62.resolve(process.cwd(), slugifyName2(fromName)),
21479
+ outputDirectory: path65.resolve(process.cwd(), slugifyName2(fromName)),
20915
21480
  siteName: fromName
20916
21481
  };
20917
21482
  }
@@ -20945,10 +21510,7 @@ async function init2(argv) {
20945
21510
  siteName,
20946
21511
  includeDefaultPlans: false
20947
21512
  });
20948
- const manifestPath = await writeManifest(
20949
- result.outputDirectory,
20950
- manifest
20951
- );
21513
+ const manifestPath = await writeManifest(result.outputDirectory, manifest);
20952
21514
  const secretsArtifacts = await writeScaffoldSecretsArtifacts(
20953
21515
  result.outputDirectory
20954
21516
  );
@@ -20959,13 +21521,18 @@ async function init2(argv) {
20959
21521
  }
20960
21522
  npmInstall = await runNpmInstall(result.outputDirectory);
20961
21523
  }
20962
- const { openApiDiscovery } = await discoverAndWireOpenApi(
21524
+ const { openApiDiscovery, docsDiscovery } = await runScaffoldDiscovery(
20963
21525
  result.outputDirectory,
20964
- openapiSearch
21526
+ { openapiSearch }
20965
21527
  );
20966
21528
  const siteValidation = await validateDevPortalSiteConfig(
20967
21529
  result.outputDirectory
20968
21530
  );
21531
+ const discoveryReport = formatInitDiscoveryReport(
21532
+ result.outputDirectory,
21533
+ openApiDiscovery,
21534
+ docsDiscovery
21535
+ );
20969
21536
  const devCommand = "npm run dev";
20970
21537
  const response = {
20971
21538
  status: "succeeded",
@@ -20983,9 +21550,11 @@ async function init2(argv) {
20983
21550
  npmInstallCompleted: install,
20984
21551
  npmInstallDurationMs: npmInstall?.durationMs ?? null,
20985
21552
  openApiDiscovery,
21553
+ docsDiscovery,
20986
21554
  openapiSearch,
20987
21555
  previewStarted: false,
20988
21556
  devCommand,
21557
+ discoveryReport,
20989
21558
  message: `Dev portal created in ${result.outputDirectory}. Run \`${devCommand}\` there to preview locally.`,
20990
21559
  ...buildSiteValidationResponseFields(siteValidation)
20991
21560
  };
@@ -20998,6 +21567,9 @@ async function init2(argv) {
20998
21567
  printResultToConsole(
20999
21568
  `Portal scaffolded in ${result.outputDirectory}. Next: apitogo config, apitogo dev, then apitogo apply.`
21000
21569
  );
21570
+ for (const line of discoveryReport) {
21571
+ printDiagnosticsToConsole(line);
21572
+ }
21001
21573
  if (!install) {
21002
21574
  printDiagnosticsToConsole(
21003
21575
  "Skipped npm install (--no-install). Run npm install before npm run dev."
@@ -21148,9 +21720,9 @@ var remove_default = {
21148
21720
  };
21149
21721
 
21150
21722
  // src/cli/status/handler.ts
21151
- import path63 from "node:path";
21723
+ import path66 from "node:path";
21152
21724
  async function status(argv) {
21153
- const sourceDirectory = path63.resolve(process.cwd(), argv.dir);
21725
+ const sourceDirectory = path66.resolve(process.cwd(), argv.dir);
21154
21726
  const config2 = loadConfig();
21155
21727
  const client = new PlatformApiClient(config2);
21156
21728
  let whoamiJson;
@@ -21230,7 +21802,7 @@ var status_default = {
21230
21802
  };
21231
21803
 
21232
21804
  // src/cli/teardown/handler.ts
21233
- import path64 from "node:path";
21805
+ import path67 from "node:path";
21234
21806
  function resultLooksFailed3(payload) {
21235
21807
  try {
21236
21808
  const parsed = JSON.parse(payload);
@@ -21246,7 +21818,7 @@ async function teardown(argv) {
21246
21818
  );
21247
21819
  return;
21248
21820
  }
21249
- const sourceDirectory = path64.resolve(process.cwd(), argv.dir);
21821
+ const sourceDirectory = path67.resolve(process.cwd(), argv.dir);
21250
21822
  const config2 = loadConfig();
21251
21823
  const client = new PlatformApiClient(config2);
21252
21824
  let projectId = argv.projectId?.trim();
@@ -21312,7 +21884,7 @@ var teardown_default = {
21312
21884
 
21313
21885
  // src/cli/common/outdated.ts
21314
21886
  import { existsSync as existsSync4, mkdirSync } from "node:fs";
21315
- import { readFile as readFile17, writeFile as writeFile16 } from "node:fs/promises";
21887
+ import { readFile as readFile19, writeFile as writeFile18 } from "node:fs/promises";
21316
21888
  import { join } from "node:path";
21317
21889
  import colors10 from "picocolors";
21318
21890
  import { gt } from "semver";
@@ -21379,12 +21951,12 @@ function box(message, {
21379
21951
 
21380
21952
  // src/cli/common/xdg/lib.ts
21381
21953
  import { homedir } from "node:os";
21382
- import path65 from "node:path";
21954
+ import path68 from "node:path";
21383
21955
  function defineDirectoryWithFallback(xdgName, fallback) {
21384
21956
  if (process.env[xdgName]) {
21385
21957
  return process.env[xdgName];
21386
21958
  } else {
21387
- return path65.join(homedir(), fallback);
21959
+ return path68.join(homedir(), fallback);
21388
21960
  }
21389
21961
  }
21390
21962
  var XDG_CONFIG_HOME = defineDirectoryWithFallback(
@@ -21399,15 +21971,15 @@ var XDG_STATE_HOME = defineDirectoryWithFallback(
21399
21971
  "XDG_DATA_HOME",
21400
21972
  ".local/state"
21401
21973
  );
21402
- var ZUDOKU_XDG_CONFIG_HOME = path65.join(
21974
+ var ZUDOKU_XDG_CONFIG_HOME = path68.join(
21403
21975
  XDG_CONFIG_HOME,
21404
21976
  CLI_XDG_FOLDER_NAME
21405
21977
  );
21406
- var ZUDOKU_XDG_DATA_HOME = path65.join(
21978
+ var ZUDOKU_XDG_DATA_HOME = path68.join(
21407
21979
  XDG_DATA_HOME,
21408
21980
  CLI_XDG_FOLDER_NAME
21409
21981
  );
21410
- var ZUDOKU_XDG_STATE_HOME = path65.join(
21982
+ var ZUDOKU_XDG_STATE_HOME = path68.join(
21411
21983
  XDG_STATE_HOME,
21412
21984
  CLI_XDG_FOLDER_NAME
21413
21985
  );
@@ -21459,7 +22031,7 @@ async function getVersionCheckInfo() {
21459
22031
  let versionCheckInfo;
21460
22032
  if (existsSync4(versionCheckPath)) {
21461
22033
  try {
21462
- versionCheckInfo = await readFile17(versionCheckPath, "utf-8").then(
22034
+ versionCheckInfo = await readFile19(versionCheckPath, "utf-8").then(
21463
22035
  JSON.parse
21464
22036
  );
21465
22037
  } catch {
@@ -21484,7 +22056,7 @@ async function getVersionCheckInfo() {
21484
22056
  lastCheck: Date.now(),
21485
22057
  latestVersion
21486
22058
  };
21487
- await writeFile16(
22059
+ await writeFile18(
21488
22060
  versionCheckPath,
21489
22061
  JSON.stringify(versionCheckInfo),
21490
22062
  "utf-8"