@lukoweb/apitogo 0.1.127 → 0.1.129
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
CHANGED
|
@@ -5809,7 +5809,7 @@ import {
|
|
|
5809
5809
|
// package.json
|
|
5810
5810
|
var package_default = {
|
|
5811
5811
|
name: "@lukoweb/apitogo",
|
|
5812
|
-
version: "0.1.
|
|
5812
|
+
version: "0.1.129",
|
|
5813
5813
|
type: "module",
|
|
5814
5814
|
sideEffects: [
|
|
5815
5815
|
"**/*.css",
|
|
@@ -16205,7 +16205,7 @@ async function ensureTsconfigJson(dir) {
|
|
|
16205
16205
|
return true;
|
|
16206
16206
|
}
|
|
16207
16207
|
}
|
|
16208
|
-
var LANDING_PAGE_SOURCE = 'import {\n ApiShowcaseSection,\n FeaturesSection,\n HeroSection,\n LandingShell,\n PlansPreviewSection,\n PricingCtaSection,\n StepsSection,\n} from "@lukoweb/apitogo-module-landing";\n\nexport default function LandingPage() {\n return (\n <LandingShell\n title="Test against a real API before you build one"\n description="Sample API gives you realistic endpoints, authentication, rate limits, and webhooks \u2014 a fully working backend for prototypes, demos, and QA."\n >\n <HeroSection\n hero={{\n badge: "SANDBOX API",\n title: "Test against a real API before you build one",\n description:\n "Sample API gives you realistic endpoints, authentication, rate limits, and webhooks \u2014 a fully working backend for prototypes, demos, and QA. No setup, no infrastructure.",\n }}\n primaryAction={{ label: "Start for free", href: "/signup" }}\n secondaryAction={{ label: "Read the docs", href: "/introduction" }}\n codeExamples={[\n {\n filename: "Create a key",\n language: "bash",\n code: `$ curl -X POST https://api.sampleapi.dev/v1/keys\n# sk_live_9f2c7a1e...`,\n },\n {\n filename: "Call an endpoint",\n language: "bash",\n code: `$ curl https://api.sampleapi.dev/v1/users/42 \\\\\n -H "Authorization: Bearer sk_live_9f2c..."\n# { "id": 42, "name": "Priya Shah", "plan": "pro" }`,\n },\n ]}\n />\n <FeaturesSection\n section={{\n label: "Everything a real API has",\n title: "Built for testing, not just browsing",\n description:\n "Realistic data, live auth, rate limits, and webhooks \u2014 so you can ship with confidence.",\n }}\n features={[\n {\n title: "Realistic mock data",\n description:\n "Users, orders, products, and posts with relationships and pagination, not lorem ipsum.",\n icon: "boxes",\n },\n {\n title: "Real auth flow",\n description:\n "Every request checks a live API key, so you can test error handling and expiry.",\n icon: "shield-check",\n },\n {\n title: "Rate limiting",\n description:\n "Per-plan request limits and 429 responses, so you can build and test backoff logic.",\n icon: "gauge",\n },\n {\n title: "Webhooks",\n description:\n "Trigger test events and inspect delivered payloads and retries.",\n icon: "webhook",\n },\n {\n title: "OpenAPI & docs",\n description:\n "A full OpenAPI spec and reference docs for every endpoint.",\n icon: "book-open",\n },\n {\n title: "Usage analytics",\n description:\n "Track requests, latency, and errors per key from your dashboard.",\n icon: "activity",\n },\n ]}\n />\n <StepsSection\n steps={[\n {\n step: "01",\n title: "Create an account",\n description:\n "Sign up and land straight in your dashboard \u2014 no approval queue.",\n },\n {\n step: "02",\n title: "Generate a key",\n description:\n "Every key is scoped and rate-limited to your plan from the moment it\'s created.",\n },\n {\n step: "03",\n title: "Call any endpoint",\n description:\n "Users, orders, products, posts, and webhooks \u2014 all documented, all live.",\n },\n ]}\n />\n <ApiShowcaseSection\n apiShowcase={{\n title: "Sample endpoints",\n subtitle:\n "A slice of what\'s available \u2014 see the full reference in the docs.",\n browseAllHref: "/api",\n browseAllLabel: "Browse all APIs",\n layout: "list",\n items: [\n {\n name: "List paginated users",\n path: "/v1/users",\n method: "GET",\n summary: "List paginated users",\n },\n {\n name: "Create a mock order",\n path: "/v1/orders",\n method: "POST",\n summary: "Create a mock order",\n },\n {\n name: "Fetch one product",\n path: "/v1/products/{id}",\n method: "GET",\n summary: "Fetch one product",\n },\n {\n name: "List posts with comments",\n path: "/v1/posts",\n method: "GET",\n summary: "List posts with comments",\n },\n {\n name: "Fire a test webhook event",\n path: "/v1/webhooks/test",\n method: "POST",\n summary: "Fire a test webhook event",\n },\n {\n name: "Delete a mock order",\n path: "/v1/orders/{id}",\n method: "DELETE",\n summary: "Delete a mock order",\n },\n ],\n }}\n />\n <PlansPreviewSection\n plans={[\n {\n name: "Free",\n price: "$0",\n unit: "per month",\n blurb: "1,000 requests/mo.",\n },\n {\n name: "Developer",\n price: "$19",\n unit: "per month",\n blurb: "50,000 requests/mo, webhooks included.",\n featured: true,\n },\n {\n name: "Team",\n price: "$79",\n unit: "per month",\n blurb: "500,000 requests/mo, 5 team seats.",\n },\n {\n name: "Enterprise",\n price: "$299",\n unit: "per month",\n blurb: "Unlimited requests, SSO, SLA.",\n },\n ]}\n />\n <PricingCtaSection\n variant="banner"\n pricingCta={{\n title: "Start testing in minutes",\n description:\n "Free tier includes 1,000 requests a month \u2014 no card required.",\n primaryAction: { label: "Start for free", href: "/signup" },\n }}\n />\n </LandingShell>\n );\n}\n';
|
|
16208
|
+
var LANDING_PAGE_SOURCE = 'import {\n ApiShowcaseSection,\n FeaturesSection,\n HeroSection,\n LandingShell,\n PlansPreviewSection,\n PricingCtaSection,\n StepsSection,\n} from "@lukoweb/apitogo-module-landing";\n\nexport default function LandingPage() {\n return (\n <LandingShell\n title="Test against a real API before you build one"\n description="Sample API gives you realistic endpoints, authentication, rate limits, and webhooks \u2014 a fully working backend for prototypes, demos, and QA."\n >\n <HeroSection\n hero={{\n badge: "SANDBOX API",\n title: "Test against a real API before you build one",\n description:\n "Sample API gives you realistic endpoints, authentication, rate limits, and webhooks \u2014 a fully working backend for prototypes, demos, and QA. No setup, no infrastructure.",\n }}\n primaryAction={{ label: "Start for free", href: "/signup" }}\n secondaryAction={{ label: "Read the docs", href: "/introduction" }}\n codeExamples={[\n {\n filename: "Create a key",\n language: "bash",\n code: `$ curl -X POST https://api.sampleapi.dev/v1/keys\n# sk_live_9f2c7a1e...`,\n },\n {\n filename: "Call an endpoint",\n language: "bash",\n code: `$ curl https://api.sampleapi.dev/v1/users/42 \\\\\n -H "Authorization: Bearer sk_live_9f2c..."\n# { "id": 42, "name": "Priya Shah", "plan": "pro" }`,\n },\n ]}\n />\n <FeaturesSection\n section={{\n label: "Everything a real API has",\n title: "Built for testing, not just browsing",\n description:\n "Realistic data, live auth, rate limits, and webhooks \u2014 so you can ship with confidence.",\n }}\n features={[\n {\n title: "Realistic mock data",\n description:\n "Users, orders, products, and posts with relationships and pagination, not lorem ipsum.",\n icon: "boxes",\n },\n {\n title: "Real auth flow",\n description:\n "Every request checks a live API key, so you can test error handling and expiry.",\n icon: "shield-check",\n },\n {\n title: "Rate limiting",\n description:\n "Per-plan request limits and 429 responses, so you can build and test backoff logic.",\n icon: "gauge",\n },\n {\n title: "Webhooks",\n description:\n "Trigger test events and inspect delivered payloads and retries.",\n icon: "webhook",\n },\n {\n title: "OpenAPI & docs",\n description:\n "A full OpenAPI spec and reference docs for every endpoint.",\n icon: "book-open",\n },\n {\n title: "Usage analytics",\n description:\n "Track requests, latency, and errors per key from your dashboard.",\n icon: "activity",\n },\n ]}\n />\n <StepsSection\n steps={[\n {\n step: "01",\n title: "Create an account",\n description:\n "Sign up and land straight in your dashboard \u2014 no approval queue.",\n },\n {\n step: "02",\n title: "Generate a key",\n description:\n "Every key is scoped and rate-limited to your plan from the moment it\'s created.",\n },\n {\n step: "03",\n title: "Call any endpoint",\n description:\n "Users, orders, products, posts, and webhooks \u2014 all documented, all live.",\n },\n ]}\n />\n {/* Static sample list. To show your real API operations from the dev portal\n backend instead, see https://docs.apitogo.com/docs/customization/landing-page#live-apis */}\n <ApiShowcaseSection\n apiShowcase={{\n title: "Sample endpoints",\n subtitle:\n "A slice of what\'s available \u2014 see the full reference in the docs.",\n browseAllHref: "/api",\n browseAllLabel: "Browse all APIs",\n layout: "list",\n items: [\n {\n name: "List paginated users",\n path: "/v1/users",\n method: "GET",\n summary: "List paginated users",\n },\n {\n name: "Create a mock order",\n path: "/v1/orders",\n method: "POST",\n summary: "Create a mock order",\n },\n {\n name: "Fetch one product",\n path: "/v1/products/{id}",\n method: "GET",\n summary: "Fetch one product",\n },\n {\n name: "List posts with comments",\n path: "/v1/posts",\n method: "GET",\n summary: "List posts with comments",\n },\n {\n name: "Fire a test webhook event",\n path: "/v1/webhooks/test",\n method: "POST",\n summary: "Fire a test webhook event",\n },\n {\n name: "Delete a mock order",\n path: "/v1/orders/{id}",\n method: "DELETE",\n summary: "Delete a mock order",\n },\n ],\n }}\n />\n <PlansPreviewSection\n plans={[\n {\n name: "Free",\n price: "$0",\n unit: "per month",\n blurb: "1,000 requests/mo.",\n },\n {\n name: "Developer",\n price: "$19",\n unit: "per month",\n blurb: "50,000 requests/mo, webhooks included.",\n featured: true,\n },\n {\n name: "Team",\n price: "$79",\n unit: "per month",\n blurb: "500,000 requests/mo, 5 team seats.",\n },\n {\n name: "Enterprise",\n price: "$299",\n unit: "per month",\n blurb: "Unlimited requests, SSO, SLA.",\n },\n ]}\n />\n <PricingCtaSection\n variant="banner"\n pricingCta={{\n title: "Start testing in minutes",\n description:\n "Free tier includes 1,000 requests a month \u2014 no card required.",\n primaryAction: { label: "Start for free", href: "/signup" },\n }}\n />\n </LandingShell>\n );\n}\n';
|
|
16209
16209
|
var ACCOUNT_PLANS_PAGE_SOURCE = `export { AccountPlansPage as default } from "@lukoweb/apitogo-plugin-dev-portal-billing";
|
|
16210
16210
|
`;
|
|
16211
16211
|
var DASHBOARD_PAGE_SOURCE = `export { OverviewDashboardPage as default } from "@lukoweb/apitogo-plugin-dev-portal-billing";
|
|
@@ -18273,17 +18273,14 @@ function isWarmPoolInfrastructureTerminal(project) {
|
|
|
18273
18273
|
return status2 === "ready" || status2 === "failed" || status2 === "deleting";
|
|
18274
18274
|
}
|
|
18275
18275
|
function shouldSkipColdModuleInfrastructureWait(project, infraStatus) {
|
|
18276
|
-
if (isWarmPoolInfrastructureReady(project)) {
|
|
18277
|
-
return true;
|
|
18278
|
-
}
|
|
18279
18276
|
const resourceType = infraStatus?.resourceType;
|
|
18280
|
-
if (resourceType === "WarmPoolBinding") {
|
|
18281
|
-
return true;
|
|
18282
|
-
}
|
|
18283
18277
|
if (resourceType && COLD_MODULE_INFRA_RESOURCE_TYPES.has(resourceType)) {
|
|
18284
18278
|
return false;
|
|
18285
18279
|
}
|
|
18286
|
-
|
|
18280
|
+
if (resourceType === "WarmPoolBinding") {
|
|
18281
|
+
return true;
|
|
18282
|
+
}
|
|
18283
|
+
return isWarmPoolInfrastructureReady(project);
|
|
18287
18284
|
}
|
|
18288
18285
|
function resolvePortalBackendFqdn(project) {
|
|
18289
18286
|
const portalApiUrl = project.portalApiUrl?.trim();
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_icon: house
|
|
3
|
+
title: Landing Page
|
|
4
|
+
description:
|
|
5
|
+
Customize your dev portal home page and show your real API operations in the API showcase, loaded
|
|
6
|
+
live from your dev portal backend.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
A scaffolded dev portal home page lives in `landing/LandingPage.tsx`. It composes section components
|
|
10
|
+
from `@lukoweb/apitogo-module-landing` inside a `LandingShell`:
|
|
11
|
+
|
|
12
|
+
| Component | Purpose |
|
|
13
|
+
| --------------------- | --------------------------------------------- |
|
|
14
|
+
| `HeroSection` | Headline, description, CTAs and code examples |
|
|
15
|
+
| `TrustSection` | Logos or social proof |
|
|
16
|
+
| `FeaturesSection` | Feature grid |
|
|
17
|
+
| `StepsSection` | Numbered "how it works" steps |
|
|
18
|
+
| `ApiShowcaseSection` | Grid or method + path list of your API |
|
|
19
|
+
| `PlansPreviewSection` | Short plan comparison linking to `/pricing` |
|
|
20
|
+
| `PricingCtaSection` | Closing call to action |
|
|
21
|
+
|
|
22
|
+
Edit the file directly to add, remove or reorder sections. The site footer is configured separately
|
|
23
|
+
in `apitogo.config.json` under `modules.landing.content.footer` (see
|
|
24
|
+
[Footer](/docs/configuration/footer)).
|
|
25
|
+
|
|
26
|
+
## API showcase
|
|
27
|
+
|
|
28
|
+
`ApiShowcaseSection` renders the items you pass it. The scaffold ships with a **static sample
|
|
29
|
+
list**:
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
<ApiShowcaseSection
|
|
33
|
+
apiShowcase={{
|
|
34
|
+
title: "Sample endpoints",
|
|
35
|
+
layout: "list", // or "grid"
|
|
36
|
+
browseAllHref: "/api",
|
|
37
|
+
items: [
|
|
38
|
+
{ name: "List users", path: "/v1/users", method: "GET", summary: "List paginated users" },
|
|
39
|
+
],
|
|
40
|
+
}}
|
|
41
|
+
/>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Each item accepts `name`, `path`, and optionally `method`, `summary`, `icon` and `latency`.
|
|
45
|
+
|
|
46
|
+
## Live APIs
|
|
47
|
+
|
|
48
|
+
Instead of maintaining the list by hand, you can load your API's real operations. Your dev portal
|
|
49
|
+
backend syncs the **gateway actions** of your project (every operation discovered from the OpenAPI
|
|
50
|
+
spec you deployed) and serves them publicly at `GET /api/v1/actions`. The `useGatewayActions()` hook
|
|
51
|
+
fetches that list; you decide what to show and pass the result to `ApiShowcaseSection`.
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
import {
|
|
55
|
+
ApiShowcaseSection,
|
|
56
|
+
LandingShell,
|
|
57
|
+
toApiShowcaseItems,
|
|
58
|
+
useGatewayActions,
|
|
59
|
+
} from "@lukoweb/apitogo-module-landing";
|
|
60
|
+
|
|
61
|
+
const staticItems = [
|
|
62
|
+
{ name: "List users", path: "/v1/users", method: "GET", summary: "List paginated users" },
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
// Optional friendly labels, keyed by action key (`method:path`, lower-case method).
|
|
66
|
+
const labels: Record<string, string> = {
|
|
67
|
+
"get:/v1/users": "List paginated users",
|
|
68
|
+
"post:/v1/orders": "Create an order",
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export default function LandingPage() {
|
|
72
|
+
const { data } = useGatewayActions({ inPlan: true });
|
|
73
|
+
|
|
74
|
+
const liveItems = toApiShowcaseItems(
|
|
75
|
+
(data?.actions ?? []).filter((action) => action.path.startsWith("/v1/")).slice(0, 6),
|
|
76
|
+
labels,
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<LandingShell title="My API">
|
|
81
|
+
<ApiShowcaseSection
|
|
82
|
+
apiShowcase={{
|
|
83
|
+
title: "Our APIs",
|
|
84
|
+
layout: "list",
|
|
85
|
+
browseAllHref: "/api",
|
|
86
|
+
items: liveItems.length > 0 ? liveItems : staticItems,
|
|
87
|
+
}}
|
|
88
|
+
/>
|
|
89
|
+
</LandingShell>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Filters
|
|
95
|
+
|
|
96
|
+
`useGatewayActions()` accepts server-side filters. All filters are combined:
|
|
97
|
+
|
|
98
|
+
| Option | Type | Description |
|
|
99
|
+
| ------------ | --------- | ------------------------------------------------------ |
|
|
100
|
+
| `inPlan` | `boolean` | Only actions included in at least one active plan |
|
|
101
|
+
| `plan` | `string` | Only actions included in the plan with this SKU |
|
|
102
|
+
| `isPublic` | `boolean` | Only actions callable without an API key (or only not) |
|
|
103
|
+
| `method` | `string` | HTTP method, e.g. `GET` |
|
|
104
|
+
| `pathPrefix` | `string` | Path prefix, e.g. `/v1/orders` |
|
|
105
|
+
| `limit` | `number` | Maximum number of actions (server cap: 500) |
|
|
106
|
+
| `enabled` | `boolean` | Set to `false` to skip the request |
|
|
107
|
+
|
|
108
|
+
Anything else — sorting, renaming, grouping, picking a hand-curated subset — is up to you in plain
|
|
109
|
+
TypeScript before you build the items.
|
|
110
|
+
|
|
111
|
+
Each action has this shape:
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
type GatewayAction = {
|
|
115
|
+
actionKey: string; // e.g. "get:/orders/{id}"
|
|
116
|
+
method: string; // e.g. "GET"
|
|
117
|
+
path: string; // e.g. "/orders/{id}"
|
|
118
|
+
isPublic: boolean; // callable without an API key
|
|
119
|
+
};
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Actions only carry the method and path. Use the `summaries` argument of `toApiShowcaseItems()` (or
|
|
123
|
+
your own mapping) to add human-friendly names.
|
|
124
|
+
|
|
125
|
+
### Always keep a fallback
|
|
126
|
+
|
|
127
|
+
The hook runs in the browser only, so the prerendered HTML never contains a stale list. `data` is
|
|
128
|
+
`undefined`:
|
|
129
|
+
|
|
130
|
+
- while the request is loading,
|
|
131
|
+
- if the request fails,
|
|
132
|
+
- in preview and demo mode, or when no dev portal backend URL is configured (for example in
|
|
133
|
+
`npm run dev` before your portal is provisioned).
|
|
134
|
+
|
|
135
|
+
`ApiShowcaseSection` renders nothing for an empty list, so pass a static fallback as shown above.
|
|
136
|
+
|
|
137
|
+
### What becomes public
|
|
138
|
+
|
|
139
|
+
`GET /api/v1/actions` is anonymous: **every operation in the OpenAPI spec deployed to your gateway
|
|
140
|
+
is listable**, including ones you may not document in the portal. Use `inPlan: true` to limit the
|
|
141
|
+
list to operations your plans actually sell, and remove internal operations from the spec you deploy
|
|
142
|
+
to the gateway if they must not be discoverable.
|
|
143
|
+
|
|
144
|
+
### Freshness and limits
|
|
145
|
+
|
|
146
|
+
- The backend syncs actions at startup and on the plan sync interval (15 minutes by default). A new
|
|
147
|
+
release shows up after the next sync.
|
|
148
|
+
- Responses are cacheable for 5 minutes (`Cache-Control: public, max-age=300`).
|
|
149
|
+
- The endpoint is rate limited per client IP (60 requests per minute).
|
|
150
|
+
|
|
151
|
+
### Troubleshooting
|
|
152
|
+
|
|
153
|
+
- **The list is always the fallback:** check that `authentication.apiBaseUrl` (or
|
|
154
|
+
`VITE_APITOGO_AUTHENTICATION_API_BASE_URL`) points at your dev portal backend and is not the
|
|
155
|
+
placeholder URL.
|
|
156
|
+
- **CORS errors:** the backend only allows the portal's configured frontend URL. Serving the site
|
|
157
|
+
from another domain requires adding it to the backend's allowed origins.
|
|
158
|
+
- **Empty list on a new portal:** the portal is not activated yet, or the gateway has no release.
|
|
159
|
+
Deploy your backend, then wait for the next sync.
|