@lukoweb/apitogo 0.2.49 → 0.2.50

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
@@ -757,12 +757,12 @@ var init_transform_config = __esm({
757
757
 
758
758
  // src/config/apitogo-config-loader.node.ts
759
759
  import { existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
760
- import path17 from "node:path";
760
+ import path18 from "node:path";
761
761
  function loadApitogoConfig(rootDir = process.cwd()) {
762
- const configPath = path17.join(path17.resolve(rootDir), APITOGO_CONFIG_FILENAME);
762
+ const configPath = path18.join(path18.resolve(rootDir), APITOGO_CONFIG_FILENAME);
763
763
  if (!existsSync3(configPath)) {
764
764
  throw new Error(
765
- `Missing ${APITOGO_CONFIG_FILENAME} in ${path17.resolve(rootDir)}`
765
+ `Missing ${APITOGO_CONFIG_FILENAME} in ${path18.resolve(rootDir)}`
766
766
  );
767
767
  }
768
768
  const raw = readFileSync3(configPath, "utf8");
@@ -837,7 +837,7 @@ import { stat as stat4 } from "node:fs/promises";
837
837
  var fileExists;
838
838
  var init_file_exists = __esm({
839
839
  "src/config/file-exists.ts"() {
840
- fileExists = (path96) => stat4(path96).then(() => true).catch(() => false);
840
+ fileExists = (path97) => stat4(path97).then(() => true).catch(() => false);
841
841
  }
842
842
  });
843
843
 
@@ -1095,7 +1095,7 @@ var init_landing_manifest = __esm({
1095
1095
  });
1096
1096
 
1097
1097
  // src/config/local-manifest.ts
1098
- import path18 from "node:path";
1098
+ import path19 from "node:path";
1099
1099
  import { z as z7 } from "zod";
1100
1100
  function isPricingEnabled(manifest) {
1101
1101
  return manifest?.pricing?.enabled === true;
@@ -1148,8 +1148,8 @@ function resolveManifestEnv(viteMode) {
1148
1148
  return viteMode === "production" ? "production" : "development";
1149
1149
  }
1150
1150
  function manifestPathsForEnv(rootDir, _env) {
1151
- const resolvedRoot = path18.resolve(rootDir);
1152
- const configPath = path18.join(resolvedRoot, APITOGO_CONFIG_FILENAME);
1151
+ const resolvedRoot = path19.resolve(rootDir);
1152
+ const configPath = path19.join(resolvedRoot, APITOGO_CONFIG_FILENAME);
1153
1153
  return {
1154
1154
  basePath: configPath,
1155
1155
  overridePath: configPath,
@@ -1841,7 +1841,7 @@ var init_shadcn_registry = __esm({
1841
1841
 
1842
1842
  // src/vite/plugin-theme.ts
1843
1843
  import { createRequire } from "node:module";
1844
- import path19 from "node:path";
1844
+ import path20 from "node:path";
1845
1845
  import { normalizeTheme } from "shiki";
1846
1846
  var THEME_VARIABLES, uncamelize, processColorValue, generateCss, generateRegistryCss, processCustomCss, MAIN_REPLACE, DEFAULT_THEME_REPLACE, GOOGLE_FONTS, getGoogleFontUrl, processFont, processFontConfig, bundledFont, DEFAULT_FONT_SANS, DEFAULT_FONT_MONO, DEFAULT_FONT_HEADING, processFonts, MODULE_SOURCE_PACKAGES, resolveModuleSourceDirs, virtualModuleId, resolvedVirtualModuleId, viteThemePlugin;
1847
1847
  var init_plugin_theme = __esm({
@@ -1956,11 +1956,11 @@ var init_plugin_theme = __esm({
1956
1956
  };
1957
1957
  };
1958
1958
  bundledFont = (pkg) => {
1959
- const dir = path19.dirname(
1959
+ const dir = path20.dirname(
1960
1960
  createRequire(import.meta.url).resolve(`@fontsource/${pkg}/package.json`)
1961
1961
  );
1962
1962
  return [400, 500, 600, 700].map(
1963
- (weight) => path19.join(dir, `latin-${weight}.css`).split(path19.sep).join("/")
1963
+ (weight) => path20.join(dir, `latin-${weight}.css`).split(path20.sep).join("/")
1964
1964
  );
1965
1965
  };
1966
1966
  DEFAULT_FONT_SANS = '"IBM Plex Sans", system-ui, sans-serif';
@@ -2029,7 +2029,7 @@ var init_plugin_theme = __esm({
2029
2029
  resolveModuleSourceDirs = (config2) => {
2030
2030
  if (config2.__meta.mode === "internal") {
2031
2031
  return MODULE_SOURCE_PACKAGES.map(
2032
- (pkg) => path19.join(
2032
+ (pkg) => path20.join(
2033
2033
  config2.__meta.moduleDir,
2034
2034
  "..",
2035
2035
  pkg.replace("@lukoweb/apitogo-", ""),
@@ -2038,12 +2038,12 @@ var init_plugin_theme = __esm({
2038
2038
  );
2039
2039
  }
2040
2040
  const require2 = createRequire(
2041
- path19.join(config2.__meta.rootDir, "package.json")
2041
+ path20.join(config2.__meta.rootDir, "package.json")
2042
2042
  );
2043
2043
  const dirs = [];
2044
2044
  for (const pkg of MODULE_SOURCE_PACKAGES) {
2045
2045
  try {
2046
- dirs.push(path19.dirname(require2.resolve(pkg)));
2046
+ dirs.push(path20.dirname(require2.resolve(pkg)));
2047
2047
  } catch {
2048
2048
  }
2049
2049
  }
@@ -2170,7 +2170,7 @@ ${rootVars.join("\n")}
2170
2170
  ...config2.__meta.dependencies,
2171
2171
  ...config2.__pluginDirs ?? [],
2172
2172
  ...resolveModuleSourceDirs(config2)
2173
- ].map((file) => path19.relative(path19.dirname(id), file))
2173
+ ].map((file) => path20.relative(path20.dirname(id), file))
2174
2174
  );
2175
2175
  const code = [...files].map((file) => `@source "${file}";`);
2176
2176
  code.push("@theme inline {");
@@ -5012,7 +5012,7 @@ var init_ZudokuConfig = __esm({
5012
5012
 
5013
5013
  // src/config/loader.ts
5014
5014
  import { stat as stat5 } from "node:fs/promises";
5015
- import path20 from "node:path";
5015
+ import path21 from "node:path";
5016
5016
  import colors6 from "picocolors";
5017
5017
  import {
5018
5018
  runnerImport,
@@ -5039,7 +5039,7 @@ function mergeJsonConfigWithRuntimeOverrides(fileConfig, importedConfig) {
5039
5039
  }
5040
5040
  async function getConfigFilePath(rootDir) {
5041
5041
  for (const fileName of zudokuConfigFiles) {
5042
- const filepath = path20.join(rootDir, fileName);
5042
+ const filepath = path21.join(rootDir, fileName);
5043
5043
  if (await fileExists(filepath)) {
5044
5044
  return filepath;
5045
5045
  }
@@ -5268,7 +5268,7 @@ __export(llms_exports, {
5268
5268
  generateLlmsTxtFiles: () => generateLlmsTxtFiles
5269
5269
  });
5270
5270
  import { writeFile as writeFile12 } from "node:fs/promises";
5271
- import path44 from "node:path";
5271
+ import path45 from "node:path";
5272
5272
  import colors10 from "picocolors";
5273
5273
  async function generateLlmsTxtFiles({
5274
5274
  markdownFileInfos,
@@ -5303,7 +5303,7 @@ async function generateLlmsTxtFiles({
5303
5303
  }
5304
5304
  }
5305
5305
  const llmsTxt2 = llmsTxtParts.join("\n");
5306
- await writeFile12(path44.join(baseOutputDir, "llms.txt"), llmsTxt2, "utf-8");
5306
+ await writeFile12(path45.join(baseOutputDir, "llms.txt"), llmsTxt2, "utf-8");
5307
5307
  if (process.env.APITOGO_JSON_ONLY !== "1") {
5308
5308
  console.log(colors10.blue("\u2713 generated llms.txt"));
5309
5309
  }
@@ -5331,7 +5331,7 @@ ${info.content}
5331
5331
  }
5332
5332
  const llmsFull = llmsFullParts.join("\n");
5333
5333
  await writeFile12(
5334
- path44.join(baseOutputDir, "llms-full.txt"),
5334
+ path45.join(baseOutputDir, "llms-full.txt"),
5335
5335
  llmsFull,
5336
5336
  "utf-8"
5337
5337
  );
@@ -5834,7 +5834,7 @@ Run the command with --help to see its options.`;
5834
5834
  import yargs from "yargs/yargs";
5835
5835
 
5836
5836
  // src/cli/services/handler.ts
5837
- import path52 from "node:path";
5837
+ import path53 from "node:path";
5838
5838
 
5839
5839
  // src/config/v2/billing.ts
5840
5840
  import { readFile as readFile2 } from "node:fs/promises";
@@ -6073,8 +6073,8 @@ var ConfigV2Schema = z.strictObject({
6073
6073
  var REMOVED_KEYS = {
6074
6074
  "plans.provider": "plans.provider was removed. Only plans.billing.provider (stripe or none) is selectable."
6075
6075
  };
6076
- function pathToString(path96) {
6077
- return path96.reduce(
6076
+ function pathToString(path97) {
6077
+ return path97.reduce(
6078
6078
  (acc, segment) => typeof segment === "number" ? `${acc}[${segment}]` : acc === "" ? String(segment) : `${acc}.${String(segment)}`,
6079
6079
  ""
6080
6080
  );
@@ -6094,9 +6094,9 @@ function step(schema2, segment) {
6094
6094
  }
6095
6095
  return void 0;
6096
6096
  }
6097
- function knownKeysAt(path96) {
6097
+ function knownKeysAt(path97) {
6098
6098
  let current = ConfigV2Schema;
6099
- for (const segment of path96) {
6099
+ for (const segment of path97) {
6100
6100
  if (!current) return [];
6101
6101
  current = step(current, segment);
6102
6102
  }
@@ -6132,7 +6132,7 @@ function unknownKeyHint(fullPath, key, known) {
6132
6132
  return known.length > 0 ? `Allowed keys: ${known.join(", ")}.` : void 0;
6133
6133
  }
6134
6134
  function mapIssue(issue4) {
6135
- const path96 = pathToString(issue4.path);
6135
+ const path97 = pathToString(issue4.path);
6136
6136
  switch (issue4.code) {
6137
6137
  case "unrecognized_keys":
6138
6138
  return issue4.keys.map((key) => {
@@ -6148,20 +6148,20 @@ function mapIssue(issue4) {
6148
6148
  return [
6149
6149
  {
6150
6150
  code: "CONFIG_INVALID_VALUE",
6151
- path: path96,
6151
+ path: path97,
6152
6152
  message: `must be one of: ${issue4.values.map((v) => JSON.stringify(v)).join(", ")}.`
6153
6153
  }
6154
6154
  ];
6155
6155
  case "custom": {
6156
6156
  const code = typeof issue4.params?.code === "string" ? issue4.params.code : "CONFIG_INVALID_VALUE";
6157
- return [{ code, path: path96, message: issue4.message ?? "is invalid." }];
6157
+ return [{ code, path: path97, message: issue4.message ?? "is invalid." }];
6158
6158
  }
6159
6159
  case "invalid_type":
6160
6160
  return [
6161
- /received undefined/.test(issue4.message) ? { code: "CONFIG_MISSING_FIELD", path: path96, message: "is required." } : { code: "CONFIG_INVALID_VALUE", path: path96, message: issue4.message }
6161
+ /received undefined/.test(issue4.message) ? { code: "CONFIG_MISSING_FIELD", path: path97, message: "is required." } : { code: "CONFIG_INVALID_VALUE", path: path97, message: issue4.message }
6162
6162
  ];
6163
6163
  default:
6164
- return [{ code: "CONFIG_INVALID_VALUE", path: path96, message: issue4.message }];
6164
+ return [{ code: "CONFIG_INVALID_VALUE", path: path97, message: issue4.message }];
6165
6165
  }
6166
6166
  }
6167
6167
  function isRecord(value) {
@@ -6483,7 +6483,7 @@ function resolveConfigV2(config2, configPath) {
6483
6483
  docs: {
6484
6484
  enabled: portal.docs?.enabled ?? true,
6485
6485
  provider,
6486
- content: provider === "external" ? [] : portal.docs?.content ? portal.docs.content.map((glob8) => fromConfig(configDir, glob8)) : [toGlobPath(path7.join(dir, "pages", "**", "*.{md,mdx}"))],
6486
+ content: provider === "external" ? [] : portal.docs?.content ? portal.docs.content.map((glob9) => fromConfig(configDir, glob9)) : [toGlobPath(path7.join(dir, "pages", "**", "*.{md,mdx}"))],
6487
6487
  url: portal.docs?.url
6488
6488
  },
6489
6489
  console: { enabled: portal.console?.enabled ?? true },
@@ -6606,10 +6606,141 @@ function loadConfigV2(pathOrDir) {
6606
6606
  }
6607
6607
 
6608
6608
  // src/config/v2/rules.ts
6609
- import { readdir as readdir2, readFile as readFile3, stat as stat2 } from "node:fs/promises";
6609
+ import { readdir as readdir2, readFile as readFile4, stat as stat2 } from "node:fs/promises";
6610
+ import path10 from "node:path";
6611
+ import { glob as glob2 } from "glob";
6612
+ import { parse as parseYaml } from "yaml";
6613
+
6614
+ // src/config/v2/tsx-pages.ts
6615
+ import { readFile as readFile3 } from "node:fs/promises";
6610
6616
  import path9 from "node:path";
6611
6617
  import { glob } from "glob";
6612
- import { parse as parseYaml } from "yaml";
6618
+ import globParent from "glob-parent";
6619
+
6620
+ // src/config/v2/docs-navigation.ts
6621
+ var DOCS_NAVIGATION_LABEL = "Documentation";
6622
+ var emptyBranch = () => ({ pages: /* @__PURE__ */ new Map(), folders: /* @__PURE__ */ new Map() });
6623
+ function folderLabel(name) {
6624
+ const words = name.replace(/[-_]+/g, " ").trim();
6625
+ return words.charAt(0).toUpperCase() + words.slice(1);
6626
+ }
6627
+ var byName = (a, b) => a.localeCompare(b);
6628
+ var toItems = (branch, prefix) => {
6629
+ const names = [...branch.pages.keys()].sort(
6630
+ (a, b) => a === "index" ? -1 : b === "index" ? 1 : byName(a, b)
6631
+ );
6632
+ const folders = [...branch.folders.keys()].sort(byName);
6633
+ const folderPath = prefix === "" ? "/" : `/${prefix.slice(0, -1)}`;
6634
+ return [
6635
+ ...names.map((name) => {
6636
+ const page = branch.pages.get(name);
6637
+ if (page.kind === "custom") {
6638
+ return {
6639
+ type: "custom-page",
6640
+ // The index page of a folder is the folder's own address.
6641
+ path: name === "index" ? folderPath : page.route,
6642
+ label: page.label,
6643
+ element: page.element
6644
+ };
6645
+ }
6646
+ return name === "index" ? { type: "doc", file: `${prefix}${name}`, path: folderPath } : `${prefix}${name}`;
6647
+ }),
6648
+ ...folders.map(
6649
+ (folder) => ({
6650
+ type: "category",
6651
+ label: folderLabel(folder),
6652
+ collapsible: true,
6653
+ collapsed: false,
6654
+ items: toItems(
6655
+ branch.folders.get(folder) ?? emptyBranch(),
6656
+ `${prefix}${folder}/`
6657
+ )
6658
+ })
6659
+ )
6660
+ ];
6661
+ };
6662
+ var branchOf = (root, route) => {
6663
+ const parts = route.split("/").filter(Boolean);
6664
+ const page = parts.pop();
6665
+ const branch = parts.reduce((current, folder) => {
6666
+ const next = current.folders.get(folder) ?? emptyBranch();
6667
+ current.folders.set(folder, next);
6668
+ return next;
6669
+ }, root);
6670
+ return { branch, page };
6671
+ };
6672
+ function docsNavigation(routes, customPages = []) {
6673
+ const root = emptyBranch();
6674
+ for (const route of routes) {
6675
+ const { branch, page } = branchOf(root, route);
6676
+ if (page) branch.pages.set(page, { kind: "doc" });
6677
+ }
6678
+ for (const custom of customPages) {
6679
+ const { branch, page } = branchOf(root, custom.route);
6680
+ if (page && !branch.pages.has(page))
6681
+ branch.pages.set(page, { kind: "custom", ...custom });
6682
+ }
6683
+ const items = toItems(root, "");
6684
+ return items.length === 0 ? [] : [{ type: "category", label: DOCS_NAVIGATION_LABEL, items }];
6685
+ }
6686
+
6687
+ // src/config/v2/tsx-pages.ts
6688
+ var IGNORED = ["**/node_modules/**", "**/dist/**", "**/.git/**"];
6689
+ function isTsxHelper(relative) {
6690
+ return relative.split("/").some((part) => part.startsWith("_")) || /\.(test|spec|stories)\.tsx$/.test(relative) || relative.split("/").includes("node_modules");
6691
+ }
6692
+ function tsxPagePatterns(contentGlobs) {
6693
+ const globs = contentGlobs.map(toGlobPath);
6694
+ const included = globs.filter((pattern) => !pattern.startsWith("!"));
6695
+ const excluded = globs.filter((pattern) => pattern.startsWith("!"));
6696
+ return [
6697
+ ...new Set(
6698
+ included.map(
6699
+ (pattern) => path9.posix.join(globParent(pattern), "**", "*.tsx")
6700
+ )
6701
+ ),
6702
+ ...excluded
6703
+ ];
6704
+ }
6705
+ var TITLE = /export\s+const\s+title\s*(?::\s*string\s*)?=\s*(["'`])((?:\\.|(?!\1).)*)\1/;
6706
+ function tsxPageLabel(source, file) {
6707
+ const match = TITLE.exec(source);
6708
+ if (match?.[2]) return match[2].replace(/\\(.)/g, "$1");
6709
+ const name = path9.basename(file, ".tsx");
6710
+ return folderLabel(
6711
+ name === "index" ? path9.basename(path9.dirname(file)) : name
6712
+ );
6713
+ }
6714
+ async function findTsxPages(contentGlobs) {
6715
+ const patterns = tsxPagePatterns(contentGlobs);
6716
+ const ignore2 = [
6717
+ ...IGNORED,
6718
+ ...patterns.filter((pattern) => pattern.startsWith("!")).map((pattern) => pattern.slice(1))
6719
+ ];
6720
+ const found = /* @__PURE__ */ new Map();
6721
+ for (const pattern of patterns.filter((p) => !p.startsWith("!"))) {
6722
+ const parent = globParent(pattern);
6723
+ const files = await glob(pattern, {
6724
+ absolute: true,
6725
+ posix: true,
6726
+ nodir: true,
6727
+ ignore: ignore2
6728
+ });
6729
+ for (const raw of files.sort()) {
6730
+ const file = raw.replace(/^\/\/\?\//, "");
6731
+ const relative = path9.posix.relative(parent, file);
6732
+ if (isTsxHelper(relative)) continue;
6733
+ const route = `/${relative.replace(/\.tsx$/, "")}`;
6734
+ if (found.has(route)) continue;
6735
+ const source = await readFile3(file, "utf8").catch(() => "");
6736
+ found.set(route, { route, file, label: tsxPageLabel(source, file) });
6737
+ }
6738
+ }
6739
+ return [...found.values()].sort((a, b) => a.route.localeCompare(b.route));
6740
+ }
6741
+ var TSX_PAGE_ELEMENT_PREFIX = "apitogo:tsx-page:";
6742
+
6743
+ // src/config/v2/rules.ts
6613
6744
  var SPEC_MAX_BYTES = 5 * 1024 * 1024;
6614
6745
  var SECRET_REFERENCE2 = /^secret:([A-Za-z_][A-Za-z0-9_]*)$/;
6615
6746
  async function isFile(target) {
@@ -6758,13 +6889,13 @@ async function portalRules(config2, resolved, out) {
6758
6889
  }
6759
6890
  if (await isFile(portal.theme)) {
6760
6891
  try {
6761
- JSON.parse(await readFile3(portal.theme, "utf8"));
6892
+ JSON.parse(await readFile4(portal.theme, "utf8"));
6762
6893
  } catch (error) {
6763
6894
  out.error({
6764
6895
  code: "PORTAL_THEME_INVALID",
6765
6896
  path: "portal.theme",
6766
6897
  message: `the theme file is not valid JSON (${error instanceof Error ? error.message : String(error)}).`,
6767
- hint: path9.relative(resolved.configDir, portal.theme)
6898
+ hint: path10.relative(resolved.configDir, portal.theme)
6768
6899
  });
6769
6900
  }
6770
6901
  }
@@ -6773,16 +6904,17 @@ async function docsContentRule(config2, patterns, resolved, out) {
6773
6904
  const globs = patterns.map(toGlobPath);
6774
6905
  const include = globs.filter((pattern) => !pattern.startsWith("!"));
6775
6906
  const ignore2 = globs.filter((pattern) => pattern.startsWith("!")).map((pattern) => pattern.slice(1));
6776
- const matches = include.length > 0 ? await glob(include, { nodir: true, ignore: ignore2, absolute: true }) : [];
6907
+ const matches = include.length > 0 ? await glob2(include, { nodir: true, ignore: ignore2, absolute: true }) : [];
6777
6908
  if (matches.length > 0) return;
6909
+ if ((await findTsxPages(patterns)).length > 0) return;
6778
6910
  const shown = config2.portal?.docs?.content ?? [
6779
- path9.relative(resolved.configDir, patterns[0] ?? "")
6911
+ path10.relative(resolved.configDir, patterns[0] ?? "")
6780
6912
  ];
6781
6913
  out.warn({
6782
6914
  code: "PORTAL_DOCS_EMPTY",
6783
6915
  path: "portal.docs",
6784
6916
  message: `portal.docs matched 0 files (${shown.join(", ")}). The site will only contain the API reference.`,
6785
- hint: "Add .md or .mdx files, or point docs.content at your existing docs."
6917
+ hint: "Add .md, .mdx or .tsx pages, or point docs.content at your existing docs."
6786
6918
  });
6787
6919
  }
6788
6920
  function isIpLiteral(hostname) {
@@ -6849,8 +6981,8 @@ async function gatewayRules(resolved, out) {
6849
6981
  }
6850
6982
  }
6851
6983
  if (origin.source) {
6852
- const inside = path9.relative(resolved.configDir, origin.source);
6853
- if (inside.startsWith("..") || path9.isAbsolute(inside)) {
6984
+ const inside = path10.relative(resolved.configDir, origin.source);
6985
+ if (inside.startsWith("..") || path10.isAbsolute(inside)) {
6854
6986
  out.error({
6855
6987
  code: "GATEWAY_ORIGIN_INVALID",
6856
6988
  path: "gateway.origin.source",
@@ -6935,7 +7067,7 @@ async function gatewayRules(resolved, out) {
6935
7067
  }
6936
7068
  async function specRule(spec, index, resolved, out) {
6937
7069
  const at = `gateway.specs[${index}]`;
6938
- const shown = path9.relative(resolved.configDir, spec);
7070
+ const shown = path10.relative(resolved.configDir, spec);
6939
7071
  const info = await stat2(spec).catch(() => void 0);
6940
7072
  if (!info?.isFile()) {
6941
7073
  out.error({
@@ -6955,7 +7087,7 @@ async function specRule(spec, index, resolved, out) {
6955
7087
  }
6956
7088
  let document;
6957
7089
  try {
6958
- const text = await readFile3(spec, "utf8");
7090
+ const text = await readFile4(spec, "utf8");
6959
7091
  document = spec.toLowerCase().endsWith(".json") ? JSON.parse(text) : parseYaml(text);
6960
7092
  } catch (error) {
6961
7093
  out.error({
@@ -7104,12 +7236,12 @@ async function plansRules(resolved, out, paid) {
7104
7236
  out.error({
7105
7237
  code: "PLANS_FILE_INVALID",
7106
7238
  path: "plans.file",
7107
- message: `the plan catalog was not found: ${path9.relative(resolved.configDir, plans.file)}.`,
7239
+ message: `the plan catalog was not found: ${path10.relative(resolved.configDir, plans.file)}.`,
7108
7240
  hint: "Create it with `apitogo add plans`."
7109
7241
  });
7110
7242
  } else {
7111
7243
  try {
7112
- JSON.parse(await readFile3(plans.file, "utf8"));
7244
+ JSON.parse(await readFile4(plans.file, "utf8"));
7113
7245
  } catch (error) {
7114
7246
  out.error({
7115
7247
  code: "PLANS_FILE_INVALID",
@@ -7225,8 +7357,8 @@ function portalProfile(resolved) {
7225
7357
  }
7226
7358
 
7227
7359
  // src/config/v2/manifest.ts
7228
- import { mkdir as mkdir3, readFile as readFile4, rename, rm, writeFile as writeFile4 } from "node:fs/promises";
7229
- import path10 from "node:path";
7360
+ import { mkdir as mkdir3, readFile as readFile5, rename, rm, writeFile as writeFile4 } from "node:fs/promises";
7361
+ import path11 from "node:path";
7230
7362
  import { z as z3 } from "zod";
7231
7363
  var SUPPORTED_MANIFEST_SCHEMA = 1;
7232
7364
  var Capabilities = z3.record(z3.string(), z3.boolean()).default({});
@@ -7275,7 +7407,7 @@ var ServiceManifestSchema = z3.looseObject({
7275
7407
  }).optional()
7276
7408
  }).default({})
7277
7409
  });
7278
- var issue = (code, path96, message, hint) => ({ code, path: path96, message, hint });
7410
+ var issue = (code, path97, message, hint) => ({ code, path: path97, message, hint });
7279
7411
  function parseManifest(raw, file = "services.json") {
7280
7412
  const version = typeof raw === "object" && raw !== null && "schemaVersion" in raw ? raw.schemaVersion : void 0;
7281
7413
  if (typeof version === "number" && version > SUPPORTED_MANIFEST_SCHEMA) {
@@ -7308,7 +7440,7 @@ async function readManifest(state) {
7308
7440
  const file = manifestPathFor(state);
7309
7441
  let text;
7310
7442
  try {
7311
- text = await readFile4(file, "utf8");
7443
+ text = await readFile5(file, "utf8");
7312
7444
  } catch (error) {
7313
7445
  if (error.code === "ENOENT") return void 0;
7314
7446
  throw error;
@@ -7492,7 +7624,7 @@ function withPlansEntry(existing, info) {
7492
7624
  }
7493
7625
  async function writeManifest(state, manifest) {
7494
7626
  const file = manifestPathFor(state);
7495
- await mkdir3(path10.dirname(file), { recursive: true });
7627
+ await mkdir3(path11.dirname(file), { recursive: true });
7496
7628
  const temporary = `${file}.${process.pid}.tmp`;
7497
7629
  try {
7498
7630
  await writeFile4(
@@ -7523,7 +7655,7 @@ async function removeServicesFromManifest(state, names) {
7523
7655
  }
7524
7656
 
7525
7657
  // src/config/v2/gateway-reference.ts
7526
- import { readFile as readFile5 } from "node:fs/promises";
7658
+ import { readFile as readFile6 } from "node:fs/promises";
7527
7659
  import { parse } from "yaml";
7528
7660
  var DEFAULT_KEY_HEADER = "Ocp-Apim-Subscription-Key";
7529
7661
  var METHODS = [
@@ -7537,8 +7669,8 @@ var METHODS = [
7537
7669
  "trace"
7538
7670
  ];
7539
7671
  var isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
7540
- function actionKey(method, path96) {
7541
- const trimmed = path96.trim();
7672
+ function actionKey(method, path97) {
7673
+ const trimmed = path97.trim();
7542
7674
  const withSlash = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
7543
7675
  const normalized = withSlash.length > 1 ? withSlash.replace(/\/+$/, "") || "/" : withSlash;
7544
7676
  return `${method.trim().toLowerCase()}:${normalized}`;
@@ -7575,8 +7707,8 @@ var ReferenceSpecError = class extends Error {
7575
7707
  };
7576
7708
  function operationsOf(paths) {
7577
7709
  return Object.entries(paths).flatMap(
7578
- ([path96, item]) => isObject(item) ? METHODS.filter((method) => isObject(item[method])).map(
7579
- (method) => [path96, item, method]
7710
+ ([path97, item]) => isObject(item) ? METHODS.filter((method) => isObject(item[method])).map(
7711
+ (method) => [path97, item, method]
7580
7712
  ) : []
7581
7713
  );
7582
7714
  }
@@ -7591,14 +7723,14 @@ function buildReferenceSpec(specText, options) {
7591
7723
  throw new ReferenceSpecError("The OpenAPI file could not be read.");
7592
7724
  const doc = structuredClone(root);
7593
7725
  const paths = isObject(doc.paths) ? doc.paths : {};
7594
- for (const [path96, item, method] of operationsOf(paths))
7595
- if (options.deniedOperations.has(actionKey(method, path96)))
7726
+ for (const [path97, item, method] of operationsOf(paths))
7727
+ if (options.deniedOperations.has(actionKey(method, path97)))
7596
7728
  delete item[method];
7597
- for (const [path96, item] of Object.entries(paths))
7729
+ for (const [path97, item] of Object.entries(paths))
7598
7730
  if (!isObject(item) || !METHODS.some((method) => method in item))
7599
- delete paths[path96];
7600
- for (const [path96, item, method] of operationsOf(paths))
7601
- if (options.publicOperations.has(actionKey(method, path96)))
7731
+ delete paths[path97];
7732
+ for (const [path97, item, method] of operationsOf(paths))
7733
+ if (options.publicOperations.has(actionKey(method, path97)))
7602
7734
  item[method].security = [];
7603
7735
  doc.servers = [{ url: options.gatewayBaseUrl.replace(/\/+$/, "") }];
7604
7736
  for (const item of Object.values(paths)) {
@@ -7661,7 +7793,7 @@ async function renderReferenceSpec(gateway, gatewayBaseUrl, keyHeaderName) {
7661
7793
  throw new ReferenceSpecError("gateway.specs lists no OpenAPI file.");
7662
7794
  let text;
7663
7795
  try {
7664
- text = await readFile5(file, "utf8");
7796
+ text = await readFile6(file, "utf8");
7665
7797
  } catch {
7666
7798
  throw new ReferenceSpecError(`Cannot read the OpenAPI file ${file}.`);
7667
7799
  }
@@ -7732,69 +7864,16 @@ function stableJson(value) {
7732
7864
  }
7733
7865
 
7734
7866
  // src/config/v2/wrapper.ts
7735
- import { mkdir as mkdir4, readFile as readFile7, rename as rename2, rm as rm2, writeFile as writeFile5 } from "node:fs/promises";
7736
- import path12 from "node:path";
7737
-
7738
- // src/config/v2/docs-navigation.ts
7739
- var DOCS_NAVIGATION_LABEL = "Documentation";
7740
- var emptyBranch = () => ({ pages: /* @__PURE__ */ new Set(), folders: /* @__PURE__ */ new Map() });
7741
- function folderLabel(name) {
7742
- const words = name.replace(/[-_]+/g, " ").trim();
7743
- return words.charAt(0).toUpperCase() + words.slice(1);
7744
- }
7745
- var byName = (a, b) => a.localeCompare(b);
7746
- var toItems = (branch, prefix) => {
7747
- const pages = [...branch.pages].sort(
7748
- (a, b) => a === "index" ? -1 : b === "index" ? 1 : byName(a, b)
7749
- );
7750
- const folders = [...branch.folders.keys()].sort(byName);
7751
- return [
7752
- // The index page of a folder is the folder's own address, so the sidebar also shows on `/`.
7753
- ...pages.map(
7754
- (page) => page === "index" ? {
7755
- type: "doc",
7756
- file: `${prefix}${page}`,
7757
- path: prefix === "" ? "/" : `/${prefix.slice(0, -1)}`
7758
- } : `${prefix}${page}`
7759
- ),
7760
- ...folders.map(
7761
- (folder) => ({
7762
- type: "category",
7763
- label: folderLabel(folder),
7764
- collapsible: true,
7765
- collapsed: false,
7766
- items: toItems(
7767
- branch.folders.get(folder) ?? emptyBranch(),
7768
- `${prefix}${folder}/`
7769
- )
7770
- })
7771
- )
7772
- ];
7773
- };
7774
- function docsNavigation(routes) {
7775
- const root = emptyBranch();
7776
- for (const route of routes) {
7777
- const parts = route.split("/").filter(Boolean);
7778
- const page = parts.pop();
7779
- if (!page) continue;
7780
- const branch = parts.reduce((current, folder) => {
7781
- const next = current.folders.get(folder) ?? emptyBranch();
7782
- current.folders.set(folder, next);
7783
- return next;
7784
- }, root);
7785
- branch.pages.add(page);
7786
- }
7787
- const items = toItems(root, "");
7788
- return items.length === 0 ? [] : [{ type: "category", label: DOCS_NAVIGATION_LABEL, items }];
7789
- }
7867
+ import { mkdir as mkdir4, readFile as readFile8, rename as rename2, rm as rm2, writeFile as writeFile5 } from "node:fs/promises";
7868
+ import path13 from "node:path";
7790
7869
 
7791
7870
  // src/config/v2/home-redirect.ts
7792
- import path11 from "node:path";
7793
- import { glob as glob2 } from "glob";
7794
- import globParent from "glob-parent";
7871
+ import path12 from "node:path";
7872
+ import { glob as glob3 } from "glob";
7873
+ import globParent2 from "glob-parent";
7795
7874
 
7796
7875
  // src/lib/util/readFrontmatter.ts
7797
- import { readFile as readFile6 } from "node:fs/promises";
7876
+ import { readFile as readFile7 } from "node:fs/promises";
7798
7877
  import matter from "gray-matter";
7799
7878
  import { parse as parse2, stringify } from "yaml";
7800
7879
  var yaml = {
@@ -7802,25 +7881,25 @@ var yaml = {
7802
7881
  stringify: (obj) => stringify(obj)
7803
7882
  };
7804
7883
  var readFrontmatter = async (filePath) => {
7805
- const content = await readFile6(filePath, "utf-8");
7884
+ const content = await readFile7(filePath, "utf-8");
7806
7885
  const normalizedContent = content.replace(/\r\n/g, "\n");
7807
7886
  return matter(normalizedContent, { engines: { yaml } });
7808
7887
  };
7809
7888
 
7810
7889
  // src/config/v2/home-redirect.ts
7811
- var IGNORED = ["**/node_modules/**", "**/dist/**", "**/.git/**"];
7890
+ var IGNORED2 = ["**/node_modules/**", "**/dist/**", "**/.git/**"];
7812
7891
  async function docRoutes(patterns, options = {}) {
7813
7892
  const globs = patterns.map(toGlobPath);
7814
7893
  const excluded = globs.filter((pattern) => pattern.startsWith("!")).map((pattern) => pattern.slice(1));
7815
7894
  const included = globs.filter((pattern) => !pattern.startsWith("!"));
7816
7895
  const routes = await Promise.all(
7817
7896
  included.map(async (pattern) => {
7818
- const files = await glob2(pattern, {
7897
+ const files = await glob3(pattern, {
7819
7898
  absolute: true,
7820
7899
  posix: true,
7821
- ignore: [...IGNORED, ...excluded]
7900
+ ignore: [...IGNORED2, ...excluded]
7822
7901
  });
7823
- const parent = globParent(pattern);
7902
+ const parent = globParent2(pattern);
7824
7903
  const published = options.includeDrafts ? files : (await Promise.all(
7825
7904
  files.map(async (file) => ({
7826
7905
  file,
@@ -7828,7 +7907,7 @@ async function docRoutes(patterns, options = {}) {
7828
7907
  }))
7829
7908
  )).filter(({ draft }) => !draft).map(({ file }) => file);
7830
7909
  return published.map(
7831
- (file) => `/${path11.posix.relative(parent, file.replace(/^\/\/\?\//, "")).replace(/\.mdx?$/, "")}`
7910
+ (file) => `/${path12.posix.relative(parent, file.replace(/^\/\/\?\//, "")).replace(/\.mdx?$/, "")}`
7832
7911
  );
7833
7912
  })
7834
7913
  );
@@ -7877,10 +7956,10 @@ function protectedRoutesFor(input5) {
7877
7956
  // src/config/v2/wrapper.ts
7878
7957
  var WRAPPER_FILE = "apitogo.config.tsx";
7879
7958
  var CONTENT_LINK = "content";
7880
- function contentGlob(configDir, glob8) {
7881
- const negated = glob8.startsWith("!");
7882
- const absolute = negated ? glob8.slice(1) : glob8;
7883
- const relative = path12.relative(configDir, absolute).split(path12.sep).join("/");
7959
+ function contentGlob(configDir, glob9) {
7960
+ const negated = glob9.startsWith("!");
7961
+ const absolute = negated ? glob9.slice(1) : glob9;
7962
+ const relative = path13.relative(configDir, absolute).split(path13.sep).join("/");
7884
7963
  return `${negated ? "!" : ""}/${CONTENT_LINK}/${relative}`;
7885
7964
  }
7886
7965
  var PLANS_CONSOLE_CAPABILITIES = [
@@ -8049,7 +8128,7 @@ function buildSiteConfig(resolved, plan2, theme, extras = {}) {
8049
8128
  enabled: true,
8050
8129
  path: "/",
8051
8130
  layout: "landing",
8052
- page: portal.landing.split(path12.sep).join("/")
8131
+ page: portal.landing.split(path13.sep).join("/")
8053
8132
  }
8054
8133
  } : {},
8055
8134
  // The plans pages (pricing, choosing a plan) exist only when billing is on, and the plans service is what makes it so.
@@ -8066,7 +8145,7 @@ function buildSiteConfig(resolved, plan2, theme, extras = {}) {
8066
8145
  ...plan2.docs ? {
8067
8146
  docs: {
8068
8147
  files: portal?.docs.content.map(
8069
- (glob8) => contentGlob(resolved.configDir, glob8)
8148
+ (glob9) => contentGlob(resolved.configDir, glob9)
8070
8149
  )
8071
8150
  }
8072
8151
  } : {},
@@ -8112,33 +8191,72 @@ function authenticationFor(plan2) {
8112
8191
  return { type: "openid", ...signIn };
8113
8192
  }
8114
8193
  var PREVIEW_BANNER_MESSAGE = "Preview mode: sign in with demo@apitogo.local / password to try the console. Run `apitogo deploy` for the real services.";
8115
- function renderWrapper(plan2) {
8194
+ function renderWrapper(plan2, pages = []) {
8116
8195
  const imports = [
8117
8196
  'import { buildApitogoConfig } from "@lukoweb/apitogo/build-config";',
8118
8197
  ...plan2.plansPlugin ? [
8119
8198
  'import { devPortalBillingPlugin } from "@lukoweb/apitogo-plugin-dev-portal-billing";'
8120
8199
  ] : [],
8200
+ ...pages.length > 0 ? ['import { createElement } from "react";'] : [],
8201
+ ...pages.map(
8202
+ (page, index) => `import TsxPage${index} from ${JSON.stringify(page.importPath)};`
8203
+ ),
8121
8204
  `import siteConfig from "./${SITE_CONFIG_FILE}";`
8122
8205
  ];
8123
8206
  const plugins = plan2.plansPlugin ? `[devPortalBillingPlugin(${JSON.stringify(plan2.plansPlugin)})]` : "[]";
8207
+ const pageLines = pages.length === 0 ? [] : [
8208
+ "",
8209
+ "// React docs pages: each sidebar placeholder becomes the page's component.",
8210
+ "const tsxPages: Record<string, any> = {",
8211
+ ...pages.map(
8212
+ (page, index) => ` ${JSON.stringify(page.id)}: TsxPage${index},`
8213
+ ),
8214
+ "};",
8215
+ "const withTsxPages = (items: any[]): any[] =>",
8216
+ " items.map((item) => {",
8217
+ ' if (item === null || typeof item !== "object") return item;',
8218
+ " const page =",
8219
+ ' typeof item.element === "string" ? tsxPages[item.element] : undefined;',
8220
+ " return {",
8221
+ " ...item,",
8222
+ " ...(page ? { element: createElement(page) } : {}),",
8223
+ " ...(Array.isArray(item.items) ? { items: withTsxPages(item.items) } : {}),",
8224
+ " };",
8225
+ " });"
8226
+ ];
8124
8227
  return [
8125
8228
  "// Generated by apitogo from apitogo.config.json and services.json. Do not edit: it is rewritten on every build.",
8126
8229
  ...plan2.preview ? [
8127
8230
  "// PREVIEW: built from a stand-in manifest for local runs. A production build refuses this file."
8128
8231
  ] : [],
8129
8232
  ...imports,
8233
+ ...pageLines,
8130
8234
  "",
8131
- "export default buildApitogoConfig({",
8132
- " ...siteConfig,",
8133
- ` plugins: ${plugins},`,
8134
- "});",
8235
+ // The components go in after buildApitogoConfig: it copies the config with structuredClone, which cannot copy a
8236
+ // React element.
8237
+ ...pages.length > 0 ? [
8238
+ "const config = buildApitogoConfig({",
8239
+ " ...siteConfig,",
8240
+ ` plugins: ${plugins},`,
8241
+ "});",
8242
+ "",
8243
+ "export default {",
8244
+ " ...config,",
8245
+ " navigation: withTsxPages((config as any).navigation ?? []),",
8246
+ "};"
8247
+ ] : [
8248
+ "export default buildApitogoConfig({",
8249
+ " ...siteConfig,",
8250
+ ` plugins: ${plugins},`,
8251
+ "});"
8252
+ ],
8135
8253
  ""
8136
8254
  ].join("\n");
8137
8255
  }
8138
8256
  async function readDemoPlans(file) {
8139
8257
  if (!file) return void 0;
8140
8258
  try {
8141
- const parsed = JSON.parse(await readFile7(file, "utf8"));
8259
+ const parsed = JSON.parse(await readFile8(file, "utf8"));
8142
8260
  return Array.isArray(parsed.plans) ? parsed.plans : void 0;
8143
8261
  } catch {
8144
8262
  return void 0;
@@ -8148,7 +8266,7 @@ async function readTheme(resolved) {
8148
8266
  const file = resolved.portal?.theme;
8149
8267
  if (!file) return void 0;
8150
8268
  try {
8151
- return JSON.parse(await readFile7(file, "utf8"));
8269
+ return JSON.parse(await readFile8(file, "utf8"));
8152
8270
  } catch {
8153
8271
  return void 0;
8154
8272
  }
@@ -8206,9 +8324,19 @@ async function preparePortal(resolved, manifest, mode, options = {}) {
8206
8324
  });
8207
8325
  }
8208
8326
  }
8209
- const hostedDocRoutes = plan2.docs ? await docRoutes(profile.docs.content, {
8327
+ const markdownRoutes = plan2.docs ? await docRoutes(profile.docs.content, {
8210
8328
  includeDrafts: mode === "development"
8211
8329
  }) : [];
8330
+ const tsxPages = plan2.docs ? (await findTsxPages(profile.docs.content)).filter(
8331
+ (page) => !markdownRoutes.includes(page.route)
8332
+ ) : [];
8333
+ const wrapperPages = tsxPages.map((page, index) => ({
8334
+ id: `${TSX_PAGE_ELEMENT_PREFIX}${index}`,
8335
+ importPath: `./${CONTENT_LINK}/${path13.relative(resolved.configDir, page.file).split(path13.sep).join("/")}`
8336
+ }));
8337
+ const hostedDocRoutes = [
8338
+ .../* @__PURE__ */ new Set([...markdownRoutes, ...tsxPages.map((page) => page.route)])
8339
+ ].sort();
8212
8340
  if (plan2.plansPlugin && plan2.docs) {
8213
8341
  const landing = hostedDocRoutes.some(
8214
8342
  (route) => route === "/" || route === "/index"
@@ -8230,7 +8358,14 @@ async function preparePortal(resolved, manifest, mode, options = {}) {
8230
8358
  await readTheme(resolved),
8231
8359
  {
8232
8360
  redirects: home ? [home] : [],
8233
- docsNavigation: docsNavigation(hostedDocRoutes),
8361
+ docsNavigation: docsNavigation(
8362
+ markdownRoutes,
8363
+ tsxPages.map((page, index) => ({
8364
+ route: page.route,
8365
+ label: page.label,
8366
+ element: wrapperPages[index]?.id ?? ""
8367
+ }))
8368
+ ),
8234
8369
  docsPath: pickLandingRoute(hostedDocRoutes),
8235
8370
  demoPlans: plan2.demo && plan2.plansPlugin ? await readDemoPlans(resolved.plans?.file) : void 0,
8236
8371
  protectedRoutes: protectedRoutesFor({
@@ -8241,21 +8376,21 @@ async function preparePortal(resolved, manifest, mode, options = {}) {
8241
8376
  })
8242
8377
  }
8243
8378
  );
8244
- const wrapper = renderWrapper(plan2);
8245
- const wrapperPath = path12.join(resolved.state.generatedDir, WRAPPER_FILE);
8379
+ const wrapper = renderWrapper(plan2, wrapperPages);
8380
+ const wrapperPath = path13.join(resolved.state.generatedDir, WRAPPER_FILE);
8246
8381
  if (options.write !== false) {
8247
- await mkdir4(path12.dirname(wrapperPath), { recursive: true });
8382
+ await mkdir4(path13.dirname(wrapperPath), { recursive: true });
8248
8383
  await writeFile5(
8249
- path12.join(path12.dirname(wrapperPath), SITE_CONFIG_FILE),
8384
+ path13.join(path13.dirname(wrapperPath), SITE_CONFIG_FILE),
8250
8385
  `${JSON.stringify(siteConfig, null, 2)}
8251
8386
  `
8252
8387
  );
8253
- const referenceFile = path12.join(
8254
- path12.dirname(wrapperPath),
8388
+ const referenceFile = path13.join(
8389
+ path13.dirname(wrapperPath),
8255
8390
  REFERENCE_SPEC_FILE
8256
8391
  );
8257
8392
  if (referenceSpec !== void 0) {
8258
- await mkdir4(path12.dirname(referenceFile), { recursive: true });
8393
+ await mkdir4(path13.dirname(referenceFile), { recursive: true });
8259
8394
  await writeFile5(referenceFile, referenceSpec);
8260
8395
  } else {
8261
8396
  await rm2(referenceFile, { force: true });
@@ -8284,9 +8419,9 @@ async function preparePortal(resolved, manifest, mode, options = {}) {
8284
8419
 
8285
8420
  // src/config/v2/workspace.ts
8286
8421
  import { createHash as createHash2 } from "node:crypto";
8287
- import { access as access2, lstat, readFile as readFile8, rm as rm3, writeFile as writeFile6 } from "node:fs/promises";
8288
- import path13 from "node:path";
8289
- import { glob as glob3 } from "glob";
8422
+ import { access as access2, lstat, readFile as readFile9, rm as rm3, writeFile as writeFile6 } from "node:fs/promises";
8423
+ import path14 from "node:path";
8424
+ import { glob as glob4 } from "glob";
8290
8425
 
8291
8426
  // src/config/v2/link-directory.ts
8292
8427
  import { symlink } from "node:fs/promises";
@@ -8319,18 +8454,18 @@ async function relink(target, link) {
8319
8454
  }
8320
8455
  var GENERATED_PACKAGE_JSON = '{\n "private": true,\n "type": "module"\n}\n';
8321
8456
  async function writeGeneratedPackageJson(root) {
8322
- const file = path13.join(root, "package.json");
8323
- const current = await readFile8(file, "utf8").catch(() => void 0);
8457
+ const file = path14.join(root, "package.json");
8458
+ const current = await readFile9(file, "utf8").catch(() => void 0);
8324
8459
  if (current !== GENERATED_PACKAGE_JSON)
8325
8460
  await writeFile6(file, GENERATED_PACKAGE_JSON, "utf8");
8326
8461
  }
8327
8462
  async function materializeWorkspace(resolved, prepared) {
8328
- const root = path13.dirname(prepared.wrapperPath);
8463
+ const root = path14.dirname(prepared.wrapperPath);
8329
8464
  await ensureStateDir(resolved.state);
8330
8465
  await writeGeneratedPackageJson(root);
8331
- await relink(resolved.configDir, path13.join(root, CONTENT_LINK));
8332
- const publicDir = resolved.portal && path13.join(resolved.portal.dir, "public");
8333
- const publicLink = path13.join(root, "public");
8466
+ await relink(resolved.configDir, path14.join(root, CONTENT_LINK));
8467
+ const publicDir = resolved.portal && path14.join(resolved.portal.dir, "public");
8468
+ const publicLink = path14.join(root, "public");
8334
8469
  if (publicDir && await exists2(publicDir)) {
8335
8470
  await relink(publicDir, publicLink);
8336
8471
  } else {
@@ -8339,7 +8474,7 @@ async function materializeWorkspace(resolved, prepared) {
8339
8474
  return root;
8340
8475
  }
8341
8476
  async function configFingerprint(configPath) {
8342
- const text = await readFile8(configPath, "utf8");
8477
+ const text = await readFile9(configPath, "utf8");
8343
8478
  try {
8344
8479
  const raw = JSON.parse(text);
8345
8480
  if (raw.project) {
@@ -8355,8 +8490,10 @@ async function portalArtifactHash(resolved, manifestText, cliVersion, wrapper =
8355
8490
  const portal = resolved.portal;
8356
8491
  const patterns = [
8357
8492
  ...portal?.docs.content ?? [],
8493
+ // React docs pages and the helpers next to them are imported by the wrapper, so their contents decide the build too.
8494
+ ...portal?.docs.provider === "apitogo" ? tsxPagePatterns(portal.docs.content) : [],
8358
8495
  ...resolved.gateway?.specs ?? [],
8359
- ...portal ? [portal.theme, path13.join(portal.dir, "public", "**", "*")] : []
8496
+ ...portal ? [portal.theme, path14.join(portal.dir, "public", "**", "*")] : []
8360
8497
  ];
8361
8498
  const positive = patterns.filter((p) => !p.startsWith("!"));
8362
8499
  const ignore2 = patterns.filter((p) => p.startsWith("!")).map((p) => p.slice(1));
@@ -8364,7 +8501,7 @@ async function portalArtifactHash(resolved, manifestText, cliVersion, wrapper =
8364
8501
  ...new Set(
8365
8502
  (await Promise.all(
8366
8503
  positive.map(
8367
- (pattern) => glob3(pattern.split(path13.sep).join("/"), {
8504
+ (pattern) => glob4(pattern.split(path14.sep).join("/"), {
8368
8505
  absolute: true,
8369
8506
  nodir: true,
8370
8507
  ignore: [...ignore2, "**/node_modules/**"]
@@ -8386,9 +8523,9 @@ async function portalArtifactHash(resolved, manifestText, cliVersion, wrapper =
8386
8523
  `);
8387
8524
  }
8388
8525
  for (const file of files) {
8389
- hash2.update(`file:${path13.relative(resolved.configDir, file)}
8526
+ hash2.update(`file:${path14.relative(resolved.configDir, file)}
8390
8527
  `);
8391
- hash2.update(await readFile8(file));
8528
+ hash2.update(await readFile9(file));
8392
8529
  }
8393
8530
  return hash2.digest("hex");
8394
8531
  }
@@ -8404,7 +8541,7 @@ import {
8404
8541
  stat as stat3,
8405
8542
  writeFile as writeFile7
8406
8543
  } from "node:fs/promises";
8407
- import path14 from "node:path";
8544
+ import path15 from "node:path";
8408
8545
 
8409
8546
  // src/config/v2/full-server.ts
8410
8547
  var FULL_SERVER_SOURCE = "server";
@@ -8770,7 +8907,7 @@ var exists3 = (target) => access3(target).then(
8770
8907
  () => true,
8771
8908
  () => false
8772
8909
  );
8773
- var rel = (dir, target) => path14.relative(dir, target).split(path14.sep).join("/") || ".";
8910
+ var rel = (dir, target) => path15.relative(dir, target).split(path15.sep).join("/") || ".";
8774
8911
  var BLANK_SPEC = (name) => `openapi: 3.1.0
8775
8912
  info:
8776
8913
  title: ${JSON.stringify(name)}
@@ -8869,14 +9006,14 @@ function pair(value, flag, unit) {
8869
9006
  return [Number(match[1]), Number(match[2])];
8870
9007
  }
8871
9008
  function insideProject(dir, requested, what) {
8872
- const absolute = path14.resolve(dir, requested);
8873
- const relative = path14.relative(dir, absolute);
8874
- if (relative === "" || relative.startsWith("..") || path14.isAbsolute(relative)) {
9009
+ const absolute = path15.resolve(dir, requested);
9010
+ const relative = path15.relative(dir, absolute);
9011
+ if (relative === "" || relative.startsWith("..") || path15.isAbsolute(relative)) {
8875
9012
  throw new ServiceEditError(
8876
9013
  `${what} "${requested}" is outside the project directory.`
8877
9014
  );
8878
9015
  }
8879
- return relative.split(path14.sep).join("/");
9016
+ return relative.split(path15.sep).join("/");
8880
9017
  }
8881
9018
  async function addFile(context, target, content) {
8882
9019
  if (await exists3(target)) context.keep.push(target);
@@ -8928,16 +9065,16 @@ async function buildPortal(context) {
8928
9065
  { value: "starter", label: "A starter page I can edit" },
8929
9066
  { value: "blank", label: "An empty pages folder" }
8930
9067
  ]);
8931
- const pages = path14.join(resolved.root, "portal", "pages");
9068
+ const pages = path15.join(resolved.root, "portal", "pages");
8932
9069
  if (template === "blank")
8933
- await addFile(context, path14.join(pages, ".gitkeep"), "");
9070
+ await addFile(context, path15.join(pages, ".gitkeep"), "");
8934
9071
  else if (isFilled(options.template)) {
8935
9072
  await addFile(
8936
9073
  context,
8937
- path14.join(pages, "introduction.mdx"),
9074
+ path15.join(pages, "introduction.mdx"),
8938
9075
  starterPage(name)
8939
9076
  );
8940
- const landingFile = path14.join(
9077
+ const landingFile = path15.join(
8941
9078
  resolved.root,
8942
9079
  "portal",
8943
9080
  "landing",
@@ -8955,7 +9092,7 @@ async function buildPortal(context) {
8955
9092
  } else
8956
9093
  await addFile(
8957
9094
  context,
8958
- path14.join(pages, "index.mdx"),
9095
+ path15.join(pages, "index.mdx"),
8959
9096
  starterPage(name)
8960
9097
  );
8961
9098
  }
@@ -8971,18 +9108,18 @@ async function buildPortal(context) {
8971
9108
  };
8972
9109
  }
8973
9110
  async function createSourceFolder(context, sourcePath, runtime, writeSample) {
8974
- const folder = path14.join(context.dir, sourcePath);
9111
+ const folder = path15.join(context.dir, sourcePath);
8975
9112
  const entries = await readdir3(folder).catch(() => []);
8976
9113
  if (entries.some((name) => name !== ".gitkeep")) return false;
8977
9114
  if (writeSample && runtime === FULL_SERVER_RUNTIME) {
8978
9115
  for (const [file, content] of Object.entries(
8979
9116
  fullServerFiles(context.resolved.project.name)
8980
9117
  ))
8981
- await addFile(context, path14.join(folder, file), content);
9118
+ await addFile(context, path15.join(folder, file), content);
8982
9119
  return true;
8983
9120
  }
8984
9121
  if (entries.length === 0)
8985
- await addFile(context, path14.join(folder, ".gitkeep"), "");
9122
+ await addFile(context, path15.join(folder, ".gitkeep"), "");
8986
9123
  context.notes.push(
8987
9124
  `The folder ${sourcePath}/ is empty: put your backend code there before you deploy.`
8988
9125
  );
@@ -9094,7 +9231,7 @@ async function buildGateway(context) {
9094
9231
  specs = [];
9095
9232
  for (const requested of requestedSpecs) {
9096
9233
  const relative = insideProject(dir, requested, "OpenAPI file");
9097
- if (!await stat3(path14.join(dir, relative)).then(
9234
+ if (!await stat3(path15.join(dir, relative)).then(
9098
9235
  (s) => s.isFile(),
9099
9236
  () => false
9100
9237
  )) {
@@ -9105,7 +9242,7 @@ async function buildGateway(context) {
9105
9242
  specs.push(relative);
9106
9243
  }
9107
9244
  } else if (createSpec) {
9108
- const target = path14.join(resolved.apisDir, "openapi.yaml");
9245
+ const target = path15.join(resolved.apisDir, "openapi.yaml");
9109
9246
  await addFile(
9110
9247
  context,
9111
9248
  target,
@@ -9199,7 +9336,7 @@ async function buildPlans(context) {
9199
9336
  const o = options.plans ?? {};
9200
9337
  const template = o.template ?? (options.template === "blank" ? "none" : isFilled(options.template) ? "starter" : "free");
9201
9338
  const file = o.file ? insideProject(dir, o.file, "Plans file") : void 0;
9202
- const target = file ? path14.join(dir, file) : resolved.plans?.file ?? path14.join(resolved.root, "plans.json");
9339
+ const target = file ? path15.join(dir, file) : resolved.plans?.file ?? path15.join(resolved.root, "plans.json");
9203
9340
  await addFile(
9204
9341
  context,
9205
9342
  target,
@@ -9232,11 +9369,11 @@ function dependencyProblems(config2, configPath) {
9232
9369
  return checkDependencies(config2, resolveConfigV2(config2, configPath));
9233
9370
  }
9234
9371
  async function planAddService(service, options) {
9235
- const dir = path14.resolve(options.dir);
9372
+ const dir = path15.resolve(options.dir);
9236
9373
  const { config: config2, resolved } = loadConfigV2(dir);
9237
9374
  if (config2[service] !== void 0) {
9238
9375
  throw new ServiceEditError(
9239
- `${service} is already in ${path14.basename(resolved.configPath)}.`,
9376
+ `${service} is already in ${path15.basename(resolved.configPath)}.`,
9240
9377
  `Edit the file, or run \`apitogo remove ${service}\` first. Its files are kept.`
9241
9378
  );
9242
9379
  }
@@ -9281,11 +9418,11 @@ async function planAddService(service, options) {
9281
9418
  };
9282
9419
  }
9283
9420
  async function planRemoveService(service, options) {
9284
- const dir = path14.resolve(options.dir);
9421
+ const dir = path15.resolve(options.dir);
9285
9422
  const { config: config2, resolved } = loadConfigV2(dir);
9286
9423
  if (config2[service] === void 0) {
9287
9424
  throw new ServiceEditError(
9288
- `${service} is not in ${path14.basename(resolved.configPath)}.`
9425
+ `${service} is not in ${path15.basename(resolved.configPath)}.`
9289
9426
  );
9290
9427
  }
9291
9428
  const { [service]: removed, ...rest } = config2;
@@ -9309,8 +9446,8 @@ async function planRemoveService(service, options) {
9309
9446
  if (service === "gateway" && r.gateway) owned.push(...r.gateway.specs);
9310
9447
  void removed;
9311
9448
  const inside = (target) => {
9312
- const relative = path14.relative(resolved.root, target);
9313
- return relative !== "" && !relative.startsWith("..") && !path14.isAbsolute(relative);
9449
+ const relative = path15.relative(resolved.root, target);
9450
+ return relative !== "" && !relative.startsWith("..") && !path15.isAbsolute(relative);
9314
9451
  };
9315
9452
  const deletes = [];
9316
9453
  const left = [];
@@ -9349,7 +9486,7 @@ async function writeConfig(configPath, config2) {
9349
9486
  async function applyServiceEdit(edit) {
9350
9487
  const created = [];
9351
9488
  for (const file of edit.files) {
9352
- await mkdir5(path14.dirname(file.path), { recursive: true });
9489
+ await mkdir5(path15.dirname(file.path), { recursive: true });
9353
9490
  try {
9354
9491
  await writeFile7(file.path, file.content, { flag: "wx" });
9355
9492
  created.push(file.path);
@@ -9365,7 +9502,7 @@ async function applyServiceEdit(edit) {
9365
9502
  function formatServiceEdit(edit) {
9366
9503
  const verb = edit.action === "add" ? "Adds" : "Removes";
9367
9504
  return [
9368
- `${verb} the ${edit.service} section in ${path14.basename(edit.configPath)}.`,
9505
+ `${verb} the ${edit.service} section in ${path15.basename(edit.configPath)}.`,
9369
9506
  ...edit.files.length > 0 ? [
9370
9507
  "Will create:",
9371
9508
  ...edit.files.map((file) => ` ${rel(edit.dir, file.path)}`)
@@ -9405,8 +9542,8 @@ async function clearProjectId(dir, projectId) {
9405
9542
 
9406
9543
  // src/config/v2/ledger.ts
9407
9544
  init_invariant();
9408
- import { mkdir as mkdir6, readFile as readFile9, rename as rename4, rm as rm5, writeFile as writeFile8 } from "node:fs/promises";
9409
- import path15 from "node:path";
9545
+ import { mkdir as mkdir6, readFile as readFile10, rename as rename4, rm as rm5, writeFile as writeFile8 } from "node:fs/promises";
9546
+ import path16 from "node:path";
9410
9547
  var LEDGER_VERSION = 1;
9411
9548
  var LedgerError = class extends ApitogoError {
9412
9549
  constructor(code, message, developerHint) {
@@ -9422,7 +9559,7 @@ var emptyLedger = () => ({
9422
9559
  async function readLedger(state) {
9423
9560
  let text;
9424
9561
  try {
9425
- text = await readFile9(state.file, "utf8");
9562
+ text = await readFile10(state.file, "utf8");
9426
9563
  } catch (error) {
9427
9564
  if (error.code === "ENOENT")
9428
9565
  return emptyLedger();
@@ -9461,7 +9598,7 @@ function corrupt(file, why) {
9461
9598
  );
9462
9599
  }
9463
9600
  async function writeLedger(state, ledger) {
9464
- await mkdir6(path15.dirname(state.file), { recursive: true });
9601
+ await mkdir6(path16.dirname(state.file), { recursive: true });
9465
9602
  const temporary = `${state.file}.${process.pid}.tmp`;
9466
9603
  try {
9467
9604
  await writeFile8(temporary, `${JSON.stringify(ledger, null, 2)}
@@ -9557,8 +9694,8 @@ init_invariant();
9557
9694
 
9558
9695
  // src/cli/check/v2.ts
9559
9696
  init_apitogo_config_core();
9560
- import { readFile as readFile16 } from "node:fs/promises";
9561
- import path49 from "node:path";
9697
+ import { readFile as readFile17 } from "node:fs/promises";
9698
+ import path50 from "node:path";
9562
9699
 
9563
9700
  // src/cli/platform/client/platform-api.ts
9564
9701
  import { basename } from "node:path";
@@ -9671,8 +9808,8 @@ var PlatformApiClient = class {
9671
9808
  constructor(config2) {
9672
9809
  this.config = config2;
9673
9810
  }
9674
- url(path96) {
9675
- return `${this.config.apiUrl}${path96.startsWith("/") ? path96 : `/${path96}`}`;
9811
+ url(path97) {
9812
+ return `${this.config.apiUrl}${path97.startsWith("/") ? path97 : `/${path97}`}`;
9676
9813
  }
9677
9814
  headers(extra) {
9678
9815
  return {
@@ -9682,9 +9819,9 @@ var PlatformApiClient = class {
9682
9819
  ...extra
9683
9820
  };
9684
9821
  }
9685
- async request(method, path96, init3) {
9822
+ async request(method, path97, init3) {
9686
9823
  const response = await fetchWithRetry(
9687
- this.url(path96),
9824
+ this.url(path97),
9688
9825
  {
9689
9826
  method,
9690
9827
  ...init3,
@@ -10130,15 +10267,15 @@ var PlatformApiClient = class {
10130
10267
  }
10131
10268
  );
10132
10269
  }
10133
- deleteDevPortalPage(projectId, path96) {
10134
- const query = new URLSearchParams({ path: path96 });
10270
+ deleteDevPortalPage(projectId, path97) {
10271
+ const query = new URLSearchParams({ path: path97 });
10135
10272
  return this.request(
10136
10273
  "DELETE",
10137
10274
  `/api/v1/projects/${projectId}/dev-portal/pages/files?${query.toString()}`
10138
10275
  );
10139
10276
  }
10140
- renameDevPortalPage(projectId, path96, newName) {
10141
- const query = new URLSearchParams({ path: path96 });
10277
+ renameDevPortalPage(projectId, path97, newName) {
10278
+ const query = new URLSearchParams({ path: path97 });
10142
10279
  return this.request(
10143
10280
  "POST",
10144
10281
  `/api/v1/projects/${projectId}/dev-portal/pages/files/rename?${query.toString()}`,
@@ -10254,8 +10391,8 @@ var PlatformApiClient = class {
10254
10391
  * the project-less endpoint is used; `planTier` overrides the tier used for paid-plan checks.
10255
10392
  */
10256
10393
  validateGatewayPlans(plans, options = {}) {
10257
- const path96 = options.projectId ? `/api/v1/projects/${options.projectId}/gateway/plans/validate` : "/api/v1/gateway/plans/validate";
10258
- return this.request("POST", path96, {
10394
+ const path97 = options.projectId ? `/api/v1/projects/${options.projectId}/gateway/plans/validate` : "/api/v1/gateway/plans/validate";
10395
+ return this.request("POST", path97, {
10259
10396
  headers: { "Content-Type": "application/json" },
10260
10397
  body: JSON.stringify({ plans, planTier: options.planTier })
10261
10398
  });
@@ -10380,8 +10517,8 @@ var PlatformApiClient = class {
10380
10517
  }
10381
10518
  };
10382
10519
  async function readFileBytes(filePath) {
10383
- const { readFile: readFile27 } = await import("node:fs/promises");
10384
- const buffer = await readFile27(filePath);
10520
+ const { readFile: readFile28 } = await import("node:fs/promises");
10521
+ const buffer = await readFile28(filePath);
10385
10522
  const arrayBuffer = new ArrayBuffer(buffer.byteLength);
10386
10523
  new Uint8Array(arrayBuffer).set(buffer);
10387
10524
  return arrayBuffer;
@@ -10392,8 +10529,8 @@ function isNotFoundError(error) {
10392
10529
 
10393
10530
  // src/cli/platform/credentials-store.ts
10394
10531
  import fs from "node:fs";
10395
- import path16 from "node:path";
10396
- var CREDENTIALS_FILE = path16.join(
10532
+ import path17 from "node:path";
10533
+ var CREDENTIALS_FILE = path17.join(
10397
10534
  ZUDOKU_XDG_CONFIG_HOME,
10398
10535
  "credentials.json"
10399
10536
  );
@@ -10414,7 +10551,7 @@ function readStoredCredentials() {
10414
10551
  }
10415
10552
  }
10416
10553
  function writeStoredCredentials(creds) {
10417
- fs.mkdirSync(path16.dirname(CREDENTIALS_FILE), { recursive: true });
10554
+ fs.mkdirSync(path17.dirname(CREDENTIALS_FILE), { recursive: true });
10418
10555
  fs.writeFileSync(CREDENTIALS_FILE, JSON.stringify(creds, null, 2), {
10419
10556
  mode: 384
10420
10557
  });
@@ -10478,16 +10615,16 @@ function resolveProjectId(explicit, config2) {
10478
10615
  import {
10479
10616
  access as access4,
10480
10617
  mkdir as mkdir12,
10481
- readFile as readFile13,
10618
+ readFile as readFile14,
10482
10619
  rename as rename6,
10483
10620
  rm as rm8,
10484
10621
  writeFile as writeFile15
10485
10622
  } from "node:fs/promises";
10486
- import path48 from "node:path";
10623
+ import path49 from "node:path";
10487
10624
 
10488
10625
  // src/vite/build.ts
10489
- import { mkdir as mkdir11, readFile as readFile11, rename as rename5, rm as rm7, writeFile as writeFile13 } from "node:fs/promises";
10490
- import path46 from "node:path";
10626
+ import { mkdir as mkdir11, readFile as readFile12, rename as rename5, rm as rm7, writeFile as writeFile13 } from "node:fs/promises";
10627
+ import path47 from "node:path";
10491
10628
  import { build as esbuild } from "esbuild";
10492
10629
  import { build as viteBuild, mergeConfig as mergeConfig3 } from "vite";
10493
10630
 
@@ -10623,7 +10760,7 @@ init_invariant();
10623
10760
  init_joinUrl();
10624
10761
 
10625
10762
  // src/vite/config.ts
10626
- import path41 from "node:path";
10763
+ import path42 from "node:path";
10627
10764
  import dotenv from "dotenv";
10628
10765
  import colors8 from "picocolors";
10629
10766
  import {
@@ -10634,7 +10771,7 @@ import {
10634
10771
  // package.json
10635
10772
  var package_default = {
10636
10773
  name: "@lukoweb/apitogo",
10637
- version: "0.2.49",
10774
+ version: "0.2.50",
10638
10775
  type: "module",
10639
10776
  sideEffects: [
10640
10777
  "**/*.css",
@@ -11071,24 +11208,24 @@ async function loadDevPortalViteDefines(rootDir, mode) {
11071
11208
 
11072
11209
  // src/vite/package-root.ts
11073
11210
  init_file_exists();
11074
- import path21 from "node:path";
11211
+ import path22 from "node:path";
11075
11212
  var findPackageRoot = async (startDir) => {
11076
11213
  let dir = startDir;
11077
- while (dir !== path21.dirname(dir)) {
11078
- if (await fileExists(path21.join(dir, "package.json"))) return dir;
11079
- dir = path21.dirname(dir);
11214
+ while (dir !== path22.dirname(dir)) {
11215
+ if (await fileExists(path22.join(dir, "package.json"))) return dir;
11216
+ dir = path22.dirname(dir);
11080
11217
  }
11081
11218
  };
11082
11219
 
11083
11220
  // src/vite/pagefind-dev-stub.ts
11084
11221
  import fs2 from "node:fs/promises";
11085
- import path22 from "node:path";
11222
+ import path23 from "node:path";
11086
11223
  var NOT_BUILT_YET = 'throw new Error("NOT_BUILT_YET");';
11087
11224
  async function ensurePagefindDevStub(publicDir) {
11088
- const pagefindPath = path22.join(publicDir, "pagefind/pagefind.js");
11225
+ const pagefindPath = path23.join(publicDir, "pagefind/pagefind.js");
11089
11226
  const exists6 = await fs2.stat(pagefindPath).catch(() => false);
11090
11227
  if (!exists6) {
11091
- await fs2.mkdir(path22.dirname(pagefindPath), { recursive: true });
11228
+ await fs2.mkdir(path23.dirname(pagefindPath), { recursive: true });
11092
11229
  await fs2.writeFile(pagefindPath, NOT_BUILT_YET);
11093
11230
  }
11094
11231
  }
@@ -11100,7 +11237,7 @@ import react from "@vitejs/plugin-react";
11100
11237
  // src/vite/css/plugin.ts
11101
11238
  init_loader();
11102
11239
  init_plugin_theme();
11103
- import path23 from "node:path";
11240
+ import path24 from "node:path";
11104
11241
  import { isCSSRequest as isCSSRequest2 } from "vite";
11105
11242
 
11106
11243
  // src/vite/css/collect.ts
@@ -11135,7 +11272,7 @@ var VIRTUAL_ENTRY = "virtual:ssr-css.css";
11135
11272
  function vitePluginSsrCss(pluginOpts) {
11136
11273
  let server;
11137
11274
  const config2 = getCurrentConfig();
11138
- const virtualHref = path23.join(
11275
+ const virtualHref = path24.join(
11139
11276
  config2.basePath ?? "",
11140
11277
  `/@id/__x00__${VIRTUAL_ENTRY}?direct`
11141
11278
  );
@@ -11272,7 +11409,7 @@ var plugin_api_keys_default = viteApiKeysPlugin;
11272
11409
 
11273
11410
  // src/vite/plugin-api.ts
11274
11411
  import fs4 from "node:fs/promises";
11275
- import path29 from "node:path";
11412
+ import path30 from "node:path";
11276
11413
  import { deepEqual as deepEqual2 } from "fast-equals";
11277
11414
  import { runnerImport as runnerImport3 } from "vite";
11278
11415
  init_package_json();
@@ -11281,7 +11418,7 @@ init_loader();
11281
11418
  // src/config/validators/BuildSchema.ts
11282
11419
  init_file_exists();
11283
11420
  init_loader();
11284
- import path24 from "node:path";
11421
+ import path25 from "node:path";
11285
11422
  import { runnerImport as runnerImport2 } from "vite";
11286
11423
  import { z as z13 } from "zod";
11287
11424
  var BuildProcessorSchema = z13.custom((val) => typeof val === "function");
@@ -11310,7 +11447,7 @@ var buildConfigFiles = [
11310
11447
  ];
11311
11448
  async function getBuildConfigFilePath(rootDir) {
11312
11449
  for (const fileName of buildConfigFiles) {
11313
- const filepath = path24.join(rootDir, fileName);
11450
+ const filepath = path25.join(rootDir, fileName);
11314
11451
  if (await fileExists(filepath)) {
11315
11452
  return filepath;
11316
11453
  }
@@ -11419,14 +11556,14 @@ var flattenAllOf = (schema2) => {
11419
11556
  };
11420
11557
 
11421
11558
  // src/lib/util/traverse.ts
11422
- var traverse = (specification, transform, path96 = []) => {
11423
- const transformed = transform(specification, path96);
11559
+ var traverse = (specification, transform, path97 = []) => {
11560
+ const transformed = transform(specification, path97);
11424
11561
  if (typeof transformed !== "object" || transformed === null) {
11425
11562
  return transformed;
11426
11563
  }
11427
11564
  const result = Array.isArray(transformed) ? [] : {};
11428
11565
  for (const [key, value] of Object.entries(transformed)) {
11429
- const currentPath = [...path96, key];
11566
+ const currentPath = [...path97, key];
11430
11567
  if (Array.isArray(value)) {
11431
11568
  result[key] = value.map(
11432
11569
  (item, index) => typeof item === "object" && item != null ? traverse(item, transform, [...currentPath, index.toString()]) : item
@@ -11454,9 +11591,9 @@ var resolveLocalRef = (schema2, ref) => {
11454
11591
  if (schemaCache?.has(ref)) {
11455
11592
  return schemaCache.get(ref);
11456
11593
  }
11457
- const path96 = ref.split("/").slice(1);
11594
+ const path97 = ref.split("/").slice(1);
11458
11595
  let current = schema2;
11459
- for (const segment of path96) {
11596
+ for (const segment of path97) {
11460
11597
  if (!current || typeof current !== "object") {
11461
11598
  current = null;
11462
11599
  }
@@ -11475,7 +11612,7 @@ var dereference = async (schema2, resolvers = []) => {
11475
11612
  }
11476
11613
  const cloned = structuredClone(schema2);
11477
11614
  const visited = /* @__PURE__ */ new Set();
11478
- const resolve = async (current, path96) => {
11615
+ const resolve = async (current, path97) => {
11479
11616
  if (isIndexableObject(current)) {
11480
11617
  if (visited.has(current)) {
11481
11618
  return CIRCULAR_REF;
@@ -11483,7 +11620,7 @@ var dereference = async (schema2, resolvers = []) => {
11483
11620
  visited.add(current);
11484
11621
  if (Array.isArray(current)) {
11485
11622
  for (let index = 0; index < current.length; index++) {
11486
- current[index] = await resolve(current[index], `${path96}/${index}`);
11623
+ current[index] = await resolve(current[index], `${path97}/${index}`);
11487
11624
  }
11488
11625
  } else {
11489
11626
  if ("$ref" in current && typeof current.$ref === "string") {
@@ -11494,13 +11631,13 @@ var dereference = async (schema2, resolvers = []) => {
11494
11631
  for (const resolver of resolvers) {
11495
11632
  const resolved = await resolver($ref);
11496
11633
  if (resolved) {
11497
- result2 = await resolve(resolved, path96);
11634
+ result2 = await resolve(resolved, path97);
11498
11635
  break;
11499
11636
  }
11500
11637
  }
11501
11638
  if (result2 === void 0) {
11502
11639
  const resolved = await resolveLocalRef(cloned, $ref);
11503
- result2 = await resolve(resolved, path96);
11640
+ result2 = await resolve(resolved, path97);
11504
11641
  }
11505
11642
  if (hasSiblings) {
11506
11643
  if (result2 === CIRCULAR_REF) {
@@ -11513,7 +11650,7 @@ var dereference = async (schema2, resolvers = []) => {
11513
11650
  return result2;
11514
11651
  }
11515
11652
  for (const key in current) {
11516
- current[key] = await resolve(current[key], `${path96}/${key}`);
11653
+ current[key] = await resolve(current[key], `${path97}/${key}`);
11517
11654
  }
11518
11655
  }
11519
11656
  visited.delete(current);
@@ -11552,9 +11689,9 @@ var upgradeSchema = (schema2) => {
11552
11689
  }
11553
11690
  return sub;
11554
11691
  });
11555
- schema2 = traverse(schema2, (sub, path96) => {
11692
+ schema2 = traverse(schema2, (sub, path97) => {
11556
11693
  if (sub.example !== void 0) {
11557
- if (isSchemaPath(path96 ?? [])) {
11694
+ if (isSchemaPath(path97 ?? [])) {
11558
11695
  sub.examples = [sub.example];
11559
11696
  } else {
11560
11697
  sub.examples = {
@@ -11567,11 +11704,11 @@ var upgradeSchema = (schema2) => {
11567
11704
  }
11568
11705
  return sub;
11569
11706
  });
11570
- schema2 = traverse(schema2, (schema3, path96) => {
11707
+ schema2 = traverse(schema2, (schema3, path97) => {
11571
11708
  if (schema3.type === "object" && schema3.properties !== void 0) {
11572
- const parentPath = path96?.slice(0, -1);
11709
+ const parentPath = path97?.slice(0, -1);
11573
11710
  const isMultipart = parentPath?.some((segment, index) => {
11574
- return segment === "content" && path96?.[index + 1] === "multipart/form-data";
11711
+ return segment === "content" && path97?.[index + 1] === "multipart/form-data";
11575
11712
  });
11576
11713
  if (isMultipart) {
11577
11714
  const entries = Object.entries(schema3.properties);
@@ -11585,8 +11722,8 @@ var upgradeSchema = (schema2) => {
11585
11722
  }
11586
11723
  return schema3;
11587
11724
  });
11588
- schema2 = traverse(schema2, (schema3, path96) => {
11589
- if (path96?.includes("content") && path96.includes("application/octet-stream")) {
11725
+ schema2 = traverse(schema2, (schema3, path97) => {
11726
+ if (path97?.includes("content") && path97.includes("application/octet-stream")) {
11590
11727
  return {};
11591
11728
  }
11592
11729
  if (schema3.type === "string" && schema3.format === "binary") {
@@ -11612,11 +11749,11 @@ var upgradeSchema = (schema2) => {
11612
11749
  }
11613
11750
  return sub;
11614
11751
  });
11615
- schema2 = traverse(schema2, (schema3, path96) => {
11752
+ schema2 = traverse(schema2, (schema3, path97) => {
11616
11753
  if (schema3.type === "string" && schema3.format === "byte") {
11617
- const parentPath = path96?.slice(0, -1);
11754
+ const parentPath = path97?.slice(0, -1);
11618
11755
  const contentMediaType = parentPath?.find(
11619
- (_, index) => path96?.[index - 1] === "content"
11756
+ (_, index) => path97?.[index - 1] === "content"
11620
11757
  );
11621
11758
  return {
11622
11759
  type: "string",
@@ -11628,7 +11765,7 @@ var upgradeSchema = (schema2) => {
11628
11765
  });
11629
11766
  return schema2;
11630
11767
  };
11631
- function isSchemaPath(path96) {
11768
+ function isSchemaPath(path97) {
11632
11769
  const schemaLocations = [
11633
11770
  ["components", "schemas"],
11634
11771
  "properties",
@@ -11641,10 +11778,10 @@ function isSchemaPath(path96) {
11641
11778
  ];
11642
11779
  return schemaLocations.some((location) => {
11643
11780
  if (Array.isArray(location)) {
11644
- return location.every((segment, index) => path96[index] === segment);
11781
+ return location.every((segment, index) => path97[index] === segment);
11645
11782
  }
11646
- return path96.includes(location);
11647
- }) || path96.includes("schema") || path96.some((segment) => segment.endsWith("Schema"));
11783
+ return path97.includes(location);
11784
+ }) || path97.includes("schema") || path97.some((segment) => segment.endsWith("Schema"));
11648
11785
  }
11649
11786
 
11650
11787
  // src/lib/oas/parser/index.ts
@@ -11726,13 +11863,13 @@ var OPENAPI_PROPS = /* @__PURE__ */ new Set([
11726
11863
  "anyOf",
11727
11864
  "oneOf"
11728
11865
  ]);
11729
- var handleCircularRefs = (obj, currentPath = /* @__PURE__ */ new WeakSet(), refs = /* @__PURE__ */ new WeakMap(), path96 = [], currentRefPaths = /* @__PURE__ */ new Set()) => {
11866
+ var handleCircularRefs = (obj, currentPath = /* @__PURE__ */ new WeakSet(), refs = /* @__PURE__ */ new WeakMap(), path97 = [], currentRefPaths = /* @__PURE__ */ new Set()) => {
11730
11867
  if (obj === null || typeof obj !== "object") return obj;
11731
11868
  const refPath = obj.__$ref;
11732
11869
  const isCircular = currentPath.has(obj) || typeof refPath === "string" && currentRefPaths.has(refPath);
11733
11870
  if (isCircular) {
11734
11871
  if (typeof refPath === "string") return SCHEMA_REF_PREFIX + refPath;
11735
- const circularProp = path96.find((p) => !OPENAPI_PROPS.has(p)) || path96[0];
11872
+ const circularProp = path97.find((p) => !OPENAPI_PROPS.has(p)) || path97[0];
11736
11873
  return [CIRCULAR_REF, circularProp].filter(Boolean).join(":");
11737
11874
  }
11738
11875
  if (refs.has(obj)) return refs.get(obj);
@@ -11742,7 +11879,7 @@ var handleCircularRefs = (obj, currentPath = /* @__PURE__ */ new WeakSet(), refs
11742
11879
  value,
11743
11880
  currentPath,
11744
11881
  refs,
11745
- [...path96, key],
11882
+ [...path97, key],
11746
11883
  currentRefPaths
11747
11884
  );
11748
11885
  const result = Array.isArray(obj) ? obj.map((item, i) => recurse(item, i.toString())) : Object.fromEntries(
@@ -11777,7 +11914,7 @@ var resolveExtensions = (obj) => Object.fromEntries(
11777
11914
  var getAllTags = (schema2) => {
11778
11915
  const rootTags = schema2.tags ?? [];
11779
11916
  const operations = Object.values(schema2.paths ?? {}).flatMap(
11780
- (path96) => HttpMethods.map((k) => path96?.[k]).filter((op) => op != null)
11917
+ (path97) => HttpMethods.map((k) => path97?.[k]).filter((op) => op != null)
11781
11918
  );
11782
11919
  const operationTags = new Set(operations.flatMap((op) => op.tags ?? []));
11783
11920
  const hasUntaggedOperations = operations.some(
@@ -11832,7 +11969,7 @@ var getAllSlugs = (ops, schemaTags = []) => {
11832
11969
  var getOperationSlugKey = (op) => [op.path, op.method, op.operationId, op.summary].filter(Boolean).join("-");
11833
11970
  var getAllOperations = (paths) => {
11834
11971
  const operations = Object.entries(paths ?? {}).flatMap(
11835
- ([path96, value]) => HttpMethods.flatMap((method) => {
11972
+ ([path97, value]) => HttpMethods.flatMap((method) => {
11836
11973
  if (!value?.[method]) return [];
11837
11974
  const operation = value[method];
11838
11975
  const pathParameters = value.parameters ?? [];
@@ -11852,7 +11989,7 @@ var getAllOperations = (paths) => {
11852
11989
  return {
11853
11990
  ...operation,
11854
11991
  method,
11855
- path: path96,
11992
+ path: path97,
11856
11993
  parameters,
11857
11994
  servers,
11858
11995
  tags: operation.tags ?? []
@@ -12210,8 +12347,8 @@ var Schema = builder.objectRef("Schema").implement({
12210
12347
  }),
12211
12348
  paths: t.field({
12212
12349
  type: [PathItem],
12213
- resolve: (root) => Object.entries(root.paths ?? {}).map(([path96, value]) => ({
12214
- path: path96,
12350
+ resolve: (root) => Object.entries(root.paths ?? {}).map(([path97, value]) => ({
12351
+ path: path97,
12215
12352
  // biome-ignore lint/style/noNonNullAssertion: value is guaranteed to be defined
12216
12353
  methods: Object.keys(value)
12217
12354
  }))
@@ -12324,7 +12461,7 @@ var ensureArray = (value) => Array.isArray(value) ? value : [value];
12324
12461
 
12325
12462
  // src/vite/api/SchemaManager.ts
12326
12463
  import fs3 from "node:fs/promises";
12327
- import path25 from "node:path";
12464
+ import path26 from "node:path";
12328
12465
  import {
12329
12466
  $RefParser as $RefParser2
12330
12467
  } from "@apidevtools/json-schema-ref-parser";
@@ -12376,7 +12513,7 @@ init_joinUrl();
12376
12513
 
12377
12514
  // src/vite/api/schema-codegen.ts
12378
12515
  var unescapeJsonPointer = (uri) => decodeURIComponent(uri.replace(/~1/g, "/").replace(/~0/g, "~"));
12379
- var getSegmentsFromPath = (path96) => path96.split("/").slice(1).map(unescapeJsonPointer);
12516
+ var getSegmentsFromPath = (path97) => path97.split("/").slice(1).map(unescapeJsonPointer);
12380
12517
  var createLocalRefMap = (obj) => {
12381
12518
  const refMap = /* @__PURE__ */ new Map();
12382
12519
  const siblingsMap = /* @__PURE__ */ new Map();
@@ -12407,16 +12544,16 @@ var replaceMarkers = (code, mergedRefs) => code.replace(/"__refMap:(.*?)"/g, '__
12407
12544
  /"__refMap\+Siblings:(.*?)"/g,
12408
12545
  (_, key) => mergedRefs.get(key) ?? `__refMap["${key}"]`
12409
12546
  );
12410
- var lookup = (schema2, path96, filePath) => {
12411
- const parts = getSegmentsFromPath(path96);
12547
+ var lookup = (schema2, path97, filePath) => {
12548
+ const parts = getSegmentsFromPath(path97);
12412
12549
  let val = schema2;
12413
12550
  for (const part of parts) {
12414
12551
  while (val.$ref?.startsWith("#/")) {
12415
- val = val.$ref === path96 ? val : lookup(schema2, val.$ref, filePath);
12552
+ val = val.$ref === path97 ? val : lookup(schema2, val.$ref, filePath);
12416
12553
  }
12417
12554
  if (val[part] === void 0) {
12418
12555
  throw new Error(
12419
- `Error in ${filePath ?? "code generation"}: Could not find path segment ${part} in path: ${path96}`
12556
+ `Error in ${filePath ?? "code generation"}: Could not find path segment ${part} in path: ${path97}`
12420
12557
  );
12421
12558
  }
12422
12559
  val = val[part];
@@ -12514,18 +12651,18 @@ var SchemaManager = class {
12514
12651
  ];
12515
12652
  }
12516
12653
  getPathForFile = (input5, params) => {
12517
- const filePath = path25.resolve(this.config.__meta.rootDir, input5);
12654
+ const filePath = path26.resolve(this.config.__meta.rootDir, input5);
12518
12655
  const apis = ensureArray(this.config.apis ?? []);
12519
12656
  for (const apiConfig of apis) {
12520
12657
  if (!apiConfig || apiConfig.type !== "file" || !apiConfig.path) continue;
12521
12658
  const match = normalizeInputs(apiConfig.input).some(
12522
- (i) => path25.resolve(this.config.__meta.rootDir, i.input) === filePath && deepEqual(i.params, params)
12659
+ (i) => path26.resolve(this.config.__meta.rootDir, i.input) === filePath && deepEqual(i.params, params)
12523
12660
  );
12524
12661
  if (match) return apiConfig.path;
12525
12662
  }
12526
12663
  };
12527
12664
  processSchema = async (input5) => {
12528
- const filePath = path25.resolve(this.config.__meta.rootDir, input5.input);
12665
+ const filePath = path26.resolve(this.config.__meta.rootDir, input5.input);
12529
12666
  const params = input5.params;
12530
12667
  const configuredPath = this.getPathForFile(input5.input, params);
12531
12668
  if (!configuredPath) {
@@ -12561,9 +12698,9 @@ var SchemaManager = class {
12561
12698
  const processedTime = Date.now();
12562
12699
  const code = generateCode(processedSchema, filePath);
12563
12700
  const prefixPath = slugify(configuredPath);
12564
- const processedFilePath = path25.posix.join(
12701
+ const processedFilePath = path26.posix.join(
12565
12702
  this.storeDir,
12566
- `${prefixPath}-${path25.basename(filePath)}${paramsSuffix(params)}.js`
12703
+ `${prefixPath}-${path26.basename(filePath)}${paramsSuffix(params)}.js`
12567
12704
  );
12568
12705
  const importKey = processedFilePath;
12569
12706
  await fs3.writeFile(processedFilePath, code);
@@ -12612,7 +12749,7 @@ var SchemaManager = class {
12612
12749
  };
12613
12750
  getAllTrackedFiles = () => Array.from(this.referencedBy.keys());
12614
12751
  getFilesToReprocess = (changedFile) => {
12615
- const resolvedPath = path25.resolve(this.config.__meta.rootDir, changedFile);
12752
+ const resolvedPath = path26.resolve(this.config.__meta.rootDir, changedFile);
12616
12753
  const referencedBy = this.referencedBy.get(resolvedPath);
12617
12754
  if (!referencedBy) return [];
12618
12755
  const filesToProcess = referencedBy.size === 0 ? [resolvedPath] : Array.from(referencedBy);
@@ -12641,7 +12778,7 @@ var SchemaManager = class {
12641
12778
  version: "",
12642
12779
  path: input5.path ?? "",
12643
12780
  label: input5.label,
12644
- inputPath: path25.resolve(this.config.__meta.rootDir, input5.input),
12781
+ inputPath: path26.resolve(this.config.__meta.rootDir, input5.input),
12645
12782
  params: input5.params,
12646
12783
  importKey: "",
12647
12784
  downloadUrl: "",
@@ -12661,8 +12798,8 @@ var SchemaManager = class {
12661
12798
  }
12662
12799
  }
12663
12800
  };
12664
- getLatestSchema = (path96) => this.processedSchemas[path96]?.at(0);
12665
- getSchemasForPath = (path96) => this.processedSchemas[path96];
12801
+ getLatestSchema = (path97) => this.processedSchemas[path97]?.at(0);
12802
+ getSchemasForPath = (path97) => this.processedSchemas[path97];
12666
12803
  getSchemaImports = () => Object.values(this.processedSchemas).flat().filter((s) => s.importKey);
12667
12804
  getUrlToFilePathMap = () => {
12668
12805
  const map = /* @__PURE__ */ new Map();
@@ -12684,7 +12821,7 @@ var SchemaManager = class {
12684
12821
  };
12685
12822
  createSchemaPath = (inputPath, versionPath, apiPath, params) => {
12686
12823
  const suffix = paramsSuffix(params);
12687
- const extension = suffix ? ".json" : path25.extname(inputPath);
12824
+ const extension = suffix ? ".json" : path26.extname(inputPath);
12688
12825
  return joinUrl(
12689
12826
  this.config.basePath,
12690
12827
  apiPath,
@@ -12707,7 +12844,7 @@ var SchemaManager = class {
12707
12844
  // src/vite/plugin-config-reload.ts
12708
12845
  init_logger();
12709
12846
  init_loader();
12710
- import path28 from "node:path";
12847
+ import path29 from "node:path";
12711
12848
  import colors7 from "picocolors";
12712
12849
 
12713
12850
  // src/vite/plugin-navigation.ts
@@ -12717,8 +12854,8 @@ import { stringify as stringify3 } from "javascript-stringify";
12717
12854
  import { isElement } from "react-is";
12718
12855
 
12719
12856
  // src/config/validators/NavigationSchema.ts
12720
- import path26 from "node:path";
12721
- import { glob as glob4 } from "glob";
12857
+ import path27 from "node:path";
12858
+ import { glob as glob5 } from "glob";
12722
12859
  import { fromMarkdown } from "mdast-util-from-markdown";
12723
12860
  import { mdxFromMarkdown } from "mdast-util-mdx";
12724
12861
  import { mdxjs } from "micromark-extension-mdxjs";
@@ -12752,7 +12889,7 @@ var extractRichH1 = (content) => {
12752
12889
  }
12753
12890
  };
12754
12891
  var isNavigationItem = (item) => item !== void 0;
12755
- var toPosixPath = (filePath) => filePath.split(path26.win32.sep).join(path26.posix.sep);
12892
+ var toPosixPath = (filePath) => filePath.split(path27.win32.sep).join(path27.posix.sep);
12756
12893
  var NavigationResolver = class {
12757
12894
  rootDir;
12758
12895
  globPatterns;
@@ -12766,7 +12903,7 @@ var NavigationResolver = class {
12766
12903
  }
12767
12904
  async initialize() {
12768
12905
  if (this.globFiles.length > 0) return;
12769
- this.globFiles = await glob4(this.globPatterns, {
12906
+ this.globFiles = await glob5(this.globPatterns, {
12770
12907
  root: this.rootDir,
12771
12908
  ignore: ["**/node_modules/**", "**/.git/**", "**/dist/**"]
12772
12909
  }).then((files) => files.map(toPosixPath));
@@ -12885,13 +13022,13 @@ init_invariant();
12885
13022
 
12886
13023
  // src/vite/debug.ts
12887
13024
  import { mkdir as mkdir7, writeFile as writeFile9 } from "node:fs/promises";
12888
- import path27 from "node:path";
13025
+ import path28 from "node:path";
12889
13026
  async function writePluginDebugCode(rootDir, pluginName, code, extension = "js") {
12890
13027
  if (process.env.ZUDOKU_BUILD_DEBUG) {
12891
- const debugDir = path27.join(rootDir, "dist", "debug");
13028
+ const debugDir = path28.join(rootDir, "dist", "debug");
12892
13029
  await mkdir7(debugDir, { recursive: true });
12893
13030
  await writeFile9(
12894
- path27.join(debugDir, `${pluginName}.${extension}`),
13031
+ path28.join(debugDir, `${pluginName}.${extension}`),
12895
13032
  typeof code === "string" ? code : code.join("\n")
12896
13033
  );
12897
13034
  }
@@ -13000,7 +13137,7 @@ var viteConfigReloadPlugin = () => ({
13000
13137
  reload(server);
13001
13138
  logger.info(
13002
13139
  colors7.blue(
13003
- `Config ${path28.basename(currentConfig.__meta.configPath)} changed. Reloading...`
13140
+ `Config ${path29.basename(currentConfig.__meta.configPath)} changed. Reloading...`
13004
13141
  ),
13005
13142
  { timestamp: true }
13006
13143
  );
@@ -13014,11 +13151,11 @@ var viteApiPlugin = async () => {
13014
13151
  const resolvedVirtualModuleId5 = `\0${virtualModuleId4}`;
13015
13152
  const initialConfig = getCurrentConfig();
13016
13153
  const zuploProcessors = ZuploEnv.isZuplo ? await runnerImport3(
13017
- path29.resolve(getZudokuRootDir(), "src/zuplo/with-zuplo-processors.ts")
13154
+ path30.resolve(getZudokuRootDir(), "src/zuplo/with-zuplo-processors.ts")
13018
13155
  ).then((m) => m.module.default(initialConfig.__meta.rootDir)) : [];
13019
13156
  const buildConfig = await getBuildConfig();
13020
13157
  const buildProcessors = buildConfig?.processors ?? [];
13021
- const tmpStoreDir = path29.posix.join(
13158
+ const tmpStoreDir = path30.posix.join(
13022
13159
  initialConfig.__meta.rootDir,
13023
13160
  "node_modules/.apitogo/processed"
13024
13161
  );
@@ -13050,7 +13187,7 @@ var viteApiPlugin = async () => {
13050
13187
  const inputPath = pathMap.get(req.url);
13051
13188
  if (!inputPath) return next();
13052
13189
  const content = await fs4.readFile(inputPath, "utf-8");
13053
- const mimeType = path29.extname(inputPath).toLowerCase() === ".json" ? "application/json" : "application/x-yaml";
13190
+ const mimeType = path30.extname(inputPath).toLowerCase() === ".json" ? "application/json" : "application/x-yaml";
13054
13191
  res.setHeader("Content-Type", `${mimeType}; charset=utf-8`);
13055
13192
  return res.end(content);
13056
13193
  });
@@ -13238,8 +13375,8 @@ var viteApiPlugin = async () => {
13238
13375
  if (process.env.NODE_ENV !== "production") return;
13239
13376
  for (const [urlPath, inputPath] of pathMap) {
13240
13377
  const content = await fs4.readFile(inputPath, "utf-8");
13241
- const outputPath = path29.join(config2.__meta.rootDir, "dist", urlPath);
13242
- await fs4.mkdir(path29.dirname(outputPath), { recursive: true });
13378
+ const outputPath = path30.join(config2.__meta.rootDir, "dist", urlPath);
13379
+ await fs4.mkdir(path30.dirname(outputPath), { recursive: true });
13243
13380
  await fs4.writeFile(outputPath, content, "utf-8");
13244
13381
  }
13245
13382
  }
@@ -13282,7 +13419,7 @@ var plugin_auth_default = viteAuthPlugin;
13282
13419
 
13283
13420
  // src/vite/plugin-component.ts
13284
13421
  init_loader();
13285
- import path30 from "node:path";
13422
+ import path31 from "node:path";
13286
13423
  var viteAliasPlugin = () => {
13287
13424
  return {
13288
13425
  name: "zudoku-component-plugin",
@@ -13310,7 +13447,7 @@ var viteAliasPlugin = () => {
13310
13447
  ];
13311
13448
  const aliases = replacements.map(([find, replacement]) => ({
13312
13449
  find,
13313
- replacement: path30.posix.join(config2.__meta.moduleDir, replacement)
13450
+ replacement: path31.posix.join(config2.__meta.moduleDir, replacement)
13314
13451
  }));
13315
13452
  return config2.__meta.mode === "internal" || config2.__meta.mode === "standalone" ? { resolve: { alias: aliases } } : void 0;
13316
13453
  }
@@ -13321,11 +13458,11 @@ var plugin_component_default = viteAliasPlugin;
13321
13458
  // src/vite/plugin-config.ts
13322
13459
  init_package_json();
13323
13460
  init_loader();
13324
- import path31 from "node:path";
13461
+ import path32 from "node:path";
13325
13462
  import { normalizePath } from "vite";
13326
13463
  var virtualModuleId3 = "virtual:zudoku-config";
13327
13464
  var resolvedVirtualModuleId3 = `\0${virtualModuleId3}`;
13328
- var browserConfigLoaderPath = path31.join(
13465
+ var browserConfigLoaderPath = path32.join(
13329
13466
  getZudokuRootDir(),
13330
13467
  "src/config/apitogo-config-loader.browser.ts"
13331
13468
  );
@@ -13459,7 +13596,7 @@ var plugin_custom_pages_default = viteCustomPagesPlugin;
13459
13596
 
13460
13597
  // src/vite/plugin-doc-metadata.ts
13461
13598
  init_loader();
13462
- import { glob as glob5 } from "glob";
13599
+ import { glob as glob6 } from "glob";
13463
13600
  var serializeMetadata = async (filePath) => {
13464
13601
  const fm = await readFrontmatter(filePath);
13465
13602
  const h1 = fm.content.match(/^#\s+(.*)$/m)?.[1];
@@ -13470,7 +13607,7 @@ var viteDocMetadataPlugin = () => ({
13470
13607
  name: "zudoku-doc-metadata-plugin",
13471
13608
  configureServer: async (server) => {
13472
13609
  const config2 = getCurrentConfig();
13473
- const files = await glob5("**/*.{md,mdx}", {
13610
+ const files = await glob6("**/*.{md,mdx}", {
13474
13611
  cwd: config2.__meta.rootDir,
13475
13612
  ignore: ["node_modules", "dist"],
13476
13613
  absolute: true
@@ -13496,9 +13633,9 @@ var viteDocMetadataPlugin = () => ({
13496
13633
 
13497
13634
  // src/vite/plugin-docs.ts
13498
13635
  init_loader();
13499
- import path32 from "node:path";
13500
- import { glob as glob6 } from "glob";
13501
- import globParent2 from "glob-parent";
13636
+ import path33 from "node:path";
13637
+ import { glob as glob7 } from "glob";
13638
+ import globParent3 from "glob-parent";
13502
13639
  init_ZudokuConfig();
13503
13640
 
13504
13641
  // src/lib/components/navigation/utils.ts
@@ -13553,19 +13690,19 @@ var globMarkdownFiles = async (config2, options = { absolute: false }) => {
13553
13690
  const docsConfig = DocsConfigSchema.parse(config2.docs ?? {});
13554
13691
  const fileMapping = {};
13555
13692
  for (const globPattern of docsConfig.files) {
13556
- const globbedFiles = await glob6(globPattern, {
13693
+ const globbedFiles = await glob7(globPattern, {
13557
13694
  root: config2.__meta.rootDir,
13558
13695
  ignore: ["**/node_modules/**", "**/dist/**", "**/.git/**"],
13559
13696
  // Always glob with relative paths to avoid issues on different OS
13560
13697
  absolute: false,
13561
13698
  posix: true
13562
13699
  });
13563
- const parent = globParent2(globPattern).replace(/^\.?\//, "");
13700
+ const parent = globParent3(globPattern).replace(/^\.?\//, "");
13564
13701
  let draftFiles = /* @__PURE__ */ new Set();
13565
13702
  if (process.env.NODE_ENV !== "development") {
13566
13703
  const draftStatuses = await Promise.all(
13567
13704
  globbedFiles.map(async (file) => {
13568
- const absolutePath = path32.resolve(config2.__meta.rootDir, file);
13705
+ const absolutePath = path33.resolve(config2.__meta.rootDir, file);
13569
13706
  const { data } = await readFrontmatter(absolutePath);
13570
13707
  return { file, isDraft: data.draft === true };
13571
13708
  })
@@ -13578,9 +13715,9 @@ var globMarkdownFiles = async (config2, options = { absolute: false }) => {
13578
13715
  if (draftFiles.has(file)) {
13579
13716
  continue;
13580
13717
  }
13581
- const relativePath = path32.posix.relative(parent, file);
13718
+ const relativePath = path33.posix.relative(parent, file);
13582
13719
  const routePath = ensureLeadingSlash(relativePath.replace(/\.mdx?$/, ""));
13583
- const filePath = options.absolute ? path32.resolve(config2.__meta.rootDir, file) : file;
13720
+ const filePath = options.absolute ? path33.resolve(config2.__meta.rootDir, file) : file;
13584
13721
  fileMapping[routePath] = filePath;
13585
13722
  }
13586
13723
  }
@@ -13644,7 +13781,7 @@ var viteDocsPlugin = () => {
13644
13781
  const globbedDocuments = {};
13645
13782
  for (const [routePath, file] of Object.entries(fileMapping)) {
13646
13783
  const importPath = ensureLeadingSlash(
13647
- path32.posix.join(globImportBasePath, file)
13784
+ path33.posix.join(globImportBasePath, file)
13648
13785
  );
13649
13786
  globbedDocuments[routePath] = importPath;
13650
13787
  }
@@ -13670,7 +13807,7 @@ var plugin_docs_default = viteDocsPlugin;
13670
13807
  // src/vite/plugin-local-manifest.ts
13671
13808
  init_apitogo_config_loader();
13672
13809
  init_local_manifest();
13673
- import path33 from "node:path";
13810
+ import path34 from "node:path";
13674
13811
  var APITOGO_LOCAL_MANIFEST_VIRTUAL_ID = "virtual:apitogo-local-manifest";
13675
13812
  var resolvedVirtualModuleId4 = `\0${APITOGO_LOCAL_MANIFEST_VIRTUAL_ID}`;
13676
13813
  var viteLocalManifestPlugin = () => {
@@ -13720,8 +13857,8 @@ var viteLocalManifestPlugin = () => {
13720
13857
  server.watcher.add(watchPath);
13721
13858
  }
13722
13859
  server.watcher.on("change", async (changedPath) => {
13723
- const resolvedChanged = path33.resolve(changedPath);
13724
- if (!watchPaths.some((p) => path33.resolve(p) === resolvedChanged)) {
13860
+ const resolvedChanged = path34.resolve(changedPath);
13861
+ if (!watchPaths.some((p) => path34.resolve(p) === resolvedChanged)) {
13725
13862
  return;
13726
13863
  }
13727
13864
  const module = server.moduleGraph.getModuleById(
@@ -13748,7 +13885,7 @@ init_loader();
13748
13885
  init_ProtectedRoutesSchema();
13749
13886
  init_joinUrl();
13750
13887
  import { mkdir as mkdir8, writeFile as writeFile10 } from "node:fs/promises";
13751
- import path34 from "node:path";
13888
+ import path35 from "node:path";
13752
13889
  import { matchPath } from "react-router";
13753
13890
  var processMarkdownFile = async (filePath) => {
13754
13891
  const { content: markdownContent, data: frontmatter } = await readFrontmatter(filePath);
@@ -13836,7 +13973,7 @@ var viteMarkdownExportPlugin = () => {
13836
13973
  if (process.env.NODE_ENV !== "production" || Object.keys(markdownFiles).length === 0 || !needsMdFiles) {
13837
13974
  return;
13838
13975
  }
13839
- const distDir = path34.join(
13976
+ const distDir = path35.join(
13840
13977
  config2.__meta.rootDir,
13841
13978
  "dist",
13842
13979
  config2.basePath ?? ""
@@ -13857,15 +13994,15 @@ var viteMarkdownExportPlugin = () => {
13857
13994
  content: finalMarkdown
13858
13995
  });
13859
13996
  const segments = routePath === "/" ? ["index"] : routePath.split("/").filter(Boolean);
13860
- const outputPath = `${path34.join(distDir, ...segments)}.md`;
13861
- await mkdir8(path34.dirname(outputPath), { recursive: true });
13997
+ const outputPath = `${path35.join(distDir, ...segments)}.md`;
13998
+ await mkdir8(path35.dirname(outputPath), { recursive: true });
13862
13999
  await writeFile10(outputPath, finalMarkdown, "utf-8");
13863
14000
  } catch (error) {
13864
14001
  console.warn(`Failed to export markdown for ${routePath}:`, error);
13865
14002
  }
13866
14003
  }
13867
14004
  if (config2.docs?.llms?.llmsTxt || config2.docs?.llms?.llmsTxtFull) {
13868
- const markdownInfoPath = path34.join(
14005
+ const markdownInfoPath = path35.join(
13869
14006
  config2.__meta.rootDir,
13870
14007
  "node_modules/.apitogo/markdown-info.json"
13871
14008
  );
@@ -14017,9 +14154,9 @@ var remarkCodeTabs = () => (tree) => {
14017
14154
  };
14018
14155
 
14019
14156
  // src/vite/mdx/remark-inject-filepath.ts
14020
- import path35 from "node:path";
14157
+ import path36 from "node:path";
14021
14158
  var remarkInjectFilepath = (rootDir) => (tree, vfile) => {
14022
- const relativePath = path35.relative(rootDir, vfile.path).split(path35.sep).join(path35.posix.sep);
14159
+ const relativePath = path36.relative(rootDir, vfile.path).split(path36.sep).join(path36.posix.sep);
14023
14160
  tree.children.unshift(exportMdxjsConst("__filepath", relativePath));
14024
14161
  };
14025
14162
 
@@ -14106,18 +14243,18 @@ var remarkLastModified = () => {
14106
14243
  };
14107
14244
 
14108
14245
  // src/vite/mdx/remark-link-rewrite.ts
14109
- import path36 from "node:path";
14246
+ import path37 from "node:path";
14110
14247
  import { visit as visit5 } from "unist-util-visit";
14111
14248
  var remarkLinkRewrite = (basePath = "") => (tree) => {
14112
14249
  visit5(tree, "link", (node) => {
14113
14250
  if (!node.url) return;
14114
14251
  if (node.url.startsWith("http") || node.url.startsWith("mailto:")) return;
14115
14252
  node.url = node.url.replace(/\\/g, "/");
14116
- const base = path36.posix.join(basePath);
14253
+ const base = path37.posix.join(basePath);
14117
14254
  if (basePath && node.url.startsWith(base)) {
14118
14255
  node.url = node.url.slice(base.length);
14119
14256
  } else if (!node.url.startsWith("/") && !node.url.startsWith("#")) {
14120
- node.url = path36.posix.join("..", node.url);
14257
+ node.url = path37.posix.join("..", node.url);
14121
14258
  }
14122
14259
  node.url = node.url.replace(/\.mdx?(#.*)?$/, "$1");
14123
14260
  });
@@ -14337,14 +14474,14 @@ var plugin_mdx_default = viteMdxPlugin;
14337
14474
 
14338
14475
  // src/vite/plugin-modules.ts
14339
14476
  init_loader();
14340
- import path37 from "node:path";
14477
+ import path38 from "node:path";
14341
14478
  import { normalizePath as normalizePath2 } from "vite";
14342
- var getLandingModuleImport = (moduleDir, mode) => mode === "internal" ? normalizePath2(path37.join(moduleDir, "../module-landing/src/index.tsx")) : "@lukoweb/apitogo-module-landing";
14343
- var getUserPanelModuleImport = (moduleDir, mode) => mode === "internal" ? normalizePath2(path37.join(moduleDir, "../module-user-panel/src/index.tsx")) : "@lukoweb/apitogo-module-user-panel";
14479
+ var getLandingModuleImport = (moduleDir, mode) => mode === "internal" ? normalizePath2(path38.join(moduleDir, "../module-landing/src/index.tsx")) : "@lukoweb/apitogo-module-landing";
14480
+ var getUserPanelModuleImport = (moduleDir, mode) => mode === "internal" ? normalizePath2(path38.join(moduleDir, "../module-user-panel/src/index.tsx")) : "@lukoweb/apitogo-module-user-panel";
14344
14481
  var getBillingPluginImport = (moduleDir, mode) => mode === "internal" ? normalizePath2(
14345
- path37.join(moduleDir, "../plugin-dev-portal-billing/src/index.ts")
14482
+ path38.join(moduleDir, "../plugin-dev-portal-billing/src/index.ts")
14346
14483
  ) : "@lukoweb/apitogo-plugin-dev-portal-billing";
14347
- var resolveProjectPageImport = (rootDir, pagePath) => normalizePath2(path37.resolve(rootDir, pagePath));
14484
+ var resolveProjectPageImport = (rootDir, pagePath) => normalizePath2(path38.resolve(rootDir, pagePath));
14348
14485
  var viteModulesPlugin = () => {
14349
14486
  const virtualModuleId4 = "virtual:zudoku-modules-plugin";
14350
14487
  const resolvedVirtualModuleId5 = `\0${virtualModuleId4}`;
@@ -14486,17 +14623,17 @@ var plugin_modules_default = viteModulesPlugin;
14486
14623
 
14487
14624
  // src/vite/plugin-offroot-resolve.ts
14488
14625
  init_loader();
14489
- import path38 from "node:path";
14626
+ import path39 from "node:path";
14490
14627
  function stripQuery(id) {
14491
14628
  const query = id.indexOf("?");
14492
14629
  return query === -1 ? id : id.slice(0, query);
14493
14630
  }
14494
14631
  function isInside(parent, child) {
14495
- const relative = path38.relative(path38.resolve(parent), path38.resolve(child));
14496
- return relative === "" || !relative.startsWith("..") && !path38.isAbsolute(relative);
14632
+ const relative = path39.relative(path39.resolve(parent), path39.resolve(child));
14633
+ return relative === "" || !relative.startsWith("..") && !path39.isAbsolute(relative);
14497
14634
  }
14498
14635
  function isBareSpecifier(source) {
14499
- return !source.startsWith("\0") && !source.startsWith(".") && !source.startsWith("/") && !path38.isAbsolute(source);
14636
+ return !source.startsWith("\0") && !source.startsWith(".") && !source.startsWith("/") && !path39.isAbsolute(source);
14500
14637
  }
14501
14638
  function isInsideNodeModules(filePath) {
14502
14639
  return filePath.split(/[\\/]/).includes("node_modules");
@@ -14520,7 +14657,7 @@ function viteOffrootResolvePlugin() {
14520
14657
  if (!shouldResolveFromSiteRoot(source, importer, rootDir)) {
14521
14658
  return;
14522
14659
  }
14523
- return this.resolve(source, path38.join(rootDir, "package.json"), {
14660
+ return this.resolve(source, path39.join(rootDir, "package.json"), {
14524
14661
  ...options,
14525
14662
  skipSelf: true
14526
14663
  });
@@ -14530,7 +14667,7 @@ function viteOffrootResolvePlugin() {
14530
14667
 
14531
14668
  // src/vite/plugin-search.ts
14532
14669
  init_loader();
14533
- import path39 from "node:path";
14670
+ import path40 from "node:path";
14534
14671
  var viteSearchPlugin = () => {
14535
14672
  const virtualModuleId4 = "virtual:zudoku-search-plugin";
14536
14673
  const resolvedVirtualModuleId5 = `\0${virtualModuleId4}`;
@@ -14548,7 +14685,7 @@ var viteSearchPlugin = () => {
14548
14685
  return resolvedVirtualModuleId5;
14549
14686
  }
14550
14687
  if (id === "/pagefind/pagefind.js" && resolvedViteConfig?.publicDir) {
14551
- return path39.join(resolvedViteConfig.publicDir, "pagefind/pagefind.js");
14688
+ return path40.join(resolvedViteConfig.publicDir, "pagefind/pagefind.js");
14552
14689
  }
14553
14690
  },
14554
14691
  async load(id) {
@@ -14689,27 +14826,27 @@ function vitePlugin() {
14689
14826
 
14690
14827
  // src/vite/watch-ignore.ts
14691
14828
  import { lstatSync, realpathSync } from "node:fs";
14692
- import path40 from "node:path";
14829
+ import path41 from "node:path";
14693
14830
  var STATE_INSIDE_CONTENT = /[\\/]content[\\/](?:\.apitogo|apitogo[\\/]\.state)(?:[\\/]|$)/;
14694
14831
  var within = (base, file) => {
14695
- const resolvedBase = path40.resolve(base);
14696
- const resolvedFile = path40.resolve(file);
14697
- return resolvedFile === resolvedBase || resolvedFile.startsWith(resolvedBase + path40.sep);
14832
+ const resolvedBase = path41.resolve(base);
14833
+ const resolvedFile = path41.resolve(file);
14834
+ return resolvedFile === resolvedBase || resolvedFile.startsWith(resolvedBase + path41.sep);
14698
14835
  };
14699
14836
  var unique = (paths) => [...new Set(paths)];
14700
14837
  function isWorkspace(root) {
14701
14838
  try {
14702
- return path40.basename(root) === "generated" && lstatSync(path40.join(root, "content")).isSymbolicLink();
14839
+ return path41.basename(root) === "generated" && lstatSync(path41.join(root, "content")).isSymbolicLink();
14703
14840
  } catch {
14704
14841
  return false;
14705
14842
  }
14706
14843
  }
14707
14844
  function tenantDir(root) {
14708
- return isWorkspace(root) ? realpathSync(path40.join(root, "content")) : void 0;
14845
+ return isWorkspace(root) ? realpathSync(path41.join(root, "content")) : void 0;
14709
14846
  }
14710
14847
  function stateIgnore(root) {
14711
14848
  if (!isWorkspace(root)) return void 0;
14712
- const state = path40.dirname(root);
14849
+ const state = path41.dirname(root);
14713
14850
  const states = unique([state, realpathSync(state)]);
14714
14851
  const roots = unique([root, realpathSync(root)]);
14715
14852
  return (file) => {
@@ -14720,17 +14857,17 @@ function stateIgnore(root) {
14720
14857
  }
14721
14858
  function devServerAllow(root, moduleDir) {
14722
14859
  const tenant = tenantDir(root);
14723
- return [root, path40.dirname(root), moduleDir, ...tenant ? [tenant] : []];
14860
+ return [root, path41.dirname(root), moduleDir, ...tenant ? [tenant] : []];
14724
14861
  }
14725
14862
 
14726
14863
  // src/vite/config.ts
14727
14864
  var resolveMergedPublicDir = (rootDir, merged) => {
14728
14865
  if (merged.publicDir === false) return void 0;
14729
14866
  const rel2 = typeof merged.publicDir === "string" ? merged.publicDir : "public";
14730
- return path41.resolve(rootDir, rel2);
14867
+ return path42.resolve(rootDir, rel2);
14731
14868
  };
14732
- var getAppClientEntryPath = () => path41.posix.join(getZudokuRootDir(), "src/app/entry.client.tsx");
14733
- var getAppServerEntryPath = () => path41.posix.join(getZudokuRootDir(), "src/app/entry.server.tsx");
14869
+ var getAppClientEntryPath = () => path42.posix.join(getZudokuRootDir(), "src/app/entry.client.tsx");
14870
+ var getAppServerEntryPath = () => path42.posix.join(getZudokuRootDir(), "src/app/entry.server.tsx");
14734
14871
  var hasLoggedCdnInfo = false;
14735
14872
  var MEDIA_REGEX = /\.(a?png|jpe?g|gif|bmp|svg|webp|tiff|ico|webm|ogg|mp3|wav|m4a|avif|mp4)/i;
14736
14873
  var defineEnvVars = (vars) => Object.fromEntries(
@@ -14761,7 +14898,7 @@ async function getViteConfig(dir, configEnv) {
14761
14898
  const ignoreState = stateIgnore(dir);
14762
14899
  if (ZuploEnv.isZuplo) {
14763
14900
  dotenv.config({
14764
- path: path41.resolve(config2.__meta.rootDir, "../.env.zuplo"),
14901
+ path: path42.resolve(config2.__meta.rootDir, "../.env.zuplo"),
14765
14902
  quiet: true
14766
14903
  });
14767
14904
  }
@@ -14824,8 +14961,8 @@ async function getViteConfig(dir, configEnv) {
14824
14961
  ssr: configEnv.isSsrBuild,
14825
14962
  sourcemap: true,
14826
14963
  target: "es2022",
14827
- outDir: path41.resolve(
14828
- path41.join(
14964
+ outDir: path42.resolve(
14965
+ path42.join(
14829
14966
  dir,
14830
14967
  "dist",
14831
14968
  config2.basePath ?? "",
@@ -14844,7 +14981,7 @@ async function getViteConfig(dir, configEnv) {
14844
14981
  },
14845
14982
  experimental: {
14846
14983
  renderBuiltUrl(filename) {
14847
- if (cdnUrl?.base && [".js", ".css"].includes(path41.extname(filename))) {
14984
+ if (cdnUrl?.base && [".js", ".css"].includes(path42.extname(filename))) {
14848
14985
  return joinUrl(cdnUrl.base, filename);
14849
14986
  }
14850
14987
  if (cdnUrl?.media && MEDIA_REGEX.test(filename)) {
@@ -14857,7 +14994,7 @@ async function getViteConfig(dir, configEnv) {
14857
14994
  esbuildOptions: {
14858
14995
  target: "es2022"
14859
14996
  },
14860
- entries: [path41.posix.join(getZudokuRootDir(), "src/{app,lib}/**")],
14997
+ entries: [path42.posix.join(getZudokuRootDir(), "src/{app,lib}/**")],
14861
14998
  exclude: [
14862
14999
  "@lukoweb/apitogo",
14863
15000
  "@lukoweb/apitogo-plugin-dev-portal-billing"
@@ -14961,7 +15098,7 @@ init_package_json();
14961
15098
  init_joinUrl();
14962
15099
  import assert from "node:assert";
14963
15100
  import { cp, mkdir as mkdir9, writeFile as writeFile11 } from "node:fs/promises";
14964
- import path42 from "node:path";
15101
+ import path43 from "node:path";
14965
15102
  var pkgJson = getZudokuPackageJson();
14966
15103
  function generateOutput({
14967
15104
  config: config2,
@@ -15018,9 +15155,9 @@ async function writeOutput(dir, {
15018
15155
  rewrites
15019
15156
  }) {
15020
15157
  const output4 = generateOutput({ config: config2, redirects, rewrites });
15021
- const outputDir = process.env.VERCEL ? path42.join(dir, ".vercel/output") : path42.join(dir, "dist/.output");
15158
+ const outputDir = process.env.VERCEL ? path43.join(dir, ".vercel/output") : path43.join(dir, "dist/.output");
15022
15159
  await mkdir9(outputDir, { recursive: true });
15023
- const outputFile = path42.join(outputDir, "config.json");
15160
+ const outputFile = path43.join(outputDir, "config.json");
15024
15161
  await writeFile11(outputFile, JSON.stringify(output4, null, 2), "utf-8");
15025
15162
  if (process.env.VERCEL) {
15026
15163
  console.log("Wrote Vercel output to", outputDir);
@@ -15030,9 +15167,9 @@ async function writeOutput(dir, {
15030
15167
  // src/vite/prerender/prerender.ts
15031
15168
  init_logger();
15032
15169
  init_file_exists();
15033
- import { readFile as readFile10, rm as rm6 } from "node:fs/promises";
15170
+ import { readFile as readFile11, rm as rm6 } from "node:fs/promises";
15034
15171
  import os from "node:os";
15035
- import path45 from "node:path";
15172
+ import path46 from "node:path";
15036
15173
  import { pathToFileURL } from "node:url";
15037
15174
  import { createIndex } from "pagefind";
15038
15175
  import colors11 from "picocolors";
@@ -15074,7 +15211,7 @@ function throttle(fn) {
15074
15211
  init_joinUrl();
15075
15212
  import { createWriteStream, existsSync as existsSync4 } from "node:fs";
15076
15213
  import { mkdir as mkdir10 } from "node:fs/promises";
15077
- import path43 from "node:path";
15214
+ import path44 from "node:path";
15078
15215
  import colors9 from "picocolors";
15079
15216
  import { SitemapStream } from "sitemap";
15080
15217
  async function generateSitemap({
@@ -15088,11 +15225,11 @@ async function generateSitemap({
15088
15225
  return;
15089
15226
  }
15090
15227
  const sitemap = new SitemapStream({ hostname: config2.siteUrl });
15091
- const outputDir = path43.resolve(baseOutputDir, config2.outDir ?? "");
15228
+ const outputDir = path44.resolve(baseOutputDir, config2.outDir ?? "");
15092
15229
  if (!existsSync4(outputDir)) {
15093
15230
  await mkdir10(outputDir, { recursive: true });
15094
15231
  }
15095
- const sitemapOutputPath = path43.join(outputDir, "sitemap.xml");
15232
+ const sitemapOutputPath = path44.join(outputDir, "sitemap.xml");
15096
15233
  const writeStream = createWriteStream(sitemapOutputPath);
15097
15234
  sitemap.pipe(writeStream);
15098
15235
  let lastmod;
@@ -15122,14 +15259,14 @@ async function generateSitemap({
15122
15259
 
15123
15260
  // src/vite/prerender/utils.ts
15124
15261
  init_joinUrl();
15125
- var resolveRoutePath = (path96) => {
15126
- const segments = path96.split("/");
15262
+ var resolveRoutePath = (path97) => {
15263
+ const segments = path97.split("/");
15127
15264
  if (segments.some((s) => s.startsWith(":") && !s.endsWith("?"))) {
15128
15265
  return void 0;
15129
15266
  }
15130
15267
  return segments.filter((s) => !s.startsWith(":")).join("/") || void 0;
15131
15268
  };
15132
- var isSkipped = (path96) => path96.includes("*") || /^\d+$/.test(path96);
15269
+ var isSkipped = (path97) => path97.includes("*") || /^\d+$/.test(path97);
15133
15270
  var resolveRoutes = (routes, parentPath = "") => routes.flatMap((route) => {
15134
15271
  if (route.path && isSkipped(route.path)) return [];
15135
15272
  const routePath = route.path ? resolveRoutePath(route.path) : void 0;
@@ -15178,12 +15315,12 @@ var prerender = async ({
15178
15315
  serverConfigFilename,
15179
15316
  writeRedirects = true
15180
15317
  }) => {
15181
- const distDir = path45.join(dir, "dist", basePath);
15318
+ const distDir = path46.join(dir, "dist", basePath);
15182
15319
  const serverConfigPath = pathToFileURL(
15183
- path45.join(distDir, "server", serverConfigFilename)
15320
+ path46.join(distDir, "server", serverConfigFilename)
15184
15321
  ).href;
15185
15322
  const entryServerPath = pathToFileURL(
15186
- path45.join(distDir, "server/entry.server.js")
15323
+ path46.join(distDir, "server/entry.server.js")
15187
15324
  ).href;
15188
15325
  const rawConfig = await import(serverConfigPath).then(
15189
15326
  (m) => m.default
@@ -15268,7 +15405,7 @@ var prerender = async ({
15268
15405
  })
15269
15406
  );
15270
15407
  const pagefindWriteResult = await pagefindIndex?.writeFiles({
15271
- outputPath: path45.join(distDir, "pagefind")
15408
+ outputPath: path46.join(distDir, "pagefind")
15272
15409
  });
15273
15410
  const seconds = ((performance.now() - start) / 1e3).toFixed(1);
15274
15411
  const message = `\u2713 finished prerendering ${paths.length} routes in ${seconds} seconds using ${maxThreads} workers`;
@@ -15300,13 +15437,13 @@ var prerender = async ({
15300
15437
  const { generateLlmsTxtFiles: generateLlmsTxtFiles2 } = await Promise.resolve().then(() => (init_llms(), llms_exports));
15301
15438
  const docsConfig = DocsConfigSchema2.parse(config2.docs);
15302
15439
  const llmsConfig = docsConfig.llms ?? {};
15303
- const markdownInfoPath = path45.join(
15440
+ const markdownInfoPath = path46.join(
15304
15441
  dir,
15305
15442
  "node_modules/.apitogo/markdown-info.json"
15306
15443
  );
15307
15444
  let markdownFileInfos = [];
15308
15445
  if (await fileExists(markdownInfoPath)) {
15309
- const markdownInfoContent = await readFile10(markdownInfoPath, "utf-8");
15446
+ const markdownInfoContent = await readFile11(markdownInfoPath, "utf-8");
15310
15447
  markdownFileInfos = JSON.parse(markdownInfoContent);
15311
15448
  }
15312
15449
  if (llmsConfig.llmsTxt || llmsConfig.llmsTxtFull) {
@@ -15391,7 +15528,7 @@ async function runBuild(options) {
15391
15528
  html,
15392
15529
  basePath: config2.basePath
15393
15530
  });
15394
- await rm7(path46.join(clientOutDir, "index.html"), { force: true });
15531
+ await rm7(path47.join(clientOutDir, "index.html"), { force: true });
15395
15532
  } else {
15396
15533
  await runPrerender({
15397
15534
  dir,
@@ -15415,7 +15552,7 @@ var runPrerender = async (options) => {
15415
15552
  serverConfigFilename,
15416
15553
  writeRedirects: process.env.VERCEL === void 0
15417
15554
  });
15418
- const indexHtml = path46.join(clientOutDir, "index.html");
15555
+ const indexHtml = path47.join(clientOutDir, "index.html");
15419
15556
  if (!workerResults.find((r) => r.outputPath === indexHtml)) {
15420
15557
  await writeFile13(indexHtml, html, "utf-8");
15421
15558
  }
@@ -15425,15 +15562,15 @@ var runPrerender = async (options) => {
15425
15562
  for (const statusPage of statusPages) {
15426
15563
  await rename5(
15427
15564
  statusPage,
15428
- path46.join(dir, DIST_DIR, path46.basename(statusPage))
15565
+ path47.join(dir, DIST_DIR, path47.basename(statusPage))
15429
15566
  );
15430
15567
  }
15431
15568
  await rm7(serverOutDir, { recursive: true, force: true });
15432
15569
  if (process.env.VERCEL) {
15433
- await mkdir11(path46.join(dir, ".vercel/output/static"), { recursive: true });
15570
+ await mkdir11(path47.join(dir, ".vercel/output/static"), { recursive: true });
15434
15571
  await rename5(
15435
- path46.join(dir, DIST_DIR),
15436
- path46.join(dir, ".vercel/output/static")
15572
+ path47.join(dir, DIST_DIR),
15573
+ path47.join(dir, ".vercel/output/static")
15437
15574
  );
15438
15575
  }
15439
15576
  await writeOutput(dir, {
@@ -15443,7 +15580,7 @@ var runPrerender = async (options) => {
15443
15580
  });
15444
15581
  if (ZuploEnv.isZuplo && issuer) {
15445
15582
  await writeFile13(
15446
- path46.join(dir, DIST_DIR, ".output/zuplo.json"),
15583
+ path47.join(dir, DIST_DIR, ".output/zuplo.json"),
15447
15584
  JSON.stringify({ issuer }, null, 2),
15448
15585
  "utf-8"
15449
15586
  );
@@ -15455,10 +15592,10 @@ var runPrerender = async (options) => {
15455
15592
  };
15456
15593
  var bundleSSREntry = async (options) => {
15457
15594
  const { dir, adapter, serverOutDir, serverConfigFilename, html, basePath } = options;
15458
- const tempEntryPath = path46.join(dir, "__ssr-entry.ts");
15595
+ const tempEntryPath = path47.join(dir, "__ssr-entry.ts");
15459
15596
  const packageRoot = getZudokuRootDir();
15460
- const templateContent = await readFile11(
15461
- path46.join(packageRoot, "src/vite/ssr-templates", `${adapter}.ts`),
15597
+ const templateContent = await readFile12(
15598
+ path47.join(packageRoot, "src/vite/ssr-templates", `${adapter}.ts`),
15462
15599
  "utf-8"
15463
15600
  );
15464
15601
  const entryContent = templateContent.replace('"__TEMPLATE__"', JSON.stringify(html)).replace('"__CONFIG_FILE__"', JSON.stringify(`./${serverConfigFilename}`)).replace(
@@ -15473,9 +15610,9 @@ var bundleSSREntry = async (options) => {
15473
15610
  platform: adapter === "node" ? "node" : "neutral",
15474
15611
  target: "es2022",
15475
15612
  format: "esm",
15476
- outfile: path46.join(serverOutDir, "entry.js"),
15613
+ outfile: path47.join(serverOutDir, "entry.js"),
15477
15614
  external: ["./entry.server.js", `./${serverConfigFilename}`],
15478
- nodePaths: [path46.join(packageRoot, "node_modules")],
15615
+ nodePaths: [path47.join(packageRoot, "node_modules")],
15479
15616
  banner: { js: "// Bundled SSR entry" }
15480
15617
  });
15481
15618
  } finally {
@@ -15488,8 +15625,8 @@ init_package_json();
15488
15625
 
15489
15626
  // src/cli/init/v2-packages.ts
15490
15627
  import { existsSync as existsSync5 } from "node:fs";
15491
- import { readFile as readFile12, writeFile as writeFile14 } from "node:fs/promises";
15492
- import path47 from "node:path";
15628
+ import { readFile as readFile13, writeFile as writeFile14 } from "node:fs/promises";
15629
+ import path48 from "node:path";
15493
15630
  var CORE_PACKAGES = [
15494
15631
  "@lukoweb/apitogo",
15495
15632
  "react",
@@ -15506,7 +15643,7 @@ function packageNameFrom(name) {
15506
15643
  return slug || "portal";
15507
15644
  }
15508
15645
  async function ensurePackageJson(dir, name) {
15509
- const file = path47.join(dir, "package.json");
15646
+ const file = path48.join(dir, "package.json");
15510
15647
  if (existsSync5(file)) return false;
15511
15648
  await writeFile14(
15512
15649
  file,
@@ -15525,11 +15662,11 @@ async function ensurePackageJson(dir, name) {
15525
15662
  return true;
15526
15663
  }
15527
15664
  function isPackageInstalled(startDir, name) {
15528
- let dir = path47.resolve(startDir);
15665
+ let dir = path48.resolve(startDir);
15529
15666
  for (; ; ) {
15530
- if (existsSync5(path47.join(dir, "node_modules", name, "package.json")))
15667
+ if (existsSync5(path48.join(dir, "node_modules", name, "package.json")))
15531
15668
  return true;
15532
- const parent = path47.dirname(dir);
15669
+ const parent = path48.dirname(dir);
15533
15670
  if (parent === dir) return false;
15534
15671
  dir = parent;
15535
15672
  }
@@ -15585,7 +15722,7 @@ function portalBuildStep(context, options = {}, build2 = runBuild) {
15585
15722
  return {
15586
15723
  name: "build",
15587
15724
  hash: () => hash2,
15588
- stillValid: () => access4(path48.join(buildDir, "index.html")).then(
15725
+ stillValid: () => access4(path49.join(buildDir, "index.html")).then(
15589
15726
  () => true,
15590
15727
  () => false
15591
15728
  ),
@@ -15602,11 +15739,11 @@ function portalBuildStep(context, options = {}, build2 = runBuild) {
15602
15739
  else process.env.NODE_ENV = originalNodeEnv;
15603
15740
  }
15604
15741
  await rm8(buildDir, { recursive: true, force: true });
15605
- await mkdir12(path48.dirname(buildDir), { recursive: true });
15606
- await rename6(path48.join(root, "dist"), buildDir);
15742
+ await mkdir12(path49.dirname(buildDir), { recursive: true });
15743
+ await rename6(path49.join(root, "dist"), buildDir);
15607
15744
  if (prepared.publishedManifest) {
15608
15745
  await writeFile15(
15609
- path48.join(buildDir, MANIFEST_FILE),
15746
+ path49.join(buildDir, MANIFEST_FILE),
15610
15747
  `${JSON.stringify(prepared.publishedManifest, null, 2)}
15611
15748
  `
15612
15749
  );
@@ -15635,17 +15772,17 @@ async function buildV2(options) {
15635
15772
  }
15636
15773
 
15637
15774
  // src/cli/check/gateway-online.ts
15638
- import { readFile as readFile14 } from "node:fs/promises";
15775
+ import { readFile as readFile15 } from "node:fs/promises";
15639
15776
  var SPEC_SEND_LIMIT = 5 * 1024 * 1024 + 64 * 1024;
15640
- var issue2 = (code, path96, message, hint) => ({ code, path: path96, message, hint });
15777
+ var issue2 = (code, path97, message, hint) => ({ code, path: path97, message, hint });
15641
15778
  function capabilityIssues(gateway, answer) {
15642
15779
  const can = answer.capabilities;
15643
15780
  const plan2 = `your ${answer.tier} plan`;
15644
15781
  const found = [];
15645
- const unsupported = (path96, what, hint) => found.push(
15782
+ const unsupported = (path97, what, hint) => found.push(
15646
15783
  issue2(
15647
15784
  "GATEWAY_CAPABILITY_UNSUPPORTED",
15648
- path96,
15785
+ path97,
15649
15786
  `${what} is not available on ${plan2}.`,
15650
15787
  hint
15651
15788
  )
@@ -15699,7 +15836,7 @@ async function onlineGatewayRules(gateway, projectId, api, derivedCors = []) {
15699
15836
  const specFile = gateway.specs[0];
15700
15837
  if (specFile) {
15701
15838
  try {
15702
- const text = await readFile14(specFile, "utf8");
15839
+ const text = await readFile15(specFile, "utf8");
15703
15840
  if (text.length <= SPEC_SEND_LIMIT) spec = text;
15704
15841
  } catch {
15705
15842
  }
@@ -15726,7 +15863,7 @@ async function onlineGatewayRules(gateway, projectId, api, derivedCors = []) {
15726
15863
  }
15727
15864
 
15728
15865
  // src/cli/deploy/plans-file.ts
15729
- import { readFile as readFile15 } from "node:fs/promises";
15866
+ import { readFile as readFile16 } from "node:fs/promises";
15730
15867
  import { z as z14 } from "zod";
15731
15868
  init_invariant();
15732
15869
  var PlansFileError = class extends ApitogoError {
@@ -15771,7 +15908,7 @@ var issuesOf = (error) => error.issues.map(
15771
15908
  async function readPlansFile(file) {
15772
15909
  let text;
15773
15910
  try {
15774
- text = await readFile15(file, "utf8");
15911
+ text = await readFile16(file, "utf8");
15775
15912
  } catch {
15776
15913
  throw new PlansFileError(
15777
15914
  "PLANS_FILE_UNREADABLE",
@@ -15849,9 +15986,9 @@ function toPlatformPlans(plans, options = {}) {
15849
15986
  }
15850
15987
 
15851
15988
  // src/cli/check/services-online.ts
15852
- var issue3 = (code, path96, message, hint) => ({
15989
+ var issue3 = (code, path97, message, hint) => ({
15853
15990
  code,
15854
- path: path96,
15991
+ path: path97,
15855
15992
  message,
15856
15993
  hint
15857
15994
  });
@@ -15962,7 +16099,7 @@ async function onlinePlansRules(resolved, projectId, api) {
15962
16099
  async function isConfigV2(dir) {
15963
16100
  try {
15964
16101
  return /"version"\s*:\s*2\b/.test(
15965
- await readFile16(path49.join(dir, APITOGO_CONFIG_FILENAME), "utf8")
16102
+ await readFile17(path50.join(dir, APITOGO_CONFIG_FILENAME), "utf8")
15966
16103
  );
15967
16104
  } catch {
15968
16105
  return false;
@@ -16109,7 +16246,7 @@ async function validatePortalBuild(dir) {
16109
16246
  }
16110
16247
  }
16111
16248
  async function runCheckV2(dir, args = {}, deps = {}) {
16112
- const configPath = path49.join(dir, APITOGO_CONFIG_FILENAME);
16249
+ const configPath = path50.join(dir, APITOGO_CONFIG_FILENAME);
16113
16250
  let report;
16114
16251
  try {
16115
16252
  const { config: config2, resolved } = loadConfigV2(dir);
@@ -16219,7 +16356,7 @@ async function checkV2(dir, args, deps = platformDependencies(args)) {
16219
16356
  init_package_json();
16220
16357
 
16221
16358
  // src/cli/init/v2-handler.ts
16222
- import path50 from "node:path";
16359
+ import path51 from "node:path";
16223
16360
  import { createInterface } from "node:readline/promises";
16224
16361
  function parseDocsFlag(value) {
16225
16362
  if (value === void 0) return void 0;
@@ -16241,15 +16378,15 @@ async function ask(question) {
16241
16378
  }
16242
16379
  function describePlan(plan2) {
16243
16380
  return {
16244
- willCreate: plan2.entries.filter((entry) => !plan2.keep.includes(entry.path)).map((entry) => path50.relative(plan2.dir, entry.path)),
16245
- willKeep: plan2.keep.map((target) => path50.relative(plan2.dir, target)),
16381
+ willCreate: plan2.entries.filter((entry) => !plan2.keep.includes(entry.path)).map((entry) => path51.relative(plan2.dir, entry.path)),
16382
+ willKeep: plan2.keep.map((target) => path51.relative(plan2.dir, target)),
16246
16383
  replacesConfig: plan2.replacesConfig
16247
16384
  };
16248
16385
  }
16249
16386
  async function initV2(argv) {
16250
16387
  const json = argv.json === true;
16251
16388
  try {
16252
- const dir = path50.resolve(process.cwd(), argv.dir ?? ".");
16389
+ const dir = path51.resolve(process.cwd(), argv.dir ?? ".");
16253
16390
  const plan2 = await planInit({
16254
16391
  dir,
16255
16392
  name: argv.name,
@@ -16290,8 +16427,8 @@ async function initV2(argv) {
16290
16427
  status: "created",
16291
16428
  dir,
16292
16429
  ...describePlan(plan2),
16293
- created: result.created.map((p) => path50.relative(dir, p)),
16294
- kept: result.kept.map((p) => path50.relative(dir, p))
16430
+ created: result.created.map((p) => path51.relative(dir, p)),
16431
+ kept: result.kept.map((p) => path51.relative(dir, p))
16295
16432
  },
16296
16433
  null,
16297
16434
  2
@@ -16300,7 +16437,7 @@ async function initV2(argv) {
16300
16437
  return;
16301
16438
  }
16302
16439
  printResultToConsole(
16303
- `Created ${path50.basename(plan2.configPath)} (config version 2) in ${dir}.`
16440
+ `Created ${path51.basename(plan2.configPath)} (config version 2) in ${dir}.`
16304
16441
  );
16305
16442
  printHintToConsole(
16306
16443
  "Next: add a service with `apitogo add <portal|gateway|identity|plans>`, or run `apitogo create` for a guided setup."
@@ -16328,7 +16465,7 @@ async function initV2(argv) {
16328
16465
  // src/cli/services/packages.ts
16329
16466
  import { spawn } from "node:child_process";
16330
16467
  import { existsSync as existsSync6 } from "node:fs";
16331
- import path51 from "node:path";
16468
+ import path52 from "node:path";
16332
16469
  var USER_PANEL_PACKAGE = "@lukoweb/apitogo-module-user-panel";
16333
16470
  var BILLING_PLUGIN_PACKAGE = "@lukoweb/apitogo-plugin-dev-portal-billing";
16334
16471
  var LANDING_PACKAGE = "@lukoweb/apitogo-module-landing";
@@ -16346,18 +16483,18 @@ function packagesForConfig(config2) {
16346
16483
  ];
16347
16484
  }
16348
16485
  function isInstalled(dir, name) {
16349
- for (let current = path51.resolve(dir); ; current = path51.dirname(current)) {
16350
- if (existsSync6(path51.join(current, "node_modules", name, "package.json")))
16486
+ for (let current = path52.resolve(dir); ; current = path52.dirname(current)) {
16487
+ if (existsSync6(path52.join(current, "node_modules", name, "package.json")))
16351
16488
  return true;
16352
- if (path51.dirname(current) === current) return false;
16489
+ if (path52.dirname(current) === current) return false;
16353
16490
  }
16354
16491
  }
16355
16492
  function missingPackages(dir, names) {
16356
16493
  return names.filter((name) => !isInstalled(dir, name));
16357
16494
  }
16358
16495
  function detectPackageManager(dir) {
16359
- if (existsSync6(path51.join(dir, "pnpm-lock.yaml"))) return "pnpm";
16360
- if (existsSync6(path51.join(dir, "yarn.lock"))) return "yarn";
16496
+ if (existsSync6(path52.join(dir, "pnpm-lock.yaml"))) return "pnpm";
16497
+ if (existsSync6(path52.join(dir, "yarn.lock"))) return "yarn";
16361
16498
  return "npm";
16362
16499
  }
16363
16500
  function installSpecsCommand(manager, specs) {
@@ -16416,7 +16553,7 @@ async function installMissingPackages(dir, config2, version, options) {
16416
16553
  reason: "--no-install was given",
16417
16554
  command: shown
16418
16555
  };
16419
- await ensurePackageJson(dir, config2.project?.name ?? path51.basename(dir));
16556
+ await ensurePackageJson(dir, config2.project?.name ?? path52.basename(dir));
16420
16557
  await (options.installer ?? runInstaller)(dir, command2);
16421
16558
  return { status: "installed", packages: missing, command: shown };
16422
16559
  }
@@ -16479,7 +16616,7 @@ var list = (value) => {
16479
16616
  return items.length > 0 ? items : void 0;
16480
16617
  };
16481
16618
  function addOptionsFromArguments(service, argv) {
16482
- const dir = path52.resolve(process.cwd(), argv.dir ?? ".");
16619
+ const dir = path53.resolve(process.cwd(), argv.dir ?? ".");
16483
16620
  const issuers = list(argv.issuer);
16484
16621
  return {
16485
16622
  dir,
@@ -16533,8 +16670,8 @@ function describe(edit, dir) {
16533
16670
  return {
16534
16671
  service: edit.service,
16535
16672
  action: edit.action,
16536
- willCreate: edit.files.map((file) => path52.relative(dir, file.path)),
16537
- keep: edit.keep.map((file) => path52.relative(dir, file)),
16673
+ willCreate: edit.files.map((file) => path53.relative(dir, file.path)),
16674
+ keep: edit.keep.map((file) => path53.relative(dir, file)),
16538
16675
  notes: edit.notes
16539
16676
  };
16540
16677
  }
@@ -16548,7 +16685,7 @@ async function run(action, argv, plan2, deps = {}) {
16548
16685
  `Choose one of ${SERVICES.join(", ")}.`
16549
16686
  );
16550
16687
  }
16551
- const dir = path52.resolve(process.cwd(), argv.dir ?? ".");
16688
+ const dir = path53.resolve(process.cwd(), argv.dir ?? ".");
16552
16689
  if (!await isConfigV2(dir)) {
16553
16690
  throw new ServiceEditError(
16554
16691
  `${action} works with a config version 2 project, and there is none in ${dir}.`,
@@ -16616,7 +16753,7 @@ async function run(action, argv, plan2, deps = {}) {
16616
16753
  {
16617
16754
  status: action === "add" ? "added" : "removed",
16618
16755
  ...describe(edit, dir),
16619
- created: created.map((file) => path52.relative(dir, file)),
16756
+ created: created.map((file) => path53.relative(dir, file)),
16620
16757
  ...install ? { packages: install } : {}
16621
16758
  },
16622
16759
  null,
@@ -16626,7 +16763,7 @@ async function run(action, argv, plan2, deps = {}) {
16626
16763
  return;
16627
16764
  }
16628
16765
  printResultToConsole(
16629
- `${action === "add" ? "Added" : "Removed"} ${edit.service} in ${path52.basename(edit.configPath)}.`
16766
+ `${action === "add" ? "Added" : "Removed"} ${edit.service} in ${path53.basename(edit.configPath)}.`
16630
16767
  );
16631
16768
  } catch (error) {
16632
16769
  const message = error instanceof Error ? error.message : String(error);
@@ -16687,7 +16824,7 @@ var removeService = (argv) => run(
16687
16824
  "remove",
16688
16825
  argv,
16689
16826
  (service) => planRemoveService(service, {
16690
- dir: path52.resolve(process.cwd(), argv.dir ?? "."),
16827
+ dir: path53.resolve(process.cwd(), argv.dir ?? "."),
16691
16828
  deleteFiles: argv.deleteFiles === true
16692
16829
  })
16693
16830
  );
@@ -16839,16 +16976,16 @@ var add_default = {
16839
16976
  };
16840
16977
 
16841
16978
  // src/cli/build/handler.ts
16842
- import path54 from "node:path";
16979
+ import path55 from "node:path";
16843
16980
  init_logger();
16844
16981
  init_package_json();
16845
16982
 
16846
16983
  // src/cli/preview/handler.ts
16847
- import path53 from "node:path";
16984
+ import path54 from "node:path";
16848
16985
  import { preview as vitePreview } from "vite";
16849
16986
  var DEFAULT_PREVIEW_PORT = 4e3;
16850
16987
  async function preview(argv) {
16851
- const dir = path53.resolve(process.cwd(), argv.dir);
16988
+ const dir = path54.resolve(process.cwd(), argv.dir);
16852
16989
  const viteConfig = await getViteConfig(dir, {
16853
16990
  command: "serve",
16854
16991
  mode: "production",
@@ -16891,7 +17028,7 @@ async function build(argv) {
16891
17028
  printDiagnosticsToConsole("");
16892
17029
  printDiagnosticsToConsole("");
16893
17030
  }
16894
- const dir = path54.resolve(process.cwd(), argv.dir);
17031
+ const dir = path55.resolve(process.cwd(), argv.dir);
16895
17032
  try {
16896
17033
  if (await isConfigV2(dir)) {
16897
17034
  const result = await buildV2({ dir, jsonOnly });
@@ -16956,10 +17093,10 @@ var build_default = {
16956
17093
  };
16957
17094
 
16958
17095
  // src/cli/check/handler.ts
16959
- import path60 from "node:path";
17096
+ import path61 from "node:path";
16960
17097
 
16961
17098
  // src/cli/platform/tools/check-publish-readiness.ts
16962
- import path59 from "node:path";
17099
+ import path60 from "node:path";
16963
17100
 
16964
17101
  // src/cli/platform/helpers/dev-portal-backend.ts
16965
17102
  function deriveProvisioningState(backend) {
@@ -17043,8 +17180,8 @@ function formatDevPortalBackendResponse(projectId, backend) {
17043
17180
  // src/cli/platform/helpers/dev-portal-manifest.ts
17044
17181
  init_gateway_limits();
17045
17182
  import { existsSync as existsSync7 } from "node:fs";
17046
- import { access as access5, mkdir as mkdir13, readFile as readFile17, writeFile as writeFile16 } from "node:fs/promises";
17047
- import path55 from "node:path";
17183
+ import { access as access5, mkdir as mkdir13, readFile as readFile18, writeFile as writeFile16 } from "node:fs/promises";
17184
+ import path56 from "node:path";
17048
17185
 
17049
17186
  // src/cli/make-config/header-pricing-nav.ts
17050
17187
  var HEADER_PRICING_PATH = "/pricing";
@@ -17166,7 +17303,7 @@ function isPlanFree(plan2) {
17166
17303
  return (plan2.priceAmount ?? 0) <= 0;
17167
17304
  }
17168
17305
  function manifestFilePath(siteDirectory) {
17169
- return path55.join(path55.resolve(siteDirectory), APITOGO_CONFIG_FILENAME2);
17306
+ return path56.join(path56.resolve(siteDirectory), APITOGO_CONFIG_FILENAME2);
17170
17307
  }
17171
17308
  var STORED_MANIFEST_KEYS = [
17172
17309
  "authentication",
@@ -17590,23 +17727,23 @@ function resolveBackendSourceDirectory(siteDirectory, sourceDirectory) {
17590
17727
  if (!trimmed) {
17591
17728
  return void 0;
17592
17729
  }
17593
- return path55.resolve(siteDirectory, trimmed);
17730
+ return path56.resolve(siteDirectory, trimmed);
17594
17731
  }
17595
17732
  function resolveBackendOpenApiPath(openApiPath, options) {
17596
17733
  const trimmed = openApiPath?.trim();
17597
17734
  if (!trimmed) {
17598
17735
  return void 0;
17599
17736
  }
17600
- if (path55.isAbsolute(trimmed)) {
17737
+ if (path56.isAbsolute(trimmed)) {
17601
17738
  return trimmed;
17602
17739
  }
17603
- const siteResolved = path55.resolve(options.siteDirectory, trimmed);
17740
+ const siteResolved = path56.resolve(options.siteDirectory, trimmed);
17604
17741
  if (existsSync7(siteResolved)) {
17605
17742
  return siteResolved;
17606
17743
  }
17607
17744
  const backendDir = options.backendSourceDirectory?.trim();
17608
17745
  if (backendDir) {
17609
- const backendResolved = path55.resolve(backendDir, trimmed);
17746
+ const backendResolved = path56.resolve(backendDir, trimmed);
17610
17747
  if (existsSync7(backendResolved)) {
17611
17748
  return backendResolved;
17612
17749
  }
@@ -17623,7 +17760,7 @@ function mergePublishPrerequisitesWithPlatformValidation(prerequisites, manifest
17623
17760
  async function readManifest2(siteDirectory) {
17624
17761
  const filePath = manifestFilePath(siteDirectory);
17625
17762
  if (await pathExists(filePath)) {
17626
- const raw = await readFile17(filePath, "utf8");
17763
+ const raw = await readFile18(filePath, "utf8");
17627
17764
  const config2 = JSON.parse(raw);
17628
17765
  return extractManifestFromConfig(config2);
17629
17766
  }
@@ -17631,10 +17768,10 @@ async function readManifest2(siteDirectory) {
17631
17768
  }
17632
17769
  async function writeManifest2(siteDirectory, manifest) {
17633
17770
  const filePath = manifestFilePath(siteDirectory);
17634
- await mkdir13(path55.dirname(filePath), { recursive: true });
17771
+ await mkdir13(path56.dirname(filePath), { recursive: true });
17635
17772
  let config2 = {};
17636
17773
  if (await pathExists(filePath)) {
17637
- const raw = await readFile17(filePath, "utf8");
17774
+ const raw = await readFile18(filePath, "utf8");
17638
17775
  config2 = JSON.parse(raw);
17639
17776
  }
17640
17777
  const {
@@ -17653,11 +17790,11 @@ import {
17653
17790
  access as access6,
17654
17791
  appendFile,
17655
17792
  mkdir as mkdir14,
17656
- readFile as readFile18,
17793
+ readFile as readFile19,
17657
17794
  unlink,
17658
17795
  writeFile as writeFile17
17659
17796
  } from "node:fs/promises";
17660
- import path56 from "node:path";
17797
+ import path57 from "node:path";
17661
17798
  var ENV_FILENAME = ".env";
17662
17799
  var COLLAPSED_UPPERCASE_ALIASES2 = {
17663
17800
  SECRETKEY: "secretKey",
@@ -17759,7 +17896,7 @@ function applyEnvOverrides2(config2, env) {
17759
17896
  }
17760
17897
  async function readEnvFile(filePath) {
17761
17898
  try {
17762
- const raw = await readFile18(filePath, "utf8");
17899
+ const raw = await readFile19(filePath, "utf8");
17763
17900
  const env = {};
17764
17901
  for (const line2 of raw.split("\n")) {
17765
17902
  const trimmed = line2.trim();
@@ -17776,12 +17913,12 @@ async function readEnvFile(filePath) {
17776
17913
  }
17777
17914
  }
17778
17915
  async function loadSiteEnv(siteDirectory) {
17779
- const resolvedDirectory = path56.resolve(siteDirectory);
17916
+ const resolvedDirectory = path57.resolve(siteDirectory);
17780
17917
  const merged = { ...process.env };
17781
17918
  for (const fileName of [ENV_FILENAME, ".env.local"]) {
17782
17919
  Object.assign(
17783
17920
  merged,
17784
- await readEnvFile(path56.join(resolvedDirectory, fileName))
17921
+ await readEnvFile(path57.join(resolvedDirectory, fileName))
17785
17922
  );
17786
17923
  }
17787
17924
  return merged;
@@ -17818,7 +17955,7 @@ function buildAuthSecretsJson(secrets2, options) {
17818
17955
  return payload;
17819
17956
  }
17820
17957
  function envFilePath(siteDirectory) {
17821
- return path56.join(path56.resolve(siteDirectory), ENV_FILENAME);
17958
+ return path57.join(path57.resolve(siteDirectory), ENV_FILENAME);
17822
17959
  }
17823
17960
  function getSecretsStatus(siteDirectory, manifest, secrets2, envExists) {
17824
17961
  const providerSecretStatus = {};
@@ -17854,7 +17991,7 @@ function validateSecretsForPublish(manifest, secrets2, emailOptions) {
17854
17991
  }
17855
17992
  async function siteEnvFileHasEntries(siteDirectory) {
17856
17993
  for (const fileName of [ENV_FILENAME, ".env.local"]) {
17857
- const loaded = await readEnvFile(path56.join(siteDirectory, fileName));
17994
+ const loaded = await readEnvFile(path57.join(siteDirectory, fileName));
17858
17995
  if (Object.keys(loaded).length > 0) {
17859
17996
  return true;
17860
17997
  }
@@ -17862,7 +17999,7 @@ async function siteEnvFileHasEntries(siteDirectory) {
17862
17999
  return false;
17863
18000
  }
17864
18001
  async function resolvePublishConfig(siteDirectory, emailOptions) {
17865
- const resolvedDirectory = path56.resolve(siteDirectory);
18002
+ const resolvedDirectory = path57.resolve(siteDirectory);
17866
18003
  const manifestRaw = await readManifest2(resolvedDirectory);
17867
18004
  if (!manifestRaw) {
17868
18005
  throw new Error("apitogo.config.json not found in sourceDirectory.");
@@ -17892,13 +18029,13 @@ var SECRETS_COLLECTION_INSTRUCTION = "For go-live, plans must already be in apit
17892
18029
 
17893
18030
  // src/cli/platform/helpers/dev-portal-site-validation.ts
17894
18031
  init_gateway_limits();
17895
- import { readFile as readFile19 } from "node:fs/promises";
18032
+ import { readFile as readFile20 } from "node:fs/promises";
17896
18033
  import { createRequire as createRequire2 } from "node:module";
17897
- import path57 from "node:path";
18034
+ import path58 from "node:path";
17898
18035
  var cachedFallbackTs;
17899
18036
  async function loadTypeScriptForSite(sourceDirectory) {
17900
18037
  const require2 = createRequire2(
17901
- path57.join(path57.resolve(sourceDirectory), "package.json")
18038
+ path58.join(path58.resolve(sourceDirectory), "package.json")
17902
18039
  );
17903
18040
  try {
17904
18041
  return require2("typescript");
@@ -17945,7 +18082,7 @@ async function referencedFileExists(sourceDirectory, reference) {
17945
18082
  return true;
17946
18083
  }
17947
18084
  return pathExists(
17948
- path57.resolve(sourceDirectory, reference.replace(/^\.\//, ""))
18085
+ path58.resolve(sourceDirectory, reference.replace(/^\.\//, ""))
17949
18086
  );
17950
18087
  }
17951
18088
  async function validateSiteConfigStructure(config2, sourceDirectory) {
@@ -18060,17 +18197,17 @@ var DEFAULT_TSX_CANDIDATES = [
18060
18197
  "landing/LandingPage.tsx"
18061
18198
  ];
18062
18199
  async function validateDevPortalSiteConfig(sourceDirectory, options) {
18063
- const resolvedDir = path57.resolve(sourceDirectory);
18200
+ const resolvedDir = path58.resolve(sourceDirectory);
18064
18201
  const issues = [];
18065
18202
  const checkedFiles = [];
18066
18203
  const skippedChecks = [];
18067
- const jsonPath = path57.join(resolvedDir, APITOGO_CONFIG_FILENAME2);
18204
+ const jsonPath = path58.join(resolvedDir, APITOGO_CONFIG_FILENAME2);
18068
18205
  if (await pathExists(jsonPath)) {
18069
18206
  checkedFiles.push(APITOGO_CONFIG_FILENAME2);
18070
18207
  let parsed;
18071
18208
  let parseFailed = false;
18072
18209
  try {
18073
- parsed = JSON.parse(await readFile19(jsonPath, "utf8"));
18210
+ parsed = JSON.parse(await readFile20(jsonPath, "utf8"));
18074
18211
  } catch (error) {
18075
18212
  parseFailed = true;
18076
18213
  issues.push({
@@ -18096,7 +18233,7 @@ async function validateDevPortalSiteConfig(sourceDirectory, options) {
18096
18233
  );
18097
18234
  const existingTsxFiles = [];
18098
18235
  for (const relativeFile of tsxFiles) {
18099
- if (await pathExists(path57.join(resolvedDir, relativeFile))) {
18236
+ if (await pathExists(path58.join(resolvedDir, relativeFile))) {
18100
18237
  existingTsxFiles.push(relativeFile);
18101
18238
  }
18102
18239
  }
@@ -18109,8 +18246,8 @@ async function validateDevPortalSiteConfig(sourceDirectory, options) {
18109
18246
  } else {
18110
18247
  for (const relativeFile of existingTsxFiles) {
18111
18248
  checkedFiles.push(relativeFile);
18112
- const content = await readFile19(
18113
- path57.join(resolvedDir, relativeFile),
18249
+ const content = await readFile20(
18250
+ path58.join(resolvedDir, relativeFile),
18114
18251
  "utf8"
18115
18252
  );
18116
18253
  issues.push(
@@ -18132,8 +18269,8 @@ async function validateDevPortalSiteConfig(sourceDirectory, options) {
18132
18269
 
18133
18270
  // src/cli/platform/helpers/npm-build.ts
18134
18271
  import { spawn as spawn2 } from "node:child_process";
18135
- import { access as access7, readFile as readFile20 } from "node:fs/promises";
18136
- import path58 from "node:path";
18272
+ import { access as access7, readFile as readFile21 } from "node:fs/promises";
18273
+ import path59 from "node:path";
18137
18274
  var BUILD_LOG_TAIL_BYTES = 8192;
18138
18275
  var MIN_NODE_MAJOR = 20;
18139
18276
  var NpmBuildError = class extends Error {
@@ -18200,13 +18337,13 @@ function runCommand(command2, args, cwd, env) {
18200
18337
  }
18201
18338
  async function runNpmInstall(sourceDirectory, options) {
18202
18339
  assertNodeVersion(options?.nodeVersion);
18203
- const cwd = path58.resolve(sourceDirectory);
18204
- const packageJsonPath = path58.join(cwd, "package.json");
18340
+ const cwd = path59.resolve(sourceDirectory);
18341
+ const packageJsonPath = path59.join(cwd, "package.json");
18205
18342
  if (!await pathExists2(packageJsonPath)) {
18206
18343
  throw new Error(`package.json not found in sourceDirectory: ${cwd}`);
18207
18344
  }
18208
18345
  const startedAt = Date.now();
18209
- const lockPath = path58.join(cwd, "package-lock.json");
18346
+ const lockPath = path59.join(cwd, "package-lock.json");
18210
18347
  const installArgs = await pathExists2(lockPath) ? ["ci"] : ["install"];
18211
18348
  const install = await runCommand("npm", installArgs, cwd);
18212
18349
  const installLog = install.output;
@@ -18224,8 +18361,8 @@ async function runNpmInstall(sourceDirectory, options) {
18224
18361
  }
18225
18362
  async function runNpmBuild(sourceDirectory, options) {
18226
18363
  assertNodeVersion(options?.nodeVersion);
18227
- const cwd = path58.resolve(sourceDirectory);
18228
- const packageJsonPath = path58.join(cwd, "package.json");
18364
+ const cwd = path59.resolve(sourceDirectory);
18365
+ const packageJsonPath = path59.join(cwd, "package.json");
18229
18366
  if (!await pathExists2(packageJsonPath)) {
18230
18367
  throw new Error(`package.json not found in sourceDirectory: ${cwd}`);
18231
18368
  }
@@ -18242,8 +18379,8 @@ async function runNpmBuild(sourceDirectory, options) {
18242
18379
  build2.exitCode
18243
18380
  );
18244
18381
  }
18245
- const distPath = path58.join(cwd, "dist");
18246
- const indexPath = path58.join(distPath, "index.html");
18382
+ const distPath = path59.join(cwd, "dist");
18383
+ const indexPath = path59.join(distPath, "index.html");
18247
18384
  if (!await pathExists2(indexPath)) {
18248
18385
  throw new NpmBuildError(
18249
18386
  `Build completed but dist/index.html was not found at ${indexPath}`,
@@ -18627,7 +18764,7 @@ function validateManifestForPlatformPublish(manifest) {
18627
18764
 
18628
18765
  // src/cli/platform/tools/check-publish-readiness.ts
18629
18766
  async function checkPublishReadiness(client, _config, args) {
18630
- const sourceDirectory = path59.resolve(args.sourceDirectory);
18767
+ const sourceDirectory = path60.resolve(args.sourceDirectory);
18631
18768
  const manifest = await readManifest2(sourceDirectory) ?? createScaffoldManifest();
18632
18769
  const emailOptions = await resolveEmailOptionsForPublish(
18633
18770
  client,
@@ -18705,7 +18842,7 @@ async function checkPublishReadiness(client, _config, args) {
18705
18842
 
18706
18843
  // src/cli/check/handler.ts
18707
18844
  async function check(argv) {
18708
- const sourceDirectory = path60.resolve(process.cwd(), argv.dir);
18845
+ const sourceDirectory = path61.resolve(process.cwd(), argv.dir);
18709
18846
  if (await isConfigV2(sourceDirectory)) {
18710
18847
  await checkV2(sourceDirectory, argv);
18711
18848
  return;
@@ -18769,7 +18906,7 @@ var check_default = {
18769
18906
 
18770
18907
  // src/cli/make-config/handler.ts
18771
18908
  init_invariant();
18772
- import path62 from "node:path";
18909
+ import path63 from "node:path";
18773
18910
  import { stdin as input2 } from "node:process";
18774
18911
 
18775
18912
  // src/cli/make-config/interactive.ts
@@ -18778,9 +18915,9 @@ import { createInterface as createInterface3 } from "node:readline/promises";
18778
18915
 
18779
18916
  // src/cli/make-config/v2-edits.ts
18780
18917
  init_apitogo_config_core();
18781
- import { access as access8, mkdir as mkdir15, readFile as readFile21, writeFile as writeFile18 } from "node:fs/promises";
18782
- import path61 from "node:path";
18783
- import { glob as glob7 } from "glob";
18918
+ import { access as access8, mkdir as mkdir15, readFile as readFile22, writeFile as writeFile18 } from "node:fs/promises";
18919
+ import path62 from "node:path";
18920
+ import { glob as glob8 } from "glob";
18784
18921
  init_invariant();
18785
18922
  var ConfigEditError = class extends ApitogoError {
18786
18923
  constructor(message, developerHint) {
@@ -18792,10 +18929,10 @@ var exists4 = (target) => access8(target).then(
18792
18929
  () => true,
18793
18930
  () => false
18794
18931
  );
18795
- var toPosix2 = (value) => value.split(path61.sep).join("/");
18796
- var relativeToConfig = (project, target) => toPosix2(path61.relative(project.resolved.configDir, target)) || ".";
18932
+ var toPosix2 = (value) => value.split(path62.sep).join("/");
18933
+ var relativeToConfig = (project, target) => toPosix2(path62.relative(project.resolved.configDir, target)) || ".";
18797
18934
  async function openConfigProject(dir) {
18798
- const configPath = path61.join(dir, APITOGO_CONFIG_FILENAME);
18935
+ const configPath = path62.join(dir, APITOGO_CONFIG_FILENAME);
18799
18936
  if (!await exists4(configPath)) {
18800
18937
  throw new ConfigEditError(
18801
18938
  `There is no ${APITOGO_CONFIG_FILENAME} in ${dir}.`,
@@ -18860,7 +18997,7 @@ function setPortalName(project, name) {
18860
18997
  }
18861
18998
  async function addGatewaySpec(project, specPath) {
18862
18999
  const gateway = requireGateway(project);
18863
- const absolute = path61.resolve(project.dir, specPath);
19000
+ const absolute = path62.resolve(project.dir, specPath);
18864
19001
  if (!await exists4(absolute)) {
18865
19002
  throw new ConfigEditError(`The OpenAPI file ${specPath} does not exist.`);
18866
19003
  }
@@ -18904,7 +19041,7 @@ function parseBackendInput(input5) {
18904
19041
  }
18905
19042
  async function setGatewayOrigin(project, backend) {
18906
19043
  const gateway = requireGateway(project);
18907
- const source = path61.resolve(project.dir, backend.source);
19044
+ const source = path62.resolve(project.dir, backend.source);
18908
19045
  if (!await exists4(source)) {
18909
19046
  throw new ConfigEditError(
18910
19047
  `The API source folder ${backend.source} does not exist.`
@@ -18942,6 +19079,33 @@ title: ${JSON.stringify(title)}
18942
19079
  ${body}
18943
19080
  `;
18944
19081
  }
19082
+ function pageComponentName(slug) {
19083
+ const name = slug.split(/[^A-Za-z0-9]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
19084
+ return `${/^[0-9]/.test(name) ? "Page" : ""}${name || "Docs"}Page`;
19085
+ }
19086
+ function buildTsxDocsPage(slug, title, file, content) {
19087
+ const text = content?.trim() ? `{${JSON.stringify(content.trim())}}` : "This page is a React component. Change it like any other component: add state, fetch data, or use the portal's components.";
19088
+ return `import { Callout, Heading, Typography } from "@lukoweb/apitogo/components";
19089
+
19090
+ /** The page's label in the sidebar. */
19091
+ export const title = ${JSON.stringify(title)};
19092
+
19093
+ export default function ${pageComponentName(slug)}() {
19094
+ return (
19095
+ <section className="mx-auto max-w-screen-lg px-4 py-12 pt-(--padding-content-top)">
19096
+ <Typography>
19097
+ <Heading level={1}>{title}</Heading>
19098
+ <p>${text}</p>
19099
+ <Callout type="info" title="Where this page lives">
19100
+ Edit <code>${file}</code>. Files whose name starts with <code>_</code> are not pages, so you can keep shared
19101
+ components next to your pages.
19102
+ </Callout>
19103
+ </Typography>
19104
+ </section>
19105
+ );
19106
+ }
19107
+ `;
19108
+ }
18945
19109
  async function writeDocsPage(project, input5) {
18946
19110
  requirePortal(project);
18947
19111
  if (/^[A-Za-z]:[\\/]/.test(input5.slug.trim())) {
@@ -18959,29 +19123,36 @@ async function writeDocsPage(project, input5) {
18959
19123
  }
18960
19124
  const slug = normalizeDocsSlug(input5.slug);
18961
19125
  if (!slug) throw new ConfigEditError("The page path must not be empty.");
18962
- const base = path61.join(portal.dir, "pages", ...slug.split("/"));
19126
+ const base = path62.join(portal.dir, "pages", ...slug.split("/"));
18963
19127
  const existing = (await Promise.all(
18964
- [`${base}.mdx`, `${base}.md`].map(
19128
+ [`${base}.tsx`, `${base}.mdx`, `${base}.md`].map(
18965
19129
  async (file2) => await exists4(file2) ? file2 : null
18966
19130
  )
18967
19131
  )).find((file2) => file2 !== null);
19132
+ const relative = (file2) => toPosix2(path62.relative(project.dir, file2));
19133
+ const write = (file2, title) => writeFile18(
19134
+ file2,
19135
+ file2.endsWith(".tsx") ? buildTsxDocsPage(slug, title, relative(file2), input5.content) : buildDocsPage(title, input5.content),
19136
+ "utf8"
19137
+ );
18968
19138
  let file;
18969
19139
  let action;
18970
19140
  if (input5.update) {
18971
19141
  if (!existing) {
18972
19142
  throw new ConfigEditError(
18973
- `There is no page at ${toPosix2(path61.relative(project.dir, `${base}.mdx`))}.`,
19143
+ `There is no page at ${relative(`${base}.${input5.format ?? "tsx"}`)}.`,
18974
19144
  "Leave out --page-update to add it."
18975
19145
  );
18976
19146
  }
18977
- const title = input5.title?.trim() || titleOf(await readFile21(existing, "utf8"));
19147
+ const source = await readFile22(existing, "utf8");
19148
+ const title = input5.title?.trim() || (existing.endsWith(".tsx") ? tsxPageLabel(source, existing) : titleOf(source));
18978
19149
  file = existing;
18979
19150
  action = "updated";
18980
- await writeFile18(file, buildDocsPage(title ?? slug, input5.content), "utf8");
19151
+ await write(file, title ?? slug);
18981
19152
  } else {
18982
19153
  if (existing) {
18983
19154
  throw new ConfigEditError(
18984
- `A page already exists at ${toPosix2(path61.relative(project.dir, existing))}.`,
19155
+ `A page already exists at ${relative(existing)}.`,
18985
19156
  "Pass --page-update to change it."
18986
19157
  );
18987
19158
  }
@@ -18989,20 +19160,19 @@ async function writeDocsPage(project, input5) {
18989
19160
  if (!title) {
18990
19161
  throw new ConfigEditError("A new page needs a title (--page-title).");
18991
19162
  }
18992
- file = `${base}.mdx`;
19163
+ file = `${base}.${input5.format ?? "tsx"}`;
18993
19164
  action = "added";
18994
- await mkdir15(path61.dirname(file), { recursive: true });
18995
- await writeFile18(file, buildDocsPage(title, input5.content), "utf8");
19165
+ await mkdir15(path62.dirname(file), { recursive: true });
19166
+ await write(file, title);
18996
19167
  }
18997
- const included = await glob7(portal.docs.content, { absolute: true });
18998
- const inPortal = included.some(
18999
- (match) => path61.resolve(match) === path61.resolve(file)
19000
- );
19168
+ const same = (match) => path62.resolve(match) === path62.resolve(file);
19169
+ const inPortal = file.endsWith(".tsx") ? (await findTsxPages(portal.docs.content)).some((page) => same(page.file)) : (await glob8(portal.docs.content, { absolute: true })).some(same);
19001
19170
  return {
19002
19171
  action,
19003
19172
  slug,
19004
19173
  route: `/${slug}`,
19005
- file: toPosix2(path61.relative(project.dir, file)),
19174
+ file: relative(file),
19175
+ format: path62.extname(file).slice(1),
19006
19176
  inPortal
19007
19177
  };
19008
19178
  }
@@ -19063,7 +19233,7 @@ async function upsertPlan(project, plan2) {
19063
19233
  if (await exists4(plans.file)) {
19064
19234
  let raw;
19065
19235
  try {
19066
- raw = JSON.parse(await readFile21(plans.file, "utf8"));
19236
+ raw = JSON.parse(await readFile22(plans.file, "utf8"));
19067
19237
  } catch (error) {
19068
19238
  throw new ConfigEditError(
19069
19239
  `${relativeToConfig(project, plans.file)} is not valid JSON (${error.message}).`
@@ -19083,7 +19253,7 @@ async function upsertPlan(project, plan2) {
19083
19253
  const next = [...catalog.plans];
19084
19254
  if (index === -1) next.push(plan2);
19085
19255
  else next[index] = plan2;
19086
- await mkdir15(path61.dirname(plans.file), { recursive: true });
19256
+ await mkdir15(path62.dirname(plans.file), { recursive: true });
19087
19257
  await writeFile18(
19088
19258
  plans.file,
19089
19259
  `${JSON.stringify({ ...catalog, plans: next }, null, 2)}
@@ -19094,7 +19264,7 @@ async function upsertPlan(project, plan2) {
19094
19264
  return {
19095
19265
  action: index === -1 ? "added" : "updated",
19096
19266
  sku: plan2.sku,
19097
- file: toPosix2(path61.relative(project.dir, plans.file)),
19267
+ file: toPosix2(path62.relative(project.dir, plans.file)),
19098
19268
  paid,
19099
19269
  needsBilling: paid && plans.billing.provider !== "stripe"
19100
19270
  };
@@ -19122,7 +19292,7 @@ function printPageResult(page) {
19122
19292
  );
19123
19293
  if (page.inPortal) {
19124
19294
  printHintToConsole(
19125
- "The sidebar is built from the pages folder, so the config does not change. Edit the file to change the content."
19295
+ page.format === "tsx" ? "The page is a React component: edit it like any component. The sidebar is built from the pages folder, so the config does not change." : "The sidebar is built from the pages folder, so the config does not change. Edit the file to change the content."
19126
19296
  );
19127
19297
  } else {
19128
19298
  printWarningToConsole(
@@ -19368,7 +19538,7 @@ async function applyConfigFlags(project, argv, changes) {
19368
19538
  return { project: next, openApi };
19369
19539
  }
19370
19540
  async function makeConfig(argv) {
19371
- const dir = path62.resolve(process.cwd(), argv.dir);
19541
+ const dir = path63.resolve(process.cwd(), argv.dir);
19372
19542
  const interactive = shouldRunInteractive(argv);
19373
19543
  const json = argv.json === true;
19374
19544
  const changes = [];
@@ -19415,7 +19585,8 @@ async function makeConfig(argv) {
19415
19585
  slug: argv.pageSlug,
19416
19586
  title: argv.pageTitle,
19417
19587
  content: argv.pageContent,
19418
- update: argv.pageUpdate === true
19588
+ update: argv.pageUpdate === true,
19589
+ format: argv.pageFormat
19419
19590
  });
19420
19591
  changes.push(page.action === "added" ? "page_add" : "page_update");
19421
19592
  }
@@ -19502,13 +19673,17 @@ function addConfigOptions(yargs2) {
19502
19673
  describe: "Runtime version of --source, for example NODE_22_LTS"
19503
19674
  }).option("page-slug", {
19504
19675
  type: "string",
19505
- describe: "Add or update a docs page at <portal>/pages/<slug>.mdx (for example guides/quickstart)"
19676
+ describe: "Add or update a docs page at <portal>/pages/<slug>.tsx (for example guides/quickstart)"
19506
19677
  }).option("page-title", {
19507
19678
  type: "string",
19508
19679
  describe: "Title of --page-slug (required when adding)"
19509
19680
  }).option("page-content", {
19510
19681
  type: "string",
19511
- describe: "Markdown body of --page-slug"
19682
+ describe: "Text of --page-slug (Markdown for an .mdx page)"
19683
+ }).option("page-format", {
19684
+ type: "string",
19685
+ choices: ["tsx", "mdx"],
19686
+ describe: "Format of a new page: tsx (a React component, the default) or mdx (Markdown)"
19512
19687
  }).option("page-update", {
19513
19688
  type: "boolean",
19514
19689
  default: false,
@@ -19534,15 +19709,15 @@ var config_default = {
19534
19709
  // src/cli/create/handler.ts
19535
19710
  init_apitogo_config_core();
19536
19711
  import { execFile } from "node:child_process";
19537
- import { readFile as readFile22 } from "node:fs/promises";
19538
- import path63 from "node:path";
19712
+ import { readFile as readFile23 } from "node:fs/promises";
19713
+ import path64 from "node:path";
19539
19714
  import { promisify } from "node:util";
19540
19715
  var execFileAsync = promisify(execFile);
19541
19716
  function nextStepHint(dir) {
19542
19717
  const linked = loadConfigV2(dir).resolved.project.id;
19543
- const cd = path63.resolve(dir) === path63.resolve(process.cwd());
19718
+ const cd = path64.resolve(dir) === path64.resolve(process.cwd());
19544
19719
  const steps = linked ? "apitogo deploy" : "apitogo project create, then apitogo deploy";
19545
- return cd ? `Next: ${steps}` : `Next: cd ${JSON.stringify(path63.relative(process.cwd(), dir))}, then ${steps}`;
19720
+ return cd ? `Next: ${steps}` : `Next: cd ${JSON.stringify(path64.relative(process.cwd(), dir))}, then ${steps}`;
19546
19721
  }
19547
19722
  function projectFolderName(name) {
19548
19723
  return name.trim().replace(/[<>:"/\\|?*\s]+/g, "-").replace(/^[-.]+|[-.]+$/g, "") || "apitogo-project";
@@ -19568,13 +19743,13 @@ async function gitHasUncommittedChanges(dir) {
19568
19743
  async function defaultName(dir) {
19569
19744
  try {
19570
19745
  const parsed = JSON.parse(
19571
- await readFile22(path63.join(dir, "package.json"), "utf8")
19746
+ await readFile23(path64.join(dir, "package.json"), "utf8")
19572
19747
  );
19573
19748
  if (typeof parsed.name === "string" && parsed.name.trim())
19574
19749
  return parsed.name.replace(/^@[^/]+\//, "");
19575
19750
  } catch {
19576
19751
  }
19577
- return path63.basename(dir);
19752
+ return path64.basename(dir);
19578
19753
  }
19579
19754
  function parseServicesFlag(value) {
19580
19755
  const names = (value ?? "").split(",").map((name) => name.trim()).filter(Boolean);
@@ -19600,7 +19775,7 @@ async function createProject(argv, deps = {}) {
19600
19775
  if (!json) printDiagnosticsToConsole(line2);
19601
19776
  };
19602
19777
  try {
19603
- const base = path63.resolve(process.cwd(), argv.dir ?? ".");
19778
+ const base = path64.resolve(process.cwd(), argv.dir ?? ".");
19604
19779
  let dir = base;
19605
19780
  let requested = parseServicesFlag(argv.services);
19606
19781
  let template = argv.template;
@@ -19623,8 +19798,8 @@ async function createProject(argv, deps = {}) {
19623
19798
  default: await defaultName(base)
19624
19799
  }) : await defaultName(base));
19625
19800
  const folder = projectFolderName(name);
19626
- if (argv.dir === void 0 && folder !== path63.basename(base))
19627
- dir = path63.join(base, folder);
19801
+ if (argv.dir === void 0 && folder !== path64.basename(base))
19802
+ dir = path64.join(base, folder);
19628
19803
  }
19629
19804
  if (await (deps.hasUncommittedChanges ?? gitHasUncommittedChanges)(dir))
19630
19805
  say(
@@ -19651,7 +19826,7 @@ async function createProject(argv, deps = {}) {
19651
19826
  }
19652
19827
  await applyInitPlan(plan2);
19653
19828
  say(
19654
- dir === base ? `Created ${APITOGO_CONFIG_FILENAME}.` : `Created ${path63.relative(base, dir)}${path63.sep}${APITOGO_CONFIG_FILENAME}.`
19829
+ dir === base ? `Created ${APITOGO_CONFIG_FILENAME}.` : `Created ${path64.relative(base, dir)}${path64.sep}${APITOGO_CONFIG_FILENAME}.`
19655
19830
  );
19656
19831
  } else {
19657
19832
  say(`${APITOGO_CONFIG_FILENAME} exists: continuing from it.`);
@@ -19794,10 +19969,10 @@ var create_default = {
19794
19969
  };
19795
19970
 
19796
19971
  // src/cli/cmds/deploy.ts
19797
- import path81 from "node:path";
19972
+ import path82 from "node:path";
19798
19973
 
19799
19974
  // src/cli/apply/handler.ts
19800
- import path75 from "node:path";
19975
+ import path76 from "node:path";
19801
19976
 
19802
19977
  // src/cli/platform/helpers/gateway-plan-validation.ts
19803
19978
  init_gateway_limits();
@@ -20006,11 +20181,11 @@ init_gateway_limits();
20006
20181
  // src/cli/platform/helpers/deploy-artifact-hash.ts
20007
20182
  import { createHash as createHash3 } from "node:crypto";
20008
20183
  import { createReadStream, promises as fs6 } from "node:fs";
20009
- import path65 from "node:path";
20184
+ import path66 from "node:path";
20010
20185
 
20011
20186
  // src/cli/platform/helpers/package-files.ts
20012
20187
  import { promises as fs5 } from "node:fs";
20013
- import path64 from "node:path";
20188
+ import path65 from "node:path";
20014
20189
  import ignore from "ignore";
20015
20190
  var DEFAULT_EXCLUDES = /* @__PURE__ */ new Set([
20016
20191
  "node_modules",
@@ -20024,7 +20199,7 @@ async function loadGitignore(rootDir, extraExcludes = []) {
20024
20199
  const ig = ignore();
20025
20200
  ig.add(["node_modules/", ".git/", "dist/", "bin/", "obj/"]);
20026
20201
  if (extraExcludes.length > 0) ig.add([...extraExcludes]);
20027
- const gitignorePath = path64.join(rootDir, ".gitignore");
20202
+ const gitignorePath = path65.join(rootDir, ".gitignore");
20028
20203
  try {
20029
20204
  const content = await fs5.readFile(gitignorePath, "utf8");
20030
20205
  ig.add(content);
@@ -20033,11 +20208,11 @@ async function loadGitignore(rootDir, extraExcludes = []) {
20033
20208
  return ig;
20034
20209
  }
20035
20210
  async function collectFiles(rootDir, relativeDir, ig, files) {
20036
- const absDir = path64.join(rootDir, relativeDir);
20211
+ const absDir = path65.join(rootDir, relativeDir);
20037
20212
  const entries = await fs5.readdir(absDir, { withFileTypes: true });
20038
20213
  for (const entry of entries) {
20039
- const rel2 = relativeDir ? path64.join(relativeDir, entry.name) : entry.name;
20040
- const relPosix = rel2.split(path64.sep).join("/");
20214
+ const rel2 = relativeDir ? path65.join(relativeDir, entry.name) : entry.name;
20215
+ const relPosix = rel2.split(path65.sep).join("/");
20041
20216
  if (DEFAULT_EXCLUDES.has(entry.name) && !relativeDir) {
20042
20217
  continue;
20043
20218
  }
@@ -20052,7 +20227,7 @@ async function collectFiles(rootDir, relativeDir, ig, files) {
20052
20227
  }
20053
20228
  }
20054
20229
  async function collectPackageableFiles(sourceDirectory, extraExcludes = []) {
20055
- const resolved = path64.resolve(sourceDirectory);
20230
+ const resolved = path65.resolve(sourceDirectory);
20056
20231
  const stat7 = await fs5.stat(resolved).catch(() => null);
20057
20232
  if (!stat7?.isDirectory()) {
20058
20233
  throw new Error(`sourceDirectory is not a directory: ${resolved}`);
@@ -20078,7 +20253,7 @@ async function sha256File(filePath) {
20078
20253
  return hash2.digest("hex");
20079
20254
  }
20080
20255
  async function hashDirectoryContents(rootDirectory, extraExcludes = []) {
20081
- const resolved = path65.resolve(rootDirectory);
20256
+ const resolved = path66.resolve(rootDirectory);
20082
20257
  const files = (await collectPackageableFiles(resolved, extraExcludes)).sort(
20083
20258
  (a, b) => a.localeCompare(b)
20084
20259
  );
@@ -20086,13 +20261,13 @@ async function hashDirectoryContents(rootDirectory, extraExcludes = []) {
20086
20261
  for (const rel2 of files) {
20087
20262
  hash2.update(rel2);
20088
20263
  hash2.update("\0");
20089
- hash2.update(await fs6.readFile(path65.join(resolved, rel2)));
20264
+ hash2.update(await fs6.readFile(path66.join(resolved, rel2)));
20090
20265
  hash2.update("\0");
20091
20266
  }
20092
20267
  return hash2.digest("hex");
20093
20268
  }
20094
20269
  async function hashDevPortalSiteSources(siteDirectory, options) {
20095
- const resolved = path65.resolve(siteDirectory);
20270
+ const resolved = path66.resolve(siteDirectory);
20096
20271
  const hash2 = createHash3("sha256");
20097
20272
  const candidates = [
20098
20273
  "apitogo.config.json",
@@ -20102,7 +20277,7 @@ async function hashDevPortalSiteSources(siteDirectory, options) {
20102
20277
  "zudoku.config.tsx"
20103
20278
  ];
20104
20279
  for (const name of candidates) {
20105
- const full = path65.join(resolved, name);
20280
+ const full = path66.join(resolved, name);
20106
20281
  try {
20107
20282
  hash2.update(name);
20108
20283
  hash2.update("\0");
@@ -20112,7 +20287,7 @@ async function hashDevPortalSiteSources(siteDirectory, options) {
20112
20287
  }
20113
20288
  }
20114
20289
  for (const dir of ["pages", "landing", "src"]) {
20115
- const full = path65.join(resolved, dir);
20290
+ const full = path66.join(resolved, dir);
20116
20291
  try {
20117
20292
  const st = await fs6.stat(full);
20118
20293
  if (!st.isDirectory()) continue;
@@ -20341,8 +20516,8 @@ function normalizeActionKey(actionKey2) {
20341
20516
  const trimmed = actionKey2.trim();
20342
20517
  if (trimmed.includes(":")) {
20343
20518
  const [method2, ...pathParts] = trimmed.split(":");
20344
- const path97 = pathParts.join(":").trim();
20345
- return `${method2?.toLowerCase()}:${path97.startsWith("/") ? path97 : `/${path97}`}`;
20519
+ const path98 = pathParts.join(":").trim();
20520
+ return `${method2?.toLowerCase()}:${path98.startsWith("/") ? path98 : `/${path98}`}`;
20346
20521
  }
20347
20522
  const spaceIndex = trimmed.indexOf(" ");
20348
20523
  if (spaceIndex <= 0) {
@@ -20351,8 +20526,8 @@ function normalizeActionKey(actionKey2) {
20351
20526
  );
20352
20527
  }
20353
20528
  const method = trimmed.slice(0, spaceIndex).trim().toLowerCase();
20354
- const path96 = trimmed.slice(spaceIndex + 1).trim();
20355
- return `${method}:${path96.startsWith("/") ? path96 : `/${path96}`}`;
20529
+ const path97 = trimmed.slice(spaceIndex + 1).trim();
20530
+ return `${method}:${path97.startsWith("/") ? path97 : `/${path97}`}`;
20356
20531
  }
20357
20532
  async function applyGatewayPublicRoutes(client, projectId, routes, options) {
20358
20533
  const applied = [];
@@ -20830,8 +21005,8 @@ async function upsertGatewayPlansFromManifest(client, config2, projectId, plans,
20830
21005
  }
20831
21006
 
20832
21007
  // src/cli/platform/helpers/openapi-gateway-servers.ts
20833
- import { mkdir as mkdir16, readFile as readFile23, writeFile as writeFile19 } from "node:fs/promises";
20834
- import path66 from "node:path";
21008
+ import { mkdir as mkdir16, readFile as readFile24, writeFile as writeFile19 } from "node:fs/promises";
21009
+ import path67 from "node:path";
20835
21010
  import YAML from "yaml";
20836
21011
  var GATEWAY_URL_ENV_KEY = "APITOGO_GATEWAY_URL";
20837
21012
  var PUBLISH_OPENAPI_RELATIVE = ".apitogo/openapi-publish.json";
@@ -20862,8 +21037,8 @@ async function resolveProjectGatewayUrl(client, projectId) {
20862
21037
  return null;
20863
21038
  }
20864
21039
  async function readOpenApiDocument(filePath) {
20865
- const content = await readFile23(filePath, "utf8");
20866
- const ext = path66.extname(filePath).toLowerCase();
21040
+ const content = await readFile24(filePath, "utf8");
21041
+ const ext = path67.extname(filePath).toLowerCase();
20867
21042
  const parsed = ext === ".json" ? JSON.parse(content) : YAML.parse(content);
20868
21043
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
20869
21044
  throw new Error(`OpenAPI document must be an object: ${filePath}`);
@@ -20871,13 +21046,13 @@ async function readOpenApiDocument(filePath) {
20871
21046
  return parsed;
20872
21047
  }
20873
21048
  async function materializePublishOpenApiWithGateway(siteDirectory, sourceOpenApiPath, gatewayUrl) {
20874
- const site = path66.resolve(siteDirectory);
20875
- const source = path66.resolve(sourceOpenApiPath);
21049
+ const site = path67.resolve(siteDirectory);
21050
+ const source = path67.resolve(sourceOpenApiPath);
20876
21051
  const relativeInput = PUBLISH_OPENAPI_RELATIVE;
20877
- const outputPath = path66.join(site, ...relativeInput.split("/"));
21052
+ const outputPath = path67.join(site, ...relativeInput.split("/"));
20878
21053
  const doc = await readOpenApiDocument(source);
20879
21054
  const rewritten = withGatewayServers(doc, gatewayUrl);
20880
- await mkdir16(path66.dirname(outputPath), { recursive: true });
21055
+ await mkdir16(path67.dirname(outputPath), { recursive: true });
20881
21056
  await writeFile19(
20882
21057
  outputPath,
20883
21058
  `${JSON.stringify(rewritten, null, 2)}
@@ -20887,11 +21062,11 @@ async function materializePublishOpenApiWithGateway(siteDirectory, sourceOpenApi
20887
21062
  return { outputPath, relativeInput };
20888
21063
  }
20889
21064
  async function pointSiteApisAtPublishOpenApi(siteDirectory, relativeInput) {
20890
- const configPath = path66.join(
20891
- path66.resolve(siteDirectory),
21065
+ const configPath = path67.join(
21066
+ path67.resolve(siteDirectory),
20892
21067
  APITOGO_CONFIG_FILENAME2
20893
21068
  );
20894
- const raw = await readFile23(configPath, "utf8");
21069
+ const raw = await readFile24(configPath, "utf8");
20895
21070
  const config2 = JSON.parse(raw);
20896
21071
  const previousApis = config2.apis;
20897
21072
  const previousBackend = config2.backend;
@@ -20908,7 +21083,7 @@ async function pointSiteApisAtPublishOpenApi(siteDirectory, relativeInput) {
20908
21083
  `, "utf8");
20909
21084
  return {
20910
21085
  restore: async () => {
20911
- const currentRaw = await readFile23(configPath, "utf8");
21086
+ const currentRaw = await readFile24(configPath, "utf8");
20912
21087
  const current = JSON.parse(currentRaw);
20913
21088
  if (previousApis === void 0) {
20914
21089
  delete current.apis;
@@ -20930,7 +21105,7 @@ async function pointSiteApisAtPublishOpenApi(siteDirectory, relativeInput) {
20930
21105
  };
20931
21106
  }
20932
21107
  async function prepareOpenApiServersForGatewayBuild(options) {
20933
- const siteDirectory = path66.resolve(options.siteDirectory);
21108
+ const siteDirectory = path67.resolve(options.siteDirectory);
20934
21109
  let openApiPath = resolveBackendOpenApiPath(
20935
21110
  options.manifest?.backend?.openApiPath,
20936
21111
  {
@@ -20943,8 +21118,8 @@ async function prepareOpenApiServersForGatewayBuild(options) {
20943
21118
  );
20944
21119
  if (!openApiPath) {
20945
21120
  try {
20946
- const raw = await readFile23(
20947
- path66.join(siteDirectory, APITOGO_CONFIG_FILENAME2),
21121
+ const raw = await readFile24(
21122
+ path67.join(siteDirectory, APITOGO_CONFIG_FILENAME2),
20948
21123
  "utf8"
20949
21124
  );
20950
21125
  const config2 = JSON.parse(raw);
@@ -20973,8 +21148,8 @@ function normalizeActionKeyFormat(actionKey2) {
20973
21148
  const trimmed = actionKey2.trim();
20974
21149
  if (trimmed.includes(":")) {
20975
21150
  const [method2, ...pathParts] = trimmed.split(":");
20976
- const path97 = pathParts.join(":").trim();
20977
- return `${method2.toLowerCase()}:${path97.startsWith("/") ? path97 : `/${path97}`}`;
21151
+ const path98 = pathParts.join(":").trim();
21152
+ return `${method2.toLowerCase()}:${path98.startsWith("/") ? path98 : `/${path98}`}`;
20978
21153
  }
20979
21154
  const spaceIndex = trimmed.indexOf(" ");
20980
21155
  if (spaceIndex <= 0) {
@@ -20983,8 +21158,8 @@ function normalizeActionKeyFormat(actionKey2) {
20983
21158
  );
20984
21159
  }
20985
21160
  const method = trimmed.slice(0, spaceIndex).trim().toLowerCase();
20986
- const path96 = trimmed.slice(spaceIndex + 1).trim();
20987
- return `${method}:${path96.startsWith("/") ? path96 : `/${path96}`}`;
21161
+ const path97 = trimmed.slice(spaceIndex + 1).trim();
21162
+ return `${method}:${path97.startsWith("/") ? path97 : `/${path97}`}`;
20988
21163
  }
20989
21164
  function normalizePublicRoute(route) {
20990
21165
  const trimmed = route.trim();
@@ -21017,16 +21192,16 @@ function collectManifestPublicActionKeys(gateway) {
21017
21192
  }
21018
21193
 
21019
21194
  // src/cli/platform/helpers/publish-ledger.ts
21020
- import { mkdir as mkdir17, readFile as readFile24, writeFile as writeFile20 } from "node:fs/promises";
21021
- import path67 from "node:path";
21195
+ import { mkdir as mkdir17, readFile as readFile25, writeFile as writeFile20 } from "node:fs/promises";
21196
+ import path68 from "node:path";
21022
21197
  var PUBLISH_LEDGER_RELATIVE_PATH = ".apitogo/publish-state.json";
21023
21198
  function publishLedgerPath(siteDirectory) {
21024
- return path67.join(path67.resolve(siteDirectory), PUBLISH_LEDGER_RELATIVE_PATH);
21199
+ return path68.join(path68.resolve(siteDirectory), PUBLISH_LEDGER_RELATIVE_PATH);
21025
21200
  }
21026
21201
  async function readPublishLedger(siteDirectory) {
21027
21202
  const filePath = publishLedgerPath(siteDirectory);
21028
21203
  try {
21029
- const raw = await readFile24(filePath, "utf8");
21204
+ const raw = await readFile25(filePath, "utf8");
21030
21205
  const parsed = JSON.parse(raw);
21031
21206
  if (parsed?.version !== 1 || !Array.isArray(parsed.steps)) {
21032
21207
  return null;
@@ -21038,7 +21213,7 @@ async function readPublishLedger(siteDirectory) {
21038
21213
  }
21039
21214
  async function writePublishLedger(siteDirectory, ledger) {
21040
21215
  const filePath = publishLedgerPath(siteDirectory);
21041
- await mkdir17(path67.dirname(filePath), { recursive: true });
21216
+ await mkdir17(path68.dirname(filePath), { recursive: true });
21042
21217
  const next = {
21043
21218
  ...ledger,
21044
21219
  version: 1,
@@ -21560,7 +21735,7 @@ async function createProjectWithWarmPoolRetry(client, body, options) {
21560
21735
  import { spawn as spawn3 } from "node:child_process";
21561
21736
  import { mkdtemp, readdir as readdir4, rm as rm9 } from "node:fs/promises";
21562
21737
  import { tmpdir } from "node:os";
21563
- import path68 from "node:path";
21738
+ import path69 from "node:path";
21564
21739
  async function directoryHasRuntimeConfig(dir) {
21565
21740
  if (!await pathExists(dir)) {
21566
21741
  return false;
@@ -21603,20 +21778,20 @@ function runDotnetPublish(projectDir, outputDir) {
21603
21778
  async function findCsproj(projectDir) {
21604
21779
  const entries = await readdir4(projectDir);
21605
21780
  const csproj = entries.find((name) => name.endsWith(".csproj"));
21606
- return csproj ? path68.join(projectDir, csproj) : null;
21781
+ return csproj ? path69.join(projectDir, csproj) : null;
21607
21782
  }
21608
21783
  async function prepareBackendPackagingDirectory(args) {
21609
- const sourceDirectory = path68.resolve(args.sourceDirectory);
21784
+ const sourceDirectory = path69.resolve(args.sourceDirectory);
21610
21785
  if (args.publishDirectory?.trim()) {
21611
21786
  return {
21612
- directory: path68.resolve(args.publishDirectory),
21787
+ directory: path69.resolve(args.publishDirectory),
21613
21788
  packagingMode: "published"
21614
21789
  };
21615
21790
  }
21616
21791
  if (await directoryHasRuntimeConfig(sourceDirectory)) {
21617
21792
  return { directory: sourceDirectory, packagingMode: "published" };
21618
21793
  }
21619
- const publishSubdir = path68.join(sourceDirectory, "publish");
21794
+ const publishSubdir = path69.join(sourceDirectory, "publish");
21620
21795
  if (await directoryHasRuntimeConfig(publishSubdir)) {
21621
21796
  return { directory: publishSubdir, packagingMode: "published" };
21622
21797
  }
@@ -21628,9 +21803,9 @@ async function prepareBackendPackagingDirectory(args) {
21628
21803
  return { directory: sourceDirectory, packagingMode: "source" };
21629
21804
  }
21630
21805
  const tempRoot = await mkdtemp(
21631
- path68.join(tmpdir(), "apitogo-dotnet-publish-")
21806
+ path69.join(tmpdir(), "apitogo-dotnet-publish-")
21632
21807
  );
21633
- const outputDir = path68.join(tempRoot, "publish");
21808
+ const outputDir = path69.join(tempRoot, "publish");
21634
21809
  const result = await runDotnetPublish(sourceDirectory, outputDir);
21635
21810
  if (result.exitCode !== 0) {
21636
21811
  await rm9(tempRoot, { recursive: true, force: true });
@@ -21675,13 +21850,13 @@ function formatJobStatusResponse(options) {
21675
21850
 
21676
21851
  // src/cli/platform/helpers/openapi.ts
21677
21852
  import { promises as fs7 } from "node:fs";
21678
- import path69 from "node:path";
21853
+ import path70 from "node:path";
21679
21854
  import SwaggerParser from "@apidevtools/swagger-parser";
21680
21855
  import YAML2 from "yaml";
21681
21856
  async function validateOpenApiFile(filePath) {
21682
- const resolved = path69.resolve(filePath);
21857
+ const resolved = path70.resolve(filePath);
21683
21858
  const content = await fs7.readFile(resolved, "utf8");
21684
- const ext = path69.extname(resolved).toLowerCase();
21859
+ const ext = path70.extname(resolved).toLowerCase();
21685
21860
  let parsed;
21686
21861
  try {
21687
21862
  parsed = ext === ".json" ? JSON.parse(content) : YAML2.parse(content);
@@ -21725,12 +21900,12 @@ async function validateOpenApiFile(filePath) {
21725
21900
  // src/cli/platform/helpers/zip.ts
21726
21901
  import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, promises as fs8 } from "node:fs";
21727
21902
  import { tmpdir as tmpdir2 } from "node:os";
21728
- import path70 from "node:path";
21903
+ import path71 from "node:path";
21729
21904
  import { ZipArchive } from "archiver";
21730
21905
  async function packageBackendDirectory(sourceDirectory, extraExcludes = []) {
21731
- const resolved = path70.resolve(sourceDirectory);
21906
+ const resolved = path71.resolve(sourceDirectory);
21732
21907
  const files = await collectPackageableFiles(resolved, extraExcludes);
21733
- const zipPath = path70.join(
21908
+ const zipPath = path71.join(
21734
21909
  tmpdir2(),
21735
21910
  `apitogo-backend-${Date.now()}-${Math.random().toString(36).slice(2)}.zip`
21736
21911
  );
@@ -21742,8 +21917,8 @@ async function packageBackendDirectory(sourceDirectory, extraExcludes = []) {
21742
21917
  output4.on("error", reject);
21743
21918
  archive.pipe(output4);
21744
21919
  for (const rel2 of files) {
21745
- archive.append(createReadStream2(path70.join(resolved, rel2)), {
21746
- name: rel2.split(path70.sep).join("/")
21920
+ archive.append(createReadStream2(path71.join(resolved, rel2)), {
21921
+ name: rel2.split(path71.sep).join("/")
21747
21922
  });
21748
21923
  }
21749
21924
  void archive.finalize();
@@ -23294,11 +23469,11 @@ async function resolveProjectIdForPublish(client, config2, args, wait, progress,
23294
23469
  }
23295
23470
 
23296
23471
  // src/cli/platform/tools/dev-portal-site-build.ts
23297
- import path74 from "node:path";
23472
+ import path75 from "node:path";
23298
23473
 
23299
23474
  // src/cli/platform/helpers/dev-portal-site-api-url.ts
23300
- import { readdir as readdir5, readFile as readFile25, writeFile as writeFile21 } from "node:fs/promises";
23301
- import path71 from "node:path";
23475
+ import { readdir as readdir5, readFile as readFile26, writeFile as writeFile21 } from "node:fs/promises";
23476
+ import path72 from "node:path";
23302
23477
  var SITE_API_BASE_URL_ENV_KEY = "VITE_APITOGO_AUTHENTICATION_API_BASE_URL";
23303
23478
  var PLACEHOLDER_HOST_MARKERS = [
23304
23479
  "dp-example.azurecontainerapps.io",
@@ -23319,10 +23494,10 @@ function isPlaceholderDevPortalApiUrl(apiBaseUrl) {
23319
23494
  return PLACEHOLDER_HOST_MARKERS.some((marker) => normalized.includes(marker));
23320
23495
  }
23321
23496
  async function readSiteApiBaseUrl(sourceDirectory) {
23322
- const resolved = path71.resolve(sourceDirectory);
23497
+ const resolved = path72.resolve(sourceDirectory);
23323
23498
  for (const envFile of [".env", ".env.production"]) {
23324
23499
  try {
23325
- const content = await readFile25(path71.join(resolved, envFile), "utf8");
23500
+ const content = await readFile26(path72.join(resolved, envFile), "utf8");
23326
23501
  const lines = [...content.matchAll(ENV_LINE_GLOBAL_RE)];
23327
23502
  if (lines.length === 0) {
23328
23503
  continue;
@@ -23347,13 +23522,13 @@ async function readSiteApiBaseUrl(sourceDirectory) {
23347
23522
  return null;
23348
23523
  }
23349
23524
  async function patchSiteApiBaseUrl(sourceDirectory, apiBaseUrl) {
23350
- const resolved = path71.resolve(sourceDirectory);
23525
+ const resolved = path72.resolve(sourceDirectory);
23351
23526
  const line2 = `${SITE_API_BASE_URL_ENV_KEY}=${apiBaseUrl}`;
23352
23527
  let patchedExisting = false;
23353
23528
  for (const envFile of [".env.production", ".env"]) {
23354
- const envPath = path71.join(resolved, envFile);
23529
+ const envPath = path72.join(resolved, envFile);
23355
23530
  try {
23356
- const content = await readFile25(envPath, "utf8");
23531
+ const content = await readFile26(envPath, "utf8");
23357
23532
  const withoutAssignments = content.replace(ENV_LINE_GLOBAL_RE, "").replace(/\n{3,}/g, "\n\n").trimEnd();
23358
23533
  const patched = withoutAssignments ? `${withoutAssignments}
23359
23534
  ${line2}
@@ -23365,7 +23540,7 @@ ${line2}
23365
23540
  }
23366
23541
  }
23367
23542
  if (!patchedExisting) {
23368
- await writeFile21(path71.join(resolved, ".env"), `${line2}
23543
+ await writeFile21(path72.join(resolved, ".env"), `${line2}
23369
23544
  `);
23370
23545
  }
23371
23546
  }
@@ -23373,7 +23548,7 @@ function tryProjectId(explicit, manifestProjectId, config2) {
23373
23548
  return explicit?.trim() || manifestProjectId?.trim() || config2.defaultProjectId?.trim() || void 0;
23374
23549
  }
23375
23550
  async function ensureLiveSiteApiBaseUrlForBuild(_client, config2, args, resolveFromProject) {
23376
- const sourceDirectory = path71.resolve(args.sourceDirectory);
23551
+ const sourceDirectory = path72.resolve(args.sourceDirectory);
23377
23552
  const explicit = args.apiBaseUrl?.trim();
23378
23553
  if (explicit && !isPlaceholderDevPortalApiUrl(explicit)) {
23379
23554
  await patchSiteApiBaseUrl(sourceDirectory, explicit);
@@ -23409,7 +23584,7 @@ async function* walkFiles(root) {
23409
23584
  return;
23410
23585
  }
23411
23586
  for (const entry of entries) {
23412
- const full = path71.join(root, entry.name);
23587
+ const full = path72.join(root, entry.name);
23413
23588
  if (entry.isDirectory()) {
23414
23589
  if (entry.name === "node_modules" || entry.name === ".git") {
23415
23590
  continue;
@@ -23421,8 +23596,8 @@ async function* walkFiles(root) {
23421
23596
  }
23422
23597
  }
23423
23598
  async function assertDeployableDistHasLiveApiBaseUrl(distDirectory, expectedApiBaseUrl) {
23424
- const dist = path71.resolve(distDirectory);
23425
- const siteRoot = path71.dirname(dist);
23599
+ const dist = path72.resolve(distDirectory);
23600
+ const siteRoot = path72.dirname(dist);
23426
23601
  const fromEnv = expectedApiBaseUrl?.trim() || await readSiteApiBaseUrl(siteRoot) || await readSiteApiBaseUrl(dist);
23427
23602
  if (!fromEnv || isPlaceholderDevPortalApiUrl(fromEnv)) {
23428
23603
  throw new Error(
@@ -23433,7 +23608,7 @@ async function assertDeployableDistHasLiveApiBaseUrl(distDirectory, expectedApiB
23433
23608
  let found = false;
23434
23609
  let foundPlaceholder = false;
23435
23610
  for await (const file of walkFiles(dist)) {
23436
- const content = await readFile25(file, "utf8");
23611
+ const content = await readFile26(file, "utf8");
23437
23612
  if (content.includes(needle)) {
23438
23613
  found = true;
23439
23614
  }
@@ -23458,7 +23633,7 @@ async function assertDeployableDistHasLiveApiBaseUrl(distDirectory, expectedApiB
23458
23633
 
23459
23634
  // src/cli/platform/tools/dev-portal.ts
23460
23635
  import { promises as fs10 } from "node:fs";
23461
- import path73 from "node:path";
23636
+ import path74 from "node:path";
23462
23637
 
23463
23638
  // src/cli/platform/helpers/dev-portal-backend-job.ts
23464
23639
  var DEV_PORTAL_BACKEND_UPDATE_RESOURCE_TYPE = "DevPortalBackendUpdate";
@@ -23568,7 +23743,7 @@ async function snapshotBackendUpdateJobIds(client, projectId) {
23568
23743
  // src/cli/platform/helpers/tarball.ts
23569
23744
  import { createReadStream as createReadStream3, createWriteStream as createWriteStream3, promises as fs9 } from "node:fs";
23570
23745
  import { tmpdir as tmpdir3 } from "node:os";
23571
- import path72 from "node:path";
23746
+ import path73 from "node:path";
23572
23747
  import { TarArchive } from "archiver";
23573
23748
  var DEV_PORTAL_DEPLOY_ARCHIVE_ROOT = "dist";
23574
23749
  function normalizeArchiveRoot(archiveRoot) {
@@ -23579,10 +23754,10 @@ function normalizeArchiveRoot(archiveRoot) {
23579
23754
  return `${trimmed}/`;
23580
23755
  }
23581
23756
  async function packageDirectoryAsTarGz(sourceDirectory, options) {
23582
- const resolved = path72.resolve(sourceDirectory);
23757
+ const resolved = path73.resolve(sourceDirectory);
23583
23758
  const files = await collectPackageableFiles(resolved);
23584
23759
  const entryPrefix = options?.archiveRoot ? normalizeArchiveRoot(options.archiveRoot) : "";
23585
- const archivePath = path72.join(
23760
+ const archivePath = path73.join(
23586
23761
  tmpdir3(),
23587
23762
  `apitogo-docs-${Date.now()}-${Math.random().toString(36).slice(2)}.tgz`
23588
23763
  );
@@ -23594,8 +23769,8 @@ async function packageDirectoryAsTarGz(sourceDirectory, options) {
23594
23769
  output4.on("error", reject);
23595
23770
  archive.pipe(output4);
23596
23771
  for (const rel2 of files) {
23597
- const entryName = entryPrefix + rel2.split(path72.sep).join("/");
23598
- archive.append(createReadStream3(path72.join(resolved, rel2)), {
23772
+ const entryName = entryPrefix + rel2.split(path73.sep).join("/");
23773
+ archive.append(createReadStream3(path73.join(resolved, rel2)), {
23599
23774
  name: entryName
23600
23775
  });
23601
23776
  }
@@ -23837,7 +24012,7 @@ function validateDeployArchiveInput(args) {
23837
24012
  async function resolveDevPortalArchive(args) {
23838
24013
  validateDeployArchiveInput(args);
23839
24014
  if (args.archivePath?.trim()) {
23840
- const archivePath = path73.resolve(args.archivePath.trim());
24015
+ const archivePath = path74.resolve(args.archivePath.trim());
23841
24016
  const stat7 = await fs10.stat(archivePath).catch(() => null);
23842
24017
  if (!stat7?.isFile()) {
23843
24018
  throw new Error(`archivePath is not a file: ${archivePath}`);
@@ -23902,7 +24077,7 @@ async function handleDeployDevPortal(client, config2, args, progress) {
23902
24077
  // src/cli/platform/tools/dev-portal-site-build.ts
23903
24078
  async function handleBuildDevPortalSite(client, config2, args, progress) {
23904
24079
  const buildProgress = progress?.child("Build dev portal site");
23905
- const sourceDirectory = path74.resolve(args.sourceDirectory);
24080
+ const sourceDirectory = path75.resolve(args.sourceDirectory);
23906
24081
  await buildProgress?.onStep("Ensuring live portal API URL");
23907
24082
  const apiBaseUrl = await ensureLiveSiteApiBaseUrlForBuild(
23908
24083
  client,
@@ -25408,7 +25583,7 @@ function resultLooksFailed(payload) {
25408
25583
  return parsed.status === "failed" || parsed.status === "blocked";
25409
25584
  }
25410
25585
  async function apply(argv) {
25411
- const sourceDirectory = path75.resolve(process.cwd(), argv.dir);
25586
+ const sourceDirectory = path76.resolve(process.cwd(), argv.dir);
25412
25587
  let config2;
25413
25588
  try {
25414
25589
  config2 = loadConfig();
@@ -25478,7 +25653,7 @@ async function apply(argv) {
25478
25653
  if (canPromptInteractively && parsed?.status === "blocked" && parsed.reason === "project_not_found") {
25479
25654
  const resolution = await resolveProjectNotFoundInteractively(
25480
25655
  parsed,
25481
- path75.basename(sourceDirectory)
25656
+ path76.basename(sourceDirectory)
25482
25657
  );
25483
25658
  if (resolution) {
25484
25659
  effectiveProjectId = void 0;
@@ -25498,7 +25673,7 @@ async function apply(argv) {
25498
25673
  while (canPromptInteractively && parsed?.status === "blocked" && parsed.reason === "project_name_exists") {
25499
25674
  const resolution = await resolveProjectNameExistsInteractively(
25500
25675
  parsed,
25501
- effectiveProjectName ?? path75.basename(sourceDirectory)
25676
+ effectiveProjectName ?? path76.basename(sourceDirectory)
25502
25677
  );
25503
25678
  if (!resolution) {
25504
25679
  break;
@@ -25569,11 +25744,11 @@ async function apply(argv) {
25569
25744
  }
25570
25745
 
25571
25746
  // src/cli/deploy/command.ts
25572
- import path80 from "node:path";
25747
+ import path81 from "node:path";
25573
25748
  init_invariant();
25574
25749
 
25575
25750
  // src/cli/project/create-handler.ts
25576
- import path76 from "node:path";
25751
+ import path77 from "node:path";
25577
25752
  import open2 from "open";
25578
25753
  init_invariant();
25579
25754
 
@@ -25877,7 +26052,7 @@ async function createLinkedProject(argv, dir, options = {}) {
25877
26052
  }
25878
26053
  }
25879
26054
  async function createProject2(argv) {
25880
- const dir = path76.resolve(process.cwd(), argv.dir ?? ".");
26055
+ const dir = path77.resolve(process.cwd(), argv.dir ?? ".");
25881
26056
  if (await isConfigV2(dir)) {
25882
26057
  await createLinkedProject(argv, dir);
25883
26058
  return;
@@ -25988,7 +26163,7 @@ async function confirm(question) {
25988
26163
  }
25989
26164
 
25990
26165
  // src/cli/deploy/stripe-key.ts
25991
- import path77 from "node:path";
26166
+ import path78 from "node:path";
25992
26167
  init_invariant();
25993
26168
  var StripeKeyError = class extends ApitogoError {
25994
26169
  constructor(message, developerHint) {
@@ -26006,7 +26181,7 @@ async function ensureStripeKey(argv, deps) {
26006
26181
  if (!wantsPlans(argv.only)) return { status: "not-needed" };
26007
26182
  let resolved;
26008
26183
  try {
26009
- resolved = loadConfigV2(path77.resolve(process.cwd(), argv.dir)).resolved;
26184
+ resolved = loadConfigV2(path78.resolve(process.cwd(), argv.dir)).resolved;
26010
26185
  } catch {
26011
26186
  return { status: "not-needed" };
26012
26187
  }
@@ -26054,11 +26229,11 @@ init_invariant();
26054
26229
 
26055
26230
  // src/cli/portal/report.ts
26056
26231
  import { access as access9 } from "node:fs/promises";
26057
- import path78 from "node:path";
26232
+ import path79 from "node:path";
26058
26233
 
26059
26234
  // src/cli/deploy/gateway.ts
26060
26235
  import { createHash as createHash4 } from "node:crypto";
26061
- import { readFile as readFile26 } from "node:fs/promises";
26236
+ import { readFile as readFile27 } from "node:fs/promises";
26062
26237
  init_invariant();
26063
26238
  var GatewayDeployError = class extends ApitogoError {
26064
26239
  constructor(code, message, developerHint) {
@@ -26096,7 +26271,7 @@ async function readSpec(gateway) {
26096
26271
  "Add one to gateway.specs in the config."
26097
26272
  );
26098
26273
  try {
26099
- return await readFile26(file);
26274
+ return await readFile27(file);
26100
26275
  } catch {
26101
26276
  throw new GatewayDeployError(
26102
26277
  "GATEWAY_SPEC_UNREADABLE",
@@ -27520,7 +27695,7 @@ async function planPortalService(resolved, ledger) {
27520
27695
  const hash2 = await portalBuildHash(resolved, prepared);
27521
27696
  const previous = stepOf(ledger, "portal", "build");
27522
27697
  const built = await exists5(
27523
- path78.join(resolved.state.buildDir, "index.html")
27698
+ path79.join(resolved.state.buildDir, "index.html")
27524
27699
  );
27525
27700
  if (previous?.status === "succeeded" && previous.hash === hash2 && built) {
27526
27701
  return {
@@ -27879,7 +28054,7 @@ async function statusV2(dir, only, options = {}) {
27879
28054
  if (service === "portal") {
27880
28055
  const build2 = stepOf(ledger, "portal", "build");
27881
28056
  const built = await exists5(
27882
- path78.join(resolved.state.buildDir, "index.html")
28057
+ path79.join(resolved.state.buildDir, "index.html")
27883
28058
  );
27884
28059
  const state = build2?.status === "failed" ? "build-failed" : build2?.status === "succeeded" && built ? "built" : "not-built";
27885
28060
  services.push({
@@ -27890,7 +28065,7 @@ async function statusV2(dir, only, options = {}) {
27890
28065
  ...build2?.finishedAt ? [`last build: ${build2.finishedAt}`] : [],
27891
28066
  ...build2?.status === "failed" ? [`error: ${build2.error ?? "unknown"}`] : [],
27892
28067
  ...state === "built" ? [
27893
- `output: ${path78.relative(resolved.configDir, resolved.state.buildDir)}`
28068
+ `output: ${path79.relative(resolved.configDir, resolved.state.buildDir)}`
27894
28069
  ] : [],
27895
28070
  ...url2 ? [`url: ${url2}`] : ["url: not known (portal is not deployed yet)"],
27896
28071
  ...await hostingLine(resolved, manifest, options.hostingRemote)
@@ -27957,7 +28132,7 @@ function formatStatus(output4) {
27957
28132
 
27958
28133
  // src/cli/deploy/static-web-config.ts
27959
28134
  import { access as access10, writeFile as writeFile22 } from "node:fs/promises";
27960
- import path79 from "node:path";
28135
+ import path80 from "node:path";
27961
28136
  var STATIC_WEB_CONFIG_FILE = "staticwebapp.config.json";
27962
28137
  var STATIC_WEB_CONFIG_VERSION = 3;
27963
28138
  var CLIENT_ONLY_ROUTES = [
@@ -27975,7 +28150,7 @@ var DEFAULT_STATIC_WEB_CONFIG = {
27975
28150
  }
27976
28151
  };
27977
28152
  async function ensureStaticWebConfig(buildDir) {
27978
- const file = path79.join(buildDir, STATIC_WEB_CONFIG_FILE);
28153
+ const file = path80.join(buildDir, STATIC_WEB_CONFIG_FILE);
27979
28154
  try {
27980
28155
  await access10(file);
27981
28156
  return false;
@@ -28326,7 +28501,7 @@ function formatDeploy(output4) {
28326
28501
  // src/cli/deploy/command.ts
28327
28502
  async function ensureLinkedProject(argv, deps) {
28328
28503
  if (argv.projectId?.trim() || deps.envProjectId?.trim()) return true;
28329
- const dir = path80.resolve(process.cwd(), argv.dir);
28504
+ const dir = path81.resolve(process.cwd(), argv.dir);
28330
28505
  let linked;
28331
28506
  try {
28332
28507
  linked = Boolean(loadConfigV2(dir).resolved.project.id);
@@ -28378,7 +28553,7 @@ async function deployProject(argv) {
28378
28553
  const config2 = loadConfig();
28379
28554
  const output4 = await deployV2(
28380
28555
  {
28381
- dir: path80.resolve(process.cwd(), argv.dir),
28556
+ dir: path81.resolve(process.cwd(), argv.dir),
28382
28557
  only: Array.isArray(argv.only) ? argv.only.join(",") : argv.only,
28383
28558
  projectId: argv.projectId,
28384
28559
  env: argv.env,
@@ -28472,7 +28647,7 @@ var deploy_default = {
28472
28647
  }),
28473
28648
  handler: async (argv) => {
28474
28649
  await captureEvent({ argv, event: "apitogo deploy" });
28475
- if (await isConfigV2(path81.resolve(process.cwd(), argv.dir))) {
28650
+ if (await isConfigV2(path82.resolve(process.cwd(), argv.dir))) {
28476
28651
  await deployProject(argv);
28477
28652
  return;
28478
28653
  }
@@ -28482,7 +28657,7 @@ var deploy_default = {
28482
28657
 
28483
28658
  // src/cli/export/handler.ts
28484
28659
  import { mkdir as mkdir18, writeFile as writeFile23 } from "node:fs/promises";
28485
- import path82 from "node:path";
28660
+ import path83 from "node:path";
28486
28661
  init_invariant();
28487
28662
  var ExportError = class extends ApitogoError {
28488
28663
  constructor(message, developerHint) {
@@ -28496,7 +28671,7 @@ async function exportOpenApi(args, deps) {
28496
28671
  `Cannot export "${args.target}".`,
28497
28672
  "Only `apitogo export openapi` exists."
28498
28673
  );
28499
- const dir = path82.resolve(process.cwd(), args.dir ?? ".");
28674
+ const dir = path83.resolve(process.cwd(), args.dir ?? ".");
28500
28675
  if (!await isConfigV2(dir))
28501
28676
  throw new ExportError(
28502
28677
  "This command needs a config version 2 project.",
@@ -28521,8 +28696,8 @@ async function exportOpenApi(args, deps) {
28521
28696
  throw error;
28522
28697
  }
28523
28698
  if (!args.out) return { text };
28524
- const file = path82.resolve(process.cwd(), args.out);
28525
- await mkdir18(path82.dirname(file), { recursive: true });
28699
+ const file = path83.resolve(process.cwd(), args.out);
28700
+ await mkdir18(path83.dirname(file), { recursive: true });
28526
28701
  await writeFile23(file, text);
28527
28702
  return { text, file };
28528
28703
  }
@@ -28615,8 +28790,8 @@ import open3 from "open";
28615
28790
  import colors14 from "picocolors";
28616
28791
 
28617
28792
  // src/cli/platform/device-auth.ts
28618
- function url(apiUrl, path96) {
28619
- return `${apiUrl}${path96.startsWith("/") ? path96 : `/${path96}`}`;
28793
+ function url(apiUrl, path97) {
28794
+ return `${apiUrl}${path97.startsWith("/") ? path97 : `/${path97}`}`;
28620
28795
  }
28621
28796
  async function requestDeviceCode(apiUrl) {
28622
28797
  const response = await fetchWithRetry(
@@ -28798,7 +28973,7 @@ var logout_default = {
28798
28973
  };
28799
28974
 
28800
28975
  // src/cli/portal/commands.ts
28801
- import path83 from "node:path";
28976
+ import path84 from "node:path";
28802
28977
  init_invariant();
28803
28978
  function parseOnly(value) {
28804
28979
  if (value === void 0) return void 0;
@@ -28815,7 +28990,7 @@ function parseOnly(value) {
28815
28990
  async function run2(command2, argv, compute, format) {
28816
28991
  const json = argv.json === true;
28817
28992
  try {
28818
- const dir = path83.resolve(process.cwd(), argv.dir ?? ".");
28993
+ const dir = path84.resolve(process.cwd(), argv.dir ?? ".");
28819
28994
  if (!await isConfigV2(dir)) {
28820
28995
  throw new ServiceEditError(
28821
28996
  `${command2} works with a config version 2 project, and there is none in ${dir}.`,
@@ -29031,14 +29206,14 @@ var remove_default = {
29031
29206
 
29032
29207
  // src/cli/dev/handler.ts
29033
29208
  init_joinUrl();
29034
- import path86 from "node:path";
29209
+ import path87 from "node:path";
29035
29210
 
29036
29211
  // src/vite/dev-server.ts
29037
29212
  init_logger();
29038
29213
  import fs11 from "node:fs/promises";
29039
29214
  import http from "node:http";
29040
29215
  import https from "node:https";
29041
- import path85 from "node:path";
29216
+ import path86 from "node:path";
29042
29217
  import { createHttpTerminator } from "http-terminator";
29043
29218
  import {
29044
29219
  createServer as createViteServer,
@@ -29071,7 +29246,7 @@ init_loader();
29071
29246
  // src/vite/pagefind-dev-index.ts
29072
29247
  init_invariant();
29073
29248
  init_joinUrl();
29074
- import path84 from "node:path";
29249
+ import path85 from "node:path";
29075
29250
  import { createIndex as createIndex2 } from "pagefind";
29076
29251
  import { isRunnableDevEnvironment } from "vite";
29077
29252
  async function* buildPagefindDevIndex(vite, config2) {
@@ -29124,7 +29299,7 @@ async function* buildPagefindDevIndex(vite, config2) {
29124
29299
  path: urlPath
29125
29300
  };
29126
29301
  }
29127
- const outputPath = path84.join(vite.config.publicDir, "pagefind");
29302
+ const outputPath = path85.join(vite.config.publicDir, "pagefind");
29128
29303
  await pagefindIndex.writeFiles({ outputPath });
29129
29304
  yield { type: "complete", success: true, indexed };
29130
29305
  }
@@ -29143,9 +29318,9 @@ var DevServer = class {
29143
29318
  this.protocol = "https";
29144
29319
  const { dir } = this.options;
29145
29320
  const [key, cert, ca] = await Promise.all([
29146
- fs11.readFile(path85.resolve(dir, config2.https.key)),
29147
- fs11.readFile(path85.resolve(dir, config2.https.cert)),
29148
- config2.https.ca ? fs11.readFile(path85.resolve(dir, config2.https.ca)) : void 0
29321
+ fs11.readFile(path86.resolve(dir, config2.https.key)),
29322
+ fs11.readFile(path86.resolve(dir, config2.https.cert)),
29323
+ config2.https.ca ? fs11.readFile(path86.resolve(dir, config2.https.ca)) : void 0
29149
29324
  ]);
29150
29325
  return https.createServer({ key, cert, ca });
29151
29326
  }
@@ -29162,7 +29337,7 @@ var DevServer = class {
29162
29337
  );
29163
29338
  const server = await this.createNodeServer(config2);
29164
29339
  if (config2.search?.type === "pagefind" && viteConfig.publicDir !== false) {
29165
- const publicRoot = path85.resolve(
29340
+ const publicRoot = path86.resolve(
29166
29341
  this.options.dir,
29167
29342
  typeof viteConfig.publicDir === "string" ? viteConfig.publicDir : "public"
29168
29343
  );
@@ -29179,7 +29354,7 @@ var DevServer = class {
29179
29354
  // built-in transform middleware which would treat the path as a static asset.
29180
29355
  name: "apitogo:entry-client",
29181
29356
  configureServer(server2) {
29182
- const entryPath = path85.posix.join(
29357
+ const entryPath = path86.posix.join(
29183
29358
  server2.config.base,
29184
29359
  "/__z/entry.client.tsx"
29185
29360
  );
@@ -29344,7 +29519,7 @@ init_package_json();
29344
29519
  async function dev(argv) {
29345
29520
  const packageJson3 = getZudokuPackageJson();
29346
29521
  process.env.NODE_ENV = "development";
29347
- let dir = path86.resolve(process.cwd(), argv.dir);
29522
+ let dir = path87.resolve(process.cwd(), argv.dir);
29348
29523
  if (await isConfigV2(dir)) {
29349
29524
  const { root, prepared } = await preparePortalWorkspace(dir, "development");
29350
29525
  dir = root;
@@ -29443,7 +29618,7 @@ var run_default = {
29443
29618
  };
29444
29619
 
29445
29620
  // src/cli/secrets/handler.ts
29446
- import path87 from "node:path";
29621
+ import path88 from "node:path";
29447
29622
  init_invariant();
29448
29623
  var SECRET_NAME = /^[A-Za-z_][A-Za-z0-9_]{0,127}$/;
29449
29624
  var SecretsError = class extends ApitogoError {
@@ -29455,7 +29630,7 @@ var SecretsError = class extends ApitogoError {
29455
29630
  async function resolveProjectId2(argv, deps) {
29456
29631
  const explicit = argv.projectId?.trim();
29457
29632
  if (explicit) return explicit;
29458
- const dir = path87.resolve(process.cwd(), argv.dir ?? ".");
29633
+ const dir = path88.resolve(process.cwd(), argv.dir ?? ".");
29459
29634
  if (await isConfigV2(dir)) {
29460
29635
  const id = loadConfigV2(dir).resolved.project.id;
29461
29636
  if (id) return id;
@@ -29615,12 +29790,12 @@ var secrets_default = {
29615
29790
  };
29616
29791
 
29617
29792
  // src/cli/cmds/status.ts
29618
- import path89 from "node:path";
29793
+ import path90 from "node:path";
29619
29794
 
29620
29795
  // src/cli/status/handler.ts
29621
- import path88 from "node:path";
29796
+ import path89 from "node:path";
29622
29797
  async function status(argv) {
29623
- const sourceDirectory = path88.resolve(process.cwd(), argv.dir);
29798
+ const sourceDirectory = path89.resolve(process.cwd(), argv.dir);
29624
29799
  let config2;
29625
29800
  try {
29626
29801
  config2 = loadConfig();
@@ -29718,7 +29893,7 @@ var status_default = {
29718
29893
  }),
29719
29894
  handler: async (argv) => {
29720
29895
  await captureEvent({ argv, event: "apitogo status" });
29721
- if (await isConfigV2(path89.resolve(process.cwd(), argv.dir))) {
29896
+ if (await isConfigV2(path90.resolve(process.cwd(), argv.dir))) {
29722
29897
  await statusOfProject(argv);
29723
29898
  return;
29724
29899
  }
@@ -29727,11 +29902,11 @@ var status_default = {
29727
29902
  };
29728
29903
 
29729
29904
  // src/cli/cmds/teardown.ts
29730
- import path92 from "node:path";
29905
+ import path93 from "node:path";
29731
29906
 
29732
29907
  // src/cli/teardown/command.ts
29733
29908
  init_invariant();
29734
- import path90 from "node:path";
29909
+ import path91 from "node:path";
29735
29910
  import { createInterface as createInterface7 } from "node:readline/promises";
29736
29911
 
29737
29912
  // src/cli/teardown/v2.ts
@@ -30092,7 +30267,7 @@ async function teardownProject(argv) {
30092
30267
  const progress = createConsoleProgressReporter();
30093
30268
  const result = await teardownV2(
30094
30269
  {
30095
- dir: path90.resolve(process.cwd(), argv.dir),
30270
+ dir: path91.resolve(process.cwd(), argv.dir),
30096
30271
  projectId: argv.projectId,
30097
30272
  only: Array.isArray(argv.only) ? argv.only.join(",") : argv.only,
30098
30273
  yes: argv.yes === true,
@@ -30151,7 +30326,7 @@ async function teardownProject(argv) {
30151
30326
  }
30152
30327
 
30153
30328
  // src/cli/teardown/handler.ts
30154
- import path91 from "node:path";
30329
+ import path92 from "node:path";
30155
30330
  function resultLooksFailed3(payload) {
30156
30331
  try {
30157
30332
  const parsed = JSON.parse(payload);
@@ -30167,7 +30342,7 @@ async function teardown(argv) {
30167
30342
  );
30168
30343
  return;
30169
30344
  }
30170
- const sourceDirectory = path91.resolve(process.cwd(), argv.dir);
30345
+ const sourceDirectory = path92.resolve(process.cwd(), argv.dir);
30171
30346
  let config2;
30172
30347
  try {
30173
30348
  config2 = loadConfig();
@@ -30245,7 +30420,7 @@ var teardown_default = {
30245
30420
  }),
30246
30421
  handler: async (argv) => {
30247
30422
  await captureEvent({ argv, event: "apitogo teardown" });
30248
- if (await isConfigV2(path92.resolve(process.cwd(), argv.dir))) {
30423
+ if (await isConfigV2(path93.resolve(process.cwd(), argv.dir))) {
30249
30424
  await teardownProject(argv);
30250
30425
  return;
30251
30426
  }
@@ -30255,7 +30430,7 @@ var teardown_default = {
30255
30430
 
30256
30431
  // src/cli/teardown/reset-command.ts
30257
30432
  init_invariant();
30258
- import path93 from "node:path";
30433
+ import path94 from "node:path";
30259
30434
 
30260
30435
  // src/cli/teardown/reset.ts
30261
30436
  init_invariant();
@@ -30378,7 +30553,7 @@ async function resetProject(argv) {
30378
30553
  const config2 = loadConfig();
30379
30554
  const result = await resetProjectV2(
30380
30555
  {
30381
- dir: path93.resolve(process.cwd(), argv.dir),
30556
+ dir: path94.resolve(process.cwd(), argv.dir),
30382
30557
  projectId: argv.projectId,
30383
30558
  yes: argv.yes === true
30384
30559
  },
@@ -30442,7 +30617,7 @@ var test_reset_default = {
30442
30617
  };
30443
30618
 
30444
30619
  // src/cli/test-sign-in/handler.ts
30445
- import path94 from "node:path";
30620
+ import path95 from "node:path";
30446
30621
  init_invariant();
30447
30622
  var TestSignInError = class extends ApitogoError {
30448
30623
  constructor(message, developerHint) {
@@ -30453,7 +30628,7 @@ var TestSignInError = class extends ApitogoError {
30453
30628
  async function resolveProjectId3(argv) {
30454
30629
  const explicit = argv.projectId?.trim();
30455
30630
  if (explicit) return explicit;
30456
- const dir = path94.resolve(process.cwd(), argv.dir ?? ".");
30631
+ const dir = path95.resolve(process.cwd(), argv.dir ?? ".");
30457
30632
  if (await isConfigV2(dir)) {
30458
30633
  const id = loadConfigV2(dir).resolved.project.id;
30459
30634
  if (id) return id;
@@ -30593,36 +30768,36 @@ function createApitogoCli(argv) {
30593
30768
  // src/cli/local-handoff.ts
30594
30769
  import { spawn as spawn4 } from "node:child_process";
30595
30770
  import { existsSync as existsSync8, realpathSync as realpathSync2 } from "node:fs";
30596
- import path95 from "node:path";
30771
+ import path96 from "node:path";
30597
30772
  var LOCAL_HANDOFF_ENV = "APITOGO_LOCAL_CLI";
30598
30773
  var PACKAGE_NAME = "@lukoweb/apitogo";
30599
30774
  var resolveProjectDir = (argv, cwd) => {
30600
30775
  for (let i = 0; i < argv.length; i++) {
30601
30776
  const arg = argv[i];
30602
30777
  const next = argv[i + 1];
30603
- if (arg === "--dir" && next) return path95.resolve(cwd, next);
30778
+ if (arg === "--dir" && next) return path96.resolve(cwd, next);
30604
30779
  if (arg?.startsWith("--dir=")) {
30605
- return path95.resolve(cwd, arg.slice("--dir=".length));
30780
+ return path96.resolve(cwd, arg.slice("--dir=".length));
30606
30781
  }
30607
30782
  }
30608
30783
  return cwd;
30609
30784
  };
30610
30785
  var findLocalCli = (projectDir, runningRoot) => {
30611
- let dir = path95.resolve(projectDir);
30786
+ let dir = path96.resolve(projectDir);
30612
30787
  let localPackageRoot;
30613
30788
  while (!localPackageRoot) {
30614
- const candidate = path95.join(dir, "node_modules", PACKAGE_NAME);
30615
- if (existsSync8(path95.join(candidate, "package.json"))) {
30789
+ const candidate = path96.join(dir, "node_modules", PACKAGE_NAME);
30790
+ if (existsSync8(path96.join(candidate, "package.json"))) {
30616
30791
  localPackageRoot = candidate;
30617
- } else if (dir === path95.dirname(dir)) {
30792
+ } else if (dir === path96.dirname(dir)) {
30618
30793
  return void 0;
30619
30794
  } else {
30620
- dir = path95.dirname(dir);
30795
+ dir = path96.dirname(dir);
30621
30796
  }
30622
30797
  }
30623
30798
  const localRoot = realpathSync2(localPackageRoot);
30624
30799
  if (localRoot === realpathSync2(runningRoot)) return void 0;
30625
- return path95.join(localRoot, "cli.js");
30800
+ return path96.join(localRoot, "cli.js");
30626
30801
  };
30627
30802
  var handoffToLocalCli = async (argv, runningRoot) => {
30628
30803
  if (process.env[LOCAL_HANDOFF_ENV] || process.env.ZUDOKU_ENV === "internal") {
@@ -30634,7 +30809,7 @@ var handoffToLocalCli = async (argv, runningRoot) => {
30634
30809
  );
30635
30810
  if (!localCli) return void 0;
30636
30811
  printDiagnosticsToConsole(
30637
- `Using the project's local ${PACKAGE_NAME} (${path95.dirname(localCli)})`
30812
+ `Using the project's local ${PACKAGE_NAME} (${path96.dirname(localCli)})`
30638
30813
  );
30639
30814
  const child = spawn4(process.execPath, [localCli, ...argv], {
30640
30815
  stdio: "inherit",