@lukoweb/apitogo 0.1.78 → 0.1.80
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 +393 -195
- package/docs/cli/commands.md +80 -0
- package/docs/cli/go-live.md +122 -0
- package/docs/cli/overview.md +89 -0
- package/docs/cli/setup.md +112 -0
- package/docs/cli/shape.md +121 -0
- package/docs/components.mdx +60 -0
- package/docs/configuration/authentication.md +4 -3
- package/docs/configuration/make-config.mdx +57 -17
- package/docs/configuration/manifest.md +3 -2
- package/docs/configuration/overview.md +3 -1
- package/docs/configuration/plans.md +113 -0
- package/docs/deploy/apitogo.md +9 -43
- package/docs/deployment.md +1 -1
- package/docs/guides/custom-pages.md +8 -0
- package/docs/guides/environment-variables.md +4 -3
- package/docs/mcp/go-live.md +1 -1
- package/docs/mcp/overview.md +1 -1
- package/docs/quickstart.md +2 -10
- package/package.json +1 -1
package/dist/cli/cli.js
CHANGED
|
@@ -744,7 +744,7 @@ import { stat } from "node:fs/promises";
|
|
|
744
744
|
var fileExists;
|
|
745
745
|
var init_file_exists = __esm({
|
|
746
746
|
"src/config/file-exists.ts"() {
|
|
747
|
-
fileExists = (
|
|
747
|
+
fileExists = (path45) => stat(path45).then(() => true).catch(() => false);
|
|
748
748
|
}
|
|
749
749
|
});
|
|
750
750
|
|
|
@@ -5633,7 +5633,7 @@ import {
|
|
|
5633
5633
|
// package.json
|
|
5634
5634
|
var package_default = {
|
|
5635
5635
|
name: "@lukoweb/apitogo",
|
|
5636
|
-
version: "0.1.
|
|
5636
|
+
version: "0.1.80",
|
|
5637
5637
|
type: "module",
|
|
5638
5638
|
sideEffects: [
|
|
5639
5639
|
"**/*.css",
|
|
@@ -6402,14 +6402,14 @@ var flattenAllOf = (schema2) => {
|
|
|
6402
6402
|
};
|
|
6403
6403
|
|
|
6404
6404
|
// src/lib/util/traverse.ts
|
|
6405
|
-
var traverse = (specification, transform,
|
|
6406
|
-
const transformed = transform(specification,
|
|
6405
|
+
var traverse = (specification, transform, path45 = []) => {
|
|
6406
|
+
const transformed = transform(specification, path45);
|
|
6407
6407
|
if (typeof transformed !== "object" || transformed === null) {
|
|
6408
6408
|
return transformed;
|
|
6409
6409
|
}
|
|
6410
6410
|
const result = Array.isArray(transformed) ? [] : {};
|
|
6411
6411
|
for (const [key, value] of Object.entries(transformed)) {
|
|
6412
|
-
const currentPath = [...
|
|
6412
|
+
const currentPath = [...path45, key];
|
|
6413
6413
|
if (Array.isArray(value)) {
|
|
6414
6414
|
result[key] = value.map(
|
|
6415
6415
|
(item, index) => typeof item === "object" && item != null ? traverse(item, transform, [...currentPath, index.toString()]) : item
|
|
@@ -6437,9 +6437,9 @@ var resolveLocalRef = (schema2, ref) => {
|
|
|
6437
6437
|
if (schemaCache?.has(ref)) {
|
|
6438
6438
|
return schemaCache.get(ref);
|
|
6439
6439
|
}
|
|
6440
|
-
const
|
|
6440
|
+
const path45 = ref.split("/").slice(1);
|
|
6441
6441
|
let current = schema2;
|
|
6442
|
-
for (const segment of
|
|
6442
|
+
for (const segment of path45) {
|
|
6443
6443
|
if (!current || typeof current !== "object") {
|
|
6444
6444
|
current = null;
|
|
6445
6445
|
}
|
|
@@ -6458,7 +6458,7 @@ var dereference = async (schema2, resolvers = []) => {
|
|
|
6458
6458
|
}
|
|
6459
6459
|
const cloned = structuredClone(schema2);
|
|
6460
6460
|
const visited = /* @__PURE__ */ new Set();
|
|
6461
|
-
const resolve = async (current,
|
|
6461
|
+
const resolve = async (current, path45) => {
|
|
6462
6462
|
if (isIndexableObject(current)) {
|
|
6463
6463
|
if (visited.has(current)) {
|
|
6464
6464
|
return CIRCULAR_REF;
|
|
@@ -6466,7 +6466,7 @@ var dereference = async (schema2, resolvers = []) => {
|
|
|
6466
6466
|
visited.add(current);
|
|
6467
6467
|
if (Array.isArray(current)) {
|
|
6468
6468
|
for (let index = 0; index < current.length; index++) {
|
|
6469
|
-
current[index] = await resolve(current[index], `${
|
|
6469
|
+
current[index] = await resolve(current[index], `${path45}/${index}`);
|
|
6470
6470
|
}
|
|
6471
6471
|
} else {
|
|
6472
6472
|
if ("$ref" in current && typeof current.$ref === "string") {
|
|
@@ -6477,13 +6477,13 @@ var dereference = async (schema2, resolvers = []) => {
|
|
|
6477
6477
|
for (const resolver of resolvers) {
|
|
6478
6478
|
const resolved = await resolver($ref);
|
|
6479
6479
|
if (resolved) {
|
|
6480
|
-
result2 = await resolve(resolved,
|
|
6480
|
+
result2 = await resolve(resolved, path45);
|
|
6481
6481
|
break;
|
|
6482
6482
|
}
|
|
6483
6483
|
}
|
|
6484
6484
|
if (result2 === void 0) {
|
|
6485
6485
|
const resolved = await resolveLocalRef(cloned, $ref);
|
|
6486
|
-
result2 = await resolve(resolved,
|
|
6486
|
+
result2 = await resolve(resolved, path45);
|
|
6487
6487
|
}
|
|
6488
6488
|
if (hasSiblings) {
|
|
6489
6489
|
if (result2 === CIRCULAR_REF) {
|
|
@@ -6496,7 +6496,7 @@ var dereference = async (schema2, resolvers = []) => {
|
|
|
6496
6496
|
return result2;
|
|
6497
6497
|
}
|
|
6498
6498
|
for (const key in current) {
|
|
6499
|
-
current[key] = await resolve(current[key], `${
|
|
6499
|
+
current[key] = await resolve(current[key], `${path45}/${key}`);
|
|
6500
6500
|
}
|
|
6501
6501
|
}
|
|
6502
6502
|
visited.delete(current);
|
|
@@ -6535,9 +6535,9 @@ var upgradeSchema = (schema2) => {
|
|
|
6535
6535
|
}
|
|
6536
6536
|
return sub;
|
|
6537
6537
|
});
|
|
6538
|
-
schema2 = traverse(schema2, (sub,
|
|
6538
|
+
schema2 = traverse(schema2, (sub, path45) => {
|
|
6539
6539
|
if (sub.example !== void 0) {
|
|
6540
|
-
if (isSchemaPath(
|
|
6540
|
+
if (isSchemaPath(path45 ?? [])) {
|
|
6541
6541
|
sub.examples = [sub.example];
|
|
6542
6542
|
} else {
|
|
6543
6543
|
sub.examples = {
|
|
@@ -6550,11 +6550,11 @@ var upgradeSchema = (schema2) => {
|
|
|
6550
6550
|
}
|
|
6551
6551
|
return sub;
|
|
6552
6552
|
});
|
|
6553
|
-
schema2 = traverse(schema2, (schema3,
|
|
6553
|
+
schema2 = traverse(schema2, (schema3, path45) => {
|
|
6554
6554
|
if (schema3.type === "object" && schema3.properties !== void 0) {
|
|
6555
|
-
const parentPath =
|
|
6555
|
+
const parentPath = path45?.slice(0, -1);
|
|
6556
6556
|
const isMultipart = parentPath?.some((segment, index) => {
|
|
6557
|
-
return segment === "content" &&
|
|
6557
|
+
return segment === "content" && path45?.[index + 1] === "multipart/form-data";
|
|
6558
6558
|
});
|
|
6559
6559
|
if (isMultipart) {
|
|
6560
6560
|
const entries = Object.entries(schema3.properties);
|
|
@@ -6568,8 +6568,8 @@ var upgradeSchema = (schema2) => {
|
|
|
6568
6568
|
}
|
|
6569
6569
|
return schema3;
|
|
6570
6570
|
});
|
|
6571
|
-
schema2 = traverse(schema2, (schema3,
|
|
6572
|
-
if (
|
|
6571
|
+
schema2 = traverse(schema2, (schema3, path45) => {
|
|
6572
|
+
if (path45?.includes("content") && path45.includes("application/octet-stream")) {
|
|
6573
6573
|
return {};
|
|
6574
6574
|
}
|
|
6575
6575
|
if (schema3.type === "string" && schema3.format === "binary") {
|
|
@@ -6595,11 +6595,11 @@ var upgradeSchema = (schema2) => {
|
|
|
6595
6595
|
}
|
|
6596
6596
|
return sub;
|
|
6597
6597
|
});
|
|
6598
|
-
schema2 = traverse(schema2, (schema3,
|
|
6598
|
+
schema2 = traverse(schema2, (schema3, path45) => {
|
|
6599
6599
|
if (schema3.type === "string" && schema3.format === "byte") {
|
|
6600
|
-
const parentPath =
|
|
6600
|
+
const parentPath = path45?.slice(0, -1);
|
|
6601
6601
|
const contentMediaType = parentPath?.find(
|
|
6602
|
-
(_, index) =>
|
|
6602
|
+
(_, index) => path45?.[index - 1] === "content"
|
|
6603
6603
|
);
|
|
6604
6604
|
return {
|
|
6605
6605
|
type: "string",
|
|
@@ -6611,7 +6611,7 @@ var upgradeSchema = (schema2) => {
|
|
|
6611
6611
|
});
|
|
6612
6612
|
return schema2;
|
|
6613
6613
|
};
|
|
6614
|
-
function isSchemaPath(
|
|
6614
|
+
function isSchemaPath(path45) {
|
|
6615
6615
|
const schemaLocations = [
|
|
6616
6616
|
["components", "schemas"],
|
|
6617
6617
|
"properties",
|
|
@@ -6624,10 +6624,10 @@ function isSchemaPath(path43) {
|
|
|
6624
6624
|
];
|
|
6625
6625
|
return schemaLocations.some((location) => {
|
|
6626
6626
|
if (Array.isArray(location)) {
|
|
6627
|
-
return location.every((segment, index) =>
|
|
6627
|
+
return location.every((segment, index) => path45[index] === segment);
|
|
6628
6628
|
}
|
|
6629
|
-
return
|
|
6630
|
-
}) ||
|
|
6629
|
+
return path45.includes(location);
|
|
6630
|
+
}) || path45.includes("schema") || path45.some((segment) => segment.endsWith("Schema"));
|
|
6631
6631
|
}
|
|
6632
6632
|
|
|
6633
6633
|
// src/lib/oas/parser/index.ts
|
|
@@ -6709,13 +6709,13 @@ var OPENAPI_PROPS = /* @__PURE__ */ new Set([
|
|
|
6709
6709
|
"anyOf",
|
|
6710
6710
|
"oneOf"
|
|
6711
6711
|
]);
|
|
6712
|
-
var handleCircularRefs = (obj, currentPath = /* @__PURE__ */ new WeakSet(), refs = /* @__PURE__ */ new WeakMap(),
|
|
6712
|
+
var handleCircularRefs = (obj, currentPath = /* @__PURE__ */ new WeakSet(), refs = /* @__PURE__ */ new WeakMap(), path45 = [], currentRefPaths = /* @__PURE__ */ new Set()) => {
|
|
6713
6713
|
if (obj === null || typeof obj !== "object") return obj;
|
|
6714
6714
|
const refPath = obj.__$ref;
|
|
6715
6715
|
const isCircular = currentPath.has(obj) || typeof refPath === "string" && currentRefPaths.has(refPath);
|
|
6716
6716
|
if (isCircular) {
|
|
6717
6717
|
if (typeof refPath === "string") return SCHEMA_REF_PREFIX + refPath;
|
|
6718
|
-
const circularProp =
|
|
6718
|
+
const circularProp = path45.find((p) => !OPENAPI_PROPS.has(p)) || path45[0];
|
|
6719
6719
|
return [CIRCULAR_REF, circularProp].filter(Boolean).join(":");
|
|
6720
6720
|
}
|
|
6721
6721
|
if (refs.has(obj)) return refs.get(obj);
|
|
@@ -6725,7 +6725,7 @@ var handleCircularRefs = (obj, currentPath = /* @__PURE__ */ new WeakSet(), refs
|
|
|
6725
6725
|
value,
|
|
6726
6726
|
currentPath,
|
|
6727
6727
|
refs,
|
|
6728
|
-
[...
|
|
6728
|
+
[...path45, key],
|
|
6729
6729
|
currentRefPaths
|
|
6730
6730
|
);
|
|
6731
6731
|
const result = Array.isArray(obj) ? obj.map((item, i) => recurse(item, i.toString())) : Object.fromEntries(
|
|
@@ -6760,7 +6760,7 @@ var resolveExtensions = (obj) => Object.fromEntries(
|
|
|
6760
6760
|
var getAllTags = (schema2) => {
|
|
6761
6761
|
const rootTags = schema2.tags ?? [];
|
|
6762
6762
|
const operations = Object.values(schema2.paths ?? {}).flatMap(
|
|
6763
|
-
(
|
|
6763
|
+
(path45) => HttpMethods.map((k) => path45?.[k]).filter((op) => op != null)
|
|
6764
6764
|
);
|
|
6765
6765
|
const operationTags = new Set(operations.flatMap((op) => op.tags ?? []));
|
|
6766
6766
|
const hasUntaggedOperations = operations.some(
|
|
@@ -6815,7 +6815,7 @@ var getAllSlugs = (ops, schemaTags = []) => {
|
|
|
6815
6815
|
var getOperationSlugKey = (op) => [op.path, op.method, op.operationId, op.summary].filter(Boolean).join("-");
|
|
6816
6816
|
var getAllOperations = (paths) => {
|
|
6817
6817
|
const operations = Object.entries(paths ?? {}).flatMap(
|
|
6818
|
-
([
|
|
6818
|
+
([path45, value]) => HttpMethods.flatMap((method) => {
|
|
6819
6819
|
if (!value?.[method]) return [];
|
|
6820
6820
|
const operation = value[method];
|
|
6821
6821
|
const pathParameters = value.parameters ?? [];
|
|
@@ -6835,7 +6835,7 @@ var getAllOperations = (paths) => {
|
|
|
6835
6835
|
return {
|
|
6836
6836
|
...operation,
|
|
6837
6837
|
method,
|
|
6838
|
-
path:
|
|
6838
|
+
path: path45,
|
|
6839
6839
|
parameters,
|
|
6840
6840
|
servers,
|
|
6841
6841
|
tags: operation.tags ?? []
|
|
@@ -7193,8 +7193,8 @@ var Schema = builder.objectRef("Schema").implement({
|
|
|
7193
7193
|
}),
|
|
7194
7194
|
paths: t.field({
|
|
7195
7195
|
type: [PathItem],
|
|
7196
|
-
resolve: (root) => Object.entries(root.paths ?? {}).map(([
|
|
7197
|
-
path:
|
|
7196
|
+
resolve: (root) => Object.entries(root.paths ?? {}).map(([path45, value]) => ({
|
|
7197
|
+
path: path45,
|
|
7198
7198
|
// biome-ignore lint/style/noNonNullAssertion: value is guaranteed to be defined
|
|
7199
7199
|
methods: Object.keys(value)
|
|
7200
7200
|
}))
|
|
@@ -7359,7 +7359,7 @@ init_joinUrl();
|
|
|
7359
7359
|
|
|
7360
7360
|
// src/vite/api/schema-codegen.ts
|
|
7361
7361
|
var unescapeJsonPointer = (uri) => decodeURIComponent(uri.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
7362
|
-
var getSegmentsFromPath = (
|
|
7362
|
+
var getSegmentsFromPath = (path45) => path45.split("/").slice(1).map(unescapeJsonPointer);
|
|
7363
7363
|
var createLocalRefMap = (obj) => {
|
|
7364
7364
|
const refMap = /* @__PURE__ */ new Map();
|
|
7365
7365
|
const siblingsMap = /* @__PURE__ */ new Map();
|
|
@@ -7390,16 +7390,16 @@ var replaceMarkers = (code, mergedRefs) => code.replace(/"__refMap:(.*?)"/g, '__
|
|
|
7390
7390
|
/"__refMap\+Siblings:(.*?)"/g,
|
|
7391
7391
|
(_, key) => mergedRefs.get(key) ?? `__refMap["${key}"]`
|
|
7392
7392
|
);
|
|
7393
|
-
var lookup = (schema2,
|
|
7394
|
-
const parts = getSegmentsFromPath(
|
|
7393
|
+
var lookup = (schema2, path45, filePath) => {
|
|
7394
|
+
const parts = getSegmentsFromPath(path45);
|
|
7395
7395
|
let val = schema2;
|
|
7396
7396
|
for (const part of parts) {
|
|
7397
7397
|
while (val.$ref?.startsWith("#/")) {
|
|
7398
|
-
val = val.$ref ===
|
|
7398
|
+
val = val.$ref === path45 ? val : lookup(schema2, val.$ref, filePath);
|
|
7399
7399
|
}
|
|
7400
7400
|
if (val[part] === void 0) {
|
|
7401
7401
|
throw new Error(
|
|
7402
|
-
`Error in ${filePath ?? "code generation"}: Could not find path segment ${part} in path: ${
|
|
7402
|
+
`Error in ${filePath ?? "code generation"}: Could not find path segment ${part} in path: ${path45}`
|
|
7403
7403
|
);
|
|
7404
7404
|
}
|
|
7405
7405
|
val = val[part];
|
|
@@ -7644,8 +7644,8 @@ var SchemaManager = class {
|
|
|
7644
7644
|
}
|
|
7645
7645
|
}
|
|
7646
7646
|
};
|
|
7647
|
-
getLatestSchema = (
|
|
7648
|
-
getSchemasForPath = (
|
|
7647
|
+
getLatestSchema = (path45) => this.processedSchemas[path45]?.at(0);
|
|
7648
|
+
getSchemasForPath = (path45) => this.processedSchemas[path45];
|
|
7649
7649
|
getSchemaImports = () => Object.values(this.processedSchemas).flat().filter((s) => s.importKey);
|
|
7650
7650
|
getUrlToFilePathMap = () => {
|
|
7651
7651
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -10046,14 +10046,14 @@ async function generateSitemap({
|
|
|
10046
10046
|
|
|
10047
10047
|
// src/vite/prerender/utils.ts
|
|
10048
10048
|
init_joinUrl();
|
|
10049
|
-
var resolveRoutePath = (
|
|
10050
|
-
const segments =
|
|
10049
|
+
var resolveRoutePath = (path45) => {
|
|
10050
|
+
const segments = path45.split("/");
|
|
10051
10051
|
if (segments.some((s) => s.startsWith(":") && !s.endsWith("?"))) {
|
|
10052
10052
|
return void 0;
|
|
10053
10053
|
}
|
|
10054
10054
|
return segments.filter((s) => !s.startsWith(":")).join("/") || void 0;
|
|
10055
10055
|
};
|
|
10056
|
-
var isSkipped = (
|
|
10056
|
+
var isSkipped = (path45) => path45.includes("*") || /^\d+$/.test(path45);
|
|
10057
10057
|
var resolveRoutes = (routes, parentPath = "") => routes.flatMap((route) => {
|
|
10058
10058
|
if (route.path && isSkipped(route.path)) return [];
|
|
10059
10059
|
const routePath = route.path ? resolveRoutePath(route.path) : void 0;
|
|
@@ -10518,103 +10518,17 @@ var build_default = {
|
|
|
10518
10518
|
|
|
10519
10519
|
// src/cli/make-config/handler.ts
|
|
10520
10520
|
import { constants as constants2 } from "node:fs";
|
|
10521
|
-
import { access as access3, readFile as readFile5, writeFile as writeFile7 } from "node:fs/promises";
|
|
10522
|
-
import
|
|
10521
|
+
import { access as access3, mkdir as mkdir7, readFile as readFile5, writeFile as writeFile7 } from "node:fs/promises";
|
|
10522
|
+
import path36 from "node:path";
|
|
10523
10523
|
import { glob as glob5 } from "glob";
|
|
10524
10524
|
|
|
10525
10525
|
// src/cli/make-config/interactive.ts
|
|
10526
10526
|
import { createInterface } from "node:readline/promises";
|
|
10527
10527
|
import { stdin as input, stdout as output } from "node:process";
|
|
10528
|
-
|
|
10529
|
-
const suffix = defaultValue ? ` [${defaultValue}]` : "";
|
|
10530
|
-
const answer = (await rl.question(`${question}${suffix}: `)).trim();
|
|
10531
|
-
return answer || defaultValue || "";
|
|
10532
|
-
};
|
|
10533
|
-
var askYesNo = async (rl, question, defaultYes) => {
|
|
10534
|
-
const hint = defaultYes ? "Y/n" : "y/N";
|
|
10535
|
-
const answer = (await rl.question(`${question} (${hint}): `)).trim().toLowerCase();
|
|
10536
|
-
if (!answer) {
|
|
10537
|
-
return defaultYes;
|
|
10538
|
-
}
|
|
10539
|
-
return answer === "y" || answer === "yes";
|
|
10540
|
-
};
|
|
10541
|
-
async function promptMakeConfigInteractive(defaults) {
|
|
10542
|
-
const rl = createInterface({ input, output });
|
|
10543
|
-
try {
|
|
10544
|
-
const title = await ask(rl, "Site title", defaults.title);
|
|
10545
|
-
const logoAlt = await ask(rl, "Logo alt text", defaults.logoAlt);
|
|
10546
|
-
const authEnabled = await askYesNo(
|
|
10547
|
-
rl,
|
|
10548
|
-
"Enable authentication",
|
|
10549
|
-
defaults.authEnabled
|
|
10550
|
-
);
|
|
10551
|
-
let apiBaseUrl = defaults.apiBaseUrl ?? "";
|
|
10552
|
-
if (authEnabled) {
|
|
10553
|
-
apiBaseUrl = await ask(
|
|
10554
|
-
rl,
|
|
10555
|
-
"Auth API base URL (optional; secrets stay in .env)",
|
|
10556
|
-
apiBaseUrl
|
|
10557
|
-
);
|
|
10558
|
-
}
|
|
10559
|
-
const sans = await ask(rl, "Sans font", defaults.sans ?? "IBM Plex Sans");
|
|
10560
|
-
const mono = await ask(
|
|
10561
|
-
rl,
|
|
10562
|
-
"Mono font",
|
|
10563
|
-
defaults.mono ?? "JetBrains Mono"
|
|
10564
|
-
);
|
|
10565
|
-
const lightPrimary = await ask(
|
|
10566
|
-
rl,
|
|
10567
|
-
"Light primary color",
|
|
10568
|
-
defaults.lightPrimary ?? "#E11D2A"
|
|
10569
|
-
);
|
|
10570
|
-
const darkPrimary = await ask(
|
|
10571
|
-
rl,
|
|
10572
|
-
"Dark primary color",
|
|
10573
|
-
defaults.darkPrimary ?? "#F23645"
|
|
10574
|
-
);
|
|
10575
|
-
let openApiPath;
|
|
10576
|
-
if (defaults.discoveredOpenApi) {
|
|
10577
|
-
const useDiscovered = await askYesNo(
|
|
10578
|
-
rl,
|
|
10579
|
-
`Wire OpenAPI at ${defaults.discoveredOpenApi}`,
|
|
10580
|
-
true
|
|
10581
|
-
);
|
|
10582
|
-
openApiPath = useDiscovered ? defaults.discoveredOpenApi : null;
|
|
10583
|
-
} else {
|
|
10584
|
-
const entered = await ask(
|
|
10585
|
-
rl,
|
|
10586
|
-
"OpenAPI file path (leave empty to skip)",
|
|
10587
|
-
""
|
|
10588
|
-
);
|
|
10589
|
-
openApiPath = entered || null;
|
|
10590
|
-
}
|
|
10591
|
-
const authentication = {
|
|
10592
|
-
enabled: authEnabled,
|
|
10593
|
-
type: "dev-portal"
|
|
10594
|
-
};
|
|
10595
|
-
if (apiBaseUrl) {
|
|
10596
|
-
authentication.apiBaseUrl = apiBaseUrl;
|
|
10597
|
-
}
|
|
10598
|
-
return {
|
|
10599
|
-
title,
|
|
10600
|
-
site: {
|
|
10601
|
-
title,
|
|
10602
|
-
logo: { alt: logoAlt }
|
|
10603
|
-
},
|
|
10604
|
-
theme: {
|
|
10605
|
-
fonts: { sans, mono },
|
|
10606
|
-
light: { primary: lightPrimary },
|
|
10607
|
-
dark: { primary: darkPrimary }
|
|
10608
|
-
},
|
|
10609
|
-
authentication,
|
|
10610
|
-
openApiPath
|
|
10611
|
-
};
|
|
10612
|
-
} finally {
|
|
10613
|
-
rl.close();
|
|
10614
|
-
}
|
|
10615
|
-
}
|
|
10528
|
+
import path34 from "node:path";
|
|
10616
10529
|
|
|
10617
10530
|
// src/cli/make-config/json-config.ts
|
|
10531
|
+
import path33 from "node:path";
|
|
10618
10532
|
var APITOGO_JSON_FILENAME = "apitogo.config.json";
|
|
10619
10533
|
var DOCUMENTATION_NAV_LABEL = "Documentation";
|
|
10620
10534
|
var API_REFERENCE_PATH = "/api";
|
|
@@ -10665,7 +10579,7 @@ function createDefaultApitogoJsonConfig(options) {
|
|
|
10665
10579
|
}
|
|
10666
10580
|
},
|
|
10667
10581
|
authentication: {
|
|
10668
|
-
enabled:
|
|
10582
|
+
enabled: true,
|
|
10669
10583
|
type: "dev-portal",
|
|
10670
10584
|
redirectToAfterSignIn: "/account/dashboard",
|
|
10671
10585
|
redirectToAfterSignUp: "/account/dashboard"
|
|
@@ -10895,6 +10809,67 @@ function openapiInputForConfig(specRelativePosix) {
|
|
|
10895
10809
|
}
|
|
10896
10810
|
return `./${specRelativePosix}`;
|
|
10897
10811
|
}
|
|
10812
|
+
function toRelativeOpenApiInput(projectDir, inputPath) {
|
|
10813
|
+
const resolved = path33.isAbsolute(inputPath) ? inputPath : path33.resolve(projectDir, inputPath);
|
|
10814
|
+
const relative = path33.relative(projectDir, resolved);
|
|
10815
|
+
const posix = relative.split(path33.sep).join(path33.posix.sep);
|
|
10816
|
+
if (!posix) {
|
|
10817
|
+
throw new Error("OpenAPI path must point to a file.");
|
|
10818
|
+
}
|
|
10819
|
+
return openapiInputForConfig(posix);
|
|
10820
|
+
}
|
|
10821
|
+
function normalizePageSlug(pathOrSlug) {
|
|
10822
|
+
return pathOrSlug.replace(/^\/+/, "").replace(/\/+$/, "").replace(/\.(mdx?|tsx|jsx)$/i, "");
|
|
10823
|
+
}
|
|
10824
|
+
function slugifyPlanSku(displayName) {
|
|
10825
|
+
const sku = displayName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
10826
|
+
return sku || "plan";
|
|
10827
|
+
}
|
|
10828
|
+
function buildLimitsJson(rateLimitCalls, monthlyQuota) {
|
|
10829
|
+
return JSON.stringify({
|
|
10830
|
+
rateLimit: { calls: rateLimitCalls, renewalPeriodSeconds: 60 },
|
|
10831
|
+
quota: { calls: monthlyQuota, renewalPeriodDays: 30 }
|
|
10832
|
+
});
|
|
10833
|
+
}
|
|
10834
|
+
function buildPlanItemFromWizard(input2) {
|
|
10835
|
+
const sku = input2.sku ?? slugifyPlanSku(input2.displayName);
|
|
10836
|
+
const item = {
|
|
10837
|
+
sku,
|
|
10838
|
+
displayName: input2.displayName,
|
|
10839
|
+
priceAmount: input2.priceAmount,
|
|
10840
|
+
limitsJson: buildLimitsJson(input2.rateLimitCalls, input2.monthlyQuota)
|
|
10841
|
+
};
|
|
10842
|
+
if (input2.priceAmount > 0) {
|
|
10843
|
+
item.priceCurrency = "usd";
|
|
10844
|
+
item.billingPeriod = "month";
|
|
10845
|
+
}
|
|
10846
|
+
return item;
|
|
10847
|
+
}
|
|
10848
|
+
function applyPlansToJsonConfig(config2, planItems) {
|
|
10849
|
+
if (planItems.length === 0) {
|
|
10850
|
+
return config2;
|
|
10851
|
+
}
|
|
10852
|
+
const modules = isPlainObject2(config2.modules) ? { ...config2.modules } : {};
|
|
10853
|
+
const userPanel = isPlainObject2(modules.userPanel) ? { ...modules.userPanel } : {};
|
|
10854
|
+
const plans = isPlainObject2(userPanel.plans) ? { ...userPanel.plans } : {};
|
|
10855
|
+
const existing = Array.isArray(plans.items) ? [...plans.items] : [];
|
|
10856
|
+
for (const item of planItems) {
|
|
10857
|
+
const sku = item.sku;
|
|
10858
|
+
const index = typeof sku === "string" ? existing.findIndex((plan) => plan.sku === sku) : -1;
|
|
10859
|
+
if (index >= 0) {
|
|
10860
|
+
existing[index] = { ...existing[index], ...item };
|
|
10861
|
+
} else {
|
|
10862
|
+
existing.push(item);
|
|
10863
|
+
}
|
|
10864
|
+
}
|
|
10865
|
+
userPanel.plans = {
|
|
10866
|
+
...plans,
|
|
10867
|
+
enabled: true,
|
|
10868
|
+
items: existing
|
|
10869
|
+
};
|
|
10870
|
+
modules.userPanel = userPanel;
|
|
10871
|
+
return { ...config2, modules };
|
|
10872
|
+
}
|
|
10898
10873
|
function toRoutePath(relativeFile, pagesDir) {
|
|
10899
10874
|
const relativeNoExt = relativeFile.replace(/\.(mdx?|tsx|jsx)$/i, "");
|
|
10900
10875
|
const escaped = pagesDir.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -10981,11 +10956,233 @@ ${customPages}
|
|
|
10981
10956
|
`;
|
|
10982
10957
|
}
|
|
10983
10958
|
|
|
10959
|
+
// src/cli/make-config/wrap-up.ts
|
|
10960
|
+
var DOCS = "https://docs.apitogo.com";
|
|
10961
|
+
function printPageAddedHint(relativePath, routePath) {
|
|
10962
|
+
printDiagnosticsToConsole(`Page created: ${relativePath} (route ${routePath})`);
|
|
10963
|
+
printDiagnosticsToConsole("Edit that file to change the content.");
|
|
10964
|
+
printDiagnosticsToConsole(
|
|
10965
|
+
`Predefined components: ${DOCS}/docs/components`
|
|
10966
|
+
);
|
|
10967
|
+
}
|
|
10968
|
+
function printPlanAddedHint(displayName) {
|
|
10969
|
+
printDiagnosticsToConsole(
|
|
10970
|
+
`Plan "${displayName}" added to modules.userPanel.plans.items in apitogo.config.json.`
|
|
10971
|
+
);
|
|
10972
|
+
printDiagnosticsToConsole(
|
|
10973
|
+
"Configure includedActionKeys, billing, and Stripe in the manifest before publish."
|
|
10974
|
+
);
|
|
10975
|
+
printDiagnosticsToConsole(`Docs: ${DOCS}/docs/configuration/plans`);
|
|
10976
|
+
}
|
|
10977
|
+
function printPaidPlanPlatformWarning() {
|
|
10978
|
+
printDiagnosticsToConsole(
|
|
10979
|
+
"Paid API plans require Starter or Professional platform hosting. Free cannot publish paid gateway plans."
|
|
10980
|
+
);
|
|
10981
|
+
}
|
|
10982
|
+
function printInteractiveWrapUp(hasPaidPlans) {
|
|
10983
|
+
printDiagnosticsToConsole("");
|
|
10984
|
+
printDiagnosticsToConsole("Configuration saved. Next steps:");
|
|
10985
|
+
printDiagnosticsToConsole("- Preview locally: npm run dev");
|
|
10986
|
+
if (hasPaidPlans) {
|
|
10987
|
+
printPaidPlanPlatformWarning();
|
|
10988
|
+
} else {
|
|
10989
|
+
printDiagnosticsToConsole(
|
|
10990
|
+
"Platform note: Free hosting does not support paid API plans or custom domains \u2014 use Starter or Professional for those."
|
|
10991
|
+
);
|
|
10992
|
+
}
|
|
10993
|
+
printDiagnosticsToConsole("");
|
|
10994
|
+
printDiagnosticsToConsole("Configure more:");
|
|
10995
|
+
printDiagnosticsToConsole(`- Overview: ${DOCS}/docs/configuration/overview`);
|
|
10996
|
+
printDiagnosticsToConsole(`- Gateway plans: ${DOCS}/docs/configuration/plans`);
|
|
10997
|
+
printDiagnosticsToConsole(`- Custom pages: ${DOCS}/docs/guides/custom-pages`);
|
|
10998
|
+
printDiagnosticsToConsole(`- API reference: ${DOCS}/docs/configuration/api-reference`);
|
|
10999
|
+
printDiagnosticsToConsole(`- Theme: ${DOCS}/docs/customization/colors-theme`);
|
|
11000
|
+
printDiagnosticsToConsole(`- Fonts: ${DOCS}/docs/customization/fonts`);
|
|
11001
|
+
printDiagnosticsToConsole(`- CLI shape: ${DOCS}/docs/cli/shape`);
|
|
11002
|
+
}
|
|
11003
|
+
|
|
11004
|
+
// src/cli/make-config/interactive.ts
|
|
11005
|
+
var ask = async (rl, question, defaultValue) => {
|
|
11006
|
+
const suffix = defaultValue ? ` [${defaultValue}]` : "";
|
|
11007
|
+
const answer = (await rl.question(`${question}${suffix}: `)).trim();
|
|
11008
|
+
return answer || defaultValue || "";
|
|
11009
|
+
};
|
|
11010
|
+
var askNonNegativeNumber = async (rl, question, defaultValue) => {
|
|
11011
|
+
while (true) {
|
|
11012
|
+
const answer = await ask(rl, question, String(defaultValue));
|
|
11013
|
+
const parsed = Number.parseFloat(answer);
|
|
11014
|
+
if (!Number.isNaN(parsed) && parsed >= 0) {
|
|
11015
|
+
return parsed;
|
|
11016
|
+
}
|
|
11017
|
+
printDiagnosticsToConsole("Enter a non-negative number.");
|
|
11018
|
+
}
|
|
11019
|
+
};
|
|
11020
|
+
var parseLoopChoice = (raw) => {
|
|
11021
|
+
const value = raw.trim().toLowerCase();
|
|
11022
|
+
if (!value || value === "done") {
|
|
11023
|
+
return "done";
|
|
11024
|
+
}
|
|
11025
|
+
if (value === "openapi" || value === "page" || value === "plan") {
|
|
11026
|
+
return value;
|
|
11027
|
+
}
|
|
11028
|
+
return null;
|
|
11029
|
+
};
|
|
11030
|
+
async function promptMakeConfigInteractive(defaults) {
|
|
11031
|
+
const rl = createInterface({ input, output });
|
|
11032
|
+
const customPages = [];
|
|
11033
|
+
const planItems = [];
|
|
11034
|
+
let hasPaidPlans = false;
|
|
11035
|
+
let openApiPath;
|
|
11036
|
+
try {
|
|
11037
|
+
const title = await ask(rl, "Site title", defaults.title);
|
|
11038
|
+
while (true) {
|
|
11039
|
+
const choiceRaw = await ask(
|
|
11040
|
+
rl,
|
|
11041
|
+
"Add OpenAPI, a custom page, or a plan? (openapi / page / plan / done)",
|
|
11042
|
+
"done"
|
|
11043
|
+
);
|
|
11044
|
+
const choice = parseLoopChoice(choiceRaw);
|
|
11045
|
+
if (!choice) {
|
|
11046
|
+
printDiagnosticsToConsole("Choose openapi, page, plan, or done.");
|
|
11047
|
+
continue;
|
|
11048
|
+
}
|
|
11049
|
+
if (choice === "done") {
|
|
11050
|
+
break;
|
|
11051
|
+
}
|
|
11052
|
+
if (choice === "openapi") {
|
|
11053
|
+
const entered = await ask(
|
|
11054
|
+
rl,
|
|
11055
|
+
"OpenAPI file path (leave empty to skip)",
|
|
11056
|
+
defaults.discoveredOpenApi ?? ""
|
|
11057
|
+
);
|
|
11058
|
+
openApiPath = entered ? entered : null;
|
|
11059
|
+
if (openApiPath) {
|
|
11060
|
+
printDiagnosticsToConsole(
|
|
11061
|
+
`OpenAPI will be linked as a relative path in apitogo.config.json.`
|
|
11062
|
+
);
|
|
11063
|
+
}
|
|
11064
|
+
continue;
|
|
11065
|
+
}
|
|
11066
|
+
if (choice === "page") {
|
|
11067
|
+
const pageTitle = await ask(rl, "Page title");
|
|
11068
|
+
if (!pageTitle.trim()) {
|
|
11069
|
+
printDiagnosticsToConsole("Page title is required.");
|
|
11070
|
+
continue;
|
|
11071
|
+
}
|
|
11072
|
+
const address = await ask(
|
|
11073
|
+
rl,
|
|
11074
|
+
"Page URL path (e.g. /guides/getting-started)"
|
|
11075
|
+
);
|
|
11076
|
+
const slug = normalizePageSlug(address);
|
|
11077
|
+
if (!slug) {
|
|
11078
|
+
printDiagnosticsToConsole("Page URL path is required.");
|
|
11079
|
+
continue;
|
|
11080
|
+
}
|
|
11081
|
+
const routePath = `/${slug}`;
|
|
11082
|
+
const relativePath = path34.posix.join(defaults.pagesDir, `${slug}.tsx`);
|
|
11083
|
+
const page = {
|
|
11084
|
+
slug,
|
|
11085
|
+
title: pageTitle.trim(),
|
|
11086
|
+
routePath,
|
|
11087
|
+
relativePath
|
|
11088
|
+
};
|
|
11089
|
+
customPages.push(page);
|
|
11090
|
+
printPageAddedHint(relativePath, routePath);
|
|
11091
|
+
continue;
|
|
11092
|
+
}
|
|
11093
|
+
const displayName = await ask(rl, "Plan title");
|
|
11094
|
+
if (!displayName.trim()) {
|
|
11095
|
+
printDiagnosticsToConsole("Plan title is required.");
|
|
11096
|
+
continue;
|
|
11097
|
+
}
|
|
11098
|
+
const priceAmount = await askNonNegativeNumber(
|
|
11099
|
+
rl,
|
|
11100
|
+
"Price (USD/month, 0 for free)",
|
|
11101
|
+
0
|
|
11102
|
+
);
|
|
11103
|
+
const rateLimitCalls = await askNonNegativeNumber(
|
|
11104
|
+
rl,
|
|
11105
|
+
"Rate limit (calls per minute)",
|
|
11106
|
+
100
|
|
11107
|
+
);
|
|
11108
|
+
const monthlyQuota = await askNonNegativeNumber(
|
|
11109
|
+
rl,
|
|
11110
|
+
"Monthly quota (calls per 30 days)",
|
|
11111
|
+
5e4
|
|
11112
|
+
);
|
|
11113
|
+
const planItem = buildPlanItemFromWizard({
|
|
11114
|
+
displayName: displayName.trim(),
|
|
11115
|
+
priceAmount,
|
|
11116
|
+
rateLimitCalls,
|
|
11117
|
+
monthlyQuota
|
|
11118
|
+
});
|
|
11119
|
+
planItems.push(planItem);
|
|
11120
|
+
if (priceAmount > 0) {
|
|
11121
|
+
hasPaidPlans = true;
|
|
11122
|
+
printPaidPlanPlatformWarning();
|
|
11123
|
+
}
|
|
11124
|
+
printPlanAddedHint(displayName.trim());
|
|
11125
|
+
}
|
|
11126
|
+
return {
|
|
11127
|
+
title,
|
|
11128
|
+
site: { title },
|
|
11129
|
+
authentication: {
|
|
11130
|
+
enabled: true,
|
|
11131
|
+
type: "dev-portal"
|
|
11132
|
+
},
|
|
11133
|
+
openApiPath,
|
|
11134
|
+
customPages,
|
|
11135
|
+
planItems,
|
|
11136
|
+
hasPaidPlans
|
|
11137
|
+
};
|
|
11138
|
+
} finally {
|
|
11139
|
+
rl.close();
|
|
11140
|
+
}
|
|
11141
|
+
}
|
|
11142
|
+
|
|
11143
|
+
// src/cli/make-config/page-scaffold.ts
|
|
11144
|
+
function buildStarterDocsPageTsx(slug, title) {
|
|
11145
|
+
const componentName = pageComponentName(slug);
|
|
11146
|
+
const safeTitle = title.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
11147
|
+
return `import { Callout, Heading, Typography } from "@lukoweb/apitogo/components";
|
|
11148
|
+
|
|
11149
|
+
export default function ${componentName}() {
|
|
11150
|
+
return (
|
|
11151
|
+
<section className="mx-auto max-w-screen-xl px-4 py-12 pt-(--padding-content-top)">
|
|
11152
|
+
<Typography>
|
|
11153
|
+
<Heading level={1}>${safeTitle}</Heading>
|
|
11154
|
+
<p className="mt-4 text-muted-foreground">
|
|
11155
|
+
Edit this page in <code>pages/${slug}.tsx</code>.
|
|
11156
|
+
</p>
|
|
11157
|
+
<Callout type="info" title="Components">
|
|
11158
|
+
APIToGo ships predefined UI components for docs pages. See{" "}
|
|
11159
|
+
<a
|
|
11160
|
+
href="https://docs.apitogo.com/docs/guides/custom-pages"
|
|
11161
|
+
className="text-primary underline"
|
|
11162
|
+
>
|
|
11163
|
+
custom pages
|
|
11164
|
+
</a>{" "}
|
|
11165
|
+
and the{" "}
|
|
11166
|
+
<a
|
|
11167
|
+
href="https://docs.apitogo.com/docs/components/callout"
|
|
11168
|
+
className="text-primary underline"
|
|
11169
|
+
>
|
|
11170
|
+
component catalog
|
|
11171
|
+
</a>
|
|
11172
|
+
.
|
|
11173
|
+
</Callout>
|
|
11174
|
+
</Typography>
|
|
11175
|
+
</section>
|
|
11176
|
+
);
|
|
11177
|
+
}
|
|
11178
|
+
`;
|
|
11179
|
+
}
|
|
11180
|
+
|
|
10984
11181
|
// src/cli/make-config/scaffold-project.ts
|
|
10985
11182
|
init_package_json();
|
|
10986
11183
|
import { constants } from "node:fs";
|
|
10987
11184
|
import { access as access2, mkdir as mkdir6, readFile as readFile4, writeFile as writeFile6 } from "node:fs/promises";
|
|
10988
|
-
import
|
|
11185
|
+
import path35 from "node:path";
|
|
10989
11186
|
import { glob as glob4 } from "glob";
|
|
10990
11187
|
var OPENAPI_GLOBS = [
|
|
10991
11188
|
"apis/openapi.json",
|
|
@@ -10995,9 +11192,9 @@ var OPENAPI_GLOBS = [
|
|
|
10995
11192
|
"openapi.yaml",
|
|
10996
11193
|
"openapi.yml"
|
|
10997
11194
|
];
|
|
10998
|
-
var toPosix = (p) => p.split(
|
|
11195
|
+
var toPosix = (p) => p.split(path35.sep).join("/");
|
|
10999
11196
|
var sanitizePackageName = (dir) => {
|
|
11000
|
-
const base =
|
|
11197
|
+
const base = path35.basename(path35.resolve(dir));
|
|
11001
11198
|
const s = base.toLowerCase().replace(/[^a-z0-9-_.]/g, "-").replace(/^-+|-+$/g, "");
|
|
11002
11199
|
return s || "apitogo-site";
|
|
11003
11200
|
};
|
|
@@ -11007,7 +11204,7 @@ var apitogoVersionRange = () => {
|
|
|
11007
11204
|
};
|
|
11008
11205
|
async function findOpenApiSpecPath(dir) {
|
|
11009
11206
|
for (const rel of OPENAPI_GLOBS) {
|
|
11010
|
-
const full =
|
|
11207
|
+
const full = path35.join(dir, rel);
|
|
11011
11208
|
try {
|
|
11012
11209
|
await access2(full, constants.R_OK);
|
|
11013
11210
|
return toPosix(rel);
|
|
@@ -11022,7 +11219,7 @@ async function findOpenApiSpecPath(dir) {
|
|
|
11022
11219
|
return extra[0] ? toPosix(extra[0]) : null;
|
|
11023
11220
|
}
|
|
11024
11221
|
async function ensurePackageJson(dir) {
|
|
11025
|
-
const pkgPath =
|
|
11222
|
+
const pkgPath = path35.join(dir, "package.json");
|
|
11026
11223
|
const apitogoVer = apitogoVersionRange();
|
|
11027
11224
|
const baseDeps = {
|
|
11028
11225
|
react: ">=19.0.0",
|
|
@@ -11089,7 +11286,7 @@ async function ensurePackageJson(dir) {
|
|
|
11089
11286
|
return false;
|
|
11090
11287
|
}
|
|
11091
11288
|
async function ensureTsconfigJson(dir) {
|
|
11092
|
-
const tsPath =
|
|
11289
|
+
const tsPath = path35.join(dir, "tsconfig.json");
|
|
11093
11290
|
try {
|
|
11094
11291
|
await access2(tsPath, constants.R_OK);
|
|
11095
11292
|
return false;
|
|
@@ -11179,19 +11376,19 @@ var fileExists2 = async (filePath) => {
|
|
|
11179
11376
|
}
|
|
11180
11377
|
};
|
|
11181
11378
|
async function ensurePortalStubFiles(dir) {
|
|
11182
|
-
const landingPath =
|
|
11379
|
+
const landingPath = path35.join(dir, "landing", "LandingPage.tsx");
|
|
11183
11380
|
if (!await fileExists2(landingPath)) {
|
|
11184
|
-
await mkdir6(
|
|
11381
|
+
await mkdir6(path35.join(dir, "landing"), { recursive: true });
|
|
11185
11382
|
await writeFile6(landingPath, LANDING_PAGE_SOURCE, "utf8");
|
|
11186
11383
|
}
|
|
11187
|
-
const plansPath =
|
|
11384
|
+
const plansPath = path35.join(dir, "user-panel", "AccountPlansPage.tsx");
|
|
11188
11385
|
if (!await fileExists2(plansPath)) {
|
|
11189
|
-
await mkdir6(
|
|
11386
|
+
await mkdir6(path35.join(dir, "user-panel"), { recursive: true });
|
|
11190
11387
|
await writeFile6(plansPath, ACCOUNT_PLANS_PAGE_SOURCE, "utf8");
|
|
11191
11388
|
}
|
|
11192
11389
|
}
|
|
11193
11390
|
async function ensureThinConfigTsx(dir) {
|
|
11194
|
-
const tsxPath =
|
|
11391
|
+
const tsxPath = path35.join(dir, "apitogo.config.tsx");
|
|
11195
11392
|
if (await fileExists2(tsxPath)) {
|
|
11196
11393
|
return false;
|
|
11197
11394
|
}
|
|
@@ -11200,7 +11397,7 @@ async function ensureThinConfigTsx(dir) {
|
|
|
11200
11397
|
}
|
|
11201
11398
|
|
|
11202
11399
|
// src/cli/make-config/handler.ts
|
|
11203
|
-
var toPosixPath2 = (value) => value.split(
|
|
11400
|
+
var toPosixPath2 = (value) => value.split(path36.sep).join(path36.posix.sep);
|
|
11204
11401
|
var fileExists3 = async (filePath) => {
|
|
11205
11402
|
try {
|
|
11206
11403
|
await access3(filePath, constants2.F_OK);
|
|
@@ -11218,7 +11415,7 @@ var readJsonConfig = async (filePath) => {
|
|
|
11218
11415
|
return parsed;
|
|
11219
11416
|
};
|
|
11220
11417
|
async function makeConfig(argv) {
|
|
11221
|
-
const dir =
|
|
11418
|
+
const dir = path36.resolve(process.cwd(), argv.dir);
|
|
11222
11419
|
const pagesDir = toPosixPath2(
|
|
11223
11420
|
argv.pagesDir.replace(/^[./]+/, "").replace(/\/+$/, "")
|
|
11224
11421
|
);
|
|
@@ -11235,14 +11432,14 @@ async function makeConfig(argv) {
|
|
|
11235
11432
|
printDiagnosticsToConsole("Created tsconfig.json.");
|
|
11236
11433
|
}
|
|
11237
11434
|
await ensurePortalStubFiles(dir);
|
|
11238
|
-
const jsonPath =
|
|
11435
|
+
const jsonPath = path36.join(dir, APITOGO_JSON_FILENAME);
|
|
11239
11436
|
let createdJson = false;
|
|
11240
11437
|
let config2;
|
|
11241
11438
|
if (await fileExists3(jsonPath)) {
|
|
11242
11439
|
config2 = await readJsonConfig(jsonPath);
|
|
11243
11440
|
} else {
|
|
11244
11441
|
config2 = createDefaultApitogoJsonConfig({
|
|
11245
|
-
title: titleFromDirectoryName(
|
|
11442
|
+
title: titleFromDirectoryName(path36.basename(dir)),
|
|
11246
11443
|
pagesDir
|
|
11247
11444
|
});
|
|
11248
11445
|
createdJson = true;
|
|
@@ -11259,27 +11456,27 @@ async function makeConfig(argv) {
|
|
|
11259
11456
|
title: argv.title
|
|
11260
11457
|
};
|
|
11261
11458
|
let openApiOverride;
|
|
11459
|
+
let interactiveHasPaidPlans = false;
|
|
11262
11460
|
if (argv.interactive) {
|
|
11263
11461
|
const site = isPlainObject2(config2.site) ? config2.site : {};
|
|
11264
|
-
const logo = isPlainObject2(site.logo) ? site.logo : {};
|
|
11265
|
-
const theme = isPlainObject2(config2.theme) ? config2.theme : {};
|
|
11266
|
-
const fonts = isPlainObject2(theme.fonts) ? theme.fonts : {};
|
|
11267
|
-
const light = isPlainObject2(theme.light) ? theme.light : {};
|
|
11268
|
-
const dark = isPlainObject2(theme.dark) ? theme.dark : {};
|
|
11269
|
-
const authentication = isPlainObject2(config2.authentication) ? config2.authentication : {};
|
|
11270
11462
|
const prompted = await promptMakeConfigInteractive({
|
|
11271
|
-
title: flagPatches.title ?? (typeof site.title === "string" ? site.title : titleFromDirectoryName(
|
|
11272
|
-
|
|
11273
|
-
|
|
11274
|
-
apiBaseUrl: typeof authentication.apiBaseUrl === "string" ? authentication.apiBaseUrl : void 0,
|
|
11275
|
-
sans: typeof fonts.sans === "string" ? fonts.sans : void 0,
|
|
11276
|
-
mono: typeof fonts.mono === "string" ? fonts.mono : void 0,
|
|
11277
|
-
lightPrimary: typeof light.primary === "string" ? light.primary : void 0,
|
|
11278
|
-
darkPrimary: typeof dark.primary === "string" ? dark.primary : void 0,
|
|
11279
|
-
discoveredOpenApi
|
|
11463
|
+
title: flagPatches.title ?? (typeof site.title === "string" ? site.title : titleFromDirectoryName(path36.basename(dir))),
|
|
11464
|
+
discoveredOpenApi,
|
|
11465
|
+
pagesDir
|
|
11280
11466
|
});
|
|
11281
11467
|
openApiOverride = prompted.openApiPath;
|
|
11468
|
+
interactiveHasPaidPlans = prompted.hasPaidPlans;
|
|
11282
11469
|
config2 = applyConfigPatches(config2, prompted);
|
|
11470
|
+
config2 = applyPlansToJsonConfig(config2, prompted.planItems);
|
|
11471
|
+
for (const page of prompted.customPages) {
|
|
11472
|
+
const pagePath = path36.join(dir, page.relativePath);
|
|
11473
|
+
await mkdir7(path36.dirname(pagePath), { recursive: true });
|
|
11474
|
+
await writeFile7(
|
|
11475
|
+
pagePath,
|
|
11476
|
+
buildStarterDocsPageTsx(page.slug, page.title),
|
|
11477
|
+
"utf8"
|
|
11478
|
+
);
|
|
11479
|
+
}
|
|
11283
11480
|
}
|
|
11284
11481
|
config2 = applyConfigPatches(config2, flagPatches);
|
|
11285
11482
|
const pageFiles = await glob5(`${pagesDir}/**/*.{md,mdx,tsx,jsx}`, {
|
|
@@ -11305,14 +11502,12 @@ async function makeConfig(argv) {
|
|
|
11305
11502
|
);
|
|
11306
11503
|
const openApiRel = openApiOverride === void 0 ? discoveredOpenApi : openApiOverride;
|
|
11307
11504
|
if (openApiRel) {
|
|
11308
|
-
|
|
11309
|
-
|
|
11310
|
-
openapiInputForConfig(openApiRel)
|
|
11311
|
-
);
|
|
11505
|
+
const openApiInput = argv.interactive ? toRelativeOpenApiInput(dir, openApiRel) : openapiInputForConfig(openApiRel);
|
|
11506
|
+
config2 = applyOpenApiToJsonConfig(config2, openApiInput);
|
|
11312
11507
|
}
|
|
11313
11508
|
await writeFile7(jsonPath, `${JSON.stringify(config2, null, 2)}
|
|
11314
11509
|
`, "utf8");
|
|
11315
|
-
const tsxPath =
|
|
11510
|
+
const tsxPath = path36.join(dir, "apitogo.config.tsx");
|
|
11316
11511
|
if (await fileExists3(tsxPath) && tsxRoutes.length > 0) {
|
|
11317
11512
|
const tsxSource = await readFile5(tsxPath, "utf8");
|
|
11318
11513
|
if (isThinConfigWrapper(tsxSource)) {
|
|
@@ -11325,13 +11520,16 @@ async function makeConfig(argv) {
|
|
|
11325
11520
|
}
|
|
11326
11521
|
const action = createdJson ? "Initialized" : "Updated";
|
|
11327
11522
|
printResultToConsole(
|
|
11328
|
-
`${action} ${APITOGO_JSON_FILENAME} (site/
|
|
11523
|
+
`${action} ${APITOGO_JSON_FILENAME} (site/auth/navigation/OpenAPI/plans as applicable; redirects unchanged).`
|
|
11329
11524
|
);
|
|
11330
11525
|
if (createdPackageJson) {
|
|
11331
11526
|
printDiagnosticsToConsole(
|
|
11332
11527
|
"Next: run npm install (or pnpm install / yarn) in this directory, then npm run dev."
|
|
11333
11528
|
);
|
|
11334
11529
|
}
|
|
11530
|
+
if (argv.interactive) {
|
|
11531
|
+
printInteractiveWrapUp(interactiveHasPaidPlans);
|
|
11532
|
+
}
|
|
11335
11533
|
} catch (error) {
|
|
11336
11534
|
await printCriticalFailureToConsoleAndExit(
|
|
11337
11535
|
error instanceof Error ? error.message : String(error)
|
|
@@ -11357,7 +11555,7 @@ var config_default = {
|
|
|
11357
11555
|
}).option("interactive", {
|
|
11358
11556
|
alias: "i",
|
|
11359
11557
|
type: "boolean",
|
|
11360
|
-
describe: "
|
|
11558
|
+
describe: "Interactive wizard: site title, OpenAPI path, custom pages, and gateway plans",
|
|
11361
11559
|
default: false
|
|
11362
11560
|
}).option("site", {
|
|
11363
11561
|
type: "string",
|
|
@@ -11411,14 +11609,14 @@ var deploy_default = {
|
|
|
11411
11609
|
|
|
11412
11610
|
// src/cli/dev/handler.ts
|
|
11413
11611
|
init_joinUrl();
|
|
11414
|
-
import
|
|
11612
|
+
import path39 from "node:path";
|
|
11415
11613
|
|
|
11416
11614
|
// src/vite/dev-server.ts
|
|
11417
11615
|
init_logger();
|
|
11418
11616
|
import fs4 from "node:fs/promises";
|
|
11419
11617
|
import http from "node:http";
|
|
11420
11618
|
import https from "node:https";
|
|
11421
|
-
import
|
|
11619
|
+
import path38 from "node:path";
|
|
11422
11620
|
import { createHttpTerminator } from "http-terminator";
|
|
11423
11621
|
import {
|
|
11424
11622
|
createServer as createViteServer,
|
|
@@ -11451,7 +11649,7 @@ init_loader();
|
|
|
11451
11649
|
// src/vite/pagefind-dev-index.ts
|
|
11452
11650
|
init_invariant();
|
|
11453
11651
|
init_joinUrl();
|
|
11454
|
-
import
|
|
11652
|
+
import path37 from "node:path";
|
|
11455
11653
|
import { createIndex as createIndex2 } from "pagefind";
|
|
11456
11654
|
import { isRunnableDevEnvironment } from "vite";
|
|
11457
11655
|
async function* buildPagefindDevIndex(vite, config2) {
|
|
@@ -11504,7 +11702,7 @@ async function* buildPagefindDevIndex(vite, config2) {
|
|
|
11504
11702
|
path: urlPath
|
|
11505
11703
|
};
|
|
11506
11704
|
}
|
|
11507
|
-
const outputPath =
|
|
11705
|
+
const outputPath = path37.join(vite.config.publicDir, "pagefind");
|
|
11508
11706
|
await pagefindIndex.writeFiles({ outputPath });
|
|
11509
11707
|
yield { type: "complete", success: true, indexed };
|
|
11510
11708
|
}
|
|
@@ -11523,9 +11721,9 @@ var DevServer = class {
|
|
|
11523
11721
|
this.protocol = "https";
|
|
11524
11722
|
const { dir } = this.options;
|
|
11525
11723
|
const [key, cert, ca] = await Promise.all([
|
|
11526
|
-
fs4.readFile(
|
|
11527
|
-
fs4.readFile(
|
|
11528
|
-
config2.https.ca ? fs4.readFile(
|
|
11724
|
+
fs4.readFile(path38.resolve(dir, config2.https.key)),
|
|
11725
|
+
fs4.readFile(path38.resolve(dir, config2.https.cert)),
|
|
11726
|
+
config2.https.ca ? fs4.readFile(path38.resolve(dir, config2.https.ca)) : void 0
|
|
11529
11727
|
]);
|
|
11530
11728
|
return https.createServer({ key, cert, ca });
|
|
11531
11729
|
}
|
|
@@ -11542,7 +11740,7 @@ var DevServer = class {
|
|
|
11542
11740
|
);
|
|
11543
11741
|
const server = await this.createNodeServer(config2);
|
|
11544
11742
|
if (config2.search?.type === "pagefind" && viteConfig.publicDir !== false) {
|
|
11545
|
-
const publicRoot =
|
|
11743
|
+
const publicRoot = path38.resolve(
|
|
11546
11744
|
this.options.dir,
|
|
11547
11745
|
typeof viteConfig.publicDir === "string" ? viteConfig.publicDir : "public"
|
|
11548
11746
|
);
|
|
@@ -11559,7 +11757,7 @@ var DevServer = class {
|
|
|
11559
11757
|
// built-in transform middleware which would treat the path as a static asset.
|
|
11560
11758
|
name: "apitogo:entry-client",
|
|
11561
11759
|
configureServer(server2) {
|
|
11562
|
-
const entryPath =
|
|
11760
|
+
const entryPath = path38.posix.join(
|
|
11563
11761
|
server2.config.base,
|
|
11564
11762
|
"/__z/entry.client.tsx"
|
|
11565
11763
|
);
|
|
@@ -11724,7 +11922,7 @@ init_package_json();
|
|
|
11724
11922
|
async function dev(argv) {
|
|
11725
11923
|
const packageJson2 = getZudokuPackageJson();
|
|
11726
11924
|
process.env.NODE_ENV = "development";
|
|
11727
|
-
const dir =
|
|
11925
|
+
const dir = path39.resolve(process.cwd(), argv.dir);
|
|
11728
11926
|
const server = new DevServer({
|
|
11729
11927
|
dir,
|
|
11730
11928
|
argPort: argv.port,
|
|
@@ -11807,9 +12005,9 @@ var dev_default = {
|
|
|
11807
12005
|
};
|
|
11808
12006
|
|
|
11809
12007
|
// src/cli/init/handler.ts
|
|
11810
|
-
import
|
|
12008
|
+
import path40 from "node:path";
|
|
11811
12009
|
async function init2(argv) {
|
|
11812
|
-
const dir =
|
|
12010
|
+
const dir = path40.resolve(process.cwd(), argv.dir ?? ".");
|
|
11813
12011
|
try {
|
|
11814
12012
|
const createdPackageJson = await ensurePackageJson(dir);
|
|
11815
12013
|
const createdTsconfig = await ensureTsconfigJson(dir);
|
|
@@ -11881,12 +12079,12 @@ var remove_default = {
|
|
|
11881
12079
|
};
|
|
11882
12080
|
|
|
11883
12081
|
// src/cli/status/handler.ts
|
|
11884
|
-
import
|
|
12082
|
+
import path42 from "node:path";
|
|
11885
12083
|
|
|
11886
12084
|
// src/cli/common/mcp-cli.ts
|
|
11887
12085
|
import { access as access4 } from "node:fs/promises";
|
|
11888
12086
|
import { spawn as spawn2 } from "node:child_process";
|
|
11889
|
-
import
|
|
12087
|
+
import path41 from "node:path";
|
|
11890
12088
|
async function pathExists2(candidate) {
|
|
11891
12089
|
try {
|
|
11892
12090
|
await access4(candidate);
|
|
@@ -11899,7 +12097,7 @@ async function resolveApitogoMcpCliCommand(binary) {
|
|
|
11899
12097
|
const binName = `apitogo-${binary}`;
|
|
11900
12098
|
const mcpPath = process.env.APITOGO_MCP_PATH?.trim();
|
|
11901
12099
|
if (mcpPath) {
|
|
11902
|
-
const scriptJs =
|
|
12100
|
+
const scriptJs = path41.join(mcpPath, "dist", "cli", `${binary}.js`);
|
|
11903
12101
|
if (await pathExists2(scriptJs)) {
|
|
11904
12102
|
return {
|
|
11905
12103
|
command: process.execPath,
|
|
@@ -11957,7 +12155,7 @@ async function runApitogoMcpCli(binary, childArgs, options = {}) {
|
|
|
11957
12155
|
|
|
11958
12156
|
// src/cli/status/handler.ts
|
|
11959
12157
|
async function status(argv) {
|
|
11960
|
-
const dir =
|
|
12158
|
+
const dir = path42.resolve(process.cwd(), argv.dir);
|
|
11961
12159
|
const args = [dir];
|
|
11962
12160
|
if (argv.projectId?.trim()) {
|
|
11963
12161
|
args.push("--project-id", argv.projectId.trim());
|
|
@@ -11999,7 +12197,7 @@ var status_default = {
|
|
|
11999
12197
|
};
|
|
12000
12198
|
|
|
12001
12199
|
// src/cli/teardown/handler.ts
|
|
12002
|
-
import
|
|
12200
|
+
import path43 from "node:path";
|
|
12003
12201
|
async function teardown(argv) {
|
|
12004
12202
|
if (!argv.yes) {
|
|
12005
12203
|
await printCriticalFailureToConsoleAndExit(
|
|
@@ -12007,7 +12205,7 @@ async function teardown(argv) {
|
|
|
12007
12205
|
);
|
|
12008
12206
|
return;
|
|
12009
12207
|
}
|
|
12010
|
-
const dir =
|
|
12208
|
+
const dir = path43.resolve(process.cwd(), argv.dir);
|
|
12011
12209
|
const args = [dir, "--yes"];
|
|
12012
12210
|
if (argv.projectId?.trim()) {
|
|
12013
12211
|
args.push("--project-id", argv.projectId.trim());
|
|
@@ -12122,12 +12320,12 @@ function box(message, {
|
|
|
12122
12320
|
|
|
12123
12321
|
// src/cli/common/xdg/lib.ts
|
|
12124
12322
|
import { homedir } from "node:os";
|
|
12125
|
-
import
|
|
12323
|
+
import path44 from "node:path";
|
|
12126
12324
|
function defineDirectoryWithFallback(xdgName, fallback) {
|
|
12127
12325
|
if (process.env[xdgName]) {
|
|
12128
12326
|
return process.env[xdgName];
|
|
12129
12327
|
} else {
|
|
12130
|
-
return
|
|
12328
|
+
return path44.join(homedir(), fallback);
|
|
12131
12329
|
}
|
|
12132
12330
|
}
|
|
12133
12331
|
var XDG_CONFIG_HOME = defineDirectoryWithFallback(
|
|
@@ -12142,15 +12340,15 @@ var XDG_STATE_HOME = defineDirectoryWithFallback(
|
|
|
12142
12340
|
"XDG_DATA_HOME",
|
|
12143
12341
|
".local/state"
|
|
12144
12342
|
);
|
|
12145
|
-
var ZUDOKU_XDG_CONFIG_HOME =
|
|
12343
|
+
var ZUDOKU_XDG_CONFIG_HOME = path44.join(
|
|
12146
12344
|
XDG_CONFIG_HOME,
|
|
12147
12345
|
CLI_XDG_FOLDER_NAME
|
|
12148
12346
|
);
|
|
12149
|
-
var ZUDOKU_XDG_DATA_HOME =
|
|
12347
|
+
var ZUDOKU_XDG_DATA_HOME = path44.join(
|
|
12150
12348
|
XDG_DATA_HOME,
|
|
12151
12349
|
CLI_XDG_FOLDER_NAME
|
|
12152
12350
|
);
|
|
12153
|
-
var ZUDOKU_XDG_STATE_HOME =
|
|
12351
|
+
var ZUDOKU_XDG_STATE_HOME = path44.join(
|
|
12154
12352
|
XDG_STATE_HOME,
|
|
12155
12353
|
CLI_XDG_FOLDER_NAME
|
|
12156
12354
|
);
|