@lukoweb/apitogo 0.1.77 → 0.1.79
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 +1674 -1624
- 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/configuration/authentication.md +4 -3
- package/docs/configuration/make-config.mdx +58 -18
- 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 +10 -138
- package/docs/deployment.md +6 -20
- package/docs/guides/custom-pages.md +8 -0
- package/docs/guides/environment-variables.md +4 -3
- package/docs/mcp/go-live.md +2 -2
- 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
|
|
|
@@ -5214,7 +5214,6 @@ var VERSION_CHECK_FILE = "version.json";
|
|
|
5214
5214
|
var SENTRY_DSN = void 0;
|
|
5215
5215
|
var MAX_WAIT_PENDING_TIME_MS = 1e3;
|
|
5216
5216
|
var POST_HOG_CAPTURE_KEY = void 0;
|
|
5217
|
-
var DEPLOY_SERVER_API_KEY = "qRVLTP22TFStdN6";
|
|
5218
5217
|
|
|
5219
5218
|
// src/cli/common/machine-id/lib.ts
|
|
5220
5219
|
import { execSync } from "node:child_process";
|
|
@@ -5338,13 +5337,6 @@ function printJsonOnlyErrorAndExit(message) {
|
|
|
5338
5337
|
function printResultToConsole(message) {
|
|
5339
5338
|
console.log(colors.bold(colors.green(message)));
|
|
5340
5339
|
}
|
|
5341
|
-
function textOrJson(text) {
|
|
5342
|
-
try {
|
|
5343
|
-
return JSON.parse(text);
|
|
5344
|
-
} catch {
|
|
5345
|
-
return text;
|
|
5346
|
-
}
|
|
5347
|
-
}
|
|
5348
5340
|
|
|
5349
5341
|
// src/cli/apply/handler.ts
|
|
5350
5342
|
async function pathExists(candidate) {
|
|
@@ -5376,6 +5368,11 @@ async function resolveApitogoApplyCommand() {
|
|
|
5376
5368
|
note: "Using npx @lukoweb/apitogo-mcp (set APITOGO_MCP_PATH for a local checkout)"
|
|
5377
5369
|
};
|
|
5378
5370
|
}
|
|
5371
|
+
function normalizeOnly(only) {
|
|
5372
|
+
if (!only) return [];
|
|
5373
|
+
const values = Array.isArray(only) ? only : [only];
|
|
5374
|
+
return values.flatMap((value) => value.split(",")).map((value) => value.trim()).filter(Boolean);
|
|
5375
|
+
}
|
|
5379
5376
|
function buildApplyArgs(argv) {
|
|
5380
5377
|
const dir = path.resolve(process.cwd(), argv.dir);
|
|
5381
5378
|
const args = [dir];
|
|
@@ -5388,14 +5385,11 @@ function buildApplyArgs(argv) {
|
|
|
5388
5385
|
if (argv.platformPlan?.trim()) {
|
|
5389
5386
|
args.push("--platform-plan", argv.platformPlan.trim());
|
|
5390
5387
|
}
|
|
5391
|
-
|
|
5392
|
-
args.push("--
|
|
5393
|
-
}
|
|
5394
|
-
if (argv.forceBackendRedeploy) {
|
|
5395
|
-
args.push("--force-backend-redeploy");
|
|
5388
|
+
for (const resource of normalizeOnly(argv.only)) {
|
|
5389
|
+
args.push("--only", resource);
|
|
5396
5390
|
}
|
|
5397
|
-
if (argv.
|
|
5398
|
-
args.push("--force
|
|
5391
|
+
if (argv.force) {
|
|
5392
|
+
args.push("--force");
|
|
5399
5393
|
}
|
|
5400
5394
|
if (argv.resumeFrom?.trim()) {
|
|
5401
5395
|
args.push("--resume-from", argv.resumeFrom.trim());
|
|
@@ -5413,7 +5407,7 @@ async function apply(argv) {
|
|
|
5413
5407
|
try {
|
|
5414
5408
|
resolved = await resolveApitogoApplyCommand();
|
|
5415
5409
|
} catch (error) {
|
|
5416
|
-
printCriticalFailureToConsoleAndExit(
|
|
5410
|
+
await printCriticalFailureToConsoleAndExit(
|
|
5417
5411
|
error instanceof Error ? error.message : String(error)
|
|
5418
5412
|
);
|
|
5419
5413
|
return;
|
|
@@ -5429,7 +5423,7 @@ async function apply(argv) {
|
|
|
5429
5423
|
shell: process.platform === "win32"
|
|
5430
5424
|
});
|
|
5431
5425
|
child.on("error", (error) => {
|
|
5432
|
-
printCriticalFailureToConsoleAndExit(
|
|
5426
|
+
void printCriticalFailureToConsoleAndExit(
|
|
5433
5427
|
`Failed to start apitogo-apply: ${error.message}`
|
|
5434
5428
|
);
|
|
5435
5429
|
resolvePromise(1);
|
|
@@ -5445,7 +5439,7 @@ async function apply(argv) {
|
|
|
5445
5439
|
|
|
5446
5440
|
// src/cli/cmds/apply.ts
|
|
5447
5441
|
var apply_default = {
|
|
5448
|
-
desc: "Apply apitogo.config.json to the APItoGo platform (
|
|
5442
|
+
desc: "Apply apitogo.config.json to the APItoGo platform (apihub, portal backend, portal frontend)",
|
|
5449
5443
|
command: "apply",
|
|
5450
5444
|
builder: (yargs2) => yargs2.option("dir", {
|
|
5451
5445
|
type: "string",
|
|
@@ -5462,17 +5456,12 @@ var apply_default = {
|
|
|
5462
5456
|
type: "string",
|
|
5463
5457
|
describe: "Platform hosting tier",
|
|
5464
5458
|
choices: ["free", "starter", "professional"]
|
|
5465
|
-
}).option("
|
|
5466
|
-
type: "
|
|
5467
|
-
describe: "
|
|
5468
|
-
|
|
5469
|
-
}).option("force-backend-redeploy", {
|
|
5470
|
-
type: "boolean",
|
|
5471
|
-
describe: "Force backend package + deploy",
|
|
5472
|
-
default: false
|
|
5473
|
-
}).option("force-site-redeploy", {
|
|
5459
|
+
}).option("only", {
|
|
5460
|
+
type: "string",
|
|
5461
|
+
describe: "Limit to resources: apihub, portal-backend, portal-frontend (comma-separated, repeatable)"
|
|
5462
|
+
}).option("force", {
|
|
5474
5463
|
type: "boolean",
|
|
5475
|
-
describe: "Force
|
|
5464
|
+
describe: "Force redeploy of selected resources even when healthy",
|
|
5476
5465
|
default: false
|
|
5477
5466
|
}).option("resume-from", {
|
|
5478
5467
|
type: "string",
|
|
@@ -5644,7 +5633,7 @@ import {
|
|
|
5644
5633
|
// package.json
|
|
5645
5634
|
var package_default = {
|
|
5646
5635
|
name: "@lukoweb/apitogo",
|
|
5647
|
-
version: "0.1.
|
|
5636
|
+
version: "0.1.79",
|
|
5648
5637
|
type: "module",
|
|
5649
5638
|
sideEffects: [
|
|
5650
5639
|
"**/*.css",
|
|
@@ -6413,14 +6402,14 @@ var flattenAllOf = (schema2) => {
|
|
|
6413
6402
|
};
|
|
6414
6403
|
|
|
6415
6404
|
// src/lib/util/traverse.ts
|
|
6416
|
-
var traverse = (specification, transform,
|
|
6417
|
-
const transformed = transform(specification,
|
|
6405
|
+
var traverse = (specification, transform, path45 = []) => {
|
|
6406
|
+
const transformed = transform(specification, path45);
|
|
6418
6407
|
if (typeof transformed !== "object" || transformed === null) {
|
|
6419
6408
|
return transformed;
|
|
6420
6409
|
}
|
|
6421
6410
|
const result = Array.isArray(transformed) ? [] : {};
|
|
6422
6411
|
for (const [key, value] of Object.entries(transformed)) {
|
|
6423
|
-
const currentPath = [...
|
|
6412
|
+
const currentPath = [...path45, key];
|
|
6424
6413
|
if (Array.isArray(value)) {
|
|
6425
6414
|
result[key] = value.map(
|
|
6426
6415
|
(item, index) => typeof item === "object" && item != null ? traverse(item, transform, [...currentPath, index.toString()]) : item
|
|
@@ -6448,9 +6437,9 @@ var resolveLocalRef = (schema2, ref) => {
|
|
|
6448
6437
|
if (schemaCache?.has(ref)) {
|
|
6449
6438
|
return schemaCache.get(ref);
|
|
6450
6439
|
}
|
|
6451
|
-
const
|
|
6440
|
+
const path45 = ref.split("/").slice(1);
|
|
6452
6441
|
let current = schema2;
|
|
6453
|
-
for (const segment of
|
|
6442
|
+
for (const segment of path45) {
|
|
6454
6443
|
if (!current || typeof current !== "object") {
|
|
6455
6444
|
current = null;
|
|
6456
6445
|
}
|
|
@@ -6469,7 +6458,7 @@ var dereference = async (schema2, resolvers = []) => {
|
|
|
6469
6458
|
}
|
|
6470
6459
|
const cloned = structuredClone(schema2);
|
|
6471
6460
|
const visited = /* @__PURE__ */ new Set();
|
|
6472
|
-
const resolve = async (current,
|
|
6461
|
+
const resolve = async (current, path45) => {
|
|
6473
6462
|
if (isIndexableObject(current)) {
|
|
6474
6463
|
if (visited.has(current)) {
|
|
6475
6464
|
return CIRCULAR_REF;
|
|
@@ -6477,7 +6466,7 @@ var dereference = async (schema2, resolvers = []) => {
|
|
|
6477
6466
|
visited.add(current);
|
|
6478
6467
|
if (Array.isArray(current)) {
|
|
6479
6468
|
for (let index = 0; index < current.length; index++) {
|
|
6480
|
-
current[index] = await resolve(current[index], `${
|
|
6469
|
+
current[index] = await resolve(current[index], `${path45}/${index}`);
|
|
6481
6470
|
}
|
|
6482
6471
|
} else {
|
|
6483
6472
|
if ("$ref" in current && typeof current.$ref === "string") {
|
|
@@ -6488,13 +6477,13 @@ var dereference = async (schema2, resolvers = []) => {
|
|
|
6488
6477
|
for (const resolver of resolvers) {
|
|
6489
6478
|
const resolved = await resolver($ref);
|
|
6490
6479
|
if (resolved) {
|
|
6491
|
-
result2 = await resolve(resolved,
|
|
6480
|
+
result2 = await resolve(resolved, path45);
|
|
6492
6481
|
break;
|
|
6493
6482
|
}
|
|
6494
6483
|
}
|
|
6495
6484
|
if (result2 === void 0) {
|
|
6496
6485
|
const resolved = await resolveLocalRef(cloned, $ref);
|
|
6497
|
-
result2 = await resolve(resolved,
|
|
6486
|
+
result2 = await resolve(resolved, path45);
|
|
6498
6487
|
}
|
|
6499
6488
|
if (hasSiblings) {
|
|
6500
6489
|
if (result2 === CIRCULAR_REF) {
|
|
@@ -6507,7 +6496,7 @@ var dereference = async (schema2, resolvers = []) => {
|
|
|
6507
6496
|
return result2;
|
|
6508
6497
|
}
|
|
6509
6498
|
for (const key in current) {
|
|
6510
|
-
current[key] = await resolve(current[key], `${
|
|
6499
|
+
current[key] = await resolve(current[key], `${path45}/${key}`);
|
|
6511
6500
|
}
|
|
6512
6501
|
}
|
|
6513
6502
|
visited.delete(current);
|
|
@@ -6546,9 +6535,9 @@ var upgradeSchema = (schema2) => {
|
|
|
6546
6535
|
}
|
|
6547
6536
|
return sub;
|
|
6548
6537
|
});
|
|
6549
|
-
schema2 = traverse(schema2, (sub,
|
|
6538
|
+
schema2 = traverse(schema2, (sub, path45) => {
|
|
6550
6539
|
if (sub.example !== void 0) {
|
|
6551
|
-
if (isSchemaPath(
|
|
6540
|
+
if (isSchemaPath(path45 ?? [])) {
|
|
6552
6541
|
sub.examples = [sub.example];
|
|
6553
6542
|
} else {
|
|
6554
6543
|
sub.examples = {
|
|
@@ -6561,11 +6550,11 @@ var upgradeSchema = (schema2) => {
|
|
|
6561
6550
|
}
|
|
6562
6551
|
return sub;
|
|
6563
6552
|
});
|
|
6564
|
-
schema2 = traverse(schema2, (schema3,
|
|
6553
|
+
schema2 = traverse(schema2, (schema3, path45) => {
|
|
6565
6554
|
if (schema3.type === "object" && schema3.properties !== void 0) {
|
|
6566
|
-
const parentPath =
|
|
6555
|
+
const parentPath = path45?.slice(0, -1);
|
|
6567
6556
|
const isMultipart = parentPath?.some((segment, index) => {
|
|
6568
|
-
return segment === "content" &&
|
|
6557
|
+
return segment === "content" && path45?.[index + 1] === "multipart/form-data";
|
|
6569
6558
|
});
|
|
6570
6559
|
if (isMultipart) {
|
|
6571
6560
|
const entries = Object.entries(schema3.properties);
|
|
@@ -6579,8 +6568,8 @@ var upgradeSchema = (schema2) => {
|
|
|
6579
6568
|
}
|
|
6580
6569
|
return schema3;
|
|
6581
6570
|
});
|
|
6582
|
-
schema2 = traverse(schema2, (schema3,
|
|
6583
|
-
if (
|
|
6571
|
+
schema2 = traverse(schema2, (schema3, path45) => {
|
|
6572
|
+
if (path45?.includes("content") && path45.includes("application/octet-stream")) {
|
|
6584
6573
|
return {};
|
|
6585
6574
|
}
|
|
6586
6575
|
if (schema3.type === "string" && schema3.format === "binary") {
|
|
@@ -6606,11 +6595,11 @@ var upgradeSchema = (schema2) => {
|
|
|
6606
6595
|
}
|
|
6607
6596
|
return sub;
|
|
6608
6597
|
});
|
|
6609
|
-
schema2 = traverse(schema2, (schema3,
|
|
6598
|
+
schema2 = traverse(schema2, (schema3, path45) => {
|
|
6610
6599
|
if (schema3.type === "string" && schema3.format === "byte") {
|
|
6611
|
-
const parentPath =
|
|
6600
|
+
const parentPath = path45?.slice(0, -1);
|
|
6612
6601
|
const contentMediaType = parentPath?.find(
|
|
6613
|
-
(_, index) =>
|
|
6602
|
+
(_, index) => path45?.[index - 1] === "content"
|
|
6614
6603
|
);
|
|
6615
6604
|
return {
|
|
6616
6605
|
type: "string",
|
|
@@ -6622,7 +6611,7 @@ var upgradeSchema = (schema2) => {
|
|
|
6622
6611
|
});
|
|
6623
6612
|
return schema2;
|
|
6624
6613
|
};
|
|
6625
|
-
function isSchemaPath(
|
|
6614
|
+
function isSchemaPath(path45) {
|
|
6626
6615
|
const schemaLocations = [
|
|
6627
6616
|
["components", "schemas"],
|
|
6628
6617
|
"properties",
|
|
@@ -6635,10 +6624,10 @@ function isSchemaPath(path41) {
|
|
|
6635
6624
|
];
|
|
6636
6625
|
return schemaLocations.some((location) => {
|
|
6637
6626
|
if (Array.isArray(location)) {
|
|
6638
|
-
return location.every((segment, index) =>
|
|
6627
|
+
return location.every((segment, index) => path45[index] === segment);
|
|
6639
6628
|
}
|
|
6640
|
-
return
|
|
6641
|
-
}) ||
|
|
6629
|
+
return path45.includes(location);
|
|
6630
|
+
}) || path45.includes("schema") || path45.some((segment) => segment.endsWith("Schema"));
|
|
6642
6631
|
}
|
|
6643
6632
|
|
|
6644
6633
|
// src/lib/oas/parser/index.ts
|
|
@@ -6720,13 +6709,13 @@ var OPENAPI_PROPS = /* @__PURE__ */ new Set([
|
|
|
6720
6709
|
"anyOf",
|
|
6721
6710
|
"oneOf"
|
|
6722
6711
|
]);
|
|
6723
|
-
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()) => {
|
|
6724
6713
|
if (obj === null || typeof obj !== "object") return obj;
|
|
6725
6714
|
const refPath = obj.__$ref;
|
|
6726
6715
|
const isCircular = currentPath.has(obj) || typeof refPath === "string" && currentRefPaths.has(refPath);
|
|
6727
6716
|
if (isCircular) {
|
|
6728
6717
|
if (typeof refPath === "string") return SCHEMA_REF_PREFIX + refPath;
|
|
6729
|
-
const circularProp =
|
|
6718
|
+
const circularProp = path45.find((p) => !OPENAPI_PROPS.has(p)) || path45[0];
|
|
6730
6719
|
return [CIRCULAR_REF, circularProp].filter(Boolean).join(":");
|
|
6731
6720
|
}
|
|
6732
6721
|
if (refs.has(obj)) return refs.get(obj);
|
|
@@ -6736,7 +6725,7 @@ var handleCircularRefs = (obj, currentPath = /* @__PURE__ */ new WeakSet(), refs
|
|
|
6736
6725
|
value,
|
|
6737
6726
|
currentPath,
|
|
6738
6727
|
refs,
|
|
6739
|
-
[...
|
|
6728
|
+
[...path45, key],
|
|
6740
6729
|
currentRefPaths
|
|
6741
6730
|
);
|
|
6742
6731
|
const result = Array.isArray(obj) ? obj.map((item, i) => recurse(item, i.toString())) : Object.fromEntries(
|
|
@@ -6771,7 +6760,7 @@ var resolveExtensions = (obj) => Object.fromEntries(
|
|
|
6771
6760
|
var getAllTags = (schema2) => {
|
|
6772
6761
|
const rootTags = schema2.tags ?? [];
|
|
6773
6762
|
const operations = Object.values(schema2.paths ?? {}).flatMap(
|
|
6774
|
-
(
|
|
6763
|
+
(path45) => HttpMethods.map((k) => path45?.[k]).filter((op) => op != null)
|
|
6775
6764
|
);
|
|
6776
6765
|
const operationTags = new Set(operations.flatMap((op) => op.tags ?? []));
|
|
6777
6766
|
const hasUntaggedOperations = operations.some(
|
|
@@ -6826,7 +6815,7 @@ var getAllSlugs = (ops, schemaTags = []) => {
|
|
|
6826
6815
|
var getOperationSlugKey = (op) => [op.path, op.method, op.operationId, op.summary].filter(Boolean).join("-");
|
|
6827
6816
|
var getAllOperations = (paths) => {
|
|
6828
6817
|
const operations = Object.entries(paths ?? {}).flatMap(
|
|
6829
|
-
([
|
|
6818
|
+
([path45, value]) => HttpMethods.flatMap((method) => {
|
|
6830
6819
|
if (!value?.[method]) return [];
|
|
6831
6820
|
const operation = value[method];
|
|
6832
6821
|
const pathParameters = value.parameters ?? [];
|
|
@@ -6846,7 +6835,7 @@ var getAllOperations = (paths) => {
|
|
|
6846
6835
|
return {
|
|
6847
6836
|
...operation,
|
|
6848
6837
|
method,
|
|
6849
|
-
path:
|
|
6838
|
+
path: path45,
|
|
6850
6839
|
parameters,
|
|
6851
6840
|
servers,
|
|
6852
6841
|
tags: operation.tags ?? []
|
|
@@ -7204,8 +7193,8 @@ var Schema = builder.objectRef("Schema").implement({
|
|
|
7204
7193
|
}),
|
|
7205
7194
|
paths: t.field({
|
|
7206
7195
|
type: [PathItem],
|
|
7207
|
-
resolve: (root) => Object.entries(root.paths ?? {}).map(([
|
|
7208
|
-
path:
|
|
7196
|
+
resolve: (root) => Object.entries(root.paths ?? {}).map(([path45, value]) => ({
|
|
7197
|
+
path: path45,
|
|
7209
7198
|
// biome-ignore lint/style/noNonNullAssertion: value is guaranteed to be defined
|
|
7210
7199
|
methods: Object.keys(value)
|
|
7211
7200
|
}))
|
|
@@ -7370,7 +7359,7 @@ init_joinUrl();
|
|
|
7370
7359
|
|
|
7371
7360
|
// src/vite/api/schema-codegen.ts
|
|
7372
7361
|
var unescapeJsonPointer = (uri) => decodeURIComponent(uri.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
7373
|
-
var getSegmentsFromPath = (
|
|
7362
|
+
var getSegmentsFromPath = (path45) => path45.split("/").slice(1).map(unescapeJsonPointer);
|
|
7374
7363
|
var createLocalRefMap = (obj) => {
|
|
7375
7364
|
const refMap = /* @__PURE__ */ new Map();
|
|
7376
7365
|
const siblingsMap = /* @__PURE__ */ new Map();
|
|
@@ -7401,16 +7390,16 @@ var replaceMarkers = (code, mergedRefs) => code.replace(/"__refMap:(.*?)"/g, '__
|
|
|
7401
7390
|
/"__refMap\+Siblings:(.*?)"/g,
|
|
7402
7391
|
(_, key) => mergedRefs.get(key) ?? `__refMap["${key}"]`
|
|
7403
7392
|
);
|
|
7404
|
-
var lookup = (schema2,
|
|
7405
|
-
const parts = getSegmentsFromPath(
|
|
7393
|
+
var lookup = (schema2, path45, filePath) => {
|
|
7394
|
+
const parts = getSegmentsFromPath(path45);
|
|
7406
7395
|
let val = schema2;
|
|
7407
7396
|
for (const part of parts) {
|
|
7408
7397
|
while (val.$ref?.startsWith("#/")) {
|
|
7409
|
-
val = val.$ref ===
|
|
7398
|
+
val = val.$ref === path45 ? val : lookup(schema2, val.$ref, filePath);
|
|
7410
7399
|
}
|
|
7411
7400
|
if (val[part] === void 0) {
|
|
7412
7401
|
throw new Error(
|
|
7413
|
-
`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}`
|
|
7414
7403
|
);
|
|
7415
7404
|
}
|
|
7416
7405
|
val = val[part];
|
|
@@ -7655,8 +7644,8 @@ var SchemaManager = class {
|
|
|
7655
7644
|
}
|
|
7656
7645
|
}
|
|
7657
7646
|
};
|
|
7658
|
-
getLatestSchema = (
|
|
7659
|
-
getSchemasForPath = (
|
|
7647
|
+
getLatestSchema = (path45) => this.processedSchemas[path45]?.at(0);
|
|
7648
|
+
getSchemasForPath = (path45) => this.processedSchemas[path45];
|
|
7660
7649
|
getSchemaImports = () => Object.values(this.processedSchemas).flat().filter((s) => s.importKey);
|
|
7661
7650
|
getUrlToFilePathMap = () => {
|
|
7662
7651
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -10057,14 +10046,14 @@ async function generateSitemap({
|
|
|
10057
10046
|
|
|
10058
10047
|
// src/vite/prerender/utils.ts
|
|
10059
10048
|
init_joinUrl();
|
|
10060
|
-
var resolveRoutePath = (
|
|
10061
|
-
const segments =
|
|
10049
|
+
var resolveRoutePath = (path45) => {
|
|
10050
|
+
const segments = path45.split("/");
|
|
10062
10051
|
if (segments.some((s) => s.startsWith(":") && !s.endsWith("?"))) {
|
|
10063
10052
|
return void 0;
|
|
10064
10053
|
}
|
|
10065
10054
|
return segments.filter((s) => !s.startsWith(":")).join("/") || void 0;
|
|
10066
10055
|
};
|
|
10067
|
-
var isSkipped = (
|
|
10056
|
+
var isSkipped = (path45) => path45.includes("*") || /^\d+$/.test(path45);
|
|
10068
10057
|
var resolveRoutes = (routes, parentPath = "") => routes.flatMap((route) => {
|
|
10069
10058
|
if (route.path && isSkipped(route.path)) return [];
|
|
10070
10059
|
const routePath = route.path ? resolveRoutePath(route.path) : void 0;
|
|
@@ -10527,1553 +10516,1523 @@ var build_default = {
|
|
|
10527
10516
|
}
|
|
10528
10517
|
};
|
|
10529
10518
|
|
|
10530
|
-
// src/cli/
|
|
10531
|
-
import { constants } from "node:fs";
|
|
10532
|
-
import { access as
|
|
10533
|
-
import
|
|
10534
|
-
|
|
10519
|
+
// src/cli/make-config/handler.ts
|
|
10520
|
+
import { constants as constants2 } from "node:fs";
|
|
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
|
+
import { glob as glob5 } from "glob";
|
|
10535
10524
|
|
|
10536
|
-
|
|
10537
|
-
|
|
10538
|
-
|
|
10539
|
-
|
|
10540
|
-
|
|
10541
|
-
|
|
10542
|
-
|
|
10543
|
-
|
|
10544
|
-
|
|
10545
|
-
|
|
10546
|
-
|
|
10547
|
-
|
|
10548
|
-
|
|
10549
|
-
|
|
10550
|
-
|
|
10551
|
-
|
|
10552
|
-
|
|
10553
|
-
|
|
10554
|
-
|
|
10555
|
-
|
|
10556
|
-
|
|
10557
|
-
|
|
10558
|
-
|
|
10559
|
-
- name: Setup Node.js
|
|
10560
|
-
uses: actions/setup-node@v4
|
|
10561
|
-
with:
|
|
10562
|
-
node-version: 20
|
|
10563
|
-
cache: npm
|
|
10564
|
-
|
|
10565
|
-
- name: Install dependencies
|
|
10566
|
-
run: npm ci
|
|
10567
|
-
|
|
10568
|
-
- name: Install APIToGo CLI
|
|
10569
|
-
run: npm install -g @lukoweb/apitogo@latest
|
|
10570
|
-
|
|
10571
|
-
- name: Check APIToGo version
|
|
10572
|
-
run: apitogo --version
|
|
10573
|
-
|
|
10574
|
-
- name: Deploy preview
|
|
10575
|
-
id: deploy
|
|
10576
|
-
env:
|
|
10577
|
-
APITOGO_TOKEN: \${{ secrets.APITOGO_TOKEN }}
|
|
10578
|
-
shell: bash
|
|
10579
|
-
run: |
|
|
10580
|
-
ENV_NAME=preview-pr-\${{ github.event.pull_request.number }}
|
|
10581
|
-
|
|
10582
|
-
OUTPUT=$(apitogo deploy --deployment-token="$APITOGO_TOKEN" --env=$ENV_NAME --json-only)
|
|
10583
|
-
|
|
10584
|
-
echo "$OUTPUT"
|
|
10585
|
-
|
|
10586
|
-
URL=$(echo "$OUTPUT" | jq -r '.url')
|
|
10587
|
-
|
|
10588
|
-
if [ -z "$URL" ] || [ "$URL" = "null" ]; then
|
|
10589
|
-
echo "Failed to extract preview URL"
|
|
10590
|
-
exit 1
|
|
10591
|
-
fi
|
|
10592
|
-
|
|
10593
|
-
echo "url=$URL" >> "$GITHUB_OUTPUT"
|
|
10594
|
-
|
|
10595
|
-
cleanup-preview:
|
|
10596
|
-
if: github.event_name == 'pull_request' && github.event.action == 'closed'
|
|
10597
|
-
runs-on: ubuntu-latest
|
|
10598
|
-
|
|
10599
|
-
steps:
|
|
10600
|
-
- name: Install APIToGo CLI
|
|
10601
|
-
run: npm install -g @lukoweb/apitogo@latest
|
|
10602
|
-
|
|
10603
|
-
- name: Remove preview deployment
|
|
10604
|
-
env:
|
|
10605
|
-
APITOGO_TOKEN: \${{ secrets.APITOGO_TOKEN }}
|
|
10606
|
-
shell: bash
|
|
10607
|
-
run: |
|
|
10608
|
-
ENV_NAME=preview-pr-\${{ github.event.pull_request.number }}
|
|
10609
|
-
|
|
10610
|
-
apitogo remove --deployment-token="$APITOGO_TOKEN" --env=$ENV_NAME --json-only
|
|
10611
|
-
|
|
10612
|
-
production:
|
|
10613
|
-
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
10614
|
-
runs-on: ubuntu-latest
|
|
10615
|
-
|
|
10616
|
-
environment:
|
|
10617
|
-
name: production
|
|
10618
|
-
|
|
10619
|
-
steps:
|
|
10620
|
-
- name: Checkout repository
|
|
10621
|
-
uses: actions/checkout@v4
|
|
10622
|
-
|
|
10623
|
-
- name: Setup Node.js
|
|
10624
|
-
uses: actions/setup-node@v4
|
|
10625
|
-
with:
|
|
10626
|
-
node-version: 20
|
|
10627
|
-
cache: npm
|
|
10628
|
-
|
|
10629
|
-
- name: Install dependencies
|
|
10630
|
-
run: npm ci
|
|
10631
|
-
|
|
10632
|
-
- name: Install APIToGo CLI
|
|
10633
|
-
run: npm install -g @lukoweb/apitogo@latest
|
|
10634
|
-
|
|
10635
|
-
- name: Check APIToGo version
|
|
10636
|
-
run: apitogo --version
|
|
10637
|
-
|
|
10638
|
-
- name: Deploy production
|
|
10639
|
-
env:
|
|
10640
|
-
APITOGO_TOKEN: \${{ secrets.APITOGO_TOKEN }}
|
|
10641
|
-
run: apitogo deploy --deployment-token="$APITOGO_TOKEN" --json-only
|
|
10642
|
-
`;
|
|
10643
|
-
async function configureGithubWorkflow(argv) {
|
|
10644
|
-
const dir = path33.resolve(process.cwd(), argv.dir);
|
|
10645
|
-
const workflowDir = path33.join(dir, ".github", "workflows");
|
|
10646
|
-
const workflowPath = path33.join(workflowDir, "apitogo-deploy.yml");
|
|
10647
|
-
try {
|
|
10648
|
-
try {
|
|
10649
|
-
await access2(workflowPath, constants.F_OK);
|
|
10650
|
-
if (!argv.force) {
|
|
10651
|
-
await printCriticalFailureToConsoleAndExit(
|
|
10652
|
-
`Workflow file already exists: ${workflowPath}. Pass --force to overwrite.`
|
|
10653
|
-
);
|
|
10654
|
-
}
|
|
10655
|
-
} catch {
|
|
10525
|
+
// src/cli/make-config/interactive.ts
|
|
10526
|
+
import { createInterface } from "node:readline/promises";
|
|
10527
|
+
import { stdin as input, stdout as output } from "node:process";
|
|
10528
|
+
import path34 from "node:path";
|
|
10529
|
+
|
|
10530
|
+
// src/cli/make-config/json-config.ts
|
|
10531
|
+
import path33 from "node:path";
|
|
10532
|
+
var APITOGO_JSON_FILENAME = "apitogo.config.json";
|
|
10533
|
+
var DOCUMENTATION_NAV_LABEL = "Documentation";
|
|
10534
|
+
var API_REFERENCE_PATH = "/api";
|
|
10535
|
+
var API_REFERENCE_LABEL = "API Reference";
|
|
10536
|
+
function isPlainObject2(value) {
|
|
10537
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
10538
|
+
}
|
|
10539
|
+
function deepMerge(target, source) {
|
|
10540
|
+
const result = { ...target };
|
|
10541
|
+
for (const [key, value] of Object.entries(source)) {
|
|
10542
|
+
const existing = result[key];
|
|
10543
|
+
if (isPlainObject2(existing) && isPlainObject2(value)) {
|
|
10544
|
+
result[key] = deepMerge(existing, value);
|
|
10545
|
+
} else {
|
|
10546
|
+
result[key] = value;
|
|
10656
10547
|
}
|
|
10657
|
-
await mkdir6(workflowDir, { recursive: true });
|
|
10658
|
-
await writeFile6(workflowPath, APITOGO_DEPLOY_WORKFLOW_YAML, "utf8");
|
|
10659
|
-
printResultToConsole("Wrote .github/workflows/apitogo-deploy.yml");
|
|
10660
|
-
} catch (error) {
|
|
10661
|
-
await printCriticalFailureToConsoleAndExit(
|
|
10662
|
-
error instanceof Error ? error.message : String(error)
|
|
10663
|
-
);
|
|
10664
10548
|
}
|
|
10549
|
+
return result;
|
|
10665
10550
|
}
|
|
10666
|
-
|
|
10667
|
-
|
|
10668
|
-
|
|
10669
|
-
desc: "Add a GitHub Actions workflow for APIToGo preview and production deploys",
|
|
10670
|
-
command: "configure-github-workflow",
|
|
10671
|
-
builder: (yargs2) => yargs2.option("dir", {
|
|
10672
|
-
type: "string",
|
|
10673
|
-
describe: "The directory containing your project",
|
|
10674
|
-
default: ".",
|
|
10675
|
-
normalize: true,
|
|
10676
|
-
hidden: true
|
|
10677
|
-
}).option("force", {
|
|
10678
|
-
type: "boolean",
|
|
10679
|
-
describe: "Overwrite .github/workflows/apitogo-deploy.yml if it already exists",
|
|
10680
|
-
default: false
|
|
10681
|
-
}),
|
|
10682
|
-
handler: async (argv) => {
|
|
10683
|
-
await captureEvent({ argv, event: "apitogo configure-github-workflow" });
|
|
10684
|
-
await configureGithubWorkflow(argv);
|
|
10551
|
+
function parseJsonObjectFlag(raw, flagName) {
|
|
10552
|
+
if (raw === void 0 || raw.trim() === "") {
|
|
10553
|
+
return void 0;
|
|
10685
10554
|
}
|
|
10686
|
-
|
|
10687
|
-
|
|
10688
|
-
|
|
10689
|
-
|
|
10690
|
-
|
|
10691
|
-
const args = process.argv;
|
|
10692
|
-
let cmdIdx = -1;
|
|
10693
|
-
for (const cmd of ["deploy", "remove"]) {
|
|
10694
|
-
const i = args.indexOf(cmd);
|
|
10695
|
-
if (i !== -1) {
|
|
10696
|
-
cmdIdx = i;
|
|
10697
|
-
break;
|
|
10698
|
-
}
|
|
10555
|
+
let parsed;
|
|
10556
|
+
try {
|
|
10557
|
+
parsed = JSON.parse(raw);
|
|
10558
|
+
} catch {
|
|
10559
|
+
throw new Error(`--${flagName} must be a JSON object.`);
|
|
10699
10560
|
}
|
|
10700
|
-
if (
|
|
10701
|
-
|
|
10561
|
+
if (!isPlainObject2(parsed)) {
|
|
10562
|
+
throw new Error(`--${flagName} must be a JSON object.`);
|
|
10702
10563
|
}
|
|
10703
|
-
return
|
|
10704
|
-
}
|
|
10705
|
-
function isJsonOnlyDeployEnv() {
|
|
10706
|
-
return process.env.APITOGO_JSON_ONLY === "1";
|
|
10564
|
+
return parsed;
|
|
10707
10565
|
}
|
|
10708
|
-
function
|
|
10709
|
-
|
|
10710
|
-
|
|
10711
|
-
};
|
|
10712
|
-
logger.info = noop;
|
|
10713
|
-
logger.warn = noop;
|
|
10714
|
-
logger.warnOnce = noop;
|
|
10566
|
+
function titleFromDirectoryName(dirName) {
|
|
10567
|
+
const titled = dirName.split(/[-_\s]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
10568
|
+
return titled || "Developer Portal";
|
|
10715
10569
|
}
|
|
10716
|
-
|
|
10717
|
-
|
|
10718
|
-
|
|
10719
|
-
|
|
10720
|
-
|
|
10721
|
-
|
|
10722
|
-
|
|
10723
|
-
|
|
10724
|
-
|
|
10725
|
-
|
|
10726
|
-
const archivePath = path34.join(dir, ARCHIVE_NAME);
|
|
10727
|
-
await createTar(
|
|
10728
|
-
{
|
|
10729
|
-
cwd: dir,
|
|
10730
|
-
file: archivePath,
|
|
10731
|
-
gzip: true,
|
|
10732
|
-
portable: true
|
|
10570
|
+
function createDefaultApitogoJsonConfig(options) {
|
|
10571
|
+
const filesGlob = `/${options.pagesDir}/**/*.{md,mdx}`;
|
|
10572
|
+
return {
|
|
10573
|
+
site: {
|
|
10574
|
+
title: options.title,
|
|
10575
|
+
logo: {
|
|
10576
|
+
src: { light: "/logo-light.png", dark: "/logo-dark.png" },
|
|
10577
|
+
alt: "APIToGo",
|
|
10578
|
+
width: "130px"
|
|
10579
|
+
}
|
|
10733
10580
|
},
|
|
10734
|
-
|
|
10735
|
-
|
|
10736
|
-
|
|
10737
|
-
|
|
10738
|
-
|
|
10739
|
-
|
|
10740
|
-
|
|
10741
|
-
|
|
10742
|
-
|
|
10743
|
-
|
|
10744
|
-
|
|
10745
|
-
|
|
10746
|
-
|
|
10747
|
-
if (!isJsonOnlyDeployEnv()) {
|
|
10748
|
-
printDiagnosticsToConsole("Creating deployment archive...");
|
|
10749
|
-
}
|
|
10750
|
-
const archivePath = await createDeploymentArchive(dir);
|
|
10751
|
-
if (!isJsonOnlyDeployEnv()) {
|
|
10752
|
-
printDiagnosticsToConsole(
|
|
10753
|
-
`Uploading ${path34.basename(archivePath)} to ${env}...`
|
|
10754
|
-
);
|
|
10755
|
-
}
|
|
10756
|
-
const archiveBuffer = await readFile4(archivePath);
|
|
10757
|
-
const formData = new FormData();
|
|
10758
|
-
formData.append(
|
|
10759
|
-
"file",
|
|
10760
|
-
new Blob([archiveBuffer], { type: "application/gzip" }),
|
|
10761
|
-
path34.basename(archivePath)
|
|
10762
|
-
);
|
|
10763
|
-
formData.append("deploymentToken", deploymentToken);
|
|
10764
|
-
formData.append("env", env);
|
|
10765
|
-
const deployUrl = new URL(DEPLOY_ENDPOINT);
|
|
10766
|
-
if (argv.jsonOnly) {
|
|
10767
|
-
deployUrl.searchParams.set("jsonOnly", "true");
|
|
10768
|
-
}
|
|
10769
|
-
const response = await fetch(deployUrl, {
|
|
10770
|
-
method: "POST",
|
|
10771
|
-
headers: {
|
|
10772
|
-
"x-api-key": DEPLOY_SERVER_API_KEY
|
|
10581
|
+
authentication: {
|
|
10582
|
+
enabled: true,
|
|
10583
|
+
type: "dev-portal",
|
|
10584
|
+
redirectToAfterSignIn: "/account/dashboard",
|
|
10585
|
+
redirectToAfterSignUp: "/account/dashboard"
|
|
10586
|
+
},
|
|
10587
|
+
metadata: {
|
|
10588
|
+
favicon: "/Icon.png"
|
|
10589
|
+
},
|
|
10590
|
+
theme: {
|
|
10591
|
+
fonts: {
|
|
10592
|
+
sans: "IBM Plex Sans",
|
|
10593
|
+
mono: "JetBrains Mono"
|
|
10773
10594
|
},
|
|
10774
|
-
|
|
10775
|
-
|
|
10776
|
-
|
|
10777
|
-
|
|
10778
|
-
|
|
10779
|
-
|
|
10780
|
-
|
|
10781
|
-
|
|
10782
|
-
|
|
10783
|
-
|
|
10784
|
-
|
|
10785
|
-
|
|
10786
|
-
|
|
10787
|
-
|
|
10788
|
-
|
|
10789
|
-
|
|
10790
|
-
|
|
10791
|
-
|
|
10792
|
-
|
|
10793
|
-
|
|
10794
|
-
|
|
10795
|
-
|
|
10796
|
-
|
|
10797
|
-
|
|
10798
|
-
|
|
10595
|
+
light: {
|
|
10596
|
+
background: "#F5F6F9",
|
|
10597
|
+
foreground: "#0E1016",
|
|
10598
|
+
card: "#FFFFFF",
|
|
10599
|
+
cardForeground: "#0E1016",
|
|
10600
|
+
primary: "#E11D2A",
|
|
10601
|
+
primaryForeground: "#ffffff",
|
|
10602
|
+
secondary: "#FAFBFC",
|
|
10603
|
+
secondaryForeground: "#0E1016",
|
|
10604
|
+
muted: "#FAFBFC",
|
|
10605
|
+
mutedForeground: "#565E70",
|
|
10606
|
+
accent: "rgba(225, 29, 42, 0.08)",
|
|
10607
|
+
accentForeground: "#E11D2A",
|
|
10608
|
+
border: "#E6E8EF",
|
|
10609
|
+
input: "#D6DAE3",
|
|
10610
|
+
ring: "#E11D2A"
|
|
10611
|
+
},
|
|
10612
|
+
dark: {
|
|
10613
|
+
background: "#0B0D12",
|
|
10614
|
+
foreground: "#EDEFF5",
|
|
10615
|
+
card: "#14171F",
|
|
10616
|
+
cardForeground: "#EDEFF5",
|
|
10617
|
+
primary: "#F23645",
|
|
10618
|
+
primaryForeground: "#ffffff",
|
|
10619
|
+
secondary: "#191D27",
|
|
10620
|
+
secondaryForeground: "#EDEFF5",
|
|
10621
|
+
muted: "#191D27",
|
|
10622
|
+
mutedForeground: "#A6AEBF",
|
|
10623
|
+
accent: "rgba(242, 54, 69, 0.13)",
|
|
10624
|
+
accentForeground: "#F23645",
|
|
10625
|
+
border: "#252B37",
|
|
10626
|
+
input: "#333A48",
|
|
10627
|
+
ring: "#F23645"
|
|
10628
|
+
}
|
|
10629
|
+
},
|
|
10630
|
+
modules: {
|
|
10631
|
+
docs: {
|
|
10632
|
+
files: filesGlob
|
|
10633
|
+
},
|
|
10634
|
+
landing: {
|
|
10635
|
+
enabled: true,
|
|
10636
|
+
path: "/",
|
|
10637
|
+
layout: "landing",
|
|
10638
|
+
page: "./landing/LandingPage.tsx"
|
|
10639
|
+
},
|
|
10640
|
+
userPanel: {
|
|
10641
|
+
enabled: true,
|
|
10642
|
+
dashboard: { enabled: true },
|
|
10643
|
+
userManagement: { enabled: true },
|
|
10644
|
+
plans: {
|
|
10645
|
+
enabled: false,
|
|
10646
|
+
page: "./user-panel/AccountPlansPage.tsx"
|
|
10647
|
+
}
|
|
10648
|
+
}
|
|
10799
10649
|
}
|
|
10800
|
-
}
|
|
10650
|
+
};
|
|
10801
10651
|
}
|
|
10802
|
-
|
|
10803
|
-
|
|
10804
|
-
|
|
10805
|
-
|
|
10806
|
-
|
|
10807
|
-
|
|
10808
|
-
|
|
10809
|
-
describe: "Deployment token sent to the deploy endpoint"
|
|
10810
|
-
}).option("env", {
|
|
10811
|
-
type: "string",
|
|
10812
|
-
describe: "Target environment name sent to the deploy API (e.g. production, preview, preview-a, preview-b)",
|
|
10813
|
-
default: "production"
|
|
10814
|
-
}).option("dir", {
|
|
10815
|
-
type: "string",
|
|
10816
|
-
describe: "The directory containing your project",
|
|
10817
|
-
default: ".",
|
|
10818
|
-
normalize: true,
|
|
10819
|
-
hidden: true
|
|
10820
|
-
}).option("experimental-ssr", {
|
|
10821
|
-
type: "boolean",
|
|
10822
|
-
describe: "Build for server-side rendering (experimental)",
|
|
10823
|
-
default: false
|
|
10824
|
-
}).option("adapter", {
|
|
10825
|
-
type: "string",
|
|
10826
|
-
describe: "SSR adapter (node, cloudflare, vercel)",
|
|
10827
|
-
choices: ["node", "cloudflare", "vercel"],
|
|
10828
|
-
default: "node"
|
|
10829
|
-
}).option("json-only", {
|
|
10830
|
-
type: "boolean",
|
|
10831
|
-
describe: "JSON-only output on stdout; adds ?jsonOnly=true to the deploy request",
|
|
10832
|
-
default: false
|
|
10833
|
-
}),
|
|
10834
|
-
handler: async (argv) => {
|
|
10835
|
-
process.env.NODE_ENV = "production";
|
|
10836
|
-
if (argv.jsonOnly) {
|
|
10837
|
-
applyJsonOnlyDeployQuietMode();
|
|
10838
|
-
}
|
|
10839
|
-
await captureEvent({ argv, event: "apitogo deploy" });
|
|
10840
|
-
await deploy(argv);
|
|
10652
|
+
function applyConfigPatches(config2, patches) {
|
|
10653
|
+
let next = { ...config2 };
|
|
10654
|
+
if (patches.site) {
|
|
10655
|
+
next.site = deepMerge(
|
|
10656
|
+
isPlainObject2(next.site) ? next.site : {},
|
|
10657
|
+
patches.site
|
|
10658
|
+
);
|
|
10841
10659
|
}
|
|
10842
|
-
|
|
10843
|
-
|
|
10844
|
-
|
|
10845
|
-
|
|
10846
|
-
|
|
10847
|
-
|
|
10848
|
-
// src/vite/dev-server.ts
|
|
10849
|
-
init_logger();
|
|
10850
|
-
import fs4 from "node:fs/promises";
|
|
10851
|
-
import http from "node:http";
|
|
10852
|
-
import https from "node:https";
|
|
10853
|
-
import path36 from "node:path";
|
|
10854
|
-
import { createHttpTerminator } from "http-terminator";
|
|
10855
|
-
import {
|
|
10856
|
-
createServer as createViteServer,
|
|
10857
|
-
isRunnableDevEnvironment as isRunnableDevEnvironment2,
|
|
10858
|
-
mergeConfig as mergeConfig4
|
|
10859
|
-
} from "vite";
|
|
10860
|
-
|
|
10861
|
-
// src/cli/common/utils/ports.ts
|
|
10862
|
-
import net from "node:net";
|
|
10863
|
-
var isPortAvailable = (port) => new Promise((resolve) => {
|
|
10864
|
-
const server = net.createServer();
|
|
10865
|
-
server.unref();
|
|
10866
|
-
server.once("error", () => resolve(false));
|
|
10867
|
-
server.listen(port, () => {
|
|
10868
|
-
server.close();
|
|
10869
|
-
resolve(true);
|
|
10870
|
-
});
|
|
10871
|
-
});
|
|
10872
|
-
async function findAvailablePort(startPort) {
|
|
10873
|
-
let port = startPort;
|
|
10874
|
-
for (; port < startPort + 1e3; port++) {
|
|
10875
|
-
if (await isPortAvailable(port)) break;
|
|
10660
|
+
if (patches.theme) {
|
|
10661
|
+
next.theme = deepMerge(
|
|
10662
|
+
isPlainObject2(next.theme) ? next.theme : {},
|
|
10663
|
+
patches.theme
|
|
10664
|
+
);
|
|
10876
10665
|
}
|
|
10877
|
-
|
|
10878
|
-
|
|
10879
|
-
|
|
10880
|
-
|
|
10881
|
-
|
|
10882
|
-
|
|
10883
|
-
// src/vite/pagefind-dev-index.ts
|
|
10884
|
-
init_invariant();
|
|
10885
|
-
init_joinUrl();
|
|
10886
|
-
import path35 from "node:path";
|
|
10887
|
-
import { createIndex as createIndex2 } from "pagefind";
|
|
10888
|
-
import { isRunnableDevEnvironment } from "vite";
|
|
10889
|
-
async function* buildPagefindDevIndex(vite, config2) {
|
|
10890
|
-
const { index, errors } = await createIndex2();
|
|
10891
|
-
invariant(index, `Failed to create pagefind index: ${errors.join(", ")}`);
|
|
10892
|
-
const pagefindIndex = index;
|
|
10893
|
-
const ssrEnvironment = vite.environments.ssr;
|
|
10894
|
-
if (!isRunnableDevEnvironment(ssrEnvironment)) {
|
|
10895
|
-
throw new Error("SSR environment is not runnable");
|
|
10666
|
+
if (patches.authentication) {
|
|
10667
|
+
next.authentication = deepMerge(
|
|
10668
|
+
isPlainObject2(next.authentication) ? next.authentication : {},
|
|
10669
|
+
patches.authentication
|
|
10670
|
+
);
|
|
10896
10671
|
}
|
|
10897
|
-
|
|
10898
|
-
|
|
10899
|
-
|
|
10900
|
-
|
|
10901
|
-
|
|
10902
|
-
|
|
10903
|
-
|
|
10904
|
-
|
|
10905
|
-
|
|
10906
|
-
|
|
10907
|
-
|
|
10908
|
-
|
|
10909
|
-
|
|
10910
|
-
|
|
10911
|
-
|
|
10912
|
-
|
|
10913
|
-
|
|
10914
|
-
|
|
10915
|
-
|
|
10916
|
-
|
|
10917
|
-
|
|
10918
|
-
|
|
10919
|
-
|
|
10920
|
-
|
|
10921
|
-
|
|
10922
|
-
|
|
10923
|
-
|
|
10924
|
-
|
|
10925
|
-
|
|
10926
|
-
|
|
10927
|
-
|
|
10672
|
+
if (patches.title?.trim()) {
|
|
10673
|
+
const site = isPlainObject2(next.site) ? next.site : {};
|
|
10674
|
+
next.site = { ...site, title: patches.title.trim() };
|
|
10675
|
+
}
|
|
10676
|
+
return next;
|
|
10677
|
+
}
|
|
10678
|
+
var docSortRank = (docPath) => {
|
|
10679
|
+
const lastSegment = docPath.split("/").at(-1) ?? docPath;
|
|
10680
|
+
if (lastSegment === "introduction") return 0;
|
|
10681
|
+
if (lastSegment === "example") return 1;
|
|
10682
|
+
if (lastSegment === "getting-started") return 2;
|
|
10683
|
+
if (lastSegment === "index") return 3;
|
|
10684
|
+
return 4;
|
|
10685
|
+
};
|
|
10686
|
+
var sortDocPaths = (docPaths) => [...docPaths].sort((a, b) => {
|
|
10687
|
+
const rankDiff = docSortRank(a) - docSortRank(b);
|
|
10688
|
+
if (rankDiff !== 0) return rankDiff;
|
|
10689
|
+
return a.localeCompare(b);
|
|
10690
|
+
});
|
|
10691
|
+
var createTreeNode = () => ({ docs: [], children: /* @__PURE__ */ new Map() });
|
|
10692
|
+
var titleCase = (value) => value.split(/[-_\s]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
10693
|
+
var buildTree = (routePaths) => {
|
|
10694
|
+
const root = createTreeNode();
|
|
10695
|
+
for (const routePath of routePaths) {
|
|
10696
|
+
const segments = routePath.replace(/^\//, "").split("/").filter(Boolean);
|
|
10697
|
+
const directorySegments = segments.slice(0, -1);
|
|
10698
|
+
let current = root;
|
|
10699
|
+
for (const segment of directorySegments) {
|
|
10700
|
+
let child = current.children.get(segment);
|
|
10701
|
+
if (!child) {
|
|
10702
|
+
child = createTreeNode();
|
|
10703
|
+
current.children.set(segment, child);
|
|
10928
10704
|
}
|
|
10929
|
-
|
|
10930
|
-
console.error(`Failed to index ${urlPath}:`, error);
|
|
10705
|
+
current = child;
|
|
10931
10706
|
}
|
|
10932
|
-
|
|
10933
|
-
|
|
10934
|
-
|
|
10935
|
-
|
|
10936
|
-
|
|
10707
|
+
current.docs.push(routePath);
|
|
10708
|
+
}
|
|
10709
|
+
return root;
|
|
10710
|
+
};
|
|
10711
|
+
var treeToNavigationItems = (node) => {
|
|
10712
|
+
const docs = sortDocPaths(node.docs);
|
|
10713
|
+
const categories = [...node.children.keys()].sort((a, b) => a.localeCompare(b)).map((directoryName) => {
|
|
10714
|
+
const childNode = node.children.get(directoryName);
|
|
10715
|
+
if (!childNode) {
|
|
10716
|
+
throw new Error(`Missing child node for directory '${directoryName}'.`);
|
|
10717
|
+
}
|
|
10718
|
+
return {
|
|
10719
|
+
type: "category",
|
|
10720
|
+
label: titleCase(directoryName),
|
|
10721
|
+
items: treeToNavigationItems(childNode)
|
|
10937
10722
|
};
|
|
10723
|
+
});
|
|
10724
|
+
return [...docs, ...categories];
|
|
10725
|
+
};
|
|
10726
|
+
function buildDocumentationItems(routePaths) {
|
|
10727
|
+
return treeToNavigationItems(buildTree(sortDocPaths(routePaths)));
|
|
10728
|
+
}
|
|
10729
|
+
function navItemKey(item) {
|
|
10730
|
+
if (typeof item === "string") {
|
|
10731
|
+
return `path:${item}`;
|
|
10938
10732
|
}
|
|
10939
|
-
|
|
10940
|
-
|
|
10941
|
-
|
|
10733
|
+
if (typeof item.to === "string") {
|
|
10734
|
+
return `to:${item.to}`;
|
|
10735
|
+
}
|
|
10736
|
+
if (typeof item.path === "string") {
|
|
10737
|
+
return `path:${item.path}`;
|
|
10738
|
+
}
|
|
10739
|
+
if (item.type === "category" && typeof item.label === "string") {
|
|
10740
|
+
return `category:${item.label}`;
|
|
10741
|
+
}
|
|
10742
|
+
return JSON.stringify(item);
|
|
10942
10743
|
}
|
|
10943
|
-
|
|
10944
|
-
|
|
10945
|
-
|
|
10946
|
-
|
|
10947
|
-
|
|
10948
|
-
|
|
10744
|
+
function mergeNavItems(existing, incoming) {
|
|
10745
|
+
const seen = new Set(existing.map(navItemKey));
|
|
10746
|
+
const merged = [...existing];
|
|
10747
|
+
for (const item of incoming) {
|
|
10748
|
+
const key = navItemKey(item);
|
|
10749
|
+
if (seen.has(key)) {
|
|
10750
|
+
continue;
|
|
10751
|
+
}
|
|
10752
|
+
seen.add(key);
|
|
10753
|
+
merged.push(item);
|
|
10949
10754
|
}
|
|
10950
|
-
|
|
10951
|
-
|
|
10952
|
-
|
|
10953
|
-
|
|
10954
|
-
|
|
10955
|
-
|
|
10956
|
-
|
|
10957
|
-
|
|
10958
|
-
|
|
10959
|
-
|
|
10960
|
-
|
|
10961
|
-
|
|
10962
|
-
|
|
10755
|
+
return merged;
|
|
10756
|
+
}
|
|
10757
|
+
function isDocumentationCategory(item) {
|
|
10758
|
+
return typeof item === "object" && item.type === "category" && item.label === DOCUMENTATION_NAV_LABEL;
|
|
10759
|
+
}
|
|
10760
|
+
function isApiReferenceLink(item) {
|
|
10761
|
+
return typeof item === "object" && item.type === "link" && item.to === API_REFERENCE_PATH;
|
|
10762
|
+
}
|
|
10763
|
+
function mergeDocumentationNavigation(navigation, docRoutePaths, options) {
|
|
10764
|
+
const existing = Array.isArray(navigation) ? navigation : [];
|
|
10765
|
+
const generated = buildDocumentationItems(docRoutePaths);
|
|
10766
|
+
const rest = existing.filter((item) => !isDocumentationCategory(item));
|
|
10767
|
+
const currentDocs = existing.find(isDocumentationCategory);
|
|
10768
|
+
const currentItems = Array.isArray(currentDocs?.items) ? currentDocs.items : [];
|
|
10769
|
+
const items = options.force ? generated : mergeNavItems(currentItems, generated);
|
|
10770
|
+
const documentation = {
|
|
10771
|
+
type: "category",
|
|
10772
|
+
label: DOCUMENTATION_NAV_LABEL,
|
|
10773
|
+
items
|
|
10774
|
+
};
|
|
10775
|
+
if (generated.length === 0) {
|
|
10776
|
+
return existing;
|
|
10963
10777
|
}
|
|
10964
|
-
|
|
10965
|
-
const
|
|
10966
|
-
|
|
10967
|
-
|
|
10968
|
-
|
|
10969
|
-
|
|
10970
|
-
|
|
10971
|
-
|
|
10972
|
-
|
|
10973
|
-
|
|
10974
|
-
|
|
10975
|
-
|
|
10976
|
-
|
|
10977
|
-
|
|
10978
|
-
|
|
10979
|
-
typeof viteConfig.publicDir === "string" ? viteConfig.publicDir : "public"
|
|
10980
|
-
);
|
|
10981
|
-
await ensurePagefindDevStub(publicRoot);
|
|
10778
|
+
if (currentDocs) {
|
|
10779
|
+
const index = existing.findIndex(isDocumentationCategory);
|
|
10780
|
+
const next = [...existing];
|
|
10781
|
+
next[index] = documentation;
|
|
10782
|
+
return next;
|
|
10783
|
+
}
|
|
10784
|
+
return [documentation, ...rest];
|
|
10785
|
+
}
|
|
10786
|
+
function applyOpenApiToJsonConfig(config2, input2) {
|
|
10787
|
+
const next = { ...config2 };
|
|
10788
|
+
next.apis = [
|
|
10789
|
+
{
|
|
10790
|
+
type: "file",
|
|
10791
|
+
input: input2,
|
|
10792
|
+
path: "api"
|
|
10982
10793
|
}
|
|
10983
|
-
|
|
10984
|
-
|
|
10985
|
-
|
|
10986
|
-
|
|
10987
|
-
|
|
10988
|
-
|
|
10989
|
-
|
|
10990
|
-
// Must be registered via configureServer so it runs before Vite's
|
|
10991
|
-
// built-in transform middleware which would treat the path as a static asset.
|
|
10992
|
-
name: "apitogo:entry-client",
|
|
10993
|
-
configureServer(server2) {
|
|
10994
|
-
const entryPath = path36.posix.join(
|
|
10995
|
-
server2.config.base,
|
|
10996
|
-
"/__z/entry.client.tsx"
|
|
10997
|
-
);
|
|
10998
|
-
server2.middlewares.use(entryPath, async (_req, res) => {
|
|
10999
|
-
const transformed = await server2.environments.client.transformRequest(
|
|
11000
|
-
getAppClientEntryPath()
|
|
11001
|
-
);
|
|
11002
|
-
if (!transformed) {
|
|
11003
|
-
res.writeHead(500);
|
|
11004
|
-
res.end("Error transforming client entry");
|
|
11005
|
-
return;
|
|
11006
|
-
}
|
|
11007
|
-
res.writeHead(200, { "Content-Type": "text/javascript" });
|
|
11008
|
-
res.end(transformed.code);
|
|
11009
|
-
});
|
|
11010
|
-
}
|
|
11011
|
-
}
|
|
11012
|
-
]
|
|
11013
|
-
});
|
|
11014
|
-
const vite = await createViteServer(mergedViteConfig);
|
|
11015
|
-
const graphql = createGraphQLServer({ graphqlEndpoint: "/__z/graphql" });
|
|
11016
|
-
vite.middlewares.use((req, res, next) => {
|
|
11017
|
-
if (req.method === "GET" && req.originalUrl === "/" && config2.basePath && config2.basePath !== "/") {
|
|
11018
|
-
res.writeHead(307, { Location: config2.basePath });
|
|
11019
|
-
res.end();
|
|
11020
|
-
return;
|
|
11021
|
-
}
|
|
11022
|
-
next();
|
|
11023
|
-
});
|
|
11024
|
-
vite.middlewares.use(graphql.graphqlEndpoint, graphql);
|
|
11025
|
-
vite.middlewares.use("/__z/pagefind-reindex", async (_req, res) => {
|
|
11026
|
-
res.writeHead(200, {
|
|
11027
|
-
"Content-Type": "text/event-stream",
|
|
11028
|
-
"Cache-Control": "no-cache",
|
|
11029
|
-
Connection: "keep-alive"
|
|
11030
|
-
});
|
|
11031
|
-
const { config: currentConfig } = await loadZudokuConfig(
|
|
11032
|
-
configEnv,
|
|
11033
|
-
this.options.dir
|
|
11034
|
-
);
|
|
11035
|
-
const sendEvent = (data) => res.write(`data: ${JSON.stringify(data)}
|
|
11036
|
-
|
|
11037
|
-
`);
|
|
11038
|
-
if (currentConfig.search?.type !== "pagefind") {
|
|
11039
|
-
sendEvent({
|
|
11040
|
-
type: "complete",
|
|
11041
|
-
success: false,
|
|
11042
|
-
indexed: 0,
|
|
11043
|
-
error: "Pagefind search is not enabled"
|
|
11044
|
-
});
|
|
11045
|
-
res.end();
|
|
11046
|
-
return;
|
|
11047
|
-
}
|
|
11048
|
-
try {
|
|
11049
|
-
for await (const event of buildPagefindDevIndex(vite, currentConfig)) {
|
|
11050
|
-
sendEvent(event);
|
|
11051
|
-
}
|
|
11052
|
-
} catch (error) {
|
|
11053
|
-
const message = error instanceof Error ? error.message : "Unknown error";
|
|
11054
|
-
sendEvent({
|
|
11055
|
-
type: "complete",
|
|
11056
|
-
success: false,
|
|
11057
|
-
indexed: 0,
|
|
11058
|
-
error: message
|
|
11059
|
-
});
|
|
11060
|
-
}
|
|
11061
|
-
res.end();
|
|
11062
|
-
});
|
|
11063
|
-
printDiagnosticsToConsole(
|
|
11064
|
-
`Server-side rendering ${this.options.ssr ? "enabled" : "disabled"}`
|
|
11065
|
-
);
|
|
11066
|
-
if (config2.search?.type === "pagefind" && vite.config.publicDir) {
|
|
11067
|
-
await ensurePagefindDevStub(vite.config.publicDir);
|
|
11068
|
-
}
|
|
11069
|
-
vite.middlewares.use(async (req, res) => {
|
|
11070
|
-
const url = req.originalUrl ?? req.url ?? "/";
|
|
11071
|
-
const ssrEnvironment = vite.environments.ssr;
|
|
11072
|
-
if (!isRunnableDevEnvironment2(ssrEnvironment)) {
|
|
11073
|
-
res.writeHead(500);
|
|
11074
|
-
res.end("SSR environment not available");
|
|
11075
|
-
return;
|
|
11076
|
-
}
|
|
11077
|
-
try {
|
|
11078
|
-
const { config: currentConfig } = await loadZudokuConfig(
|
|
11079
|
-
configEnv,
|
|
11080
|
-
this.options.dir
|
|
11081
|
-
);
|
|
11082
|
-
const rawHtml = getDevHtml({
|
|
11083
|
-
jsEntry: "/__z/entry.client.tsx",
|
|
11084
|
-
dir: currentConfig.site?.dir
|
|
11085
|
-
});
|
|
11086
|
-
const template = await vite.transformIndexHtml(url, rawHtml);
|
|
11087
|
-
if (this.options.ssr) {
|
|
11088
|
-
const entryServer = await ssrEnvironment.runner.import(
|
|
11089
|
-
getAppServerEntryPath()
|
|
11090
|
-
);
|
|
11091
|
-
const hasBody = req.method !== "GET" && req.method !== "HEAD";
|
|
11092
|
-
const request = new Request(
|
|
11093
|
-
`${this.protocol}://${req.headers.host}${url}`,
|
|
11094
|
-
{
|
|
11095
|
-
method: req.method,
|
|
11096
|
-
headers: req.headers,
|
|
11097
|
-
body: hasBody ? req : void 0,
|
|
11098
|
-
// Required by Node when body is a readable stream
|
|
11099
|
-
// @ts-expect-error Missing type definition
|
|
11100
|
-
duplex: hasBody ? "half" : void 0
|
|
11101
|
-
}
|
|
11102
|
-
);
|
|
11103
|
-
const response = await entryServer.handleRequest({
|
|
11104
|
-
template,
|
|
11105
|
-
request,
|
|
11106
|
-
routes: entryServer.getRoutesByConfig(currentConfig),
|
|
11107
|
-
basePath: currentConfig.basePath
|
|
11108
|
-
});
|
|
11109
|
-
for (const [key, value] of response.headers) {
|
|
11110
|
-
res.appendHeader(key, value);
|
|
11111
|
-
}
|
|
11112
|
-
res.writeHead(response.status);
|
|
11113
|
-
for await (const chunk of response.body ?? []) {
|
|
11114
|
-
res.write(chunk);
|
|
11115
|
-
}
|
|
11116
|
-
res.end();
|
|
11117
|
-
} else {
|
|
11118
|
-
res.writeHead(200, { "Content-Type": "text/html" });
|
|
11119
|
-
res.end(template);
|
|
11120
|
-
}
|
|
11121
|
-
} catch (e) {
|
|
11122
|
-
logger.error(e);
|
|
11123
|
-
const html = `<!DOCTYPE html><html><body><script type="module">
|
|
11124
|
-
import { ErrorOverlay } from '/@vite/client';
|
|
11125
|
-
document.body.appendChild(new ErrorOverlay(${JSON.stringify({
|
|
11126
|
-
message: e instanceof Error ? e.message : String(e),
|
|
11127
|
-
stack: e instanceof Error ? e.stack : ""
|
|
11128
|
-
})}));
|
|
11129
|
-
</script></body></html>`;
|
|
11130
|
-
res.writeHead(500, { "Content-Type": "text/html" });
|
|
11131
|
-
res.end(html);
|
|
11132
|
-
}
|
|
11133
|
-
});
|
|
11134
|
-
server.on("request", vite.middlewares);
|
|
11135
|
-
await new Promise((resolve) => {
|
|
11136
|
-
server.listen(this.resolvedPort, resolve);
|
|
10794
|
+
];
|
|
10795
|
+
const navigation = Array.isArray(next.navigation) ? [...next.navigation] : [];
|
|
10796
|
+
if (!navigation.some(isApiReferenceLink)) {
|
|
10797
|
+
navigation.push({
|
|
10798
|
+
type: "link",
|
|
10799
|
+
to: API_REFERENCE_PATH,
|
|
10800
|
+
label: API_REFERENCE_LABEL
|
|
11137
10801
|
});
|
|
11138
|
-
|
|
11139
|
-
|
|
11140
|
-
|
|
11141
|
-
|
|
11142
|
-
|
|
11143
|
-
|
|
11144
|
-
|
|
11145
|
-
|
|
10802
|
+
}
|
|
10803
|
+
next.navigation = navigation;
|
|
10804
|
+
return next;
|
|
10805
|
+
}
|
|
10806
|
+
function openapiInputForConfig(specRelativePosix) {
|
|
10807
|
+
if (specRelativePosix.startsWith("./")) {
|
|
10808
|
+
return specRelativePosix;
|
|
10809
|
+
}
|
|
10810
|
+
return `./${specRelativePosix}`;
|
|
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);
|
|
11146
10863
|
}
|
|
11147
|
-
return { vite };
|
|
11148
10864
|
}
|
|
11149
|
-
|
|
11150
|
-
|
|
10865
|
+
userPanel.plans = {
|
|
10866
|
+
...plans,
|
|
10867
|
+
enabled: true,
|
|
10868
|
+
items: existing
|
|
10869
|
+
};
|
|
10870
|
+
modules.userPanel = userPanel;
|
|
10871
|
+
return { ...config2, modules };
|
|
10872
|
+
}
|
|
10873
|
+
function toRoutePath(relativeFile, pagesDir) {
|
|
10874
|
+
const relativeNoExt = relativeFile.replace(/\.(mdx?|tsx|jsx)$/i, "");
|
|
10875
|
+
const escaped = pagesDir.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
10876
|
+
const withoutPagesPrefix = relativeNoExt.replace(
|
|
10877
|
+
new RegExp(`^${escaped}/?`),
|
|
10878
|
+
""
|
|
10879
|
+
);
|
|
10880
|
+
const normalized = withoutPagesPrefix.replace(/\/index$/, "");
|
|
10881
|
+
return `/${normalized || "index"}`;
|
|
10882
|
+
}
|
|
10883
|
+
function pageComponentName(slug) {
|
|
10884
|
+
const pascal = slug.replace(/^\/+/, "").split(/[^a-zA-Z0-9]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
10885
|
+
const name = /^[A-Za-z]/.test(pascal) ? pascal : `Page${pascal}`;
|
|
10886
|
+
return name.endsWith("Page") ? name : `${name}Page`;
|
|
10887
|
+
}
|
|
10888
|
+
var THIN_WRAPPER_SOURCE = `import { devPortalBillingPlugin } from "@lukoweb/apitogo-plugin-dev-portal-billing";
|
|
10889
|
+
import { buildApitogoConfig } from "@lukoweb/apitogo/build-config";
|
|
10890
|
+
import siteConfig from "./apitogo.config.json";
|
|
10891
|
+
|
|
10892
|
+
export default buildApitogoConfig({
|
|
10893
|
+
...siteConfig,
|
|
10894
|
+
plugins: [devPortalBillingPlugin()],
|
|
10895
|
+
});
|
|
10896
|
+
`;
|
|
10897
|
+
function isThinConfigWrapper(source) {
|
|
10898
|
+
return /export\s+default\s+buildApitogoConfig\s*\(/.test(source);
|
|
10899
|
+
}
|
|
10900
|
+
function buildThinWrapperWithCustomPages(tsxRoutePaths) {
|
|
10901
|
+
if (tsxRoutePaths.length === 0) {
|
|
10902
|
+
return THIN_WRAPPER_SOURCE;
|
|
11151
10903
|
}
|
|
10904
|
+
const imports = tsxRoutePaths.map((routePath) => {
|
|
10905
|
+
const slug = routePath.replace(/^\//, "");
|
|
10906
|
+
const name = pageComponentName(slug);
|
|
10907
|
+
return `import ${name} from "./pages/${slug}";`;
|
|
10908
|
+
}).join("\n");
|
|
10909
|
+
const customPages = tsxRoutePaths.map((routePath) => {
|
|
10910
|
+
const slug = routePath.replace(/^\//, "");
|
|
10911
|
+
const name = pageComponentName(slug);
|
|
10912
|
+
return ` {
|
|
10913
|
+
type: "custom-page",
|
|
10914
|
+
path: ${JSON.stringify(routePath)},
|
|
10915
|
+
element: <${name} />,
|
|
10916
|
+
},`;
|
|
10917
|
+
}).join("\n");
|
|
10918
|
+
return `${imports}
|
|
10919
|
+
import { devPortalBillingPlugin } from "@lukoweb/apitogo-plugin-dev-portal-billing";
|
|
10920
|
+
import { buildApitogoConfig } from "@lukoweb/apitogo/build-config";
|
|
10921
|
+
import siteConfig from "./apitogo.config.json";
|
|
10922
|
+
|
|
10923
|
+
const config = buildApitogoConfig({
|
|
10924
|
+
...siteConfig,
|
|
10925
|
+
plugins: [devPortalBillingPlugin()],
|
|
10926
|
+
});
|
|
10927
|
+
|
|
10928
|
+
export default {
|
|
10929
|
+
...config,
|
|
10930
|
+
navigation: [
|
|
10931
|
+
{
|
|
10932
|
+
type: "category",
|
|
10933
|
+
label: ${JSON.stringify(DOCUMENTATION_NAV_LABEL)},
|
|
10934
|
+
items: [
|
|
10935
|
+
${customPages}
|
|
10936
|
+
...(((config.navigation ?? []).find(
|
|
10937
|
+
(item) =>
|
|
10938
|
+
typeof item === "object" &&
|
|
10939
|
+
item !== null &&
|
|
10940
|
+
"label" in item &&
|
|
10941
|
+
item.label === ${JSON.stringify(DOCUMENTATION_NAV_LABEL)},
|
|
10942
|
+
) as { items?: unknown[] } | undefined)?.items ?? []),
|
|
10943
|
+
],
|
|
10944
|
+
},
|
|
10945
|
+
...(config.navigation ?? []).filter(
|
|
10946
|
+
(item) =>
|
|
10947
|
+
!(
|
|
10948
|
+
typeof item === "object" &&
|
|
10949
|
+
item !== null &&
|
|
10950
|
+
"label" in item &&
|
|
10951
|
+
item.label === ${JSON.stringify(DOCUMENTATION_NAV_LABEL)}
|
|
10952
|
+
),
|
|
10953
|
+
),
|
|
10954
|
+
],
|
|
11152
10955
|
};
|
|
10956
|
+
`;
|
|
10957
|
+
}
|
|
11153
10958
|
|
|
11154
|
-
// src/cli/
|
|
11155
|
-
|
|
11156
|
-
|
|
11157
|
-
|
|
11158
|
-
|
|
11159
|
-
|
|
11160
|
-
|
|
11161
|
-
dir,
|
|
11162
|
-
argPort: argv.port,
|
|
11163
|
-
ssr: argv.ssr,
|
|
11164
|
-
open: argv.open
|
|
11165
|
-
});
|
|
11166
|
-
const { vite } = await server.start();
|
|
11167
|
-
const url = joinUrl(
|
|
11168
|
-
`${server.protocol}://localhost:${server.resolvedPort}`,
|
|
11169
|
-
vite.config.base
|
|
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/guides/custom-pages and ${DOCS}/docs/components/callout`
|
|
11170
10966
|
);
|
|
11171
|
-
|
|
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 or custom domains."
|
|
10980
|
+
);
|
|
10981
|
+
}
|
|
10982
|
+
function printInteractiveWrapUp(hasPaidPlans) {
|
|
11172
10983
|
printDiagnosticsToConsole("");
|
|
10984
|
+
printDiagnosticsToConsole("Configuration saved. Next steps:");
|
|
10985
|
+
printDiagnosticsToConsole("- Preview locally: npm run dev");
|
|
11173
10986
|
printDiagnosticsToConsole(
|
|
11174
|
-
|
|
10987
|
+
"- Auth API URL is written automatically when you run apitogo apply"
|
|
11175
10988
|
);
|
|
10989
|
+
if (hasPaidPlans) {
|
|
10990
|
+
printPaidPlanPlatformWarning();
|
|
10991
|
+
} else {
|
|
10992
|
+
printDiagnosticsToConsole(
|
|
10993
|
+
"Platform note: Free hosting does not support paid API plans or custom domains \u2014 use Starter or Professional for those."
|
|
10994
|
+
);
|
|
10995
|
+
}
|
|
11176
10996
|
printDiagnosticsToConsole("");
|
|
11177
|
-
|
|
11178
|
-
|
|
11179
|
-
|
|
11180
|
-
|
|
11181
|
-
|
|
11182
|
-
|
|
11183
|
-
|
|
11184
|
-
|
|
11185
|
-
|
|
11186
|
-
|
|
11187
|
-
});
|
|
11188
|
-
}
|
|
11189
|
-
}
|
|
11190
|
-
process.on("SIGTERM", exit);
|
|
11191
|
-
process.on("SIGINT", exit);
|
|
11192
|
-
process.on("uncaughtException", (e) => {
|
|
11193
|
-
console.error("Uncaught exception", e);
|
|
11194
|
-
void exit();
|
|
11195
|
-
});
|
|
11196
|
-
process.on("unhandledRejection", (e) => {
|
|
11197
|
-
if (e instanceof DOMException && e.name === "AbortError") {
|
|
11198
|
-
console.log(`[Abort] ${e.message}`);
|
|
11199
|
-
return;
|
|
11200
|
-
}
|
|
11201
|
-
console.error("Unhandled rejection", e);
|
|
11202
|
-
void exit();
|
|
11203
|
-
});
|
|
11204
|
-
process.on("exit", exit);
|
|
11205
|
-
});
|
|
10997
|
+
printDiagnosticsToConsole("Configure more:");
|
|
10998
|
+
printDiagnosticsToConsole(`- Overview: ${DOCS}/docs/configuration/overview`);
|
|
10999
|
+
printDiagnosticsToConsole(`- Manifest: ${DOCS}/docs/configuration/manifest`);
|
|
11000
|
+
printDiagnosticsToConsole(`- Gateway plans: ${DOCS}/docs/configuration/plans`);
|
|
11001
|
+
printDiagnosticsToConsole(`- Custom pages: ${DOCS}/docs/guides/custom-pages`);
|
|
11002
|
+
printDiagnosticsToConsole(`- API reference: ${DOCS}/docs/configuration/api-reference`);
|
|
11003
|
+
printDiagnosticsToConsole(`- Theme: ${DOCS}/docs/customization/colors-theme`);
|
|
11004
|
+
printDiagnosticsToConsole(`- Fonts: ${DOCS}/docs/customization/fonts`);
|
|
11005
|
+
printDiagnosticsToConsole(`- CLI shape: ${DOCS}/docs/cli/shape`);
|
|
11006
|
+
printDiagnosticsToConsole(`- apitogo config: ${DOCS}/docs/configuration/make-config`);
|
|
11206
11007
|
}
|
|
11207
11008
|
|
|
11208
|
-
// src/cli/cmds/dev.ts
|
|
11209
|
-
var dev_default = {
|
|
11210
|
-
desc: "Runs locally",
|
|
11211
|
-
command: "dev",
|
|
11212
|
-
builder: (yargs2) => {
|
|
11213
|
-
return yargs2.option("dir", {
|
|
11214
|
-
type: "string",
|
|
11215
|
-
describe: "The directory containing your project",
|
|
11216
|
-
default: ".",
|
|
11217
|
-
normalize: true,
|
|
11218
|
-
hidden: true
|
|
11219
|
-
}).option("port", {
|
|
11220
|
-
type: "number",
|
|
11221
|
-
describe: "The port to run the local server on"
|
|
11222
|
-
}).option("ssr", {
|
|
11223
|
-
type: "boolean",
|
|
11224
|
-
describe: "Enable server-side rendering",
|
|
11225
|
-
default: true
|
|
11226
|
-
}).option("open", {
|
|
11227
|
-
type: "boolean",
|
|
11228
|
-
describe: "Automatically open the browser",
|
|
11229
|
-
default: false
|
|
11230
|
-
});
|
|
11231
|
-
},
|
|
11232
|
-
handler: async (argv) => {
|
|
11233
|
-
await captureEvent({
|
|
11234
|
-
argv,
|
|
11235
|
-
event: "apitogo dev"
|
|
11236
|
-
});
|
|
11237
|
-
await dev(argv);
|
|
11238
|
-
}
|
|
11239
|
-
};
|
|
11240
|
-
|
|
11241
|
-
// src/cli/make-config/handler.ts
|
|
11242
|
-
import { constants as constants3 } from "node:fs";
|
|
11243
|
-
import { access as access5, mkdir as mkdir8, readFile as readFile6, writeFile as writeFile8 } from "node:fs/promises";
|
|
11244
|
-
import path39 from "node:path";
|
|
11245
|
-
import { glob as glob5 } from "glob";
|
|
11246
|
-
|
|
11247
11009
|
// src/cli/make-config/interactive.ts
|
|
11248
|
-
import { createInterface } from "node:readline/promises";
|
|
11249
|
-
import { stdin as input, stdout as output } from "node:process";
|
|
11250
11010
|
var ask = async (rl, question, defaultValue) => {
|
|
11251
11011
|
const suffix = defaultValue ? ` [${defaultValue}]` : "";
|
|
11252
11012
|
const answer = (await rl.question(`${question}${suffix}: `)).trim();
|
|
11253
11013
|
return answer || defaultValue || "";
|
|
11254
11014
|
};
|
|
11255
|
-
var
|
|
11256
|
-
|
|
11257
|
-
|
|
11258
|
-
|
|
11259
|
-
|
|
11015
|
+
var askNonNegativeNumber = async (rl, question, defaultValue) => {
|
|
11016
|
+
while (true) {
|
|
11017
|
+
const answer = await ask(rl, question, String(defaultValue));
|
|
11018
|
+
const parsed = Number.parseFloat(answer);
|
|
11019
|
+
if (!Number.isNaN(parsed) && parsed >= 0) {
|
|
11020
|
+
return parsed;
|
|
11021
|
+
}
|
|
11022
|
+
printDiagnosticsToConsole("Enter a non-negative number.");
|
|
11023
|
+
}
|
|
11024
|
+
};
|
|
11025
|
+
var parseLoopChoice = (raw) => {
|
|
11026
|
+
const value = raw.trim().toLowerCase();
|
|
11027
|
+
if (!value || value === "done") {
|
|
11028
|
+
return "done";
|
|
11029
|
+
}
|
|
11030
|
+
if (value === "openapi" || value === "page" || value === "plan") {
|
|
11031
|
+
return value;
|
|
11260
11032
|
}
|
|
11261
|
-
return
|
|
11033
|
+
return null;
|
|
11262
11034
|
};
|
|
11263
11035
|
async function promptMakeConfigInteractive(defaults) {
|
|
11264
11036
|
const rl = createInterface({ input, output });
|
|
11037
|
+
const customPages = [];
|
|
11038
|
+
const planItems = [];
|
|
11039
|
+
let hasPaidPlans = false;
|
|
11040
|
+
let openApiPath;
|
|
11265
11041
|
try {
|
|
11266
11042
|
const title = await ask(rl, "Site title", defaults.title);
|
|
11267
|
-
|
|
11268
|
-
|
|
11269
|
-
rl,
|
|
11270
|
-
"Enable authentication",
|
|
11271
|
-
defaults.authEnabled
|
|
11272
|
-
);
|
|
11273
|
-
let apiBaseUrl = defaults.apiBaseUrl ?? "";
|
|
11274
|
-
if (authEnabled) {
|
|
11275
|
-
apiBaseUrl = await ask(
|
|
11043
|
+
while (true) {
|
|
11044
|
+
const choiceRaw = await ask(
|
|
11276
11045
|
rl,
|
|
11277
|
-
"
|
|
11278
|
-
|
|
11046
|
+
"Add OpenAPI, a custom page, or a plan? (openapi / page / plan / done)",
|
|
11047
|
+
"done"
|
|
11279
11048
|
);
|
|
11280
|
-
|
|
11281
|
-
|
|
11282
|
-
|
|
11283
|
-
|
|
11284
|
-
|
|
11285
|
-
|
|
11286
|
-
|
|
11287
|
-
|
|
11288
|
-
|
|
11289
|
-
|
|
11290
|
-
|
|
11291
|
-
|
|
11292
|
-
|
|
11293
|
-
|
|
11294
|
-
|
|
11295
|
-
|
|
11296
|
-
|
|
11297
|
-
|
|
11298
|
-
|
|
11299
|
-
|
|
11049
|
+
const choice = parseLoopChoice(choiceRaw);
|
|
11050
|
+
if (!choice) {
|
|
11051
|
+
printDiagnosticsToConsole("Choose openapi, page, plan, or done.");
|
|
11052
|
+
continue;
|
|
11053
|
+
}
|
|
11054
|
+
if (choice === "done") {
|
|
11055
|
+
break;
|
|
11056
|
+
}
|
|
11057
|
+
if (choice === "openapi") {
|
|
11058
|
+
const entered = await ask(
|
|
11059
|
+
rl,
|
|
11060
|
+
"OpenAPI file path (leave empty to skip)",
|
|
11061
|
+
defaults.discoveredOpenApi ?? ""
|
|
11062
|
+
);
|
|
11063
|
+
openApiPath = entered ? entered : null;
|
|
11064
|
+
if (openApiPath) {
|
|
11065
|
+
printDiagnosticsToConsole(
|
|
11066
|
+
`OpenAPI will be linked as a relative path in apitogo.config.json.`
|
|
11067
|
+
);
|
|
11068
|
+
}
|
|
11069
|
+
continue;
|
|
11070
|
+
}
|
|
11071
|
+
if (choice === "page") {
|
|
11072
|
+
const pageTitle = await ask(rl, "Page title");
|
|
11073
|
+
if (!pageTitle.trim()) {
|
|
11074
|
+
printDiagnosticsToConsole("Page title is required.");
|
|
11075
|
+
continue;
|
|
11076
|
+
}
|
|
11077
|
+
const address = await ask(
|
|
11078
|
+
rl,
|
|
11079
|
+
"Page URL path (e.g. /guides/getting-started)"
|
|
11080
|
+
);
|
|
11081
|
+
const slug = normalizePageSlug(address);
|
|
11082
|
+
if (!slug) {
|
|
11083
|
+
printDiagnosticsToConsole("Page URL path is required.");
|
|
11084
|
+
continue;
|
|
11085
|
+
}
|
|
11086
|
+
const routePath = `/${slug}`;
|
|
11087
|
+
const relativePath = path34.posix.join(defaults.pagesDir, `${slug}.tsx`);
|
|
11088
|
+
const page = {
|
|
11089
|
+
slug,
|
|
11090
|
+
title: pageTitle.trim(),
|
|
11091
|
+
routePath,
|
|
11092
|
+
relativePath
|
|
11093
|
+
};
|
|
11094
|
+
customPages.push(page);
|
|
11095
|
+
printPageAddedHint(relativePath, routePath);
|
|
11096
|
+
continue;
|
|
11097
|
+
}
|
|
11098
|
+
const displayName = await ask(rl, "Plan title");
|
|
11099
|
+
if (!displayName.trim()) {
|
|
11100
|
+
printDiagnosticsToConsole("Plan title is required.");
|
|
11101
|
+
continue;
|
|
11102
|
+
}
|
|
11103
|
+
const priceAmount = await askNonNegativeNumber(
|
|
11104
|
+
rl,
|
|
11105
|
+
"Price (USD/month, 0 for free)",
|
|
11106
|
+
0
|
|
11107
|
+
);
|
|
11108
|
+
const rateLimitCalls = await askNonNegativeNumber(
|
|
11300
11109
|
rl,
|
|
11301
|
-
|
|
11302
|
-
|
|
11110
|
+
"Rate limit (calls per minute)",
|
|
11111
|
+
100
|
|
11303
11112
|
);
|
|
11304
|
-
|
|
11305
|
-
} else {
|
|
11306
|
-
const entered = await ask(
|
|
11113
|
+
const monthlyQuota = await askNonNegativeNumber(
|
|
11307
11114
|
rl,
|
|
11308
|
-
"
|
|
11309
|
-
|
|
11115
|
+
"Monthly quota (calls per 30 days)",
|
|
11116
|
+
5e4
|
|
11310
11117
|
);
|
|
11311
|
-
|
|
11312
|
-
|
|
11313
|
-
|
|
11314
|
-
|
|
11315
|
-
|
|
11316
|
-
|
|
11317
|
-
|
|
11318
|
-
|
|
11118
|
+
const planItem = buildPlanItemFromWizard({
|
|
11119
|
+
displayName: displayName.trim(),
|
|
11120
|
+
priceAmount,
|
|
11121
|
+
rateLimitCalls,
|
|
11122
|
+
monthlyQuota
|
|
11123
|
+
});
|
|
11124
|
+
planItems.push(planItem);
|
|
11125
|
+
if (priceAmount > 0) {
|
|
11126
|
+
hasPaidPlans = true;
|
|
11127
|
+
printPaidPlanPlatformWarning();
|
|
11128
|
+
}
|
|
11129
|
+
printPlanAddedHint(displayName.trim());
|
|
11319
11130
|
}
|
|
11320
11131
|
return {
|
|
11321
11132
|
title,
|
|
11322
|
-
site: {
|
|
11323
|
-
|
|
11324
|
-
|
|
11325
|
-
|
|
11326
|
-
theme: {
|
|
11327
|
-
fonts: { sans, mono },
|
|
11328
|
-
light: { primary: lightPrimary },
|
|
11329
|
-
dark: { primary: darkPrimary }
|
|
11133
|
+
site: { title },
|
|
11134
|
+
authentication: {
|
|
11135
|
+
enabled: true,
|
|
11136
|
+
type: "dev-portal"
|
|
11330
11137
|
},
|
|
11331
|
-
|
|
11332
|
-
|
|
11138
|
+
openApiPath,
|
|
11139
|
+
customPages,
|
|
11140
|
+
planItems,
|
|
11141
|
+
hasPaidPlans
|
|
11333
11142
|
};
|
|
11334
11143
|
} finally {
|
|
11335
11144
|
rl.close();
|
|
11336
11145
|
}
|
|
11337
11146
|
}
|
|
11338
11147
|
|
|
11339
|
-
// src/cli/make-config/
|
|
11340
|
-
|
|
11341
|
-
|
|
11342
|
-
|
|
11343
|
-
|
|
11344
|
-
|
|
11345
|
-
|
|
11346
|
-
|
|
11347
|
-
|
|
11348
|
-
|
|
11349
|
-
|
|
11350
|
-
|
|
11351
|
-
|
|
11352
|
-
|
|
11353
|
-
|
|
11354
|
-
|
|
11355
|
-
|
|
11356
|
-
|
|
11357
|
-
|
|
11358
|
-
|
|
11359
|
-
|
|
11360
|
-
|
|
11361
|
-
|
|
11362
|
-
|
|
11363
|
-
|
|
11364
|
-
|
|
11365
|
-
|
|
11366
|
-
|
|
11367
|
-
|
|
11368
|
-
|
|
11369
|
-
|
|
11370
|
-
|
|
11371
|
-
|
|
11372
|
-
|
|
11373
|
-
}
|
|
11374
|
-
function titleFromDirectoryName(dirName) {
|
|
11375
|
-
const titled = dirName.split(/[-_\s]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
11376
|
-
return titled || "Developer Portal";
|
|
11377
|
-
}
|
|
11378
|
-
function createDefaultApitogoJsonConfig(options) {
|
|
11379
|
-
const filesGlob = `/${options.pagesDir}/**/*.{md,mdx}`;
|
|
11380
|
-
return {
|
|
11381
|
-
site: {
|
|
11382
|
-
title: options.title,
|
|
11383
|
-
logo: {
|
|
11384
|
-
src: { light: "/logo-light.png", dark: "/logo-dark.png" },
|
|
11385
|
-
alt: "APIToGo",
|
|
11386
|
-
width: "130px"
|
|
11387
|
-
}
|
|
11388
|
-
},
|
|
11389
|
-
authentication: {
|
|
11390
|
-
enabled: false,
|
|
11391
|
-
type: "dev-portal",
|
|
11392
|
-
redirectToAfterSignIn: "/account/dashboard",
|
|
11393
|
-
redirectToAfterSignUp: "/account/dashboard"
|
|
11394
|
-
},
|
|
11395
|
-
metadata: {
|
|
11396
|
-
favicon: "/Icon.png"
|
|
11397
|
-
},
|
|
11398
|
-
theme: {
|
|
11399
|
-
fonts: {
|
|
11400
|
-
sans: "IBM Plex Sans",
|
|
11401
|
-
mono: "JetBrains Mono"
|
|
11402
|
-
},
|
|
11403
|
-
light: {
|
|
11404
|
-
background: "#F5F6F9",
|
|
11405
|
-
foreground: "#0E1016",
|
|
11406
|
-
card: "#FFFFFF",
|
|
11407
|
-
cardForeground: "#0E1016",
|
|
11408
|
-
primary: "#E11D2A",
|
|
11409
|
-
primaryForeground: "#ffffff",
|
|
11410
|
-
secondary: "#FAFBFC",
|
|
11411
|
-
secondaryForeground: "#0E1016",
|
|
11412
|
-
muted: "#FAFBFC",
|
|
11413
|
-
mutedForeground: "#565E70",
|
|
11414
|
-
accent: "rgba(225, 29, 42, 0.08)",
|
|
11415
|
-
accentForeground: "#E11D2A",
|
|
11416
|
-
border: "#E6E8EF",
|
|
11417
|
-
input: "#D6DAE3",
|
|
11418
|
-
ring: "#E11D2A"
|
|
11419
|
-
},
|
|
11420
|
-
dark: {
|
|
11421
|
-
background: "#0B0D12",
|
|
11422
|
-
foreground: "#EDEFF5",
|
|
11423
|
-
card: "#14171F",
|
|
11424
|
-
cardForeground: "#EDEFF5",
|
|
11425
|
-
primary: "#F23645",
|
|
11426
|
-
primaryForeground: "#ffffff",
|
|
11427
|
-
secondary: "#191D27",
|
|
11428
|
-
secondaryForeground: "#EDEFF5",
|
|
11429
|
-
muted: "#191D27",
|
|
11430
|
-
mutedForeground: "#A6AEBF",
|
|
11431
|
-
accent: "rgba(242, 54, 69, 0.13)",
|
|
11432
|
-
accentForeground: "#F23645",
|
|
11433
|
-
border: "#252B37",
|
|
11434
|
-
input: "#333A48",
|
|
11435
|
-
ring: "#F23645"
|
|
11436
|
-
}
|
|
11437
|
-
},
|
|
11438
|
-
modules: {
|
|
11439
|
-
docs: {
|
|
11440
|
-
files: filesGlob
|
|
11441
|
-
},
|
|
11442
|
-
landing: {
|
|
11443
|
-
enabled: true,
|
|
11444
|
-
path: "/",
|
|
11445
|
-
layout: "landing",
|
|
11446
|
-
page: "./landing/LandingPage.tsx"
|
|
11447
|
-
},
|
|
11448
|
-
userPanel: {
|
|
11449
|
-
enabled: true,
|
|
11450
|
-
dashboard: { enabled: true },
|
|
11451
|
-
userManagement: { enabled: true },
|
|
11452
|
-
plans: {
|
|
11453
|
-
enabled: false,
|
|
11454
|
-
page: "./user-panel/AccountPlansPage.tsx"
|
|
11455
|
-
}
|
|
11456
|
-
}
|
|
11457
|
-
}
|
|
11458
|
-
};
|
|
11148
|
+
// src/cli/make-config/page-scaffold.ts
|
|
11149
|
+
function buildStarterDocsPageTsx(slug, title) {
|
|
11150
|
+
const componentName = pageComponentName(slug);
|
|
11151
|
+
const safeTitle = title.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
11152
|
+
return `import { Callout, Heading, Typography } from "@lukoweb/apitogo/components";
|
|
11153
|
+
|
|
11154
|
+
export default function ${componentName}() {
|
|
11155
|
+
return (
|
|
11156
|
+
<section className="mx-auto max-w-screen-xl px-4 py-12 pt-(--padding-content-top)">
|
|
11157
|
+
<Typography>
|
|
11158
|
+
<Heading level={1}>${safeTitle}</Heading>
|
|
11159
|
+
<p className="mt-4 text-muted-foreground">
|
|
11160
|
+
Edit this page in <code>pages/${slug}.tsx</code>.
|
|
11161
|
+
</p>
|
|
11162
|
+
<Callout type="info" title="Components">
|
|
11163
|
+
APIToGo ships predefined UI components for docs pages. See{" "}
|
|
11164
|
+
<a
|
|
11165
|
+
href="https://docs.apitogo.com/docs/guides/custom-pages"
|
|
11166
|
+
className="text-primary underline"
|
|
11167
|
+
>
|
|
11168
|
+
custom pages
|
|
11169
|
+
</a>{" "}
|
|
11170
|
+
and the{" "}
|
|
11171
|
+
<a
|
|
11172
|
+
href="https://docs.apitogo.com/docs/components/callout"
|
|
11173
|
+
className="text-primary underline"
|
|
11174
|
+
>
|
|
11175
|
+
component catalog
|
|
11176
|
+
</a>
|
|
11177
|
+
.
|
|
11178
|
+
</Callout>
|
|
11179
|
+
</Typography>
|
|
11180
|
+
</section>
|
|
11181
|
+
);
|
|
11459
11182
|
}
|
|
11460
|
-
|
|
11461
|
-
let next = { ...config2 };
|
|
11462
|
-
if (patches.site) {
|
|
11463
|
-
next.site = deepMerge(
|
|
11464
|
-
isPlainObject2(next.site) ? next.site : {},
|
|
11465
|
-
patches.site
|
|
11466
|
-
);
|
|
11467
|
-
}
|
|
11468
|
-
if (patches.theme) {
|
|
11469
|
-
next.theme = deepMerge(
|
|
11470
|
-
isPlainObject2(next.theme) ? next.theme : {},
|
|
11471
|
-
patches.theme
|
|
11472
|
-
);
|
|
11473
|
-
}
|
|
11474
|
-
if (patches.authentication) {
|
|
11475
|
-
next.authentication = deepMerge(
|
|
11476
|
-
isPlainObject2(next.authentication) ? next.authentication : {},
|
|
11477
|
-
patches.authentication
|
|
11478
|
-
);
|
|
11479
|
-
}
|
|
11480
|
-
if (patches.title?.trim()) {
|
|
11481
|
-
const site = isPlainObject2(next.site) ? next.site : {};
|
|
11482
|
-
next.site = { ...site, title: patches.title.trim() };
|
|
11483
|
-
}
|
|
11484
|
-
return next;
|
|
11183
|
+
`;
|
|
11485
11184
|
}
|
|
11486
|
-
|
|
11487
|
-
|
|
11488
|
-
|
|
11489
|
-
|
|
11490
|
-
|
|
11491
|
-
|
|
11492
|
-
|
|
11185
|
+
|
|
11186
|
+
// src/cli/make-config/scaffold-project.ts
|
|
11187
|
+
init_package_json();
|
|
11188
|
+
import { constants } from "node:fs";
|
|
11189
|
+
import { access as access2, mkdir as mkdir6, readFile as readFile4, writeFile as writeFile6 } from "node:fs/promises";
|
|
11190
|
+
import path35 from "node:path";
|
|
11191
|
+
import { glob as glob4 } from "glob";
|
|
11192
|
+
var OPENAPI_GLOBS = [
|
|
11193
|
+
"apis/openapi.json",
|
|
11194
|
+
"apis/openapi.yaml",
|
|
11195
|
+
"apis/openapi.yml",
|
|
11196
|
+
"openapi.json",
|
|
11197
|
+
"openapi.yaml",
|
|
11198
|
+
"openapi.yml"
|
|
11199
|
+
];
|
|
11200
|
+
var toPosix = (p) => p.split(path35.sep).join("/");
|
|
11201
|
+
var sanitizePackageName = (dir) => {
|
|
11202
|
+
const base = path35.basename(path35.resolve(dir));
|
|
11203
|
+
const s = base.toLowerCase().replace(/[^a-z0-9-_.]/g, "-").replace(/^-+|-+$/g, "");
|
|
11204
|
+
return s || "apitogo-site";
|
|
11493
11205
|
};
|
|
11494
|
-
var
|
|
11495
|
-
const
|
|
11496
|
-
|
|
11497
|
-
return a.localeCompare(b);
|
|
11498
|
-
});
|
|
11499
|
-
var createTreeNode = () => ({ docs: [], children: /* @__PURE__ */ new Map() });
|
|
11500
|
-
var titleCase = (value) => value.split(/[-_\s]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
11501
|
-
var buildTree = (routePaths) => {
|
|
11502
|
-
const root = createTreeNode();
|
|
11503
|
-
for (const routePath of routePaths) {
|
|
11504
|
-
const segments = routePath.replace(/^\//, "").split("/").filter(Boolean);
|
|
11505
|
-
const directorySegments = segments.slice(0, -1);
|
|
11506
|
-
let current = root;
|
|
11507
|
-
for (const segment of directorySegments) {
|
|
11508
|
-
let child = current.children.get(segment);
|
|
11509
|
-
if (!child) {
|
|
11510
|
-
child = createTreeNode();
|
|
11511
|
-
current.children.set(segment, child);
|
|
11512
|
-
}
|
|
11513
|
-
current = child;
|
|
11514
|
-
}
|
|
11515
|
-
current.docs.push(routePath);
|
|
11516
|
-
}
|
|
11517
|
-
return root;
|
|
11206
|
+
var apitogoVersionRange = () => {
|
|
11207
|
+
const v = getZudokuPackageJson()?.version;
|
|
11208
|
+
return v ? `^${v}` : "latest";
|
|
11518
11209
|
};
|
|
11519
|
-
|
|
11520
|
-
const
|
|
11521
|
-
|
|
11522
|
-
|
|
11523
|
-
|
|
11524
|
-
|
|
11210
|
+
async function findOpenApiSpecPath(dir) {
|
|
11211
|
+
for (const rel of OPENAPI_GLOBS) {
|
|
11212
|
+
const full = path35.join(dir, rel);
|
|
11213
|
+
try {
|
|
11214
|
+
await access2(full, constants.R_OK);
|
|
11215
|
+
return toPosix(rel);
|
|
11216
|
+
} catch {
|
|
11525
11217
|
}
|
|
11526
|
-
|
|
11527
|
-
|
|
11528
|
-
|
|
11529
|
-
|
|
11218
|
+
}
|
|
11219
|
+
const extra = await glob4("apis/**/*.{json,yaml,yml}", {
|
|
11220
|
+
cwd: dir,
|
|
11221
|
+
posix: true,
|
|
11222
|
+
ignore: ["**/node_modules/**"]
|
|
11223
|
+
});
|
|
11224
|
+
return extra[0] ? toPosix(extra[0]) : null;
|
|
11225
|
+
}
|
|
11226
|
+
async function ensurePackageJson(dir) {
|
|
11227
|
+
const pkgPath = path35.join(dir, "package.json");
|
|
11228
|
+
const apitogoVer = apitogoVersionRange();
|
|
11229
|
+
const baseDeps = {
|
|
11230
|
+
react: ">=19.0.0",
|
|
11231
|
+
"react-dom": ">=19.0.0",
|
|
11232
|
+
"@lukoweb/apitogo": apitogoVer,
|
|
11233
|
+
"@lukoweb/apitogo-plugin-dev-portal-billing": apitogoVer,
|
|
11234
|
+
"@lukoweb/apitogo-module-landing": apitogoVer,
|
|
11235
|
+
"@lukoweb/apitogo-module-user-panel": apitogoVer,
|
|
11236
|
+
"lucide-react": "0.577.0"
|
|
11237
|
+
};
|
|
11238
|
+
const baseScripts = {
|
|
11239
|
+
dev: "apitogo dev",
|
|
11240
|
+
build: "apitogo build",
|
|
11241
|
+
preview: "apitogo build --preview"
|
|
11242
|
+
};
|
|
11243
|
+
try {
|
|
11244
|
+
await access2(pkgPath, constants.R_OK);
|
|
11245
|
+
} catch (err) {
|
|
11246
|
+
const code = err.code;
|
|
11247
|
+
if (code !== "ENOENT") throw err;
|
|
11248
|
+
const pkg2 = {
|
|
11249
|
+
name: sanitizePackageName(dir),
|
|
11250
|
+
version: "0.1.0",
|
|
11251
|
+
private: true,
|
|
11252
|
+
type: "module",
|
|
11253
|
+
scripts: baseScripts,
|
|
11254
|
+
dependencies: baseDeps,
|
|
11255
|
+
devDependencies: {
|
|
11256
|
+
"@types/node": "^22",
|
|
11257
|
+
"@types/react": "^19",
|
|
11258
|
+
"@types/react-dom": "^19",
|
|
11259
|
+
typescript: "^5"
|
|
11260
|
+
}
|
|
11530
11261
|
};
|
|
11531
|
-
|
|
11532
|
-
|
|
11533
|
-
|
|
11534
|
-
function buildDocumentationItems(routePaths) {
|
|
11535
|
-
return treeToNavigationItems(buildTree(sortDocPaths(routePaths)));
|
|
11536
|
-
}
|
|
11537
|
-
function navItemKey(item) {
|
|
11538
|
-
if (typeof item === "string") {
|
|
11539
|
-
return `path:${item}`;
|
|
11262
|
+
await writeFile6(pkgPath, `${JSON.stringify(pkg2, null, 2)}
|
|
11263
|
+
`, "utf8");
|
|
11264
|
+
return true;
|
|
11540
11265
|
}
|
|
11541
|
-
|
|
11542
|
-
|
|
11266
|
+
const raw = await readFile4(pkgPath, "utf8");
|
|
11267
|
+
let pkg;
|
|
11268
|
+
try {
|
|
11269
|
+
pkg = JSON.parse(raw);
|
|
11270
|
+
} catch {
|
|
11271
|
+
throw new Error(
|
|
11272
|
+
"package.json exists but is not valid JSON; fix or remove it and run again."
|
|
11273
|
+
);
|
|
11543
11274
|
}
|
|
11544
|
-
|
|
11545
|
-
|
|
11275
|
+
pkg.scripts = {
|
|
11276
|
+
...typeof pkg.scripts === "object" && pkg.scripts !== null ? pkg.scripts : {}
|
|
11277
|
+
};
|
|
11278
|
+
const scripts = pkg.scripts;
|
|
11279
|
+
for (const [k, v] of Object.entries(baseScripts)) {
|
|
11280
|
+
if (!scripts[k]) scripts[k] = v;
|
|
11546
11281
|
}
|
|
11547
|
-
|
|
11548
|
-
|
|
11282
|
+
pkg.dependencies = {
|
|
11283
|
+
...typeof pkg.dependencies === "object" && pkg.dependencies !== null ? pkg.dependencies : {}
|
|
11284
|
+
};
|
|
11285
|
+
const deps = pkg.dependencies;
|
|
11286
|
+
for (const [k, v] of Object.entries(baseDeps)) {
|
|
11287
|
+
if (!deps[k]) deps[k] = v;
|
|
11549
11288
|
}
|
|
11550
|
-
|
|
11289
|
+
await writeFile6(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
11290
|
+
`, "utf8");
|
|
11291
|
+
return false;
|
|
11551
11292
|
}
|
|
11552
|
-
function
|
|
11553
|
-
const
|
|
11554
|
-
|
|
11555
|
-
|
|
11556
|
-
|
|
11557
|
-
|
|
11558
|
-
|
|
11559
|
-
|
|
11560
|
-
|
|
11561
|
-
|
|
11293
|
+
async function ensureTsconfigJson(dir) {
|
|
11294
|
+
const tsPath = path35.join(dir, "tsconfig.json");
|
|
11295
|
+
try {
|
|
11296
|
+
await access2(tsPath, constants.R_OK);
|
|
11297
|
+
return false;
|
|
11298
|
+
} catch {
|
|
11299
|
+
const tsconfig = {
|
|
11300
|
+
compilerOptions: {
|
|
11301
|
+
target: "ES2022",
|
|
11302
|
+
lib: ["ESNext", "DOM", "DOM.Iterable", "WebWorker"],
|
|
11303
|
+
module: "ESNext",
|
|
11304
|
+
moduleResolution: "Bundler",
|
|
11305
|
+
useDefineForClassFields: true,
|
|
11306
|
+
skipLibCheck: true,
|
|
11307
|
+
skipDefaultLibCheck: true,
|
|
11308
|
+
resolveJsonModule: true,
|
|
11309
|
+
isolatedModules: true,
|
|
11310
|
+
useUnknownInCatchVariables: false,
|
|
11311
|
+
jsx: "react-jsx"
|
|
11312
|
+
},
|
|
11313
|
+
include: [
|
|
11314
|
+
"*.config.ts",
|
|
11315
|
+
"*.config.tsx",
|
|
11316
|
+
"*.config.jsx",
|
|
11317
|
+
"*.config.js",
|
|
11318
|
+
"*.config.mjs",
|
|
11319
|
+
"pages",
|
|
11320
|
+
"landing",
|
|
11321
|
+
"user-panel"
|
|
11322
|
+
]
|
|
11323
|
+
};
|
|
11324
|
+
await writeFile6(tsPath, `${JSON.stringify(tsconfig, null, 2)}
|
|
11325
|
+
`, "utf8");
|
|
11326
|
+
return true;
|
|
11562
11327
|
}
|
|
11563
|
-
return merged;
|
|
11564
|
-
}
|
|
11565
|
-
function isDocumentationCategory(item) {
|
|
11566
|
-
return typeof item === "object" && item.type === "category" && item.label === DOCUMENTATION_NAV_LABEL;
|
|
11567
11328
|
}
|
|
11568
|
-
|
|
11569
|
-
|
|
11329
|
+
var LANDING_PAGE_SOURCE = `import {
|
|
11330
|
+
FeaturesSection,
|
|
11331
|
+
HeroSection,
|
|
11332
|
+
LandingShell,
|
|
11333
|
+
} from "@lukoweb/apitogo-module-landing";
|
|
11334
|
+
|
|
11335
|
+
export default function LandingPage() {
|
|
11336
|
+
return (
|
|
11337
|
+
<LandingShell
|
|
11338
|
+
title="Your API, ready for developers"
|
|
11339
|
+
description="Documentation, API reference, and a developer portal \u2014 all in one place."
|
|
11340
|
+
>
|
|
11341
|
+
<HeroSection
|
|
11342
|
+
hero={{
|
|
11343
|
+
title: "Your API, ready for developers",
|
|
11344
|
+
description:
|
|
11345
|
+
"Ship docs, interactive API reference, and a developer portal without building from scratch.",
|
|
11346
|
+
}}
|
|
11347
|
+
primaryAction={{ label: "Get started", href: "/introduction" }}
|
|
11348
|
+
secondaryAction={{ label: "API Reference", href: "/api" }}
|
|
11349
|
+
/>
|
|
11350
|
+
<FeaturesSection
|
|
11351
|
+
features={[
|
|
11352
|
+
{
|
|
11353
|
+
title: "Documentation",
|
|
11354
|
+
description: "Guides and references for every integration path.",
|
|
11355
|
+
icon: "book-open",
|
|
11356
|
+
},
|
|
11357
|
+
{
|
|
11358
|
+
title: "API Reference",
|
|
11359
|
+
description: "Interactive OpenAPI explorer with code samples.",
|
|
11360
|
+
icon: "code",
|
|
11361
|
+
},
|
|
11362
|
+
{
|
|
11363
|
+
title: "Developer Portal",
|
|
11364
|
+
description: "Auth, API keys, and subscription billing built in.",
|
|
11365
|
+
icon: "shield-check",
|
|
11366
|
+
},
|
|
11367
|
+
]}
|
|
11368
|
+
/>
|
|
11369
|
+
</LandingShell>
|
|
11370
|
+
);
|
|
11570
11371
|
}
|
|
11571
|
-
|
|
11572
|
-
|
|
11573
|
-
|
|
11574
|
-
|
|
11575
|
-
|
|
11576
|
-
|
|
11577
|
-
|
|
11578
|
-
|
|
11579
|
-
|
|
11580
|
-
label: DOCUMENTATION_NAV_LABEL,
|
|
11581
|
-
items
|
|
11582
|
-
};
|
|
11583
|
-
if (generated.length === 0) {
|
|
11584
|
-
return existing;
|
|
11372
|
+
`;
|
|
11373
|
+
var ACCOUNT_PLANS_PAGE_SOURCE = `export { AccountPlansPage as default } from "@lukoweb/apitogo-plugin-dev-portal-billing";
|
|
11374
|
+
`;
|
|
11375
|
+
var fileExists2 = async (filePath) => {
|
|
11376
|
+
try {
|
|
11377
|
+
await access2(filePath, constants.F_OK);
|
|
11378
|
+
return true;
|
|
11379
|
+
} catch {
|
|
11380
|
+
return false;
|
|
11585
11381
|
}
|
|
11586
|
-
|
|
11587
|
-
|
|
11588
|
-
|
|
11589
|
-
|
|
11590
|
-
|
|
11382
|
+
};
|
|
11383
|
+
async function ensurePortalStubFiles(dir) {
|
|
11384
|
+
const landingPath = path35.join(dir, "landing", "LandingPage.tsx");
|
|
11385
|
+
if (!await fileExists2(landingPath)) {
|
|
11386
|
+
await mkdir6(path35.join(dir, "landing"), { recursive: true });
|
|
11387
|
+
await writeFile6(landingPath, LANDING_PAGE_SOURCE, "utf8");
|
|
11388
|
+
}
|
|
11389
|
+
const plansPath = path35.join(dir, "user-panel", "AccountPlansPage.tsx");
|
|
11390
|
+
if (!await fileExists2(plansPath)) {
|
|
11391
|
+
await mkdir6(path35.join(dir, "user-panel"), { recursive: true });
|
|
11392
|
+
await writeFile6(plansPath, ACCOUNT_PLANS_PAGE_SOURCE, "utf8");
|
|
11591
11393
|
}
|
|
11592
|
-
return [documentation, ...rest];
|
|
11593
11394
|
}
|
|
11594
|
-
function
|
|
11595
|
-
const
|
|
11596
|
-
|
|
11597
|
-
|
|
11598
|
-
|
|
11599
|
-
|
|
11600
|
-
|
|
11395
|
+
async function ensureThinConfigTsx(dir) {
|
|
11396
|
+
const tsxPath = path35.join(dir, "apitogo.config.tsx");
|
|
11397
|
+
if (await fileExists2(tsxPath)) {
|
|
11398
|
+
return false;
|
|
11399
|
+
}
|
|
11400
|
+
await writeFile6(tsxPath, THIN_WRAPPER_SOURCE, "utf8");
|
|
11401
|
+
return true;
|
|
11402
|
+
}
|
|
11403
|
+
|
|
11404
|
+
// src/cli/make-config/handler.ts
|
|
11405
|
+
var toPosixPath2 = (value) => value.split(path36.sep).join(path36.posix.sep);
|
|
11406
|
+
var fileExists3 = async (filePath) => {
|
|
11407
|
+
try {
|
|
11408
|
+
await access3(filePath, constants2.F_OK);
|
|
11409
|
+
return true;
|
|
11410
|
+
} catch {
|
|
11411
|
+
return false;
|
|
11412
|
+
}
|
|
11413
|
+
};
|
|
11414
|
+
var readJsonConfig = async (filePath) => {
|
|
11415
|
+
const raw = await readFile5(filePath, "utf8");
|
|
11416
|
+
const parsed = JSON.parse(raw);
|
|
11417
|
+
if (!isPlainObject2(parsed)) {
|
|
11418
|
+
throw new Error(`${APITOGO_JSON_FILENAME} must be a JSON object.`);
|
|
11419
|
+
}
|
|
11420
|
+
return parsed;
|
|
11421
|
+
};
|
|
11422
|
+
async function makeConfig(argv) {
|
|
11423
|
+
const dir = path36.resolve(process.cwd(), argv.dir);
|
|
11424
|
+
const pagesDir = toPosixPath2(
|
|
11425
|
+
argv.pagesDir.replace(/^[./]+/, "").replace(/\/+$/, "")
|
|
11426
|
+
);
|
|
11427
|
+
try {
|
|
11428
|
+
const discoveredOpenApi = await findOpenApiSpecPath(dir);
|
|
11429
|
+
const createdPackageJson = await ensurePackageJson(dir);
|
|
11430
|
+
const createdTsconfig = await ensureTsconfigJson(dir);
|
|
11431
|
+
if (createdPackageJson) {
|
|
11432
|
+
printDiagnosticsToConsole(
|
|
11433
|
+
"Created package.json with dev, build, and preview scripts."
|
|
11434
|
+
);
|
|
11601
11435
|
}
|
|
11602
|
-
|
|
11603
|
-
|
|
11604
|
-
|
|
11605
|
-
|
|
11606
|
-
|
|
11607
|
-
|
|
11608
|
-
|
|
11436
|
+
if (createdTsconfig) {
|
|
11437
|
+
printDiagnosticsToConsole("Created tsconfig.json.");
|
|
11438
|
+
}
|
|
11439
|
+
await ensurePortalStubFiles(dir);
|
|
11440
|
+
const jsonPath = path36.join(dir, APITOGO_JSON_FILENAME);
|
|
11441
|
+
let createdJson = false;
|
|
11442
|
+
let config2;
|
|
11443
|
+
if (await fileExists3(jsonPath)) {
|
|
11444
|
+
config2 = await readJsonConfig(jsonPath);
|
|
11445
|
+
} else {
|
|
11446
|
+
config2 = createDefaultApitogoJsonConfig({
|
|
11447
|
+
title: titleFromDirectoryName(path36.basename(dir)),
|
|
11448
|
+
pagesDir
|
|
11449
|
+
});
|
|
11450
|
+
createdJson = true;
|
|
11451
|
+
printDiagnosticsToConsole(`Created ${APITOGO_JSON_FILENAME}`);
|
|
11452
|
+
}
|
|
11453
|
+
const createdTsx = await ensureThinConfigTsx(dir);
|
|
11454
|
+
if (createdTsx) {
|
|
11455
|
+
printDiagnosticsToConsole("Created apitogo.config.tsx");
|
|
11456
|
+
}
|
|
11457
|
+
const flagPatches = {
|
|
11458
|
+
site: parseJsonObjectFlag(argv.site, "site"),
|
|
11459
|
+
theme: parseJsonObjectFlag(argv.theme, "theme"),
|
|
11460
|
+
authentication: parseJsonObjectFlag(argv.authentication, "authentication"),
|
|
11461
|
+
title: argv.title
|
|
11462
|
+
};
|
|
11463
|
+
let openApiOverride;
|
|
11464
|
+
let interactiveHasPaidPlans = false;
|
|
11465
|
+
if (argv.interactive) {
|
|
11466
|
+
const site = isPlainObject2(config2.site) ? config2.site : {};
|
|
11467
|
+
const prompted = await promptMakeConfigInteractive({
|
|
11468
|
+
title: flagPatches.title ?? (typeof site.title === "string" ? site.title : titleFromDirectoryName(path36.basename(dir))),
|
|
11469
|
+
discoveredOpenApi,
|
|
11470
|
+
pagesDir
|
|
11471
|
+
});
|
|
11472
|
+
openApiOverride = prompted.openApiPath;
|
|
11473
|
+
interactiveHasPaidPlans = prompted.hasPaidPlans;
|
|
11474
|
+
config2 = applyConfigPatches(config2, prompted);
|
|
11475
|
+
config2 = applyPlansToJsonConfig(config2, prompted.planItems);
|
|
11476
|
+
for (const page of prompted.customPages) {
|
|
11477
|
+
const pagePath = path36.join(dir, page.relativePath);
|
|
11478
|
+
await mkdir7(path36.dirname(pagePath), { recursive: true });
|
|
11479
|
+
await writeFile7(
|
|
11480
|
+
pagePath,
|
|
11481
|
+
buildStarterDocsPageTsx(page.slug, page.title),
|
|
11482
|
+
"utf8"
|
|
11483
|
+
);
|
|
11484
|
+
}
|
|
11485
|
+
}
|
|
11486
|
+
config2 = applyConfigPatches(config2, flagPatches);
|
|
11487
|
+
const pageFiles = await glob5(`${pagesDir}/**/*.{md,mdx,tsx,jsx}`, {
|
|
11488
|
+
cwd: dir,
|
|
11489
|
+
ignore: ["**/node_modules/**", "**/.git/**", "**/dist/**"],
|
|
11490
|
+
posix: true
|
|
11609
11491
|
});
|
|
11492
|
+
const markdownFiles = pageFiles.filter((file) => /\.mdx?$/i.test(file));
|
|
11493
|
+
const tsxFiles = pageFiles.filter((file) => /\.(tsx|jsx)$/i.test(file));
|
|
11494
|
+
const markdownRoutes = markdownFiles.map(
|
|
11495
|
+
(file) => toRoutePath(file, pagesDir)
|
|
11496
|
+
);
|
|
11497
|
+
const tsxRoutes = tsxFiles.map((file) => toRoutePath(file, pagesDir));
|
|
11498
|
+
if (markdownRoutes.length === 0 && tsxRoutes.length === 0) {
|
|
11499
|
+
printDiagnosticsToConsole(
|
|
11500
|
+
`No docs pages under '${pagesDir}/' \u2014 skipping documentation nav scan.`
|
|
11501
|
+
);
|
|
11502
|
+
}
|
|
11503
|
+
config2.navigation = mergeDocumentationNavigation(
|
|
11504
|
+
config2.navigation,
|
|
11505
|
+
markdownRoutes,
|
|
11506
|
+
{ force: argv.force === true }
|
|
11507
|
+
);
|
|
11508
|
+
const openApiRel = openApiOverride === void 0 ? discoveredOpenApi : openApiOverride;
|
|
11509
|
+
if (openApiRel) {
|
|
11510
|
+
const openApiInput = argv.interactive ? toRelativeOpenApiInput(dir, openApiRel) : openapiInputForConfig(openApiRel);
|
|
11511
|
+
config2 = applyOpenApiToJsonConfig(config2, openApiInput);
|
|
11512
|
+
}
|
|
11513
|
+
await writeFile7(jsonPath, `${JSON.stringify(config2, null, 2)}
|
|
11514
|
+
`, "utf8");
|
|
11515
|
+
const tsxPath = path36.join(dir, "apitogo.config.tsx");
|
|
11516
|
+
if (await fileExists3(tsxPath) && tsxRoutes.length > 0) {
|
|
11517
|
+
const tsxSource = await readFile5(tsxPath, "utf8");
|
|
11518
|
+
if (isThinConfigWrapper(tsxSource)) {
|
|
11519
|
+
await writeFile7(
|
|
11520
|
+
tsxPath,
|
|
11521
|
+
buildThinWrapperWithCustomPages(tsxRoutes),
|
|
11522
|
+
"utf8"
|
|
11523
|
+
);
|
|
11524
|
+
}
|
|
11525
|
+
}
|
|
11526
|
+
const action = createdJson ? "Initialized" : "Updated";
|
|
11527
|
+
printResultToConsole(
|
|
11528
|
+
`${action} ${APITOGO_JSON_FILENAME} (site/auth/navigation/OpenAPI/plans as applicable; redirects unchanged).`
|
|
11529
|
+
);
|
|
11530
|
+
if (createdPackageJson) {
|
|
11531
|
+
printDiagnosticsToConsole(
|
|
11532
|
+
"Next: run npm install (or pnpm install / yarn) in this directory, then npm run dev."
|
|
11533
|
+
);
|
|
11534
|
+
}
|
|
11535
|
+
if (argv.interactive) {
|
|
11536
|
+
printInteractiveWrapUp(interactiveHasPaidPlans);
|
|
11537
|
+
}
|
|
11538
|
+
} catch (error) {
|
|
11539
|
+
await printCriticalFailureToConsoleAndExit(
|
|
11540
|
+
error instanceof Error ? error.message : String(error)
|
|
11541
|
+
);
|
|
11610
11542
|
}
|
|
11611
|
-
next.navigation = navigation;
|
|
11612
|
-
return next;
|
|
11613
|
-
}
|
|
11614
|
-
function openapiInputForConfig(specRelativePosix) {
|
|
11615
|
-
if (specRelativePosix.startsWith("./")) {
|
|
11616
|
-
return specRelativePosix;
|
|
11617
|
-
}
|
|
11618
|
-
return `./${specRelativePosix}`;
|
|
11619
|
-
}
|
|
11620
|
-
function toRoutePath(relativeFile, pagesDir) {
|
|
11621
|
-
const relativeNoExt = relativeFile.replace(/\.(mdx?|tsx|jsx)$/i, "");
|
|
11622
|
-
const escaped = pagesDir.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
11623
|
-
const withoutPagesPrefix = relativeNoExt.replace(
|
|
11624
|
-
new RegExp(`^${escaped}/?`),
|
|
11625
|
-
""
|
|
11626
|
-
);
|
|
11627
|
-
const normalized = withoutPagesPrefix.replace(/\/index$/, "");
|
|
11628
|
-
return `/${normalized || "index"}`;
|
|
11629
|
-
}
|
|
11630
|
-
function pageComponentName(slug) {
|
|
11631
|
-
const pascal = slug.replace(/^\/+/, "").split(/[^a-zA-Z0-9]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
11632
|
-
const name = /^[A-Za-z]/.test(pascal) ? pascal : `Page${pascal}`;
|
|
11633
|
-
return name.endsWith("Page") ? name : `${name}Page`;
|
|
11634
11543
|
}
|
|
11635
|
-
var THIN_WRAPPER_SOURCE = `import { devPortalBillingPlugin } from "@lukoweb/apitogo-plugin-dev-portal-billing";
|
|
11636
|
-
import { buildApitogoConfig } from "@lukoweb/apitogo/build-config";
|
|
11637
|
-
import siteConfig from "./apitogo.config.json";
|
|
11638
11544
|
|
|
11639
|
-
|
|
11640
|
-
|
|
11641
|
-
|
|
11642
|
-
|
|
11643
|
-
|
|
11644
|
-
|
|
11645
|
-
|
|
11646
|
-
|
|
11647
|
-
|
|
11648
|
-
|
|
11649
|
-
|
|
11545
|
+
// src/cli/cmds/config.ts
|
|
11546
|
+
var config_default = {
|
|
11547
|
+
desc: "Create or update apitogo.config.json from pages, OpenAPI, and optional site/theme/auth flags",
|
|
11548
|
+
command: "config",
|
|
11549
|
+
aliases: ["make-config"],
|
|
11550
|
+
builder: (yargs2) => yargs2.option("dir", {
|
|
11551
|
+
type: "string",
|
|
11552
|
+
describe: "The directory containing your project",
|
|
11553
|
+
default: ".",
|
|
11554
|
+
normalize: true,
|
|
11555
|
+
hidden: true
|
|
11556
|
+
}).option("pages-dir", {
|
|
11557
|
+
type: "string",
|
|
11558
|
+
describe: "Directory to scan for md/mdx/tsx pages",
|
|
11559
|
+
default: "pages"
|
|
11560
|
+
}).option("interactive", {
|
|
11561
|
+
alias: "i",
|
|
11562
|
+
type: "boolean",
|
|
11563
|
+
describe: "Interactive wizard: site title, OpenAPI path, custom pages, and gateway plans",
|
|
11564
|
+
default: false
|
|
11565
|
+
}).option("site", {
|
|
11566
|
+
type: "string",
|
|
11567
|
+
describe: "JSON object merged into site"
|
|
11568
|
+
}).option("theme", {
|
|
11569
|
+
type: "string",
|
|
11570
|
+
describe: "JSON object merged into theme"
|
|
11571
|
+
}).option("authentication", {
|
|
11572
|
+
type: "string",
|
|
11573
|
+
describe: "JSON object merged into authentication"
|
|
11574
|
+
}).option("title", {
|
|
11575
|
+
type: "string",
|
|
11576
|
+
describe: "Set site.title"
|
|
11577
|
+
}).option("force", {
|
|
11578
|
+
type: "boolean",
|
|
11579
|
+
describe: "Replace Documentation nav items from disk (keeps API Reference)",
|
|
11580
|
+
default: false
|
|
11581
|
+
}),
|
|
11582
|
+
handler: async (argv) => {
|
|
11583
|
+
await captureEvent({ argv, event: "apitogo config" });
|
|
11584
|
+
await makeConfig(argv);
|
|
11650
11585
|
}
|
|
11651
|
-
|
|
11652
|
-
const slug = routePath.replace(/^\//, "");
|
|
11653
|
-
const name = pageComponentName(slug);
|
|
11654
|
-
return `import ${name} from "./pages/${slug}";`;
|
|
11655
|
-
}).join("\n");
|
|
11656
|
-
const customPages = tsxRoutePaths.map((routePath) => {
|
|
11657
|
-
const slug = routePath.replace(/^\//, "");
|
|
11658
|
-
const name = pageComponentName(slug);
|
|
11659
|
-
return ` {
|
|
11660
|
-
type: "custom-page",
|
|
11661
|
-
path: ${JSON.stringify(routePath)},
|
|
11662
|
-
element: <${name} />,
|
|
11663
|
-
},`;
|
|
11664
|
-
}).join("\n");
|
|
11665
|
-
return `${imports}
|
|
11666
|
-
import { devPortalBillingPlugin } from "@lukoweb/apitogo-plugin-dev-portal-billing";
|
|
11667
|
-
import { buildApitogoConfig } from "@lukoweb/apitogo/build-config";
|
|
11668
|
-
import siteConfig from "./apitogo.config.json";
|
|
11586
|
+
};
|
|
11669
11587
|
|
|
11670
|
-
|
|
11671
|
-
|
|
11672
|
-
|
|
11673
|
-
|
|
11588
|
+
// src/cli/cmds/configure-github-workflow.ts
|
|
11589
|
+
var REMOVED = "apitogo configure-github-workflow was removed. Multi-env SWA deploy is deprecated; use `apitogo apply`.";
|
|
11590
|
+
var configure_github_workflow_default = {
|
|
11591
|
+
desc: "Removed \u2014 multi-env SWA deploy is deprecated",
|
|
11592
|
+
command: "configure-github-workflow",
|
|
11593
|
+
builder: (yargs2) => yargs2,
|
|
11594
|
+
handler: async (argv) => {
|
|
11595
|
+
await captureEvent({
|
|
11596
|
+
argv,
|
|
11597
|
+
event: "apitogo configure-github-workflow removed"
|
|
11598
|
+
});
|
|
11599
|
+
await printCriticalFailureToConsoleAndExit(REMOVED);
|
|
11600
|
+
}
|
|
11601
|
+
};
|
|
11674
11602
|
|
|
11675
|
-
|
|
11676
|
-
|
|
11677
|
-
|
|
11678
|
-
|
|
11679
|
-
|
|
11680
|
-
|
|
11681
|
-
|
|
11682
|
-
|
|
11683
|
-
|
|
11684
|
-
|
|
11685
|
-
typeof item === "object" &&
|
|
11686
|
-
item !== null &&
|
|
11687
|
-
"label" in item &&
|
|
11688
|
-
item.label === ${JSON.stringify(DOCUMENTATION_NAV_LABEL)},
|
|
11689
|
-
) as { items?: unknown[] } | undefined)?.items ?? []),
|
|
11690
|
-
],
|
|
11691
|
-
},
|
|
11692
|
-
...(config.navigation ?? []).filter(
|
|
11693
|
-
(item) =>
|
|
11694
|
-
!(
|
|
11695
|
-
typeof item === "object" &&
|
|
11696
|
-
item !== null &&
|
|
11697
|
-
"label" in item &&
|
|
11698
|
-
item.label === ${JSON.stringify(DOCUMENTATION_NAV_LABEL)}
|
|
11699
|
-
),
|
|
11700
|
-
),
|
|
11701
|
-
],
|
|
11603
|
+
// src/cli/cmds/deploy.ts
|
|
11604
|
+
var REMOVED2 = "apitogo deploy was removed. Use `apitogo apply` (optionally `--only portal-frontend`).";
|
|
11605
|
+
var deploy_default = {
|
|
11606
|
+
desc: "Removed \u2014 use apitogo apply",
|
|
11607
|
+
command: "deploy",
|
|
11608
|
+
builder: (yargs2) => yargs2,
|
|
11609
|
+
handler: async (argv) => {
|
|
11610
|
+
await captureEvent({ argv, event: "apitogo deploy removed" });
|
|
11611
|
+
await printCriticalFailureToConsoleAndExit(REMOVED2);
|
|
11612
|
+
}
|
|
11702
11613
|
};
|
|
11703
|
-
`;
|
|
11704
|
-
}
|
|
11705
11614
|
|
|
11706
|
-
// src/cli/
|
|
11707
|
-
|
|
11708
|
-
import
|
|
11709
|
-
|
|
11615
|
+
// src/cli/dev/handler.ts
|
|
11616
|
+
init_joinUrl();
|
|
11617
|
+
import path39 from "node:path";
|
|
11618
|
+
|
|
11619
|
+
// src/vite/dev-server.ts
|
|
11620
|
+
init_logger();
|
|
11621
|
+
import fs4 from "node:fs/promises";
|
|
11622
|
+
import http from "node:http";
|
|
11623
|
+
import https from "node:https";
|
|
11710
11624
|
import path38 from "node:path";
|
|
11711
|
-
import {
|
|
11712
|
-
|
|
11713
|
-
|
|
11714
|
-
|
|
11715
|
-
|
|
11716
|
-
|
|
11717
|
-
|
|
11718
|
-
|
|
11719
|
-
|
|
11720
|
-
var
|
|
11721
|
-
|
|
11722
|
-
|
|
11723
|
-
|
|
11724
|
-
|
|
11725
|
-
|
|
11726
|
-
|
|
11727
|
-
|
|
11728
|
-
|
|
11729
|
-
|
|
11730
|
-
|
|
11731
|
-
for (
|
|
11732
|
-
|
|
11733
|
-
|
|
11734
|
-
|
|
11735
|
-
|
|
11736
|
-
|
|
11737
|
-
|
|
11625
|
+
import { createHttpTerminator } from "http-terminator";
|
|
11626
|
+
import {
|
|
11627
|
+
createServer as createViteServer,
|
|
11628
|
+
isRunnableDevEnvironment as isRunnableDevEnvironment2,
|
|
11629
|
+
mergeConfig as mergeConfig4
|
|
11630
|
+
} from "vite";
|
|
11631
|
+
|
|
11632
|
+
// src/cli/common/utils/ports.ts
|
|
11633
|
+
import net from "node:net";
|
|
11634
|
+
var isPortAvailable = (port) => new Promise((resolve) => {
|
|
11635
|
+
const server = net.createServer();
|
|
11636
|
+
server.unref();
|
|
11637
|
+
server.once("error", () => resolve(false));
|
|
11638
|
+
server.listen(port, () => {
|
|
11639
|
+
server.close();
|
|
11640
|
+
resolve(true);
|
|
11641
|
+
});
|
|
11642
|
+
});
|
|
11643
|
+
async function findAvailablePort(startPort) {
|
|
11644
|
+
let port = startPort;
|
|
11645
|
+
for (; port < startPort + 1e3; port++) {
|
|
11646
|
+
if (await isPortAvailable(port)) break;
|
|
11647
|
+
}
|
|
11648
|
+
return port;
|
|
11649
|
+
}
|
|
11650
|
+
|
|
11651
|
+
// src/vite/dev-server.ts
|
|
11652
|
+
init_loader();
|
|
11653
|
+
|
|
11654
|
+
// src/vite/pagefind-dev-index.ts
|
|
11655
|
+
init_invariant();
|
|
11656
|
+
init_joinUrl();
|
|
11657
|
+
import path37 from "node:path";
|
|
11658
|
+
import { createIndex as createIndex2 } from "pagefind";
|
|
11659
|
+
import { isRunnableDevEnvironment } from "vite";
|
|
11660
|
+
async function* buildPagefindDevIndex(vite, config2) {
|
|
11661
|
+
const { index, errors } = await createIndex2();
|
|
11662
|
+
invariant(index, `Failed to create pagefind index: ${errors.join(", ")}`);
|
|
11663
|
+
const pagefindIndex = index;
|
|
11664
|
+
const ssrEnvironment = vite.environments.ssr;
|
|
11665
|
+
if (!isRunnableDevEnvironment(ssrEnvironment)) {
|
|
11666
|
+
throw new Error("SSR environment is not runnable");
|
|
11738
11667
|
}
|
|
11739
|
-
const
|
|
11740
|
-
|
|
11741
|
-
|
|
11742
|
-
|
|
11668
|
+
const serverModule = await ssrEnvironment.runner.import(
|
|
11669
|
+
getAppServerEntryPath()
|
|
11670
|
+
);
|
|
11671
|
+
const routes = serverModule.getRoutesByConfig(config2);
|
|
11672
|
+
const paths = routesToPaths(routes);
|
|
11673
|
+
const { basePath } = config2;
|
|
11674
|
+
const template = getDevHtml({
|
|
11675
|
+
jsEntry: "/__z/entry.client.tsx",
|
|
11676
|
+
dir: config2.site?.dir
|
|
11743
11677
|
});
|
|
11744
|
-
|
|
11745
|
-
|
|
11746
|
-
|
|
11747
|
-
|
|
11748
|
-
|
|
11749
|
-
|
|
11750
|
-
|
|
11751
|
-
|
|
11752
|
-
|
|
11753
|
-
|
|
11754
|
-
|
|
11755
|
-
|
|
11756
|
-
|
|
11757
|
-
|
|
11758
|
-
|
|
11759
|
-
|
|
11760
|
-
|
|
11761
|
-
|
|
11762
|
-
|
|
11763
|
-
|
|
11764
|
-
|
|
11765
|
-
} catch (err) {
|
|
11766
|
-
const code = err.code;
|
|
11767
|
-
if (code !== "ENOENT") throw err;
|
|
11768
|
-
const pkg2 = {
|
|
11769
|
-
name: sanitizePackageName(dir),
|
|
11770
|
-
version: "0.1.0",
|
|
11771
|
-
private: true,
|
|
11772
|
-
type: "module",
|
|
11773
|
-
scripts: baseScripts,
|
|
11774
|
-
dependencies: baseDeps,
|
|
11775
|
-
devDependencies: {
|
|
11776
|
-
"@types/node": "^22",
|
|
11777
|
-
"@types/react": "^19",
|
|
11778
|
-
"@types/react-dom": "^19",
|
|
11779
|
-
typescript: "^5"
|
|
11678
|
+
const transformedTemplate = await vite.transformIndexHtml("/", template);
|
|
11679
|
+
let indexed = 0;
|
|
11680
|
+
for (const urlPath of paths) {
|
|
11681
|
+
try {
|
|
11682
|
+
const pathname = joinUrl(basePath, urlPath);
|
|
11683
|
+
const url = joinUrl("http://localhost", pathname);
|
|
11684
|
+
const request = new Request(url);
|
|
11685
|
+
const response = await serverModule.handleRequest({
|
|
11686
|
+
template: transformedTemplate,
|
|
11687
|
+
request,
|
|
11688
|
+
routes,
|
|
11689
|
+
basePath,
|
|
11690
|
+
bypassProtection: true
|
|
11691
|
+
});
|
|
11692
|
+
if (response.status < 400 && response.body) {
|
|
11693
|
+
const content = await response.text();
|
|
11694
|
+
await pagefindIndex.addHTMLFile({
|
|
11695
|
+
url: urlPath,
|
|
11696
|
+
content
|
|
11697
|
+
});
|
|
11698
|
+
indexed++;
|
|
11780
11699
|
}
|
|
11700
|
+
} catch (error) {
|
|
11701
|
+
console.error(`Failed to index ${urlPath}:`, error);
|
|
11702
|
+
}
|
|
11703
|
+
yield {
|
|
11704
|
+
type: "progress",
|
|
11705
|
+
total: paths.length,
|
|
11706
|
+
current: indexed,
|
|
11707
|
+
path: urlPath
|
|
11781
11708
|
};
|
|
11782
|
-
await writeFile7(pkgPath, `${JSON.stringify(pkg2, null, 2)}
|
|
11783
|
-
`, "utf8");
|
|
11784
|
-
return true;
|
|
11785
|
-
}
|
|
11786
|
-
const raw = await readFile5(pkgPath, "utf8");
|
|
11787
|
-
let pkg;
|
|
11788
|
-
try {
|
|
11789
|
-
pkg = JSON.parse(raw);
|
|
11790
|
-
} catch {
|
|
11791
|
-
throw new Error(
|
|
11792
|
-
"package.json exists but is not valid JSON; fix or remove it and run again."
|
|
11793
|
-
);
|
|
11794
11709
|
}
|
|
11795
|
-
|
|
11796
|
-
|
|
11797
|
-
};
|
|
11798
|
-
|
|
11799
|
-
|
|
11800
|
-
|
|
11710
|
+
const outputPath = path37.join(vite.config.publicDir, "pagefind");
|
|
11711
|
+
await pagefindIndex.writeFiles({ outputPath });
|
|
11712
|
+
yield { type: "complete", success: true, indexed };
|
|
11713
|
+
}
|
|
11714
|
+
|
|
11715
|
+
// src/vite/dev-server.ts
|
|
11716
|
+
var DEFAULT_DEV_PORT = 3e3;
|
|
11717
|
+
var DevServer = class {
|
|
11718
|
+
constructor(options) {
|
|
11719
|
+
this.options = options;
|
|
11801
11720
|
}
|
|
11802
|
-
|
|
11803
|
-
|
|
11804
|
-
|
|
11805
|
-
|
|
11806
|
-
|
|
11807
|
-
|
|
11721
|
+
terminator;
|
|
11722
|
+
resolvedPort = 0;
|
|
11723
|
+
protocol = "http";
|
|
11724
|
+
async createNodeServer(config2) {
|
|
11725
|
+
if (!config2.https) return http.createServer();
|
|
11726
|
+
this.protocol = "https";
|
|
11727
|
+
const { dir } = this.options;
|
|
11728
|
+
const [key, cert, ca] = await Promise.all([
|
|
11729
|
+
fs4.readFile(path38.resolve(dir, config2.https.key)),
|
|
11730
|
+
fs4.readFile(path38.resolve(dir, config2.https.cert)),
|
|
11731
|
+
config2.https.ca ? fs4.readFile(path38.resolve(dir, config2.https.ca)) : void 0
|
|
11732
|
+
]);
|
|
11733
|
+
return https.createServer({ key, cert, ca });
|
|
11808
11734
|
}
|
|
11809
|
-
|
|
11810
|
-
|
|
11811
|
-
|
|
11812
|
-
|
|
11813
|
-
|
|
11814
|
-
|
|
11815
|
-
|
|
11816
|
-
await
|
|
11817
|
-
|
|
11818
|
-
|
|
11819
|
-
|
|
11820
|
-
|
|
11821
|
-
|
|
11822
|
-
|
|
11823
|
-
|
|
11824
|
-
|
|
11825
|
-
|
|
11826
|
-
|
|
11827
|
-
|
|
11828
|
-
|
|
11829
|
-
|
|
11830
|
-
|
|
11831
|
-
jsx: "react-jsx"
|
|
11735
|
+
async start() {
|
|
11736
|
+
const configEnv = {
|
|
11737
|
+
mode: "development",
|
|
11738
|
+
command: "serve",
|
|
11739
|
+
isSsrBuild: this.options.ssr
|
|
11740
|
+
};
|
|
11741
|
+
const viteConfig = await getViteConfig(this.options.dir, configEnv);
|
|
11742
|
+
const { config: config2 } = await loadZudokuConfig(configEnv, this.options.dir);
|
|
11743
|
+
this.resolvedPort = await findAvailablePort(
|
|
11744
|
+
this.options.argPort ?? config2.port ?? DEFAULT_DEV_PORT
|
|
11745
|
+
);
|
|
11746
|
+
const server = await this.createNodeServer(config2);
|
|
11747
|
+
if (config2.search?.type === "pagefind" && viteConfig.publicDir !== false) {
|
|
11748
|
+
const publicRoot = path38.resolve(
|
|
11749
|
+
this.options.dir,
|
|
11750
|
+
typeof viteConfig.publicDir === "string" ? viteConfig.publicDir : "public"
|
|
11751
|
+
);
|
|
11752
|
+
await ensurePagefindDevStub(publicRoot);
|
|
11753
|
+
}
|
|
11754
|
+
const mergedViteConfig = mergeConfig4(viteConfig, {
|
|
11755
|
+
server: {
|
|
11756
|
+
hmr: { server }
|
|
11832
11757
|
},
|
|
11833
|
-
|
|
11834
|
-
|
|
11835
|
-
|
|
11836
|
-
|
|
11837
|
-
|
|
11838
|
-
|
|
11839
|
-
|
|
11840
|
-
|
|
11841
|
-
|
|
11758
|
+
plugins: [
|
|
11759
|
+
{
|
|
11760
|
+
// Serves the client entry via Vite's client transform pipeline.
|
|
11761
|
+
// Must be registered via configureServer so it runs before Vite's
|
|
11762
|
+
// built-in transform middleware which would treat the path as a static asset.
|
|
11763
|
+
name: "apitogo:entry-client",
|
|
11764
|
+
configureServer(server2) {
|
|
11765
|
+
const entryPath = path38.posix.join(
|
|
11766
|
+
server2.config.base,
|
|
11767
|
+
"/__z/entry.client.tsx"
|
|
11768
|
+
);
|
|
11769
|
+
server2.middlewares.use(entryPath, async (_req, res) => {
|
|
11770
|
+
const transformed = await server2.environments.client.transformRequest(
|
|
11771
|
+
getAppClientEntryPath()
|
|
11772
|
+
);
|
|
11773
|
+
if (!transformed) {
|
|
11774
|
+
res.writeHead(500);
|
|
11775
|
+
res.end("Error transforming client entry");
|
|
11776
|
+
return;
|
|
11777
|
+
}
|
|
11778
|
+
res.writeHead(200, { "Content-Type": "text/javascript" });
|
|
11779
|
+
res.end(transformed.code);
|
|
11780
|
+
});
|
|
11781
|
+
}
|
|
11782
|
+
}
|
|
11842
11783
|
]
|
|
11843
|
-
};
|
|
11844
|
-
|
|
11845
|
-
|
|
11846
|
-
|
|
11784
|
+
});
|
|
11785
|
+
const vite = await createViteServer(mergedViteConfig);
|
|
11786
|
+
const graphql = createGraphQLServer({ graphqlEndpoint: "/__z/graphql" });
|
|
11787
|
+
vite.middlewares.use((req, res, next) => {
|
|
11788
|
+
if (req.method === "GET" && req.originalUrl === "/" && config2.basePath && config2.basePath !== "/") {
|
|
11789
|
+
res.writeHead(307, { Location: config2.basePath });
|
|
11790
|
+
res.end();
|
|
11791
|
+
return;
|
|
11792
|
+
}
|
|
11793
|
+
next();
|
|
11794
|
+
});
|
|
11795
|
+
vite.middlewares.use(graphql.graphqlEndpoint, graphql);
|
|
11796
|
+
vite.middlewares.use("/__z/pagefind-reindex", async (_req, res) => {
|
|
11797
|
+
res.writeHead(200, {
|
|
11798
|
+
"Content-Type": "text/event-stream",
|
|
11799
|
+
"Cache-Control": "no-cache",
|
|
11800
|
+
Connection: "keep-alive"
|
|
11801
|
+
});
|
|
11802
|
+
const { config: currentConfig } = await loadZudokuConfig(
|
|
11803
|
+
configEnv,
|
|
11804
|
+
this.options.dir
|
|
11805
|
+
);
|
|
11806
|
+
const sendEvent = (data) => res.write(`data: ${JSON.stringify(data)}
|
|
11807
|
+
|
|
11808
|
+
`);
|
|
11809
|
+
if (currentConfig.search?.type !== "pagefind") {
|
|
11810
|
+
sendEvent({
|
|
11811
|
+
type: "complete",
|
|
11812
|
+
success: false,
|
|
11813
|
+
indexed: 0,
|
|
11814
|
+
error: "Pagefind search is not enabled"
|
|
11815
|
+
});
|
|
11816
|
+
res.end();
|
|
11817
|
+
return;
|
|
11818
|
+
}
|
|
11819
|
+
try {
|
|
11820
|
+
for await (const event of buildPagefindDevIndex(vite, currentConfig)) {
|
|
11821
|
+
sendEvent(event);
|
|
11822
|
+
}
|
|
11823
|
+
} catch (error) {
|
|
11824
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
11825
|
+
sendEvent({
|
|
11826
|
+
type: "complete",
|
|
11827
|
+
success: false,
|
|
11828
|
+
indexed: 0,
|
|
11829
|
+
error: message
|
|
11830
|
+
});
|
|
11831
|
+
}
|
|
11832
|
+
res.end();
|
|
11833
|
+
});
|
|
11834
|
+
printDiagnosticsToConsole(
|
|
11835
|
+
`Server-side rendering ${this.options.ssr ? "enabled" : "disabled"}`
|
|
11836
|
+
);
|
|
11837
|
+
if (config2.search?.type === "pagefind" && vite.config.publicDir) {
|
|
11838
|
+
await ensurePagefindDevStub(vite.config.publicDir);
|
|
11839
|
+
}
|
|
11840
|
+
vite.middlewares.use(async (req, res) => {
|
|
11841
|
+
const url = req.originalUrl ?? req.url ?? "/";
|
|
11842
|
+
const ssrEnvironment = vite.environments.ssr;
|
|
11843
|
+
if (!isRunnableDevEnvironment2(ssrEnvironment)) {
|
|
11844
|
+
res.writeHead(500);
|
|
11845
|
+
res.end("SSR environment not available");
|
|
11846
|
+
return;
|
|
11847
|
+
}
|
|
11848
|
+
try {
|
|
11849
|
+
const { config: currentConfig } = await loadZudokuConfig(
|
|
11850
|
+
configEnv,
|
|
11851
|
+
this.options.dir
|
|
11852
|
+
);
|
|
11853
|
+
const rawHtml = getDevHtml({
|
|
11854
|
+
jsEntry: "/__z/entry.client.tsx",
|
|
11855
|
+
dir: currentConfig.site?.dir
|
|
11856
|
+
});
|
|
11857
|
+
const template = await vite.transformIndexHtml(url, rawHtml);
|
|
11858
|
+
if (this.options.ssr) {
|
|
11859
|
+
const entryServer = await ssrEnvironment.runner.import(
|
|
11860
|
+
getAppServerEntryPath()
|
|
11861
|
+
);
|
|
11862
|
+
const hasBody = req.method !== "GET" && req.method !== "HEAD";
|
|
11863
|
+
const request = new Request(
|
|
11864
|
+
`${this.protocol}://${req.headers.host}${url}`,
|
|
11865
|
+
{
|
|
11866
|
+
method: req.method,
|
|
11867
|
+
headers: req.headers,
|
|
11868
|
+
body: hasBody ? req : void 0,
|
|
11869
|
+
// Required by Node when body is a readable stream
|
|
11870
|
+
// @ts-expect-error Missing type definition
|
|
11871
|
+
duplex: hasBody ? "half" : void 0
|
|
11872
|
+
}
|
|
11873
|
+
);
|
|
11874
|
+
const response = await entryServer.handleRequest({
|
|
11875
|
+
template,
|
|
11876
|
+
request,
|
|
11877
|
+
routes: entryServer.getRoutesByConfig(currentConfig),
|
|
11878
|
+
basePath: currentConfig.basePath
|
|
11879
|
+
});
|
|
11880
|
+
for (const [key, value] of response.headers) {
|
|
11881
|
+
res.appendHeader(key, value);
|
|
11882
|
+
}
|
|
11883
|
+
res.writeHead(response.status);
|
|
11884
|
+
for await (const chunk of response.body ?? []) {
|
|
11885
|
+
res.write(chunk);
|
|
11886
|
+
}
|
|
11887
|
+
res.end();
|
|
11888
|
+
} else {
|
|
11889
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
11890
|
+
res.end(template);
|
|
11891
|
+
}
|
|
11892
|
+
} catch (e) {
|
|
11893
|
+
logger.error(e);
|
|
11894
|
+
const html = `<!DOCTYPE html><html><body><script type="module">
|
|
11895
|
+
import { ErrorOverlay } from '/@vite/client';
|
|
11896
|
+
document.body.appendChild(new ErrorOverlay(${JSON.stringify({
|
|
11897
|
+
message: e instanceof Error ? e.message : String(e),
|
|
11898
|
+
stack: e instanceof Error ? e.stack : ""
|
|
11899
|
+
})}));
|
|
11900
|
+
</script></body></html>`;
|
|
11901
|
+
res.writeHead(500, { "Content-Type": "text/html" });
|
|
11902
|
+
res.end(html);
|
|
11903
|
+
}
|
|
11904
|
+
});
|
|
11905
|
+
server.on("request", vite.middlewares);
|
|
11906
|
+
await new Promise((resolve) => {
|
|
11907
|
+
server.listen(this.resolvedPort, resolve);
|
|
11908
|
+
});
|
|
11909
|
+
this.terminator = createHttpTerminator({ server });
|
|
11910
|
+
if (this.options.open || process.env.ZUDOKU_OPEN_BROWSER) {
|
|
11911
|
+
const url = `${this.protocol}://localhost:${this.resolvedPort}`;
|
|
11912
|
+
vite.resolvedUrls = {
|
|
11913
|
+
local: [`${url}${vite.config.base || "/"}`],
|
|
11914
|
+
network: []
|
|
11915
|
+
};
|
|
11916
|
+
vite.openBrowser();
|
|
11917
|
+
}
|
|
11918
|
+
return { vite };
|
|
11847
11919
|
}
|
|
11848
|
-
|
|
11849
|
-
|
|
11850
|
-
FeaturesSection,
|
|
11851
|
-
HeroSection,
|
|
11852
|
-
LandingShell,
|
|
11853
|
-
} from "@lukoweb/apitogo-module-landing";
|
|
11854
|
-
|
|
11855
|
-
export default function LandingPage() {
|
|
11856
|
-
return (
|
|
11857
|
-
<LandingShell
|
|
11858
|
-
title="Your API, ready for developers"
|
|
11859
|
-
description="Documentation, API reference, and a developer portal \u2014 all in one place."
|
|
11860
|
-
>
|
|
11861
|
-
<HeroSection
|
|
11862
|
-
hero={{
|
|
11863
|
-
title: "Your API, ready for developers",
|
|
11864
|
-
description:
|
|
11865
|
-
"Ship docs, interactive API reference, and a developer portal without building from scratch.",
|
|
11866
|
-
}}
|
|
11867
|
-
primaryAction={{ label: "Get started", href: "/introduction" }}
|
|
11868
|
-
secondaryAction={{ label: "API Reference", href: "/api" }}
|
|
11869
|
-
/>
|
|
11870
|
-
<FeaturesSection
|
|
11871
|
-
features={[
|
|
11872
|
-
{
|
|
11873
|
-
title: "Documentation",
|
|
11874
|
-
description: "Guides and references for every integration path.",
|
|
11875
|
-
icon: "book-open",
|
|
11876
|
-
},
|
|
11877
|
-
{
|
|
11878
|
-
title: "API Reference",
|
|
11879
|
-
description: "Interactive OpenAPI explorer with code samples.",
|
|
11880
|
-
icon: "code",
|
|
11881
|
-
},
|
|
11882
|
-
{
|
|
11883
|
-
title: "Developer Portal",
|
|
11884
|
-
description: "Auth, API keys, and subscription billing built in.",
|
|
11885
|
-
icon: "shield-check",
|
|
11886
|
-
},
|
|
11887
|
-
]}
|
|
11888
|
-
/>
|
|
11889
|
-
</LandingShell>
|
|
11890
|
-
);
|
|
11891
|
-
}
|
|
11892
|
-
`;
|
|
11893
|
-
var ACCOUNT_PLANS_PAGE_SOURCE = `export { AccountPlansPage as default } from "@lukoweb/apitogo-plugin-dev-portal-billing";
|
|
11894
|
-
`;
|
|
11895
|
-
var fileExists2 = async (filePath) => {
|
|
11896
|
-
try {
|
|
11897
|
-
await access4(filePath, constants2.F_OK);
|
|
11898
|
-
return true;
|
|
11899
|
-
} catch {
|
|
11900
|
-
return false;
|
|
11920
|
+
async stop() {
|
|
11921
|
+
await this.terminator?.terminate();
|
|
11901
11922
|
}
|
|
11902
11923
|
};
|
|
11903
|
-
async function ensurePortalStubFiles(dir) {
|
|
11904
|
-
const landingPath = path38.join(dir, "landing", "LandingPage.tsx");
|
|
11905
|
-
if (!await fileExists2(landingPath)) {
|
|
11906
|
-
await mkdir7(path38.join(dir, "landing"), { recursive: true });
|
|
11907
|
-
await writeFile7(landingPath, LANDING_PAGE_SOURCE, "utf8");
|
|
11908
|
-
}
|
|
11909
|
-
const plansPath = path38.join(dir, "user-panel", "AccountPlansPage.tsx");
|
|
11910
|
-
if (!await fileExists2(plansPath)) {
|
|
11911
|
-
await mkdir7(path38.join(dir, "user-panel"), { recursive: true });
|
|
11912
|
-
await writeFile7(plansPath, ACCOUNT_PLANS_PAGE_SOURCE, "utf8");
|
|
11913
|
-
}
|
|
11914
|
-
}
|
|
11915
|
-
async function ensureThinConfigTsx(dir) {
|
|
11916
|
-
const tsxPath = path38.join(dir, "apitogo.config.tsx");
|
|
11917
|
-
if (await fileExists2(tsxPath)) {
|
|
11918
|
-
return false;
|
|
11919
|
-
}
|
|
11920
|
-
await writeFile7(tsxPath, THIN_WRAPPER_SOURCE, "utf8");
|
|
11921
|
-
return true;
|
|
11922
|
-
}
|
|
11923
11924
|
|
|
11924
|
-
// src/cli/
|
|
11925
|
-
|
|
11926
|
-
|
|
11927
|
-
|
|
11928
|
-
|
|
11929
|
-
|
|
11930
|
-
|
|
11931
|
-
return false;
|
|
11932
|
-
}
|
|
11933
|
-
};
|
|
11934
|
-
var ensureApitogoDeployWorkflow = async (dir) => {
|
|
11935
|
-
const workflowPath = path39.join(
|
|
11925
|
+
// src/cli/dev/handler.ts
|
|
11926
|
+
init_package_json();
|
|
11927
|
+
async function dev(argv) {
|
|
11928
|
+
const packageJson2 = getZudokuPackageJson();
|
|
11929
|
+
process.env.NODE_ENV = "development";
|
|
11930
|
+
const dir = path39.resolve(process.cwd(), argv.dir);
|
|
11931
|
+
const server = new DevServer({
|
|
11936
11932
|
dir,
|
|
11937
|
-
|
|
11938
|
-
|
|
11939
|
-
|
|
11933
|
+
argPort: argv.port,
|
|
11934
|
+
ssr: argv.ssr,
|
|
11935
|
+
open: argv.open
|
|
11936
|
+
});
|
|
11937
|
+
const { vite } = await server.start();
|
|
11938
|
+
const url = joinUrl(
|
|
11939
|
+
`${server.protocol}://localhost:${server.resolvedPort}`,
|
|
11940
|
+
vite.config.base
|
|
11940
11941
|
);
|
|
11941
|
-
|
|
11942
|
-
|
|
11943
|
-
|
|
11944
|
-
|
|
11945
|
-
await writeFile8(workflowPath, APITOGO_DEPLOY_WORKFLOW_YAML, "utf8");
|
|
11946
|
-
return true;
|
|
11947
|
-
};
|
|
11948
|
-
var readJsonConfig = async (filePath) => {
|
|
11949
|
-
const raw = await readFile6(filePath, "utf8");
|
|
11950
|
-
const parsed = JSON.parse(raw);
|
|
11951
|
-
if (!isPlainObject2(parsed)) {
|
|
11952
|
-
throw new Error(`${APITOGO_JSON_FILENAME} must be a JSON object.`);
|
|
11953
|
-
}
|
|
11954
|
-
return parsed;
|
|
11955
|
-
};
|
|
11956
|
-
async function makeConfig(argv) {
|
|
11957
|
-
const dir = path39.resolve(process.cwd(), argv.dir);
|
|
11958
|
-
const pagesDir = toPosixPath2(
|
|
11959
|
-
argv.pagesDir.replace(/^[./]+/, "").replace(/\/+$/, "")
|
|
11942
|
+
printDiagnosticsToConsole("Ctrl+C to exit");
|
|
11943
|
+
printDiagnosticsToConsole("");
|
|
11944
|
+
printDiagnosticsToConsole(
|
|
11945
|
+
`\u{1F680} Running APIToGo v${packageJson2.version}: ${url}`
|
|
11960
11946
|
);
|
|
11961
|
-
|
|
11962
|
-
|
|
11963
|
-
|
|
11964
|
-
|
|
11965
|
-
|
|
11966
|
-
|
|
11967
|
-
|
|
11968
|
-
|
|
11969
|
-
|
|
11970
|
-
|
|
11971
|
-
|
|
11947
|
+
printDiagnosticsToConsole("");
|
|
11948
|
+
let hasExited = false;
|
|
11949
|
+
return new Promise((resolve) => {
|
|
11950
|
+
function exit() {
|
|
11951
|
+
if (!hasExited) {
|
|
11952
|
+
hasExited = true;
|
|
11953
|
+
server.stop().then(() => {
|
|
11954
|
+
resolve();
|
|
11955
|
+
}).catch((e) => {
|
|
11956
|
+
console.error("Error stopping server", e);
|
|
11957
|
+
resolve();
|
|
11958
|
+
});
|
|
11959
|
+
}
|
|
11972
11960
|
}
|
|
11961
|
+
process.on("SIGTERM", exit);
|
|
11962
|
+
process.on("SIGINT", exit);
|
|
11963
|
+
process.on("uncaughtException", (e) => {
|
|
11964
|
+
console.error("Uncaught exception", e);
|
|
11965
|
+
void exit();
|
|
11966
|
+
});
|
|
11967
|
+
process.on("unhandledRejection", (e) => {
|
|
11968
|
+
if (e instanceof DOMException && e.name === "AbortError") {
|
|
11969
|
+
console.log(`[Abort] ${e.message}`);
|
|
11970
|
+
return;
|
|
11971
|
+
}
|
|
11972
|
+
console.error("Unhandled rejection", e);
|
|
11973
|
+
void exit();
|
|
11974
|
+
});
|
|
11975
|
+
process.on("exit", exit);
|
|
11976
|
+
});
|
|
11977
|
+
}
|
|
11978
|
+
|
|
11979
|
+
// src/cli/cmds/dev.ts
|
|
11980
|
+
var dev_default = {
|
|
11981
|
+
desc: "Runs locally",
|
|
11982
|
+
command: "dev",
|
|
11983
|
+
builder: (yargs2) => {
|
|
11984
|
+
return yargs2.option("dir", {
|
|
11985
|
+
type: "string",
|
|
11986
|
+
describe: "The directory containing your project",
|
|
11987
|
+
default: ".",
|
|
11988
|
+
normalize: true,
|
|
11989
|
+
hidden: true
|
|
11990
|
+
}).option("port", {
|
|
11991
|
+
type: "number",
|
|
11992
|
+
describe: "The port to run the local server on"
|
|
11993
|
+
}).option("ssr", {
|
|
11994
|
+
type: "boolean",
|
|
11995
|
+
describe: "Enable server-side rendering",
|
|
11996
|
+
default: true
|
|
11997
|
+
}).option("open", {
|
|
11998
|
+
type: "boolean",
|
|
11999
|
+
describe: "Automatically open the browser",
|
|
12000
|
+
default: false
|
|
12001
|
+
});
|
|
12002
|
+
},
|
|
12003
|
+
handler: async (argv) => {
|
|
12004
|
+
await captureEvent({
|
|
12005
|
+
argv,
|
|
12006
|
+
event: "apitogo dev"
|
|
12007
|
+
});
|
|
12008
|
+
await dev(argv);
|
|
12009
|
+
}
|
|
12010
|
+
};
|
|
12011
|
+
|
|
12012
|
+
// src/cli/init/handler.ts
|
|
12013
|
+
import path40 from "node:path";
|
|
12014
|
+
async function init2(argv) {
|
|
12015
|
+
const dir = path40.resolve(process.cwd(), argv.dir ?? ".");
|
|
12016
|
+
try {
|
|
12017
|
+
const createdPackageJson = await ensurePackageJson(dir);
|
|
12018
|
+
const createdTsconfig = await ensureTsconfigJson(dir);
|
|
11973
12019
|
await ensurePortalStubFiles(dir);
|
|
11974
|
-
|
|
11975
|
-
|
|
11976
|
-
|
|
11977
|
-
if (await fileExists3(jsonPath)) {
|
|
11978
|
-
config2 = await readJsonConfig(jsonPath);
|
|
11979
|
-
} else {
|
|
11980
|
-
config2 = createDefaultApitogoJsonConfig({
|
|
11981
|
-
title: titleFromDirectoryName(path39.basename(dir)),
|
|
11982
|
-
pagesDir
|
|
11983
|
-
});
|
|
11984
|
-
createdJson = true;
|
|
11985
|
-
printDiagnosticsToConsole(`Created ${APITOGO_JSON_FILENAME}`);
|
|
11986
|
-
}
|
|
11987
|
-
const createdTsx = await ensureThinConfigTsx(dir);
|
|
11988
|
-
if (createdTsx) {
|
|
11989
|
-
printDiagnosticsToConsole("Created apitogo.config.tsx");
|
|
12020
|
+
await ensureThinConfigTsx(dir);
|
|
12021
|
+
if (createdPackageJson) {
|
|
12022
|
+
printDiagnosticsToConsole("Created package.json");
|
|
11990
12023
|
}
|
|
11991
|
-
|
|
11992
|
-
|
|
11993
|
-
theme: parseJsonObjectFlag(argv.theme, "theme"),
|
|
11994
|
-
authentication: parseJsonObjectFlag(argv.authentication, "authentication"),
|
|
11995
|
-
title: argv.title
|
|
11996
|
-
};
|
|
11997
|
-
let openApiOverride;
|
|
11998
|
-
if (argv.interactive) {
|
|
11999
|
-
const site = isPlainObject2(config2.site) ? config2.site : {};
|
|
12000
|
-
const logo = isPlainObject2(site.logo) ? site.logo : {};
|
|
12001
|
-
const theme = isPlainObject2(config2.theme) ? config2.theme : {};
|
|
12002
|
-
const fonts = isPlainObject2(theme.fonts) ? theme.fonts : {};
|
|
12003
|
-
const light = isPlainObject2(theme.light) ? theme.light : {};
|
|
12004
|
-
const dark = isPlainObject2(theme.dark) ? theme.dark : {};
|
|
12005
|
-
const authentication = isPlainObject2(config2.authentication) ? config2.authentication : {};
|
|
12006
|
-
const prompted = await promptMakeConfigInteractive({
|
|
12007
|
-
title: flagPatches.title ?? (typeof site.title === "string" ? site.title : titleFromDirectoryName(path39.basename(dir))),
|
|
12008
|
-
logoAlt: typeof logo.alt === "string" ? logo.alt : "APIToGo",
|
|
12009
|
-
authEnabled: authentication.enabled === true,
|
|
12010
|
-
apiBaseUrl: typeof authentication.apiBaseUrl === "string" ? authentication.apiBaseUrl : void 0,
|
|
12011
|
-
sans: typeof fonts.sans === "string" ? fonts.sans : void 0,
|
|
12012
|
-
mono: typeof fonts.mono === "string" ? fonts.mono : void 0,
|
|
12013
|
-
lightPrimary: typeof light.primary === "string" ? light.primary : void 0,
|
|
12014
|
-
darkPrimary: typeof dark.primary === "string" ? dark.primary : void 0,
|
|
12015
|
-
discoveredOpenApi
|
|
12016
|
-
});
|
|
12017
|
-
openApiOverride = prompted.openApiPath;
|
|
12018
|
-
config2 = applyConfigPatches(config2, prompted);
|
|
12024
|
+
if (createdTsconfig) {
|
|
12025
|
+
printDiagnosticsToConsole("Created tsconfig.json");
|
|
12019
12026
|
}
|
|
12020
|
-
|
|
12021
|
-
|
|
12022
|
-
|
|
12023
|
-
|
|
12024
|
-
|
|
12027
|
+
await makeConfig({
|
|
12028
|
+
dir,
|
|
12029
|
+
pagesDir: "pages",
|
|
12030
|
+
title: argv.name,
|
|
12031
|
+
force: false
|
|
12025
12032
|
});
|
|
12026
|
-
const markdownFiles = pageFiles.filter((file) => /\.mdx?$/i.test(file));
|
|
12027
|
-
const tsxFiles = pageFiles.filter((file) => /\.(tsx|jsx)$/i.test(file));
|
|
12028
|
-
const markdownRoutes = markdownFiles.map(
|
|
12029
|
-
(file) => toRoutePath(file, pagesDir)
|
|
12030
|
-
);
|
|
12031
|
-
const tsxRoutes = tsxFiles.map((file) => toRoutePath(file, pagesDir));
|
|
12032
|
-
if (markdownRoutes.length === 0 && tsxRoutes.length === 0) {
|
|
12033
|
-
printDiagnosticsToConsole(
|
|
12034
|
-
`No docs pages under '${pagesDir}/' \u2014 skipping documentation nav scan.`
|
|
12035
|
-
);
|
|
12036
|
-
}
|
|
12037
|
-
config2.navigation = mergeDocumentationNavigation(
|
|
12038
|
-
config2.navigation,
|
|
12039
|
-
markdownRoutes,
|
|
12040
|
-
{ force: argv.force === true }
|
|
12041
|
-
);
|
|
12042
|
-
const openApiRel = openApiOverride === void 0 ? discoveredOpenApi : openApiOverride;
|
|
12043
|
-
if (openApiRel) {
|
|
12044
|
-
config2 = applyOpenApiToJsonConfig(
|
|
12045
|
-
config2,
|
|
12046
|
-
openapiInputForConfig(openApiRel)
|
|
12047
|
-
);
|
|
12048
|
-
}
|
|
12049
|
-
await writeFile8(jsonPath, `${JSON.stringify(config2, null, 2)}
|
|
12050
|
-
`, "utf8");
|
|
12051
|
-
const tsxPath = path39.join(dir, "apitogo.config.tsx");
|
|
12052
|
-
if (await fileExists3(tsxPath) && tsxRoutes.length > 0) {
|
|
12053
|
-
const tsxSource = await readFile6(tsxPath, "utf8");
|
|
12054
|
-
if (isThinConfigWrapper(tsxSource)) {
|
|
12055
|
-
await writeFile8(
|
|
12056
|
-
tsxPath,
|
|
12057
|
-
buildThinWrapperWithCustomPages(tsxRoutes),
|
|
12058
|
-
"utf8"
|
|
12059
|
-
);
|
|
12060
|
-
}
|
|
12061
|
-
}
|
|
12062
|
-
const action = createdJson ? "Initialized" : "Updated";
|
|
12063
12033
|
printResultToConsole(
|
|
12064
|
-
|
|
12034
|
+
`Portal scaffolded in ${dir}. Next: apitogo config -i, apitogo dev, then apitogo apply.`
|
|
12065
12035
|
);
|
|
12066
|
-
const createdWorkflow = await ensureApitogoDeployWorkflow(dir);
|
|
12067
|
-
if (createdWorkflow) {
|
|
12068
|
-
printDiagnosticsToConsole(
|
|
12069
|
-
"Created .github/workflows/apitogo-deploy.yml (preview + production; removes preview when a PR is closed)."
|
|
12070
|
-
);
|
|
12071
|
-
}
|
|
12072
|
-
if (createdPackageJson) {
|
|
12073
|
-
printDiagnosticsToConsole(
|
|
12074
|
-
"Next: run npm install (or pnpm install / yarn) in this directory, then npm run dev."
|
|
12075
|
-
);
|
|
12076
|
-
}
|
|
12077
12036
|
} catch (error) {
|
|
12078
12037
|
await printCriticalFailureToConsoleAndExit(
|
|
12079
12038
|
error instanceof Error ? error.message : String(error)
|
|
@@ -12081,155 +12040,246 @@ async function makeConfig(argv) {
|
|
|
12081
12040
|
}
|
|
12082
12041
|
}
|
|
12083
12042
|
|
|
12084
|
-
// src/cli/cmds/
|
|
12085
|
-
var
|
|
12086
|
-
desc: "
|
|
12087
|
-
command: "
|
|
12088
|
-
builder: (yargs2) => yargs2.
|
|
12043
|
+
// src/cli/cmds/init.ts
|
|
12044
|
+
var init_default = {
|
|
12045
|
+
desc: "Scaffold a local APItoGo developer portal (no platform calls)",
|
|
12046
|
+
command: "init [dir]",
|
|
12047
|
+
builder: (yargs2) => yargs2.positional("dir", {
|
|
12089
12048
|
type: "string",
|
|
12090
|
-
describe: "
|
|
12049
|
+
describe: "Directory to scaffold into",
|
|
12091
12050
|
default: ".",
|
|
12092
|
-
normalize: true
|
|
12093
|
-
|
|
12094
|
-
}).option("pages-dir", {
|
|
12095
|
-
type: "string",
|
|
12096
|
-
describe: "Directory to scan for md/mdx/tsx pages",
|
|
12097
|
-
default: "pages"
|
|
12098
|
-
}).option("interactive", {
|
|
12099
|
-
alias: "i",
|
|
12100
|
-
type: "boolean",
|
|
12101
|
-
describe: "Prompt for site, theme, authentication, and OpenAPI",
|
|
12102
|
-
default: false
|
|
12103
|
-
}).option("site", {
|
|
12104
|
-
type: "string",
|
|
12105
|
-
describe: "JSON object merged into site"
|
|
12106
|
-
}).option("theme", {
|
|
12107
|
-
type: "string",
|
|
12108
|
-
describe: "JSON object merged into theme"
|
|
12109
|
-
}).option("authentication", {
|
|
12110
|
-
type: "string",
|
|
12111
|
-
describe: "JSON object merged into authentication"
|
|
12112
|
-
}).option("title", {
|
|
12051
|
+
normalize: true
|
|
12052
|
+
}).option("name", {
|
|
12113
12053
|
type: "string",
|
|
12114
|
-
describe: "
|
|
12115
|
-
}).option("force", {
|
|
12116
|
-
type: "boolean",
|
|
12117
|
-
describe: "Replace Documentation nav items from disk (keeps API Reference)",
|
|
12118
|
-
default: false
|
|
12054
|
+
describe: "Package / site name"
|
|
12119
12055
|
}),
|
|
12120
12056
|
handler: async (argv) => {
|
|
12121
|
-
await captureEvent({ argv, event: "apitogo
|
|
12122
|
-
await
|
|
12057
|
+
await captureEvent({ argv, event: "apitogo init" });
|
|
12058
|
+
await init2(argv);
|
|
12123
12059
|
}
|
|
12124
12060
|
};
|
|
12125
12061
|
|
|
12126
12062
|
// src/cli/cmds/preview.ts
|
|
12127
|
-
var
|
|
12128
|
-
|
|
12063
|
+
var REMOVED3 = "apitogo preview was removed. Use `apitogo build --preview` or `apitogo dev`.";
|
|
12064
|
+
var preview_default = {
|
|
12065
|
+
desc: "Removed \u2014 use apitogo build --preview",
|
|
12129
12066
|
command: "preview",
|
|
12067
|
+
builder: (yargs2) => yargs2,
|
|
12068
|
+
handler: async (argv) => {
|
|
12069
|
+
await captureEvent({ argv, event: "apitogo preview removed" });
|
|
12070
|
+
await printCriticalFailureToConsoleAndExit(REMOVED3);
|
|
12071
|
+
}
|
|
12072
|
+
};
|
|
12073
|
+
|
|
12074
|
+
// src/cli/cmds/remove.ts
|
|
12075
|
+
var REMOVED4 = "apitogo remove was removed. Use `apitogo teardown --yes` to delete the platform project.";
|
|
12076
|
+
var remove_default = {
|
|
12077
|
+
desc: "Removed \u2014 use apitogo teardown",
|
|
12078
|
+
command: "remove",
|
|
12079
|
+
builder: (yargs2) => yargs2,
|
|
12080
|
+
handler: async (argv) => {
|
|
12081
|
+
await captureEvent({ argv, event: "apitogo remove removed" });
|
|
12082
|
+
await printCriticalFailureToConsoleAndExit(REMOVED4);
|
|
12083
|
+
}
|
|
12084
|
+
};
|
|
12085
|
+
|
|
12086
|
+
// src/cli/status/handler.ts
|
|
12087
|
+
import path42 from "node:path";
|
|
12088
|
+
|
|
12089
|
+
// src/cli/common/mcp-cli.ts
|
|
12090
|
+
import { access as access4 } from "node:fs/promises";
|
|
12091
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
12092
|
+
import path41 from "node:path";
|
|
12093
|
+
async function pathExists2(candidate) {
|
|
12094
|
+
try {
|
|
12095
|
+
await access4(candidate);
|
|
12096
|
+
return true;
|
|
12097
|
+
} catch {
|
|
12098
|
+
return false;
|
|
12099
|
+
}
|
|
12100
|
+
}
|
|
12101
|
+
async function resolveApitogoMcpCliCommand(binary) {
|
|
12102
|
+
const binName = `apitogo-${binary}`;
|
|
12103
|
+
const mcpPath = process.env.APITOGO_MCP_PATH?.trim();
|
|
12104
|
+
if (mcpPath) {
|
|
12105
|
+
const scriptJs = path41.join(mcpPath, "dist", "cli", `${binary}.js`);
|
|
12106
|
+
if (await pathExists2(scriptJs)) {
|
|
12107
|
+
return {
|
|
12108
|
+
command: process.execPath,
|
|
12109
|
+
argsPrefix: [scriptJs],
|
|
12110
|
+
note: `Using local ${binName} from APITOGO_MCP_PATH=${mcpPath}`
|
|
12111
|
+
};
|
|
12112
|
+
}
|
|
12113
|
+
throw new Error(
|
|
12114
|
+
`APITOGO_MCP_PATH is set (${mcpPath}) but dist/cli/${binary}.js was not found. Run npm run build in the MCP checkout.`
|
|
12115
|
+
);
|
|
12116
|
+
}
|
|
12117
|
+
return {
|
|
12118
|
+
command: "npx",
|
|
12119
|
+
argsPrefix: ["--yes", "--package=@lukoweb/apitogo-mcp", binName],
|
|
12120
|
+
note: "Using npx @lukoweb/apitogo-mcp (set APITOGO_MCP_PATH for a local checkout)"
|
|
12121
|
+
};
|
|
12122
|
+
}
|
|
12123
|
+
async function runApitogoMcpCli(binary, childArgs, options = {}) {
|
|
12124
|
+
let resolved;
|
|
12125
|
+
try {
|
|
12126
|
+
resolved = await resolveApitogoMcpCliCommand(binary);
|
|
12127
|
+
} catch (error) {
|
|
12128
|
+
await printCriticalFailureToConsoleAndExit(
|
|
12129
|
+
error instanceof Error ? error.message : String(error)
|
|
12130
|
+
);
|
|
12131
|
+
return;
|
|
12132
|
+
}
|
|
12133
|
+
if (resolved.note && !options.quiet) {
|
|
12134
|
+
printDiagnosticsToConsole(resolved.note);
|
|
12135
|
+
}
|
|
12136
|
+
const exitCode = await new Promise((resolvePromise) => {
|
|
12137
|
+
const child = spawn2(
|
|
12138
|
+
resolved.command,
|
|
12139
|
+
[...resolved.argsPrefix, ...childArgs],
|
|
12140
|
+
{
|
|
12141
|
+
stdio: "inherit",
|
|
12142
|
+
env: process.env,
|
|
12143
|
+
shell: process.platform === "win32"
|
|
12144
|
+
}
|
|
12145
|
+
);
|
|
12146
|
+
child.on("error", (error) => {
|
|
12147
|
+
void printCriticalFailureToConsoleAndExit(
|
|
12148
|
+
`Failed to start apitogo-${binary}: ${error.message}`
|
|
12149
|
+
);
|
|
12150
|
+
resolvePromise(1);
|
|
12151
|
+
});
|
|
12152
|
+
child.on("close", (code) => {
|
|
12153
|
+
resolvePromise(code ?? 1);
|
|
12154
|
+
});
|
|
12155
|
+
});
|
|
12156
|
+
if (exitCode !== 0) {
|
|
12157
|
+
process.exit(exitCode);
|
|
12158
|
+
}
|
|
12159
|
+
}
|
|
12160
|
+
|
|
12161
|
+
// src/cli/status/handler.ts
|
|
12162
|
+
async function status(argv) {
|
|
12163
|
+
const dir = path42.resolve(process.cwd(), argv.dir);
|
|
12164
|
+
const args = [dir];
|
|
12165
|
+
if (argv.projectId?.trim()) {
|
|
12166
|
+
args.push("--project-id", argv.projectId.trim());
|
|
12167
|
+
}
|
|
12168
|
+
if (argv.skipLive) {
|
|
12169
|
+
args.push("--skip-live");
|
|
12170
|
+
}
|
|
12171
|
+
if (argv.json) {
|
|
12172
|
+
args.push("--json");
|
|
12173
|
+
}
|
|
12174
|
+
await runApitogoMcpCli("status", args, { quiet: Boolean(argv.json) });
|
|
12175
|
+
}
|
|
12176
|
+
|
|
12177
|
+
// src/cli/cmds/status.ts
|
|
12178
|
+
var status_default = {
|
|
12179
|
+
desc: "Show account, project, and live readiness for the linked APItoGo project",
|
|
12180
|
+
command: "status",
|
|
12130
12181
|
builder: (yargs2) => yargs2.option("dir", {
|
|
12131
12182
|
type: "string",
|
|
12132
|
-
describe: "
|
|
12183
|
+
describe: "Site directory containing apitogo.config.json",
|
|
12133
12184
|
default: ".",
|
|
12134
|
-
normalize: true
|
|
12135
|
-
|
|
12136
|
-
|
|
12137
|
-
|
|
12138
|
-
|
|
12185
|
+
normalize: true
|
|
12186
|
+
}).option("project-id", {
|
|
12187
|
+
type: "string",
|
|
12188
|
+
describe: "Override project GUID"
|
|
12189
|
+
}).option("skip-live", {
|
|
12190
|
+
type: "boolean",
|
|
12191
|
+
describe: "Skip live health checks",
|
|
12192
|
+
default: false
|
|
12193
|
+
}).option("json", {
|
|
12194
|
+
type: "boolean",
|
|
12195
|
+
describe: "Print raw JSON only",
|
|
12196
|
+
default: false
|
|
12139
12197
|
}),
|
|
12140
12198
|
handler: async (argv) => {
|
|
12141
|
-
|
|
12142
|
-
await
|
|
12143
|
-
await preview(argv);
|
|
12199
|
+
await captureEvent({ argv, event: "apitogo status" });
|
|
12200
|
+
await status(argv);
|
|
12144
12201
|
}
|
|
12145
12202
|
};
|
|
12146
|
-
var preview_default = previewCommand;
|
|
12147
12203
|
|
|
12148
|
-
// src/cli/
|
|
12149
|
-
|
|
12150
|
-
async function
|
|
12151
|
-
|
|
12152
|
-
|
|
12153
|
-
|
|
12154
|
-
|
|
12155
|
-
|
|
12156
|
-
|
|
12157
|
-
|
|
12158
|
-
|
|
12159
|
-
|
|
12160
|
-
|
|
12161
|
-
formData.append("deploymentToken", deploymentToken);
|
|
12162
|
-
formData.append("env", env);
|
|
12163
|
-
const removeUrl = new URL(REMOVE_ENDPOINT);
|
|
12164
|
-
if (argv.jsonOnly) {
|
|
12165
|
-
removeUrl.searchParams.set("jsonOnly", "true");
|
|
12166
|
-
}
|
|
12167
|
-
const response = await fetch(removeUrl, {
|
|
12168
|
-
method: "POST",
|
|
12169
|
-
headers: {
|
|
12170
|
-
"x-api-key": DEPLOY_SERVER_API_KEY
|
|
12171
|
-
},
|
|
12172
|
-
body: formData
|
|
12173
|
-
});
|
|
12174
|
-
const responseText = await response.text();
|
|
12175
|
-
if (!response.ok) {
|
|
12176
|
-
throw new Error(
|
|
12177
|
-
`Remove failed with ${response.status}: ${JSON.stringify(textOrJson(responseText))}`
|
|
12178
|
-
);
|
|
12179
|
-
}
|
|
12180
|
-
if (isJsonOnlyDeployEnv()) {
|
|
12181
|
-
const parsed = responseText.trim() ? textOrJson(responseText) : {};
|
|
12182
|
-
console.log(JSON.stringify(parsed));
|
|
12183
|
-
return;
|
|
12184
|
-
}
|
|
12185
|
-
printResultToConsole(`Removal request sent to ${removeUrl.href}`);
|
|
12186
|
-
if (responseText.trim()) {
|
|
12187
|
-
printDiagnosticsToConsole(
|
|
12188
|
-
JSON.stringify(textOrJson(responseText), null, 2)
|
|
12189
|
-
);
|
|
12190
|
-
}
|
|
12191
|
-
} catch (error) {
|
|
12192
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
12193
|
-
if (isJsonOnlyDeployEnv()) {
|
|
12194
|
-
printJsonOnlyErrorAndExit(message);
|
|
12195
|
-
} else {
|
|
12196
|
-
await printCriticalFailureToConsoleAndExit(message);
|
|
12197
|
-
}
|
|
12204
|
+
// src/cli/teardown/handler.ts
|
|
12205
|
+
import path43 from "node:path";
|
|
12206
|
+
async function teardown(argv) {
|
|
12207
|
+
if (!argv.yes) {
|
|
12208
|
+
await printCriticalFailureToConsoleAndExit(
|
|
12209
|
+
"Refusing to teardown without --yes."
|
|
12210
|
+
);
|
|
12211
|
+
return;
|
|
12212
|
+
}
|
|
12213
|
+
const dir = path43.resolve(process.cwd(), argv.dir);
|
|
12214
|
+
const args = [dir, "--yes"];
|
|
12215
|
+
if (argv.projectId?.trim()) {
|
|
12216
|
+
args.push("--project-id", argv.projectId.trim());
|
|
12198
12217
|
}
|
|
12218
|
+
if (argv.wait === false) {
|
|
12219
|
+
args.push("--no-wait");
|
|
12220
|
+
}
|
|
12221
|
+
if (argv.json) {
|
|
12222
|
+
args.push("--json");
|
|
12223
|
+
}
|
|
12224
|
+
await runApitogoMcpCli("teardown", args, { quiet: Boolean(argv.json) });
|
|
12199
12225
|
}
|
|
12200
12226
|
|
|
12201
|
-
// src/cli/cmds/
|
|
12202
|
-
var
|
|
12203
|
-
desc: "
|
|
12204
|
-
command: "
|
|
12205
|
-
builder: (yargs2) => yargs2.option("
|
|
12227
|
+
// src/cli/cmds/teardown.ts
|
|
12228
|
+
var teardown_default = {
|
|
12229
|
+
desc: "Delete the linked APItoGo project",
|
|
12230
|
+
command: "teardown",
|
|
12231
|
+
builder: (yargs2) => yargs2.option("dir", {
|
|
12206
12232
|
type: "string",
|
|
12207
|
-
describe: "
|
|
12208
|
-
|
|
12233
|
+
describe: "Site directory containing apitogo.config.json",
|
|
12234
|
+
default: ".",
|
|
12235
|
+
normalize: true
|
|
12236
|
+
}).option("project-id", {
|
|
12209
12237
|
type: "string",
|
|
12210
|
-
describe: "
|
|
12211
|
-
|
|
12212
|
-
|
|
12238
|
+
describe: "Override project GUID"
|
|
12239
|
+
}).option("yes", {
|
|
12240
|
+
alias: "y",
|
|
12241
|
+
type: "boolean",
|
|
12242
|
+
describe: "Confirm teardown (required)",
|
|
12243
|
+
default: false
|
|
12244
|
+
}).option("wait", {
|
|
12245
|
+
type: "boolean",
|
|
12246
|
+
describe: "Wait for deletion to finish",
|
|
12247
|
+
default: true
|
|
12248
|
+
}).option("json", {
|
|
12213
12249
|
type: "boolean",
|
|
12214
|
-
describe: "
|
|
12250
|
+
describe: "Print raw JSON only",
|
|
12215
12251
|
default: false
|
|
12216
12252
|
}),
|
|
12217
12253
|
handler: async (argv) => {
|
|
12218
|
-
|
|
12219
|
-
|
|
12220
|
-
}
|
|
12221
|
-
await captureEvent({ argv, event: "apitogo remove" });
|
|
12222
|
-
await remove(argv);
|
|
12254
|
+
await captureEvent({ argv, event: "apitogo teardown" });
|
|
12255
|
+
await teardown(argv);
|
|
12223
12256
|
}
|
|
12224
12257
|
};
|
|
12225
12258
|
|
|
12226
12259
|
// src/cli/common/outdated.ts
|
|
12227
12260
|
import { existsSync as existsSync3, mkdirSync } from "node:fs";
|
|
12228
|
-
import { readFile as
|
|
12261
|
+
import { readFile as readFile6, writeFile as writeFile8 } from "node:fs/promises";
|
|
12229
12262
|
import { join } from "node:path";
|
|
12230
12263
|
import colors10 from "picocolors";
|
|
12231
12264
|
import { gt } from "semver";
|
|
12232
12265
|
|
|
12266
|
+
// src/cli/common/json-only-deploy.ts
|
|
12267
|
+
function isDeployJsonOnlyArgv() {
|
|
12268
|
+
const args = process.argv;
|
|
12269
|
+
let cmdIdx = -1;
|
|
12270
|
+
for (const cmd of ["deploy", "remove"]) {
|
|
12271
|
+
const i = args.indexOf(cmd);
|
|
12272
|
+
if (i !== -1) {
|
|
12273
|
+
cmdIdx = i;
|
|
12274
|
+
break;
|
|
12275
|
+
}
|
|
12276
|
+
}
|
|
12277
|
+
if (cmdIdx === -1) {
|
|
12278
|
+
return false;
|
|
12279
|
+
}
|
|
12280
|
+
return args.slice(cmdIdx).some((a) => a === "--json-only" || a.startsWith("--json-only="));
|
|
12281
|
+
}
|
|
12282
|
+
|
|
12233
12283
|
// src/cli/common/utils/box.ts
|
|
12234
12284
|
import colors9 from "picocolors";
|
|
12235
12285
|
import stripAnsi from "strip-ansi";
|
|
@@ -12275,12 +12325,12 @@ function box(message, {
|
|
|
12275
12325
|
|
|
12276
12326
|
// src/cli/common/xdg/lib.ts
|
|
12277
12327
|
import { homedir } from "node:os";
|
|
12278
|
-
import
|
|
12328
|
+
import path44 from "node:path";
|
|
12279
12329
|
function defineDirectoryWithFallback(xdgName, fallback) {
|
|
12280
12330
|
if (process.env[xdgName]) {
|
|
12281
12331
|
return process.env[xdgName];
|
|
12282
12332
|
} else {
|
|
12283
|
-
return
|
|
12333
|
+
return path44.join(homedir(), fallback);
|
|
12284
12334
|
}
|
|
12285
12335
|
}
|
|
12286
12336
|
var XDG_CONFIG_HOME = defineDirectoryWithFallback(
|
|
@@ -12295,15 +12345,15 @@ var XDG_STATE_HOME = defineDirectoryWithFallback(
|
|
|
12295
12345
|
"XDG_DATA_HOME",
|
|
12296
12346
|
".local/state"
|
|
12297
12347
|
);
|
|
12298
|
-
var ZUDOKU_XDG_CONFIG_HOME =
|
|
12348
|
+
var ZUDOKU_XDG_CONFIG_HOME = path44.join(
|
|
12299
12349
|
XDG_CONFIG_HOME,
|
|
12300
12350
|
CLI_XDG_FOLDER_NAME
|
|
12301
12351
|
);
|
|
12302
|
-
var ZUDOKU_XDG_DATA_HOME =
|
|
12352
|
+
var ZUDOKU_XDG_DATA_HOME = path44.join(
|
|
12303
12353
|
XDG_DATA_HOME,
|
|
12304
12354
|
CLI_XDG_FOLDER_NAME
|
|
12305
12355
|
);
|
|
12306
|
-
var ZUDOKU_XDG_STATE_HOME =
|
|
12356
|
+
var ZUDOKU_XDG_STATE_HOME = path44.join(
|
|
12307
12357
|
XDG_STATE_HOME,
|
|
12308
12358
|
CLI_XDG_FOLDER_NAME
|
|
12309
12359
|
);
|
|
@@ -12355,7 +12405,7 @@ async function getVersionCheckInfo() {
|
|
|
12355
12405
|
let versionCheckInfo;
|
|
12356
12406
|
if (existsSync3(versionCheckPath)) {
|
|
12357
12407
|
try {
|
|
12358
|
-
versionCheckInfo = await
|
|
12408
|
+
versionCheckInfo = await readFile6(versionCheckPath, "utf-8").then(
|
|
12359
12409
|
JSON.parse
|
|
12360
12410
|
);
|
|
12361
12411
|
} catch {
|
|
@@ -12380,7 +12430,7 @@ async function getVersionCheckInfo() {
|
|
|
12380
12430
|
lastCheck: Date.now(),
|
|
12381
12431
|
latestVersion
|
|
12382
12432
|
};
|
|
12383
|
-
await
|
|
12433
|
+
await writeFile8(
|
|
12384
12434
|
versionCheckPath,
|
|
12385
12435
|
JSON.stringify(versionCheckInfo),
|
|
12386
12436
|
"utf-8"
|
|
@@ -12467,7 +12517,7 @@ var cli = yargs(hideBin(process.argv)).option("zuplo", {
|
|
|
12467
12517
|
process.env.ZUPLO = "1";
|
|
12468
12518
|
printDiagnosticsToConsole("Running in Zuplo mode");
|
|
12469
12519
|
}
|
|
12470
|
-
}).middleware(warnPackageVersionMismatch).command(
|
|
12520
|
+
}).middleware(warnPackageVersionMismatch).command(init_default).command(config_default).command(dev_default).command(build_default).command(apply_default).command(status_default).command(teardown_default).command(deploy_default).command(remove_default).command(preview_default).command(configure_github_workflow_default).demandCommand().strictCommands().version(packageJson?.version).fail(false).help();
|
|
12471
12521
|
try {
|
|
12472
12522
|
void warnIfOutdatedVersion(packageJson?.version);
|
|
12473
12523
|
await cli.argv;
|