@lukoweb/apitogo 0.2.60 → 0.2.64
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 +1101 -589
- package/dist/declarations/cli/platform/client/platform-api.d.ts +3 -0
- package/dist/declarations/cli/platform/errors.d.ts +5 -0
- package/docs/cli/commands.md +6 -6
- package/docs/cli/go-live.md +12 -12
- package/docs/cli/overview.md +26 -27
- package/docs/cli/setup.md +38 -46
- package/docs/cli/shape.md +32 -35
- package/docs/cli/walkthrough.md +19 -19
- package/docs/components/slot.mdx +116 -116
- package/docs/configuration/api-reference.md +1 -1
- package/docs/configuration/authentication.md +3 -3
- package/docs/configuration/footer.mdx +89 -89
- package/docs/configuration/gateway.md +8 -8
- package/docs/configuration/make-config.mdx +20 -10
- package/docs/configuration/overview.md +3 -3
- package/docs/configuration/plans.md +5 -5
- package/docs/configuration/portal.md +36 -0
- package/docs/customization/colors-theme.mdx +255 -255
- package/docs/customization/fonts.md +105 -105
- package/docs/customization/landing-page.md +1 -1
- package/docs/deploy/apitogo.md +3 -3
- package/docs/deployment.md +3 -3
- package/docs/guides/custom-pages.md +3 -3
- package/docs/guides/customer-account.md +1 -1
- package/docs/guides/stripe-setup.mdx +9 -9
- package/docs/markdown/frontmatter.md +2 -2
- package/docs/mcp/go-live.md +7 -7
- package/docs/mcp/overview.md +58 -58
- package/docs/mcp/setup.md +20 -15
- package/docs/mcp/shape.md +2 -2
- package/docs/mcp/tools.md +57 -57
- package/docs/quickstart.md +6 -4
- package/docs/writing.mdx +68 -68
- package/package.json +1 -1
- package/src/config/apitogo-config-core.ts +11 -1
- package/src/config/v2/home-redirect.ts +5 -5
- package/src/config/v2/index.ts +5 -1
- package/src/config/v2/portal-profile.ts +17 -0
- package/src/config/v2/resolve.ts +19 -0
- package/src/config/v2/rules.ts +124 -0
- package/src/config/v2/schema.ts +28 -0
- package/src/config/v2/wrapper.ts +76 -13
- package/src/vite/config.ts +278 -273
- package/src/vite/markdown-output-path.ts +48 -0
- package/src/vite/plugin-markdown-export.ts +210 -214
- package/src/vite/prerender/prerender.ts +4 -4
- package/src/vite/watch-ignore.ts +19 -0
package/dist/cli/cli.js
CHANGED
|
@@ -457,8 +457,12 @@ function syncAuthentication(normalized) {
|
|
|
457
457
|
if (!userPanelEnabled && !authentication) {
|
|
458
458
|
return;
|
|
459
459
|
}
|
|
460
|
+
if (!userPanelEnabled && authentication?.enabled === false) {
|
|
461
|
+
delete normalized.authentication;
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
460
464
|
const auth = authentication ?? {};
|
|
461
|
-
auth.enabled =
|
|
465
|
+
if (userPanelEnabled) auth.enabled = true;
|
|
462
466
|
const keepsOpenId = auth.type === "openid";
|
|
463
467
|
if (!keepsOpenId) auth.type = "dev-portal";
|
|
464
468
|
if (userPanelEnabled && !keepsOpenId) {
|
|
@@ -837,7 +841,7 @@ import { stat as stat4 } from "node:fs/promises";
|
|
|
837
841
|
var fileExists;
|
|
838
842
|
var init_file_exists = __esm({
|
|
839
843
|
"src/config/file-exists.ts"() {
|
|
840
|
-
fileExists = (
|
|
844
|
+
fileExists = (path100) => stat4(path100).then(() => true).catch(() => false);
|
|
841
845
|
}
|
|
842
846
|
});
|
|
843
847
|
|
|
@@ -5270,7 +5274,7 @@ __export(llms_exports, {
|
|
|
5270
5274
|
generateLlmsTxtFiles: () => generateLlmsTxtFiles
|
|
5271
5275
|
});
|
|
5272
5276
|
import { writeFile as writeFile12 } from "node:fs/promises";
|
|
5273
|
-
import
|
|
5277
|
+
import path47 from "node:path";
|
|
5274
5278
|
import colors10 from "picocolors";
|
|
5275
5279
|
async function generateLlmsTxtFiles({
|
|
5276
5280
|
markdownFileInfos,
|
|
@@ -5305,7 +5309,7 @@ async function generateLlmsTxtFiles({
|
|
|
5305
5309
|
}
|
|
5306
5310
|
}
|
|
5307
5311
|
const llmsTxt2 = llmsTxtParts.join("\n");
|
|
5308
|
-
await writeFile12(
|
|
5312
|
+
await writeFile12(path47.join(baseOutputDir, "llms.txt"), llmsTxt2, "utf-8");
|
|
5309
5313
|
if (process.env.APITOGO_JSON_ONLY !== "1") {
|
|
5310
5314
|
console.log(colors10.blue("\u2713 generated llms.txt"));
|
|
5311
5315
|
}
|
|
@@ -5333,7 +5337,7 @@ ${info.content}
|
|
|
5333
5337
|
}
|
|
5334
5338
|
const llmsFull = llmsFullParts.join("\n");
|
|
5335
5339
|
await writeFile12(
|
|
5336
|
-
|
|
5340
|
+
path47.join(baseOutputDir, "llms-full.txt"),
|
|
5337
5341
|
llmsFull,
|
|
5338
5342
|
"utf-8"
|
|
5339
5343
|
);
|
|
@@ -5836,7 +5840,7 @@ Run the command with --help to see its options.`;
|
|
|
5836
5840
|
import yargs from "yargs/yargs";
|
|
5837
5841
|
|
|
5838
5842
|
// src/cli/services/handler.ts
|
|
5839
|
-
import
|
|
5843
|
+
import path55 from "node:path";
|
|
5840
5844
|
|
|
5841
5845
|
// src/config/v2/billing.ts
|
|
5842
5846
|
import { readFile as readFile2 } from "node:fs/promises";
|
|
@@ -5915,6 +5919,21 @@ var nonEmpty = z.string().min(1, { error: "must not be empty" });
|
|
|
5915
5919
|
var path3 = nonEmpty;
|
|
5916
5920
|
var pathList = z.array(nonEmpty);
|
|
5917
5921
|
var enabled = z.boolean().optional();
|
|
5922
|
+
var headerLabel = z.string().trim().min(1, { error: "must not be empty" }).max(40, { error: "must be 40 characters or fewer" });
|
|
5923
|
+
var HeaderLinkSchema = z.union(
|
|
5924
|
+
[
|
|
5925
|
+
z.strictObject({ label: headerLabel, page: path3 }),
|
|
5926
|
+
z.strictObject({
|
|
5927
|
+
label: headerLabel,
|
|
5928
|
+
to: z.string().regex(/^(\/(?!\/)|https:\/\/)/, {
|
|
5929
|
+
error: 'must start with "/" or "https://"'
|
|
5930
|
+
})
|
|
5931
|
+
})
|
|
5932
|
+
],
|
|
5933
|
+
{
|
|
5934
|
+
error: 'must be { "label": "...", "page": "path/to/page.tsx" } or { "label": "...", "to": "/path or https://..." }'
|
|
5935
|
+
}
|
|
5936
|
+
);
|
|
5918
5937
|
var PortalSchema = z.strictObject({
|
|
5919
5938
|
enabled,
|
|
5920
5939
|
dir: path3.optional(),
|
|
@@ -5931,6 +5950,8 @@ var PortalSchema = z.strictObject({
|
|
|
5931
5950
|
landing: path3.optional(),
|
|
5932
5951
|
/** The footer: a React component file shown under every page except the console's (API-129). */
|
|
5933
5952
|
footer: path3.optional(),
|
|
5953
|
+
/** Links of the header's top menu, after the built-in ones (Documentation, API Reference; the plans add Pricing). */
|
|
5954
|
+
header: z.strictObject({ links: z.array(HeaderLinkSchema) }).optional(),
|
|
5934
5955
|
/**
|
|
5935
5956
|
* The logo in the portal header: one image, or one per color scheme (API-129). `dark` is optional; without it the
|
|
5936
5957
|
* light image is used in both.
|
|
@@ -6094,8 +6115,8 @@ var ConfigV2Schema = z.strictObject({
|
|
|
6094
6115
|
var REMOVED_KEYS = {
|
|
6095
6116
|
"plans.provider": "plans.provider was removed. Only plans.billing.provider (stripe or none) is selectable."
|
|
6096
6117
|
};
|
|
6097
|
-
function pathToString(
|
|
6098
|
-
return
|
|
6118
|
+
function pathToString(path100) {
|
|
6119
|
+
return path100.reduce(
|
|
6099
6120
|
(acc, segment) => typeof segment === "number" ? `${acc}[${segment}]` : acc === "" ? String(segment) : `${acc}.${String(segment)}`,
|
|
6100
6121
|
""
|
|
6101
6122
|
);
|
|
@@ -6115,9 +6136,9 @@ function step(schema2, segment) {
|
|
|
6115
6136
|
}
|
|
6116
6137
|
return void 0;
|
|
6117
6138
|
}
|
|
6118
|
-
function knownKeysAt(
|
|
6139
|
+
function knownKeysAt(path100) {
|
|
6119
6140
|
let current = ConfigV2Schema;
|
|
6120
|
-
for (const segment of
|
|
6141
|
+
for (const segment of path100) {
|
|
6121
6142
|
if (!current) return [];
|
|
6122
6143
|
current = step(current, segment);
|
|
6123
6144
|
}
|
|
@@ -6153,7 +6174,7 @@ function unknownKeyHint(fullPath, key, known) {
|
|
|
6153
6174
|
return known.length > 0 ? `Allowed keys: ${known.join(", ")}.` : void 0;
|
|
6154
6175
|
}
|
|
6155
6176
|
function mapIssue(issue4) {
|
|
6156
|
-
const
|
|
6177
|
+
const path100 = pathToString(issue4.path);
|
|
6157
6178
|
switch (issue4.code) {
|
|
6158
6179
|
case "unrecognized_keys":
|
|
6159
6180
|
return issue4.keys.map((key) => {
|
|
@@ -6169,20 +6190,20 @@ function mapIssue(issue4) {
|
|
|
6169
6190
|
return [
|
|
6170
6191
|
{
|
|
6171
6192
|
code: "CONFIG_INVALID_VALUE",
|
|
6172
|
-
path:
|
|
6193
|
+
path: path100,
|
|
6173
6194
|
message: `must be one of: ${issue4.values.map((v) => JSON.stringify(v)).join(", ")}.`
|
|
6174
6195
|
}
|
|
6175
6196
|
];
|
|
6176
6197
|
case "custom": {
|
|
6177
6198
|
const code = typeof issue4.params?.code === "string" ? issue4.params.code : "CONFIG_INVALID_VALUE";
|
|
6178
|
-
return [{ code, path:
|
|
6199
|
+
return [{ code, path: path100, message: issue4.message ?? "is invalid." }];
|
|
6179
6200
|
}
|
|
6180
6201
|
case "invalid_type":
|
|
6181
6202
|
return [
|
|
6182
|
-
/received undefined/.test(issue4.message) ? { code: "CONFIG_MISSING_FIELD", path:
|
|
6203
|
+
/received undefined/.test(issue4.message) ? { code: "CONFIG_MISSING_FIELD", path: path100, message: "is required." } : { code: "CONFIG_INVALID_VALUE", path: path100, message: issue4.message }
|
|
6183
6204
|
];
|
|
6184
6205
|
default:
|
|
6185
|
-
return [{ code: "CONFIG_INVALID_VALUE", path:
|
|
6206
|
+
return [{ code: "CONFIG_INVALID_VALUE", path: path100, message: issue4.message }];
|
|
6186
6207
|
}
|
|
6187
6208
|
}
|
|
6188
6209
|
function isRecord(value) {
|
|
@@ -6478,6 +6499,7 @@ function toGlobPath(value) {
|
|
|
6478
6499
|
function fromConfig(configDir, value) {
|
|
6479
6500
|
return value.startsWith("!") ? `!${toGlobPath(path7.resolve(configDir, value.slice(1)))}` : toGlobPath(path7.resolve(configDir, value));
|
|
6480
6501
|
}
|
|
6502
|
+
var headerPageRoute = (file) => `/${path7.basename(file).replace(/\.(mdx?|tsx)$/i, "")}`;
|
|
6481
6503
|
var isLogoUrl = (value) => value.toLowerCase().startsWith("https://");
|
|
6482
6504
|
var logoSource = (configDir, value) => isLogoUrl(value) ? value : path7.resolve(configDir, value);
|
|
6483
6505
|
function resolveConfigV2(config2, configPath) {
|
|
@@ -6513,6 +6535,13 @@ function resolveConfigV2(config2, configPath) {
|
|
|
6513
6535
|
theme: portal.theme ? path7.resolve(configDir, portal.theme) : path7.join(dir, "theme.json"),
|
|
6514
6536
|
...portal.landing ? { landing: path7.resolve(configDir, portal.landing) } : {},
|
|
6515
6537
|
...portal.footer ? { footer: path7.resolve(configDir, portal.footer) } : {},
|
|
6538
|
+
headerLinks: (portal.header?.links ?? []).map(
|
|
6539
|
+
(link) => {
|
|
6540
|
+
if ("to" in link) return { label: link.label, to: link.to };
|
|
6541
|
+
const page = path7.resolve(configDir, link.page);
|
|
6542
|
+
return { label: link.label, to: headerPageRoute(page), page };
|
|
6543
|
+
}
|
|
6544
|
+
),
|
|
6516
6545
|
...portal.logo ? {
|
|
6517
6546
|
logo: typeof portal.logo === "string" ? {
|
|
6518
6547
|
light: logoSource(configDir, portal.logo),
|
|
@@ -6644,17 +6673,30 @@ function loadConfigV2(pathOrDir) {
|
|
|
6644
6673
|
}
|
|
6645
6674
|
|
|
6646
6675
|
// src/config/v2/rules.ts
|
|
6647
|
-
import { readdir as readdir2, readFile as
|
|
6648
|
-
import
|
|
6649
|
-
import { glob as
|
|
6676
|
+
import { readdir as readdir2, readFile as readFile5, stat as stat2 } from "node:fs/promises";
|
|
6677
|
+
import path11 from "node:path";
|
|
6678
|
+
import { glob as glob3 } from "glob";
|
|
6650
6679
|
import { parse as parseYaml } from "yaml";
|
|
6651
6680
|
|
|
6652
|
-
// src/config/v2/
|
|
6653
|
-
import { readFile as readFile3 } from "node:fs/promises";
|
|
6681
|
+
// src/config/v2/home-redirect.ts
|
|
6654
6682
|
import path9 from "node:path";
|
|
6655
6683
|
import { glob } from "glob";
|
|
6656
6684
|
import globParent from "glob-parent";
|
|
6657
6685
|
|
|
6686
|
+
// src/lib/util/readFrontmatter.ts
|
|
6687
|
+
import { readFile as readFile3 } from "node:fs/promises";
|
|
6688
|
+
import matter from "gray-matter";
|
|
6689
|
+
import { parse, stringify } from "yaml";
|
|
6690
|
+
var yaml = {
|
|
6691
|
+
parse: (input5) => parse(input5) ?? {},
|
|
6692
|
+
stringify: (obj) => stringify(obj)
|
|
6693
|
+
};
|
|
6694
|
+
var readFrontmatter = async (filePath) => {
|
|
6695
|
+
const content = await readFile3(filePath, "utf-8");
|
|
6696
|
+
const normalizedContent = content.replace(/\r\n/g, "\n");
|
|
6697
|
+
return matter(normalizedContent, { engines: { yaml } });
|
|
6698
|
+
};
|
|
6699
|
+
|
|
6658
6700
|
// src/config/v2/page-order.ts
|
|
6659
6701
|
var FIRST_PAGE_NAMES = [
|
|
6660
6702
|
"introduction",
|
|
@@ -6696,6 +6738,128 @@ function tsxPageOrder(source) {
|
|
|
6696
6738
|
return match?.[1] ? Number(match[1]) : void 0;
|
|
6697
6739
|
}
|
|
6698
6740
|
|
|
6741
|
+
// src/config/v2/home-redirect.ts
|
|
6742
|
+
var IGNORED = ["**/node_modules/**", "**/dist/**", "**/.git/**"];
|
|
6743
|
+
async function docRoutes(patterns, options = {}) {
|
|
6744
|
+
const globs = patterns.map(toGlobPath);
|
|
6745
|
+
const excluded = globs.filter((pattern) => pattern.startsWith("!")).map((pattern) => pattern.slice(1));
|
|
6746
|
+
const included = globs.filter((pattern) => !pattern.startsWith("!"));
|
|
6747
|
+
const routes = await Promise.all(
|
|
6748
|
+
included.map(async (pattern) => {
|
|
6749
|
+
const files = await glob(pattern, {
|
|
6750
|
+
absolute: true,
|
|
6751
|
+
posix: true,
|
|
6752
|
+
ignore: [...IGNORED, ...excluded]
|
|
6753
|
+
});
|
|
6754
|
+
const parent = globParent(pattern);
|
|
6755
|
+
const published = options.includeDrafts ? files : (await Promise.all(
|
|
6756
|
+
files.map(async (file) => ({
|
|
6757
|
+
file,
|
|
6758
|
+
draft: (await readFrontmatter(file)).data.draft === true
|
|
6759
|
+
}))
|
|
6760
|
+
)).filter(({ draft }) => !draft).map(({ file }) => file);
|
|
6761
|
+
return published.map(
|
|
6762
|
+
(file) => `/${path9.posix.relative(parent, file.replace(/^\/\/\?\//, "")).replace(/\.mdx?$/, "")}`
|
|
6763
|
+
);
|
|
6764
|
+
})
|
|
6765
|
+
);
|
|
6766
|
+
return [...new Set(routes.flat())].sort();
|
|
6767
|
+
}
|
|
6768
|
+
function pickLandingRoute(routes, orders) {
|
|
6769
|
+
return firstPage(routes, orders);
|
|
6770
|
+
}
|
|
6771
|
+
async function docPageOrders(patterns) {
|
|
6772
|
+
const globs = patterns.map(toGlobPath);
|
|
6773
|
+
const excluded = globs.filter((pattern) => pattern.startsWith("!")).map((pattern) => pattern.slice(1));
|
|
6774
|
+
const orders = /* @__PURE__ */ new Map();
|
|
6775
|
+
for (const pattern of globs.filter((p) => !p.startsWith("!"))) {
|
|
6776
|
+
const parent = globParent(pattern);
|
|
6777
|
+
const files = await glob(pattern, {
|
|
6778
|
+
absolute: true,
|
|
6779
|
+
posix: true,
|
|
6780
|
+
ignore: [...IGNORED, ...excluded]
|
|
6781
|
+
});
|
|
6782
|
+
for (const raw of files) {
|
|
6783
|
+
const order = orderValue((await readFrontmatter(raw)).data.order);
|
|
6784
|
+
if (order === void 0) continue;
|
|
6785
|
+
const route = `/${path9.posix.relative(parent, raw.replace(/^\/\/\?\//, "")).replace(/\.mdx?$/, "")}`;
|
|
6786
|
+
if (!orders.has(route)) orders.set(route, order);
|
|
6787
|
+
}
|
|
6788
|
+
}
|
|
6789
|
+
return orders;
|
|
6790
|
+
}
|
|
6791
|
+
function homeRedirect(input5) {
|
|
6792
|
+
if (input5.hostsDocs) {
|
|
6793
|
+
if (input5.docRoutes.some((route) => route === "/" || route === "/index"))
|
|
6794
|
+
return void 0;
|
|
6795
|
+
const landing = pickLandingRoute(input5.docRoutes, input5.pageOrders);
|
|
6796
|
+
if (landing) return { from: "/", to: landing };
|
|
6797
|
+
if (input5.apiReferencePath)
|
|
6798
|
+
return { from: "/", to: input5.apiReferencePath };
|
|
6799
|
+
}
|
|
6800
|
+
if (!input5.hostsDocs && input5.externalDocsUrl && !input5.userPanel) {
|
|
6801
|
+
return { from: "/", to: input5.externalDocsUrl };
|
|
6802
|
+
}
|
|
6803
|
+
if (input5.userPanel) {
|
|
6804
|
+
return { from: "/", to: input5.pricingPath ?? "/account" };
|
|
6805
|
+
}
|
|
6806
|
+
return void 0;
|
|
6807
|
+
}
|
|
6808
|
+
|
|
6809
|
+
// src/config/v2/portal-profile.ts
|
|
6810
|
+
var NOT_BUILT = {
|
|
6811
|
+
enabled: false,
|
|
6812
|
+
docs: { enabled: false, provider: "apitogo", content: [] },
|
|
6813
|
+
console: { enabled: false },
|
|
6814
|
+
pipelines: { markdown: false, openapi: false, search: "none" },
|
|
6815
|
+
modules: { docs: false, userPanel: false }
|
|
6816
|
+
};
|
|
6817
|
+
function portalOnlyLinksExternalDocs(resolved) {
|
|
6818
|
+
const portal = resolved.portal;
|
|
6819
|
+
if (!portal?.enabled) return false;
|
|
6820
|
+
if (!portal.docs.enabled || portal.docs.provider !== "external") return false;
|
|
6821
|
+
const consoleFed = portal.console.enabled && (resolved.identity?.enabled === true || resolved.plans?.enabled === true);
|
|
6822
|
+
return !consoleFed;
|
|
6823
|
+
}
|
|
6824
|
+
function portalProfile(resolved) {
|
|
6825
|
+
const portal = resolved.portal;
|
|
6826
|
+
if (!portal?.enabled) return NOT_BUILT;
|
|
6827
|
+
const hostsDocs = portal.docs.enabled && portal.docs.provider === "apitogo";
|
|
6828
|
+
const externalDocs = portal.docs.enabled && portal.docs.provider === "external";
|
|
6829
|
+
const gatewayOn2 = resolved.gateway?.enabled === true;
|
|
6830
|
+
return {
|
|
6831
|
+
enabled: true,
|
|
6832
|
+
docs: {
|
|
6833
|
+
enabled: portal.docs.enabled,
|
|
6834
|
+
provider: portal.docs.provider,
|
|
6835
|
+
content: hostsDocs ? portal.docs.content : [],
|
|
6836
|
+
url: externalDocs ? portal.docs.url : void 0
|
|
6837
|
+
},
|
|
6838
|
+
console: { enabled: portal.console.enabled },
|
|
6839
|
+
pipelines: {
|
|
6840
|
+
markdown: hostsDocs,
|
|
6841
|
+
openapi: hostsDocs && gatewayOn2,
|
|
6842
|
+
search: hostsDocs ? portal.search : "none"
|
|
6843
|
+
},
|
|
6844
|
+
modules: { docs: hostsDocs, userPanel: portal.console.enabled },
|
|
6845
|
+
...externalDocs ? {
|
|
6846
|
+
externalDocs: {
|
|
6847
|
+
url: portal.docs.url,
|
|
6848
|
+
openapiExport: gatewayOn2,
|
|
6849
|
+
cors: portal.console.enabled,
|
|
6850
|
+
consoleLinksInManifest: portal.console.enabled,
|
|
6851
|
+
whiteLabelConsole: portal.console.enabled
|
|
6852
|
+
}
|
|
6853
|
+
} : {}
|
|
6854
|
+
};
|
|
6855
|
+
}
|
|
6856
|
+
|
|
6857
|
+
// src/config/v2/tsx-pages.ts
|
|
6858
|
+
import { readFile as readFile4 } from "node:fs/promises";
|
|
6859
|
+
import path10 from "node:path";
|
|
6860
|
+
import { glob as glob2 } from "glob";
|
|
6861
|
+
import globParent2 from "glob-parent";
|
|
6862
|
+
|
|
6699
6863
|
// src/config/v2/docs-navigation.ts
|
|
6700
6864
|
var DOCS_NAVIGATION_LABEL = "Documentation";
|
|
6701
6865
|
var emptyBranch = () => ({ pages: /* @__PURE__ */ new Map(), folders: /* @__PURE__ */ new Map() });
|
|
@@ -6766,7 +6930,7 @@ function docsNavigation(routes, customPages = [], orders = /* @__PURE__ */ new M
|
|
|
6766
6930
|
}
|
|
6767
6931
|
|
|
6768
6932
|
// src/config/v2/tsx-pages.ts
|
|
6769
|
-
var
|
|
6933
|
+
var IGNORED2 = ["**/node_modules/**", "**/dist/**", "**/.git/**"];
|
|
6770
6934
|
function isTsxHelper(relative) {
|
|
6771
6935
|
return relative.split("/").some((part) => part.startsWith("_")) || /\.(test|spec|stories)\.tsx$/.test(relative) || relative.split("/").includes("node_modules");
|
|
6772
6936
|
}
|
|
@@ -6777,7 +6941,7 @@ function tsxPagePatterns(contentGlobs) {
|
|
|
6777
6941
|
return [
|
|
6778
6942
|
...new Set(
|
|
6779
6943
|
included.map(
|
|
6780
|
-
(pattern) =>
|
|
6944
|
+
(pattern) => path10.posix.join(globParent2(pattern), "**", "*.tsx")
|
|
6781
6945
|
)
|
|
6782
6946
|
),
|
|
6783
6947
|
...excluded
|
|
@@ -6787,21 +6951,21 @@ var TITLE = /export\s+const\s+title\s*(?::\s*string\s*)?=\s*(["'`])((?:\\.|(?!\1
|
|
|
6787
6951
|
function tsxPageLabel(source, file) {
|
|
6788
6952
|
const match = TITLE.exec(source);
|
|
6789
6953
|
if (match?.[2]) return match[2].replace(/\\(.)/g, "$1");
|
|
6790
|
-
const name =
|
|
6954
|
+
const name = path10.basename(file, ".tsx");
|
|
6791
6955
|
return folderLabel(
|
|
6792
|
-
name === "index" ?
|
|
6956
|
+
name === "index" ? path10.basename(path10.dirname(file)) : name
|
|
6793
6957
|
);
|
|
6794
6958
|
}
|
|
6795
6959
|
async function findTsxPages(contentGlobs) {
|
|
6796
6960
|
const patterns = tsxPagePatterns(contentGlobs);
|
|
6797
6961
|
const ignore2 = [
|
|
6798
|
-
...
|
|
6962
|
+
...IGNORED2,
|
|
6799
6963
|
...patterns.filter((pattern) => pattern.startsWith("!")).map((pattern) => pattern.slice(1))
|
|
6800
6964
|
];
|
|
6801
6965
|
const found = /* @__PURE__ */ new Map();
|
|
6802
6966
|
for (const pattern of patterns.filter((p) => !p.startsWith("!"))) {
|
|
6803
|
-
const parent =
|
|
6804
|
-
const files = await
|
|
6967
|
+
const parent = globParent2(pattern);
|
|
6968
|
+
const files = await glob2(pattern, {
|
|
6805
6969
|
absolute: true,
|
|
6806
6970
|
posix: true,
|
|
6807
6971
|
nodir: true,
|
|
@@ -6809,11 +6973,11 @@ async function findTsxPages(contentGlobs) {
|
|
|
6809
6973
|
});
|
|
6810
6974
|
for (const raw of files.sort()) {
|
|
6811
6975
|
const file = raw.replace(/^\/\/\?\//, "");
|
|
6812
|
-
const relative =
|
|
6976
|
+
const relative = path10.posix.relative(parent, file);
|
|
6813
6977
|
if (isTsxHelper(relative)) continue;
|
|
6814
6978
|
const route = `/${relative.replace(/\.tsx$/, "")}`;
|
|
6815
6979
|
if (found.has(route)) continue;
|
|
6816
|
-
const source = await
|
|
6980
|
+
const source = await readFile4(file, "utf8").catch(() => "");
|
|
6817
6981
|
const order = tsxPageOrder(source);
|
|
6818
6982
|
found.set(route, {
|
|
6819
6983
|
route,
|
|
@@ -6857,11 +7021,11 @@ function collectSecretRefs(config2) {
|
|
|
6857
7021
|
return found;
|
|
6858
7022
|
}
|
|
6859
7023
|
function dependencyRules(config2, resolved, out) {
|
|
6860
|
-
const
|
|
7024
|
+
const gatewayOn2 = resolved.gateway?.enabled === true;
|
|
6861
7025
|
const identityOn = resolved.identity?.enabled === true;
|
|
6862
|
-
const oidcGateway =
|
|
7026
|
+
const oidcGateway = gatewayOn2 && resolved.gateway?.auth?.mode === "oidc";
|
|
6863
7027
|
const hasIdentitySource = identityOn || oidcGateway;
|
|
6864
|
-
if (identityOn && resolved.portal?.enabled !== true && !
|
|
7028
|
+
if (identityOn && resolved.portal?.enabled !== true && !gatewayOn2 && !resolved.project.id) {
|
|
6865
7029
|
out.error({
|
|
6866
7030
|
code: "NOTHING_TO_HOST",
|
|
6867
7031
|
path: "identity",
|
|
@@ -6878,7 +7042,7 @@ function dependencyRules(config2, resolved, out) {
|
|
|
6878
7042
|
});
|
|
6879
7043
|
}
|
|
6880
7044
|
if (resolved.plans?.enabled) {
|
|
6881
|
-
if (!
|
|
7045
|
+
if (!gatewayOn2) {
|
|
6882
7046
|
out.error({
|
|
6883
7047
|
code: "PLANS_GATEWAY_REQUIRED",
|
|
6884
7048
|
path: "plans",
|
|
@@ -6974,44 +7138,53 @@ async function portalRules(config2, resolved, out) {
|
|
|
6974
7138
|
hint: "Enable identity or plans, or enable portal.docs."
|
|
6975
7139
|
});
|
|
6976
7140
|
}
|
|
7141
|
+
if (portalOnlyLinksExternalDocs(resolved)) {
|
|
7142
|
+
out.warn({
|
|
7143
|
+
code: "PORTAL_NOTHING_TO_HOST",
|
|
7144
|
+
path: "portal",
|
|
7145
|
+
message: "docs are on an external site and no service feeds the console, so there is no portal to host: `project create` takes no website hosting for it and `deploy` skips it.",
|
|
7146
|
+
hint: "Enable identity or plans for a console next to your docs, or remove the portal section."
|
|
7147
|
+
});
|
|
7148
|
+
}
|
|
6977
7149
|
if (portal.footer && !await isFile(portal.footer))
|
|
6978
7150
|
out.error({
|
|
6979
7151
|
code: "PORTAL_FILE_MISSING",
|
|
6980
7152
|
path: "portal.footer",
|
|
6981
|
-
message: `the file ${
|
|
7153
|
+
message: `the file ${path11.relative(resolved.configDir, portal.footer)} does not exist.`,
|
|
6982
7154
|
hint: "Create it, or remove portal.footer."
|
|
6983
7155
|
});
|
|
6984
|
-
|
|
7156
|
+
await headerLinksRule(portal, resolved, out);
|
|
7157
|
+
const publicDir = path11.join(portal.dir, "public");
|
|
6985
7158
|
for (const file of new Set(
|
|
6986
7159
|
[portal.logo?.light, portal.logo?.dark].filter(
|
|
6987
7160
|
(value) => !!value && !isLogoUrl(value)
|
|
6988
7161
|
)
|
|
6989
7162
|
)) {
|
|
6990
|
-
const inside =
|
|
6991
|
-
if (inside.startsWith("..") ||
|
|
7163
|
+
const inside = path11.relative(publicDir, file);
|
|
7164
|
+
if (inside.startsWith("..") || path11.isAbsolute(inside))
|
|
6992
7165
|
out.error({
|
|
6993
7166
|
code: "PORTAL_LOGO_OUTSIDE_PUBLIC",
|
|
6994
7167
|
path: "portal.logo",
|
|
6995
|
-
message: `the logo ${
|
|
6996
|
-
hint: `Move it into ${
|
|
7168
|
+
message: `the logo ${path11.relative(resolved.configDir, file)} is not in the portal's public folder, which is what the site serves.`,
|
|
7169
|
+
hint: `Move it into ${path11.relative(resolved.configDir, publicDir)}/, or use an https:// address.`
|
|
6997
7170
|
});
|
|
6998
7171
|
else if (!await isFile(file))
|
|
6999
7172
|
out.error({
|
|
7000
7173
|
code: "PORTAL_FILE_MISSING",
|
|
7001
7174
|
path: "portal.logo",
|
|
7002
|
-
message: `the file ${
|
|
7175
|
+
message: `the file ${path11.relative(resolved.configDir, file)} does not exist.`,
|
|
7003
7176
|
hint: "Create it, or remove portal.logo."
|
|
7004
7177
|
});
|
|
7005
7178
|
}
|
|
7006
7179
|
if (await isFile(portal.theme)) {
|
|
7007
7180
|
try {
|
|
7008
|
-
JSON.parse(await
|
|
7181
|
+
JSON.parse(await readFile5(portal.theme, "utf8"));
|
|
7009
7182
|
} catch (error) {
|
|
7010
7183
|
out.error({
|
|
7011
7184
|
code: "PORTAL_THEME_INVALID",
|
|
7012
7185
|
path: "portal.theme",
|
|
7013
7186
|
message: `the theme file is not valid JSON (${error instanceof Error ? error.message : String(error)}).`,
|
|
7014
|
-
hint:
|
|
7187
|
+
hint: path11.relative(resolved.configDir, portal.theme)
|
|
7015
7188
|
});
|
|
7016
7189
|
}
|
|
7017
7190
|
}
|
|
@@ -7020,12 +7193,21 @@ async function docsContentRule(config2, patterns, resolved, out) {
|
|
|
7020
7193
|
const globs = patterns.map(toGlobPath);
|
|
7021
7194
|
const include = globs.filter((pattern) => !pattern.startsWith("!"));
|
|
7022
7195
|
const ignore2 = globs.filter((pattern) => pattern.startsWith("!")).map((pattern) => pattern.slice(1));
|
|
7023
|
-
const matches = include.length > 0 ? await
|
|
7196
|
+
const matches = include.length > 0 ? await glob3(include, { nodir: true, ignore: ignore2, absolute: true }) : [];
|
|
7024
7197
|
if (matches.length > 0) return;
|
|
7025
7198
|
if ((await findTsxPages(patterns)).length > 0) return;
|
|
7026
7199
|
const shown = config2.portal?.docs?.content ?? [
|
|
7027
|
-
|
|
7200
|
+
path11.relative(resolved.configDir, patterns[0] ?? "")
|
|
7028
7201
|
];
|
|
7202
|
+
if (portalHasNothingToShow(resolved)) {
|
|
7203
|
+
out.error({
|
|
7204
|
+
code: "PORTAL_HOME_EMPTY",
|
|
7205
|
+
path: "portal.docs",
|
|
7206
|
+
message: `portal.docs matched 0 files (${shown.join(", ")}), and the portal has no API reference, console pages or home page of its own, so its home page would say "Page not found".`,
|
|
7207
|
+
hint: "Add a .md or .mdx page there (for example introduction.mdx), point docs.content at your existing docs, or enable the gateway with an OpenAPI file for an API reference."
|
|
7208
|
+
});
|
|
7209
|
+
return;
|
|
7210
|
+
}
|
|
7029
7211
|
out.warn({
|
|
7030
7212
|
code: "PORTAL_DOCS_EMPTY",
|
|
7031
7213
|
path: "portal.docs",
|
|
@@ -7033,6 +7215,84 @@ async function docsContentRule(config2, patterns, resolved, out) {
|
|
|
7033
7215
|
hint: "Add .md, .mdx or .tsx pages, or point docs.content at your existing docs."
|
|
7034
7216
|
});
|
|
7035
7217
|
}
|
|
7218
|
+
function portalHasNothingToShow(resolved) {
|
|
7219
|
+
const portal = resolved.portal;
|
|
7220
|
+
if (!portal?.enabled || portal.landing) return false;
|
|
7221
|
+
if (resolved.gateway?.enabled === true) return false;
|
|
7222
|
+
const consoleFed = portal.console.enabled && (resolved.identity?.enabled === true || resolved.plans?.enabled === true);
|
|
7223
|
+
return !consoleFed;
|
|
7224
|
+
}
|
|
7225
|
+
var RESERVED_HEADER_ROUTES = [
|
|
7226
|
+
"/",
|
|
7227
|
+
"/index",
|
|
7228
|
+
"/api",
|
|
7229
|
+
"/pricing",
|
|
7230
|
+
"/account",
|
|
7231
|
+
"/login",
|
|
7232
|
+
"/signup"
|
|
7233
|
+
];
|
|
7234
|
+
async function headerLinksRule(portal, resolved, out) {
|
|
7235
|
+
const pages = portal.headerLinks.map((link, index) => ({ link, index })).filter(({ link }) => link.page !== void 0);
|
|
7236
|
+
if (pages.length === 0) return;
|
|
7237
|
+
const hostsDocs = portal.docs.enabled && portal.docs.provider === "apitogo";
|
|
7238
|
+
const docs = hostsDocs ? [
|
|
7239
|
+
...await docRoutes(portal.docs.content, { includeDrafts: true }),
|
|
7240
|
+
...(await findTsxPages(portal.docs.content)).map((page) => page.route)
|
|
7241
|
+
] : [];
|
|
7242
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7243
|
+
for (const { link, index } of pages) {
|
|
7244
|
+
const file = link.page;
|
|
7245
|
+
const at = `portal.header.links[${index}].page`;
|
|
7246
|
+
const shown = path11.relative(resolved.configDir, file);
|
|
7247
|
+
if (!hostsDocs) {
|
|
7248
|
+
out.error({
|
|
7249
|
+
code: "PORTAL_HEADER_PAGE_NO_DOCS",
|
|
7250
|
+
path: at,
|
|
7251
|
+
message: `the header page ${shown} needs hosted docs, which this portal does not have.`,
|
|
7252
|
+
hint: 'Header pages are served with the docs pages: set portal.docs.provider to "apitogo", or link an address with "to" instead.'
|
|
7253
|
+
});
|
|
7254
|
+
continue;
|
|
7255
|
+
}
|
|
7256
|
+
if (!/\.(mdx?|tsx)$/i.test(file)) {
|
|
7257
|
+
out.error({
|
|
7258
|
+
code: "PORTAL_HEADER_PAGE_INVALID",
|
|
7259
|
+
path: at,
|
|
7260
|
+
message: `the header page ${shown} is neither a React page nor a Markdown page.`,
|
|
7261
|
+
hint: "Use a .tsx file (its default export is the page) or a .md / .mdx file."
|
|
7262
|
+
});
|
|
7263
|
+
continue;
|
|
7264
|
+
}
|
|
7265
|
+
if (!await isFile(file)) {
|
|
7266
|
+
out.error({
|
|
7267
|
+
code: "PORTAL_FILE_MISSING",
|
|
7268
|
+
path: at,
|
|
7269
|
+
message: `the file ${shown} does not exist.`,
|
|
7270
|
+
hint: "Create it (`apitogo config --page-slug <name> --page-title <title> --page-header`), or remove the link."
|
|
7271
|
+
});
|
|
7272
|
+
continue;
|
|
7273
|
+
}
|
|
7274
|
+
const route = link.to;
|
|
7275
|
+
if (RESERVED_HEADER_ROUTES.includes(route.toLowerCase())) {
|
|
7276
|
+
out.error({
|
|
7277
|
+
code: "PORTAL_HEADER_PAGE_ROUTE_TAKEN",
|
|
7278
|
+
path: at,
|
|
7279
|
+
message: `the header page ${shown} would be served at ${route}, which the portal uses itself.`,
|
|
7280
|
+
hint: "Rename the file: its name is the page's address."
|
|
7281
|
+
});
|
|
7282
|
+
continue;
|
|
7283
|
+
}
|
|
7284
|
+
if (docs.includes(route) || seen.has(route)) {
|
|
7285
|
+
out.error({
|
|
7286
|
+
code: "PORTAL_HEADER_PAGE_ROUTE_TAKEN",
|
|
7287
|
+
path: at,
|
|
7288
|
+
message: `the header page ${shown} would be served at ${route}, which another page already has.`,
|
|
7289
|
+
hint: `Rename the file: its name is the page's address. A docs page that should be in the header too can be linked with "to" instead.`
|
|
7290
|
+
});
|
|
7291
|
+
continue;
|
|
7292
|
+
}
|
|
7293
|
+
seen.add(route);
|
|
7294
|
+
}
|
|
7295
|
+
}
|
|
7036
7296
|
function isIpLiteral(hostname) {
|
|
7037
7297
|
return /^\d{1,3}(\.\d{1,3}){3}$/.test(hostname) || hostname.startsWith("[");
|
|
7038
7298
|
}
|
|
@@ -7097,8 +7357,8 @@ async function gatewayRules(resolved, out) {
|
|
|
7097
7357
|
}
|
|
7098
7358
|
}
|
|
7099
7359
|
if (origin.source) {
|
|
7100
|
-
const inside =
|
|
7101
|
-
if (inside.startsWith("..") ||
|
|
7360
|
+
const inside = path11.relative(resolved.configDir, origin.source);
|
|
7361
|
+
if (inside.startsWith("..") || path11.isAbsolute(inside)) {
|
|
7102
7362
|
out.error({
|
|
7103
7363
|
code: "GATEWAY_ORIGIN_INVALID",
|
|
7104
7364
|
path: "gateway.origin.source",
|
|
@@ -7183,7 +7443,7 @@ async function gatewayRules(resolved, out) {
|
|
|
7183
7443
|
}
|
|
7184
7444
|
async function specRule(spec, index, resolved, out) {
|
|
7185
7445
|
const at = `gateway.specs[${index}]`;
|
|
7186
|
-
const shown =
|
|
7446
|
+
const shown = path11.relative(resolved.configDir, spec);
|
|
7187
7447
|
const info = await stat2(spec).catch(() => void 0);
|
|
7188
7448
|
if (!info?.isFile()) {
|
|
7189
7449
|
out.error({
|
|
@@ -7203,7 +7463,7 @@ async function specRule(spec, index, resolved, out) {
|
|
|
7203
7463
|
}
|
|
7204
7464
|
let document;
|
|
7205
7465
|
try {
|
|
7206
|
-
const text2 = await
|
|
7466
|
+
const text2 = await readFile5(spec, "utf8");
|
|
7207
7467
|
document = spec.toLowerCase().endsWith(".json") ? JSON.parse(text2) : parseYaml(text2);
|
|
7208
7468
|
} catch (error) {
|
|
7209
7469
|
out.error({
|
|
@@ -7352,12 +7612,12 @@ async function plansRules(resolved, out, paid) {
|
|
|
7352
7612
|
out.error({
|
|
7353
7613
|
code: "PLANS_FILE_INVALID",
|
|
7354
7614
|
path: "plans.file",
|
|
7355
|
-
message: `the plan catalog was not found: ${
|
|
7615
|
+
message: `the plan catalog was not found: ${path11.relative(resolved.configDir, plans.file)}.`,
|
|
7356
7616
|
hint: "Create it with `apitogo add plans`."
|
|
7357
7617
|
});
|
|
7358
7618
|
} else {
|
|
7359
7619
|
try {
|
|
7360
|
-
JSON.parse(await
|
|
7620
|
+
JSON.parse(await readFile5(plans.file, "utf8"));
|
|
7361
7621
|
} catch (error) {
|
|
7362
7622
|
out.error({
|
|
7363
7623
|
code: "PLANS_FILE_INVALID",
|
|
@@ -7431,50 +7691,9 @@ async function checkConfigV2(config2, resolved, context = {}) {
|
|
|
7431
7691
|
return { errors, warnings, skipped };
|
|
7432
7692
|
}
|
|
7433
7693
|
|
|
7434
|
-
// src/config/v2/portal-profile.ts
|
|
7435
|
-
var NOT_BUILT = {
|
|
7436
|
-
enabled: false,
|
|
7437
|
-
docs: { enabled: false, provider: "apitogo", content: [] },
|
|
7438
|
-
console: { enabled: false },
|
|
7439
|
-
pipelines: { markdown: false, openapi: false, search: "none" },
|
|
7440
|
-
modules: { docs: false, userPanel: false }
|
|
7441
|
-
};
|
|
7442
|
-
function portalProfile(resolved) {
|
|
7443
|
-
const portal = resolved.portal;
|
|
7444
|
-
if (!portal?.enabled) return NOT_BUILT;
|
|
7445
|
-
const hostsDocs = portal.docs.enabled && portal.docs.provider === "apitogo";
|
|
7446
|
-
const externalDocs = portal.docs.enabled && portal.docs.provider === "external";
|
|
7447
|
-
const gatewayOn = resolved.gateway?.enabled === true;
|
|
7448
|
-
return {
|
|
7449
|
-
enabled: true,
|
|
7450
|
-
docs: {
|
|
7451
|
-
enabled: portal.docs.enabled,
|
|
7452
|
-
provider: portal.docs.provider,
|
|
7453
|
-
content: hostsDocs ? portal.docs.content : [],
|
|
7454
|
-
url: externalDocs ? portal.docs.url : void 0
|
|
7455
|
-
},
|
|
7456
|
-
console: { enabled: portal.console.enabled },
|
|
7457
|
-
pipelines: {
|
|
7458
|
-
markdown: hostsDocs,
|
|
7459
|
-
openapi: hostsDocs && gatewayOn,
|
|
7460
|
-
search: hostsDocs ? portal.search : "none"
|
|
7461
|
-
},
|
|
7462
|
-
modules: { docs: hostsDocs, userPanel: portal.console.enabled },
|
|
7463
|
-
...externalDocs ? {
|
|
7464
|
-
externalDocs: {
|
|
7465
|
-
url: portal.docs.url,
|
|
7466
|
-
openapiExport: gatewayOn,
|
|
7467
|
-
cors: portal.console.enabled,
|
|
7468
|
-
consoleLinksInManifest: portal.console.enabled,
|
|
7469
|
-
whiteLabelConsole: portal.console.enabled
|
|
7470
|
-
}
|
|
7471
|
-
} : {}
|
|
7472
|
-
};
|
|
7473
|
-
}
|
|
7474
|
-
|
|
7475
7694
|
// src/config/v2/manifest.ts
|
|
7476
|
-
import { mkdir as mkdir3, readFile as
|
|
7477
|
-
import
|
|
7695
|
+
import { mkdir as mkdir3, readFile as readFile6, rename, rm, writeFile as writeFile4 } from "node:fs/promises";
|
|
7696
|
+
import path12 from "node:path";
|
|
7478
7697
|
import { z as z3 } from "zod";
|
|
7479
7698
|
var SUPPORTED_MANIFEST_SCHEMA = 1;
|
|
7480
7699
|
var Capabilities = z3.record(z3.string(), z3.boolean()).default({});
|
|
@@ -7525,7 +7744,7 @@ var ServiceManifestSchema = z3.looseObject({
|
|
|
7525
7744
|
}).optional()
|
|
7526
7745
|
}).default({})
|
|
7527
7746
|
});
|
|
7528
|
-
var issue = (code,
|
|
7747
|
+
var issue = (code, path100, message, hint) => ({ code, path: path100, message, hint });
|
|
7529
7748
|
function parseManifest(raw, file = "services.json") {
|
|
7530
7749
|
const version = typeof raw === "object" && raw !== null && "schemaVersion" in raw ? raw.schemaVersion : void 0;
|
|
7531
7750
|
if (typeof version === "number" && version > SUPPORTED_MANIFEST_SCHEMA) {
|
|
@@ -7558,7 +7777,7 @@ async function readManifest(state) {
|
|
|
7558
7777
|
const file = manifestPathFor(state);
|
|
7559
7778
|
let text2;
|
|
7560
7779
|
try {
|
|
7561
|
-
text2 = await
|
|
7780
|
+
text2 = await readFile6(file, "utf8");
|
|
7562
7781
|
} catch (error) {
|
|
7563
7782
|
if (error.code === "ENOENT") return void 0;
|
|
7564
7783
|
throw error;
|
|
@@ -7590,10 +7809,10 @@ function requiredServices(resolved) {
|
|
|
7590
7809
|
if (!portal?.enabled) return [];
|
|
7591
7810
|
const needs = [];
|
|
7592
7811
|
const consoleOn = portal.console.enabled;
|
|
7593
|
-
const
|
|
7812
|
+
const gatewayOn2 = resolved.gateway?.enabled === true;
|
|
7594
7813
|
const identityOn = resolved.identity?.enabled === true;
|
|
7595
7814
|
if (identityOn && (consoleOn || portal.requireAuth)) needs.push("identity");
|
|
7596
|
-
if (
|
|
7815
|
+
if (gatewayOn2 && (consoleOn || portal.docs.enabled)) needs.push("gateway");
|
|
7597
7816
|
if (resolved.plans?.enabled === true && consoleOn) needs.push("plans");
|
|
7598
7817
|
return needs;
|
|
7599
7818
|
}
|
|
@@ -7756,7 +7975,7 @@ function withPlansEntry(existing, info) {
|
|
|
7756
7975
|
}
|
|
7757
7976
|
async function writeManifest(state, manifest) {
|
|
7758
7977
|
const file = manifestPathFor(state);
|
|
7759
|
-
await mkdir3(
|
|
7978
|
+
await mkdir3(path12.dirname(file), { recursive: true });
|
|
7760
7979
|
const temporary = `${file}.${process.pid}.tmp`;
|
|
7761
7980
|
try {
|
|
7762
7981
|
await writeFile4(
|
|
@@ -7787,8 +8006,8 @@ async function removeServicesFromManifest(state, names) {
|
|
|
7787
8006
|
}
|
|
7788
8007
|
|
|
7789
8008
|
// src/config/v2/gateway-reference.ts
|
|
7790
|
-
import { readFile as
|
|
7791
|
-
import { parse } from "yaml";
|
|
8009
|
+
import { readFile as readFile7 } from "node:fs/promises";
|
|
8010
|
+
import { parse as parse2 } from "yaml";
|
|
7792
8011
|
var DEFAULT_KEY_HEADER = "X-API-Key";
|
|
7793
8012
|
var KEY_HEADER_EXTENSION = "x-apitogo-key-header";
|
|
7794
8013
|
var METHODS = [
|
|
@@ -7802,8 +8021,8 @@ var METHODS = [
|
|
|
7802
8021
|
"trace"
|
|
7803
8022
|
];
|
|
7804
8023
|
var isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7805
|
-
function actionKey(method,
|
|
7806
|
-
const trimmed =
|
|
8024
|
+
function actionKey(method, path100) {
|
|
8025
|
+
const trimmed = path100.trim();
|
|
7807
8026
|
const withSlash = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
7808
8027
|
const normalized = withSlash.length > 1 ? withSlash.replace(/\/+$/, "") || "/" : withSlash;
|
|
7809
8028
|
return `${method.trim().toLowerCase()}:${normalized}`;
|
|
@@ -7840,15 +8059,15 @@ var ReferenceSpecError = class extends Error {
|
|
|
7840
8059
|
};
|
|
7841
8060
|
function operationsOf(paths) {
|
|
7842
8061
|
return Object.entries(paths).flatMap(
|
|
7843
|
-
([
|
|
7844
|
-
(method) => [
|
|
8062
|
+
([path100, item]) => isObject(item) ? METHODS.filter((method) => isObject(item[method])).map(
|
|
8063
|
+
(method) => [path100, item, method]
|
|
7845
8064
|
) : []
|
|
7846
8065
|
);
|
|
7847
8066
|
}
|
|
7848
8067
|
function buildReferenceSpec(specText, options) {
|
|
7849
8068
|
let root;
|
|
7850
8069
|
try {
|
|
7851
|
-
root =
|
|
8070
|
+
root = parse2(specText);
|
|
7852
8071
|
} catch {
|
|
7853
8072
|
throw new ReferenceSpecError("The OpenAPI file could not be read.");
|
|
7854
8073
|
}
|
|
@@ -7856,14 +8075,14 @@ function buildReferenceSpec(specText, options) {
|
|
|
7856
8075
|
throw new ReferenceSpecError("The OpenAPI file could not be read.");
|
|
7857
8076
|
const doc = structuredClone(root);
|
|
7858
8077
|
const paths = isObject(doc.paths) ? doc.paths : {};
|
|
7859
|
-
for (const [
|
|
7860
|
-
if (options.deniedOperations.has(actionKey(method,
|
|
8078
|
+
for (const [path100, item, method] of operationsOf(paths))
|
|
8079
|
+
if (options.deniedOperations.has(actionKey(method, path100)))
|
|
7861
8080
|
delete item[method];
|
|
7862
|
-
for (const [
|
|
8081
|
+
for (const [path100, item] of Object.entries(paths))
|
|
7863
8082
|
if (!isObject(item) || !METHODS.some((method) => method in item))
|
|
7864
|
-
delete paths[
|
|
7865
|
-
for (const [
|
|
7866
|
-
if (options.publicOperations.has(actionKey(method,
|
|
8083
|
+
delete paths[path100];
|
|
8084
|
+
for (const [path100, item, method] of operationsOf(paths))
|
|
8085
|
+
if (options.publicOperations.has(actionKey(method, path100)))
|
|
7867
8086
|
item[method].security = [];
|
|
7868
8087
|
doc.servers = [{ url: options.gatewayBaseUrl.replace(/\/+$/, "") }];
|
|
7869
8088
|
for (const item of Object.values(paths)) {
|
|
@@ -7903,11 +8122,11 @@ function buildReferenceSpec(specText, options) {
|
|
|
7903
8122
|
if (Object.keys(components).length > 0) doc.components = components;
|
|
7904
8123
|
else delete doc.components;
|
|
7905
8124
|
doc.security = Object.keys(requirement).length > 0 ? [requirement] : [];
|
|
7906
|
-
for (const [
|
|
8125
|
+
for (const [path100, item, method] of operationsOf(paths)) {
|
|
7907
8126
|
const operation = item[method];
|
|
7908
8127
|
if (Array.isArray(operation.security) && operation.security.length > 0)
|
|
7909
8128
|
delete operation.security;
|
|
7910
|
-
if (options.apiKeyRequired && !options.publicOperations.has(actionKey(method,
|
|
8129
|
+
if (options.apiKeyRequired && !options.publicOperations.has(actionKey(method, path100)))
|
|
7911
8130
|
operation[KEY_HEADER_EXTENSION] = options.apiKeyHeader;
|
|
7912
8131
|
else delete operation[KEY_HEADER_EXTENSION];
|
|
7913
8132
|
}
|
|
@@ -7929,7 +8148,7 @@ async function renderReferenceSpec(gateway, gatewayBaseUrl, keyHeaderName) {
|
|
|
7929
8148
|
throw new ReferenceSpecError("gateway.specs lists no OpenAPI file.");
|
|
7930
8149
|
let text2;
|
|
7931
8150
|
try {
|
|
7932
|
-
text2 = await
|
|
8151
|
+
text2 = await readFile7(file, "utf8");
|
|
7933
8152
|
} catch {
|
|
7934
8153
|
throw new ReferenceSpecError(`Cannot read the OpenAPI file ${file}.`);
|
|
7935
8154
|
}
|
|
@@ -8006,7 +8225,7 @@ import path14 from "node:path";
|
|
|
8006
8225
|
|
|
8007
8226
|
// src/cli/platform/helpers/openapi-action-keys.ts
|
|
8008
8227
|
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
|
|
8009
|
-
import
|
|
8228
|
+
import path13 from "node:path";
|
|
8010
8229
|
import YAML from "yaml";
|
|
8011
8230
|
var HTTP_METHODS = [
|
|
8012
8231
|
"get",
|
|
@@ -8075,7 +8294,7 @@ function extractGatewayActionKeysFromOpenApiDocument(document) {
|
|
|
8075
8294
|
function extractGatewayActionKeysFromOpenApiFile(filePath) {
|
|
8076
8295
|
try {
|
|
8077
8296
|
const raw = readFileSync3(filePath, "utf8");
|
|
8078
|
-
const ext =
|
|
8297
|
+
const ext = path13.extname(filePath).toLowerCase();
|
|
8079
8298
|
const parsed = ext === ".json" ? JSON.parse(raw) : YAML.parse(raw);
|
|
8080
8299
|
return extractGatewayActionKeysFromOpenApiDocument(parsed);
|
|
8081
8300
|
} catch {
|
|
@@ -8083,92 +8302,6 @@ function extractGatewayActionKeysFromOpenApiFile(filePath) {
|
|
|
8083
8302
|
}
|
|
8084
8303
|
}
|
|
8085
8304
|
|
|
8086
|
-
// src/config/v2/home-redirect.ts
|
|
8087
|
-
import path13 from "node:path";
|
|
8088
|
-
import { glob as glob3 } from "glob";
|
|
8089
|
-
import globParent2 from "glob-parent";
|
|
8090
|
-
|
|
8091
|
-
// src/lib/util/readFrontmatter.ts
|
|
8092
|
-
import { readFile as readFile7 } from "node:fs/promises";
|
|
8093
|
-
import matter from "gray-matter";
|
|
8094
|
-
import { parse as parse2, stringify } from "yaml";
|
|
8095
|
-
var yaml = {
|
|
8096
|
-
parse: (input5) => parse2(input5) ?? {},
|
|
8097
|
-
stringify: (obj) => stringify(obj)
|
|
8098
|
-
};
|
|
8099
|
-
var readFrontmatter = async (filePath) => {
|
|
8100
|
-
const content = await readFile7(filePath, "utf-8");
|
|
8101
|
-
const normalizedContent = content.replace(/\r\n/g, "\n");
|
|
8102
|
-
return matter(normalizedContent, { engines: { yaml } });
|
|
8103
|
-
};
|
|
8104
|
-
|
|
8105
|
-
// src/config/v2/home-redirect.ts
|
|
8106
|
-
var IGNORED2 = ["**/node_modules/**", "**/dist/**", "**/.git/**"];
|
|
8107
|
-
async function docRoutes(patterns, options = {}) {
|
|
8108
|
-
const globs = patterns.map(toGlobPath);
|
|
8109
|
-
const excluded = globs.filter((pattern) => pattern.startsWith("!")).map((pattern) => pattern.slice(1));
|
|
8110
|
-
const included = globs.filter((pattern) => !pattern.startsWith("!"));
|
|
8111
|
-
const routes = await Promise.all(
|
|
8112
|
-
included.map(async (pattern) => {
|
|
8113
|
-
const files = await glob3(pattern, {
|
|
8114
|
-
absolute: true,
|
|
8115
|
-
posix: true,
|
|
8116
|
-
ignore: [...IGNORED2, ...excluded]
|
|
8117
|
-
});
|
|
8118
|
-
const parent = globParent2(pattern);
|
|
8119
|
-
const published = options.includeDrafts ? files : (await Promise.all(
|
|
8120
|
-
files.map(async (file) => ({
|
|
8121
|
-
file,
|
|
8122
|
-
draft: (await readFrontmatter(file)).data.draft === true
|
|
8123
|
-
}))
|
|
8124
|
-
)).filter(({ draft }) => !draft).map(({ file }) => file);
|
|
8125
|
-
return published.map(
|
|
8126
|
-
(file) => `/${path13.posix.relative(parent, file.replace(/^\/\/\?\//, "")).replace(/\.mdx?$/, "")}`
|
|
8127
|
-
);
|
|
8128
|
-
})
|
|
8129
|
-
);
|
|
8130
|
-
return [...new Set(routes.flat())].sort();
|
|
8131
|
-
}
|
|
8132
|
-
function pickLandingRoute(routes, orders) {
|
|
8133
|
-
return firstPage(routes, orders);
|
|
8134
|
-
}
|
|
8135
|
-
async function docPageOrders(patterns) {
|
|
8136
|
-
const globs = patterns.map(toGlobPath);
|
|
8137
|
-
const excluded = globs.filter((pattern) => pattern.startsWith("!")).map((pattern) => pattern.slice(1));
|
|
8138
|
-
const orders = /* @__PURE__ */ new Map();
|
|
8139
|
-
for (const pattern of globs.filter((p) => !p.startsWith("!"))) {
|
|
8140
|
-
const parent = globParent2(pattern);
|
|
8141
|
-
const files = await glob3(pattern, {
|
|
8142
|
-
absolute: true,
|
|
8143
|
-
posix: true,
|
|
8144
|
-
ignore: [...IGNORED2, ...excluded]
|
|
8145
|
-
});
|
|
8146
|
-
for (const raw of files) {
|
|
8147
|
-
const order = orderValue((await readFrontmatter(raw)).data.order);
|
|
8148
|
-
if (order === void 0) continue;
|
|
8149
|
-
const route = `/${path13.posix.relative(parent, raw.replace(/^\/\/\?\//, "")).replace(/\.mdx?$/, "")}`;
|
|
8150
|
-
if (!orders.has(route)) orders.set(route, order);
|
|
8151
|
-
}
|
|
8152
|
-
}
|
|
8153
|
-
return orders;
|
|
8154
|
-
}
|
|
8155
|
-
function homeRedirect(input5) {
|
|
8156
|
-
if (input5.hostsDocs) {
|
|
8157
|
-
if (input5.docRoutes.some((route) => route === "/" || route === "/index"))
|
|
8158
|
-
return void 0;
|
|
8159
|
-
const landing = pickLandingRoute(input5.docRoutes, input5.pageOrders);
|
|
8160
|
-
if (landing) return { from: "/", to: landing };
|
|
8161
|
-
return input5.apiReferencePath ? { from: "/", to: input5.apiReferencePath } : void 0;
|
|
8162
|
-
}
|
|
8163
|
-
if (input5.externalDocsUrl && !input5.userPanel) {
|
|
8164
|
-
return { from: "/", to: input5.externalDocsUrl };
|
|
8165
|
-
}
|
|
8166
|
-
if (input5.userPanel) {
|
|
8167
|
-
return { from: "/", to: input5.pricingPath ?? "/account" };
|
|
8168
|
-
}
|
|
8169
|
-
return void 0;
|
|
8170
|
-
}
|
|
8171
|
-
|
|
8172
8305
|
// src/config/v2/protected-routes.ts
|
|
8173
8306
|
function protectedRoutesFor(input5) {
|
|
8174
8307
|
const { requireAuth } = input5;
|
|
@@ -8346,11 +8479,38 @@ function planPortal(profile, manifest) {
|
|
|
8346
8479
|
var SITE_CONFIG_FILE = "apitogo.config.json";
|
|
8347
8480
|
var REFERENCE_SPEC_FILE = "openapi/gateway.json";
|
|
8348
8481
|
var API_REFERENCE_PATH = "api";
|
|
8482
|
+
var MARKDOWN_PAGE = /\.mdx?$/i;
|
|
8483
|
+
var HEADER_PAGE_ELEMENT_PREFIX = "apitogo:header-page:";
|
|
8484
|
+
function headerTsxPages(resolved, plan2) {
|
|
8485
|
+
if (!plan2.docs) return [];
|
|
8486
|
+
return (resolved.portal?.headerLinks ?? []).flatMap(
|
|
8487
|
+
(link) => link.page && /\.tsx$/i.test(link.page) ? [{ route: link.to, label: link.label, file: link.page }] : []
|
|
8488
|
+
).map((page, index) => ({
|
|
8489
|
+
...page,
|
|
8490
|
+
id: `${HEADER_PAGE_ELEMENT_PREFIX}${index}`
|
|
8491
|
+
}));
|
|
8492
|
+
}
|
|
8349
8493
|
function buildSiteConfig(resolved, plan2, theme, extras = {}) {
|
|
8350
8494
|
const portal = resolved.portal;
|
|
8351
8495
|
const redirects = extras.redirects ?? [];
|
|
8496
|
+
const headerLinks = portal?.headerLinks ?? [];
|
|
8497
|
+
const headerPages = plan2.docs ? headerLinks.flatMap(
|
|
8498
|
+
(link) => link.page && MARKDOWN_PAGE.test(link.page) ? [link.page] : []
|
|
8499
|
+
) : [];
|
|
8500
|
+
const shownHeaderLinks = headerLinks.filter((link) => !link.page || plan2.docs).map((link) => ({
|
|
8501
|
+
label: link.label,
|
|
8502
|
+
to: link.to,
|
|
8503
|
+
...link.to.startsWith("https://") ? { target: "_blank" } : {}
|
|
8504
|
+
}));
|
|
8352
8505
|
const navigation = [
|
|
8353
8506
|
...extras.docsNavigation ?? [],
|
|
8507
|
+
...headerTsxPages(resolved, plan2).map((page) => ({
|
|
8508
|
+
type: "custom-page",
|
|
8509
|
+
path: page.route,
|
|
8510
|
+
label: page.label,
|
|
8511
|
+
element: page.id,
|
|
8512
|
+
display: "hide"
|
|
8513
|
+
})),
|
|
8354
8514
|
...plan2.apiReference ? [
|
|
8355
8515
|
{
|
|
8356
8516
|
type: "link",
|
|
@@ -8389,9 +8549,10 @@ function buildSiteConfig(resolved, plan2, theme, extras = {}) {
|
|
|
8389
8549
|
},
|
|
8390
8550
|
...plan2.docs ? {
|
|
8391
8551
|
docs: {
|
|
8392
|
-
files:
|
|
8393
|
-
|
|
8394
|
-
|
|
8552
|
+
files: [
|
|
8553
|
+
...portal?.docs.content ?? [],
|
|
8554
|
+
...headerPages.map(toGlobPath)
|
|
8555
|
+
].map((glob9) => contentGlob(resolved.configDir, glob9))
|
|
8395
8556
|
}
|
|
8396
8557
|
} : {},
|
|
8397
8558
|
...plan2.search ? { search: { type: plan2.search } } : {},
|
|
@@ -8406,12 +8567,13 @@ function buildSiteConfig(resolved, plan2, theme, extras = {}) {
|
|
|
8406
8567
|
} : {},
|
|
8407
8568
|
...navigation.length > 0 ? { navigation } : {},
|
|
8408
8569
|
// The sidebar link above is only seen inside the docs; the header is what every page shows. A header navigation
|
|
8409
|
-
// replaces the docs tab, so the docs get a header link of their own.
|
|
8410
|
-
...plan2.apiReference ? {
|
|
8570
|
+
// replaces the docs tab, so the docs get a header link of their own. The tenant's own links (portal.header) follow.
|
|
8571
|
+
...plan2.apiReference || shownHeaderLinks.length > 0 ? {
|
|
8411
8572
|
header: {
|
|
8412
8573
|
navigation: [
|
|
8413
8574
|
...plan2.docs && extras.docsPath ? [{ label: "Documentation", to: extras.docsPath }] : [],
|
|
8414
|
-
{ label: "API Reference", to: `/${API_REFERENCE_PATH}` }
|
|
8575
|
+
...plan2.apiReference ? [{ label: "API Reference", to: `/${API_REFERENCE_PATH}` }] : [],
|
|
8576
|
+
...shownHeaderLinks
|
|
8415
8577
|
]
|
|
8416
8578
|
}
|
|
8417
8579
|
} : {},
|
|
@@ -8617,10 +8779,14 @@ async function preparePortal(resolved, manifest, mode, options = {}) {
|
|
|
8617
8779
|
const tsxPages = plan2.docs ? (await findTsxPages(profile.docs.content)).filter(
|
|
8618
8780
|
(page) => !markdownRoutes.includes(page.route)
|
|
8619
8781
|
) : [];
|
|
8782
|
+
const importPathOf = (file) => `./${CONTENT_LINK}/${path14.relative(resolved.configDir, file).split(path14.sep).join("/")}`;
|
|
8620
8783
|
const wrapperPages = tsxPages.map((page, index) => ({
|
|
8621
8784
|
id: `${TSX_PAGE_ELEMENT_PREFIX}${index}`,
|
|
8622
|
-
importPath:
|
|
8785
|
+
importPath: importPathOf(page.file)
|
|
8623
8786
|
}));
|
|
8787
|
+
const headerWrapperPages = headerTsxPages(resolved, plan2).map(
|
|
8788
|
+
(page) => ({ id: page.id, importPath: importPathOf(page.file) })
|
|
8789
|
+
);
|
|
8624
8790
|
const hostedDocRoutes = [
|
|
8625
8791
|
.../* @__PURE__ */ new Set([...markdownRoutes, ...tsxPages.map((page) => page.route)])
|
|
8626
8792
|
].sort();
|
|
@@ -8691,14 +8857,20 @@ async function preparePortal(resolved, manifest, mode, options = {}) {
|
|
|
8691
8857
|
protectedRoutes: protectedRoutesFor({
|
|
8692
8858
|
requireAuth: resolved.portal?.requireAuth,
|
|
8693
8859
|
hasAuth: !!plan2.auth,
|
|
8694
|
-
|
|
8860
|
+
// A header page is a docs page too, so a portal behind login keeps it behind login.
|
|
8861
|
+
docRoutes: plan2.docs ? [
|
|
8862
|
+
...hostedDocRoutes,
|
|
8863
|
+
...(resolved.portal?.headerLinks ?? []).flatMap(
|
|
8864
|
+
(link) => link.page ? [link.to] : []
|
|
8865
|
+
)
|
|
8866
|
+
] : hostedDocRoutes,
|
|
8695
8867
|
apiReferencePath: plan2.apiReference ? `/${API_REFERENCE_PATH}` : void 0
|
|
8696
8868
|
})
|
|
8697
8869
|
}
|
|
8698
8870
|
);
|
|
8699
8871
|
const wrapper = renderWrapper(
|
|
8700
8872
|
plan2,
|
|
8701
|
-
wrapperPages,
|
|
8873
|
+
[...wrapperPages, ...headerWrapperPages],
|
|
8702
8874
|
resolved.portal?.footer ? wrapperImport(contentFile(resolved.configDir, resolved.portal.footer)) : void 0
|
|
8703
8875
|
);
|
|
8704
8876
|
const wrapperPath = path14.join(resolved.state.generatedDir, WRAPPER_FILE);
|
|
@@ -10105,7 +10277,7 @@ init_invariant();
|
|
|
10105
10277
|
// src/cli/check/v2.ts
|
|
10106
10278
|
init_apitogo_config_core();
|
|
10107
10279
|
import { readFile as readFile18 } from "node:fs/promises";
|
|
10108
|
-
import
|
|
10280
|
+
import path52 from "node:path";
|
|
10109
10281
|
|
|
10110
10282
|
// src/cli/platform/client/platform-api.ts
|
|
10111
10283
|
import { basename } from "node:path";
|
|
@@ -10121,6 +10293,17 @@ var PlatformApiError = class extends Error {
|
|
|
10121
10293
|
this.problem = problem;
|
|
10122
10294
|
}
|
|
10123
10295
|
};
|
|
10296
|
+
var ProjectGoneError = class extends PlatformApiError {
|
|
10297
|
+
constructor(projectId) {
|
|
10298
|
+
super(
|
|
10299
|
+
`The project ${projectId} no longer exists on the platform: it was deleted, or it is not in the account you are signed in to. Run \`apitogo project create\` to make a new project for this folder, or link another one with \`--project-id <id>\`.`,
|
|
10300
|
+
410
|
|
10301
|
+
);
|
|
10302
|
+
this.projectId = projectId;
|
|
10303
|
+
this.name = "ProjectGoneError";
|
|
10304
|
+
}
|
|
10305
|
+
code = "PROJECT_GONE";
|
|
10306
|
+
};
|
|
10124
10307
|
function formatProblemDetails(problem) {
|
|
10125
10308
|
const parts = [];
|
|
10126
10309
|
if (problem.title) parts.push(problem.title);
|
|
@@ -10212,14 +10395,19 @@ async function fetchWithRetry(input5, init3, options) {
|
|
|
10212
10395
|
}
|
|
10213
10396
|
|
|
10214
10397
|
// src/cli/platform/client/platform-api.ts
|
|
10398
|
+
function projectIdOfPath(path100) {
|
|
10399
|
+
return /^\/api\/v1\/projects\/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:[/?#]|$)/i.exec(
|
|
10400
|
+
path100
|
|
10401
|
+
)?.[1];
|
|
10402
|
+
}
|
|
10215
10403
|
var MAX_RETRIES = 3;
|
|
10216
10404
|
var UPLOAD_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
10217
10405
|
var PlatformApiClient = class {
|
|
10218
10406
|
constructor(config2) {
|
|
10219
10407
|
this.config = config2;
|
|
10220
10408
|
}
|
|
10221
|
-
url(
|
|
10222
|
-
return `${this.config.apiUrl}${
|
|
10409
|
+
url(path100) {
|
|
10410
|
+
return `${this.config.apiUrl}${path100.startsWith("/") ? path100 : `/${path100}`}`;
|
|
10223
10411
|
}
|
|
10224
10412
|
headers(extra) {
|
|
10225
10413
|
return {
|
|
@@ -10229,9 +10417,9 @@ var PlatformApiClient = class {
|
|
|
10229
10417
|
...extra
|
|
10230
10418
|
};
|
|
10231
10419
|
}
|
|
10232
|
-
async request(method,
|
|
10420
|
+
async request(method, path100, init3) {
|
|
10233
10421
|
const response = await fetchWithRetry(
|
|
10234
|
-
this.url(
|
|
10422
|
+
this.url(path100),
|
|
10235
10423
|
{
|
|
10236
10424
|
method,
|
|
10237
10425
|
...init3,
|
|
@@ -10247,13 +10435,39 @@ var PlatformApiClient = class {
|
|
|
10247
10435
|
}
|
|
10248
10436
|
);
|
|
10249
10437
|
if (!response.ok) {
|
|
10250
|
-
throw await
|
|
10438
|
+
throw await this.failure(response, path100);
|
|
10251
10439
|
}
|
|
10252
10440
|
if (response.status === 204) {
|
|
10253
10441
|
return void 0;
|
|
10254
10442
|
}
|
|
10255
10443
|
return await response.json();
|
|
10256
10444
|
}
|
|
10445
|
+
/**
|
|
10446
|
+
* The error for a failed answer. A 404 under a project may mean the project itself is gone; a bare "Not Found" hid
|
|
10447
|
+
* that (API-133), so the project is asked once and a missing one becomes {@link ProjectGoneError}.
|
|
10448
|
+
*/
|
|
10449
|
+
async failure(response, path100) {
|
|
10450
|
+
const error = await parseErrorResponse(response);
|
|
10451
|
+
const projectId = response.status === 404 ? projectIdOfPath(path100) : void 0;
|
|
10452
|
+
if (projectId && await this.projectMissing(projectId, path100))
|
|
10453
|
+
return new ProjectGoneError(projectId);
|
|
10454
|
+
return error;
|
|
10455
|
+
}
|
|
10456
|
+
/** Whether the project answers 404 itself. A path that is the project needs no second call. */
|
|
10457
|
+
async projectMissing(projectId, path100) {
|
|
10458
|
+
const projectPath = `/api/v1/projects/${projectId}`;
|
|
10459
|
+
if (path100.replace(/[?#].*$/, "").replace(/\/+$/, "") === projectPath)
|
|
10460
|
+
return true;
|
|
10461
|
+
try {
|
|
10462
|
+
const response = await fetch(this.url(projectPath), {
|
|
10463
|
+
method: "GET",
|
|
10464
|
+
headers: this.headers()
|
|
10465
|
+
});
|
|
10466
|
+
return response.status === 404;
|
|
10467
|
+
} catch {
|
|
10468
|
+
return false;
|
|
10469
|
+
}
|
|
10470
|
+
}
|
|
10257
10471
|
whoami() {
|
|
10258
10472
|
return this.request("GET", "/api/v1/auth/me");
|
|
10259
10473
|
}
|
|
@@ -10361,7 +10575,10 @@ var PlatformApiClient = class {
|
|
|
10361
10575
|
{ method: "POST", maxRetries: 0, retryMutatingOnServerError: false }
|
|
10362
10576
|
);
|
|
10363
10577
|
if (!response.ok) {
|
|
10364
|
-
throw await
|
|
10578
|
+
throw await this.failure(
|
|
10579
|
+
response,
|
|
10580
|
+
`/api/v1/projects/${projectId}/infrastructure/static-web/deployments`
|
|
10581
|
+
);
|
|
10365
10582
|
}
|
|
10366
10583
|
return await response.json();
|
|
10367
10584
|
} catch (error) {
|
|
@@ -10437,7 +10654,10 @@ var PlatformApiClient = class {
|
|
|
10437
10654
|
}
|
|
10438
10655
|
);
|
|
10439
10656
|
if (!response.ok) {
|
|
10440
|
-
throw await
|
|
10657
|
+
throw await this.failure(
|
|
10658
|
+
response,
|
|
10659
|
+
`/api/v1/projects/${projectId}/backend/openapi`
|
|
10660
|
+
);
|
|
10441
10661
|
}
|
|
10442
10662
|
return await response.json();
|
|
10443
10663
|
}
|
|
@@ -10486,7 +10706,11 @@ var PlatformApiClient = class {
|
|
|
10486
10706
|
maxRetries: MAX_RETRIES
|
|
10487
10707
|
}
|
|
10488
10708
|
);
|
|
10489
|
-
if (!response.ok)
|
|
10709
|
+
if (!response.ok)
|
|
10710
|
+
throw await this.failure(
|
|
10711
|
+
response,
|
|
10712
|
+
`/api/v1/projects/${projectId}/gateway/openapi.json`
|
|
10713
|
+
);
|
|
10490
10714
|
return response.text();
|
|
10491
10715
|
}
|
|
10492
10716
|
getGatewayCapabilities(projectId) {
|
|
@@ -10699,15 +10923,15 @@ var PlatformApiClient = class {
|
|
|
10699
10923
|
}
|
|
10700
10924
|
);
|
|
10701
10925
|
}
|
|
10702
|
-
deleteDevPortalPage(projectId,
|
|
10703
|
-
const query = new URLSearchParams({ path:
|
|
10926
|
+
deleteDevPortalPage(projectId, path100) {
|
|
10927
|
+
const query = new URLSearchParams({ path: path100 });
|
|
10704
10928
|
return this.request(
|
|
10705
10929
|
"DELETE",
|
|
10706
10930
|
`/api/v1/projects/${projectId}/dev-portal/pages/files?${query.toString()}`
|
|
10707
10931
|
);
|
|
10708
10932
|
}
|
|
10709
|
-
renameDevPortalPage(projectId,
|
|
10710
|
-
const query = new URLSearchParams({ path:
|
|
10933
|
+
renameDevPortalPage(projectId, path100, newName) {
|
|
10934
|
+
const query = new URLSearchParams({ path: path100 });
|
|
10711
10935
|
return this.request(
|
|
10712
10936
|
"POST",
|
|
10713
10937
|
`/api/v1/projects/${projectId}/dev-portal/pages/files/rename?${query.toString()}`,
|
|
@@ -10798,7 +11022,10 @@ var PlatformApiClient = class {
|
|
|
10798
11022
|
}
|
|
10799
11023
|
);
|
|
10800
11024
|
if (!response.ok) {
|
|
10801
|
-
throw await
|
|
11025
|
+
throw await this.failure(
|
|
11026
|
+
response,
|
|
11027
|
+
`/api/v1/projects/${projectId}/backend/deployments`
|
|
11028
|
+
);
|
|
10802
11029
|
}
|
|
10803
11030
|
return await response.json();
|
|
10804
11031
|
}
|
|
@@ -10823,8 +11050,8 @@ var PlatformApiClient = class {
|
|
|
10823
11050
|
* the project-less endpoint is used; `planTier` overrides the tier used for paid-plan checks.
|
|
10824
11051
|
*/
|
|
10825
11052
|
validateGatewayPlans(plans, options = {}) {
|
|
10826
|
-
const
|
|
10827
|
-
return this.request("POST",
|
|
11053
|
+
const path100 = options.projectId ? `/api/v1/projects/${options.projectId}/gateway/plans/validate` : "/api/v1/gateway/plans/validate";
|
|
11054
|
+
return this.request("POST", path100, {
|
|
10828
11055
|
headers: { "Content-Type": "application/json" },
|
|
10829
11056
|
body: JSON.stringify({ plans, planTier: options.planTier })
|
|
10830
11057
|
});
|
|
@@ -11052,11 +11279,11 @@ import {
|
|
|
11052
11279
|
rm as rm8,
|
|
11053
11280
|
writeFile as writeFile15
|
|
11054
11281
|
} from "node:fs/promises";
|
|
11055
|
-
import
|
|
11282
|
+
import path51 from "node:path";
|
|
11056
11283
|
|
|
11057
11284
|
// src/vite/build.ts
|
|
11058
11285
|
import { mkdir as mkdir11, readFile as readFile13, rename as rename5, rm as rm7, writeFile as writeFile13 } from "node:fs/promises";
|
|
11059
|
-
import
|
|
11286
|
+
import path49 from "node:path";
|
|
11060
11287
|
import { build as esbuild } from "esbuild";
|
|
11061
11288
|
import { build as viteBuild, mergeConfig as mergeConfig3 } from "vite";
|
|
11062
11289
|
|
|
@@ -11192,7 +11419,7 @@ init_invariant();
|
|
|
11192
11419
|
init_joinUrl();
|
|
11193
11420
|
|
|
11194
11421
|
// src/vite/config.ts
|
|
11195
|
-
import
|
|
11422
|
+
import path44 from "node:path";
|
|
11196
11423
|
import dotenv from "dotenv";
|
|
11197
11424
|
import colors8 from "picocolors";
|
|
11198
11425
|
import {
|
|
@@ -11203,7 +11430,7 @@ import {
|
|
|
11203
11430
|
// package.json
|
|
11204
11431
|
var package_default = {
|
|
11205
11432
|
name: "@lukoweb/apitogo",
|
|
11206
|
-
version: "0.2.
|
|
11433
|
+
version: "0.2.64",
|
|
11207
11434
|
type: "module",
|
|
11208
11435
|
sideEffects: [
|
|
11209
11436
|
"**/*.css",
|
|
@@ -11988,14 +12215,14 @@ var flattenAllOf = (schema2) => {
|
|
|
11988
12215
|
};
|
|
11989
12216
|
|
|
11990
12217
|
// src/lib/util/traverse.ts
|
|
11991
|
-
var traverse = (specification, transform,
|
|
11992
|
-
const transformed = transform(specification,
|
|
12218
|
+
var traverse = (specification, transform, path100 = []) => {
|
|
12219
|
+
const transformed = transform(specification, path100);
|
|
11993
12220
|
if (typeof transformed !== "object" || transformed === null) {
|
|
11994
12221
|
return transformed;
|
|
11995
12222
|
}
|
|
11996
12223
|
const result = Array.isArray(transformed) ? [] : {};
|
|
11997
12224
|
for (const [key, value] of Object.entries(transformed)) {
|
|
11998
|
-
const currentPath = [...
|
|
12225
|
+
const currentPath = [...path100, key];
|
|
11999
12226
|
if (Array.isArray(value)) {
|
|
12000
12227
|
result[key] = value.map(
|
|
12001
12228
|
(item, index) => typeof item === "object" && item != null ? traverse(item, transform, [...currentPath, index.toString()]) : item
|
|
@@ -12023,9 +12250,9 @@ var resolveLocalRef = (schema2, ref) => {
|
|
|
12023
12250
|
if (schemaCache?.has(ref)) {
|
|
12024
12251
|
return schemaCache.get(ref);
|
|
12025
12252
|
}
|
|
12026
|
-
const
|
|
12253
|
+
const path100 = ref.split("/").slice(1);
|
|
12027
12254
|
let current = schema2;
|
|
12028
|
-
for (const segment of
|
|
12255
|
+
for (const segment of path100) {
|
|
12029
12256
|
if (!current || typeof current !== "object") {
|
|
12030
12257
|
current = null;
|
|
12031
12258
|
}
|
|
@@ -12044,7 +12271,7 @@ var dereference = async (schema2, resolvers = []) => {
|
|
|
12044
12271
|
}
|
|
12045
12272
|
const cloned = structuredClone(schema2);
|
|
12046
12273
|
const visited = /* @__PURE__ */ new Set();
|
|
12047
|
-
const resolve = async (current,
|
|
12274
|
+
const resolve = async (current, path100) => {
|
|
12048
12275
|
if (isIndexableObject(current)) {
|
|
12049
12276
|
if (visited.has(current)) {
|
|
12050
12277
|
return CIRCULAR_REF;
|
|
@@ -12052,7 +12279,7 @@ var dereference = async (schema2, resolvers = []) => {
|
|
|
12052
12279
|
visited.add(current);
|
|
12053
12280
|
if (Array.isArray(current)) {
|
|
12054
12281
|
for (let index = 0; index < current.length; index++) {
|
|
12055
|
-
current[index] = await resolve(current[index], `${
|
|
12282
|
+
current[index] = await resolve(current[index], `${path100}/${index}`);
|
|
12056
12283
|
}
|
|
12057
12284
|
} else {
|
|
12058
12285
|
if ("$ref" in current && typeof current.$ref === "string") {
|
|
@@ -12063,13 +12290,13 @@ var dereference = async (schema2, resolvers = []) => {
|
|
|
12063
12290
|
for (const resolver of resolvers) {
|
|
12064
12291
|
const resolved = await resolver($ref);
|
|
12065
12292
|
if (resolved) {
|
|
12066
|
-
result2 = await resolve(resolved,
|
|
12293
|
+
result2 = await resolve(resolved, path100);
|
|
12067
12294
|
break;
|
|
12068
12295
|
}
|
|
12069
12296
|
}
|
|
12070
12297
|
if (result2 === void 0) {
|
|
12071
12298
|
const resolved = await resolveLocalRef(cloned, $ref);
|
|
12072
|
-
result2 = await resolve(resolved,
|
|
12299
|
+
result2 = await resolve(resolved, path100);
|
|
12073
12300
|
}
|
|
12074
12301
|
if (hasSiblings) {
|
|
12075
12302
|
if (result2 === CIRCULAR_REF) {
|
|
@@ -12082,7 +12309,7 @@ var dereference = async (schema2, resolvers = []) => {
|
|
|
12082
12309
|
return result2;
|
|
12083
12310
|
}
|
|
12084
12311
|
for (const key in current) {
|
|
12085
|
-
current[key] = await resolve(current[key], `${
|
|
12312
|
+
current[key] = await resolve(current[key], `${path100}/${key}`);
|
|
12086
12313
|
}
|
|
12087
12314
|
}
|
|
12088
12315
|
visited.delete(current);
|
|
@@ -12121,9 +12348,9 @@ var upgradeSchema = (schema2) => {
|
|
|
12121
12348
|
}
|
|
12122
12349
|
return sub;
|
|
12123
12350
|
});
|
|
12124
|
-
schema2 = traverse(schema2, (sub,
|
|
12351
|
+
schema2 = traverse(schema2, (sub, path100) => {
|
|
12125
12352
|
if (sub.example !== void 0) {
|
|
12126
|
-
if (isSchemaPath(
|
|
12353
|
+
if (isSchemaPath(path100 ?? [])) {
|
|
12127
12354
|
sub.examples = [sub.example];
|
|
12128
12355
|
} else {
|
|
12129
12356
|
sub.examples = {
|
|
@@ -12136,11 +12363,11 @@ var upgradeSchema = (schema2) => {
|
|
|
12136
12363
|
}
|
|
12137
12364
|
return sub;
|
|
12138
12365
|
});
|
|
12139
|
-
schema2 = traverse(schema2, (schema3,
|
|
12366
|
+
schema2 = traverse(schema2, (schema3, path100) => {
|
|
12140
12367
|
if (schema3.type === "object" && schema3.properties !== void 0) {
|
|
12141
|
-
const parentPath =
|
|
12368
|
+
const parentPath = path100?.slice(0, -1);
|
|
12142
12369
|
const isMultipart = parentPath?.some((segment, index) => {
|
|
12143
|
-
return segment === "content" &&
|
|
12370
|
+
return segment === "content" && path100?.[index + 1] === "multipart/form-data";
|
|
12144
12371
|
});
|
|
12145
12372
|
if (isMultipart) {
|
|
12146
12373
|
const entries = Object.entries(schema3.properties);
|
|
@@ -12154,8 +12381,8 @@ var upgradeSchema = (schema2) => {
|
|
|
12154
12381
|
}
|
|
12155
12382
|
return schema3;
|
|
12156
12383
|
});
|
|
12157
|
-
schema2 = traverse(schema2, (schema3,
|
|
12158
|
-
if (
|
|
12384
|
+
schema2 = traverse(schema2, (schema3, path100) => {
|
|
12385
|
+
if (path100?.includes("content") && path100.includes("application/octet-stream")) {
|
|
12159
12386
|
return {};
|
|
12160
12387
|
}
|
|
12161
12388
|
if (schema3.type === "string" && schema3.format === "binary") {
|
|
@@ -12181,11 +12408,11 @@ var upgradeSchema = (schema2) => {
|
|
|
12181
12408
|
}
|
|
12182
12409
|
return sub;
|
|
12183
12410
|
});
|
|
12184
|
-
schema2 = traverse(schema2, (schema3,
|
|
12411
|
+
schema2 = traverse(schema2, (schema3, path100) => {
|
|
12185
12412
|
if (schema3.type === "string" && schema3.format === "byte") {
|
|
12186
|
-
const parentPath =
|
|
12413
|
+
const parentPath = path100?.slice(0, -1);
|
|
12187
12414
|
const contentMediaType = parentPath?.find(
|
|
12188
|
-
(_, index) =>
|
|
12415
|
+
(_, index) => path100?.[index - 1] === "content"
|
|
12189
12416
|
);
|
|
12190
12417
|
return {
|
|
12191
12418
|
type: "string",
|
|
@@ -12197,7 +12424,7 @@ var upgradeSchema = (schema2) => {
|
|
|
12197
12424
|
});
|
|
12198
12425
|
return schema2;
|
|
12199
12426
|
};
|
|
12200
|
-
function isSchemaPath(
|
|
12427
|
+
function isSchemaPath(path100) {
|
|
12201
12428
|
const schemaLocations = [
|
|
12202
12429
|
["components", "schemas"],
|
|
12203
12430
|
"properties",
|
|
@@ -12210,10 +12437,10 @@ function isSchemaPath(path99) {
|
|
|
12210
12437
|
];
|
|
12211
12438
|
return schemaLocations.some((location) => {
|
|
12212
12439
|
if (Array.isArray(location)) {
|
|
12213
|
-
return location.every((segment, index) =>
|
|
12440
|
+
return location.every((segment, index) => path100[index] === segment);
|
|
12214
12441
|
}
|
|
12215
|
-
return
|
|
12216
|
-
}) ||
|
|
12442
|
+
return path100.includes(location);
|
|
12443
|
+
}) || path100.includes("schema") || path100.some((segment) => segment.endsWith("Schema"));
|
|
12217
12444
|
}
|
|
12218
12445
|
|
|
12219
12446
|
// src/lib/oas/parser/index.ts
|
|
@@ -12295,13 +12522,13 @@ var OPENAPI_PROPS = /* @__PURE__ */ new Set([
|
|
|
12295
12522
|
"anyOf",
|
|
12296
12523
|
"oneOf"
|
|
12297
12524
|
]);
|
|
12298
|
-
var handleCircularRefs = (obj, currentPath = /* @__PURE__ */ new WeakSet(), refs = /* @__PURE__ */ new WeakMap(),
|
|
12525
|
+
var handleCircularRefs = (obj, currentPath = /* @__PURE__ */ new WeakSet(), refs = /* @__PURE__ */ new WeakMap(), path100 = [], currentRefPaths = /* @__PURE__ */ new Set()) => {
|
|
12299
12526
|
if (obj === null || typeof obj !== "object") return obj;
|
|
12300
12527
|
const refPath = obj.__$ref;
|
|
12301
12528
|
const isCircular = currentPath.has(obj) || typeof refPath === "string" && currentRefPaths.has(refPath);
|
|
12302
12529
|
if (isCircular) {
|
|
12303
12530
|
if (typeof refPath === "string") return SCHEMA_REF_PREFIX + refPath;
|
|
12304
|
-
const circularProp =
|
|
12531
|
+
const circularProp = path100.find((p) => !OPENAPI_PROPS.has(p)) || path100[0];
|
|
12305
12532
|
return [CIRCULAR_REF, circularProp].filter(Boolean).join(":");
|
|
12306
12533
|
}
|
|
12307
12534
|
if (refs.has(obj)) return refs.get(obj);
|
|
@@ -12311,7 +12538,7 @@ var handleCircularRefs = (obj, currentPath = /* @__PURE__ */ new WeakSet(), refs
|
|
|
12311
12538
|
value,
|
|
12312
12539
|
currentPath,
|
|
12313
12540
|
refs,
|
|
12314
|
-
[...
|
|
12541
|
+
[...path100, key],
|
|
12315
12542
|
currentRefPaths
|
|
12316
12543
|
);
|
|
12317
12544
|
const result = Array.isArray(obj) ? obj.map((item, i) => recurse(item, i.toString())) : Object.fromEntries(
|
|
@@ -12346,7 +12573,7 @@ var resolveExtensions = (obj) => Object.fromEntries(
|
|
|
12346
12573
|
var getAllTags = (schema2) => {
|
|
12347
12574
|
const rootTags = schema2.tags ?? [];
|
|
12348
12575
|
const operations = Object.values(schema2.paths ?? {}).flatMap(
|
|
12349
|
-
(
|
|
12576
|
+
(path100) => HttpMethods.map((k) => path100?.[k]).filter((op) => op != null)
|
|
12350
12577
|
);
|
|
12351
12578
|
const operationTags = new Set(operations.flatMap((op) => op.tags ?? []));
|
|
12352
12579
|
const hasUntaggedOperations = operations.some(
|
|
@@ -12401,7 +12628,7 @@ var getAllSlugs = (ops, schemaTags = []) => {
|
|
|
12401
12628
|
var getOperationSlugKey = (op) => [op.path, op.method, op.operationId, op.summary].filter(Boolean).join("-");
|
|
12402
12629
|
var getAllOperations = (paths) => {
|
|
12403
12630
|
const operations = Object.entries(paths ?? {}).flatMap(
|
|
12404
|
-
([
|
|
12631
|
+
([path100, value]) => HttpMethods.flatMap((method) => {
|
|
12405
12632
|
if (!value?.[method]) return [];
|
|
12406
12633
|
const operation = value[method];
|
|
12407
12634
|
const pathParameters = value.parameters ?? [];
|
|
@@ -12421,7 +12648,7 @@ var getAllOperations = (paths) => {
|
|
|
12421
12648
|
return {
|
|
12422
12649
|
...operation,
|
|
12423
12650
|
method,
|
|
12424
|
-
path:
|
|
12651
|
+
path: path100,
|
|
12425
12652
|
parameters,
|
|
12426
12653
|
servers,
|
|
12427
12654
|
tags: operation.tags ?? []
|
|
@@ -12779,8 +13006,8 @@ var Schema = builder.objectRef("Schema").implement({
|
|
|
12779
13006
|
}),
|
|
12780
13007
|
paths: t.field({
|
|
12781
13008
|
type: [PathItem],
|
|
12782
|
-
resolve: (root) => Object.entries(root.paths ?? {}).map(([
|
|
12783
|
-
path:
|
|
13009
|
+
resolve: (root) => Object.entries(root.paths ?? {}).map(([path100, value]) => ({
|
|
13010
|
+
path: path100,
|
|
12784
13011
|
// biome-ignore lint/style/noNonNullAssertion: value is guaranteed to be defined
|
|
12785
13012
|
methods: Object.keys(value)
|
|
12786
13013
|
}))
|
|
@@ -12945,7 +13172,7 @@ init_joinUrl();
|
|
|
12945
13172
|
|
|
12946
13173
|
// src/vite/api/schema-codegen.ts
|
|
12947
13174
|
var unescapeJsonPointer = (uri) => decodeURIComponent(uri.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
12948
|
-
var getSegmentsFromPath = (
|
|
13175
|
+
var getSegmentsFromPath = (path100) => path100.split("/").slice(1).map(unescapeJsonPointer);
|
|
12949
13176
|
var createLocalRefMap = (obj) => {
|
|
12950
13177
|
const refMap = /* @__PURE__ */ new Map();
|
|
12951
13178
|
const siblingsMap = /* @__PURE__ */ new Map();
|
|
@@ -12976,16 +13203,16 @@ var replaceMarkers = (code, mergedRefs) => code.replace(/"__refMap:(.*?)"/g, '__
|
|
|
12976
13203
|
/"__refMap\+Siblings:(.*?)"/g,
|
|
12977
13204
|
(_, key) => mergedRefs.get(key) ?? `__refMap["${key}"]`
|
|
12978
13205
|
);
|
|
12979
|
-
var lookup = (schema2,
|
|
12980
|
-
const parts = getSegmentsFromPath(
|
|
13206
|
+
var lookup = (schema2, path100, filePath) => {
|
|
13207
|
+
const parts = getSegmentsFromPath(path100);
|
|
12981
13208
|
let val = schema2;
|
|
12982
13209
|
for (const part of parts) {
|
|
12983
13210
|
while (val.$ref?.startsWith("#/")) {
|
|
12984
|
-
val = val.$ref ===
|
|
13211
|
+
val = val.$ref === path100 ? val : lookup(schema2, val.$ref, filePath);
|
|
12985
13212
|
}
|
|
12986
13213
|
if (val[part] === void 0) {
|
|
12987
13214
|
throw new Error(
|
|
12988
|
-
`Error in ${filePath ?? "code generation"}: Could not find path segment ${part} in path: ${
|
|
13215
|
+
`Error in ${filePath ?? "code generation"}: Could not find path segment ${part} in path: ${path100}`
|
|
12989
13216
|
);
|
|
12990
13217
|
}
|
|
12991
13218
|
val = val[part];
|
|
@@ -13232,8 +13459,8 @@ var SchemaManager = class {
|
|
|
13232
13459
|
}
|
|
13233
13460
|
}
|
|
13234
13461
|
};
|
|
13235
|
-
getLatestSchema = (
|
|
13236
|
-
getSchemasForPath = (
|
|
13462
|
+
getLatestSchema = (path100) => this.processedSchemas[path100]?.at(0);
|
|
13463
|
+
getSchemasForPath = (path100) => this.processedSchemas[path100];
|
|
13237
13464
|
getSchemaImports = () => Object.values(this.processedSchemas).flat().filter((s) => s.importKey);
|
|
13238
13465
|
getUrlToFilePathMap = () => {
|
|
13239
13466
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -14357,8 +14584,32 @@ init_loader();
|
|
|
14357
14584
|
init_ProtectedRoutesSchema();
|
|
14358
14585
|
init_joinUrl();
|
|
14359
14586
|
import { mkdir as mkdir8, writeFile as writeFile10 } from "node:fs/promises";
|
|
14360
|
-
import
|
|
14587
|
+
import path37 from "node:path";
|
|
14361
14588
|
import { matchPath } from "react-router";
|
|
14589
|
+
|
|
14590
|
+
// src/vite/markdown-output-path.ts
|
|
14591
|
+
import { rm as rm6 } from "node:fs/promises";
|
|
14592
|
+
import path36 from "node:path";
|
|
14593
|
+
var markdownOutputPath = (distDir, routePath) => {
|
|
14594
|
+
const segments = routePath === "/" ? ["index"] : routePath.split("/").filter(Boolean);
|
|
14595
|
+
return `${path36.join(distDir, ...segments)}.md`;
|
|
14596
|
+
};
|
|
14597
|
+
var removableMarkdownOutput = (distDir, routePath) => {
|
|
14598
|
+
const output4 = path36.resolve(markdownOutputPath(distDir, routePath));
|
|
14599
|
+
const relative = path36.relative(path36.resolve(distDir), output4);
|
|
14600
|
+
if (!relative || relative.startsWith("..") || path36.isAbsolute(relative)) {
|
|
14601
|
+
return void 0;
|
|
14602
|
+
}
|
|
14603
|
+
return output4;
|
|
14604
|
+
};
|
|
14605
|
+
var removeExportedMarkdown = async (distDir, pages) => {
|
|
14606
|
+
await Promise.all(
|
|
14607
|
+
pages.map((page) => removableMarkdownOutput(distDir, page.routePath)).filter((output4) => output4 !== void 0).map((output4) => rm6(output4, { force: true }).catch(() => {
|
|
14608
|
+
}))
|
|
14609
|
+
);
|
|
14610
|
+
};
|
|
14611
|
+
|
|
14612
|
+
// src/vite/plugin-markdown-export.ts
|
|
14362
14613
|
var processMarkdownFile = async (filePath) => {
|
|
14363
14614
|
const { content: markdownContent, data: frontmatter } = await readFrontmatter(filePath);
|
|
14364
14615
|
let finalMarkdown = markdownContent;
|
|
@@ -14445,7 +14696,7 @@ var viteMarkdownExportPlugin = () => {
|
|
|
14445
14696
|
if (process.env.NODE_ENV !== "production" || Object.keys(markdownFiles).length === 0 || !needsMdFiles) {
|
|
14446
14697
|
return;
|
|
14447
14698
|
}
|
|
14448
|
-
const distDir =
|
|
14699
|
+
const distDir = path37.join(
|
|
14449
14700
|
config2.__meta.rootDir,
|
|
14450
14701
|
"dist",
|
|
14451
14702
|
config2.basePath ?? ""
|
|
@@ -14465,16 +14716,15 @@ var viteMarkdownExportPlugin = () => {
|
|
|
14465
14716
|
description,
|
|
14466
14717
|
content: finalMarkdown
|
|
14467
14718
|
});
|
|
14468
|
-
const
|
|
14469
|
-
|
|
14470
|
-
await mkdir8(path36.dirname(outputPath), { recursive: true });
|
|
14719
|
+
const outputPath = markdownOutputPath(distDir, routePath);
|
|
14720
|
+
await mkdir8(path37.dirname(outputPath), { recursive: true });
|
|
14471
14721
|
await writeFile10(outputPath, finalMarkdown, "utf-8");
|
|
14472
14722
|
} catch (error) {
|
|
14473
14723
|
console.warn(`Failed to export markdown for ${routePath}:`, error);
|
|
14474
14724
|
}
|
|
14475
14725
|
}
|
|
14476
14726
|
if (config2.docs?.llms?.llmsTxt || config2.docs?.llms?.llmsTxtFull) {
|
|
14477
|
-
const markdownInfoPath =
|
|
14727
|
+
const markdownInfoPath = path37.join(
|
|
14478
14728
|
config2.__meta.rootDir,
|
|
14479
14729
|
"node_modules/.apitogo/markdown-info.json"
|
|
14480
14730
|
);
|
|
@@ -14626,9 +14876,9 @@ var remarkCodeTabs = () => (tree) => {
|
|
|
14626
14876
|
};
|
|
14627
14877
|
|
|
14628
14878
|
// src/vite/mdx/remark-inject-filepath.ts
|
|
14629
|
-
import
|
|
14879
|
+
import path38 from "node:path";
|
|
14630
14880
|
var remarkInjectFilepath = (rootDir) => (tree, vfile) => {
|
|
14631
|
-
const relativePath =
|
|
14881
|
+
const relativePath = path38.relative(rootDir, vfile.path).split(path38.sep).join(path38.posix.sep);
|
|
14632
14882
|
tree.children.unshift(exportMdxjsConst("__filepath", relativePath));
|
|
14633
14883
|
};
|
|
14634
14884
|
|
|
@@ -14715,18 +14965,18 @@ var remarkLastModified = () => {
|
|
|
14715
14965
|
};
|
|
14716
14966
|
|
|
14717
14967
|
// src/vite/mdx/remark-link-rewrite.ts
|
|
14718
|
-
import
|
|
14968
|
+
import path39 from "node:path";
|
|
14719
14969
|
import { visit as visit5 } from "unist-util-visit";
|
|
14720
14970
|
var remarkLinkRewrite = (basePath = "") => (tree) => {
|
|
14721
14971
|
visit5(tree, "link", (node) => {
|
|
14722
14972
|
if (!node.url) return;
|
|
14723
14973
|
if (node.url.startsWith("http") || node.url.startsWith("mailto:")) return;
|
|
14724
14974
|
node.url = node.url.replace(/\\/g, "/");
|
|
14725
|
-
const base =
|
|
14975
|
+
const base = path39.posix.join(basePath);
|
|
14726
14976
|
if (basePath && node.url.startsWith(base)) {
|
|
14727
14977
|
node.url = node.url.slice(base.length);
|
|
14728
14978
|
} else if (!node.url.startsWith("/") && !node.url.startsWith("#")) {
|
|
14729
|
-
node.url =
|
|
14979
|
+
node.url = path39.posix.join("..", node.url);
|
|
14730
14980
|
}
|
|
14731
14981
|
node.url = node.url.replace(/\.mdx?(#.*)?$/, "$1");
|
|
14732
14982
|
});
|
|
@@ -14946,14 +15196,14 @@ var plugin_mdx_default = viteMdxPlugin;
|
|
|
14946
15196
|
|
|
14947
15197
|
// src/vite/plugin-modules.ts
|
|
14948
15198
|
init_loader();
|
|
14949
|
-
import
|
|
15199
|
+
import path40 from "node:path";
|
|
14950
15200
|
import { normalizePath as normalizePath2 } from "vite";
|
|
14951
|
-
var getLandingModuleImport = (moduleDir, mode) => mode === "internal" ? normalizePath2(
|
|
14952
|
-
var getUserPanelModuleImport = (moduleDir, mode) => mode === "internal" ? normalizePath2(
|
|
15201
|
+
var getLandingModuleImport = (moduleDir, mode) => mode === "internal" ? normalizePath2(path40.join(moduleDir, "../module-landing/src/index.tsx")) : "@lukoweb/apitogo-module-landing";
|
|
15202
|
+
var getUserPanelModuleImport = (moduleDir, mode) => mode === "internal" ? normalizePath2(path40.join(moduleDir, "../module-user-panel/src/index.tsx")) : "@lukoweb/apitogo-module-user-panel";
|
|
14953
15203
|
var getBillingPluginImport = (moduleDir, mode) => mode === "internal" ? normalizePath2(
|
|
14954
|
-
|
|
15204
|
+
path40.join(moduleDir, "../plugin-dev-portal-billing/src/index.ts")
|
|
14955
15205
|
) : "@lukoweb/apitogo-plugin-dev-portal-billing";
|
|
14956
|
-
var resolveProjectPageImport = (rootDir, pagePath) => normalizePath2(
|
|
15206
|
+
var resolveProjectPageImport = (rootDir, pagePath) => normalizePath2(path40.resolve(rootDir, pagePath));
|
|
14957
15207
|
var viteModulesPlugin = () => {
|
|
14958
15208
|
const virtualModuleId4 = "virtual:zudoku-modules-plugin";
|
|
14959
15209
|
const resolvedVirtualModuleId5 = `\0${virtualModuleId4}`;
|
|
@@ -15095,17 +15345,17 @@ var plugin_modules_default = viteModulesPlugin;
|
|
|
15095
15345
|
|
|
15096
15346
|
// src/vite/plugin-offroot-resolve.ts
|
|
15097
15347
|
init_loader();
|
|
15098
|
-
import
|
|
15348
|
+
import path41 from "node:path";
|
|
15099
15349
|
function stripQuery(id) {
|
|
15100
15350
|
const query = id.indexOf("?");
|
|
15101
15351
|
return query === -1 ? id : id.slice(0, query);
|
|
15102
15352
|
}
|
|
15103
15353
|
function isInside(parent, child) {
|
|
15104
|
-
const relative =
|
|
15105
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
15354
|
+
const relative = path41.relative(path41.resolve(parent), path41.resolve(child));
|
|
15355
|
+
return relative === "" || !relative.startsWith("..") && !path41.isAbsolute(relative);
|
|
15106
15356
|
}
|
|
15107
15357
|
function isBareSpecifier(source) {
|
|
15108
|
-
return !source.startsWith("\0") && !source.startsWith(".") && !source.startsWith("/") && !
|
|
15358
|
+
return !source.startsWith("\0") && !source.startsWith(".") && !source.startsWith("/") && !path41.isAbsolute(source);
|
|
15109
15359
|
}
|
|
15110
15360
|
function isInsideNodeModules(filePath) {
|
|
15111
15361
|
return filePath.split(/[\\/]/).includes("node_modules");
|
|
@@ -15129,7 +15379,7 @@ function viteOffrootResolvePlugin() {
|
|
|
15129
15379
|
if (!shouldResolveFromSiteRoot(source, importer, rootDir)) {
|
|
15130
15380
|
return;
|
|
15131
15381
|
}
|
|
15132
|
-
return this.resolve(source,
|
|
15382
|
+
return this.resolve(source, path41.join(rootDir, "package.json"), {
|
|
15133
15383
|
...options,
|
|
15134
15384
|
skipSelf: true
|
|
15135
15385
|
});
|
|
@@ -15139,7 +15389,7 @@ function viteOffrootResolvePlugin() {
|
|
|
15139
15389
|
|
|
15140
15390
|
// src/vite/plugin-search.ts
|
|
15141
15391
|
init_loader();
|
|
15142
|
-
import
|
|
15392
|
+
import path42 from "node:path";
|
|
15143
15393
|
var viteSearchPlugin = () => {
|
|
15144
15394
|
const virtualModuleId4 = "virtual:zudoku-search-plugin";
|
|
15145
15395
|
const resolvedVirtualModuleId5 = `\0${virtualModuleId4}`;
|
|
@@ -15157,7 +15407,7 @@ var viteSearchPlugin = () => {
|
|
|
15157
15407
|
return resolvedVirtualModuleId5;
|
|
15158
15408
|
}
|
|
15159
15409
|
if (id === "/pagefind/pagefind.js" && resolvedViteConfig?.publicDir) {
|
|
15160
|
-
return
|
|
15410
|
+
return path42.join(resolvedViteConfig.publicDir, "pagefind/pagefind.js");
|
|
15161
15411
|
}
|
|
15162
15412
|
},
|
|
15163
15413
|
async load(id) {
|
|
@@ -15298,27 +15548,27 @@ function vitePlugin() {
|
|
|
15298
15548
|
|
|
15299
15549
|
// src/vite/watch-ignore.ts
|
|
15300
15550
|
import { lstatSync, realpathSync } from "node:fs";
|
|
15301
|
-
import
|
|
15551
|
+
import path43 from "node:path";
|
|
15302
15552
|
var STATE_INSIDE_CONTENT = /[\\/]content[\\/](?:\.apitogo|apitogo[\\/]\.state)(?:[\\/]|$)/;
|
|
15303
15553
|
var within = (base, file) => {
|
|
15304
|
-
const resolvedBase =
|
|
15305
|
-
const resolvedFile =
|
|
15306
|
-
return resolvedFile === resolvedBase || resolvedFile.startsWith(resolvedBase +
|
|
15554
|
+
const resolvedBase = path43.resolve(base);
|
|
15555
|
+
const resolvedFile = path43.resolve(file);
|
|
15556
|
+
return resolvedFile === resolvedBase || resolvedFile.startsWith(resolvedBase + path43.sep);
|
|
15307
15557
|
};
|
|
15308
15558
|
var unique = (paths) => [...new Set(paths)];
|
|
15309
15559
|
function isWorkspace(root) {
|
|
15310
15560
|
try {
|
|
15311
|
-
return
|
|
15561
|
+
return path43.basename(root) === "generated" && lstatSync(path43.join(root, "content")).isSymbolicLink();
|
|
15312
15562
|
} catch {
|
|
15313
15563
|
return false;
|
|
15314
15564
|
}
|
|
15315
15565
|
}
|
|
15316
15566
|
function tenantDir(root) {
|
|
15317
|
-
return isWorkspace(root) ? realpathSync(
|
|
15567
|
+
return isWorkspace(root) ? realpathSync(path43.join(root, "content")) : void 0;
|
|
15318
15568
|
}
|
|
15319
15569
|
function stateIgnore(root) {
|
|
15320
15570
|
if (!isWorkspace(root)) return void 0;
|
|
15321
|
-
const state =
|
|
15571
|
+
const state = path43.dirname(root);
|
|
15322
15572
|
const states = unique([state, realpathSync(state)]);
|
|
15323
15573
|
const roots = unique([root, realpathSync(root)]);
|
|
15324
15574
|
return (file) => {
|
|
@@ -15327,19 +15577,28 @@ function stateIgnore(root) {
|
|
|
15327
15577
|
return STATE_INSIDE_CONTENT.test(file);
|
|
15328
15578
|
};
|
|
15329
15579
|
}
|
|
15580
|
+
var STATE_FOLDER = /(?:^|[\\/])(?:\.apitogo|apitogo[\\/]\.state)(?:[\\/]|$)/;
|
|
15581
|
+
function nestedStateIgnore(root) {
|
|
15582
|
+
const resolvedRoot = path43.resolve(root);
|
|
15583
|
+
return (file) => {
|
|
15584
|
+
const relative = path43.relative(resolvedRoot, path43.resolve(file));
|
|
15585
|
+
if (relative.startsWith("..") || path43.isAbsolute(relative)) return false;
|
|
15586
|
+
return STATE_FOLDER.test(relative);
|
|
15587
|
+
};
|
|
15588
|
+
}
|
|
15330
15589
|
function devServerAllow(root, moduleDir) {
|
|
15331
15590
|
const tenant = tenantDir(root);
|
|
15332
|
-
return [root,
|
|
15591
|
+
return [root, path43.dirname(root), moduleDir, ...tenant ? [tenant] : []];
|
|
15333
15592
|
}
|
|
15334
15593
|
|
|
15335
15594
|
// src/vite/config.ts
|
|
15336
15595
|
var resolveMergedPublicDir = (rootDir, merged) => {
|
|
15337
15596
|
if (merged.publicDir === false) return void 0;
|
|
15338
15597
|
const rel2 = typeof merged.publicDir === "string" ? merged.publicDir : "public";
|
|
15339
|
-
return
|
|
15598
|
+
return path44.resolve(rootDir, rel2);
|
|
15340
15599
|
};
|
|
15341
|
-
var getAppClientEntryPath = () =>
|
|
15342
|
-
var getAppServerEntryPath = () =>
|
|
15600
|
+
var getAppClientEntryPath = () => path44.posix.join(getZudokuRootDir(), "src/app/entry.client.tsx");
|
|
15601
|
+
var getAppServerEntryPath = () => path44.posix.join(getZudokuRootDir(), "src/app/entry.server.tsx");
|
|
15343
15602
|
var hasLoggedCdnInfo = false;
|
|
15344
15603
|
var MEDIA_REGEX = /\.(a?png|jpe?g|gif|bmp|svg|webp|tiff|ico|webm|ogg|mp3|wav|m4a|avif|mp4)/i;
|
|
15345
15604
|
var defineEnvVars = (vars) => Object.fromEntries(
|
|
@@ -15370,7 +15629,7 @@ async function getViteConfig(dir, configEnv) {
|
|
|
15370
15629
|
const ignoreState = stateIgnore(dir);
|
|
15371
15630
|
if (ZuploEnv.isZuplo) {
|
|
15372
15631
|
dotenv.config({
|
|
15373
|
-
path:
|
|
15632
|
+
path: path44.resolve(config2.__meta.rootDir, "../.env.zuplo"),
|
|
15374
15633
|
quiet: true
|
|
15375
15634
|
});
|
|
15376
15635
|
}
|
|
@@ -15425,6 +15684,7 @@ async function getViteConfig(dir, configEnv) {
|
|
|
15425
15684
|
`${dir}/.git`,
|
|
15426
15685
|
`${config2.__meta.moduleDir}/src/vite`,
|
|
15427
15686
|
`${config2.__meta.moduleDir}/src/cli`,
|
|
15687
|
+
nestedStateIgnore(dir),
|
|
15428
15688
|
...ignoreState ? [ignoreState] : []
|
|
15429
15689
|
]
|
|
15430
15690
|
}
|
|
@@ -15433,8 +15693,8 @@ async function getViteConfig(dir, configEnv) {
|
|
|
15433
15693
|
ssr: configEnv.isSsrBuild,
|
|
15434
15694
|
sourcemap: true,
|
|
15435
15695
|
target: "es2022",
|
|
15436
|
-
outDir:
|
|
15437
|
-
|
|
15696
|
+
outDir: path44.resolve(
|
|
15697
|
+
path44.join(
|
|
15438
15698
|
dir,
|
|
15439
15699
|
"dist",
|
|
15440
15700
|
config2.basePath ?? "",
|
|
@@ -15453,7 +15713,7 @@ async function getViteConfig(dir, configEnv) {
|
|
|
15453
15713
|
},
|
|
15454
15714
|
experimental: {
|
|
15455
15715
|
renderBuiltUrl(filename) {
|
|
15456
|
-
if (cdnUrl?.base && [".js", ".css"].includes(
|
|
15716
|
+
if (cdnUrl?.base && [".js", ".css"].includes(path44.extname(filename))) {
|
|
15457
15717
|
return joinUrl(cdnUrl.base, filename);
|
|
15458
15718
|
}
|
|
15459
15719
|
if (cdnUrl?.media && MEDIA_REGEX.test(filename)) {
|
|
@@ -15466,7 +15726,7 @@ async function getViteConfig(dir, configEnv) {
|
|
|
15466
15726
|
esbuildOptions: {
|
|
15467
15727
|
target: "es2022"
|
|
15468
15728
|
},
|
|
15469
|
-
entries: [
|
|
15729
|
+
entries: [path44.posix.join(getZudokuRootDir(), "src/{app,lib}/**")],
|
|
15470
15730
|
exclude: [
|
|
15471
15731
|
"@lukoweb/apitogo",
|
|
15472
15732
|
"@lukoweb/apitogo-plugin-dev-portal-billing"
|
|
@@ -15570,7 +15830,7 @@ init_package_json();
|
|
|
15570
15830
|
init_joinUrl();
|
|
15571
15831
|
import assert from "node:assert";
|
|
15572
15832
|
import { cp, mkdir as mkdir9, writeFile as writeFile11 } from "node:fs/promises";
|
|
15573
|
-
import
|
|
15833
|
+
import path45 from "node:path";
|
|
15574
15834
|
var pkgJson = getZudokuPackageJson();
|
|
15575
15835
|
function generateOutput({
|
|
15576
15836
|
config: config2,
|
|
@@ -15627,9 +15887,9 @@ async function writeOutput(dir, {
|
|
|
15627
15887
|
rewrites
|
|
15628
15888
|
}) {
|
|
15629
15889
|
const output4 = generateOutput({ config: config2, redirects, rewrites });
|
|
15630
|
-
const outputDir = process.env.VERCEL ?
|
|
15890
|
+
const outputDir = process.env.VERCEL ? path45.join(dir, ".vercel/output") : path45.join(dir, "dist/.output");
|
|
15631
15891
|
await mkdir9(outputDir, { recursive: true });
|
|
15632
|
-
const outputFile =
|
|
15892
|
+
const outputFile = path45.join(outputDir, "config.json");
|
|
15633
15893
|
await writeFile11(outputFile, JSON.stringify(output4, null, 2), "utf-8");
|
|
15634
15894
|
if (process.env.VERCEL) {
|
|
15635
15895
|
console.log("Wrote Vercel output to", outputDir);
|
|
@@ -15639,9 +15899,9 @@ async function writeOutput(dir, {
|
|
|
15639
15899
|
// src/vite/prerender/prerender.ts
|
|
15640
15900
|
init_logger();
|
|
15641
15901
|
init_file_exists();
|
|
15642
|
-
import { readFile as readFile12
|
|
15902
|
+
import { readFile as readFile12 } from "node:fs/promises";
|
|
15643
15903
|
import os from "node:os";
|
|
15644
|
-
import
|
|
15904
|
+
import path48 from "node:path";
|
|
15645
15905
|
import { pathToFileURL } from "node:url";
|
|
15646
15906
|
import { createIndex } from "pagefind";
|
|
15647
15907
|
import colors11 from "picocolors";
|
|
@@ -15683,7 +15943,7 @@ function throttle(fn) {
|
|
|
15683
15943
|
init_joinUrl();
|
|
15684
15944
|
import { createWriteStream, existsSync as existsSync5 } from "node:fs";
|
|
15685
15945
|
import { mkdir as mkdir10 } from "node:fs/promises";
|
|
15686
|
-
import
|
|
15946
|
+
import path46 from "node:path";
|
|
15687
15947
|
import colors9 from "picocolors";
|
|
15688
15948
|
import { SitemapStream } from "sitemap";
|
|
15689
15949
|
async function generateSitemap({
|
|
@@ -15697,11 +15957,11 @@ async function generateSitemap({
|
|
|
15697
15957
|
return;
|
|
15698
15958
|
}
|
|
15699
15959
|
const sitemap = new SitemapStream({ hostname: config2.siteUrl });
|
|
15700
|
-
const outputDir =
|
|
15960
|
+
const outputDir = path46.resolve(baseOutputDir, config2.outDir ?? "");
|
|
15701
15961
|
if (!existsSync5(outputDir)) {
|
|
15702
15962
|
await mkdir10(outputDir, { recursive: true });
|
|
15703
15963
|
}
|
|
15704
|
-
const sitemapOutputPath =
|
|
15964
|
+
const sitemapOutputPath = path46.join(outputDir, "sitemap.xml");
|
|
15705
15965
|
const writeStream = createWriteStream(sitemapOutputPath);
|
|
15706
15966
|
sitemap.pipe(writeStream);
|
|
15707
15967
|
let lastmod;
|
|
@@ -15731,14 +15991,14 @@ async function generateSitemap({
|
|
|
15731
15991
|
|
|
15732
15992
|
// src/vite/prerender/utils.ts
|
|
15733
15993
|
init_joinUrl();
|
|
15734
|
-
var resolveRoutePath = (
|
|
15735
|
-
const segments =
|
|
15994
|
+
var resolveRoutePath = (path100) => {
|
|
15995
|
+
const segments = path100.split("/");
|
|
15736
15996
|
if (segments.some((s) => s.startsWith(":") && !s.endsWith("?"))) {
|
|
15737
15997
|
return void 0;
|
|
15738
15998
|
}
|
|
15739
15999
|
return segments.filter((s) => !s.startsWith(":")).join("/") || void 0;
|
|
15740
16000
|
};
|
|
15741
|
-
var isSkipped = (
|
|
16001
|
+
var isSkipped = (path100) => path100.includes("*") || /^\d+$/.test(path100);
|
|
15742
16002
|
var resolveRoutes = (routes, parentPath = "") => routes.flatMap((route) => {
|
|
15743
16003
|
if (route.path && isSkipped(route.path)) return [];
|
|
15744
16004
|
const routePath = route.path ? resolveRoutePath(route.path) : void 0;
|
|
@@ -15788,12 +16048,12 @@ var prerender = async ({
|
|
|
15788
16048
|
serverConfigFilename,
|
|
15789
16049
|
writeRedirects = true
|
|
15790
16050
|
}) => {
|
|
15791
|
-
const distDir =
|
|
16051
|
+
const distDir = path48.join(dir, "dist", basePath);
|
|
15792
16052
|
const serverConfigPath = pathToFileURL(
|
|
15793
|
-
|
|
16053
|
+
path48.join(distDir, "server", serverConfigFilename)
|
|
15794
16054
|
).href;
|
|
15795
16055
|
const entryServerPath = pathToFileURL(
|
|
15796
|
-
|
|
16056
|
+
path48.join(distDir, "server/entry.server.js")
|
|
15797
16057
|
).href;
|
|
15798
16058
|
const rawConfig = await import(serverConfigPath).then(
|
|
15799
16059
|
(m) => m.default
|
|
@@ -15878,7 +16138,7 @@ var prerender = async ({
|
|
|
15878
16138
|
})
|
|
15879
16139
|
);
|
|
15880
16140
|
const pagefindWriteResult = await pagefindIndex?.writeFiles({
|
|
15881
|
-
outputPath:
|
|
16141
|
+
outputPath: path48.join(distDir, "pagefind")
|
|
15882
16142
|
});
|
|
15883
16143
|
const seconds = ((performance.now() - start) / 1e3).toFixed(1);
|
|
15884
16144
|
const message = `\u2713 finished prerendering ${paths.length} routes in ${seconds} seconds using ${maxThreads} workers`;
|
|
@@ -15910,7 +16170,7 @@ var prerender = async ({
|
|
|
15910
16170
|
const { generateLlmsTxtFiles: generateLlmsTxtFiles2 } = await Promise.resolve().then(() => (init_llms(), llms_exports));
|
|
15911
16171
|
const docsConfig = DocsConfigSchema2.parse(config2.docs);
|
|
15912
16172
|
const llmsConfig = docsConfig.llms ?? {};
|
|
15913
|
-
const markdownInfoPath =
|
|
16173
|
+
const markdownInfoPath = path48.join(
|
|
15914
16174
|
dir,
|
|
15915
16175
|
"node_modules/.apitogo/markdown-info.json"
|
|
15916
16176
|
);
|
|
@@ -15932,10 +16192,7 @@ var prerender = async ({
|
|
|
15932
16192
|
});
|
|
15933
16193
|
}
|
|
15934
16194
|
if (!docsConfig.publishMarkdown) {
|
|
15935
|
-
await
|
|
15936
|
-
markdownFileInfos.map((info) => rm6(info.filePath).catch(() => {
|
|
15937
|
-
}))
|
|
15938
|
-
);
|
|
16195
|
+
await removeExportedMarkdown(distDir, markdownFileInfos);
|
|
15939
16196
|
}
|
|
15940
16197
|
}
|
|
15941
16198
|
return { workerResults, rewrites };
|
|
@@ -16001,7 +16258,7 @@ async function runBuild(options) {
|
|
|
16001
16258
|
html,
|
|
16002
16259
|
basePath: config2.basePath
|
|
16003
16260
|
});
|
|
16004
|
-
await rm7(
|
|
16261
|
+
await rm7(path49.join(clientOutDir, "index.html"), { force: true });
|
|
16005
16262
|
} else {
|
|
16006
16263
|
await runPrerender({
|
|
16007
16264
|
dir,
|
|
@@ -16025,7 +16282,7 @@ var runPrerender = async (options) => {
|
|
|
16025
16282
|
serverConfigFilename,
|
|
16026
16283
|
writeRedirects: process.env.VERCEL === void 0
|
|
16027
16284
|
});
|
|
16028
|
-
const indexHtml =
|
|
16285
|
+
const indexHtml = path49.join(clientOutDir, "index.html");
|
|
16029
16286
|
if (!workerResults.find((r) => r.outputPath === indexHtml)) {
|
|
16030
16287
|
await writeFile13(indexHtml, html, "utf-8");
|
|
16031
16288
|
}
|
|
@@ -16035,15 +16292,15 @@ var runPrerender = async (options) => {
|
|
|
16035
16292
|
for (const statusPage of statusPages) {
|
|
16036
16293
|
await rename5(
|
|
16037
16294
|
statusPage,
|
|
16038
|
-
|
|
16295
|
+
path49.join(dir, DIST_DIR, path49.basename(statusPage))
|
|
16039
16296
|
);
|
|
16040
16297
|
}
|
|
16041
16298
|
await rm7(serverOutDir, { recursive: true, force: true });
|
|
16042
16299
|
if (process.env.VERCEL) {
|
|
16043
|
-
await mkdir11(
|
|
16300
|
+
await mkdir11(path49.join(dir, ".vercel/output/static"), { recursive: true });
|
|
16044
16301
|
await rename5(
|
|
16045
|
-
|
|
16046
|
-
|
|
16302
|
+
path49.join(dir, DIST_DIR),
|
|
16303
|
+
path49.join(dir, ".vercel/output/static")
|
|
16047
16304
|
);
|
|
16048
16305
|
}
|
|
16049
16306
|
await writeOutput(dir, {
|
|
@@ -16053,7 +16310,7 @@ var runPrerender = async (options) => {
|
|
|
16053
16310
|
});
|
|
16054
16311
|
if (ZuploEnv.isZuplo && issuer) {
|
|
16055
16312
|
await writeFile13(
|
|
16056
|
-
|
|
16313
|
+
path49.join(dir, DIST_DIR, ".output/zuplo.json"),
|
|
16057
16314
|
JSON.stringify({ issuer }, null, 2),
|
|
16058
16315
|
"utf-8"
|
|
16059
16316
|
);
|
|
@@ -16065,10 +16322,10 @@ var runPrerender = async (options) => {
|
|
|
16065
16322
|
};
|
|
16066
16323
|
var bundleSSREntry = async (options) => {
|
|
16067
16324
|
const { dir, adapter, serverOutDir, serverConfigFilename, html, basePath } = options;
|
|
16068
|
-
const tempEntryPath =
|
|
16325
|
+
const tempEntryPath = path49.join(dir, "__ssr-entry.ts");
|
|
16069
16326
|
const packageRoot = getZudokuRootDir();
|
|
16070
16327
|
const templateContent = await readFile13(
|
|
16071
|
-
|
|
16328
|
+
path49.join(packageRoot, "src/vite/ssr-templates", `${adapter}.ts`),
|
|
16072
16329
|
"utf-8"
|
|
16073
16330
|
);
|
|
16074
16331
|
const entryContent = templateContent.replace('"__TEMPLATE__"', JSON.stringify(html)).replace('"__CONFIG_FILE__"', JSON.stringify(`./${serverConfigFilename}`)).replace(
|
|
@@ -16083,9 +16340,9 @@ var bundleSSREntry = async (options) => {
|
|
|
16083
16340
|
platform: adapter === "node" ? "node" : "neutral",
|
|
16084
16341
|
target: "es2022",
|
|
16085
16342
|
format: "esm",
|
|
16086
|
-
outfile:
|
|
16343
|
+
outfile: path49.join(serverOutDir, "entry.js"),
|
|
16087
16344
|
external: ["./entry.server.js", `./${serverConfigFilename}`],
|
|
16088
|
-
nodePaths: [
|
|
16345
|
+
nodePaths: [path49.join(packageRoot, "node_modules")],
|
|
16089
16346
|
banner: { js: "// Bundled SSR entry" }
|
|
16090
16347
|
});
|
|
16091
16348
|
} finally {
|
|
@@ -16099,7 +16356,7 @@ init_package_json();
|
|
|
16099
16356
|
// src/cli/init/v2-packages.ts
|
|
16100
16357
|
import { existsSync as existsSync6 } from "node:fs";
|
|
16101
16358
|
import { readFile as readFile14, writeFile as writeFile14 } from "node:fs/promises";
|
|
16102
|
-
import
|
|
16359
|
+
import path50 from "node:path";
|
|
16103
16360
|
var CORE_PACKAGES = [
|
|
16104
16361
|
"@lukoweb/apitogo",
|
|
16105
16362
|
"react",
|
|
@@ -16116,7 +16373,7 @@ function packageNameFrom(name) {
|
|
|
16116
16373
|
return slug || "portal";
|
|
16117
16374
|
}
|
|
16118
16375
|
async function ensurePackageJson(dir, name) {
|
|
16119
|
-
const file =
|
|
16376
|
+
const file = path50.join(dir, "package.json");
|
|
16120
16377
|
if (existsSync6(file)) return false;
|
|
16121
16378
|
await writeFile14(
|
|
16122
16379
|
file,
|
|
@@ -16135,11 +16392,11 @@ async function ensurePackageJson(dir, name) {
|
|
|
16135
16392
|
return true;
|
|
16136
16393
|
}
|
|
16137
16394
|
function isPackageInstalled(startDir, name) {
|
|
16138
|
-
let dir =
|
|
16395
|
+
let dir = path50.resolve(startDir);
|
|
16139
16396
|
for (; ; ) {
|
|
16140
|
-
if (existsSync6(
|
|
16397
|
+
if (existsSync6(path50.join(dir, "node_modules", name, "package.json")))
|
|
16141
16398
|
return true;
|
|
16142
|
-
const parent =
|
|
16399
|
+
const parent = path50.dirname(dir);
|
|
16143
16400
|
if (parent === dir) return false;
|
|
16144
16401
|
dir = parent;
|
|
16145
16402
|
}
|
|
@@ -16196,7 +16453,7 @@ function portalBuildStep(context, options = {}, build2 = runBuild) {
|
|
|
16196
16453
|
return {
|
|
16197
16454
|
name: "build",
|
|
16198
16455
|
hash: () => hash2,
|
|
16199
|
-
stillValid: () => access4(
|
|
16456
|
+
stillValid: () => access4(path51.join(buildDir, "index.html")).then(
|
|
16200
16457
|
() => true,
|
|
16201
16458
|
() => false
|
|
16202
16459
|
),
|
|
@@ -16213,11 +16470,11 @@ function portalBuildStep(context, options = {}, build2 = runBuild) {
|
|
|
16213
16470
|
else process.env.NODE_ENV = originalNodeEnv;
|
|
16214
16471
|
}
|
|
16215
16472
|
await rm8(buildDir, { recursive: true, force: true });
|
|
16216
|
-
await mkdir12(
|
|
16217
|
-
await rename6(
|
|
16473
|
+
await mkdir12(path51.dirname(buildDir), { recursive: true });
|
|
16474
|
+
await rename6(path51.join(root, "dist"), buildDir);
|
|
16218
16475
|
if (prepared.publishedManifest) {
|
|
16219
16476
|
await writeFile15(
|
|
16220
|
-
|
|
16477
|
+
path51.join(buildDir, MANIFEST_FILE),
|
|
16221
16478
|
`${JSON.stringify(prepared.publishedManifest, null, 2)}
|
|
16222
16479
|
`
|
|
16223
16480
|
);
|
|
@@ -16248,15 +16505,15 @@ async function buildV2(options) {
|
|
|
16248
16505
|
// src/cli/check/gateway-online.ts
|
|
16249
16506
|
import { readFile as readFile16 } from "node:fs/promises";
|
|
16250
16507
|
var SPEC_SEND_LIMIT = 5 * 1024 * 1024 + 64 * 1024;
|
|
16251
|
-
var issue2 = (code,
|
|
16508
|
+
var issue2 = (code, path100, message, hint) => ({ code, path: path100, message, hint });
|
|
16252
16509
|
function capabilityIssues(gateway, answer) {
|
|
16253
16510
|
const can = answer.capabilities;
|
|
16254
16511
|
const plan2 = `your ${answer.tier} plan`;
|
|
16255
16512
|
const found = [];
|
|
16256
|
-
const unsupported = (
|
|
16513
|
+
const unsupported = (path100, what, hint) => found.push(
|
|
16257
16514
|
issue2(
|
|
16258
16515
|
"GATEWAY_CAPABILITY_UNSUPPORTED",
|
|
16259
|
-
|
|
16516
|
+
path100,
|
|
16260
16517
|
`${what} is not available on ${plan2}.`,
|
|
16261
16518
|
hint
|
|
16262
16519
|
)
|
|
@@ -16467,9 +16724,9 @@ function toPlatformPlans(plans, options = {}) {
|
|
|
16467
16724
|
}
|
|
16468
16725
|
|
|
16469
16726
|
// src/cli/check/services-online.ts
|
|
16470
|
-
var issue3 = (code,
|
|
16727
|
+
var issue3 = (code, path100, message, hint) => ({
|
|
16471
16728
|
code,
|
|
16472
|
-
path:
|
|
16729
|
+
path: path100,
|
|
16473
16730
|
message,
|
|
16474
16731
|
hint
|
|
16475
16732
|
});
|
|
@@ -16581,7 +16838,7 @@ var withPlanName = (message, sku) => !sku || message.toLowerCase().startsWith(`p
|
|
|
16581
16838
|
async function isConfigV2(dir) {
|
|
16582
16839
|
try {
|
|
16583
16840
|
return /"version"\s*:\s*2\b/.test(
|
|
16584
|
-
await readFile18(
|
|
16841
|
+
await readFile18(path52.join(dir, APITOGO_CONFIG_FILENAME), "utf8")
|
|
16585
16842
|
);
|
|
16586
16843
|
} catch {
|
|
16587
16844
|
return false;
|
|
@@ -16590,7 +16847,7 @@ async function isConfigV2(dir) {
|
|
|
16590
16847
|
async function isLegacyConfig(dir) {
|
|
16591
16848
|
let text2;
|
|
16592
16849
|
try {
|
|
16593
|
-
text2 = await readFile18(
|
|
16850
|
+
text2 = await readFile18(path52.join(dir, APITOGO_CONFIG_FILENAME), "utf8");
|
|
16594
16851
|
} catch {
|
|
16595
16852
|
return false;
|
|
16596
16853
|
}
|
|
@@ -16738,7 +16995,7 @@ async function validatePortalBuild(dir) {
|
|
|
16738
16995
|
}
|
|
16739
16996
|
}
|
|
16740
16997
|
async function runCheckV2(dir, args = {}, deps = {}) {
|
|
16741
|
-
const configPath =
|
|
16998
|
+
const configPath = path52.join(dir, APITOGO_CONFIG_FILENAME);
|
|
16742
16999
|
let report;
|
|
16743
17000
|
try {
|
|
16744
17001
|
const { config: config2, resolved } = loadConfigV2(dir);
|
|
@@ -16848,7 +17105,7 @@ async function checkV2(dir, args, deps = platformDependencies(args)) {
|
|
|
16848
17105
|
init_package_json();
|
|
16849
17106
|
|
|
16850
17107
|
// src/cli/init/v2-handler.ts
|
|
16851
|
-
import
|
|
17108
|
+
import path53 from "node:path";
|
|
16852
17109
|
import { createInterface } from "node:readline/promises";
|
|
16853
17110
|
function parseDocsFlag(value) {
|
|
16854
17111
|
if (value === void 0) return void 0;
|
|
@@ -16870,15 +17127,15 @@ async function ask(question) {
|
|
|
16870
17127
|
}
|
|
16871
17128
|
function describePlan(plan2) {
|
|
16872
17129
|
return {
|
|
16873
|
-
willCreate: plan2.entries.filter((entry) => !plan2.keep.includes(entry.path)).map((entry) =>
|
|
16874
|
-
willKeep: plan2.keep.map((target) =>
|
|
17130
|
+
willCreate: plan2.entries.filter((entry) => !plan2.keep.includes(entry.path)).map((entry) => path53.relative(plan2.dir, entry.path)),
|
|
17131
|
+
willKeep: plan2.keep.map((target) => path53.relative(plan2.dir, target)),
|
|
16875
17132
|
replacesConfig: plan2.replacesConfig
|
|
16876
17133
|
};
|
|
16877
17134
|
}
|
|
16878
17135
|
async function initV2(argv) {
|
|
16879
17136
|
const json = argv.json === true;
|
|
16880
17137
|
try {
|
|
16881
|
-
const dir =
|
|
17138
|
+
const dir = path53.resolve(process.cwd(), argv.dir ?? ".");
|
|
16882
17139
|
const plan2 = await planInit({
|
|
16883
17140
|
dir,
|
|
16884
17141
|
name: argv.name,
|
|
@@ -16919,8 +17176,8 @@ async function initV2(argv) {
|
|
|
16919
17176
|
status: "created",
|
|
16920
17177
|
dir,
|
|
16921
17178
|
...describePlan(plan2),
|
|
16922
|
-
created: result.created.map((p) =>
|
|
16923
|
-
kept: result.kept.map((p) =>
|
|
17179
|
+
created: result.created.map((p) => path53.relative(dir, p)),
|
|
17180
|
+
kept: result.kept.map((p) => path53.relative(dir, p))
|
|
16924
17181
|
},
|
|
16925
17182
|
null,
|
|
16926
17183
|
2
|
|
@@ -16929,7 +17186,7 @@ async function initV2(argv) {
|
|
|
16929
17186
|
return;
|
|
16930
17187
|
}
|
|
16931
17188
|
printResultToConsole(
|
|
16932
|
-
`Created ${
|
|
17189
|
+
`Created ${path53.basename(plan2.configPath)} (config version 2) in ${dir}.`
|
|
16933
17190
|
);
|
|
16934
17191
|
printHintToConsole(
|
|
16935
17192
|
"Next: add a service with `apitogo add <portal|gateway|identity|plans>`, or run `apitogo create` for a guided setup."
|
|
@@ -16956,7 +17213,7 @@ async function initV2(argv) {
|
|
|
16956
17213
|
|
|
16957
17214
|
// src/cli/services/packages.ts
|
|
16958
17215
|
import { existsSync as existsSync7 } from "node:fs";
|
|
16959
|
-
import
|
|
17216
|
+
import path54 from "node:path";
|
|
16960
17217
|
|
|
16961
17218
|
// src/cli/common/spawn-command.ts
|
|
16962
17219
|
import {
|
|
@@ -16989,18 +17246,18 @@ function packagesForConfig(config2) {
|
|
|
16989
17246
|
];
|
|
16990
17247
|
}
|
|
16991
17248
|
function isInstalled(dir, name) {
|
|
16992
|
-
for (let current =
|
|
16993
|
-
if (existsSync7(
|
|
17249
|
+
for (let current = path54.resolve(dir); ; current = path54.dirname(current)) {
|
|
17250
|
+
if (existsSync7(path54.join(current, "node_modules", name, "package.json")))
|
|
16994
17251
|
return true;
|
|
16995
|
-
if (
|
|
17252
|
+
if (path54.dirname(current) === current) return false;
|
|
16996
17253
|
}
|
|
16997
17254
|
}
|
|
16998
17255
|
function missingPackages(dir, names) {
|
|
16999
17256
|
return names.filter((name) => !isInstalled(dir, name));
|
|
17000
17257
|
}
|
|
17001
17258
|
function detectPackageManager(dir) {
|
|
17002
|
-
if (existsSync7(
|
|
17003
|
-
if (existsSync7(
|
|
17259
|
+
if (existsSync7(path54.join(dir, "pnpm-lock.yaml"))) return "pnpm";
|
|
17260
|
+
if (existsSync7(path54.join(dir, "yarn.lock"))) return "yarn";
|
|
17004
17261
|
return "npm";
|
|
17005
17262
|
}
|
|
17006
17263
|
function installSpecsCommand(manager, specs) {
|
|
@@ -17058,7 +17315,7 @@ async function installMissingPackages(dir, config2, version, options) {
|
|
|
17058
17315
|
reason: "--no-install was given",
|
|
17059
17316
|
command: shown
|
|
17060
17317
|
};
|
|
17061
|
-
await ensurePackageJson(dir, config2.project?.name ??
|
|
17318
|
+
await ensurePackageJson(dir, config2.project?.name ?? path54.basename(dir));
|
|
17062
17319
|
await (options.installer ?? runInstaller)(dir, command2);
|
|
17063
17320
|
return { status: "installed", packages: missing, command: shown };
|
|
17064
17321
|
}
|
|
@@ -17121,7 +17378,7 @@ var list = (value) => {
|
|
|
17121
17378
|
return items.length > 0 ? items : void 0;
|
|
17122
17379
|
};
|
|
17123
17380
|
function addOptionsFromArguments(service, argv) {
|
|
17124
|
-
const dir =
|
|
17381
|
+
const dir = path55.resolve(process.cwd(), argv.dir ?? ".");
|
|
17125
17382
|
const issuers = list(argv.issuer);
|
|
17126
17383
|
return {
|
|
17127
17384
|
dir,
|
|
@@ -17175,8 +17432,8 @@ function describe(edit, dir) {
|
|
|
17175
17432
|
return {
|
|
17176
17433
|
service: edit.service,
|
|
17177
17434
|
action: edit.action,
|
|
17178
|
-
willCreate: edit.files.map((file) =>
|
|
17179
|
-
keep: edit.keep.map((file) =>
|
|
17435
|
+
willCreate: edit.files.map((file) => path55.relative(dir, file.path)),
|
|
17436
|
+
keep: edit.keep.map((file) => path55.relative(dir, file)),
|
|
17180
17437
|
notes: edit.notes
|
|
17181
17438
|
};
|
|
17182
17439
|
}
|
|
@@ -17190,7 +17447,7 @@ async function run(action, argv, plan2, deps = {}) {
|
|
|
17190
17447
|
`Choose one of ${SERVICES.join(", ")}.`
|
|
17191
17448
|
);
|
|
17192
17449
|
}
|
|
17193
|
-
const dir =
|
|
17450
|
+
const dir = path55.resolve(process.cwd(), argv.dir ?? ".");
|
|
17194
17451
|
if (!await isConfigV2(dir)) {
|
|
17195
17452
|
throw new ServiceEditError(
|
|
17196
17453
|
`${action} works with a config version 2 project, and there is none in ${dir}.`,
|
|
@@ -17258,7 +17515,7 @@ async function run(action, argv, plan2, deps = {}) {
|
|
|
17258
17515
|
{
|
|
17259
17516
|
status: action === "add" ? "added" : "removed",
|
|
17260
17517
|
...describe(edit, dir),
|
|
17261
|
-
created: created.map((file) =>
|
|
17518
|
+
created: created.map((file) => path55.relative(dir, file)),
|
|
17262
17519
|
...install ? { packages: install } : {}
|
|
17263
17520
|
},
|
|
17264
17521
|
null,
|
|
@@ -17268,7 +17525,7 @@ async function run(action, argv, plan2, deps = {}) {
|
|
|
17268
17525
|
return;
|
|
17269
17526
|
}
|
|
17270
17527
|
printResultToConsole(
|
|
17271
|
-
`${action === "add" ? "Added" : "Removed"} ${edit.service} in ${
|
|
17528
|
+
`${action === "add" ? "Added" : "Removed"} ${edit.service} in ${path55.basename(edit.configPath)}.`
|
|
17272
17529
|
);
|
|
17273
17530
|
} catch (error) {
|
|
17274
17531
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -17329,7 +17586,7 @@ var removeService = (argv) => run(
|
|
|
17329
17586
|
"remove",
|
|
17330
17587
|
argv,
|
|
17331
17588
|
(service) => planRemoveService(service, {
|
|
17332
|
-
dir:
|
|
17589
|
+
dir: path55.resolve(process.cwd(), argv.dir ?? "."),
|
|
17333
17590
|
deleteFiles: argv.deleteFiles === true
|
|
17334
17591
|
})
|
|
17335
17592
|
);
|
|
@@ -17481,16 +17738,16 @@ var add_default = {
|
|
|
17481
17738
|
};
|
|
17482
17739
|
|
|
17483
17740
|
// src/cli/build/handler.ts
|
|
17484
|
-
import
|
|
17741
|
+
import path57 from "node:path";
|
|
17485
17742
|
init_logger();
|
|
17486
17743
|
init_package_json();
|
|
17487
17744
|
|
|
17488
17745
|
// src/cli/preview/handler.ts
|
|
17489
|
-
import
|
|
17746
|
+
import path56 from "node:path";
|
|
17490
17747
|
import { preview as vitePreview } from "vite";
|
|
17491
17748
|
var DEFAULT_PREVIEW_PORT = 4e3;
|
|
17492
17749
|
async function preview(argv) {
|
|
17493
|
-
const dir =
|
|
17750
|
+
const dir = path56.resolve(process.cwd(), argv.dir);
|
|
17494
17751
|
const viteConfig = await getViteConfig(dir, {
|
|
17495
17752
|
command: "serve",
|
|
17496
17753
|
mode: "production",
|
|
@@ -17533,7 +17790,7 @@ async function build(argv) {
|
|
|
17533
17790
|
printDiagnosticsToConsole("");
|
|
17534
17791
|
printDiagnosticsToConsole("");
|
|
17535
17792
|
}
|
|
17536
|
-
const dir =
|
|
17793
|
+
const dir = path57.resolve(process.cwd(), argv.dir);
|
|
17537
17794
|
try {
|
|
17538
17795
|
if (await isConfigV2(dir)) {
|
|
17539
17796
|
const result = await buildV2({ dir, jsonOnly });
|
|
@@ -17598,10 +17855,10 @@ var build_default = {
|
|
|
17598
17855
|
};
|
|
17599
17856
|
|
|
17600
17857
|
// src/cli/check/handler.ts
|
|
17601
|
-
import
|
|
17858
|
+
import path63 from "node:path";
|
|
17602
17859
|
|
|
17603
17860
|
// src/cli/platform/tools/check-publish-readiness.ts
|
|
17604
|
-
import
|
|
17861
|
+
import path62 from "node:path";
|
|
17605
17862
|
|
|
17606
17863
|
// src/cli/platform/helpers/dev-portal-backend.ts
|
|
17607
17864
|
function deriveProvisioningState(backend) {
|
|
@@ -17686,7 +17943,7 @@ function formatDevPortalBackendResponse(projectId, backend) {
|
|
|
17686
17943
|
init_gateway_limits();
|
|
17687
17944
|
import { existsSync as existsSync8 } from "node:fs";
|
|
17688
17945
|
import { access as access5, mkdir as mkdir13, readFile as readFile19, writeFile as writeFile16 } from "node:fs/promises";
|
|
17689
|
-
import
|
|
17946
|
+
import path58 from "node:path";
|
|
17690
17947
|
|
|
17691
17948
|
// src/cli/make-config/header-pricing-nav.ts
|
|
17692
17949
|
var HEADER_PRICING_PATH = "/pricing";
|
|
@@ -17808,7 +18065,7 @@ function isPlanFree(plan2) {
|
|
|
17808
18065
|
return (plan2.priceAmount ?? 0) <= 0;
|
|
17809
18066
|
}
|
|
17810
18067
|
function manifestFilePath(siteDirectory) {
|
|
17811
|
-
return
|
|
18068
|
+
return path58.join(path58.resolve(siteDirectory), APITOGO_CONFIG_FILENAME2);
|
|
17812
18069
|
}
|
|
17813
18070
|
var STORED_MANIFEST_KEYS = [
|
|
17814
18071
|
"authentication",
|
|
@@ -18232,23 +18489,23 @@ function resolveBackendSourceDirectory(siteDirectory, sourceDirectory) {
|
|
|
18232
18489
|
if (!trimmed) {
|
|
18233
18490
|
return void 0;
|
|
18234
18491
|
}
|
|
18235
|
-
return
|
|
18492
|
+
return path58.resolve(siteDirectory, trimmed);
|
|
18236
18493
|
}
|
|
18237
18494
|
function resolveBackendOpenApiPath(openApiPath, options) {
|
|
18238
18495
|
const trimmed = openApiPath?.trim();
|
|
18239
18496
|
if (!trimmed) {
|
|
18240
18497
|
return void 0;
|
|
18241
18498
|
}
|
|
18242
|
-
if (
|
|
18499
|
+
if (path58.isAbsolute(trimmed)) {
|
|
18243
18500
|
return trimmed;
|
|
18244
18501
|
}
|
|
18245
|
-
const siteResolved =
|
|
18502
|
+
const siteResolved = path58.resolve(options.siteDirectory, trimmed);
|
|
18246
18503
|
if (existsSync8(siteResolved)) {
|
|
18247
18504
|
return siteResolved;
|
|
18248
18505
|
}
|
|
18249
18506
|
const backendDir = options.backendSourceDirectory?.trim();
|
|
18250
18507
|
if (backendDir) {
|
|
18251
|
-
const backendResolved =
|
|
18508
|
+
const backendResolved = path58.resolve(backendDir, trimmed);
|
|
18252
18509
|
if (existsSync8(backendResolved)) {
|
|
18253
18510
|
return backendResolved;
|
|
18254
18511
|
}
|
|
@@ -18273,7 +18530,7 @@ async function readManifest2(siteDirectory) {
|
|
|
18273
18530
|
}
|
|
18274
18531
|
async function writeManifest2(siteDirectory, manifest) {
|
|
18275
18532
|
const filePath = manifestFilePath(siteDirectory);
|
|
18276
|
-
await mkdir13(
|
|
18533
|
+
await mkdir13(path58.dirname(filePath), { recursive: true });
|
|
18277
18534
|
let config2 = {};
|
|
18278
18535
|
if (await pathExists(filePath)) {
|
|
18279
18536
|
const raw = await readFile19(filePath, "utf8");
|
|
@@ -18299,7 +18556,7 @@ import {
|
|
|
18299
18556
|
unlink,
|
|
18300
18557
|
writeFile as writeFile17
|
|
18301
18558
|
} from "node:fs/promises";
|
|
18302
|
-
import
|
|
18559
|
+
import path59 from "node:path";
|
|
18303
18560
|
var ENV_FILENAME = ".env";
|
|
18304
18561
|
var COLLAPSED_UPPERCASE_ALIASES2 = {
|
|
18305
18562
|
SECRETKEY: "secretKey",
|
|
@@ -18418,12 +18675,12 @@ async function readEnvFile(filePath) {
|
|
|
18418
18675
|
}
|
|
18419
18676
|
}
|
|
18420
18677
|
async function loadSiteEnv(siteDirectory) {
|
|
18421
|
-
const resolvedDirectory =
|
|
18678
|
+
const resolvedDirectory = path59.resolve(siteDirectory);
|
|
18422
18679
|
const merged = { ...process.env };
|
|
18423
18680
|
for (const fileName of [ENV_FILENAME, ".env.local"]) {
|
|
18424
18681
|
Object.assign(
|
|
18425
18682
|
merged,
|
|
18426
|
-
await readEnvFile(
|
|
18683
|
+
await readEnvFile(path59.join(resolvedDirectory, fileName))
|
|
18427
18684
|
);
|
|
18428
18685
|
}
|
|
18429
18686
|
return merged;
|
|
@@ -18460,7 +18717,7 @@ function buildAuthSecretsJson(secrets2, options) {
|
|
|
18460
18717
|
return payload;
|
|
18461
18718
|
}
|
|
18462
18719
|
function envFilePath(siteDirectory) {
|
|
18463
|
-
return
|
|
18720
|
+
return path59.join(path59.resolve(siteDirectory), ENV_FILENAME);
|
|
18464
18721
|
}
|
|
18465
18722
|
function getSecretsStatus(siteDirectory, manifest, secrets2, envExists) {
|
|
18466
18723
|
const providerSecretStatus = {};
|
|
@@ -18496,7 +18753,7 @@ function validateSecretsForPublish(manifest, secrets2, emailOptions) {
|
|
|
18496
18753
|
}
|
|
18497
18754
|
async function siteEnvFileHasEntries(siteDirectory) {
|
|
18498
18755
|
for (const fileName of [ENV_FILENAME, ".env.local"]) {
|
|
18499
|
-
const loaded = await readEnvFile(
|
|
18756
|
+
const loaded = await readEnvFile(path59.join(siteDirectory, fileName));
|
|
18500
18757
|
if (Object.keys(loaded).length > 0) {
|
|
18501
18758
|
return true;
|
|
18502
18759
|
}
|
|
@@ -18504,7 +18761,7 @@ async function siteEnvFileHasEntries(siteDirectory) {
|
|
|
18504
18761
|
return false;
|
|
18505
18762
|
}
|
|
18506
18763
|
async function resolvePublishConfig(siteDirectory, emailOptions) {
|
|
18507
|
-
const resolvedDirectory =
|
|
18764
|
+
const resolvedDirectory = path59.resolve(siteDirectory);
|
|
18508
18765
|
const manifestRaw = await readManifest2(resolvedDirectory);
|
|
18509
18766
|
if (!manifestRaw) {
|
|
18510
18767
|
throw new Error("apitogo.config.json not found in sourceDirectory.");
|
|
@@ -18536,11 +18793,11 @@ var SECRETS_COLLECTION_INSTRUCTION = "For go-live, plans must already be in apit
|
|
|
18536
18793
|
init_gateway_limits();
|
|
18537
18794
|
import { readFile as readFile21 } from "node:fs/promises";
|
|
18538
18795
|
import { createRequire as createRequire2 } from "node:module";
|
|
18539
|
-
import
|
|
18796
|
+
import path60 from "node:path";
|
|
18540
18797
|
var cachedFallbackTs;
|
|
18541
18798
|
async function loadTypeScriptForSite(sourceDirectory) {
|
|
18542
18799
|
const require2 = createRequire2(
|
|
18543
|
-
|
|
18800
|
+
path60.join(path60.resolve(sourceDirectory), "package.json")
|
|
18544
18801
|
);
|
|
18545
18802
|
try {
|
|
18546
18803
|
return require2("typescript");
|
|
@@ -18587,7 +18844,7 @@ async function referencedFileExists(sourceDirectory, reference) {
|
|
|
18587
18844
|
return true;
|
|
18588
18845
|
}
|
|
18589
18846
|
return pathExists(
|
|
18590
|
-
|
|
18847
|
+
path60.resolve(sourceDirectory, reference.replace(/^\.\//, ""))
|
|
18591
18848
|
);
|
|
18592
18849
|
}
|
|
18593
18850
|
async function validateSiteConfigStructure(config2, sourceDirectory) {
|
|
@@ -18702,11 +18959,11 @@ var DEFAULT_TSX_CANDIDATES = [
|
|
|
18702
18959
|
"landing/LandingPage.tsx"
|
|
18703
18960
|
];
|
|
18704
18961
|
async function validateDevPortalSiteConfig(sourceDirectory, options) {
|
|
18705
|
-
const resolvedDir =
|
|
18962
|
+
const resolvedDir = path60.resolve(sourceDirectory);
|
|
18706
18963
|
const issues = [];
|
|
18707
18964
|
const checkedFiles = [];
|
|
18708
18965
|
const skippedChecks = [];
|
|
18709
|
-
const jsonPath =
|
|
18966
|
+
const jsonPath = path60.join(resolvedDir, APITOGO_CONFIG_FILENAME2);
|
|
18710
18967
|
if (await pathExists(jsonPath)) {
|
|
18711
18968
|
checkedFiles.push(APITOGO_CONFIG_FILENAME2);
|
|
18712
18969
|
let parsed;
|
|
@@ -18738,7 +18995,7 @@ async function validateDevPortalSiteConfig(sourceDirectory, options) {
|
|
|
18738
18995
|
);
|
|
18739
18996
|
const existingTsxFiles = [];
|
|
18740
18997
|
for (const relativeFile of tsxFiles) {
|
|
18741
|
-
if (await pathExists(
|
|
18998
|
+
if (await pathExists(path60.join(resolvedDir, relativeFile))) {
|
|
18742
18999
|
existingTsxFiles.push(relativeFile);
|
|
18743
19000
|
}
|
|
18744
19001
|
}
|
|
@@ -18752,7 +19009,7 @@ async function validateDevPortalSiteConfig(sourceDirectory, options) {
|
|
|
18752
19009
|
for (const relativeFile of existingTsxFiles) {
|
|
18753
19010
|
checkedFiles.push(relativeFile);
|
|
18754
19011
|
const content = await readFile21(
|
|
18755
|
-
|
|
19012
|
+
path60.join(resolvedDir, relativeFile),
|
|
18756
19013
|
"utf8"
|
|
18757
19014
|
);
|
|
18758
19015
|
issues.push(
|
|
@@ -18774,7 +19031,7 @@ async function validateDevPortalSiteConfig(sourceDirectory, options) {
|
|
|
18774
19031
|
|
|
18775
19032
|
// src/cli/platform/helpers/npm-build.ts
|
|
18776
19033
|
import { access as access7, readFile as readFile22 } from "node:fs/promises";
|
|
18777
|
-
import
|
|
19034
|
+
import path61 from "node:path";
|
|
18778
19035
|
var BUILD_LOG_TAIL_BYTES = 8192;
|
|
18779
19036
|
var MIN_NODE_MAJOR = 20;
|
|
18780
19037
|
var NpmBuildError = class extends Error {
|
|
@@ -18840,13 +19097,13 @@ function runCommand(command2, args, cwd, env) {
|
|
|
18840
19097
|
}
|
|
18841
19098
|
async function runNpmInstall(sourceDirectory, options) {
|
|
18842
19099
|
assertNodeVersion(options?.nodeVersion);
|
|
18843
|
-
const cwd =
|
|
18844
|
-
const packageJsonPath =
|
|
19100
|
+
const cwd = path61.resolve(sourceDirectory);
|
|
19101
|
+
const packageJsonPath = path61.join(cwd, "package.json");
|
|
18845
19102
|
if (!await pathExists2(packageJsonPath)) {
|
|
18846
19103
|
throw new Error(`package.json not found in sourceDirectory: ${cwd}`);
|
|
18847
19104
|
}
|
|
18848
19105
|
const startedAt = Date.now();
|
|
18849
|
-
const lockPath =
|
|
19106
|
+
const lockPath = path61.join(cwd, "package-lock.json");
|
|
18850
19107
|
const installArgs = await pathExists2(lockPath) ? ["ci"] : ["install"];
|
|
18851
19108
|
const install = await runCommand("npm", installArgs, cwd);
|
|
18852
19109
|
const installLog = install.output;
|
|
@@ -18864,8 +19121,8 @@ async function runNpmInstall(sourceDirectory, options) {
|
|
|
18864
19121
|
}
|
|
18865
19122
|
async function runNpmBuild(sourceDirectory, options) {
|
|
18866
19123
|
assertNodeVersion(options?.nodeVersion);
|
|
18867
|
-
const cwd =
|
|
18868
|
-
const packageJsonPath =
|
|
19124
|
+
const cwd = path61.resolve(sourceDirectory);
|
|
19125
|
+
const packageJsonPath = path61.join(cwd, "package.json");
|
|
18869
19126
|
if (!await pathExists2(packageJsonPath)) {
|
|
18870
19127
|
throw new Error(`package.json not found in sourceDirectory: ${cwd}`);
|
|
18871
19128
|
}
|
|
@@ -18882,8 +19139,8 @@ async function runNpmBuild(sourceDirectory, options) {
|
|
|
18882
19139
|
build2.exitCode
|
|
18883
19140
|
);
|
|
18884
19141
|
}
|
|
18885
|
-
const distPath =
|
|
18886
|
-
const indexPath =
|
|
19142
|
+
const distPath = path61.join(cwd, "dist");
|
|
19143
|
+
const indexPath = path61.join(distPath, "index.html");
|
|
18887
19144
|
if (!await pathExists2(indexPath)) {
|
|
18888
19145
|
throw new NpmBuildError(
|
|
18889
19146
|
`Build completed but dist/index.html was not found at ${indexPath}`,
|
|
@@ -19267,7 +19524,7 @@ function validateManifestForPlatformPublish(manifest) {
|
|
|
19267
19524
|
|
|
19268
19525
|
// src/cli/platform/tools/check-publish-readiness.ts
|
|
19269
19526
|
async function checkPublishReadiness(client, _config, args) {
|
|
19270
|
-
const sourceDirectory =
|
|
19527
|
+
const sourceDirectory = path62.resolve(args.sourceDirectory);
|
|
19271
19528
|
const manifest = await readManifest2(sourceDirectory) ?? createScaffoldManifest();
|
|
19272
19529
|
const emailOptions = await resolveEmailOptionsForPublish(
|
|
19273
19530
|
client,
|
|
@@ -19345,7 +19602,7 @@ async function checkPublishReadiness(client, _config, args) {
|
|
|
19345
19602
|
|
|
19346
19603
|
// src/cli/check/handler.ts
|
|
19347
19604
|
async function check(argv) {
|
|
19348
|
-
const sourceDirectory =
|
|
19605
|
+
const sourceDirectory = path63.resolve(process.cwd(), argv.dir);
|
|
19349
19606
|
if (await isConfigV2(sourceDirectory)) {
|
|
19350
19607
|
await checkV2(sourceDirectory, argv);
|
|
19351
19608
|
return;
|
|
@@ -19409,7 +19666,7 @@ var check_default = {
|
|
|
19409
19666
|
|
|
19410
19667
|
// src/cli/make-config/handler.ts
|
|
19411
19668
|
init_invariant();
|
|
19412
|
-
import
|
|
19669
|
+
import path65 from "node:path";
|
|
19413
19670
|
import { stdin as input2 } from "node:process";
|
|
19414
19671
|
|
|
19415
19672
|
// src/cli/make-config/interactive.ts
|
|
@@ -19419,7 +19676,7 @@ import { createInterface as createInterface3 } from "node:readline/promises";
|
|
|
19419
19676
|
// src/cli/make-config/v2-edits.ts
|
|
19420
19677
|
init_apitogo_config_core();
|
|
19421
19678
|
import { access as access8, mkdir as mkdir15, readFile as readFile23, writeFile as writeFile18 } from "node:fs/promises";
|
|
19422
|
-
import
|
|
19679
|
+
import path64 from "node:path";
|
|
19423
19680
|
import { glob as glob8 } from "glob";
|
|
19424
19681
|
init_invariant();
|
|
19425
19682
|
var ConfigEditError = class extends ApitogoError {
|
|
@@ -19432,10 +19689,10 @@ var exists4 = (target) => access8(target).then(
|
|
|
19432
19689
|
() => true,
|
|
19433
19690
|
() => false
|
|
19434
19691
|
);
|
|
19435
|
-
var toPosix2 = (value) => value.split(
|
|
19436
|
-
var relativeToConfig = (project, target) => toPosix2(
|
|
19692
|
+
var toPosix2 = (value) => value.split(path64.sep).join("/");
|
|
19693
|
+
var relativeToConfig = (project, target) => toPosix2(path64.relative(project.resolved.configDir, target)) || ".";
|
|
19437
19694
|
async function openConfigProject(dir) {
|
|
19438
|
-
const configPath =
|
|
19695
|
+
const configPath = path64.join(dir, APITOGO_CONFIG_FILENAME);
|
|
19439
19696
|
if (!await exists4(configPath)) {
|
|
19440
19697
|
throw new ConfigEditError(
|
|
19441
19698
|
`There is no ${APITOGO_CONFIG_FILENAME} in ${dir}.`,
|
|
@@ -19500,7 +19757,7 @@ function setPortalName(project, name) {
|
|
|
19500
19757
|
}
|
|
19501
19758
|
async function addGatewaySpec(project, specPath) {
|
|
19502
19759
|
const gateway = requireGateway(project);
|
|
19503
|
-
const absolute =
|
|
19760
|
+
const absolute = path64.resolve(project.dir, specPath);
|
|
19504
19761
|
if (!await exists4(absolute)) {
|
|
19505
19762
|
throw new ConfigEditError(`The OpenAPI file ${specPath} does not exist.`);
|
|
19506
19763
|
}
|
|
@@ -19544,7 +19801,7 @@ function parseBackendInput(input5) {
|
|
|
19544
19801
|
}
|
|
19545
19802
|
async function setGatewayOrigin(project, backend) {
|
|
19546
19803
|
const gateway = requireGateway(project);
|
|
19547
|
-
const source =
|
|
19804
|
+
const source = path64.resolve(project.dir, backend.source);
|
|
19548
19805
|
if (!await exists4(source)) {
|
|
19549
19806
|
throw new ConfigEditError(
|
|
19550
19807
|
`The API source folder ${backend.source} does not exist.`
|
|
@@ -19622,6 +19879,164 @@ export default function ${pageComponentName(slug)}() {
|
|
|
19622
19879
|
}
|
|
19623
19880
|
`;
|
|
19624
19881
|
}
|
|
19882
|
+
var HEADER_PAGES_FOLDER = "header-pages";
|
|
19883
|
+
var RESERVED_HEADER_SLUGS = [
|
|
19884
|
+
"index",
|
|
19885
|
+
"api",
|
|
19886
|
+
"pricing",
|
|
19887
|
+
"account",
|
|
19888
|
+
"login",
|
|
19889
|
+
"signup"
|
|
19890
|
+
];
|
|
19891
|
+
function buildTsxHeaderPage(slug, title, file, content) {
|
|
19892
|
+
const given = content?.trim() ? withoutLeadingH1(content) : "";
|
|
19893
|
+
const text2 = given ? `{${JSON.stringify(given)}}` : "Coming soon.";
|
|
19894
|
+
return `import { Callout, Heading, Typography } from "@lukoweb/apitogo/components";
|
|
19895
|
+
|
|
19896
|
+
/** The page's label in the header's top menu (portal.header.links in ${APITOGO_CONFIG_FILENAME}). */
|
|
19897
|
+
export const title = ${JSON.stringify(title)};
|
|
19898
|
+
|
|
19899
|
+
// This page is a React component: change it like any other one (add state, fetch data, use the portal's components).
|
|
19900
|
+
export default function ${pageComponentName(slug)}() {
|
|
19901
|
+
return (
|
|
19902
|
+
<section className="mx-auto max-w-screen-lg px-4 py-12 pt-(--padding-content-top)">
|
|
19903
|
+
<Typography>
|
|
19904
|
+
<Heading level={1}>{title}</Heading>
|
|
19905
|
+
<p>${text2}</p>
|
|
19906
|
+
{/* A note for you while you run the portal locally (\`apitogo run\`); the deployed portal does not show it. */}
|
|
19907
|
+
{import.meta.env.DEV && (
|
|
19908
|
+
<Callout type="info" title="Where this page lives">
|
|
19909
|
+
Edit <code>${file}</code>. The header's top menu links to it; the docs sidebar does not.
|
|
19910
|
+
</Callout>
|
|
19911
|
+
)}
|
|
19912
|
+
</Typography>
|
|
19913
|
+
</section>
|
|
19914
|
+
);
|
|
19915
|
+
}
|
|
19916
|
+
`;
|
|
19917
|
+
}
|
|
19918
|
+
var TSX_TITLE = /^export\s+const\s+title\s*(?::\s*string\s*)?=\s*.*$/m;
|
|
19919
|
+
async function writeHeaderPage(project, input5) {
|
|
19920
|
+
const portalConfig = requirePortal(project);
|
|
19921
|
+
const portal = project.resolved.portal;
|
|
19922
|
+
if (!portal?.docs.enabled || portal.docs.provider !== "apitogo") {
|
|
19923
|
+
throw new ConfigEditError(
|
|
19924
|
+
"This portal does not host pages.",
|
|
19925
|
+
'Header pages are served with the docs pages: they need portal.docs.provider "apitogo" and portal.docs.enabled not false.'
|
|
19926
|
+
);
|
|
19927
|
+
}
|
|
19928
|
+
const slug = normalizeDocsSlug(input5.slug);
|
|
19929
|
+
if (!slug) throw new ConfigEditError("The page path must not be empty.");
|
|
19930
|
+
if (slug.includes("/")) {
|
|
19931
|
+
throw new ConfigEditError(
|
|
19932
|
+
`A header page has a plain name, not a path: "${input5.slug}".`,
|
|
19933
|
+
"Pass one word, for example --page-slug partners (the page is then at /partners)."
|
|
19934
|
+
);
|
|
19935
|
+
}
|
|
19936
|
+
if (RESERVED_HEADER_SLUGS.includes(slug)) {
|
|
19937
|
+
throw new ConfigEditError(
|
|
19938
|
+
`The portal uses /${slug} itself, so a header page cannot have it.`,
|
|
19939
|
+
"Pick another name."
|
|
19940
|
+
);
|
|
19941
|
+
}
|
|
19942
|
+
const relative = (file2) => toPosix2(path64.relative(project.dir, file2));
|
|
19943
|
+
const docsBase = path64.join(portal.dir, "pages", slug);
|
|
19944
|
+
for (const file2 of [`${docsBase}.md`, `${docsBase}.mdx`, `${docsBase}.tsx`]) {
|
|
19945
|
+
if (await exists4(file2)) {
|
|
19946
|
+
throw new ConfigEditError(
|
|
19947
|
+
`The docs page ${relative(file2)} already has the address /${slug}.`,
|
|
19948
|
+
"Pick another name for the header page."
|
|
19949
|
+
);
|
|
19950
|
+
}
|
|
19951
|
+
}
|
|
19952
|
+
const base = path64.join(portal.dir, HEADER_PAGES_FOLDER, slug);
|
|
19953
|
+
const existing = (await Promise.all(
|
|
19954
|
+
[`${base}.tsx`, `${base}.mdx`, `${base}.md`].map(
|
|
19955
|
+
async (file2) => await exists4(file2) ? file2 : null
|
|
19956
|
+
)
|
|
19957
|
+
)).find((file2) => file2 !== null);
|
|
19958
|
+
let file;
|
|
19959
|
+
let title;
|
|
19960
|
+
let action;
|
|
19961
|
+
if (input5.update) {
|
|
19962
|
+
if (!existing) {
|
|
19963
|
+
throw new ConfigEditError(
|
|
19964
|
+
`There is no header page at ${relative(`${base}.${input5.format ?? "tsx"}`)}.`,
|
|
19965
|
+
"Leave out --page-update to add it."
|
|
19966
|
+
);
|
|
19967
|
+
}
|
|
19968
|
+
const source = await readFile23(existing, "utf8");
|
|
19969
|
+
const react2 = existing.endsWith(".tsx");
|
|
19970
|
+
title = input5.title?.trim() || (react2 ? tsxPageLabel(source, existing) : titleOf(source)) || slug;
|
|
19971
|
+
file = existing;
|
|
19972
|
+
action = "updated";
|
|
19973
|
+
if (react2) {
|
|
19974
|
+
await writeFile18(
|
|
19975
|
+
file,
|
|
19976
|
+
input5.content !== void 0 ? buildTsxHeaderPage(slug, title, relative(file), input5.content) : TSX_TITLE.test(source) ? source.replace(
|
|
19977
|
+
TSX_TITLE,
|
|
19978
|
+
`export const title = ${JSON.stringify(title)};`
|
|
19979
|
+
) : source,
|
|
19980
|
+
"utf8"
|
|
19981
|
+
);
|
|
19982
|
+
} else {
|
|
19983
|
+
const body = input5.content ?? source.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, "").trim();
|
|
19984
|
+
await writeFile18(file, buildDocsPage(title, body), "utf8");
|
|
19985
|
+
}
|
|
19986
|
+
} else {
|
|
19987
|
+
if (existing) {
|
|
19988
|
+
throw new ConfigEditError(
|
|
19989
|
+
`A header page already exists at ${relative(existing)}.`,
|
|
19990
|
+
"Pass --page-update to change it."
|
|
19991
|
+
);
|
|
19992
|
+
}
|
|
19993
|
+
const given = input5.title?.trim();
|
|
19994
|
+
if (!given) {
|
|
19995
|
+
throw new ConfigEditError("A new page needs a title (--page-title).");
|
|
19996
|
+
}
|
|
19997
|
+
title = given;
|
|
19998
|
+
file = `${base}.${input5.format ?? "tsx"}`;
|
|
19999
|
+
action = "added";
|
|
20000
|
+
await mkdir15(path64.dirname(file), { recursive: true });
|
|
20001
|
+
await writeFile18(
|
|
20002
|
+
file,
|
|
20003
|
+
file.endsWith(".tsx") ? buildTsxHeaderPage(slug, title, relative(file), input5.content) : buildDocsPage(
|
|
20004
|
+
title,
|
|
20005
|
+
input5.content?.trim() ? input5.content : `{/* Write this page in Markdown. It is linked from the header's top menu (portal.header.links in ${APITOGO_CONFIG_FILENAME}), not from the docs sidebar. */}
|
|
20006
|
+
|
|
20007
|
+
Coming soon.`
|
|
20008
|
+
),
|
|
20009
|
+
"utf8"
|
|
20010
|
+
);
|
|
20011
|
+
}
|
|
20012
|
+
const page = relativeToConfig(project, file);
|
|
20013
|
+
const target = path64.resolve(file);
|
|
20014
|
+
const links = portalConfig.header?.links ?? [];
|
|
20015
|
+
const known = links.some(
|
|
20016
|
+
(link) => "page" in link && path64.resolve(project.resolved.configDir, link.page) === target
|
|
20017
|
+
);
|
|
20018
|
+
const nextLinks = known ? links.map(
|
|
20019
|
+
(link) => "page" in link && path64.resolve(project.resolved.configDir, link.page) === target ? { label: title, page: link.page } : link
|
|
20020
|
+
) : [...links, { label: title, page }];
|
|
20021
|
+
return {
|
|
20022
|
+
project: withConfig(project, {
|
|
20023
|
+
...project.config,
|
|
20024
|
+
portal: {
|
|
20025
|
+
...portalConfig,
|
|
20026
|
+
header: { ...portalConfig.header, links: nextLinks }
|
|
20027
|
+
}
|
|
20028
|
+
}),
|
|
20029
|
+
page: {
|
|
20030
|
+
action,
|
|
20031
|
+
slug,
|
|
20032
|
+
route: `/${slug}`,
|
|
20033
|
+
file: relative(file),
|
|
20034
|
+
format: path64.extname(file).slice(1),
|
|
20035
|
+
inPortal: true,
|
|
20036
|
+
header: true
|
|
20037
|
+
}
|
|
20038
|
+
};
|
|
20039
|
+
}
|
|
19625
20040
|
async function writeDocsPage(project, input5) {
|
|
19626
20041
|
requirePortal(project);
|
|
19627
20042
|
if (/^[A-Za-z]:[\\/]/.test(input5.slug.trim())) {
|
|
@@ -19645,13 +20060,13 @@ async function writeDocsPage(project, input5) {
|
|
|
19645
20060
|
"For example --page-order 1 puts the page first in the sidebar."
|
|
19646
20061
|
);
|
|
19647
20062
|
}
|
|
19648
|
-
const base =
|
|
20063
|
+
const base = path64.join(portal.dir, "pages", ...slug.split("/"));
|
|
19649
20064
|
const existing = (await Promise.all(
|
|
19650
20065
|
[`${base}.tsx`, `${base}.mdx`, `${base}.md`].map(
|
|
19651
20066
|
async (file2) => await exists4(file2) ? file2 : null
|
|
19652
20067
|
)
|
|
19653
20068
|
)).find((file2) => file2 !== null);
|
|
19654
|
-
const relative = (file2) => toPosix2(
|
|
20069
|
+
const relative = (file2) => toPosix2(path64.relative(project.dir, file2));
|
|
19655
20070
|
const write = (file2, title, order = input5.order) => writeFile18(
|
|
19656
20071
|
file2,
|
|
19657
20072
|
file2.endsWith(".tsx") ? buildTsxDocsPage(slug, title, relative(file2), input5.content, order) : buildDocsPage(title, input5.content, order),
|
|
@@ -19685,17 +20100,17 @@ async function writeDocsPage(project, input5) {
|
|
|
19685
20100
|
}
|
|
19686
20101
|
file = `${base}.${input5.format ?? "tsx"}`;
|
|
19687
20102
|
action = "added";
|
|
19688
|
-
await mkdir15(
|
|
20103
|
+
await mkdir15(path64.dirname(file), { recursive: true });
|
|
19689
20104
|
await write(file, title);
|
|
19690
20105
|
}
|
|
19691
|
-
const same = (match) =>
|
|
20106
|
+
const same = (match) => path64.resolve(match) === path64.resolve(file);
|
|
19692
20107
|
const inPortal = file.endsWith(".tsx") ? (await findTsxPages(portal.docs.content)).some((page) => same(page.file)) : (await glob8(portal.docs.content, { absolute: true })).some(same);
|
|
19693
20108
|
return {
|
|
19694
20109
|
action,
|
|
19695
20110
|
slug,
|
|
19696
20111
|
route: `/${slug}`,
|
|
19697
20112
|
file: relative(file),
|
|
19698
|
-
format:
|
|
20113
|
+
format: path64.extname(file).slice(1),
|
|
19699
20114
|
inPortal
|
|
19700
20115
|
};
|
|
19701
20116
|
}
|
|
@@ -19774,7 +20189,7 @@ async function readPlanCatalog(project) {
|
|
|
19774
20189
|
}
|
|
19775
20190
|
var skuOf = (item) => isPlainObject3(item) && typeof item.sku === "string" ? item.sku.trim().toLowerCase() : void 0;
|
|
19776
20191
|
async function writePlanCatalog(file, catalog, plans) {
|
|
19777
|
-
await mkdir15(
|
|
20192
|
+
await mkdir15(path64.dirname(file), { recursive: true });
|
|
19778
20193
|
await writeFile18(
|
|
19779
20194
|
file,
|
|
19780
20195
|
`${JSON.stringify({ ...catalog, plans }, null, 2)}
|
|
@@ -19797,7 +20212,7 @@ async function upsertPlan(project, plan2) {
|
|
|
19797
20212
|
return {
|
|
19798
20213
|
action: index === -1 ? "added" : "updated",
|
|
19799
20214
|
sku: plan2.sku,
|
|
19800
|
-
file: toPosix2(
|
|
20215
|
+
file: toPosix2(path64.relative(project.dir, file)),
|
|
19801
20216
|
paid,
|
|
19802
20217
|
needsBilling: paid && billing.provider !== "stripe"
|
|
19803
20218
|
};
|
|
@@ -19887,12 +20302,12 @@ async function removePlan(project, rawSku) {
|
|
|
19887
20302
|
if (next.length === catalog.plans.length) {
|
|
19888
20303
|
const known = catalog.plans.map(skuOf).filter(Boolean).join(", ");
|
|
19889
20304
|
throw new ConfigEditError(
|
|
19890
|
-
`There is no plan "${sku}" in ${toPosix2(
|
|
20305
|
+
`There is no plan "${sku}" in ${toPosix2(path64.relative(project.dir, file))}.`,
|
|
19891
20306
|
known ? `The plans are: ${known}.` : "The plans file has no plans."
|
|
19892
20307
|
);
|
|
19893
20308
|
}
|
|
19894
20309
|
await writePlanCatalog(file, catalog, next);
|
|
19895
|
-
return { sku, file: toPosix2(
|
|
20310
|
+
return { sku, file: toPosix2(path64.relative(project.dir, file)) };
|
|
19896
20311
|
}
|
|
19897
20312
|
|
|
19898
20313
|
// src/cli/make-config/wrap-up.ts
|
|
@@ -19915,6 +20330,12 @@ function printPageResult(page) {
|
|
|
19915
20330
|
printSuccessToConsole(
|
|
19916
20331
|
`Page ${page.action}: ${page.file} (route ${page.route})`
|
|
19917
20332
|
);
|
|
20333
|
+
if (page.header) {
|
|
20334
|
+
printHintToConsole(
|
|
20335
|
+
`The header's top menu links to it (portal.header.links); the docs sidebar does not. Edit the file to change the content. Run \`apitogo deploy --only portal\` to publish it.`
|
|
20336
|
+
);
|
|
20337
|
+
return;
|
|
20338
|
+
}
|
|
19918
20339
|
if (page.inPortal) {
|
|
19919
20340
|
printHintToConsole(
|
|
19920
20341
|
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."
|
|
@@ -20173,7 +20594,7 @@ async function applyConfigFlags(project, argv, changes) {
|
|
|
20173
20594
|
return { project: next, openApi };
|
|
20174
20595
|
}
|
|
20175
20596
|
async function makeConfig(argv) {
|
|
20176
|
-
const dir =
|
|
20597
|
+
const dir = path65.resolve(process.cwd(), argv.dir);
|
|
20177
20598
|
const interactive = shouldRunInteractive(argv);
|
|
20178
20599
|
const json = argv.json === true;
|
|
20179
20600
|
const changes = [];
|
|
@@ -20216,7 +20637,32 @@ async function makeConfig(argv) {
|
|
|
20216
20637
|
const applied = await applyConfigFlags(project, argv, changes);
|
|
20217
20638
|
project = applied.project;
|
|
20218
20639
|
openApi = applied.openApi;
|
|
20219
|
-
if (argv.pageSlug
|
|
20640
|
+
if (argv.pageHeader === true && argv.pageSlug === void 0) {
|
|
20641
|
+
throw new ApitogoError("--page-header needs --page-slug.", {
|
|
20642
|
+
developerHint: "Name the page, for example --page-slug partners --page-title Partners --page-header."
|
|
20643
|
+
});
|
|
20644
|
+
}
|
|
20645
|
+
if (argv.pageSlug !== void 0 && argv.pageHeader === true) {
|
|
20646
|
+
if (argv.pageOrder !== void 0) {
|
|
20647
|
+
throw new ApitogoError(
|
|
20648
|
+
"--page-order sets a place in the docs sidebar, which a header page is not in.",
|
|
20649
|
+
{
|
|
20650
|
+
developerHint: "Header links show in the order of portal.header.links in apitogo.config.json."
|
|
20651
|
+
}
|
|
20652
|
+
);
|
|
20653
|
+
}
|
|
20654
|
+
const written = await writeHeaderPage(project, {
|
|
20655
|
+
slug: argv.pageSlug,
|
|
20656
|
+
title: argv.pageTitle,
|
|
20657
|
+
content: argv.pageContent,
|
|
20658
|
+
update: argv.pageUpdate === true,
|
|
20659
|
+
format: argv.pageFormat
|
|
20660
|
+
});
|
|
20661
|
+
project = written.project;
|
|
20662
|
+
await saveConfigProject(project);
|
|
20663
|
+
page = written.page;
|
|
20664
|
+
changes.push(page.action === "added" ? "page_add" : "page_update");
|
|
20665
|
+
} else if (argv.pageSlug !== void 0) {
|
|
20220
20666
|
page = await writeDocsPage(project, {
|
|
20221
20667
|
slug: argv.pageSlug,
|
|
20222
20668
|
title: argv.pageTitle,
|
|
@@ -20365,6 +20811,10 @@ function addConfigOptions(yargs2) {
|
|
|
20365
20811
|
type: "boolean",
|
|
20366
20812
|
default: false,
|
|
20367
20813
|
describe: "Update an existing page instead of adding one"
|
|
20814
|
+
}).option("page-header", {
|
|
20815
|
+
type: "boolean",
|
|
20816
|
+
default: false,
|
|
20817
|
+
describe: "Make --page-slug a page of its own, linked from the header's top menu instead of the docs sidebar (<portal>/header-pages/<slug>.tsx; --page-format mdx for Markdown)"
|
|
20368
20818
|
}).option("plan-sku", {
|
|
20369
20819
|
type: "string",
|
|
20370
20820
|
describe: "Add or change the plan with this SKU in the plans file; the --plan-* options set its fields"
|
|
@@ -20402,7 +20852,10 @@ function addConfigOptions(yargs2) {
|
|
|
20402
20852
|
).example(
|
|
20403
20853
|
"$0 config --plan-sku enterprise --plan-price custom",
|
|
20404
20854
|
"A contact-us plan"
|
|
20405
|
-
).example("$0 config --remove-plan enterprise", "Take a plan out").
|
|
20855
|
+
).example("$0 config --remove-plan enterprise", "Take a plan out").example(
|
|
20856
|
+
"$0 config --page-slug partners --page-title Partners --page-header",
|
|
20857
|
+
"A page at /partners, linked from the header's top menu"
|
|
20858
|
+
).option("plan", {
|
|
20406
20859
|
type: "string",
|
|
20407
20860
|
describe: "JSON plan added to the plans file (plans.file, default apitogo/plans.json), or replacing the one with the same sku"
|
|
20408
20861
|
}).option("patch", {
|
|
@@ -20424,27 +20877,27 @@ var config_default = {
|
|
|
20424
20877
|
init_apitogo_config_core();
|
|
20425
20878
|
import { execFile } from "node:child_process";
|
|
20426
20879
|
import { readFile as readFile24 } from "node:fs/promises";
|
|
20427
|
-
import
|
|
20880
|
+
import path67 from "node:path";
|
|
20428
20881
|
import { promisify } from "node:util";
|
|
20429
20882
|
|
|
20430
20883
|
// src/cli/create/dry-run.ts
|
|
20431
20884
|
import { mkdir as mkdir16, mkdtemp, readdir as readdir4, rm as rm9 } from "node:fs/promises";
|
|
20432
20885
|
import { tmpdir } from "node:os";
|
|
20433
|
-
import
|
|
20886
|
+
import path66 from "node:path";
|
|
20434
20887
|
async function listFiles(root, dir = root) {
|
|
20435
20888
|
const entries = await readdir4(dir, { withFileTypes: true });
|
|
20436
20889
|
const nested = await Promise.all(
|
|
20437
20890
|
entries.map(async (entry) => {
|
|
20438
|
-
const full =
|
|
20891
|
+
const full = path66.join(dir, entry.name);
|
|
20439
20892
|
if (entry.isDirectory()) return listFiles(root, full);
|
|
20440
|
-
return [
|
|
20893
|
+
return [path66.relative(root, full).split(path66.sep).join("/")];
|
|
20441
20894
|
})
|
|
20442
20895
|
);
|
|
20443
20896
|
return nested.flat();
|
|
20444
20897
|
}
|
|
20445
20898
|
async function previewCreate(input5) {
|
|
20446
|
-
const scratch = await mkdtemp(
|
|
20447
|
-
const dir =
|
|
20899
|
+
const scratch = await mkdtemp(path66.join(tmpdir(), "apitogo-create-"));
|
|
20900
|
+
const dir = path66.join(scratch, "project");
|
|
20448
20901
|
try {
|
|
20449
20902
|
await mkdir16(dir);
|
|
20450
20903
|
await applyInitPlan(await planInit({ dir, name: input5.name }));
|
|
@@ -20477,9 +20930,9 @@ async function previewCreate(input5) {
|
|
|
20477
20930
|
var execFileAsync = promisify(execFile);
|
|
20478
20931
|
function nextStepHint(dir) {
|
|
20479
20932
|
const linked = loadConfigV2(dir).resolved.project.id;
|
|
20480
|
-
const cd =
|
|
20933
|
+
const cd = path67.resolve(dir) === path67.resolve(process.cwd());
|
|
20481
20934
|
const steps = linked ? "apitogo deploy" : "apitogo project create, then apitogo deploy";
|
|
20482
|
-
return cd ? `Next: ${steps}` : `Next: cd ${JSON.stringify(
|
|
20935
|
+
return cd ? `Next: ${steps}` : `Next: cd ${JSON.stringify(path67.relative(process.cwd(), dir))}, then ${steps}`;
|
|
20483
20936
|
}
|
|
20484
20937
|
function projectFolderName(name) {
|
|
20485
20938
|
return name.trim().replace(/[<>:"/\\|?*\s]+/g, "-").replace(/^[-.]+|[-.]+$/g, "") || "apitogo-project";
|
|
@@ -20505,13 +20958,13 @@ async function gitHasUncommittedChanges(dir) {
|
|
|
20505
20958
|
async function defaultName(dir) {
|
|
20506
20959
|
try {
|
|
20507
20960
|
const parsed = JSON.parse(
|
|
20508
|
-
await readFile24(
|
|
20961
|
+
await readFile24(path67.join(dir, "package.json"), "utf8")
|
|
20509
20962
|
);
|
|
20510
20963
|
if (typeof parsed.name === "string" && parsed.name.trim())
|
|
20511
20964
|
return parsed.name.replace(/^@[^/]+\//, "");
|
|
20512
20965
|
} catch {
|
|
20513
20966
|
}
|
|
20514
|
-
return
|
|
20967
|
+
return path67.basename(dir);
|
|
20515
20968
|
}
|
|
20516
20969
|
function parseServicesFlag(value) {
|
|
20517
20970
|
const names = (value ?? "").split(",").map((name) => name.trim()).filter(Boolean);
|
|
@@ -20537,7 +20990,7 @@ async function createProject(argv, deps = {}) {
|
|
|
20537
20990
|
if (!json) printDiagnosticsToConsole(line2);
|
|
20538
20991
|
};
|
|
20539
20992
|
try {
|
|
20540
|
-
const base =
|
|
20993
|
+
const base = path67.resolve(process.cwd(), argv.dir ?? ".");
|
|
20541
20994
|
let dir = base;
|
|
20542
20995
|
let requested = parseServicesFlag(argv.services);
|
|
20543
20996
|
let template = argv.template;
|
|
@@ -20560,8 +21013,8 @@ async function createProject(argv, deps = {}) {
|
|
|
20560
21013
|
default: await defaultName(base)
|
|
20561
21014
|
}) : await defaultName(base));
|
|
20562
21015
|
const folder = projectFolderName(name);
|
|
20563
|
-
if (argv.dir === void 0 && folder !==
|
|
20564
|
-
dir =
|
|
21016
|
+
if (argv.dir === void 0 && folder !== path67.basename(base))
|
|
21017
|
+
dir = path67.join(base, folder);
|
|
20565
21018
|
}
|
|
20566
21019
|
if (await (deps.hasUncommittedChanges ?? gitHasUncommittedChanges)(dir))
|
|
20567
21020
|
say(
|
|
@@ -20574,7 +21027,7 @@ async function createProject(argv, deps = {}) {
|
|
|
20574
21027
|
if (argv.dryRun) {
|
|
20575
21028
|
const services = requested.length > 0 ? requested : templateServices ? STARTER_SERVICES : [];
|
|
20576
21029
|
const preview2 = services.length > 0 ? await previewCreate({ name, template, services }) : void 0;
|
|
20577
|
-
const folder =
|
|
21030
|
+
const folder = path67.relative(process.cwd(), dir) || ".";
|
|
20578
21031
|
if (json)
|
|
20579
21032
|
console.log(
|
|
20580
21033
|
JSON.stringify({
|
|
@@ -20607,7 +21060,7 @@ async function createProject(argv, deps = {}) {
|
|
|
20607
21060
|
}
|
|
20608
21061
|
await applyInitPlan(plan2);
|
|
20609
21062
|
say(
|
|
20610
|
-
dir === base ? `Created ${APITOGO_CONFIG_FILENAME}.` : `Created ${
|
|
21063
|
+
dir === base ? `Created ${APITOGO_CONFIG_FILENAME}.` : `Created ${path67.relative(base, dir)}${path67.sep}${APITOGO_CONFIG_FILENAME}.`
|
|
20611
21064
|
);
|
|
20612
21065
|
} else {
|
|
20613
21066
|
say(`${APITOGO_CONFIG_FILENAME} exists: continuing from it.`);
|
|
@@ -20749,10 +21202,10 @@ var create_default = {
|
|
|
20749
21202
|
};
|
|
20750
21203
|
|
|
20751
21204
|
// src/cli/cmds/deploy.ts
|
|
20752
|
-
import
|
|
21205
|
+
import path86 from "node:path";
|
|
20753
21206
|
|
|
20754
21207
|
// src/cli/apply/handler.ts
|
|
20755
|
-
import
|
|
21208
|
+
import path79 from "node:path";
|
|
20756
21209
|
|
|
20757
21210
|
// src/cli/platform/helpers/gateway-plan-validation.ts
|
|
20758
21211
|
init_gateway_limits();
|
|
@@ -20971,11 +21424,11 @@ init_gateway_limits();
|
|
|
20971
21424
|
// src/cli/platform/helpers/deploy-artifact-hash.ts
|
|
20972
21425
|
import { createHash as createHash3 } from "node:crypto";
|
|
20973
21426
|
import { createReadStream, promises as fs6 } from "node:fs";
|
|
20974
|
-
import
|
|
21427
|
+
import path69 from "node:path";
|
|
20975
21428
|
|
|
20976
21429
|
// src/cli/platform/helpers/package-files.ts
|
|
20977
21430
|
import { promises as fs5 } from "node:fs";
|
|
20978
|
-
import
|
|
21431
|
+
import path68 from "node:path";
|
|
20979
21432
|
import ignore from "ignore";
|
|
20980
21433
|
var DEFAULT_EXCLUDES = /* @__PURE__ */ new Set([
|
|
20981
21434
|
"node_modules",
|
|
@@ -20989,7 +21442,7 @@ async function loadGitignore(rootDir, extraExcludes = []) {
|
|
|
20989
21442
|
const ig = ignore();
|
|
20990
21443
|
ig.add(["node_modules/", ".git/", "dist/", "bin/", "obj/"]);
|
|
20991
21444
|
if (extraExcludes.length > 0) ig.add([...extraExcludes]);
|
|
20992
|
-
const gitignorePath =
|
|
21445
|
+
const gitignorePath = path68.join(rootDir, ".gitignore");
|
|
20993
21446
|
try {
|
|
20994
21447
|
const content = await fs5.readFile(gitignorePath, "utf8");
|
|
20995
21448
|
ig.add(content);
|
|
@@ -20998,11 +21451,11 @@ async function loadGitignore(rootDir, extraExcludes = []) {
|
|
|
20998
21451
|
return ig;
|
|
20999
21452
|
}
|
|
21000
21453
|
async function collectFiles(rootDir, relativeDir, ig, files) {
|
|
21001
|
-
const absDir =
|
|
21454
|
+
const absDir = path68.join(rootDir, relativeDir);
|
|
21002
21455
|
const entries = await fs5.readdir(absDir, { withFileTypes: true });
|
|
21003
21456
|
for (const entry of entries) {
|
|
21004
|
-
const rel2 = relativeDir ?
|
|
21005
|
-
const relPosix = rel2.split(
|
|
21457
|
+
const rel2 = relativeDir ? path68.join(relativeDir, entry.name) : entry.name;
|
|
21458
|
+
const relPosix = rel2.split(path68.sep).join("/");
|
|
21006
21459
|
if (DEFAULT_EXCLUDES.has(entry.name) && !relativeDir) {
|
|
21007
21460
|
continue;
|
|
21008
21461
|
}
|
|
@@ -21017,7 +21470,7 @@ async function collectFiles(rootDir, relativeDir, ig, files) {
|
|
|
21017
21470
|
}
|
|
21018
21471
|
}
|
|
21019
21472
|
async function collectPackageableFiles(sourceDirectory, extraExcludes = []) {
|
|
21020
|
-
const resolved =
|
|
21473
|
+
const resolved = path68.resolve(sourceDirectory);
|
|
21021
21474
|
const stat7 = await fs5.stat(resolved).catch(() => null);
|
|
21022
21475
|
if (!stat7?.isDirectory()) {
|
|
21023
21476
|
throw new Error(`sourceDirectory is not a directory: ${resolved}`);
|
|
@@ -21043,7 +21496,7 @@ async function sha256File(filePath) {
|
|
|
21043
21496
|
return hash2.digest("hex");
|
|
21044
21497
|
}
|
|
21045
21498
|
async function hashDirectoryContents(rootDirectory, extraExcludes = []) {
|
|
21046
|
-
const resolved =
|
|
21499
|
+
const resolved = path69.resolve(rootDirectory);
|
|
21047
21500
|
const files = (await collectPackageableFiles(resolved, extraExcludes)).sort(
|
|
21048
21501
|
(a, b) => a.localeCompare(b)
|
|
21049
21502
|
);
|
|
@@ -21051,13 +21504,13 @@ async function hashDirectoryContents(rootDirectory, extraExcludes = []) {
|
|
|
21051
21504
|
for (const rel2 of files) {
|
|
21052
21505
|
hash2.update(rel2);
|
|
21053
21506
|
hash2.update("\0");
|
|
21054
|
-
hash2.update(await fs6.readFile(
|
|
21507
|
+
hash2.update(await fs6.readFile(path69.join(resolved, rel2)));
|
|
21055
21508
|
hash2.update("\0");
|
|
21056
21509
|
}
|
|
21057
21510
|
return hash2.digest("hex");
|
|
21058
21511
|
}
|
|
21059
21512
|
async function hashDevPortalSiteSources(siteDirectory, options) {
|
|
21060
|
-
const resolved =
|
|
21513
|
+
const resolved = path69.resolve(siteDirectory);
|
|
21061
21514
|
const hash2 = createHash3("sha256");
|
|
21062
21515
|
const candidates = [
|
|
21063
21516
|
"apitogo.config.json",
|
|
@@ -21067,7 +21520,7 @@ async function hashDevPortalSiteSources(siteDirectory, options) {
|
|
|
21067
21520
|
"zudoku.config.tsx"
|
|
21068
21521
|
];
|
|
21069
21522
|
for (const name of candidates) {
|
|
21070
|
-
const full =
|
|
21523
|
+
const full = path69.join(resolved, name);
|
|
21071
21524
|
try {
|
|
21072
21525
|
hash2.update(name);
|
|
21073
21526
|
hash2.update("\0");
|
|
@@ -21077,7 +21530,7 @@ async function hashDevPortalSiteSources(siteDirectory, options) {
|
|
|
21077
21530
|
}
|
|
21078
21531
|
}
|
|
21079
21532
|
for (const dir of ["pages", "landing", "src"]) {
|
|
21080
|
-
const full =
|
|
21533
|
+
const full = path69.join(resolved, dir);
|
|
21081
21534
|
try {
|
|
21082
21535
|
const st = await fs6.stat(full);
|
|
21083
21536
|
if (!st.isDirectory()) continue;
|
|
@@ -21306,8 +21759,8 @@ function normalizeActionKey(actionKey2) {
|
|
|
21306
21759
|
const trimmed = actionKey2.trim();
|
|
21307
21760
|
if (trimmed.includes(":")) {
|
|
21308
21761
|
const [method2, ...pathParts] = trimmed.split(":");
|
|
21309
|
-
const
|
|
21310
|
-
return `${method2?.toLowerCase()}:${
|
|
21762
|
+
const path101 = pathParts.join(":").trim();
|
|
21763
|
+
return `${method2?.toLowerCase()}:${path101.startsWith("/") ? path101 : `/${path101}`}`;
|
|
21311
21764
|
}
|
|
21312
21765
|
const spaceIndex = trimmed.indexOf(" ");
|
|
21313
21766
|
if (spaceIndex <= 0) {
|
|
@@ -21316,8 +21769,8 @@ function normalizeActionKey(actionKey2) {
|
|
|
21316
21769
|
);
|
|
21317
21770
|
}
|
|
21318
21771
|
const method = trimmed.slice(0, spaceIndex).trim().toLowerCase();
|
|
21319
|
-
const
|
|
21320
|
-
return `${method}:${
|
|
21772
|
+
const path100 = trimmed.slice(spaceIndex + 1).trim();
|
|
21773
|
+
return `${method}:${path100.startsWith("/") ? path100 : `/${path100}`}`;
|
|
21321
21774
|
}
|
|
21322
21775
|
async function applyGatewayPublicRoutes(client, projectId, routes, options) {
|
|
21323
21776
|
const applied = [];
|
|
@@ -21796,7 +22249,7 @@ async function upsertGatewayPlansFromManifest(client, config2, projectId, plans,
|
|
|
21796
22249
|
|
|
21797
22250
|
// src/cli/platform/helpers/openapi-gateway-servers.ts
|
|
21798
22251
|
import { mkdir as mkdir17, readFile as readFile25, writeFile as writeFile19 } from "node:fs/promises";
|
|
21799
|
-
import
|
|
22252
|
+
import path70 from "node:path";
|
|
21800
22253
|
import YAML2 from "yaml";
|
|
21801
22254
|
var GATEWAY_URL_ENV_KEY = "APITOGO_GATEWAY_URL";
|
|
21802
22255
|
var PUBLISH_OPENAPI_RELATIVE = ".apitogo/openapi-publish.json";
|
|
@@ -21828,7 +22281,7 @@ async function resolveProjectGatewayUrl(client, projectId) {
|
|
|
21828
22281
|
}
|
|
21829
22282
|
async function readOpenApiDocument(filePath) {
|
|
21830
22283
|
const content = await readFile25(filePath, "utf8");
|
|
21831
|
-
const ext =
|
|
22284
|
+
const ext = path70.extname(filePath).toLowerCase();
|
|
21832
22285
|
const parsed = ext === ".json" ? JSON.parse(content) : YAML2.parse(content);
|
|
21833
22286
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
21834
22287
|
throw new Error(`OpenAPI document must be an object: ${filePath}`);
|
|
@@ -21836,13 +22289,13 @@ async function readOpenApiDocument(filePath) {
|
|
|
21836
22289
|
return parsed;
|
|
21837
22290
|
}
|
|
21838
22291
|
async function materializePublishOpenApiWithGateway(siteDirectory, sourceOpenApiPath, gatewayUrl) {
|
|
21839
|
-
const site =
|
|
21840
|
-
const source =
|
|
22292
|
+
const site = path70.resolve(siteDirectory);
|
|
22293
|
+
const source = path70.resolve(sourceOpenApiPath);
|
|
21841
22294
|
const relativeInput = PUBLISH_OPENAPI_RELATIVE;
|
|
21842
|
-
const outputPath =
|
|
22295
|
+
const outputPath = path70.join(site, ...relativeInput.split("/"));
|
|
21843
22296
|
const doc = await readOpenApiDocument(source);
|
|
21844
22297
|
const rewritten = withGatewayServers(doc, gatewayUrl);
|
|
21845
|
-
await mkdir17(
|
|
22298
|
+
await mkdir17(path70.dirname(outputPath), { recursive: true });
|
|
21846
22299
|
await writeFile19(
|
|
21847
22300
|
outputPath,
|
|
21848
22301
|
`${JSON.stringify(rewritten, null, 2)}
|
|
@@ -21852,8 +22305,8 @@ async function materializePublishOpenApiWithGateway(siteDirectory, sourceOpenApi
|
|
|
21852
22305
|
return { outputPath, relativeInput };
|
|
21853
22306
|
}
|
|
21854
22307
|
async function pointSiteApisAtPublishOpenApi(siteDirectory, relativeInput) {
|
|
21855
|
-
const configPath =
|
|
21856
|
-
|
|
22308
|
+
const configPath = path70.join(
|
|
22309
|
+
path70.resolve(siteDirectory),
|
|
21857
22310
|
APITOGO_CONFIG_FILENAME2
|
|
21858
22311
|
);
|
|
21859
22312
|
const raw = await readFile25(configPath, "utf8");
|
|
@@ -21895,7 +22348,7 @@ async function pointSiteApisAtPublishOpenApi(siteDirectory, relativeInput) {
|
|
|
21895
22348
|
};
|
|
21896
22349
|
}
|
|
21897
22350
|
async function prepareOpenApiServersForGatewayBuild(options) {
|
|
21898
|
-
const siteDirectory =
|
|
22351
|
+
const siteDirectory = path70.resolve(options.siteDirectory);
|
|
21899
22352
|
let openApiPath = resolveBackendOpenApiPath(
|
|
21900
22353
|
options.manifest?.backend?.openApiPath,
|
|
21901
22354
|
{
|
|
@@ -21909,7 +22362,7 @@ async function prepareOpenApiServersForGatewayBuild(options) {
|
|
|
21909
22362
|
if (!openApiPath) {
|
|
21910
22363
|
try {
|
|
21911
22364
|
const raw = await readFile25(
|
|
21912
|
-
|
|
22365
|
+
path70.join(siteDirectory, APITOGO_CONFIG_FILENAME2),
|
|
21913
22366
|
"utf8"
|
|
21914
22367
|
);
|
|
21915
22368
|
const config2 = JSON.parse(raw);
|
|
@@ -21938,8 +22391,8 @@ function normalizeActionKeyFormat(actionKey2) {
|
|
|
21938
22391
|
const trimmed = actionKey2.trim();
|
|
21939
22392
|
if (trimmed.includes(":")) {
|
|
21940
22393
|
const [method2, ...pathParts] = trimmed.split(":");
|
|
21941
|
-
const
|
|
21942
|
-
return `${method2.toLowerCase()}:${
|
|
22394
|
+
const path101 = pathParts.join(":").trim();
|
|
22395
|
+
return `${method2.toLowerCase()}:${path101.startsWith("/") ? path101 : `/${path101}`}`;
|
|
21943
22396
|
}
|
|
21944
22397
|
const spaceIndex = trimmed.indexOf(" ");
|
|
21945
22398
|
if (spaceIndex <= 0) {
|
|
@@ -21948,8 +22401,8 @@ function normalizeActionKeyFormat(actionKey2) {
|
|
|
21948
22401
|
);
|
|
21949
22402
|
}
|
|
21950
22403
|
const method = trimmed.slice(0, spaceIndex).trim().toLowerCase();
|
|
21951
|
-
const
|
|
21952
|
-
return `${method}:${
|
|
22404
|
+
const path100 = trimmed.slice(spaceIndex + 1).trim();
|
|
22405
|
+
return `${method}:${path100.startsWith("/") ? path100 : `/${path100}`}`;
|
|
21953
22406
|
}
|
|
21954
22407
|
function normalizePublicRoute(route) {
|
|
21955
22408
|
const trimmed = route.trim();
|
|
@@ -21983,10 +22436,10 @@ function collectManifestPublicActionKeys(gateway) {
|
|
|
21983
22436
|
|
|
21984
22437
|
// src/cli/platform/helpers/publish-ledger.ts
|
|
21985
22438
|
import { mkdir as mkdir18, readFile as readFile26, writeFile as writeFile20 } from "node:fs/promises";
|
|
21986
|
-
import
|
|
22439
|
+
import path71 from "node:path";
|
|
21987
22440
|
var PUBLISH_LEDGER_RELATIVE_PATH = ".apitogo/publish-state.json";
|
|
21988
22441
|
function publishLedgerPath(siteDirectory) {
|
|
21989
|
-
return
|
|
22442
|
+
return path71.join(path71.resolve(siteDirectory), PUBLISH_LEDGER_RELATIVE_PATH);
|
|
21990
22443
|
}
|
|
21991
22444
|
async function readPublishLedger(siteDirectory) {
|
|
21992
22445
|
const filePath = publishLedgerPath(siteDirectory);
|
|
@@ -22003,7 +22456,7 @@ async function readPublishLedger(siteDirectory) {
|
|
|
22003
22456
|
}
|
|
22004
22457
|
async function writePublishLedger(siteDirectory, ledger) {
|
|
22005
22458
|
const filePath = publishLedgerPath(siteDirectory);
|
|
22006
|
-
await mkdir18(
|
|
22459
|
+
await mkdir18(path71.dirname(filePath), { recursive: true });
|
|
22007
22460
|
const next = {
|
|
22008
22461
|
...ledger,
|
|
22009
22462
|
version: 1,
|
|
@@ -22524,7 +22977,7 @@ async function createProjectWithWarmPoolRetry(client, body, options) {
|
|
|
22524
22977
|
// src/cli/platform/helpers/backend-packaging.ts
|
|
22525
22978
|
import { mkdtemp as mkdtemp2, readdir as readdir5, rm as rm10 } from "node:fs/promises";
|
|
22526
22979
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
22527
|
-
import
|
|
22980
|
+
import path72 from "node:path";
|
|
22528
22981
|
async function directoryHasRuntimeConfig(dir) {
|
|
22529
22982
|
if (!await pathExists(dir)) {
|
|
22530
22983
|
return false;
|
|
@@ -22566,20 +23019,20 @@ function runDotnetPublish(projectDir, outputDir) {
|
|
|
22566
23019
|
async function findCsproj(projectDir) {
|
|
22567
23020
|
const entries = await readdir5(projectDir);
|
|
22568
23021
|
const csproj = entries.find((name) => name.endsWith(".csproj"));
|
|
22569
|
-
return csproj ?
|
|
23022
|
+
return csproj ? path72.join(projectDir, csproj) : null;
|
|
22570
23023
|
}
|
|
22571
23024
|
async function prepareBackendPackagingDirectory(args) {
|
|
22572
|
-
const sourceDirectory =
|
|
23025
|
+
const sourceDirectory = path72.resolve(args.sourceDirectory);
|
|
22573
23026
|
if (args.publishDirectory?.trim()) {
|
|
22574
23027
|
return {
|
|
22575
|
-
directory:
|
|
23028
|
+
directory: path72.resolve(args.publishDirectory),
|
|
22576
23029
|
packagingMode: "published"
|
|
22577
23030
|
};
|
|
22578
23031
|
}
|
|
22579
23032
|
if (await directoryHasRuntimeConfig(sourceDirectory)) {
|
|
22580
23033
|
return { directory: sourceDirectory, packagingMode: "published" };
|
|
22581
23034
|
}
|
|
22582
|
-
const publishSubdir =
|
|
23035
|
+
const publishSubdir = path72.join(sourceDirectory, "publish");
|
|
22583
23036
|
if (await directoryHasRuntimeConfig(publishSubdir)) {
|
|
22584
23037
|
return { directory: publishSubdir, packagingMode: "published" };
|
|
22585
23038
|
}
|
|
@@ -22591,9 +23044,9 @@ async function prepareBackendPackagingDirectory(args) {
|
|
|
22591
23044
|
return { directory: sourceDirectory, packagingMode: "source" };
|
|
22592
23045
|
}
|
|
22593
23046
|
const tempRoot = await mkdtemp2(
|
|
22594
|
-
|
|
23047
|
+
path72.join(tmpdir2(), "apitogo-dotnet-publish-")
|
|
22595
23048
|
);
|
|
22596
|
-
const outputDir =
|
|
23049
|
+
const outputDir = path72.join(tempRoot, "publish");
|
|
22597
23050
|
const result = await runDotnetPublish(sourceDirectory, outputDir);
|
|
22598
23051
|
if (result.exitCode !== 0) {
|
|
22599
23052
|
await rm10(tempRoot, { recursive: true, force: true });
|
|
@@ -22638,13 +23091,13 @@ function formatJobStatusResponse(options) {
|
|
|
22638
23091
|
|
|
22639
23092
|
// src/cli/platform/helpers/openapi.ts
|
|
22640
23093
|
import { promises as fs7 } from "node:fs";
|
|
22641
|
-
import
|
|
23094
|
+
import path73 from "node:path";
|
|
22642
23095
|
import SwaggerParser from "@apidevtools/swagger-parser";
|
|
22643
23096
|
import YAML3 from "yaml";
|
|
22644
23097
|
async function validateOpenApiFile(filePath) {
|
|
22645
|
-
const resolved =
|
|
23098
|
+
const resolved = path73.resolve(filePath);
|
|
22646
23099
|
const content = await fs7.readFile(resolved, "utf8");
|
|
22647
|
-
const ext =
|
|
23100
|
+
const ext = path73.extname(resolved).toLowerCase();
|
|
22648
23101
|
let parsed;
|
|
22649
23102
|
try {
|
|
22650
23103
|
parsed = ext === ".json" ? JSON.parse(content) : YAML3.parse(content);
|
|
@@ -22688,12 +23141,12 @@ async function validateOpenApiFile(filePath) {
|
|
|
22688
23141
|
// src/cli/platform/helpers/zip.ts
|
|
22689
23142
|
import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, promises as fs8 } from "node:fs";
|
|
22690
23143
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
22691
|
-
import
|
|
23144
|
+
import path74 from "node:path";
|
|
22692
23145
|
import { ZipArchive } from "archiver";
|
|
22693
23146
|
async function packageBackendDirectory(sourceDirectory, extraExcludes = []) {
|
|
22694
|
-
const resolved =
|
|
23147
|
+
const resolved = path74.resolve(sourceDirectory);
|
|
22695
23148
|
const files = await collectPackageableFiles(resolved, extraExcludes);
|
|
22696
|
-
const zipPath =
|
|
23149
|
+
const zipPath = path74.join(
|
|
22697
23150
|
tmpdir3(),
|
|
22698
23151
|
`apitogo-backend-${Date.now()}-${Math.random().toString(36).slice(2)}.zip`
|
|
22699
23152
|
);
|
|
@@ -22705,8 +23158,8 @@ async function packageBackendDirectory(sourceDirectory, extraExcludes = []) {
|
|
|
22705
23158
|
output4.on("error", reject);
|
|
22706
23159
|
archive.pipe(output4);
|
|
22707
23160
|
for (const rel2 of files) {
|
|
22708
|
-
archive.append(createReadStream2(
|
|
22709
|
-
name: rel2.split(
|
|
23161
|
+
archive.append(createReadStream2(path74.join(resolved, rel2)), {
|
|
23162
|
+
name: rel2.split(path74.sep).join("/")
|
|
22710
23163
|
});
|
|
22711
23164
|
}
|
|
22712
23165
|
void archive.finalize();
|
|
@@ -24276,11 +24729,11 @@ async function resolveProjectIdForPublish(client, config2, args, wait, progress,
|
|
|
24276
24729
|
}
|
|
24277
24730
|
|
|
24278
24731
|
// src/cli/platform/tools/dev-portal-site-build.ts
|
|
24279
|
-
import
|
|
24732
|
+
import path78 from "node:path";
|
|
24280
24733
|
|
|
24281
24734
|
// src/cli/platform/helpers/dev-portal-site-api-url.ts
|
|
24282
24735
|
import { readdir as readdir6, readFile as readFile27, writeFile as writeFile21 } from "node:fs/promises";
|
|
24283
|
-
import
|
|
24736
|
+
import path75 from "node:path";
|
|
24284
24737
|
var SITE_API_BASE_URL_ENV_KEY = "VITE_APITOGO_AUTHENTICATION_API_BASE_URL";
|
|
24285
24738
|
var PLACEHOLDER_HOST_MARKERS = [
|
|
24286
24739
|
"dp-example.azurecontainerapps.io",
|
|
@@ -24301,10 +24754,10 @@ function isPlaceholderDevPortalApiUrl(apiBaseUrl) {
|
|
|
24301
24754
|
return PLACEHOLDER_HOST_MARKERS.some((marker) => normalized.includes(marker));
|
|
24302
24755
|
}
|
|
24303
24756
|
async function readSiteApiBaseUrl(sourceDirectory) {
|
|
24304
|
-
const resolved =
|
|
24757
|
+
const resolved = path75.resolve(sourceDirectory);
|
|
24305
24758
|
for (const envFile of [".env", ".env.production"]) {
|
|
24306
24759
|
try {
|
|
24307
|
-
const content = await readFile27(
|
|
24760
|
+
const content = await readFile27(path75.join(resolved, envFile), "utf8");
|
|
24308
24761
|
const lines = [...content.matchAll(ENV_LINE_GLOBAL_RE)];
|
|
24309
24762
|
if (lines.length === 0) {
|
|
24310
24763
|
continue;
|
|
@@ -24329,11 +24782,11 @@ async function readSiteApiBaseUrl(sourceDirectory) {
|
|
|
24329
24782
|
return null;
|
|
24330
24783
|
}
|
|
24331
24784
|
async function patchSiteApiBaseUrl(sourceDirectory, apiBaseUrl) {
|
|
24332
|
-
const resolved =
|
|
24785
|
+
const resolved = path75.resolve(sourceDirectory);
|
|
24333
24786
|
const line2 = `${SITE_API_BASE_URL_ENV_KEY}=${apiBaseUrl}`;
|
|
24334
24787
|
let patchedExisting = false;
|
|
24335
24788
|
for (const envFile of [".env.production", ".env"]) {
|
|
24336
|
-
const envPath =
|
|
24789
|
+
const envPath = path75.join(resolved, envFile);
|
|
24337
24790
|
try {
|
|
24338
24791
|
const content = await readFile27(envPath, "utf8");
|
|
24339
24792
|
const withoutAssignments = content.replace(ENV_LINE_GLOBAL_RE, "").replace(/\n{3,}/g, "\n\n").trimEnd();
|
|
@@ -24347,7 +24800,7 @@ ${line2}
|
|
|
24347
24800
|
}
|
|
24348
24801
|
}
|
|
24349
24802
|
if (!patchedExisting) {
|
|
24350
|
-
await writeFile21(
|
|
24803
|
+
await writeFile21(path75.join(resolved, ".env"), `${line2}
|
|
24351
24804
|
`);
|
|
24352
24805
|
}
|
|
24353
24806
|
}
|
|
@@ -24355,7 +24808,7 @@ function tryProjectId(explicit, manifestProjectId, config2) {
|
|
|
24355
24808
|
return explicit?.trim() || manifestProjectId?.trim() || config2.defaultProjectId?.trim() || void 0;
|
|
24356
24809
|
}
|
|
24357
24810
|
async function ensureLiveSiteApiBaseUrlForBuild(_client, config2, args, resolveFromProject) {
|
|
24358
|
-
const sourceDirectory =
|
|
24811
|
+
const sourceDirectory = path75.resolve(args.sourceDirectory);
|
|
24359
24812
|
const explicit = args.apiBaseUrl?.trim();
|
|
24360
24813
|
if (explicit && !isPlaceholderDevPortalApiUrl(explicit)) {
|
|
24361
24814
|
await patchSiteApiBaseUrl(sourceDirectory, explicit);
|
|
@@ -24391,7 +24844,7 @@ async function* walkFiles(root) {
|
|
|
24391
24844
|
return;
|
|
24392
24845
|
}
|
|
24393
24846
|
for (const entry of entries) {
|
|
24394
|
-
const full =
|
|
24847
|
+
const full = path75.join(root, entry.name);
|
|
24395
24848
|
if (entry.isDirectory()) {
|
|
24396
24849
|
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
24397
24850
|
continue;
|
|
@@ -24403,8 +24856,8 @@ async function* walkFiles(root) {
|
|
|
24403
24856
|
}
|
|
24404
24857
|
}
|
|
24405
24858
|
async function assertDeployableDistHasLiveApiBaseUrl(distDirectory, expectedApiBaseUrl) {
|
|
24406
|
-
const dist =
|
|
24407
|
-
const siteRoot =
|
|
24859
|
+
const dist = path75.resolve(distDirectory);
|
|
24860
|
+
const siteRoot = path75.dirname(dist);
|
|
24408
24861
|
const fromEnv = expectedApiBaseUrl?.trim() || await readSiteApiBaseUrl(siteRoot) || await readSiteApiBaseUrl(dist);
|
|
24409
24862
|
if (!fromEnv || isPlaceholderDevPortalApiUrl(fromEnv)) {
|
|
24410
24863
|
throw new Error(
|
|
@@ -24440,7 +24893,7 @@ async function assertDeployableDistHasLiveApiBaseUrl(distDirectory, expectedApiB
|
|
|
24440
24893
|
|
|
24441
24894
|
// src/cli/platform/tools/dev-portal.ts
|
|
24442
24895
|
import { promises as fs10 } from "node:fs";
|
|
24443
|
-
import
|
|
24896
|
+
import path77 from "node:path";
|
|
24444
24897
|
|
|
24445
24898
|
// src/cli/platform/helpers/dev-portal-backend-job.ts
|
|
24446
24899
|
var DEV_PORTAL_BACKEND_UPDATE_RESOURCE_TYPE = "DevPortalBackendUpdate";
|
|
@@ -24550,7 +25003,7 @@ async function snapshotBackendUpdateJobIds(client, projectId) {
|
|
|
24550
25003
|
// src/cli/platform/helpers/tarball.ts
|
|
24551
25004
|
import { createReadStream as createReadStream3, createWriteStream as createWriteStream3, promises as fs9 } from "node:fs";
|
|
24552
25005
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
24553
|
-
import
|
|
25006
|
+
import path76 from "node:path";
|
|
24554
25007
|
import { TarArchive } from "archiver";
|
|
24555
25008
|
var DEV_PORTAL_DEPLOY_ARCHIVE_ROOT = "dist";
|
|
24556
25009
|
function normalizeArchiveRoot(archiveRoot) {
|
|
@@ -24561,10 +25014,10 @@ function normalizeArchiveRoot(archiveRoot) {
|
|
|
24561
25014
|
return `${trimmed}/`;
|
|
24562
25015
|
}
|
|
24563
25016
|
async function packageDirectoryAsTarGz(sourceDirectory, options) {
|
|
24564
|
-
const resolved =
|
|
25017
|
+
const resolved = path76.resolve(sourceDirectory);
|
|
24565
25018
|
const files = await collectPackageableFiles(resolved);
|
|
24566
25019
|
const entryPrefix = options?.archiveRoot ? normalizeArchiveRoot(options.archiveRoot) : "";
|
|
24567
|
-
const archivePath =
|
|
25020
|
+
const archivePath = path76.join(
|
|
24568
25021
|
tmpdir4(),
|
|
24569
25022
|
`apitogo-docs-${Date.now()}-${Math.random().toString(36).slice(2)}.tgz`
|
|
24570
25023
|
);
|
|
@@ -24576,8 +25029,8 @@ async function packageDirectoryAsTarGz(sourceDirectory, options) {
|
|
|
24576
25029
|
output4.on("error", reject);
|
|
24577
25030
|
archive.pipe(output4);
|
|
24578
25031
|
for (const rel2 of files) {
|
|
24579
|
-
const entryName = entryPrefix + rel2.split(
|
|
24580
|
-
archive.append(createReadStream3(
|
|
25032
|
+
const entryName = entryPrefix + rel2.split(path76.sep).join("/");
|
|
25033
|
+
archive.append(createReadStream3(path76.join(resolved, rel2)), {
|
|
24581
25034
|
name: entryName
|
|
24582
25035
|
});
|
|
24583
25036
|
}
|
|
@@ -24819,7 +25272,7 @@ function validateDeployArchiveInput(args) {
|
|
|
24819
25272
|
async function resolveDevPortalArchive(args) {
|
|
24820
25273
|
validateDeployArchiveInput(args);
|
|
24821
25274
|
if (args.archivePath?.trim()) {
|
|
24822
|
-
const archivePath =
|
|
25275
|
+
const archivePath = path77.resolve(args.archivePath.trim());
|
|
24823
25276
|
const stat7 = await fs10.stat(archivePath).catch(() => null);
|
|
24824
25277
|
if (!stat7?.isFile()) {
|
|
24825
25278
|
throw new Error(`archivePath is not a file: ${archivePath}`);
|
|
@@ -24884,7 +25337,7 @@ async function handleDeployDevPortal(client, config2, args, progress) {
|
|
|
24884
25337
|
// src/cli/platform/tools/dev-portal-site-build.ts
|
|
24885
25338
|
async function handleBuildDevPortalSite(client, config2, args, progress) {
|
|
24886
25339
|
const buildProgress = progress?.child("Build dev portal site");
|
|
24887
|
-
const sourceDirectory =
|
|
25340
|
+
const sourceDirectory = path78.resolve(args.sourceDirectory);
|
|
24888
25341
|
await buildProgress?.onStep("Ensuring live portal API URL");
|
|
24889
25342
|
const apiBaseUrl = await ensureLiveSiteApiBaseUrlForBuild(
|
|
24890
25343
|
client,
|
|
@@ -26390,7 +26843,7 @@ function resultLooksFailed(payload) {
|
|
|
26390
26843
|
return parsed.status === "failed" || parsed.status === "blocked";
|
|
26391
26844
|
}
|
|
26392
26845
|
async function apply(argv) {
|
|
26393
|
-
const sourceDirectory =
|
|
26846
|
+
const sourceDirectory = path79.resolve(process.cwd(), argv.dir);
|
|
26394
26847
|
let config2;
|
|
26395
26848
|
try {
|
|
26396
26849
|
config2 = loadConfig();
|
|
@@ -26460,7 +26913,7 @@ async function apply(argv) {
|
|
|
26460
26913
|
if (canPromptInteractively && parsed?.status === "blocked" && parsed.reason === "project_not_found") {
|
|
26461
26914
|
const resolution = await resolveProjectNotFoundInteractively(
|
|
26462
26915
|
parsed,
|
|
26463
|
-
|
|
26916
|
+
path79.basename(sourceDirectory)
|
|
26464
26917
|
);
|
|
26465
26918
|
if (resolution) {
|
|
26466
26919
|
effectiveProjectId = void 0;
|
|
@@ -26480,7 +26933,7 @@ async function apply(argv) {
|
|
|
26480
26933
|
while (canPromptInteractively && parsed?.status === "blocked" && parsed.reason === "project_name_exists") {
|
|
26481
26934
|
const resolution = await resolveProjectNameExistsInteractively(
|
|
26482
26935
|
parsed,
|
|
26483
|
-
effectiveProjectName ??
|
|
26936
|
+
effectiveProjectName ?? path79.basename(sourceDirectory)
|
|
26484
26937
|
);
|
|
26485
26938
|
if (!resolution) {
|
|
26486
26939
|
break;
|
|
@@ -26551,11 +27004,11 @@ async function apply(argv) {
|
|
|
26551
27004
|
}
|
|
26552
27005
|
|
|
26553
27006
|
// src/cli/deploy/command.ts
|
|
26554
|
-
import
|
|
27007
|
+
import path85 from "node:path";
|
|
26555
27008
|
init_invariant();
|
|
26556
27009
|
|
|
26557
27010
|
// src/cli/project/create-handler.ts
|
|
26558
|
-
import
|
|
27011
|
+
import path80 from "node:path";
|
|
26559
27012
|
import open2 from "open";
|
|
26560
27013
|
init_invariant();
|
|
26561
27014
|
|
|
@@ -26589,11 +27042,22 @@ function assertConfigChecksOut(output4) {
|
|
|
26589
27042
|
].join("\n")
|
|
26590
27043
|
);
|
|
26591
27044
|
}
|
|
26592
|
-
var
|
|
27045
|
+
var gatewayOn = (config2) => config2.gateway !== void 0 && config2.gateway.enabled !== false;
|
|
27046
|
+
var hostsAnything = (config2) => config2.portal && config2.portal.enabled !== false || gatewayOn(config2);
|
|
26593
27047
|
async function createProjectV2(options, deps) {
|
|
26594
27048
|
const { config: config2, resolved } = loadConfigV2(options.dir);
|
|
26595
27049
|
const linkedProjectId = resolved.project.id;
|
|
26596
|
-
const
|
|
27050
|
+
const externalDocsOnly = portalOnlyLinksExternalDocs(resolved);
|
|
27051
|
+
const modules = modulesForConfig(config2).filter(
|
|
27052
|
+
(module) => module !== "dev-portal" || !externalDocsOnly
|
|
27053
|
+
);
|
|
27054
|
+
if (externalDocsOnly && !gatewayOn(config2)) {
|
|
27055
|
+
throw new ProjectCreateError(
|
|
27056
|
+
"NOTHING_TO_HOST",
|
|
27057
|
+
"No enabled service needs a project: the docs are on an external site and nothing feeds the portal console.",
|
|
27058
|
+
"Enable identity or plans for a console next to your docs (`apitogo add identity`), or a gateway (`apitogo add gateway`)."
|
|
27059
|
+
);
|
|
27060
|
+
}
|
|
26597
27061
|
if (!hostsAnything(config2)) {
|
|
26598
27062
|
throw new ProjectCreateError(
|
|
26599
27063
|
"NOTHING_TO_HOST",
|
|
@@ -26869,7 +27333,7 @@ async function createLinkedProject(argv, dir, options = {}) {
|
|
|
26869
27333
|
}
|
|
26870
27334
|
}
|
|
26871
27335
|
async function createProject2(argv) {
|
|
26872
|
-
const dir =
|
|
27336
|
+
const dir = path80.resolve(process.cwd(), argv.dir ?? ".");
|
|
26873
27337
|
if (await isConfigV2(dir)) {
|
|
26874
27338
|
await createLinkedProject(argv, dir);
|
|
26875
27339
|
return;
|
|
@@ -26929,7 +27393,7 @@ async function createProject2(argv) {
|
|
|
26929
27393
|
}
|
|
26930
27394
|
|
|
26931
27395
|
// src/cli/secrets/handler.ts
|
|
26932
|
-
import
|
|
27396
|
+
import path81 from "node:path";
|
|
26933
27397
|
init_invariant();
|
|
26934
27398
|
|
|
26935
27399
|
// src/cli/secrets/input.ts
|
|
@@ -26994,7 +27458,7 @@ var SecretsError = class extends ApitogoError {
|
|
|
26994
27458
|
async function resolveProjectId2(argv, deps) {
|
|
26995
27459
|
const explicit = argv.projectId?.trim();
|
|
26996
27460
|
if (explicit) return explicit;
|
|
26997
|
-
const dir =
|
|
27461
|
+
const dir = path81.resolve(process.cwd(), argv.dir ?? ".");
|
|
26998
27462
|
if (await isConfigV2(dir)) {
|
|
26999
27463
|
const id = loadConfigV2(dir).resolved.project.id;
|
|
27000
27464
|
if (id) return id;
|
|
@@ -27079,7 +27543,7 @@ var KNOWN_SECRET_PLACES = {
|
|
|
27079
27543
|
async function wireKnownSecret(argv, name) {
|
|
27080
27544
|
const place = KNOWN_SECRET_PLACES[name.toUpperCase()];
|
|
27081
27545
|
if (!place) return void 0;
|
|
27082
|
-
const dir =
|
|
27546
|
+
const dir = path81.resolve(process.cwd(), argv.dir ?? ".");
|
|
27083
27547
|
if (!await isConfigV2(dir)) return void 0;
|
|
27084
27548
|
const project = await openConfigProject(dir);
|
|
27085
27549
|
const plans = project.resolved.plans;
|
|
@@ -27140,7 +27604,7 @@ async function secrets(argv) {
|
|
|
27140
27604
|
}
|
|
27141
27605
|
|
|
27142
27606
|
// src/cli/deploy/stripe-key.ts
|
|
27143
|
-
import
|
|
27607
|
+
import path82 from "node:path";
|
|
27144
27608
|
init_invariant();
|
|
27145
27609
|
var StripeKeyError = class extends ApitogoError {
|
|
27146
27610
|
constructor(message, developerHint) {
|
|
@@ -27158,7 +27622,7 @@ async function ensureStripeKey(argv, deps) {
|
|
|
27158
27622
|
if (!wantsPlans(argv.only)) return { status: "not-needed" };
|
|
27159
27623
|
let resolved;
|
|
27160
27624
|
try {
|
|
27161
|
-
resolved = loadConfigV2(
|
|
27625
|
+
resolved = loadConfigV2(path82.resolve(process.cwd(), argv.dir)).resolved;
|
|
27162
27626
|
} catch {
|
|
27163
27627
|
return { status: "not-needed" };
|
|
27164
27628
|
}
|
|
@@ -28095,7 +28559,7 @@ init_invariant();
|
|
|
28095
28559
|
|
|
28096
28560
|
// src/cli/portal/report.ts
|
|
28097
28561
|
import { access as access9 } from "node:fs/promises";
|
|
28098
|
-
import
|
|
28562
|
+
import path83 from "node:path";
|
|
28099
28563
|
|
|
28100
28564
|
// src/cli/deploy/identity.ts
|
|
28101
28565
|
init_invariant();
|
|
@@ -28106,6 +28570,16 @@ var IdentityDeployError = class extends ApitogoError {
|
|
|
28106
28570
|
this.name = "IdentityDeployError";
|
|
28107
28571
|
}
|
|
28108
28572
|
};
|
|
28573
|
+
var IDENTITY_NOT_ACTIVE = "IDENTITY_NOT_ACTIVE";
|
|
28574
|
+
async function identityLost(client, projectId) {
|
|
28575
|
+
if (!client.listProjectIdentityConnections) return false;
|
|
28576
|
+
try {
|
|
28577
|
+
await client.listProjectIdentityConnections(projectId);
|
|
28578
|
+
return false;
|
|
28579
|
+
} catch (error) {
|
|
28580
|
+
return error instanceof PlatformApiError && error.status === 409 && error.problem?.code === IDENTITY_NOT_ACTIVE;
|
|
28581
|
+
}
|
|
28582
|
+
}
|
|
28109
28583
|
var IDENTITY_STEPS = ["request", "activate"];
|
|
28110
28584
|
var IDENTITY_CONNECTIONS_STEP = "connections";
|
|
28111
28585
|
var SECRET_PREFIX = "secret:";
|
|
@@ -28305,10 +28779,13 @@ async function deployIdentity(resolved, projectId, deps, options = {}) {
|
|
|
28305
28779
|
return rejected2(error);
|
|
28306
28780
|
}
|
|
28307
28781
|
},
|
|
28308
|
-
// An identity that was removed, or that failed, is not a result worth keeping.
|
|
28782
|
+
// An identity that was removed, or that failed, is not a result worth keeping. Neither is one the platform still
|
|
28783
|
+
// lists as Active while the identity service lost it (API-132): asking again makes it again.
|
|
28309
28784
|
stillValid: async () => {
|
|
28310
28785
|
const found = await client.getProjectIdentity(projectId);
|
|
28311
|
-
|
|
28786
|
+
if (found === null || found.status === "Failed" || found.status === "Released" || found.status === "Releasing")
|
|
28787
|
+
return false;
|
|
28788
|
+
return found.status !== "Active" || !await identityLost(client, projectId);
|
|
28312
28789
|
}
|
|
28313
28790
|
};
|
|
28314
28791
|
const activateStep = {
|
|
@@ -28866,7 +29343,7 @@ async function planPortalService(resolved, ledger) {
|
|
|
28866
29343
|
const hash2 = await portalBuildHash(resolved, prepared);
|
|
28867
29344
|
const previous = stepOf(ledger, "portal", "build");
|
|
28868
29345
|
const built = await exists5(
|
|
28869
|
-
|
|
29346
|
+
path83.join(resolved.state.buildDir, "index.html")
|
|
28870
29347
|
);
|
|
28871
29348
|
if (previous?.status === "succeeded" && previous.hash === hash2 && built) {
|
|
28872
29349
|
return {
|
|
@@ -29238,6 +29715,25 @@ async function statusV2(dir, only, options = {}) {
|
|
|
29238
29715
|
const ledger = await readLedger(resolved.state);
|
|
29239
29716
|
const manifest = await readManifest(resolved.state);
|
|
29240
29717
|
const services = [];
|
|
29718
|
+
const manifestSummary = {
|
|
29719
|
+
present: manifest !== void 0,
|
|
29720
|
+
schemaVersion: manifest?.schemaVersion,
|
|
29721
|
+
generatedAt: manifest?.generatedAt
|
|
29722
|
+
};
|
|
29723
|
+
const projectId = resolved.project.id ?? manifest?.project.id;
|
|
29724
|
+
if (options.projectRemote && projectId) {
|
|
29725
|
+
try {
|
|
29726
|
+
await options.projectRemote(projectId);
|
|
29727
|
+
} catch (error) {
|
|
29728
|
+
if (error instanceof ProjectGoneError)
|
|
29729
|
+
return {
|
|
29730
|
+
configPath: resolved.configPath,
|
|
29731
|
+
manifest: manifestSummary,
|
|
29732
|
+
project: { state: "gone", id: projectId, message: error.message },
|
|
29733
|
+
services: []
|
|
29734
|
+
};
|
|
29735
|
+
}
|
|
29736
|
+
}
|
|
29241
29737
|
for (const service of chooseServices(only)) {
|
|
29242
29738
|
const section = sectionOf(resolved, service);
|
|
29243
29739
|
if (!section) {
|
|
@@ -29252,7 +29748,7 @@ async function statusV2(dir, only, options = {}) {
|
|
|
29252
29748
|
if (service === "portal") {
|
|
29253
29749
|
const build2 = stepOf(ledger, "portal", "build");
|
|
29254
29750
|
const built = await exists5(
|
|
29255
|
-
|
|
29751
|
+
path83.join(resolved.state.buildDir, "index.html")
|
|
29256
29752
|
);
|
|
29257
29753
|
const state = build2?.status === "failed" ? "build-failed" : build2?.status === "succeeded" && built ? "built" : "not-built";
|
|
29258
29754
|
services.push({
|
|
@@ -29263,7 +29759,7 @@ async function statusV2(dir, only, options = {}) {
|
|
|
29263
29759
|
...build2?.finishedAt ? [`last build: ${build2.finishedAt}`] : [],
|
|
29264
29760
|
...build2?.status === "failed" ? [`error: ${build2.error ?? "unknown"}`] : [],
|
|
29265
29761
|
...state === "built" ? [
|
|
29266
|
-
`output: ${
|
|
29762
|
+
`output: ${path83.relative(resolved.configDir, resolved.state.buildDir)}`
|
|
29267
29763
|
] : [],
|
|
29268
29764
|
...url2 ? [`url: ${url2}`] : ["url: not known (portal is not deployed yet)"],
|
|
29269
29765
|
...await hostingLine(resolved, manifest, options.hostingRemote)
|
|
@@ -29301,11 +29797,7 @@ async function statusV2(dir, only, options = {}) {
|
|
|
29301
29797
|
}
|
|
29302
29798
|
return {
|
|
29303
29799
|
configPath: resolved.configPath,
|
|
29304
|
-
manifest:
|
|
29305
|
-
present: manifest !== void 0,
|
|
29306
|
-
schemaVersion: manifest?.schemaVersion,
|
|
29307
|
-
generatedAt: manifest?.generatedAt
|
|
29308
|
-
},
|
|
29800
|
+
manifest: manifestSummary,
|
|
29309
29801
|
services
|
|
29310
29802
|
};
|
|
29311
29803
|
}
|
|
@@ -29319,6 +29811,8 @@ function formatPlan(output4, options = {}) {
|
|
|
29319
29811
|
]);
|
|
29320
29812
|
}
|
|
29321
29813
|
function formatStatus(output4) {
|
|
29814
|
+
if (output4.project?.state === "gone")
|
|
29815
|
+
return [`project: gone`, ` ${output4.project.message}`];
|
|
29322
29816
|
return [
|
|
29323
29817
|
output4.manifest.present ? `services.json: version ${output4.manifest.schemaVersion}${output4.manifest.generatedAt ? `, written ${output4.manifest.generatedAt}` : ""}` : "services.json: none yet",
|
|
29324
29818
|
...output4.services.flatMap((svc) => [
|
|
@@ -29330,7 +29824,7 @@ function formatStatus(output4) {
|
|
|
29330
29824
|
|
|
29331
29825
|
// src/cli/deploy/static-web-config.ts
|
|
29332
29826
|
import { access as access10, writeFile as writeFile22 } from "node:fs/promises";
|
|
29333
|
-
import
|
|
29827
|
+
import path84 from "node:path";
|
|
29334
29828
|
var STATIC_WEB_CONFIG_FILE = "staticwebapp.config.json";
|
|
29335
29829
|
var STATIC_WEB_CONFIG_VERSION = 3;
|
|
29336
29830
|
var CLIENT_ONLY_ROUTES = [
|
|
@@ -29348,7 +29842,7 @@ var DEFAULT_STATIC_WEB_CONFIG = {
|
|
|
29348
29842
|
}
|
|
29349
29843
|
};
|
|
29350
29844
|
async function ensureStaticWebConfig(buildDir) {
|
|
29351
|
-
const file =
|
|
29845
|
+
const file = path84.join(buildDir, STATIC_WEB_CONFIG_FILE);
|
|
29352
29846
|
try {
|
|
29353
29847
|
await access10(file);
|
|
29354
29848
|
return false;
|
|
@@ -29471,6 +29965,15 @@ async function deployV2(options, deps) {
|
|
|
29471
29965
|
results.push(await deployPlansService(options, deps, projectId, named));
|
|
29472
29966
|
continue;
|
|
29473
29967
|
}
|
|
29968
|
+
if (portalOnlyLinksExternalDocs(resolved)) {
|
|
29969
|
+
results.push({
|
|
29970
|
+
service: "portal",
|
|
29971
|
+
status: "skipped",
|
|
29972
|
+
reason: "docs are on an external site and no service feeds the console, so there is nothing to host",
|
|
29973
|
+
steps: []
|
|
29974
|
+
});
|
|
29975
|
+
continue;
|
|
29976
|
+
}
|
|
29474
29977
|
results.push(await deployPortal(options, deps, projectId));
|
|
29475
29978
|
}
|
|
29476
29979
|
const gatewayAt = results.findIndex(
|
|
@@ -29703,7 +30206,7 @@ function formatDeploy(output4) {
|
|
|
29703
30206
|
// src/cli/deploy/command.ts
|
|
29704
30207
|
async function ensureLinkedProject(argv, deps) {
|
|
29705
30208
|
if (argv.projectId?.trim() || deps.envProjectId?.trim()) return true;
|
|
29706
|
-
const dir =
|
|
30209
|
+
const dir = path85.resolve(process.cwd(), argv.dir);
|
|
29707
30210
|
let linked;
|
|
29708
30211
|
try {
|
|
29709
30212
|
linked = Boolean(loadConfigV2(dir).resolved.project.id);
|
|
@@ -29754,7 +30257,7 @@ async function deployProject(argv) {
|
|
|
29754
30257
|
try {
|
|
29755
30258
|
const config2 = loadConfig();
|
|
29756
30259
|
const client = new PlatformApiClient(config2);
|
|
29757
|
-
const dir =
|
|
30260
|
+
const dir = path85.resolve(process.cwd(), argv.dir);
|
|
29758
30261
|
const deploy = (only) => deployV2(
|
|
29759
30262
|
{
|
|
29760
30263
|
dir,
|
|
@@ -29862,7 +30365,7 @@ var deploy_default = {
|
|
|
29862
30365
|
}),
|
|
29863
30366
|
handler: async (argv) => {
|
|
29864
30367
|
await captureEvent({ argv, event: "apitogo deploy" });
|
|
29865
|
-
if (!await isLegacyConfig(
|
|
30368
|
+
if (!await isLegacyConfig(path86.resolve(process.cwd(), argv.dir))) {
|
|
29866
30369
|
await deployProject(argv);
|
|
29867
30370
|
return;
|
|
29868
30371
|
}
|
|
@@ -29872,7 +30375,7 @@ var deploy_default = {
|
|
|
29872
30375
|
|
|
29873
30376
|
// src/cli/export/handler.ts
|
|
29874
30377
|
import { mkdir as mkdir19, writeFile as writeFile23 } from "node:fs/promises";
|
|
29875
|
-
import
|
|
30378
|
+
import path87 from "node:path";
|
|
29876
30379
|
init_invariant();
|
|
29877
30380
|
var ExportError = class extends ApitogoError {
|
|
29878
30381
|
constructor(message, developerHint) {
|
|
@@ -29886,7 +30389,7 @@ async function exportOpenApi(args, deps) {
|
|
|
29886
30389
|
`Cannot export "${args.target}".`,
|
|
29887
30390
|
"Only `apitogo export openapi` exists."
|
|
29888
30391
|
);
|
|
29889
|
-
const dir =
|
|
30392
|
+
const dir = path87.resolve(process.cwd(), args.dir ?? ".");
|
|
29890
30393
|
if (!await isConfigV2(dir))
|
|
29891
30394
|
throw new ExportError(
|
|
29892
30395
|
"This command needs a config version 2 project.",
|
|
@@ -29911,8 +30414,8 @@ async function exportOpenApi(args, deps) {
|
|
|
29911
30414
|
throw error;
|
|
29912
30415
|
}
|
|
29913
30416
|
if (!args.out) return { text: text2 };
|
|
29914
|
-
const file =
|
|
29915
|
-
await mkdir19(
|
|
30417
|
+
const file = path87.resolve(process.cwd(), args.out);
|
|
30418
|
+
await mkdir19(path87.dirname(file), { recursive: true });
|
|
29916
30419
|
await writeFile23(file, text2);
|
|
29917
30420
|
return { text: text2, file };
|
|
29918
30421
|
}
|
|
@@ -30005,8 +30508,8 @@ import open3 from "open";
|
|
|
30005
30508
|
import colors14 from "picocolors";
|
|
30006
30509
|
|
|
30007
30510
|
// src/cli/platform/device-auth.ts
|
|
30008
|
-
function url(apiUrl,
|
|
30009
|
-
return `${apiUrl}${
|
|
30511
|
+
function url(apiUrl, path100) {
|
|
30512
|
+
return `${apiUrl}${path100.startsWith("/") ? path100 : `/${path100}`}`;
|
|
30010
30513
|
}
|
|
30011
30514
|
async function requestDeviceCode(apiUrl) {
|
|
30012
30515
|
const response = await fetchWithRetry(
|
|
@@ -30188,7 +30691,7 @@ var logout_default = {
|
|
|
30188
30691
|
};
|
|
30189
30692
|
|
|
30190
30693
|
// src/cli/portal/commands.ts
|
|
30191
|
-
import
|
|
30694
|
+
import path88 from "node:path";
|
|
30192
30695
|
init_invariant();
|
|
30193
30696
|
function parseOnly(value) {
|
|
30194
30697
|
if (value === void 0) return void 0;
|
|
@@ -30205,7 +30708,7 @@ function parseOnly(value) {
|
|
|
30205
30708
|
async function run2(command2, argv, compute, format) {
|
|
30206
30709
|
const json = argv.json === true;
|
|
30207
30710
|
try {
|
|
30208
|
-
const dir =
|
|
30711
|
+
const dir = path88.resolve(process.cwd(), argv.dir ?? ".");
|
|
30209
30712
|
if (!await isConfigV2(dir)) {
|
|
30210
30713
|
throw new ServiceEditError(
|
|
30211
30714
|
`${command2} works with a config version 2 project, and there is none in ${dir}.`,
|
|
@@ -30243,6 +30746,14 @@ var plan = (argv) => run2(
|
|
|
30243
30746
|
}),
|
|
30244
30747
|
(output4) => formatPlan(output4, { verbose: argv.verbose === true })
|
|
30245
30748
|
);
|
|
30749
|
+
function projectRemote() {
|
|
30750
|
+
try {
|
|
30751
|
+
const client = new PlatformApiClient(loadConfig());
|
|
30752
|
+
return (projectId) => client.getProject(projectId);
|
|
30753
|
+
} catch {
|
|
30754
|
+
return void 0;
|
|
30755
|
+
}
|
|
30756
|
+
}
|
|
30246
30757
|
function gatewayRemote() {
|
|
30247
30758
|
try {
|
|
30248
30759
|
const client = new PlatformApiClient(loadConfig());
|
|
@@ -30300,6 +30811,7 @@ var statusOfProject = (argv) => run2(
|
|
|
30300
30811
|
"status",
|
|
30301
30812
|
argv,
|
|
30302
30813
|
(dir, only) => statusV2(dir, only, {
|
|
30814
|
+
projectRemote: projectRemote(),
|
|
30303
30815
|
hostingRemote: hostingRemote(),
|
|
30304
30816
|
gatewayRemote: gatewayRemote(),
|
|
30305
30817
|
identityRemote: identityRemote(),
|
|
@@ -30421,7 +30933,7 @@ async function switchProject(options, deps) {
|
|
|
30421
30933
|
try {
|
|
30422
30934
|
project = await deps.getProject(projectId);
|
|
30423
30935
|
} catch (error) {
|
|
30424
|
-
if (error instanceof PlatformApiError && (error.status === 404 || error.status === 403))
|
|
30936
|
+
if (error instanceof ProjectGoneError || error instanceof PlatformApiError && (error.status === 404 || error.status === 403))
|
|
30425
30937
|
throw new ProjectUseError(
|
|
30426
30938
|
"PROJECT_NOT_FOUND",
|
|
30427
30939
|
`No project ${projectId} is yours.`,
|
|
@@ -30567,14 +31079,14 @@ var remove_default = {
|
|
|
30567
31079
|
|
|
30568
31080
|
// src/cli/dev/handler.ts
|
|
30569
31081
|
init_joinUrl();
|
|
30570
|
-
import
|
|
31082
|
+
import path91 from "node:path";
|
|
30571
31083
|
|
|
30572
31084
|
// src/vite/dev-server.ts
|
|
30573
31085
|
init_logger();
|
|
30574
31086
|
import fs11 from "node:fs/promises";
|
|
30575
31087
|
import http from "node:http";
|
|
30576
31088
|
import https from "node:https";
|
|
30577
|
-
import
|
|
31089
|
+
import path90 from "node:path";
|
|
30578
31090
|
import { createHttpTerminator } from "http-terminator";
|
|
30579
31091
|
import {
|
|
30580
31092
|
createServer as createViteServer,
|
|
@@ -30619,7 +31131,7 @@ function withSsrGraphParts(config2, ssrConfig) {
|
|
|
30619
31131
|
// src/vite/pagefind-dev-index.ts
|
|
30620
31132
|
init_invariant();
|
|
30621
31133
|
init_joinUrl();
|
|
30622
|
-
import
|
|
31134
|
+
import path89 from "node:path";
|
|
30623
31135
|
import { createIndex as createIndex2 } from "pagefind";
|
|
30624
31136
|
import { isRunnableDevEnvironment } from "vite";
|
|
30625
31137
|
async function* buildPagefindDevIndex(vite, config2) {
|
|
@@ -30672,7 +31184,7 @@ async function* buildPagefindDevIndex(vite, config2) {
|
|
|
30672
31184
|
path: urlPath
|
|
30673
31185
|
};
|
|
30674
31186
|
}
|
|
30675
|
-
const outputPath =
|
|
31187
|
+
const outputPath = path89.join(vite.config.publicDir, "pagefind");
|
|
30676
31188
|
await pagefindIndex.writeFiles({ outputPath });
|
|
30677
31189
|
yield { type: "complete", success: true, indexed };
|
|
30678
31190
|
}
|
|
@@ -30691,9 +31203,9 @@ var DevServer = class {
|
|
|
30691
31203
|
this.protocol = "https";
|
|
30692
31204
|
const { dir } = this.options;
|
|
30693
31205
|
const [key, cert, ca] = await Promise.all([
|
|
30694
|
-
fs11.readFile(
|
|
30695
|
-
fs11.readFile(
|
|
30696
|
-
config2.https.ca ? fs11.readFile(
|
|
31206
|
+
fs11.readFile(path90.resolve(dir, config2.https.key)),
|
|
31207
|
+
fs11.readFile(path90.resolve(dir, config2.https.cert)),
|
|
31208
|
+
config2.https.ca ? fs11.readFile(path90.resolve(dir, config2.https.ca)) : void 0
|
|
30697
31209
|
]);
|
|
30698
31210
|
return https.createServer({ key, cert, ca });
|
|
30699
31211
|
}
|
|
@@ -30710,7 +31222,7 @@ var DevServer = class {
|
|
|
30710
31222
|
);
|
|
30711
31223
|
const server = await this.createNodeServer(config2);
|
|
30712
31224
|
if (config2.search?.type === "pagefind" && viteConfig.publicDir !== false) {
|
|
30713
|
-
const publicRoot =
|
|
31225
|
+
const publicRoot = path90.resolve(
|
|
30714
31226
|
this.options.dir,
|
|
30715
31227
|
typeof viteConfig.publicDir === "string" ? viteConfig.publicDir : "public"
|
|
30716
31228
|
);
|
|
@@ -30727,7 +31239,7 @@ var DevServer = class {
|
|
|
30727
31239
|
// built-in transform middleware which would treat the path as a static asset.
|
|
30728
31240
|
name: "apitogo:entry-client",
|
|
30729
31241
|
configureServer(server2) {
|
|
30730
|
-
const entryPath =
|
|
31242
|
+
const entryPath = path90.posix.join(
|
|
30731
31243
|
server2.config.base,
|
|
30732
31244
|
"/__z/entry.client.tsx"
|
|
30733
31245
|
);
|
|
@@ -30895,7 +31407,7 @@ init_package_json();
|
|
|
30895
31407
|
async function dev(argv) {
|
|
30896
31408
|
const packageJson3 = getZudokuPackageJson();
|
|
30897
31409
|
process.env.NODE_ENV = "development";
|
|
30898
|
-
let dir =
|
|
31410
|
+
let dir = path91.resolve(process.cwd(), argv.dir);
|
|
30899
31411
|
if (await isConfigV2(dir)) {
|
|
30900
31412
|
const { root, prepared } = await preparePortalWorkspace(dir, "development");
|
|
30901
31413
|
dir = root;
|
|
@@ -31030,12 +31542,12 @@ var secrets_default = {
|
|
|
31030
31542
|
};
|
|
31031
31543
|
|
|
31032
31544
|
// src/cli/cmds/status.ts
|
|
31033
|
-
import
|
|
31545
|
+
import path93 from "node:path";
|
|
31034
31546
|
|
|
31035
31547
|
// src/cli/status/handler.ts
|
|
31036
|
-
import
|
|
31548
|
+
import path92 from "node:path";
|
|
31037
31549
|
async function status(argv) {
|
|
31038
|
-
const sourceDirectory =
|
|
31550
|
+
const sourceDirectory = path92.resolve(process.cwd(), argv.dir);
|
|
31039
31551
|
let config2;
|
|
31040
31552
|
try {
|
|
31041
31553
|
config2 = loadConfig();
|
|
@@ -31161,7 +31673,7 @@ var status_default = {
|
|
|
31161
31673
|
}),
|
|
31162
31674
|
handler: async (argv) => {
|
|
31163
31675
|
await captureEvent({ argv, event: "apitogo status" });
|
|
31164
|
-
if (await isConfigV2(
|
|
31676
|
+
if (await isConfigV2(path93.resolve(process.cwd(), argv.dir))) {
|
|
31165
31677
|
await statusOfProject(argv);
|
|
31166
31678
|
return;
|
|
31167
31679
|
}
|
|
@@ -31170,11 +31682,11 @@ var status_default = {
|
|
|
31170
31682
|
};
|
|
31171
31683
|
|
|
31172
31684
|
// src/cli/cmds/teardown.ts
|
|
31173
|
-
import
|
|
31685
|
+
import path96 from "node:path";
|
|
31174
31686
|
|
|
31175
31687
|
// src/cli/teardown/command.ts
|
|
31176
31688
|
init_invariant();
|
|
31177
|
-
import
|
|
31689
|
+
import path94 from "node:path";
|
|
31178
31690
|
import { createInterface as createInterface7 } from "node:readline/promises";
|
|
31179
31691
|
|
|
31180
31692
|
// src/cli/teardown/v2.ts
|
|
@@ -31535,7 +32047,7 @@ async function teardownProject(argv) {
|
|
|
31535
32047
|
const progress = createConsoleProgressReporter();
|
|
31536
32048
|
const result = await teardownV2(
|
|
31537
32049
|
{
|
|
31538
|
-
dir:
|
|
32050
|
+
dir: path94.resolve(process.cwd(), argv.dir),
|
|
31539
32051
|
projectId: argv.projectId,
|
|
31540
32052
|
only: Array.isArray(argv.only) ? argv.only.join(",") : argv.only,
|
|
31541
32053
|
yes: argv.yes === true,
|
|
@@ -31594,7 +32106,7 @@ async function teardownProject(argv) {
|
|
|
31594
32106
|
}
|
|
31595
32107
|
|
|
31596
32108
|
// src/cli/teardown/handler.ts
|
|
31597
|
-
import
|
|
32109
|
+
import path95 from "node:path";
|
|
31598
32110
|
function resultLooksFailed3(payload) {
|
|
31599
32111
|
try {
|
|
31600
32112
|
const parsed = JSON.parse(payload);
|
|
@@ -31610,7 +32122,7 @@ async function teardown(argv) {
|
|
|
31610
32122
|
);
|
|
31611
32123
|
return;
|
|
31612
32124
|
}
|
|
31613
|
-
const sourceDirectory =
|
|
32125
|
+
const sourceDirectory = path95.resolve(process.cwd(), argv.dir);
|
|
31614
32126
|
let config2;
|
|
31615
32127
|
try {
|
|
31616
32128
|
config2 = loadConfig();
|
|
@@ -31688,7 +32200,7 @@ var teardown_default = {
|
|
|
31688
32200
|
}),
|
|
31689
32201
|
handler: async (argv) => {
|
|
31690
32202
|
await captureEvent({ argv, event: "apitogo teardown" });
|
|
31691
|
-
if (!await isLegacyConfig(
|
|
32203
|
+
if (!await isLegacyConfig(path96.resolve(process.cwd(), argv.dir))) {
|
|
31692
32204
|
await teardownProject(argv);
|
|
31693
32205
|
return;
|
|
31694
32206
|
}
|
|
@@ -31698,7 +32210,7 @@ var teardown_default = {
|
|
|
31698
32210
|
|
|
31699
32211
|
// src/cli/teardown/reset-command.ts
|
|
31700
32212
|
init_invariant();
|
|
31701
|
-
import
|
|
32213
|
+
import path97 from "node:path";
|
|
31702
32214
|
|
|
31703
32215
|
// src/cli/teardown/reset.ts
|
|
31704
32216
|
init_invariant();
|
|
@@ -31821,7 +32333,7 @@ async function resetProject(argv) {
|
|
|
31821
32333
|
const config2 = loadConfig();
|
|
31822
32334
|
const result = await resetProjectV2(
|
|
31823
32335
|
{
|
|
31824
|
-
dir:
|
|
32336
|
+
dir: path97.resolve(process.cwd(), argv.dir),
|
|
31825
32337
|
projectId: argv.projectId,
|
|
31826
32338
|
yes: argv.yes === true
|
|
31827
32339
|
},
|
|
@@ -31885,7 +32397,7 @@ var test_reset_default = {
|
|
|
31885
32397
|
};
|
|
31886
32398
|
|
|
31887
32399
|
// src/cli/test-sign-in/handler.ts
|
|
31888
|
-
import
|
|
32400
|
+
import path98 from "node:path";
|
|
31889
32401
|
init_invariant();
|
|
31890
32402
|
var TestSignInError = class extends ApitogoError {
|
|
31891
32403
|
constructor(message, developerHint) {
|
|
@@ -31896,7 +32408,7 @@ var TestSignInError = class extends ApitogoError {
|
|
|
31896
32408
|
async function resolveProjectId3(argv) {
|
|
31897
32409
|
const explicit = argv.projectId?.trim();
|
|
31898
32410
|
if (explicit) return explicit;
|
|
31899
|
-
const dir =
|
|
32411
|
+
const dir = path98.resolve(process.cwd(), argv.dir ?? ".");
|
|
31900
32412
|
if (await isConfigV2(dir)) {
|
|
31901
32413
|
const id = loadConfigV2(dir).resolved.project.id;
|
|
31902
32414
|
if (id) return id;
|
|
@@ -32036,36 +32548,36 @@ function createApitogoCli(argv) {
|
|
|
32036
32548
|
// src/cli/local-handoff.ts
|
|
32037
32549
|
import { spawn as spawn2 } from "node:child_process";
|
|
32038
32550
|
import { existsSync as existsSync9, realpathSync as realpathSync2 } from "node:fs";
|
|
32039
|
-
import
|
|
32551
|
+
import path99 from "node:path";
|
|
32040
32552
|
var LOCAL_HANDOFF_ENV = "APITOGO_LOCAL_CLI";
|
|
32041
32553
|
var PACKAGE_NAME = "@lukoweb/apitogo";
|
|
32042
32554
|
var resolveProjectDir = (argv, cwd) => {
|
|
32043
32555
|
for (let i = 0; i < argv.length; i++) {
|
|
32044
32556
|
const arg = argv[i];
|
|
32045
32557
|
const next = argv[i + 1];
|
|
32046
|
-
if (arg === "--dir" && next) return
|
|
32558
|
+
if (arg === "--dir" && next) return path99.resolve(cwd, next);
|
|
32047
32559
|
if (arg?.startsWith("--dir=")) {
|
|
32048
|
-
return
|
|
32560
|
+
return path99.resolve(cwd, arg.slice("--dir=".length));
|
|
32049
32561
|
}
|
|
32050
32562
|
}
|
|
32051
32563
|
return cwd;
|
|
32052
32564
|
};
|
|
32053
32565
|
var findLocalCli = (projectDir, runningRoot) => {
|
|
32054
|
-
let dir =
|
|
32566
|
+
let dir = path99.resolve(projectDir);
|
|
32055
32567
|
let localPackageRoot;
|
|
32056
32568
|
while (!localPackageRoot) {
|
|
32057
|
-
const candidate =
|
|
32058
|
-
if (existsSync9(
|
|
32569
|
+
const candidate = path99.join(dir, "node_modules", PACKAGE_NAME);
|
|
32570
|
+
if (existsSync9(path99.join(candidate, "package.json"))) {
|
|
32059
32571
|
localPackageRoot = candidate;
|
|
32060
|
-
} else if (dir ===
|
|
32572
|
+
} else if (dir === path99.dirname(dir)) {
|
|
32061
32573
|
return void 0;
|
|
32062
32574
|
} else {
|
|
32063
|
-
dir =
|
|
32575
|
+
dir = path99.dirname(dir);
|
|
32064
32576
|
}
|
|
32065
32577
|
}
|
|
32066
32578
|
const localRoot = realpathSync2(localPackageRoot);
|
|
32067
32579
|
if (localRoot === realpathSync2(runningRoot)) return void 0;
|
|
32068
|
-
return
|
|
32580
|
+
return path99.join(localRoot, "cli.js");
|
|
32069
32581
|
};
|
|
32070
32582
|
var handoffToLocalCli = async (argv, runningRoot) => {
|
|
32071
32583
|
if (process.env[LOCAL_HANDOFF_ENV] || process.env.ZUDOKU_ENV === "internal") {
|
|
@@ -32077,7 +32589,7 @@ var handoffToLocalCli = async (argv, runningRoot) => {
|
|
|
32077
32589
|
);
|
|
32078
32590
|
if (!localCli) return void 0;
|
|
32079
32591
|
printDiagnosticsToConsole(
|
|
32080
|
-
`Using the project's local ${PACKAGE_NAME} (${
|
|
32592
|
+
`Using the project's local ${PACKAGE_NAME} (${path99.dirname(localCli)})`
|
|
32081
32593
|
);
|
|
32082
32594
|
const child = spawn2(process.execPath, [localCli, ...argv], {
|
|
32083
32595
|
stdio: "inherit",
|