@lukoweb/apitogo 0.2.50 → 0.2.52

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
@@ -6268,7 +6268,7 @@ title: Welcome
6268
6268
 
6269
6269
  # ${name}
6270
6270
 
6271
- This page was created by \`apitogo init\`. Edit it, and add more \`.md\` or \`.mdx\` files next to it: each one becomes a page of your portal.
6271
+ Welcome to the ${name} developer portal. Here you will find guides, the API reference, and everything you need to get an API key and make your first call.
6272
6272
  `;
6273
6273
  }
6274
6274
  async function docsFromPaths(dir, requested) {
@@ -7657,7 +7657,8 @@ async function removeServicesFromManifest(state, names) {
7657
7657
  // src/config/v2/gateway-reference.ts
7658
7658
  import { readFile as readFile6 } from "node:fs/promises";
7659
7659
  import { parse } from "yaml";
7660
- var DEFAULT_KEY_HEADER = "Ocp-Apim-Subscription-Key";
7660
+ var DEFAULT_KEY_HEADER = "X-API-Key";
7661
+ var KEY_HEADER_EXTENSION = "x-apitogo-key-header";
7661
7662
  var METHODS = [
7662
7663
  "get",
7663
7664
  "put",
@@ -7770,10 +7771,13 @@ function buildReferenceSpec(specText, options) {
7770
7771
  if (Object.keys(components).length > 0) doc.components = components;
7771
7772
  else delete doc.components;
7772
7773
  doc.security = Object.keys(requirement).length > 0 ? [requirement] : [];
7773
- for (const [, item, method] of operationsOf(paths)) {
7774
+ for (const [path97, item, method] of operationsOf(paths)) {
7774
7775
  const operation = item[method];
7775
7776
  if (Array.isArray(operation.security) && operation.security.length > 0)
7776
7777
  delete operation.security;
7778
+ if (options.apiKeyRequired && !options.publicOperations.has(actionKey(method, path97)))
7779
+ operation[KEY_HEADER_EXTENSION] = options.apiKeyHeader;
7780
+ else delete operation[KEY_HEADER_EXTENSION];
7777
7781
  }
7778
7782
  return JSON.parse(hideOrigin(JSON.stringify(doc), options));
7779
7783
  }
@@ -7962,6 +7966,12 @@ function contentGlob(configDir, glob9) {
7962
7966
  const relative = path13.relative(configDir, absolute).split(path13.sep).join("/");
7963
7967
  return `${negated ? "!" : ""}/${CONTENT_LINK}/${relative}`;
7964
7968
  }
7969
+ function contentFile(configDir, file) {
7970
+ const relative = path13.relative(configDir, file);
7971
+ if (relative.startsWith("..") || path13.isAbsolute(relative))
7972
+ return file.split(path13.sep).join("/");
7973
+ return `${CONTENT_LINK}/${relative.split(path13.sep).join("/")}`;
7974
+ }
7965
7975
  var PLANS_CONSOLE_CAPABILITIES = [
7966
7976
  "catalog",
7967
7977
  "checkout",
@@ -8089,6 +8099,8 @@ function planPortal(profile, manifest) {
8089
8099
  apiBaseUrl: plans.apiBaseUrl,
8090
8100
  keysApiBaseUrl: plans.keysApiBaseUrl,
8091
8101
  billing: plans.billing,
8102
+ ...gateway?.keyHeaderName ? { keyHeader: gateway.keyHeaderName } : {},
8103
+ ...gateway?.baseUrl && serviceReady(gateway) ? { gatewayBaseUrl: gateway.baseUrl } : {},
8092
8104
  links: {
8093
8105
  // Hosted docs are linked once their pages are known (see `buildPortalWorkspace`): there is no page to
8094
8106
  // name before that, and a guessed one was a 404 on every portal whose first page is not called `introduction`.
@@ -8122,13 +8134,13 @@ function buildSiteConfig(resolved, plan2, theme, extras = {}) {
8122
8134
  },
8123
8135
  modules: {
8124
8136
  docs: { enabled: plan2.docs },
8125
- // A custom home page (`portal.landing`) is served at `/`; the build imports the component from its absolute path.
8137
+ // A custom home page (`portal.landing`) is served at `/`; the build imports the component through the content link.
8126
8138
  ...portal?.landing ? {
8127
8139
  landing: {
8128
8140
  enabled: true,
8129
8141
  path: "/",
8130
8142
  layout: "landing",
8131
- page: portal.landing.split(path13.sep).join("/")
8143
+ page: contentFile(resolved.configDir, portal.landing)
8132
8144
  }
8133
8145
  } : {},
8134
8146
  // The plans pages (pricing, choosing a plan) exist only when billing is on, and the plans service is what makes it so.
@@ -8630,7 +8642,7 @@ var FULL_SPEC = (name) => `openapi: 3.1.0
8630
8642
  info:
8631
8643
  title: ${JSON.stringify(name)}
8632
8644
  version: 1.0.0
8633
- description: A small sample API. Edit server/index.js and this file together.
8645
+ description: A sample API with a greeting and a list of items.
8634
8646
  paths:
8635
8647
  /health:
8636
8648
  get:
@@ -8719,10 +8731,14 @@ components:
8719
8731
  // src/config/v2/starter-landing.ts
8720
8732
  function starterLandingPage(options) {
8721
8733
  const name = JSON.stringify(options.name);
8722
- const plansImport = options.withPlans ? 'import { usePlansPreview } from "@lukoweb/apitogo-plugin-dev-portal-billing";\n' : "";
8723
- const plansHook = options.withPlans ? " // The plans of the project's catalog: the same ones the pricing page shows.\n const plans = usePlansPreview();\n\n" : "";
8734
+ const plansImport = options.withPlans ? 'import {\n useGatewayCall,\n usePlansPreview,\n} from "@lukoweb/apitogo-plugin-dev-portal-billing";\n' : "";
8735
+ const plansHook = options.withPlans ? " // The plans of the project's catalog: the same ones the pricing page shows.\n const plans = usePlansPreview();\n // The real gateway address and key header, so the sample works when it is pasted with a key.\n const gateway = useGatewayCall();\n\n" : "";
8736
+ const sampleUrl = options.withPlans ? '${gateway.baseUrl ?? "https://YOUR-GATEWAY"}' : "https://YOUR-GATEWAY";
8737
+ const sampleHeader = options.withPlans ? "${gateway.keyHeader}" : "X-API-Key";
8724
8738
  const plansSection = options.withPlans ? " <PlansPreviewSection plans={plans} />\n" : "";
8725
- return `import {
8739
+ return `// Your portal's home page. Edit this file (apitogo/portal/landing/LandingPage.tsx) to make it yours: everything
8740
+ // on it is public, so keep notes for yourself in comments like this one.
8741
+ import {
8726
8742
  ApiShowcaseSection,
8727
8743
  FeaturesSection,
8728
8744
  HeroSection,
@@ -8752,8 +8768,8 @@ ${plansHook} return (
8752
8768
  {
8753
8769
  filename: "Call the API",
8754
8770
  language: "bash",
8755
- code: \`$ curl https://your-api.example.com/health \\\\
8756
- -H "x-api-key: YOUR_API_KEY"
8771
+ code: \`$ curl ${sampleUrl}/health \\\\
8772
+ -H "${sampleHeader}: YOUR_API_KEY"
8757
8773
  # { "status": "ok" }\`,
8758
8774
  },
8759
8775
  ]}
@@ -8763,7 +8779,7 @@ ${plansHook} return (
8763
8779
  label: "What you get",
8764
8780
  title: "A developer portal that is ready on day one",
8765
8781
  description:
8766
- "Edit this page in apitogo/portal/landing/LandingPage.tsx to make it yours.",
8782
+ "Docs, a live API reference, self-service API keys and clear plans, all in one place.",
8767
8783
  }}
8768
8784
  features={[
8769
8785
  {
@@ -9694,7 +9710,7 @@ init_invariant();
9694
9710
 
9695
9711
  // src/cli/check/v2.ts
9696
9712
  init_apitogo_config_core();
9697
- import { readFile as readFile17 } from "node:fs/promises";
9713
+ import { readFile as readFile18 } from "node:fs/promises";
9698
9714
  import path50 from "node:path";
9699
9715
 
9700
9716
  // src/cli/platform/client/platform-api.ts
@@ -10517,8 +10533,8 @@ var PlatformApiClient = class {
10517
10533
  }
10518
10534
  };
10519
10535
  async function readFileBytes(filePath) {
10520
- const { readFile: readFile28 } = await import("node:fs/promises");
10521
- const buffer = await readFile28(filePath);
10536
+ const { readFile: readFile29 } = await import("node:fs/promises");
10537
+ const buffer = await readFile29(filePath);
10522
10538
  const arrayBuffer = new ArrayBuffer(buffer.byteLength);
10523
10539
  new Uint8Array(arrayBuffer).set(buffer);
10524
10540
  return arrayBuffer;
@@ -10615,7 +10631,7 @@ function resolveProjectId(explicit, config2) {
10615
10631
  import {
10616
10632
  access as access4,
10617
10633
  mkdir as mkdir12,
10618
- readFile as readFile14,
10634
+ readFile as readFile15,
10619
10635
  rename as rename6,
10620
10636
  rm as rm8,
10621
10637
  writeFile as writeFile15
@@ -10623,7 +10639,7 @@ import {
10623
10639
  import path49 from "node:path";
10624
10640
 
10625
10641
  // src/vite/build.ts
10626
- import { mkdir as mkdir11, readFile as readFile12, rename as rename5, rm as rm7, writeFile as writeFile13 } from "node:fs/promises";
10642
+ import { mkdir as mkdir11, readFile as readFile13, rename as rename5, rm as rm7, writeFile as writeFile13 } from "node:fs/promises";
10627
10643
  import path47 from "node:path";
10628
10644
  import { build as esbuild } from "esbuild";
10629
10645
  import { build as viteBuild, mergeConfig as mergeConfig3 } from "vite";
@@ -10771,7 +10787,7 @@ import {
10771
10787
  // package.json
10772
10788
  var package_default = {
10773
10789
  name: "@lukoweb/apitogo",
10774
- version: "0.2.50",
10790
+ version: "0.2.52",
10775
10791
  type: "module",
10776
10792
  sideEffects: [
10777
10793
  "**/*.css",
@@ -12702,7 +12718,7 @@ var SchemaManager = class {
12702
12718
  this.storeDir,
12703
12719
  `${prefixPath}-${path26.basename(filePath)}${paramsSuffix(params)}.js`
12704
12720
  );
12705
- const importKey = processedFilePath;
12721
+ const importKey = path26.posix.basename(processedFilePath);
12706
12722
  await fs3.writeFile(processedFilePath, code);
12707
12723
  const processedJsonPath = paramsSuffix(params) ? processedFilePath.replace(/\.js$/, ".json") : "";
12708
12724
  if (processedJsonPath) {
@@ -12729,6 +12745,7 @@ var SchemaManager = class {
12729
12745
  inputPath: filePath,
12730
12746
  params,
12731
12747
  importKey,
12748
+ processedFilePath,
12732
12749
  downloadUrl: this.createSchemaPath(
12733
12750
  filePath,
12734
12751
  versionPath,
@@ -12781,6 +12798,7 @@ var SchemaManager = class {
12781
12798
  inputPath: path26.resolve(this.config.__meta.rootDir, input5.input),
12782
12799
  params: input5.params,
12783
12800
  importKey: "",
12801
+ processedFilePath: "",
12784
12802
  downloadUrl: "",
12785
12803
  processedJsonPath: "",
12786
12804
  processedTime: 0
@@ -13296,7 +13314,7 @@ var viteApiPlugin = async () => {
13296
13314
  ` },`,
13297
13315
  ` schemaImports: {`,
13298
13316
  ...schemaImports.map(
13299
- (s) => ` "${s.importKey.replaceAll("\\", "\\\\")}": () => import("${s.importKey.replaceAll("\\", "/")}?d=${s.processedTime}"),`
13317
+ (s) => ` ${JSON.stringify(s.importKey)}: () => import("${s.processedFilePath.replaceAll("\\", "/")}?d=${s.processedTime}"),`
13300
13318
  ),
13301
13319
  ` },`,
13302
13320
  "}));"
@@ -13458,6 +13476,7 @@ var plugin_component_default = viteAliasPlugin;
13458
13476
  // src/vite/plugin-config.ts
13459
13477
  init_package_json();
13460
13478
  init_loader();
13479
+ import { readFile as readFile11 } from "node:fs/promises";
13461
13480
  import path32 from "node:path";
13462
13481
  import { normalizePath } from "vite";
13463
13482
  var virtualModuleId3 = "virtual:zudoku-config";
@@ -13466,18 +13485,54 @@ var browserConfigLoaderPath = path32.join(
13466
13485
  getZudokuRootDir(),
13467
13486
  "src/config/apitogo-config-loader.browser.ts"
13468
13487
  );
13488
+ var BUILD_ONLY_KEYS = /* @__PURE__ */ new Set(["page"]);
13489
+ function stripBuildOnlyPaths(value) {
13490
+ if (Array.isArray(value)) return value.map(stripBuildOnlyPaths);
13491
+ if (typeof value !== "object" || value === null) return value;
13492
+ return Object.fromEntries(
13493
+ Object.entries(value).flatMap(
13494
+ ([key, child]) => BUILD_ONLY_KEYS.has(key) && typeof child === "string" ? [] : [[key, stripBuildOnlyPaths(child)]]
13495
+ )
13496
+ );
13497
+ }
13469
13498
  function serializeClientConfig(config2) {
13470
13499
  const {
13471
13500
  plugins: _plugins,
13472
13501
  __meta: _meta,
13502
+ // Folders of the plugin packages on the build machine, for the build's Tailwind sources only.
13503
+ __pluginDirs: _pluginDirs,
13473
13504
  __resolvedModules,
13505
+ modules,
13474
13506
  ...rest
13475
13507
  } = config2;
13476
13508
  return JSON.stringify(
13477
- { ...rest, __resolvedModules },
13509
+ {
13510
+ ...rest,
13511
+ ...modules !== void 0 ? { modules: stripBuildOnlyPaths(modules) } : {},
13512
+ __resolvedModules
13513
+ },
13478
13514
  (_key, value) => typeof value === "function" ? void 0 : value
13479
13515
  );
13480
13516
  }
13517
+ function clientMetaOf(meta) {
13518
+ return {
13519
+ pricingEnabled: meta.pricingEnabled,
13520
+ authenticationEnabled: meta.authenticationEnabled,
13521
+ previewPlans: meta.previewPlans,
13522
+ gatewayBaseUrl: meta.gatewayBaseUrl
13523
+ };
13524
+ }
13525
+ async function rawConfigSource(configPath) {
13526
+ if (!configPath.toLowerCase().endsWith(".json"))
13527
+ return `import rawConfig from "${normalizePath(configPath)}";`;
13528
+ let navigation;
13529
+ try {
13530
+ navigation = JSON.parse(await readFile11(configPath, "utf8")).navigation;
13531
+ } catch {
13532
+ navigation = void 0;
13533
+ }
13534
+ return `const rawConfig = ${JSON.stringify(navigation === void 0 ? {} : { navigation })};`;
13535
+ }
13481
13536
  var viteConfigPlugin = () => {
13482
13537
  let viteConfig;
13483
13538
  return {
@@ -13510,15 +13565,10 @@ var viteConfigPlugin = () => {
13510
13565
  },
13511
13566
  viteConfig.root
13512
13567
  );
13513
- const clientMeta = {
13514
- rootDir: loadedConfig.__meta.rootDir,
13515
- pricingEnabled: loadedConfig.__meta.pricingEnabled,
13516
- authenticationEnabled: loadedConfig.__meta.authenticationEnabled,
13517
- previewPlans: loadedConfig.__meta.previewPlans,
13518
- gatewayBaseUrl: loadedConfig.__meta.gatewayBaseUrl
13519
- };
13568
+ const clientMeta = clientMetaOf(loadedConfig.__meta);
13569
+ this.addWatchFile(configPath);
13520
13570
  return `
13521
- import rawConfig from "${normalizePath(configPath)}";
13571
+ ${await rawConfigSource(configPath)}
13522
13572
  import { runPluginTransformConfig } from "@lukoweb/apitogo/plugins";
13523
13573
 
13524
13574
  const embeddedConfig = ${serializeClientConfig(loadedConfig)};
@@ -15167,7 +15217,7 @@ async function writeOutput(dir, {
15167
15217
  // src/vite/prerender/prerender.ts
15168
15218
  init_logger();
15169
15219
  init_file_exists();
15170
- import { readFile as readFile11, rm as rm6 } from "node:fs/promises";
15220
+ import { readFile as readFile12, rm as rm6 } from "node:fs/promises";
15171
15221
  import os from "node:os";
15172
15222
  import path46 from "node:path";
15173
15223
  import { pathToFileURL } from "node:url";
@@ -15443,7 +15493,7 @@ var prerender = async ({
15443
15493
  );
15444
15494
  let markdownFileInfos = [];
15445
15495
  if (await fileExists(markdownInfoPath)) {
15446
- const markdownInfoContent = await readFile11(markdownInfoPath, "utf-8");
15496
+ const markdownInfoContent = await readFile12(markdownInfoPath, "utf-8");
15447
15497
  markdownFileInfos = JSON.parse(markdownInfoContent);
15448
15498
  }
15449
15499
  if (llmsConfig.llmsTxt || llmsConfig.llmsTxtFull) {
@@ -15594,7 +15644,7 @@ var bundleSSREntry = async (options) => {
15594
15644
  const { dir, adapter, serverOutDir, serverConfigFilename, html, basePath } = options;
15595
15645
  const tempEntryPath = path47.join(dir, "__ssr-entry.ts");
15596
15646
  const packageRoot = getZudokuRootDir();
15597
- const templateContent = await readFile12(
15647
+ const templateContent = await readFile13(
15598
15648
  path47.join(packageRoot, "src/vite/ssr-templates", `${adapter}.ts`),
15599
15649
  "utf-8"
15600
15650
  );
@@ -15625,7 +15675,7 @@ init_package_json();
15625
15675
 
15626
15676
  // src/cli/init/v2-packages.ts
15627
15677
  import { existsSync as existsSync5 } from "node:fs";
15628
- import { readFile as readFile13, writeFile as writeFile14 } from "node:fs/promises";
15678
+ import { readFile as readFile14, writeFile as writeFile14 } from "node:fs/promises";
15629
15679
  import path48 from "node:path";
15630
15680
  var CORE_PACKAGES = [
15631
15681
  "@lukoweb/apitogo",
@@ -15772,7 +15822,7 @@ async function buildV2(options) {
15772
15822
  }
15773
15823
 
15774
15824
  // src/cli/check/gateway-online.ts
15775
- import { readFile as readFile15 } from "node:fs/promises";
15825
+ import { readFile as readFile16 } from "node:fs/promises";
15776
15826
  var SPEC_SEND_LIMIT = 5 * 1024 * 1024 + 64 * 1024;
15777
15827
  var issue2 = (code, path97, message, hint) => ({ code, path: path97, message, hint });
15778
15828
  function capabilityIssues(gateway, answer) {
@@ -15836,7 +15886,7 @@ async function onlineGatewayRules(gateway, projectId, api, derivedCors = []) {
15836
15886
  const specFile = gateway.specs[0];
15837
15887
  if (specFile) {
15838
15888
  try {
15839
- const text = await readFile15(specFile, "utf8");
15889
+ const text = await readFile16(specFile, "utf8");
15840
15890
  if (text.length <= SPEC_SEND_LIMIT) spec = text;
15841
15891
  } catch {
15842
15892
  }
@@ -15863,7 +15913,7 @@ async function onlineGatewayRules(gateway, projectId, api, derivedCors = []) {
15863
15913
  }
15864
15914
 
15865
15915
  // src/cli/deploy/plans-file.ts
15866
- import { readFile as readFile16 } from "node:fs/promises";
15916
+ import { readFile as readFile17 } from "node:fs/promises";
15867
15917
  import { z as z14 } from "zod";
15868
15918
  init_invariant();
15869
15919
  var PlansFileError = class extends ApitogoError {
@@ -15908,7 +15958,7 @@ var issuesOf = (error) => error.issues.map(
15908
15958
  async function readPlansFile(file) {
15909
15959
  let text;
15910
15960
  try {
15911
- text = await readFile16(file, "utf8");
15961
+ text = await readFile17(file, "utf8");
15912
15962
  } catch {
15913
15963
  throw new PlansFileError(
15914
15964
  "PLANS_FILE_UNREADABLE",
@@ -16080,7 +16130,7 @@ async function onlinePlansRules(resolved, projectId, api) {
16080
16130
  const convert = (item) => issue3(
16081
16131
  "PLANS_PLAN_INVALID",
16082
16132
  `plans.file ${item.field}`,
16083
- `${item.sku ? `plan ${item.sku}: ` : ""}${item.message}`
16133
+ withPlanName(item.message, item.sku)
16084
16134
  );
16085
16135
  return {
16086
16136
  errors: answer.errors.map(convert),
@@ -16094,12 +16144,13 @@ async function onlinePlansRules(resolved, projectId, api) {
16094
16144
  };
16095
16145
  }
16096
16146
  }
16147
+ var withPlanName = (message, sku) => !sku || message.toLowerCase().startsWith(`plan "${sku.toLowerCase()}"`) ? message : `plan ${sku}: ${message}`;
16097
16148
 
16098
16149
  // src/cli/check/v2.ts
16099
16150
  async function isConfigV2(dir) {
16100
16151
  try {
16101
16152
  return /"version"\s*:\s*2\b/.test(
16102
- await readFile17(path50.join(dir, APITOGO_CONFIG_FILENAME), "utf8")
16153
+ await readFile18(path50.join(dir, APITOGO_CONFIG_FILENAME), "utf8")
16103
16154
  );
16104
16155
  } catch {
16105
16156
  return false;
@@ -17180,7 +17231,7 @@ function formatDevPortalBackendResponse(projectId, backend) {
17180
17231
  // src/cli/platform/helpers/dev-portal-manifest.ts
17181
17232
  init_gateway_limits();
17182
17233
  import { existsSync as existsSync7 } from "node:fs";
17183
- import { access as access5, mkdir as mkdir13, readFile as readFile18, writeFile as writeFile16 } from "node:fs/promises";
17234
+ import { access as access5, mkdir as mkdir13, readFile as readFile19, writeFile as writeFile16 } from "node:fs/promises";
17184
17235
  import path56 from "node:path";
17185
17236
 
17186
17237
  // src/cli/make-config/header-pricing-nav.ts
@@ -17760,7 +17811,7 @@ function mergePublishPrerequisitesWithPlatformValidation(prerequisites, manifest
17760
17811
  async function readManifest2(siteDirectory) {
17761
17812
  const filePath = manifestFilePath(siteDirectory);
17762
17813
  if (await pathExists(filePath)) {
17763
- const raw = await readFile18(filePath, "utf8");
17814
+ const raw = await readFile19(filePath, "utf8");
17764
17815
  const config2 = JSON.parse(raw);
17765
17816
  return extractManifestFromConfig(config2);
17766
17817
  }
@@ -17771,7 +17822,7 @@ async function writeManifest2(siteDirectory, manifest) {
17771
17822
  await mkdir13(path56.dirname(filePath), { recursive: true });
17772
17823
  let config2 = {};
17773
17824
  if (await pathExists(filePath)) {
17774
- const raw = await readFile18(filePath, "utf8");
17825
+ const raw = await readFile19(filePath, "utf8");
17775
17826
  config2 = JSON.parse(raw);
17776
17827
  }
17777
17828
  const {
@@ -17790,7 +17841,7 @@ import {
17790
17841
  access as access6,
17791
17842
  appendFile,
17792
17843
  mkdir as mkdir14,
17793
- readFile as readFile19,
17844
+ readFile as readFile20,
17794
17845
  unlink,
17795
17846
  writeFile as writeFile17
17796
17847
  } from "node:fs/promises";
@@ -17896,7 +17947,7 @@ function applyEnvOverrides2(config2, env) {
17896
17947
  }
17897
17948
  async function readEnvFile(filePath) {
17898
17949
  try {
17899
- const raw = await readFile19(filePath, "utf8");
17950
+ const raw = await readFile20(filePath, "utf8");
17900
17951
  const env = {};
17901
17952
  for (const line2 of raw.split("\n")) {
17902
17953
  const trimmed = line2.trim();
@@ -18029,7 +18080,7 @@ var SECRETS_COLLECTION_INSTRUCTION = "For go-live, plans must already be in apit
18029
18080
 
18030
18081
  // src/cli/platform/helpers/dev-portal-site-validation.ts
18031
18082
  init_gateway_limits();
18032
- import { readFile as readFile20 } from "node:fs/promises";
18083
+ import { readFile as readFile21 } from "node:fs/promises";
18033
18084
  import { createRequire as createRequire2 } from "node:module";
18034
18085
  import path58 from "node:path";
18035
18086
  var cachedFallbackTs;
@@ -18207,7 +18258,7 @@ async function validateDevPortalSiteConfig(sourceDirectory, options) {
18207
18258
  let parsed;
18208
18259
  let parseFailed = false;
18209
18260
  try {
18210
- parsed = JSON.parse(await readFile20(jsonPath, "utf8"));
18261
+ parsed = JSON.parse(await readFile21(jsonPath, "utf8"));
18211
18262
  } catch (error) {
18212
18263
  parseFailed = true;
18213
18264
  issues.push({
@@ -18246,7 +18297,7 @@ async function validateDevPortalSiteConfig(sourceDirectory, options) {
18246
18297
  } else {
18247
18298
  for (const relativeFile of existingTsxFiles) {
18248
18299
  checkedFiles.push(relativeFile);
18249
- const content = await readFile20(
18300
+ const content = await readFile21(
18250
18301
  path58.join(resolvedDir, relativeFile),
18251
18302
  "utf8"
18252
18303
  );
@@ -18269,7 +18320,7 @@ async function validateDevPortalSiteConfig(sourceDirectory, options) {
18269
18320
 
18270
18321
  // src/cli/platform/helpers/npm-build.ts
18271
18322
  import { spawn as spawn2 } from "node:child_process";
18272
- import { access as access7, readFile as readFile21 } from "node:fs/promises";
18323
+ import { access as access7, readFile as readFile22 } from "node:fs/promises";
18273
18324
  import path59 from "node:path";
18274
18325
  var BUILD_LOG_TAIL_BYTES = 8192;
18275
18326
  var MIN_NODE_MAJOR = 20;
@@ -18915,7 +18966,7 @@ import { createInterface as createInterface3 } from "node:readline/promises";
18915
18966
 
18916
18967
  // src/cli/make-config/v2-edits.ts
18917
18968
  init_apitogo_config_core();
18918
- import { access as access8, mkdir as mkdir15, readFile as readFile22, writeFile as writeFile18 } from "node:fs/promises";
18969
+ import { access as access8, mkdir as mkdir15, readFile as readFile23, writeFile as writeFile18 } from "node:fs/promises";
18919
18970
  import path62 from "node:path";
18920
18971
  import { glob as glob8 } from "glob";
18921
18972
  init_invariant();
@@ -19096,10 +19147,13 @@ export default function ${pageComponentName(slug)}() {
19096
19147
  <Typography>
19097
19148
  <Heading level={1}>{title}</Heading>
19098
19149
  <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>
19150
+ {/* A note for you while you run the portal locally (\`apitogo dev\`); the deployed portal does not show it. */}
19151
+ {import.meta.env.DEV && (
19152
+ <Callout type="info" title="Where this page lives">
19153
+ Edit <code>${file}</code>. Files whose name starts with <code>_</code> are not pages, so you can keep
19154
+ shared components next to your pages.
19155
+ </Callout>
19156
+ )}
19103
19157
  </Typography>
19104
19158
  </section>
19105
19159
  );
@@ -19144,7 +19198,7 @@ async function writeDocsPage(project, input5) {
19144
19198
  "Leave out --page-update to add it."
19145
19199
  );
19146
19200
  }
19147
- const source = await readFile22(existing, "utf8");
19201
+ const source = await readFile23(existing, "utf8");
19148
19202
  const title = input5.title?.trim() || (existing.endsWith(".tsx") ? tsxPageLabel(source, existing) : titleOf(source));
19149
19203
  file = existing;
19150
19204
  action = "updated";
@@ -19233,7 +19287,7 @@ async function upsertPlan(project, plan2) {
19233
19287
  if (await exists4(plans.file)) {
19234
19288
  let raw;
19235
19289
  try {
19236
- raw = JSON.parse(await readFile22(plans.file, "utf8"));
19290
+ raw = JSON.parse(await readFile23(plans.file, "utf8"));
19237
19291
  } catch (error) {
19238
19292
  throw new ConfigEditError(
19239
19293
  `${relativeToConfig(project, plans.file)} is not valid JSON (${error.message}).`
@@ -19709,7 +19763,7 @@ var config_default = {
19709
19763
  // src/cli/create/handler.ts
19710
19764
  init_apitogo_config_core();
19711
19765
  import { execFile } from "node:child_process";
19712
- import { readFile as readFile23 } from "node:fs/promises";
19766
+ import { readFile as readFile24 } from "node:fs/promises";
19713
19767
  import path64 from "node:path";
19714
19768
  import { promisify } from "node:util";
19715
19769
  var execFileAsync = promisify(execFile);
@@ -19743,7 +19797,7 @@ async function gitHasUncommittedChanges(dir) {
19743
19797
  async function defaultName(dir) {
19744
19798
  try {
19745
19799
  const parsed = JSON.parse(
19746
- await readFile23(path64.join(dir, "package.json"), "utf8")
19800
+ await readFile24(path64.join(dir, "package.json"), "utf8")
19747
19801
  );
19748
19802
  if (typeof parsed.name === "string" && parsed.name.trim())
19749
19803
  return parsed.name.replace(/^@[^/]+\//, "");
@@ -21005,7 +21059,7 @@ async function upsertGatewayPlansFromManifest(client, config2, projectId, plans,
21005
21059
  }
21006
21060
 
21007
21061
  // src/cli/platform/helpers/openapi-gateway-servers.ts
21008
- import { mkdir as mkdir16, readFile as readFile24, writeFile as writeFile19 } from "node:fs/promises";
21062
+ import { mkdir as mkdir16, readFile as readFile25, writeFile as writeFile19 } from "node:fs/promises";
21009
21063
  import path67 from "node:path";
21010
21064
  import YAML from "yaml";
21011
21065
  var GATEWAY_URL_ENV_KEY = "APITOGO_GATEWAY_URL";
@@ -21037,7 +21091,7 @@ async function resolveProjectGatewayUrl(client, projectId) {
21037
21091
  return null;
21038
21092
  }
21039
21093
  async function readOpenApiDocument(filePath) {
21040
- const content = await readFile24(filePath, "utf8");
21094
+ const content = await readFile25(filePath, "utf8");
21041
21095
  const ext = path67.extname(filePath).toLowerCase();
21042
21096
  const parsed = ext === ".json" ? JSON.parse(content) : YAML.parse(content);
21043
21097
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
@@ -21066,7 +21120,7 @@ async function pointSiteApisAtPublishOpenApi(siteDirectory, relativeInput) {
21066
21120
  path67.resolve(siteDirectory),
21067
21121
  APITOGO_CONFIG_FILENAME2
21068
21122
  );
21069
- const raw = await readFile24(configPath, "utf8");
21123
+ const raw = await readFile25(configPath, "utf8");
21070
21124
  const config2 = JSON.parse(raw);
21071
21125
  const previousApis = config2.apis;
21072
21126
  const previousBackend = config2.backend;
@@ -21083,7 +21137,7 @@ async function pointSiteApisAtPublishOpenApi(siteDirectory, relativeInput) {
21083
21137
  `, "utf8");
21084
21138
  return {
21085
21139
  restore: async () => {
21086
- const currentRaw = await readFile24(configPath, "utf8");
21140
+ const currentRaw = await readFile25(configPath, "utf8");
21087
21141
  const current = JSON.parse(currentRaw);
21088
21142
  if (previousApis === void 0) {
21089
21143
  delete current.apis;
@@ -21118,7 +21172,7 @@ async function prepareOpenApiServersForGatewayBuild(options) {
21118
21172
  );
21119
21173
  if (!openApiPath) {
21120
21174
  try {
21121
- const raw = await readFile24(
21175
+ const raw = await readFile25(
21122
21176
  path67.join(siteDirectory, APITOGO_CONFIG_FILENAME2),
21123
21177
  "utf8"
21124
21178
  );
@@ -21192,7 +21246,7 @@ function collectManifestPublicActionKeys(gateway) {
21192
21246
  }
21193
21247
 
21194
21248
  // src/cli/platform/helpers/publish-ledger.ts
21195
- import { mkdir as mkdir17, readFile as readFile25, writeFile as writeFile20 } from "node:fs/promises";
21249
+ import { mkdir as mkdir17, readFile as readFile26, writeFile as writeFile20 } from "node:fs/promises";
21196
21250
  import path68 from "node:path";
21197
21251
  var PUBLISH_LEDGER_RELATIVE_PATH = ".apitogo/publish-state.json";
21198
21252
  function publishLedgerPath(siteDirectory) {
@@ -21201,7 +21255,7 @@ function publishLedgerPath(siteDirectory) {
21201
21255
  async function readPublishLedger(siteDirectory) {
21202
21256
  const filePath = publishLedgerPath(siteDirectory);
21203
21257
  try {
21204
- const raw = await readFile25(filePath, "utf8");
21258
+ const raw = await readFile26(filePath, "utf8");
21205
21259
  const parsed = JSON.parse(raw);
21206
21260
  if (parsed?.version !== 1 || !Array.isArray(parsed.steps)) {
21207
21261
  return null;
@@ -21330,7 +21384,7 @@ function buildPostPublishChecklist(args) {
21330
21384
  if (args.gatewayUrl) {
21331
21385
  items.push({
21332
21386
  id: "test_gateway",
21333
- label: "Call the API gateway with Ocp-Apim-Subscription-Key",
21387
+ label: "Call the API gateway with X-API-Key",
21334
21388
  required: false,
21335
21389
  completed: false,
21336
21390
  url: args.gatewayUrl
@@ -23472,7 +23526,7 @@ async function resolveProjectIdForPublish(client, config2, args, wait, progress,
23472
23526
  import path75 from "node:path";
23473
23527
 
23474
23528
  // src/cli/platform/helpers/dev-portal-site-api-url.ts
23475
- import { readdir as readdir5, readFile as readFile26, writeFile as writeFile21 } from "node:fs/promises";
23529
+ import { readdir as readdir5, readFile as readFile27, writeFile as writeFile21 } from "node:fs/promises";
23476
23530
  import path72 from "node:path";
23477
23531
  var SITE_API_BASE_URL_ENV_KEY = "VITE_APITOGO_AUTHENTICATION_API_BASE_URL";
23478
23532
  var PLACEHOLDER_HOST_MARKERS = [
@@ -23497,7 +23551,7 @@ async function readSiteApiBaseUrl(sourceDirectory) {
23497
23551
  const resolved = path72.resolve(sourceDirectory);
23498
23552
  for (const envFile of [".env", ".env.production"]) {
23499
23553
  try {
23500
- const content = await readFile26(path72.join(resolved, envFile), "utf8");
23554
+ const content = await readFile27(path72.join(resolved, envFile), "utf8");
23501
23555
  const lines = [...content.matchAll(ENV_LINE_GLOBAL_RE)];
23502
23556
  if (lines.length === 0) {
23503
23557
  continue;
@@ -23528,7 +23582,7 @@ async function patchSiteApiBaseUrl(sourceDirectory, apiBaseUrl) {
23528
23582
  for (const envFile of [".env.production", ".env"]) {
23529
23583
  const envPath = path72.join(resolved, envFile);
23530
23584
  try {
23531
- const content = await readFile26(envPath, "utf8");
23585
+ const content = await readFile27(envPath, "utf8");
23532
23586
  const withoutAssignments = content.replace(ENV_LINE_GLOBAL_RE, "").replace(/\n{3,}/g, "\n\n").trimEnd();
23533
23587
  const patched = withoutAssignments ? `${withoutAssignments}
23534
23588
  ${line2}
@@ -23608,7 +23662,7 @@ async function assertDeployableDistHasLiveApiBaseUrl(distDirectory, expectedApiB
23608
23662
  let found = false;
23609
23663
  let foundPlaceholder = false;
23610
23664
  for await (const file of walkFiles(dist)) {
23611
- const content = await readFile26(file, "utf8");
23665
+ const content = await readFile27(file, "utf8");
23612
23666
  if (content.includes(needle)) {
23613
23667
  found = true;
23614
23668
  }
@@ -26233,7 +26287,7 @@ import path79 from "node:path";
26233
26287
 
26234
26288
  // src/cli/deploy/gateway.ts
26235
26289
  import { createHash as createHash4 } from "node:crypto";
26236
- import { readFile as readFile27 } from "node:fs/promises";
26290
+ import { readFile as readFile28 } from "node:fs/promises";
26237
26291
  init_invariant();
26238
26292
  var GatewayDeployError = class extends ApitogoError {
26239
26293
  constructor(code, message, developerHint) {
@@ -26271,7 +26325,7 @@ async function readSpec(gateway) {
26271
26325
  "Add one to gateway.specs in the config."
26272
26326
  );
26273
26327
  try {
26274
- return await readFile27(file);
26328
+ return await readFile28(file);
26275
26329
  } catch {
26276
26330
  throw new GatewayDeployError(
26277
26331
  "GATEWAY_SPEC_UNREADABLE",
@@ -26619,7 +26673,9 @@ async function deployGateway(resolved, projectId, deps, options = {}) {
26619
26673
  baseUrl,
26620
26674
  capabilities: capabilities.capabilities,
26621
26675
  openapiUrl: status2.openApiPath ?? void 0,
26622
- openapiHash: status2.openApiHash ?? status2.specSha256 ?? void 0
26676
+ openapiHash: status2.openApiHash ?? status2.specSha256 ?? void 0,
26677
+ // The portal's keys page and API page show this header (API-120).
26678
+ keyHeaderName: resolved.gateway?.policies.access?.apiKeyHeader ?? DEFAULT_KEY_HEADER
26623
26679
  })
26624
26680
  );
26625
26681
  }
@@ -1,5 +1,7 @@
1
1
  import { HTTPSnippet } from "@zudoku/httpsnippet";
2
2
  import type { OperationsFragmentFragment } from "../graphql/graphql.js";
3
+ export declare const KEY_HEADER_EXTENSION = "x-apitogo-key-header";
4
+ export declare const KEY_PLACEHOLDER = "YOUR_API_KEY";
3
5
  export declare const createHttpSnippet: ({ operation, selectedServer, exampleBody, }: {
4
6
  operation: OperationsFragmentFragment;
5
7
  selectedServer: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lukoweb/apitogo",
3
- "version": "0.2.50",
3
+ "version": "0.2.52",
4
4
  "type": "module",
5
5
  "sideEffects": [
6
6
  "**/*.css",
@@ -105,7 +105,7 @@ export const FULL_SPEC = (name: string) => `openapi: 3.1.0
105
105
  info:
106
106
  title: ${JSON.stringify(name)}
107
107
  version: 1.0.0
108
- description: A small sample API. Edit server/index.js and this file together.
108
+ description: A sample API with a greeting and a list of items.
109
109
  paths:
110
110
  /health:
111
111
  get: