@lukoweb/apitogo 0.1.93 → 0.1.95
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 +475 -89
- package/docs/cli/commands.md +2 -1
- package/docs/cli/overview.md +1 -1
- package/docs/cli/setup.md +19 -5
- package/docs/cli/shape.md +2 -2
- package/docs/configuration/make-config.mdx +1 -1
- package/package.json +1 -1
package/dist/cli/cli.js
CHANGED
|
@@ -734,7 +734,7 @@ import { stat } from "node:fs/promises";
|
|
|
734
734
|
var fileExists;
|
|
735
735
|
var init_file_exists = __esm({
|
|
736
736
|
"src/config/file-exists.ts"() {
|
|
737
|
-
fileExists = (
|
|
737
|
+
fileExists = (path67) => stat(path67).then(() => true).catch(() => false);
|
|
738
738
|
}
|
|
739
739
|
});
|
|
740
740
|
|
|
@@ -5504,8 +5504,8 @@ var PlatformApiClient = class {
|
|
|
5504
5504
|
constructor(config2) {
|
|
5505
5505
|
this.config = config2;
|
|
5506
5506
|
}
|
|
5507
|
-
url(
|
|
5508
|
-
return `${this.config.apiUrl}${
|
|
5507
|
+
url(path67) {
|
|
5508
|
+
return `${this.config.apiUrl}${path67.startsWith("/") ? path67 : `/${path67}`}`;
|
|
5509
5509
|
}
|
|
5510
5510
|
headers(extra) {
|
|
5511
5511
|
return {
|
|
@@ -5515,9 +5515,9 @@ var PlatformApiClient = class {
|
|
|
5515
5515
|
...extra
|
|
5516
5516
|
};
|
|
5517
5517
|
}
|
|
5518
|
-
async request(method,
|
|
5518
|
+
async request(method, path67, init4) {
|
|
5519
5519
|
const response = await fetchWithRetry(
|
|
5520
|
-
this.url(
|
|
5520
|
+
this.url(path67),
|
|
5521
5521
|
{
|
|
5522
5522
|
method,
|
|
5523
5523
|
...init4,
|
|
@@ -5717,15 +5717,15 @@ var PlatformApiClient = class {
|
|
|
5717
5717
|
}
|
|
5718
5718
|
);
|
|
5719
5719
|
}
|
|
5720
|
-
deleteDevPortalPage(projectId,
|
|
5721
|
-
const query = new URLSearchParams({ path:
|
|
5720
|
+
deleteDevPortalPage(projectId, path67) {
|
|
5721
|
+
const query = new URLSearchParams({ path: path67 });
|
|
5722
5722
|
return this.request(
|
|
5723
5723
|
"DELETE",
|
|
5724
5724
|
`/api/v1/projects/${projectId}/dev-portal/pages/files?${query.toString()}`
|
|
5725
5725
|
);
|
|
5726
5726
|
}
|
|
5727
|
-
renameDevPortalPage(projectId,
|
|
5728
|
-
const query = new URLSearchParams({ path:
|
|
5727
|
+
renameDevPortalPage(projectId, path67, newName) {
|
|
5728
|
+
const query = new URLSearchParams({ path: path67 });
|
|
5729
5729
|
return this.request(
|
|
5730
5730
|
"POST",
|
|
5731
5731
|
`/api/v1/projects/${projectId}/dev-portal/pages/files/rename?${query.toString()}`,
|
|
@@ -5896,8 +5896,8 @@ var PlatformApiClient = class {
|
|
|
5896
5896
|
}
|
|
5897
5897
|
};
|
|
5898
5898
|
async function readFileBytes(filePath) {
|
|
5899
|
-
const { readFile:
|
|
5900
|
-
const buffer = await
|
|
5899
|
+
const { readFile: readFile19 } = await import("node:fs/promises");
|
|
5900
|
+
const buffer = await readFile19(filePath);
|
|
5901
5901
|
const arrayBuffer = new ArrayBuffer(buffer.byteLength);
|
|
5902
5902
|
new Uint8Array(arrayBuffer).set(buffer);
|
|
5903
5903
|
return arrayBuffer;
|
|
@@ -7317,8 +7317,8 @@ function normalizeActionKey(actionKey) {
|
|
|
7317
7317
|
const trimmed = actionKey.trim();
|
|
7318
7318
|
if (trimmed.includes(":")) {
|
|
7319
7319
|
const [method2, ...pathParts] = trimmed.split(":");
|
|
7320
|
-
const
|
|
7321
|
-
return `${method2.toLowerCase()}:${
|
|
7320
|
+
const path68 = pathParts.join(":").trim();
|
|
7321
|
+
return `${method2.toLowerCase()}:${path68.startsWith("/") ? path68 : `/${path68}`}`;
|
|
7322
7322
|
}
|
|
7323
7323
|
const spaceIndex = trimmed.indexOf(" ");
|
|
7324
7324
|
if (spaceIndex <= 0) {
|
|
@@ -7327,8 +7327,8 @@ function normalizeActionKey(actionKey) {
|
|
|
7327
7327
|
);
|
|
7328
7328
|
}
|
|
7329
7329
|
const method = trimmed.slice(0, spaceIndex).trim().toLowerCase();
|
|
7330
|
-
const
|
|
7331
|
-
return `${method}:${
|
|
7330
|
+
const path67 = trimmed.slice(spaceIndex + 1).trim();
|
|
7331
|
+
return `${method}:${path67.startsWith("/") ? path67 : `/${path67}`}`;
|
|
7332
7332
|
}
|
|
7333
7333
|
async function applyGatewayPublicRoutes(client, projectId, routes, options) {
|
|
7334
7334
|
const applied = [];
|
|
@@ -9395,7 +9395,8 @@ var PLATFORM_PLAN_CATALOG = [
|
|
|
9395
9395
|
"Paid end-user gateway plans (Stripe checkout for API subscribers)",
|
|
9396
9396
|
"1 custom domain on the dev portal",
|
|
9397
9397
|
"100k requests included; up to 1M requests / month",
|
|
9398
|
-
"Stripe subscription billing with promotion codes at checkout"
|
|
9398
|
+
"Stripe subscription billing with promotion codes at checkout",
|
|
9399
|
+
"Standard support"
|
|
9399
9400
|
],
|
|
9400
9401
|
limitations: [
|
|
9401
9402
|
"Requires Stripe checkout to activate",
|
|
@@ -9415,7 +9416,8 @@ var PLATFORM_PLAN_CATALOG = [
|
|
|
9415
9416
|
"3 custom domains",
|
|
9416
9417
|
"1M requests included; up to 10M requests / month",
|
|
9417
9418
|
"Advanced analytics and CDN for your API",
|
|
9418
|
-
"Extended monitoring history and alerts"
|
|
9419
|
+
"Extended monitoring history and alerts",
|
|
9420
|
+
"Enterprise support"
|
|
9419
9421
|
],
|
|
9420
9422
|
limitations: [
|
|
9421
9423
|
"Requires Stripe checkout to activate",
|
|
@@ -9434,8 +9436,8 @@ function buildPlatformPlanSelectionAgentInstruction(quota) {
|
|
|
9434
9436
|
const lines = [
|
|
9435
9437
|
"Before calling ensure_platform_plan, explain the platform hosting tiers to the user using platformPlanCatalog from the bootstrap response or list_platform_plans.",
|
|
9436
9438
|
"Free: $0/month, dev portal + API hub, no custom domain, free ($0) gateway/API plans only.",
|
|
9437
|
-
"Starter: $99/month via Stripe, custom domain, paid gateway plans, production hosting.",
|
|
9438
|
-
"Professional: $999/month via Stripe, higher limits, multiple domains, advanced analytics.",
|
|
9439
|
+
"Starter: $99/month via Stripe, custom domain, paid gateway plans, production hosting, standard support.",
|
|
9440
|
+
"Professional: $999/month via Stripe, higher limits, multiple domains, advanced analytics, enterprise support.",
|
|
9439
9441
|
"This is separate from gateway/API plans (what end users pay for API access) configured in apitogo.config.json.",
|
|
9440
9442
|
"If apitogo.config.json already has paid gateway plans (priceAmount > 0), warn before they pick Free: Free cannot publish paid API plans \u2014 they must choose Starter/Professional, or remove/zero those paid plans first. Never silently strip paid plans."
|
|
9441
9443
|
];
|
|
@@ -11405,8 +11407,8 @@ function normalizeActionKeyFormat(actionKey) {
|
|
|
11405
11407
|
const trimmed = actionKey.trim();
|
|
11406
11408
|
if (trimmed.includes(":")) {
|
|
11407
11409
|
const [method2, ...pathParts] = trimmed.split(":");
|
|
11408
|
-
const
|
|
11409
|
-
return `${method2.toLowerCase()}:${
|
|
11410
|
+
const path68 = pathParts.join(":").trim();
|
|
11411
|
+
return `${method2.toLowerCase()}:${path68.startsWith("/") ? path68 : `/${path68}`}`;
|
|
11410
11412
|
}
|
|
11411
11413
|
const spaceIndex = trimmed.indexOf(" ");
|
|
11412
11414
|
if (spaceIndex <= 0) {
|
|
@@ -11415,8 +11417,8 @@ function normalizeActionKeyFormat(actionKey) {
|
|
|
11415
11417
|
);
|
|
11416
11418
|
}
|
|
11417
11419
|
const method = trimmed.slice(0, spaceIndex).trim().toLowerCase();
|
|
11418
|
-
const
|
|
11419
|
-
return `${method}:${
|
|
11420
|
+
const path67 = trimmed.slice(spaceIndex + 1).trim();
|
|
11421
|
+
return `${method}:${path67.startsWith("/") ? path67 : `/${path67}`}`;
|
|
11420
11422
|
}
|
|
11421
11423
|
function normalizePublicRoute(route) {
|
|
11422
11424
|
const trimmed = route.trim();
|
|
@@ -12533,7 +12535,7 @@ import {
|
|
|
12533
12535
|
// package.json
|
|
12534
12536
|
var package_default = {
|
|
12535
12537
|
name: "@lukoweb/apitogo",
|
|
12536
|
-
version: "0.1.
|
|
12538
|
+
version: "0.1.95",
|
|
12537
12539
|
type: "module",
|
|
12538
12540
|
sideEffects: [
|
|
12539
12541
|
"**/*.css",
|
|
@@ -13311,14 +13313,14 @@ var flattenAllOf = (schema2) => {
|
|
|
13311
13313
|
};
|
|
13312
13314
|
|
|
13313
13315
|
// src/lib/util/traverse.ts
|
|
13314
|
-
var traverse = (specification, transform,
|
|
13315
|
-
const transformed = transform(specification,
|
|
13316
|
+
var traverse = (specification, transform, path67 = []) => {
|
|
13317
|
+
const transformed = transform(specification, path67);
|
|
13316
13318
|
if (typeof transformed !== "object" || transformed === null) {
|
|
13317
13319
|
return transformed;
|
|
13318
13320
|
}
|
|
13319
13321
|
const result = Array.isArray(transformed) ? [] : {};
|
|
13320
13322
|
for (const [key, value] of Object.entries(transformed)) {
|
|
13321
|
-
const currentPath = [...
|
|
13323
|
+
const currentPath = [...path67, key];
|
|
13322
13324
|
if (Array.isArray(value)) {
|
|
13323
13325
|
result[key] = value.map(
|
|
13324
13326
|
(item, index) => typeof item === "object" && item != null ? traverse(item, transform, [...currentPath, index.toString()]) : item
|
|
@@ -13346,9 +13348,9 @@ var resolveLocalRef = (schema2, ref) => {
|
|
|
13346
13348
|
if (schemaCache?.has(ref)) {
|
|
13347
13349
|
return schemaCache.get(ref);
|
|
13348
13350
|
}
|
|
13349
|
-
const
|
|
13351
|
+
const path67 = ref.split("/").slice(1);
|
|
13350
13352
|
let current = schema2;
|
|
13351
|
-
for (const segment of
|
|
13353
|
+
for (const segment of path67) {
|
|
13352
13354
|
if (!current || typeof current !== "object") {
|
|
13353
13355
|
current = null;
|
|
13354
13356
|
}
|
|
@@ -13367,7 +13369,7 @@ var dereference = async (schema2, resolvers = []) => {
|
|
|
13367
13369
|
}
|
|
13368
13370
|
const cloned = structuredClone(schema2);
|
|
13369
13371
|
const visited = /* @__PURE__ */ new Set();
|
|
13370
|
-
const resolve = async (current,
|
|
13372
|
+
const resolve = async (current, path67) => {
|
|
13371
13373
|
if (isIndexableObject(current)) {
|
|
13372
13374
|
if (visited.has(current)) {
|
|
13373
13375
|
return CIRCULAR_REF;
|
|
@@ -13375,7 +13377,7 @@ var dereference = async (schema2, resolvers = []) => {
|
|
|
13375
13377
|
visited.add(current);
|
|
13376
13378
|
if (Array.isArray(current)) {
|
|
13377
13379
|
for (let index = 0; index < current.length; index++) {
|
|
13378
|
-
current[index] = await resolve(current[index], `${
|
|
13380
|
+
current[index] = await resolve(current[index], `${path67}/${index}`);
|
|
13379
13381
|
}
|
|
13380
13382
|
} else {
|
|
13381
13383
|
if ("$ref" in current && typeof current.$ref === "string") {
|
|
@@ -13386,13 +13388,13 @@ var dereference = async (schema2, resolvers = []) => {
|
|
|
13386
13388
|
for (const resolver of resolvers) {
|
|
13387
13389
|
const resolved = await resolver($ref);
|
|
13388
13390
|
if (resolved) {
|
|
13389
|
-
result2 = await resolve(resolved,
|
|
13391
|
+
result2 = await resolve(resolved, path67);
|
|
13390
13392
|
break;
|
|
13391
13393
|
}
|
|
13392
13394
|
}
|
|
13393
13395
|
if (result2 === void 0) {
|
|
13394
13396
|
const resolved = await resolveLocalRef(cloned, $ref);
|
|
13395
|
-
result2 = await resolve(resolved,
|
|
13397
|
+
result2 = await resolve(resolved, path67);
|
|
13396
13398
|
}
|
|
13397
13399
|
if (hasSiblings) {
|
|
13398
13400
|
if (result2 === CIRCULAR_REF) {
|
|
@@ -13405,7 +13407,7 @@ var dereference = async (schema2, resolvers = []) => {
|
|
|
13405
13407
|
return result2;
|
|
13406
13408
|
}
|
|
13407
13409
|
for (const key in current) {
|
|
13408
|
-
current[key] = await resolve(current[key], `${
|
|
13410
|
+
current[key] = await resolve(current[key], `${path67}/${key}`);
|
|
13409
13411
|
}
|
|
13410
13412
|
}
|
|
13411
13413
|
visited.delete(current);
|
|
@@ -13444,9 +13446,9 @@ var upgradeSchema = (schema2) => {
|
|
|
13444
13446
|
}
|
|
13445
13447
|
return sub;
|
|
13446
13448
|
});
|
|
13447
|
-
schema2 = traverse(schema2, (sub,
|
|
13449
|
+
schema2 = traverse(schema2, (sub, path67) => {
|
|
13448
13450
|
if (sub.example !== void 0) {
|
|
13449
|
-
if (isSchemaPath(
|
|
13451
|
+
if (isSchemaPath(path67 ?? [])) {
|
|
13450
13452
|
sub.examples = [sub.example];
|
|
13451
13453
|
} else {
|
|
13452
13454
|
sub.examples = {
|
|
@@ -13459,11 +13461,11 @@ var upgradeSchema = (schema2) => {
|
|
|
13459
13461
|
}
|
|
13460
13462
|
return sub;
|
|
13461
13463
|
});
|
|
13462
|
-
schema2 = traverse(schema2, (schema3,
|
|
13464
|
+
schema2 = traverse(schema2, (schema3, path67) => {
|
|
13463
13465
|
if (schema3.type === "object" && schema3.properties !== void 0) {
|
|
13464
|
-
const parentPath =
|
|
13466
|
+
const parentPath = path67?.slice(0, -1);
|
|
13465
13467
|
const isMultipart = parentPath?.some((segment, index) => {
|
|
13466
|
-
return segment === "content" &&
|
|
13468
|
+
return segment === "content" && path67?.[index + 1] === "multipart/form-data";
|
|
13467
13469
|
});
|
|
13468
13470
|
if (isMultipart) {
|
|
13469
13471
|
const entries = Object.entries(schema3.properties);
|
|
@@ -13477,8 +13479,8 @@ var upgradeSchema = (schema2) => {
|
|
|
13477
13479
|
}
|
|
13478
13480
|
return schema3;
|
|
13479
13481
|
});
|
|
13480
|
-
schema2 = traverse(schema2, (schema3,
|
|
13481
|
-
if (
|
|
13482
|
+
schema2 = traverse(schema2, (schema3, path67) => {
|
|
13483
|
+
if (path67?.includes("content") && path67.includes("application/octet-stream")) {
|
|
13482
13484
|
return {};
|
|
13483
13485
|
}
|
|
13484
13486
|
if (schema3.type === "string" && schema3.format === "binary") {
|
|
@@ -13504,11 +13506,11 @@ var upgradeSchema = (schema2) => {
|
|
|
13504
13506
|
}
|
|
13505
13507
|
return sub;
|
|
13506
13508
|
});
|
|
13507
|
-
schema2 = traverse(schema2, (schema3,
|
|
13509
|
+
schema2 = traverse(schema2, (schema3, path67) => {
|
|
13508
13510
|
if (schema3.type === "string" && schema3.format === "byte") {
|
|
13509
|
-
const parentPath =
|
|
13511
|
+
const parentPath = path67?.slice(0, -1);
|
|
13510
13512
|
const contentMediaType = parentPath?.find(
|
|
13511
|
-
(_, index) =>
|
|
13513
|
+
(_, index) => path67?.[index - 1] === "content"
|
|
13512
13514
|
);
|
|
13513
13515
|
return {
|
|
13514
13516
|
type: "string",
|
|
@@ -13520,7 +13522,7 @@ var upgradeSchema = (schema2) => {
|
|
|
13520
13522
|
});
|
|
13521
13523
|
return schema2;
|
|
13522
13524
|
};
|
|
13523
|
-
function isSchemaPath(
|
|
13525
|
+
function isSchemaPath(path67) {
|
|
13524
13526
|
const schemaLocations = [
|
|
13525
13527
|
["components", "schemas"],
|
|
13526
13528
|
"properties",
|
|
@@ -13533,10 +13535,10 @@ function isSchemaPath(path66) {
|
|
|
13533
13535
|
];
|
|
13534
13536
|
return schemaLocations.some((location) => {
|
|
13535
13537
|
if (Array.isArray(location)) {
|
|
13536
|
-
return location.every((segment, index) =>
|
|
13538
|
+
return location.every((segment, index) => path67[index] === segment);
|
|
13537
13539
|
}
|
|
13538
|
-
return
|
|
13539
|
-
}) ||
|
|
13540
|
+
return path67.includes(location);
|
|
13541
|
+
}) || path67.includes("schema") || path67.some((segment) => segment.endsWith("Schema"));
|
|
13540
13542
|
}
|
|
13541
13543
|
|
|
13542
13544
|
// src/lib/oas/parser/index.ts
|
|
@@ -13618,13 +13620,13 @@ var OPENAPI_PROPS = /* @__PURE__ */ new Set([
|
|
|
13618
13620
|
"anyOf",
|
|
13619
13621
|
"oneOf"
|
|
13620
13622
|
]);
|
|
13621
|
-
var handleCircularRefs = (obj, currentPath = /* @__PURE__ */ new WeakSet(), refs = /* @__PURE__ */ new WeakMap(),
|
|
13623
|
+
var handleCircularRefs = (obj, currentPath = /* @__PURE__ */ new WeakSet(), refs = /* @__PURE__ */ new WeakMap(), path67 = [], currentRefPaths = /* @__PURE__ */ new Set()) => {
|
|
13622
13624
|
if (obj === null || typeof obj !== "object") return obj;
|
|
13623
13625
|
const refPath = obj.__$ref;
|
|
13624
13626
|
const isCircular = currentPath.has(obj) || typeof refPath === "string" && currentRefPaths.has(refPath);
|
|
13625
13627
|
if (isCircular) {
|
|
13626
13628
|
if (typeof refPath === "string") return SCHEMA_REF_PREFIX + refPath;
|
|
13627
|
-
const circularProp =
|
|
13629
|
+
const circularProp = path67.find((p) => !OPENAPI_PROPS.has(p)) || path67[0];
|
|
13628
13630
|
return [CIRCULAR_REF, circularProp].filter(Boolean).join(":");
|
|
13629
13631
|
}
|
|
13630
13632
|
if (refs.has(obj)) return refs.get(obj);
|
|
@@ -13634,7 +13636,7 @@ var handleCircularRefs = (obj, currentPath = /* @__PURE__ */ new WeakSet(), refs
|
|
|
13634
13636
|
value,
|
|
13635
13637
|
currentPath,
|
|
13636
13638
|
refs,
|
|
13637
|
-
[...
|
|
13639
|
+
[...path67, key],
|
|
13638
13640
|
currentRefPaths
|
|
13639
13641
|
);
|
|
13640
13642
|
const result = Array.isArray(obj) ? obj.map((item, i) => recurse(item, i.toString())) : Object.fromEntries(
|
|
@@ -13669,7 +13671,7 @@ var resolveExtensions = (obj) => Object.fromEntries(
|
|
|
13669
13671
|
var getAllTags = (schema2) => {
|
|
13670
13672
|
const rootTags = schema2.tags ?? [];
|
|
13671
13673
|
const operations = Object.values(schema2.paths ?? {}).flatMap(
|
|
13672
|
-
(
|
|
13674
|
+
(path67) => HttpMethods.map((k) => path67?.[k]).filter((op) => op != null)
|
|
13673
13675
|
);
|
|
13674
13676
|
const operationTags = new Set(operations.flatMap((op) => op.tags ?? []));
|
|
13675
13677
|
const hasUntaggedOperations = operations.some(
|
|
@@ -13724,7 +13726,7 @@ var getAllSlugs = (ops, schemaTags = []) => {
|
|
|
13724
13726
|
var getOperationSlugKey = (op) => [op.path, op.method, op.operationId, op.summary].filter(Boolean).join("-");
|
|
13725
13727
|
var getAllOperations = (paths) => {
|
|
13726
13728
|
const operations = Object.entries(paths ?? {}).flatMap(
|
|
13727
|
-
([
|
|
13729
|
+
([path67, value]) => HttpMethods.flatMap((method) => {
|
|
13728
13730
|
if (!value?.[method]) return [];
|
|
13729
13731
|
const operation = value[method];
|
|
13730
13732
|
const pathParameters = value.parameters ?? [];
|
|
@@ -13744,7 +13746,7 @@ var getAllOperations = (paths) => {
|
|
|
13744
13746
|
return {
|
|
13745
13747
|
...operation,
|
|
13746
13748
|
method,
|
|
13747
|
-
path:
|
|
13749
|
+
path: path67,
|
|
13748
13750
|
parameters,
|
|
13749
13751
|
servers,
|
|
13750
13752
|
tags: operation.tags ?? []
|
|
@@ -14102,8 +14104,8 @@ var Schema = builder.objectRef("Schema").implement({
|
|
|
14102
14104
|
}),
|
|
14103
14105
|
paths: t.field({
|
|
14104
14106
|
type: [PathItem],
|
|
14105
|
-
resolve: (root) => Object.entries(root.paths ?? {}).map(([
|
|
14106
|
-
path:
|
|
14107
|
+
resolve: (root) => Object.entries(root.paths ?? {}).map(([path67, value]) => ({
|
|
14108
|
+
path: path67,
|
|
14107
14109
|
// biome-ignore lint/style/noNonNullAssertion: value is guaranteed to be defined
|
|
14108
14110
|
methods: Object.keys(value)
|
|
14109
14111
|
}))
|
|
@@ -14268,7 +14270,7 @@ init_joinUrl();
|
|
|
14268
14270
|
|
|
14269
14271
|
// src/vite/api/schema-codegen.ts
|
|
14270
14272
|
var unescapeJsonPointer = (uri) => decodeURIComponent(uri.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
14271
|
-
var getSegmentsFromPath = (
|
|
14273
|
+
var getSegmentsFromPath = (path67) => path67.split("/").slice(1).map(unescapeJsonPointer);
|
|
14272
14274
|
var createLocalRefMap = (obj) => {
|
|
14273
14275
|
const refMap = /* @__PURE__ */ new Map();
|
|
14274
14276
|
const siblingsMap = /* @__PURE__ */ new Map();
|
|
@@ -14299,16 +14301,16 @@ var replaceMarkers = (code, mergedRefs) => code.replace(/"__refMap:(.*?)"/g, '__
|
|
|
14299
14301
|
/"__refMap\+Siblings:(.*?)"/g,
|
|
14300
14302
|
(_, key) => mergedRefs.get(key) ?? `__refMap["${key}"]`
|
|
14301
14303
|
);
|
|
14302
|
-
var lookup2 = (schema2,
|
|
14303
|
-
const parts = getSegmentsFromPath(
|
|
14304
|
+
var lookup2 = (schema2, path67, filePath) => {
|
|
14305
|
+
const parts = getSegmentsFromPath(path67);
|
|
14304
14306
|
let val = schema2;
|
|
14305
14307
|
for (const part of parts) {
|
|
14306
14308
|
while (val.$ref?.startsWith("#/")) {
|
|
14307
|
-
val = val.$ref ===
|
|
14309
|
+
val = val.$ref === path67 ? val : lookup2(schema2, val.$ref, filePath);
|
|
14308
14310
|
}
|
|
14309
14311
|
if (val[part] === void 0) {
|
|
14310
14312
|
throw new Error(
|
|
14311
|
-
`Error in ${filePath ?? "code generation"}: Could not find path segment ${part} in path: ${
|
|
14313
|
+
`Error in ${filePath ?? "code generation"}: Could not find path segment ${part} in path: ${path67}`
|
|
14312
14314
|
);
|
|
14313
14315
|
}
|
|
14314
14316
|
val = val[part];
|
|
@@ -14553,8 +14555,8 @@ var SchemaManager = class {
|
|
|
14553
14555
|
}
|
|
14554
14556
|
}
|
|
14555
14557
|
};
|
|
14556
|
-
getLatestSchema = (
|
|
14557
|
-
getSchemasForPath = (
|
|
14558
|
+
getLatestSchema = (path67) => this.processedSchemas[path67]?.at(0);
|
|
14559
|
+
getSchemasForPath = (path67) => this.processedSchemas[path67];
|
|
14558
14560
|
getSchemaImports = () => Object.values(this.processedSchemas).flat().filter((s) => s.importKey);
|
|
14559
14561
|
getUrlToFilePathMap = () => {
|
|
14560
14562
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -16964,14 +16966,14 @@ async function generateSitemap({
|
|
|
16964
16966
|
|
|
16965
16967
|
// src/vite/prerender/utils.ts
|
|
16966
16968
|
init_joinUrl();
|
|
16967
|
-
var resolveRoutePath = (
|
|
16968
|
-
const segments =
|
|
16969
|
+
var resolveRoutePath = (path67) => {
|
|
16970
|
+
const segments = path67.split("/");
|
|
16969
16971
|
if (segments.some((s) => s.startsWith(":") && !s.endsWith("?"))) {
|
|
16970
16972
|
return void 0;
|
|
16971
16973
|
}
|
|
16972
16974
|
return segments.filter((s) => !s.startsWith(":")).join("/") || void 0;
|
|
16973
16975
|
};
|
|
16974
|
-
var isSkipped = (
|
|
16976
|
+
var isSkipped = (path67) => path67.includes("*") || /^\d+$/.test(path67);
|
|
16975
16977
|
var resolveRoutes = (routes, parentPath = "") => routes.flatMap((route) => {
|
|
16976
16978
|
if (route.path && isSkipped(route.path)) return [];
|
|
16977
16979
|
const routePath = route.path ? resolveRoutePath(route.path) : void 0;
|
|
@@ -18449,8 +18451,8 @@ async function pathExists3(filePath) {
|
|
|
18449
18451
|
}
|
|
18450
18452
|
async function directoryHasEntries(dir) {
|
|
18451
18453
|
try {
|
|
18452
|
-
const { readdir:
|
|
18453
|
-
const entries = await
|
|
18454
|
+
const { readdir: readdir4 } = await import("node:fs/promises");
|
|
18455
|
+
const entries = await readdir4(dir);
|
|
18454
18456
|
return entries.length > 0;
|
|
18455
18457
|
} catch {
|
|
18456
18458
|
return false;
|
|
@@ -18504,12 +18506,13 @@ function buildCreateApitogoCliArgs(invocationArgs, projectName, options) {
|
|
|
18504
18506
|
const cliArgs = [
|
|
18505
18507
|
...invocationArgs,
|
|
18506
18508
|
projectName,
|
|
18507
|
-
"--
|
|
18509
|
+
"--typescript",
|
|
18510
|
+
"--eslint",
|
|
18508
18511
|
"--skip-install",
|
|
18509
18512
|
"--use-npm"
|
|
18510
18513
|
];
|
|
18511
18514
|
if (options?.withExamples) {
|
|
18512
|
-
cliArgs.push("--
|
|
18515
|
+
cliArgs.push("--include-examples");
|
|
18513
18516
|
}
|
|
18514
18517
|
return cliArgs;
|
|
18515
18518
|
}
|
|
@@ -20892,13 +20895,388 @@ var dev_default = {
|
|
|
20892
20895
|
};
|
|
20893
20896
|
|
|
20894
20897
|
// src/cli/init/handler.ts
|
|
20898
|
+
import path63 from "node:path";
|
|
20899
|
+
|
|
20900
|
+
// src/cli/scaffold/wire-docs.ts
|
|
20901
|
+
import {
|
|
20902
|
+
access as access9,
|
|
20903
|
+
lstat,
|
|
20904
|
+
mkdir as mkdir13,
|
|
20905
|
+
readdir as readdir3,
|
|
20906
|
+
readFile as readFile17,
|
|
20907
|
+
readlink,
|
|
20908
|
+
symlink,
|
|
20909
|
+
writeFile as writeFile16
|
|
20910
|
+
} from "node:fs/promises";
|
|
20895
20911
|
import path62 from "node:path";
|
|
20912
|
+
var DOCS_DIR_WHITELIST = [
|
|
20913
|
+
"docs",
|
|
20914
|
+
"documents",
|
|
20915
|
+
"documentation",
|
|
20916
|
+
"doc"
|
|
20917
|
+
];
|
|
20918
|
+
var SKIP_SEARCH_DIRS = /* @__PURE__ */ new Set([
|
|
20919
|
+
"node_modules",
|
|
20920
|
+
".git",
|
|
20921
|
+
"dist",
|
|
20922
|
+
"build",
|
|
20923
|
+
".next",
|
|
20924
|
+
"coverage",
|
|
20925
|
+
".turbo",
|
|
20926
|
+
".cache",
|
|
20927
|
+
".apitogo"
|
|
20928
|
+
]);
|
|
20929
|
+
var PAGES_DIR = "pages";
|
|
20930
|
+
var CONFIG_FILENAME = "apitogo.config.json";
|
|
20931
|
+
async function pathExists5(filePath) {
|
|
20932
|
+
try {
|
|
20933
|
+
await access9(filePath);
|
|
20934
|
+
return true;
|
|
20935
|
+
} catch {
|
|
20936
|
+
return false;
|
|
20937
|
+
}
|
|
20938
|
+
}
|
|
20939
|
+
async function isDirectory(filePath) {
|
|
20940
|
+
try {
|
|
20941
|
+
const stat4 = await lstat(filePath);
|
|
20942
|
+
return stat4.isDirectory();
|
|
20943
|
+
} catch {
|
|
20944
|
+
return false;
|
|
20945
|
+
}
|
|
20946
|
+
}
|
|
20947
|
+
function toPosix2(value) {
|
|
20948
|
+
return value.split(path62.sep).join(path62.posix.sep);
|
|
20949
|
+
}
|
|
20950
|
+
function isWhitelistedDirName(name) {
|
|
20951
|
+
return DOCS_DIR_WHITELIST.includes(name.toLowerCase());
|
|
20952
|
+
}
|
|
20953
|
+
function isInside(parent, child) {
|
|
20954
|
+
const relative = path62.relative(parent, child);
|
|
20955
|
+
return relative === "" || !relative.startsWith("..") && !path62.isAbsolute(relative);
|
|
20956
|
+
}
|
|
20957
|
+
async function collectMarkdownFiles(dir) {
|
|
20958
|
+
const files = [];
|
|
20959
|
+
let entries;
|
|
20960
|
+
try {
|
|
20961
|
+
entries = await readdir3(dir, { withFileTypes: true });
|
|
20962
|
+
} catch {
|
|
20963
|
+
return files;
|
|
20964
|
+
}
|
|
20965
|
+
for (const entry of entries) {
|
|
20966
|
+
if (entry.name.startsWith(".")) {
|
|
20967
|
+
continue;
|
|
20968
|
+
}
|
|
20969
|
+
const full = path62.join(dir, entry.name);
|
|
20970
|
+
if (entry.isDirectory()) {
|
|
20971
|
+
if (SKIP_SEARCH_DIRS.has(entry.name) || entry.isSymbolicLink()) {
|
|
20972
|
+
continue;
|
|
20973
|
+
}
|
|
20974
|
+
files.push(...await collectMarkdownFiles(full));
|
|
20975
|
+
continue;
|
|
20976
|
+
}
|
|
20977
|
+
if ((entry.isFile() || entry.isSymbolicLink()) && /\.mdx?$/i.test(entry.name)) {
|
|
20978
|
+
files.push(full);
|
|
20979
|
+
}
|
|
20980
|
+
}
|
|
20981
|
+
return files;
|
|
20982
|
+
}
|
|
20983
|
+
async function collectSearchRoots(siteDirectory) {
|
|
20984
|
+
const site = path62.resolve(siteDirectory);
|
|
20985
|
+
const parent = path62.dirname(site);
|
|
20986
|
+
const roots = [];
|
|
20987
|
+
const add = (dir) => {
|
|
20988
|
+
const resolved = path62.resolve(dir);
|
|
20989
|
+
if (!roots.includes(resolved)) {
|
|
20990
|
+
roots.push(resolved);
|
|
20991
|
+
}
|
|
20992
|
+
};
|
|
20993
|
+
if (parent && parent !== site) {
|
|
20994
|
+
add(parent);
|
|
20995
|
+
try {
|
|
20996
|
+
const entries = await readdir3(parent, { withFileTypes: true });
|
|
20997
|
+
for (const entry of entries) {
|
|
20998
|
+
if (!entry.isDirectory() || SKIP_SEARCH_DIRS.has(entry.name)) {
|
|
20999
|
+
continue;
|
|
21000
|
+
}
|
|
21001
|
+
add(path62.join(parent, entry.name));
|
|
21002
|
+
}
|
|
21003
|
+
} catch {
|
|
21004
|
+
}
|
|
21005
|
+
}
|
|
21006
|
+
add(site);
|
|
21007
|
+
return roots;
|
|
21008
|
+
}
|
|
21009
|
+
async function discoverNearbyDocsDirectories(siteDirectory) {
|
|
21010
|
+
const site = path62.resolve(siteDirectory);
|
|
21011
|
+
const sitePages = path62.join(site, PAGES_DIR);
|
|
21012
|
+
const searchedDirectories = await collectSearchRoots(site);
|
|
21013
|
+
const directories = [];
|
|
21014
|
+
const seen = /* @__PURE__ */ new Set();
|
|
21015
|
+
const consider = async (dir) => {
|
|
21016
|
+
const resolved = path62.resolve(dir);
|
|
21017
|
+
if (resolved === site || seen.has(resolved) || isInside(sitePages, resolved)) {
|
|
21018
|
+
return;
|
|
21019
|
+
}
|
|
21020
|
+
if (!await isDirectory(resolved)) {
|
|
21021
|
+
return;
|
|
21022
|
+
}
|
|
21023
|
+
const files = (await collectMarkdownFiles(resolved)).sort(
|
|
21024
|
+
(a, b) => a.localeCompare(b)
|
|
21025
|
+
);
|
|
21026
|
+
if (files.length === 0) {
|
|
21027
|
+
return;
|
|
21028
|
+
}
|
|
21029
|
+
seen.add(resolved);
|
|
21030
|
+
directories.push({ sourceDirectory: resolved, files });
|
|
21031
|
+
};
|
|
21032
|
+
for (const root of searchedDirectories) {
|
|
21033
|
+
if (isWhitelistedDirName(path62.basename(root))) {
|
|
21034
|
+
await consider(root);
|
|
21035
|
+
}
|
|
21036
|
+
try {
|
|
21037
|
+
const entries = await readdir3(root, { withFileTypes: true });
|
|
21038
|
+
for (const entry of entries) {
|
|
21039
|
+
if (!entry.isDirectory() || SKIP_SEARCH_DIRS.has(entry.name)) {
|
|
21040
|
+
continue;
|
|
21041
|
+
}
|
|
21042
|
+
if (!isWhitelistedDirName(entry.name)) {
|
|
21043
|
+
continue;
|
|
21044
|
+
}
|
|
21045
|
+
await consider(path62.join(root, entry.name));
|
|
21046
|
+
}
|
|
21047
|
+
} catch {
|
|
21048
|
+
}
|
|
21049
|
+
}
|
|
21050
|
+
return { directories, searchedDirectories };
|
|
21051
|
+
}
|
|
21052
|
+
function slugifyDirName(name) {
|
|
21053
|
+
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "docs";
|
|
21054
|
+
}
|
|
21055
|
+
async function allocateLinkName(pagesDir, sourceDirectory, used) {
|
|
21056
|
+
const base = slugifyDirName(path62.basename(sourceDirectory));
|
|
21057
|
+
const parent = slugifyDirName(path62.basename(path62.dirname(sourceDirectory)));
|
|
21058
|
+
const candidates = [base, `${parent}-${base}`];
|
|
21059
|
+
let index = 2;
|
|
21060
|
+
while (true) {
|
|
21061
|
+
const name = candidates.shift() ?? `${base}-${index++}`;
|
|
21062
|
+
if (used.has(name)) {
|
|
21063
|
+
continue;
|
|
21064
|
+
}
|
|
21065
|
+
const target = path62.join(pagesDir, name);
|
|
21066
|
+
if (await pathExists5(target)) {
|
|
21067
|
+
const stat4 = await lstat(target);
|
|
21068
|
+
if (!stat4.isDirectory() || !await isManagedLinkDir(target)) {
|
|
21069
|
+
continue;
|
|
21070
|
+
}
|
|
21071
|
+
}
|
|
21072
|
+
used.add(name);
|
|
21073
|
+
return name;
|
|
21074
|
+
}
|
|
21075
|
+
}
|
|
21076
|
+
async function isManagedLinkDir(dir) {
|
|
21077
|
+
try {
|
|
21078
|
+
const entries = await readdir3(dir, { withFileTypes: true });
|
|
21079
|
+
if (entries.length === 0) {
|
|
21080
|
+
return true;
|
|
21081
|
+
}
|
|
21082
|
+
return entries.every(
|
|
21083
|
+
(entry) => entry.isSymbolicLink() || entry.isDirectory()
|
|
21084
|
+
);
|
|
21085
|
+
} catch {
|
|
21086
|
+
return false;
|
|
21087
|
+
}
|
|
21088
|
+
}
|
|
21089
|
+
async function alreadyLinked(linkPath, sourcePath) {
|
|
21090
|
+
try {
|
|
21091
|
+
const stat4 = await lstat(linkPath);
|
|
21092
|
+
if (!stat4.isSymbolicLink()) {
|
|
21093
|
+
return false;
|
|
21094
|
+
}
|
|
21095
|
+
const current = await readlink(linkPath);
|
|
21096
|
+
const resolved = path62.resolve(path62.dirname(linkPath), current);
|
|
21097
|
+
return resolved === path62.resolve(sourcePath);
|
|
21098
|
+
} catch {
|
|
21099
|
+
return false;
|
|
21100
|
+
}
|
|
21101
|
+
}
|
|
21102
|
+
async function linkMarkdownFile(sourcePath, linkPath) {
|
|
21103
|
+
if (await alreadyLinked(linkPath, sourcePath)) {
|
|
21104
|
+
return "exists";
|
|
21105
|
+
}
|
|
21106
|
+
if (await pathExists5(linkPath)) {
|
|
21107
|
+
return "skipped";
|
|
21108
|
+
}
|
|
21109
|
+
await mkdir13(path62.dirname(linkPath), { recursive: true });
|
|
21110
|
+
const relativeTarget = path62.relative(path62.dirname(linkPath), sourcePath);
|
|
21111
|
+
await symlink(
|
|
21112
|
+
relativeTarget,
|
|
21113
|
+
linkPath,
|
|
21114
|
+
process.platform === "win32" ? "file" : void 0
|
|
21115
|
+
);
|
|
21116
|
+
return "linked";
|
|
21117
|
+
}
|
|
21118
|
+
function isPlainObject4(value) {
|
|
21119
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
21120
|
+
}
|
|
21121
|
+
async function applyDocsNavigation(siteDirectory, routes) {
|
|
21122
|
+
if (routes.length === 0) {
|
|
21123
|
+
return;
|
|
21124
|
+
}
|
|
21125
|
+
const configPath = path62.join(siteDirectory, CONFIG_FILENAME);
|
|
21126
|
+
if (!await pathExists5(configPath)) {
|
|
21127
|
+
return;
|
|
21128
|
+
}
|
|
21129
|
+
const raw = await readFile17(configPath, "utf8");
|
|
21130
|
+
const parsed = JSON.parse(raw);
|
|
21131
|
+
if (!isPlainObject4(parsed)) {
|
|
21132
|
+
return;
|
|
21133
|
+
}
|
|
21134
|
+
parsed.navigation = mergeDocumentationNavigation(parsed.navigation, routes, {
|
|
21135
|
+
force: false
|
|
21136
|
+
});
|
|
21137
|
+
await writeFile16(configPath, `${JSON.stringify(parsed, null, 2)}
|
|
21138
|
+
`, "utf8");
|
|
21139
|
+
}
|
|
21140
|
+
async function discoverAndWireDocs(siteDirectory) {
|
|
21141
|
+
const site = path62.resolve(siteDirectory);
|
|
21142
|
+
const pagesDir = path62.join(site, PAGES_DIR);
|
|
21143
|
+
const { directories, searchedDirectories } = await discoverNearbyDocsDirectories(site);
|
|
21144
|
+
if (directories.length === 0) {
|
|
21145
|
+
return {
|
|
21146
|
+
status: "not_found",
|
|
21147
|
+
whitelist: DOCS_DIR_WHITELIST,
|
|
21148
|
+
searchedDirectories,
|
|
21149
|
+
sources: [],
|
|
21150
|
+
fileCount: 0,
|
|
21151
|
+
skippedCount: 0
|
|
21152
|
+
};
|
|
21153
|
+
}
|
|
21154
|
+
await mkdir13(pagesDir, { recursive: true });
|
|
21155
|
+
const usedNames = /* @__PURE__ */ new Set();
|
|
21156
|
+
const sources = [];
|
|
21157
|
+
const routes = [];
|
|
21158
|
+
for (const directory of directories) {
|
|
21159
|
+
const linkName = await allocateLinkName(
|
|
21160
|
+
pagesDir,
|
|
21161
|
+
directory.sourceDirectory,
|
|
21162
|
+
usedNames
|
|
21163
|
+
);
|
|
21164
|
+
const linkDirectory = path62.join(pagesDir, linkName);
|
|
21165
|
+
const linked = [];
|
|
21166
|
+
const skipped = [];
|
|
21167
|
+
for (const sourcePath of directory.files) {
|
|
21168
|
+
const relativeSource = toPosix2(
|
|
21169
|
+
path62.relative(directory.sourceDirectory, sourcePath)
|
|
21170
|
+
);
|
|
21171
|
+
const linkPath = path62.join(linkDirectory, relativeSource);
|
|
21172
|
+
const result = await linkMarkdownFile(sourcePath, linkPath);
|
|
21173
|
+
if (result === "skipped") {
|
|
21174
|
+
skipped.push({
|
|
21175
|
+
sourcePath,
|
|
21176
|
+
reason: "target already exists and is not this source"
|
|
21177
|
+
});
|
|
21178
|
+
continue;
|
|
21179
|
+
}
|
|
21180
|
+
const relativeLink = toPosix2(path62.relative(site, linkPath));
|
|
21181
|
+
const route = toRoutePath(relativeLink, PAGES_DIR);
|
|
21182
|
+
linked.push({ sourcePath, linkPath, route, relativeSource });
|
|
21183
|
+
routes.push(route);
|
|
21184
|
+
}
|
|
21185
|
+
sources.push({
|
|
21186
|
+
sourceDirectory: directory.sourceDirectory,
|
|
21187
|
+
linkDirectory,
|
|
21188
|
+
linkName,
|
|
21189
|
+
files: linked,
|
|
21190
|
+
skipped
|
|
21191
|
+
});
|
|
21192
|
+
}
|
|
21193
|
+
await applyDocsNavigation(site, routes);
|
|
21194
|
+
const fileCount = sources.reduce(
|
|
21195
|
+
(sum, source) => sum + source.files.length,
|
|
21196
|
+
0
|
|
21197
|
+
);
|
|
21198
|
+
const skippedCount = sources.reduce(
|
|
21199
|
+
(sum, source) => sum + source.skipped.length,
|
|
21200
|
+
0
|
|
21201
|
+
);
|
|
21202
|
+
const status2 = fileCount === 0 ? "not_found" : skippedCount > 0 ? "partial" : "wired";
|
|
21203
|
+
return {
|
|
21204
|
+
status: status2,
|
|
21205
|
+
whitelist: DOCS_DIR_WHITELIST,
|
|
21206
|
+
searchedDirectories,
|
|
21207
|
+
sources,
|
|
21208
|
+
fileCount,
|
|
21209
|
+
skippedCount
|
|
21210
|
+
};
|
|
21211
|
+
}
|
|
21212
|
+
function siteRelative(siteDirectory, filePath) {
|
|
21213
|
+
const relative = toPosix2(path62.relative(siteDirectory, filePath));
|
|
21214
|
+
if (!relative) {
|
|
21215
|
+
return ".";
|
|
21216
|
+
}
|
|
21217
|
+
if (path62.isAbsolute(relative)) {
|
|
21218
|
+
return toPosix2(filePath);
|
|
21219
|
+
}
|
|
21220
|
+
if (relative.startsWith("..")) {
|
|
21221
|
+
return relative;
|
|
21222
|
+
}
|
|
21223
|
+
return `./${relative}`;
|
|
21224
|
+
}
|
|
21225
|
+
function formatOpenApiDiscoveryLines(siteDirectory, openApiDiscovery) {
|
|
21226
|
+
const status2 = String(openApiDiscovery.status ?? "unknown");
|
|
21227
|
+
if (status2 === "wired") {
|
|
21228
|
+
const input3 = typeof openApiDiscovery.openApiInput === "string" ? openApiDiscovery.openApiInput : typeof openApiDiscovery.openApiPath === "string" ? siteRelative(siteDirectory, openApiDiscovery.openApiPath) : "OpenAPI";
|
|
21229
|
+
const title = typeof openApiDiscovery.openApiTitle === "string" ? ` (${openApiDiscovery.openApiTitle})` : "";
|
|
21230
|
+
const apiPath = typeof openApiDiscovery.apiReferencePath === "string" ? openApiDiscovery.apiReferencePath : "/api";
|
|
21231
|
+
return [`OpenAPI: wired ${input3}${title} \u2192 ${apiPath}`];
|
|
21232
|
+
}
|
|
21233
|
+
if (status2 === "skipped") {
|
|
21234
|
+
return ["OpenAPI: search skipped"];
|
|
21235
|
+
}
|
|
21236
|
+
if (status2 === "invalid" || status2 === "wire_failed") {
|
|
21237
|
+
const error = typeof openApiDiscovery.error === "string" ? `: ${openApiDiscovery.error}` : "";
|
|
21238
|
+
return [`OpenAPI: found a spec but did not wire it${error}`];
|
|
21239
|
+
}
|
|
21240
|
+
return ["OpenAPI: none found nearby"];
|
|
21241
|
+
}
|
|
21242
|
+
function formatDocsDiscoveryLines(siteDirectory, docsDiscovery) {
|
|
21243
|
+
if (docsDiscovery.status === "not_found") {
|
|
21244
|
+
return [
|
|
21245
|
+
`Docs: none found in ${DOCS_DIR_WHITELIST.join("/")}/ folders nearby`
|
|
21246
|
+
];
|
|
21247
|
+
}
|
|
21248
|
+
const lines = [
|
|
21249
|
+
`Docs: linked ${docsDiscovery.fileCount} markdown file${docsDiscovery.fileCount === 1 ? "" : "s"} (not copied)`
|
|
21250
|
+
];
|
|
21251
|
+
for (const source of docsDiscovery.sources) {
|
|
21252
|
+
const from = siteRelative(siteDirectory, source.sourceDirectory);
|
|
21253
|
+
const to = siteRelative(siteDirectory, source.linkDirectory);
|
|
21254
|
+
lines.push(` ${from} \u2192 ${to}`);
|
|
21255
|
+
for (const file of source.files) {
|
|
21256
|
+
lines.push(` ${file.relativeSource} \u2192 ${file.route}`);
|
|
21257
|
+
}
|
|
21258
|
+
for (const skipped of source.skipped) {
|
|
21259
|
+
lines.push(
|
|
21260
|
+
` skipped ${siteRelative(siteDirectory, skipped.sourcePath)}`
|
|
21261
|
+
);
|
|
21262
|
+
}
|
|
21263
|
+
}
|
|
21264
|
+
return lines;
|
|
21265
|
+
}
|
|
21266
|
+
function formatInitDiscoveryReport(siteDirectory, openApiDiscovery, docsDiscovery) {
|
|
21267
|
+
return [
|
|
21268
|
+
...formatOpenApiDiscoveryLines(siteDirectory, openApiDiscovery),
|
|
21269
|
+
...formatDocsDiscoveryLines(siteDirectory, docsDiscovery)
|
|
21270
|
+
];
|
|
21271
|
+
}
|
|
21272
|
+
|
|
21273
|
+
// src/cli/init/handler.ts
|
|
20896
21274
|
function slugifyName2(name) {
|
|
20897
21275
|
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "dev-portal-site";
|
|
20898
21276
|
}
|
|
20899
21277
|
function resolveInitOutputDirectory(dirArg, name) {
|
|
20900
|
-
const resolved =
|
|
20901
|
-
const base =
|
|
21278
|
+
const resolved = path63.resolve(process.cwd(), dirArg);
|
|
21279
|
+
const base = path63.basename(resolved);
|
|
20902
21280
|
const isDot = dirArg === "." || dirArg === "./" || base === "." || resolved === process.cwd();
|
|
20903
21281
|
if (isDot) {
|
|
20904
21282
|
const fromName = name?.trim();
|
|
@@ -20908,7 +21286,7 @@ function resolveInitOutputDirectory(dirArg, name) {
|
|
|
20908
21286
|
);
|
|
20909
21287
|
}
|
|
20910
21288
|
return {
|
|
20911
|
-
outputDirectory:
|
|
21289
|
+
outputDirectory: path63.resolve(process.cwd(), slugifyName2(fromName)),
|
|
20912
21290
|
siteName: fromName
|
|
20913
21291
|
};
|
|
20914
21292
|
}
|
|
@@ -20942,10 +21320,7 @@ async function init2(argv) {
|
|
|
20942
21320
|
siteName,
|
|
20943
21321
|
includeDefaultPlans: false
|
|
20944
21322
|
});
|
|
20945
|
-
const manifestPath = await writeManifest(
|
|
20946
|
-
result.outputDirectory,
|
|
20947
|
-
manifest
|
|
20948
|
-
);
|
|
21323
|
+
const manifestPath = await writeManifest(result.outputDirectory, manifest);
|
|
20949
21324
|
const secretsArtifacts = await writeScaffoldSecretsArtifacts(
|
|
20950
21325
|
result.outputDirectory
|
|
20951
21326
|
);
|
|
@@ -20960,9 +21335,15 @@ async function init2(argv) {
|
|
|
20960
21335
|
result.outputDirectory,
|
|
20961
21336
|
openapiSearch
|
|
20962
21337
|
);
|
|
21338
|
+
const docsDiscovery = await discoverAndWireDocs(result.outputDirectory);
|
|
20963
21339
|
const siteValidation = await validateDevPortalSiteConfig(
|
|
20964
21340
|
result.outputDirectory
|
|
20965
21341
|
);
|
|
21342
|
+
const discoveryReport = formatInitDiscoveryReport(
|
|
21343
|
+
result.outputDirectory,
|
|
21344
|
+
openApiDiscovery,
|
|
21345
|
+
docsDiscovery
|
|
21346
|
+
);
|
|
20966
21347
|
const devCommand = "npm run dev";
|
|
20967
21348
|
const response = {
|
|
20968
21349
|
status: "succeeded",
|
|
@@ -20980,9 +21361,11 @@ async function init2(argv) {
|
|
|
20980
21361
|
npmInstallCompleted: install,
|
|
20981
21362
|
npmInstallDurationMs: npmInstall?.durationMs ?? null,
|
|
20982
21363
|
openApiDiscovery,
|
|
21364
|
+
docsDiscovery,
|
|
20983
21365
|
openapiSearch,
|
|
20984
21366
|
previewStarted: false,
|
|
20985
21367
|
devCommand,
|
|
21368
|
+
discoveryReport,
|
|
20986
21369
|
message: `Dev portal created in ${result.outputDirectory}. Run \`${devCommand}\` there to preview locally.`,
|
|
20987
21370
|
...buildSiteValidationResponseFields(siteValidation)
|
|
20988
21371
|
};
|
|
@@ -20995,6 +21378,9 @@ async function init2(argv) {
|
|
|
20995
21378
|
printResultToConsole(
|
|
20996
21379
|
`Portal scaffolded in ${result.outputDirectory}. Next: apitogo config, apitogo dev, then apitogo apply.`
|
|
20997
21380
|
);
|
|
21381
|
+
for (const line of discoveryReport) {
|
|
21382
|
+
printDiagnosticsToConsole(line);
|
|
21383
|
+
}
|
|
20998
21384
|
if (!install) {
|
|
20999
21385
|
printDiagnosticsToConsole(
|
|
21000
21386
|
"Skipped npm install (--no-install). Run npm install before npm run dev."
|
|
@@ -21145,9 +21531,9 @@ var remove_default = {
|
|
|
21145
21531
|
};
|
|
21146
21532
|
|
|
21147
21533
|
// src/cli/status/handler.ts
|
|
21148
|
-
import
|
|
21534
|
+
import path64 from "node:path";
|
|
21149
21535
|
async function status(argv) {
|
|
21150
|
-
const sourceDirectory =
|
|
21536
|
+
const sourceDirectory = path64.resolve(process.cwd(), argv.dir);
|
|
21151
21537
|
const config2 = loadConfig();
|
|
21152
21538
|
const client = new PlatformApiClient(config2);
|
|
21153
21539
|
let whoamiJson;
|
|
@@ -21227,7 +21613,7 @@ var status_default = {
|
|
|
21227
21613
|
};
|
|
21228
21614
|
|
|
21229
21615
|
// src/cli/teardown/handler.ts
|
|
21230
|
-
import
|
|
21616
|
+
import path65 from "node:path";
|
|
21231
21617
|
function resultLooksFailed3(payload) {
|
|
21232
21618
|
try {
|
|
21233
21619
|
const parsed = JSON.parse(payload);
|
|
@@ -21243,7 +21629,7 @@ async function teardown(argv) {
|
|
|
21243
21629
|
);
|
|
21244
21630
|
return;
|
|
21245
21631
|
}
|
|
21246
|
-
const sourceDirectory =
|
|
21632
|
+
const sourceDirectory = path65.resolve(process.cwd(), argv.dir);
|
|
21247
21633
|
const config2 = loadConfig();
|
|
21248
21634
|
const client = new PlatformApiClient(config2);
|
|
21249
21635
|
let projectId = argv.projectId?.trim();
|
|
@@ -21309,7 +21695,7 @@ var teardown_default = {
|
|
|
21309
21695
|
|
|
21310
21696
|
// src/cli/common/outdated.ts
|
|
21311
21697
|
import { existsSync as existsSync4, mkdirSync } from "node:fs";
|
|
21312
|
-
import { readFile as
|
|
21698
|
+
import { readFile as readFile18, writeFile as writeFile17 } from "node:fs/promises";
|
|
21313
21699
|
import { join } from "node:path";
|
|
21314
21700
|
import colors10 from "picocolors";
|
|
21315
21701
|
import { gt } from "semver";
|
|
@@ -21376,12 +21762,12 @@ function box(message, {
|
|
|
21376
21762
|
|
|
21377
21763
|
// src/cli/common/xdg/lib.ts
|
|
21378
21764
|
import { homedir } from "node:os";
|
|
21379
|
-
import
|
|
21765
|
+
import path66 from "node:path";
|
|
21380
21766
|
function defineDirectoryWithFallback(xdgName, fallback) {
|
|
21381
21767
|
if (process.env[xdgName]) {
|
|
21382
21768
|
return process.env[xdgName];
|
|
21383
21769
|
} else {
|
|
21384
|
-
return
|
|
21770
|
+
return path66.join(homedir(), fallback);
|
|
21385
21771
|
}
|
|
21386
21772
|
}
|
|
21387
21773
|
var XDG_CONFIG_HOME = defineDirectoryWithFallback(
|
|
@@ -21396,15 +21782,15 @@ var XDG_STATE_HOME = defineDirectoryWithFallback(
|
|
|
21396
21782
|
"XDG_DATA_HOME",
|
|
21397
21783
|
".local/state"
|
|
21398
21784
|
);
|
|
21399
|
-
var ZUDOKU_XDG_CONFIG_HOME =
|
|
21785
|
+
var ZUDOKU_XDG_CONFIG_HOME = path66.join(
|
|
21400
21786
|
XDG_CONFIG_HOME,
|
|
21401
21787
|
CLI_XDG_FOLDER_NAME
|
|
21402
21788
|
);
|
|
21403
|
-
var ZUDOKU_XDG_DATA_HOME =
|
|
21789
|
+
var ZUDOKU_XDG_DATA_HOME = path66.join(
|
|
21404
21790
|
XDG_DATA_HOME,
|
|
21405
21791
|
CLI_XDG_FOLDER_NAME
|
|
21406
21792
|
);
|
|
21407
|
-
var ZUDOKU_XDG_STATE_HOME =
|
|
21793
|
+
var ZUDOKU_XDG_STATE_HOME = path66.join(
|
|
21408
21794
|
XDG_STATE_HOME,
|
|
21409
21795
|
CLI_XDG_FOLDER_NAME
|
|
21410
21796
|
);
|
|
@@ -21456,7 +21842,7 @@ async function getVersionCheckInfo() {
|
|
|
21456
21842
|
let versionCheckInfo;
|
|
21457
21843
|
if (existsSync4(versionCheckPath)) {
|
|
21458
21844
|
try {
|
|
21459
|
-
versionCheckInfo = await
|
|
21845
|
+
versionCheckInfo = await readFile18(versionCheckPath, "utf-8").then(
|
|
21460
21846
|
JSON.parse
|
|
21461
21847
|
);
|
|
21462
21848
|
} catch {
|
|
@@ -21481,7 +21867,7 @@ async function getVersionCheckInfo() {
|
|
|
21481
21867
|
lastCheck: Date.now(),
|
|
21482
21868
|
latestVersion
|
|
21483
21869
|
};
|
|
21484
|
-
await
|
|
21870
|
+
await writeFile17(
|
|
21485
21871
|
versionCheckPath,
|
|
21486
21872
|
JSON.stringify(versionCheckInfo),
|
|
21487
21873
|
"utf-8"
|
package/docs/cli/commands.md
CHANGED
|
@@ -29,7 +29,8 @@ same commands so agents and humans get identical behavior.
|
|
|
29
29
|
| `init [dir]` | Named folder; `--install` (default), `--overwrite`, `--json`, `--openapi-search` |
|
|
30
30
|
| `config` | Interactive on TTY; flags: `--openapi`, `--page-*`, `--plan`, `--backend`, `--theme`, `--patch`, `--json` |
|
|
31
31
|
|
|
32
|
-
`
|
|
32
|
+
`npx @lukoweb/create-apitogo@latest` remains an interactive alternative for new folders.
|
|
33
|
+
Pass `--typescript --eslint` to skip those prompts. See [Install the CLI](./setup.md#scaffold-options).
|
|
33
34
|
|
|
34
35
|
See [Make config (CLI)](../configuration/make-config.mdx) for all `config` flags.
|
|
35
36
|
|
package/docs/cli/overview.md
CHANGED
|
@@ -13,7 +13,7 @@ local files, preview with `apitogo dev`, and publish to APItoGo hosting with `ap
|
|
|
13
13
|
|
|
14
14
|
## What you get
|
|
15
15
|
|
|
16
|
-
- Scaffold a local portal site (`
|
|
16
|
+
- Scaffold a local portal site (`npx @lukoweb/create-apitogo@latest` or `apitogo init`)
|
|
17
17
|
- Shape backend, OpenAPI, plans, and docs pages via `apitogo config` and file edits
|
|
18
18
|
- Preview locally (`apitogo dev`)
|
|
19
19
|
- Publish to APItoGo hosting (`apitogo apply`) with platform plans **Free**, **Starter**, or
|
package/docs/cli/setup.md
CHANGED
|
@@ -23,10 +23,10 @@ need a global install — scaffold commands add it to your project and `npm inst
|
|
|
23
23
|
|
|
24
24
|
### New project (recommended)
|
|
25
25
|
|
|
26
|
-
`
|
|
26
|
+
`npx @lukoweb/create-apitogo` scaffolds the site **and** installs `@lukoweb/apitogo` locally:
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
|
-
|
|
29
|
+
npx @lukoweb/create-apitogo@latest
|
|
30
30
|
cd your-project-name
|
|
31
31
|
npx apitogo config # interactive: backend, OpenAPI, pages, plans
|
|
32
32
|
npm run dev
|
|
@@ -35,14 +35,28 @@ npm run dev
|
|
|
35
35
|
Also works with `pnpm create @lukoweb/apitogo`, `yarn create @lukoweb/apitogo`, or
|
|
36
36
|
`bunx @lukoweb/create-apitogo`.
|
|
37
37
|
|
|
38
|
-
Non-interactive
|
|
38
|
+
Non-interactive:
|
|
39
39
|
|
|
40
40
|
```bash
|
|
41
|
-
|
|
41
|
+
npx @lukoweb/create-apitogo@latest my-portal --typescript --eslint
|
|
42
42
|
cd my-portal
|
|
43
43
|
npx apitogo config
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
+
#### Scaffold options
|
|
47
|
+
|
|
48
|
+
| Flag | Effect |
|
|
49
|
+
| ---- | ------ |
|
|
50
|
+
| `--typescript` / `--ts` | TypeScript project |
|
|
51
|
+
| `--javascript` / `--js` | JavaScript project |
|
|
52
|
+
| `--eslint` | Add ESLint config |
|
|
53
|
+
| `--no-eslint` | Skip ESLint |
|
|
54
|
+
| `--include-examples` | Add starter docs and a sample OpenAPI spec (off unless passed) |
|
|
55
|
+
|
|
56
|
+
Omit flags to be prompted for TypeScript and ESLint. Example files are never prompted.
|
|
57
|
+
|
|
58
|
+
See `@lukoweb/create-apitogo --help` for package manager and install flags.
|
|
59
|
+
|
|
46
60
|
### Scaffold into an existing folder
|
|
47
61
|
|
|
48
62
|
`apitogo init` writes `package.json` with `@lukoweb/apitogo` as a dependency. Run **`npm install`**
|
|
@@ -63,7 +77,7 @@ to preview, then `apitogo apply` when ready to go live.
|
|
|
63
77
|
|
|
64
78
|
| Situation | Command |
|
|
65
79
|
| --------- | ------- |
|
|
66
|
-
| After `
|
|
80
|
+
| After `npx @lukoweb/create-apitogo` or `npm install` in the project | `npx apitogo <command>` (e.g. `npx apitogo config`) |
|
|
67
81
|
| Same, if `node_modules/.bin` is on your PATH | `apitogo <command>` |
|
|
68
82
|
| One-off, no project yet | `npx @lukoweb/apitogo <command>` |
|
|
69
83
|
| Optional global install | `npm install -g @lukoweb/apitogo` then `apitogo <command>` anywhere |
|
package/docs/cli/shape.md
CHANGED
|
@@ -13,10 +13,10 @@ Requires the **`apitogo`** CLI (`@lukoweb/apitogo`). If you have not installed i
|
|
|
13
13
|
|
|
14
14
|
## Happy path
|
|
15
15
|
|
|
16
|
-
`
|
|
16
|
+
`npx @lukoweb/create-apitogo` installs `@lukoweb/apitogo` into the new project. Then run config via `npx`:
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
|
-
|
|
19
|
+
npx @lukoweb/create-apitogo@latest my-portal --typescript --eslint
|
|
20
20
|
cd my-portal
|
|
21
21
|
npx apitogo config # backend, OpenAPI, pages, plans (apply each immediately)
|
|
22
22
|
npm run dev # http://localhost:3000
|
|
@@ -20,7 +20,7 @@ on new scaffolds. The command does **not** change `redirects`.
|
|
|
20
20
|
|
|
21
21
|
Install the CLI first — see [Install the CLI](../cli/setup.md). In short:
|
|
22
22
|
|
|
23
|
-
- **New site:** `
|
|
23
|
+
- **New site:** `npx @lukoweb/create-apitogo@latest` (installs `@lukoweb/apitogo` into the project)
|
|
24
24
|
- **Existing folder:** `npx @lukoweb/apitogo init .` then `npm install`
|
|
25
25
|
|
|
26
26
|
Run config from the project root with `npx apitogo config` (or `apitogo config` if
|