@autoview/cli 0.1.0
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/LICENSE +661 -0
- package/README.md +407 -0
- package/lib/AutoViewAgent.d.ts +109 -0
- package/lib/AutoViewAgent.js +123 -0
- package/lib/AutoViewAgent.js.map +1 -0
- package/lib/agent/emitMcpServer.d.ts +15 -0
- package/lib/agent/emitMcpServer.js +157 -0
- package/lib/agent/emitMcpServer.js.map +1 -0
- package/lib/agent/emitReport.d.ts +14 -0
- package/lib/agent/emitReport.js +85 -0
- package/lib/agent/emitReport.js.map +1 -0
- package/lib/agent/toolSurface.d.ts +130 -0
- package/lib/agent/toolSurface.js +342 -0
- package/lib/agent/toolSurface.js.map +1 -0
- package/lib/agent/verifyAgentTasks.d.ts +87 -0
- package/lib/agent/verifyAgentTasks.js +126 -0
- package/lib/agent/verifyAgentTasks.js.map +1 -0
- package/lib/cli/main.d.ts +2 -0
- package/lib/cli/main.js +295 -0
- package/lib/cli/main.js.map +1 -0
- package/lib/compiler/AutoViewInterfaceCompiler.d.ts +27 -0
- package/lib/compiler/AutoViewInterfaceCompiler.js +68 -0
- package/lib/compiler/AutoViewInterfaceCompiler.js.map +1 -0
- package/lib/constants/AutoViewFrontendTemplate.d.ts +1 -0
- package/lib/constants/AutoViewFrontendTemplate.js +46 -0
- package/lib/constants/AutoViewFrontendTemplate.js.map +1 -0
- package/lib/constants/AutoViewSystemPromptConstant.d.ts +5 -0
- package/lib/constants/AutoViewSystemPromptConstant.js +4 -0
- package/lib/constants/AutoViewSystemPromptConstant.js.map +1 -0
- package/lib/context/IAutoViewAgentContext.d.ts +60 -0
- package/lib/context/IAutoViewAgentContext.js +3 -0
- package/lib/context/IAutoViewAgentContext.js.map +1 -0
- package/lib/fromSwagger.d.ts +53 -0
- package/lib/fromSwagger.js +513 -0
- package/lib/fromSwagger.js.map +1 -0
- package/lib/generateDeterministic.d.ts +26 -0
- package/lib/generateDeterministic.js +75 -0
- package/lib/generateDeterministic.js.map +1 -0
- package/lib/index.d.ts +15 -0
- package/lib/index.js +41 -0
- package/lib/index.js.map +1 -0
- package/lib/orchestrate/orchestrateAutoView.d.ts +17 -0
- package/lib/orchestrate/orchestrateAutoView.js +491 -0
- package/lib/orchestrate/orchestrateAutoView.js.map +1 -0
- package/lib/orchestrate/orchestrateAutoViewProductPlan.d.ts +37 -0
- package/lib/orchestrate/orchestrateAutoViewProductPlan.js +109 -0
- package/lib/orchestrate/orchestrateAutoViewProductPlan.js.map +1 -0
- package/lib/orchestrate/orchestrateAutoViewRender.d.ts +133 -0
- package/lib/orchestrate/orchestrateAutoViewRender.js +943 -0
- package/lib/orchestrate/orchestrateAutoViewRender.js.map +1 -0
- package/lib/orchestrate/orchestrateAutoViewRenderDeterministic.d.ts +24 -0
- package/lib/orchestrate/orchestrateAutoViewRenderDeterministic.js +92 -0
- package/lib/orchestrate/orchestrateAutoViewRenderDeterministic.js.map +1 -0
- package/lib/orchestrate/orchestrateAutoViewReview.d.ts +48 -0
- package/lib/orchestrate/orchestrateAutoViewReview.js +328 -0
- package/lib/orchestrate/orchestrateAutoViewReview.js.map +1 -0
- package/lib/orchestrate/orchestrateAutoViewScaffold.d.ts +45 -0
- package/lib/orchestrate/orchestrateAutoViewScaffold.js +586 -0
- package/lib/orchestrate/orchestrateAutoViewScaffold.js.map +1 -0
- package/lib/orchestrate/orchestrateAutoViewSdkStudy.d.ts +26 -0
- package/lib/orchestrate/orchestrateAutoViewSdkStudy.js +85 -0
- package/lib/orchestrate/orchestrateAutoViewSdkStudy.js.map +1 -0
- package/lib/orchestrate/structures/IAutoViewProductPlan.d.ts +96 -0
- package/lib/orchestrate/structures/IAutoViewProductPlan.js +3 -0
- package/lib/orchestrate/structures/IAutoViewProductPlan.js.map +1 -0
- package/lib/orchestrate/structures/IAutoViewProductPlanApplication.d.ts +38 -0
- package/lib/orchestrate/structures/IAutoViewProductPlanApplication.js +3 -0
- package/lib/orchestrate/structures/IAutoViewProductPlanApplication.js.map +1 -0
- package/lib/orchestrate/structures/IAutoViewRenderApplication.d.ts +38 -0
- package/lib/orchestrate/structures/IAutoViewRenderApplication.js +3 -0
- package/lib/orchestrate/structures/IAutoViewRenderApplication.js.map +1 -0
- package/lib/orchestrate/structures/IAutoViewReviewApplication.d.ts +40 -0
- package/lib/orchestrate/structures/IAutoViewReviewApplication.js +3 -0
- package/lib/orchestrate/structures/IAutoViewReviewApplication.js.map +1 -0
- package/lib/orchestrate/structures/IAutoViewSdkMap.d.ts +63 -0
- package/lib/orchestrate/structures/IAutoViewSdkMap.js +3 -0
- package/lib/orchestrate/structures/IAutoViewSdkMap.js.map +1 -0
- package/lib/orchestrate/structures/IAutoViewSdkStudyApplication.d.ts +37 -0
- package/lib/orchestrate/structures/IAutoViewSdkStudyApplication.js +3 -0
- package/lib/orchestrate/structures/IAutoViewSdkStudyApplication.js.map +1 -0
- package/lib/orchestrate/utils/HistoryMessage.d.ts +10 -0
- package/lib/orchestrate/utils/HistoryMessage.js +25 -0
- package/lib/orchestrate/utils/HistoryMessage.js.map +1 -0
- package/lib/orchestrate/utils/auditFrontendRuntime.d.ts +53 -0
- package/lib/orchestrate/utils/auditFrontendRuntime.js +362 -0
- package/lib/orchestrate/utils/auditFrontendRuntime.js.map +1 -0
- package/lib/orchestrate/utils/buildDeterministicPlan.d.ts +4 -0
- package/lib/orchestrate/utils/buildDeterministicPlan.js +233 -0
- package/lib/orchestrate/utils/buildDeterministicPlan.js.map +1 -0
- package/lib/orchestrate/utils/buildDeterministicSdkMap.d.ts +22 -0
- package/lib/orchestrate/utils/buildDeterministicSdkMap.js +154 -0
- package/lib/orchestrate/utils/buildDeterministicSdkMap.js.map +1 -0
- package/lib/orchestrate/utils/cacheNodeModules.d.ts +31 -0
- package/lib/orchestrate/utils/cacheNodeModules.js +134 -0
- package/lib/orchestrate/utils/cacheNodeModules.js.map +1 -0
- package/lib/orchestrate/utils/describeEndpointPropsShape.d.ts +37 -0
- package/lib/orchestrate/utils/describeEndpointPropsShape.js +192 -0
- package/lib/orchestrate/utils/describeEndpointPropsShape.js.map +1 -0
- package/lib/orchestrate/utils/describeEndpointRequestBodyShape.d.ts +22 -0
- package/lib/orchestrate/utils/describeEndpointRequestBodyShape.js +29 -0
- package/lib/orchestrate/utils/describeEndpointRequestBodyShape.js.map +1 -0
- package/lib/orchestrate/utils/describeEndpointResponseShape.d.ts +19 -0
- package/lib/orchestrate/utils/describeEndpointResponseShape.js +30 -0
- package/lib/orchestrate/utils/describeEndpointResponseShape.js.map +1 -0
- package/lib/orchestrate/utils/executeCachedBatch.d.ts +22 -0
- package/lib/orchestrate/utils/executeCachedBatch.js +64 -0
- package/lib/orchestrate/utils/executeCachedBatch.js.map +1 -0
- package/lib/orchestrate/utils/loadShoppingFixture.d.ts +33 -0
- package/lib/orchestrate/utils/loadShoppingFixture.js +17 -0
- package/lib/orchestrate/utils/loadShoppingFixture.js.map +1 -0
- package/lib/orchestrate/utils/normalizeProductPlanPaths.d.ts +24 -0
- package/lib/orchestrate/utils/normalizeProductPlanPaths.js +77 -0
- package/lib/orchestrate/utils/normalizeProductPlanPaths.js.map +1 -0
- package/lib/orchestrate/utils/renderJsonSchema.d.ts +23 -0
- package/lib/orchestrate/utils/renderJsonSchema.js +122 -0
- package/lib/orchestrate/utils/renderJsonSchema.js.map +1 -0
- package/lib/orchestrate/utils/renderResourcePage.d.ts +36 -0
- package/lib/orchestrate/utils/renderResourcePage.js +1415 -0
- package/lib/orchestrate/utils/renderResourcePage.js.map +1 -0
- package/lib/orchestrate/utils/validateFrontendTypecheck.d.ts +109 -0
- package/lib/orchestrate/utils/validateFrontendTypecheck.js +274 -0
- package/lib/orchestrate/utils/validateFrontendTypecheck.js.map +1 -0
- package/lib/preview/renderPreview.d.ts +22 -0
- package/lib/preview/renderPreview.js +198 -0
- package/lib/preview/renderPreview.js.map +1 -0
- package/lib/typings/compiler.d.ts +39 -0
- package/lib/typings/compiler.js +3 -0
- package/lib/typings/compiler.js.map +1 -0
- package/lib/typings/events.d.ts +106 -0
- package/lib/typings/events.js +3 -0
- package/lib/typings/events.js.map +1 -0
- package/lib/typings/index.d.ts +10 -0
- package/lib/typings/index.js +27 -0
- package/lib/typings/index.js.map +1 -0
- package/lib/typings/misc.d.ts +78 -0
- package/lib/typings/misc.js +3 -0
- package/lib/typings/misc.js.map +1 -0
- package/lib/utils/ArrayUtil.d.ts +8 -0
- package/lib/utils/ArrayUtil.js +30 -0
- package/lib/utils/ArrayUtil.js.map +1 -0
- package/lib/utils/StringUtil.d.ts +11 -0
- package/lib/utils/StringUtil.js +28 -0
- package/lib/utils/StringUtil.js.map +1 -0
- package/lib/utils/classifyEndpoints.d.ts +62 -0
- package/lib/utils/classifyEndpoints.js +216 -0
- package/lib/utils/classifyEndpoints.js.map +1 -0
- package/lib/utils/endpointFilter.d.ts +26 -0
- package/lib/utils/endpointFilter.js +0 -0
- package/lib/utils/endpointFilter.js.map +1 -0
- package/lib/utils/extractFields.d.ts +85 -0
- package/lib/utils/extractFields.js +231 -0
- package/lib/utils/extractFields.js.map +1 -0
- package/lib/utils/index.d.ts +13 -0
- package/lib/utils/index.js +30 -0
- package/lib/utils/index.js.map +1 -0
- package/lib/utils/normalizeForNestia.d.ts +34 -0
- package/lib/utils/normalizeForNestia.js +133 -0
- package/lib/utils/normalizeForNestia.js.map +1 -0
- package/lib/utils/resourcePlan.d.ts +39 -0
- package/lib/utils/resourcePlan.js +95 -0
- package/lib/utils/resourcePlan.js.map +1 -0
- package/lib/utils/sliceDocument.d.ts +17 -0
- package/lib/utils/sliceDocument.js +114 -0
- package/lib/utils/sliceDocument.js.map +1 -0
- package/lib/utils/toEndpoints.d.ts +90 -0
- package/lib/utils/toEndpoints.js +227 -0
- package/lib/utils/toEndpoints.js.map +1 -0
- package/lib/verify/runWorkflows.d.ts +25 -0
- package/lib/verify/runWorkflows.js +366 -0
- package/lib/verify/runWorkflows.js.map +1 -0
- package/lib/verify/workflows.d.ts +53 -0
- package/lib/verify/workflows.js +107 -0
- package/lib/verify/workflows.js.map +1 -0
- package/package.json +82 -0
- package/prompts/AUTOVIEW_RENDER.md +398 -0
- package/prompts/AUTOVIEW_REVIEW.md +60 -0
- package/prompts/AUTOVIEW_SDK_STUDY.md +89 -0
- package/src/AutoViewAgent.ts +222 -0
- package/src/agent/emitMcpServer.integration.test.ts +168 -0
- package/src/agent/emitMcpServer.test.ts +51 -0
- package/src/agent/emitMcpServer.ts +178 -0
- package/src/agent/emitReport.ts +117 -0
- package/src/agent/toolSurface.test.ts +243 -0
- package/src/agent/toolSurface.ts +501 -0
- package/src/agent/verifyAgentTasks.test.ts +106 -0
- package/src/agent/verifyAgentTasks.ts +171 -0
- package/src/cli/main.ts +363 -0
- package/src/compiler/AutoViewInterfaceCompiler.ts +69 -0
- package/src/constants/AutoViewFrontendTemplate.ts +42 -0
- package/src/constants/AutoViewSystemPromptConstant.ts +6 -0
- package/src/context/IAutoViewAgentContext.ts +84 -0
- package/src/fromSwagger.test.ts +269 -0
- package/src/fromSwagger.ts +500 -0
- package/src/generateDeterministic.test.ts +39 -0
- package/src/generateDeterministic.ts +77 -0
- package/src/index.ts +30 -0
- package/src/orchestrate/orchestrateAutoView.ts +590 -0
- package/src/orchestrate/orchestrateAutoViewProductPlan.ts +121 -0
- package/src/orchestrate/orchestrateAutoViewRender.ts +1117 -0
- package/src/orchestrate/orchestrateAutoViewRenderDeterministic.ts +101 -0
- package/src/orchestrate/orchestrateAutoViewReview.ts +272 -0
- package/src/orchestrate/orchestrateAutoViewScaffold.ts +627 -0
- package/src/orchestrate/orchestrateAutoViewSdkStudy.ts +90 -0
- package/src/orchestrate/renderNavTs.test.ts +74 -0
- package/src/orchestrate/structures/IAutoViewProductPlan.ts +119 -0
- package/src/orchestrate/structures/IAutoViewProductPlanApplication.ts +41 -0
- package/src/orchestrate/structures/IAutoViewRenderApplication.ts +40 -0
- package/src/orchestrate/structures/IAutoViewReviewApplication.ts +42 -0
- package/src/orchestrate/structures/IAutoViewSdkMap.ts +72 -0
- package/src/orchestrate/structures/IAutoViewSdkStudyApplication.ts +40 -0
- package/src/orchestrate/utils/HistoryMessage.ts +41 -0
- package/src/orchestrate/utils/auditFrontendRuntime.test.ts +18 -0
- package/src/orchestrate/utils/auditFrontendRuntime.ts +454 -0
- package/src/orchestrate/utils/buildDeterministicPlan.test.ts +170 -0
- package/src/orchestrate/utils/buildDeterministicPlan.ts +289 -0
- package/src/orchestrate/utils/buildDeterministicSdkMap.test.ts +90 -0
- package/src/orchestrate/utils/buildDeterministicSdkMap.ts +169 -0
- package/src/orchestrate/utils/cacheNodeModules.ts +136 -0
- package/src/orchestrate/utils/describeEndpointPropsShape.test.ts +86 -0
- package/src/orchestrate/utils/describeEndpointPropsShape.ts +202 -0
- package/src/orchestrate/utils/describeEndpointRequestBodyShape.test.ts +87 -0
- package/src/orchestrate/utils/describeEndpointRequestBodyShape.ts +31 -0
- package/src/orchestrate/utils/describeEndpointResponseShape.test.ts +70 -0
- package/src/orchestrate/utils/describeEndpointResponseShape.ts +32 -0
- package/src/orchestrate/utils/executeCachedBatch.ts +59 -0
- package/src/orchestrate/utils/loadShoppingFixture.ts +52 -0
- package/src/orchestrate/utils/normalizeProductPlanPaths.ts +92 -0
- package/src/orchestrate/utils/renderJsonSchema.test.ts +162 -0
- package/src/orchestrate/utils/renderJsonSchema.ts +133 -0
- package/src/orchestrate/utils/renderResourcePage.test.ts +468 -0
- package/src/orchestrate/utils/renderResourcePage.ts +1624 -0
- package/src/orchestrate/utils/validateFrontendTypecheck.test.ts +32 -0
- package/src/orchestrate/utils/validateFrontendTypecheck.ts +335 -0
- package/src/preview/renderPreview.ts +273 -0
- package/src/typings/compiler.ts +47 -0
- package/src/typings/events.ts +155 -0
- package/src/typings/index.ts +10 -0
- package/src/typings/misc.ts +93 -0
- package/src/utils/ArrayUtil.ts +16 -0
- package/src/utils/StringUtil.ts +29 -0
- package/src/utils/classifyEndpoints.test.ts +86 -0
- package/src/utils/classifyEndpoints.ts +291 -0
- package/src/utils/endpointFilter.test.ts +50 -0
- package/src/utils/endpointFilter.ts +0 -0
- package/src/utils/extractFields.test.ts +82 -0
- package/src/utils/extractFields.ts +306 -0
- package/src/utils/index.ts +13 -0
- package/src/utils/normalizeForNestia.test.ts +93 -0
- package/src/utils/normalizeForNestia.ts +139 -0
- package/src/utils/resourcePlan.test.ts +104 -0
- package/src/utils/resourcePlan.ts +180 -0
- package/src/utils/sliceDocument.test.ts +85 -0
- package/src/utils/sliceDocument.ts +119 -0
- package/src/utils/toEndpoints.test.ts +251 -0
- package/src/utils/toEndpoints.ts +343 -0
- package/src/verify/runWorkflows.ts +403 -0
- package/src/verify/workflows.test.ts +117 -0
- package/src/verify/workflows.ts +154 -0
- package/template/CLAUDE.md +140 -0
- package/template/Dockerfile +31 -0
- package/template/PROMPT.md +80 -0
- package/template/SANDBOX.md +70 -0
- package/template/app/api/health/route.ts +10 -0
- package/template/app/globals.css +97 -0
- package/template/app/layout.tsx +30 -0
- package/template/app/page.tsx +19 -0
- package/template/components/AppShell.tsx +114 -0
- package/template/components/auto/CatalogGrid.tsx +159 -0
- package/template/components/auto/ConfirmButton.tsx +67 -0
- package/template/components/auto/EmbeddedCollection.tsx +144 -0
- package/template/components/auto/ResourceDashboard.tsx +104 -0
- package/template/components/auto/ResourceDetail.tsx +93 -0
- package/template/components/auto/ResourceForm.tsx +235 -0
- package/template/components/auto/ResourceIcon.tsx +88 -0
- package/template/components/auto/ResourceLanding.tsx +155 -0
- package/template/components/auto/ResourceTable.tsx +223 -0
- package/template/components/auto/formatValue.tsx +186 -0
- package/template/components/auto/types.ts +42 -0
- package/template/components/ui/badge.tsx +40 -0
- package/template/components/ui/button.tsx +57 -0
- package/template/components/ui/card.tsx +86 -0
- package/template/components/ui/dialog.tsx +119 -0
- package/template/components/ui/input.tsx +23 -0
- package/template/components/ui/label.tsx +24 -0
- package/template/components/ui/pagination.tsx +117 -0
- package/template/components/ui/select.tsx +92 -0
- package/template/components/ui/sheet.tsx +135 -0
- package/template/components/ui/skeleton.tsx +15 -0
- package/template/components/ui/table.tsx +120 -0
- package/template/components/ui/tabs.tsx +55 -0
- package/template/lib/utils.ts +35 -0
- package/template/next.config.mjs +52 -0
- package/template/package.json +46 -0
- package/template/postcss.config.js +6 -0
- package/template/scripts/start-shopping-backend.sh +56 -0
- package/template/tailwind.config.ts +96 -0
- package/template/tsconfig.json +29 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { OpenApi } from "@typia/interface";
|
|
2
|
+
import { IAutoViewEndpoint } from "./toEndpoints";
|
|
3
|
+
/**
|
|
4
|
+
* Deterministic CRUD role of an endpoint — the first brick of the "정확한 틀".
|
|
5
|
+
*
|
|
6
|
+
* The MAP layer (SdkStudy + ProductPlan) was 100% LLM improvisation: same
|
|
7
|
+
* swagger, different screens every run, no CRUD-completeness guarantee, and a
|
|
8
|
+
* commerce-hardcoded prompt. This classifier derives each endpoint's role from
|
|
9
|
+
* method + path shape + query presence — purely structural, zero LLM, fully
|
|
10
|
+
* reproducible and domain-agnostic.
|
|
11
|
+
*
|
|
12
|
+
* - `list` GET on a collection (no trailing path param), no query
|
|
13
|
+
* - `search` GET on a collection WITH query parameters (filter/paginate)
|
|
14
|
+
* - `detail` GET on a single item (trailing `{param}`)
|
|
15
|
+
* - `create` POST on a collection
|
|
16
|
+
* - `update` PUT / PATCH on a single item
|
|
17
|
+
* - `delete` DELETE on a single item
|
|
18
|
+
* - `action` anything else (e.g. POST /pets/{id}/uploadImage, RPC-ish verbs)
|
|
19
|
+
*/
|
|
20
|
+
export type EndpointRole = "list" | "search" | "detail" | "create" | "update" | "delete" | "action";
|
|
21
|
+
/**
|
|
22
|
+
* One link in a resource hierarchy: a collection name plus the path param that
|
|
23
|
+
* addresses a single item of it. `param` is `null` for a leaf collection that
|
|
24
|
+
* the endpoint does not item-address (`/sales/{saleId}/questions` → the
|
|
25
|
+
* `questions` link has `param: null` on a list, `param: "id"` on a detail).
|
|
26
|
+
*/
|
|
27
|
+
export interface IResourceLink {
|
|
28
|
+
name: string;
|
|
29
|
+
param: string | null;
|
|
30
|
+
}
|
|
31
|
+
export interface IClassifiedEndpoint {
|
|
32
|
+
endpoint: IAutoViewEndpoint;
|
|
33
|
+
/** Top-level resource bucket = the first link of {@link chain}. */
|
|
34
|
+
resource: string;
|
|
35
|
+
/**
|
|
36
|
+
* Full resource hierarchy parsed from the path, skipping namespace/actor
|
|
37
|
+
* prefixes. `/shoppings/admins/sales/{saleId}/questions/{id}` →
|
|
38
|
+
* `[{sales, saleId}, {questions, id}]`. Length 1 = a top-level resource.
|
|
39
|
+
*/
|
|
40
|
+
chain: IResourceLink[];
|
|
41
|
+
role: EndpointRole;
|
|
42
|
+
/** True when the path targets a single item (trailing `{param}`). */
|
|
43
|
+
itemScoped: boolean;
|
|
44
|
+
}
|
|
45
|
+
/** All endpoints of one resource, plus the set of roles it actually exposes. */
|
|
46
|
+
export interface IResourceGroup {
|
|
47
|
+
/** Leaf resource name = the last link of {@link chain}. */
|
|
48
|
+
resource: string;
|
|
49
|
+
/** Full hierarchy of this group (`[sales]`, `[sales, questions]`). */
|
|
50
|
+
chain: IResourceLink[];
|
|
51
|
+
/** `chain.length` — 1 = top-level, ≥2 = nested under a parent. */
|
|
52
|
+
depth: number;
|
|
53
|
+
endpoints: IClassifiedEndpoint[];
|
|
54
|
+
/** Which CRUD roles this resource supports — drives the screen set later. */
|
|
55
|
+
roles: Set<EndpointRole>;
|
|
56
|
+
}
|
|
57
|
+
export declare function classifyEndpoint(endpoint: IAutoViewEndpoint, candidates?: ReadonlySet<string>, document?: OpenApi.IDocument): IClassifiedEndpoint;
|
|
58
|
+
/**
|
|
59
|
+
* Classify every endpoint and bucket by resource. Resource order follows first
|
|
60
|
+
* appearance; endpoints within a resource keep their input order.
|
|
61
|
+
*/
|
|
62
|
+
export declare function classifyEndpoints(endpoints: IAutoViewEndpoint[], document?: OpenApi.IDocument): IResourceGroup[];
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.classifyEndpoint = classifyEndpoint;
|
|
4
|
+
exports.classifyEndpoints = classifyEndpoints;
|
|
5
|
+
const extractFields_1 = require("./extractFields");
|
|
6
|
+
const PARAM = /^\{.*\}$/;
|
|
7
|
+
function segments(path) {
|
|
8
|
+
return path.split("/").filter((s) => s.length > 0);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Whether an endpoint's response is a browsable collection — an array, or a
|
|
12
|
+
* page/wrapper object whose resolved fields contain a collection field
|
|
13
|
+
* (`data` / `items` / `entries` / …). Used to tell a real `PATCH`-as-search
|
|
14
|
+
* (returns a page of results) from a `PATCH` that merely uses the verb to mutate
|
|
15
|
+
* a named sub-resource (`/databases/{id}/config`) and returns void or a single
|
|
16
|
+
* object. Without a document a page wrapper cannot be resolved, so any named
|
|
17
|
+
* body is conservatively treated as a collection (preserving legacy behavior)
|
|
18
|
+
* while a void response is still recognized as a non-collection.
|
|
19
|
+
*/
|
|
20
|
+
function returnsCollection(endpoint, document) {
|
|
21
|
+
if (endpoint.responseBody === null)
|
|
22
|
+
return false;
|
|
23
|
+
if (endpoint.responseBody.isArray)
|
|
24
|
+
return true;
|
|
25
|
+
if (document === undefined)
|
|
26
|
+
return true;
|
|
27
|
+
return ((0, extractFields_1.findCollectionField)((0, extractFields_1.extractFields)(endpoint.responseBody.typeName, document)) !==
|
|
28
|
+
undefined);
|
|
29
|
+
}
|
|
30
|
+
function classifyEndpoint(endpoint, candidates = new Set(), document) {
|
|
31
|
+
var _a, _b, _c;
|
|
32
|
+
const segs = segments(endpoint.path);
|
|
33
|
+
const last = (_a = segs.at(-1)) !== null && _a !== void 0 ? _a : "";
|
|
34
|
+
// "single item" = the path's last segment is a parameter (`/pets/{id}`),
|
|
35
|
+
// i.e. it addresses one entity. `/pets/{id}/photos` is a collection again
|
|
36
|
+
// (last segment `photos` is not a param), so it lists pet-scoped photos.
|
|
37
|
+
const itemScoped = PARAM.test(last);
|
|
38
|
+
// Any path parameter means the write targets a specific entity (or a child
|
|
39
|
+
// of one) — `/orders/{id}/cancel`, `/pets/{id}/photos`, `/items/{id}`. We
|
|
40
|
+
// cannot tell a sub-resource create from an RPC verb deterministically (no
|
|
41
|
+
// noun/verb NLP), so both collapse to `action`: an item-scoped write the
|
|
42
|
+
// detail screen surfaces as a button/sub-form. A `create` is reserved for a
|
|
43
|
+
// POST on a bare collection (`/items`).
|
|
44
|
+
const hasPathParam = segs.some((s) => PARAM.test(s));
|
|
45
|
+
const method = endpoint.method.toLowerCase();
|
|
46
|
+
const hasQuery = endpoint.query !== null;
|
|
47
|
+
const role = (() => {
|
|
48
|
+
switch (method) {
|
|
49
|
+
case "get":
|
|
50
|
+
// `/pets/{id}` → detail; `/pets/{id}/photos` → list (sub-collection).
|
|
51
|
+
if (itemScoped)
|
|
52
|
+
return "detail";
|
|
53
|
+
return hasQuery ? "search" : "list";
|
|
54
|
+
case "post":
|
|
55
|
+
return hasPathParam ? "action" : "create";
|
|
56
|
+
case "put":
|
|
57
|
+
return "update";
|
|
58
|
+
case "patch":
|
|
59
|
+
// nestia / AutoBE convention: PATCH on a collection is index/search
|
|
60
|
+
// (the filter rides in the request body), NOT a partial update — this
|
|
61
|
+
// is how shopping/ERP expose their list endpoints. PATCH on a single
|
|
62
|
+
// item (`/x/{id}`) is a genuine update.
|
|
63
|
+
if (itemScoped)
|
|
64
|
+
return "update";
|
|
65
|
+
// ...but only when it actually returns a collection. A non-item PATCH
|
|
66
|
+
// that returns void or a single object (`PATCH /databases/{id}/config`)
|
|
67
|
+
// is a mutation, not a search — classifying it as a read would tag the
|
|
68
|
+
// tool `readOnly` and tell an agent a state-changing call is safe.
|
|
69
|
+
if (!returnsCollection(endpoint, document))
|
|
70
|
+
return "action";
|
|
71
|
+
return hasQuery ? "search" : "list";
|
|
72
|
+
case "delete":
|
|
73
|
+
return "delete";
|
|
74
|
+
default:
|
|
75
|
+
return "action";
|
|
76
|
+
}
|
|
77
|
+
})();
|
|
78
|
+
const chain = resourceChainOf(segs, candidates, role);
|
|
79
|
+
return {
|
|
80
|
+
endpoint,
|
|
81
|
+
resource: (_c = (_b = chain[0]) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : resourceOf(segs, candidates),
|
|
82
|
+
chain,
|
|
83
|
+
role,
|
|
84
|
+
itemScoped,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function stripBraces(seg) {
|
|
88
|
+
return seg.replace(/^\{/, "").replace(/\}$/, "");
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Parse a path into its resource hierarchy, skipping namespace / actor prefix
|
|
92
|
+
* segments. A static segment becomes a resource link when it is item-addressed
|
|
93
|
+
* (a `{param}` follows it), is a known resource elsewhere (in `candidates`), or
|
|
94
|
+
* is the terminal collection. Pure namespacing (`shoppings`, `admins`,
|
|
95
|
+
* `systematic`) is dropped.
|
|
96
|
+
*
|
|
97
|
+
* `/shoppings/admins/sales/{saleId}/questions/{id}` → `[{sales,saleId},{questions,id}]`
|
|
98
|
+
* `/shoppings/customers/orders/{id}/publish` (action) → `[{orders,id}]`
|
|
99
|
+
* (the trailing verb is the action name, not a sub-resource).
|
|
100
|
+
*/
|
|
101
|
+
function resourceChainOf(segs, candidates, role) {
|
|
102
|
+
const chain = [];
|
|
103
|
+
for (let i = 0; i < segs.length; i++) {
|
|
104
|
+
const seg = segs[i];
|
|
105
|
+
if (PARAM.test(seg))
|
|
106
|
+
continue;
|
|
107
|
+
const next = segs[i + 1];
|
|
108
|
+
const nextIsParam = next !== undefined && PARAM.test(next);
|
|
109
|
+
const isTerminal = i === segs.length - 1;
|
|
110
|
+
if (nextIsParam) {
|
|
111
|
+
// item-addressed collection → a real resource (`sales/{saleId}`).
|
|
112
|
+
chain.push({ name: seg, param: stripBraces(next) });
|
|
113
|
+
}
|
|
114
|
+
else if (candidates.has(seg)) {
|
|
115
|
+
// a known resource (item-addressed elsewhere), here without an id.
|
|
116
|
+
chain.push({ name: seg, param: null });
|
|
117
|
+
}
|
|
118
|
+
else if (isTerminal && chain.length === 0) {
|
|
119
|
+
// a top-level read-only collection that is never item-addressed
|
|
120
|
+
// (`/health`, `/system`, `/store/inventory`).
|
|
121
|
+
chain.push({ name: seg, param: null });
|
|
122
|
+
}
|
|
123
|
+
// else: a namespace/actor prefix, OR a deeper trailing verb/view that is
|
|
124
|
+
// never item-addressed (`/sales/details`, `/channels/hierarchical`,
|
|
125
|
+
// `/orders/incompletes`). The latter is a VARIANT of its parent resource,
|
|
126
|
+
// not a resource of its own — skip it so the endpoint folds into the parent
|
|
127
|
+
// group instead of spawning a junk top-level card.
|
|
128
|
+
}
|
|
129
|
+
// An action's trailing static verb (`.../{id}/publish`) is not a resource —
|
|
130
|
+
// drop it so the action attaches to its parent. Keep length ≥ 1.
|
|
131
|
+
if (role === "action" && chain.length > 1 && chain.at(-1).param === null) {
|
|
132
|
+
chain.pop();
|
|
133
|
+
}
|
|
134
|
+
return chain.length > 0 ? chain : [{ name: "root", param: null }];
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* The segment immediately before a path's last `{param}` — the entity the path
|
|
138
|
+
* addresses (`/shoppings/admins/coupons/{id}` → `coupons`, `/pet/{petId}` →
|
|
139
|
+
* `pet`). `null` when the path has no param (a collection or verb path).
|
|
140
|
+
*/
|
|
141
|
+
function paramAnchoredResource(segs) {
|
|
142
|
+
for (let i = segs.length - 1; i >= 0; i--) {
|
|
143
|
+
if (PARAM.test(segs[i]))
|
|
144
|
+
return i > 0 ? segs[i - 1] : null;
|
|
145
|
+
}
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Resource bucket of a path, using the set of param-anchored resources as
|
|
150
|
+
* the source of truth.
|
|
151
|
+
*
|
|
152
|
+
* - Param path (`/pet/{petId}`, `/coupons/{id}`) → the segment before the
|
|
153
|
+
* param. This recovers the real resource even under deep accessors that
|
|
154
|
+
* share a `shoppings` prefix.
|
|
155
|
+
* - Collection / verb path with no param (`/pet/findByStatus`, `/pet`,
|
|
156
|
+
* `/user/login`) → absorbed into a known resource if the path passes through
|
|
157
|
+
* one (findByStatus → pet, login → user), so RPC-style verbs do not spawn
|
|
158
|
+
* junk resources. Falls back to its own last segment when it belongs to no
|
|
159
|
+
* known resource (`/store/inventory` → inventory).
|
|
160
|
+
*/
|
|
161
|
+
function resourceOf(segs, candidates) {
|
|
162
|
+
var _a;
|
|
163
|
+
const anchored = paramAnchoredResource(segs);
|
|
164
|
+
if (anchored !== null)
|
|
165
|
+
return anchored;
|
|
166
|
+
const nonParam = segs.filter((s) => !PARAM.test(s));
|
|
167
|
+
for (let i = nonParam.length - 1; i >= 0; i--) {
|
|
168
|
+
if (candidates.has(nonParam[i]))
|
|
169
|
+
return nonParam[i];
|
|
170
|
+
}
|
|
171
|
+
return (_a = nonParam.at(-1)) !== null && _a !== void 0 ? _a : "root";
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Classify every endpoint and bucket by resource. Resource order follows first
|
|
175
|
+
* appearance; endpoints within a resource keep their input order.
|
|
176
|
+
*/
|
|
177
|
+
function classifyEndpoints(endpoints, document) {
|
|
178
|
+
// Pass 1: collect the real resources — segments that have a `{param}` child.
|
|
179
|
+
const candidates = new Set();
|
|
180
|
+
for (const endpoint of endpoints) {
|
|
181
|
+
const r = paramAnchoredResource(segments(endpoint.path));
|
|
182
|
+
if (r !== null)
|
|
183
|
+
candidates.add(r);
|
|
184
|
+
}
|
|
185
|
+
// Pass 2: classify and bucket by the FULL resource chain (so a sub-resource
|
|
186
|
+
// like `sales/questions` is its own group, distinct from `sales`), absorbing
|
|
187
|
+
// param-less verb paths into a known resource.
|
|
188
|
+
const groups = new Map();
|
|
189
|
+
for (const endpoint of endpoints) {
|
|
190
|
+
const classified = classifyEndpoint(endpoint, candidates, document);
|
|
191
|
+
const chainKey = classified.chain.map((c) => c.name).join("/");
|
|
192
|
+
const existing = groups.get(chainKey);
|
|
193
|
+
const group = existing !== null && existing !== void 0 ? existing : {
|
|
194
|
+
resource: classified.chain.at(-1).name,
|
|
195
|
+
chain: classified.chain,
|
|
196
|
+
depth: classified.chain.length,
|
|
197
|
+
endpoints: [],
|
|
198
|
+
roles: new Set(),
|
|
199
|
+
};
|
|
200
|
+
// Prefer a chain link that carries an item param (a detail endpoint) so the
|
|
201
|
+
// group's chain has the real param names for routing, not just `null`s.
|
|
202
|
+
if (existing !== undefined) {
|
|
203
|
+
classified.chain.forEach((link, i) => {
|
|
204
|
+
var _a;
|
|
205
|
+
if (link.param !== null && ((_a = existing.chain[i]) === null || _a === void 0 ? void 0 : _a.param) == null) {
|
|
206
|
+
existing.chain[i] = link;
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
group.endpoints.push(classified);
|
|
211
|
+
group.roles.add(classified.role);
|
|
212
|
+
groups.set(chainKey, group);
|
|
213
|
+
}
|
|
214
|
+
return [...groups.values()];
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=classifyEndpoints.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classifyEndpoints.js","sourceRoot":"","sources":["../../src/utils/classifyEndpoints.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { IAutoViewEndpoint } from "./toEndpoints";
|
|
2
|
+
/**
|
|
3
|
+
* Operator-controlled endpoint filter — the answer to "huge swaggers explode
|
|
4
|
+
* into 73 screens and mix actor scopes".
|
|
5
|
+
*
|
|
6
|
+
* A big swagger (shopping/ERP) should not be turned into a screen per endpoint:
|
|
7
|
+
* actor scopes collide (a customer screen calling an admin endpoint 500s) and
|
|
8
|
+
* the screen count is unusable. Instead of guessing actors from the path
|
|
9
|
+
* (swagger-specific), the operator slices the surface explicitly:
|
|
10
|
+
*
|
|
11
|
+
* --include "shoppings/customers/**" → only the customer surface
|
|
12
|
+
* --exclude "**/monitors/**" → drop monitoring noise
|
|
13
|
+
*
|
|
14
|
+
* Patterns match against the endpoint PATH (leading slash optional). Glob:
|
|
15
|
+
* `*` matches within a path segment (no `/`)
|
|
16
|
+
* `**` matches across segments
|
|
17
|
+
*/
|
|
18
|
+
export interface IEndpointFilter {
|
|
19
|
+
include?: string[];
|
|
20
|
+
exclude?: string[];
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Apply include/exclude to an endpoint list. Include keeps only matches (when
|
|
24
|
+
* given); exclude then drops matches. Empty/absent filter is a no-op.
|
|
25
|
+
*/
|
|
26
|
+
export declare function filterEndpoints(endpoints: IAutoViewEndpoint[], filter?: IEndpointFilter): IAutoViewEndpoint[];
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"endpointFilter.js","sourceRoot":"","sources":["../../src/utils/endpointFilter.ts"],"names":[],"mappings":";;AA4CA,0CAYC;AAjCD,SAAS,YAAY,CAAC,IAAY;IAChC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC3C,4EAA4E;IAC5E,kDAAkD;IAClD,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;IAChE,MAAM,QAAQ,GAAG,OAAO;SACrB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;SACrB,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACvB,OAAO,IAAI,MAAM,CAAC,IAAI,QAAQ,GAAG,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,UAAU,CAAC,IAAY,EAAE,QAAkB;IAClD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACxC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED;;;GAGG;AACH,SAAgB,eAAe,CAC7B,SAA8B,EAC9B,SAA0B,EAAE;IAE5B,IAAI,MAAM,GAAG,SAAS,CAAC;IACvB,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChD,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,OAAQ,CAAC,CAAC,CAAC;IACrE,CAAC;IACD,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChD,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,OAAQ,CAAC,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { OpenApi } from "@typia/interface";
|
|
2
|
+
/**
|
|
3
|
+
* Deterministic data contract — the field list a screen renders.
|
|
4
|
+
*
|
|
5
|
+
* Derived structurally from a component schema's properties: list table
|
|
6
|
+
* columns, detail rows, and form inputs all come from here instead of the LLM
|
|
7
|
+
* guessing. This is what makes "table 엄청 적게" structurally impossible — every
|
|
8
|
+
* property of the row/response/request type becomes a column/row/input.
|
|
9
|
+
*/
|
|
10
|
+
export type FieldKind = "string" | "number" | "boolean" | "enum" | "array" | "object" | "ref" | "union" | "unknown";
|
|
11
|
+
export interface IFieldSpec {
|
|
12
|
+
name: string;
|
|
13
|
+
required: boolean;
|
|
14
|
+
kind: FieldKind;
|
|
15
|
+
/** String format (`uuid`, `date-time`, `uri`, ...) when present. */
|
|
16
|
+
format?: string;
|
|
17
|
+
/** Allowed values for an `enum` field. */
|
|
18
|
+
enumValues?: Array<string | number | boolean>;
|
|
19
|
+
/** Component type name for a `ref` field, or the element type of an `array`. */
|
|
20
|
+
ref?: string;
|
|
21
|
+
/** For an `array`, the element's kind (e.g. array of strings vs array of refs). */
|
|
22
|
+
itemKind?: FieldKind;
|
|
23
|
+
/** For an `array` of primitives, the element's string format (`uri`, …). A
|
|
24
|
+
* `string[]` of image URLs carries `format: "uri"` on the ITEM, not the
|
|
25
|
+
* array, so the signal is lost without preserving it here. */
|
|
26
|
+
itemFormat?: string;
|
|
27
|
+
/**
|
|
28
|
+
* For an `array` whose elements are an INLINE object (no `$ref`, so {@link ref}
|
|
29
|
+
* is undefined), the element's own field list — e.g. DigitalOcean's
|
|
30
|
+
* `{ droplets: [ { id, name, … } ] }`, where the droplet shape is inline. Lets
|
|
31
|
+
* a table render real columns for such collections instead of one opaque cell.
|
|
32
|
+
*/
|
|
33
|
+
itemFields?: IFieldSpec[];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Field names a paginated/collection response uses to hold its array of items.
|
|
37
|
+
* `data` is the nestia/AutoBE convention; real APIs vary (Box uses `entries`,
|
|
38
|
+
* others `items` / `results`). Recognizing all of them lets a list endpoint be
|
|
39
|
+
* rendered as a table off its element type instead of a one-record detail.
|
|
40
|
+
*/
|
|
41
|
+
export declare const COLLECTION_FIELD_NAMES: Set<string>;
|
|
42
|
+
/** The array field that holds a collection response's items, if any. */
|
|
43
|
+
export declare function findCollectionField(fields: IFieldSpec[]): IFieldSpec | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* Resolve a schema's effective `{ properties, required }`, following `$ref` and
|
|
46
|
+
* merging every `allOf` member. Composition (`allOf`) is a core OpenAPI feature
|
|
47
|
+
* real swaggers (Box, Stripe, …) lean on heavily — a type is often
|
|
48
|
+
* `allOf: [BasePagination, { properties: { entries } }]` with no direct
|
|
49
|
+
* `properties` of its own. Without this, such a type renders zero fields.
|
|
50
|
+
*
|
|
51
|
+
* Own `properties` win over inherited ones on a name clash; `required` is the
|
|
52
|
+
* union. Depth-guarded against cyclic `$ref`.
|
|
53
|
+
*/
|
|
54
|
+
export declare function resolveProperties(schema: OpenApi.IJsonSchema, doc: OpenApi.IDocument, depth?: number): {
|
|
55
|
+
properties: Record<string, OpenApi.IJsonSchema>;
|
|
56
|
+
required: string[];
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Extract the field list of a schema directly (resolving `$ref` and `allOf`).
|
|
60
|
+
* Works for both named component schemas and INLINE schemas — e.g. a response
|
|
61
|
+
* `{ databases: T[], links: … }` that is not a named component (common on
|
|
62
|
+
* DigitalOcean). Returns `[]` when there are no resolvable `properties`.
|
|
63
|
+
*/
|
|
64
|
+
export declare function extractFieldsFromSchema(schema: OpenApi.IJsonSchema, document: OpenApi.IDocument): IFieldSpec[];
|
|
65
|
+
/**
|
|
66
|
+
* Extract the field list of a NAMED component schema. Returns `[]` when the type
|
|
67
|
+
* is unknown or has no resolvable `properties` — the caller then degrades
|
|
68
|
+
* gracefully rather than inventing fields.
|
|
69
|
+
*/
|
|
70
|
+
export declare function extractFields(typeName: string, document: OpenApi.IDocument): IFieldSpec[];
|
|
71
|
+
/**
|
|
72
|
+
* The field that best represents a record's image, or `undefined`. A scalar
|
|
73
|
+
* `string` (often `format: uri`) or a `string[]` of image URLs whose NAME reads
|
|
74
|
+
* as an image wins; failing that, a uri-formatted url-ish field. This is the
|
|
75
|
+
* signal that turns a list into a catalog of cards instead of a table.
|
|
76
|
+
*/
|
|
77
|
+
export declare function imageFieldOf(columns: IFieldSpec[]): IFieldSpec | undefined;
|
|
78
|
+
/** The field that best titles a record (a card's heading), or `undefined`. */
|
|
79
|
+
export declare function titleFieldOf(columns: IFieldSpec[]): IFieldSpec | undefined;
|
|
80
|
+
/**
|
|
81
|
+
* A collection deserves a catalog (card grid) rather than a table when its rows
|
|
82
|
+
* carry both an image and a title — the two things a card needs. Purely
|
|
83
|
+
* structural from the element schema; no domain keywords.
|
|
84
|
+
*/
|
|
85
|
+
export declare function isCatalogCollection(columns: IFieldSpec[]): boolean;
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.COLLECTION_FIELD_NAMES = void 0;
|
|
4
|
+
exports.findCollectionField = findCollectionField;
|
|
5
|
+
exports.resolveProperties = resolveProperties;
|
|
6
|
+
exports.extractFieldsFromSchema = extractFieldsFromSchema;
|
|
7
|
+
exports.extractFields = extractFields;
|
|
8
|
+
exports.imageFieldOf = imageFieldOf;
|
|
9
|
+
exports.titleFieldOf = titleFieldOf;
|
|
10
|
+
exports.isCatalogCollection = isCatalogCollection;
|
|
11
|
+
function refName($ref) {
|
|
12
|
+
return $ref.split("/").pop();
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Field names a paginated/collection response uses to hold its array of items.
|
|
16
|
+
* `data` is the nestia/AutoBE convention; real APIs vary (Box uses `entries`,
|
|
17
|
+
* others `items` / `results`). Recognizing all of them lets a list endpoint be
|
|
18
|
+
* rendered as a table off its element type instead of a one-record detail.
|
|
19
|
+
*/
|
|
20
|
+
exports.COLLECTION_FIELD_NAMES = new Set([
|
|
21
|
+
"data",
|
|
22
|
+
"entries",
|
|
23
|
+
"items",
|
|
24
|
+
"results",
|
|
25
|
+
"values",
|
|
26
|
+
"list",
|
|
27
|
+
"records",
|
|
28
|
+
"rows",
|
|
29
|
+
]);
|
|
30
|
+
/** The array field that holds a collection response's items, if any. */
|
|
31
|
+
function findCollectionField(fields) {
|
|
32
|
+
return fields.find((f) => f.kind === "array" && exports.COLLECTION_FIELD_NAMES.has(f.name.toLowerCase()));
|
|
33
|
+
}
|
|
34
|
+
function kindOf(schema) {
|
|
35
|
+
if ("$ref" in schema && typeof schema.$ref === "string") {
|
|
36
|
+
return { kind: "ref", ref: refName(schema.$ref) };
|
|
37
|
+
}
|
|
38
|
+
// A bare `const` (no `oneOf`) is a single-value literal — typically a
|
|
39
|
+
// discriminant like `{ const: "customer" }`. Treat it as a one-value enum so
|
|
40
|
+
// it renders as a labeled value, not `unknown`.
|
|
41
|
+
if ("const" in schema && !("oneOf" in schema)) {
|
|
42
|
+
return {
|
|
43
|
+
kind: "enum",
|
|
44
|
+
enumValues: [schema.const],
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
// upgradeDocument normalizes a string enum into `oneOf: [{ const }, ...]`, and
|
|
48
|
+
// a nullable type into `oneOf: [{ type: "null" }, <real schema>]`. Drop the
|
|
49
|
+
// null branch first, then: an all-`const` set is an enum; a single remaining
|
|
50
|
+
// branch is just that type made nullable (unwrap it — a nullable `$ref`
|
|
51
|
+
// becomes a `ref`, not a `union`); anything else is a real union.
|
|
52
|
+
if ("oneOf" in schema && Array.isArray(schema.oneOf)) {
|
|
53
|
+
const branches = schema.oneOf.filter((b) => !("type" in b && b.type === "null"));
|
|
54
|
+
const consts = branches.map((b) => "const" in b ? b.const : undefined);
|
|
55
|
+
if (consts.length > 0 && consts.every((c) => c !== undefined)) {
|
|
56
|
+
return { kind: "enum", enumValues: consts };
|
|
57
|
+
}
|
|
58
|
+
if (branches.length === 1)
|
|
59
|
+
return kindOf(branches[0]);
|
|
60
|
+
// A homogeneous primitive union (e.g. a string that is `ipv4 | ipv6`, or
|
|
61
|
+
// `uri | ""`) is, for display, just that primitive — collapse it. Branches
|
|
62
|
+
// with differing or no `type` (a real polymorphic `$ref` union) stay
|
|
63
|
+
// `union` so we never mislabel one variant as another.
|
|
64
|
+
const prims = branches.map((b) => "type" in b ? b.type : undefined);
|
|
65
|
+
if (prims.every((t) => t !== undefined && t === prims[0])) {
|
|
66
|
+
return kindOf(branches[0]);
|
|
67
|
+
}
|
|
68
|
+
return { kind: "union" };
|
|
69
|
+
}
|
|
70
|
+
if ("anyOf" in schema || "allOf" in schema) {
|
|
71
|
+
return { kind: "union" };
|
|
72
|
+
}
|
|
73
|
+
if (!("type" in schema))
|
|
74
|
+
return { kind: "unknown" };
|
|
75
|
+
switch (schema.type) {
|
|
76
|
+
case "boolean":
|
|
77
|
+
return { kind: "boolean" };
|
|
78
|
+
case "integer":
|
|
79
|
+
case "number":
|
|
80
|
+
return { kind: "number" };
|
|
81
|
+
case "string": {
|
|
82
|
+
// biome-ignore lint: enum is part of the JSON Schema string node
|
|
83
|
+
const enumValues = schema.enum;
|
|
84
|
+
if (Array.isArray(enumValues) && enumValues.length > 0) {
|
|
85
|
+
return { kind: "enum", enumValues, format: schema.format };
|
|
86
|
+
}
|
|
87
|
+
return { kind: "string", format: schema.format };
|
|
88
|
+
}
|
|
89
|
+
case "array": {
|
|
90
|
+
const items = "items" in schema ? schema.items : undefined;
|
|
91
|
+
if (items === undefined)
|
|
92
|
+
return { kind: "array", itemKind: "unknown" };
|
|
93
|
+
const inner = kindOf(items);
|
|
94
|
+
return {
|
|
95
|
+
kind: "array",
|
|
96
|
+
itemKind: inner.kind,
|
|
97
|
+
ref: inner.ref,
|
|
98
|
+
itemFormat: inner.format,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
case "object":
|
|
102
|
+
return { kind: "object" };
|
|
103
|
+
default:
|
|
104
|
+
return { kind: "unknown" };
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Resolve a schema's effective `{ properties, required }`, following `$ref` and
|
|
109
|
+
* merging every `allOf` member. Composition (`allOf`) is a core OpenAPI feature
|
|
110
|
+
* real swaggers (Box, Stripe, …) lean on heavily — a type is often
|
|
111
|
+
* `allOf: [BasePagination, { properties: { entries } }]` with no direct
|
|
112
|
+
* `properties` of its own. Without this, such a type renders zero fields.
|
|
113
|
+
*
|
|
114
|
+
* Own `properties` win over inherited ones on a name clash; `required` is the
|
|
115
|
+
* union. Depth-guarded against cyclic `$ref`.
|
|
116
|
+
*/
|
|
117
|
+
function resolveProperties(schema, doc, depth = 0) {
|
|
118
|
+
var _a, _b;
|
|
119
|
+
if (depth > 8)
|
|
120
|
+
return { properties: {}, required: [] };
|
|
121
|
+
if ("$ref" in schema && typeof schema.$ref === "string") {
|
|
122
|
+
const target = ((_b = (_a = doc.components) === null || _a === void 0 ? void 0 : _a.schemas) !== null && _b !== void 0 ? _b : {})[refName(schema.$ref)];
|
|
123
|
+
return target === undefined
|
|
124
|
+
? { properties: {}, required: [] }
|
|
125
|
+
: resolveProperties(target, doc, depth + 1);
|
|
126
|
+
}
|
|
127
|
+
let properties = {};
|
|
128
|
+
let required = [];
|
|
129
|
+
if ("allOf" in schema && Array.isArray(schema.allOf)) {
|
|
130
|
+
for (const member of schema.allOf) {
|
|
131
|
+
const sub = resolveProperties(member, doc, depth + 1);
|
|
132
|
+
properties = Object.assign(Object.assign({}, properties), sub.properties);
|
|
133
|
+
required = [...required, ...sub.required];
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if ("properties" in schema && schema.properties !== undefined) {
|
|
137
|
+
properties = Object.assign(Object.assign({}, properties), schema.properties);
|
|
138
|
+
}
|
|
139
|
+
if ("required" in schema && Array.isArray(schema.required)) {
|
|
140
|
+
required = [...required, ...schema.required];
|
|
141
|
+
}
|
|
142
|
+
return { properties, required: [...new Set(required)] };
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Extract the field list of a schema directly (resolving `$ref` and `allOf`).
|
|
146
|
+
* Works for both named component schemas and INLINE schemas — e.g. a response
|
|
147
|
+
* `{ databases: T[], links: … }` that is not a named component (common on
|
|
148
|
+
* DigitalOcean). Returns `[]` when there are no resolvable `properties`.
|
|
149
|
+
*/
|
|
150
|
+
function extractFieldsFromSchema(schema, document) {
|
|
151
|
+
const { properties, required } = resolveProperties(schema, document, 0);
|
|
152
|
+
const requiredSet = new Set(required);
|
|
153
|
+
return Object.entries(properties).map(([name, prop]) => {
|
|
154
|
+
const k = kindOf(prop);
|
|
155
|
+
// For an array of INLINE objects (no $ref element type), resolve the
|
|
156
|
+
// element's own fields so a table can show its columns.
|
|
157
|
+
let itemFields;
|
|
158
|
+
if (k.kind === "array" && k.ref === undefined) {
|
|
159
|
+
const items = prop.items;
|
|
160
|
+
if (items !== undefined) {
|
|
161
|
+
const inner = extractFieldsFromSchema(items, document);
|
|
162
|
+
if (inner.length > 0)
|
|
163
|
+
itemFields = inner;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return {
|
|
167
|
+
name,
|
|
168
|
+
required: requiredSet.has(name),
|
|
169
|
+
kind: k.kind,
|
|
170
|
+
format: k.format,
|
|
171
|
+
enumValues: k.enumValues,
|
|
172
|
+
ref: k.ref,
|
|
173
|
+
itemKind: k.itemKind,
|
|
174
|
+
itemFormat: k.itemFormat,
|
|
175
|
+
itemFields,
|
|
176
|
+
};
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Extract the field list of a NAMED component schema. Returns `[]` when the type
|
|
181
|
+
* is unknown or has no resolvable `properties` — the caller then degrades
|
|
182
|
+
* gracefully rather than inventing fields.
|
|
183
|
+
*/
|
|
184
|
+
function extractFields(typeName, document) {
|
|
185
|
+
var _a, _b;
|
|
186
|
+
const schema = ((_b = (_a = document.components) === null || _a === void 0 ? void 0 : _a.schemas) !== null && _b !== void 0 ? _b : {})[typeName];
|
|
187
|
+
if (schema === undefined)
|
|
188
|
+
return [];
|
|
189
|
+
return extractFieldsFromSchema(schema, document);
|
|
190
|
+
}
|
|
191
|
+
/** Field names that read as an image, optionally suffixed with url(s)/uri(s)/src. */
|
|
192
|
+
const IMAGE_NAME = /(image|img|photo|picture|thumbnail|thumb|avatar|icon|logo|banner|cover|poster|artwork)s?(_?(url|uri|src|href)s?)?$/i;
|
|
193
|
+
/** Field names that hold a human title for a record (the card's heading). */
|
|
194
|
+
const TITLE_NAMES = new Set([
|
|
195
|
+
"name",
|
|
196
|
+
"title",
|
|
197
|
+
"label",
|
|
198
|
+
"headline",
|
|
199
|
+
"subject",
|
|
200
|
+
"nickname",
|
|
201
|
+
]);
|
|
202
|
+
/**
|
|
203
|
+
* The field that best represents a record's image, or `undefined`. A scalar
|
|
204
|
+
* `string` (often `format: uri`) or a `string[]` of image URLs whose NAME reads
|
|
205
|
+
* as an image wins; failing that, a uri-formatted url-ish field. This is the
|
|
206
|
+
* signal that turns a list into a catalog of cards instead of a table.
|
|
207
|
+
*/
|
|
208
|
+
function imageFieldOf(columns) {
|
|
209
|
+
const named = columns.find((c) => IMAGE_NAME.test(c.name) &&
|
|
210
|
+
(c.kind === "string" || (c.kind === "array" && c.itemKind === "string")));
|
|
211
|
+
if (named !== undefined)
|
|
212
|
+
return named;
|
|
213
|
+
return columns.find((c) => (c.kind === "string" &&
|
|
214
|
+
c.format === "uri" &&
|
|
215
|
+
/url|uri|src|link/i.test(c.name)) ||
|
|
216
|
+
(c.kind === "array" && c.itemKind === "string" && c.itemFormat === "uri"));
|
|
217
|
+
}
|
|
218
|
+
/** The field that best titles a record (a card's heading), or `undefined`. */
|
|
219
|
+
function titleFieldOf(columns) {
|
|
220
|
+
var _a;
|
|
221
|
+
return ((_a = columns.find((c) => c.kind === "string" && TITLE_NAMES.has(c.name.toLowerCase()))) !== null && _a !== void 0 ? _a : columns.find((c) => c.kind === "string" && /name|title/i.test(c.name)));
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* A collection deserves a catalog (card grid) rather than a table when its rows
|
|
225
|
+
* carry both an image and a title — the two things a card needs. Purely
|
|
226
|
+
* structural from the element schema; no domain keywords.
|
|
227
|
+
*/
|
|
228
|
+
function isCatalogCollection(columns) {
|
|
229
|
+
return (imageFieldOf(columns) !== undefined && titleFieldOf(columns) !== undefined);
|
|
230
|
+
}
|
|
231
|
+
//# sourceMappingURL=extractFields.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractFields.js","sourceRoot":"","sources":["../../src/utils/extractFields.ts"],"names":[],"mappings":"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"}
|