@lukoweb/apitogo 0.1.143 → 0.1.146

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
@@ -836,7 +836,7 @@ import { stat } from "node:fs/promises";
836
836
  var fileExists;
837
837
  var init_file_exists = __esm({
838
838
  "src/config/file-exists.ts"() {
839
- fileExists = (path73) => stat(path73).then(() => true).catch(() => false);
839
+ fileExists = (path74) => stat(path74).then(() => true).catch(() => false);
840
840
  }
841
841
  });
842
842
 
@@ -5845,7 +5845,7 @@ import {
5845
5845
  // package.json
5846
5846
  var package_default = {
5847
5847
  name: "@lukoweb/apitogo",
5848
- version: "0.1.143",
5848
+ version: "0.1.146",
5849
5849
  type: "module",
5850
5850
  sideEffects: [
5851
5851
  "**/*.css",
@@ -6624,14 +6624,14 @@ var flattenAllOf = (schema2) => {
6624
6624
  };
6625
6625
 
6626
6626
  // src/lib/util/traverse.ts
6627
- var traverse = (specification, transform, path73 = []) => {
6628
- const transformed = transform(specification, path73);
6627
+ var traverse = (specification, transform, path74 = []) => {
6628
+ const transformed = transform(specification, path74);
6629
6629
  if (typeof transformed !== "object" || transformed === null) {
6630
6630
  return transformed;
6631
6631
  }
6632
6632
  const result = Array.isArray(transformed) ? [] : {};
6633
6633
  for (const [key, value] of Object.entries(transformed)) {
6634
- const currentPath = [...path73, key];
6634
+ const currentPath = [...path74, key];
6635
6635
  if (Array.isArray(value)) {
6636
6636
  result[key] = value.map(
6637
6637
  (item, index) => typeof item === "object" && item != null ? traverse(item, transform, [...currentPath, index.toString()]) : item
@@ -6659,9 +6659,9 @@ var resolveLocalRef = (schema2, ref) => {
6659
6659
  if (schemaCache?.has(ref)) {
6660
6660
  return schemaCache.get(ref);
6661
6661
  }
6662
- const path73 = ref.split("/").slice(1);
6662
+ const path74 = ref.split("/").slice(1);
6663
6663
  let current = schema2;
6664
- for (const segment of path73) {
6664
+ for (const segment of path74) {
6665
6665
  if (!current || typeof current !== "object") {
6666
6666
  current = null;
6667
6667
  }
@@ -6680,7 +6680,7 @@ var dereference = async (schema2, resolvers = []) => {
6680
6680
  }
6681
6681
  const cloned = structuredClone(schema2);
6682
6682
  const visited = /* @__PURE__ */ new Set();
6683
- const resolve = async (current, path73) => {
6683
+ const resolve = async (current, path74) => {
6684
6684
  if (isIndexableObject(current)) {
6685
6685
  if (visited.has(current)) {
6686
6686
  return CIRCULAR_REF;
@@ -6688,7 +6688,7 @@ var dereference = async (schema2, resolvers = []) => {
6688
6688
  visited.add(current);
6689
6689
  if (Array.isArray(current)) {
6690
6690
  for (let index = 0; index < current.length; index++) {
6691
- current[index] = await resolve(current[index], `${path73}/${index}`);
6691
+ current[index] = await resolve(current[index], `${path74}/${index}`);
6692
6692
  }
6693
6693
  } else {
6694
6694
  if ("$ref" in current && typeof current.$ref === "string") {
@@ -6699,13 +6699,13 @@ var dereference = async (schema2, resolvers = []) => {
6699
6699
  for (const resolver of resolvers) {
6700
6700
  const resolved = await resolver($ref);
6701
6701
  if (resolved) {
6702
- result2 = await resolve(resolved, path73);
6702
+ result2 = await resolve(resolved, path74);
6703
6703
  break;
6704
6704
  }
6705
6705
  }
6706
6706
  if (result2 === void 0) {
6707
6707
  const resolved = await resolveLocalRef(cloned, $ref);
6708
- result2 = await resolve(resolved, path73);
6708
+ result2 = await resolve(resolved, path74);
6709
6709
  }
6710
6710
  if (hasSiblings) {
6711
6711
  if (result2 === CIRCULAR_REF) {
@@ -6718,7 +6718,7 @@ var dereference = async (schema2, resolvers = []) => {
6718
6718
  return result2;
6719
6719
  }
6720
6720
  for (const key in current) {
6721
- current[key] = await resolve(current[key], `${path73}/${key}`);
6721
+ current[key] = await resolve(current[key], `${path74}/${key}`);
6722
6722
  }
6723
6723
  }
6724
6724
  visited.delete(current);
@@ -6757,9 +6757,9 @@ var upgradeSchema = (schema2) => {
6757
6757
  }
6758
6758
  return sub;
6759
6759
  });
6760
- schema2 = traverse(schema2, (sub, path73) => {
6760
+ schema2 = traverse(schema2, (sub, path74) => {
6761
6761
  if (sub.example !== void 0) {
6762
- if (isSchemaPath(path73 ?? [])) {
6762
+ if (isSchemaPath(path74 ?? [])) {
6763
6763
  sub.examples = [sub.example];
6764
6764
  } else {
6765
6765
  sub.examples = {
@@ -6772,11 +6772,11 @@ var upgradeSchema = (schema2) => {
6772
6772
  }
6773
6773
  return sub;
6774
6774
  });
6775
- schema2 = traverse(schema2, (schema3, path73) => {
6775
+ schema2 = traverse(schema2, (schema3, path74) => {
6776
6776
  if (schema3.type === "object" && schema3.properties !== void 0) {
6777
- const parentPath = path73?.slice(0, -1);
6777
+ const parentPath = path74?.slice(0, -1);
6778
6778
  const isMultipart = parentPath?.some((segment, index) => {
6779
- return segment === "content" && path73?.[index + 1] === "multipart/form-data";
6779
+ return segment === "content" && path74?.[index + 1] === "multipart/form-data";
6780
6780
  });
6781
6781
  if (isMultipart) {
6782
6782
  const entries = Object.entries(schema3.properties);
@@ -6790,8 +6790,8 @@ var upgradeSchema = (schema2) => {
6790
6790
  }
6791
6791
  return schema3;
6792
6792
  });
6793
- schema2 = traverse(schema2, (schema3, path73) => {
6794
- if (path73?.includes("content") && path73.includes("application/octet-stream")) {
6793
+ schema2 = traverse(schema2, (schema3, path74) => {
6794
+ if (path74?.includes("content") && path74.includes("application/octet-stream")) {
6795
6795
  return {};
6796
6796
  }
6797
6797
  if (schema3.type === "string" && schema3.format === "binary") {
@@ -6817,11 +6817,11 @@ var upgradeSchema = (schema2) => {
6817
6817
  }
6818
6818
  return sub;
6819
6819
  });
6820
- schema2 = traverse(schema2, (schema3, path73) => {
6820
+ schema2 = traverse(schema2, (schema3, path74) => {
6821
6821
  if (schema3.type === "string" && schema3.format === "byte") {
6822
- const parentPath = path73?.slice(0, -1);
6822
+ const parentPath = path74?.slice(0, -1);
6823
6823
  const contentMediaType = parentPath?.find(
6824
- (_, index) => path73?.[index - 1] === "content"
6824
+ (_, index) => path74?.[index - 1] === "content"
6825
6825
  );
6826
6826
  return {
6827
6827
  type: "string",
@@ -6833,7 +6833,7 @@ var upgradeSchema = (schema2) => {
6833
6833
  });
6834
6834
  return schema2;
6835
6835
  };
6836
- function isSchemaPath(path73) {
6836
+ function isSchemaPath(path74) {
6837
6837
  const schemaLocations = [
6838
6838
  ["components", "schemas"],
6839
6839
  "properties",
@@ -6846,10 +6846,10 @@ function isSchemaPath(path73) {
6846
6846
  ];
6847
6847
  return schemaLocations.some((location) => {
6848
6848
  if (Array.isArray(location)) {
6849
- return location.every((segment, index) => path73[index] === segment);
6849
+ return location.every((segment, index) => path74[index] === segment);
6850
6850
  }
6851
- return path73.includes(location);
6852
- }) || path73.includes("schema") || path73.some((segment) => segment.endsWith("Schema"));
6851
+ return path74.includes(location);
6852
+ }) || path74.includes("schema") || path74.some((segment) => segment.endsWith("Schema"));
6853
6853
  }
6854
6854
 
6855
6855
  // src/lib/oas/parser/index.ts
@@ -6931,13 +6931,13 @@ var OPENAPI_PROPS = /* @__PURE__ */ new Set([
6931
6931
  "anyOf",
6932
6932
  "oneOf"
6933
6933
  ]);
6934
- var handleCircularRefs = (obj, currentPath = /* @__PURE__ */ new WeakSet(), refs = /* @__PURE__ */ new WeakMap(), path73 = [], currentRefPaths = /* @__PURE__ */ new Set()) => {
6934
+ var handleCircularRefs = (obj, currentPath = /* @__PURE__ */ new WeakSet(), refs = /* @__PURE__ */ new WeakMap(), path74 = [], currentRefPaths = /* @__PURE__ */ new Set()) => {
6935
6935
  if (obj === null || typeof obj !== "object") return obj;
6936
6936
  const refPath = obj.__$ref;
6937
6937
  const isCircular = currentPath.has(obj) || typeof refPath === "string" && currentRefPaths.has(refPath);
6938
6938
  if (isCircular) {
6939
6939
  if (typeof refPath === "string") return SCHEMA_REF_PREFIX + refPath;
6940
- const circularProp = path73.find((p) => !OPENAPI_PROPS.has(p)) || path73[0];
6940
+ const circularProp = path74.find((p) => !OPENAPI_PROPS.has(p)) || path74[0];
6941
6941
  return [CIRCULAR_REF, circularProp].filter(Boolean).join(":");
6942
6942
  }
6943
6943
  if (refs.has(obj)) return refs.get(obj);
@@ -6947,7 +6947,7 @@ var handleCircularRefs = (obj, currentPath = /* @__PURE__ */ new WeakSet(), refs
6947
6947
  value,
6948
6948
  currentPath,
6949
6949
  refs,
6950
- [...path73, key],
6950
+ [...path74, key],
6951
6951
  currentRefPaths
6952
6952
  );
6953
6953
  const result = Array.isArray(obj) ? obj.map((item, i) => recurse(item, i.toString())) : Object.fromEntries(
@@ -6982,7 +6982,7 @@ var resolveExtensions = (obj) => Object.fromEntries(
6982
6982
  var getAllTags = (schema2) => {
6983
6983
  const rootTags = schema2.tags ?? [];
6984
6984
  const operations = Object.values(schema2.paths ?? {}).flatMap(
6985
- (path73) => HttpMethods.map((k) => path73?.[k]).filter((op) => op != null)
6985
+ (path74) => HttpMethods.map((k) => path74?.[k]).filter((op) => op != null)
6986
6986
  );
6987
6987
  const operationTags = new Set(operations.flatMap((op) => op.tags ?? []));
6988
6988
  const hasUntaggedOperations = operations.some(
@@ -7037,7 +7037,7 @@ var getAllSlugs = (ops, schemaTags = []) => {
7037
7037
  var getOperationSlugKey = (op) => [op.path, op.method, op.operationId, op.summary].filter(Boolean).join("-");
7038
7038
  var getAllOperations = (paths) => {
7039
7039
  const operations = Object.entries(paths ?? {}).flatMap(
7040
- ([path73, value]) => HttpMethods.flatMap((method) => {
7040
+ ([path74, value]) => HttpMethods.flatMap((method) => {
7041
7041
  if (!value?.[method]) return [];
7042
7042
  const operation = value[method];
7043
7043
  const pathParameters = value.parameters ?? [];
@@ -7057,7 +7057,7 @@ var getAllOperations = (paths) => {
7057
7057
  return {
7058
7058
  ...operation,
7059
7059
  method,
7060
- path: path73,
7060
+ path: path74,
7061
7061
  parameters,
7062
7062
  servers,
7063
7063
  tags: operation.tags ?? []
@@ -7415,8 +7415,8 @@ var Schema = builder.objectRef("Schema").implement({
7415
7415
  }),
7416
7416
  paths: t.field({
7417
7417
  type: [PathItem],
7418
- resolve: (root) => Object.entries(root.paths ?? {}).map(([path73, value]) => ({
7419
- path: path73,
7418
+ resolve: (root) => Object.entries(root.paths ?? {}).map(([path74, value]) => ({
7419
+ path: path74,
7420
7420
  // biome-ignore lint/style/noNonNullAssertion: value is guaranteed to be defined
7421
7421
  methods: Object.keys(value)
7422
7422
  }))
@@ -7581,7 +7581,7 @@ init_joinUrl();
7581
7581
 
7582
7582
  // src/vite/api/schema-codegen.ts
7583
7583
  var unescapeJsonPointer = (uri) => decodeURIComponent(uri.replace(/~1/g, "/").replace(/~0/g, "~"));
7584
- var getSegmentsFromPath = (path73) => path73.split("/").slice(1).map(unescapeJsonPointer);
7584
+ var getSegmentsFromPath = (path74) => path74.split("/").slice(1).map(unescapeJsonPointer);
7585
7585
  var createLocalRefMap = (obj) => {
7586
7586
  const refMap = /* @__PURE__ */ new Map();
7587
7587
  const siblingsMap = /* @__PURE__ */ new Map();
@@ -7612,16 +7612,16 @@ var replaceMarkers = (code, mergedRefs) => code.replace(/"__refMap:(.*?)"/g, '__
7612
7612
  /"__refMap\+Siblings:(.*?)"/g,
7613
7613
  (_, key) => mergedRefs.get(key) ?? `__refMap["${key}"]`
7614
7614
  );
7615
- var lookup = (schema2, path73, filePath) => {
7616
- const parts = getSegmentsFromPath(path73);
7615
+ var lookup = (schema2, path74, filePath) => {
7616
+ const parts = getSegmentsFromPath(path74);
7617
7617
  let val = schema2;
7618
7618
  for (const part of parts) {
7619
7619
  while (val.$ref?.startsWith("#/")) {
7620
- val = val.$ref === path73 ? val : lookup(schema2, val.$ref, filePath);
7620
+ val = val.$ref === path74 ? val : lookup(schema2, val.$ref, filePath);
7621
7621
  }
7622
7622
  if (val[part] === void 0) {
7623
7623
  throw new Error(
7624
- `Error in ${filePath ?? "code generation"}: Could not find path segment ${part} in path: ${path73}`
7624
+ `Error in ${filePath ?? "code generation"}: Could not find path segment ${part} in path: ${path74}`
7625
7625
  );
7626
7626
  }
7627
7627
  val = val[part];
@@ -7866,8 +7866,8 @@ var SchemaManager = class {
7866
7866
  }
7867
7867
  }
7868
7868
  };
7869
- getLatestSchema = (path73) => this.processedSchemas[path73]?.at(0);
7870
- getSchemasForPath = (path73) => this.processedSchemas[path73];
7869
+ getLatestSchema = (path74) => this.processedSchemas[path74]?.at(0);
7870
+ getSchemasForPath = (path74) => this.processedSchemas[path74];
7871
7871
  getSchemaImports = () => Object.values(this.processedSchemas).flat().filter((s) => s.importKey);
7872
7872
  getUrlToFilePathMap = () => {
7873
7873
  const map = /* @__PURE__ */ new Map();
@@ -10305,14 +10305,14 @@ async function generateSitemap({
10305
10305
 
10306
10306
  // src/vite/prerender/utils.ts
10307
10307
  init_joinUrl();
10308
- var resolveRoutePath = (path73) => {
10309
- const segments = path73.split("/");
10308
+ var resolveRoutePath = (path74) => {
10309
+ const segments = path74.split("/");
10310
10310
  if (segments.some((s) => s.startsWith(":") && !s.endsWith("?"))) {
10311
10311
  return void 0;
10312
10312
  }
10313
10313
  return segments.filter((s) => !s.startsWith(":")).join("/") || void 0;
10314
10314
  };
10315
- var isSkipped = (path73) => path73.includes("*") || /^\d+$/.test(path73);
10315
+ var isSkipped = (path74) => path74.includes("*") || /^\d+$/.test(path74);
10316
10316
  var resolveRoutes = (routes, parentPath = "") => routes.flatMap((route) => {
10317
10317
  if (route.path && isSkipped(route.path)) return [];
10318
10318
  const routePath = route.path ? resolveRoutePath(route.path) : void 0;
@@ -10944,8 +10944,8 @@ var PlatformApiClient = class {
10944
10944
  constructor(config2) {
10945
10945
  this.config = config2;
10946
10946
  }
10947
- url(path73) {
10948
- return `${this.config.apiUrl}${path73.startsWith("/") ? path73 : `/${path73}`}`;
10947
+ url(path74) {
10948
+ return `${this.config.apiUrl}${path74.startsWith("/") ? path74 : `/${path74}`}`;
10949
10949
  }
10950
10950
  headers(extra) {
10951
10951
  return {
@@ -10955,9 +10955,9 @@ var PlatformApiClient = class {
10955
10955
  ...extra
10956
10956
  };
10957
10957
  }
10958
- async request(method, path73, init4) {
10958
+ async request(method, path74, init4) {
10959
10959
  const response = await fetchWithRetry(
10960
- this.url(path73),
10960
+ this.url(path74),
10961
10961
  {
10962
10962
  method,
10963
10963
  ...init4,
@@ -11169,15 +11169,15 @@ var PlatformApiClient = class {
11169
11169
  }
11170
11170
  );
11171
11171
  }
11172
- deleteDevPortalPage(projectId, path73) {
11173
- const query = new URLSearchParams({ path: path73 });
11172
+ deleteDevPortalPage(projectId, path74) {
11173
+ const query = new URLSearchParams({ path: path74 });
11174
11174
  return this.request(
11175
11175
  "DELETE",
11176
11176
  `/api/v1/projects/${projectId}/dev-portal/pages/files?${query.toString()}`
11177
11177
  );
11178
11178
  }
11179
- renameDevPortalPage(projectId, path73, newName) {
11180
- const query = new URLSearchParams({ path: path73 });
11179
+ renameDevPortalPage(projectId, path74, newName) {
11180
+ const query = new URLSearchParams({ path: path74 });
11181
11181
  return this.request(
11182
11182
  "POST",
11183
11183
  `/api/v1/projects/${projectId}/dev-portal/pages/files/rename?${query.toString()}`,
@@ -11293,8 +11293,8 @@ var PlatformApiClient = class {
11293
11293
  * the project-less endpoint is used; `planTier` overrides the tier used for paid-plan checks.
11294
11294
  */
11295
11295
  validateGatewayPlans(plans, options = {}) {
11296
- const path73 = options.projectId ? `/api/v1/projects/${options.projectId}/gateway/plans/validate` : "/api/v1/gateway/plans/validate";
11297
- return this.request("POST", path73, {
11296
+ const path74 = options.projectId ? `/api/v1/projects/${options.projectId}/gateway/plans/validate` : "/api/v1/gateway/plans/validate";
11297
+ return this.request("POST", path74, {
11298
11298
  headers: { "Content-Type": "application/json" },
11299
11299
  body: JSON.stringify({ plans, planTier: options.planTier })
11300
11300
  });
@@ -11395,8 +11395,8 @@ var PlatformApiClient = class {
11395
11395
  }
11396
11396
  };
11397
11397
  async function readFileBytes(filePath) {
11398
- const { readFile: readFile20 } = await import("node:fs/promises");
11399
- const buffer = await readFile20(filePath);
11398
+ const { readFile: readFile21 } = await import("node:fs/promises");
11399
+ const buffer = await readFile21(filePath);
11400
11400
  const arrayBuffer = new ArrayBuffer(buffer.byteLength);
11401
11401
  new Uint8Array(arrayBuffer).set(buffer);
11402
11402
  return arrayBuffer;
@@ -12818,6 +12818,13 @@ function mergePlansBySku2(existing, patch) {
12818
12818
  }
12819
12819
  return Array.from(bySku.values());
12820
12820
  }
12821
+ function resolveBackendSourceDirectory(siteDirectory, sourceDirectory) {
12822
+ const trimmed = sourceDirectory?.trim();
12823
+ if (!trimmed) {
12824
+ return void 0;
12825
+ }
12826
+ return path37.resolve(siteDirectory, trimmed);
12827
+ }
12821
12828
  function resolveBackendOpenApiPath(openApiPath, options) {
12822
12829
  const trimmed = openApiPath?.trim();
12823
12830
  if (!trimmed) {
@@ -15370,8 +15377,8 @@ async function pathExists3(filePath) {
15370
15377
  }
15371
15378
  async function directoryHasEntries(dir) {
15372
15379
  try {
15373
- const { readdir: readdir4 } = await import("node:fs/promises");
15374
- const entries = await readdir4(dir);
15380
+ const { readdir: readdir5 } = await import("node:fs/promises");
15381
+ const entries = await readdir5(dir);
15375
15382
  return entries.length > 0;
15376
15383
  } catch {
15377
15384
  return false;
@@ -17356,8 +17363,8 @@ function normalizeActionKey(actionKey) {
17356
17363
  const trimmed = actionKey.trim();
17357
17364
  if (trimmed.includes(":")) {
17358
17365
  const [method2, ...pathParts] = trimmed.split(":");
17359
- const path74 = pathParts.join(":").trim();
17360
- return `${method2?.toLowerCase()}:${path74.startsWith("/") ? path74 : `/${path74}`}`;
17366
+ const path75 = pathParts.join(":").trim();
17367
+ return `${method2?.toLowerCase()}:${path75.startsWith("/") ? path75 : `/${path75}`}`;
17361
17368
  }
17362
17369
  const spaceIndex = trimmed.indexOf(" ");
17363
17370
  if (spaceIndex <= 0) {
@@ -17366,8 +17373,8 @@ function normalizeActionKey(actionKey) {
17366
17373
  );
17367
17374
  }
17368
17375
  const method = trimmed.slice(0, spaceIndex).trim().toLowerCase();
17369
- const path73 = trimmed.slice(spaceIndex + 1).trim();
17370
- return `${method}:${path73.startsWith("/") ? path73 : `/${path73}`}`;
17376
+ const path74 = trimmed.slice(spaceIndex + 1).trim();
17377
+ return `${method}:${path74.startsWith("/") ? path74 : `/${path74}`}`;
17371
17378
  }
17372
17379
  async function applyGatewayPublicRoutes(client, projectId, routes, options) {
17373
17380
  const applied = [];
@@ -17950,7 +17957,10 @@ async function prepareOpenApiServersForGatewayBuild(options) {
17950
17957
  options.manifest?.backend?.openApiPath,
17951
17958
  {
17952
17959
  siteDirectory,
17953
- backendSourceDirectory: options.manifest?.backend?.sourceDirectory
17960
+ backendSourceDirectory: resolveBackendSourceDirectory(
17961
+ siteDirectory,
17962
+ options.manifest?.backend?.sourceDirectory
17963
+ )
17954
17964
  }
17955
17965
  );
17956
17966
  if (!openApiPath) {
@@ -17985,8 +17995,8 @@ function normalizeActionKeyFormat(actionKey) {
17985
17995
  const trimmed = actionKey.trim();
17986
17996
  if (trimmed.includes(":")) {
17987
17997
  const [method2, ...pathParts] = trimmed.split(":");
17988
- const path74 = pathParts.join(":").trim();
17989
- return `${method2.toLowerCase()}:${path74.startsWith("/") ? path74 : `/${path74}`}`;
17998
+ const path75 = pathParts.join(":").trim();
17999
+ return `${method2.toLowerCase()}:${path75.startsWith("/") ? path75 : `/${path75}`}`;
17990
18000
  }
17991
18001
  const spaceIndex = trimmed.indexOf(" ");
17992
18002
  if (spaceIndex <= 0) {
@@ -17995,8 +18005,8 @@ function normalizeActionKeyFormat(actionKey) {
17995
18005
  );
17996
18006
  }
17997
18007
  const method = trimmed.slice(0, spaceIndex).trim().toLowerCase();
17998
- const path73 = trimmed.slice(spaceIndex + 1).trim();
17999
- return `${method}:${path73.startsWith("/") ? path73 : `/${path73}`}`;
18008
+ const path74 = trimmed.slice(spaceIndex + 1).trim();
18009
+ return `${method}:${path74.startsWith("/") ? path74 : `/${path74}`}`;
18000
18010
  }
18001
18011
  function normalizePublicRoute(route) {
18002
18012
  const trimmed = route.trim();
@@ -18467,11 +18477,6 @@ function isPollableJobValue(value) {
18467
18477
 
18468
18478
  // src/cli/platform/helpers/warm-pool.ts
18469
18479
  var WARM_POOL_CAPACITY_TEMPORARILY_UNAVAILABLE = "WARM_POOL_CAPACITY_TEMPORARILY_UNAVAILABLE";
18470
- var COLD_MODULE_INFRA_RESOURCE_TYPES = /* @__PURE__ */ new Set([
18471
- "AzureProjectInfrastructure",
18472
- "DevPortalInfrastructure",
18473
- "BackendInfrastructure"
18474
- ]);
18475
18480
  var WARM_POOL_CREATE_RETRY_BUDGET_MS = 10 * 60 * 1e3;
18476
18481
  function sleep3(ms) {
18477
18482
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -18499,16 +18504,6 @@ function isWarmPoolInfrastructureTerminal(project) {
18499
18504
  const status2 = project.infrastructureStatus?.toLowerCase() ?? "";
18500
18505
  return status2 === "ready" || status2 === "failed" || status2 === "deleting";
18501
18506
  }
18502
- function shouldSkipColdModuleInfrastructureWait(project, infraStatus) {
18503
- const resourceType = infraStatus?.resourceType;
18504
- if (resourceType && COLD_MODULE_INFRA_RESOURCE_TYPES.has(resourceType)) {
18505
- return false;
18506
- }
18507
- if (resourceType === "WarmPoolBinding") {
18508
- return true;
18509
- }
18510
- return isWarmPoolInfrastructureReady(project);
18511
- }
18512
18507
  function resolvePortalBackendFqdn(project) {
18513
18508
  const portalApiUrl = project.portalApiUrl?.trim();
18514
18509
  if (!portalApiUrl) {
@@ -20058,12 +20053,6 @@ async function ensureModuleProvisioned(client, config2, projectId, moduleType, w
20058
20053
  if (isModuleProvisioned(project, moduleType)) {
20059
20054
  return;
20060
20055
  }
20061
- if (isWarmPoolInfrastructureReady(project)) {
20062
- const infra = await client.getInfrastructureStatus(projectId, moduleType);
20063
- if (shouldSkipColdModuleInfrastructureWait(project, infra) || isTerminalInfrastructureStatus(infra.status)) {
20064
- return;
20065
- }
20066
- }
20067
20056
  await progress?.onStep(`Activating module ${moduleType}`);
20068
20057
  try {
20069
20058
  await handleActivateModule(
@@ -20087,12 +20076,6 @@ async function ensureModuleProvisioned(client, config2, projectId, moduleType, w
20087
20076
  if (isModuleProvisioned(project, moduleType)) {
20088
20077
  return;
20089
20078
  }
20090
- if (isWarmPoolInfrastructureReady(project)) {
20091
- const infra = await client.getInfrastructureStatus(projectId, moduleType);
20092
- if (shouldSkipColdModuleInfrastructureWait(project, infra) || isTerminalInfrastructureStatus(infra.status)) {
20093
- return;
20094
- }
20095
- }
20096
20079
  const waitedJson = await handleWaitForJob(
20097
20080
  client,
20098
20081
  { ...config2, defaultProjectId: projectId },
@@ -21475,7 +21458,10 @@ async function runApplyFromSiteDirectory(client, config2, args, progress) {
21475
21458
  );
21476
21459
  const skipBackend = skipBackendDecision.skip;
21477
21460
  const backendConfig = manifest.backend;
21478
- const backendSourceDirectory = backendConfig?.sourceDirectory?.trim();
21461
+ const backendSourceDirectory = resolveBackendSourceDirectory(
21462
+ args.sourceDirectory,
21463
+ backendConfig?.sourceDirectory
21464
+ );
21479
21465
  const hasBackendSource = Boolean(backendSourceDirectory);
21480
21466
  let backendDeploySucceeded = false;
21481
21467
  let backendDeployFailed = false;
@@ -22538,24 +22524,123 @@ var deploy_default = {
22538
22524
  };
22539
22525
 
22540
22526
  // src/cli/init/handler.ts
22541
- import path66 from "node:path";
22527
+ import path67 from "node:path";
22542
22528
 
22543
22529
  // src/cli/scaffold/run-scaffold-discovery.ts
22544
- import { access as access10, readFile as readFile19, writeFile as writeFile18 } from "node:fs/promises";
22545
- import path65 from "node:path";
22530
+ import { access as access10, readFile as readFile20, writeFile as writeFile18 } from "node:fs/promises";
22531
+ import path66 from "node:path";
22532
+
22533
+ // src/cli/scaffold/detect-backend.ts
22534
+ import { readdir as readdir3, readFile as readFile18 } from "node:fs/promises";
22535
+ import path64 from "node:path";
22536
+ var DEFAULT_RUNTIME_VERSION = {
22537
+ dotnet: "DOTNET_10",
22538
+ nodejs: "NODE_22_LTS",
22539
+ python: "PYTHON_312"
22540
+ };
22541
+ var PYTHON_MARKERS = ["pyproject.toml", "requirements.txt", "Pipfile"];
22542
+ async function listFiles(directory) {
22543
+ try {
22544
+ const entries = await readdir3(directory, { withFileTypes: true });
22545
+ return entries.filter((e) => e.isFile()).map((e) => e.name);
22546
+ } catch {
22547
+ return [];
22548
+ }
22549
+ }
22550
+ async function readText(filePath) {
22551
+ try {
22552
+ return await readFile18(filePath, "utf8");
22553
+ } catch {
22554
+ return void 0;
22555
+ }
22556
+ }
22557
+ function dotnetVersionFromCsproj(content) {
22558
+ const match = content?.match(/<TargetFrameworks?>\s*net(\d+)\.\d/i);
22559
+ const major = match?.[1];
22560
+ if (major === "8" || major === "9" || major === "10") {
22561
+ return `DOTNET_${major}`;
22562
+ }
22563
+ return DEFAULT_RUNTIME_VERSION.dotnet;
22564
+ }
22565
+ function nodeVersionFromEngines(engines) {
22566
+ const range = engines && typeof engines === "object" && !Array.isArray(engines) ? engines.node : void 0;
22567
+ if (typeof range === "string" && /(^|[^\d])24/.test(range)) {
22568
+ return "NODE_24_LTS";
22569
+ }
22570
+ return DEFAULT_RUNTIME_VERSION.nodejs;
22571
+ }
22572
+ function pythonVersionFromText(content) {
22573
+ const match = content?.match(/3\.(1[0-4])/);
22574
+ return match ? `PYTHON_3${match[1]}` : DEFAULT_RUNTIME_VERSION.python;
22575
+ }
22576
+ function isRunnableNodePackage(pkg) {
22577
+ const scripts = pkg.scripts && typeof pkg.scripts === "object" ? pkg.scripts : {};
22578
+ return typeof scripts.start === "string" || typeof pkg.main === "string";
22579
+ }
22580
+ async function detectParentBackend(siteDirectory) {
22581
+ const site = path64.resolve(siteDirectory);
22582
+ const directory = path64.dirname(site);
22583
+ if (directory === site) {
22584
+ return void 0;
22585
+ }
22586
+ const files = await listFiles(directory);
22587
+ const toResult = (runtime, runtimeVersion, marker) => ({
22588
+ directory,
22589
+ sourceDirectory: path64.relative(site, directory).split(path64.sep).join("/") || ".",
22590
+ runtime,
22591
+ runtimeVersion,
22592
+ marker
22593
+ });
22594
+ const csproj = files.find((f) => f.endsWith(".csproj"));
22595
+ const solution = files.find((f) => /\.slnx?$/.test(f));
22596
+ if (csproj || solution) {
22597
+ const content = csproj ? await readText(path64.join(directory, csproj)) : void 0;
22598
+ return toResult(
22599
+ "dotnet",
22600
+ dotnetVersionFromCsproj(content),
22601
+ csproj ?? solution
22602
+ );
22603
+ }
22604
+ if (files.includes("package.json")) {
22605
+ const raw = await readText(path64.join(directory, "package.json"));
22606
+ try {
22607
+ const pkg = JSON.parse(raw ?? "");
22608
+ if (isRunnableNodePackage(pkg)) {
22609
+ return toResult(
22610
+ "nodejs",
22611
+ nodeVersionFromEngines(pkg.engines),
22612
+ "package.json"
22613
+ );
22614
+ }
22615
+ } catch {
22616
+ }
22617
+ }
22618
+ const pythonMarker = PYTHON_MARKERS.find((m) => files.includes(m));
22619
+ if (pythonMarker) {
22620
+ const versionSource = await readText(path64.join(directory, ".python-version")) ?? (pythonMarker === "pyproject.toml" ? (await readText(path64.join(directory, pythonMarker)))?.match(
22621
+ /requires-python\s*=\s*"([^"]+)"/
22622
+ )?.[1] : void 0);
22623
+ return toResult(
22624
+ "python",
22625
+ pythonVersionFromText(versionSource),
22626
+ pythonMarker
22627
+ );
22628
+ }
22629
+ return void 0;
22630
+ }
22546
22631
 
22547
22632
  // src/cli/scaffold/wire-docs.ts
22548
22633
  import {
22549
22634
  access as access9,
22550
22635
  lstat,
22551
22636
  mkdir as mkdir13,
22552
- readdir as readdir3,
22553
- readFile as readFile18,
22637
+ readdir as readdir4,
22638
+ readFile as readFile19,
22554
22639
  readlink,
22555
22640
  symlink,
22556
22641
  writeFile as writeFile17
22557
22642
  } from "node:fs/promises";
22558
- import path64 from "node:path";
22643
+ import path65 from "node:path";
22559
22644
  var DOCS_DIR_WHITELIST = [
22560
22645
  "docs",
22561
22646
  "documents",
@@ -22592,20 +22677,20 @@ async function isDirectory(filePath) {
22592
22677
  }
22593
22678
  }
22594
22679
  function toPosix2(value) {
22595
- return value.split(path64.sep).join(path64.posix.sep);
22680
+ return value.split(path65.sep).join(path65.posix.sep);
22596
22681
  }
22597
22682
  function isWhitelistedDirName(name) {
22598
22683
  return DOCS_DIR_WHITELIST.includes(name.toLowerCase());
22599
22684
  }
22600
22685
  function isInside2(parent, child) {
22601
- const relative = path64.relative(parent, child);
22602
- return relative === "" || !relative.startsWith("..") && !path64.isAbsolute(relative);
22686
+ const relative = path65.relative(parent, child);
22687
+ return relative === "" || !relative.startsWith("..") && !path65.isAbsolute(relative);
22603
22688
  }
22604
22689
  async function collectMarkdownFiles(dir, excludeDir) {
22605
22690
  const files = [];
22606
22691
  let entries;
22607
22692
  try {
22608
- entries = await readdir3(dir, { withFileTypes: true });
22693
+ entries = await readdir4(dir, { withFileTypes: true });
22609
22694
  } catch {
22610
22695
  return files;
22611
22696
  }
@@ -22613,9 +22698,9 @@ async function collectMarkdownFiles(dir, excludeDir) {
22613
22698
  if (entry.name.startsWith(".")) {
22614
22699
  continue;
22615
22700
  }
22616
- const full = path64.join(dir, entry.name);
22701
+ const full = path65.join(dir, entry.name);
22617
22702
  if (entry.isDirectory()) {
22618
- if (SKIP_SEARCH_DIRS.has(entry.name) || entry.isSymbolicLink() || excludeDir && path64.resolve(full) === excludeDir) {
22703
+ if (SKIP_SEARCH_DIRS.has(entry.name) || entry.isSymbolicLink() || excludeDir && path65.resolve(full) === excludeDir) {
22619
22704
  continue;
22620
22705
  }
22621
22706
  files.push(...await collectMarkdownFiles(full, excludeDir));
@@ -22628,11 +22713,11 @@ async function collectMarkdownFiles(dir, excludeDir) {
22628
22713
  return files;
22629
22714
  }
22630
22715
  async function collectSearchRoots(siteDirectory) {
22631
- const site = path64.resolve(siteDirectory);
22632
- const parent = path64.dirname(site);
22716
+ const site = path65.resolve(siteDirectory);
22717
+ const parent = path65.dirname(site);
22633
22718
  const roots = [];
22634
22719
  const add = (dir) => {
22635
- const resolved = path64.resolve(dir);
22720
+ const resolved = path65.resolve(dir);
22636
22721
  if (!roots.includes(resolved)) {
22637
22722
  roots.push(resolved);
22638
22723
  }
@@ -22640,12 +22725,12 @@ async function collectSearchRoots(siteDirectory) {
22640
22725
  if (parent && parent !== site) {
22641
22726
  add(parent);
22642
22727
  try {
22643
- const entries = await readdir3(parent, { withFileTypes: true });
22728
+ const entries = await readdir4(parent, { withFileTypes: true });
22644
22729
  for (const entry of entries) {
22645
22730
  if (!entry.isDirectory() || SKIP_SEARCH_DIRS.has(entry.name)) {
22646
22731
  continue;
22647
22732
  }
22648
- add(path64.join(parent, entry.name));
22733
+ add(path65.join(parent, entry.name));
22649
22734
  }
22650
22735
  } catch {
22651
22736
  }
@@ -22654,13 +22739,13 @@ async function collectSearchRoots(siteDirectory) {
22654
22739
  return roots;
22655
22740
  }
22656
22741
  async function discoverNearbyDocsDirectories(siteDirectory) {
22657
- const site = path64.resolve(siteDirectory);
22658
- const sitePages = path64.join(site, PAGES_DIR);
22742
+ const site = path65.resolve(siteDirectory);
22743
+ const sitePages = path65.join(site, PAGES_DIR);
22659
22744
  const searchedDirectories = await collectSearchRoots(site);
22660
22745
  const directories = [];
22661
22746
  const seen = /* @__PURE__ */ new Set();
22662
22747
  const consider = async (dir) => {
22663
- const resolved = path64.resolve(dir);
22748
+ const resolved = path65.resolve(dir);
22664
22749
  if (resolved === site || seen.has(resolved) || isInside2(sitePages, resolved)) {
22665
22750
  return;
22666
22751
  }
@@ -22677,11 +22762,11 @@ async function discoverNearbyDocsDirectories(siteDirectory) {
22677
22762
  directories.push({ sourceDirectory: resolved, files });
22678
22763
  };
22679
22764
  for (const root of searchedDirectories) {
22680
- if (isWhitelistedDirName(path64.basename(root))) {
22765
+ if (isWhitelistedDirName(path65.basename(root))) {
22681
22766
  await consider(root);
22682
22767
  }
22683
22768
  try {
22684
- const entries = await readdir3(root, { withFileTypes: true });
22769
+ const entries = await readdir4(root, { withFileTypes: true });
22685
22770
  for (const entry of entries) {
22686
22771
  if (!entry.isDirectory() || SKIP_SEARCH_DIRS.has(entry.name)) {
22687
22772
  continue;
@@ -22689,7 +22774,7 @@ async function discoverNearbyDocsDirectories(siteDirectory) {
22689
22774
  if (!isWhitelistedDirName(entry.name)) {
22690
22775
  continue;
22691
22776
  }
22692
- await consider(path64.join(root, entry.name));
22777
+ await consider(path65.join(root, entry.name));
22693
22778
  }
22694
22779
  } catch {
22695
22780
  }
@@ -22708,8 +22793,8 @@ function slugifyDirName(name) {
22708
22793
  return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "docs";
22709
22794
  }
22710
22795
  async function allocateLinkName(pagesDir, sourceDirectory, used) {
22711
- const base = slugifyDirName(path64.basename(sourceDirectory));
22712
- const parent = slugifyDirName(path64.basename(path64.dirname(sourceDirectory)));
22796
+ const base = slugifyDirName(path65.basename(sourceDirectory));
22797
+ const parent = slugifyDirName(path65.basename(path65.dirname(sourceDirectory)));
22713
22798
  const candidates = [base, `${parent}-${base}`];
22714
22799
  let index = 2;
22715
22800
  while (true) {
@@ -22717,7 +22802,7 @@ async function allocateLinkName(pagesDir, sourceDirectory, used) {
22717
22802
  if (used.has(name)) {
22718
22803
  continue;
22719
22804
  }
22720
- const target = path64.join(pagesDir, name);
22805
+ const target = path65.join(pagesDir, name);
22721
22806
  if (await pathExists5(target)) {
22722
22807
  const stat4 = await lstat(target);
22723
22808
  if (!stat4.isDirectory() || !await isManagedLinkDir(target)) {
@@ -22730,7 +22815,7 @@ async function allocateLinkName(pagesDir, sourceDirectory, used) {
22730
22815
  }
22731
22816
  async function isManagedLinkDir(dir) {
22732
22817
  try {
22733
- const entries = await readdir3(dir, { withFileTypes: true });
22818
+ const entries = await readdir4(dir, { withFileTypes: true });
22734
22819
  if (entries.length === 0) {
22735
22820
  return true;
22736
22821
  }
@@ -22748,8 +22833,8 @@ async function alreadyLinked(linkPath, sourcePath) {
22748
22833
  return false;
22749
22834
  }
22750
22835
  const current = await readlink(linkPath);
22751
- const resolved = path64.resolve(path64.dirname(linkPath), current);
22752
- return resolved === path64.resolve(sourcePath);
22836
+ const resolved = path65.resolve(path65.dirname(linkPath), current);
22837
+ return resolved === path65.resolve(sourcePath);
22753
22838
  } catch {
22754
22839
  return false;
22755
22840
  }
@@ -22761,8 +22846,8 @@ async function linkMarkdownFile(sourcePath, linkPath) {
22761
22846
  if (await pathExists5(linkPath)) {
22762
22847
  return "skipped";
22763
22848
  }
22764
- await mkdir13(path64.dirname(linkPath), { recursive: true });
22765
- const relativeTarget = path64.relative(path64.dirname(linkPath), sourcePath);
22849
+ await mkdir13(path65.dirname(linkPath), { recursive: true });
22850
+ const relativeTarget = path65.relative(path65.dirname(linkPath), sourcePath);
22766
22851
  await symlink(
22767
22852
  relativeTarget,
22768
22853
  linkPath,
@@ -22777,11 +22862,11 @@ async function applyDocsNavigation(siteDirectory, routes) {
22777
22862
  if (routes.length === 0) {
22778
22863
  return;
22779
22864
  }
22780
- const configPath = path64.join(siteDirectory, CONFIG_FILENAME);
22865
+ const configPath = path65.join(siteDirectory, CONFIG_FILENAME);
22781
22866
  if (!await pathExists5(configPath)) {
22782
22867
  return;
22783
22868
  }
22784
- const raw = await readFile18(configPath, "utf8");
22869
+ const raw = await readFile19(configPath, "utf8");
22785
22870
  const parsed = JSON.parse(raw);
22786
22871
  if (!isPlainObject5(parsed)) {
22787
22872
  return;
@@ -22794,8 +22879,8 @@ async function applyDocsNavigation(siteDirectory, routes) {
22794
22879
  `, "utf8");
22795
22880
  }
22796
22881
  async function discoverAndWireDocs(siteDirectory) {
22797
- const site = path64.resolve(siteDirectory);
22798
- const pagesDir = path64.join(site, PAGES_DIR);
22882
+ const site = path65.resolve(siteDirectory);
22883
+ const pagesDir = path65.join(site, PAGES_DIR);
22799
22884
  const { directories, searchedDirectories } = await discoverNearbyDocsDirectories(site);
22800
22885
  if (directories.length === 0) {
22801
22886
  return {
@@ -22817,15 +22902,15 @@ async function discoverAndWireDocs(siteDirectory) {
22817
22902
  directory.sourceDirectory,
22818
22903
  usedNames
22819
22904
  );
22820
- const linkDirectory = path64.join(pagesDir, linkName);
22905
+ const linkDirectory = path65.join(pagesDir, linkName);
22821
22906
  const linked = [];
22822
22907
  const skipped = [];
22823
22908
  for (const sourcePath of directory.files) {
22824
22909
  const relativeSource = toPosix2(
22825
- path64.relative(directory.sourceDirectory, sourcePath)
22910
+ path65.relative(directory.sourceDirectory, sourcePath)
22826
22911
  );
22827
- const linkPath = path64.join(linkDirectory, relativeSource);
22828
- const relativeLink = toPosix2(path64.relative(site, linkPath));
22912
+ const linkPath = path65.join(linkDirectory, relativeSource);
22913
+ const relativeLink = toPosix2(path65.relative(site, linkPath));
22829
22914
  const route = toRoutePath(relativeLink, PAGES_DIR);
22830
22915
  if (routes.includes(route)) {
22831
22916
  skipped.push({
@@ -22873,11 +22958,11 @@ async function discoverAndWireDocs(siteDirectory) {
22873
22958
  };
22874
22959
  }
22875
22960
  function siteRelative(siteDirectory, filePath) {
22876
- const relative = toPosix2(path64.relative(siteDirectory, filePath));
22961
+ const relative = toPosix2(path65.relative(siteDirectory, filePath));
22877
22962
  if (!relative) {
22878
22963
  return ".";
22879
22964
  }
22880
- if (path64.isAbsolute(relative)) {
22965
+ if (path65.isAbsolute(relative)) {
22881
22966
  return toPosix2(filePath);
22882
22967
  }
22883
22968
  if (relative.startsWith("..")) {
@@ -22926,10 +23011,31 @@ function formatDocsDiscoveryLines(siteDirectory, docsDiscovery) {
22926
23011
  }
22927
23012
  return lines;
22928
23013
  }
22929
- function formatInitDiscoveryReport(siteDirectory, openApiDiscovery, docsDiscovery) {
23014
+ function formatBackendDiscoveryLines(backendDiscovery) {
23015
+ const status2 = String(backendDiscovery?.status ?? "unknown");
23016
+ if (status2 === "wired" || status2 === "already_configured") {
23017
+ const runtime = backendDiscovery?.runtime ?? "unknown runtime";
23018
+ const version = backendDiscovery?.runtimeVersion ?? "";
23019
+ const source = backendDiscovery?.sourceDirectory ?? "";
23020
+ const verb = status2 === "wired" ? "detected" : "kept";
23021
+ return [`Backend: ${verb} ${runtime} ${version} at ${source}`.trimEnd()];
23022
+ }
23023
+ if (status2 === "wire_failed") {
23024
+ const error = typeof backendDiscovery?.error === "string" ? `: ${backendDiscovery.error}` : "";
23025
+ return [`Backend: found a project but did not wire it${error}`];
23026
+ }
23027
+ if (status2 === "skipped") {
23028
+ return ["Backend: search skipped"];
23029
+ }
23030
+ return [
23031
+ "Backend: none detected in the parent folder (set one with apitogo config)"
23032
+ ];
23033
+ }
23034
+ function formatInitDiscoveryReport(siteDirectory, openApiDiscovery, docsDiscovery, backendDiscovery) {
22930
23035
  return [
22931
23036
  ...formatOpenApiDiscoveryLines(siteDirectory, openApiDiscovery),
22932
- ...formatDocsDiscoveryLines(siteDirectory, docsDiscovery)
23037
+ ...formatDocsDiscoveryLines(siteDirectory, docsDiscovery),
23038
+ ...backendDiscovery ? formatBackendDiscoveryLines(backendDiscovery) : []
22933
23039
  ];
22934
23040
  }
22935
23041
 
@@ -22944,8 +23050,8 @@ async function pathExists6(filePath) {
22944
23050
  }
22945
23051
  async function wireOpenApiIntoJsonConfig(siteDirectory, openApiPath) {
22946
23052
  const input5 = toSiteRelativeOpenApiInput(siteDirectory, openApiPath);
22947
- const jsonConfigPath = path65.join(siteDirectory, "apitogo.config.json");
22948
- const raw = await readFile19(jsonConfigPath, "utf8");
23053
+ const jsonConfigPath = path66.join(siteDirectory, "apitogo.config.json");
23054
+ const raw = await readFile20(jsonConfigPath, "utf8");
22949
23055
  const siteConfig = JSON.parse(raw);
22950
23056
  const updated = applyOpenApiToSiteConfig(siteConfig, {
22951
23057
  input: input5,
@@ -22972,7 +23078,7 @@ async function discoverAndWireOpenApiLite(siteDirectory, mode) {
22972
23078
  const invalidCandidates = [];
22973
23079
  let selected;
22974
23080
  for (const candidate of search.candidates) {
22975
- const content = await readFile19(candidate, "utf8");
23081
+ const content = await readFile20(candidate, "utf8");
22976
23082
  const parsed = liteParseOpenApi(content, candidate);
22977
23083
  if (parsed.valid) {
22978
23084
  selected = {
@@ -22996,7 +23102,7 @@ async function discoverAndWireOpenApiLite(siteDirectory, mode) {
22996
23102
  wired: false
22997
23103
  };
22998
23104
  }
22999
- const jsonConfigPath = path65.join(siteDirectory, "apitogo.config.json");
23105
+ const jsonConfigPath = path66.join(siteDirectory, "apitogo.config.json");
23000
23106
  if (!await pathExists6(jsonConfigPath)) {
23001
23107
  return {
23002
23108
  openApiDiscovery: {
@@ -23042,6 +23148,58 @@ async function discoverAndWireOpenApiLite(siteDirectory, mode) {
23042
23148
  };
23043
23149
  }
23044
23150
  }
23151
+ async function discoverAndWireBackend(siteDirectory, mode) {
23152
+ if (mode !== "nearby") {
23153
+ return { status: "skipped", mode };
23154
+ }
23155
+ const jsonConfigPath = path66.join(siteDirectory, "apitogo.config.json");
23156
+ if (!await pathExists6(jsonConfigPath)) {
23157
+ return { status: "not_found" };
23158
+ }
23159
+ try {
23160
+ const siteConfig = JSON.parse(
23161
+ await readFile20(jsonConfigPath, "utf8")
23162
+ );
23163
+ const existing = siteConfig.backend && typeof siteConfig.backend === "object" && !Array.isArray(siteConfig.backend) ? siteConfig.backend : {};
23164
+ if (typeof existing.sourceDirectory === "string" && existing.sourceDirectory.trim()) {
23165
+ return {
23166
+ status: "already_configured",
23167
+ sourceDirectory: existing.sourceDirectory,
23168
+ runtime: existing.runtime ?? null,
23169
+ runtimeVersion: existing.runtimeVersion ?? null
23170
+ };
23171
+ }
23172
+ const detected = await detectParentBackend(siteDirectory);
23173
+ if (!detected) {
23174
+ return { status: "not_found" };
23175
+ }
23176
+ siteConfig.backend = {
23177
+ ...existing,
23178
+ sourceDirectory: detected.sourceDirectory,
23179
+ runtime: detected.runtime,
23180
+ runtimeVersion: detected.runtimeVersion
23181
+ };
23182
+ await writeFile18(
23183
+ jsonConfigPath,
23184
+ `${JSON.stringify(siteConfig, null, 2)}
23185
+ `,
23186
+ "utf8"
23187
+ );
23188
+ return {
23189
+ status: "wired",
23190
+ directory: detected.directory,
23191
+ sourceDirectory: detected.sourceDirectory,
23192
+ runtime: detected.runtime,
23193
+ runtimeVersion: detected.runtimeVersion,
23194
+ marker: detected.marker
23195
+ };
23196
+ } catch (error) {
23197
+ return {
23198
+ status: "wire_failed",
23199
+ error: error instanceof Error ? error.message : String(error)
23200
+ };
23201
+ }
23202
+ }
23045
23203
  async function runScaffoldDiscovery(siteDirectory, options) {
23046
23204
  const openapiSearch = options?.openapiSearch ?? "nearby";
23047
23205
  const { openApiDiscovery } = await discoverAndWireOpenApiLite(
@@ -23049,7 +23207,11 @@ async function runScaffoldDiscovery(siteDirectory, options) {
23049
23207
  openapiSearch
23050
23208
  );
23051
23209
  const docsDiscovery = await discoverAndWireDocs(siteDirectory);
23052
- return { openApiDiscovery, docsDiscovery };
23210
+ const backendDiscovery = await discoverAndWireBackend(
23211
+ siteDirectory,
23212
+ openapiSearch
23213
+ );
23214
+ return { openApiDiscovery, docsDiscovery, backendDiscovery };
23053
23215
  }
23054
23216
 
23055
23217
  // src/cli/init/handler.ts
@@ -23057,8 +23219,8 @@ function slugifyName2(name) {
23057
23219
  return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "dev-portal-site";
23058
23220
  }
23059
23221
  function resolveInitOutputDirectory(dirArg, name) {
23060
- const resolved = path66.resolve(process.cwd(), dirArg);
23061
- const base = path66.basename(resolved);
23222
+ const resolved = path67.resolve(process.cwd(), dirArg);
23223
+ const base = path67.basename(resolved);
23062
23224
  const isDot = dirArg === "." || dirArg === "./" || base === "." || resolved === process.cwd();
23063
23225
  if (isDot) {
23064
23226
  const fromName = name?.trim();
@@ -23068,7 +23230,7 @@ function resolveInitOutputDirectory(dirArg, name) {
23068
23230
  );
23069
23231
  }
23070
23232
  return {
23071
- outputDirectory: path66.resolve(process.cwd(), slugifyName2(fromName)),
23233
+ outputDirectory: path67.resolve(process.cwd(), slugifyName2(fromName)),
23072
23234
  siteName: fromName
23073
23235
  };
23074
23236
  }
@@ -23113,17 +23275,15 @@ async function init2(argv) {
23113
23275
  }
23114
23276
  npmInstall = await runNpmInstall(result.outputDirectory);
23115
23277
  }
23116
- const { openApiDiscovery, docsDiscovery } = await runScaffoldDiscovery(
23117
- result.outputDirectory,
23118
- { openapiSearch }
23119
- );
23278
+ const { openApiDiscovery, docsDiscovery, backendDiscovery } = await runScaffoldDiscovery(result.outputDirectory, { openapiSearch });
23120
23279
  const siteValidation = await validateDevPortalSiteConfig(
23121
23280
  result.outputDirectory
23122
23281
  );
23123
23282
  const discoveryReport = formatInitDiscoveryReport(
23124
23283
  result.outputDirectory,
23125
23284
  openApiDiscovery,
23126
- docsDiscovery
23285
+ docsDiscovery,
23286
+ backendDiscovery
23127
23287
  );
23128
23288
  const devCommand = "npm run dev";
23129
23289
  const response = {
@@ -23143,6 +23303,7 @@ async function init2(argv) {
23143
23303
  npmInstallDurationMs: npmInstall?.durationMs ?? null,
23144
23304
  openApiDiscovery,
23145
23305
  docsDiscovery,
23306
+ backendDiscovery,
23146
23307
  openapiSearch,
23147
23308
  previewStarted: false,
23148
23309
  devCommand,
@@ -23221,8 +23382,8 @@ import open2 from "open";
23221
23382
  import colors13 from "picocolors";
23222
23383
 
23223
23384
  // src/cli/platform/device-auth.ts
23224
- function url(apiUrl, path73) {
23225
- return `${apiUrl}${path73.startsWith("/") ? path73 : `/${path73}`}`;
23385
+ function url(apiUrl, path74) {
23386
+ return `${apiUrl}${path74.startsWith("/") ? path74 : `/${path74}`}`;
23226
23387
  }
23227
23388
  async function requestDeviceCode(apiUrl) {
23228
23389
  const response = await fetchWithRetry(
@@ -23485,14 +23646,14 @@ var project_create_default = {
23485
23646
 
23486
23647
  // src/cli/dev/handler.ts
23487
23648
  init_joinUrl();
23488
- import path69 from "node:path";
23649
+ import path70 from "node:path";
23489
23650
 
23490
23651
  // src/vite/dev-server.ts
23491
23652
  init_logger();
23492
23653
  import fs12 from "node:fs/promises";
23493
23654
  import http from "node:http";
23494
23655
  import https from "node:https";
23495
- import path68 from "node:path";
23656
+ import path69 from "node:path";
23496
23657
  import { createHttpTerminator } from "http-terminator";
23497
23658
  import {
23498
23659
  createServer as createViteServer,
@@ -23525,7 +23686,7 @@ init_loader();
23525
23686
  // src/vite/pagefind-dev-index.ts
23526
23687
  init_invariant();
23527
23688
  init_joinUrl();
23528
- import path67 from "node:path";
23689
+ import path68 from "node:path";
23529
23690
  import { createIndex as createIndex2 } from "pagefind";
23530
23691
  import { isRunnableDevEnvironment } from "vite";
23531
23692
  async function* buildPagefindDevIndex(vite, config2) {
@@ -23578,7 +23739,7 @@ async function* buildPagefindDevIndex(vite, config2) {
23578
23739
  path: urlPath
23579
23740
  };
23580
23741
  }
23581
- const outputPath = path67.join(vite.config.publicDir, "pagefind");
23742
+ const outputPath = path68.join(vite.config.publicDir, "pagefind");
23582
23743
  await pagefindIndex.writeFiles({ outputPath });
23583
23744
  yield { type: "complete", success: true, indexed };
23584
23745
  }
@@ -23597,9 +23758,9 @@ var DevServer = class {
23597
23758
  this.protocol = "https";
23598
23759
  const { dir } = this.options;
23599
23760
  const [key, cert, ca] = await Promise.all([
23600
- fs12.readFile(path68.resolve(dir, config2.https.key)),
23601
- fs12.readFile(path68.resolve(dir, config2.https.cert)),
23602
- config2.https.ca ? fs12.readFile(path68.resolve(dir, config2.https.ca)) : void 0
23761
+ fs12.readFile(path69.resolve(dir, config2.https.key)),
23762
+ fs12.readFile(path69.resolve(dir, config2.https.cert)),
23763
+ config2.https.ca ? fs12.readFile(path69.resolve(dir, config2.https.ca)) : void 0
23603
23764
  ]);
23604
23765
  return https.createServer({ key, cert, ca });
23605
23766
  }
@@ -23616,7 +23777,7 @@ var DevServer = class {
23616
23777
  );
23617
23778
  const server = await this.createNodeServer(config2);
23618
23779
  if (config2.search?.type === "pagefind" && viteConfig.publicDir !== false) {
23619
- const publicRoot = path68.resolve(
23780
+ const publicRoot = path69.resolve(
23620
23781
  this.options.dir,
23621
23782
  typeof viteConfig.publicDir === "string" ? viteConfig.publicDir : "public"
23622
23783
  );
@@ -23633,7 +23794,7 @@ var DevServer = class {
23633
23794
  // built-in transform middleware which would treat the path as a static asset.
23634
23795
  name: "apitogo:entry-client",
23635
23796
  configureServer(server2) {
23636
- const entryPath = path68.posix.join(
23797
+ const entryPath = path69.posix.join(
23637
23798
  server2.config.base,
23638
23799
  "/__z/entry.client.tsx"
23639
23800
  );
@@ -23798,7 +23959,7 @@ init_package_json();
23798
23959
  async function dev(argv) {
23799
23960
  const packageJson3 = getZudokuPackageJson();
23800
23961
  process.env.NODE_ENV = "development";
23801
- const dir = path69.resolve(process.cwd(), argv.dir);
23962
+ const dir = path70.resolve(process.cwd(), argv.dir);
23802
23963
  const server = new DevServer({
23803
23964
  dir,
23804
23965
  argPort: argv.port,
@@ -23887,9 +24048,9 @@ var run_default = {
23887
24048
  };
23888
24049
 
23889
24050
  // src/cli/status/handler.ts
23890
- import path70 from "node:path";
24051
+ import path71 from "node:path";
23891
24052
  async function status(argv) {
23892
- const sourceDirectory = path70.resolve(process.cwd(), argv.dir);
24053
+ const sourceDirectory = path71.resolve(process.cwd(), argv.dir);
23893
24054
  let config2;
23894
24055
  try {
23895
24056
  config2 = loadConfig();
@@ -23977,7 +24138,7 @@ var status_default = {
23977
24138
  };
23978
24139
 
23979
24140
  // src/cli/teardown/handler.ts
23980
- import path71 from "node:path";
24141
+ import path72 from "node:path";
23981
24142
  function resultLooksFailed3(payload) {
23982
24143
  try {
23983
24144
  const parsed = JSON.parse(payload);
@@ -23993,7 +24154,7 @@ async function teardown(argv) {
23993
24154
  );
23994
24155
  return;
23995
24156
  }
23996
- const sourceDirectory = path71.resolve(process.cwd(), argv.dir);
24157
+ const sourceDirectory = path72.resolve(process.cwd(), argv.dir);
23997
24158
  let config2;
23998
24159
  try {
23999
24160
  config2 = loadConfig();
@@ -24150,36 +24311,36 @@ function createApitogoCli(argv) {
24150
24311
  // src/cli/local-handoff.ts
24151
24312
  import { spawn as spawn4 } from "node:child_process";
24152
24313
  import { existsSync as existsSync6, realpathSync } from "node:fs";
24153
- import path72 from "node:path";
24314
+ import path73 from "node:path";
24154
24315
  var LOCAL_HANDOFF_ENV = "APITOGO_LOCAL_CLI";
24155
24316
  var PACKAGE_NAME = "@lukoweb/apitogo";
24156
24317
  var resolveProjectDir = (argv, cwd) => {
24157
24318
  for (let i = 0; i < argv.length; i++) {
24158
24319
  const arg = argv[i];
24159
24320
  const next = argv[i + 1];
24160
- if (arg === "--dir" && next) return path72.resolve(cwd, next);
24321
+ if (arg === "--dir" && next) return path73.resolve(cwd, next);
24161
24322
  if (arg?.startsWith("--dir=")) {
24162
- return path72.resolve(cwd, arg.slice("--dir=".length));
24323
+ return path73.resolve(cwd, arg.slice("--dir=".length));
24163
24324
  }
24164
24325
  }
24165
24326
  return cwd;
24166
24327
  };
24167
24328
  var findLocalCli = (projectDir, runningRoot) => {
24168
- let dir = path72.resolve(projectDir);
24329
+ let dir = path73.resolve(projectDir);
24169
24330
  let localPackageRoot;
24170
24331
  while (!localPackageRoot) {
24171
- const candidate = path72.join(dir, "node_modules", PACKAGE_NAME);
24172
- if (existsSync6(path72.join(candidate, "package.json"))) {
24332
+ const candidate = path73.join(dir, "node_modules", PACKAGE_NAME);
24333
+ if (existsSync6(path73.join(candidate, "package.json"))) {
24173
24334
  localPackageRoot = candidate;
24174
- } else if (dir === path72.dirname(dir)) {
24335
+ } else if (dir === path73.dirname(dir)) {
24175
24336
  return void 0;
24176
24337
  } else {
24177
- dir = path72.dirname(dir);
24338
+ dir = path73.dirname(dir);
24178
24339
  }
24179
24340
  }
24180
24341
  const localRoot = realpathSync(localPackageRoot);
24181
24342
  if (localRoot === realpathSync(runningRoot)) return void 0;
24182
- return path72.join(localRoot, "cli.js");
24343
+ return path73.join(localRoot, "cli.js");
24183
24344
  };
24184
24345
  var handoffToLocalCli = async (argv, runningRoot) => {
24185
24346
  if (process.env[LOCAL_HANDOFF_ENV] || process.env.ZUDOKU_ENV === "internal") {
@@ -24191,7 +24352,7 @@ var handoffToLocalCli = async (argv, runningRoot) => {
24191
24352
  );
24192
24353
  if (!localCli) return void 0;
24193
24354
  printDiagnosticsToConsole(
24194
- `Using the project's local ${PACKAGE_NAME} (${path72.dirname(localCli)})`
24355
+ `Using the project's local ${PACKAGE_NAME} (${path73.dirname(localCli)})`
24195
24356
  );
24196
24357
  const child = spawn4(process.execPath, [localCli, ...argv], {
24197
24358
  stdio: "inherit",
@@ -151,6 +151,7 @@ export declare function applyScaffoldManifestPolicy(manifest: DevPortalLocalMani
151
151
  includeDefaultPlans?: boolean;
152
152
  }): DevPortalLocalManifest;
153
153
  export declare function mergePlansBySku(existing: ManifestPlanInput[] | undefined, patch: ManifestPlanInput[]): ManifestPlanInput[];
154
+ export declare function resolveBackendSourceDirectory(siteDirectory: string, sourceDirectory: string | undefined): string | undefined;
154
155
  export declare function resolveBackendOpenApiPath(openApiPath: string | undefined, options: {
155
156
  siteDirectory: string;
156
157
  backendSourceDirectory?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lukoweb/apitogo",
3
- "version": "0.1.143",
3
+ "version": "0.1.146",
4
4
  "type": "module",
5
5
  "sideEffects": [
6
6
  "**/*.css",