From 70c27e191ab700cc3759aef5a9f244c59c287475 Mon Sep 17 00:00:00 2001 From: adrians5j Date: Mon, 23 Mar 2026 21:52:26 +0100 Subject: [PATCH 1/6] wip:1 (4fxqc) --- AGENTS.md | 2 +- docs/developer-docs/6.x/navigation.tsx | 1 + .../multi-tenant-nextjs.ai.txt | 52 ++++ .../website-builder/multi-tenant-nextjs.mdx | 227 ++++++++++++++++++ 4 files changed, 281 insertions(+), 1 deletion(-) create mode 100644 docs/developer-docs/6.x/website-builder/multi-tenant-nextjs.ai.txt create mode 100644 docs/developer-docs/6.x/website-builder/multi-tenant-nextjs.mdx diff --git a/AGENTS.md b/AGENTS.md index f843b67f2..b09ce101d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -49,7 +49,7 @@ docs/developer-docs/6.0.x/ ├── reference/ # Auto-generated API reference (extensions, admin, API) ├── tasks/ # Background task system (about, reference, management) ├── tenant-manager/ # Multi-tenancy management (GraphQL API, model extension) -└── website-builder/ # Website Builder extensibility (Next.js setup, theming, custom components) +└── website-builder/ # Website Builder extensibility (Next.js setup, multi-tenant setup, theming, custom components) ``` ### Key Patterns diff --git a/docs/developer-docs/6.x/navigation.tsx b/docs/developer-docs/6.x/navigation.tsx index 51a8a5b96..3983fc6cc 100644 --- a/docs/developer-docs/6.x/navigation.tsx +++ b/docs/developer-docs/6.x/navigation.tsx @@ -100,6 +100,7 @@ export const Navigation = ({ children }: { children: React.ReactNode }) => { > + diff --git a/docs/developer-docs/6.x/website-builder/multi-tenant-nextjs.ai.txt b/docs/developer-docs/6.x/website-builder/multi-tenant-nextjs.ai.txt new file mode 100644 index 000000000..831803a1b --- /dev/null +++ b/docs/developer-docs/6.x/website-builder/multi-tenant-nextjs.ai.txt @@ -0,0 +1,52 @@ +AI Context: Multi-Tenant Next.js Setup (website-builder/multi-tenant-nextjs.mdx) + +Source of Information: +1. /Users/adrian/dev/website-builder-nextjs-presales - Internal POC codebase demonstrating the pattern +2. Slack thread (Boris → Pavel → Adrian) confirming multi-tenancy is supported and POCs exist +3. website-builder/setup-nextjs.mdx - Single-tenant baseline this article extends +4. website-builder/how-it-works.mdx - Architecture context + +Key Documentation Decisions: +1. Based on internal presales POC at ~/dev/website-builder-nextjs-presales - not a public repo +2. Simplified examples: stripped project-specific component groups (restaurant, retail, clover) from initializeContentSdk +3. Kept wb.tenant query param handling because the editor iframe passes tenant this way +4. Subdomain resolution is the example strategy — article makes clear other strategies (domain table, path prefix, cookie) are equally valid +5. Per-tenant theming kept as brief conceptual section — implementation is project-specific (requires custom fields on tenant model) +6. Universal API key recommended as default — Pavel confirmed this is a supported approach +7. Did not document the webinyApi.js GraphQL utility from presales — too project-specific +8. ContentSdkInitializer is a client component wrapping initializeContentSdk; passes tenantId from server layout to browser side + +Understanding Multi-Tenant Architecture: +- SDK apiTenant param scopes all API calls to that tenant +- Middleware is the canonical place to resolve tenant identity (runs before all rendering) +- X-Tenant header propagates tenant ID from middleware to server components +- getTenant() reads X-Tenant header; falls back to "root" when missing (build-time static generation) +- initializeContentSdk called in: generateStaticParams, generateMetadata, getPage (server), ContentSdkInitializer (client) +- Editor loads Next.js in iframe with ?wb.tenant=&wb.editing=true — middleware already handles this via wb.tenant query param check + +Key Files in Presales POC: +- src/middleware.ts — tenant from wb.tenant param; preview mode handling +- src/contentSdk/getTenant.ts — reads X-Tenant header from next/headers +- src/contentSdk/initializeContentSdk.ts — accepts tenantId, passes as apiTenant +- src/contentSdk/ContentSdkInitializer.ts — client-side wrapper (React.memo) +- src/app/layout.tsx — calls getTenant(), does dynamic theme merge, passes tenantId to ContentSdkInitializer +- src/app/[[...slug]]/page.tsx — calls initializeContentSdk({ tenantId: await getTenant() }) in all three functions + +Dynamic Theming Pattern (from presales layout.tsx): +- Fetch static base theme from getTheme() +- Fetch per-tenant dynamic theme (websiteTitle, font, primaryColor, additionalColors) from Webiny GraphQL API with X-Tenant header +- Merge: dynamic font → fonts array, dynamic colors → cssVariables, CSS injected into +- Theme stored as custom fields on tenant model in Webiny +- mergeThemes() is project-specific utility — not included in docs example + +Related Documents: +- website-builder/setup-nextjs.mdx — single-tenant baseline (prerequisite) +- website-builder/how-it-works.mdx — SDK and architecture overview +- website-builder/theme.mdx — theme configuration +- core-concepts/multi-tenancy.mdx — Webiny tenant model and provisioning + +Tone Guidelines: +- Practical and direct — this is an implementation guide for developers setting up multi-tenancy +- Show real code; explain why each piece exists +- Don't over-explain; trust the reader can adapt examples to their strategy +- Keep per-tenant theming brief — it's project-specific, not prescriptive diff --git a/docs/developer-docs/6.x/website-builder/multi-tenant-nextjs.mdx b/docs/developer-docs/6.x/website-builder/multi-tenant-nextjs.mdx new file mode 100644 index 000000000..242d5e9c4 --- /dev/null +++ b/docs/developer-docs/6.x/website-builder/multi-tenant-nextjs.mdx @@ -0,0 +1,227 @@ +--- +id: wbmt7n4k +title: Multi-Tenant Next.js Setup +description: Configure a single Next.js application to serve content from multiple Webiny tenants based on domain, subdomain, or other request context. +--- + +import { Alert } from "@/components/Alert"; + + + +- How a single Next.js app can serve content from multiple Webiny tenants +- How to resolve tenant identity from the incoming request +- How to initialize the SDK with the correct tenant per request +- Which API key strategy fits multi-tenant deployments + + + +## Overview + +The default Next.js starter kit connects to one Webiny tenant set by the `NEXT_PUBLIC_WEBSITE_BUILDER_API_TENANT` environment variable. For SaaS platforms and multi-tenant deployments, a single Next.js instance can serve content from many tenants by resolving tenant identity at request time. + +The pattern has three parts: resolve tenant identity in middleware, propagate it to server components via a request header, then read it when initializing the SDK. + +## How Tenant Scoping Works + +The `contentSdk.init()` call accepts an `apiTenant` parameter. Normally this is set from the environment variable, but you can pass it dynamically. The SDK then scopes all API calls — page fetching, redirect resolution — to that tenant. + +``` +Request arrives + │ + ▼ +middleware.ts ← resolves tenant from hostname, subdomain, etc. + │ sets X-Tenant header + ▼ +Server component + │ + ▼ +getTenant() ← reads X-Tenant header + │ + ▼ +initializeContentSdk({ tenantId }) ← scopes SDK to tenant + │ + ▼ +contentSdk.getPage() ← fetches pages for that tenant only +``` + +## Resolving Tenant in Middleware + +Next.js middleware runs before any rendering and is the right place to resolve tenant identity from the request — subdomain, full domain, path prefix, or any other signal — and attach it as a header for downstream components. + +Create or update `src/middleware.ts`: + +```typescript src/middleware.ts +import { draftMode } from "next/headers"; +import { NextResponse, type NextRequest } from "next/server"; + +const ENABLE_DRAFT_MODE_ROUTE = "/api/preview"; + +export async function middleware(request: NextRequest) { + const { searchParams, hostname } = request.nextUrl; + const requestHeaders = new Headers(request.headers); + + // Resolve tenant from the wb.tenant query param (sent by the editor iframe), + // or fall back to subdomain-based resolution for public traffic. + const tenantId = searchParams.get("wb.tenant") ?? resolveTenantFromHostname(hostname); + + if (tenantId) { + requestHeaders.set("X-Tenant", tenantId); + } + + // Handle preview/draft mode. + const previewRequested = + searchParams.get("wb.preview") === "true" || searchParams.get("wb.editing") === "true"; + const previewMode = await draftMode(); + + if (previewRequested) { + const response = NextResponse.next({ request: { headers: requestHeaders } }); + if (previewMode.isEnabled) { + response.headers.set("Cache-Control", "no-store, no-cache, must-revalidate"); + return response; + } + const url = new URL(request.url); + url.pathname = ENABLE_DRAFT_MODE_ROUTE; + return NextResponse.redirect(url); + } else if (!previewRequested && previewMode.isEnabled) { + previewMode.disable(); + return NextResponse.redirect(request.url); + } + + return NextResponse.next({ request: { headers: requestHeaders } }); +} + +function resolveTenantFromHostname(hostname: string): string | undefined { + // Example: tenant-a.example.com → "tenant-a" + const subdomain = hostname.split(".")[0]; + return subdomain !== "www" ? subdomain : undefined; +} + +export const config = { + matcher: ["/((?!_next|api|static|favicon.ico|.well-known).*)"] +}; +``` + +The `wb.tenant` check handles editor traffic: when the Website Builder editor loads your Next.js app in an iframe, it passes the current tenant via this query parameter. Your domain-based resolution runs as a fallback for public visitors. + + + +The example above uses subdomain-based resolution. Replace `resolveTenantFromHostname` with any strategy that fits your routing — full domain matching against a lookup table, a path prefix, a cookie, or a JWT claim. + + + +## Reading Tenant in Server Components + +Add a utility that reads the `X-Tenant` header set by middleware: + +```typescript src/contentSdk/getTenant.ts +import { headers } from "next/headers"; + +export const getTenant = async (): Promise => { + try { + const headersContainer = await headers(); + return headersContainer.get("X-Tenant") ?? "root"; + } catch { + return "root"; + } +}; +``` + +The fallback to `"root"` ensures the app keeps working when no tenant header is present, for example during static generation at build time. + +## Initializing the SDK Per Request + +Update `initializeContentSdk` to accept a `tenantId` parameter. When provided, it overrides the `NEXT_PUBLIC_WEBSITE_BUILDER_API_TENANT` environment variable: + +```typescript src/contentSdk/initializeContentSdk.ts +import { contentSdk } from "@webiny/website-builder-nextjs"; + +interface ContentSdkOptions { + tenantId?: string; + preview?: boolean; +} + +export const initializeContentSdk = ({ tenantId, preview }: ContentSdkOptions = {}) => { + contentSdk.init({ + apiKey: String(process.env.NEXT_PUBLIC_WEBSITE_BUILDER_API_KEY), + apiHost: String(process.env.NEXT_PUBLIC_WEBSITE_BUILDER_API_HOST), + apiTenant: tenantId ?? String(process.env.NEXT_PUBLIC_WEBSITE_BUILDER_API_TENANT), + preview + }); +}; +``` + +Call `getTenant()` and pass the result wherever you initialize the SDK — in `generateStaticParams`, `generateMetadata`, and the page render function: + +```typescript src/app/[[...slug]]/page.tsx +import { draftMode } from "next/headers"; +import { contentSdk } from "@webiny/website-builder-nextjs"; +import { initializeContentSdk, getTenant } from "@/src/contentSdk"; + +export async function generateStaticParams() { + initializeContentSdk({ tenantId: await getTenant() }); + const pages = await contentSdk.listPages(); + return pages.map(page => ({ + slug: page.properties.path.split("/").slice(1) + })); +} + +export async function generateMetadata({ params }: PageProps) { + initializeContentSdk({ tenantId: await getTenant() }); + // ... +} + +async function getPage(path: string) { + const { isEnabled } = await draftMode(); + initializeContentSdk({ preview: isEnabled, tenantId: await getTenant() }); + return await contentSdk.getPage(path); +} +``` + +The root layout passes the tenant to the client-side `ContentSdkInitializer` component: + +```typescript src/app/layout.tsx +import { draftMode } from "next/headers"; +import { ContentSdkInitializer, getTenant } from "@/src/contentSdk"; +import { getTheme } from "@/src/theme"; + +export default async function RootLayout({ children }: { children: React.ReactNode }) { + const tenantId = await getTenant(); + const { isEnabled } = await draftMode(); + const { theme } = await getTheme(); + + return ( + + + + {children} + + + ); +} +``` + +`ContentSdkInitializer` is a memoized client component that calls `initializeContentSdk` on the browser side with the same tenant context. + +## API Key Strategy + +Two approaches work for multi-tenant deployments: + +**Universal key** — Create one API key at the root tenant level with read access across all tenants. Set it as `NEXT_PUBLIC_WEBSITE_BUILDER_API_KEY`. The `apiTenant` parameter already scopes all API calls to the correct tenant, so a single key is sufficient for most cases. + +**Per-tenant keys** — Each tenant has its own Website Builder API key (auto-created by the platform under **Settings → Access Management → API Keys**). You resolve the key per request by fetching it from your own data store or the Webiny API. This adds per-request key resolution overhead but provides stronger isolation at the credential level. + +For most SaaS deployments, a universal key is the simpler and recommended starting point. + +## Per-Tenant Theming + +The Website Builder supports per-tenant theming — each tenant can have its own fonts, colors, and CSS variables managed through Webiny Admin. In the root layout, fetch the tenant's theme configuration from the Webiny API and merge it with your static base theme before passing it to `ContentSdkInitializer` and injecting it into ``. + +```typescript +// Conceptual example — implementation details depend on your data model. +const tenantId = await getTenant(); +const { theme } = await getTheme(); // static base theme +const dynamicTheme = await fetchTenantTheme(tenantId); // per-tenant overrides from Webiny API +const mergedTheme = mergeThemes(theme, dynamicTheme); +``` + +The per-tenant theme data (font family, primary color, etc.) is stored as custom fields on the tenant model in Webiny and fetched via GraphQL with the `X-Tenant` header. From 21eb6ade0a29867f5d3a1718db9383ddb3756eec Mon Sep 17 00:00:00 2001 From: adrians5j Date: Thu, 26 Mar 2026 10:47:59 +0100 Subject: [PATCH 2/6] wip:2 (r6m5y) --- .local/img.png | Bin 120857 -> 0 bytes docs/developer-docs/6.x/navigation.tsx | 19 +- .../developer-docs/6.x/reference/admin.ai.txt | 9 +- docs/developer-docs/6.x/reference/admin.mdx | 32 +- .../6.x/reference/admin/buildParams.mdx | 115 --- .../cms/fieldRenderers/dynamic-zone.ai.txt | 25 - .../admin/cms/fieldRenderers/dynamic-zone.mdx | 21 - .../cms/fieldRenderers/dynamicZone.ai.txt | 25 - .../admin/cms/fieldRenderers/dynamicZone.mdx | 21 - .../admin/cms/fieldRenderers/object.mdx | 21 - .../6.x/reference/admin/env-config.ai.txt | 3 +- .../6.x/reference/admin/env-config.mdx | 27 +- .../6.x/reference/admin/envConfig.ai.txt | 25 - .../6.x/reference/admin/envConfig.mdx | 33 - .../6.x/reference/admin/form.mdx | 65 +- .../6.x/reference/admin/graphqlClient.ai.txt | 25 - .../6.x/reference/admin/graphqlClient.mdx | 67 -- .../6.x/reference/admin/lexical.mdx | 1 + .../6.x/reference/admin/localStorage.ai.txt | 26 - .../6.x/reference/admin/localStorage.mdx | 84 -- .../6.x/reference/admin/router.mdx | 35 +- .../6.x/reference/admin/ui.ai.txt | 5 +- .../developer-docs/6.x/reference/admin/ui.mdx | 13 + .../reference/admin/website-builder.ai.txt | 3 +- .../6.x/reference/admin/website-builder.mdx | 18 + .../admin/website-builder/page/editor.ai.txt | 19 +- .../admin/website-builder/page/editor.mdx | 506 +++++++++++- .../6.x/reference/api/aco/flp.ai.txt | 29 + .../6.x/reference/api/aco/flp.mdx | 149 ++++ .../object.ai.txt => api/aco/folder.ai.txt} | 15 +- .../6.x/reference/api/aco/folder.mdx | 83 ++ .../6.x/reference/api/buildParams.ai.txt | 25 - .../6.x/reference/api/buildParams.mdx | 115 --- .../6.x/reference/api/cms/entry.mdx | 2 + .../6.x/reference/api/cms/model.ai.txt | 2 +- .../6.x/reference/api/cms/model.mdx | 24 +- .../scheduler.ai.txt} | 15 +- .../6.x/reference/api/cms/scheduler.mdx | 80 ++ .../6.x/reference/api/event-publisher.mdx | 2 + .../6.x/reference/api/eventPublisher.ai.txt | 25 - .../6.x/reference/api/eventPublisher.mdx | 56 -- .../reference/api/file-manager/file.ai.txt | 36 + .../6.x/reference/api/file-manager/file.mdx | 743 ++++++++++++++++++ .../file-manager/permissions.ai.txt} | 14 +- .../api/file-manager/permissions.mdx | 29 + .../api/file-manager/settings.ai.txt | 27 + .../reference/api/file-manager/settings.mdx | 166 ++++ .../6.x/reference/api/graphql.mdx | 24 +- .../6.x/reference/api/keyValueStore.mdx | 132 ---- .../6.x/reference/api/logger.mdx | 12 - .../6.x/reference/api/scheduler.ai.txt | 32 + .../6.x/reference/api/scheduler.mdx | 399 ++++++++++ .../6.x/reference/api/security.ai.txt | 12 +- .../6.x/reference/api/security.mdx | 62 +- .../6.x/reference/api/security/api-key.mdx | 4 +- .../6.x/reference/api/tenancy.mdx | 4 - .../api/website-builder/scheduler.ai.txt | 28 + .../api/website-builder/scheduler.mdx | 138 ++++ .../{cli/overview.ai.txt => cli.ai.txt} | 6 +- .../reference/{cli/overview.mdx => cli.mdx} | 16 +- .../{infra/overview.ai.txt => infra.ai.txt} | 6 +- .../{infra/overview.mdx => infra.mdx} | 60 +- .../6.x/reference/sdk/cms.ai.txt | 128 +++ docs/developer-docs/6.x/reference/sdk/cms.mdx | 644 +++++++++++++++ .../6.x/reference/sdk/file-manager.ai.txt | 157 ++++ .../6.x/reference/sdk/file-manager.mdx | 698 ++++++++++++++++ .../6.x/reference/sdk/index.ai.txt | 140 ++++ .../6.x/reference/sdk/index.mdx | 523 ++++++++++++ .../6.x/reference/sdk/tenant-manager.ai.txt | 78 ++ .../6.x/reference/sdk/tenant-manager.mdx | 337 ++++++++ .../multi-tenant-nextjs.ai.txt | 1 + .../website-builder/multi-tenant-nextjs.mdx | 150 +++- package.json | 7 +- scripts/ref/_shared.ts | 698 ++++++++++++++++ scripts/ref/sdk.ts | 472 +++++++++++ scripts/ref/webiny-sdk.ts | 501 ++++++++++++ yarn.lock | 41 + 77 files changed, 7333 insertions(+), 1057 deletions(-) delete mode 100644 .local/img.png delete mode 100644 docs/developer-docs/6.x/reference/admin/buildParams.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/cms/fieldRenderers/dynamic-zone.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/cms/fieldRenderers/dynamic-zone.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/cms/fieldRenderers/dynamicZone.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/cms/fieldRenderers/dynamicZone.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/cms/fieldRenderers/object.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/envConfig.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/envConfig.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/graphqlClient.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/graphqlClient.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/localStorage.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/localStorage.mdx create mode 100644 docs/developer-docs/6.x/reference/api/aco/flp.ai.txt create mode 100644 docs/developer-docs/6.x/reference/api/aco/flp.mdx rename docs/developer-docs/6.x/reference/{admin/cms/fieldRenderers/object.ai.txt => api/aco/folder.ai.txt} (51%) create mode 100644 docs/developer-docs/6.x/reference/api/aco/folder.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/buildParams.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/buildParams.mdx rename docs/developer-docs/6.x/reference/api/{keyValueStore.ai.txt => cms/scheduler.ai.txt} (50%) create mode 100644 docs/developer-docs/6.x/reference/api/cms/scheduler.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/eventPublisher.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/eventPublisher.mdx create mode 100644 docs/developer-docs/6.x/reference/api/file-manager/file.ai.txt create mode 100644 docs/developer-docs/6.x/reference/api/file-manager/file.mdx rename docs/developer-docs/6.x/reference/{admin/buildParams.ai.txt => api/file-manager/permissions.ai.txt} (58%) create mode 100644 docs/developer-docs/6.x/reference/api/file-manager/permissions.mdx create mode 100644 docs/developer-docs/6.x/reference/api/file-manager/settings.ai.txt create mode 100644 docs/developer-docs/6.x/reference/api/file-manager/settings.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/keyValueStore.mdx create mode 100644 docs/developer-docs/6.x/reference/api/scheduler.ai.txt create mode 100644 docs/developer-docs/6.x/reference/api/scheduler.mdx create mode 100644 docs/developer-docs/6.x/reference/api/website-builder/scheduler.ai.txt create mode 100644 docs/developer-docs/6.x/reference/api/website-builder/scheduler.mdx rename docs/developer-docs/6.x/reference/{cli/overview.ai.txt => cli.ai.txt} (88%) rename docs/developer-docs/6.x/reference/{cli/overview.mdx => cli.mdx} (77%) rename docs/developer-docs/6.x/reference/{infra/overview.ai.txt => infra.ai.txt} (93%) rename docs/developer-docs/6.x/reference/{infra/overview.mdx => infra.mdx} (79%) create mode 100644 docs/developer-docs/6.x/reference/sdk/cms.ai.txt create mode 100644 docs/developer-docs/6.x/reference/sdk/cms.mdx create mode 100644 docs/developer-docs/6.x/reference/sdk/file-manager.ai.txt create mode 100644 docs/developer-docs/6.x/reference/sdk/file-manager.mdx create mode 100644 docs/developer-docs/6.x/reference/sdk/index.ai.txt create mode 100644 docs/developer-docs/6.x/reference/sdk/index.mdx create mode 100644 docs/developer-docs/6.x/reference/sdk/tenant-manager.ai.txt create mode 100644 docs/developer-docs/6.x/reference/sdk/tenant-manager.mdx create mode 100644 scripts/ref/_shared.ts create mode 100644 scripts/ref/sdk.ts create mode 100644 scripts/ref/webiny-sdk.ts diff --git a/.local/img.png b/.local/img.png deleted file mode 100644 index e3ca6f960b52e20b5262b0dd0e455ec49952d543..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 120857 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�O{ry0UXI(7tAoOkZFbc*c?s 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 { + + + + + + @@ -231,6 +237,7 @@ export const Navigation = ({ children }: { children: React.ReactNode }) => { + @@ -243,18 +250,26 @@ export const Navigation = ({ children }: { children: React.ReactNode }) => { + - + - + + {/* __SDK_PAGES_START__ */} + + + + + + {/* __SDK_PAGES_END__ */} {/* __REFERENCE_PAGES_END__ */} diff --git a/docs/developer-docs/6.x/reference/admin.ai.txt b/docs/developer-docs/6.x/reference/admin.ai.txt index 77654e17c..b7e0d6620 100644 --- a/docs/developer-docs/6.x/reference/admin.ai.txt +++ b/docs/developer-docs/6.x/reference/admin.ai.txt @@ -4,9 +4,10 @@ Source of Information: 1. packages/webiny/src/admin.ts — barrel re-export file 2. /Users/adrian/dev/wby-next/packages/app/src/shared/di/useFeature.ts — originating source 3. /Users/adrian/dev/wby-next/packages/app/src/errors/index.ts — originating source -4. /Users/adrian/dev/wby-next/packages/app-admin/src/permissions/index.ts — originating source -5. /Users/adrian/dev/wby-next/packages/app-admin/src/features/buildParams/index.ts — originating source -6. /Users/adrian/dev/wby-next/packages/app-admin/src/routes.ts — originating source +4. /Users/adrian/dev/wby-next/packages/app-admin/src/components/index.ts — originating source +5. /Users/adrian/dev/wby-next/packages/app-admin/src/permissions/index.ts — originating source +6. /Users/adrian/dev/wby-next/packages/app-admin/src/features/buildParams/index.ts — originating source +7. /Users/adrian/dev/wby-next/packages/app-admin/src/routes.ts — originating source Key Documentation Decisions: - This file is auto-generated by scripts/generate-reference.ts — do not edit manually @@ -15,7 +16,7 @@ Key Documentation Decisions: - Type-only exports are labeled as "Type"; namespace exports include member listings Exported Symbols: -useFeature, NetworkErrorEventHandler, createPermissionSchema, createHasPermission, createUsePermissions, BuildParam, BuildParams, Routes +useFeature, NetworkErrorEventHandler, DevToolsSection, createPermissionSchema, createHasPermission, createUsePermissions, BuildParam, BuildParams, Routes Import Path: webiny/admin diff --git a/docs/developer-docs/6.x/reference/admin.mdx b/docs/developer-docs/6.x/reference/admin.mdx index 1cd2dcf0a..4f819ec57 100644 --- a/docs/developer-docs/6.x/reference/admin.mdx +++ b/docs/developer-docs/6.x/reference/admin.mdx @@ -20,7 +20,12 @@ This page documents everything exported from `webiny/admin`. Import any of the i **Components** - + **Hooks** @@ -41,6 +46,31 @@ This page documents everything exported from `webiny/admin`. Import any of the i ## Components +### `DevToolsSection` + +**Function** — imported from `webiny/admin` + +Registers a named section in the Webiny DevTools extension. +Renders nothing — purely a data registration side-effect. + +When the component unmounts (e.g., route change), the section +is automatically removed from DevTools. + +@example + +```tsx + + +``` + +```typescript +import { DevToolsSection } from "webiny/admin"; +``` + +```typescript +export declare function DevToolsSection( +``` + ### `Routes` **Constant** — imported from `webiny/admin` diff --git a/docs/developer-docs/6.x/reference/admin/buildParams.mdx b/docs/developer-docs/6.x/reference/admin/buildParams.mdx deleted file mode 100644 index a3fd1fabb..000000000 --- a/docs/developer-docs/6.x/reference/admin/buildParams.mdx +++ /dev/null @@ -1,115 +0,0 @@ ---- -id: ywrtaw4v -title: Build Params -description: "Admin build parameter types" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/buildParams`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/buildParams`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `BuildParam` - -**Abstraction** — imported from `webiny/admin/buildParams` - -```typescript -import { BuildParam } from "webiny/admin/buildParams"; -``` - -**Interface `BuildParam.Interface`:** - -```typescript -interface BuildParam.Interface { - key: string; - value: any; -} -``` - -**Types:** - -```typescript -namespace BuildParam { - type Interface = IBuildParam; -} -``` - -**Usage:** - -```typescript -// extensions/MyImpl.ts -import { BuildParam } from "webiny/admin/buildParams"; - -class MyImpl implements MyUseCase.Interface { - public constructor(private buildParam: BuildParam.Interface) {} - - public async execute(/* ... */): Promise { - this.buildParam.key: string(/* ... */); - } -} - -export default MyUseCase.createImplementation({ - implementation: MyImpl, - dependencies: [BuildParam] -}); -``` - -## `BuildParams` - -**Abstraction** — imported from `webiny/admin/buildParams` - -```typescript -import { BuildParams } from "webiny/admin/buildParams"; -``` - -**Interface `BuildParams.Interface`:** - -```typescript -interface BuildParams.Interface { - get(key: string): T | null; -} -``` - -**Types:** - -```typescript -namespace BuildParams { - type Interface = IBuildParams; -} -``` - -**Usage:** - -```typescript -// extensions/MyImpl.ts -import { BuildParams } from "webiny/admin/buildParams"; - -class MyImpl implements MyUseCase.Interface { - public constructor(private buildParams: BuildParams.Interface) {} - - public async execute(/* ... */): Promise { - this.buildParams.get(/* ... */); - } -} - -export default MyUseCase.createImplementation({ - implementation: MyImpl, - dependencies: [BuildParams] -}); -``` diff --git a/docs/developer-docs/6.x/reference/admin/cms/fieldRenderers/dynamic-zone.ai.txt b/docs/developer-docs/6.x/reference/admin/cms/fieldRenderers/dynamic-zone.ai.txt deleted file mode 100644 index ef5bdb06c..000000000 --- a/docs/developer-docs/6.x/reference/admin/cms/fieldRenderers/dynamic-zone.ai.txt +++ /dev/null @@ -1,25 +0,0 @@ -AI Context: Dynamic Zone (reference/admin/cms/fieldRenderers/dynamic-zone.mdx) - -Source of Information: -1. packages/webiny/src/admin/cms/fieldRenderers/dynamic-zone.ts — barrel re-export file - - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: - - -Import Path: webiny/admin/cms/fieldRenderers/dynamic-zone - -Related Documents: -- docs/developer-docs/6.0.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.0.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/cms/fieldRenderers/dynamic-zone.mdx b/docs/developer-docs/6.x/reference/admin/cms/fieldRenderers/dynamic-zone.mdx deleted file mode 100644 index d0715ac77..000000000 --- a/docs/developer-docs/6.x/reference/admin/cms/fieldRenderers/dynamic-zone.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: ywrtaw4v -title: Dynamic Zone -description: "Reference for webiny/admin/cms/fieldRenderers/dynamic-zone" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/cms/fieldRenderers/dynamic-zone`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/cms/fieldRenderers/dynamic-zone`. Import any of the items below directly from this path in your Webiny extensions. - -_No exported symbols found._ diff --git a/docs/developer-docs/6.x/reference/admin/cms/fieldRenderers/dynamicZone.ai.txt b/docs/developer-docs/6.x/reference/admin/cms/fieldRenderers/dynamicZone.ai.txt deleted file mode 100644 index bcd8aad34..000000000 --- a/docs/developer-docs/6.x/reference/admin/cms/fieldRenderers/dynamicZone.ai.txt +++ /dev/null @@ -1,25 +0,0 @@ -AI Context: DynamicZone (reference/admin/cms/fieldRenderers/dynamicZone.mdx) - -Source of Information: -1. packages/webiny/src/admin/cms/fieldRenderers/dynamicZone.ts — barrel re-export file - - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: - - -Import Path: webiny/admin/cms/fieldRenderers/dynamicZone - -Related Documents: -- docs/developer-docs/6.0.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.0.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/cms/fieldRenderers/dynamicZone.mdx b/docs/developer-docs/6.x/reference/admin/cms/fieldRenderers/dynamicZone.mdx deleted file mode 100644 index 348784ce4..000000000 --- a/docs/developer-docs/6.x/reference/admin/cms/fieldRenderers/dynamicZone.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: ywrtaw4v -title: DynamicZone -description: "Dynamic zone field renderer components" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/cms/fieldRenderers/dynamicZone`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/cms/fieldRenderers/dynamicZone`. Import any of the items below directly from this path in your Webiny extensions. - -_No exported symbols found._ diff --git a/docs/developer-docs/6.x/reference/admin/cms/fieldRenderers/object.mdx b/docs/developer-docs/6.x/reference/admin/cms/fieldRenderers/object.mdx deleted file mode 100644 index 37925bb50..000000000 --- a/docs/developer-docs/6.x/reference/admin/cms/fieldRenderers/object.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: ywrtaw4v -title: Object -description: "Object field renderer components" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/cms/fieldRenderers/object`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/cms/fieldRenderers/object`. Import any of the items below directly from this path in your Webiny extensions. - -_No exported symbols found._ diff --git a/docs/developer-docs/6.x/reference/admin/env-config.ai.txt b/docs/developer-docs/6.x/reference/admin/env-config.ai.txt index 1a7322e88..6e0be0b16 100644 --- a/docs/developer-docs/6.x/reference/admin/env-config.ai.txt +++ b/docs/developer-docs/6.x/reference/admin/env-config.ai.txt @@ -3,6 +3,7 @@ AI Context: Env Config (reference/admin/env-config.mdx) Source of Information: 1. packages/webiny/src/admin/env-config.ts — barrel re-export file 2. /Users/adrian/dev/wby-next/packages/app/src/features/envConfig/index.ts — originating source +3. /Users/adrian/dev/wby-next/packages/app/src/presentation/envConfig/useEnvConfig.ts — originating source Key Documentation Decisions: - This file is auto-generated by scripts/generate-reference.ts — do not edit manually @@ -11,7 +12,7 @@ Key Documentation Decisions: - Type-only exports are labeled as "Type"; namespace exports include member listings Exported Symbols: -EnvConfig +EnvConfig, useEnvConfig Import Path: webiny/admin/env-config diff --git a/docs/developer-docs/6.x/reference/admin/env-config.mdx b/docs/developer-docs/6.x/reference/admin/env-config.mdx index 62088ff73..908f3620e 100644 --- a/docs/developer-docs/6.x/reference/admin/env-config.mdx +++ b/docs/developer-docs/6.x/reference/admin/env-config.mdx @@ -18,9 +18,17 @@ import { SymbolList } from "@/components/SymbolList"; This page documents everything exported from `webiny/admin/env-config`. Import any of the items below directly from this path in your Webiny extensions. +**Components** + -## `EnvConfig` +**Hooks** + + + +## Components + +### `EnvConfig` **Constant** — imported from `webiny/admin/env-config` @@ -31,3 +39,20 @@ import { EnvConfig } from "webiny/admin/env-config"; ```typescript export const EnvConfig = new Abstraction("EnvConfig"); ``` + +## Hooks + +### `useEnvConfig` + +**Function** — imported from `webiny/admin/env-config` + +Returns the EnvConfig instance from DI. +Useful when you want to access EnvConfig inside components and hooks. + +```typescript +import { useEnvConfig } from "webiny/admin/env-config"; +``` + +```typescript +export function useEnvConfig(): EnvConfig.Config; +``` diff --git a/docs/developer-docs/6.x/reference/admin/envConfig.ai.txt b/docs/developer-docs/6.x/reference/admin/envConfig.ai.txt deleted file mode 100644 index bdcd7a895..000000000 --- a/docs/developer-docs/6.x/reference/admin/envConfig.ai.txt +++ /dev/null @@ -1,25 +0,0 @@ -AI Context: Env Config (reference/admin/envConfig.mdx) - -Source of Information: -1. packages/webiny/src/admin/envConfig.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/app/src/features/envConfig/index.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -EnvConfig - -Import Path: webiny/admin/envConfig - -Related Documents: -- docs/developer-docs/6.0.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.0.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/envConfig.mdx b/docs/developer-docs/6.x/reference/admin/envConfig.mdx deleted file mode 100644 index 4615fe11f..000000000 --- a/docs/developer-docs/6.x/reference/admin/envConfig.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -id: ywrtaw4v -title: Env Config -description: "Environment configuration for admin" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/envConfig`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/envConfig`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `EnvConfig` - -**Constant** — imported from `webiny/admin/envConfig` - -```typescript -import { EnvConfig } from "webiny/admin/envConfig"; -``` - -```typescript -export const EnvConfig = new Abstraction("EnvConfig"); -``` diff --git a/docs/developer-docs/6.x/reference/admin/form.mdx b/docs/developer-docs/6.x/reference/admin/form.mdx index 11160ea49..6c8639d31 100644 --- a/docs/developer-docs/6.x/reference/admin/form.mdx +++ b/docs/developer-docs/6.x/reference/admin/form.mdx @@ -4,8 +4,8 @@ title: Form description: "Form primitives: Bind, Form, useForm, validation" --- -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; +import {Alert} from "@/components/Alert"; +import {SymbolList} from "@/components/SymbolList"; @@ -20,36 +20,15 @@ This page documents everything exported from `webiny/admin/form`. Import any of **Components** - + **Hooks** - + **Types** - + **Other** @@ -79,9 +58,9 @@ import { Form } from "webiny/admin/form"; ```typescript export const Form = observer( - React.forwardRef(FormInner) as ( - props: FormProps & { ref?: React.ForwardedRef } - ) => ReturnType> + React.forwardRef(FormInner) as ( + props: FormProps & { ref?: React.ForwardedRef } + ) => ReturnType> ); ``` @@ -157,10 +136,10 @@ import { ValidationError } from "webiny/admin/form"; ```typescript class ValidationError extends Error { - public override readonly message: string; - public readonly validator: string | null; - public readonly value: any; - constructor(message = "", validator: string | null = null, value: string | null = null); + public override readonly message: string; + public readonly validator: string | null; + public readonly value: any; + constructor(message = "", validator: string | null = null, value: string | null = null); } ``` @@ -188,7 +167,7 @@ export const useBind = makeDecoratable((props: BindComponentProps): UseBindHook useEffect(() => { form.registerField(fieldProps); - + ``` ### `useBindPrefix` @@ -200,7 +179,7 @@ import { useBindPrefix } from "webiny/admin/form"; ``` ```typescript -export function useBindPrefix(); +export function useBindPrefix() ``` ### `useForm` @@ -213,11 +192,11 @@ import { useForm } from "webiny/admin/form"; ```typescript export const useForm = () => { - const context = useContext(FormContext) as FormAPI; - if (!context) { - throw new Error("Missing Form component in the component hierarchy!"); - } - return context; + const context = useContext(FormContext) as FormAPI; + if (!context) { + throw new Error("Missing Form component in the component hierarchy!"); + } + return context; }; ``` @@ -236,7 +215,7 @@ import { useGenerateSlug } from "webiny/admin/form"; ``` ```typescript -export function useGenerateSlug(form: FormAPI, from: string, to = "slug"); +export function useGenerateSlug(form: FormAPI, from: string, to = "slug") ``` ## Types @@ -263,7 +242,7 @@ import type { FormOnSubmit } from "webiny/admin/form"; ```typescript export interface FormOnSubmit { - (data: T, form: FormAPI): any; + (data: T, form: FormAPI): any; } ``` @@ -277,7 +256,7 @@ import type { GenericFormData } from "webiny/admin/form"; ```typescript export type GenericFormData = { - [key: string]: any; + [key: string]: any; }; ``` diff --git a/docs/developer-docs/6.x/reference/admin/graphqlClient.ai.txt b/docs/developer-docs/6.x/reference/admin/graphqlClient.ai.txt deleted file mode 100644 index f403fce26..000000000 --- a/docs/developer-docs/6.x/reference/admin/graphqlClient.ai.txt +++ /dev/null @@ -1,25 +0,0 @@ -AI Context: GraphQL Client (reference/admin/graphqlClient.mdx) - -Source of Information: -1. packages/webiny/src/admin/graphqlClient.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/app/src/features/graphqlClient/abstractions.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -GraphQLClient - -Import Path: webiny/admin/graphqlClient - -Related Documents: -- docs/developer-docs/6.0.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.0.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/graphqlClient.mdx b/docs/developer-docs/6.x/reference/admin/graphqlClient.mdx deleted file mode 100644 index 26db5c331..000000000 --- a/docs/developer-docs/6.x/reference/admin/graphqlClient.mdx +++ /dev/null @@ -1,67 +0,0 @@ ---- -id: ywrtaw4v -title: GraphQL Client -description: "GraphQL client hooks and utilities" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/graphqlClient`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/graphqlClient`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `GraphQLClient` - -**Abstraction** — imported from `webiny/admin/graphqlClient` - -```typescript -import { GraphQLClient } from "webiny/admin/graphqlClient"; -``` - -**Interface `GraphQLClient.Interface`:** - -```typescript -interface GraphQLClient.Interface { - execute(params: GraphQLRequest): Promise; -} -``` - -**Types:** - -```typescript -namespace GraphQLClient { - type Headers = IHeaders; - type Interface = IGraphQLClient; - type Request = GraphQLRequest; -} -``` - -**Usage:** - -```typescript -// extensions/MyImpl.ts -import { GraphQLClient } from "webiny/admin/graphqlClient"; - -class MyImpl implements MyUseCase.Interface { - public constructor(private graphQLClient: GraphQLClient.Interface) {} - - public async execute(/* ... */): Promise { - await this.graphQLClient.execute(/* ... */); - } -} - -export default MyUseCase.createImplementation({ - implementation: MyImpl, - dependencies: [GraphQLClient] -}); -``` diff --git a/docs/developer-docs/6.x/reference/admin/lexical.mdx b/docs/developer-docs/6.x/reference/admin/lexical.mdx index ba297b811..47c2c2429 100644 --- a/docs/developer-docs/6.x/reference/admin/lexical.mdx +++ b/docs/developer-docs/6.x/reference/admin/lexical.mdx @@ -72,6 +72,7 @@ export declare class LexicalNode { config: Config ): StaticNodeConfigRecord; afterCloneFrom(prevNode: this): void; + resetOnCopyNodeFrom(originalNode: this): void; static importDOM?: () => DOMConversionMap | null; constructor(key?: NodeKey); getType(): string; diff --git a/docs/developer-docs/6.x/reference/admin/localStorage.ai.txt b/docs/developer-docs/6.x/reference/admin/localStorage.ai.txt deleted file mode 100644 index 28fe2bb45..000000000 --- a/docs/developer-docs/6.x/reference/admin/localStorage.ai.txt +++ /dev/null @@ -1,26 +0,0 @@ -AI Context: Local Storage (reference/admin/localStorage.mdx) - -Source of Information: -1. packages/webiny/src/admin/localStorage.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/app/src/features/localStorage/abstractions.ts — originating source -3. /Users/adrian/dev/wby-next/packages/app/src/presentation/localStorage/index.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -LocalStorage, useLocalStorage, useLocalStorageValue, useLocalStorageValues - -Import Path: webiny/admin/localStorage - -Related Documents: -- docs/developer-docs/6.0.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.0.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/localStorage.mdx b/docs/developer-docs/6.x/reference/admin/localStorage.mdx deleted file mode 100644 index 728d3800e..000000000 --- a/docs/developer-docs/6.x/reference/admin/localStorage.mdx +++ /dev/null @@ -1,84 +0,0 @@ ---- -id: ywrtaw4v -title: Local Storage -description: "Local storage abstraction and hooks" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/localStorage`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/localStorage`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `LocalStorage` - -**Constant** — imported from `webiny/admin/localStorage` - -```typescript -import { LocalStorage } from "webiny/admin/localStorage"; -``` - -```typescript -export const LocalStorage = new Abstraction("LocalStorage"); -``` - -## `useLocalStorage` - -**Function** — imported from `webiny/admin/localStorage` - -Returns the LocalStorage instance from DI. -Useful when you want to call service methods imperatively inside components. - -```typescript -import { useLocalStorage } from "webiny/admin/localStorage"; -``` - -```typescript -export function useLocalStorage(): LocalStorage.Interface; -``` - -## `useLocalStorageValue` - -**Function** — imported from `webiny/admin/localStorage` - -```typescript -import { useLocalStorageValue } from "webiny/admin/localStorage"; -``` - -```typescript -export function useLocalStorageValue(key: string): T | undefined; -``` - -## `useLocalStorageValues` - -**Function** — imported from `webiny/admin/localStorage` - -Observes multiple keys in LocalStorage and returns an object of { key: value }. -Re-renders when any of the observed keys change. - -```typescript -import { useLocalStorageValues } from "webiny/admin/localStorage"; -``` - -```typescript -export function useLocalStorageValues>( - keys: (keyof T & string)[] -): Partial; -``` diff --git a/docs/developer-docs/6.x/reference/admin/router.mdx b/docs/developer-docs/6.x/reference/admin/router.mdx index 231cc1977..0088fe55f 100644 --- a/docs/developer-docs/6.x/reference/admin/router.mdx +++ b/docs/developer-docs/6.x/reference/admin/router.mdx @@ -4,8 +4,8 @@ title: Router description: "Router components and hooks" --- -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; +import {Alert} from "@/components/Alert"; +import {SymbolList} from "@/components/SymbolList"; @@ -24,12 +24,7 @@ This page documents everything exported from `webiny/admin/router`. Import any o **Hooks** - + ## Components @@ -43,15 +38,15 @@ import { Route } from "webiny/admin/router"; ```typescript export class Route { - private readonly route: RouteParams; - private readonly schema: TParams extends RouteParamsDefinition - ? RouteParamsInfer - : undefined; - constructor(route: RouteParams); - get name(); - get path(); - get params(): TParams extends RouteParamsDefinition ? RouteParamsInfer : undefined; - private coerceParams>(shape: T); + private readonly route: RouteParams; + private readonly schema: TParams extends RouteParamsDefinition + ? RouteParamsInfer + : undefined; + constructor(route: RouteParams); + get name(); + get path(); + get params(): TParams extends RouteParamsDefinition ? RouteParamsInfer : undefined; + private coerceParams>(shape: T); } ``` @@ -67,9 +62,9 @@ import { useRoute } from "webiny/admin/router"; ```typescript export function useRoute( - // eslint-disable-next-line @typescript-eslint/no-unused-vars - route?: Route -); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + route?: Route +) ``` ### `useRouter` diff --git a/docs/developer-docs/6.x/reference/admin/ui.ai.txt b/docs/developer-docs/6.x/reference/admin/ui.ai.txt index ccea00fe3..dc6f5ba94 100644 --- a/docs/developer-docs/6.x/reference/admin/ui.ai.txt +++ b/docs/developer-docs/6.x/reference/admin/ui.ai.txt @@ -60,7 +60,8 @@ Source of Information: 57. /Users/adrian/dev/wby-next/packages/admin-ui/src/Tree/index.ts — originating source 58. /Users/adrian/dev/wby-next/packages/admin-ui/src/Widget/index.ts — originating source 59. /Users/adrian/dev/wby-next/packages/admin-ui/src/hooks/index.ts — originating source -60. /Users/adrian/dev/wby-next/packages/app-admin/src/components/Dialogs/useDialogs.ts — originating source +60. /Users/adrian/dev/wby-next/packages/app-admin/src/hooks/useHotkeys.ts — originating source +61. /Users/adrian/dev/wby-next/packages/app-admin/src/components/Dialogs/useDialogs.ts — originating source Key Documentation Decisions: - This file is auto-generated by scripts/generate-reference.ts — do not edit manually @@ -69,7 +70,7 @@ Key Documentation Decisions: - Type-only exports are labeled as "Type"; namespace exports include member listings Exported Symbols: -Accordion, Alert, AutoComplete, Avatar, Button, CopyButton, IconButton, Card, Checkbox, CheckboxGroup, CodeEditor, ColorPicker, CloneIcon, CreateIcon, DataList, DataListModal, DataListWithSections, DeleteIcon, DownloadIcon, EditIcon, FilterIcon, ListIcon, LoginIcon, NextPageIcon, OptionsIcon, PreviousPageIcon, RefreshIcon, SortIcon, UploadIcon, DataTable, DelayedOnChange, Dialog, Drawer, DropdownMenu, DynamicFieldset, FilePicker, Grid, HeaderBar, Heading, Icon, IconPicker, Image, Input, Label, Link, List, Loader, OverlayLoader, MultiAutoComplete, MultiFilePicker, Portal, Popover, ProgressBar, Radio, RadioGroup, RangeSlider, Scrollbar, ScrollArea, ScrollBar, SegmentedControl, Select, Separator, Sidebar, SidebarProvider, useSidebar, Skeleton, Slider, SteppedProgress, Switch, Table, Tabs, Tag, Tags, Text, Textarea, TimeAgo, Toast, useToast, Tooltip, Tree, Widget, useDisclosure, useDialogs +Accordion, Alert, AutoComplete, Avatar, Button, CopyButton, IconButton, Card, Checkbox, CheckboxGroup, CodeEditor, ColorPicker, CloneIcon, CreateIcon, DataList, DataListModal, DataListWithSections, DeleteIcon, DownloadIcon, EditIcon, FilterIcon, ListIcon, LoginIcon, NextPageIcon, OptionsIcon, PreviousPageIcon, RefreshIcon, SortIcon, UploadIcon, DataTable, DelayedOnChange, Dialog, Drawer, DropdownMenu, DynamicFieldset, FilePicker, Grid, HeaderBar, Heading, Icon, IconPicker, Image, Input, Label, Link, List, Loader, OverlayLoader, MultiAutoComplete, MultiFilePicker, Portal, Popover, ProgressBar, Radio, RadioGroup, RangeSlider, Scrollbar, ScrollArea, ScrollBar, SegmentedControl, Select, Separator, Sidebar, SidebarProvider, useSidebar, Skeleton, Slider, SteppedProgress, Switch, Table, Tabs, Tag, Tags, Text, Textarea, TimeAgo, Toast, useToast, Tooltip, Tree, Widget, useDisclosure, useHotkeys, useDialogs Import Path: webiny/admin/ui diff --git a/docs/developer-docs/6.x/reference/admin/ui.mdx b/docs/developer-docs/6.x/reference/admin/ui.mdx index b15da94de..a58f3814a 100644 --- a/docs/developer-docs/6.x/reference/admin/ui.mdx +++ b/docs/developer-docs/6.x/reference/admin/ui.mdx @@ -110,6 +110,7 @@ This page documents everything exported from `webiny/admin/ui`. Import any of th symbols={[ { name: "useDialogs", anchor: "use-dialogs" }, { name: "useDisclosure", anchor: "use-disclosure" }, + { name: "useHotkeys", anchor: "use-hotkeys" }, { name: "useSidebar", anchor: "use-sidebar" }, { name: "useToast", anchor: "use-toast" } ]} @@ -1398,6 +1399,18 @@ export const useDisclosure = (isOpenDefault = false) => { ``` +### `useHotkeys` + +**Function** — imported from `webiny/admin/ui` + +```typescript +import { useHotkeys } from "webiny/admin/ui"; +``` + +```typescript +export function useHotkeys(props: HookProps); +``` + ### `useSidebar` **Function** — imported from `webiny/admin/ui` diff --git a/docs/developer-docs/6.x/reference/admin/website-builder.ai.txt b/docs/developer-docs/6.x/reference/admin/website-builder.ai.txt index 2b1b16a41..091ef3891 100644 --- a/docs/developer-docs/6.x/reference/admin/website-builder.ai.txt +++ b/docs/developer-docs/6.x/reference/admin/website-builder.ai.txt @@ -4,6 +4,7 @@ Source of Information: 1. packages/webiny/src/admin/website-builder.ts — barrel re-export file 2. /Users/adrian/dev/wby-next/packages/app-website-builder/src/routes.ts — originating source 3. /Users/adrian/dev/wby-next/packages/app-website-builder/src/index.ts — originating source +4. /Users/adrian/dev/wby-next/packages/app-website-builder/src/presentation/security/usePermissions.ts — originating source Key Documentation Decisions: - This file is auto-generated by scripts/generate-reference.ts — do not edit manually @@ -12,7 +13,7 @@ Key Documentation Decisions: - Type-only exports are labeled as "Type"; namespace exports include member listings Exported Symbols: -Routes, pagePathFromTitle +Routes, pagePathFromTitle, usePermissions Import Path: webiny/admin/website-builder diff --git a/docs/developer-docs/6.x/reference/admin/website-builder.mdx b/docs/developer-docs/6.x/reference/admin/website-builder.mdx index 56a8de27d..29d4d8449 100644 --- a/docs/developer-docs/6.x/reference/admin/website-builder.mdx +++ b/docs/developer-docs/6.x/reference/admin/website-builder.mdx @@ -22,6 +22,10 @@ This page documents everything exported from `webiny/admin/website-builder`. Imp +**Hooks** + + + **Other** @@ -53,6 +57,20 @@ export const Routes = { ``` +## Hooks + +### `usePermissions` + +**Constant** — imported from `webiny/admin/website-builder` + +```typescript +import { usePermissions } from "webiny/admin/website-builder"; +``` + +```typescript +export const usePermissions = createUsePermissions(WB_PERMISSIONS_SCHEMA); +``` + ## Other ### `pagePathFromTitle` diff --git a/docs/developer-docs/6.x/reference/admin/website-builder/page/editor.ai.txt b/docs/developer-docs/6.x/reference/admin/website-builder/page/editor.ai.txt index 24be056d3..cee1488cb 100644 --- a/docs/developer-docs/6.x/reference/admin/website-builder/page/editor.ai.txt +++ b/docs/developer-docs/6.x/reference/admin/website-builder/page/editor.ai.txt @@ -2,7 +2,22 @@ AI Context: Editor (reference/admin/website-builder/page/editor.mdx) Source of Information: 1. packages/webiny/src/admin/website-builder/page/editor.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/app-website-builder/src/index.ts — originating source +2. /Users/adrian/dev/wby-next/packages/app-website-builder/src/modules/pages/PageEditor/usePageEditorConfig.ts — originating source +3. /Users/adrian/dev/wby-next/packages/app-website-builder/src/editorSdk/createCommand.ts — originating source +4. /Users/adrian/dev/wby-next/packages/app-website-builder/src/BaseEditor/hooks/useSelectFromEditor.ts — originating source +5. /Users/adrian/dev/wby-next/packages/app-website-builder/src/BaseEditor/hooks/useSelectFromDocument.ts — originating source +6. /Users/adrian/dev/wby-next/packages/app-website-builder/src/DocumentEditor/index.ts — originating source +7. /Users/adrian/dev/wby-next/packages/app-website-builder/src/BaseEditor/hooks/useActiveElement.ts — originating source +8. /Users/adrian/dev/wby-next/packages/app-website-builder/src/BaseEditor/hooks/useHighlightedElement.ts — originating source +9. /Users/adrian/dev/wby-next/packages/app-website-builder/src/BaseEditor/hooks/useComponent.ts — originating source +10. /Users/adrian/dev/wby-next/packages/app-website-builder/src/BaseEditor/hooks/useElementInputs.ts — originating source +11. /Users/adrian/dev/wby-next/packages/app-website-builder/src/BaseEditor/hooks/useCreateElement.ts — originating source +12. /Users/adrian/dev/wby-next/packages/app-website-builder/src/BaseEditor/hooks/useDeleteElement.ts — originating source +13. /Users/adrian/dev/wby-next/packages/app-website-builder/src/BaseEditor/hooks/useUpdateElement.ts — originating source +14. /Users/adrian/dev/wby-next/packages/app-website-builder/src/BaseEditor/hooks/useElementOverlay.ts — originating source +15. /Users/adrian/dev/wby-next/packages/app-website-builder/src/BaseEditor/defaultConfig/Content/Preview/useElementComponentManifest.ts — originating source +16. /Users/adrian/dev/wby-next/packages/app-website-builder/src/editorSdk/utils/index.ts — originating source +17. /Users/adrian/dev/wby-next/packages/website-builder-sdk/src/index.ts — originating source Key Documentation Decisions: - This file is auto-generated by scripts/generate-reference.ts — do not edit manually @@ -11,7 +26,7 @@ Key Documentation Decisions: - Type-only exports are labeled as "Type"; namespace exports include member listings Exported Symbols: -Editor, PageEditorConfig +usePageEditorConfig, createCommand, useSelectFromEditor, useSelectFromDocument, useDocumentEditor, useActiveElement, useHighlightedElement, useComponent, useElementInputs, useCreateElement, useDeleteElement, useUpdateElement, useElementOverlay, useElementComponentManifest, $selectElement, $deselectElement, $highlightElement, $getElementById, $getActiveElementId, $getComponentManifestByElementId, $deleteElement, $createElement, $moveElement, $removeElementReferenceFromParent, $addElementReferenceToParent, $getElementsOfType, $getFirstElementOfType, $getElementInputValues, $updateElementInputs, $previewElementInputs, createElement Import Path: webiny/admin/website-builder/page/editor diff --git a/docs/developer-docs/6.x/reference/admin/website-builder/page/editor.mdx b/docs/developer-docs/6.x/reference/admin/website-builder/page/editor.mdx index 0b4f824d7..f7c737591 100644 --- a/docs/developer-docs/6.x/reference/admin/website-builder/page/editor.mdx +++ b/docs/developer-docs/6.x/reference/admin/website-builder/page/editor.mdx @@ -18,41 +18,519 @@ import { SymbolList } from "@/components/SymbolList"; This page documents everything exported from `webiny/admin/website-builder/page/editor`. Import any of the items below directly from this path in your Webiny extensions. -**Components** +**Hooks** - + **Other** - + -## Components +## Hooks -### `PageEditorConfig` +### `useActiveElement` **Constant** — imported from `webiny/admin/website-builder/page/editor` ```typescript -import { PageEditorConfig } from "webiny/admin/website-builder/page/editor"; +import { useActiveElement } from "webiny/admin/website-builder/page/editor"; ``` ```typescript -export const PageEditorConfig = Object.assign(BasePageEditorConfig, EditorConfig); +export const useActiveElement = () => { + const [activeElement, setActiveElement] = useState(null); + const editor = useDocumentEditor(); + + useEffect(() => { + return autorun(() => { + const editorState = editor.getEditorState().read(); + const documentState = editor.getDocumentState().read(); + + const activeElementId = editorState +``` + +### `useComponent` + +**Constant** — imported from `webiny/admin/website-builder/page/editor` + +```typescript +import { useComponent } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export const useComponent = (name: string) => { + const selector = useCallback((state: EditorState) => state.components[name], [name]); + + return useSelectFromEditor(selector, [name]); +}; +``` + +### `useCreateElement` + +**Function** — imported from `webiny/admin/website-builder/page/editor` + +```typescript +import { useCreateElement } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export function useCreateElement(); +``` + +### `useDeleteElement` + +**Function** — imported from `webiny/admin/website-builder/page/editor` + +```typescript +import { useDeleteElement } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export function useDeleteElement(); +``` + +### `useDocumentEditor` + +**Function** — imported from `webiny/admin/website-builder/page/editor` + +```typescript +import { useDocumentEditor } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export function useDocumentEditor(); +``` + +### `useElementComponentManifest` + +**Constant** — imported from `webiny/admin/website-builder/page/editor` + +```typescript +import { useElementComponentManifest } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export const useElementComponentManifest = (elementId: string) => { + const editor = useDocumentEditor(); + const document = editor.getDocumentState().read(); + const componentName = document.elements[elementId]?.component.name; + + return useSelectFromEditor( + state => { + return state.components[componentName]; + }, + [componentName] + ); +}; +``` + +### `useElementInputs` + +**Function** — imported from `webiny/admin/website-builder/page/editor` + +Returns the resolved input values for the given element, plus an updater callback. + +@param elementId The element whose inputs to resolve (null returns {}). +@param depth How many levels of slot children to resolve (default 0). + +```typescript +import { useElementInputs } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export function useElementInputs = Record>( + elementId: string | null, + depth = 0 +); +``` + +### `useHighlightedElement` + +**Constant** — imported from `webiny/admin/website-builder/page/editor` + +```typescript +import { useHighlightedElement } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export const useHighlightedElement = () => { + const [highlightedElement, setHighlightedElement] = useState(null); + const editor = useDocumentEditor(); + + useEffect(() => { + return autorun(() => { + const editorState = editor.getEditorState().read(); + const documentState = editor.getDocumentState().read(); + + const elementId = ed +``` + +### `usePageEditorConfig` + +**Constant** — imported from `webiny/admin/website-builder/page/editor` + +```typescript +import { usePageEditorConfig } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export const usePageEditorConfig = (): PageEditorConfig => { + const config = useEditorConfig(); + + return { + ...config, + pageSettings: { + groups: config.pageSettings.groups ?? [], + viewMode: config.pageSettings.viewMode ?? "dialog" + } + }; +}; +``` + +### `useSelectFromDocument` + +**Function** — imported from `webiny/admin/website-builder/page/editor` + +Subscribe to part of the document state. +@param selector Pick the slice of state you care about. +@param equals (optional) comparator, defaults to Object.is + +```typescript +import { useSelectFromDocument } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export function useSelectFromDocument( + selector: (doc: TDocument) => TReturn, + deps: React.DependencyList = [], + equals: Equals = deepEqual +): TReturn; +``` + +### `useSelectFromEditor` + +**Function** — imported from `webiny/admin/website-builder/page/editor` + +Subscribe to part of the document state. +@param selector Pick the slice of state you care about. +@param equals (optional) comparator, defaults to Object.is + +```typescript +import { useSelectFromEditor } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export function useSelectFromEditor( + selector: (doc: EditorState) => T, + deps: React.DependencyList = [], + equals: Equals = deepEqual +): T; +``` + +### `useUpdateElement` + +**Function** — imported from `webiny/admin/website-builder/page/editor` + +```typescript +import { useUpdateElement } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export function useUpdateElement(); ``` ## Other -### `Editor` +### `$addElementReferenceToParent` -**Export** — imported from `webiny/admin/website-builder/page/editor` +**Function** — imported from `webiny/admin/website-builder/page/editor` + +```typescript +import { $addElementReferenceToParent } from "webiny/admin/website-builder/page/editor"; +``` ```typescript -import { Editor } from "webiny/admin/website-builder/page/editor"; +export function $addElementReferenceToParent( + document: Document, ``` +### `$createElement` + +**Function** — imported from `webiny/admin/website-builder/page/editor` + +```typescript +import { $createElement } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export function $createElement( + editor: Editor, + payload: CommandPayload +): ConstraintResult | undefined; +``` + +### `$deleteElement` + +**Function** — imported from `webiny/admin/website-builder/page/editor` + +```typescript +import { $deleteElement } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export function $deleteElement(editor: Editor, id: string, ignoreConstraints = false); +``` + +### `$deselectElement` + +**Function** — imported from `webiny/admin/website-builder/page/editor` + +```typescript +import { $deselectElement } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export function $deselectElement(editor: Editor); +``` + +### `$getActiveElementId` + +**Function** — imported from `webiny/admin/website-builder/page/editor` + +```typescript +import { $getActiveElementId } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export function $getActiveElementId(editor: Editor); +``` + +### `$getComponentManifestByElementId` + +**Function** — imported from `webiny/admin/website-builder/page/editor` + +```typescript +import { $getComponentManifestByElementId } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export function $getComponentManifestByElementId( + editor: Editor, + id: string +): ComponentManifest | undefined; +``` + +### `$getElementById` + +**Function** — imported from `webiny/admin/website-builder/page/editor` + +```typescript +import { $getElementById } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export function $getElementById(document: Document, id: string); +``` + +### `$getElementInputValues` + +**Function** — imported from `webiny/admin/website-builder/page/editor` + +```typescript +import { $getElementInputValues } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export function $getElementInputValues( + document: Document, + components: Record, + elementId: string | null, + depth = 0 +); +``` + +### `$getElementsOfType` + +**Function** — imported from `webiny/admin/website-builder/page/editor` + +```typescript +import { $getElementsOfType } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export function $getElementsOfType(document: Document, componentName: string); +``` + +### `$getFirstElementOfType` + +**Function** — imported from `webiny/admin/website-builder/page/editor` + +```typescript +import { $getFirstElementOfType } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export function $getFirstElementOfType(document: Document, componentName: string); +``` + +### `$highlightElement` + +**Function** — imported from `webiny/admin/website-builder/page/editor` + +```typescript +import { $highlightElement } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export function $highlightElement(editor: Editor, id: string | null); +``` + +### `$moveElement` + +**Function** — imported from `webiny/admin/website-builder/page/editor` + +```typescript +import { $moveElement } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export function $moveElement(document: Document, params: MoveParams): ConstraintResult | undefined; +``` + +### `$previewElementInputs` + +**Function** — imported from `webiny/admin/website-builder/page/editor` + +Programmatically update an element's inputs in the preview iframe only (via JSON patch). +Does NOT write to the editor document state. + +```typescript +import { $previewElementInputs } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export function $previewElementInputs( + editor: Editor, + elementId: string, + updater: (inputs: Record) => void +): void; +``` + +### `$removeElementReferenceFromParent` + +**Function** — imported from `webiny/admin/website-builder/page/editor` + +```typescript +import { $removeElementReferenceFromParent } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export function $removeElementReferenceFromParent( + document: Document, +``` + +### `$selectElement` + +**Function** — imported from `webiny/admin/website-builder/page/editor` + +```typescript +import { $selectElement } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export function $selectElement(editor: Editor, id: string | null); +``` + +### `$updateElementInputs` + +**Function** — imported from `webiny/admin/website-builder/page/editor` + +Programmatically update an element's inputs using a callback-based API. +The updater receives a deep object representation of the element's inputs +which can be mutated in place. + +```typescript +import { $updateElementInputs } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export function $updateElementInputs( + editor: Editor, + elementId: string, + updater: (inputs: Record) => void +): void; +``` + +### `createCommand` + +**Function** — imported from `webiny/admin/website-builder/page/editor` + +```typescript +import { createCommand } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export function createCommand(type: string): Command; +``` + +### `createElement` + +**Constant** — imported from `webiny/admin/website-builder/page/editor` + +```typescript +import { createElement } from "webiny/admin/website-builder/page/editor"; +``` + +```typescript +export const createElement = (params: CreateElementParams) => { + return { + action: "CreateElement", + params + }; +}; +``` + +### `useElementOverlay` + +**Export** — imported from `webiny/admin/website-builder/page/editor` + ```typescript -export { DefaultEditorConfig } from "./defaultConfig/DefaultEditorConfig.js"; -export * from "./config/index.js"; -export * from "./commands.js"; -export type { ElementInputRendererProps } from "./config/ElementInput.js"; +import { useElementOverlay } from "webiny/admin/website-builder/page/editor"; ``` diff --git a/docs/developer-docs/6.x/reference/api/aco/flp.ai.txt b/docs/developer-docs/6.x/reference/api/aco/flp.ai.txt new file mode 100644 index 000000000..0c200c38d --- /dev/null +++ b/docs/developer-docs/6.x/reference/api/aco/flp.ai.txt @@ -0,0 +1,29 @@ +AI Context: Flp (reference/api/aco/flp.mdx) + +Source of Information: +1. packages/webiny/src/api/aco/flp.ts — barrel re-export file +2. /Users/adrian/dev/wby-next/packages/api-aco/src/features/flp/CreateFlp/abstractions.ts — originating source +3. /Users/adrian/dev/wby-next/packages/api-aco/src/features/flp/DeleteFlp/abstractions.ts — originating source +4. /Users/adrian/dev/wby-next/packages/api-aco/src/features/flp/GetFlp/abstractions.ts — originating source +5. /Users/adrian/dev/wby-next/packages/api-aco/src/features/flp/ListFlps/abstractions.ts — originating source +6. /Users/adrian/dev/wby-next/packages/api-aco/src/features/flp/UpdateFlp/abstractions.ts — originating source + +Key Documentation Decisions: +- This file is auto-generated by scripts/generate-reference.ts — do not edit manually +- Symbols are documented in the order they appear in the barrel file +- Declaration text is extracted from the TypeScript AST; method bodies are stripped +- Type-only exports are labeled as "Type"; namespace exports include member listings + +Exported Symbols: +CreateFlpUseCase, DeleteFlpUseCase, GetFlpUseCase, ListFlpsUseCase, UpdateFlpUseCase + +Import Path: webiny/api/aco/flp + +Related Documents: +- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions +- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns + +Tone Guidelines: +- This is a reference page — terse, API-focused, no prose beyond what's necessary +- Code blocks are the primary content; descriptions serve only to clarify intent +- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/aco/flp.mdx b/docs/developer-docs/6.x/reference/api/aco/flp.mdx new file mode 100644 index 000000000..2fbec9831 --- /dev/null +++ b/docs/developer-docs/6.x/reference/api/aco/flp.mdx @@ -0,0 +1,149 @@ +--- +id: yxbpl2fj +title: Flp +description: "Reference for webiny/api/aco/flp" +--- + +import { Alert } from "@/components/Alert"; +import { SymbolList } from "@/components/SymbolList"; + + + +- What use cases are available in `webiny/api/aco/flp`? +- How to import and use each exported item? + + + +## Overview + +This page documents everything exported from `webiny/api/aco/flp`. Import any of the items below directly from this path in your Webiny extensions. + + + +## `CreateFlpUseCase` + +**Use Case Abstraction** — imported from `webiny/api/aco/flp` + +```typescript +import { CreateFlpUseCase } from "webiny/api/aco/flp"; +``` + +**Interface `CreateFlpUseCase.Interface`:** + +```typescript +interface CreateFlpUseCase.Interface { + execute: (folder: Folder) => Promise; +} +``` + +**Types:** + +```typescript +namespace CreateFlpUseCase { + type Interface = ICreateFlpUseCase; +} +``` + +## `DeleteFlpUseCase` + +**Use Case Abstraction** — imported from `webiny/api/aco/flp` + +```typescript +import { DeleteFlpUseCase } from "webiny/api/aco/flp"; +``` + +**Interface `DeleteFlpUseCase.Interface`:** + +```typescript +interface DeleteFlpUseCase.Interface { + execute: (folder: Folder) => Promise; +} +``` + +**Types:** + +```typescript +namespace DeleteFlpUseCase { + type Interface = IDeleteFlpUseCase; +} +``` + +## `GetFlpUseCase` + +**Use Case Abstraction** — imported from `webiny/api/aco/flp` + +```typescript +import { GetFlpUseCase } from "webiny/api/aco/flp"; +``` + +**Interface `GetFlpUseCase.Interface`:** + +```typescript +interface GetFlpUseCase.Interface { + execute: (id: string) => Promise; +} +``` + +**Types:** + +```typescript +namespace GetFlpUseCase { + type Interface = IGetFolderPermission; +} +``` + +## `ListFlpsUseCase` + +**Use Case Abstraction** — imported from `webiny/api/aco/flp` + +```typescript +import { ListFlpsUseCase } from "webiny/api/aco/flp"; +``` + +**Interface `ListFlpsUseCase.Interface`:** + +```typescript +interface ListFlpsUseCase.Interface { + execute: (params: ListFlpsParams) => Promise; +} +``` + +**Types:** + +```typescript +namespace ListFlpsUseCase { + type Interface = IListFlps; +} +``` + +## `UpdateFlpUseCase` + +**Use Case Abstraction** — imported from `webiny/api/aco/flp` + +```typescript +import { UpdateFlpUseCase } from "webiny/api/aco/flp"; +``` + +**Interface `UpdateFlpUseCase.Interface`:** + +```typescript +interface UpdateFlpUseCase.Interface { + execute: (params: UpdateFlpParams) => Promise; +} +``` + +**Types:** + +```typescript +namespace UpdateFlpUseCase { + type Interface = IUpdateFlpUseCase; +} +``` diff --git a/docs/developer-docs/6.x/reference/admin/cms/fieldRenderers/object.ai.txt b/docs/developer-docs/6.x/reference/api/aco/folder.ai.txt similarity index 51% rename from docs/developer-docs/6.x/reference/admin/cms/fieldRenderers/object.ai.txt rename to docs/developer-docs/6.x/reference/api/aco/folder.ai.txt index fcd502b81..0493c4bbb 100644 --- a/docs/developer-docs/6.x/reference/admin/cms/fieldRenderers/object.ai.txt +++ b/docs/developer-docs/6.x/reference/api/aco/folder.ai.txt @@ -1,8 +1,9 @@ -AI Context: Object (reference/admin/cms/fieldRenderers/object.mdx) +AI Context: Folder (reference/api/aco/folder.mdx) Source of Information: -1. packages/webiny/src/admin/cms/fieldRenderers/object.ts — barrel re-export file - +1. packages/webiny/src/api/aco/folder.ts — barrel re-export file +2. /Users/adrian/dev/wby-next/packages/api-aco/src/features/folder/ListFolderLevelPermissionsTargets/abstractions.ts — originating source +3. /Users/adrian/dev/wby-next/packages/api-aco/src/features/folder/shared/abstractions.ts — originating source Key Documentation Decisions: - This file is auto-generated by scripts/generate-reference.ts — do not edit manually @@ -11,13 +12,13 @@ Key Documentation Decisions: - Type-only exports are labeled as "Type"; namespace exports include member listings Exported Symbols: +ListFolderLevelPermissionsTargetsUseCase, FilterStorageOperations - -Import Path: webiny/admin/cms/fieldRenderers/object +Import Path: webiny/api/aco/folder Related Documents: -- docs/developer-docs/6.0.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.0.x/basic/result.mdx — Result type used in use case returns +- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions +- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns Tone Guidelines: - This is a reference page — terse, API-focused, no prose beyond what's necessary diff --git a/docs/developer-docs/6.x/reference/api/aco/folder.mdx b/docs/developer-docs/6.x/reference/api/aco/folder.mdx new file mode 100644 index 000000000..77526fb1a --- /dev/null +++ b/docs/developer-docs/6.x/reference/api/aco/folder.mdx @@ -0,0 +1,83 @@ +--- +id: yxbpl2fj +title: Folder +description: "Reference for webiny/api/aco/folder" +--- + +import { Alert } from "@/components/Alert"; +import { SymbolList } from "@/components/SymbolList"; + + + +- What use cases are available in `webiny/api/aco/folder`? +- How to import and use each exported item? + + + +## Overview + +This page documents everything exported from `webiny/api/aco/folder`. Import any of the items below directly from this path in your Webiny extensions. + +**Use Cases** + + + +**Services** + + + +## Use Cases + +### `ListFolderLevelPermissionsTargetsUseCase` + +**Use Case Abstraction** — imported from `webiny/api/aco/folder` + +```typescript +import { ListFolderLevelPermissionsTargetsUseCase } from "webiny/api/aco/folder"; +``` + +**Interface `ListFolderLevelPermissionsTargetsUseCase.Interface`:** + +```typescript +interface ListFolderLevelPermissionsTargetsUseCase.Interface { + execute: () => Promise< + Result<[FolderLevelPermissionsTarget[], FolderLevelPermissionsTargetListMeta]> + >; +} +``` + +**Types:** + +```typescript +namespace ListFolderLevelPermissionsTargetsUseCase { + type Interface = IListFolderLevelPermissionsTargetsUseCase; + type Return = Promise< + Result<[FolderLevelPermissionsTarget[], FolderLevelPermissionsTargetListMeta]> + >; +} +``` + +## Services + +### `FilterStorageOperations` + +**Abstraction** — imported from `webiny/api/aco/folder` + +```typescript +import { FilterStorageOperations } from "webiny/api/aco/folder"; +``` + +**Types:** + +```typescript +namespace FilterStorageOperations { + type Interface = IAcoStorageOperations["filter"]; +} +``` diff --git a/docs/developer-docs/6.x/reference/api/buildParams.ai.txt b/docs/developer-docs/6.x/reference/api/buildParams.ai.txt deleted file mode 100644 index c27a9c8e8..000000000 --- a/docs/developer-docs/6.x/reference/api/buildParams.ai.txt +++ /dev/null @@ -1,25 +0,0 @@ -AI Context: Build Params (reference/api/buildParams.mdx) - -Source of Information: -1. packages/webiny/src/api/buildParams.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-core/src/features/buildParams/index.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -BuildParam, BuildParams - -Import Path: webiny/api/buildParams - -Related Documents: -- docs/developer-docs/6.0.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.0.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/buildParams.mdx b/docs/developer-docs/6.x/reference/api/buildParams.mdx deleted file mode 100644 index 52e3e79a0..000000000 --- a/docs/developer-docs/6.x/reference/api/buildParams.mdx +++ /dev/null @@ -1,115 +0,0 @@ ---- -id: yxbpl2j1 -title: Build Params -description: "API build parameter types" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/api/buildParams`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/buildParams`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `BuildParam` - -**Abstraction** — imported from `webiny/api/buildParams` - -```typescript -import { BuildParam } from "webiny/api/buildParams"; -``` - -**Interface `BuildParam.Interface`:** - -```typescript -interface BuildParam.Interface { - key: string; - value: any; -} -``` - -**Types:** - -```typescript -namespace BuildParam { - type Interface = IBuildParam; -} -``` - -**Usage:** - -```typescript -// extensions/MyImpl.ts -import { BuildParam } from "webiny/api/buildParams"; - -class MyImpl implements MyUseCase.Interface { - public constructor(private buildParam: BuildParam.Interface) {} - - public async execute(/* ... */): Promise { - this.buildParam.key: string(/* ... */); - } -} - -export default MyUseCase.createImplementation({ - implementation: MyImpl, - dependencies: [BuildParam] -}); -``` - -## `BuildParams` - -**Abstraction** — imported from `webiny/api/buildParams` - -```typescript -import { BuildParams } from "webiny/api/buildParams"; -``` - -**Interface `BuildParams.Interface`:** - -```typescript -interface BuildParams.Interface { - get(key: string): T | null; -} -``` - -**Types:** - -```typescript -namespace BuildParams { - type Interface = IBuildParams; -} -``` - -**Usage:** - -```typescript -// extensions/MyImpl.ts -import { BuildParams } from "webiny/api/buildParams"; - -class MyImpl implements MyUseCase.Interface { - public constructor(private buildParams: BuildParams.Interface) {} - - public async execute(/* ... */): Promise { - this.buildParams.get(/* ... */); - } -} - -export default MyUseCase.createImplementation({ - implementation: MyImpl, - dependencies: [BuildParams] -}); -``` diff --git a/docs/developer-docs/6.x/reference/api/cms/entry.mdx b/docs/developer-docs/6.x/reference/api/cms/entry.mdx index 0c3d74ca9..ddd6af683 100644 --- a/docs/developer-docs/6.x/reference/api/cms/entry.mdx +++ b/docs/developer-docs/6.x/reference/api/cms/entry.mdx @@ -1928,6 +1928,8 @@ export interface CmsEntryValues { **Class** — imported from `webiny/api/cms/entry` +Generate and parse content entry IDs. + ```typescript import { EntryId } from "webiny/api/cms/entry"; ``` diff --git a/docs/developer-docs/6.x/reference/api/cms/model.ai.txt b/docs/developer-docs/6.x/reference/api/cms/model.ai.txt index 612b23d72..db7f2369e 100644 --- a/docs/developer-docs/6.x/reference/api/cms/model.ai.txt +++ b/docs/developer-docs/6.x/reference/api/cms/model.ai.txt @@ -27,7 +27,7 @@ Key Documentation Decisions: - Type-only exports are labeled as "Type"; namespace exports include member listings Exported Symbols: -ModelFactory, ModelBuilder, FieldBuilder, FieldRendererRegistry, FieldType, LayoutBuilder, CmsModel, CmsModelField, CreateModelUseCase, ModelBeforeCreateEventHandler, ModelAfterCreateEventHandler, CreateModelFromUseCase, ModelBeforeCreateFromEventHandler, ModelAfterCreateFromEventHandler, UpdateModelUseCase, ModelBeforeUpdateEventHandler, ModelAfterUpdateEventHandler, DeleteModelUseCase, ModelBeforeDeleteEventHandler, ModelAfterDeleteEventHandler, GetModelUseCase, ListModelsUseCase +ModelFactory, ModelBuilder, DataFieldBuilder, LayoutFieldBuilder, FieldRendererRegistry, FieldType, LayoutBuilder, CmsModel, CmsModelField, CreateModelUseCase, ModelBeforeCreateEventHandler, ModelAfterCreateEventHandler, CreateModelFromUseCase, ModelBeforeCreateFromEventHandler, ModelAfterCreateFromEventHandler, UpdateModelUseCase, ModelBeforeUpdateEventHandler, ModelAfterUpdateEventHandler, DeleteModelUseCase, ModelBeforeDeleteEventHandler, ModelAfterDeleteEventHandler, GetModelUseCase, ListModelsUseCase Import Path: webiny/api/cms/model diff --git a/docs/developer-docs/6.x/reference/api/cms/model.mdx b/docs/developer-docs/6.x/reference/api/cms/model.mdx index 3bd1c5e56..895d83f50 100644 --- a/docs/developer-docs/6.x/reference/api/cms/model.mdx +++ b/docs/developer-docs/6.x/reference/api/cms/model.mdx @@ -63,9 +63,10 @@ This page documents everything exported from `webiny/api/cms/model`. Import any symbols={[ { name: "CmsModel", anchor: "cms-model" }, { name: "CmsModelField", anchor: "cms-model-field" }, - { name: "FieldBuilder", anchor: "field-builder" }, + { name: "DataFieldBuilder", anchor: "data-field-builder" }, { name: "FieldRendererRegistry", anchor: "field-renderer-registry" }, { name: "LayoutBuilder", anchor: "layout-builder" }, + { name: "LayoutFieldBuilder", anchor: "layout-field-builder" }, { name: "ModelBuilder", anchor: "model-builder" } ]} /> @@ -609,7 +610,7 @@ import type { CmsModelField } from "webiny/api/cms/model"; export interface CmsModelField { ... } ``` -### `FieldBuilder` +### `DataFieldBuilder` **Class** — imported from `webiny/api/cms/model` @@ -617,7 +618,7 @@ DataFieldBuilder class for data fields that produce CmsModelField instances. Provides storageId, list, validation, renderer, and other data-field methods. ```typescript -import { FieldBuilder } from "webiny/api/cms/model"; +import { DataFieldBuilder } from "webiny/api/cms/model"; ``` ```typescript @@ -697,6 +698,23 @@ export class LayoutBuilder { } ``` +### `LayoutFieldBuilder` + +**Class** — imported from `webiny/api/cms/model` + +Slim base class for layout fields (separators, alerts, tabs, etc.). +Layout fields only support label, description, help, and note — no list(), storageId(), etc. + +```typescript +import { LayoutFieldBuilder } from "webiny/api/cms/model"; +``` + +```typescript +export abstract class LayoutFieldBuilder< + TType extends string = string +> extends BaseFieldBuilder {} +``` + ### `ModelBuilder` **Class** — imported from `webiny/api/cms/model` diff --git a/docs/developer-docs/6.x/reference/api/keyValueStore.ai.txt b/docs/developer-docs/6.x/reference/api/cms/scheduler.ai.txt similarity index 50% rename from docs/developer-docs/6.x/reference/api/keyValueStore.ai.txt rename to docs/developer-docs/6.x/reference/api/cms/scheduler.ai.txt index dad3eca93..923f13bef 100644 --- a/docs/developer-docs/6.x/reference/api/keyValueStore.ai.txt +++ b/docs/developer-docs/6.x/reference/api/cms/scheduler.ai.txt @@ -1,8 +1,9 @@ -AI Context: Key-Value Store (reference/api/keyValueStore.mdx) +AI Context: Scheduler (reference/api/cms/scheduler.mdx) Source of Information: -1. packages/webiny/src/api/keyValueStore.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-core/src/features/keyValueStore/index.ts — originating source +1. packages/webiny/src/api/cms/scheduler.ts — barrel re-export file +2. /Users/adrian/dev/wby-next/packages/api-headless-cms-scheduler/src/features/SchedulePublishEntryUseCase/abstractions.ts — originating source +3. /Users/adrian/dev/wby-next/packages/api-headless-cms-scheduler/src/features/ScheduleUnpublishEntryUseCase/abstractions.ts — originating source Key Documentation Decisions: - This file is auto-generated by scripts/generate-reference.ts — do not edit manually @@ -11,13 +12,13 @@ Key Documentation Decisions: - Type-only exports are labeled as "Type"; namespace exports include member listings Exported Symbols: -GlobalKeyValueStore, KeyValueStore +SchedulePublishEntryUseCase, ScheduleUnpublishEntryUseCase -Import Path: webiny/api/keyValueStore +Import Path: webiny/api/cms/scheduler Related Documents: -- docs/developer-docs/6.0.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.0.x/basic/result.mdx — Result type used in use case returns +- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions +- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns Tone Guidelines: - This is a reference page — terse, API-focused, no prose beyond what's necessary diff --git a/docs/developer-docs/6.x/reference/api/cms/scheduler.mdx b/docs/developer-docs/6.x/reference/api/cms/scheduler.mdx new file mode 100644 index 000000000..1499b7999 --- /dev/null +++ b/docs/developer-docs/6.x/reference/api/cms/scheduler.mdx @@ -0,0 +1,80 @@ +--- +id: yxbpl2nt +title: Scheduler +description: "Reference for webiny/api/cms/scheduler" +--- + +import { Alert } from "@/components/Alert"; +import { SymbolList } from "@/components/SymbolList"; + + + +- What use cases are available in `webiny/api/cms/scheduler`? +- How to import and use each exported item? + + + +## Overview + +This page documents everything exported from `webiny/api/cms/scheduler`. Import any of the items below directly from this path in your Webiny extensions. + + + +## `SchedulePublishEntryUseCase` + +**Use Case Abstraction** — imported from `webiny/api/cms/scheduler` + +```typescript +import { SchedulePublishEntryUseCase } from "webiny/api/cms/scheduler"; +``` + +**Interface `SchedulePublishEntryUseCase.Interface`:** + +```typescript +interface SchedulePublishEntryUseCase.Interface { + execute(params: ISchedulePublishEntryUseCaseParams): ISchedulePublishEntryUseCaseResponse; +} +``` + +**Types:** + +```typescript +namespace SchedulePublishEntryUseCase { + type Interface = ISchedulePublishEntryUseCase; + type Error = ScheduleActionError; + type Params = ISchedulePublishEntryUseCaseParams; + type Result = ISchedulePublishEntryUseCaseResponse; +} +``` + +## `ScheduleUnpublishEntryUseCase` + +**Use Case Abstraction** — imported from `webiny/api/cms/scheduler` + +```typescript +import { ScheduleUnpublishEntryUseCase } from "webiny/api/cms/scheduler"; +``` + +**Interface `ScheduleUnpublishEntryUseCase.Interface`:** + +```typescript +interface ScheduleUnpublishEntryUseCase.Interface { + execute(params: IScheduleUnpublishEntryUseCaseParams): IScheduleUnpublishEntryUseCaseResponse; +} +``` + +**Types:** + +```typescript +namespace ScheduleUnpublishEntryUseCase { + type Interface = IScheduleUnpublishEntryUseCase; + type Error = ScheduleActionError; + type Params = IScheduleUnpublishEntryUseCaseParams; + type Result = IScheduleUnpublishEntryUseCaseResponse; +} +``` diff --git a/docs/developer-docs/6.x/reference/api/event-publisher.mdx b/docs/developer-docs/6.x/reference/api/event-publisher.mdx index 5261348de..62802364e 100644 --- a/docs/developer-docs/6.x/reference/api/event-publisher.mdx +++ b/docs/developer-docs/6.x/reference/api/event-publisher.mdx @@ -29,6 +29,8 @@ This page documents everything exported from `webiny/api/event-publisher`. Impor **Class** — imported from `webiny/api/event-publisher` +Base class for all domain events. + ```typescript import { DomainEvent } from "webiny/api/event-publisher"; ``` diff --git a/docs/developer-docs/6.x/reference/api/eventPublisher.ai.txt b/docs/developer-docs/6.x/reference/api/eventPublisher.ai.txt deleted file mode 100644 index 19a802166..000000000 --- a/docs/developer-docs/6.x/reference/api/eventPublisher.ai.txt +++ /dev/null @@ -1,25 +0,0 @@ -AI Context: Event Publisher (reference/api/eventPublisher.mdx) - -Source of Information: -1. packages/webiny/src/api/eventPublisher.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-core/src/features/eventPublisher/index.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -DomainEvent, EventPublisher - -Import Path: webiny/api/eventPublisher - -Related Documents: -- docs/developer-docs/6.0.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.0.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/eventPublisher.mdx b/docs/developer-docs/6.x/reference/api/eventPublisher.mdx deleted file mode 100644 index 439a1a656..000000000 --- a/docs/developer-docs/6.x/reference/api/eventPublisher.mdx +++ /dev/null @@ -1,56 +0,0 @@ ---- -id: yxbpl2v2 -title: Event Publisher -description: "Domain event publishing primitives" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/api/eventPublisher`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/eventPublisher`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `DomainEvent` - -**Class** — imported from `webiny/api/eventPublisher` - -```typescript -import { DomainEvent } from "webiny/api/eventPublisher"; -``` - -```typescript -export abstract class DomainEvent { - public abstract readonly eventType: string; - public readonly occurredAt: Date; - public readonly payload: TPayload extends void ? undefined : TPayload; - constructor(payload?: never); - abstract getHandlerAbstraction(): Abstraction>; -} -``` - -## `EventPublisher` - -**Constant** — imported from `webiny/api/eventPublisher` - -```typescript -import { EventPublisher } from "webiny/api/eventPublisher"; -``` - -```typescript -export const EventPublisher = new Abstraction("EventPublisher"); -``` diff --git a/docs/developer-docs/6.x/reference/api/file-manager/file.ai.txt b/docs/developer-docs/6.x/reference/api/file-manager/file.ai.txt new file mode 100644 index 000000000..5d1674106 --- /dev/null +++ b/docs/developer-docs/6.x/reference/api/file-manager/file.ai.txt @@ -0,0 +1,36 @@ +AI Context: File (reference/api/file-manager/file.mdx) + +Source of Information: +1. packages/webiny/src/api/file-manager/file.ts — barrel re-export file +2. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/file/CreateFile/abstractions.ts — originating source +3. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/file/CreateFile/events.ts — originating source +4. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/file/CreateFilesInBatch/abstractions.ts — originating source +5. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/file/CreateFilesInBatch/events.ts — originating source +6. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/file/UpdateFile/abstractions.ts — originating source +7. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/file/UpdateFile/events.ts — originating source +8. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/file/DeleteFile/abstractions.ts — originating source +9. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/file/DeleteFile/events.ts — originating source +10. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/file/FileUrlGenerator/abstractions.ts — originating source +11. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/file/GetFile/abstractions.ts — originating source +12. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/file/ListFiles/abstractions.ts — originating source +13. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/file/ListTags/abstractions.ts — originating source + +Key Documentation Decisions: +- This file is auto-generated by scripts/generate-reference.ts — do not edit manually +- Symbols are documented in the order they appear in the barrel file +- Declaration text is extracted from the TypeScript AST; method bodies are stripped +- Type-only exports are labeled as "Type"; namespace exports include member listings + +Exported Symbols: +CreateFileRepository, CreateFileUseCase, FileAfterCreateEventHandler, FileBeforeCreateEventHandler, CreateFilesInBatchRepository, CreateFilesInBatchUseCase, FileAfterBatchCreateEventHandler, FileBeforeBatchCreateEventHandler, UpdateFileRepository, UpdateFileUseCase, FileAfterUpdateEventHandler, FileBeforeUpdateEventHandler, DeleteFileRepository, DeleteFileUseCase, FileAfterDeleteEventHandler, FileBeforeDeleteEventHandler, FileUrlGenerator, GetFileRepository, GetFileUseCase, ListFilesRepository, ListFilesUseCase, ListTagsRepository, ListTagsUseCase + +Import Path: webiny/api/file-manager/file + +Related Documents: +- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions +- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns + +Tone Guidelines: +- This is a reference page — terse, API-focused, no prose beyond what's necessary +- Code blocks are the primary content; descriptions serve only to clarify intent +- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/file-manager/file.mdx b/docs/developer-docs/6.x/reference/api/file-manager/file.mdx new file mode 100644 index 000000000..471981bf7 --- /dev/null +++ b/docs/developer-docs/6.x/reference/api/file-manager/file.mdx @@ -0,0 +1,743 @@ +--- +id: yxbpl2zp +title: File +description: "Reference for webiny/api/file-manager/file" +--- + +import { Alert } from "@/components/Alert"; +import { SymbolList } from "@/components/SymbolList"; + + + +- What use cases are available in `webiny/api/file-manager/file`? +- Which event handlers can you implement? +- How to import and use each exported item? + + + +## Overview + +This page documents everything exported from `webiny/api/file-manager/file`. Import any of the items below directly from this path in your Webiny extensions. + +**Use Cases** + + + +**Event Handlers** + + + +**Services** + + + +## Use Cases + +### `CreateFileRepository` + +**Use Case Abstraction** — imported from `webiny/api/file-manager/file` + +```typescript +import { CreateFileRepository } from "webiny/api/file-manager/file"; +``` + +**Interface `CreateFileRepository.Interface`:** + +CreateFile repository interface + +```typescript +interface CreateFileRepository.Interface { + execute(data: FileInput): Promise>; +} +``` + +**Types:** + +```typescript +namespace CreateFileRepository { + type Interface = ICreateFileRepository; + type Error = RepositoryError; +} +``` + +### `CreateFilesInBatchRepository` + +**Use Case Abstraction** — imported from `webiny/api/file-manager/file` + +```typescript +import { CreateFilesInBatchRepository } from "webiny/api/file-manager/file"; +``` + +**Interface `CreateFilesInBatchRepository.Interface`:** + +CreateFilesInBatch repository interface + +```typescript +interface CreateFilesInBatchRepository.Interface { + createBatch(files: FileInput[]): Promise>; +} +``` + +**Types:** + +```typescript +namespace CreateFilesInBatchRepository { + type Interface = ICreateFilesInBatchRepository; + type Error = RepositoryError; +} +``` + +### `CreateFilesInBatchUseCase` + +**Use Case Abstraction** — imported from `webiny/api/file-manager/file` + +```typescript +import { CreateFilesInBatchUseCase } from "webiny/api/file-manager/file"; +``` + +**Interface `CreateFilesInBatchUseCase.Interface`:** + +CreateFilesInBatch use case interface + +```typescript +interface CreateFilesInBatchUseCase.Interface { + execute(input: CreateFilesInBatchInput): Promise>; +} +``` + +**Types:** + +```typescript +namespace CreateFilesInBatchUseCase { + type Interface = ICreateFilesInBatchUseCase; + type Error = UseCaseError; +} +``` + +### `CreateFileUseCase` + +**Use Case Abstraction** — imported from `webiny/api/file-manager/file` + +```typescript +import { CreateFileUseCase } from "webiny/api/file-manager/file"; +``` + +**Interface `CreateFileUseCase.Interface`:** + +CreateFile use case interface + +```typescript +interface CreateFileUseCase.Interface { + execute( + input: CreateFileInput, + meta?: Record + ): Promise>; +} +``` + +**Types:** + +```typescript +namespace CreateFileUseCase { + type Interface = ICreateFileUseCase; + type Error = UseCaseError; +} +``` + +### `DeleteFileRepository` + +**Use Case Abstraction** — imported from `webiny/api/file-manager/file` + +```typescript +import { DeleteFileRepository } from "webiny/api/file-manager/file"; +``` + +**Interface `DeleteFileRepository.Interface`:** + +DeleteFile repository interface + +```typescript +interface DeleteFileRepository.Interface { + delete(file: File): Promise>; +} +``` + +**Types:** + +```typescript +namespace DeleteFileRepository { + type Interface = IDeleteFileRepository; + type Error = RepositoryError; +} +``` + +### `DeleteFileUseCase` + +**Use Case Abstraction** — imported from `webiny/api/file-manager/file` + +```typescript +import { DeleteFileUseCase } from "webiny/api/file-manager/file"; +``` + +**Interface `DeleteFileUseCase.Interface`:** + +DeleteFile use case interface + +```typescript +interface DeleteFileUseCase.Interface { + execute(id: string): Promise>; +} +``` + +**Types:** + +```typescript +namespace DeleteFileUseCase { + type Interface = IDeleteFileUseCase; + type Error = UseCaseError; +} +``` + +### `GetFileRepository` + +**Use Case Abstraction** — imported from `webiny/api/file-manager/file` + +```typescript +import { GetFileRepository } from "webiny/api/file-manager/file"; +``` + +**Interface `GetFileRepository.Interface`:** + +GetFile repository interface + +```typescript +interface GetFileRepository.Interface { + execute(id: string): Promise>; +} +``` + +**Types:** + +```typescript +namespace GetFileRepository { + type Interface = IGetFileRepository; + type Error = RepositoryError; +} +``` + +### `GetFileUseCase` + +**Use Case Abstraction** — imported from `webiny/api/file-manager/file` + +```typescript +import { GetFileUseCase } from "webiny/api/file-manager/file"; +``` + +**Interface `GetFileUseCase.Interface`:** + +GetFile use case interface + +```typescript +interface GetFileUseCase.Interface { + execute(id: string): Promise>; +} +``` + +**Types:** + +```typescript +namespace GetFileUseCase { + type Interface = IGetFileUseCase; + type Error = UseCaseError; +} +``` + +### `ListFilesRepository` + +**Use Case Abstraction** — imported from `webiny/api/file-manager/file` + +```typescript +import { ListFilesRepository } from "webiny/api/file-manager/file"; +``` + +**Interface `ListFilesRepository.Interface`:** + +ListFiles repository interface + +```typescript +interface ListFilesRepository.Interface { + execute(input: ListFilesInput): Promise>; +} +``` + +**Types:** + +```typescript +namespace ListFilesRepository { + type Interface = IListFilesRepository; + type Error = RepositoryError; +} +``` + +### `ListFilesUseCase` + +**Use Case Abstraction** — imported from `webiny/api/file-manager/file` + +```typescript +import { ListFilesUseCase } from "webiny/api/file-manager/file"; +``` + +**Interface `ListFilesUseCase.Interface`:** + +ListFiles use case interface + +```typescript +interface ListFilesUseCase.Interface { + execute(input: ListFilesInput): Promise>; +} +``` + +**Types:** + +```typescript +namespace ListFilesUseCase { + type Interface = IListFilesUseCase; + type Error = UseCaseError; +} +``` + +### `ListTagsRepository` + +**Use Case Abstraction** — imported from `webiny/api/file-manager/file` + +```typescript +import { ListTagsRepository } from "webiny/api/file-manager/file"; +``` + +**Interface `ListTagsRepository.Interface`:** + +ListTags repository interface + +```typescript +interface ListTagsRepository.Interface { + execute(input: ListTagsInput): Promise>; +} +``` + +**Types:** + +```typescript +namespace ListTagsRepository { + type Interface = IListTagsRepository; + type Error = RepositoryError; +} +``` + +### `ListTagsUseCase` + +**Use Case Abstraction** — imported from `webiny/api/file-manager/file` + +```typescript +import { ListTagsUseCase } from "webiny/api/file-manager/file"; +``` + +**Interface `ListTagsUseCase.Interface`:** + +ListTags use case interface + +```typescript +interface ListTagsUseCase.Interface { + execute(input: ListTagsInput): Promise>; +} +``` + +**Types:** + +```typescript +namespace ListTagsUseCase { + type Interface = IListTagsUseCase; + type Error = UseCaseError; +} +``` + +### `UpdateFileRepository` + +**Use Case Abstraction** — imported from `webiny/api/file-manager/file` + +```typescript +import { UpdateFileRepository } from "webiny/api/file-manager/file"; +``` + +**Interface `UpdateFileRepository.Interface`:** + +UpdateFile repository interface + +```typescript +interface UpdateFileRepository.Interface { + update(file: File): Promise>; +} +``` + +**Types:** + +```typescript +namespace UpdateFileRepository { + type Interface = IUpdateFileRepository; + type Error = RepositoryError; +} +``` + +### `UpdateFileUseCase` + +**Use Case Abstraction** — imported from `webiny/api/file-manager/file` + +```typescript +import { UpdateFileUseCase } from "webiny/api/file-manager/file"; +``` + +**Interface `UpdateFileUseCase.Interface`:** + +UpdateFile use case interface + +```typescript +interface UpdateFileUseCase.Interface { + execute(input: UpdateFileInput): Promise>; +} +``` + +**Types:** + +```typescript +namespace UpdateFileUseCase { + type Interface = IUpdateFileUseCase; + type Error = UseCaseError; +} +``` + +## Event Handlers + +### `FileAfterBatchCreateEventHandler` + +**Event Handler Abstraction** — imported from `webiny/api/file-manager/file` + +```typescript +import { FileAfterBatchCreateEventHandler } from "webiny/api/file-manager/file"; +``` + +**Interface `FileAfterBatchCreateEventHandler.Interface`:** + +```typescript +interface FileAfterBatchCreateEventHandler.Interface { + handle(event: FileAfterBatchCreateEvent): Promise; +} +``` + +**Event payload `FileAfterBatchCreatePayload`:** + +```typescript +interface FileAfterBatchCreatePayload { + files: File[]; + meta?: Record; +} +``` + +**Types:** + +```typescript +namespace FileAfterBatchCreateEventHandler { + type Interface = IEventHandler; + type Event = FileAfterBatchCreateEvent; +} +``` + +### `FileAfterCreateEventHandler` + +**Event Handler Abstraction** — imported from `webiny/api/file-manager/file` + +```typescript +import { FileAfterCreateEventHandler } from "webiny/api/file-manager/file"; +``` + +**Interface `FileAfterCreateEventHandler.Interface`:** + +```typescript +interface FileAfterCreateEventHandler.Interface { + handle(event: FileAfterCreateEvent): Promise; +} +``` + +**Event payload `FileAfterCreatePayload`:** + +```typescript +interface FileAfterCreatePayload { + file: File; + meta?: Record; +} +``` + +**Types:** + +```typescript +namespace FileAfterCreateEventHandler { + type Interface = IEventHandler; + type Event = FileAfterCreateEvent; +} +``` + +### `FileAfterDeleteEventHandler` + +**Event Handler Abstraction** — imported from `webiny/api/file-manager/file` + +```typescript +import { FileAfterDeleteEventHandler } from "webiny/api/file-manager/file"; +``` + +**Interface `FileAfterDeleteEventHandler.Interface`:** + +```typescript +interface FileAfterDeleteEventHandler.Interface { + handle(event: FileAfterDeleteEvent): Promise; +} +``` + +**Event payload `FileAfterDeletePayload`:** + +```typescript +interface FileAfterDeletePayload { + file: File; +} +``` + +**Types:** + +```typescript +namespace FileAfterDeleteEventHandler { + type Interface = IEventHandler; + type Event = FileAfterDeleteEvent; +} +``` + +### `FileAfterUpdateEventHandler` + +**Event Handler Abstraction** — imported from `webiny/api/file-manager/file` + +```typescript +import { FileAfterUpdateEventHandler } from "webiny/api/file-manager/file"; +``` + +**Interface `FileAfterUpdateEventHandler.Interface`:** + +```typescript +interface FileAfterUpdateEventHandler.Interface { + handle(event: FileAfterUpdateEvent): Promise; +} +``` + +**Event payload `FileAfterUpdatePayload`:** + +```typescript +interface FileAfterUpdatePayload { + original: File; + file: File; + input: UpdateFileInput; +} +``` + +**Types:** + +```typescript +namespace FileAfterUpdateEventHandler { + type Interface = IEventHandler; + type Event = FileAfterUpdateEvent; +} +``` + +### `FileBeforeBatchCreateEventHandler` + +**Event Handler Abstraction** — imported from `webiny/api/file-manager/file` + +```typescript +import { FileBeforeBatchCreateEventHandler } from "webiny/api/file-manager/file"; +``` + +**Interface `FileBeforeBatchCreateEventHandler.Interface`:** + +```typescript +interface FileBeforeBatchCreateEventHandler.Interface { + handle(event: FileBeforeBatchCreateEvent): Promise; +} +``` + +**Event payload `FileBeforeBatchCreatePayload`:** + +```typescript +interface FileBeforeBatchCreatePayload { + files: FileInput[]; + meta?: Record; +} +``` + +**Types:** + +```typescript +namespace FileBeforeBatchCreateEventHandler { + type Interface = IEventHandler; + type Event = FileBeforeBatchCreateEvent; +} +``` + +### `FileBeforeCreateEventHandler` + +**Event Handler Abstraction** — imported from `webiny/api/file-manager/file` + +```typescript +import { FileBeforeCreateEventHandler } from "webiny/api/file-manager/file"; +``` + +**Interface `FileBeforeCreateEventHandler.Interface`:** + +```typescript +interface FileBeforeCreateEventHandler.Interface { + handle(event: FileBeforeCreateEvent): Promise; +} +``` + +**Event payload `FileBeforeCreatePayload`:** + +```typescript +interface FileBeforeCreatePayload { + file: FileInput; + meta?: Record; +} +``` + +**Types:** + +```typescript +namespace FileBeforeCreateEventHandler { + type Interface = IEventHandler; + type Event = FileBeforeCreateEvent; +} +``` + +### `FileBeforeDeleteEventHandler` + +**Event Handler Abstraction** — imported from `webiny/api/file-manager/file` + +```typescript +import { FileBeforeDeleteEventHandler } from "webiny/api/file-manager/file"; +``` + +**Interface `FileBeforeDeleteEventHandler.Interface`:** + +```typescript +interface FileBeforeDeleteEventHandler.Interface { + handle(event: FileBeforeDeleteEvent): Promise; +} +``` + +**Event payload `FileBeforeDeletePayload`:** + +```typescript +interface FileBeforeDeletePayload { + file: File; +} +``` + +**Types:** + +```typescript +namespace FileBeforeDeleteEventHandler { + type Interface = IEventHandler; + type Event = FileBeforeDeleteEvent; +} +``` + +### `FileBeforeUpdateEventHandler` + +**Event Handler Abstraction** — imported from `webiny/api/file-manager/file` + +```typescript +import { FileBeforeUpdateEventHandler } from "webiny/api/file-manager/file"; +``` + +**Interface `FileBeforeUpdateEventHandler.Interface`:** + +```typescript +interface FileBeforeUpdateEventHandler.Interface { + handle(event: FileBeforeUpdateEvent): Promise; +} +``` + +**Event payload `FileBeforeUpdatePayload`:** + +```typescript +interface FileBeforeUpdatePayload { + original: File; + file: File; + input: UpdateFileInput; +} +``` + +**Types:** + +```typescript +namespace FileBeforeUpdateEventHandler { + type Interface = IEventHandler; + type Event = FileBeforeUpdateEvent; +} +``` + +## Services + +### `FileUrlGenerator` + +**Abstraction** — imported from `webiny/api/file-manager/file` + +```typescript +import { FileUrlGenerator } from "webiny/api/file-manager/file"; +``` + +**Interface `FileUrlGenerator.Interface`:** + +```typescript +interface FileUrlGenerator.Interface { + generateUrl(file: File): string; +} +``` + +**Types:** + +```typescript +namespace FileUrlGenerator { + type Interface = IFileUrlGenerator; +} +``` diff --git a/docs/developer-docs/6.x/reference/admin/buildParams.ai.txt b/docs/developer-docs/6.x/reference/api/file-manager/permissions.ai.txt similarity index 58% rename from docs/developer-docs/6.x/reference/admin/buildParams.ai.txt rename to docs/developer-docs/6.x/reference/api/file-manager/permissions.ai.txt index 129386644..4948e47c5 100644 --- a/docs/developer-docs/6.x/reference/admin/buildParams.ai.txt +++ b/docs/developer-docs/6.x/reference/api/file-manager/permissions.ai.txt @@ -1,8 +1,8 @@ -AI Context: Build Params (reference/admin/buildParams.mdx) +AI Context: Permissions (reference/api/file-manager/permissions.mdx) Source of Information: -1. packages/webiny/src/admin/buildParams.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/app-admin/src/features/buildParams/index.ts — originating source +1. packages/webiny/src/api/file-manager/permissions.ts — barrel re-export file +2. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/shared/abstractions.ts — originating source Key Documentation Decisions: - This file is auto-generated by scripts/generate-reference.ts — do not edit manually @@ -11,13 +11,13 @@ Key Documentation Decisions: - Type-only exports are labeled as "Type"; namespace exports include member listings Exported Symbols: -BuildParam, BuildParams +FmPermissions -Import Path: webiny/admin/buildParams +Import Path: webiny/api/file-manager/permissions Related Documents: -- docs/developer-docs/6.0.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.0.x/basic/result.mdx — Result type used in use case returns +- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions +- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns Tone Guidelines: - This is a reference page — terse, API-focused, no prose beyond what's necessary diff --git a/docs/developer-docs/6.x/reference/api/file-manager/permissions.mdx b/docs/developer-docs/6.x/reference/api/file-manager/permissions.mdx new file mode 100644 index 000000000..84583834b --- /dev/null +++ b/docs/developer-docs/6.x/reference/api/file-manager/permissions.mdx @@ -0,0 +1,29 @@ +--- +id: yxbpl2zp +title: Permissions +description: "Reference for webiny/api/file-manager/permissions" +--- + +import { Alert } from "@/components/Alert"; +import { SymbolList } from "@/components/SymbolList"; + + + +- What is exported from `webiny/api/file-manager/permissions`? +- How to import and use each exported item? + + + +## Overview + +This page documents everything exported from `webiny/api/file-manager/permissions`. Import any of the items below directly from this path in your Webiny extensions. + + + +## `FmPermissions` + +**Export** — imported from `webiny/api/file-manager/permissions` + +```typescript +import { FmPermissions } from "webiny/api/file-manager/permissions"; +``` diff --git a/docs/developer-docs/6.x/reference/api/file-manager/settings.ai.txt b/docs/developer-docs/6.x/reference/api/file-manager/settings.ai.txt new file mode 100644 index 000000000..3035038db --- /dev/null +++ b/docs/developer-docs/6.x/reference/api/file-manager/settings.ai.txt @@ -0,0 +1,27 @@ +AI Context: Settings (reference/api/file-manager/settings.mdx) + +Source of Information: +1. packages/webiny/src/api/file-manager/settings.ts — barrel re-export file +2. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/settings/GetSettings/abstractions.ts — originating source +3. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/settings/UpdateSettings/abstractions.ts — originating source +4. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/settings/UpdateSettings/events.ts — originating source + +Key Documentation Decisions: +- This file is auto-generated by scripts/generate-reference.ts — do not edit manually +- Symbols are documented in the order they appear in the barrel file +- Declaration text is extracted from the TypeScript AST; method bodies are stripped +- Type-only exports are labeled as "Type"; namespace exports include member listings + +Exported Symbols: +GetSettingsUseCase, UpdateSettingsUseCase, SettingsAfterUpdateEventHandler, SettingsBeforeUpdateEventHandler + +Import Path: webiny/api/file-manager/settings + +Related Documents: +- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions +- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns + +Tone Guidelines: +- This is a reference page — terse, API-focused, no prose beyond what's necessary +- Code blocks are the primary content; descriptions serve only to clarify intent +- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/file-manager/settings.mdx b/docs/developer-docs/6.x/reference/api/file-manager/settings.mdx new file mode 100644 index 000000000..637812c0e --- /dev/null +++ b/docs/developer-docs/6.x/reference/api/file-manager/settings.mdx @@ -0,0 +1,166 @@ +--- +id: yxbpl2zp +title: Settings +description: "Reference for webiny/api/file-manager/settings" +--- + +import { Alert } from "@/components/Alert"; +import { SymbolList } from "@/components/SymbolList"; + + + +- What use cases are available in `webiny/api/file-manager/settings`? +- Which event handlers can you implement? +- How to import and use each exported item? + + + +## Overview + +This page documents everything exported from `webiny/api/file-manager/settings`. Import any of the items below directly from this path in your Webiny extensions. + +**Use Cases** + + + +**Event Handlers** + + + +## Use Cases + +### `GetSettingsUseCase` + +**Use Case Abstraction** — imported from `webiny/api/file-manager/settings` + +```typescript +import { GetSettingsUseCase } from "webiny/api/file-manager/settings"; +``` + +**Interface `GetSettingsUseCase.Interface`:** + +GetSettings use case - retrieves file manager settings. + +```typescript +interface GetSettingsUseCase.Interface { + execute(): Promise>; +} +``` + +**Types:** + +```typescript +namespace GetSettingsUseCase { + type Interface = IGetSettingsUseCase; + type Error = UseCaseError; +} +``` + +### `UpdateSettingsUseCase` + +**Use Case Abstraction** — imported from `webiny/api/file-manager/settings` + +```typescript +import { UpdateSettingsUseCase } from "webiny/api/file-manager/settings"; +``` + +**Interface `UpdateSettingsUseCase.Interface`:** + +UpdateSettings use case interface + +```typescript +interface UpdateSettingsUseCase.Interface { + execute(input: UpdateSettingsInput): Promise>; +} +``` + +**Types:** + +```typescript +namespace UpdateSettingsUseCase { + type Interface = IUpdateSettingsUseCase; + type Error = UseCaseError; +} +``` + +## Event Handlers + +### `SettingsAfterUpdateEventHandler` + +**Event Handler Abstraction** — imported from `webiny/api/file-manager/settings` + +```typescript +import { SettingsAfterUpdateEventHandler } from "webiny/api/file-manager/settings"; +``` + +**Interface `SettingsAfterUpdateEventHandler.Interface`:** + +```typescript +interface SettingsAfterUpdateEventHandler.Interface { + handle(event: SettingsAfterUpdateEvent): Promise; +} +``` + +**Event payload `SettingsAfterUpdatePayload`:** + +```typescript +interface SettingsAfterUpdatePayload { + original: FileManagerSettings; + settings: FileManagerSettings; + input: UpdateSettingsInput; +} +``` + +**Types:** + +```typescript +namespace SettingsAfterUpdateEventHandler { + type Interface = IEventHandler; + type Event = SettingsAfterUpdateEvent; +} +``` + +### `SettingsBeforeUpdateEventHandler` + +**Event Handler Abstraction** — imported from `webiny/api/file-manager/settings` + +```typescript +import { SettingsBeforeUpdateEventHandler } from "webiny/api/file-manager/settings"; +``` + +**Interface `SettingsBeforeUpdateEventHandler.Interface`:** + +```typescript +interface SettingsBeforeUpdateEventHandler.Interface { + handle(event: SettingsBeforeUpdateEvent): Promise; +} +``` + +**Event payload `SettingsBeforeUpdatePayload`:** + +```typescript +interface SettingsBeforeUpdatePayload { + original: FileManagerSettings; + settings: FileManagerSettings; + input: UpdateSettingsInput; +} +``` + +**Types:** + +```typescript +namespace SettingsBeforeUpdateEventHandler { + type Interface = IEventHandler; + type Event = SettingsBeforeUpdateEvent; +} +``` diff --git a/docs/developer-docs/6.x/reference/api/graphql.mdx b/docs/developer-docs/6.x/reference/api/graphql.mdx index c0f555f93..c54dffcdb 100644 --- a/docs/developer-docs/6.x/reference/api/graphql.mdx +++ b/docs/developer-docs/6.x/reference/api/graphql.mdx @@ -47,7 +47,7 @@ import { GraphQLSchemaFactory } from "webiny/api/graphql"; **Interface `GraphQLSchemaFactory.Interface`:** -GraphQLSchemaFactory +Define custom GraphQL schema extensions. ```typescript interface GraphQLSchemaFactory.Interface { @@ -67,8 +67,6 @@ namespace GraphQLSchemaFactory { **`SchemaBuilder` — `GraphQLSchemaBuilder.Interface`:** -Interface for building GraphQL schemas by adding type definitions and resolvers. - ```typescript interface GraphQLSchemaBuilder.Interface { addTypeDefs(typeDefs: TypeDefs): this; @@ -77,18 +75,14 @@ interface GraphQLSchemaBuilder.Interface { } ``` -| Method | Description | -| ------------------------------------------- | -------------------------------------------------- | -| `addTypeDefs()` | Add GraphQL type definitions to the schema. | -| `addResolver()` | Add a GraphQL resolver with optional dependencies. | -| `build()` | Build and return the GraphQL schema. | - ## Types & Classes ### `ErrorResponse` **Class** — imported from `webiny/api/graphql` +GraphQL error response helper. + ```typescript import { ErrorResponse } from "webiny/api/graphql"; ``` @@ -105,6 +99,8 @@ export class ErrorResponse { **Class** — imported from `webiny/api/graphql` +GraphQL list error response helper. + ```typescript import { ListErrorResponse } from "webiny/api/graphql"; ``` @@ -122,12 +118,14 @@ export class ListErrorResponse { **Class** — imported from `webiny/api/graphql` +GraphQL list response helper. + ```typescript import { ListResponse } from "webiny/api/graphql"; ``` ```typescript -export class ListResponse { +export class ListResponse { public readonly data: Array; public readonly meta: M; public readonly error: null; @@ -139,6 +137,8 @@ export class ListResponse { **Class** — imported from `webiny/api/graphql` +GraphQL not-authorized response helper. + ```typescript import { NotAuthorizedResponse } from "webiny/api/graphql"; ``` @@ -153,6 +153,8 @@ export class NotAuthorizedResponse extends ErrorResponse { **Class** — imported from `webiny/api/graphql` +GraphQL not-found response helper. + ```typescript import { NotFoundResponse } from "webiny/api/graphql"; ``` @@ -167,6 +169,8 @@ export class NotFoundResponse extends ErrorResponse { **Class** — imported from `webiny/api/graphql` +GraphQL response helper. + ```typescript import { Response } from "webiny/api/graphql"; ``` diff --git a/docs/developer-docs/6.x/reference/api/keyValueStore.mdx b/docs/developer-docs/6.x/reference/api/keyValueStore.mdx deleted file mode 100644 index 0eea91669..000000000 --- a/docs/developer-docs/6.x/reference/api/keyValueStore.mdx +++ /dev/null @@ -1,132 +0,0 @@ ---- -id: yxbpl2tl -title: Key-Value Store -description: "Key-value store abstraction" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/api/keyValueStore`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/keyValueStore`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `GlobalKeyValueStore` - -**Abstraction** — imported from `webiny/api/keyValueStore` - -```typescript -import { GlobalKeyValueStore } from "webiny/api/keyValueStore"; -``` - -**Interface `GlobalKeyValueStore.Interface`:** - -```typescript -interface GlobalKeyValueStore.Interface { - get( - key: string, - options?: IGlobalKeyValueStoreOptions - ): Promise>; - set( - key: string, - value: any, - options?: IGlobalKeyValueStoreOptions - ): Promise>; - delete( - key: string, - options?: IGlobalKeyValueStoreOptions - ): Promise>; -} -``` - -**Types:** - -```typescript -namespace GlobalKeyValueStore { - type Interface = IGlobalKeyValueStore; - type KeyValueRecord = IKeyValueRecord; - type Error = KeyValueStoreRepository.Error; -} -``` - -**Usage:** - -```typescript -// extensions/MyImpl.ts -import { GlobalKeyValueStore } from "webiny/api/keyValueStore"; - -class MyImpl implements MyUseCase.Interface { - public constructor(private globalKeyValueStore: GlobalKeyValueStore.Interface) {} - - public async execute(/* ... */): Promise { - await this.globalKeyValueStore.get(/* ... */); - } -} - -export default MyUseCase.createImplementation({ - implementation: MyImpl, - dependencies: [GlobalKeyValueStore] -}); -``` - -## `KeyValueStore` - -**Abstraction** — imported from `webiny/api/keyValueStore` - -```typescript -import { KeyValueStore } from "webiny/api/keyValueStore"; -``` - -**Interface `KeyValueStore.Interface`:** - -```typescript -interface KeyValueStore.Interface { - get(key: string): Promise>; - set(key: string, value: any): Promise>; - delete(key: string): Promise>; -} -``` - -**Types:** - -```typescript -namespace KeyValueStore { - type Interface = IKeyValueStore; - type KeyValueRecord = IKeyValueRecord; - type Error = KeyValueStoreRepository.Error; -} -``` - -**Usage:** - -```typescript -// extensions/MyImpl.ts -import { KeyValueStore } from "webiny/api/keyValueStore"; - -class MyImpl implements MyUseCase.Interface { - public constructor(private keyValueStore: KeyValueStore.Interface) {} - - public async execute(/* ... */): Promise { - await this.keyValueStore.get(/* ... */); - } -} - -export default MyUseCase.createImplementation({ - implementation: MyImpl, - dependencies: [KeyValueStore] -}); -``` diff --git a/docs/developer-docs/6.x/reference/api/logger.mdx b/docs/developer-docs/6.x/reference/api/logger.mdx index 0f3c823d4..175e6bd3e 100644 --- a/docs/developer-docs/6.x/reference/api/logger.mdx +++ b/docs/developer-docs/6.x/reference/api/logger.mdx @@ -30,8 +30,6 @@ import { Logger } from "webiny/api/logger"; **Interface `Logger.Interface`:** -Interface for logging messages at different severity levels. - ```typescript interface Logger.Interface { trace(objOrMsg: object | string, ...args: any[]): void; @@ -44,16 +42,6 @@ interface Logger.Interface { } ``` -| Method | Description | -| --------- | ---------------------------------------------------------------------------------- | -| `trace()` | Log a trace-level message with optional additional arguments. | -| `debug()` | Log a debug-level message with optional additional arguments. | -| `info()` | Log an info-level message with optional additional arguments. | -| `warn()` | Log a warning-level message with optional additional arguments. | -| `error()` | Log an error-level message with optional additional arguments. | -| `fatal()` | Log a fatal-level message with optional additional arguments. | -| `log()` | Log a generic message (defaults to info level) with optional additional arguments. | - **Types:** ```typescript diff --git a/docs/developer-docs/6.x/reference/api/scheduler.ai.txt b/docs/developer-docs/6.x/reference/api/scheduler.ai.txt new file mode 100644 index 000000000..a984bbc28 --- /dev/null +++ b/docs/developer-docs/6.x/reference/api/scheduler.ai.txt @@ -0,0 +1,32 @@ +AI Context: Scheduler (reference/api/scheduler.mdx) + +Source of Information: +1. packages/webiny/src/api/scheduler.ts — barrel re-export file +2. /Users/adrian/dev/wby-next/packages/api-scheduler/src/features/ScheduleAction/index.ts — originating source +3. /Users/adrian/dev/wby-next/packages/api-scheduler/src/features/GetScheduledAction/index.ts — originating source +4. /Users/adrian/dev/wby-next/packages/api-scheduler/src/features/ListScheduledActions/index.ts — originating source +5. /Users/adrian/dev/wby-next/packages/api-scheduler/src/features/CancelScheduledAction/index.ts — originating source +6. /Users/adrian/dev/wby-next/packages/api-scheduler/src/features/ExecuteScheduledAction/index.ts — originating source +7. /Users/adrian/dev/wby-next/packages/api-scheduler/src/features/NamespaceHandler/index.ts — originating source +8. /Users/adrian/dev/wby-next/packages/api-scheduler/src/shared/abstractions.ts — originating source +9. /Users/adrian/dev/wby-next/packages/api-scheduler/src/constants.ts — originating source + +Key Documentation Decisions: +- This file is auto-generated by scripts/generate-reference.ts — do not edit manually +- Symbols are documented in the order they appear in the barrel file +- Declaration text is extracted from the TypeScript AST; method bodies are stripped +- Type-only exports are labeled as "Type"; namespace exports include member listings + +Exported Symbols: +ScheduleActionUseCase, ScheduleActionError, GetScheduledActionUseCase, ListScheduledActionsUseCase, CancelScheduledActionUseCase, ExecuteScheduledActionUseCase, NamespaceHandler, IScheduledAction, IScheduledActionEntry, ScheduledActionType, SchedulerService, ScheduledActionModel, ScheduledActionHandler, ScheduledActionTypePublish, ScheduledActionTypeUnpublish + +Import Path: webiny/api/scheduler + +Related Documents: +- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions +- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns + +Tone Guidelines: +- This is a reference page — terse, API-focused, no prose beyond what's necessary +- Code blocks are the primary content; descriptions serve only to clarify intent +- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/scheduler.mdx b/docs/developer-docs/6.x/reference/api/scheduler.mdx new file mode 100644 index 000000000..7b24f2200 --- /dev/null +++ b/docs/developer-docs/6.x/reference/api/scheduler.mdx @@ -0,0 +1,399 @@ +--- +id: yxbpl3nj +title: Scheduler +description: "Reference for webiny/api/scheduler" +--- + +import { Alert } from "@/components/Alert"; +import { SymbolList } from "@/components/SymbolList"; + + + +- What use cases are available in `webiny/api/scheduler`? +- How to import and use each exported item? + + + +## Overview + +This page documents everything exported from `webiny/api/scheduler`. Import any of the items below directly from this path in your Webiny extensions. + +**Use Cases** + + + +**Event Handlers** + + + +**Services** + + + +**Types & Classes** + + + +## Use Cases + +### `CancelScheduledActionUseCase` + +**Use Case Abstraction** — imported from `webiny/api/scheduler` + +```typescript +import { CancelScheduledActionUseCase } from "webiny/api/scheduler"; +``` + +**Interface `CancelScheduledActionUseCase.Interface`:** + +```typescript +interface CancelScheduledActionUseCase.Interface { + execute( + params: ICancelScheduledActionUseCaseParams + ): Promise>; +} +``` + +**Types:** + +```typescript +namespace CancelScheduledActionUseCase { + type Interface = ICancelScheduledActionUseCase; + type Error = CancelScheduledActionError; + type Params = ICancelScheduledActionUseCaseParams; +} +``` + +### `ExecuteScheduledActionUseCase` + +**Use Case Abstraction** — imported from `webiny/api/scheduler` + +```typescript +import { ExecuteScheduledActionUseCase } from "webiny/api/scheduler"; +``` + +**Interface `ExecuteScheduledActionUseCase.Interface`:** + +```typescript +interface ExecuteScheduledActionUseCase.Interface { + execute( + params: IExecuteScheduledActionUseCaseParams + ): Promise>; +} +``` + +**Types:** + +```typescript +namespace ExecuteScheduledActionUseCase { + type Interface = IExecuteScheduledActionUseCase; + type Error = ExecuteScheduledActionError; + type Params = IExecuteScheduledActionUseCaseParams; +} +``` + +### `GetScheduledActionUseCase` + +**Use Case Abstraction** — imported from `webiny/api/scheduler` + +```typescript +import { GetScheduledActionUseCase } from "webiny/api/scheduler"; +``` + +**Interface `GetScheduledActionUseCase.Interface`:** + +```typescript +interface GetScheduledActionUseCase.Interface { + execute( + params: IGetScheduledActionUseCaseParams + ): Promise, GetScheduledActionError>>; +} +``` + +**Types:** + +```typescript +namespace GetScheduledActionUseCase { + type Interface = IGetScheduledActionUseCase; + type Error = GetScheduledActionError; + type Params = IGetScheduledActionUseCaseParams; +} +``` + +### `ListScheduledActionsUseCase` + +**Use Case Abstraction** — imported from `webiny/api/scheduler` + +```typescript +import { ListScheduledActionsUseCase } from "webiny/api/scheduler"; +``` + +**Interface `ListScheduledActionsUseCase.Interface`:** + +```typescript +interface ListScheduledActionsUseCase.Interface { + execute( + params: IListScheduledActionsParams + ): Promise, ListScheduledActionsError>>; +} +``` + +**Types:** + +```typescript +namespace ListScheduledActionsUseCase { + type Interface = IListScheduledActionsUseCase; + type Error = ListScheduledActionsError; + type Params = IListScheduledActionsParams; + type Where = IListScheduledActionsWhere; + type Sort = CmsEntryListSort; + type Meta = IListScheduledActionsMeta; + type Response = IListScheduledActionsResponse; +} +``` + +**`Meta` — `CmsEntryMeta`:** + +Meta information for GraphQL output. + +@category CmsEntry +@category GraphQL output + +| Field | Type | Required | Description | +| -------------- | ---------------- | -------- | ----------- | +| `cursor` | `string \| null` | yes | — | +| `hasMoreItems` | `boolean` | yes | — | +| `totalCount` | `number` | yes | — | + +### `ScheduleActionUseCase` + +**Use Case Abstraction** — imported from `webiny/api/scheduler` + +```typescript +import { ScheduleActionUseCase } from "webiny/api/scheduler"; +``` + +**Interface `ScheduleActionUseCase.Interface`:** + +```typescript +interface ScheduleActionUseCase.Interface { + execute( + params: IScheduleActionParams + ): Promise, ScheduleActionError>>; +} +``` + +**Types:** + +```typescript +namespace ScheduleActionUseCase { + type Interface = IScheduleActionUseCase; + type Params = IScheduleActionParams; + type Error = ScheduleActionError; +} +``` + +## Event Handlers + +### `NamespaceHandler` + +**Event Handler Abstraction** — imported from `webiny/api/scheduler` + +```typescript +import { NamespaceHandler } from "webiny/api/scheduler"; +``` + +**Interface `NamespaceHandler.Interface`:** + +```typescript +interface NamespaceHandler.Interface { + handle(event: DomainEvent): Promise; +} +``` + +**Types:** + +```typescript +namespace NamespaceHandler { + type Interface = INamespaceHandler; + type Response = Promise, NamespaceHandlerError>>; + type Params = INamespaceHandlerParams; +} +``` + +### `ScheduledActionHandler` + +**Event Handler Abstraction** — imported from `webiny/api/scheduler` + +```typescript +import { ScheduledActionHandler } from "webiny/api/scheduler"; +``` + +**Interface `ScheduledActionHandler.Interface`:** + +```typescript +interface ScheduledActionHandler.Interface { + handle(event: DomainEvent): Promise; +} +``` + +**Types:** + +```typescript +namespace ScheduledActionHandler { + type Interface = IScheduledActionHandler; +} +``` + +## Services + +### `ScheduledActionModel` + +**Abstraction** — imported from `webiny/api/scheduler` + +```typescript +import { ScheduledActionModel } from "webiny/api/scheduler"; +``` + +**Types:** + +```typescript +namespace ScheduledActionModel { + type Interface = CmsModel; +} +``` + +### `SchedulerService` + +**Abstraction** — imported from `webiny/api/scheduler` + +```typescript +import { SchedulerService } from "webiny/api/scheduler"; +``` + +**Interface `SchedulerService.Interface`:** + +```typescript +interface SchedulerService.Interface { + create(params: ISchedulerServiceCreateParams): Promise; + update(params: ISchedulerServiceUpdateParams): Promise; + delete(id: string): Promise; + exists(id: string): Promise; +} +``` + +**Types:** + +```typescript +namespace SchedulerService { + type Interface = ISchedulerService; +} +``` + +## Types & Classes + +### `IScheduledAction` + +**Type** — imported from `webiny/api/scheduler` + +```typescript +import type { IScheduledAction } from "webiny/api/scheduler"; +``` + +```typescript +export interface IScheduledAction + extends Omit, "scheduledFor"> { + id: string; + scheduledFor: Date; +} +``` + +### `IScheduledActionEntry` + +**Type** — imported from `webiny/api/scheduler` + +```typescript +import type { IScheduledActionEntry } from "webiny/api/scheduler"; +``` + +```typescript +export interface IScheduledActionEntry + extends CmsEntry> {} +``` + +### `ScheduleActionError` + +**Type** — imported from `webiny/api/scheduler` + +```typescript +import type { ScheduleActionError } from "webiny/api/scheduler"; +``` + +```typescript +export type ScheduleActionError = IScheduleActionErrors[keyof IScheduleActionErrors]; +``` + +### `ScheduledActionType` + +**Type** — imported from `webiny/api/scheduler` + +```typescript +import type { ScheduledActionType } from "webiny/api/scheduler"; +``` + +```typescript +export type ScheduledActionType = + | typeof SCHEDULED_ACTION_PUBLISH + | typeof SCHEDULED_ACTION_UNPUBLISH; +``` + +### `ScheduledActionTypePublish` + +**Constant** — imported from `webiny/api/scheduler` + +```typescript +import { ScheduledActionTypePublish } from "webiny/api/scheduler"; +``` + +```typescript +export const SCHEDULED_ACTION_PUBLISH = "publish" as const; +``` + +### `ScheduledActionTypeUnpublish` + +**Constant** — imported from `webiny/api/scheduler` + +```typescript +import { ScheduledActionTypeUnpublish } from "webiny/api/scheduler"; +``` + +```typescript +export const SCHEDULED_ACTION_UNPUBLISH = "unpublish" as const; +``` diff --git a/docs/developer-docs/6.x/reference/api/security.ai.txt b/docs/developer-docs/6.x/reference/api/security.ai.txt index bb4cf44ae..fef552846 100644 --- a/docs/developer-docs/6.x/reference/api/security.ai.txt +++ b/docs/developer-docs/6.x/reference/api/security.ai.txt @@ -4,10 +4,12 @@ Source of Information: 1. packages/webiny/src/api/security.ts — barrel re-export file 2. /Users/adrian/dev/wby-next/packages/api-core/src/features/security/IdentityContext/index.ts — originating source 3. /Users/adrian/dev/wby-next/packages/api-core/src/features/security/apiKeys/shared/abstractions.ts — originating source -4. /Users/adrian/dev/wby-next/packages/api-core/src/domain/security/ApiToken.ts — originating source -5. /Users/adrian/dev/wby-next/packages/api-core/src/idp/index.ts — originating source -6. /Users/adrian/dev/wby-next/packages/api-core/src/features/security/authentication/Authenticator/abstractions.ts — originating source -7. /Users/adrian/dev/wby-next/packages/api-core/src/features/security/authorization/Authorizer/index.ts — originating source +4. /Users/adrian/dev/wby-next/packages/api-core/src/features/security/roles/shared/abstractions.ts — originating source +5. /Users/adrian/dev/wby-next/packages/api-core/src/features/security/teams/shared/abstractions.ts — originating source +6. /Users/adrian/dev/wby-next/packages/api-core/src/domain/security/ApiToken.ts — originating source +7. /Users/adrian/dev/wby-next/packages/api-core/src/idp/index.ts — originating source +8. /Users/adrian/dev/wby-next/packages/api-core/src/features/security/authentication/Authenticator/abstractions.ts — originating source +9. /Users/adrian/dev/wby-next/packages/api-core/src/features/security/authorization/Authorizer/index.ts — originating source Key Documentation Decisions: - This file is auto-generated by scripts/generate-reference.ts — do not edit manually @@ -16,7 +18,7 @@ Key Documentation Decisions: - Type-only exports are labeled as "Type"; namespace exports include member listings Exported Symbols: -IdentityContext, ApiKeyFactory, ApiToken, IdentityProvider, OidcIdentityProvider, JwtIdentityProvider, Authenticator, Authorizer +IdentityContext, ApiKeyFactory, RoleFactory, TeamFactory, ApiToken, IdentityProvider, OidcIdentityProvider, JwtIdentityProvider, Authenticator, Authorizer Import Path: webiny/api/security diff --git a/docs/developer-docs/6.x/reference/api/security.mdx b/docs/developer-docs/6.x/reference/api/security.mdx index b92fb0927..38362fc57 100644 --- a/docs/developer-docs/6.x/reference/api/security.mdx +++ b/docs/developer-docs/6.x/reference/api/security.mdx @@ -28,7 +28,9 @@ This page documents everything exported from `webiny/api/security`. Import any o { name: "IdentityContext", anchor: "identity-context" }, { name: "IdentityProvider", anchor: "identity-provider" }, { name: "JwtIdentityProvider", anchor: "jwt-identity-provider" }, - { name: "OidcIdentityProvider", anchor: "oidc-identity-provider" } + { name: "OidcIdentityProvider", anchor: "oidc-identity-provider" }, + { name: "RoleFactory", anchor: "role-factory" }, + { name: "TeamFactory", anchor: "team-factory" } ]} /> @@ -50,7 +52,7 @@ import { ApiKeyFactory } from "webiny/api/security"; ```typescript interface ApiKeyFactory.Interface { - execute(): Promise | CodeApiKey[]; + execute(): Promise; } ``` @@ -59,7 +61,7 @@ interface ApiKeyFactory.Interface { ```typescript namespace ApiKeyFactory { type Interface = IApiKeyFactory; - type Return = Promise | CodeApiKey[]; + type Return = Promise; type ApiKey = CodeApiKey; } ``` @@ -235,12 +237,66 @@ namespace OidcIdentityProvider { } ``` +### `RoleFactory` + +**Abstraction** — imported from `webiny/api/security` + +```typescript +import { RoleFactory } from "webiny/api/security"; +``` + +**Interface `RoleFactory.Interface`:** + +```typescript +interface RoleFactory.Interface { + execute(): Promise; +} +``` + +**Types:** + +```typescript +namespace RoleFactory { + type Interface = IRoleFactory; + type Return = Promise; + type Role = CodeRole; +} +``` + +### `TeamFactory` + +**Abstraction** — imported from `webiny/api/security` + +```typescript +import { TeamFactory } from "webiny/api/security"; +``` + +**Interface `TeamFactory.Interface`:** + +```typescript +interface TeamFactory.Interface { + execute(): Promise; +} +``` + +**Types:** + +```typescript +namespace TeamFactory { + type Interface = ITeamFactory; + type Return = Promise; + type Team = CodeTeam; +} +``` + ## Types & Classes ### `ApiToken` **Class** — imported from `webiny/api/security` +Represents an API token identity. + ```typescript import { ApiToken } from "webiny/api/security"; ``` diff --git a/docs/developer-docs/6.x/reference/api/security/api-key.mdx b/docs/developer-docs/6.x/reference/api/security/api-key.mdx index 53c171d92..7b94bae07 100644 --- a/docs/developer-docs/6.x/reference/api/security/api-key.mdx +++ b/docs/developer-docs/6.x/reference/api/security/api-key.mdx @@ -368,7 +368,7 @@ import { ApiKeyFactory } from "webiny/api/security/api-key"; ```typescript interface ApiKeyFactory.Interface { - execute(): Promise | CodeApiKey[]; + execute(): Promise; } ``` @@ -377,7 +377,7 @@ interface ApiKeyFactory.Interface { ```typescript namespace ApiKeyFactory { type Interface = IApiKeyFactory; - type Return = Promise | CodeApiKey[]; + type Return = Promise; type ApiKey = CodeApiKey; } ``` diff --git a/docs/developer-docs/6.x/reference/api/tenancy.mdx b/docs/developer-docs/6.x/reference/api/tenancy.mdx index e1bbda4c3..645f392b6 100644 --- a/docs/developer-docs/6.x/reference/api/tenancy.mdx +++ b/docs/developer-docs/6.x/reference/api/tenancy.mdx @@ -198,8 +198,6 @@ import { InstallTenantUseCase } from "webiny/api/tenancy"; **Interface `InstallTenantUseCase.Interface`:** -Use Case Abstraction - ```typescript interface InstallTenantUseCase.Interface { execute( @@ -455,8 +453,6 @@ import { AppInstaller } from "webiny/api/tenancy"; **Interface `AppInstaller.Interface`:** -App Installer Abstraction - ```typescript interface AppInstaller.Interface { readonly alwaysRun?: boolean; diff --git a/docs/developer-docs/6.x/reference/api/website-builder/scheduler.ai.txt b/docs/developer-docs/6.x/reference/api/website-builder/scheduler.ai.txt new file mode 100644 index 000000000..388051b78 --- /dev/null +++ b/docs/developer-docs/6.x/reference/api/website-builder/scheduler.ai.txt @@ -0,0 +1,28 @@ +AI Context: Scheduler (reference/api/website-builder/scheduler.mdx) + +Source of Information: +1. packages/webiny/src/api/website-builder/scheduler.ts — barrel re-export file +2. /Users/adrian/dev/wby-next/packages/api-website-builder-scheduler/src/features/SchedulePublishPageUseCase/abstractions.ts — originating source +3. /Users/adrian/dev/wby-next/packages/api-website-builder-scheduler/src/features/ScheduleUnpublishPageUseCase/abstractions.ts — originating source +4. /Users/adrian/dev/wby-next/packages/api-website-builder-scheduler/src/features/SchedulePublishRedirectUseCase/abstractions.ts — originating source +5. /Users/adrian/dev/wby-next/packages/api-website-builder-scheduler/src/features/ScheduleUnpublishRedirectUseCase/abstractions.ts — originating source + +Key Documentation Decisions: +- This file is auto-generated by scripts/generate-reference.ts — do not edit manually +- Symbols are documented in the order they appear in the barrel file +- Declaration text is extracted from the TypeScript AST; method bodies are stripped +- Type-only exports are labeled as "Type"; namespace exports include member listings + +Exported Symbols: +SchedulePublishPageUseCase, ScheduleUnpublishPageUseCase, SchedulePublishRedirectUseCase, ScheduleUnpublishRedirectUseCase + +Import Path: webiny/api/website-builder/scheduler + +Related Documents: +- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions +- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns + +Tone Guidelines: +- This is a reference page — terse, API-focused, no prose beyond what's necessary +- Code blocks are the primary content; descriptions serve only to clarify intent +- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/website-builder/scheduler.mdx b/docs/developer-docs/6.x/reference/api/website-builder/scheduler.mdx new file mode 100644 index 000000000..d8696fce4 --- /dev/null +++ b/docs/developer-docs/6.x/reference/api/website-builder/scheduler.mdx @@ -0,0 +1,138 @@ +--- +id: yxbpl3dl +title: Scheduler +description: "Reference for webiny/api/website-builder/scheduler" +--- + +import { Alert } from "@/components/Alert"; +import { SymbolList } from "@/components/SymbolList"; + + + +- What use cases are available in `webiny/api/website-builder/scheduler`? +- How to import and use each exported item? + + + +## Overview + +This page documents everything exported from `webiny/api/website-builder/scheduler`. Import any of the items below directly from this path in your Webiny extensions. + + + +## `SchedulePublishPageUseCase` + +**Use Case Abstraction** — imported from `webiny/api/website-builder/scheduler` + +```typescript +import { SchedulePublishPageUseCase } from "webiny/api/website-builder/scheduler"; +``` + +**Interface `SchedulePublishPageUseCase.Interface`:** + +```typescript +interface SchedulePublishPageUseCase.Interface { + execute(params: ISchedulePublishPageUseCaseParams): ISchedulePublishPageUseCaseResponse; +} +``` + +**Types:** + +```typescript +namespace SchedulePublishPageUseCase { + type Interface = ISchedulePublishPageUseCase; + type Error = ScheduleActionError; + type Params = ISchedulePublishPageUseCaseParams; + type Result = ISchedulePublishPageUseCaseResponse; +} +``` + +## `SchedulePublishRedirectUseCase` + +**Use Case Abstraction** — imported from `webiny/api/website-builder/scheduler` + +```typescript +import { SchedulePublishRedirectUseCase } from "webiny/api/website-builder/scheduler"; +``` + +**Interface `SchedulePublishRedirectUseCase.Interface`:** + +```typescript +interface SchedulePublishRedirectUseCase.Interface { + execute(params: ISchedulePublishRedirectUseCaseParams): ISchedulePublishRedirectUseCaseResponse; +} +``` + +**Types:** + +```typescript +namespace SchedulePublishRedirectUseCase { + type Interface = ISchedulePublishRedirectUseCase; + type Error = ScheduleActionError; + type Params = ISchedulePublishRedirectUseCaseParams; + type Result = ISchedulePublishRedirectUseCaseResponse; +} +``` + +## `ScheduleUnpublishPageUseCase` + +**Use Case Abstraction** — imported from `webiny/api/website-builder/scheduler` + +```typescript +import { ScheduleUnpublishPageUseCase } from "webiny/api/website-builder/scheduler"; +``` + +**Interface `ScheduleUnpublishPageUseCase.Interface`:** + +```typescript +interface ScheduleUnpublishPageUseCase.Interface { + execute(params: IScheduleUnpublishPageUseCaseParams): IScheduleUnpublishPageUseCaseResponse; +} +``` + +**Types:** + +```typescript +namespace ScheduleUnpublishPageUseCase { + type Interface = IScheduleUnpublishPageUseCase; + type Error = ScheduleActionError; + type Params = IScheduleUnpublishPageUseCaseParams; + type Result = IScheduleUnpublishPageUseCaseResponse; +} +``` + +## `ScheduleUnpublishRedirectUseCase` + +**Use Case Abstraction** — imported from `webiny/api/website-builder/scheduler` + +```typescript +import { ScheduleUnpublishRedirectUseCase } from "webiny/api/website-builder/scheduler"; +``` + +**Interface `ScheduleUnpublishRedirectUseCase.Interface`:** + +```typescript +interface ScheduleUnpublishRedirectUseCase.Interface { + execute( + params: IScheduleUnpublishRedirectUseCaseParams + ): IScheduleUnpublishRedirectUseCaseResponse; +} +``` + +**Types:** + +```typescript +namespace ScheduleUnpublishRedirectUseCase { + type Interface = IScheduleUnpublishRedirectUseCase; + type Error = ScheduleActionError; + type Params = IScheduleUnpublishRedirectUseCaseParams; + type Result = IScheduleUnpublishRedirectUseCaseResponse; +} +``` diff --git a/docs/developer-docs/6.x/reference/cli/overview.ai.txt b/docs/developer-docs/6.x/reference/cli.ai.txt similarity index 88% rename from docs/developer-docs/6.x/reference/cli/overview.ai.txt rename to docs/developer-docs/6.x/reference/cli.ai.txt index e4b07e228..7f9600287 100644 --- a/docs/developer-docs/6.x/reference/cli/overview.ai.txt +++ b/docs/developer-docs/6.x/reference/cli.ai.txt @@ -1,7 +1,7 @@ -AI Context: CLI (reference/cli/index.mdx) +AI Context: CLI (reference/cli.mdx) Source of Information: -1. packages/webiny/src/cli/index.ts — barrel re-export file +1. packages/webiny/src/cli.ts — barrel re-export file 2. /Users/adrian/dev/wby-next/packages/cli-core/src/abstractions/services/LoggerService.ts — originating source 3. /Users/adrian/dev/wby-next/packages/cli-core/src/abstractions/services/UiService.ts — originating source @@ -14,7 +14,7 @@ Key Documentation Decisions: Exported Symbols: Logger, Ui -Import Path: webiny/cli/index +Import Path: webiny/cli Related Documents: - docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions diff --git a/docs/developer-docs/6.x/reference/cli/overview.mdx b/docs/developer-docs/6.x/reference/cli.mdx similarity index 77% rename from docs/developer-docs/6.x/reference/cli/overview.mdx rename to docs/developer-docs/6.x/reference/cli.mdx index 25b435229..23d17eb36 100644 --- a/docs/developer-docs/6.x/reference/cli/overview.mdx +++ b/docs/developer-docs/6.x/reference/cli.mdx @@ -1,7 +1,7 @@ --- -id: y2xpl2lu +id: y2xp0000 title: CLI -description: "CLI-scoped Logger and Ui abstractions" +description: "Reference for webiny/cli" --- import { Alert } from "@/components/Alert"; @@ -9,14 +9,14 @@ import { SymbolList } from "@/components/SymbolList"; -- What is exported from `webiny/cli/index`? +- What is exported from `webiny/cli`? - How to import and use each exported item? ## Overview -This page documents everything exported from `webiny/cli/index`. Import any of the items below directly from this path in your Webiny extensions. +This page documents everything exported from `webiny/cli`. Import any of the items below directly from this path in your Webiny extensions. -- What is exported from `webiny/infra/index`? +- What is exported from `webiny/infra`? - How to import and use each exported item? ## Overview -This page documents everything exported from `webiny/infra/index`. Import any of the items below directly from this path in your Webiny extensions. +This page documents everything exported from `webiny/infra`. Import any of the items below directly from this path in your Webiny extensions. types—never throw errors directly +- Read operations (getEntry, listEntries) default to Read API (published content only) +- preview: true parameter switches read operations to Preview API (includes unpublished/draft content) +- Write operations (create, update, publish, unpublish, delete) always use Manage API +- TypeScript generic provides type safety for entry.values field +- fields parameter controls response shape—use "values.fieldId" for entry fields, "id"/"createdOn" etc. for metadata +- Revision IDs have format "entryId#revisionNumber" (e.g., "abc123#0001") +- Entry lifecycle: create (draft) → updateEntryRevision (optional) → publishEntryRevision (public) → unpublishEntryRevision (back to draft) or deleteEntryRevision (soft/permanent delete) + +Code Patterns: +```typescript +// Initialization +import { Webiny } from "@webiny/sdk"; +const sdk = new Webiny({ token, endpoint, tenant }); + +// Type-safe query +interface Product { name: string; price: number; } +const result = await sdk.cms.listEntries({ + modelId: "product", + fields: ["id", "values.name", "values.price"] +}); + +// Result pattern +if (result.isOk()) { + const products = result.value.data; // CmsEntryData[] +} else { + console.error(result.error.message); +} + +// Create + publish workflow +const createResult = await sdk.cms.createEntry({ + modelId: "product", + data: { values: { name: "Laptop", price: 1299 } }, + fields: ["id", "entryId"] +}); + +if (createResult.isOk()) { + await sdk.cms.publishEntryRevision({ + modelId: "product", + revisionId: createResult.value.id!, + fields: ["id", "status"] + }); +} + +// Filtering and sorting +const result = await sdk.cms.listEntries({ + modelId: "product", + where: { "values.price_gte": 100 }, + sort: { "values.name": "asc" }, + limit: 20, + fields: ["id", "values.name", "values.price"] +}); + +// Pagination +if (result.isOk() && result.value.meta.hasMoreItems) { + const nextResult = await sdk.cms.listEntries({ + modelId: "product", + after: result.value.meta.cursor, + fields: ["id", "values.name"] + }); +} + +// Reference field resolution +const result = await sdk.cms.getEntry({ + modelId: "product", + where: { entryId: "abc123" }, + fields: [ + "id", + "values.name", + "values.category.id", + "values.category.values.name" + ] +}); +``` + +Related Documents: +- reference/sdk/webiny.mdx — Webiny class initialization and configuration +- reference/sdk/result.mdx — Result pattern details (isOk(), isFail(), value, error) +- reference/sdk/errors.mdx — Error types (HttpError, GraphQLError, NetworkError) +- core-concepts/webiny-sdk.mdx — SDK overview, installation, authentication +- headless-cms/using-webiny-sdk.mdx — Practical SDK usage examples + +Key Code Locations: +- packages/sdk/src/CmsSdk.ts — CmsSdk class definition +- packages/sdk/src/methods/cms/*.ts — Individual method implementations +- packages/sdk/src/methods/cms/cmsTypes.ts — Type definitions + +Tone Guidelines: +- Technical reference tone — concise, complete, API-focused +- Method signature blocks before each parameter table +- Parameter tables: name, type, required, description columns +- Minimal prose—let signatures and tables speak +- Examples show complete working code with type annotations +- Error handling always demonstrated (isOk() checks) +- Use TypeScript generics in all examples for type safety demonstration +- Emphasize Result pattern throughout—never suggest throwing/catching errors +- "When true/false" instead of "if true/false" for boolean parameter descriptions +- Active voice for method descriptions: "Retrieves", "Creates", "Publishes", "Deletes" \ No newline at end of file diff --git a/docs/developer-docs/6.x/reference/sdk/cms.mdx b/docs/developer-docs/6.x/reference/sdk/cms.mdx new file mode 100644 index 000000000..9c3545310 --- /dev/null +++ b/docs/developer-docs/6.x/reference/sdk/cms.mdx @@ -0,0 +1,644 @@ +--- +id: c2rrl2nt +title: CMS +description: CmsSdk class for querying and mutating Headless CMS entries from external applications +--- + +import { Alert } from "@/components/Alert"; + + + +- How to query entries from the Headless CMS using `sdk.cms`? +- How to create, update, publish, and delete CMS entries? +- How to use TypeScript generics for type-safe entry data? +- How to handle the Result pattern in CMS operations? + + + +## Overview + +The `CmsSdk` class provides methods for interacting with Headless CMS entries from external applications. Access it via `sdk.cms` on a `Webiny` instance. All read operations use the Read API by default (published content only), while write operations use the Manage API. Methods return `Result` objects—check for success with `isOk()` before accessing values. + +**Read Methods** + +- [`getEntry`](#get-entry) — fetch a single entry by ID or filter +- [`listEntries`](#list-entries) — list entries with filtering, sorting, and pagination + +**Write Methods** + +- [`createEntry`](#create-entry) — create a draft entry +- [`updateEntryRevision`](#update-entry-revision) — update specific fields on a revision +- [`publishEntryRevision`](#publish-entry-revision) — publish a revision to the Read API +- [`unpublishEntryRevision`](#unpublish-entry-revision) — revert a revision to draft +- [`deleteEntryRevision`](#delete-entry-revision) — delete a revision + +### CmsSdk + +The `CmsSdk` class is instantiated automatically when you create a `Webiny` instance. Access it via the `cms` property. + +```typescript +import { Webiny } from "@webiny/sdk"; + +const sdk = new Webiny({ + token: process.env.WEBINY_API_TOKEN!, + endpoint: process.env.WEBINY_API_ENDPOINT!, + tenant: "root" +}); + +// Access CMS methods +const result = await sdk.cms.listEntries({ + modelId: "product", + fields: ["id", "values.name"] +}); +``` + +### getEntry + +Retrieves a single entry from the CMS by ID, entry ID, or custom field values. + +```typescript +async getEntry( + params: GetEntryParams +): Promise, HttpError | GraphQLError | NetworkError>> +``` + +#### Parameters + +| Name | Type | Required | Description | +| ---------------------- | ------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------- | +| `params` | `GetEntryParams` | Yes | Parameters for retrieving the entry | +| `params.modelId` | `string` | Yes | The model ID of the entry to retrieve | +| `params.where` | `GetEntryWhere` | Yes | Filter conditions for finding the entry | +| `params.where.id` | `string` | No | The revision ID (e.g., `"abc123#0001"`) | +| `params.where.entryId` | `string` | No | The entry ID (e.g., `"abc123"`) | +| `params.where.values` | `Record` | No | Filter by entry field values | +| `params.fields` | `string[]` | Yes | Fields to include in response. Use `"values.fieldId"` for entry values or top-level fields like `"id"`, `"createdOn"` | +| `params.preview` | `boolean` | No | When `true`, uses Preview API to access unpublished/draft content. When `false` (default), uses Read API for published content only | + +#### Return Type + +`Result, HttpError | GraphQLError | NetworkError>` + +Returns a `Result` containing the entry data on success or an error on failure. + +#### Example + +```typescript +import type { CmsEntryData } from "@webiny/sdk"; + +interface Product { + name: string; + price: number; +} + +const result = await sdk.cms.getEntry({ + modelId: "product", + where: { entryId: "abc123" }, + fields: ["id", "entryId", "values.name", "values.price"] +}); + +if (result.isOk()) { + const product = result.value; + console.log(product.values.name); // string + console.log(product.values.price); // number +} +``` + +### listEntries + +Lists entries from the CMS with support for filtering, sorting, pagination, and full-text search. + +```typescript +async listEntries( + params: ListEntriesParams +): Promise, HttpError | GraphQLError | NetworkError>> +``` + +#### Parameters + +| Name | Type | Required | Description | +| ---------------- | --------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------- | +| `params` | `ListEntriesParams` | Yes | Parameters for listing entries | +| `params.modelId` | `string` | Yes | The model ID of entries to list | +| `params.where` | `Record` | No | Filter conditions using operators like `_eq`, `_gt`, `_contains`, etc. | +| `params.sort` | `Record` | No | Sort configuration (e.g., `{ "values.name": "asc" }`) | +| `params.limit` | `number` | No | Maximum number of entries to return (default: `10`) | +| `params.after` | `string` | No | Cursor for pagination from previous response | +| `params.search` | `string` | No | Full-text search term to filter entries across searchable fields (text, longText fields with `fullTextSearch` enabled) | +| `params.fields` | `string[]` | Yes | Fields to include in response. Use `"values.fieldId"` for entry values or top-level fields like `"id"`, `"createdOn"` | +| `params.preview` | `boolean` | No | When `true`, uses Preview API to access unpublished/draft content. When `false` (default), uses Read API for published content only | + +#### Return Type + +`Result, HttpError | GraphQLError | NetworkError>` + +Returns a `Result` containing an object with: + +- `data`: Array of `CmsEntryData` objects +- `meta`: Pagination metadata (`cursor`, `hasMoreItems`, `totalCount`) + +#### Example + +```typescript +interface Product { + name: string; + price: number; + inStock: boolean; +} + +const result = await sdk.cms.listEntries({ + modelId: "product", + where: { + "values.price_gte": 100, + "values.inStock": true + }, + sort: { "values.name": "asc" }, + limit: 20, + fields: ["id", "entryId", "values.name", "values.price"] +}); + +if (result.isOk()) { + const { data, meta } = result.value; + console.log(`Found ${meta.totalCount} products`); + + for (const product of data) { + console.log(product.values.name, product.values.price); + } + + if (meta.hasMoreItems) { + // Fetch next page using meta.cursor + } +} +``` + +### createEntry + +Creates a new entry in the CMS. The entry is created in draft status—call `publishEntryRevision` to make it publicly visible. + +```typescript +async createEntry( + params: CreateEntryParams +): Promise, HttpError | GraphQLError | NetworkError>> +``` + +#### Parameters + +| Name | Type | Required | Description | +| ---------------- | ----------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------- | +| `params` | `CreateEntryParams` | Yes | Parameters for creating the entry | +| `params.modelId` | `string` | Yes | The model ID for the entry | +| `params.data` | `CreateCmsEntryData` | Yes | The entry data to create. Must include `values` object with field data | +| `params.fields` | `string[]` | Yes | Fields to include in response. Use `"values.fieldId"` for entry values or top-level fields like `"id"`, `"createdOn"` | + +#### Return Type + +`Result, HttpError | GraphQLError | NetworkError>` + +Returns a `Result` containing the created entry data on success or an error on failure. + +#### Example + +```typescript +interface Product { + name: string; + price: number; + description: string; +} + +const result = await sdk.cms.createEntry({ + modelId: "product", + data: { + values: { + name: "Laptop", + price: 1299, + description: "High-performance laptop" + } + }, + fields: ["id", "entryId", "status", "values.name"] +}); + +if (result.isOk()) { + const product = result.value; + console.log(`Created entry: ${product.id}`); + console.log(`Status: ${product.status}`); // "draft" +} +``` + +### updateEntryRevision + +Updates an existing entry revision in the CMS. Only the specified fields in `data.values` are modified—other fields remain unchanged. + +```typescript +async updateEntryRevision( + params: UpdateEntryRevisionParams +): Promise, HttpError | GraphQLError | NetworkError>> +``` + +#### Parameters + +| Name | Type | Required | Description | +| ------------------- | ------------------------------------ | -------- | --------------------------------------------------------------------------------------------------------------------- | +| `params` | `UpdateEntryRevisionParams` | Yes | Parameters for updating the entry revision | +| `params.modelId` | `string` | Yes | The model ID for the entry | +| `params.revisionId` | `string` | Yes | The revision ID of the entry to update (e.g., `"abc123#0001"`) | +| `params.data` | `UpdateCmsEntryData` | Yes | The updated entry data. Use `values` for field updates | +| `params.fields` | `string[]` | Yes | Fields to include in response. Use `"values.fieldId"` for entry values or top-level fields like `"id"`, `"createdOn"` | + +#### Return Type + +`Result, HttpError | GraphQLError | NetworkError>` + +Returns a `Result` containing the updated entry data on success or an error on failure. + +#### Example + +```typescript +interface Product { + price: number; +} + +const result = await sdk.cms.updateEntryRevision({ + modelId: "product", + revisionId: "abc123#0001", + data: { + values: { + price: 1199 // Only update price field + } + }, + fields: ["id", "revisionId", "values.price"] +}); + +if (result.isOk()) { + console.log(`Updated price: ${result.value.values.price}`); +} +``` + +### publishEntryRevision + +Publishes an entry revision, making it available via the Read API. Published entries are visible to public consumers of your content. + +```typescript +async publishEntryRevision( + params: PublishEntryRevisionParams +): Promise, HttpError | GraphQLError | NetworkError>> +``` + +#### Parameters + +| Name | Type | Required | Description | +| ------------------- | ---------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------- | +| `params` | `PublishEntryRevisionParams` | Yes | Parameters for publishing the entry revision | +| `params.modelId` | `string` | Yes | The model ID of the entry to publish | +| `params.revisionId` | `string` | Yes | The revision ID of the entry to publish (e.g., `"abc123#0001"`) | +| `params.fields` | `string[]` | Yes | Fields to include in response. Use `"values.fieldId"` for entry values or top-level fields like `"id"`, `"createdOn"` | + +#### Return Type + +`Result, HttpError | GraphQLError | NetworkError>` + +Returns a `Result` containing the published entry data on success or an error on failure. + +#### Example + +```typescript +const result = await sdk.cms.publishEntryRevision({ + modelId: "product", + revisionId: "abc123#0001", + fields: ["id", "status", "values.name"] +}); + +if (result.isOk()) { + console.log(`Status: ${result.value.status}`); // "published" +} +``` + +### unpublishEntryRevision + +Unpublishes an entry revision, reverting it to draft status and removing it from the Read API. + +```typescript +async unpublishEntryRevision( + params: UnpublishEntryRevisionParams +): Promise, HttpError | GraphQLError | NetworkError>> +``` + +#### Parameters + +| Name | Type | Required | Description | +| ------------------- | ------------------------------ | -------- | --------------------------------------------------------------------------------------------------------------------- | +| `params` | `UnpublishEntryRevisionParams` | Yes | Parameters for unpublishing the entry revision | +| `params.modelId` | `string` | Yes | The model ID of the entry to unpublish | +| `params.revisionId` | `string` | Yes | The revision ID of the entry to unpublish (e.g., `"abc123#0001"`) | +| `params.fields` | `string[]` | Yes | Fields to include in response. Use `"values.fieldId"` for entry values or top-level fields like `"id"`, `"createdOn"` | + +#### Return Type + +`Result, HttpError | GraphQLError | NetworkError>` + +Returns a `Result` containing the unpublished entry data on success or an error on failure. + +#### Example + +```typescript +const result = await sdk.cms.unpublishEntryRevision({ + modelId: "product", + revisionId: "abc123#0001", + fields: ["id", "status"] +}); + +if (result.isOk()) { + console.log(`Status: ${result.value.status}`); // "unpublished" +} +``` + +### deleteEntryRevision + +Deletes an entry revision from the CMS. By default, performs a soft delete (entry can be restored). Pass `permanent: true` for permanent deletion. + +```typescript +async deleteEntryRevision( + params: DeleteEntryRevisionParams +): Promise> +``` + +#### Parameters + +| Name | Type | Required | Description | +| ------------------- | --------------------------- | -------- | -------------------------------------------------------------- | +| `params` | `DeleteEntryRevisionParams` | Yes | Parameters for deleting the entry revision | +| `params.modelId` | `string` | Yes | The model ID of the entry to delete | +| `params.revisionId` | `string` | Yes | The revision ID of the entry to delete (e.g., `"abc123#0001"`) | +| `params.permanent` | `boolean` | No | Whether to permanently delete the entry (default: `false`) | + +#### Return Type + +`Result` + +Returns a `Result` containing `true` on success or an error on failure. + +#### Example + +```typescript +// Soft delete (can be restored) +const result = await sdk.cms.deleteEntryRevision({ + modelId: "product", + revisionId: "abc123#0001" +}); + +if (result.isOk()) { + console.log("Entry deleted (soft delete)"); +} + +// Permanent delete +const permanentResult = await sdk.cms.deleteEntryRevision({ + modelId: "product", + revisionId: "abc123#0001", + permanent: true +}); + +if (permanentResult.isOk()) { + console.log("Entry permanently deleted"); +} +``` + +## Types + +### CmsEntryValues + +Base type for entry field values. Extend this interface to define your content model structure. + +```typescript +interface CmsEntryValues { + [key: string]: any; +} +``` + +### CmsEntryData + +Type representing a complete CMS entry with metadata and field values. + +```typescript +interface CmsEntryData { + id?: string; + entryId?: string; + status?: CmsEntryStatus; + + // Entry-level metadata + createdOn?: Date | string; + modifiedOn?: Date | string | null; + savedOn?: Date | string; + createdBy?: CmsIdentity; + modifiedBy?: CmsIdentity; + savedBy?: CmsIdentity; + firstPublishedOn?: Date | string; + lastPublishedOn?: Date | string; + firstPublishedBy?: CmsIdentity; + lastPublishedBy?: CmsIdentity; + + // Revision-level metadata + revisionCreatedOn?: Date | string; + revisionSavedOn?: Date | string; + revisionCreatedBy?: CmsIdentity; + revisionSavedBy?: CmsIdentity; + + location?: { + folderId?: string | null; + }; + + values?: TValues; +} +``` + +### CmsEntryStatus + +Entry publication status. + +```typescript +type CmsEntryStatus = "published" | "unpublished" | "draft"; +``` + +### CmsIdentity + +User identity information in entry metadata. + +```typescript +interface CmsIdentity { + id: string; + displayName: string; + type: string; +} +``` + +## Practical Examples + +### List with Filter, Sort, and Pagination + +```typescript +import type { CmsEntryData } from "@webiny/sdk"; + +interface Product { + name: string; + price: number; + category: string; +} + +async function fetchProducts(cursor?: string) { + const result = await sdk.cms.listEntries({ + modelId: "product", + where: { + "values.price_gte": 100, + "values.category": "electronics" + }, + sort: { "values.price": "asc" }, + limit: 20, + after: cursor, + fields: ["id", "entryId", "values.name", "values.price", "values.category"] + }); + + if (result.isFail()) { + console.error("Error:", result.error.message); + return; + } + + const { data, meta } = result.value; + + for (const product of data) { + console.log(`${product.values.name}: $${product.values.price}`); + } + + if (meta.hasMoreItems) { + await fetchProducts(meta.cursor); + } +} +``` + +### Get Entry by ID + +```typescript +interface Author { + name: string; + bio: string; + email: string; +} + +const result = await sdk.cms.getEntry({ + modelId: "author", + where: { entryId: "xyz789" }, + fields: ["id", "entryId", "createdOn", "values.name", "values.bio", "values.email"] +}); + +if (result.isOk()) { + const author = result.value; + console.log(`Author: ${author.values.name}`); + console.log(`Created: ${author.createdOn}`); +} +``` + +### Create and Publish Flow + +```typescript +interface BlogPost { + title: string; + content: string; + slug: string; +} + +// Step 1: Create draft entry +const createResult = await sdk.cms.createEntry({ + modelId: "blogPost", + data: { + values: { + title: "Getting Started with Webiny", + content: "This is the post content...", + slug: "getting-started" + } + }, + fields: ["id", "entryId", "status"] +}); + +if (createResult.isFail()) { + console.error("Create failed:", createResult.error.message); + return; +} + +const draft = createResult.value; +console.log(`Created draft: ${draft.id}`); + +// Step 2: Publish the entry +const publishResult = await sdk.cms.publishEntryRevision({ + modelId: "blogPost", + revisionId: draft.id!, + fields: ["id", "status"] +}); + +if (publishResult.isOk()) { + console.log(`Published: ${publishResult.value.id}`); +} +``` + +### TypeScript Generics Usage + +```typescript +import type { CmsEntryData } from "@webiny/sdk"; + +interface Product { + name: string; + price: number; + category: CmsEntryData; +} + +interface ProductCategory { + name: string; + slug: string; +} + +const result = await sdk.cms.getEntry({ + modelId: "product", + where: { entryId: "abc123" }, + fields: [ + "id", + "values.name", + "values.price", + "values.category.id", + "values.category.values.name", + "values.category.values.slug" + ] +}); + +if (result.isOk()) { + const product = result.value; + + // Full type safety with autocomplete + const name: string = product.values.name; + const price: number = product.values.price; + const categoryName: string = product.values.category.values.name; +} +``` + +### Error Handling Pattern + +```typescript +const result = await sdk.cms.getEntry({ + modelId: "product", + where: { entryId: "nonexistent" }, + fields: ["id", "values.name"] +}); + +if (result.isFail()) { + const error = result.error; + + if (error.name === "GraphQLError") { + console.error("GraphQL Error:", error.message); + console.error("Error Code:", error.code); + } else if (error.name === "HttpError") { + console.error("HTTP Error:", error.statusCode); + } else if (error.name === "NetworkError") { + console.error("Network Error:", error.message); + } + + return; +} + +// Safe to access value +const product = result.value; +``` diff --git a/docs/developer-docs/6.x/reference/sdk/file-manager.ai.txt b/docs/developer-docs/6.x/reference/sdk/file-manager.ai.txt new file mode 100644 index 000000000..0f3515512 --- /dev/null +++ b/docs/developer-docs/6.x/reference/sdk/file-manager.ai.txt @@ -0,0 +1,157 @@ +AI Context: File Manager (reference/sdk/file-manager.mdx) + +Source of Information: +1. FileManagerSdk.ts — class definition with all method signatures +2. methods/fileManager/getFile.ts — single file retrieval implementation +3. methods/fileManager/listFiles.ts — file listing with search, where, sort, pagination +4. methods/fileManager/createFile.ts — file creation with upload support (small/large files) +5. methods/fileManager/createFiles.ts — bulk file creation with concurrent uploads +6. methods/fileManager/updateFile.ts — file metadata update +7. methods/fileManager/deleteFile.ts — file deletion +8. methods/fileManager/listTags.ts — tag listing with counts +9. methods/fileManager/getPresignedPostPayload.ts — presigned POST URL for browser uploads +10. methods/fileManager/getPresignedPostPayloads.ts — bulk presigned POST URLs +11. methods/fileManager/createMultiPartUpload.ts — multipart upload initiation for large files +12. methods/fileManager/completeMultiPartUpload.ts — multipart upload completion +13. methods/fileManager/fileManagerTypes.ts — all type definitions + +Key Documentation Decisions: +1. Grouped methods into logical sections: Reading (get/list), Creating/Updating (CRUD), Upload Helpers (presigned/multipart) +2. Documented all method parameters in param tables with Required column +3. Included return types showing Result pattern with specific error types +4. Provided complete type reference section for key interfaces +5. Examples show both simple cases (metadata only) and complex cases (file upload, multipart, batch) +6. Highlighted automatic upload strategy selection (small vs large files) based on multiPartThreshold +7. Documented both fail-fast and continue strategies for batch operations +8. Showed complete flow for presigned POST and multipart upload patterns + +File Manager SDK Understanding: +- `FileManagerSdk` handles file metadata operations (CRUD) and upload orchestration +- File uploads happen in two stages: (1) upload to S3 via presigned URL, (2) create metadata record +- Small files (<100MB default) use simple presigned POST; large files use multipart upload +- `createFile()` intelligently selects upload strategy based on file size +- `createFiles()` uses p-map for controlled concurrency (default: 5 concurrent uploads) +- Presigned POST URLs allow direct browser→S3 uploads without proxying through API +- Multipart uploads split large files into chunks, upload in parallel, then finalize with completeMultiPartUpload +- All file operations return Result pattern — check isOk() before accessing value +- Fields parameter controls which properties are returned (same as CMS SDK pattern) +- Tags are freeform strings; listTags returns usage counts across all files +- File location uses folderId to organize files in hierarchical structure + +Code Patterns: +1. **Simple file retrieval:** + ```typescript + const result = await sdk.fileManager.getFile({ + id: "file-id", + fields: ["id", "name", "src", "size"] + }); + ``` + +2. **List with search and filters:** + ```typescript + const result = await sdk.fileManager.listFiles({ + fields: ["id", "name", "src"], + search: "logo", + where: { type_in: ["image/png", "image/jpeg"] }, + limit: 10, + sort: ["savedOn_DESC"] + }); + ``` + +3. **File upload (automatic strategy):** + ```typescript + const result = await sdk.fileManager.createFile({ + file: fileBlob, + data: { name: "photo.jpg", type: "image/jpeg" }, + fields: ["id", "src"], + onProgress: (p) => console.log(`${p.percentage}%`) + }); + ``` + +4. **Presigned POST upload (manual):** + ```typescript + // 1. Get presigned POST payload + const presigned = await sdk.fileManager.getPresignedPostPayload({ + name: "file.jpg", + type: "image/jpeg", + size: 102400 + }); + + // 2. Upload to S3 + const formData = new FormData(); + Object.entries(presigned.value.data.fields).forEach(([k, v]) => { + formData.append(k, v); + }); + formData.append("file", fileBlob); + await fetch(presigned.value.data.url, { method: "POST", body: formData }); + + // 3. Create file record + await sdk.fileManager.createFile({ + data: { + id: presigned.value.file.id, + key: presigned.value.file.key, + // ... other metadata + }, + fields: ["id", "src"] + }); + ``` + +5. **Multipart upload:** + ```typescript + // 1. Create multipart upload + const upload = await sdk.fileManager.createMultiPartUpload({ + data: { name: "large.mp4", type: "video/mp4", size: 500000000 }, + numberOfParts: 10 + }); + + // 2. Upload each part + for (const part of upload.value.parts) { + const chunk = getChunk(part.partNumber - 1); + await fetch(part.url, { method: "PUT", body: chunk }); + } + + // 3. Complete upload + await sdk.fileManager.completeMultiPartUpload({ + fileKey: upload.value.file.key, + uploadId: upload.value.uploadId + }); + ``` + +6. **Batch upload with error handling:** + ```typescript + const result = await sdk.fileManager.createFiles({ + files: [ + { file: file1, data: { name: "1.jpg", type: "image/jpeg" }, fields: ["id"] }, + { file: file2, data: { name: "2.jpg", type: "image/jpeg" }, fields: ["id"] } + ], + concurrency: 3, + strategy: "continue" // continue on errors + }); + + if (result.isOk()) { + console.log(`Success: ${result.value.successful.length}`); + console.log(`Failed: ${result.value.failed.length}`); + } + ``` + +Related Documents: +- /docs/developer-docs/6.0.x/core-concepts/webiny-sdk.mdx — SDK overview and initialization +- /docs/developer-docs/6.0.x/headless-cms/using-webiny-sdk.mdx — CMS SDK usage patterns +- /docs/developer-docs/6.0.x/reference/sdk/cms.mdx — CMS SDK reference (sibling reference page) + +Key Code Locations: +- packages/sdk/src/FileManagerSdk.ts — main class definition +- packages/sdk/src/methods/fileManager/*.ts — all method implementations +- packages/sdk/src/methods/fileManager/utils/uploadToS3.ts — S3 upload helper +- packages/sdk/src/methods/fileManager/utils/uploadLargeFile.ts — multipart upload logic +- packages/sdk/src/methods/fileManager/fileManagerTypes.ts — type definitions + +Tone Guidelines: +- Technical reference style — concise, API-focused, minimal prose +- Every method gets: signature + param table + return type + example +- Examples are practical and production-ready (error handling, progress callbacks) +- Highlight automatic behaviors (upload strategy selection, concurrent limits) +- Type reference section uses code blocks for interfaces (not param tables) +- No analogies or conceptual explanations — save those for about.mdx (none exists yet) +- Assume reader knows Result pattern from core-concepts/result.mdx +- All examples show Result error checking with if (result.isOk()) \ No newline at end of file diff --git a/docs/developer-docs/6.x/reference/sdk/file-manager.mdx b/docs/developer-docs/6.x/reference/sdk/file-manager.mdx new file mode 100644 index 000000000..a6a2c3dd6 --- /dev/null +++ b/docs/developer-docs/6.x/reference/sdk/file-manager.mdx @@ -0,0 +1,698 @@ +--- +id: c2rrl2zp +title: File Manager +description: "FileManagerSdk: upload, retrieve, and manage files" +--- + +import { Alert } from "@/components/Alert"; + + + +- How to retrieve files and file metadata? +- How to upload files using presigned URLs? +- How to handle large file uploads with multipart upload? +- How to manage file records and tags? + + + +## Overview + +The `FileManagerSdk` provides methods for managing files in Webiny File Manager. Access it via `sdk.fileManager` on a `Webiny` instance. The SDK handles file metadata operations (create, read, update, delete) and provides helpers for uploading files to S3 using presigned URLs. For large files, multipart upload is supported automatically based on configurable size thresholds. + +## Reading Files + +### getFile + +Retrieves a single file by ID. + +```typescript +async getFile(params: GetFileParams): Promise> +``` + +**Parameters:** + +| Name | Type | Required | Description | +| --------------- | --------------- | -------- | -------------------------------------------------------- | +| `params` | `GetFileParams` | Yes | Parameters for getting the file | +| `params.id` | `string` | Yes | ID of the file to retrieve | +| `params.fields` | `string[]` | Yes | Fields to return (e.g., `["id", "name", "src", "size"]`) | + +**Returns:** + +`Result` — Result containing the file data or an error. + +**Example:** + +```typescript +const result = await sdk.fileManager.getFile({ + id: "67a8f2e1d26d020002c00456", + fields: ["id", "name", "src", "size", "type", "createdOn"] +}); + +if (result.isOk()) { + const file = result.value; + console.log(`File: ${file.name}, Size: ${file.size} bytes`); +} else { + console.error("Error:", result.error.message); +} +``` + +### listFiles + +Lists files with filtering, sorting, and pagination. + +```typescript +async listFiles(params: ListFilesParams): Promise> +``` + +**Parameters:** + +| Name | Type | Required | Description | +| --------------- | ---------------------- | -------- | ------------------------------------- | +| `params` | `ListFilesParams` | Yes | Parameters for listing files | +| `params.fields` | `string[]` | Yes | Fields to return for each file | +| `params.search` | `string` | No | Search query to filter files by name | +| `params.where` | `FmFileListWhereInput` | No | Filter conditions | +| `params.limit` | `number` | No | Maximum number of files to return | +| `params.after` | `string` | No | Cursor for pagination | +| `params.sort` | `FmFileListSorter[]` | No | Sort order (e.g., `["savedOn_DESC"]`) | + +**Returns:** + +`Result` — Result containing: + +- `data` — Array of `FmFile` objects +- `meta` — Pagination metadata (`cursor`, `hasMoreItems`, `totalCount`) + +**Example:** + +```typescript +const result = await sdk.fileManager.listFiles({ + fields: ["id", "name", "src", "size", "type", "tags"], + search: "logo", + where: { + type_in: ["image/png", "image/jpeg"], + tags_in: ["marketing"] + }, + limit: 10, + sort: ["savedOn_DESC"] +}); + +if (result.isOk()) { + const { data, meta } = result.value; + console.log(`Found ${data.length} files`); + + if (meta.hasMoreItems) { + console.log(`More items available. Cursor: ${meta.cursor}`); + } +} +``` + +**Available sort options:** + +- `savedOn_ASC` / `savedOn_DESC` +- `createdOn_ASC` / `createdOn_DESC` +- `name_ASC` / `name_DESC` +- `key_ASC` / `key_DESC` +- `type_ASC` / `type_DESC` +- `size_ASC` / `size_DESC` + +### listTags + +Lists all tags used on files with usage counts. + +```typescript +async listTags(params?: ListTagsParams): Promise> +``` + +**Parameters:** + +| Name | Type | Required | Description | +| ---------------------------------- | ---------------------- | -------- | ------------------------------------ | +| `params` | `ListTagsParams` | No | Parameters for listing tags | +| `params.where` | `FmTagsListWhereInput` | No | Filter conditions | +| `params.where.createdBy` | `string` | No | Filter by creator ID | +| `params.where.tags_startsWith` | `string` | No | Filter tags starting with prefix | +| `params.where.tags_not_startsWith` | `string` | No | Filter tags not starting with prefix | + +**Returns:** + +`Result` — Result containing array of tags with counts. + +**Example:** + +```typescript +const result = await sdk.fileManager.listTags({ + where: { + tags_startsWith: "prod" + } +}); + +if (result.isOk()) { + result.value.forEach(tag => { + console.log(`${tag.tag}: ${tag.count} files`); + }); +} +``` + +## Creating and Updating Files + +### createFile + +Creates a new file record in File Manager. If a file is provided, it uploads to S3 first using presigned POST (small files) or multipart upload (large files). + +```typescript +async createFile(params: CreateFileParams): Promise> +``` + +**Parameters:** + +| Name | Type | Required | Description | +| --------------------------- | ------------------------------------ | -------- | --------------------------------------------------- | +| `params` | `CreateFileParams` | Yes | Parameters for creating the file | +| `params.data` | `CreateFileData` | Yes | File metadata | +| `params.data.name` | `string` | Yes\* | File name | +| `params.data.type` | `string` | Yes\* | MIME type (e.g., `"image/png"`) | +| `params.data.size` | `number` | No | File size in bytes | +| `params.data.key` | `string` | No | Custom S3 key | +| `params.data.keyPrefix` | `string` | No | Custom key prefix | +| `params.data.location` | `FmLocationInput` | No | Folder location (`{ folderId: string }`) | +| `params.data.tags` | `string[]` | No | Tags for the file | +| `params.file` | `Buffer \| Blob \| File` | No | Actual file content to upload | +| `params.fields` | `string[]` | Yes | Fields to return for created file | +| `params.onProgress` | `(progress: UploadProgress) => void` | No | Upload progress callback | +| `params.multiPartThreshold` | `number` | No | Threshold in MB for multipart upload (default: 100) | +| `params.signal` | `AbortSignal` | No | AbortSignal for cancellation | + +\*Required when `file` is provided. + +**Returns:** + +`Result` — Result containing the created file data. + +**Example (metadata only):** + +```typescript +const result = await sdk.fileManager.createFile({ + data: { + name: "document.pdf", + type: "application/pdf", + size: 1024, + key: "files/document.pdf", + tags: ["legal", "contracts"] + }, + fields: ["id", "name", "key", "src"] +}); +``` + +**Example (with file upload):** + +```typescript +const file = new File([buffer], "photo.jpg", { type: "image/jpeg" }); + +const result = await sdk.fileManager.createFile({ + file, + data: { + name: "photo.jpg", + type: "image/jpeg", + location: { folderId: "root" }, + tags: ["photos"] + }, + fields: ["id", "name", "src", "size"], + onProgress: progress => { + console.log(`Upload progress: ${progress.percentage}%`); + } +}); + +if (result.isOk()) { + console.log(`File uploaded: ${result.value.src}`); +} +``` + +### createFiles + +Creates multiple file records in bulk with concurrent uploads. + +```typescript +async createFiles(params: CreateFilesParams): Promise> +``` + +**Parameters:** + +| Name | Type | Required | Description | +| --------------------------- | --------------------------------------------- | -------- | ------------------------------------------------------ | +| `params` | `CreateFilesParams` | Yes | Parameters for creating multiple files | +| `params.files` | `Array<{ file?, data, fields, onProgress? }>` | Yes | Array of files to create | +| `params.multiPartThreshold` | `number` | No | Threshold in MB for multipart upload (default: 100) | +| `params.concurrency` | `number` | No | Number of concurrent uploads (default: 5) | +| `params.strategy` | `BatchUploadStrategy` | No | `"fail-fast"` or `"continue"` (default: `"fail-fast"`) | +| `params.signal` | `AbortSignal` | No | AbortSignal for cancellation | + +**Returns:** + +`Result` — Result containing: + +- `successful` — Array of successfully created `FmFile` objects +- `failed` — Array of failed uploads with error details + +**Example:** + +```typescript +const result = await sdk.fileManager.createFiles({ + files: [ + { + file: file1, + data: { name: "image1.jpg", type: "image/jpeg" }, + fields: ["id", "name", "src"] + }, + { + file: file2, + data: { name: "image2.jpg", type: "image/jpeg" }, + fields: ["id", "name", "src"] + } + ], + concurrency: 3, + strategy: "continue" +}); + +if (result.isOk()) { + console.log(`Successful: ${result.value.successful.length}`); + console.log(`Failed: ${result.value.failed.length}`); + + result.value.failed.forEach(item => { + console.error(`Failed to upload ${item.data.name}:`, item.error.message); + }); +} +``` + +### updateFile + +Updates file metadata (does not re-upload file content). + +```typescript +async updateFile(params: UpdateFileParams): Promise> +``` + +**Parameters:** + +| Name | Type | Required | Description | +| ---------------------- | ------------------ | -------- | --------------------------------- | +| `params` | `UpdateFileParams` | Yes | Parameters for updating the file | +| `params.id` | `string` | Yes | ID of the file to update | +| `params.data` | `UpdateFileData` | Yes | Updated file metadata | +| `params.data.name` | `string` | No | Updated file name | +| `params.data.tags` | `string[]` | No | Updated tags | +| `params.data.location` | `FmLocationInput` | No | Updated folder location | +| `params.fields` | `string[]` | Yes | Fields to return for updated file | + +**Returns:** + +`Result` — Result containing the updated file data. + +**Example:** + +```typescript +const result = await sdk.fileManager.updateFile({ + id: "67a8f2e1d26d020002c00456", + data: { + name: "updated-name.jpg", + tags: ["archived", "2024"] + }, + fields: ["id", "name", "tags", "modifiedOn"] +}); +``` + +### deleteFile + +Deletes a file record from File Manager. + +```typescript +async deleteFile(params: DeleteFileParams): Promise> +``` + +**Parameters:** + +| Name | Type | Required | Description | +| ----------- | ------------------ | -------- | -------------------------------- | +| `params` | `DeleteFileParams` | Yes | Parameters for deleting the file | +| `params.id` | `string` | Yes | ID of the file to delete | + +**Returns:** + +`Result` — Result containing `true` on success. + +**Example:** + +```typescript +const result = await sdk.fileManager.deleteFile({ + id: "67a8f2e1d26d020002c00456" +}); + +if (result.isOk()) { + console.log("File deleted successfully"); +} +``` + +## Upload Helpers + +### getPresignedPostPayload + +Gets a presigned POST URL for uploading a file directly to S3 from a browser. + +```typescript +async getPresignedPostPayload(params: GetPresignedPostPayloadParams): Promise> +``` + +**Parameters:** + +| Name | Type | Required | Description | +| ------------------ | ------------------------------- | -------- | --------------------------------------------- | +| `params` | `GetPresignedPostPayloadParams` | Yes | Parameters for getting presigned POST payload | +| `params.name` | `string` | Yes | File name | +| `params.type` | `string` | Yes | MIME type | +| `params.size` | `number` | Yes | File size in bytes | +| `params.key` | `string` | No | Custom S3 key | +| `params.keyPrefix` | `string` | No | Custom key prefix | + +**Returns:** + +`Result` — Result containing: + +- `data` — Presigned POST payload with `url` and `fields` +- `file` — File metadata including generated `id` and `key` + +**Example:** + +```typescript +const result = await sdk.fileManager.getPresignedPostPayload({ + name: "upload.jpg", + type: "image/jpeg", + size: 102400 +}); + +if (result.isOk()) { + const { data, file } = result.value; + + // Upload to S3 using presigned POST + const formData = new FormData(); + Object.entries(data.fields).forEach(([key, value]) => { + formData.append(key, value); + }); + formData.append("file", fileBlob); + + await fetch(data.url, { + method: "POST", + body: formData + }); + + // Create file record after upload + await sdk.fileManager.createFile({ + data: { + id: file.id, + name: file.name, + type: file.type, + size: file.size, + key: file.key + }, + fields: ["id", "src"] + }); +} +``` + +### getPresignedPostPayloads + +Gets presigned POST URLs for multiple files in bulk. + +```typescript +async getPresignedPostPayloads(params: GetPresignedPostPayloadsParams): Promise> +``` + +**Parameters:** + +| Name | Type | Required | Description | +| -------------- | --------------------------------- | -------- | ---------------------------------------------- | +| `params` | `GetPresignedPostPayloadsParams` | Yes | Parameters for getting presigned POST payloads | +| `params.files` | `GetPresignedPostPayloadParams[]` | Yes | Array of file metadata | + +**Returns:** + +`Result` — Result containing array of presigned POST payloads. + +**Example:** + +```typescript +const result = await sdk.fileManager.getPresignedPostPayloads({ + files: [ + { name: "file1.jpg", type: "image/jpeg", size: 102400 }, + { name: "file2.jpg", type: "image/jpeg", size: 204800 } + ] +}); + +if (result.isOk()) { + result.value.forEach(({ data, file }) => { + console.log(`Upload URL for ${file.name}: ${data.url}`); + }); +} +``` + +### createMultiPartUpload + +Initiates a multipart upload for large files. + +```typescript +async createMultiPartUpload(params: CreateMultiPartUploadParams): Promise> +``` + +**Parameters:** + +| Name | Type | Required | Description | +| ----------------------- | ----------------------------- | -------- | ------------------------------------------------------- | +| `params` | `CreateMultiPartUploadParams` | Yes | Parameters for creating multipart upload | +| `params.data` | `object` | Yes | File metadata (same as `GetPresignedPostPayloadParams`) | +| `params.data.name` | `string` | Yes | File name | +| `params.data.type` | `string` | Yes | MIME type | +| `params.data.size` | `number` | Yes | File size in bytes | +| `params.data.key` | `string` | No | Custom S3 key | +| `params.data.keyPrefix` | `string` | No | Custom key prefix | +| `params.numberOfParts` | `number` | Yes | Number of parts to split file into | + +**Returns:** + +`Result` — Result containing: + +- `uploadId` — Upload ID for tracking +- `file` — File metadata including `id` and `key` +- `parts` — Array of presigned URLs for each part (`{ partNumber, url }`) + +**Example:** + +```typescript +const fileSize = 500 * 1024 * 1024; // 500 MB +const chunkSize = 50 * 1024 * 1024; // 50 MB chunks +const numberOfParts = Math.ceil(fileSize / chunkSize); + +const result = await sdk.fileManager.createMultiPartUpload({ + data: { + name: "large-file.mp4", + type: "video/mp4", + size: fileSize + }, + numberOfParts +}); + +if (result.isOk()) { + const { uploadId, file, parts } = result.value; + + // Upload each part to S3 + for (const part of parts) { + const chunk = getFileChunk(part.partNumber - 1, chunkSize); + await fetch(part.url, { + method: "PUT", + body: chunk + }); + } + + // Complete the upload + await sdk.fileManager.completeMultiPartUpload({ + fileKey: file.key, + uploadId + }); +} +``` + +### completeMultiPartUpload + +Completes a multipart upload after all parts are uploaded. + +```typescript +async completeMultiPartUpload(params: CompleteMultiPartUploadParams): Promise> +``` + +**Parameters:** + +| Name | Type | Required | Description | +| ----------------- | ------------------------------- | -------- | ----------------------------------------------- | +| `params` | `CompleteMultiPartUploadParams` | Yes | Parameters for completing multipart upload | +| `params.fileKey` | `string` | Yes | S3 key from `createMultiPartUpload` response | +| `params.uploadId` | `string` | Yes | Upload ID from `createMultiPartUpload` response | + +**Returns:** + +`Result` — Result containing `true` on success. + +**Example:** + +```typescript +const result = await sdk.fileManager.completeMultiPartUpload({ + fileKey: "files/67a8f2e1d26d020002c00456/large-file.mp4", + uploadId: "abc123xyz" +}); + +if (result.isOk()) { + console.log("Multipart upload completed"); + + // Create file record + await sdk.fileManager.createFile({ + data: { + id: fileId, + name: "large-file.mp4", + type: "video/mp4", + size: fileSize, + key: fileKey + }, + fields: ["id", "src"] + }); +} +``` + +## Type Reference + +### FmFile + +Represents a file in File Manager. + +```typescript +interface FmFile { + id: string; + createdOn: Date | string; + modifiedOn?: Date | string; + savedOn: Date | string; + createdBy: FmIdentity; + modifiedBy?: FmIdentity; + savedBy: FmIdentity; + location: FmLocation; + src?: string; + name?: string; + key?: string; + type?: string; + size?: number; + metadata?: FmFile_Metadata; + tags?: string[]; + accessControl?: FmFile_AccessControl; + [key: string]: any; +} +``` + +### FmTag + +Represents a tag with usage count. + +```typescript +interface FmTag { + tag: string; + count: number; +} +``` + +### FmListMeta + +Pagination metadata for list operations. + +```typescript +interface FmListMeta { + cursor: string | null; + hasMoreItems: boolean; + totalCount: number; +} +``` + +### FmFile_Metadata + +File metadata including image dimensions and EXIF data. + +```typescript +interface FmFile_Metadata { + image?: { + width?: number; + height?: number; + format?: string; + orientation?: number; + }; + exif?: Record; + iptc?: Record; + [key: string]: any; +} +``` + +### FmFile_AccessControl + +File access control settings. + +```typescript +type FmFile_AccessControl = { + type: "public" | "private-authenticated"; +}; +``` + +### PresignedPostPayloadResponse + +Response containing presigned POST data for S3 upload. + +```typescript +interface PresignedPostPayloadResponse { + data: { + url: string; + fields: Record; + }; + file: { + id: string; + name: string; + type: string; + size: number; + key: string; + }; +} +``` + +### MultiPartUploadResponse + +Response containing multipart upload data. + +```typescript +interface MultiPartUploadResponse { + uploadId: string; + file: { + id: string; + name: string; + type: string; + size: number; + key: string; + }; + parts: Array<{ + partNumber: number; + url: string; + }>; +} +``` + +### UploadProgress + +Upload progress callback data. + +```typescript +interface UploadProgress { + sent: number; + total: number; + percentage: number; +} +``` diff --git a/docs/developer-docs/6.x/reference/sdk/index.ai.txt b/docs/developer-docs/6.x/reference/sdk/index.ai.txt new file mode 100644 index 000000000..ce2ecaa48 --- /dev/null +++ b/docs/developer-docs/6.x/reference/sdk/index.ai.txt @@ -0,0 +1,140 @@ +AI Context: Overview (reference/sdk/index.mdx) + +Source of Information: +1. @webiny/sdk/src/index.ts - Main export file listing all public exports +2. @webiny/sdk/src/Webiny.ts - Main Webiny class implementation +3. @webiny/sdk/src/types.ts - WebinyConfig interface definition +4. @webiny/sdk/src/Result.ts - Result class implementation with generics and functional methods +5. @webiny/sdk/src/BaseError.ts - Abstract base error class +6. @webiny/sdk/src/errors.ts - HttpError, GraphQLError, NetworkError implementations +7. docs/developer-docs/6.0.x/core-concepts/webiny-sdk.mdx - Existing SDK overview doc +8. docs/developer-docs/6.0.x/headless-cms/using-webiny-sdk.mdx - SDK usage examples + +Key Documentation Decisions: +1. Page structure: Overview → Installation → Initialization → Quick Start → Webiny class → WebinyConfig → Result class → Error classes +2. WebinyConfig documented with all five properties (endpoint, token, tenant, headers, fetch) and their purposes +3. Result class documented with all static methods (ok, fail), instance methods (isOk, isFail, value, error, map, mapError, flatMap, match), and namespace types (UnwrapResult, UnwrapError) +4. Error classes documented with their specific properties (HttpError.data.status, GraphQLError.data.code) and example usage patterns +5. Quick Start section shows the most common pattern: initialize → call method → check isOk()/isFail() +6. Import path emphasized as @webiny/sdk (not webiny/*) — this is an external package +7. "Finding Your API Endpoint" alert preserved from existing docs +8. Error handling pattern documented with switch statement for all three error types + +Understanding the Webiny SDK Architecture: +- External package pattern: @webiny/sdk is installed via npm, not part of the Webiny monorepo extensions system +- Single entry point: Webiny class constructor instantiates CmsSdk, TenantManagerSdk, FileManagerSdk +- Singleton pattern recommended: create one instance, reuse throughout application +- Authentication: token-based using API key from Webiny Admin (Settings → API Keys) +- API selection: SDK internally chooses Read API vs Manage API based on operation (hidden from user) +- Result pattern: all async methods return Result instead of throwing — forces explicit error handling +- Error hierarchy: BaseError → HttpError/GraphQLError/NetworkError with discriminated code property +- Type safety: generic type parameters on Result allow full type inference for success/error paths + +Result Pattern Design: +- Inspired by functional programming (Either, Result types from Rust/Haskell) +- Two states: ok (success with value) or fail (failure with error) +- Type guards: isOk() and isFail() narrow types for safe value/error access +- Functional methods: map, mapError, flatMap for composition without explicit if checks +- Pattern matching: match() provides exhaustive handling of both cases +- Namespace utilities: UnwrapResult and UnwrapError extract inner types from Result + +WebinyConfig Properties: +- endpoint: base CloudFront URL (yarn webiny info shows this) — NOT the full /graphql path +- token: optional but required for authenticated operations (all CMS ops require it) +- tenant: defaults to "root" — multi-tenancy support +- headers: optional custom headers merged with defaults (authorization, content-type) +- fetch: optional custom fetch implementation (useful for testing, proxying, server-side rendering) + +Error Classes: +- HttpError: HTTP transport failures (404, 500, etc.) — has data.status number +- GraphQLError: API-level errors (validation, permissions) — has optional data.code string +- NetworkError: fetch itself failed (no connection, DNS failure) — no data property +- All have code property for switch statements +- All extend BaseError which has message, data, optional stack + +Code Patterns: + +## Initialize SDK (singleton): +```typescript +import { Webiny } from "@webiny/sdk"; + +export const sdk = new Webiny({ + token: process.env.WEBINY_API_TOKEN!, + endpoint: process.env.WEBINY_API_ENDPOINT!, + tenant: process.env.WEBINY_API_TENANT || "root" +}); +``` + +## Basic usage with Result: +```typescript +const result = await sdk.cms.listEntries({ modelId: "product" }); + +if (result.isOk()) { + const entries = result.value.data; +} else { + console.error(result.error.message); +} +``` + +## Error handling with discriminated code: +```typescript +if (result.isFail()) { + switch (result.error.code) { + case "HTTP_ERROR": + console.error(`HTTP ${result.error.data.status}`); + break; + case "GRAPHQL_ERROR": + console.error(`API error: ${result.error.data.code || "unknown"}`); + break; + case "NETWORK_ERROR": + console.error("Network failure"); + break; + } +} +``` + +## Result functional methods: +```typescript +const result = await sdk.cms.getEntry({ modelId: "product", entryId: "123" }); + +// map transforms success value +const nameResult = result.map(entry => entry.values.name); + +// mapError transforms error +const httpResult = result.mapError(e => new HttpError(500, e.message)); + +// flatMap chains Result-returning functions +const detailsResult = result.flatMap(entry => getDetails(entry.id)); + +// match handles both cases +const message = result.match({ + ok: entry => `Found: ${entry.values.name}`, + fail: error => `Error: ${error.message}` +}); +``` + +Related Documents: +- reference/sdk/cms-sdk.mdx - CmsSdk class reference (listEntries, getEntry, createEntry, etc.) +- reference/sdk/tenant-manager-sdk.mdx - TenantManagerSdk class reference +- reference/sdk/file-manager-sdk.mdx - FileManagerSdk class reference +- core-concepts/webiny-sdk.mdx - Conceptual overview of SDK (when to use, core concepts) +- headless-cms/using-webiny-sdk.mdx - Practical examples and patterns + +Key Code Locations: +- packages/sdk/src/Webiny.ts - Main class constructor and property initialization +- packages/sdk/src/types.ts - WebinyConfig interface +- packages/sdk/src/Result.ts - Result class with all methods +- packages/sdk/src/errors.ts - Error class definitions +- packages/sdk/src/CmsSdk.ts - CMS operations implementation +- packages/sdk/src/TenantManagerSdk.ts - Tenant operations implementation +- packages/sdk/src/FileManagerSdk.ts - File operations implementation + +Tone Guidelines: +- Type: Technical reference +- Audience: External developers integrating Webiny into their applications +- Voice: Concise, accurate, API-focused +- Structure: Method signatures → param tables → return types → minimal examples +- Focus: What each property/method does, not why or when to use it (that's in core-concepts/webiny-sdk.mdx) +- Examples: Minimal, type-safe, showing correct usage patterns +- Emphasis: Result pattern (every method returns Result), error handling (explicit isOk/isFail checks), type safety (generics) +- Cross-references: Link to sibling reference pages (cms-sdk, tenant-manager-sdk, file-manager-sdk) for module-specific APIs \ No newline at end of file diff --git a/docs/developer-docs/6.x/reference/sdk/index.mdx b/docs/developer-docs/6.x/reference/sdk/index.mdx new file mode 100644 index 000000000..5ea4bb7cc --- /dev/null +++ b/docs/developer-docs/6.x/reference/sdk/index.mdx @@ -0,0 +1,523 @@ +--- +id: c2rrl2lu +title: Overview +description: Webiny SDK configuration, Result pattern, and error classes +--- + +import { Alert } from "@/components/Alert"; + + + +- How to install and initialize the Webiny SDK? +- What is the `WebinyConfig` interface and its required fields? +- How does the `Result` pattern work for error handling? +- What error classes are available and when are they used? + + + +## Overview + +The Webiny SDK (`@webiny/sdk`) is a standalone TypeScript library that provides a programmatic interface for interacting with Webiny from external JavaScript or TypeScript applications. It is designed for use in Next.js, Node.js scripts, Vue, SvelteKit, or any JavaScript runtime outside the Webiny backend. Unlike internal Webiny extensions (which import from `webiny/*`), the SDK is installed via npm and imported from `@webiny/sdk`. + +All SDK methods return a `Result` type instead of throwing errors, making error handling explicit and predictable. The SDK automatically selects the correct API (Read or Manage) based on the operation and handles authentication using API key tokens. + +## Installation + +Install the SDK as a dependency in your project: + +```bash +npm install @webiny/sdk +``` + +## Initialization + +Create a singleton instance of the `Webiny` class and reuse it throughout your application: + +```typescript lib/webiny.ts +import { Webiny } from "@webiny/sdk"; + +export const sdk = new Webiny({ + token: process.env.WEBINY_API_TOKEN!, + endpoint: process.env.WEBINY_API_ENDPOINT!, + tenant: process.env.WEBINY_API_TENANT || "root" +}); +``` + +Store credentials in environment variables: + +```bash .env +WEBINY_API_TOKEN=your-api-token +WEBINY_API_ENDPOINT=https://xxx.cloudfront.net +WEBINY_API_TENANT=root +``` + + + +Run `yarn webiny info` in your Webiny project to find the API endpoint URL. Use the base CloudFront domain (e.g., `https://xxx.cloudfront.net`), not the full path with `/graphql`. + + + +## Quick Start + +```typescript +import { sdk } from "@/lib/webiny"; + +// List entries from a content model +const result = await sdk.cms.listEntries({ + modelId: "product", + fields: ["id", "entryId", "values.name", "values.price"] +}); + +// Check for errors using Result pattern +if (result.isOk()) { + const products = result.value.data; + console.log(`Found ${products.length} products`); +} else { + console.error("Error:", result.error.message); + console.error("Code:", result.error.code); +} +``` + +## Webiny Class + +The main entry point to the SDK. Create one instance per application and reuse it. + +### Constructor + +```typescript +constructor(config: WebinyConfig) +``` + +**Parameters:** + +| Name | Type | Required | Description | +| -------- | -------------- | -------- | ------------------------ | +| `config` | `WebinyConfig` | Yes | SDK configuration object | + +### Properties + +| Name | Type | Description | +| --------------- | ------------------ | ---------------------------- | +| `cms` | `CmsSdk` | Headless CMS operations | +| `tenantManager` | `TenantManagerSdk` | Tenant management operations | +| `fileManager` | `FileManagerSdk` | File Manager operations | + +**Example:** + +```typescript +import { Webiny } from "@webiny/sdk"; + +const sdk = new Webiny({ + token: "your-api-token", + endpoint: "https://xxx.cloudfront.net", + tenant: "root" +}); + +// Access different modules +const cmsResult = await sdk.cms.listEntries({ modelId: "product" }); +const fileResult = await sdk.fileManager.listFiles({ limit: 10 }); +``` + +## WebinyConfig Interface + +Configuration object passed to the `Webiny` constructor. + +### Properties + +| Name | Type | Required | Description | +| ---------- | ------------------------ | -------- | ---------------------------------------------------------------- | +| `endpoint` | `string` | Yes | Base URL of your Webiny API (e.g., `https://xxx.cloudfront.net`) | +| `token` | `string` | No | API key token from Webiny Admin (Settings → API Keys) | +| `tenant` | `string` | No | Tenant ID (defaults to `"root"`) | +| `headers` | `Record` | No | Custom HTTP headers to include in all requests | +| `fetch` | `typeof fetch` | No | Custom fetch implementation (useful for testing or proxying) | + +**Key points:** + +- `endpoint` must be the base domain, not the full GraphQL path +- `token` authenticates requests — API key must have appropriate permissions +- `tenant` defaults to `"root"` if omitted +- `headers` are merged with default headers (e.g., authorization, content-type) +- `fetch` allows custom implementations for testing or server-side rendering + +**Example:** + +```typescript +const sdk = new Webiny({ + endpoint: "https://xxx.cloudfront.net", + token: process.env.WEBINY_API_TOKEN, + tenant: "acme-corp", + headers: { + "X-Custom-Header": "value" + } +}); +``` + +## Result Class + +A container type representing either success (`ok`) or failure (`fail`). All SDK methods return `Result` instead of throwing errors. + +### Type Parameters + +| Name | Description | +| -------- | --------------------------------------- | +| `TValue` | Type of the success value | +| `TError` | Type of the error (defaults to `never`) | + +### Static Methods + +#### `Result.ok(value)` + +Creates a successful result containing the provided value. + +```typescript +public static ok(value: T): Result +public static ok(): Result +``` + +**Example:** + +```typescript +const success = Result.ok({ id: "123", name: "Product" }); +const voidSuccess = Result.ok(); +``` + +#### `Result.fail(error)` + +Creates a failed result containing the provided error. + +```typescript +public static fail(error: E): Result +``` + +**Example:** + +```typescript +const failure = Result.fail(new HttpError(404, "Not found")); +``` + +### Instance Methods + +#### `isOk()` + +Checks whether the result is successful. Acts as a type guard. + +```typescript +public isOk(): this is { _value: TValue } & Result +``` + +**Returns:** `true` if successful, `false` otherwise. + +**Example:** + +```typescript +if (result.isOk()) { + console.log(result.value); // Type-safe access to value +} +``` + +#### `isFail()` + +Checks whether the result is a failure. Acts as a type guard. + +```typescript +public isFail(): this is { _error: TError } & Result +``` + +**Returns:** `true` if failed, `false` otherwise. + +**Example:** + +```typescript +if (result.isFail()) { + console.error(result.error.message); // Type-safe access to error +} +``` + +#### `value` + +Gets the value from a successful result. + +```typescript +public get value(): TValue +``` + +**Throws:** Error if the result is a failure. + +**Example:** + +```typescript +if (result.isOk()) { + const data = result.value; // Safe after isOk() check +} +``` + +#### `error` + +Gets the error from a failed result. + +```typescript +public get error(): TError +``` + +**Throws:** Error if the result is successful. + +**Example:** + +```typescript +if (result.isFail()) { + const error = result.error; // Safe after isFail() check +} +``` + +#### `map(fn)` + +Transforms the success value using the provided function. If the result is a failure, returns the original error. + +```typescript +public map(fn: (value: TValue) => U): Result +``` + +**Parameters:** + +| Name | Type | Description | +| ---- | ---------------------- | ------------------------------- | +| `fn` | `(value: TValue) => U` | Function to transform the value | + +**Returns:** New `Result` with transformed value or original error. + +**Example:** + +```typescript +const result = Result.ok(5); +const doubled = result.map(n => n * 2); // Result.ok(10) + +const failure = Result.fail(new Error("Oops")); +const stillFailure = failure.map(n => n * 2); // Still Result.fail(error) +``` + +#### `mapError(fn)` + +Transforms the error value using the provided function. If the result is successful, returns the original value. + +```typescript +public mapError(fn: (error: TError) => F): Result +``` + +**Parameters:** + +| Name | Type | Description | +| ---- | ---------------------- | ------------------------------- | +| `fn` | `(error: TError) => F` | Function to transform the error | + +**Returns:** New `Result` with original value or transformed error. + +**Example:** + +```typescript +const result = Result.fail(new Error("Not found")); +const httpError = result.mapError(e => new HttpError(404, e.message)); +``` + +#### `flatMap(fn)` + +Chains another Result-producing function onto this result. If successful, applies the function; if failed, returns the original error. + +```typescript +public flatMap(fn: (value: TValue) => Result): Result +``` + +**Parameters:** + +| Name | Type | Description | +| ---- | -------------------------------------- | --------------------------------- | +| `fn` | `(value: TValue) => Result` | Function returning another Result | + +**Returns:** New `Result` from the function or original failure. + +**Example:** + +```typescript +const getUser = (id: string) => Result.ok({ id, name: "Alice" }); +const getEmail = (user: { id: string }) => Result.ok(`${user.id}@example.com`); + +const result = getUser("123").flatMap(user => getEmail(user)); // Result.ok("123@example.com") +``` + +#### `match(handlers)` + +Pattern-matches the result to handle both success and failure cases. + +```typescript +public match(handlers: { + ok: (value: TValue) => U; + fail: (error: TError) => U +}): U +``` + +**Parameters:** + +| Name | Type | Description | +| ---------- | ---------------------------------------------------------- | ------------------------------------ | +| `handlers` | `{ ok: (value: TValue) => U; fail: (error: TError) => U }` | Object with success/failure handlers | + +**Returns:** Result of the appropriate handler. + +**Example:** + +```typescript +const message = result.match({ + ok: data => `Success: ${data.length} items`, + fail: error => `Error: ${error.message}` +}); +console.log(message); +``` + +### Namespace Types + +#### `Result.UnwrapResult` + +Extracts the success type from a `Result`. + +```typescript +type UnwrapResult = Awaited extends Result ? Ok : never; +``` + +**Example:** + +```typescript +type MyResult = Result; +type Value = Result.UnwrapResult; // string +``` + +#### `Result.UnwrapError` + +Extracts the error type from a `Result`. + +```typescript +type UnwrapError = Awaited extends Result ? Err : never; +``` + +**Example:** + +```typescript +type MyResult = Result; +type ErrorType = Result.UnwrapError; // HttpError +``` + +## Error Classes + +The SDK defines three error classes for different failure scenarios. All extend `BaseError` and include a `code` property for programmatic error handling. + +### HttpError + +HTTP-level errors (e.g., 404 Not Found, 500 Internal Server Error). + +```typescript +class HttpError extends BaseError<{ status: number }> +``` + +**Properties:** + +| Name | Type | Description | +| --------- | -------- | -------------------------- | +| `code` | `string` | Always `"HTTP_ERROR"` | +| `message` | `string` | Error message | +| `data` | `object` | Contains `status` property | + +**Example:** + +```typescript +const result = await sdk.cms.getEntry({ modelId: "product", entryId: "999" }); + +if (result.isFail() && result.error.code === "HTTP_ERROR") { + console.error(`HTTP ${result.error.data.status}: ${result.error.message}`); +} +``` + +### GraphQLError + +GraphQL-level errors returned by the API (e.g., validation errors, permission errors). + +```typescript +class GraphQLError extends BaseError<{ code?: string }> +``` + +**Properties:** + +| Name | Type | Description | +| --------- | -------- | ----------------------------------- | +| `code` | `string` | Always `"GRAPHQL_ERROR"` | +| `message` | `string` | Error message from GraphQL response | +| `data` | `object` | Contains optional `code` property | + +**Example:** + +```typescript +const result = await sdk.cms.createEntry({ + modelId: "product", + data: { values: {} } +}); + +if (result.isFail() && result.error.code === "GRAPHQL_ERROR") { + console.error(`GraphQL error: ${result.error.message}`); + if (result.error.data.code) { + console.error(`Error code: ${result.error.data.code}`); + } +} +``` + +### NetworkError + +Network-level errors when the fetch request itself fails (e.g., no internet connection, DNS resolution failure). + +```typescript +class NetworkError extends BaseError +``` + +**Properties:** + +| Name | Type | Description | +| --------- | -------- | ------------------------ | +| `code` | `string` | Always `"NETWORK_ERROR"` | +| `message` | `string` | Error message | + +**Example:** + +```typescript +const result = await sdk.cms.listEntries({ modelId: "product" }); + +if (result.isFail() && result.error.code === "NETWORK_ERROR") { + console.error("Network error - check your connection"); +} +``` + +### Error Handling Pattern + +Use a switch or if-else chain to handle specific error types: + +```typescript +const result = await sdk.cms.getEntry({ + modelId: "product", + entryId: "abc123" +}); + +if (result.isFail()) { + switch (result.error.code) { + case "HTTP_ERROR": + if (result.error.data.status === 404) { + console.error("Entry not found"); + } + break; + case "GRAPHQL_ERROR": + console.error("API error:", result.error.message); + break; + case "NETWORK_ERROR": + console.error("Network failure - retry later"); + break; + } + return; +} + +const entry = result.value; +``` diff --git a/docs/developer-docs/6.x/reference/sdk/tenant-manager.ai.txt b/docs/developer-docs/6.x/reference/sdk/tenant-manager.ai.txt new file mode 100644 index 000000000..8fb234ea6 --- /dev/null +++ b/docs/developer-docs/6.x/reference/sdk/tenant-manager.ai.txt @@ -0,0 +1,78 @@ +AI Context: Tenant Manager (reference/sdk/tenant-manager.mdx) + +Source of Information: +1. TenantManagerSdk.ts - Class definition with all four methods +2. methods/tenantManager/createTenant.ts - createTenant implementation and types +3. methods/tenantManager/installTenant.ts - installTenant implementation +4. methods/tenantManager/disableTenant.ts - disableTenant implementation +5. methods/tenantManager/enableTenant.ts - enableTenant implementation +6. methods/tenantManager/tenantManagerTypes.ts - CreateTenantInput interface +7. AGENTS.md - Documentation conventions for SDK reference pages + +Key Documentation Decisions: +1. Emphasized the two-step create+install flow as the primary use case +2. Documented all four methods with consistent structure: signature, params table, returns, example +3. Included complete examples section showing: full provisioning flow, disable/enable, error handling +4. Highlighted that API key needs tenant manager permissions +5. Used Result pattern consistently across all examples +6. Kept method descriptions concise - no duplicate explanation between method signature and params table + +Understanding of Tenant Manager SDK: +- TenantManagerSdk is accessed via sdk.tenantManager namespace +- Four operations: createTenant, installTenant, disableTenant, enableTenant +- Creating a tenant is a two-step process: create registers the tenant, install provisions it +- All methods return Result +- Tenant ID can be auto-generated (omit id field) or explicitly set +- Disabled tenants block all access until re-enabled +- All operations require tenant manager permissions on the API key + +Method Signatures and Parameters: +```typescript +// createTenant +interface CreateTenantParams { + data: CreateTenantInput; +} +interface CreateTenantInput { + id?: string; // Optional - generated if omitted + name: string; // Required + description?: string; +} + +// installTenant +interface InstallTenantParams { + tenantId: string; // Required - must match created tenant +} + +// disableTenant +interface DisableTenantParams { + tenantId: string; // Required +} + +// enableTenant +interface EnableTenantParams { + tenantId: string; // Required +} +``` + +Return Types: +- All methods: Result +- Success: result.value is true +- Failure: result.error contains message and code + +Related Documents: +1. core-concepts/webiny-sdk.mdx - SDK initialization, authentication, Result pattern +2. core-concepts/result.mdx - Result type usage and error handling +3. tenant-manager/*.mdx - Multi-tenancy concepts and management +4. reference/sdk/headless-cms.mdx - Similar SDK reference structure + +Key Code Locations: +- packages/sdk/src/TenantManagerSdk.ts - Class definition +- packages/sdk/src/methods/tenantManager/ - All tenant manager method implementations + +Tone Guidelines: +- Technical reference tone - concise, accurate, no filler +- Method descriptions are brief - implementation details left to examples +- Params tables complete and precise +- Examples show real-world patterns: full flows, error handling, common operations +- Emphasize required permissions and two-step provisioning flow +- No analogies - direct technical explanation only \ No newline at end of file diff --git a/docs/developer-docs/6.x/reference/sdk/tenant-manager.mdx b/docs/developer-docs/6.x/reference/sdk/tenant-manager.mdx new file mode 100644 index 000000000..2c030199b --- /dev/null +++ b/docs/developer-docs/6.x/reference/sdk/tenant-manager.mdx @@ -0,0 +1,337 @@ +--- +id: c2rrl3rl +title: Tenant Manager +description: TenantManagerSdk reference - create and manage tenants programmatically +--- + +import { Alert } from "@/components/Alert"; + + + +- How to access the Tenant Manager SDK? +- How to create and install new tenants? +- How to disable and enable existing tenants? +- How to handle tenant management errors? + + + +## Overview + +The `TenantManagerSdk` provides methods for creating, installing, disabling, and enabling tenants programmatically. Access it via the `tenantManager` namespace on your Webiny SDK instance. Creating a new tenant requires two steps: `createTenant()` to register the tenant, then `installTenant()` to provision its resources and configurations. + +All tenant management operations require an API key with tenant manager permissions. + +## Class Reference + +### TenantManagerSdk + +The Tenant Manager SDK is accessed via `sdk.tenantManager` on a `Webiny` instance: + +```typescript +import { Webiny } from "@webiny/sdk"; + +const sdk = new Webiny({ + token: process.env.WEBINY_API_TOKEN!, + endpoint: process.env.WEBINY_API_ENDPOINT!, + tenant: "root" +}); + +// Access tenant manager operations +const result = await sdk.tenantManager.createTenant({ + data: { + name: "Acme Corp", + description: "Acme Corporation tenant" + } +}); +``` + +## Methods + +### createTenant + +Creates a new tenant in the system. Returns the tenant ID on success. + +```typescript +async createTenant( + params: CreateTenantParams +): Promise> +``` + +**Parameters:** + +| Name | Type | Required | Description | +| ------------------------- | -------------------- | -------- | --------------------------------------- | +| `params` | `CreateTenantParams` | Yes | Tenant creation parameters | +| `params.data` | `CreateTenantInput` | Yes | Tenant data | +| `params.data.id` | `string` | No | Custom tenant ID (generated if omitted) | +| `params.data.name` | `string` | Yes | Tenant name | +| `params.data.description` | `string` | No | Tenant description | + +**Returns:** + +`Result` - Success returns `true`, failure returns error with message and code. + +**Example:** + +```typescript +const result = await sdk.tenantManager.createTenant({ + data: { + id: "acme", + name: "Acme Corp", + description: "Acme Corporation tenant" + } +}); + +if (result.isFail()) { + console.error("Failed to create tenant:", result.error.message); + return; +} + +console.log("Tenant created successfully"); +``` + +### installTenant + +Installs and provisions a tenant with default settings and configurations. Must be called after `createTenant()` before the tenant is usable. + +```typescript +async installTenant( + params: InstallTenantParams +): Promise> +``` + +**Parameters:** + +| Name | Type | Required | Description | +| ----------------- | --------------------- | -------- | --------------------------- | +| `params` | `InstallTenantParams` | Yes | Installation parameters | +| `params.tenantId` | `string` | Yes | ID of the tenant to install | + +**Returns:** + +`Result` - Success returns `true`, failure returns error with message and code. + +**Example:** + +```typescript +const result = await sdk.tenantManager.installTenant({ + tenantId: "acme" +}); + +if (result.isFail()) { + console.error("Failed to install tenant:", result.error.message); + return; +} + +console.log("Tenant installed successfully"); +``` + +### disableTenant + +Disables a tenant, preventing access to its resources. Disabled tenants cannot be accessed until re-enabled. + +```typescript +async disableTenant( + params: DisableTenantParams +): Promise> +``` + +**Parameters:** + +| Name | Type | Required | Description | +| ----------------- | --------------------- | -------- | --------------------------- | +| `params` | `DisableTenantParams` | Yes | Disable parameters | +| `params.tenantId` | `string` | Yes | ID of the tenant to disable | + +**Returns:** + +`Result` - Success returns `true`, failure returns error with message and code. + +**Example:** + +```typescript +const result = await sdk.tenantManager.disableTenant({ + tenantId: "acme" +}); + +if (result.isFail()) { + console.error("Failed to disable tenant:", result.error.message); + return; +} + +console.log("Tenant disabled successfully"); +``` + +### enableTenant + +Re-enables a previously disabled tenant, restoring access to its resources. + +```typescript +async enableTenant( + params: EnableTenantParams +): Promise> +``` + +**Parameters:** + +| Name | Type | Required | Description | +| ----------------- | -------------------- | -------- | -------------------------- | +| `params` | `EnableTenantParams` | Yes | Enable parameters | +| `params.tenantId` | `string` | Yes | ID of the tenant to enable | + +**Returns:** + +`Result` - Success returns `true`, failure returns error with message and code. + +**Example:** + +```typescript +const result = await sdk.tenantManager.enableTenant({ + tenantId: "acme" +}); + +if (result.isFail()) { + console.error("Failed to enable tenant:", result.error.message); + return; +} + +console.log("Tenant enabled successfully"); +``` + +## Error Handling + +All tenant manager methods return a `Result` type. Check for errors before accessing the value: + +```typescript +const result = await sdk.tenantManager.createTenant({ + data: { + name: "Acme Corp" + } +}); + +if (result.isFail()) { + console.error("Error:", result.error.message); + console.error("Code:", result.error.code); + return; +} + +// Success - result.value is true +console.log("Operation successful"); +``` + +**Common error scenarios:** + +- Permission denied (API key lacks tenant manager permissions) +- Tenant already exists (duplicate tenant ID) +- Tenant not found (invalid tenant ID) +- Network errors (API unreachable) + +## Examples + +### Creating and Installing a New Tenant + +The complete flow for provisioning a new tenant requires two steps: + +```typescript +import { Webiny } from "@webiny/sdk"; + +const sdk = new Webiny({ + token: process.env.WEBINY_API_TOKEN!, + endpoint: process.env.WEBINY_API_ENDPOINT!, + tenant: "root" +}); + +// Step 1: Create the tenant +const createResult = await sdk.tenantManager.createTenant({ + data: { + id: "acme", + name: "Acme Corp", + description: "Acme Corporation tenant" + } +}); + +if (createResult.isFail()) { + console.error("Failed to create tenant:", createResult.error.message); + return; +} + +console.log("Tenant created successfully"); + +// Step 2: Install the tenant +const installResult = await sdk.tenantManager.installTenant({ + tenantId: "acme" +}); + +if (installResult.isFail()) { + console.error("Failed to install tenant:", installResult.error.message); + return; +} + +console.log("Tenant installed and ready to use"); +``` + +### Disabling and Enabling a Tenant + +```typescript +// Disable a tenant +const disableResult = await sdk.tenantManager.disableTenant({ + tenantId: "acme" +}); + +if (disableResult.isFail()) { + console.error("Failed to disable tenant:", disableResult.error.message); + return; +} + +console.log("Tenant disabled - access blocked"); + +// Later, re-enable the tenant +const enableResult = await sdk.tenantManager.enableTenant({ + tenantId: "acme" +}); + +if (enableResult.isFail()) { + console.error("Failed to enable tenant:", enableResult.error.message); + return; +} + +console.log("Tenant re-enabled - access restored"); +``` + +### Error Handling Pattern + +```typescript +async function provisionTenant(tenantId: string, name: string) { + // Create tenant + const createResult = await sdk.tenantManager.createTenant({ + data: { id: tenantId, name } + }); + + if (createResult.isFail()) { + return { + success: false, + error: `Create failed: ${createResult.error.message}` + }; + } + + // Install tenant + const installResult = await sdk.tenantManager.installTenant({ + tenantId + }); + + if (installResult.isFail()) { + return { + success: false, + error: `Install failed: ${installResult.error.message}` + }; + } + + return { success: true }; +} + +// Usage +const result = await provisionTenant("acme", "Acme Corp"); +if (!result.success) { + console.error(result.error); +} +``` diff --git a/docs/developer-docs/6.x/website-builder/multi-tenant-nextjs.ai.txt b/docs/developer-docs/6.x/website-builder/multi-tenant-nextjs.ai.txt index 831803a1b..b82e77955 100644 --- a/docs/developer-docs/6.x/website-builder/multi-tenant-nextjs.ai.txt +++ b/docs/developer-docs/6.x/website-builder/multi-tenant-nextjs.ai.txt @@ -13,6 +13,7 @@ Key Documentation Decisions: 4. Subdomain resolution is the example strategy — article makes clear other strategies (domain table, path prefix, cookie) are equally valid 5. Per-tenant theming kept as brief conceptual section — implementation is project-specific (requires custom fields on tenant model) 6. Universal API key recommended as default — Pavel confirmed this is a supported approach +7. ApiKeyFactory extension pattern added to show how to programmatically provision the universal key — token set as NEXT_PUBLIC_WEBSITE_BUILDER_API_KEY in Next.js env 7. Did not document the webinyApi.js GraphQL utility from presales — too project-specific 8. ContentSdkInitializer is a client component wrapping initializeContentSdk; passes tenantId from server layout to browser side diff --git a/docs/developer-docs/6.x/website-builder/multi-tenant-nextjs.mdx b/docs/developer-docs/6.x/website-builder/multi-tenant-nextjs.mdx index 242d5e9c4..15bd163c3 100644 --- a/docs/developer-docs/6.x/website-builder/multi-tenant-nextjs.mdx +++ b/docs/developer-docs/6.x/website-builder/multi-tenant-nextjs.mdx @@ -12,6 +12,7 @@ import { Alert } from "@/components/Alert"; - How to resolve tenant identity from the incoming request - How to initialize the SDK with the correct tenant per request - Which API key strategy fits multi-tenant deployments +- How to fetch per-tenant brand colors server-side and inject them as CSS custom properties @@ -185,18 +186,18 @@ import { ContentSdkInitializer, getTenant } from "@/src/contentSdk"; import { getTheme } from "@/src/theme"; export default async function RootLayout({ children }: { children: React.ReactNode }) { - const tenantId = await getTenant(); - const { isEnabled } = await draftMode(); - const { theme } = await getTheme(); - - return ( - - - - {children} - - - ); + const tenantId = await getTenant(); + const { isEnabled } = await draftMode(); + const { theme } = await getTheme(); + + return ( + + + + {children} + + + ); } ``` @@ -212,16 +213,127 @@ Two approaches work for multi-tenant deployments: For most SaaS deployments, a universal key is the simpler and recommended starting point. +### Creating a Universal API Key + +A universal API key must be provisioned programmatically via the `ApiKeyFactory` extension. This factory runs when Webiny boots and ensures the key exists in the root tenant with the permissions you specify. + +Create the factory file: + +```typescript extensions/security/universalApiKey.ts +import { ApiKeyFactory } from "webiny/api/security"; + +class UniversalApiKeyImpl implements ApiKeyFactory.Interface { + async execute(): ApiKeyFactory.Return { + return [ + { + name: "Universal API Key", + slug: "universal-key", + token: "wat_12345678", + permissions: [{ name: "*" }] + } + ]; + } +} + +export default ApiKeyFactory.createImplementation({ + implementation: UniversalApiKeyImpl, + dependencies: [] +}); +``` + +Register it in `webiny.config.tsx`: + +```tsx webiny.config.tsx +import React from "react"; +import { Api } from "webiny/extensions"; + +export const Extensions = () => { + return ( + <> + {/* ... your other extensions */} + + + ); +}; +``` + +Set the `token` value as `NEXT_PUBLIC_WEBSITE_BUILDER_API_KEY` in your Next.js environment: + +``` +NEXT_PUBLIC_WEBSITE_BUILDER_API_KEY=wat_12345678 +``` + + + +Store the token value in a secret manager and inject it at deploy time. Do not commit the raw token to source control. The `permissions: [{ name: "*" }]` grant gives full read access across all tenants — use a more restrictive permission set if your deployment requires it. + + + ## Per-Tenant Theming -The Website Builder supports per-tenant theming — each tenant can have its own fonts, colors, and CSS variables managed through Webiny Admin. In the root layout, fetch the tenant's theme configuration from the Webiny API and merge it with your static base theme before passing it to `ContentSdkInitializer` and injecting it into ``. +Each tenant can carry its own brand colors stored as custom fields on the Webiny tenant model (e.g. `primaryColor`, `secondaryColor`). The recommended pattern is to fetch them server-side in your page component using `@webiny/sdk`, then inject them into `` as CSS custom properties — available on the very first render with no client-side flash. + +### Initialize the Webiny SDK + +Create a singleton `Sdk` instance using the same environment variables as the Website Builder SDK: + +```typescript src/lib/webiny.ts +import { Sdk } from "@webiny/sdk"; + +export const sdk = new Sdk({ + token: process.env.NEXT_PUBLIC_WEBSITE_BUILDER_API_KEY!, + endpoint: process.env.NEXT_PUBLIC_WEBSITE_BUILDER_API_HOST!, + tenant: process.env.NEXT_PUBLIC_WEBSITE_BUILDER_API_TENANT ?? "root" +}); +``` + +### Fetch and inject theme colors + +Add a server-side helper that calls `sdk.tenantManager.getCurrentTenant()`, reads the custom `extensions.theme` object, and builds a `:root` CSS rule: ```typescript -// Conceptual example — implementation details depend on your data model. -const tenantId = await getTenant(); -const { theme } = await getTheme(); // static base theme -const dynamicTheme = await fetchTenantTheme(tenantId); // per-tenant overrides from Webiny API -const mergedTheme = mergeThemes(theme, dynamicTheme); +async function getTenantThemeCss(): Promise { + const result = await sdk.tenantManager.getCurrentTenant(); + if (!result.isOk()) { + return ""; + } + const theme = ((result.value.values.extensions as any)?.theme ?? {}) as { + primaryColor?: string; + secondaryColor?: string; + }; + const primary = theme.primaryColor || "#000000"; + const secondary = theme.secondaryColor || "#000000"; + return `:root { --fub-primary-color: ${primary}; --fub-secondary-color: ${secondary}; }`; +} +``` + +Call it in parallel with your page fetch and inject the result as a `} + + + ); +} ``` -The per-tenant theme data (font family, primary color, etc.) is stored as custom fields on the tenant model in Webiny and fetched via GraphQL with the `X-Tenant` header. +### Use the CSS variables in components + +Any client component can now reference the variables directly — no props, no context: + +```tsx + +``` + +The custom properties are set on `:root` before any React hydration, so the correct tenant colors are always visible on first paint. + + + +The `extensions.theme` object is populated via a custom tenant model extension in Webiny Admin. The field names (`primaryColor`, `secondaryColor`, etc.) depend on how your extension is defined. Cast `values.extensions` to your own typed interface when reading it. + + diff --git a/package.json b/package.json index e14f4c5b2..390c7507b 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,11 @@ "lint:fix": "yarn format && yarn eslint", "get-id": "node -e 'console.log(require(\"@webiny/utils\").mdbid().slice(-8))'", "validate:mdx": "tsx scripts/validate-mdx-pairing.ts", - "generate:reference": "tsx scripts/generate-reference.ts" + "generate:reference": "tsx scripts/generate-reference.ts", + "generate:reference:ai": "tsx scripts/ref/sdk.ts", + "generate:reference:ai:force": "tsx scripts/ref/sdk.ts --force", + "generate:sdk": "tsx scripts/ref/webiny-sdk.ts", + "generate:sdk:force": "tsx scripts/ref/webiny-sdk.ts --force" }, "browserslist": { "development": [ @@ -99,6 +103,7 @@ "wts": "https://github.com/webiny/wts#ae82e59470d79dc448a74239bf9d2328f4b93499" }, "devDependencies": { + "@anthropic-ai/sdk": "^0.80.0", "@types/jest": "^29.5.4", "@types/react": "^18.3.28", "@types/react-dom": "^18.3.7", diff --git a/scripts/ref/_shared.ts b/scripts/ref/_shared.ts new file mode 100644 index 000000000..9e8c51a91 --- /dev/null +++ b/scripts/ref/_shared.ts @@ -0,0 +1,698 @@ +/** + * Shared utilities for the AI-powered reference generator. + * + * - Source collection (ts-morph barrel parsing + symbol extraction) + * - Claude API caller + * - Navigation rewriter + * - Common types + */ + +import { readFileSync, writeFileSync, existsSync } from "fs"; +import { join, dirname } from "path"; +import { Project, SourceFile, SyntaxKind, Node } from "ts-morph"; +import Anthropic from "@anthropic-ai/sdk"; + +// --------------------------------------------------------------------------- +// Config +// --------------------------------------------------------------------------- + +export const WEBINY_PKG = "/Users/adrian/dev/wby-next/packages/webiny"; +export const WEBINY_MONOREPO = "/Users/adrian/dev/wby-next/packages"; +export const DOCS_ROOT = join(process.cwd(), "docs/developer-docs/6.x"); +export const REF_DIR = join(DOCS_ROOT, "reference"); +export const NAV_FILE = join(DOCS_ROOT, "navigation.tsx"); + +// --------------------------------------------------------------------------- +// Types +// --------------------------------------------------------------------------- + +export interface ExportEntry { + exportedName: string; + originalName: string; + sourceFile: string; + isTypeOnly: boolean; +} + +export interface SymbolDecl { + name: string; + kind: string; + isTypeOnly: boolean; + declarationText: string; + jsDoc: string; + sourceFile: string; +} + +export interface EntryPointSource { + /** e.g. "api/logger" */ + relPath: string; + /** e.g. "webiny/api/logger" */ + importPath: string; + /** Resolved symbols with declaration text */ + symbols: SymbolDecl[]; + /** Raw TypeScript source of all originating files (keyed by file path) */ + sourceFiles: Map; + /** Contents of an .examples.md file if found */ + examplesContent?: string; +} + +// --------------------------------------------------------------------------- +// Package path map +// --------------------------------------------------------------------------- + +let _pkgMap: Map | null = null; + +export function getPackagePathMap(): Map { + if (_pkgMap) return _pkgMap; + const entries = readFileSync(join(WEBINY_PKG, "tsconfig.json"), "utf-8"); + const cleaned = entries.replace(/\/\/[^\n]*/g, "").replace(/\/\*[\s\S]*?\*\//g, ""); + const tsconfig = JSON.parse(cleaned); + const paths: Record = tsconfig?.compilerOptions?.paths ?? {}; + const map = new Map(); + for (const [alias, targets] of Object.entries(paths)) { + if (!alias.startsWith("@webiny/")) continue; + const rawTarget = targets[0]; + if (!rawTarget) continue; + const resolved = join(WEBINY_PKG, rawTarget.replace(/\/\*$/, "").replace(/\*$/, "")); + const pkgAlias = alias.replace(/\/\*$/, ""); + map.set(pkgAlias, resolved); + } + _pkgMap = map; + return map; +} + +export function resolveWebinyImport( + importPath: string, + pkgMap: Map +): string | null { + for (const [alias, srcDir] of Array.from(pkgMap.entries())) { + if (importPath.startsWith(alias + "/")) { + const rest = importPath.slice(alias.length + 1).replace(/\.js$/, ".ts"); + return join(srcDir, rest); + } + if (importPath === alias) { + return join(srcDir, "index.ts"); + } + } + return null; +} + +export function resolveModuleSpecifier( + sf: SourceFile, + modSpec: string, + pkgMap: Map +): string | null { + if (modSpec.startsWith(".")) { + return join(sf.getDirectoryPath(), modSpec.replace(/\.js$/, ".ts")); + } + if (modSpec.startsWith("~/")) { + const parts = sf.getFilePath().split("/"); + const srcIdx = parts.lastIndexOf("src"); + if (srcIdx !== -1) { + const srcRoot = parts.slice(0, srcIdx + 1).join("/"); + return join(srcRoot, modSpec.slice(2).replace(/\.js$/, ".ts")); + } + return null; + } + return resolveWebinyImport(modSpec, pkgMap); +} + +// --------------------------------------------------------------------------- +// Barrel parsing +// --------------------------------------------------------------------------- + +export function parseBarrel(sf: SourceFile, pkgMap: Map): ExportEntry[] { + const entries: ExportEntry[] = []; + for (const decl of sf.getExportDeclarations()) { + const moduleSpecifier = decl.getModuleSpecifierValue(); + if (!moduleSpecifier) continue; + const resolvedPath = resolveWebinyImport(moduleSpecifier, pkgMap); + if (!resolvedPath) continue; + const isTypeOnly = decl.isTypeOnly(); + const namedExports = decl.getNamedExports(); + if (namedExports.length === 0) { + entries.push({ exportedName: "*", originalName: "*", sourceFile: resolvedPath, isTypeOnly }); + } else { + for (const ne of namedExports) { + entries.push({ + exportedName: ne.getAliasNode()?.getText() ?? ne.getNameNode().getText(), + originalName: ne.getNameNode().getText(), + sourceFile: resolvedPath, + isTypeOnly: isTypeOnly || ne.isTypeOnly() + }); + } + } + } + return entries; +} + +// --------------------------------------------------------------------------- +// Symbol extraction (signatures only, no bodies) +// --------------------------------------------------------------------------- + +function extractJsDoc(node: Node): string { + const jsDocNodes = node.getChildrenOfKind(SyntaxKind.JSDoc); + if (jsDocNodes.length === 0) return ""; + return jsDocNodes + .map(jd => jd.getInnerText().trim()) + .filter(Boolean) + .join("\n"); +} + +function isInternalNode(node: Node): boolean { + return node.getChildrenOfKind(SyntaxKind.JSDoc).some(jd => jd.getText().includes("@internal")); +} + +function stripBody(node: Node): string { + // For functions / constructors / methods: return everything up to the body block + const txt = node.getText(); + const body = (node as any).getBody ? (node as any).getBody() : null; + if (body) { + const bodyStart = body.getStart(); + const nodeStart = node.getStart(); + return txt.substring(0, bodyStart - nodeStart).trim(); + } + return txt.trim(); +} + +export function extractSymbolDecl(sf: SourceFile, name: string): SymbolDecl | null { + const allExported = sf.getExportedDeclarations(); + for (const [exportName, decls] of Array.from(allExported.entries())) { + if (exportName !== name || decls.length === 0) continue; + + const varDecl = decls.find(d => Node.isVariableDeclaration(d)); + const node = varDecl ?? decls[0]; + const jsDoc = extractJsDoc(node); + + if (Node.isInterfaceDeclaration(node)) { + // Strip @internal members + const members = node + .getMembers() + .filter(m => !isInternalNode(m)) + .map(m => " " + m.getText().trim()) + .join("\n"); + return { + name, + kind: "interface", + isTypeOnly: true, + declarationText: `interface ${node.getName()} {\n${members}\n}`, + jsDoc, + sourceFile: sf.getFilePath() + }; + } + + if (Node.isClassDeclaration(node)) { + const members = node + .getMembers() + .filter(m => !isInternalNode(m)) + .map(m => { + if (Node.isPropertyDeclaration(m)) { + return " " + m.getText().trim().replace(/;?$/, ";"); + } + if (Node.isConstructorDeclaration(m) || Node.isMethodDeclaration(m)) { + return " " + stripBody(m) + ";"; + } + return " " + m.getText().trim(); + }) + .filter(Boolean); + const head = node.getText().split("{")[0].trim(); + const body = members.length ? "\n" + members.join("\n") + "\n" : ""; + return { + name, + kind: "class", + isTypeOnly: false, + declarationText: `${head} {${body}}`, + jsDoc, + sourceFile: sf.getFilePath() + }; + } + + if (Node.isTypeAliasDeclaration(node)) { + return { + name, + kind: "type", + isTypeOnly: true, + declarationText: node.getText().trim(), + jsDoc, + sourceFile: sf.getFilePath() + }; + } + + if (Node.isEnumDeclaration(node)) { + return { + name, + kind: "enum", + isTypeOnly: false, + declarationText: node.getText().trim(), + jsDoc, + sourceFile: sf.getFilePath() + }; + } + + if (Node.isFunctionDeclaration(node)) { + return { + name, + kind: "function", + isTypeOnly: false, + declarationText: stripBody(node), + jsDoc, + sourceFile: sf.getFilePath() + }; + } + + if (Node.isVariableDeclaration(node)) { + // Check if it's a createAbstraction call + const initializer = node.getInitializer(); + const initText = initializer?.getText() ?? ""; + const isAbstraction = initText.includes("createAbstraction<"); + if (isAbstraction) { + // Get the full var statement for context, but just the signature + const parent = node.getParent(); + const gp = parent?.getParent(); + const declText = gp ? gp.getText().trim() : node.getText().trim(); + return { + name, + kind: "abstraction", + isTypeOnly: false, + declarationText: declText.slice(0, 500), + jsDoc, + sourceFile: sf.getFilePath() + }; + } + // Regular variable + const parent = node.getParent(); + const gp = parent?.getParent(); + return { + name, + kind: "variable", + isTypeOnly: false, + declarationText: (gp ? gp.getText() : node.getText()).trim().slice(0, 500), + jsDoc, + sourceFile: sf.getFilePath() + }; + } + + if (Node.isModuleDeclaration(node)) { + return { + name, + kind: "namespace", + isTypeOnly: true, + declarationText: node.getText().trim(), + jsDoc, + sourceFile: sf.getFilePath() + }; + } + + // Fallback + return { + name, + kind: "other", + isTypeOnly: false, + declarationText: node.getText().trim().slice(0, 300), + jsDoc, + sourceFile: sf.getFilePath() + }; + } + return null; +} + +// --------------------------------------------------------------------------- +// Examples file finder +// --------------------------------------------------------------------------- + +export function findExamplesContent(relPath: string): string | undefined { + const pkgMap = getPackagePathMap(); + + // Check alongside the barrel in @webiny/* packages + for (const [alias, srcDir] of Array.from(pkgMap.entries())) { + const pkgName = alias.replace("@webiny/", ""); + const exportsDir = join(WEBINY_MONOREPO, pkgName.replace(/-/g, "-"), "src", "exports"); + const candidate = join(exportsDir, relPath + ".examples.md"); + if (existsSync(candidate)) { + return readFileSync(candidate, "utf-8"); + } + } + + // Also check api-core specifically (most common location) + const apiCoreExports = join(WEBINY_MONOREPO, "api-core", "src", "exports"); + const candidate2 = join(apiCoreExports, relPath + ".examples.md"); + if (existsSync(candidate2)) { + return readFileSync(candidate2, "utf-8"); + } + + return undefined; +} + +// --------------------------------------------------------------------------- +// Collect all source content for an entry point +// --------------------------------------------------------------------------- + +export function collectEntryPointSource( + relPath: string, + project: Project, + pkgMap: Map +): EntryPointSource | null { + const barrelSrc = join(WEBINY_PKG, "src", relPath + ".ts"); + if (!existsSync(barrelSrc)) return null; + + let barrelFile: SourceFile; + try { + barrelFile = project.addSourceFileAtPath(barrelSrc); + } catch { + return null; + } + + const exportEntries = parseBarrel(barrelFile, pkgMap); + const symbols: SymbolDecl[] = []; + const sourceFiles = new Map(); + const loadedSfs = new Map(); + + for (const entry of exportEntries) { + if (entry.exportedName === "*") continue; + if (!existsSync(entry.sourceFile)) continue; + + let sourceSf = loadedSfs.get(entry.sourceFile); + if (!sourceSf) { + try { + sourceSf = project.addSourceFileAtPath(entry.sourceFile); + loadedSfs.set(entry.sourceFile, sourceSf); + } catch { + continue; + } + } + + // Collect raw source (once per file) + if (!sourceFiles.has(entry.sourceFile)) { + sourceFiles.set(entry.sourceFile, sourceSf.getFullText()); + } + + const sym = extractSymbolDecl(sourceSf, entry.originalName); + if (sym) { + symbols.push({ + ...sym, + name: entry.exportedName, + isTypeOnly: entry.isTypeOnly || sym.isTypeOnly + }); + } else { + symbols.push({ + name: entry.exportedName, + kind: "other", + isTypeOnly: entry.isTypeOnly, + declarationText: "", + jsDoc: "", + sourceFile: entry.sourceFile + }); + } + } + + const examplesContent = findExamplesContent(relPath); + + return { + relPath, + importPath: `webiny/${relPath}`, + symbols, + sourceFiles, + examplesContent + }; +} + +// --------------------------------------------------------------------------- +// Claude caller +// --------------------------------------------------------------------------- + +let _claude: Anthropic | null = null; +function getClaude(): Anthropic { + if (!_claude) { + const apiKey = process.env.ANTHROPIC_API_KEY; + if (!apiKey) throw new Error("ANTHROPIC_API_KEY environment variable is not set"); + _claude = new Anthropic({ apiKey }); + } + return _claude; +} + +export async function callClaude(systemPrompt: string, userPrompt: string): Promise { + const claude = getClaude(); + const message = await claude.messages.create({ + model: "claude-sonnet-4-5", + max_tokens: 8192, + messages: [{ role: "user", content: userPrompt }], + system: systemPrompt + }); + + const textBlock = message.content.find(b => b.type === "text"); + if (!textBlock || textBlock.type !== "text") throw new Error("No text in Claude response"); + return textBlock.text; +} + +// --------------------------------------------------------------------------- +// ID generation (stable, path-based) +// --------------------------------------------------------------------------- + +export function stableId(relPath: string): string { + return Buffer.from(relPath) + .toString("base64") + .replace(/[^a-z0-9]/gi, "") + .slice(0, 8) + .toLowerCase() + .padEnd(8, "0"); +} + +// --------------------------------------------------------------------------- +// Title helper +// --------------------------------------------------------------------------- + +const TITLE_MAP: Record = { + api: "API", + cms: "CMS", + graphql: "GraphQL", + ui: "UI", + aco: "ACO", + cli: "CLI", + infra: "Infrastructure", + extensions: "Extensions", + admin: "Admin", + index: "Overview", + "build-params": "Build Params", + "event-publisher": "Event Publisher", + "key-value-store": "Key-Value Store", + tenancy: "Tenancy", + security: "Security", + system: "System", + tasks: "Tasks", + logger: "Logger", + entry: "Entry", + group: "Group", + model: "Model", + field: "Field", + page: "Page", + redirect: "Redirect", + nextjs: "Next.js", + "api-key": "API Key", + authentication: "Authentication", + role: "Role", + user: "User", + lexical: "Lexical Editor", + form: "Form", + router: "Router", + "local-storage": "Local Storage", + "env-config": "Env Config", + "graphql-client": "GraphQL Client", + configs: "Configs", + "website-builder": "Website Builder", + "tenant-manager": "Tenant Manager", + command: "Command", + core: "Core", + scheduler: "Scheduler", + flp: "FLP", + folder: "Folder", + "file-manager": "File Manager", + "build-params-api": "API Build Params" +}; + +export function toTitle(relPath: string): string { + const parts = relPath.split("/"); + const last = parts[parts.length - 1]; + const section = TITLE_MAP[last] ?? last.replace(/-/g, " ").replace(/\b\w/g, c => c.toUpperCase()); + if (parts.length === 1) return section; + if (last === "index") { + const parent = parts[parts.length - 2]; + return TITLE_MAP[parent] ?? parent.replace(/-/g, " ").replace(/\b\w/g, c => c.toUpperCase()); + } + return section; +} + +export function toOutputPath(relPath: string): string { + const overrides: Record = { + "cli/index": "cli/overview", + "infra/index": "infra/overview", + cli: "cli/overview", + infra: "infra/overview" + }; + return overrides[relPath] ?? relPath; +} + +// --------------------------------------------------------------------------- +// Navigation rewriter +// --------------------------------------------------------------------------- + +interface NavPage { + link: string; + title?: string; +} + +interface NavGroup { + title: string; + link?: string; + pages: (NavPage | NavGroup)[]; +} + +function isNavGroup(item: NavPage | NavGroup): item is NavGroup { + return "pages" in item; +} + +const LAYER_ORDER = ["api", "admin", "cli", "infra", "extensions"]; +const LAYER_LANDING: Record = { + api: "reference/api", + admin: "reference/admin", + cli: "reference/cli/overview", + infra: "reference/infra/overview" +}; +const SUBDOMAIN_LANDING: Record = { + "api/cms": "reference/api/cms/entry", + "api/security": "reference/api/security", + "api/website-builder": "reference/api/website-builder/page", + "admin/cms": "reference/admin/cms", + "admin/website-builder": "reference/admin/website-builder" +}; + +function makeGroup(title: string, link: string): NavGroup & { link: string } { + return { title, link, pages: [] }; +} + +function buildNavTree(entryPoints: { relPath: string; title: string }[]): NavGroup { + const root: NavGroup = { title: "Reference", pages: [] }; + const byLayer = new Map(); + + for (const ep of entryPoints) { + const layer = ep.relPath.split("/")[0]; + if (!byLayer.has(layer)) byLayer.set(layer, []); + byLayer.get(layer)!.push(ep); + } + + const orderedLayers = Array.from(byLayer.keys()).sort((a, b) => { + const ai = LAYER_ORDER.indexOf(a); + const bi = LAYER_ORDER.indexOf(b); + if (ai === -1 && bi === -1) return a.localeCompare(b); + if (ai === -1) return 1; + if (bi === -1) return -1; + return ai - bi; + }); + + for (const layer of orderedLayers) { + const eps = byLayer.get(layer)!; + if (eps.length === 1) { + root.pages.push({ link: `reference/${toOutputPath(eps[0].relPath)}` }); + continue; + } + + const layerLanding = LAYER_LANDING[layer] ?? `reference/${toOutputPath(eps[0].relPath)}`; + const layerGroup = makeGroup(toTitle(layer), layerLanding); + + const SUB_DOMAINS = ["cms", "website-builder", "security", "file-manager", "aco"]; + const bySubDomain = new Map(); + const flat: typeof entryPoints = []; + const subDomainIndex = new Map(); + + for (const ep of eps) { + const parts = ep.relPath.split("/"); + if (parts.length === 2 && SUB_DOMAINS.includes(parts[1])) { + subDomainIndex.set(parts[1], ep); + } else if (parts.length >= 3 && SUB_DOMAINS.includes(parts[1])) { + const sub = parts[1]; + if (!bySubDomain.has(sub)) bySubDomain.set(sub, []); + bySubDomain.get(sub)!.push(ep); + } else { + flat.push(ep); + } + } + + const rootFlat = flat.filter( + ep => `reference/${toOutputPath(ep.relPath)}` === layerLanding || ep.relPath === layer + ); + const otherFlat = flat.filter(ep => !rootFlat.includes(ep)); + for (const ep of [...rootFlat, ...otherFlat]) { + const isRoot = rootFlat.includes(ep); + layerGroup.pages.push({ + link: `reference/${toOutputPath(ep.relPath)}`, + title: isRoot ? "Root" : ep.title + }); + } + + for (const [subDomain, subEps] of Array.from(bySubDomain.entries())) { + const key = `${layer}/${subDomain}`; + const subLanding = SUBDOMAIN_LANDING[key] ?? `reference/${toOutputPath(subEps[0].relPath)}`; + const subGroup = makeGroup(toTitle(subDomain), subLanding); + const indexEp = subDomainIndex.get(subDomain); + if (indexEp) + subGroup.pages.push({ link: `reference/${toOutputPath(indexEp.relPath)}`, title: "Root" }); + for (const ep of subEps) { + subGroup.pages.push({ link: `reference/${toOutputPath(ep.relPath)}`, title: ep.title }); + } + layerGroup.pages.push(subGroup); + } + + root.pages.push(layerGroup); + } + return root; +} + +function findFirstLink(group: NavGroup): string { + for (const p of group.pages) { + if (!isNavGroup(p)) return p.link; + const nested = findFirstLink(p); + if (nested) return nested; + } + return ""; +} + +function renderNavItem(item: NavPage | NavGroup, indent: number): string { + const pad = " ".repeat(indent); + if (isNavGroup(item)) { + const groupLink = (item as NavGroup & { link?: string }).link ?? findFirstLink(item); + const lines = [ + `${pad}`, + ...item.pages.map(p => renderNavItem(p, indent + 1)), + `${pad}` + ]; + return lines.join("\n"); + } + if (item.title) return `${pad}`; + return `${pad}`; +} + +const NAV_MARKER_START = " {/* __REFERENCE_PAGES_START__ */}"; +const NAV_MARKER_END = " {/* __REFERENCE_PAGES_END__ */}"; + +export function rewriteNavigation(entryPoints: { relPath: string; title: string }[]): void { + const nav = readFileSync(NAV_FILE, "utf-8"); + const tree = buildNavTree(entryPoints); + + const innerLines: string[] = []; + for (const page of tree.pages) { + innerLines.push(renderNavItem(page, 2)); + } + const inner = innerLines.join("\n"); + + const startIdx = nav.indexOf(NAV_MARKER_START); + const endIdx = nav.indexOf(NAV_MARKER_END); + + if (startIdx === -1 || endIdx === -1) { + console.warn(" [nav] Markers not found in navigation.tsx — skipping nav update"); + return; + } + + const before = nav.slice(0, startIdx + NAV_MARKER_START.length); + const after = nav.slice(endIdx); + const updated = `${before}\n${inner}\n ${after}`; + writeFileSync(NAV_FILE, updated, "utf-8"); + console.log(` [nav] Updated navigation.tsx Reference group`); +} diff --git a/scripts/ref/sdk.ts b/scripts/ref/sdk.ts new file mode 100644 index 000000000..5a535e610 --- /dev/null +++ b/scripts/ref/sdk.ts @@ -0,0 +1,472 @@ +/** + * AI-powered Webiny SDK Reference Generator + * + * For each webiny/* entry point: + * 1. Resolves all exported symbols via ts-morph (declaration text + JSDoc) + * 2. Sends the source to Claude with a structured prompt + * 3. Claude writes the complete .mdx page and .ai.txt companion + * 4. Files are written to docs/developer-docs/6.x/reference/ + * + * Usage: + * tsx scripts/ref/sdk.ts # skip existing pages + * tsx scripts/ref/sdk.ts --force # regenerate all + * tsx scripts/ref/sdk.ts --only api/logger,api/graphql + */ + +import { readFileSync, writeFileSync, mkdirSync, existsSync, rmSync } from "fs"; +import { join, dirname } from "path"; +import { Project } from "ts-morph"; +import { + WEBINY_PKG, + DOCS_ROOT, + REF_DIR, + collectEntryPointSource, + getPackagePathMap, + callClaude, + stableId, + toTitle, + toOutputPath, + rewriteNavigation, + type EntryPointSource +} from "./_shared.js"; + +// --------------------------------------------------------------------------- +// Prompt construction +// --------------------------------------------------------------------------- + +const AGENTS_MD = readFileSync(join(process.cwd(), "AGENTS.md"), "utf-8"); + +const LOGGER_EXAMPLE = `--- +id: yxbpl2xv +title: Logger +description: "Logger abstraction for server-side logging" +--- + +import { Alert } from "@/components/Alert"; +import { SymbolList } from "@/components/SymbolList"; + + + +- What is the \`Logger\` abstraction and when do you need it? +- How to inject and use \`Logger\` in your extensions? + + + +## Overview + +\`webiny/api/logger\` exports the \`Logger\` abstraction — a structured logger for server-side Webiny extensions. Inject it via the DI container to write log output at different severity levels without coupling your code to a specific logging library. + + + +## \`Logger\` + +**Abstraction** — imported from \`webiny/api/logger\` + +\`\`\`typescript +import { Logger } from "webiny/api/logger"; +\`\`\` + +**Interface \`Logger.Interface\`:** + +Structured logger with severity-level methods. The underlying implementation is Pino. + +\`\`\`typescript +interface Logger.Interface { + trace(objOrMsg: object | string, ...args: any[]): void; + debug(objOrMsg: object | string, ...args: any[]): void; + info(objOrMsg: object | string, ...args: any[]): void; + warn(objOrMsg: object | string, ...args: any[]): void; + error(objOrMsg: object | string, ...args: any[]): void; + fatal(objOrMsg: object | string, ...args: any[]): void; + log(objOrMsg: object | string, ...args: any[]): void; +} +\`\`\` + +| Method | Description | +| --------- | ------------------------------------------------------------------- | +| \`trace()\` | Log a trace-level message. Use for very verbose diagnostic output. | +| \`debug()\` | Log a debug-level message. Use for development-time diagnostics. | +| \`info()\` | Log an informational message. Use for normal operational events. | +| \`warn()\` | Log a warning. Use for recoverable issues that warrant attention. | +| \`error()\` | Log an error. Use when an operation fails. | +| \`fatal()\` | Log a fatal error. Use when the process cannot continue. | +| \`log()\` | Log at info level. Alias for \`info()\`. | + +**Types:** + +\`\`\`typescript +namespace Logger { + type Interface = ILogger; +} +\`\`\` + +## Examples + +### Basic Usage + +Simple logger injection and usage: + +\`\`\`typescript +import { ApiKeyAfterUpdateEventHandler } from "webiny/api/security/api-key"; +import { Logger } from "webiny/api/logger"; + +class MyApiKeyAfterUpdateImpl implements ApiKeyAfterUpdateEventHandler.Interface { + constructor(private logger: Logger.Interface) {} + + async handle() { + this.logger.debug("An API key was updated!"); + } +} + +const MyApiKeyAfterUpdate = ApiKeyAfterUpdateEventHandler.createImplementation({ + implementation: MyApiKeyAfterUpdateImpl, + dependencies: [Logger] +}); + +export default MyApiKeyAfterUpdate; +\`\`\``; + +const GRAPHQL_EXAMPLE = `--- +id: yxbpl2dy +title: GraphQL +description: "GraphQL schema factory and response helpers" +--- + +import { Alert } from "@/components/Alert"; +import { SymbolList } from "@/components/SymbolList"; + + + +- How to extend the Webiny GraphQL schema using \`GraphQLSchemaFactory\`? +- What response classes are available and when to use each? + + + +## Overview + +\`webiny/api/graphql\` provides the building blocks for extending Webiny's GraphQL API. Use \`GraphQLSchemaFactory\` to add custom type definitions and resolvers. The response classes (\`Response\`, \`ListResponse\`, \`ErrorResponse\`, etc.) standardize the shape of GraphQL resolver return values. + +**Services** + + + +**Types & Classes** + + + +## Services + +### \`GraphQLSchemaFactory\` + +**Abstraction** — imported from \`webiny/api/graphql\` + +Implement \`GraphQLSchemaFactory\` to add custom type definitions and resolvers to the Webiny GraphQL schema. The factory receives a \`GraphQLSchemaBuilder\` instance you use to register your schema extensions. + +\`\`\`typescript +import { GraphQLSchemaFactory } from "webiny/api/graphql"; +\`\`\` + +**Interface \`GraphQLSchemaFactory.Interface\`:** + +\`\`\`typescript +interface GraphQLSchemaFactory.Interface { + execute(builder: GraphQLSchemaBuilder.Interface): Promise; +} +\`\`\` + +**\`SchemaBuilder\` — \`GraphQLSchemaBuilder.Interface\`:** + +\`\`\`typescript +interface GraphQLSchemaBuilder.Interface { + addTypeDefs(typeDefs: TypeDefs): this; + addResolver(config: ResolverConfig): this; + build(): IGraphQLSchema; +} +\`\`\` + +| Method | Description | +| ------ | ----------- | +| \`addTypeDefs()\` | Add GraphQL SDL type definitions to the schema. | +| \`addResolver()\` | Register a resolver with optional middleware decorators. | +| \`build()\` | Build and return the final schema object. |`; + +function buildSystemPrompt(): string { + return `You are a technical documentation writer for Webiny, an open-source serverless CMS. You write concise, accurate API reference pages in MDX format. + +## Your task +For each webiny/* entry point you receive, write a complete reference page (.mdx) and a short .ai.txt companion file. The user will provide the TypeScript source and extracted symbol declarations. + +## MDX conventions (follow exactly) + +${AGENTS_MD} + +## Gold-standard example pages + +### Example 1: webiny/api/logger (simple, single abstraction) + +${LOGGER_EXAMPLE} + +### Example 2: webiny/api/graphql (mixed: abstraction + classes) + +${GRAPHQL_EXAMPLE} + +## Output format + +Respond with EXACTLY two sections separated by the delimiter \`---AI-TXT---\`: + +1. The complete .mdx content (frontmatter through last line) +2. The .ai.txt companion + +Do not include any other text, explanation, or markdown fences around the output. + +Example response structure: +--- +id: PLACEHOLDER_ID +title: ... +--- +[rest of mdx] +---AI-TXT--- +AI Context: Title (reference/path/to/file.mdx) +[rest of ai.txt] + +## Key rules +- The id field will be injected after — write PLACEHOLDER_ID and it will be replaced +- description field: ALWAYS wrap in double quotes (e.g. \`description: "My desc"\`) — required if it contains a colon +- Use "webiny/" prefix in import paths, NEVER "@webiny/" +- SymbolList anchors: slugify symbol name (camelCase → kebab-case, e.g. "GraphQLSchemaFactory" → "graph-ql-schema-factory") +- Do NOT use @example JSDoc — examples go in the Examples section +- Code blocks always have a language tag (typescript, graphql, tsx) +- No shell/bash code blocks +- No H1 in body (title comes from frontmatter) +- "WHAT YOU'LL LEARN" bullets must be specific to this entry point — not generic boilerplate +- Overview section: 1-3 paragraphs explaining what this entry point provides and when to use it +- For abstractions: show the Interface code block + a method table with descriptions +- For classes: show the class signature with public API only (no private members) +- If the entry point has many symbols (>5), group them with bold labels + SymbolList chips in Overview +- The .ai.txt must follow the format from AGENTS.md exactly`; +} + +function buildUserPrompt(src: EntryPointSource): string { + const lines: string[] = []; + + lines.push(`## Entry point: ${src.importPath}`); + lines.push(`Import path: \`import { ... } from "${src.importPath}"\``); + lines.push(`Output file: reference/${toOutputPath(src.relPath)}.mdx`); + lines.push(`Page title: ${toTitle(src.relPath)}`); + lines.push(``); + + lines.push(`## Exported symbols (${src.symbols.length} total)`); + lines.push(``); + for (const sym of src.symbols) { + lines.push(`### ${sym.name} (${sym.kind}${sym.isTypeOnly ? ", type-only" : ""})`); + if (sym.jsDoc) { + lines.push(`**JSDoc:** ${sym.jsDoc}`); + } + if (sym.declarationText) { + lines.push("```typescript"); + lines.push(sym.declarationText); + lines.push("```"); + } + lines.push(``); + } + + lines.push(`## Source files`); + lines.push(``); + for (const [filePath, content] of Array.from(src.sourceFiles.entries())) { + // Show a shortened path for readability + const shortPath = filePath.replace("/Users/adrian/dev/wby-next/packages/", "packages/"); + lines.push(`### ${shortPath}`); + lines.push("```typescript"); + // Trim very long files to avoid token limits + const trimmed = + content.length > 6000 ? content.slice(0, 6000) + "\n// ... (truncated)" : content; + lines.push(trimmed); + lines.push("```"); + lines.push(``); + } + + if (src.examplesContent) { + lines.push(`## Examples file content`); + lines.push(``); + lines.push(src.examplesContent); + lines.push(``); + lines.push( + `**Important:** Include these examples verbatim in an "## Examples" section at the bottom of the .mdx. Each H2 heading in the examples file becomes a "### Title" subsection.` + ); + } + + lines.push(`## Instructions`); + lines.push( + `Write the complete reference page for \`${src.importPath}\`. Follow all conventions from the system prompt exactly. Be specific and technical — this is a developer API reference.` + ); + + return lines.join("\n"); +} + +// --------------------------------------------------------------------------- +// Parse Claude response → {mdx, aiTxt} +// --------------------------------------------------------------------------- + +function parseClaudeResponse( + response: string, + relPath: string, + id: string +): { mdx: string; aiTxt: string } { + const delimiter = "---AI-TXT---"; + const delimIdx = response.indexOf(delimiter); + + let mdx: string; + let aiTxt: string; + + if (delimIdx === -1) { + // No delimiter — treat entire response as MDX, generate minimal ai.txt + mdx = response.trim(); + aiTxt = `AI Context: ${toTitle(relPath)} (reference/${toOutputPath( + relPath + )}.mdx)\n\nGenerated by AI reference generator.`; + } else { + mdx = response.slice(0, delimIdx).trim(); + aiTxt = response.slice(delimIdx + delimiter.length).trim(); + } + + // Replace PLACEHOLDER_ID with the actual stable ID + mdx = mdx.replace("PLACEHOLDER_ID", id); + + // Strip any accidental markdown code fences wrapping the output + if (mdx.startsWith("```")) { + mdx = mdx + .replace(/^```[a-z]*\n?/, "") + .replace(/```\s*$/, "") + .trim(); + } + + return { mdx, aiTxt }; +} + +// --------------------------------------------------------------------------- +// Main +// --------------------------------------------------------------------------- + +async function main(): Promise { + const args = process.argv.slice(2); + const force = args.includes("--force"); + const onlyArg = args.find(a => a.startsWith("--only=")); + const onlyPaths = onlyArg ? onlyArg.replace("--only=", "").split(",") : null; + + console.log(`\nWebiny SDK Reference Generator (AI-powered)`); + console.log(`Model: claude-sonnet-4-5`); + console.log(`Force: ${force}`); + if (onlyPaths) console.log(`Only: ${onlyPaths.join(", ")}`); + console.log(``); + + // Wipe reference/ on force mode if running full set + if (force && !onlyPaths) { + console.log("Clearing reference/ directory..."); + if (existsSync(REF_DIR)) { + rmSync(REF_DIR, { recursive: true }); + } + mkdirSync(REF_DIR, { recursive: true }); + } + + // Read webiny package exports + const pkgJson = JSON.parse(readFileSync(join(WEBINY_PKG, "package.json"), "utf-8")); + const exportsMap: Record = pkgJson.exports ?? {}; + const pkgMap = getPackagePathMap(); + + const entryPaths: string[] = Object.keys(exportsMap) + .filter(k => !k.includes("*") && !k.endsWith(".json") && !k.endsWith(".ts")) + .map(k => k.replace(/^\.\//, "")) + .sort(); + + console.log(`Found ${entryPaths.length} entry points`); + + // Filter to --only if specified + const pathsToProcess = onlyPaths + ? entryPaths.filter(p => onlyPaths.some(o => p === o || p.startsWith(o + "/"))) + : entryPaths; + + // Set up ts-morph project + const project = new Project({ + tsConfigFilePath: join(WEBINY_PKG, "tsconfig.json"), + skipAddingFilesFromTsConfig: true + }); + + const systemPrompt = buildSystemPrompt(); + + const processedEntryPoints: { relPath: string; title: string }[] = []; + let generated = 0; + let skipped = 0; + let failed = 0; + + for (const relPath of pathsToProcess) { + const outputPath = toOutputPath(relPath); + const mdxPath = join(REF_DIR, outputPath + ".mdx"); + const aiTxtPath = join(REF_DIR, outputPath + ".ai.txt"); + + // Skip if exists and not forcing + if (!force && existsSync(mdxPath)) { + console.log(` [skip] ${relPath} — already exists`); + processedEntryPoints.push({ relPath, title: toTitle(relPath) }); + skipped++; + continue; + } + + process.stdout.write(` [gen] ${relPath}... `); + + // Collect source + const src = collectEntryPointSource(relPath, project, pkgMap); + if (!src || src.symbols.length === 0) { + console.log(`SKIP (no symbols)`); + skipped++; + continue; + } + + // Build prompt + const userPrompt = buildUserPrompt(src); + + // Call Claude + let response: string; + try { + response = await callClaude(systemPrompt, userPrompt); + } catch (err) { + console.log(`FAILED (${(err as Error).message})`); + failed++; + continue; + } + + // Parse response + const id = stableId(relPath); + const { mdx, aiTxt } = parseClaudeResponse(response, relPath, id); + + // Write files + const dir = join(REF_DIR, dirname(outputPath)); + mkdirSync(dir, { recursive: true }); + writeFileSync(mdxPath, mdx, "utf-8"); + writeFileSync(aiTxtPath, aiTxt, "utf-8"); + + processedEntryPoints.push({ relPath, title: toTitle(relPath) }); + generated++; + console.log(`OK (${src.symbols.length} symbols)`); + } + + // Update navigation + console.log(`\nUpdating navigation...`); + rewriteNavigation(processedEntryPoints); + + console.log(`\nDone.`); + console.log(` Generated: ${generated}`); + console.log(` Skipped: ${skipped}`); + console.log(` Failed: ${failed}`); +} + +main().catch(err => { + console.error("Fatal:", err); + process.exit(1); +}); diff --git a/scripts/ref/webiny-sdk.ts b/scripts/ref/webiny-sdk.ts new file mode 100644 index 000000000..51bc40a44 --- /dev/null +++ b/scripts/ref/webiny-sdk.ts @@ -0,0 +1,501 @@ +/** + * AI-powered @webiny/sdk Reference Generator + * + * Generates 4 reference pages for the @webiny/sdk package: + * - reference/sdk/index.mdx — Overview, WebinyConfig, Result, error classes + * - reference/sdk/cms.mdx — CmsSdk: all CMS methods + param types + * - reference/sdk/file-manager.mdx — FileManagerSdk: all file methods + types + * - reference/sdk/tenant-manager.mdx — TenantManagerSdk: all tenant methods + types + * + * Usage: + * tsx scripts/ref/webiny-sdk.ts # skip existing pages + * tsx scripts/ref/webiny-sdk.ts --force # regenerate all + * tsx scripts/ref/webiny-sdk.ts --only=cms # regenerate one page + */ + +import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs"; +import { join } from "path"; +import { callClaude, REF_DIR, DOCS_ROOT, NAV_FILE, stableId } from "./_shared.js"; + +// --------------------------------------------------------------------------- +// SDK source root +// --------------------------------------------------------------------------- + +const SDK_SRC = "/Users/adrian/dev/wby-next/packages/sdk/src"; + +function src(relPath: string): string { + return readFileSync(join(SDK_SRC, relPath), "utf-8"); +} + +// --------------------------------------------------------------------------- +// Existing guide docs (context for Claude) +// --------------------------------------------------------------------------- + +const WEBINY_SDK_GUIDE = readFileSync(join(DOCS_ROOT, "core-concepts/webiny-sdk.mdx"), "utf-8"); + +const USING_SDK_GUIDE = readFileSync(join(DOCS_ROOT, "headless-cms/using-webiny-sdk.mdx"), "utf-8"); + +// --------------------------------------------------------------------------- +// Page definitions +// --------------------------------------------------------------------------- + +interface SdkPage { + key: string; // --only= filter key + outputPath: string; // relative to reference/ + title: string; + description: string; + sourceFiles: Record; // label -> content + pageInstruction: string; +} + +function buildPages(): SdkPage[] { + return [ + // ----------------------------------------------------------------------- + // Overview + // ----------------------------------------------------------------------- + { + key: "index", + outputPath: "sdk/index", + title: "Overview", + description: "Webiny SDK: WebinyConfig, Result, and error classes", + sourceFiles: { + "index.ts": src("index.ts"), + "Webiny.ts": src("Webiny.ts"), + "types.ts": src("types.ts"), + "Result.ts": src("Result.ts"), + "BaseError.ts": src("BaseError.ts"), + "errors.ts": src("errors.ts") + }, + pageInstruction: ` +Write the Overview reference page for \`@webiny/sdk\`. This page covers: + +1. **What the SDK is** — a standalone TypeScript library for calling Webiny APIs from external apps (Next.js, Node.js, etc.). Not for use inside Webiny extensions (use \`webiny/*\` for that). + +2. **Installation and initialization** — \`npm install @webiny/sdk\`, then instantiate with \`WebinyConfig\`. + +3. **\`WebinyConfig\`** — document all fields: \`endpoint\` (required), \`token\` (API key token from Admin → Settings → API Keys), \`tenant\` (defaults to "root"), \`headers\` (optional custom headers), \`fetch\` (optional custom fetch implementation). + +4. **\`Result\`** — the return type of all SDK methods. Document: \`isOk()\`, \`isFail()\`, \`value\`, \`error\`, \`map()\`, \`mapError()\`, \`flatMap()\`, \`match()\`. Also document the namespace types \`Result.UnwrapResult\` and \`Result.UnwrapError\`. + +5. **Error classes** — \`HttpError\` (HTTP-level failures, has \`data.status\`), \`GraphQLError\` (API returned an error, has \`data.code\`), \`NetworkError\` (fetch itself failed). All extend \`BaseError\`. + +6. **\`Webiny\` class** — the main entry point. Document properties: \`cms\` (\`CmsSdk\`), \`tenantManager\` (\`TenantManagerSdk\`), \`fileManager\` (\`FileManagerSdk\`). Document constructor params. + +Key facts from the existing docs: +- Authentication uses an API key token (not Basic auth or OAuth) +- Find API endpoint with \`yarn webiny info\` — use the base CloudFront domain +- Create a singleton instance and reuse it throughout the app +- Import path is \`@webiny/sdk\` (not \`webiny/\` — this is an external package) + +Include a "Quick Start" examples section showing: installation, initializing the \`Webiny\` class, and a simple \`isOk()\`/\`isFail()\` check pattern. +` + }, + + // ----------------------------------------------------------------------- + // CMS + // ----------------------------------------------------------------------- + { + key: "cms", + outputPath: "sdk/cms", + title: "CMS", + description: "CmsSdk: query and mutate Headless CMS entries", + sourceFiles: { + "CmsSdk.ts": src("CmsSdk.ts"), + "methods/cms/cmsTypes.ts": src("methods/cms/cmsTypes.ts"), + "methods/cms/getEntry.ts": src("methods/cms/getEntry.ts"), + "methods/cms/listEntries.ts": src("methods/cms/listEntries.ts"), + "methods/cms/createEntry.ts": src("methods/cms/createEntry.ts"), + "methods/cms/updateEntryRevision.ts": src("methods/cms/updateEntryRevision.ts"), + "methods/cms/publishEntryRevision.ts": src("methods/cms/publishEntryRevision.ts"), + "methods/cms/unpublishEntryRevision.ts": src("methods/cms/unpublishEntryRevision.ts"), + "methods/cms/deleteEntryRevision.ts": src("methods/cms/deleteEntryRevision.ts") + }, + pageInstruction: ` +Write the CMS reference page for \`sdk.cms\` (\`CmsSdk\`). Access via \`sdk.cms\` on a \`Webiny\` instance. + +Document every method on \`CmsSdk\` with: +- Method signature +- All parameters with types, required/optional, and descriptions +- Return type +- Key behavioral notes + +Methods to document (in this order): + +**Read methods** (use the Read API — published content only, unless \`preview: true\`): +- \`getEntry(params)\` — fetch a single entry by \`id\`, \`entryId\`, or \`values\` filter +- \`listEntries(params)\` — list entries with filtering, sorting, pagination, full-text search + +**Write methods** (use the Manage API): +- \`createEntry(params)\` — creates a draft entry +- \`updateEntryRevision(params)\` — partial update (only specified fields change) +- \`publishEntryRevision(params)\` — makes entry visible via Read API +- \`unpublishEntryRevision(params)\` — reverts to draft +- \`deleteEntryRevision(params)\` — soft delete by default; \`permanent: true\` for hard delete + +Key facts to include: +- \`fields\` parameter: use \`"values.fieldId"\` for entry values, \`"id"\`, \`"entryId"\`, \`"createdOn"\` etc. for metadata +- \`preview: true\` on read methods uses the Preview API (returns unpublished/draft content) +- \`createEntry\` always creates a draft — call \`publishEntryRevision\` to publish +- \`revisionId\` format is \`"entryId#revisionNumber"\` e.g. \`"abc123#0001"\` +- TypeScript generic \`\` types the \`values\` field on returned \`CmsEntryData\` +- Also document \`CmsEntryData\`, \`CmsEntryValues\`, \`CmsEntryStatus\`, \`CmsIdentity\` types + +Include a practical examples section covering: list with filter+sort+pagination, get by ID, create+publish flow, TypeScript generics usage, error handling pattern. +` + }, + + // ----------------------------------------------------------------------- + // File Manager + // ----------------------------------------------------------------------- + { + key: "file-manager", + outputPath: "sdk/file-manager", + title: "File Manager", + description: '"FileManagerSdk: upload, retrieve, and manage files"', + sourceFiles: { + "FileManagerSdk.ts": src("FileManagerSdk.ts"), + "methods/fileManager/fileManagerTypes.ts": src("methods/fileManager/fileManagerTypes.ts"), + "methods/fileManager/getFile.ts": src("methods/fileManager/getFile.ts"), + "methods/fileManager/listFiles.ts": src("methods/fileManager/listFiles.ts"), + "methods/fileManager/createFile.ts": src("methods/fileManager/createFile.ts"), + "methods/fileManager/createFiles.ts": src("methods/fileManager/createFiles.ts"), + "methods/fileManager/updateFile.ts": src("methods/fileManager/updateFile.ts"), + "methods/fileManager/deleteFile.ts": src("methods/fileManager/deleteFile.ts"), + "methods/fileManager/listTags.ts": src("methods/fileManager/listTags.ts"), + "methods/fileManager/getPresignedPostPayload.ts": src( + "methods/fileManager/getPresignedPostPayload.ts" + ), + "methods/fileManager/getPresignedPostPayloads.ts": src( + "methods/fileManager/getPresignedPostPayloads.ts" + ), + "methods/fileManager/createMultiPartUpload.ts": src( + "methods/fileManager/createMultiPartUpload.ts" + ), + "methods/fileManager/completeMultiPartUpload.ts": src( + "methods/fileManager/completeMultiPartUpload.ts" + ) + }, + pageInstruction: ` +Write the File Manager reference page for \`sdk.fileManager\` (\`FileManagerSdk\`). Access via \`sdk.fileManager\` on a \`Webiny\` instance. + +Document every method on \`FileManagerSdk\` with full param tables and return types. + +Group methods into logical sections: + +**Reading files:** +- \`getFile(params)\` — get a single file by ID +- \`listFiles(params)\` — list files with search, where filters, sort, pagination +- \`listTags(params)\` — list all tags used on files + +**Creating and updating files:** +- \`createFile(params)\` — register a file record (after upload) +- \`createFiles(params)\` — bulk register file records +- \`updateFile(params)\` — update file metadata +- \`deleteFile(params)\` — delete a file record + +**Upload helpers (S3 presigned uploads):** +- \`getPresignedPostPayload(params)\` — get a single S3 presigned POST URL for direct browser upload +- \`getPresignedPostPayloads(params)\` — get multiple presigned POST URLs in bulk +- \`createMultiPartUpload(params)\` — initiate a multipart upload for large files +- \`completeMultiPartUpload(params)\` — finalize a multipart upload after all parts are uploaded + +Key types to document: \`FmFile\`, \`FmTag\`, \`FmListMeta\`, \`FmFile_Metadata\`, \`FmFile_AccessControl\`, \`PresignedPostPayloadResponse\`, \`MultiPartUploadResponse\`. + +Include examples covering: listing files with search, single file get, basic upload flow (presigned POST → createFile), multipart upload flow for large files. +` + }, + + // ----------------------------------------------------------------------- + // Tenant Manager + // ----------------------------------------------------------------------- + { + key: "tenant-manager", + outputPath: "sdk/tenant-manager", + title: "Tenant Manager", + description: "TenantManagerSdk: create and manage tenants programmatically", + sourceFiles: { + "TenantManagerSdk.ts": src("TenantManagerSdk.ts"), + "methods/tenantManager/tenantManagerTypes.ts": src( + "methods/tenantManager/tenantManagerTypes.ts" + ), + "methods/tenantManager/createTenant.ts": src("methods/tenantManager/createTenant.ts"), + "methods/tenantManager/installTenant.ts": src("methods/tenantManager/installTenant.ts"), + "methods/tenantManager/disableTenant.ts": src("methods/tenantManager/disableTenant.ts"), + "methods/tenantManager/enableTenant.ts": src("methods/tenantManager/enableTenant.ts") + }, + pageInstruction: ` +Write the Tenant Manager reference page for \`sdk.tenantManager\` (\`TenantManagerSdk\`). Access via \`sdk.tenantManager\` on a \`Webiny\` instance. + +Document all 4 methods: +- \`createTenant(params)\` — creates a new tenant. \`CreateTenantInput\`: \`id?\`, \`name\` (required), \`description?\` +- \`installTenant(params)\` — provisions a tenant with default settings. Must be called after \`createTenant\` before the tenant is usable. +- \`disableTenant(params)\` — disables a tenant, blocking access to its resources +- \`enableTenant(params)\` — re-enables a previously disabled tenant + +Key facts: +- All methods return \`Result\` +- \`createTenant\` + \`installTenant\` is the required two-step flow for provisioning a new tenant +- Tenant \`id\` is optional in create — Webiny generates one if omitted +- The API key used must have tenant manager permissions + +Include an examples section showing: the full create+install flow, disabling/enabling a tenant, error handling. +` + } + ]; +} + +// --------------------------------------------------------------------------- +// System prompt +// --------------------------------------------------------------------------- + +const AGENTS_MD = readFileSync(join(process.cwd(), "AGENTS.md"), "utf-8"); + +function buildSystemPrompt(): string { + return `You are a technical documentation writer for Webiny, an open-source serverless CMS. You write concise, accurate API reference pages in MDX format. + +## Your task +Write a complete reference page (.mdx) and a companion .ai.txt file for a section of the \`@webiny/sdk\` package — the standalone Webiny JavaScript/TypeScript SDK for external applications. + +## MDX conventions (follow exactly) + +${AGENTS_MD} + +## IMPORTANT: Import paths for @webiny/sdk + +This is an EXTERNAL package — not part of the \`webiny/*\` internal extensions system. Use: +\`\`\`typescript +import { Webiny } from "@webiny/sdk"; +import type { CmsEntryData } from "@webiny/sdk"; +\`\`\` +NOT \`webiny/\` (that's for internal extensions). + +## Existing guide docs (use for tone, examples, and key facts) + +### core-concepts/webiny-sdk.mdx +${WEBINY_SDK_GUIDE} + +### headless-cms/using-webiny-sdk.mdx +${USING_SDK_GUIDE} + +## Output format + +Respond with EXACTLY two sections separated by \`---AI-TXT---\`: + +1. The complete .mdx content +2. The .ai.txt companion + +No other text, no markdown fences wrapping the output. + +Response structure: +--- +id: PLACEHOLDER_ID +title: ... +description: ... +--- +[rest of mdx] +---AI-TXT--- +AI Context: Title (reference/sdk/page.mdx) +[rest of ai.txt] + +## Key rules +- id field: write PLACEHOLDER_ID (replaced after) +- description field: ALWAYS wrap in double quotes (e.g. \`description: "My desc"\`) — required if it contains a colon +- NEVER use angle brackets in headings (e.g. \`#### \`Foo\`\` breaks MDX) — use \`#### \`Foo\`\` and mention the generic in prose instead +- Do NOT use \`\` as a wrapper around markdown lists — it expects a \`symbols\` prop array. For SDK pages, use plain markdown lists or bold group headers instead of SymbolList chips +- No H1 in body +- No shell/bash code blocks — use \`typescript\` or \`tsx\` instead +- Except in installation section where \`bash\` is acceptable for \`npm install\` +- "WHAT YOU'LL LEARN" bullets must be specific to this page +- Overview: 1-3 paragraphs — what this class/module provides, when to use it +- For each method: signature block + param table (name, type, required, description) + return type +- Use \`Result\` return type throughout — never \`Promise\` +- The .ai.txt follows the format from AGENTS.md exactly`; +} + +// --------------------------------------------------------------------------- +// User prompt per page +// --------------------------------------------------------------------------- + +function buildUserPrompt(page: SdkPage): string { + const lines: string[] = []; + + lines.push(`## Page to generate`); + lines.push(`Output: reference/${page.outputPath}.mdx`); + lines.push(`Title: ${page.title}`); + lines.push(`Description: ${page.description}`); + lines.push(``); + + lines.push(`## Source files`); + lines.push(``); + for (const [label, content] of Object.entries(page.sourceFiles)) { + lines.push(`### ${label}`); + lines.push("```typescript"); + lines.push(content); + lines.push("```"); + lines.push(``); + } + + lines.push(`## What to document`); + lines.push(page.pageInstruction.trim()); + + return lines.join("\n"); +} + +// --------------------------------------------------------------------------- +// Nav rewrite — appends SDK group, preserves existing webiny/* entries +// --------------------------------------------------------------------------- + +function rewriteNavWithSdk(pages: SdkPage[]): void { + const nav = readFileSync(NAV_FILE, "utf-8"); + + const SDK_NAV_START = " {/* __SDK_PAGES_START__ */}"; + const SDK_NAV_END = " {/* __SDK_PAGES_END__ */}"; + + const sdkLinks = pages + .filter(p => p.key !== "index") // index is the group landing, not a child page + .map(p => ` `) + .join("\n"); + + const sdkGroup = + ` \n` + + sdkLinks + + `\n `; + + // If markers already exist, replace between them + if (nav.includes(SDK_NAV_START) && nav.includes(SDK_NAV_END)) { + const startIdx = nav.indexOf(SDK_NAV_START); + const endIdx = nav.indexOf(SDK_NAV_END); + const before = nav.slice(0, startIdx + SDK_NAV_START.length); + const after = nav.slice(endIdx); + writeFileSync(NAV_FILE, `${before}\n${sdkGroup}\n ${after}`, "utf-8"); + console.log(` [nav] Updated SDK group in navigation.tsx`); + return; + } + + // Otherwise inject before the REFERENCE_PAGES_END marker + const REF_END = " {/* __REFERENCE_PAGES_END__ */}"; + const refEndIdx = nav.indexOf(REF_END); + if (refEndIdx === -1) { + console.warn(` [nav] Could not find __REFERENCE_PAGES_END__ marker — skipping nav update`); + return; + } + + const before = nav.slice(0, refEndIdx); + const after = nav.slice(refEndIdx); + const sdkBlock = ` ${SDK_NAV_START}\n` + sdkGroup + `\n ${SDK_NAV_END}\n `; + + writeFileSync(NAV_FILE, `${before}${sdkBlock}${after}`, "utf-8"); + console.log(` [nav] Injected SDK group into navigation.tsx`); +} + +// --------------------------------------------------------------------------- +// Parse Claude response +// --------------------------------------------------------------------------- + +function parseResponse(response: string, page: SdkPage): { mdx: string; aiTxt: string } { + const delimiter = "---AI-TXT---"; + const delimIdx = response.indexOf(delimiter); + + let mdx: string; + let aiTxt: string; + + if (delimIdx === -1) { + mdx = response.trim(); + aiTxt = `AI Context: ${page.title} (reference/${page.outputPath}.mdx)\n\nGenerated by AI reference generator.`; + } else { + mdx = response.slice(0, delimIdx).trim(); + aiTxt = response.slice(delimIdx + delimiter.length).trim(); + } + + // Replace placeholder ID + const id = stableId(`sdk/${page.key}`); + mdx = mdx.replace("PLACEHOLDER_ID", id); + + // Strip any accidental outer fences + if (mdx.startsWith("```")) { + mdx = mdx + .replace(/^```[a-z]*\n?/, "") + .replace(/```\s*$/, "") + .trim(); + } + + return { mdx, aiTxt }; +} + +// --------------------------------------------------------------------------- +// Main +// --------------------------------------------------------------------------- + +async function main(): Promise { + const args = process.argv.slice(2); + const force = args.includes("--force"); + const onlyArg = args.find(a => a.startsWith("--only=")); + const onlyKeys = onlyArg ? onlyArg.replace("--only=", "").split(",") : null; + + console.log(`\n@webiny/sdk Reference Generator (AI-powered)`); + console.log(`Model: claude-sonnet-4-5`); + console.log(`Force: ${force}`); + if (onlyKeys) console.log(`Only: ${onlyKeys.join(", ")}`); + console.log(``); + + const pages = buildPages(); + const pagesToProcess = onlyKeys ? pages.filter(p => onlyKeys.includes(p.key)) : pages; + + if (pagesToProcess.length === 0) { + console.error(`No matching pages found. Valid keys: ${pages.map(p => p.key).join(", ")}`); + process.exit(1); + } + + // Ensure output directory exists + mkdirSync(join(REF_DIR, "sdk"), { recursive: true }); + + const systemPrompt = buildSystemPrompt(); + let generated = 0; + let skipped = 0; + let failed = 0; + + for (const page of pagesToProcess) { + const mdxPath = join(REF_DIR, page.outputPath + ".mdx"); + const aiTxtPath = join(REF_DIR, page.outputPath + ".ai.txt"); + + if (!force && existsSync(mdxPath)) { + console.log(` [skip] ${page.outputPath} — already exists`); + skipped++; + continue; + } + + process.stdout.write(` [gen] ${page.outputPath}... `); + + const userPrompt = buildUserPrompt(page); + + let response: string; + try { + response = await callClaude(systemPrompt, userPrompt); + } catch (err) { + console.log(`FAILED (${(err as Error).message})`); + failed++; + continue; + } + + const { mdx, aiTxt } = parseResponse(response, page); + writeFileSync(mdxPath, mdx, "utf-8"); + writeFileSync(aiTxtPath, aiTxt, "utf-8"); + + generated++; + console.log(`OK`); + } + + // Update navigation with all pages (even skipped — they're already on disk) + console.log(`\nUpdating navigation...`); + rewriteNavWithSdk(pages); + + console.log(`\nDone.`); + console.log(` Generated: ${generated}`); + console.log(` Skipped: ${skipped}`); + console.log(` Failed: ${failed}`); +} + +main().catch(err => { + console.error("Fatal:", err); + process.exit(1); +}); diff --git a/yarn.lock b/yarn.lock index 43f168787..fc7d5ded7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -209,6 +209,22 @@ __metadata: languageName: node linkType: hard +"@anthropic-ai/sdk@npm:^0.80.0": + version: 0.80.0 + resolution: "@anthropic-ai/sdk@npm:0.80.0" + dependencies: + json-schema-to-ts: ^3.1.1 + peerDependencies: + zod: ^3.25.0 || ^4.0.0 + peerDependenciesMeta: + zod: + optional: true + bin: + anthropic-ai-sdk: bin/cli + checksum: f1894fcca570a5f0145641bff36c970ae5e9c58e0d73282a39b39f8975a5105a92a9f778c14fc9f3aae1566b7ec1110af7615cc45e80324b0b928932321b6498 + languageName: node + linkType: hard + "@babel/code-frame@npm:7.12.11": version: 7.12.11 resolution: "@babel/code-frame@npm:7.12.11" @@ -1614,6 +1630,13 @@ __metadata: languageName: node linkType: hard +"@babel/runtime@npm:^7.18.3": + version: 7.29.2 + resolution: "@babel/runtime@npm:7.29.2" + checksum: d5548d1165de8995f8afc93a5694b8625409be16cd1f2250ac13e331335858ddac3cb9fd278e6c43956a130101a2203f09417938a1a96f9fb70f02b4b4172e1d + languageName: node + linkType: hard + "@babel/runtime@npm:^7.21.0": version: 7.28.6 resolution: "@babel/runtime@npm:7.28.6" @@ -8292,6 +8315,16 @@ __metadata: languageName: node linkType: hard +"json-schema-to-ts@npm:^3.1.1": + version: 3.1.1 + resolution: "json-schema-to-ts@npm:3.1.1" + dependencies: + "@babel/runtime": ^7.18.3 + ts-algebra: ^2.0.0 + checksum: b616f1c2d7492502e11eec4f8e4539ee1e897543a679d929494afdc164d9557275cead8372747b73f239b1e68056ffbf551b03ae82d0047bba0dfe2bbd6b64f4 + languageName: node + linkType: hard + "json-schema-traverse@npm:^0.4.1": version: 0.4.1 resolution: "json-schema-traverse@npm:0.4.1" @@ -10627,6 +10660,7 @@ __metadata: version: 0.0.0-use.local resolution: "root-workspace-0b6124@workspace:." dependencies: + "@anthropic-ai/sdk": ^0.80.0 "@babel/preset-env": ^7.18.6 "@babel/preset-react": ^7.18.6 "@babel/register": ^7.18.6 @@ -11826,6 +11860,13 @@ __metadata: languageName: node linkType: hard +"ts-algebra@npm:^2.0.0": + version: 2.0.0 + resolution: "ts-algebra@npm:2.0.0" + checksum: 970b0e7db49cf8c1a8ff2a816eb047fac8add47511f5e4995e4998c56c6f7b226399284412de88f3e137ab55c857a4262c0d8f02f0765730e7d3a021de2ea7ef + languageName: node + linkType: hard + "ts-interface-checker@npm:^0.1.9": version: 0.1.13 resolution: "ts-interface-checker@npm:0.1.13" From 7c2f5e8fdd3cf7e8a8adce7bbc57eb6dbadb797f Mon Sep 17 00:00:00 2001 From: adrians5j Date: Thu, 2 Apr 2026 23:51:11 +0200 Subject: [PATCH 3/6] wip:3 (45ium) --- AGENTS.md | 3 +- docs/developer-docs/6.x/navigation.tsx | 9 + .../webiny-api/connect-custom-domain.ai.txt | 25 +++ .../6.x/webiny-api/connect-custom-domain.mdx | 91 ++++++++ .../webiny-api/extend-graphql-schema.ai.txt | 44 ++++ .../6.x/webiny-api/extend-graphql-schema.mdx | 201 ++++++++++++++++++ .../6.x/webiny-api/universal-api-keys.ai.txt | 29 +++ .../6.x/webiny-api/universal-api-keys.mdx | 110 ++++++++++ .../website-builder/multi-tenant-nextjs.mdx | 94 ++------ 9 files changed, 530 insertions(+), 76 deletions(-) create mode 100644 docs/developer-docs/6.x/webiny-api/connect-custom-domain.ai.txt create mode 100644 docs/developer-docs/6.x/webiny-api/connect-custom-domain.mdx create mode 100644 docs/developer-docs/6.x/webiny-api/extend-graphql-schema.ai.txt create mode 100644 docs/developer-docs/6.x/webiny-api/extend-graphql-schema.mdx create mode 100644 docs/developer-docs/6.x/webiny-api/universal-api-keys.ai.txt create mode 100644 docs/developer-docs/6.x/webiny-api/universal-api-keys.mdx diff --git a/AGENTS.md b/AGENTS.md index b09ce101d..a36a708a2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -33,6 +33,7 @@ ``` docs/developer-docs/6.0.x/ ├── admin/ # Admin area customization (whitelabeling) +├── webiny-api/ # API customization (custom domain, extend GraphQL schema, universal API keys) ├── cli/ # CLI commands reference (deploy, destroy, watch, etc.) ├── core-concepts/ # Foundational knowledge: architecture, applications, project structure, DI, Result pattern, multi-tenancy, local dev, env vars ├── get-started/ # Welcome, installation, upgrade to Business @@ -151,7 +152,7 @@ import type { CmsEntry } from "webiny/api"; - **Bold** for key labels: `**Naming Convention:**`, `**Key Point:**` - Bullet lists use `-`, not numbered lists (even for sequential steps) - No emojis in prose -- Inline links use standard markdown: `[text](/docs/path)` +- Inline links use standard markdown: `[text](/{version}/path)` - "Webiny" always capitalized ## Tone and Voice diff --git a/docs/developer-docs/6.x/navigation.tsx b/docs/developer-docs/6.x/navigation.tsx index 13766867e..e72f8883d 100644 --- a/docs/developer-docs/6.x/navigation.tsx +++ b/docs/developer-docs/6.x/navigation.tsx @@ -93,6 +93,15 @@ export const Navigation = ({ children }: { children: React.ReactNode }) => { + + + + + + +- how to connect a custom domain to the API CloudFront distribution + + + + + +To connect a custom domain to the Admin Area instead, see [Connect Custom Domain](/{version}/admin/connect-custom-domain). + + + +## Overview + +By default, the Webiny API is accessible via an auto-generated CloudFront URL. For production environments, you will typically want to serve it from a custom domain. + +To do this, you need an AWS Certificate Manager (ACM) certificate that covers your domain, then declare the domain via `Infra.Api.CustomDomains` in `webiny.config.tsx`. Webiny will attach the domain as an alternate domain name on the API's CloudFront distribution. + +## Before You Begin + +- Register your domain with a DNS provider of your choice. +- Create (or import) a certificate in [AWS Certificate Manager (ACM)](https://docs.aws.amazon.com/acm/latest/userguide/acm-overview.html) that covers the domain you plan to use. + + + +The certificate **must** be created in the `us-east-1` region — this is an AWS requirement for certificates used with CloudFront distributions. + + + + + +Learn how to request a public certificate in the official [AWS documentation](https://docs.aws.amazon.com/acm/latest/userguide/gs-acm-request-public.html#request-public-console). Read more about [alternate domain name requirements](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CNAMEs.html#alternate-domain-names-requirements) for CloudFront. + + + +## Configure the Custom Domain + +Add `Infra.Api.CustomDomains` to `webiny.config.tsx`: + +```tsx webiny.config.tsx +import React from "react"; +import { Infra } from "webiny/extensions"; + +export const Extensions = () => { + return ( + <> + + + ); +}; +``` + +Replace `api.my-domain.com` with your domain and `certificateArn` with the ARN of your ACM certificate. + +After making the change, redeploy: + +``` +yarn webiny deploy +``` + +Use `--env ` to target a specific environment if needed. + +## Point Your Domain to CloudFront + +Once deployed, Webiny will output the CloudFront domain name for the API distribution (e.g. `d111111abcdef8.cloudfront.net`). + +Add a **CNAME** record with your DNS provider pointing your domain to that CloudFront domain name: + +| Type | Name | Value | +| ----- | ------------------- | ------------------------------- | +| CNAME | `api.my-domain.com` | `d111111abcdef8.cloudfront.net` | + + + +DNS changes can take a few minutes to propagate. Use a service like [DNS Checker](https://dnschecker.org/) to verify that your CNAME record is live. + + + +Once propagated, the Webiny API will be accessible at your custom domain. diff --git a/docs/developer-docs/6.x/webiny-api/extend-graphql-schema.ai.txt b/docs/developer-docs/6.x/webiny-api/extend-graphql-schema.ai.txt new file mode 100644 index 000000000..f18304825 --- /dev/null +++ b/docs/developer-docs/6.x/webiny-api/extend-graphql-schema.ai.txt @@ -0,0 +1,44 @@ +AI Context: Extend the GraphQL Schema (extend-graphql-schema.mdx) + +Source of Information: +1. docs/developer-docs/6.x/graphql/about.mdx — archived about article (structure/concepts) +2. docs/developer-docs/6.x/graphql/reference.mdx — archived reference article (API signatures) +3. docs/developer-docs/6.x/graphql/example.mdx — archived example article (full query/mutation examples) +4. headless-cms/content-models-via-code.mdx — structural reference for the new format + +Key Documentation Decisions: +1. Merged the three archived graphql articles (about, reference, example) into one practical article +2. Did not carry over the old about/reference structure — the new article leads with a working example +3. Kept both a query example and a mutation example to show the pattern is symmetric +4. Used /* GraphQL */ template tag in addTypeDefs() calls — matches codebase convention +5. Explained the Result pattern inline in the "How It Works" section rather than linking to a hidden doc +6. Archived graphql/ directory articles intentionally excluded from navigation — data was correct but structure was wrong + +Understanding: +GraphQLSchemaFactory is the extension point for adding custom queries/mutations. It uses a builder pattern: +- builder.addTypeDefs(sdl) — extends the schema with new types +- builder.addResolver({ path, dependencies, resolver }) — registers resolver with DI +- path uses dot notation: "Query.myField" or "Mutation.myMutation" +- dependencies array is positional — matches resolver factory parameters in order +- resolver factory returns the actual async resolver function (double-function pattern) +- All resolver operations return structured { data, error } responses using the Result pattern + +Code Patterns: +- extend type Query / extend type Mutation to add to existing root types +- Custom response types follow { data, error } or { data, meta, error } shapes +- CmsError and CmsListMeta are built-in types available in the schema +- createImplementation wraps the class for DI registration + +Related Documents: +- docs/developer-docs/6.x/core-concepts/di.mdx — dependency injection pattern +- docs/developer-docs/6.x/core-concepts/result.mdx — Result pattern +- docs/developer-docs/6.x/reference/api/graphql.mdx — API reference + +Key Code Locations: +- packages/api-graphql — GraphQLSchemaFactory implementation +- packages/api-headless-cms — GetModelUseCase, ListPublishedEntriesUseCase, CreateEntryUseCase + +Tone Guidelines: +- Technical and practical — lead with working code +- Explain the "how it works" after the example, not before +- Same depth and style as headless-cms/content-models-via-code.mdx diff --git a/docs/developer-docs/6.x/webiny-api/extend-graphql-schema.mdx b/docs/developer-docs/6.x/webiny-api/extend-graphql-schema.mdx new file mode 100644 index 000000000..42745cbca --- /dev/null +++ b/docs/developer-docs/6.x/webiny-api/extend-graphql-schema.mdx @@ -0,0 +1,201 @@ +--- +id: nf7q3bv5 +title: Extend the GraphQL Schema +description: Learn how to add custom types, queries, and mutations to the Webiny GraphQL API using the GraphQLSchemaFactory. +--- + +import { Alert } from "@/components/Alert"; + + + +- how to add custom GraphQL types, queries, and mutations +- how to register resolvers with dependency injection +- how to handle errors in GraphQL responses using the Result pattern + + + +## Overview + +Webiny exposes a GraphQL API for all its core applications. You can extend it with your own types, queries, and mutations by implementing the `GraphQLSchemaFactory` interface. The factory receives a schema builder, you call `addTypeDefs()` and `addResolver()` on it, and Webiny merges your additions into the running schema. + +The GraphQL layer stays thin: resolvers delegate to use cases and services that carry the business logic. + +## Adding a Custom Query + +Create an extension file and implement `GraphQLSchemaFactory.Interface`: + +```typescript extensions/listCmsEntriesGraphQL.ts +import { GraphQLSchemaFactory } from "webiny/api/graphql"; +import { GetModelUseCase } from "webiny/api/cms/model"; +import { ListPublishedEntriesUseCase } from "webiny/api/cms/entry"; + +interface IListCmsEntriesArgs { + modelId: string; + limit?: number; + after?: string; +} + +class ListCmsEntriesGraphQL implements GraphQLSchemaFactory.Interface { + public async execute(builder: GraphQLSchemaFactory.SchemaBuilder): GraphQLSchemaFactory.Return { + builder.addTypeDefs(/* GraphQL */ ` + type CustomListCmsEntriesResponseItem { + id: ID! + title: String! + } + type CustomListCmsEntriesResponse { + data: [CustomListCmsEntriesResponseItem!] + meta: CmsListMeta + error: CmsError + } + + extend type Query { + listCmsEntries(modelId: ID!, limit: Int, after: String): CustomListCmsEntriesResponse! + } + `); + + builder.addResolver({ + path: "Query.listCmsEntries", + dependencies: [GetModelUseCase, ListPublishedEntriesUseCase], + resolver( + getModel: GetModelUseCase.Interface, + listEntries: ListPublishedEntriesUseCase.Interface + ) { + return async ({ args }) => { + const { modelId, limit, after } = args; + + const modelResult = await getModel.execute(modelId); + if (modelResult.isFail()) { + return { error: modelResult.error, data: null, meta: null }; + } + const model = modelResult.value; + + const entriesResult = await listEntries.execute(model, { + limit: limit ?? 10, + after: after ?? null + }); + if (entriesResult.isFail()) { + return { error: entriesResult.error, data: null, meta: null }; + } + + const { entries, meta } = entriesResult.value; + return { + data: entries.map(item => ({ + id: item.id, + title: item.values[model.titleFieldId] || "No title" + })), + meta, + error: null + }; + }; + } + }); + + return builder; + } +} + +export default GraphQLSchemaFactory.createImplementation({ + implementation: ListCmsEntriesGraphQL, + dependencies: [] +}); +``` + +Then register it in `webiny.config.tsx`: + +```tsx webiny.config.tsx +import React from "react"; +import { Api } from "webiny/extensions"; + +export const Extensions = () => { + return ( + <> + {/* ... other extensions */} + + + ); +}; +``` + +### How It Works + +- **`addTypeDefs()`** — accepts a GraphQL SDL string (use the `/* GraphQL */` tag for editor syntax highlighting). Extend built-in types with `extend type Query` or `extend type Mutation`. +- **`addResolver()`** — registers a resolver for a path in the schema (e.g. `"Query.listCmsEntries"`). The `dependencies` array lists the DI tokens that Webiny injects into the `resolver` factory in the same order. +- **Result pattern** — all use cases return a `Result` object. Check `result.isFail()` before accessing `result.value`, and return the error from the GraphQL response so clients receive structured error information. + +## Adding a Custom Mutation + +The same pattern applies for mutations — extend `Mutation` instead of `Query`: + +```typescript extensions/logMyClickGraphQL.ts +import { GraphQLSchemaFactory } from "webiny/api/graphql"; +import { GetModelUseCase } from "webiny/api/cms/model"; +import { CreateEntryUseCase } from "webiny/api/cms/entry"; + +interface ILogMyClickArgs { + id: string; + ip: string; +} + +class LogMyClickGraphQL implements GraphQLSchemaFactory.Interface { + public async execute(builder: GraphQLSchemaFactory.SchemaBuilder): GraphQLSchemaFactory.Return { + builder.addTypeDefs(/* GraphQL */ ` + type LogMyClickResponseItem { + id: ID! + ip: String! + createdOn: String! + } + type LogMyClickResponse { + data: LogMyClickResponseItem + error: CmsError + } + + extend type Mutation { + logMyClick(id: ID!, ip: String!): LogMyClickResponse! + } + `); + + builder.addResolver({ + path: "Mutation.logMyClick", + dependencies: [GetModelUseCase, CreateEntryUseCase], + resolver(getModel: GetModelUseCase.Interface, createEntry: CreateEntryUseCase.Interface) { + return async ({ args }) => { + const modelResult = await getModel.execute("logMyClickModel"); + if (modelResult.isFail()) { + return { error: modelResult.error, data: null }; + } + const model = modelResult.value; + + const result = await createEntry.execute(model, { + values: { id: args.id, ip: args.ip } + }); + if (result.isFail()) { + return { error: result.error, data: null }; + } + return { data: result.value, error: null }; + }; + } + }); + + return builder; + } +} + +export default GraphQLSchemaFactory.createImplementation({ + implementation: LogMyClickGraphQL, + dependencies: [] +}); +``` + +## Deploying Changes + +After creating or modifying a GraphQL extension, deploy the API: + +``` +yarn webiny deploy api +``` + +During development, use watch mode for automatic redeployment: + +``` +yarn webiny watch api +``` diff --git a/docs/developer-docs/6.x/webiny-api/universal-api-keys.ai.txt b/docs/developer-docs/6.x/webiny-api/universal-api-keys.ai.txt new file mode 100644 index 000000000..cf0fd1187 --- /dev/null +++ b/docs/developer-docs/6.x/webiny-api/universal-api-keys.ai.txt @@ -0,0 +1,29 @@ +AI Context: Universal API Keys (universal-api-keys.mdx) + +Source of Information: +1. docs/developer-docs/6.x/website-builder/multi-tenant-nextjs.mdx — "API Key Strategy" and "Creating a Universal API Key" sections; code examples taken from there +2. User-provided code snippet showing ApiKeyFactory pattern +3. admin/whitelabeling.mdx — structural reference for extension articles + +Key Documentation Decisions: +1. Scoped to the API key provisioning pattern — does not repeat multi-tenancy concepts from multi-tenant-nextjs +2. Included a properties table to explain slug, name, token, permissions fields clearly +3. Called out slug as the idempotency key (Webiny looks up by slug to update vs create) +4. Added a "Restricting Permissions" section to discourage blanket { name: "*" } in production +5. The wat_ token prefix is documented as required based on the example +6. Warning about not committing tokens carried over from multi-tenant-nextjs + +Understanding: +ApiKeyFactory is an extension that runs at boot time. It returns an array of key definitions. Each definition has name, slug, token, and permissions. The slug is used for idempotent upsert — if a key with that slug exists it is updated, otherwise created. The token is the raw secret clients send in API requests. permissions is an array of permission objects where name: "*" is the wildcard. For multi-tenant deployments, one universal key at the root tenant with { name: "*" } is the recommended starting point; tenant scoping happens via the apiTenant SDK parameter, not the key. + +Related Documents: +- docs/developer-docs/6.x/website-builder/multi-tenant-nextjs.mdx — usage of universal key in Next.js +- docs/developer-docs/6.x/reference/api/security/api-key.mdx — API reference + +Key Code Locations: +- packages/api-security — ApiKeyFactory interface and createImplementation + +Tone Guidelines: +- Technical and practical — audience knows what API keys are, explain the Webiny-specific factory pattern +- Lead with the what/when (overview), then the how (extension + registration) +- Table for properties adds scannability without verbose prose diff --git a/docs/developer-docs/6.x/webiny-api/universal-api-keys.mdx b/docs/developer-docs/6.x/webiny-api/universal-api-keys.mdx new file mode 100644 index 000000000..1b12900e1 --- /dev/null +++ b/docs/developer-docs/6.x/webiny-api/universal-api-keys.mdx @@ -0,0 +1,110 @@ +--- +id: tm8c6wj1 +title: Universal API Keys +description: Learn how to provision a universal API key programmatically using the ApiKeyFactory extension. +--- + +import { Alert } from "@/components/Alert"; + + + +- what a universal API key is and when to use one +- how to create an API key programmatically using `ApiKeyFactory` +- how to control permissions on the key + + + +## Overview + +API keys are used by external clients — such as a Next.js front end, a mobile app, or a CI/CD pipeline — to authenticate requests to the Webiny API. By default, every tenant gets its own API key managed through the Admin UI under **Settings → Access Management → API Keys**. + +For multi-tenant deployments, managing one key per tenant becomes impractical. A **universal API key** is a single key provisioned at the root tenant level that can access content across all tenants. The tenant is scoped per request through the `apiTenant` parameter on the SDK, not through the key itself. + +Universal keys are created programmatically via the `ApiKeyFactory` extension. The factory runs when Webiny boots and ensures the key exists with the permissions you specify. + +## Creating the Extension + +Create a new extension file: + +```typescript extensions/security/universalApiKey.ts +import { ApiKeyFactory } from "webiny/api/security"; + +class UniversalApiKeyImpl implements ApiKeyFactory.Interface { + async execute(): ApiKeyFactory.Return { + return [ + { + name: "Universal API Key", + slug: "universal-key", + token: process.env.WEBINY_API_UNIVERSAL_KEY as string, + permissions: [{ name: "*" }] + } + ]; + } +} + +export default ApiKeyFactory.createImplementation({ + implementation: UniversalApiKeyImpl, + dependencies: [] +}); +``` + +Set `WEBINY_API_UNIVERSAL_KEY` in your environment before deploying. Generate a strong, random token prefixed with `wat_` (e.g. `wat_` followed by a securely generated string) and store it in your secret manager. Inject it at deploy time — do not commit the value to source control. + +Then register it in `webiny.config.tsx`: + +```tsx webiny.config.tsx +import React from "react"; +import { Api } from "webiny/extensions"; + +export const Extensions = () => { + return ( + <> + {/* ... other extensions */} + + + ); +}; +``` + +## Key Properties + +| Property | Description | +| ------------- | ---------------------------------------------------------------------------------------------------------------------------------- | +| `name` | Human-readable label shown in the Admin UI | +| `slug` | Unique identifier for the key; used internally to look up and update the key on each boot | +| `token` | The secret value clients include in API requests; must be prefixed with `wat_`; read from an environment variable, never hardcoded | +| `permissions` | Array of permission objects; `{ name: "*" }` grants full access across all tenants | + +The `slug` field is important: Webiny uses it to determine whether the key already exists. If the key is found by its slug, it is updated in place rather than created again. Use a stable, unique slug for each key in your project. + + + +Store the token value in a secret manager and inject it at deploy time. Do not commit the raw token to source control. + + + +## Restricting Permissions + +The `permissions: [{ name: "*" }]` grant gives broad access. For tighter control, specify the exact permission scopes your clients need. For example, to restrict the key to read-only Website Builder access: + +```typescript +permissions: [{ name: "pb.page", rwd: "r" }, { name: "pb.settings" }]; +``` + +The available permission names and their options depend on the Webiny applications you have installed. You can inspect the permissions an existing key holds in the Admin UI under **Settings → Access Management → API Keys**. + +## Deploying the Key + +After creating the extension, deploy the API so the factory runs and the key is provisioned: + +``` +yarn webiny deploy api +``` + +During development, the key is created on the next boot triggered by watch mode: + +``` +yarn webiny watch api +``` + +Once deployed, use the token value wherever your client authenticates against the Webiny API — for example, as the `NEXT_PUBLIC_WEBSITE_BUILDER_API_KEY` environment variable in a Next.js project. diff --git a/docs/developer-docs/6.x/website-builder/multi-tenant-nextjs.mdx b/docs/developer-docs/6.x/website-builder/multi-tenant-nextjs.mdx index 15bd163c3..f4a44168b 100644 --- a/docs/developer-docs/6.x/website-builder/multi-tenant-nextjs.mdx +++ b/docs/developer-docs/6.x/website-builder/multi-tenant-nextjs.mdx @@ -1,14 +1,14 @@ --- id: wbmt7n4k -title: Multi-Tenant Next.js Setup -description: Configure a single Next.js application to serve content from multiple Webiny tenants based on domain, subdomain, or other request context. +title: Multi-Tenant Setup +description: Configure a single front-end application to serve content from multiple Webiny tenants based on domain, subdomain, or other request context. --- import { Alert } from "@/components/Alert"; -- How a single Next.js app can serve content from multiple Webiny tenants +- How a single front-end app can serve content from multiple Webiny tenants - How to resolve tenant identity from the incoming request - How to initialize the SDK with the correct tenant per request - Which API key strategy fits multi-tenant deployments @@ -18,11 +18,13 @@ import { Alert } from "@/components/Alert"; ## Overview -The default Next.js starter kit connects to one Webiny tenant set by the `NEXT_PUBLIC_WEBSITE_BUILDER_API_TENANT` environment variable. For SaaS platforms and multi-tenant deployments, a single Next.js instance can serve content from many tenants by resolving tenant identity at request time. +By default, the Website Builder SDK connects to one Webiny tenant configured via an environment variable. For SaaS platforms and multi-tenant deployments, a single front-end instance can serve content from many tenants by resolving tenant identity at request time and passing it to the SDK. -The pattern has three parts: resolve tenant identity in middleware, propagate it to server components via a request header, then read it when initializing the SDK. +The core idea is the same regardless of framework: resolve the tenant from the incoming request, then pass it to the SDK initializer so all API calls are scoped to that tenant. -## How Tenant Scoping Works +## Next.js + +### How Tenant Scoping Works The `contentSdk.init()` call accepts an `apiTenant` parameter. Normally this is set from the environment variable, but you can pass it dynamically. The SDK then scopes all API calls — page fetching, redirect resolution — to that tenant. @@ -45,7 +47,7 @@ initializeContentSdk({ tenantId }) ← scopes SDK to tenant contentSdk.getPage() ← fetches pages for that tenant only ``` -## Resolving Tenant in Middleware +### Resolving Tenant in Middleware Next.js middleware runs before any rendering and is the right place to resolve tenant identity from the request — subdomain, full domain, path prefix, or any other signal — and attach it as a header for downstream components. @@ -110,7 +112,7 @@ The example above uses subdomain-based resolution. Replace `resolveTenantFromHos -## Reading Tenant in Server Components +### Reading Tenant in Server Components Add a utility that reads the `X-Tenant` header set by middleware: @@ -129,7 +131,7 @@ export const getTenant = async (): Promise => { The fallback to `"root"` ensures the app keeps working when no tenant header is present, for example during static generation at build time. -## Initializing the SDK Per Request +### Initializing the SDK Per Request Update `initializeContentSdk` to accept a `tenantId` parameter. When provided, it overrides the `NEXT_PUBLIC_WEBSITE_BUILDER_API_TENANT` environment variable: @@ -203,7 +205,7 @@ export default async function RootLayout({ children }: { children: React.ReactNo `ContentSdkInitializer` is a memoized client component that calls `initializeContentSdk` on the browser side with the same tenant context. -## API Key Strategy +### API Key Strategy Two approaches work for multi-tenant deployments: @@ -213,67 +215,15 @@ Two approaches work for multi-tenant deployments: For most SaaS deployments, a universal key is the simpler and recommended starting point. -### Creating a Universal API Key - -A universal API key must be provisioned programmatically via the `ApiKeyFactory` extension. This factory runs when Webiny boots and ensures the key exists in the root tenant with the permissions you specify. - -Create the factory file: - -```typescript extensions/security/universalApiKey.ts -import { ApiKeyFactory } from "webiny/api/security"; - -class UniversalApiKeyImpl implements ApiKeyFactory.Interface { - async execute(): ApiKeyFactory.Return { - return [ - { - name: "Universal API Key", - slug: "universal-key", - token: "wat_12345678", - permissions: [{ name: "*" }] - } - ]; - } -} - -export default ApiKeyFactory.createImplementation({ - implementation: UniversalApiKeyImpl, - dependencies: [] -}); -``` - -Register it in `webiny.config.tsx`: - -```tsx webiny.config.tsx -import React from "react"; -import { Api } from "webiny/extensions"; - -export const Extensions = () => { - return ( - <> - {/* ... your other extensions */} - - - ); -}; -``` - -Set the `token` value as `NEXT_PUBLIC_WEBSITE_BUILDER_API_KEY` in your Next.js environment: - -``` -NEXT_PUBLIC_WEBSITE_BUILDER_API_KEY=wat_12345678 -``` - - - -Store the token value in a secret manager and inject it at deploy time. Do not commit the raw token to source control. The `permissions: [{ name: "*" }]` grant gives full read access across all tenants — use a more restrictive permission set if your deployment requires it. +#### Creating a Universal API Key - +See [Universal API Keys](/{version}/webiny-api/universal-api-keys) for a complete guide on provisioning a universal API key programmatically. Once deployed, set the token as `NEXT_PUBLIC_WEBSITE_BUILDER_API_KEY` in your Next.js environment. -## Per-Tenant Theming +### Per-Tenant Theming Each tenant can carry its own brand colors stored as custom fields on the Webiny tenant model (e.g. `primaryColor`, `secondaryColor`). The recommended pattern is to fetch them server-side in your page component using `@webiny/sdk`, then inject them into `` as CSS custom properties — available on the very first render with no client-side flash. -### Initialize the Webiny SDK +#### Initialize the Webiny SDK Create a singleton `Sdk` instance using the same environment variables as the Website Builder SDK: @@ -287,9 +237,9 @@ export const sdk = new Sdk({ }); ``` -### Fetch and inject theme colors +#### Fetch and inject theme colors -Add a server-side helper that calls `sdk.tenantManager.getCurrentTenant()`, reads the custom `extensions.theme` object, and builds a `:root` CSS rule: +Add a server-side helper that calls `sdk.tenantManager.getCurrentTenant()`, reads the custom `extensions.theme` object, and builds a `:root` CSS rule. The `extensions.theme` fields are defined via a tenant model extension — see [Extend Tenant Model](/{version}/tenant-manager/extend-tenant-model) for how to add them. This is the simplest approach; alternatively, theme data can also be stored in a single-entry Headless CMS content model and fetched via the CMS API. ```typescript async function getTenantThemeCss(): Promise { @@ -322,7 +272,7 @@ export default async function Page({ params, searchParams }: PageProps) { } ``` -### Use the CSS variables in components +#### Use the CSS variables in components Any client component can now reference the variables directly — no props, no context: @@ -331,9 +281,3 @@ Any client component can now reference the variables directly — no props, no c ``` The custom properties are set on `:root` before any React hydration, so the correct tenant colors are always visible on first paint. - - - -The `extensions.theme` object is populated via a custom tenant model extension in Webiny Admin. The field names (`primaryColor`, `secondaryColor`, etc.) depend on how your extension is defined. Cast `values.extensions` to your own typed interface when reading it. - - From aa06f7ccf6545f27406ce454dd3832d71bde3838 Mon Sep 17 00:00:00 2001 From: adrians5j Date: Thu, 2 Apr 2026 23:54:10 +0200 Subject: [PATCH 4/6] wip:4 (ms64k) --- .../headless-cms/content-models-via-code.mdx | 53 ++++++++++++++++--- 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/docs/developer-docs/6.x/headless-cms/content-models-via-code.mdx b/docs/developer-docs/6.x/headless-cms/content-models-via-code.mdx index f05523eb2..73611a9d8 100644 --- a/docs/developer-docs/6.x/headless-cms/content-models-via-code.mdx +++ b/docs/developer-docs/6.x/headless-cms/content-models-via-code.mdx @@ -11,6 +11,7 @@ import { Alert } from "@/components/Alert"; - Why define content models via code? - How to create a content model using the [`ModelFactory`](/{version}/reference/api/cms/model#model-factory) API? - How to define reference fields and object fields? +- How to create single-entry and private models? - How to register models as extensions? @@ -98,14 +99,15 @@ export const Extensions = () => { **Model configuration** -| Method | Description | -| ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -| `.public({ modelId, name, group })` | Model is visible in the Admin sidebar and exposed via the Read, Preview, and Manage GraphQL endpoints | -| `.private({ modelId, name, group })` | Model is not visible in the Admin sidebar and not exposed via the public GraphQL endpoints; useful for internal or system-level models | -| `.description()` | Model description shown in the Admin | -| `.singularApiName()` / `.pluralApiName()` | GraphQL query names | -| `.layout()` | Defines how fields are arranged in rows in the Admin UI (`[["field1", "field2"], ["field3"]]`) | -| `.titleFieldId()` | Which field to use as the entry title in list views | +| Method | Description | +| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | +| `.public({ modelId, name, group })` | Model is visible in the Admin sidebar and exposed via the Read, Preview, and Manage GraphQL endpoints | +| `.private({ modelId, name, group })` | Model is not visible in the Admin sidebar and not exposed via the public GraphQL endpoints; access data via use cases in backend code | +| `.singleEntry()` | Only one entry of this model can exist; the Admin shows the entry form directly instead of a list view | +| `.description()` | Model description shown in the Admin | +| `.singularApiName()` / `.pluralApiName()` | GraphQL query names | +| `.layout()` | Defines how fields are arranged in rows in the Admin UI (`[["field1", "field2"], ["field3"]]`) | +| `.titleFieldId()` | Which field to use as the entry title in list views | **Field types** @@ -236,6 +238,41 @@ All renderer names are available via TypeScript autocomplete when calling `.rend | Special | `dynamicZone`, `hidden`, `passthrough` | | UI elements | `uiSeparator`, `uiAlert`, `uiTabs` | +## Single-Entry Models + +A single-entry model allows only one entry to exist. Call `.singleEntry()` on the builder to enable this mode. It is useful for global site settings, per-tenant configuration, or any data that should have exactly one record. + +```typescript extensions/siteSettingsModel.ts +import { ModelFactory } from "webiny/api/cms/model"; + +class SiteSettingsModelImpl implements ModelFactory.Interface { + async execute(builder: ModelFactory.Builder) { + return [ + builder + .public({ + modelId: "siteSettings", + name: "Site Settings", + group: "ungrouped" + }) + .singleEntry() + .fields(fields => ({ + googleAnalyticsId: fields.text().renderer("textInput").label("Google Analytics ID"), + facebookPixelId: fields.text().renderer("textInput").label("Facebook Pixel ID") + })) + .singularApiName("SiteSetting") + .pluralApiName("SiteSettings") + ]; + } +} + +export default ModelFactory.createImplementation({ + implementation: SiteSettingsModelImpl, + dependencies: [] +}); +``` + +The entry is available on both the Manage and Read GraphQL endpoints. The Admin shows the entry form directly — there is no list view. + ## Deploying Changes After creating or modifying a model extension, deploy the API: From 5c5200024a5c37391bbcdf392772ef49c6ef7469 Mon Sep 17 00:00:00 2001 From: adrians5j Date: Fri, 3 Apr 2026 11:23:51 +0200 Subject: [PATCH 5/6] wip:5 (5ixog) --- docs/developer-docs/6.x/navigation.tsx | 29 ++++++++++--------- generator/src/components/navigation.tsx | 4 ++- .../sidebar/components/HorizontalLine.js | 12 +++++++- .../sidebar/components/NavTreeElement.js | 2 +- 4 files changed, 31 insertions(+), 16 deletions(-) diff --git a/docs/developer-docs/6.x/navigation.tsx b/docs/developer-docs/6.x/navigation.tsx index e72f8883d..79f24fad1 100644 --- a/docs/developer-docs/6.x/navigation.tsx +++ b/docs/developer-docs/6.x/navigation.tsx @@ -43,6 +43,21 @@ export const Navigation = ({ children }: { children: React.ReactNode }) => { + + + + + + + + + + + { {/* */} {/**/} - - - - - - - - - { {/* */} {/* */} {/**/} + diff --git a/generator/src/components/navigation.tsx b/generator/src/components/navigation.tsx index 1497fc046..8047c6df4 100644 --- a/generator/src/components/navigation.tsx +++ b/generator/src/components/navigation.tsx @@ -140,12 +140,14 @@ interface SeparatorProps { remove?: boolean; before?: string; after?: string; + title?: string; } -export const Separator = ({ after, before, remove }: SeparatorProps) => { +export const Separator = ({ after, before, remove, title }: SeparatorProps) => { return ( + {title ? : null} ); }; diff --git a/src/layouts/sidebar/components/HorizontalLine.js b/src/layouts/sidebar/components/HorizontalLine.js index 272bb5a21..bb0fbe6b0 100644 --- a/src/layouts/sidebar/components/HorizontalLine.js +++ b/src/layouts/sidebar/components/HorizontalLine.js @@ -1,7 +1,7 @@ import { useRouter } from "next/router"; import { useHomepage } from "@/hooks/useHomepage"; -export const HorizontalLine = ({ visible }) => { +export const HorizontalLine = ({ visible, title }) => { const router = useRouter(); const { homepageUrl } = useHomepage(); const showFullMenu = visible || router.pathname === homepageUrl; @@ -10,6 +10,16 @@ export const HorizontalLine = ({ visible }) => { return null; } + if (title) { + return ( +
+ + {title} + +
+ ); + } + return (
diff --git a/src/layouts/sidebar/components/NavTreeElement.js b/src/layouts/sidebar/components/NavTreeElement.js index ab26e5a1c..5540cab2b 100644 --- a/src/layouts/sidebar/components/NavTreeElement.js +++ b/src/layouts/sidebar/components/NavTreeElement.js @@ -46,7 +46,7 @@ export const NavTreeElement = forwardRef(({ element, depth = 0, mode, depthOverr ); if (type === "separator") { - return ; + return ; } if (type === "page") { From 2a2f4b48a95a6243935455c5c51b4a1dde849344 Mon Sep 17 00:00:00 2001 From: adrians5j Date: Fri, 3 Apr 2026 11:40:07 +0200 Subject: [PATCH 6/6] wip:6 (o5758) --- docs/developer-docs/6.x/navigation.tsx | 98 +- .../developer-docs/6.x/reference/admin.ai.txt | 30 - docs/developer-docs/6.x/reference/admin.mdx | 228 -- .../6.x/reference/admin/aco.ai.txt | 26 - .../6.x/reference/admin/aco.mdx | 72 - .../6.x/reference/admin/build-params.ai.txt | 25 - .../6.x/reference/admin/build-params.mdx | 75 - .../6.x/reference/admin/cms.ai.txt | 32 - .../6.x/reference/admin/cms.mdx | 265 -- .../reference/admin/cms/entry/editor.ai.txt | 28 - .../6.x/reference/admin/cms/entry/editor.mdx | 113 - .../6.x/reference/admin/cms/entry/list.ai.txt | 26 - .../6.x/reference/admin/cms/entry/list.mdx | 51 - .../cms/field-renderers/dynamic-zone.ai.txt | 25 - .../cms/field-renderers/dynamic-zone.mdx | 21 - .../admin/cms/field-renderers/object.ai.txt | 25 - .../admin/cms/field-renderers/object.mdx | 21 - .../6.x/reference/admin/cms/lexical.ai.txt | 25 - .../6.x/reference/admin/cms/lexical.mdx | 168 -- .../6.x/reference/admin/cms/model.ai.txt | 26 - .../6.x/reference/admin/cms/model.mdx | 90 - .../6.x/reference/admin/configs.ai.txt | 25 - .../6.x/reference/admin/configs.mdx | 21 - .../6.x/reference/admin/env-config.ai.txt | 26 - .../6.x/reference/admin/env-config.mdx | 58 - .../6.x/reference/admin/form.ai.txt | 26 - .../6.x/reference/admin/form.mdx | 275 -- .../6.x/reference/admin/graphql-client.ai.txt | 25 - .../6.x/reference/admin/graphql-client.mdx | 47 - .../6.x/reference/admin/lexical.ai.txt | 26 - .../6.x/reference/admin/lexical.mdx | 253 -- .../6.x/reference/admin/local-storage.ai.txt | 26 - .../6.x/reference/admin/local-storage.mdx | 93 - .../6.x/reference/admin/router.ai.txt | 26 - .../6.x/reference/admin/router.mdx | 89 - .../6.x/reference/admin/security.ai.txt | 31 - .../6.x/reference/admin/security.mdx | 199 -- .../6.x/reference/admin/tenancy.ai.txt | 30 - .../6.x/reference/admin/tenancy.mdx | 150 - .../6.x/reference/admin/ui.ai.txt | 84 - .../developer-docs/6.x/reference/admin/ui.mdx | 1443 ---------- .../reference/admin/website-builder.ai.txt | 27 - .../6.x/reference/admin/website-builder.mdx | 93 - .../admin/website-builder/lexical.ai.txt | 25 - .../admin/website-builder/lexical.mdx | 168 -- .../admin/website-builder/page/editor.ai.txt | 40 - .../admin/website-builder/page/editor.mdx | 536 ---- .../admin/website-builder/page/list.ai.txt | 25 - .../admin/website-builder/page/list.mdx | 29 - .../website-builder/redirect/list.ai.txt | 25 - .../admin/website-builder/redirect/list.mdx | 29 - docs/developer-docs/6.x/reference/api.ai.txt | 25 - docs/developer-docs/6.x/reference/api.mdx | 21 - .../6.x/reference/api/aco/flp.ai.txt | 29 - .../6.x/reference/api/aco/flp.mdx | 149 - .../6.x/reference/api/aco/folder.ai.txt | 26 - .../6.x/reference/api/aco/folder.mdx | 83 - .../6.x/reference/api/build-params.ai.txt | 25 - .../6.x/reference/api/build-params.mdx | 75 - .../6.x/reference/api/cms/entry.ai.txt | 64 - .../6.x/reference/api/cms/entry.mdx | 1952 ------------- .../6.x/reference/api/cms/group.ai.txt | 34 - .../6.x/reference/api/cms/group.mdx | 476 ---- .../6.x/reference/api/cms/model.ai.txt | 41 - .../6.x/reference/api/cms/model.mdx | 735 ----- .../6.x/reference/api/cms/scheduler.ai.txt | 26 - .../6.x/reference/api/cms/scheduler.mdx | 80 - .../6.x/reference/api/event-publisher.ai.txt | 25 - .../6.x/reference/api/event-publisher.mdx | 58 - .../reference/api/file-manager/file.ai.txt | 36 - .../6.x/reference/api/file-manager/file.mdx | 743 ----- .../api/file-manager/permissions.ai.txt | 25 - .../api/file-manager/permissions.mdx | 29 - .../api/file-manager/settings.ai.txt | 27 - .../reference/api/file-manager/settings.mdx | 166 -- .../6.x/reference/api/graphql.ai.txt | 27 - .../6.x/reference/api/graphql.mdx | 184 -- .../6.x/reference/api/key-value-store.ai.txt | 25 - .../6.x/reference/api/key-value-store.mdx | 92 - .../6.x/reference/api/logger.ai.txt | 25 - .../6.x/reference/api/logger.mdx | 51 - .../6.x/reference/api/scheduler.ai.txt | 32 - .../6.x/reference/api/scheduler.mdx | 399 --- .../6.x/reference/api/security.ai.txt | 32 - .../6.x/reference/api/security.mdx | 308 -- .../6.x/reference/api/security/api-key.ai.txt | 31 - .../6.x/reference/api/security/api-key.mdx | 383 --- .../api/security/authentication.ai.txt | 25 - .../reference/api/security/authentication.mdx | 76 - .../6.x/reference/api/security/role.ai.txt | 29 - .../6.x/reference/api/security/role.mdx | 327 --- .../6.x/reference/api/security/user.ai.txt | 30 - .../6.x/reference/api/security/user.mdx | 351 --- .../6.x/reference/api/system.ai.txt | 25 - .../6.x/reference/api/system.mdx | 97 - .../6.x/reference/api/tasks.ai.txt | 26 - .../6.x/reference/api/tasks.mdx | 137 - .../6.x/reference/api/tenancy.ai.txt | 30 - .../6.x/reference/api/tenancy.mdx | 513 ---- .../6.x/reference/api/tenant-manager.ai.txt | 26 - .../6.x/reference/api/tenant-manager.mdx | 68 - .../api/website-builder/nextjs.ai.txt | 25 - .../reference/api/website-builder/nextjs.mdx | 46 - .../reference/api/website-builder/page.ai.txt | 36 - .../reference/api/website-builder/page.mdx | 968 ------- .../api/website-builder/redirect.ai.txt | 32 - .../api/website-builder/redirect.mdx | 561 ---- .../api/website-builder/scheduler.ai.txt | 28 - .../api/website-builder/scheduler.mdx | 138 - docs/developer-docs/6.x/reference/cli.ai.txt | 26 - docs/developer-docs/6.x/reference/cli.mdx | 88 - .../6.x/reference/cli/command.ai.txt | 25 - .../6.x/reference/cli/command.mdx | 40 - .../6.x/reference/extensions.ai.txt | 29 - .../6.x/reference/extensions.mdx | 581 ---- .../developer-docs/6.x/reference/infra.ai.txt | 33 - docs/developer-docs/6.x/reference/infra.mdx | 377 --- .../6.x/reference/infra/admin.ai.txt | 31 - .../6.x/reference/infra/admin.mdx | 198 -- .../6.x/reference/infra/api.ai.txt | 31 - .../6.x/reference/infra/api.mdx | 198 -- .../6.x/reference/infra/core.ai.txt | 30 - .../6.x/reference/infra/core.mdx | 172 -- .../6.x/reference/sdk/cms.ai.txt | 128 - docs/developer-docs/6.x/reference/sdk/cms.mdx | 644 ----- .../6.x/reference/sdk/file-manager.ai.txt | 157 -- .../6.x/reference/sdk/file-manager.mdx | 698 ----- .../6.x/reference/sdk/index.ai.txt | 140 - .../6.x/reference/sdk/index.mdx | 523 ---- .../6.x/reference/sdk/tenant-manager.ai.txt | 78 - .../6.x/reference/sdk/tenant-manager.mdx | 337 --- generateDocs.js | 66 - package.json | 10 +- public/menu-icons/api.svg | 15 + scripts/generate-reference.ts | 2478 ----------------- scripts/ref/_shared.ts | 698 ----- scripts/ref/sdk.ts | 472 ---- scripts/ref/webiny-sdk.ts | 501 ---- 138 files changed, 18 insertions(+), 24339 deletions(-) delete mode 100644 docs/developer-docs/6.x/reference/admin.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/aco.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/aco.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/build-params.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/build-params.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/cms.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/cms.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/cms/entry/editor.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/cms/entry/editor.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/cms/entry/list.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/cms/entry/list.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/cms/field-renderers/dynamic-zone.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/cms/field-renderers/dynamic-zone.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/cms/field-renderers/object.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/cms/field-renderers/object.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/cms/lexical.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/cms/lexical.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/cms/model.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/cms/model.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/configs.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/configs.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/env-config.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/env-config.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/form.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/form.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/graphql-client.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/graphql-client.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/lexical.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/lexical.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/local-storage.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/local-storage.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/router.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/router.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/security.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/security.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/tenancy.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/tenancy.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/ui.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/ui.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/website-builder.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/website-builder.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/website-builder/lexical.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/website-builder/lexical.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/website-builder/page/editor.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/website-builder/page/editor.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/website-builder/page/list.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/website-builder/page/list.mdx delete mode 100644 docs/developer-docs/6.x/reference/admin/website-builder/redirect/list.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/admin/website-builder/redirect/list.mdx delete mode 100644 docs/developer-docs/6.x/reference/api.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/aco/flp.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/aco/flp.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/aco/folder.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/aco/folder.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/build-params.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/build-params.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/cms/entry.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/cms/entry.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/cms/group.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/cms/group.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/cms/model.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/cms/model.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/cms/scheduler.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/cms/scheduler.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/event-publisher.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/event-publisher.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/file-manager/file.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/file-manager/file.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/file-manager/permissions.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/file-manager/permissions.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/file-manager/settings.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/file-manager/settings.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/graphql.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/graphql.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/key-value-store.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/key-value-store.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/logger.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/logger.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/scheduler.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/scheduler.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/security.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/security.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/security/api-key.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/security/api-key.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/security/authentication.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/security/authentication.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/security/role.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/security/role.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/security/user.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/security/user.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/system.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/system.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/tasks.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/tasks.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/tenancy.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/tenancy.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/tenant-manager.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/tenant-manager.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/website-builder/nextjs.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/website-builder/nextjs.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/website-builder/page.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/website-builder/page.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/website-builder/redirect.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/website-builder/redirect.mdx delete mode 100644 docs/developer-docs/6.x/reference/api/website-builder/scheduler.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/api/website-builder/scheduler.mdx delete mode 100644 docs/developer-docs/6.x/reference/cli.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/cli.mdx delete mode 100644 docs/developer-docs/6.x/reference/cli/command.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/cli/command.mdx delete mode 100644 docs/developer-docs/6.x/reference/extensions.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/extensions.mdx delete mode 100644 docs/developer-docs/6.x/reference/infra.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/infra.mdx delete mode 100644 docs/developer-docs/6.x/reference/infra/admin.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/infra/admin.mdx delete mode 100644 docs/developer-docs/6.x/reference/infra/api.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/infra/api.mdx delete mode 100644 docs/developer-docs/6.x/reference/infra/core.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/infra/core.mdx delete mode 100644 docs/developer-docs/6.x/reference/sdk/cms.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/sdk/cms.mdx delete mode 100644 docs/developer-docs/6.x/reference/sdk/file-manager.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/sdk/file-manager.mdx delete mode 100644 docs/developer-docs/6.x/reference/sdk/index.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/sdk/index.mdx delete mode 100644 docs/developer-docs/6.x/reference/sdk/tenant-manager.ai.txt delete mode 100644 docs/developer-docs/6.x/reference/sdk/tenant-manager.mdx delete mode 100644 generateDocs.js create mode 100644 public/menu-icons/api.svg delete mode 100644 scripts/generate-reference.ts delete mode 100644 scripts/ref/_shared.ts delete mode 100644 scripts/ref/sdk.ts delete mode 100644 scripts/ref/webiny-sdk.ts diff --git a/docs/developer-docs/6.x/navigation.tsx b/docs/developer-docs/6.x/navigation.tsx index 79f24fad1..3c0954301 100644 --- a/docs/developer-docs/6.x/navigation.tsx +++ b/docs/developer-docs/6.x/navigation.tsx @@ -50,7 +50,7 @@ export const Navigation = ({ children }: { children: React.ReactNode }) => { @@ -188,102 +188,6 @@ export const Navigation = ({ children }: { children: React.ReactNode }) => { /> - - {/* __REFERENCE_PAGES_START__ */} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {/* __SDK_PAGES_START__ */} - - - - - - {/* __SDK_PAGES_END__ */} - {/* __REFERENCE_PAGES_END__ */} - {children} diff --git a/docs/developer-docs/6.x/reference/admin.ai.txt b/docs/developer-docs/6.x/reference/admin.ai.txt deleted file mode 100644 index b7e0d6620..000000000 --- a/docs/developer-docs/6.x/reference/admin.ai.txt +++ /dev/null @@ -1,30 +0,0 @@ -AI Context: Admin (reference/admin.mdx) - -Source of Information: -1. packages/webiny/src/admin.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/app/src/shared/di/useFeature.ts — originating source -3. /Users/adrian/dev/wby-next/packages/app/src/errors/index.ts — originating source -4. /Users/adrian/dev/wby-next/packages/app-admin/src/components/index.ts — originating source -5. /Users/adrian/dev/wby-next/packages/app-admin/src/permissions/index.ts — originating source -6. /Users/adrian/dev/wby-next/packages/app-admin/src/features/buildParams/index.ts — originating source -7. /Users/adrian/dev/wby-next/packages/app-admin/src/routes.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -useFeature, NetworkErrorEventHandler, DevToolsSection, createPermissionSchema, createHasPermission, createUsePermissions, BuildParam, BuildParams, Routes - -Import Path: webiny/admin - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin.mdx b/docs/developer-docs/6.x/reference/admin.mdx deleted file mode 100644 index 4f819ec57..000000000 --- a/docs/developer-docs/6.x/reference/admin.mdx +++ /dev/null @@ -1,228 +0,0 @@ ---- -id: ywrtaw40 -title: Admin -description: "Admin app core: createFeature, createAbstraction, Provider, Plugin" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- Which event handlers can you implement? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin`. Import any of the items below directly from this path in your Webiny extensions. - -**Components** - - - -**Hooks** - - - -**Other** - - - -## Components - -### `DevToolsSection` - -**Function** — imported from `webiny/admin` - -Registers a named section in the Webiny DevTools extension. -Renders nothing — purely a data registration side-effect. - -When the component unmounts (e.g., route change), the section -is automatically removed from DevTools. - -@example - -```tsx - - -``` - -```typescript -import { DevToolsSection } from "webiny/admin"; -``` - -```typescript -export declare function DevToolsSection( -``` - -### `Routes` - -**Constant** — imported from `webiny/admin` - -```typescript -import { Routes } from "webiny/admin"; -``` - -```typescript -export const Routes = { - Dashboard: new Route({ - name: "Dashboard", - path: "/" - }), - - FileManager: new Route({ - name: "FileManager", - path: "/file-manager" - }), - - CatchAll: new Route({ - name: "CatchAll", - path: "*" - }) -}; -``` - -## Hooks - -### `useFeature` - -**Function** — imported from `webiny/admin` - -```typescript -import { useFeature } from "webiny/admin"; -``` - -```typescript -export function useFeature(feature: FeatureDefinition): TExports; -``` - -## Other - -### `BuildParam` - -**Abstraction** — imported from `webiny/admin` - -```typescript -import { BuildParam } from "webiny/admin"; -``` - -**Interface `BuildParam.Interface`:** - -```typescript -interface BuildParam.Interface { - key: string; - value: any; -} -``` - -**Types:** - -```typescript -namespace BuildParam { - type Interface = IBuildParam; -} -``` - -### `BuildParams` - -**Abstraction** — imported from `webiny/admin` - -```typescript -import { BuildParams } from "webiny/admin"; -``` - -**Interface `BuildParams.Interface`:** - -```typescript -interface BuildParams.Interface { - get(key: string): T | null; -} -``` - -**Types:** - -```typescript -namespace BuildParams { - type Interface = IBuildParams; -} -``` - -### `createHasPermission` - -**Function** — imported from `webiny/admin` - -```typescript -import { createHasPermission } from "webiny/admin"; -``` - -```typescript -export function createHasPermission( - schema: S -): React.FC>; -``` - -### `createPermissionSchema` - -**Function** — imported from `webiny/admin` - -```typescript -import { createPermissionSchema } from "webiny/admin"; -``` - -```typescript -export function createPermissionSchema(config: T): T; -``` - -### `createUsePermissions` - -**Function** — imported from `webiny/admin` - -```typescript -import { createUsePermissions } from "webiny/admin"; -``` - -```typescript -export function createUsePermissions( - schema: S -): () => UsePermissionsResult; -``` - -### `NetworkErrorEventHandler` - -**Event Handler Abstraction** — imported from `webiny/admin` - -```typescript -import { NetworkErrorEventHandler } from "webiny/admin"; -``` - -**Interface `NetworkErrorEventHandler.Interface`:** - -```typescript -interface NetworkErrorEventHandler.Interface { - handle(event: NetworkErrorEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace NetworkErrorEventHandler { - type Interface = IEventHandler; -} -``` diff --git a/docs/developer-docs/6.x/reference/admin/aco.ai.txt b/docs/developer-docs/6.x/reference/admin/aco.ai.txt deleted file mode 100644 index 7a6e5aa77..000000000 --- a/docs/developer-docs/6.x/reference/admin/aco.ai.txt +++ /dev/null @@ -1,26 +0,0 @@ -AI Context: ACO (reference/admin/aco.mdx) - -Source of Information: -1. packages/webiny/src/admin/aco.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/app-aco/src/hooks/useRecords.ts — originating source -3. /Users/adrian/dev/wby-next/packages/app-aco/src/hooks/useNavigateFolder.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -useRecords, useNavigateFolder - -Import Path: webiny/admin/aco - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/aco.mdx b/docs/developer-docs/6.x/reference/admin/aco.mdx deleted file mode 100644 index 36e32fb1a..000000000 --- a/docs/developer-docs/6.x/reference/admin/aco.mdx +++ /dev/null @@ -1,72 +0,0 @@ ---- -id: ywrtaw4v -title: ACO -description: "ACO (Advanced Content Organisation) hooks and utilities" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/aco`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/aco`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `useNavigateFolder` - -**Constant** — imported from `webiny/admin/aco` - -```typescript -import { useNavigateFolder } from "webiny/admin/aco"; -``` - -```typescript -export const useNavigateFolder = () => { - const context = useContext(NavigateFolderContext); - if (!context) { - throw new Error("useNavigateFolder must be used within a NavigateFolderContext"); - } - - return context; -}; -``` - -## `useRecords` - -**Constant** — imported from `webiny/admin/aco` - -```typescript -import { useRecords } from "webiny/admin/aco"; -``` - -```typescript -export const useRecords = makeDecoratable((folderId?: string) => { - const context = useContext(SearchRecordsContext); - - if (!context) { - throw new Error("useSearchRecords must be used within a SearchRecordsContext"); - } - - const { folderIdPath } = useAcoApp(); - - const { currentFolderId } = useNavigateFolder(); - - const { - records, - loading, - meta, - -``` diff --git a/docs/developer-docs/6.x/reference/admin/build-params.ai.txt b/docs/developer-docs/6.x/reference/admin/build-params.ai.txt deleted file mode 100644 index 8b9d8acfa..000000000 --- a/docs/developer-docs/6.x/reference/admin/build-params.ai.txt +++ /dev/null @@ -1,25 +0,0 @@ -AI Context: Build Params (reference/admin/build-params.mdx) - -Source of Information: -1. packages/webiny/src/admin/build-params.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/app-admin/src/features/buildParams/index.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -BuildParam, BuildParams - -Import Path: webiny/admin/build-params - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/build-params.mdx b/docs/developer-docs/6.x/reference/admin/build-params.mdx deleted file mode 100644 index 1ec993269..000000000 --- a/docs/developer-docs/6.x/reference/admin/build-params.mdx +++ /dev/null @@ -1,75 +0,0 @@ ---- -id: ywrtaw4v -title: Build Params -description: "Reference for webiny/admin/build-params" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/build-params`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/build-params`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `BuildParam` - -**Abstraction** — imported from `webiny/admin/build-params` - -```typescript -import { BuildParam } from "webiny/admin/build-params"; -``` - -**Interface `BuildParam.Interface`:** - -```typescript -interface BuildParam.Interface { - key: string; - value: any; -} -``` - -**Types:** - -```typescript -namespace BuildParam { - type Interface = IBuildParam; -} -``` - -## `BuildParams` - -**Abstraction** — imported from `webiny/admin/build-params` - -```typescript -import { BuildParams } from "webiny/admin/build-params"; -``` - -**Interface `BuildParams.Interface`:** - -```typescript -interface BuildParams.Interface { - get(key: string): T | null; -} -``` - -**Types:** - -```typescript -namespace BuildParams { - type Interface = IBuildParams; -} -``` diff --git a/docs/developer-docs/6.x/reference/admin/cms.ai.txt b/docs/developer-docs/6.x/reference/admin/cms.ai.txt deleted file mode 100644 index 8c368b204..000000000 --- a/docs/developer-docs/6.x/reference/admin/cms.ai.txt +++ /dev/null @@ -1,32 +0,0 @@ -AI Context: CMS (reference/admin/cms.mdx) - -Source of Information: -1. packages/webiny/src/admin/cms.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/app-headless-cms/src/admin/hooks/useQuery.ts — originating source -3. /Users/adrian/dev/wby-next/packages/app-headless-cms/src/admin/hooks/useCms.ts — originating source -4. /Users/adrian/dev/wby-next/packages/app-headless-cms/src/admin/hooks/useLazyQuery.ts — originating source -5. /Users/adrian/dev/wby-next/packages/app-headless-cms/src/admin/hooks/useMutation.ts — originating source -6. /Users/adrian/dev/wby-next/packages/app-headless-cms/src/admin/components/ModelProvider/index.ts — originating source -7. /Users/adrian/dev/wby-next/packages/app-headless-cms/src/admin/hooks/usePermission.ts — originating source -8. /Users/adrian/dev/wby-next/packages/app-headless-cms/src/routes.ts — originating source -9. /Users/adrian/dev/wby-next/packages/app-headless-cms-common/src/types/index.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -useQuery, useCms, useLazyQuery, useMutation, useModel, usePermission, Routes, CmsContentEntry, CmsModel, CmsModelField, CmsModelLayoutField, CmsIdentity - -Import Path: webiny/admin/cms - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/cms.mdx b/docs/developer-docs/6.x/reference/admin/cms.mdx deleted file mode 100644 index ea750f1f9..000000000 --- a/docs/developer-docs/6.x/reference/admin/cms.mdx +++ /dev/null @@ -1,265 +0,0 @@ ---- -id: ywrtaw4v -title: CMS -description: "CMS admin hooks, types and utilities" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/cms`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/cms`. Import any of the items below directly from this path in your Webiny extensions. - -**Components** - - - -**Hooks** - - - -**Types** - - - -## Components - -### `Routes` - -**Constant** — imported from `webiny/admin/cms` - -```typescript -import { Routes } from "webiny/admin/cms"; -``` - -```typescript -export const Routes = { - ContentModelGroups: { - List: new Route({ - name: "Cms/ContentModelGroups/List", - path: "/cms/content-model-groups", - params: zod => { - return { - id: zod.string().optional(), - new: zod.boolean().optional() - }; - } - }) - }, - - ContentEntries: { - -``` - -## Hooks - -### `useCms` - -**Function** — imported from `webiny/admin/cms` - -```typescript -import { useCms } from "webiny/admin/cms"; -``` - -```typescript -export function useCms(); -``` - -### `useLazyQuery` - -**Constant** — imported from `webiny/admin/cms` - -```typescript -import { useLazyQuery } from "webiny/admin/cms"; -``` - -```typescript -export const useLazyQuery = function ( - query: DocumentNode, - options: LazyQueryHookOptions = {} -): QueryTuple { - const { apolloClient } = useCms(); - - return apolloUseLazyQuery(query, { - client: apolloClient, - ...options - }); -}; -``` - -### `useModel` - -**Function** — imported from `webiny/admin/cms` - -Get model from the current context. - -```typescript -import { useModel } from "webiny/admin/cms"; -``` - -```typescript -export function useModel(): UseModelReturnType; -``` - -### `useMutation` - -**Constant** — imported from `webiny/admin/cms` - -```typescript -import { useMutation } from "webiny/admin/cms"; -``` - -```typescript -export const useMutation = function ( - mutation: DocumentNode, - options: MutationHookOptions = {} -): MutationTuple { - const { apolloClient } = useCms(); - - return apolloUseMutation(mutation, { - client: apolloClient, - ...options - }); -}; -``` - -### `usePermission` - -**Constant** — imported from `webiny/admin/cms` - -```typescript -import { usePermission } from "webiny/admin/cms"; -``` - -```typescript -export const usePermission = makeDecoratable(() => { - const { identity } = useIdentity(); - - const hasFullAccess = useMemo(() => !!identity.getPermission("cms.*"), [identity]); - - const canRead = useCallback( - (permissionName: string): boolean => { - if (hasFullAccess) { - return true; - } - const permissions = - identity.getP -``` - -### `useQuery` - -**Constant** — imported from `webiny/admin/cms` - -```typescript -import { useQuery } from "webiny/admin/cms"; -``` - -```typescript -export const useQuery = function ( - query: DocumentNode, - options: QueryHookOptions = {} -): QueryResult { - const { apolloClient } = useCms(); - - return apolloUseQuery(query, { - client: apolloClient, - skip: !apolloClient, - ...options - }); -}; -``` - -## Types - -### `CmsContentEntry` - -**Type** — imported from `webiny/admin/cms` - -```typescript -import type { CmsContentEntry } from "webiny/admin/cms"; -``` - -```typescript -export interface CmsContentEntry { ... } -``` - -### `CmsIdentity` - -**Type** — imported from `webiny/admin/cms` - -```typescript -import type { CmsIdentity } from "webiny/admin/cms"; -``` - -```typescript -export interface CmsIdentity { - id: string; - displayName: string; - type: string; -} -``` - -### `CmsModel` - -**Type** — imported from `webiny/admin/cms` - -```typescript -import type { CmsModel } from "webiny/admin/cms"; -``` - -```typescript -export interface CmsModel { ... } -``` - -### `CmsModelField` - -**Type** — imported from `webiny/admin/cms` - -```typescript -import type { CmsModelField } from "webiny/admin/cms"; -``` - -```typescript -export type CmsModelField = T & { ... }; -``` - -### `CmsModelLayoutField` - -**Type** — imported from `webiny/admin/cms` - -```typescript -import type { CmsModelLayoutField } from "webiny/admin/cms"; -``` - -```typescript -export interface CmsModelLayoutField { - id: string; - type: string; - rules?: FieldRule[]; -} -``` diff --git a/docs/developer-docs/6.x/reference/admin/cms/entry/editor.ai.txt b/docs/developer-docs/6.x/reference/admin/cms/entry/editor.ai.txt deleted file mode 100644 index f770c5ce0..000000000 --- a/docs/developer-docs/6.x/reference/admin/cms/entry/editor.ai.txt +++ /dev/null @@ -1,28 +0,0 @@ -AI Context: Editor (reference/admin/cms/entry/editor.mdx) - -Source of Information: -1. packages/webiny/src/admin/cms/entry/editor.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/app-headless-cms/src/admin/components/ContentEntryForm/useContentEntryForm.ts — originating source -3. /Users/adrian/dev/wby-next/packages/app-headless-cms/src/admin/views/contentEntries/hooks/index.ts — originating source -4. /Users/adrian/dev/wby-next/packages/app-headless-cms/src/admin/config/contentEntries/index.ts — originating source -5. /Users/adrian/dev/wby-next/packages/app-headless-cms/src/admin/views/contentEntries/hooks/useSingletonContentEntry.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -useContentEntryForm, useContentEntryEditor, ContentEntryEditorConfig, useSingleEntryContentEntry - -Import Path: webiny/admin/cms/entry/editor - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/cms/entry/editor.mdx b/docs/developer-docs/6.x/reference/admin/cms/entry/editor.mdx deleted file mode 100644 index 73fea49b7..000000000 --- a/docs/developer-docs/6.x/reference/admin/cms/entry/editor.mdx +++ /dev/null @@ -1,113 +0,0 @@ ---- -id: ywrtaw4v -title: Editor -description: "Content entry editor components and hooks" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/cms/entry/editor`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/cms/entry/editor`. Import any of the items below directly from this path in your Webiny extensions. - -**Components** - - - -**Hooks** - - - -## Components - -### `ContentEntryEditorConfig` - -**Constant** — imported from `webiny/admin/cms/entry/editor` - -```typescript -import { ContentEntryEditorConfig } from "webiny/admin/cms/entry/editor"; -``` - -```typescript -export const ContentEntryEditorConfig = Object.assign(base.Config, { - Actions, - FieldElement, - Width, - ValidationIndicators: ValidationIndicatorsConfig -}); -``` - -## Hooks - -### `useContentEntryEditor` - -**Constant** — imported from `webiny/admin/cms/entry/editor` - -```typescript -import { useContentEntryEditor } from "webiny/admin/cms/entry/editor"; -``` - -```typescript -export const useContentEntry = makeDecoratable(() => { - const context = useContext(ContentEntryContext); - if (!context) { - throw Error(`useContentEntry() hook can only be used within the ContentEntryContext provider.`); - } - return context; -}); -``` - -### `useContentEntryForm` - -**Constant** — imported from `webiny/admin/cms/entry/editor` - -```typescript -import { useContentEntryForm } from "webiny/admin/cms/entry/editor"; -``` - -```typescript -export const useContentEntryForm = makeDecoratable(() => { - const context = React.useContext(ContentEntryFormContext); - if (!context) { - throw new Error("ContentEntryFormProvider is missing in the component hierarchy!"); - } - - return context; -}); -``` - -### `useSingleEntryContentEntry` - -**Constant** — imported from `webiny/admin/cms/entry/editor` - -```typescript -import { useSingleEntryContentEntry } from "webiny/admin/cms/entry/editor"; -``` - -```typescript -export const useSingletonContentEntry = makeDecoratable(() => { - const context = useContext(SingletonContentEntryContext); - if (!context) { - throw Error( - `useSingletonContentEntry() hook can only be used within the SingletonContentEntryContext provider.` - ); - } - return context; -}); -``` diff --git a/docs/developer-docs/6.x/reference/admin/cms/entry/list.ai.txt b/docs/developer-docs/6.x/reference/admin/cms/entry/list.ai.txt deleted file mode 100644 index 2a7704f2c..000000000 --- a/docs/developer-docs/6.x/reference/admin/cms/entry/list.ai.txt +++ /dev/null @@ -1,26 +0,0 @@ -AI Context: List (reference/admin/cms/entry/list.mdx) - -Source of Information: -1. packages/webiny/src/admin/cms/entry/list.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/app-headless-cms/src/admin/config/contentEntries/index.ts — originating source -3. /Users/adrian/dev/wby-next/packages/app-headless-cms/src/admin/hooks/index.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -ContentEntryListConfig, useContentEntriesList - -Import Path: webiny/admin/cms/entry/list - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/cms/entry/list.mdx b/docs/developer-docs/6.x/reference/admin/cms/entry/list.mdx deleted file mode 100644 index 4fc1e69f3..000000000 --- a/docs/developer-docs/6.x/reference/admin/cms/entry/list.mdx +++ /dev/null @@ -1,51 +0,0 @@ ---- -id: ywrtaw4v -title: List -description: "Content entry list configuration" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/cms/entry/list`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/cms/entry/list`. Import any of the items below directly from this path in your Webiny extensions. - -**Components** - - - -**Other** - - - -## Components - -### `ContentEntryListConfig` - -**Constant** — imported from `webiny/admin/cms/entry/list` - -```typescript -import { ContentEntryListConfig } from "webiny/admin/cms/entry/list"; -``` - -```typescript -export const ContentEntryListConfig = Object.assign(PublicContentEntryListConfig, { Browser }); -``` - -## Other - -### `useContentEntriesList` - -**Export** — imported from `webiny/admin/cms/entry/list` - -```typescript -import { useContentEntriesList } from "webiny/admin/cms/entry/list"; -``` diff --git a/docs/developer-docs/6.x/reference/admin/cms/field-renderers/dynamic-zone.ai.txt b/docs/developer-docs/6.x/reference/admin/cms/field-renderers/dynamic-zone.ai.txt deleted file mode 100644 index 8021b1469..000000000 --- a/docs/developer-docs/6.x/reference/admin/cms/field-renderers/dynamic-zone.ai.txt +++ /dev/null @@ -1,25 +0,0 @@ -AI Context: Dynamic Zone (reference/admin/cms/field-renderers/dynamic-zone.mdx) - -Source of Information: -1. packages/webiny/src/admin/cms/field-renderers/dynamic-zone.ts — barrel re-export file - - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: - - -Import Path: webiny/admin/cms/field-renderers/dynamic-zone - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/cms/field-renderers/dynamic-zone.mdx b/docs/developer-docs/6.x/reference/admin/cms/field-renderers/dynamic-zone.mdx deleted file mode 100644 index 47801d2af..000000000 --- a/docs/developer-docs/6.x/reference/admin/cms/field-renderers/dynamic-zone.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: ywrtaw4v -title: Dynamic Zone -description: "Reference for webiny/admin/cms/field-renderers/dynamic-zone" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/cms/field-renderers/dynamic-zone`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/cms/field-renderers/dynamic-zone`. Import any of the items below directly from this path in your Webiny extensions. - -_No exported symbols found._ diff --git a/docs/developer-docs/6.x/reference/admin/cms/field-renderers/object.ai.txt b/docs/developer-docs/6.x/reference/admin/cms/field-renderers/object.ai.txt deleted file mode 100644 index 28277b00e..000000000 --- a/docs/developer-docs/6.x/reference/admin/cms/field-renderers/object.ai.txt +++ /dev/null @@ -1,25 +0,0 @@ -AI Context: Object (reference/admin/cms/field-renderers/object.mdx) - -Source of Information: -1. packages/webiny/src/admin/cms/field-renderers/object.ts — barrel re-export file - - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: - - -Import Path: webiny/admin/cms/field-renderers/object - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/cms/field-renderers/object.mdx b/docs/developer-docs/6.x/reference/admin/cms/field-renderers/object.mdx deleted file mode 100644 index 2ca35754a..000000000 --- a/docs/developer-docs/6.x/reference/admin/cms/field-renderers/object.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: ywrtaw4v -title: Object -description: "Reference for webiny/admin/cms/field-renderers/object" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/cms/field-renderers/object`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/cms/field-renderers/object`. Import any of the items below directly from this path in your Webiny extensions. - -_No exported symbols found._ diff --git a/docs/developer-docs/6.x/reference/admin/cms/lexical.ai.txt b/docs/developer-docs/6.x/reference/admin/cms/lexical.ai.txt deleted file mode 100644 index 78042214d..000000000 --- a/docs/developer-docs/6.x/reference/admin/cms/lexical.ai.txt +++ /dev/null @@ -1,25 +0,0 @@ -AI Context: Lexical Editor (reference/admin/cms/lexical.mdx) - -Source of Information: -1. packages/webiny/src/admin/cms/lexical.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/lexical-editor/src/exports/admin/lexical.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -useLexicalEditorConfig, LexicalHtmlRenderer, getNodeFromSelection, useCurrentElement, useCurrentSelection, useDeriveValueFromSelection, useRichTextEditor, useFontColorPicker, useTextAlignmentAction, useTypographyAction, useIsMounted, Divider, DropDownItem, DropDown, Klass, LexicalNode - -Import Path: webiny/admin/cms/lexical - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/cms/lexical.mdx b/docs/developer-docs/6.x/reference/admin/cms/lexical.mdx deleted file mode 100644 index 38113ff49..000000000 --- a/docs/developer-docs/6.x/reference/admin/cms/lexical.mdx +++ /dev/null @@ -1,168 +0,0 @@ ---- -id: ywrtaw4v -title: Lexical Editor -description: "CMS Lexical rich-text editor config" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/cms/lexical`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/cms/lexical`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `Divider` - -**Export** — imported from `webiny/admin/cms/lexical` - -```typescript -import { Divider } from "webiny/admin/cms/lexical"; -``` - -## `DropDown` - -**Export** — imported from `webiny/admin/cms/lexical` - -```typescript -import { DropDown } from "webiny/admin/cms/lexical"; -``` - -## `DropDownItem` - -**Export** — imported from `webiny/admin/cms/lexical` - -```typescript -import { DropDownItem } from "webiny/admin/cms/lexical"; -``` - -## `getNodeFromSelection` - -**Export** — imported from `webiny/admin/cms/lexical` - -```typescript -import { getNodeFromSelection } from "webiny/admin/cms/lexical"; -``` - -## `Klass` - -**Type** — imported from `webiny/admin/cms/lexical` - -```typescript -import type { Klass } from "webiny/admin/cms/lexical"; -``` - -## `LexicalHtmlRenderer` - -**Export** — imported from `webiny/admin/cms/lexical` - -```typescript -import { LexicalHtmlRenderer } from "webiny/admin/cms/lexical"; -``` - -## `LexicalNode` - -**Type** — imported from `webiny/admin/cms/lexical` - -```typescript -import type { LexicalNode } from "webiny/admin/cms/lexical"; -``` - -## `useCurrentElement` - -**Export** — imported from `webiny/admin/cms/lexical` - -```typescript -import { useCurrentElement } from "webiny/admin/cms/lexical"; -``` - -## `useCurrentSelection` - -**Export** — imported from `webiny/admin/cms/lexical` - -```typescript -import { useCurrentSelection } from "webiny/admin/cms/lexical"; -``` - -## `useDeriveValueFromSelection` - -**Export** — imported from `webiny/admin/cms/lexical` - -```typescript -import { useDeriveValueFromSelection } from "webiny/admin/cms/lexical"; -``` - -## `useFontColorPicker` - -**Export** — imported from `webiny/admin/cms/lexical` - -```typescript -import { useFontColorPicker } from "webiny/admin/cms/lexical"; -``` - -## `useIsMounted` - -**Export** — imported from `webiny/admin/cms/lexical` - -```typescript -import { useIsMounted } from "webiny/admin/cms/lexical"; -``` - -## `useLexicalEditorConfig` - -**Export** — imported from `webiny/admin/cms/lexical` - -```typescript -import { useLexicalEditorConfig } from "webiny/admin/cms/lexical"; -``` - -## `useRichTextEditor` - -**Export** — imported from `webiny/admin/cms/lexical` - -```typescript -import { useRichTextEditor } from "webiny/admin/cms/lexical"; -``` - -## `useTextAlignmentAction` - -**Export** — imported from `webiny/admin/cms/lexical` - -```typescript -import { useTextAlignmentAction } from "webiny/admin/cms/lexical"; -``` - -## `useTypographyAction` - -**Export** — imported from `webiny/admin/cms/lexical` - -```typescript -import { useTypographyAction } from "webiny/admin/cms/lexical"; -``` diff --git a/docs/developer-docs/6.x/reference/admin/cms/model.ai.txt b/docs/developer-docs/6.x/reference/admin/cms/model.ai.txt deleted file mode 100644 index c0bc62491..000000000 --- a/docs/developer-docs/6.x/reference/admin/cms/model.ai.txt +++ /dev/null @@ -1,26 +0,0 @@ -AI Context: Model (reference/admin/cms/model.mdx) - -Source of Information: -1. packages/webiny/src/admin/cms/model.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/app-headless-cms/src/admin/components/FieldEditor/EditFieldDialog/RulesEditor/index.ts — originating source -3. /Users/adrian/dev/wby-next/packages/app-headless-cms-common/src/Fields/index.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -RulesEditor, useFieldAccessControlRules, useFieldEffectiveRules - -Import Path: webiny/admin/cms/model - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/cms/model.mdx b/docs/developer-docs/6.x/reference/admin/cms/model.mdx deleted file mode 100644 index ed0d86bbd..000000000 --- a/docs/developer-docs/6.x/reference/admin/cms/model.mdx +++ /dev/null @@ -1,90 +0,0 @@ ---- -id: ywrtaw4v -title: Model -description: "Reference for webiny/admin/cms/model" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/cms/model`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/cms/model`. Import any of the items below directly from this path in your Webiny extensions. - -**Components** - - - -**Hooks** - - - -## Components - -### `RulesEditor` - -**Constant** — imported from `webiny/admin/cms/model` - -```typescript -import { RulesEditor } from "webiny/admin/cms/model"; -``` - -```typescript -export const RulesEditor = ({ - fieldOptions, - actionOptions = DEFAULT_ACTION_OPTIONS -}: RulesTabProps) => { - const bind = useBind({ name: "rules" }); - const allRules: FieldRule[] = bind.value || []; - const entryRules = allRules.filter(r => r.type === "condition"); - const otherRules = allRules.filter(r => r.type !== "condition"); - - const addRule = () => { - const newRule: -``` - -## Hooks - -### `useFieldAccessControlRules` - -**Function** — imported from `webiny/admin/cms/model` - -Hook that evaluates access control rules for the current identity. -Does not require `bindParentName` — only identity-based permissions. - -```typescript -import { useFieldAccessControlRules } from "webiny/admin/cms/model"; -``` - -```typescript -export function useFieldAccessControlRules( - item: HasRules -): Pick; -``` - -### `useFieldEffectiveRules` - -**Function** — imported from `webiny/admin/cms/model` - -Composes useParentRules and useFieldRules into a single hook -that returns the effective (intersected) rules. - -```typescript -import { useFieldEffectiveRules } from "webiny/admin/cms/model"; -``` - -```typescript -export function useFieldEffectiveRules(item: HasRules): EffectiveFieldRules; -``` diff --git a/docs/developer-docs/6.x/reference/admin/configs.ai.txt b/docs/developer-docs/6.x/reference/admin/configs.ai.txt deleted file mode 100644 index 8d8d1bbfc..000000000 --- a/docs/developer-docs/6.x/reference/admin/configs.ai.txt +++ /dev/null @@ -1,25 +0,0 @@ -AI Context: Configs (reference/admin/configs.mdx) - -Source of Information: -1. packages/webiny/src/admin/configs.ts — barrel re-export file - - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: - - -Import Path: webiny/admin/configs - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/configs.mdx b/docs/developer-docs/6.x/reference/admin/configs.mdx deleted file mode 100644 index 4f863d758..000000000 --- a/docs/developer-docs/6.x/reference/admin/configs.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: ywrtaw4v -title: Configs -description: "Admin configuration types" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/configs`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/configs`. Import any of the items below directly from this path in your Webiny extensions. - -_No exported symbols found._ diff --git a/docs/developer-docs/6.x/reference/admin/env-config.ai.txt b/docs/developer-docs/6.x/reference/admin/env-config.ai.txt deleted file mode 100644 index 6e0be0b16..000000000 --- a/docs/developer-docs/6.x/reference/admin/env-config.ai.txt +++ /dev/null @@ -1,26 +0,0 @@ -AI Context: Env Config (reference/admin/env-config.mdx) - -Source of Information: -1. packages/webiny/src/admin/env-config.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/app/src/features/envConfig/index.ts — originating source -3. /Users/adrian/dev/wby-next/packages/app/src/presentation/envConfig/useEnvConfig.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -EnvConfig, useEnvConfig - -Import Path: webiny/admin/env-config - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/env-config.mdx b/docs/developer-docs/6.x/reference/admin/env-config.mdx deleted file mode 100644 index 908f3620e..000000000 --- a/docs/developer-docs/6.x/reference/admin/env-config.mdx +++ /dev/null @@ -1,58 +0,0 @@ ---- -id: ywrtaw4v -title: Env Config -description: "Reference for webiny/admin/env-config" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/env-config`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/env-config`. Import any of the items below directly from this path in your Webiny extensions. - -**Components** - - - -**Hooks** - - - -## Components - -### `EnvConfig` - -**Constant** — imported from `webiny/admin/env-config` - -```typescript -import { EnvConfig } from "webiny/admin/env-config"; -``` - -```typescript -export const EnvConfig = new Abstraction("EnvConfig"); -``` - -## Hooks - -### `useEnvConfig` - -**Function** — imported from `webiny/admin/env-config` - -Returns the EnvConfig instance from DI. -Useful when you want to access EnvConfig inside components and hooks. - -```typescript -import { useEnvConfig } from "webiny/admin/env-config"; -``` - -```typescript -export function useEnvConfig(): EnvConfig.Config; -``` diff --git a/docs/developer-docs/6.x/reference/admin/form.ai.txt b/docs/developer-docs/6.x/reference/admin/form.ai.txt deleted file mode 100644 index b4cf9aa41..000000000 --- a/docs/developer-docs/6.x/reference/admin/form.ai.txt +++ /dev/null @@ -1,26 +0,0 @@ -AI Context: Form (reference/admin/form.mdx) - -Source of Information: -1. packages/webiny/src/admin/form.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/form/src/index.ts — originating source -3. /Users/adrian/dev/wby-next/packages/validation/src/index.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -Bind, Form, UnsetOnUnmount, useBind, useBindPrefix, useGenerateSlug, useForm, FormApi, FormOnSubmit, GenericFormData, validation, Validation, ValidationError - -Import Path: webiny/admin/form - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/form.mdx b/docs/developer-docs/6.x/reference/admin/form.mdx deleted file mode 100644 index 6c8639d31..000000000 --- a/docs/developer-docs/6.x/reference/admin/form.mdx +++ /dev/null @@ -1,275 +0,0 @@ ---- -id: ywrtaw4v -title: Form -description: "Form primitives: Bind, Form, useForm, validation" ---- - -import {Alert} from "@/components/Alert"; -import {SymbolList} from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/form`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/form`. Import any of the items below directly from this path in your Webiny extensions. - -**Components** - - - -**Hooks** - - - -**Types** - - - -**Other** - - - -## Components - -### `Bind` - -**Function** — imported from `webiny/admin/form` - -```typescript -import { Bind } from "webiny/admin/form"; -``` - -```typescript -export function Bind( -``` - -### `Form` - -**Constant** — imported from `webiny/admin/form` - -```typescript -import { Form } from "webiny/admin/form"; -``` - -```typescript -export const Form = observer( - React.forwardRef(FormInner) as ( - props: FormProps & { ref?: React.ForwardedRef } - ) => ReturnType> -); -``` - -### `UnsetOnUnmount` - -**Constant** — imported from `webiny/admin/form` - -```typescript -import { UnsetOnUnmount } from "webiny/admin/form"; -``` - -```typescript -export const UnsetOnUnmount = ({ name, children }: { name: string; children: React.ReactNode }) => { - const form = useForm(); - - useEffect(() => { - return () => { - form.setValue(name, undefined); - }; - }, []); - - return <>{children}; -}; -``` - -### `Validation` - -**Class** — imported from `webiny/admin/form` - -Main class of Validation library. -Exported as a singleton instance, it offers methods for sync/async data validation and overwriting or adding new validators. - -@class Validation -@example -import { validation } from '@webiny/validation'; - -// `validation` is a preconfigured instance of Validation class. -// From here you can either add new validators or use it as-is. - -```typescript -import { Validation } from "webiny/admin/form"; -``` - -```typescript -class Validation { - __validators:; - constructor(); - setValidator(name: string, callable: Validator): this; - getValidator(name: string): Validator; - async validate( - value: any, - validators: string, - options: ValidateOptions =; - validateSync( - value: any, - validators: string, - options: ValidateOptions =; - create(validators: string); - createSync(validators: string); - __parseValidateProperty(validators: string): ParsedValidators; -} -``` - -### `ValidationError` - -**Class** — imported from `webiny/admin/form` - -This class is used by validators to throw an error when value validation fails. - -```typescript -import { ValidationError } from "webiny/admin/form"; -``` - -```typescript -class ValidationError extends Error { - public override readonly message: string; - public readonly validator: string | null; - public readonly value: any; - constructor(message = "", validator: string | null = null, value: string | null = null); -} -``` - -## Hooks - -### `useBind` - -**Constant** — imported from `webiny/admin/form` - -```typescript -import { useBind } from "webiny/admin/form"; -``` - -```typescript -export const useBind = makeDecoratable((props: BindComponentProps): UseBindHook => { - const form = useForm(); - const bindPrefix = useBindPrefix(); - - const bindName = useMemo(() => { - return [bindPrefix, props.name].filter(Boolean).join("."); - }, [props.name]); - - const fieldProps = { ...props, name: bindName }; - - useEffect(() => { - form.registerField(fieldProps); - - -``` - -### `useBindPrefix` - -**Function** — imported from `webiny/admin/form` - -```typescript -import { useBindPrefix } from "webiny/admin/form"; -``` - -```typescript -export function useBindPrefix() -``` - -### `useForm` - -**Constant** — imported from `webiny/admin/form` - -```typescript -import { useForm } from "webiny/admin/form"; -``` - -```typescript -export const useForm = () => { - const context = useContext(FormContext) as FormAPI; - if (!context) { - throw new Error("Missing Form component in the component hierarchy!"); - } - return context; -}; -``` - -### `useGenerateSlug` - -**Function** — imported from `webiny/admin/form` - -This hook is designed to be used with the `useForm` hook. -When `generateSlug` is called, it will generate a slug using the `from` form field, and set it into the `to` form field. -@param form -@param from -@param to - -```typescript -import { useGenerateSlug } from "webiny/admin/form"; -``` - -```typescript -export function useGenerateSlug(form: FormAPI, from: string, to = "slug") -``` - -## Types - -### `FormApi` - -**Type** — imported from `webiny/admin/form` - -```typescript -import type { FormApi } from "webiny/admin/form"; -``` - -```typescript -export interface FormAPI { ... } -``` - -### `FormOnSubmit` - -**Type** — imported from `webiny/admin/form` - -```typescript -import type { FormOnSubmit } from "webiny/admin/form"; -``` - -```typescript -export interface FormOnSubmit { - (data: T, form: FormAPI): any; -} -``` - -### `GenericFormData` - -**Type** — imported from `webiny/admin/form` - -```typescript -import type { GenericFormData } from "webiny/admin/form"; -``` - -```typescript -export type GenericFormData = { - [key: string]: any; -}; -``` - -## Other - -### `validation` - -**Constant** — imported from `webiny/admin/form` - -```typescript -import { validation } from "webiny/admin/form"; -``` - -```typescript -export const validation = new Validation(); -``` diff --git a/docs/developer-docs/6.x/reference/admin/graphql-client.ai.txt b/docs/developer-docs/6.x/reference/admin/graphql-client.ai.txt deleted file mode 100644 index 2a36cd042..000000000 --- a/docs/developer-docs/6.x/reference/admin/graphql-client.ai.txt +++ /dev/null @@ -1,25 +0,0 @@ -AI Context: Graphql Client (reference/admin/graphql-client.mdx) - -Source of Information: -1. packages/webiny/src/admin/graphql-client.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/app/src/features/graphqlClient/abstractions.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -GraphQLClient - -Import Path: webiny/admin/graphql-client - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/graphql-client.mdx b/docs/developer-docs/6.x/reference/admin/graphql-client.mdx deleted file mode 100644 index af342a846..000000000 --- a/docs/developer-docs/6.x/reference/admin/graphql-client.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -id: ywrtaw4v -title: Graphql Client -description: "Reference for webiny/admin/graphql-client" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/graphql-client`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/graphql-client`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `GraphQLClient` - -**Abstraction** — imported from `webiny/admin/graphql-client` - -```typescript -import { GraphQLClient } from "webiny/admin/graphql-client"; -``` - -**Interface `GraphQLClient.Interface`:** - -```typescript -interface GraphQLClient.Interface { - execute(params: GraphQLRequest): Promise; -} -``` - -**Types:** - -```typescript -namespace GraphQLClient { - type Headers = IHeaders; - type Interface = IGraphQLClient; - type Request = GraphQLRequest; -} -``` diff --git a/docs/developer-docs/6.x/reference/admin/lexical.ai.txt b/docs/developer-docs/6.x/reference/admin/lexical.ai.txt deleted file mode 100644 index 43cc19c8c..000000000 --- a/docs/developer-docs/6.x/reference/admin/lexical.ai.txt +++ /dev/null @@ -1,26 +0,0 @@ -AI Context: Lexical Editor (reference/admin/lexical.mdx) - -Source of Information: -1. packages/webiny/src/admin/lexical.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/lexical-editor/src/hooks/index.ts — originating source -3. /Users/adrian/dev/wby-next/packages/lexical-editor/src/types.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -getNodeFromSelection, useCurrentElement, useCurrentSelection, useDeriveValueFromSelection, useRichTextEditor, useFontColorPicker, useTextAlignmentAction, useTypographyAction, useIsMounted, Klass, LexicalNode - -Import Path: webiny/admin/lexical - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/lexical.mdx b/docs/developer-docs/6.x/reference/admin/lexical.mdx deleted file mode 100644 index 47c2c2429..000000000 --- a/docs/developer-docs/6.x/reference/admin/lexical.mdx +++ /dev/null @@ -1,253 +0,0 @@ ---- -id: ywrtaw4v -title: Lexical Editor -description: "Lexical editor components and hooks" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/lexical`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/lexical`. Import any of the items below directly from this path in your Webiny extensions. - -**Components** - - - -**Hooks** - - - -**Types** - - - -**Other** - - - -## Components - -### `LexicalNode` - -**Type** — imported from `webiny/admin/lexical` - -```typescript -import type { LexicalNode } from "webiny/admin/lexical"; -``` - -```typescript -export declare class LexicalNode { - ["constructor"]: KlassConstructor; - __type: string; - __key: string; - __parent: null | NodeKey; - __prev: null | NodeKey; - __next: null | NodeKey; - __state?: NodeState; - static getType(): string; - static clone(_data: unknown): LexicalNode; - $config(): BaseStaticNodeConfig; - config>( - type: Type, - config: Config - ): StaticNodeConfigRecord; - afterCloneFrom(prevNode: this): void; - resetOnCopyNodeFrom(originalNode: this): void; - static importDOM?: () => DOMConversionMap | null; - constructor(key?: NodeKey); - getType(): string; - isInline(): boolean; - isAttached(): boolean; - isSelected(selection?: null | BaseSelection): boolean; - getKey(): NodeKey; - getIndexWithinParent(): number; - getParent(): T | null; - getParentOrThrow(): T; - getTopLevelElement(): ElementNode | DecoratorNode | null; - getTopLevelElementOrThrow(): ElementNode | DecoratorNode; - getParents(): Array; - getParentKeys(): Array; - getPreviousSibling(): T | null; - getPreviousSiblings(): Array; - getNextSibling(): T | null; - getNextSiblings(): Array; - getCommonAncestor(node: LexicalNode): T | null; - is(object: LexicalNode | null | undefined): boolean; - isBefore(targetNode: LexicalNode): boolean; - isParentOf(targetNode: LexicalNode): boolean; - getNodesBetween(targetNode: LexicalNode): Array; - isDirty(): boolean; - getLatest(): this; - getWritable(): this; - getTextContent(): string; - getTextContentSize(): number; - createDOM(_config: EditorConfig, _editor: LexicalEditor): HTMLElement; - updateDOM(_prevNode: unknown, _dom: HTMLElement, _config: EditorConfig): boolean; - exportDOM(editor: LexicalEditor): DOMExportOutput; - exportJSON(): SerializedLexicalNode; - static importJSON(_serializedNode: SerializedLexicalNode): LexicalNode; - updateFromJSON(serializedNode: LexicalUpdateJSON): this; - static transform(): ((node: LexicalNode) => void) | null; - remove(preserveEmptyParent?: boolean): void; - replace(replaceWith: N, includeChildren?: boolean): N; - insertAfter(nodeToInsert: LexicalNode, restoreSelection?: boolean): LexicalNode; - insertBefore(nodeToInsert: LexicalNode, restoreSelection?: boolean): LexicalNode; - isParentRequired(): boolean; - createParentElementNode(): ElementNode; - selectStart(): RangeSelection; - selectEnd(): RangeSelection; - selectPrevious(anchorOffset?: number, focusOffset?: number): RangeSelection; - selectNext(anchorOffset?: number, focusOffset?: number): RangeSelection; - markDirty(): void; - reconcileObservedMutation(dom: HTMLElement, editor: LexicalEditor): void; -} -``` - -## Hooks - -### `useCurrentElement` - -**Function** — imported from `webiny/admin/lexical` - -```typescript -import { useCurrentElement } from "webiny/admin/lexical"; -``` - -```typescript -export function useCurrentElement(); -``` - -### `useCurrentSelection` - -**Function** — imported from `webiny/admin/lexical` - -```typescript -import { useCurrentSelection } from "webiny/admin/lexical"; -``` - -```typescript -export function useCurrentSelection(); -``` - -### `useDeriveValueFromSelection` - -**Function** — imported from `webiny/admin/lexical` - -```typescript -import { useDeriveValueFromSelection } from "webiny/admin/lexical"; -``` - -```typescript -export function useDeriveValueFromSelection(generator: Generator); -``` - -### `useFontColorPicker` - -**Function** — imported from `webiny/admin/lexical` - -```typescript -import { useFontColorPicker } from "webiny/admin/lexical"; -``` - -```typescript -export function useFontColorPicker(); -``` - -### `useIsMounted` - -**Function** — imported from `webiny/admin/lexical` - -```typescript -import { useIsMounted } from "webiny/admin/lexical"; -``` - -```typescript -export function useIsMounted(); -``` - -### `useRichTextEditor` - -**Function** — imported from `webiny/admin/lexical` - -```typescript -import { useRichTextEditor } from "webiny/admin/lexical"; -``` - -```typescript -export function useRichTextEditor(); -``` - -### `useTextAlignmentAction` - -**Function** — imported from `webiny/admin/lexical` - -```typescript -import { useTextAlignmentAction } from "webiny/admin/lexical"; -``` - -```typescript -export function useTextAlignmentAction(); -``` - -### `useTypographyAction` - -**Function** — imported from `webiny/admin/lexical` - -```typescript -import { useTypographyAction } from "webiny/admin/lexical"; -``` - -```typescript -export function useTypographyAction(); -``` - -## Types - -### `Klass` - -**Type** — imported from `webiny/admin/lexical` - -```typescript -import type { Klass } from "webiny/admin/lexical"; -``` - -```typescript -export type Klass = - InstanceType extends T - ? T["constructor"] - : GenericConstructor & T["constructor"]; -``` - -## Other - -### `getNodeFromSelection` - -**Function** — imported from `webiny/admin/lexical` - -```typescript -import { getNodeFromSelection } from "webiny/admin/lexical"; -``` - -```typescript -export function getNodeFromSelection(selection: RangeSelection); -``` diff --git a/docs/developer-docs/6.x/reference/admin/local-storage.ai.txt b/docs/developer-docs/6.x/reference/admin/local-storage.ai.txt deleted file mode 100644 index 74c84ee59..000000000 --- a/docs/developer-docs/6.x/reference/admin/local-storage.ai.txt +++ /dev/null @@ -1,26 +0,0 @@ -AI Context: Local Storage (reference/admin/local-storage.mdx) - -Source of Information: -1. packages/webiny/src/admin/local-storage.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/app/src/features/localStorage/abstractions.ts — originating source -3. /Users/adrian/dev/wby-next/packages/app/src/presentation/localStorage/index.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -LocalStorage, useLocalStorage, useLocalStorageValue, useLocalStorageValues - -Import Path: webiny/admin/local-storage - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/local-storage.mdx b/docs/developer-docs/6.x/reference/admin/local-storage.mdx deleted file mode 100644 index 2d47af6ac..000000000 --- a/docs/developer-docs/6.x/reference/admin/local-storage.mdx +++ /dev/null @@ -1,93 +0,0 @@ ---- -id: ywrtaw4v -title: Local Storage -description: "Reference for webiny/admin/local-storage" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/local-storage`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/local-storage`. Import any of the items below directly from this path in your Webiny extensions. - -**Components** - - - -**Hooks** - - - -## Components - -### `LocalStorage` - -**Constant** — imported from `webiny/admin/local-storage` - -```typescript -import { LocalStorage } from "webiny/admin/local-storage"; -``` - -```typescript -export const LocalStorage = new Abstraction("LocalStorage"); -``` - -## Hooks - -### `useLocalStorage` - -**Function** — imported from `webiny/admin/local-storage` - -Returns the LocalStorage instance from DI. -Useful when you want to call service methods imperatively inside components. - -```typescript -import { useLocalStorage } from "webiny/admin/local-storage"; -``` - -```typescript -export function useLocalStorage(): LocalStorage.Interface; -``` - -### `useLocalStorageValue` - -**Function** — imported from `webiny/admin/local-storage` - -```typescript -import { useLocalStorageValue } from "webiny/admin/local-storage"; -``` - -```typescript -export function useLocalStorageValue(key: string): T | undefined; -``` - -### `useLocalStorageValues` - -**Function** — imported from `webiny/admin/local-storage` - -Observes multiple keys in LocalStorage and returns an object of { key: value }. -Re-renders when any of the observed keys change. - -```typescript -import { useLocalStorageValues } from "webiny/admin/local-storage"; -``` - -```typescript -export function useLocalStorageValues>( - keys: (keyof T & string)[] -): Partial; -``` diff --git a/docs/developer-docs/6.x/reference/admin/router.ai.txt b/docs/developer-docs/6.x/reference/admin/router.ai.txt deleted file mode 100644 index 4a9f4c6cd..000000000 --- a/docs/developer-docs/6.x/reference/admin/router.ai.txt +++ /dev/null @@ -1,26 +0,0 @@ -AI Context: Router (reference/admin/router.mdx) - -Source of Information: -1. packages/webiny/src/admin/router.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/app/src/features/router/Route.ts — originating source -3. /Users/adrian/dev/wby-next/packages/app/src/presentation/router/index.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -Route, useRoute, useRouter - -Import Path: webiny/admin/router - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/router.mdx b/docs/developer-docs/6.x/reference/admin/router.mdx deleted file mode 100644 index 0088fe55f..000000000 --- a/docs/developer-docs/6.x/reference/admin/router.mdx +++ /dev/null @@ -1,89 +0,0 @@ ---- -id: ywrtaw4v -title: Router -description: "Router components and hooks" ---- - -import {Alert} from "@/components/Alert"; -import {SymbolList} from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/router`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/router`. Import any of the items below directly from this path in your Webiny extensions. - -**Components** - - - -**Hooks** - - - -## Components - -### `Route` - -**Class** — imported from `webiny/admin/router` - -```typescript -import { Route } from "webiny/admin/router"; -``` - -```typescript -export class Route { - private readonly route: RouteParams; - private readonly schema: TParams extends RouteParamsDefinition - ? RouteParamsInfer - : undefined; - constructor(route: RouteParams); - get name(); - get path(); - get params(): TParams extends RouteParamsDefinition ? RouteParamsInfer : undefined; - private coerceParams>(shape: T); -} -``` - -## Hooks - -### `useRoute` - -**Function** — imported from `webiny/admin/router` - -```typescript -import { useRoute } from "webiny/admin/router"; -``` - -```typescript -export function useRoute( - // eslint-disable-next-line @typescript-eslint/no-unused-vars - route?: Route -) -``` - -### `useRouter` - -**Constant** — imported from `webiny/admin/router` - -```typescript -import { useRouter } from "webiny/admin/router"; -``` - -```typescript -export const useRouter = () => { - const { presenter } = useFeature(RouterFeature); - const container = useContainer(); - const registry = container.resolve(RouteElementRegistry); - - return { - goToRoute: presenter.goToRoute.bind(presenter), - getLink: presenter.getLink.bind(presenter), - onRouteExit: presenter.onRouteExit.bind(presenter), - setRoutes: (routes: Reac -``` diff --git a/docs/developer-docs/6.x/reference/admin/security.ai.txt b/docs/developer-docs/6.x/reference/admin/security.ai.txt deleted file mode 100644 index 074175022..000000000 --- a/docs/developer-docs/6.x/reference/admin/security.ai.txt +++ /dev/null @@ -1,31 +0,0 @@ -AI Context: Security (reference/admin/security.mdx) - -Source of Information: -1. packages/webiny/src/admin/security.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/app/src/errors/abstractions.ts — originating source -3. /Users/adrian/dev/wby-next/packages/app-admin/src/features/security/LogIn/index.ts — originating source -4. /Users/adrian/dev/wby-next/packages/app-admin/src/features/security/LogOut/index.ts — originating source -5. /Users/adrian/dev/wby-next/packages/app-admin/src/features/security/AuthenticationContext/index.ts — originating source -6. /Users/adrian/dev/wby-next/packages/app-admin/src/features/security/IdentityContext/index.ts — originating source -7. /Users/adrian/dev/wby-next/packages/app-admin/src/presentation/security/hooks/useAuthentication.ts — originating source -8. /Users/adrian/dev/wby-next/packages/app-admin/src/presentation/security/hooks/useIdentity.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -AuthenticationErrorEventHandler, LogInUseCase, LogOutUseCase, AuthenticationContext, IdentityContext, useAuthentication, useIdentity - -Import Path: webiny/admin/security - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/security.mdx b/docs/developer-docs/6.x/reference/admin/security.mdx deleted file mode 100644 index 325e17f0e..000000000 --- a/docs/developer-docs/6.x/reference/admin/security.mdx +++ /dev/null @@ -1,199 +0,0 @@ ---- -id: ywrtaw4v -title: Security -description: "Admin security: authentication, identity, permissions" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What use cases are available in `webiny/admin/security`? -- Which event handlers can you implement? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/security`. Import any of the items below directly from this path in your Webiny extensions. - -**Hooks** - - - -**Other** - - - -## Hooks - -### `useAuthentication` - -**Function** — imported from `webiny/admin/security` - -```typescript -import { useAuthentication } from "webiny/admin/security"; -``` - -```typescript -export function useAuthentication(): IUseAuthenticationReturn; -``` - -### `useIdentity` - -**Function** — imported from `webiny/admin/security` - -```typescript -import { useIdentity } from "webiny/admin/security"; -``` - -```typescript -export function useIdentity(): IUseIdentityReturn; -``` - -## Other - -### `AuthenticationContext` - -**Abstraction** — imported from `webiny/admin/security` - -```typescript -import { AuthenticationContext } from "webiny/admin/security"; -``` - -**Interface `AuthenticationContext.Interface`:** - -```typescript -interface AuthenticationContext.Interface { - clear(): void; - getIdToken: IIdTokenProvider; - setIdTokenProvider(provider: IIdTokenProvider): void; - setLogoutCallback(callback: ILogoutCallback): void; - getLogoutCallback(): ILogoutCallback; -} -``` - -**Types:** - -```typescript -namespace AuthenticationContext { - type Interface = IAuthenticationContext; - type IdTokenProvider = IIdTokenProvider; - type LogoutCallback = ILogoutCallback; -} -``` - -### `AuthenticationErrorEventHandler` - -**Event Handler Abstraction** — imported from `webiny/admin/security` - -```typescript -import { AuthenticationErrorEventHandler } from "webiny/admin/security"; -``` - -**Interface `AuthenticationErrorEventHandler.Interface`:** - -```typescript -interface AuthenticationErrorEventHandler.Interface { - handle(event: AuthenticationErrorEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace AuthenticationErrorEventHandler { - type Interface = IEventHandler; - type Event = AuthenticationErrorEvent; -} -``` - -### `IdentityContext` - -**Abstraction** — imported from `webiny/admin/security` - -```typescript -import { IdentityContext } from "webiny/admin/security"; -``` - -**Interface `IdentityContext.Interface`:** - -```typescript -interface IdentityContext.Interface { - getIdentity(): Identity; - setIdentity(identity: Identity): void; - clear(): void; -} -``` - -**Types:** - -```typescript -namespace IdentityContext { - type Interface = IIdentityContext; -} -``` - -### `LogInUseCase` - -**Use Case Abstraction** — imported from `webiny/admin/security` - -```typescript -import { LogInUseCase } from "webiny/admin/security"; -``` - -**Interface `LogInUseCase.Interface`:** - -```typescript -interface LogInUseCase.Interface { - execute(params: ILoginParams): Promise; -} -``` - -**Types:** - -```typescript -namespace LogInUseCase { - type Interface = ILogInUseCase; - type Params = ILoginParams; -} -``` - -### `LogOutUseCase` - -**Use Case Abstraction** — imported from `webiny/admin/security` - -```typescript -import { LogOutUseCase } from "webiny/admin/security"; -``` - -**Interface `LogOutUseCase.Interface`:** - -```typescript -interface LogOutUseCase.Interface { - execute(): Promise; -} -``` - -**Types:** - -```typescript -namespace LogOutUseCase { - type Interface = ILogOutUseCase; -} -``` diff --git a/docs/developer-docs/6.x/reference/admin/tenancy.ai.txt b/docs/developer-docs/6.x/reference/admin/tenancy.ai.txt deleted file mode 100644 index cd7ae5299..000000000 --- a/docs/developer-docs/6.x/reference/admin/tenancy.ai.txt +++ /dev/null @@ -1,30 +0,0 @@ -AI Context: Tenancy (reference/admin/tenancy.mdx) - -Source of Information: -1. packages/webiny/src/admin/tenancy.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/app-admin/src/features/tenancy/abstractions.ts — originating source -3. /Users/adrian/dev/wby-next/packages/app-admin/src/presentation/tenancy/useTenantContext.ts — originating source -4. /Users/adrian/dev/wby-next/packages/tenant-manager/src/admin/types.ts — originating source -5. /Users/adrian/dev/wby-next/packages/tenant-manager/src/admin/EnableTenant/index.ts — originating source -6. /Users/adrian/dev/wby-next/packages/tenant-manager/src/admin/DisableTenant/index.ts — originating source -7. /Users/adrian/dev/wby-next/packages/tenant-manager/src/admin/CurrentTenant/useCurrentTenant.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -TenantContext, useTenantContext, TenantEntry, useEnableTenant, useDisableTenant, useCurrentTenant - -Import Path: webiny/admin/tenancy - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/tenancy.mdx b/docs/developer-docs/6.x/reference/admin/tenancy.mdx deleted file mode 100644 index 70889e39c..000000000 --- a/docs/developer-docs/6.x/reference/admin/tenancy.mdx +++ /dev/null @@ -1,150 +0,0 @@ ---- -id: ywrtaw4v -title: Tenancy -description: "Admin tenancy hooks and context" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/tenancy`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/tenancy`. Import any of the items below directly from this path in your Webiny extensions. - -**Components** - - - -**Hooks** - - - -**Types** - - - -## Components - -### `TenantContext` - -**Constant** — imported from `webiny/admin/tenancy` - -```typescript -import { TenantContext } from "webiny/admin/tenancy"; -``` - -```typescript -export const TenantContext = new Abstraction("TenantContext"); -``` - -## Hooks - -### `useCurrentTenant` - -**Constant** — imported from `webiny/admin/tenancy` - -```typescript -import { useCurrentTenant } from "webiny/admin/tenancy"; -``` - -```typescript -export const useCurrentTenant = () => { - const { presenter } = useFeature(CurrentTenantFeature); - // The app is not rendered till the tenant is loaded. - // If this hook is used, it's safe to assume the tenant is loaded. - const [tenant, setTenant] = useState(presenter.vm.tenant as Tenant); - - useEffect(() => { - return autorun(() => { - const tenant = presenter.vm.tena -``` - -### `useDisableTenant` - -**Constant** — imported from `webiny/admin/tenancy` - -```typescript -import { useDisableTenant } from "webiny/admin/tenancy"; -``` - -```typescript -export const useDisableTenant = (tenant: TenantEntry) => { - const { useCase } = useFeature(DisableTenantFeature); - const { updateRecordInCache } = useRecords(); - - const disableTenant = useCallback(async () => { - await useCase.execute(tenant.entryId); - - updateRecordInCache({ - ...tenant, - values: { - ...tenant.values, - status: -``` - -### `useEnableTenant` - -**Constant** — imported from `webiny/admin/tenancy` - -```typescript -import { useEnableTenant } from "webiny/admin/tenancy"; -``` - -```typescript -export const useEnableTenant = () => { - const { useCase } = useFeature(EnableTenantFeature); - const [loading, setLoading] = useState(false); - - const enableTenant = useCallback( - async (tenantId: string) => { - setLoading(true); - - try { - await useCase.execute(tenantId); - } finally { - setLoading(false); - } - -``` - -### `useTenantContext` - -**Function** — imported from `webiny/admin/tenancy` - -```typescript -import { useTenantContext } from "webiny/admin/tenancy"; -``` - -```typescript -export function useTenantContext(); -``` - -## Types - -### `TenantEntry` - -**Type** — imported from `webiny/admin/tenancy` - -```typescript -import type { TenantEntry } from "webiny/admin/tenancy"; -``` - -```typescript -export interface TenantEntry extends BaseEntry { - values: TenantValues; -} -``` diff --git a/docs/developer-docs/6.x/reference/admin/ui.ai.txt b/docs/developer-docs/6.x/reference/admin/ui.ai.txt deleted file mode 100644 index dc6f5ba94..000000000 --- a/docs/developer-docs/6.x/reference/admin/ui.ai.txt +++ /dev/null @@ -1,84 +0,0 @@ -AI Context: UI (reference/admin/ui.mdx) - -Source of Information: -1. packages/webiny/src/admin/ui.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/admin-ui/src/Accordion/index.ts — originating source -3. /Users/adrian/dev/wby-next/packages/admin-ui/src/Alert/index.ts — originating source -4. /Users/adrian/dev/wby-next/packages/admin-ui/src/AutoComplete/index.ts — originating source -5. /Users/adrian/dev/wby-next/packages/admin-ui/src/Avatar/index.ts — originating source -6. /Users/adrian/dev/wby-next/packages/admin-ui/src/Button/index.ts — originating source -7. /Users/adrian/dev/wby-next/packages/admin-ui/src/Card/index.ts — originating source -8. /Users/adrian/dev/wby-next/packages/admin-ui/src/Checkbox/index.ts — originating source -9. /Users/adrian/dev/wby-next/packages/admin-ui/src/CheckboxGroup/index.ts — originating source -10. /Users/adrian/dev/wby-next/packages/admin-ui/src/CodeEditor/index.ts — originating source -11. /Users/adrian/dev/wby-next/packages/admin-ui/src/ColorPicker/index.ts — originating source -12. /Users/adrian/dev/wby-next/packages/admin-ui/src/DataList/index.ts — originating source -13. /Users/adrian/dev/wby-next/packages/admin-ui/src/DataTable/index.ts — originating source -14. /Users/adrian/dev/wby-next/packages/admin-ui/src/DelayedOnChange/index.ts — originating source -15. /Users/adrian/dev/wby-next/packages/admin-ui/src/Dialog/index.ts — originating source -16. /Users/adrian/dev/wby-next/packages/admin-ui/src/Drawer/index.ts — originating source -17. /Users/adrian/dev/wby-next/packages/admin-ui/src/DropdownMenu/index.ts — originating source -18. /Users/adrian/dev/wby-next/packages/admin-ui/src/DynamicFieldset/index.ts — originating source -19. /Users/adrian/dev/wby-next/packages/admin-ui/src/FilePicker/index.ts — originating source -20. /Users/adrian/dev/wby-next/packages/admin-ui/src/Grid/index.ts — originating source -21. /Users/adrian/dev/wby-next/packages/admin-ui/src/HeaderBar/index.ts — originating source -22. /Users/adrian/dev/wby-next/packages/admin-ui/src/Heading/index.ts — originating source -23. /Users/adrian/dev/wby-next/packages/admin-ui/src/Icon/index.ts — originating source -24. /Users/adrian/dev/wby-next/packages/admin-ui/src/IconPicker/index.ts — originating source -25. /Users/adrian/dev/wby-next/packages/admin-ui/src/Image/index.ts — originating source -26. /Users/adrian/dev/wby-next/packages/admin-ui/src/Input/index.ts — originating source -27. /Users/adrian/dev/wby-next/packages/admin-ui/src/Label/index.ts — originating source -28. /Users/adrian/dev/wby-next/packages/admin-ui/src/Link/index.ts — originating source -29. /Users/adrian/dev/wby-next/packages/admin-ui/src/List/index.ts — originating source -30. /Users/adrian/dev/wby-next/packages/admin-ui/src/Loader/index.ts — originating source -31. /Users/adrian/dev/wby-next/packages/admin-ui/src/MultiAutoComplete/index.ts — originating source -32. /Users/adrian/dev/wby-next/packages/admin-ui/src/MultiFilePicker/index.ts — originating source -33. /Users/adrian/dev/wby-next/packages/admin-ui/src/Portal/index.ts — originating source -34. /Users/adrian/dev/wby-next/packages/admin-ui/src/Popover/index.ts — originating source -35. /Users/adrian/dev/wby-next/packages/admin-ui/src/ProgressBar/index.ts — originating source -36. /Users/adrian/dev/wby-next/packages/admin-ui/src/RadioGroup/index.ts — originating source -37. /Users/adrian/dev/wby-next/packages/admin-ui/src/RangeSlider/index.ts — originating source -38. /Users/adrian/dev/wby-next/packages/admin-ui/src/Scrollbar/index.ts — originating source -39. /Users/adrian/dev/wby-next/packages/admin-ui/src/ScrollArea/index.ts — originating source -40. /Users/adrian/dev/wby-next/packages/admin-ui/src/SegmentedControl/index.ts — originating source -41. /Users/adrian/dev/wby-next/packages/admin-ui/src/Select/index.ts — originating source -42. /Users/adrian/dev/wby-next/packages/admin-ui/src/Separator/index.ts — originating source -43. /Users/adrian/dev/wby-next/packages/admin-ui/src/Sidebar/index.ts — originating source -44. /Users/adrian/dev/wby-next/packages/admin-ui/src/Skeleton/index.ts — originating source -45. /Users/adrian/dev/wby-next/packages/admin-ui/src/Slider/index.ts — originating source -46. /Users/adrian/dev/wby-next/packages/admin-ui/src/SteppedProgress/index.ts — originating source -47. /Users/adrian/dev/wby-next/packages/admin-ui/src/Switch/index.ts — originating source -48. /Users/adrian/dev/wby-next/packages/admin-ui/src/Table/index.ts — originating source -49. /Users/adrian/dev/wby-next/packages/admin-ui/src/Tabs/index.ts — originating source -50. /Users/adrian/dev/wby-next/packages/admin-ui/src/Tag/index.ts — originating source -51. /Users/adrian/dev/wby-next/packages/admin-ui/src/Tags/index.ts — originating source -52. /Users/adrian/dev/wby-next/packages/admin-ui/src/Text/index.ts — originating source -53. /Users/adrian/dev/wby-next/packages/admin-ui/src/Textarea/index.ts — originating source -54. /Users/adrian/dev/wby-next/packages/admin-ui/src/TimeAgo/index.ts — originating source -55. /Users/adrian/dev/wby-next/packages/admin-ui/src/Toast/index.ts — originating source -56. /Users/adrian/dev/wby-next/packages/admin-ui/src/Tooltip/index.ts — originating source -57. /Users/adrian/dev/wby-next/packages/admin-ui/src/Tree/index.ts — originating source -58. /Users/adrian/dev/wby-next/packages/admin-ui/src/Widget/index.ts — originating source -59. /Users/adrian/dev/wby-next/packages/admin-ui/src/hooks/index.ts — originating source -60. /Users/adrian/dev/wby-next/packages/app-admin/src/hooks/useHotkeys.ts — originating source -61. /Users/adrian/dev/wby-next/packages/app-admin/src/components/Dialogs/useDialogs.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -Accordion, Alert, AutoComplete, Avatar, Button, CopyButton, IconButton, Card, Checkbox, CheckboxGroup, CodeEditor, ColorPicker, CloneIcon, CreateIcon, DataList, DataListModal, DataListWithSections, DeleteIcon, DownloadIcon, EditIcon, FilterIcon, ListIcon, LoginIcon, NextPageIcon, OptionsIcon, PreviousPageIcon, RefreshIcon, SortIcon, UploadIcon, DataTable, DelayedOnChange, Dialog, Drawer, DropdownMenu, DynamicFieldset, FilePicker, Grid, HeaderBar, Heading, Icon, IconPicker, Image, Input, Label, Link, List, Loader, OverlayLoader, MultiAutoComplete, MultiFilePicker, Portal, Popover, ProgressBar, Radio, RadioGroup, RangeSlider, Scrollbar, ScrollArea, ScrollBar, SegmentedControl, Select, Separator, Sidebar, SidebarProvider, useSidebar, Skeleton, Slider, SteppedProgress, Switch, Table, Tabs, Tag, Tags, Text, Textarea, TimeAgo, Toast, useToast, Tooltip, Tree, Widget, useDisclosure, useHotkeys, useDialogs - -Import Path: webiny/admin/ui - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/ui.mdx b/docs/developer-docs/6.x/reference/admin/ui.mdx deleted file mode 100644 index a58f3814a..000000000 --- a/docs/developer-docs/6.x/reference/admin/ui.mdx +++ /dev/null @@ -1,1443 +0,0 @@ ---- -id: ywrtaw4v -title: UI -description: "Admin UI component library" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/ui`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/ui`. Import any of the items below directly from this path in your Webiny extensions. - -**Components** - - - -**Hooks** - - - -## Components - -### `Accordion` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Accordion } from "webiny/admin/ui"; -``` - -```typescript -export const Accordion = withStaticProps(DecoratableAccordion, { - Item: AccordionItem -}); -``` - -### `Alert` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Alert } from "webiny/admin/ui"; -``` - -```typescript -const Alert = withStaticProps(makeDecoratable("AlertBase", AlertBase), { - Action: AlertAction -}); -``` - -### `AutoComplete` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { AutoComplete } from "webiny/admin/ui"; -``` - -```typescript -const AutoComplete = makeDecoratable("AutoComplete", DecoratableAutoComplete); -``` - -### `Avatar` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Avatar } from "webiny/admin/ui"; -``` - -```typescript -const Avatar = withStaticProps(makeDecoratable("Avatar", AvatarBase), { - Fallback: AvatarFallback, - Image: AvatarImage -}); -``` - -### `Button` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Button } from "webiny/admin/ui"; -``` - -```typescript -const Button = makeDecoratable("Button", ButtonBase); -``` - -### `Card` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Card } from "webiny/admin/ui"; -``` - -```typescript -const Card = withStaticProps(DecoratableCard, { - ConfirmAction, - CancelAction, - Icon -}); -``` - -### `Checkbox` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Checkbox } from "webiny/admin/ui"; -``` - -```typescript -const Checkbox = makeDecoratable("Checkbox", DecoratableCheckbox); -``` - -### `CheckboxGroup` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { CheckboxGroup } from "webiny/admin/ui"; -``` - -```typescript -const CheckboxGroup = makeDecoratable("CheckboxGroup", DecoratableCheckboxGroup); -``` - -### `CloneIcon` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { CloneIcon } from "webiny/admin/ui"; -``` - -```typescript -export const CloneIcon = (props: IconButtonProps) => { - return ( - } label={"Clone"} />} - variant={"ghost"} - size={"sm"} - {...props} - /> - ); -}; -``` - -### `CodeEditor` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { CodeEditor } from "webiny/admin/ui"; -``` - -```typescript -const CodeEditor = makeDecoratable("CodeEditor", DecoratableCodeEditor); -``` - -### `ColorPicker` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { ColorPicker } from "webiny/admin/ui"; -``` - -```typescript -const ColorPicker = makeDecoratable("ColorPicker", DecoratableIconPicker); -``` - -### `CopyButton` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { CopyButton } from "webiny/admin/ui"; -``` - -```typescript -const CopyButton = makeDecoratable("CopyButton", CopyButtonBase); -``` - -### `CreateIcon` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { CreateIcon } from "webiny/admin/ui"; -``` - -```typescript -export const CreateIcon = (props: IconButtonProps) => { - return ( - } label={"Create"} />} - variant={"ghost"} - size={"sm"} - {...props} - /> - ); -}; -``` - -### `DataList` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { DataList } from "webiny/admin/ui"; -``` - -```typescript -export const DataList = (propsInput: DataListProps) => { - let render: React.ReactNode | null; - - const props = useMemo(() => { - return { - ...defaultDataListProps, - ...propsInput - }; - }, [propsInput]); - - if (props.loading) { - render = props.loader; - } else if (isEmpty(props.data)) { - render = props.noData; - } else { - -``` - -### `DataListModal` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { DataListModal } from "webiny/admin/ui"; -``` - -```typescript -const DataListModal = withStaticProps(BaseDataListModal, { - Trigger: DataListModalTrigger, - Content: DataListModalContent -}); -``` - -### `DataListWithSections` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { DataListWithSections } from "webiny/admin/ui"; -``` - -```typescript -export const DataListWithSections = (propsInput: DataListProps) => { - let render: React.ReactNode | null; - - const props = useMemo(() => { - return { - ...dataListWithSectionsDefaultProps, - ...propsInput - }; - }, [propsInput]); - - if (props.loading) { - render = props.loader; - } else if (isEmpty(props.data)) { - render = prop -``` - -### `DataTable` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { DataTable } from "webiny/admin/ui"; -``` - -```typescript -const DataTable = makeDecoratable("DataTable", DecoratableDataTable); -``` - -### `DelayedOnChange` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { DelayedOnChange } from "webiny/admin/ui"; -``` - -```typescript -export const DelayedOnChange = ({ - children, - ...other -}: DelayedOnChangeProps) => { - const firstMount = useRef(true); - const { onChange, delay = 400, value: initialValue } = other; - const [value, setValue] = useState(initialValue); - // Sync state and props - useEffect(() => { - // Do not update local state, if the incoming value -``` - -### `DeleteIcon` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { DeleteIcon } from "webiny/admin/ui"; -``` - -```typescript -export const DeleteIcon = (props: IconButtonProps) => { - return ( - } label={"Delete"} />} - variant={"ghost"} - size={"sm"} - {...props} - /> - ); -}; -``` - -### `Dialog` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Dialog } from "webiny/admin/ui"; -``` - -```typescript -const Dialog = withStaticProps(DecoratableDialog, { - ConfirmAction, - CancelAction, - Icon, - Close: DialogClose -}); -``` - -### `DownloadIcon` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { DownloadIcon } from "webiny/admin/ui"; -``` - -```typescript -export const DownloadIcon = (props: IconButtonProps) => { - return ( - } label={"Download"} />} - variant={"ghost"} - size={"sm"} - {...props} - /> - ); -}; -``` - -### `Drawer` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Drawer } from "webiny/admin/ui"; -``` - -```typescript -const Drawer = withStaticProps(DecoratableDrawer, { - ConfirmButton, - CancelButton, - Icon -}); -``` - -### `DropdownMenu` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { DropdownMenu } from "webiny/admin/ui"; -``` - -```typescript -const DropdownMenu = withStaticProps(DecoratableDropdownMenu, { - Separator: DropdownMenuSeparator, - Label: DropdownMenuLabel, - Group: DropdownMenuGroup, - Item: DropdownMenuItem, - Link: DropdownMenuLink, - CheckboxItem: DropdownMenuCheckboxItem -}); -``` - -### `DynamicFieldset` - -**Class** — imported from `webiny/admin/ui` - -```typescript -import { DynamicFieldset } from "webiny/admin/ui"; -``` - -```typescript -class DynamicFieldset extends React.Component { - static defaultProps: Partial =; - header: React.ReactNode = null; - footer: React.ReactNode = null; - rows: React.ReactNode = null; - empty: React.ReactNode = null; - actions =; - removeData = (index: number) =>; - addData = (index = -1) =>; - renderHeader = (cb: () => React.ReactNode): React.ReactNode =>; - renderFooter = (cb: () => React.ReactNode): React.ReactNode =>; - renderRow = (cb: ChildrenRenderPropRowCallable): React.ReactNode =>; - renderEmpty = (cb: () => React.ReactNode): React.ReactNode =>; - public renderComponent(): React.ReactNode; - public override render(); -} -``` - -### `EditIcon` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { EditIcon } from "webiny/admin/ui"; -``` - -```typescript -export const EditIcon = (props: IconButtonProps) => { - return ( - } label={"Edit"} />} - variant={"ghost"} - size={"sm"} - {...props} - /> - ); -}; -``` - -### `FilePicker` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { FilePicker } from "webiny/admin/ui"; -``` - -```typescript -const FilePicker = withStaticProps(DecoratableFilePicker, { - Preview: { - Image: ImagePreview, - RichItem: RichItemPreview, - TextOnly: TextOnlyPreview - } -}); -``` - -### `FilterIcon` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { FilterIcon } from "webiny/admin/ui"; -``` - -```typescript -export const FilterIcon = (props: IconButtonProps) => { - return ( - } label={"Filter"} />} - variant={"ghost"} - size={"sm"} - {...props} - /> - ); -}; -``` - -### `Grid` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Grid } from "webiny/admin/ui"; -``` - -```typescript -const Grid = withStaticProps(DecoratableGrid, { Column }); -``` - -### `HeaderBar` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { HeaderBar } from "webiny/admin/ui"; -``` - -```typescript -const HeaderBar = makeDecoratable("HeaderBar", HeaderBarBase); -``` - -### `Heading` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Heading } from "webiny/admin/ui"; -``` - -```typescript -const Heading = makeDecoratable("Heading", HeadingBase); -``` - -### `Icon` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Icon } from "webiny/admin/ui"; -``` - -```typescript -const Icon = makeDecoratable("Icon", IconBase); -``` - -### `IconButton` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { IconButton } from "webiny/admin/ui"; -``` - -```typescript -const IconButton = makeDecoratable("IconButton", DecoratableIconButton); -``` - -### `IconPicker` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { IconPicker } from "webiny/admin/ui"; -``` - -```typescript -const IconPicker = makeDecoratable("IconPicker", DecoratableIconPicker); -``` - -### `Image` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Image } from "webiny/admin/ui"; -``` - -```typescript -const Image = ({ ...rest }: ImageProps) => { - const finalProps = { ...rest }; - const srcSet = finalProps.srcSet; - if (srcSet && typeof srcSet === "object") { - finalProps.srcSet = Object.keys(srcSet) - .map(key => `${srcSet[key]} ${key}`) - .join(", "); - } - - return ; -}; -``` - -### `Input` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Input } from "webiny/admin/ui"; -``` - -```typescript -const Input = makeDecoratable("Input", DecoratableInput); -``` - -### `Label` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Label } from "webiny/admin/ui"; -``` - -```typescript -const Label = makeDecoratable("Label", LabelBase); -``` - -### `Link` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Link } from "webiny/admin/ui"; -``` - -```typescript -export const Link = makeDecoratable("Link", LinkBase); -``` - -### `List` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { List } from "webiny/admin/ui"; -``` - -```typescript -const List = withStaticProps(makeDecoratable("List", DecoratableList), { - Item: ListItem -}); -``` - -### `ListIcon` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { ListIcon } from "webiny/admin/ui"; -``` - -```typescript -export const ListIcon = (props: IconButtonProps) => { - return ( - } label={"List"} />} - variant={"ghost"} - size={"sm"} - {...props} - /> - ); -}; -``` - -### `Loader` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Loader } from "webiny/admin/ui"; -``` - -```typescript -const Loader = makeDecoratable("Loader", DecoratableLoader); -``` - -### `LoginIcon` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { LoginIcon } from "webiny/admin/ui"; -``` - -```typescript -export const LoginIcon = (props: IconButtonProps) => { - return ( - } label={"Login"} />} - variant={"ghost"} - size={"sm"} - {...props} - /> - ); -}; -``` - -### `MultiAutoComplete` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { MultiAutoComplete } from "webiny/admin/ui"; -``` - -```typescript -const MultiAutoComplete = makeDecoratable("MultiAutoComplete", DecoratableMultiAutoComplete); -``` - -### `MultiFilePicker` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { MultiFilePicker } from "webiny/admin/ui"; -``` - -```typescript -const MultiFilePicker = withStaticProps(DecoratableMultiFilePicker, { - Preview: { - Image: ImagePreview, - RichItem: RichItemPreview, - TextOnly: TextOnlyPreview - } -}); -``` - -### `NextPageIcon` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { NextPageIcon } from "webiny/admin/ui"; -``` - -```typescript -export const NextPageIcon = (props: IconButtonProps) => { - return ( - } label={"Next Page"} />} - variant={"ghost"} - size={"sm"} - {...props} - /> - ); -}; -``` - -### `OptionsIcon` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { OptionsIcon } from "webiny/admin/ui"; -``` - -```typescript -export const OptionsIcon = (props: IconButtonProps) => { - return ( - } label={"Options"} />} - variant={"ghost"} - size={"sm"} - {...props} - /> - ); -}; -``` - -### `OverlayLoader` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { OverlayLoader } from "webiny/admin/ui"; -``` - -```typescript -const OverlayLoader = makeDecoratable("OverlayLoader", DecoratableOverlayLoader); -``` - -### `Popover` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Popover } from "webiny/admin/ui"; -``` - -```typescript -const Popover = makeDecoratable("Popover", DecoratablePopover); -``` - -### `Portal` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Portal } from "webiny/admin/ui"; -``` - -```typescript -const Portal = PortalPrimitive.Root; -``` - -### `PreviousPageIcon` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { PreviousPageIcon } from "webiny/admin/ui"; -``` - -```typescript -export const PreviousPageIcon = (props: IconButtonProps) => { - return ( - } label={"Previous Page"} />} - variant={"ghost"} - size={"sm"} - {...props} - /> - ); -}; -``` - -### `ProgressBar` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { ProgressBar } from "webiny/admin/ui"; -``` - -```typescript -const ProgressBar = makeDecoratable("ProgressBar", DecoratableProgressBar); -``` - -### `Radio` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Radio } from "webiny/admin/ui"; -``` - -```typescript -const Radio = makeDecoratable("Radio", DecoratableRadio); -``` - -### `RadioGroup` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { RadioGroup } from "webiny/admin/ui"; -``` - -```typescript -const RadioGroup = makeDecoratable("RadioGroup", DecoratableRadioGroup); -``` - -### `RangeSlider` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { RangeSlider } from "webiny/admin/ui"; -``` - -```typescript -const RangeSlider = makeDecoratable("RangeSlider", DecoratableRangeSlider); -``` - -### `RefreshIcon` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { RefreshIcon } from "webiny/admin/ui"; -``` - -```typescript -export const RefreshIcon = (props: IconButtonProps) => { - return ( - } label={"Refresh"} />} - variant={"ghost"} - size={"sm"} - {...props} - /> - ); -}; -``` - -### `ScrollArea` - -**Function** — imported from `webiny/admin/ui` - -```typescript -import { ScrollArea } from "webiny/admin/ui"; -``` - -```typescript -function ScrollArea( -``` - -### `Scrollbar` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Scrollbar } from "webiny/admin/ui"; -``` - -```typescript -const Scrollbar = (props: ScrollbarProps) => { - return ; -}; -``` - -### `ScrollBar` - -**Function** — imported from `webiny/admin/ui` - -```typescript -import { ScrollBar } from "webiny/admin/ui"; -``` - -```typescript -function ScrollBar( -``` - -### `SegmentedControl` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { SegmentedControl } from "webiny/admin/ui"; -``` - -```typescript -const SegmentedControl = makeDecoratable("SegmentedControl", DecoratableSegmentedControl); -``` - -### `Select` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Select } from "webiny/admin/ui"; -``` - -```typescript -const Select = makeDecoratable("Select", DecoratableSelect); -``` - -### `Separator` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Separator } from "webiny/admin/ui"; -``` - -```typescript -const Separator = makeDecoratable("Separator", SeparatorBase); -``` - -### `Sidebar` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Sidebar } from "webiny/admin/ui"; -``` - -```typescript -const Sidebar = withStaticProps(DecoratableSidebar, { - Item: SidebarMenuItem, - Link: SidebarMenuLink, - Group: SidebarMenuGroup, - Icon: SidebarIcon -}); -``` - -### `SidebarProvider` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { SidebarProvider } from "webiny/admin/ui"; -``` - -```typescript -const SidebarProvider = ({ - className, - children, - state: cachedState, - onChangeState, - ...props -}: SidebarProviderProps) => { - const [sidebarState, setSidebarState] = React.useState(() => - createInitialSidebarState(cachedState) - ); - const [pinnedItemsData, setPinnedItemsData] = React.useState>( - new Map() - ); - - -``` - -### `Skeleton` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Skeleton } from "webiny/admin/ui"; -``` - -```typescript -const Skeleton = makeDecoratable("Skeleton", DecoratableSkeleton); -``` - -### `Slider` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Slider } from "webiny/admin/ui"; -``` - -```typescript -const Slider = makeDecoratable("Slider", DecoratableSlider); -``` - -### `SortIcon` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { SortIcon } from "webiny/admin/ui"; -``` - -```typescript -export const SortIcon = (props: IconButtonProps) => { - return ( - } label={"Sort"} />} - variant={"ghost"} - size={"sm"} - {...props} - /> - ); -}; -``` - -### `SteppedProgress` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { SteppedProgress } from "webiny/admin/ui"; -``` - -```typescript -const SteppedProgress = withStaticProps(BaseSteppedProgress, { - Item: SteppedProgressItem -}); -``` - -### `Switch` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Switch } from "webiny/admin/ui"; -``` - -```typescript -const Switch = makeDecoratable("Switch", DecoratableSwitch); -``` - -### `Table` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Table } from "webiny/admin/ui"; -``` - -```typescript -const Table = withStaticProps(BaseTable, { - Body, - Caption, - Cell, - Direction, - Footer, - Head, - Header, - Resizer, - Row -}); -``` - -### `Tabs` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Tabs } from "webiny/admin/ui"; -``` - -```typescript -const Tabs = withStaticProps(BaseTabs, { - Tab -}); -``` - -### `Tag` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Tag } from "webiny/admin/ui"; -``` - -```typescript -const Tag = makeDecoratable("Tag", DecoratableTag); -``` - -### `Tags` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Tags } from "webiny/admin/ui"; -``` - -```typescript -const Tags = makeDecoratable("Tags", DecoratableTags); -``` - -### `Text` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Text } from "webiny/admin/ui"; -``` - -```typescript -const Text = makeDecoratable("Text", TextBase); -``` - -### `Textarea` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Textarea } from "webiny/admin/ui"; -``` - -```typescript -const Textarea = makeDecoratable("Textarea", DecoratableTextarea); -``` - -### `TimeAgo` - -**Class** — imported from `webiny/admin/ui` - -```typescript -import { TimeAgo } from "webiny/admin/ui"; -``` - -```typescript -export default class TimeAgo extends React.PureComponent { - static defaultProps:; - dom: HTMLTimeElement; - componentDidMount(): void; - componentDidUpdate(): void; - renderTimeAgo(): void; - componentWillUnmount(): void; - render(): JSX.Element; -} -``` - -### `Toast` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Toast } from "webiny/admin/ui"; -``` - -```typescript -const Toast = withStaticProps(makeDecoratable("Toast", DecoratableToast), { - Title: ToastTitle, - Description: ToastDescription, - Actions: ToastActions, - Provider: (props: ToasterProps) => ( - - - - ) -}); -``` - -### `Tooltip` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Tooltip } from "webiny/admin/ui"; -``` - -```typescript -const Tooltip = withStaticProps(makeDecoratable("Tooltip", DecoratableTooltip), { - Provider: TooltipProvider -}); -``` - -### `Tree` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Tree } from "webiny/admin/ui"; -``` - -```typescript -const Tree = withStaticProps(DecoratableTree, { - Item -}); -``` - -### `UploadIcon` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { UploadIcon } from "webiny/admin/ui"; -``` - -```typescript -export const UploadIcon = (props: IconButtonProps) => { - return ( - } label={"Upload"} />} - variant={"ghost"} - size={"sm"} - {...props} - /> - ); -}; -``` - -### `Widget` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { Widget } from "webiny/admin/ui"; -``` - -```typescript -const Widget = withStaticProps(DecoratableWidget, { - Action: WidgetAction, - Icon -}); -``` - -## Hooks - -### `useDialogs` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { useDialogs } from "webiny/admin/ui"; -``` - -```typescript -export const useDialogs = () => { - const context = useContext(DialogsContext); - - if (!context) { - throw new Error("useDialogs must be used within a DialogsContext.Provider"); - } - - return context; -}; -``` - -### `useDisclosure` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { useDisclosure } from "webiny/admin/ui"; -``` - -```typescript -export const useDisclosure = (isOpenDefault = false) => { - const [isOpen, defaultSetIsOpen] = useState(isOpenDefault); - const [data, setData] = useState(null); - - const setIsOpen = useCallback( - (isOpen: boolean | ((prev: boolean) => boolean), data?: TData) => { - defaultSetIsOpen(isOpen); - if (typeof data !== "undefined") { - -``` - -### `useHotkeys` - -**Function** — imported from `webiny/admin/ui` - -```typescript -import { useHotkeys } from "webiny/admin/ui"; -``` - -```typescript -export function useHotkeys(props: HookProps); -``` - -### `useSidebar` - -**Function** — imported from `webiny/admin/ui` - -```typescript -import { useSidebar } from "webiny/admin/ui"; -``` - -```typescript -function useSidebar(); -``` - -### `useToast` - -**Constant** — imported from `webiny/admin/ui` - -```typescript -import { useToast } from "webiny/admin/ui"; -``` - -```typescript -const useToast = () => { - const getTitle = React.useCallback((title: React.ReactElement | string) => { - return typeof title === "string" ? : title; - }, []); - - const getDescription = React.useCallback( - (description: React.ReactElement | string | undefined) => { - return typeof description === " -``` diff --git a/docs/developer-docs/6.x/reference/admin/website-builder.ai.txt b/docs/developer-docs/6.x/reference/admin/website-builder.ai.txt deleted file mode 100644 index 091ef3891..000000000 --- a/docs/developer-docs/6.x/reference/admin/website-builder.ai.txt +++ /dev/null @@ -1,27 +0,0 @@ -AI Context: Website Builder (reference/admin/website-builder.mdx) - -Source of Information: -1. packages/webiny/src/admin/website-builder.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/app-website-builder/src/routes.ts — originating source -3. /Users/adrian/dev/wby-next/packages/app-website-builder/src/index.ts — originating source -4. /Users/adrian/dev/wby-next/packages/app-website-builder/src/presentation/security/usePermissions.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -Routes, pagePathFromTitle, usePermissions - -Import Path: webiny/admin/website-builder - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/website-builder.mdx b/docs/developer-docs/6.x/reference/admin/website-builder.mdx deleted file mode 100644 index 29d4d8449..000000000 --- a/docs/developer-docs/6.x/reference/admin/website-builder.mdx +++ /dev/null @@ -1,93 +0,0 @@ ---- -id: ywrtaw4v -title: Website Builder -description: "Website Builder admin utilities" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/website-builder`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/website-builder`. Import any of the items below directly from this path in your Webiny extensions. - -**Components** - - - -**Hooks** - - - -**Other** - - - -## Components - -### `Routes` - -**Constant** — imported from `webiny/admin/website-builder` - -```typescript -import { Routes } from "webiny/admin/website-builder"; -``` - -```typescript -export const Routes = { - Pages: { - List: new Route({ - name: "WebsiteBuilder/Pages/List", - path: "/website-builder/pages", - params: zod => { - return { - folderId: zod.string().optional(), - search: zod.string().optional() - }; - } - }), - Editor: new Route({ - -``` - -## Hooks - -### `usePermissions` - -**Constant** — imported from `webiny/admin/website-builder` - -```typescript -import { usePermissions } from "webiny/admin/website-builder"; -``` - -```typescript -export const usePermissions = createUsePermissions(WB_PERMISSIONS_SCHEMA); -``` - -## Other - -### `pagePathFromTitle` - -**Constant** — imported from `webiny/admin/website-builder` - -```typescript -import { pagePathFromTitle } from "webiny/admin/website-builder"; -``` - -```typescript -export const pagePathFromTitle = (title: string = "") => { - return slugify(title, { - replacement: "-", - lower: true, - remove: /[*#\?<>_\{\}\[\]+~.()'"!:;@]/g, - trim: false - }); -}; -``` diff --git a/docs/developer-docs/6.x/reference/admin/website-builder/lexical.ai.txt b/docs/developer-docs/6.x/reference/admin/website-builder/lexical.ai.txt deleted file mode 100644 index 547bd9556..000000000 --- a/docs/developer-docs/6.x/reference/admin/website-builder/lexical.ai.txt +++ /dev/null @@ -1,25 +0,0 @@ -AI Context: Lexical Editor (reference/admin/website-builder/lexical.mdx) - -Source of Information: -1. packages/webiny/src/admin/website-builder/lexical.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/lexical-editor/src/exports/admin/lexical.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -useLexicalEditorConfig, LexicalHtmlRenderer, getNodeFromSelection, useCurrentElement, useCurrentSelection, useDeriveValueFromSelection, useRichTextEditor, useFontColorPicker, useTextAlignmentAction, useTypographyAction, useIsMounted, Divider, DropDownItem, DropDown, Klass, LexicalNode - -Import Path: webiny/admin/website-builder/lexical - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/website-builder/lexical.mdx b/docs/developer-docs/6.x/reference/admin/website-builder/lexical.mdx deleted file mode 100644 index 3ae307131..000000000 --- a/docs/developer-docs/6.x/reference/admin/website-builder/lexical.mdx +++ /dev/null @@ -1,168 +0,0 @@ ---- -id: ywrtaw4v -title: Lexical Editor -description: "Website Builder Lexical editor config" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/website-builder/lexical`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/website-builder/lexical`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `Divider` - -**Export** — imported from `webiny/admin/website-builder/lexical` - -```typescript -import { Divider } from "webiny/admin/website-builder/lexical"; -``` - -## `DropDown` - -**Export** — imported from `webiny/admin/website-builder/lexical` - -```typescript -import { DropDown } from "webiny/admin/website-builder/lexical"; -``` - -## `DropDownItem` - -**Export** — imported from `webiny/admin/website-builder/lexical` - -```typescript -import { DropDownItem } from "webiny/admin/website-builder/lexical"; -``` - -## `getNodeFromSelection` - -**Export** — imported from `webiny/admin/website-builder/lexical` - -```typescript -import { getNodeFromSelection } from "webiny/admin/website-builder/lexical"; -``` - -## `Klass` - -**Type** — imported from `webiny/admin/website-builder/lexical` - -```typescript -import type { Klass } from "webiny/admin/website-builder/lexical"; -``` - -## `LexicalHtmlRenderer` - -**Export** — imported from `webiny/admin/website-builder/lexical` - -```typescript -import { LexicalHtmlRenderer } from "webiny/admin/website-builder/lexical"; -``` - -## `LexicalNode` - -**Type** — imported from `webiny/admin/website-builder/lexical` - -```typescript -import type { LexicalNode } from "webiny/admin/website-builder/lexical"; -``` - -## `useCurrentElement` - -**Export** — imported from `webiny/admin/website-builder/lexical` - -```typescript -import { useCurrentElement } from "webiny/admin/website-builder/lexical"; -``` - -## `useCurrentSelection` - -**Export** — imported from `webiny/admin/website-builder/lexical` - -```typescript -import { useCurrentSelection } from "webiny/admin/website-builder/lexical"; -``` - -## `useDeriveValueFromSelection` - -**Export** — imported from `webiny/admin/website-builder/lexical` - -```typescript -import { useDeriveValueFromSelection } from "webiny/admin/website-builder/lexical"; -``` - -## `useFontColorPicker` - -**Export** — imported from `webiny/admin/website-builder/lexical` - -```typescript -import { useFontColorPicker } from "webiny/admin/website-builder/lexical"; -``` - -## `useIsMounted` - -**Export** — imported from `webiny/admin/website-builder/lexical` - -```typescript -import { useIsMounted } from "webiny/admin/website-builder/lexical"; -``` - -## `useLexicalEditorConfig` - -**Export** — imported from `webiny/admin/website-builder/lexical` - -```typescript -import { useLexicalEditorConfig } from "webiny/admin/website-builder/lexical"; -``` - -## `useRichTextEditor` - -**Export** — imported from `webiny/admin/website-builder/lexical` - -```typescript -import { useRichTextEditor } from "webiny/admin/website-builder/lexical"; -``` - -## `useTextAlignmentAction` - -**Export** — imported from `webiny/admin/website-builder/lexical` - -```typescript -import { useTextAlignmentAction } from "webiny/admin/website-builder/lexical"; -``` - -## `useTypographyAction` - -**Export** — imported from `webiny/admin/website-builder/lexical` - -```typescript -import { useTypographyAction } from "webiny/admin/website-builder/lexical"; -``` diff --git a/docs/developer-docs/6.x/reference/admin/website-builder/page/editor.ai.txt b/docs/developer-docs/6.x/reference/admin/website-builder/page/editor.ai.txt deleted file mode 100644 index cee1488cb..000000000 --- a/docs/developer-docs/6.x/reference/admin/website-builder/page/editor.ai.txt +++ /dev/null @@ -1,40 +0,0 @@ -AI Context: Editor (reference/admin/website-builder/page/editor.mdx) - -Source of Information: -1. packages/webiny/src/admin/website-builder/page/editor.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/app-website-builder/src/modules/pages/PageEditor/usePageEditorConfig.ts — originating source -3. /Users/adrian/dev/wby-next/packages/app-website-builder/src/editorSdk/createCommand.ts — originating source -4. /Users/adrian/dev/wby-next/packages/app-website-builder/src/BaseEditor/hooks/useSelectFromEditor.ts — originating source -5. /Users/adrian/dev/wby-next/packages/app-website-builder/src/BaseEditor/hooks/useSelectFromDocument.ts — originating source -6. /Users/adrian/dev/wby-next/packages/app-website-builder/src/DocumentEditor/index.ts — originating source -7. /Users/adrian/dev/wby-next/packages/app-website-builder/src/BaseEditor/hooks/useActiveElement.ts — originating source -8. /Users/adrian/dev/wby-next/packages/app-website-builder/src/BaseEditor/hooks/useHighlightedElement.ts — originating source -9. /Users/adrian/dev/wby-next/packages/app-website-builder/src/BaseEditor/hooks/useComponent.ts — originating source -10. /Users/adrian/dev/wby-next/packages/app-website-builder/src/BaseEditor/hooks/useElementInputs.ts — originating source -11. /Users/adrian/dev/wby-next/packages/app-website-builder/src/BaseEditor/hooks/useCreateElement.ts — originating source -12. /Users/adrian/dev/wby-next/packages/app-website-builder/src/BaseEditor/hooks/useDeleteElement.ts — originating source -13. /Users/adrian/dev/wby-next/packages/app-website-builder/src/BaseEditor/hooks/useUpdateElement.ts — originating source -14. /Users/adrian/dev/wby-next/packages/app-website-builder/src/BaseEditor/hooks/useElementOverlay.ts — originating source -15. /Users/adrian/dev/wby-next/packages/app-website-builder/src/BaseEditor/defaultConfig/Content/Preview/useElementComponentManifest.ts — originating source -16. /Users/adrian/dev/wby-next/packages/app-website-builder/src/editorSdk/utils/index.ts — originating source -17. /Users/adrian/dev/wby-next/packages/website-builder-sdk/src/index.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -usePageEditorConfig, createCommand, useSelectFromEditor, useSelectFromDocument, useDocumentEditor, useActiveElement, useHighlightedElement, useComponent, useElementInputs, useCreateElement, useDeleteElement, useUpdateElement, useElementOverlay, useElementComponentManifest, $selectElement, $deselectElement, $highlightElement, $getElementById, $getActiveElementId, $getComponentManifestByElementId, $deleteElement, $createElement, $moveElement, $removeElementReferenceFromParent, $addElementReferenceToParent, $getElementsOfType, $getFirstElementOfType, $getElementInputValues, $updateElementInputs, $previewElementInputs, createElement - -Import Path: webiny/admin/website-builder/page/editor - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/website-builder/page/editor.mdx b/docs/developer-docs/6.x/reference/admin/website-builder/page/editor.mdx deleted file mode 100644 index f7c737591..000000000 --- a/docs/developer-docs/6.x/reference/admin/website-builder/page/editor.mdx +++ /dev/null @@ -1,536 +0,0 @@ ---- -id: ywrtaw4v -title: Editor -description: "Page editor components" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/website-builder/page/editor`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/website-builder/page/editor`. Import any of the items below directly from this path in your Webiny extensions. - -**Hooks** - - - -**Other** - - - -## Hooks - -### `useActiveElement` - -**Constant** — imported from `webiny/admin/website-builder/page/editor` - -```typescript -import { useActiveElement } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export const useActiveElement = () => { - const [activeElement, setActiveElement] = useState(null); - const editor = useDocumentEditor(); - - useEffect(() => { - return autorun(() => { - const editorState = editor.getEditorState().read(); - const documentState = editor.getDocumentState().read(); - - const activeElementId = editorState -``` - -### `useComponent` - -**Constant** — imported from `webiny/admin/website-builder/page/editor` - -```typescript -import { useComponent } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export const useComponent = (name: string) => { - const selector = useCallback((state: EditorState) => state.components[name], [name]); - - return useSelectFromEditor(selector, [name]); -}; -``` - -### `useCreateElement` - -**Function** — imported from `webiny/admin/website-builder/page/editor` - -```typescript -import { useCreateElement } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export function useCreateElement(); -``` - -### `useDeleteElement` - -**Function** — imported from `webiny/admin/website-builder/page/editor` - -```typescript -import { useDeleteElement } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export function useDeleteElement(); -``` - -### `useDocumentEditor` - -**Function** — imported from `webiny/admin/website-builder/page/editor` - -```typescript -import { useDocumentEditor } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export function useDocumentEditor(); -``` - -### `useElementComponentManifest` - -**Constant** — imported from `webiny/admin/website-builder/page/editor` - -```typescript -import { useElementComponentManifest } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export const useElementComponentManifest = (elementId: string) => { - const editor = useDocumentEditor(); - const document = editor.getDocumentState().read(); - const componentName = document.elements[elementId]?.component.name; - - return useSelectFromEditor( - state => { - return state.components[componentName]; - }, - [componentName] - ); -}; -``` - -### `useElementInputs` - -**Function** — imported from `webiny/admin/website-builder/page/editor` - -Returns the resolved input values for the given element, plus an updater callback. - -@param elementId The element whose inputs to resolve (null returns {}). -@param depth How many levels of slot children to resolve (default 0). - -```typescript -import { useElementInputs } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export function useElementInputs = Record>( - elementId: string | null, - depth = 0 -); -``` - -### `useHighlightedElement` - -**Constant** — imported from `webiny/admin/website-builder/page/editor` - -```typescript -import { useHighlightedElement } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export const useHighlightedElement = () => { - const [highlightedElement, setHighlightedElement] = useState(null); - const editor = useDocumentEditor(); - - useEffect(() => { - return autorun(() => { - const editorState = editor.getEditorState().read(); - const documentState = editor.getDocumentState().read(); - - const elementId = ed -``` - -### `usePageEditorConfig` - -**Constant** — imported from `webiny/admin/website-builder/page/editor` - -```typescript -import { usePageEditorConfig } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export const usePageEditorConfig = (): PageEditorConfig => { - const config = useEditorConfig(); - - return { - ...config, - pageSettings: { - groups: config.pageSettings.groups ?? [], - viewMode: config.pageSettings.viewMode ?? "dialog" - } - }; -}; -``` - -### `useSelectFromDocument` - -**Function** — imported from `webiny/admin/website-builder/page/editor` - -Subscribe to part of the document state. -@param selector Pick the slice of state you care about. -@param equals (optional) comparator, defaults to Object.is - -```typescript -import { useSelectFromDocument } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export function useSelectFromDocument( - selector: (doc: TDocument) => TReturn, - deps: React.DependencyList = [], - equals: Equals = deepEqual -): TReturn; -``` - -### `useSelectFromEditor` - -**Function** — imported from `webiny/admin/website-builder/page/editor` - -Subscribe to part of the document state. -@param selector Pick the slice of state you care about. -@param equals (optional) comparator, defaults to Object.is - -```typescript -import { useSelectFromEditor } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export function useSelectFromEditor( - selector: (doc: EditorState) => T, - deps: React.DependencyList = [], - equals: Equals = deepEqual -): T; -``` - -### `useUpdateElement` - -**Function** — imported from `webiny/admin/website-builder/page/editor` - -```typescript -import { useUpdateElement } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export function useUpdateElement(); -``` - -## Other - -### `$addElementReferenceToParent` - -**Function** — imported from `webiny/admin/website-builder/page/editor` - -```typescript -import { $addElementReferenceToParent } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export function $addElementReferenceToParent( - document: Document, -``` - -### `$createElement` - -**Function** — imported from `webiny/admin/website-builder/page/editor` - -```typescript -import { $createElement } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export function $createElement( - editor: Editor, - payload: CommandPayload -): ConstraintResult | undefined; -``` - -### `$deleteElement` - -**Function** — imported from `webiny/admin/website-builder/page/editor` - -```typescript -import { $deleteElement } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export function $deleteElement(editor: Editor, id: string, ignoreConstraints = false); -``` - -### `$deselectElement` - -**Function** — imported from `webiny/admin/website-builder/page/editor` - -```typescript -import { $deselectElement } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export function $deselectElement(editor: Editor); -``` - -### `$getActiveElementId` - -**Function** — imported from `webiny/admin/website-builder/page/editor` - -```typescript -import { $getActiveElementId } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export function $getActiveElementId(editor: Editor); -``` - -### `$getComponentManifestByElementId` - -**Function** — imported from `webiny/admin/website-builder/page/editor` - -```typescript -import { $getComponentManifestByElementId } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export function $getComponentManifestByElementId( - editor: Editor, - id: string -): ComponentManifest | undefined; -``` - -### `$getElementById` - -**Function** — imported from `webiny/admin/website-builder/page/editor` - -```typescript -import { $getElementById } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export function $getElementById(document: Document, id: string); -``` - -### `$getElementInputValues` - -**Function** — imported from `webiny/admin/website-builder/page/editor` - -```typescript -import { $getElementInputValues } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export function $getElementInputValues( - document: Document, - components: Record, - elementId: string | null, - depth = 0 -); -``` - -### `$getElementsOfType` - -**Function** — imported from `webiny/admin/website-builder/page/editor` - -```typescript -import { $getElementsOfType } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export function $getElementsOfType(document: Document, componentName: string); -``` - -### `$getFirstElementOfType` - -**Function** — imported from `webiny/admin/website-builder/page/editor` - -```typescript -import { $getFirstElementOfType } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export function $getFirstElementOfType(document: Document, componentName: string); -``` - -### `$highlightElement` - -**Function** — imported from `webiny/admin/website-builder/page/editor` - -```typescript -import { $highlightElement } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export function $highlightElement(editor: Editor, id: string | null); -``` - -### `$moveElement` - -**Function** — imported from `webiny/admin/website-builder/page/editor` - -```typescript -import { $moveElement } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export function $moveElement(document: Document, params: MoveParams): ConstraintResult | undefined; -``` - -### `$previewElementInputs` - -**Function** — imported from `webiny/admin/website-builder/page/editor` - -Programmatically update an element's inputs in the preview iframe only (via JSON patch). -Does NOT write to the editor document state. - -```typescript -import { $previewElementInputs } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export function $previewElementInputs( - editor: Editor, - elementId: string, - updater: (inputs: Record) => void -): void; -``` - -### `$removeElementReferenceFromParent` - -**Function** — imported from `webiny/admin/website-builder/page/editor` - -```typescript -import { $removeElementReferenceFromParent } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export function $removeElementReferenceFromParent( - document: Document, -``` - -### `$selectElement` - -**Function** — imported from `webiny/admin/website-builder/page/editor` - -```typescript -import { $selectElement } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export function $selectElement(editor: Editor, id: string | null); -``` - -### `$updateElementInputs` - -**Function** — imported from `webiny/admin/website-builder/page/editor` - -Programmatically update an element's inputs using a callback-based API. -The updater receives a deep object representation of the element's inputs -which can be mutated in place. - -```typescript -import { $updateElementInputs } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export function $updateElementInputs( - editor: Editor, - elementId: string, - updater: (inputs: Record) => void -): void; -``` - -### `createCommand` - -**Function** — imported from `webiny/admin/website-builder/page/editor` - -```typescript -import { createCommand } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export function createCommand(type: string): Command; -``` - -### `createElement` - -**Constant** — imported from `webiny/admin/website-builder/page/editor` - -```typescript -import { createElement } from "webiny/admin/website-builder/page/editor"; -``` - -```typescript -export const createElement = (params: CreateElementParams) => { - return { - action: "CreateElement", - params - }; -}; -``` - -### `useElementOverlay` - -**Export** — imported from `webiny/admin/website-builder/page/editor` - -```typescript -import { useElementOverlay } from "webiny/admin/website-builder/page/editor"; -``` diff --git a/docs/developer-docs/6.x/reference/admin/website-builder/page/list.ai.txt b/docs/developer-docs/6.x/reference/admin/website-builder/page/list.ai.txt deleted file mode 100644 index 768eba450..000000000 --- a/docs/developer-docs/6.x/reference/admin/website-builder/page/list.ai.txt +++ /dev/null @@ -1,25 +0,0 @@ -AI Context: List (reference/admin/website-builder/page/list.mdx) - -Source of Information: -1. packages/webiny/src/admin/website-builder/page/list.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/app-website-builder/src/index.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -PageListConfig - -Import Path: webiny/admin/website-builder/page/list - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/website-builder/page/list.mdx b/docs/developer-docs/6.x/reference/admin/website-builder/page/list.mdx deleted file mode 100644 index 392176817..000000000 --- a/docs/developer-docs/6.x/reference/admin/website-builder/page/list.mdx +++ /dev/null @@ -1,29 +0,0 @@ ---- -id: ywrtaw4v -title: List -description: "Page list configuration" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/website-builder/page/list`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/website-builder/page/list`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `PageListConfig` - -**Export** — imported from `webiny/admin/website-builder/page/list` - -```typescript -import { PageListConfig } from "webiny/admin/website-builder/page/list"; -``` diff --git a/docs/developer-docs/6.x/reference/admin/website-builder/redirect/list.ai.txt b/docs/developer-docs/6.x/reference/admin/website-builder/redirect/list.ai.txt deleted file mode 100644 index 6fa90e2bf..000000000 --- a/docs/developer-docs/6.x/reference/admin/website-builder/redirect/list.ai.txt +++ /dev/null @@ -1,25 +0,0 @@ -AI Context: List (reference/admin/website-builder/redirect/list.mdx) - -Source of Information: -1. packages/webiny/src/admin/website-builder/redirect/list.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/app-website-builder/src/index.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -RedirectListConfig - -Import Path: webiny/admin/website-builder/redirect/list - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/admin/website-builder/redirect/list.mdx b/docs/developer-docs/6.x/reference/admin/website-builder/redirect/list.mdx deleted file mode 100644 index ab4d27adc..000000000 --- a/docs/developer-docs/6.x/reference/admin/website-builder/redirect/list.mdx +++ /dev/null @@ -1,29 +0,0 @@ ---- -id: ywrtaw4v -title: List -description: "Redirect list configuration" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/admin/website-builder/redirect/list`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/admin/website-builder/redirect/list`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `RedirectListConfig` - -**Export** — imported from `webiny/admin/website-builder/redirect/list` - -```typescript -import { RedirectListConfig } from "webiny/admin/website-builder/redirect/list"; -``` diff --git a/docs/developer-docs/6.x/reference/api.ai.txt b/docs/developer-docs/6.x/reference/api.ai.txt deleted file mode 100644 index ac4617720..000000000 --- a/docs/developer-docs/6.x/reference/api.ai.txt +++ /dev/null @@ -1,25 +0,0 @@ -AI Context: API (reference/api.mdx) - -Source of Information: -1. packages/webiny/src/api.ts — barrel re-export file - - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: - - -Import Path: webiny/api - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api.mdx b/docs/developer-docs/6.x/reference/api.mdx deleted file mode 100644 index 19b8a8e57..000000000 --- a/docs/developer-docs/6.x/reference/api.mdx +++ /dev/null @@ -1,21 +0,0 @@ ---- -id: yxbp0000 -title: API -description: "Core API primitives: createFeature, createAbstraction, Result, BaseError" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/api`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api`. Import any of the items below directly from this path in your Webiny extensions. - -_No exported symbols found._ diff --git a/docs/developer-docs/6.x/reference/api/aco/flp.ai.txt b/docs/developer-docs/6.x/reference/api/aco/flp.ai.txt deleted file mode 100644 index 0c200c38d..000000000 --- a/docs/developer-docs/6.x/reference/api/aco/flp.ai.txt +++ /dev/null @@ -1,29 +0,0 @@ -AI Context: Flp (reference/api/aco/flp.mdx) - -Source of Information: -1. packages/webiny/src/api/aco/flp.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-aco/src/features/flp/CreateFlp/abstractions.ts — originating source -3. /Users/adrian/dev/wby-next/packages/api-aco/src/features/flp/DeleteFlp/abstractions.ts — originating source -4. /Users/adrian/dev/wby-next/packages/api-aco/src/features/flp/GetFlp/abstractions.ts — originating source -5. /Users/adrian/dev/wby-next/packages/api-aco/src/features/flp/ListFlps/abstractions.ts — originating source -6. /Users/adrian/dev/wby-next/packages/api-aco/src/features/flp/UpdateFlp/abstractions.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -CreateFlpUseCase, DeleteFlpUseCase, GetFlpUseCase, ListFlpsUseCase, UpdateFlpUseCase - -Import Path: webiny/api/aco/flp - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/aco/flp.mdx b/docs/developer-docs/6.x/reference/api/aco/flp.mdx deleted file mode 100644 index 2fbec9831..000000000 --- a/docs/developer-docs/6.x/reference/api/aco/flp.mdx +++ /dev/null @@ -1,149 +0,0 @@ ---- -id: yxbpl2fj -title: Flp -description: "Reference for webiny/api/aco/flp" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What use cases are available in `webiny/api/aco/flp`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/aco/flp`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `CreateFlpUseCase` - -**Use Case Abstraction** — imported from `webiny/api/aco/flp` - -```typescript -import { CreateFlpUseCase } from "webiny/api/aco/flp"; -``` - -**Interface `CreateFlpUseCase.Interface`:** - -```typescript -interface CreateFlpUseCase.Interface { - execute: (folder: Folder) => Promise; -} -``` - -**Types:** - -```typescript -namespace CreateFlpUseCase { - type Interface = ICreateFlpUseCase; -} -``` - -## `DeleteFlpUseCase` - -**Use Case Abstraction** — imported from `webiny/api/aco/flp` - -```typescript -import { DeleteFlpUseCase } from "webiny/api/aco/flp"; -``` - -**Interface `DeleteFlpUseCase.Interface`:** - -```typescript -interface DeleteFlpUseCase.Interface { - execute: (folder: Folder) => Promise; -} -``` - -**Types:** - -```typescript -namespace DeleteFlpUseCase { - type Interface = IDeleteFlpUseCase; -} -``` - -## `GetFlpUseCase` - -**Use Case Abstraction** — imported from `webiny/api/aco/flp` - -```typescript -import { GetFlpUseCase } from "webiny/api/aco/flp"; -``` - -**Interface `GetFlpUseCase.Interface`:** - -```typescript -interface GetFlpUseCase.Interface { - execute: (id: string) => Promise; -} -``` - -**Types:** - -```typescript -namespace GetFlpUseCase { - type Interface = IGetFolderPermission; -} -``` - -## `ListFlpsUseCase` - -**Use Case Abstraction** — imported from `webiny/api/aco/flp` - -```typescript -import { ListFlpsUseCase } from "webiny/api/aco/flp"; -``` - -**Interface `ListFlpsUseCase.Interface`:** - -```typescript -interface ListFlpsUseCase.Interface { - execute: (params: ListFlpsParams) => Promise; -} -``` - -**Types:** - -```typescript -namespace ListFlpsUseCase { - type Interface = IListFlps; -} -``` - -## `UpdateFlpUseCase` - -**Use Case Abstraction** — imported from `webiny/api/aco/flp` - -```typescript -import { UpdateFlpUseCase } from "webiny/api/aco/flp"; -``` - -**Interface `UpdateFlpUseCase.Interface`:** - -```typescript -interface UpdateFlpUseCase.Interface { - execute: (params: UpdateFlpParams) => Promise; -} -``` - -**Types:** - -```typescript -namespace UpdateFlpUseCase { - type Interface = IUpdateFlpUseCase; -} -``` diff --git a/docs/developer-docs/6.x/reference/api/aco/folder.ai.txt b/docs/developer-docs/6.x/reference/api/aco/folder.ai.txt deleted file mode 100644 index 0493c4bbb..000000000 --- a/docs/developer-docs/6.x/reference/api/aco/folder.ai.txt +++ /dev/null @@ -1,26 +0,0 @@ -AI Context: Folder (reference/api/aco/folder.mdx) - -Source of Information: -1. packages/webiny/src/api/aco/folder.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-aco/src/features/folder/ListFolderLevelPermissionsTargets/abstractions.ts — originating source -3. /Users/adrian/dev/wby-next/packages/api-aco/src/features/folder/shared/abstractions.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -ListFolderLevelPermissionsTargetsUseCase, FilterStorageOperations - -Import Path: webiny/api/aco/folder - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/aco/folder.mdx b/docs/developer-docs/6.x/reference/api/aco/folder.mdx deleted file mode 100644 index 77526fb1a..000000000 --- a/docs/developer-docs/6.x/reference/api/aco/folder.mdx +++ /dev/null @@ -1,83 +0,0 @@ ---- -id: yxbpl2fj -title: Folder -description: "Reference for webiny/api/aco/folder" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What use cases are available in `webiny/api/aco/folder`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/aco/folder`. Import any of the items below directly from this path in your Webiny extensions. - -**Use Cases** - - - -**Services** - - - -## Use Cases - -### `ListFolderLevelPermissionsTargetsUseCase` - -**Use Case Abstraction** — imported from `webiny/api/aco/folder` - -```typescript -import { ListFolderLevelPermissionsTargetsUseCase } from "webiny/api/aco/folder"; -``` - -**Interface `ListFolderLevelPermissionsTargetsUseCase.Interface`:** - -```typescript -interface ListFolderLevelPermissionsTargetsUseCase.Interface { - execute: () => Promise< - Result<[FolderLevelPermissionsTarget[], FolderLevelPermissionsTargetListMeta]> - >; -} -``` - -**Types:** - -```typescript -namespace ListFolderLevelPermissionsTargetsUseCase { - type Interface = IListFolderLevelPermissionsTargetsUseCase; - type Return = Promise< - Result<[FolderLevelPermissionsTarget[], FolderLevelPermissionsTargetListMeta]> - >; -} -``` - -## Services - -### `FilterStorageOperations` - -**Abstraction** — imported from `webiny/api/aco/folder` - -```typescript -import { FilterStorageOperations } from "webiny/api/aco/folder"; -``` - -**Types:** - -```typescript -namespace FilterStorageOperations { - type Interface = IAcoStorageOperations["filter"]; -} -``` diff --git a/docs/developer-docs/6.x/reference/api/build-params.ai.txt b/docs/developer-docs/6.x/reference/api/build-params.ai.txt deleted file mode 100644 index 46a469299..000000000 --- a/docs/developer-docs/6.x/reference/api/build-params.ai.txt +++ /dev/null @@ -1,25 +0,0 @@ -AI Context: Build Params (reference/api/build-params.mdx) - -Source of Information: -1. packages/webiny/src/api/build-params.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-core/src/features/buildParams/index.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -BuildParam, BuildParams - -Import Path: webiny/api/build-params - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/build-params.mdx b/docs/developer-docs/6.x/reference/api/build-params.mdx deleted file mode 100644 index 610d8b272..000000000 --- a/docs/developer-docs/6.x/reference/api/build-params.mdx +++ /dev/null @@ -1,75 +0,0 @@ ---- -id: yxbpl2j1 -title: Build Params -description: "Reference for webiny/api/build-params" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/api/build-params`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/build-params`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `BuildParam` - -**Abstraction** — imported from `webiny/api/build-params` - -```typescript -import { BuildParam } from "webiny/api/build-params"; -``` - -**Interface `BuildParam.Interface`:** - -```typescript -interface BuildParam.Interface { - key: string; - value: any; -} -``` - -**Types:** - -```typescript -namespace BuildParam { - type Interface = IBuildParam; -} -``` - -## `BuildParams` - -**Abstraction** — imported from `webiny/api/build-params` - -```typescript -import { BuildParams } from "webiny/api/build-params"; -``` - -**Interface `BuildParams.Interface`:** - -```typescript -interface BuildParams.Interface { - get(key: string): T | null; -} -``` - -**Types:** - -```typescript -namespace BuildParams { - type Interface = IBuildParams; -} -``` diff --git a/docs/developer-docs/6.x/reference/api/cms/entry.ai.txt b/docs/developer-docs/6.x/reference/api/cms/entry.ai.txt deleted file mode 100644 index 6931e429c..000000000 --- a/docs/developer-docs/6.x/reference/api/cms/entry.ai.txt +++ /dev/null @@ -1,64 +0,0 @@ -AI Context: Entry (reference/api/cms/entry.mdx) - -Source of Information: -1. packages/webiny/src/api/cms/entry.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/domain/contentEntry/EntryId.ts — originating source -3. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/types/types.ts — originating source -4. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/CreateEntry/abstractions.ts — originating source -5. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/CreateEntry/events.ts — originating source -6. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/CreateEntryRevisionFrom/abstractions.ts — originating source -7. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/CreateEntryRevisionFrom/events.ts — originating source -8. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/DeleteEntry/abstractions.ts — originating source -9. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/DeleteEntry/events.ts — originating source -10. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/DeleteEntryRevision/abstractions.ts — originating source -11. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/DeleteEntryRevision/events.ts — originating source -12. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/DeleteMultipleEntries/abstractions.ts — originating source -13. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/DeleteMultipleEntries/events.ts — originating source -14. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/MoveEntry/abstractions.ts — originating source -15. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/MoveEntry/events.ts — originating source -16. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/PublishEntry/abstractions.ts — originating source -17. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/PublishEntry/events.ts — originating source -18. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/RepublishEntry/abstractions.ts — originating source -19. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/RepublishEntry/events.ts — originating source -20. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/RestoreEntryFromBin/abstractions.ts — originating source -21. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/RestoreEntryFromBin/events.ts — originating source -22. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/UnpublishEntry/abstractions.ts — originating source -23. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/UnpublishEntry/events.ts — originating source -24. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/UpdateEntry/abstractions.ts — originating source -25. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/UpdateEntry/events.ts — originating source -26. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/UpdateSingletonEntry/abstractions.ts — originating source -27. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/GetEntriesByIds/abstractions.ts — originating source -28. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/GetEntry/abstractions.ts — originating source -29. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/GetEntryById/abstractions.ts — originating source -30. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/GetLatestEntriesByIds/abstractions.ts — originating source -31. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/GetLatestRevisionByEntryId/abstractions.ts — originating source -32. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/GetPreviousRevisionByEntryId/abstractions.ts — originating source -33. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/GetPublishedEntriesByIds/abstractions.ts — originating source -34. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/GetPublishedRevisionByEntryId/abstractions.ts — originating source -35. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/GetRevisionById/abstractions.ts — originating source -36. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/GetRevisionsByEntryId/abstractions.ts — originating source -37. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/GetSingletonEntry/abstractions.ts — originating source -38. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/ListEntries/abstractions.ts — originating source -39. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentEntry/ValidateEntry/abstractions.ts — originating source -40. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/whereMapper/abstractions.ts — originating source -41. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/sortMapper/abstractions.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -EntryId, CmsEntry, CmsEntryValues, CreateEntryUseCase, EntryBeforeCreateEventHandler, EntryAfterCreateEventHandler, CreateEntryRevisionFromUseCase, EntryRevisionBeforeCreateEventHandler, EntryRevisionAfterCreateEventHandler, DeleteEntryUseCase, MoveEntryToBinUseCase, EntryBeforeDeleteEventHandler, EntryAfterDeleteEventHandler, DeleteEntryRevisionUseCase, EntryRevisionBeforeDeleteEventHandler, EntryRevisionAfterDeleteEventHandler, DeleteMultipleEntriesUseCase, EntryBeforeDeleteMultipleEventHandler, EntryAfterDeleteMultipleEventHandler, MoveEntryUseCase, EntryBeforeMoveEventHandler, EntryAfterMoveEventHandler, PublishEntryUseCase, EntryBeforePublishEventHandler, EntryAfterPublishEventHandler, RepublishEntryUseCase, EntryBeforeRepublishEventHandler, EntryAfterRepublishEventHandler, RestoreEntryFromBinUseCase, EntryBeforeRestoreFromBinEventHandler, EntryAfterRestoreFromBinEventHandler, UnpublishEntryUseCase, EntryBeforeUnpublishEventHandler, EntryAfterUnpublishEventHandler, UpdateEntryUseCase, EntryBeforeUpdateEventHandler, EntryAfterUpdateEventHandler, UpdateSingletonEntryUseCase, GetEntriesByIdsUseCase, GetEntryUseCase, GetEntryByIdUseCase, GetLatestEntriesByIdsUseCase, GetLatestRevisionByEntryIdBaseUseCase, GetLatestRevisionByEntryIdUseCase, GetLatestDeletedRevisionByEntryIdUseCase, GetLatestRevisionByEntryIdIncludingDeletedUseCase, GetPreviousRevisionByEntryIdBaseUseCase, GetPreviousRevisionByEntryIdUseCase, GetPublishedEntriesByIdsUseCase, GetPublishedRevisionByEntryIdUseCase, GetRevisionByIdUseCase, GetRevisionsByEntryIdUseCase, GetSingletonEntryUseCase, ListEntriesUseCase, ListLatestEntriesUseCase, ListPublishedEntriesUseCase, ListDeletedEntriesUseCase, ValidateEntryUseCase, CmsWhereMapper, CmsSortMapper - -Import Path: webiny/api/cms/entry - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/cms/entry.mdx b/docs/developer-docs/6.x/reference/api/cms/entry.mdx deleted file mode 100644 index ddd6af683..000000000 --- a/docs/developer-docs/6.x/reference/api/cms/entry.mdx +++ /dev/null @@ -1,1952 +0,0 @@ ---- -id: yxbpl2nt -title: Entry -description: "CMS entry use cases and event handlers" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What use cases are available in `webiny/api/cms/entry`? -- Which event handlers can you implement? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/cms/entry`. Import any of the items below directly from this path in your Webiny extensions. - -**Use Cases** - - - -**Event Handlers** - - - -**Services** - - - -**Types & Classes** - - - -## Use Cases - -### `CreateEntryRevisionFromUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { CreateEntryRevisionFromUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `CreateEntryRevisionFromUseCase.Interface`:** - -CreateEntryRevisionFrom Use Case - Creates a new revision from an existing entry. - -```typescript -interface CreateEntryRevisionFromUseCase.Interface { - execute( - model: CmsModel, - sourceId: string, - input: CreateCmsEntryInput, - options?: CreateCmsEntryOptionsInput - ): Promise, UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace CreateEntryRevisionFromUseCase { - type Interface = ICreateEntryRevisionFromUseCase; - type Input = CreateCmsEntryInput; - type Options = CreateCmsEntryOptionsInput; - type Return = Promise, UseCaseError>>; - type Error = UseCaseError; -} -``` - -### `CreateEntryUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { CreateEntryUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `CreateEntryUseCase.Interface`:** - -CreateEntry Use Case - -```typescript -interface CreateEntryUseCase.Interface { - execute( - model: CmsModel, - input: CreateCmsEntryInput, - options?: CreateCmsEntryOptionsInput - ): Promise, UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace CreateEntryUseCase { - type Interface = ICreateEntryUseCase; - type Input = CreateCmsEntryInput; - type Options = CreateCmsEntryOptionsInput; - type Error = UseCaseError; - type Return = Promise, UseCaseError>>; -} -``` - -### `DeleteEntryRevisionUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { DeleteEntryRevisionUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `DeleteEntryRevisionUseCase.Interface`:** - -DeleteEntryRevision Use Case - Deletes a specific revision of an entry. -Handles special cases like deleting the latest revision. - -```typescript -interface DeleteEntryRevisionUseCase.Interface { - execute(model: CmsModel, revisionId: string): Promise>; -} -``` - -**Types:** - -```typescript -namespace DeleteEntryRevisionUseCase { - type Interface = IDeleteEntryRevisionUseCase; - type Error = UseCaseError; - type Return = Promise>; -} -``` - -### `DeleteEntryUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { DeleteEntryUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `DeleteEntryUseCase.Interface`:** - -DeleteEntry Use Case - Permanently deletes an entry from the database. -This is a hard delete that removes all traces of the entry. - -```typescript -interface DeleteEntryUseCase.Interface { - execute( - model: CmsModel, - id: string, - options?: CmsDeleteEntryOptions - ): Promise>; -} -``` - -**Types:** - -```typescript -namespace DeleteEntryUseCase { - type Interface = IDeleteEntryUseCase; - type Options = CmsDeleteEntryOptions; - type Error = UseCaseError; - type Return = Promise>; -} -``` - -### `DeleteMultipleEntriesUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { DeleteMultipleEntriesUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `DeleteMultipleEntriesUseCase.Interface`:** - -```typescript -interface DeleteMultipleEntriesUseCase.Interface { - execute( - model: CmsModel, - params: IDeleteMultipleEntriesUseCaseParams - ): Promise>; -} -``` - -**Types:** - -```typescript -namespace DeleteMultipleEntriesUseCase { - type Interface = IDeleteMultipleEntriesUseCase; - type Params = IDeleteMultipleEntriesUseCaseParams; - type Error = UseCaseError; - type Return = Promise>; -} -``` - -### `GetEntriesByIdsUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { GetEntriesByIdsUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `GetEntriesByIdsUseCase.Interface`:** - -GetEntriesByIds Use Case - Fetches multiple entries by their exact revision IDs. -Returns array of entries (excludes deleted entries via decorator). - -```typescript -interface GetEntriesByIdsUseCase.Interface { - execute( - model: CmsModel, - ids: string[] - ): Promise[], UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace GetEntriesByIdsUseCase { - type Interface = IGetEntriesByIdsUseCase; - type Error = UseCaseError; - type Return = Promise[], UseCaseError>>; -} -``` - -### `GetEntryByIdUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { GetEntryByIdUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `GetEntryByIdUseCase.Interface`:** - -GetEntryById Use Case - Fetches a single entry by its exact revision ID. -Returns entry or fails with EntryNotFoundError if not found or deleted. - -```typescript -interface GetEntryByIdUseCase.Interface { - execute( - model: CmsModel, - id: string - ): Promise, UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace GetEntryByIdUseCase { - type Interface = IGetEntryByIdUseCase; - type Error = UseCaseError; - type Return = Promise, UseCaseError>>; -} -``` - -### `GetEntryUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { GetEntryUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `GetEntryUseCase.Interface`:** - -GetEntry Use Case - Gets a single entry by query parameters (where + sort). -Uses list operation with limit 1 and returns first result or NotFoundError. - -```typescript -interface GetEntryUseCase.Interface { - execute( - model: CmsModel, - params: CmsEntryGetParams - ): Promise, UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace GetEntryUseCase { - type Interface = IGetEntryUseCase; - type Error = UseCaseError; - type Params = CmsEntryGetParams; - type Return = Promise, UseCaseError>>; -} -``` - -### `GetLatestDeletedRevisionByEntryIdUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { GetLatestDeletedRevisionByEntryIdUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `GetLatestDeletedRevisionByEntryIdUseCase.Interface`:** - -Base internal use case - returns entry regardless of deleted state. -This is used internally by the three public variations. - -```typescript -interface GetLatestDeletedRevisionByEntryIdUseCase.Interface { - execute( - model: CmsModel, - params: CmsEntryStorageOperationsGetLatestRevisionParams - ): Promise, UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace GetLatestDeletedRevisionByEntryIdUseCase { - type Interface = IGetLatestRevisionByEntryIdBaseUseCase; - type Params = CmsEntryStorageOperationsGetLatestRevisionParams; - type Error = UseCaseError; - type Return = Promise, UseCaseError>>; -} -``` - -### `GetLatestEntriesByIdsUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { GetLatestEntriesByIdsUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `GetLatestEntriesByIdsUseCase.Interface`:** - -GetLatestEntriesByIds Use Case - Fetches latest revisions by entry IDs. -Returns array of latest entries (excludes deleted entries via decorator). - -```typescript -interface GetLatestEntriesByIdsUseCase.Interface { - execute( - model: CmsModel, - ids: string[] - ): Promise[], UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace GetLatestEntriesByIdsUseCase { - type Interface = IGetLatestEntriesByIdsUseCase; - type Error = UseCaseError; - type Return = Promise[], UseCaseError>>; -} -``` - -### `GetLatestRevisionByEntryIdBaseUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { GetLatestRevisionByEntryIdBaseUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `GetLatestRevisionByEntryIdBaseUseCase.Interface`:** - -Base internal use case - returns entry regardless of deleted state. -This is used internally by the three public variations. - -```typescript -interface GetLatestRevisionByEntryIdBaseUseCase.Interface { - execute( - model: CmsModel, - params: CmsEntryStorageOperationsGetLatestRevisionParams - ): Promise, UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace GetLatestRevisionByEntryIdBaseUseCase { - type Interface = IGetLatestRevisionByEntryIdBaseUseCase; - type Params = CmsEntryStorageOperationsGetLatestRevisionParams; - type Error = UseCaseError; - type Return = Promise, UseCaseError>>; -} -``` - -### `GetLatestRevisionByEntryIdIncludingDeletedUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { GetLatestRevisionByEntryIdIncludingDeletedUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `GetLatestRevisionByEntryIdIncludingDeletedUseCase.Interface`:** - -Base internal use case - returns entry regardless of deleted state. -This is used internally by the three public variations. - -```typescript -interface GetLatestRevisionByEntryIdIncludingDeletedUseCase.Interface { - execute( - model: CmsModel, - params: CmsEntryStorageOperationsGetLatestRevisionParams - ): Promise, UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace GetLatestRevisionByEntryIdIncludingDeletedUseCase { - type Interface = IGetLatestRevisionByEntryIdBaseUseCase; - type Params = CmsEntryStorageOperationsGetLatestRevisionParams; - type Error = UseCaseError; - type Return = Promise, UseCaseError>>; -} -``` - -### `GetLatestRevisionByEntryIdUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { GetLatestRevisionByEntryIdUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `GetLatestRevisionByEntryIdUseCase.Interface`:** - -Base internal use case - returns entry regardless of deleted state. -This is used internally by the three public variations. - -```typescript -interface GetLatestRevisionByEntryIdUseCase.Interface { - execute( - model: CmsModel, - params: CmsEntryStorageOperationsGetLatestRevisionParams - ): Promise, UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace GetLatestRevisionByEntryIdUseCase { - type Interface = IGetLatestRevisionByEntryIdBaseUseCase; - type Params = CmsEntryStorageOperationsGetLatestRevisionParams; - type Error = UseCaseError; - type Return = Promise, UseCaseError>>; -} -``` - -### `GetPreviousRevisionByEntryIdBaseUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { GetPreviousRevisionByEntryIdBaseUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `GetPreviousRevisionByEntryIdBaseUseCase.Interface`:** - -Base internal use case - returns entry regardless of deleted state. -This is used internally by the public variation. - -```typescript -interface GetPreviousRevisionByEntryIdBaseUseCase.Interface { - execute( - model: CmsModel, - params: CmsEntryStorageOperationsGetPreviousRevisionParams - ): Promise, UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace GetPreviousRevisionByEntryIdBaseUseCase { - type Interface = IGetPreviousRevisionByEntryIdBaseUseCase; - type Params = CmsEntryStorageOperationsGetPreviousRevisionParams; - type Error = UseCaseError; - type Return = Promise, UseCaseError>>; -} -``` - -### `GetPreviousRevisionByEntryIdUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { GetPreviousRevisionByEntryIdUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `GetPreviousRevisionByEntryIdUseCase.Interface`:** - -Base internal use case - returns entry regardless of deleted state. -This is used internally by the public variation. - -```typescript -interface GetPreviousRevisionByEntryIdUseCase.Interface { - execute( - model: CmsModel, - params: CmsEntryStorageOperationsGetPreviousRevisionParams - ): Promise, UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace GetPreviousRevisionByEntryIdUseCase { - type Interface = IGetPreviousRevisionByEntryIdBaseUseCase; - type Params = CmsEntryStorageOperationsGetPreviousRevisionParams; - type Error = UseCaseError; - type Return = Promise, UseCaseError>>; -} -``` - -### `GetPublishedEntriesByIdsUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { GetPublishedEntriesByIdsUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `GetPublishedEntriesByIdsUseCase.Interface`:** - -GetPublishedEntriesByIds Use Case - Fetches published revisions by entry IDs. -Returns array of published entries (excludes deleted entries via decorator). - -```typescript -interface GetPublishedEntriesByIdsUseCase.Interface { - execute( - model: CmsModel, - ids: string[] - ): Promise[], UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace GetPublishedEntriesByIdsUseCase { - type Interface = IGetPublishedEntriesByIdsUseCase; - type Error = UseCaseError; - type Return = Promise[], UseCaseError>>; -} -``` - -### `GetPublishedRevisionByEntryIdUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { GetPublishedRevisionByEntryIdUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `GetPublishedRevisionByEntryIdUseCase.Interface`:** - -GetPublishedRevisionByEntryId Use Case - -```typescript -interface GetPublishedRevisionByEntryIdUseCase.Interface { - execute( - model: CmsModel, - entryId: string - ): Promise | null, UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace GetPublishedRevisionByEntryIdUseCase { - type Interface = IGetPublishedRevisionByEntryIdUseCase; - type Error = UseCaseError; - type Return = Promise | null, UseCaseError>>; -} -``` - -### `GetRevisionByIdUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { GetRevisionByIdUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `GetRevisionByIdUseCase.Interface`:** - -GetRevisionById Use Case - Fetches a specific entry revision by ID. -Returns the entry or fails with EntryNotFoundError if not found or deleted. - -```typescript -interface GetRevisionByIdUseCase.Interface { - execute( - model: CmsModel, - id: string - ): Promise, UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace GetRevisionByIdUseCase { - type Interface = IGetRevisionByIdUseCase; - type Error = UseCaseError; - type Return = Promise, UseCaseError>>; -} -``` - -### `GetRevisionsByEntryIdUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { GetRevisionsByEntryIdUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `GetRevisionsByEntryIdUseCase.Interface`:** - -GetRevisionsByEntryId Use Case - Fetches all revisions for a given entry ID. -Returns array of entry revisions. - -```typescript -interface GetRevisionsByEntryIdUseCase.Interface { - execute( - model: CmsModel, - entryId: string - ): Promise[], UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace GetRevisionsByEntryIdUseCase { - type Interface = IGetRevisionsByEntryIdUseCase; - type Error = UseCaseError; - type Return = Promise[], UseCaseError>>; -} -``` - -### `GetSingletonEntryUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { GetSingletonEntryUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `GetSingletonEntryUseCase.Interface`:** - -GetSingletonEntry Use Case - -Gets the singleton entry for a model, creating it if it doesn't exist. - -```typescript -interface GetSingletonEntryUseCase.Interface { - execute( - model: CmsModel - ): Promise, UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace GetSingletonEntryUseCase { - type Interface = IGetSingletonEntryUseCase; - type Error = UseCaseError; - type Return = Promise, UseCaseError>>; -} -``` - -### `ListDeletedEntriesUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { ListDeletedEntriesUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `ListDeletedEntriesUseCase.Interface`:** - -ListDeletedEntries Use Case - Lists deleted entries (manage API). - -```typescript -interface ListDeletedEntriesUseCase.Interface { - execute( - model: CmsModel, - params?: CmsEntryListParams - ): Promise, UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace ListDeletedEntriesUseCase { - type Interface = IListDeletedEntriesUseCase; - type Params = CmsEntryListParams; - type Return = Promise, UseCaseError>>; - type Error = UseCaseError; -} -``` - -### `ListEntriesUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { ListEntriesUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `ListEntriesUseCase.Interface`:** - -Base ListEntries Use Case - Internal base use case for listing entries. -Used by specific variants (Latest, Published, Deleted). - -```typescript -interface ListEntriesUseCase.Interface { - execute( - model: CmsModel, - params?: CmsEntryListParams - ): Promise, UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace ListEntriesUseCase { - type Interface = IListEntriesUseCase; - type Params = CmsEntryListParams; - type Return = Promise, UseCaseError>>; - type Error = UseCaseError; -} -``` - -### `ListLatestEntriesUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { ListLatestEntriesUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `ListLatestEntriesUseCase.Interface`:** - -ListLatestEntries Use Case - Lists latest entries (manage API). - -```typescript -interface ListLatestEntriesUseCase.Interface { - execute( - model: CmsModel, - params?: CmsEntryListParams - ): Promise, UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace ListLatestEntriesUseCase { - type Interface = IListLatestEntriesUseCase; - type Params = CmsEntryListParams; - type Return = Promise, UseCaseError>>; - type Error = UseCaseError; -} -``` - -### `ListPublishedEntriesUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { ListPublishedEntriesUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `ListPublishedEntriesUseCase.Interface`:** - -ListPublishedEntries Use Case - Lists published entries (read API). - -```typescript -interface ListPublishedEntriesUseCase.Interface { - execute( - model: CmsModel, - params?: CmsEntryListParams - ): Promise, UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace ListPublishedEntriesUseCase { - type Interface = IListPublishedEntriesUseCase; - type Params = CmsEntryListParams; - type Return = Promise, UseCaseError>>; - type Error = UseCaseError; -} -``` - -### `MoveEntryToBinUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { MoveEntryToBinUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `MoveEntryToBinUseCase.Interface`:** - -MoveEntryToBin Use Case - Soft deletes an entry by marking it as deleted. -This moves the entry to the bin (trash) instead of permanently deleting it. - -```typescript -interface MoveEntryToBinUseCase.Interface { - execute(model: CmsModel, id: string): Promise>; -} -``` - -**Types:** - -```typescript -namespace MoveEntryToBinUseCase { - type Interface = IMoveEntryToBinUseCase; - type Error = UseCaseError; -} -``` - -### `MoveEntryUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { MoveEntryUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `MoveEntryUseCase.Interface`:** - -MoveEntry Use Case - Moves an entry to a different folder. - -```typescript -interface MoveEntryUseCase.Interface { - execute( - model: CmsModel, - id: string, - folderId: string - ): Promise, UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace MoveEntryUseCase { - type Interface = IMoveEntryUseCase; - type Error = UseCaseError; - type Return = Promise, UseCaseError>>; -} -``` - -### `PublishEntryUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { PublishEntryUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `PublishEntryUseCase.Interface`:** - -PublishEntry Use Case - Publishes an entry revision. - -```typescript -interface PublishEntryUseCase.Interface { - execute( - model: CmsModel, - id: string - ): Promise, UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace PublishEntryUseCase { - type Interface = IPublishEntryUseCase; - type Error = UseCaseError; - type Return = Promise, UseCaseError>>; -} -``` - -### `RepublishEntryUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { RepublishEntryUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `RepublishEntryUseCase.Interface`:** - -RepublishEntry Use Case - Republishes an already published entry. -This updates the entry and publishes it again. - -```typescript -interface RepublishEntryUseCase.Interface { - execute( - model: CmsModel, - id: string - ): Promise, UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace RepublishEntryUseCase { - type Interface = IRepublishEntryUseCase; - type Error = UseCaseError; - type Return = Promise, UseCaseError>>; -} -``` - -### `RestoreEntryFromBinUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { RestoreEntryFromBinUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `RestoreEntryFromBinUseCase.Interface`:** - -RestoreEntryFromBin Use Case - Restores a soft-deleted entry from the bin. -This clears the wbyDeleted flag and restores the entry to its original folder. - -```typescript -interface RestoreEntryFromBinUseCase.Interface { - execute( - model: CmsModel, - id: string - ): Promise, UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace RestoreEntryFromBinUseCase { - type Interface = IRestoreEntryFromBinUseCase; - type Error = UseCaseError; - type Return = Promise, UseCaseError>>; -} -``` - -### `UnpublishEntryUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { UnpublishEntryUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `UnpublishEntryUseCase.Interface`:** - -UnpublishEntry Use Case - -```typescript -interface UnpublishEntryUseCase.Interface { - execute( - model: CmsModel, - id: string - ): Promise, UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace UnpublishEntryUseCase { - type Interface = IUnpublishEntryUseCase; - type Error = UseCaseError; - type Return = Promise, UseCaseError>>; -} -``` - -### `UpdateEntryUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { UpdateEntryUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `UpdateEntryUseCase.Interface`:** - -UpdateEntry Use Case - -```typescript -interface UpdateEntryUseCase.Interface { - execute( - model: CmsModel, - id: string, - input: UpdateCmsEntryInput, - metaInput?: GenericRecord, - options?: UpdateCmsEntryOptionsInput - ): Promise, UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace UpdateEntryUseCase { - type Interface = IUpdateEntryUseCase; - type Input = UpdateCmsEntryInput; - type Meta = GenericRecord; - type Options = UpdateCmsEntryOptionsInput; - type Error = UseCaseError; - type Return = Promise, UseCaseError>>; -} -``` - -### `UpdateSingletonEntryUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { UpdateSingletonEntryUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `UpdateSingletonEntryUseCase.Interface`:** - -UpdateSingletonEntry Use Case - -Updates the singleton entry for a model. - -```typescript -interface UpdateSingletonEntryUseCase.Interface { - execute( - model: CmsModel, - data: UpdateCmsEntryInput, - options?: UpdateCmsEntryOptionsInput - ): Promise, UseCaseError>>; -} -``` - -**Types:** - -```typescript -namespace UpdateSingletonEntryUseCase { - type Interface = IUpdateSingletonEntryUseCase; - type Input = UpdateCmsEntryInput; - type Options = UpdateCmsEntryOptionsInput; - type Error = UseCaseError; - type Return = Promise, UseCaseError>>; -} -``` - -### `ValidateEntryUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { ValidateEntryUseCase } from "webiny/api/cms/entry"; -``` - -**Interface `ValidateEntryUseCase.Interface`:** - -```typescript -interface ValidateEntryUseCase.Interface { - execute( - model: CmsModel, - id: string | null | undefined, - input: UpdateCmsEntryInput - ): IValidateEntryUseCaseExecuteResult; -} -``` - -**Types:** - -```typescript -namespace ValidateEntryUseCase { - type Interface = IValidateEntryUseCase; - type Input = UpdateCmsEntryInput; - type Error = UseCaseError; - type Return = IValidateEntryUseCaseExecuteResult; -} -``` - -## Event Handlers - -### `EntryAfterCreateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { EntryAfterCreateEventHandler } from "webiny/api/cms/entry"; -``` - -**Interface `EntryAfterCreateEventHandler.Interface`:** - -```typescript -interface EntryAfterCreateEventHandler.Interface { - handle(event: EntryAfterCreateEvent): Promise; -} -``` - -**Event payload `EntryAfterCreateEventPayload`:** - -```typescript -interface EntryAfterCreateEventPayload { - entry: CmsEntry; - input: CreateCmsEntryInput; - model: CmsModel; -} -``` - -**Types:** - -```typescript -namespace EntryAfterCreateEventHandler { - type Interface = IEventHandler; - type Event = EntryAfterCreateEvent; -} -``` - -### `EntryAfterDeleteEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { EntryAfterDeleteEventHandler } from "webiny/api/cms/entry"; -``` - -**Interface `EntryAfterDeleteEventHandler.Interface`:** - -```typescript -interface EntryAfterDeleteEventHandler.Interface { - handle(event: EntryAfterDeleteEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace EntryAfterDeleteEventHandler { - type Interface = IEventHandler; - type Event = EntryAfterDeleteEvent; -} -``` - -### `EntryAfterDeleteMultipleEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { EntryAfterDeleteMultipleEventHandler } from "webiny/api/cms/entry"; -``` - -**Interface `EntryAfterDeleteMultipleEventHandler.Interface`:** - -```typescript -interface EntryAfterDeleteMultipleEventHandler.Interface { - handle(event: EntryAfterDeleteMultipleEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace EntryAfterDeleteMultipleEventHandler { - type Interface = IEventHandler; - type Event = EntryAfterDeleteMultipleEvent; -} -``` - -### `EntryAfterMoveEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { EntryAfterMoveEventHandler } from "webiny/api/cms/entry"; -``` - -**Interface `EntryAfterMoveEventHandler.Interface`:** - -```typescript -interface EntryAfterMoveEventHandler.Interface { - handle(event: EntryAfterMoveEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace EntryAfterMoveEventHandler { - type Interface = IEventHandler; - type Event = EntryAfterMoveEvent; -} -``` - -### `EntryAfterPublishEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { EntryAfterPublishEventHandler } from "webiny/api/cms/entry"; -``` - -**Interface `EntryAfterPublishEventHandler.Interface`:** - -```typescript -interface EntryAfterPublishEventHandler.Interface { - handle(event: EntryAfterPublishEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace EntryAfterPublishEventHandler { - type Interface = IEventHandler; - type Event = EntryAfterPublishEvent; -} -``` - -### `EntryAfterRepublishEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { EntryAfterRepublishEventHandler } from "webiny/api/cms/entry"; -``` - -**Interface `EntryAfterRepublishEventHandler.Interface`:** - -```typescript -interface EntryAfterRepublishEventHandler.Interface { - handle(event: EntryAfterRepublishEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace EntryAfterRepublishEventHandler { - type Interface = IEventHandler; - type Event = EntryAfterRepublishEvent; -} -``` - -### `EntryAfterRestoreFromBinEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { EntryAfterRestoreFromBinEventHandler } from "webiny/api/cms/entry"; -``` - -**Interface `EntryAfterRestoreFromBinEventHandler.Interface`:** - -```typescript -interface EntryAfterRestoreFromBinEventHandler.Interface { - handle(event: EntryAfterRestoreFromBinEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace EntryAfterRestoreFromBinEventHandler { - type Interface = IEventHandler; - type Event = EntryAfterRestoreFromBinEvent; -} -``` - -### `EntryAfterUnpublishEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { EntryAfterUnpublishEventHandler } from "webiny/api/cms/entry"; -``` - -**Interface `EntryAfterUnpublishEventHandler.Interface`:** - -```typescript -interface EntryAfterUnpublishEventHandler.Interface { - handle(event: EntryAfterUnpublishEvent): Promise; -} -``` - -**Event payload `EntryAfterUnpublishEventPayload`:** - -```typescript -interface EntryAfterUnpublishEventPayload { - entry: CmsEntry; - storageEntry: any; - model: CmsModel; -} -``` - -**Types:** - -```typescript -namespace EntryAfterUnpublishEventHandler { - type Interface = IEventHandler; - type Event = EntryAfterUnpublishEvent; -} -``` - -### `EntryAfterUpdateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { EntryAfterUpdateEventHandler } from "webiny/api/cms/entry"; -``` - -**Interface `EntryAfterUpdateEventHandler.Interface`:** - -```typescript -interface EntryAfterUpdateEventHandler.Interface { - handle(event: EntryAfterUpdateEvent): Promise; -} -``` - -**Event payload `EntryAfterUpdateEventPayload`:** - -```typescript -interface EntryAfterUpdateEventPayload { - entry: CmsEntry; - original: CmsEntry; - input: UpdateCmsEntryInput; - model: CmsModel; -} -``` - -**Types:** - -```typescript -namespace EntryAfterUpdateEventHandler { - type Interface = IEventHandler; - type Event = EntryAfterUpdateEvent; -} -``` - -### `EntryBeforeCreateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { EntryBeforeCreateEventHandler } from "webiny/api/cms/entry"; -``` - -**Interface `EntryBeforeCreateEventHandler.Interface`:** - -```typescript -interface EntryBeforeCreateEventHandler.Interface { - handle(event: EntryBeforeCreateEvent): Promise; -} -``` - -**Event payload `EntryBeforeCreateEventPayload`:** - -```typescript -interface EntryBeforeCreateEventPayload { - entry: CmsEntry; - input: CreateCmsEntryInput; - model: CmsModel; -} -``` - -**Types:** - -```typescript -namespace EntryBeforeCreateEventHandler { - type Interface = IEventHandler; - type Event = EntryBeforeCreateEvent; -} -``` - -### `EntryBeforeDeleteEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { EntryBeforeDeleteEventHandler } from "webiny/api/cms/entry"; -``` - -**Interface `EntryBeforeDeleteEventHandler.Interface`:** - -```typescript -interface EntryBeforeDeleteEventHandler.Interface { - handle(event: EntryBeforeDeleteEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace EntryBeforeDeleteEventHandler { - type Interface = IEventHandler; - type Event = EntryBeforeDeleteEvent; -} -``` - -### `EntryBeforeDeleteMultipleEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { EntryBeforeDeleteMultipleEventHandler } from "webiny/api/cms/entry"; -``` - -**Interface `EntryBeforeDeleteMultipleEventHandler.Interface`:** - -```typescript -interface EntryBeforeDeleteMultipleEventHandler.Interface { - handle(event: EntryBeforeDeleteMultipleEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace EntryBeforeDeleteMultipleEventHandler { - type Interface = IEventHandler; - type Event = EntryBeforeDeleteMultipleEvent; -} -``` - -### `EntryBeforeMoveEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { EntryBeforeMoveEventHandler } from "webiny/api/cms/entry"; -``` - -**Interface `EntryBeforeMoveEventHandler.Interface`:** - -```typescript -interface EntryBeforeMoveEventHandler.Interface { - handle(event: EntryBeforeMoveEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace EntryBeforeMoveEventHandler { - type Interface = IEventHandler; - type Event = EntryBeforeMoveEvent; -} -``` - -### `EntryBeforePublishEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { EntryBeforePublishEventHandler } from "webiny/api/cms/entry"; -``` - -**Interface `EntryBeforePublishEventHandler.Interface`:** - -```typescript -interface EntryBeforePublishEventHandler.Interface { - handle(event: EntryBeforePublishEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace EntryBeforePublishEventHandler { - type Interface = IEventHandler; - type Event = EntryBeforePublishEvent; -} -``` - -### `EntryBeforeRepublishEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { EntryBeforeRepublishEventHandler } from "webiny/api/cms/entry"; -``` - -**Interface `EntryBeforeRepublishEventHandler.Interface`:** - -```typescript -interface EntryBeforeRepublishEventHandler.Interface { - handle(event: EntryBeforeRepublishEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace EntryBeforeRepublishEventHandler { - type Interface = IEventHandler; - type Event = EntryBeforeRepublishEvent; -} -``` - -### `EntryBeforeRestoreFromBinEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { EntryBeforeRestoreFromBinEventHandler } from "webiny/api/cms/entry"; -``` - -**Interface `EntryBeforeRestoreFromBinEventHandler.Interface`:** - -```typescript -interface EntryBeforeRestoreFromBinEventHandler.Interface { - handle(event: EntryBeforeRestoreFromBinEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace EntryBeforeRestoreFromBinEventHandler { - type Interface = IEventHandler; - type Event = EntryBeforeRestoreFromBinEvent; -} -``` - -### `EntryBeforeUnpublishEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { EntryBeforeUnpublishEventHandler } from "webiny/api/cms/entry"; -``` - -**Interface `EntryBeforeUnpublishEventHandler.Interface`:** - -```typescript -interface EntryBeforeUnpublishEventHandler.Interface { - handle(event: EntryBeforeUnpublishEvent): Promise; -} -``` - -**Event payload `EntryBeforeUnpublishEventPayload`:** - -```typescript -interface EntryBeforeUnpublishEventPayload { - entry: CmsEntry; - model: CmsModel; -} -``` - -**Types:** - -```typescript -namespace EntryBeforeUnpublishEventHandler { - type Interface = IEventHandler; - type Event = EntryBeforeUnpublishEvent; -} -``` - -### `EntryBeforeUpdateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { EntryBeforeUpdateEventHandler } from "webiny/api/cms/entry"; -``` - -**Interface `EntryBeforeUpdateEventHandler.Interface`:** - -```typescript -interface EntryBeforeUpdateEventHandler.Interface { - handle(event: EntryBeforeUpdateEvent): Promise; -} -``` - -**Event payload `EntryBeforeUpdateEventPayload`:** - -```typescript -interface EntryBeforeUpdateEventPayload { - entry: CmsEntry; - original: CmsEntry; - input: UpdateCmsEntryInput; - model: CmsModel; -} -``` - -**Types:** - -```typescript -namespace EntryBeforeUpdateEventHandler { - type Interface = IEventHandler; - type Event = EntryBeforeUpdateEvent; -} -``` - -### `EntryRevisionAfterCreateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { EntryRevisionAfterCreateEventHandler } from "webiny/api/cms/entry"; -``` - -**Interface `EntryRevisionAfterCreateEventHandler.Interface`:** - -```typescript -interface EntryRevisionAfterCreateEventHandler.Interface { - handle(event: EntryRevisionAfterCreateEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace EntryRevisionAfterCreateEventHandler { - type Interface = IEventHandler; - type Event = EntryRevisionAfterCreateEvent; -} -``` - -### `EntryRevisionAfterDeleteEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { EntryRevisionAfterDeleteEventHandler } from "webiny/api/cms/entry"; -``` - -**Interface `EntryRevisionAfterDeleteEventHandler.Interface`:** - -```typescript -interface EntryRevisionAfterDeleteEventHandler.Interface { - handle(event: EntryRevisionAfterDeleteEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace EntryRevisionAfterDeleteEventHandler { - type Interface = IEventHandler; - type Event = EntryRevisionAfterDeleteEvent; -} -``` - -### `EntryRevisionBeforeCreateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { EntryRevisionBeforeCreateEventHandler } from "webiny/api/cms/entry"; -``` - -**Interface `EntryRevisionBeforeCreateEventHandler.Interface`:** - -```typescript -interface EntryRevisionBeforeCreateEventHandler.Interface { - handle(event: EntryRevisionBeforeCreateEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace EntryRevisionBeforeCreateEventHandler { - type Interface = IEventHandler; - type Event = EntryRevisionBeforeCreateEvent; -} -``` - -### `EntryRevisionBeforeDeleteEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { EntryRevisionBeforeDeleteEventHandler } from "webiny/api/cms/entry"; -``` - -**Interface `EntryRevisionBeforeDeleteEventHandler.Interface`:** - -```typescript -interface EntryRevisionBeforeDeleteEventHandler.Interface { - handle(event: EntryRevisionBeforeDeleteEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace EntryRevisionBeforeDeleteEventHandler { - type Interface = IEventHandler; - type Event = EntryRevisionBeforeDeleteEvent; -} -``` - -## Services - -### `CmsSortMapper` - -**Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { CmsSortMapper } from "webiny/api/cms/entry"; -``` - -**Interface `CmsSortMapper.Interface`:** - -```typescript -interface CmsSortMapper.Interface { - map(params: ICmsSortMapperParams): CmsEntryListSort | undefined; -} -``` - -**Types:** - -```typescript -namespace CmsSortMapper { - type Interface = ICmsSortMapper; - type Params = ICmsSortMapperParams; -} -``` - -### `CmsWhereMapper` - -**Abstraction** — imported from `webiny/api/cms/entry` - -```typescript -import { CmsWhereMapper } from "webiny/api/cms/entry"; -``` - -**Interface `CmsWhereMapper.Interface`:** - -```typescript -interface CmsWhereMapper.Interface { - map(params: ICmsWhereMapperParams): CmsEntryListWhere | undefined; -} -``` - -**Types:** - -```typescript -namespace CmsWhereMapper { - type Interface = ICmsWhereMapper; - type Params = ICmsWhereMapperParams; -} -``` - -## Types & Classes - -### `CmsEntry` - -**Type** — imported from `webiny/api/cms/entry` - -A content entry definition for and from the database. - -@category Database model -@category CmsEntry - -```typescript -import type { CmsEntry } from "webiny/api/cms/entry"; -``` - -```typescript -export interface CmsEntry { ... } -``` - -### `CmsEntryValues` - -**Type** — imported from `webiny/api/cms/entry` - -A content entry values definition for and from the database. - -@category Database model -@category CmsEntry - -```typescript -import type { CmsEntryValues } from "webiny/api/cms/entry"; -``` - -```typescript -export interface CmsEntryValues { - [key: string]: any; -} -``` - -### `EntryId` - -**Class** — imported from `webiny/api/cms/entry` - -Generate and parse content entry IDs. - -```typescript -import { EntryId } from "webiny/api/cms/entry"; -``` - -```typescript -export class EntryId { - private constructor( - private _id: string, - private _version: number - ); - static create(); - static from(value: string); - toString(); - get id(); - get version(); - incrementVersion(); - decrementVersion(); - setVersion(version: number); -} -``` diff --git a/docs/developer-docs/6.x/reference/api/cms/group.ai.txt b/docs/developer-docs/6.x/reference/api/cms/group.ai.txt deleted file mode 100644 index 88386db3c..000000000 --- a/docs/developer-docs/6.x/reference/api/cms/group.ai.txt +++ /dev/null @@ -1,34 +0,0 @@ -AI Context: Group (reference/api/cms/group.mdx) - -Source of Information: -1. packages/webiny/src/api/cms/group.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentModelGroup/shared/abstractions.ts — originating source -3. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/types/modelGroup.ts — originating source -4. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentModelGroup/CreateGroup/abstractions.ts — originating source -5. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentModelGroup/CreateGroup/events.ts — originating source -6. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentModelGroup/UpdateGroup/abstractions.ts — originating source -7. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentModelGroup/UpdateGroup/events.ts — originating source -8. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentModelGroup/DeleteGroup/abstractions.ts — originating source -9. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentModelGroup/DeleteGroup/events.ts — originating source -10. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentModelGroup/ListGroups/abstractions.ts — originating source -11. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentModelGroup/GetGroup/abstractions.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -ModelGroupFactory, CmsGroup, CmsModelGroup, CreateGroupUseCase, GroupBeforeCreateEventHandler, GroupAfterCreateEventHandler, UpdateGroupUseCase, GroupBeforeUpdateEventHandler, GroupAfterUpdateEventHandler, DeleteGroupUseCase, GroupBeforeDeleteEventHandler, GroupAfterDeleteEventHandler, ListGroupsUseCase, GetGroupUseCase - -Import Path: webiny/api/cms/group - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/cms/group.mdx b/docs/developer-docs/6.x/reference/api/cms/group.mdx deleted file mode 100644 index 6dfdaec1f..000000000 --- a/docs/developer-docs/6.x/reference/api/cms/group.mdx +++ /dev/null @@ -1,476 +0,0 @@ ---- -id: yxbpl2nt -title: Group -description: "CMS group use cases and event handlers" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What use cases are available in `webiny/api/cms/group`? -- Which event handlers can you implement? -- How to use the builder and factory APIs? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/cms/group`. Import any of the items below directly from this path in your Webiny extensions. - -**Use Cases** - - - -**Event Handlers** - - - -**Services** - - - -**Types & Classes** - - - -## Use Cases - -### `CreateGroupUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/group` - -```typescript -import { CreateGroupUseCase } from "webiny/api/cms/group"; -``` - -**Interface `CreateGroupUseCase.Interface`:** - -CreateGroup Use Case - -```typescript -interface CreateGroupUseCase.Interface { - execute(input: CmsGroupCreateInput): Promise>; -} -``` - -**Types:** - -```typescript -namespace CreateGroupUseCase { - type Interface = ICreateGroupUseCase; - type Input = CmsGroupCreateInput; - type Error = UseCaseError; - type Return = Promise>; -} -``` - -### `DeleteGroupUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/group` - -```typescript -import { DeleteGroupUseCase } from "webiny/api/cms/group"; -``` - -**Interface `DeleteGroupUseCase.Interface`:** - -DeleteGroup Use Case - -```typescript -interface DeleteGroupUseCase.Interface { - execute(groupId: string): Promise>; -} -``` - -**Types:** - -```typescript -namespace DeleteGroupUseCase { - type Interface = IDeleteGroupUseCase; - type Error = UseCaseError; - type Return = Promise>; -} -``` - -### `GetGroupUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/group` - -```typescript -import { GetGroupUseCase } from "webiny/api/cms/group"; -``` - -**Interface `GetGroupUseCase.Interface`:** - -GetGroup Use Case - -```typescript -interface GetGroupUseCase.Interface { - execute(groupId: string): Promise>; -} -``` - -**Types:** - -```typescript -namespace GetGroupUseCase { - type Interface = IGetGroupUseCase; - type Error = UseCaseError; - type Return = Promise>; -} -``` - -### `ListGroupsUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/group` - -```typescript -import { ListGroupsUseCase } from "webiny/api/cms/group"; -``` - -**Interface `ListGroupsUseCase.Interface`:** - -ListGroups Use Case - -```typescript -interface ListGroupsUseCase.Interface { - execute(): Promise>; -} -``` - -**Types:** - -```typescript -namespace ListGroupsUseCase { - type Interface = IListGroupsUseCase; - type Error = UseCaseError; - type Return = Promise>; -} -``` - -### `UpdateGroupUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/group` - -```typescript -import { UpdateGroupUseCase } from "webiny/api/cms/group"; -``` - -**Interface `UpdateGroupUseCase.Interface`:** - -UpdateGroup Use Case - -```typescript -interface UpdateGroupUseCase.Interface { - execute(groupId: string, input: CmsGroupUpdateInput): Promise>; -} -``` - -**Types:** - -```typescript -namespace UpdateGroupUseCase { - type Interface = IUpdateGroupUseCase; - type Input = CmsGroupUpdateInput; - type Error = UseCaseError; - type Return = Promise>; -} -``` - -## Event Handlers - -### `GroupAfterCreateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/group` - -```typescript -import { GroupAfterCreateEventHandler } from "webiny/api/cms/group"; -``` - -**Interface `GroupAfterCreateEventHandler.Interface`:** - -```typescript -interface GroupAfterCreateEventHandler.Interface { - handle(event: GroupAfterCreateEvent): Promise; -} -``` - -**Event payload `GroupAfterCreateEventPayload`:** - -```typescript -interface GroupAfterCreateEventPayload { - group: CmsGroup; -} -``` - -**Types:** - -```typescript -namespace GroupAfterCreateEventHandler { - type Interface = IEventHandler; - type Event = GroupAfterCreateEvent; -} -``` - -### `GroupAfterDeleteEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/group` - -```typescript -import { GroupAfterDeleteEventHandler } from "webiny/api/cms/group"; -``` - -**Interface `GroupAfterDeleteEventHandler.Interface`:** - -```typescript -interface GroupAfterDeleteEventHandler.Interface { - handle(event: GroupAfterDeleteEvent): Promise; -} -``` - -**Event payload `GroupAfterDeleteEventPayload`:** - -```typescript -interface GroupAfterDeleteEventPayload { - group: CmsGroup; -} -``` - -**Types:** - -```typescript -namespace GroupAfterDeleteEventHandler { - type Interface = IEventHandler; - type Event = GroupAfterDeleteEvent; -} -``` - -### `GroupAfterUpdateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/group` - -```typescript -import { GroupAfterUpdateEventHandler } from "webiny/api/cms/group"; -``` - -**Interface `GroupAfterUpdateEventHandler.Interface`:** - -```typescript -interface GroupAfterUpdateEventHandler.Interface { - handle(event: GroupAfterUpdateEvent): Promise; -} -``` - -**Event payload `GroupAfterUpdateEventPayload`:** - -```typescript -interface GroupAfterUpdateEventPayload { - original: CmsGroup; - group: CmsGroup; -} -``` - -**Types:** - -```typescript -namespace GroupAfterUpdateEventHandler { - type Interface = IEventHandler; - type Event = GroupAfterUpdateEvent; -} -``` - -### `GroupBeforeCreateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/group` - -```typescript -import { GroupBeforeCreateEventHandler } from "webiny/api/cms/group"; -``` - -**Interface `GroupBeforeCreateEventHandler.Interface`:** - -```typescript -interface GroupBeforeCreateEventHandler.Interface { - handle(event: GroupBeforeCreateEventEvent): Promise; -} -``` - -**Event payload `GroupBeforeCreateEventPayload`:** - -```typescript -interface GroupBeforeCreateEventPayload { - group: CmsGroup; -} -``` - -**Types:** - -```typescript -namespace GroupBeforeCreateEventHandler { - type Interface = IEventHandler; - type Event = GroupBeforeCreateEventEvent; -} -``` - -### `GroupBeforeDeleteEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/group` - -```typescript -import { GroupBeforeDeleteEventHandler } from "webiny/api/cms/group"; -``` - -**Interface `GroupBeforeDeleteEventHandler.Interface`:** - -```typescript -interface GroupBeforeDeleteEventHandler.Interface { - handle(event: GroupBeforeDeleteEvent): Promise; -} -``` - -**Event payload `GroupBeforeDeleteEventPayload`:** - -```typescript -interface GroupBeforeDeleteEventPayload { - group: CmsGroup; -} -``` - -**Types:** - -```typescript -namespace GroupBeforeDeleteEventHandler { - type Interface = IEventHandler; - type Event = GroupBeforeDeleteEvent; -} -``` - -### `GroupBeforeUpdateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/group` - -```typescript -import { GroupBeforeUpdateEventHandler } from "webiny/api/cms/group"; -``` - -**Interface `GroupBeforeUpdateEventHandler.Interface`:** - -```typescript -interface GroupBeforeUpdateEventHandler.Interface { - handle(event: GroupBeforeUpdateEvent): Promise; -} -``` - -**Event payload `GroupBeforeUpdateEventPayload`:** - -```typescript -interface GroupBeforeUpdateEventPayload { - original: CmsGroup; - group: CmsGroup; -} -``` - -**Types:** - -```typescript -namespace GroupBeforeUpdateEventHandler { - type Interface = IEventHandler; - type Event = GroupBeforeUpdateEvent; -} -``` - -## Services - -### `ModelGroupFactory` - -**Abstraction** — imported from `webiny/api/cms/group` - -```typescript -import { ModelGroupFactory } from "webiny/api/cms/group"; -``` - -**Interface `ModelGroupFactory.Interface`:** - -```typescript -interface ModelGroupFactory.Interface { - execute(): Promise; -} -``` - -**Types:** - -```typescript -namespace ModelGroupFactory { - type Interface = IModelGroupFactory; - type Return = Promise; - type Group = IModelGroup; -} -``` - -## Types & Classes - -### `CmsGroup` - -**Type** — imported from `webiny/api/cms/group` - -A representation of content model group in the database. - -@category CmsGroup -@category Database model - -```typescript -import type { CmsGroup } from "webiny/api/cms/group"; -``` - -```typescript -export interface CmsGroup { ... } -``` - -### `CmsModelGroup` - -**Type** — imported from `webiny/api/cms/group` - -@category Database model -@category CmsModel - -```typescript -import type { CmsModelGroup } from "webiny/api/cms/group"; -``` - -```typescript -export interface CmsModelGroup { - /** - * Generated ID of the group - */ - id: string; - /** - * Name of the group - */ - name: string; -} -``` diff --git a/docs/developer-docs/6.x/reference/api/cms/model.ai.txt b/docs/developer-docs/6.x/reference/api/cms/model.ai.txt deleted file mode 100644 index db7f2369e..000000000 --- a/docs/developer-docs/6.x/reference/api/cms/model.ai.txt +++ /dev/null @@ -1,41 +0,0 @@ -AI Context: Model (reference/api/cms/model.mdx) - -Source of Information: -1. packages/webiny/src/api/cms/model.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/modelBuilder/abstractions.ts — originating source -3. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/modelBuilder/models/ModelBuilder.ts — originating source -4. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/modelBuilder/fields/FieldBuilder.ts — originating source -5. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/modelBuilder/fields/abstractions.ts — originating source -6. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/modelBuilder/LayoutBuilder.ts — originating source -7. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/types/model.ts — originating source -8. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/types/modelField.ts — originating source -9. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentModel/CreateModel/abstractions.ts — originating source -10. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentModel/CreateModel/events.ts — originating source -11. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentModel/CreateModelFrom/abstractions.ts — originating source -12. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentModel/CreateModelFrom/events.ts — originating source -13. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentModel/UpdateModel/abstractions.ts — originating source -14. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentModel/UpdateModel/events.ts — originating source -15. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentModel/DeleteModel/abstractions.ts — originating source -16. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentModel/DeleteModel/events.ts — originating source -17. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentModel/GetModel/abstractions.ts — originating source -18. /Users/adrian/dev/wby-next/packages/api-headless-cms/src/features/contentModel/ListModels/abstractions.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -ModelFactory, ModelBuilder, DataFieldBuilder, LayoutFieldBuilder, FieldRendererRegistry, FieldType, LayoutBuilder, CmsModel, CmsModelField, CreateModelUseCase, ModelBeforeCreateEventHandler, ModelAfterCreateEventHandler, CreateModelFromUseCase, ModelBeforeCreateFromEventHandler, ModelAfterCreateFromEventHandler, UpdateModelUseCase, ModelBeforeUpdateEventHandler, ModelAfterUpdateEventHandler, DeleteModelUseCase, ModelBeforeDeleteEventHandler, ModelAfterDeleteEventHandler, GetModelUseCase, ListModelsUseCase - -Import Path: webiny/api/cms/model - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/cms/model.mdx b/docs/developer-docs/6.x/reference/api/cms/model.mdx deleted file mode 100644 index 895d83f50..000000000 --- a/docs/developer-docs/6.x/reference/api/cms/model.mdx +++ /dev/null @@ -1,735 +0,0 @@ ---- -id: yxbpl2nt -title: Model -description: "CMS model builders, factories, use cases and event handlers" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What use cases are available in `webiny/api/cms/model`? -- Which event handlers can you implement? -- How to use the builder and factory APIs? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/cms/model`. Import any of the items below directly from this path in your Webiny extensions. - -**Use Cases** - - - -**Event Handlers** - - - -**Services** - - - -**Types & Classes** - - - -## Use Cases - -### `CreateModelFromUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/model` - -```typescript -import { CreateModelFromUseCase } from "webiny/api/cms/model"; -``` - -**Interface `CreateModelFromUseCase.Interface`:** - -CreateModelFrom Use Case (Clone/Copy Model) - -```typescript -interface CreateModelFromUseCase.Interface { - execute( - modelId: string, - input: CmsModelCreateFromInput - ): Promise>; -} -``` - -**Types:** - -```typescript -namespace CreateModelFromUseCase { - type Interface = ICreateModelFromUseCase; - type Input = CmsModelCreateFromInput; - type Error = UseCaseError; - type Return = Promise>; -} -``` - -### `CreateModelUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/model` - -```typescript -import { CreateModelUseCase } from "webiny/api/cms/model"; -``` - -**Interface `CreateModelUseCase.Interface`:** - -CreateModel Use Case - -```typescript -interface CreateModelUseCase.Interface { - execute(input: CmsModelCreateInput): Promise>; -} -``` - -**Types:** - -```typescript -namespace CreateModelUseCase { - type Interface = ICreateModelUseCase; - type Input = CmsModelCreateInput; - type Error = UseCaseError; - type Return = Promise>; -} -``` - -### `DeleteModelUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/model` - -```typescript -import { DeleteModelUseCase } from "webiny/api/cms/model"; -``` - -**Interface `DeleteModelUseCase.Interface`:** - -DeleteModel Use Case - -```typescript -interface DeleteModelUseCase.Interface { - execute(modelId: string): Promise>; -} -``` - -**Types:** - -```typescript -namespace DeleteModelUseCase { - type Interface = IDeleteModelUseCase; - type Error = UseCaseError; - type Return = Promise>; -} -``` - -### `GetModelUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/model` - -```typescript -import { GetModelUseCase } from "webiny/api/cms/model"; -``` - -**Interface `GetModelUseCase.Interface`:** - -GetModel Use Case - -```typescript -interface GetModelUseCase.Interface { - execute(modelId: string): Promise>; -} -``` - -**Types:** - -```typescript -namespace GetModelUseCase { - type Interface = IGetModelUseCase; - type Error = UseCaseError; - type Return = Promise>; -} -``` - -### `ListModelsUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/model` - -```typescript -import { ListModelsUseCase } from "webiny/api/cms/model"; -``` - -**Interface `ListModelsUseCase.Interface`:** - -ListModels Use Case - -```typescript -interface ListModelsUseCase.Interface { - execute(params?: ICmsModelListParams): Promise>; -} -``` - -**Types:** - -```typescript -namespace ListModelsUseCase { - type Interface = IListModelsUseCase; - type Params = ICmsModelListParams; - type Error = UseCaseError; - type Return = Promise>; -} -``` - -### `UpdateModelUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/model` - -```typescript -import { UpdateModelUseCase } from "webiny/api/cms/model"; -``` - -**Interface `UpdateModelUseCase.Interface`:** - -UpdateModel Use Case - -```typescript -interface UpdateModelUseCase.Interface { - execute(modelId: string, input: CmsModelUpdateInput): Promise>; -} -``` - -**Types:** - -```typescript -namespace UpdateModelUseCase { - type Interface = IUpdateModelUseCase; - type Input = CmsModelUpdateInput; - type Error = UseCaseError; - type Return = Promise>; -} -``` - -## Event Handlers - -### `ModelAfterCreateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/model` - -```typescript -import { ModelAfterCreateEventHandler } from "webiny/api/cms/model"; -``` - -**Interface `ModelAfterCreateEventHandler.Interface`:** - -```typescript -interface ModelAfterCreateEventHandler.Interface { - handle(event: ModelAfterCreateEvent): Promise; -} -``` - -**Event payload `ModelAfterCreateEventPayload`:** - -```typescript -interface ModelAfterCreateEventPayload { - model: CmsModel; -} -``` - -**Types:** - -```typescript -namespace ModelAfterCreateEventHandler { - type Interface = IEventHandler; - type Event = ModelAfterCreateEvent; -} -``` - -### `ModelAfterCreateFromEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/model` - -```typescript -import { ModelAfterCreateFromEventHandler } from "webiny/api/cms/model"; -``` - -**Interface `ModelAfterCreateFromEventHandler.Interface`:** - -```typescript -interface ModelAfterCreateFromEventHandler.Interface { - handle(event: ModelAfterCreateFromEvent): Promise; -} -``` - -**Event payload `ModelAfterCreateFromEventPayload`:** - -```typescript -interface ModelAfterCreateFromEventPayload { - model: CmsModel; - original: CmsModel; -} -``` - -**Types:** - -```typescript -namespace ModelAfterCreateFromEventHandler { - type Interface = IEventHandler; - type Event = ModelAfterCreateFromEvent; -} -``` - -### `ModelAfterDeleteEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/model` - -```typescript -import { ModelAfterDeleteEventHandler } from "webiny/api/cms/model"; -``` - -**Interface `ModelAfterDeleteEventHandler.Interface`:** - -```typescript -interface ModelAfterDeleteEventHandler.Interface { - handle(event: ModelAfterDeleteEvent): Promise; -} -``` - -**Event payload `ModelAfterDeleteEventPayload`:** - -```typescript -interface ModelAfterDeleteEventPayload { - model: CmsModel; -} -``` - -**Types:** - -```typescript -namespace ModelAfterDeleteEventHandler { - type Interface = IEventHandler; - type Event = ModelAfterDeleteEvent; -} -``` - -### `ModelAfterUpdateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/model` - -```typescript -import { ModelAfterUpdateEventHandler } from "webiny/api/cms/model"; -``` - -**Interface `ModelAfterUpdateEventHandler.Interface`:** - -```typescript -interface ModelAfterUpdateEventHandler.Interface { - handle(event: ModelAfterUpdateEvent): Promise; -} -``` - -**Event payload `ModelAfterUpdateEventPayload`:** - -```typescript -interface ModelAfterUpdateEventPayload { - model: CmsModel; - original: CmsModel; -} -``` - -**Types:** - -```typescript -namespace ModelAfterUpdateEventHandler { - type Interface = IEventHandler; - type Event = ModelAfterUpdateEvent; -} -``` - -### `ModelBeforeCreateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/model` - -```typescript -import { ModelBeforeCreateEventHandler } from "webiny/api/cms/model"; -``` - -**Interface `ModelBeforeCreateEventHandler.Interface`:** - -```typescript -interface ModelBeforeCreateEventHandler.Interface { - handle(event: ModelBeforeCreateEvent): Promise; -} -``` - -**Event payload `ModelBeforeCreateEventPayload`:** - -```typescript -interface ModelBeforeCreateEventPayload { - model: CmsModel; - input: CmsModelCreateInput; -} -``` - -**Types:** - -```typescript -namespace ModelBeforeCreateEventHandler { - type Interface = IEventHandler; - type Event = ModelBeforeCreateEvent; -} -``` - -### `ModelBeforeCreateFromEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/model` - -```typescript -import { ModelBeforeCreateFromEventHandler } from "webiny/api/cms/model"; -``` - -**Interface `ModelBeforeCreateFromEventHandler.Interface`:** - -```typescript -interface ModelBeforeCreateFromEventHandler.Interface { - handle(event: ModelBeforeCreateFromEvent): Promise; -} -``` - -**Event payload `ModelBeforeCreateFromEventPayload`:** - -```typescript -interface ModelBeforeCreateFromEventPayload { - model: CmsModel; - original: CmsModel; - input: CmsModelCreateFromInput; -} -``` - -**Types:** - -```typescript -namespace ModelBeforeCreateFromEventHandler { - type Interface = IEventHandler; - type Event = ModelBeforeCreateFromEvent; -} -``` - -### `ModelBeforeDeleteEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/model` - -```typescript -import { ModelBeforeDeleteEventHandler } from "webiny/api/cms/model"; -``` - -**Interface `ModelBeforeDeleteEventHandler.Interface`:** - -```typescript -interface ModelBeforeDeleteEventHandler.Interface { - handle(event: ModelBeforeDeleteEvent): Promise; -} -``` - -**Event payload `ModelBeforeDeleteEventPayload`:** - -```typescript -interface ModelBeforeDeleteEventPayload { - model: CmsModel; -} -``` - -**Types:** - -```typescript -namespace ModelBeforeDeleteEventHandler { - type Interface = IEventHandler; - type Event = ModelBeforeDeleteEvent; -} -``` - -### `ModelBeforeUpdateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/cms/model` - -```typescript -import { ModelBeforeUpdateEventHandler } from "webiny/api/cms/model"; -``` - -**Interface `ModelBeforeUpdateEventHandler.Interface`:** - -```typescript -interface ModelBeforeUpdateEventHandler.Interface { - handle(event: ModelBeforeUpdateEvent): Promise; -} -``` - -**Event payload `ModelBeforeUpdateEventPayload`:** - -```typescript -interface ModelBeforeUpdateEventPayload { - model: CmsModel; - original: CmsModel; - input: CmsModelUpdateInput; -} -``` - -**Types:** - -```typescript -namespace ModelBeforeUpdateEventHandler { - type Interface = IEventHandler; - type Event = ModelBeforeUpdateEvent; -} -``` - -## Services - -### `FieldType` - -**Abstraction** — imported from `webiny/api/cms/model` - -```typescript -import { FieldType } from "webiny/api/cms/model"; -``` - -**Interface `FieldType.Interface`:** - -Field Type Factory - creates a field builder instance - -```typescript -interface FieldType.Interface { - readonly type: string; - create(registry: IFieldBuilderRegistry): BaseFieldBuilder; -} -``` - -| Method | Description | -| ------------------------- | ------------------------------------- | -| `readonly type: string()` | Unique identifier for this field type | -| `create()` | Create a new field builder instance | - -### `ModelFactory` - -**Abstraction** — imported from `webiny/api/cms/model` - -```typescript -import { ModelFactory } from "webiny/api/cms/model"; -``` - -**Interface `ModelFactory.Interface`:** - -```typescript -interface ModelFactory.Interface { - execute(builder: IModelBuilder): Promise; -} -``` - -**Types:** - -```typescript -namespace ModelFactory { - type Interface = IModelFactory; - type Return = Promise; - type Builder = IModelBuilder; - type FieldBuilder = FieldBuilderRegistry.Interface; -} -``` - -## Types & Classes - -### `CmsModel` - -**Type** — imported from `webiny/api/cms/model` - -Base CMS Model. Should not be exported and used outside of this package. - -@category Database model -@category CmsModel - -```typescript -import type { CmsModel } from "webiny/api/cms/model"; -``` - -```typescript -export interface CmsModel { ... } -``` - -### `CmsModelField` - -**Type** — imported from `webiny/api/cms/model` - -A definition for content model field. This type exists on the app side as well. - -@category ModelField -@category Database model - -```typescript -import type { CmsModelField } from "webiny/api/cms/model"; -``` - -```typescript -export interface CmsModelField { ... } -``` - -### `DataFieldBuilder` - -**Class** — imported from `webiny/api/cms/model` - -DataFieldBuilder class for data fields that produce CmsModelField instances. -Provides storageId, list, validation, renderer, and other data-field methods. - -```typescript -import { DataFieldBuilder } from "webiny/api/cms/model"; -``` - -```typescript -export class DataFieldBuilder extends BaseFieldBuilder { - protected override config: FieldBuilderConfig; - public constructor(type: TType, label?: string); - placeholder(text: string): this; - storageId(id: string): this; - defaultValue(value: any): this; - list(): this; - tags(tags: string[]): this; - listMinLength(value: number, message?: string): this; - listMaxLength(value: number, message?: string): this; - protected validation(validation: CmsModelFieldValidation): this; - protected listValidation(validation: CmsModelFieldValidation): this; - predefinedValues(values: CmsModelFieldPredefinedValues["values"]): this; - renderer>( - name: TName, - ...args: undefined extends FieldRendererSettings - ? [settings?: FieldRendererSettings] - : FieldRendererSettings extends undefined - ? [] - : [settings: FieldRendererSettings] - ): this; - settings(settings: Record): this; - build(): DataFieldBuildResult; -} -``` - -### `FieldRendererRegistry` - -**Type** — imported from `webiny/api/cms/model` - -Augmentable renderer registry. -Each entry maps a renderer name to its applicable field type(s) and settings. - -Example: -declare module "@webiny/api-headless-cms/features/modelBuilder/fields/FieldBuilder" { -interface FieldRendererRegistry { -"my-renderer": { fieldType: "text" | "long-text"; settings: { color: string } }; -} -} - -```typescript -import type { FieldRendererRegistry } from "webiny/api/cms/model"; -``` - -```typescript -export interface FieldRendererRegistry { ... } -``` - -### `LayoutBuilder` - -**Class** — imported from `webiny/api/cms/model` - -LayoutBuilder provides a fluent API for modifying field layouts. -Supports adding fields to existing rows and inserting new rows at specific positions. -Callbacks can be queued and executed lazily for efficient composition. - -```typescript -import { LayoutBuilder } from "webiny/api/cms/model"; -``` - -```typescript -export class LayoutBuilder { - private layout: string[][]; - private modifiers: LayoutModifier[] = []; - constructor(existingLayout: string[][] = []); - setLayout(layout: string[][]): this; - addModifier(modifier: LayoutModifier): this; - addField(field: string, position:; - addRow(fields: string[]): this; - insertRow(fields: string[], position:; - getSnapshot():; - build(): string[][]; - private findFieldPosition(field: string):; -} -``` - -### `LayoutFieldBuilder` - -**Class** — imported from `webiny/api/cms/model` - -Slim base class for layout fields (separators, alerts, tabs, etc.). -Layout fields only support label, description, help, and note — no list(), storageId(), etc. - -```typescript -import { LayoutFieldBuilder } from "webiny/api/cms/model"; -``` - -```typescript -export abstract class LayoutFieldBuilder< - TType extends string = string -> extends BaseFieldBuilder {} -``` - -### `ModelBuilder` - -**Class** — imported from `webiny/api/cms/model` - -Entry point builder that allows selecting model type. -Call .private() or .public() to get the appropriate typed builder. - -```typescript -import { ModelBuilder } from "webiny/api/cms/model"; -``` - -```typescript -export class ModelBuilder { - public constructor(private registry: FieldBuilderRegistry.Interface); - public private(input: IModelBuilderPrivateInput): PrivateModelBuilder; - public public(input: IModelBuilderPublicInput): PublicModelBuilder; -} -``` diff --git a/docs/developer-docs/6.x/reference/api/cms/scheduler.ai.txt b/docs/developer-docs/6.x/reference/api/cms/scheduler.ai.txt deleted file mode 100644 index 923f13bef..000000000 --- a/docs/developer-docs/6.x/reference/api/cms/scheduler.ai.txt +++ /dev/null @@ -1,26 +0,0 @@ -AI Context: Scheduler (reference/api/cms/scheduler.mdx) - -Source of Information: -1. packages/webiny/src/api/cms/scheduler.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-headless-cms-scheduler/src/features/SchedulePublishEntryUseCase/abstractions.ts — originating source -3. /Users/adrian/dev/wby-next/packages/api-headless-cms-scheduler/src/features/ScheduleUnpublishEntryUseCase/abstractions.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -SchedulePublishEntryUseCase, ScheduleUnpublishEntryUseCase - -Import Path: webiny/api/cms/scheduler - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/cms/scheduler.mdx b/docs/developer-docs/6.x/reference/api/cms/scheduler.mdx deleted file mode 100644 index 1499b7999..000000000 --- a/docs/developer-docs/6.x/reference/api/cms/scheduler.mdx +++ /dev/null @@ -1,80 +0,0 @@ ---- -id: yxbpl2nt -title: Scheduler -description: "Reference for webiny/api/cms/scheduler" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What use cases are available in `webiny/api/cms/scheduler`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/cms/scheduler`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `SchedulePublishEntryUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/scheduler` - -```typescript -import { SchedulePublishEntryUseCase } from "webiny/api/cms/scheduler"; -``` - -**Interface `SchedulePublishEntryUseCase.Interface`:** - -```typescript -interface SchedulePublishEntryUseCase.Interface { - execute(params: ISchedulePublishEntryUseCaseParams): ISchedulePublishEntryUseCaseResponse; -} -``` - -**Types:** - -```typescript -namespace SchedulePublishEntryUseCase { - type Interface = ISchedulePublishEntryUseCase; - type Error = ScheduleActionError; - type Params = ISchedulePublishEntryUseCaseParams; - type Result = ISchedulePublishEntryUseCaseResponse; -} -``` - -## `ScheduleUnpublishEntryUseCase` - -**Use Case Abstraction** — imported from `webiny/api/cms/scheduler` - -```typescript -import { ScheduleUnpublishEntryUseCase } from "webiny/api/cms/scheduler"; -``` - -**Interface `ScheduleUnpublishEntryUseCase.Interface`:** - -```typescript -interface ScheduleUnpublishEntryUseCase.Interface { - execute(params: IScheduleUnpublishEntryUseCaseParams): IScheduleUnpublishEntryUseCaseResponse; -} -``` - -**Types:** - -```typescript -namespace ScheduleUnpublishEntryUseCase { - type Interface = IScheduleUnpublishEntryUseCase; - type Error = ScheduleActionError; - type Params = IScheduleUnpublishEntryUseCaseParams; - type Result = IScheduleUnpublishEntryUseCaseResponse; -} -``` diff --git a/docs/developer-docs/6.x/reference/api/event-publisher.ai.txt b/docs/developer-docs/6.x/reference/api/event-publisher.ai.txt deleted file mode 100644 index 1263f6647..000000000 --- a/docs/developer-docs/6.x/reference/api/event-publisher.ai.txt +++ /dev/null @@ -1,25 +0,0 @@ -AI Context: Event Publisher (reference/api/event-publisher.mdx) - -Source of Information: -1. packages/webiny/src/api/event-publisher.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-core/src/features/eventPublisher/index.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -DomainEvent, EventPublisher - -Import Path: webiny/api/event-publisher - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/event-publisher.mdx b/docs/developer-docs/6.x/reference/api/event-publisher.mdx deleted file mode 100644 index 62802364e..000000000 --- a/docs/developer-docs/6.x/reference/api/event-publisher.mdx +++ /dev/null @@ -1,58 +0,0 @@ ---- -id: yxbpl2v2 -title: Event Publisher -description: "Reference for webiny/api/event-publisher" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/api/event-publisher`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/event-publisher`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `DomainEvent` - -**Class** — imported from `webiny/api/event-publisher` - -Base class for all domain events. - -```typescript -import { DomainEvent } from "webiny/api/event-publisher"; -``` - -```typescript -export abstract class DomainEvent { - public abstract readonly eventType: string; - public readonly occurredAt: Date; - public readonly payload: TPayload extends void ? undefined : TPayload; - constructor(payload?: never); - abstract getHandlerAbstraction(): Abstraction>; -} -``` - -## `EventPublisher` - -**Constant** — imported from `webiny/api/event-publisher` - -```typescript -import { EventPublisher } from "webiny/api/event-publisher"; -``` - -```typescript -export const EventPublisher = new Abstraction("EventPublisher"); -``` diff --git a/docs/developer-docs/6.x/reference/api/file-manager/file.ai.txt b/docs/developer-docs/6.x/reference/api/file-manager/file.ai.txt deleted file mode 100644 index 5d1674106..000000000 --- a/docs/developer-docs/6.x/reference/api/file-manager/file.ai.txt +++ /dev/null @@ -1,36 +0,0 @@ -AI Context: File (reference/api/file-manager/file.mdx) - -Source of Information: -1. packages/webiny/src/api/file-manager/file.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/file/CreateFile/abstractions.ts — originating source -3. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/file/CreateFile/events.ts — originating source -4. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/file/CreateFilesInBatch/abstractions.ts — originating source -5. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/file/CreateFilesInBatch/events.ts — originating source -6. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/file/UpdateFile/abstractions.ts — originating source -7. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/file/UpdateFile/events.ts — originating source -8. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/file/DeleteFile/abstractions.ts — originating source -9. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/file/DeleteFile/events.ts — originating source -10. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/file/FileUrlGenerator/abstractions.ts — originating source -11. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/file/GetFile/abstractions.ts — originating source -12. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/file/ListFiles/abstractions.ts — originating source -13. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/file/ListTags/abstractions.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -CreateFileRepository, CreateFileUseCase, FileAfterCreateEventHandler, FileBeforeCreateEventHandler, CreateFilesInBatchRepository, CreateFilesInBatchUseCase, FileAfterBatchCreateEventHandler, FileBeforeBatchCreateEventHandler, UpdateFileRepository, UpdateFileUseCase, FileAfterUpdateEventHandler, FileBeforeUpdateEventHandler, DeleteFileRepository, DeleteFileUseCase, FileAfterDeleteEventHandler, FileBeforeDeleteEventHandler, FileUrlGenerator, GetFileRepository, GetFileUseCase, ListFilesRepository, ListFilesUseCase, ListTagsRepository, ListTagsUseCase - -Import Path: webiny/api/file-manager/file - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/file-manager/file.mdx b/docs/developer-docs/6.x/reference/api/file-manager/file.mdx deleted file mode 100644 index 471981bf7..000000000 --- a/docs/developer-docs/6.x/reference/api/file-manager/file.mdx +++ /dev/null @@ -1,743 +0,0 @@ ---- -id: yxbpl2zp -title: File -description: "Reference for webiny/api/file-manager/file" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What use cases are available in `webiny/api/file-manager/file`? -- Which event handlers can you implement? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/file-manager/file`. Import any of the items below directly from this path in your Webiny extensions. - -**Use Cases** - - - -**Event Handlers** - - - -**Services** - - - -## Use Cases - -### `CreateFileRepository` - -**Use Case Abstraction** — imported from `webiny/api/file-manager/file` - -```typescript -import { CreateFileRepository } from "webiny/api/file-manager/file"; -``` - -**Interface `CreateFileRepository.Interface`:** - -CreateFile repository interface - -```typescript -interface CreateFileRepository.Interface { - execute(data: FileInput): Promise>; -} -``` - -**Types:** - -```typescript -namespace CreateFileRepository { - type Interface = ICreateFileRepository; - type Error = RepositoryError; -} -``` - -### `CreateFilesInBatchRepository` - -**Use Case Abstraction** — imported from `webiny/api/file-manager/file` - -```typescript -import { CreateFilesInBatchRepository } from "webiny/api/file-manager/file"; -``` - -**Interface `CreateFilesInBatchRepository.Interface`:** - -CreateFilesInBatch repository interface - -```typescript -interface CreateFilesInBatchRepository.Interface { - createBatch(files: FileInput[]): Promise>; -} -``` - -**Types:** - -```typescript -namespace CreateFilesInBatchRepository { - type Interface = ICreateFilesInBatchRepository; - type Error = RepositoryError; -} -``` - -### `CreateFilesInBatchUseCase` - -**Use Case Abstraction** — imported from `webiny/api/file-manager/file` - -```typescript -import { CreateFilesInBatchUseCase } from "webiny/api/file-manager/file"; -``` - -**Interface `CreateFilesInBatchUseCase.Interface`:** - -CreateFilesInBatch use case interface - -```typescript -interface CreateFilesInBatchUseCase.Interface { - execute(input: CreateFilesInBatchInput): Promise>; -} -``` - -**Types:** - -```typescript -namespace CreateFilesInBatchUseCase { - type Interface = ICreateFilesInBatchUseCase; - type Error = UseCaseError; -} -``` - -### `CreateFileUseCase` - -**Use Case Abstraction** — imported from `webiny/api/file-manager/file` - -```typescript -import { CreateFileUseCase } from "webiny/api/file-manager/file"; -``` - -**Interface `CreateFileUseCase.Interface`:** - -CreateFile use case interface - -```typescript -interface CreateFileUseCase.Interface { - execute( - input: CreateFileInput, - meta?: Record - ): Promise>; -} -``` - -**Types:** - -```typescript -namespace CreateFileUseCase { - type Interface = ICreateFileUseCase; - type Error = UseCaseError; -} -``` - -### `DeleteFileRepository` - -**Use Case Abstraction** — imported from `webiny/api/file-manager/file` - -```typescript -import { DeleteFileRepository } from "webiny/api/file-manager/file"; -``` - -**Interface `DeleteFileRepository.Interface`:** - -DeleteFile repository interface - -```typescript -interface DeleteFileRepository.Interface { - delete(file: File): Promise>; -} -``` - -**Types:** - -```typescript -namespace DeleteFileRepository { - type Interface = IDeleteFileRepository; - type Error = RepositoryError; -} -``` - -### `DeleteFileUseCase` - -**Use Case Abstraction** — imported from `webiny/api/file-manager/file` - -```typescript -import { DeleteFileUseCase } from "webiny/api/file-manager/file"; -``` - -**Interface `DeleteFileUseCase.Interface`:** - -DeleteFile use case interface - -```typescript -interface DeleteFileUseCase.Interface { - execute(id: string): Promise>; -} -``` - -**Types:** - -```typescript -namespace DeleteFileUseCase { - type Interface = IDeleteFileUseCase; - type Error = UseCaseError; -} -``` - -### `GetFileRepository` - -**Use Case Abstraction** — imported from `webiny/api/file-manager/file` - -```typescript -import { GetFileRepository } from "webiny/api/file-manager/file"; -``` - -**Interface `GetFileRepository.Interface`:** - -GetFile repository interface - -```typescript -interface GetFileRepository.Interface { - execute(id: string): Promise>; -} -``` - -**Types:** - -```typescript -namespace GetFileRepository { - type Interface = IGetFileRepository; - type Error = RepositoryError; -} -``` - -### `GetFileUseCase` - -**Use Case Abstraction** — imported from `webiny/api/file-manager/file` - -```typescript -import { GetFileUseCase } from "webiny/api/file-manager/file"; -``` - -**Interface `GetFileUseCase.Interface`:** - -GetFile use case interface - -```typescript -interface GetFileUseCase.Interface { - execute(id: string): Promise>; -} -``` - -**Types:** - -```typescript -namespace GetFileUseCase { - type Interface = IGetFileUseCase; - type Error = UseCaseError; -} -``` - -### `ListFilesRepository` - -**Use Case Abstraction** — imported from `webiny/api/file-manager/file` - -```typescript -import { ListFilesRepository } from "webiny/api/file-manager/file"; -``` - -**Interface `ListFilesRepository.Interface`:** - -ListFiles repository interface - -```typescript -interface ListFilesRepository.Interface { - execute(input: ListFilesInput): Promise>; -} -``` - -**Types:** - -```typescript -namespace ListFilesRepository { - type Interface = IListFilesRepository; - type Error = RepositoryError; -} -``` - -### `ListFilesUseCase` - -**Use Case Abstraction** — imported from `webiny/api/file-manager/file` - -```typescript -import { ListFilesUseCase } from "webiny/api/file-manager/file"; -``` - -**Interface `ListFilesUseCase.Interface`:** - -ListFiles use case interface - -```typescript -interface ListFilesUseCase.Interface { - execute(input: ListFilesInput): Promise>; -} -``` - -**Types:** - -```typescript -namespace ListFilesUseCase { - type Interface = IListFilesUseCase; - type Error = UseCaseError; -} -``` - -### `ListTagsRepository` - -**Use Case Abstraction** — imported from `webiny/api/file-manager/file` - -```typescript -import { ListTagsRepository } from "webiny/api/file-manager/file"; -``` - -**Interface `ListTagsRepository.Interface`:** - -ListTags repository interface - -```typescript -interface ListTagsRepository.Interface { - execute(input: ListTagsInput): Promise>; -} -``` - -**Types:** - -```typescript -namespace ListTagsRepository { - type Interface = IListTagsRepository; - type Error = RepositoryError; -} -``` - -### `ListTagsUseCase` - -**Use Case Abstraction** — imported from `webiny/api/file-manager/file` - -```typescript -import { ListTagsUseCase } from "webiny/api/file-manager/file"; -``` - -**Interface `ListTagsUseCase.Interface`:** - -ListTags use case interface - -```typescript -interface ListTagsUseCase.Interface { - execute(input: ListTagsInput): Promise>; -} -``` - -**Types:** - -```typescript -namespace ListTagsUseCase { - type Interface = IListTagsUseCase; - type Error = UseCaseError; -} -``` - -### `UpdateFileRepository` - -**Use Case Abstraction** — imported from `webiny/api/file-manager/file` - -```typescript -import { UpdateFileRepository } from "webiny/api/file-manager/file"; -``` - -**Interface `UpdateFileRepository.Interface`:** - -UpdateFile repository interface - -```typescript -interface UpdateFileRepository.Interface { - update(file: File): Promise>; -} -``` - -**Types:** - -```typescript -namespace UpdateFileRepository { - type Interface = IUpdateFileRepository; - type Error = RepositoryError; -} -``` - -### `UpdateFileUseCase` - -**Use Case Abstraction** — imported from `webiny/api/file-manager/file` - -```typescript -import { UpdateFileUseCase } from "webiny/api/file-manager/file"; -``` - -**Interface `UpdateFileUseCase.Interface`:** - -UpdateFile use case interface - -```typescript -interface UpdateFileUseCase.Interface { - execute(input: UpdateFileInput): Promise>; -} -``` - -**Types:** - -```typescript -namespace UpdateFileUseCase { - type Interface = IUpdateFileUseCase; - type Error = UseCaseError; -} -``` - -## Event Handlers - -### `FileAfterBatchCreateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/file-manager/file` - -```typescript -import { FileAfterBatchCreateEventHandler } from "webiny/api/file-manager/file"; -``` - -**Interface `FileAfterBatchCreateEventHandler.Interface`:** - -```typescript -interface FileAfterBatchCreateEventHandler.Interface { - handle(event: FileAfterBatchCreateEvent): Promise; -} -``` - -**Event payload `FileAfterBatchCreatePayload`:** - -```typescript -interface FileAfterBatchCreatePayload { - files: File[]; - meta?: Record; -} -``` - -**Types:** - -```typescript -namespace FileAfterBatchCreateEventHandler { - type Interface = IEventHandler; - type Event = FileAfterBatchCreateEvent; -} -``` - -### `FileAfterCreateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/file-manager/file` - -```typescript -import { FileAfterCreateEventHandler } from "webiny/api/file-manager/file"; -``` - -**Interface `FileAfterCreateEventHandler.Interface`:** - -```typescript -interface FileAfterCreateEventHandler.Interface { - handle(event: FileAfterCreateEvent): Promise; -} -``` - -**Event payload `FileAfterCreatePayload`:** - -```typescript -interface FileAfterCreatePayload { - file: File; - meta?: Record; -} -``` - -**Types:** - -```typescript -namespace FileAfterCreateEventHandler { - type Interface = IEventHandler; - type Event = FileAfterCreateEvent; -} -``` - -### `FileAfterDeleteEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/file-manager/file` - -```typescript -import { FileAfterDeleteEventHandler } from "webiny/api/file-manager/file"; -``` - -**Interface `FileAfterDeleteEventHandler.Interface`:** - -```typescript -interface FileAfterDeleteEventHandler.Interface { - handle(event: FileAfterDeleteEvent): Promise; -} -``` - -**Event payload `FileAfterDeletePayload`:** - -```typescript -interface FileAfterDeletePayload { - file: File; -} -``` - -**Types:** - -```typescript -namespace FileAfterDeleteEventHandler { - type Interface = IEventHandler; - type Event = FileAfterDeleteEvent; -} -``` - -### `FileAfterUpdateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/file-manager/file` - -```typescript -import { FileAfterUpdateEventHandler } from "webiny/api/file-manager/file"; -``` - -**Interface `FileAfterUpdateEventHandler.Interface`:** - -```typescript -interface FileAfterUpdateEventHandler.Interface { - handle(event: FileAfterUpdateEvent): Promise; -} -``` - -**Event payload `FileAfterUpdatePayload`:** - -```typescript -interface FileAfterUpdatePayload { - original: File; - file: File; - input: UpdateFileInput; -} -``` - -**Types:** - -```typescript -namespace FileAfterUpdateEventHandler { - type Interface = IEventHandler; - type Event = FileAfterUpdateEvent; -} -``` - -### `FileBeforeBatchCreateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/file-manager/file` - -```typescript -import { FileBeforeBatchCreateEventHandler } from "webiny/api/file-manager/file"; -``` - -**Interface `FileBeforeBatchCreateEventHandler.Interface`:** - -```typescript -interface FileBeforeBatchCreateEventHandler.Interface { - handle(event: FileBeforeBatchCreateEvent): Promise; -} -``` - -**Event payload `FileBeforeBatchCreatePayload`:** - -```typescript -interface FileBeforeBatchCreatePayload { - files: FileInput[]; - meta?: Record; -} -``` - -**Types:** - -```typescript -namespace FileBeforeBatchCreateEventHandler { - type Interface = IEventHandler; - type Event = FileBeforeBatchCreateEvent; -} -``` - -### `FileBeforeCreateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/file-manager/file` - -```typescript -import { FileBeforeCreateEventHandler } from "webiny/api/file-manager/file"; -``` - -**Interface `FileBeforeCreateEventHandler.Interface`:** - -```typescript -interface FileBeforeCreateEventHandler.Interface { - handle(event: FileBeforeCreateEvent): Promise; -} -``` - -**Event payload `FileBeforeCreatePayload`:** - -```typescript -interface FileBeforeCreatePayload { - file: FileInput; - meta?: Record; -} -``` - -**Types:** - -```typescript -namespace FileBeforeCreateEventHandler { - type Interface = IEventHandler; - type Event = FileBeforeCreateEvent; -} -``` - -### `FileBeforeDeleteEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/file-manager/file` - -```typescript -import { FileBeforeDeleteEventHandler } from "webiny/api/file-manager/file"; -``` - -**Interface `FileBeforeDeleteEventHandler.Interface`:** - -```typescript -interface FileBeforeDeleteEventHandler.Interface { - handle(event: FileBeforeDeleteEvent): Promise; -} -``` - -**Event payload `FileBeforeDeletePayload`:** - -```typescript -interface FileBeforeDeletePayload { - file: File; -} -``` - -**Types:** - -```typescript -namespace FileBeforeDeleteEventHandler { - type Interface = IEventHandler; - type Event = FileBeforeDeleteEvent; -} -``` - -### `FileBeforeUpdateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/file-manager/file` - -```typescript -import { FileBeforeUpdateEventHandler } from "webiny/api/file-manager/file"; -``` - -**Interface `FileBeforeUpdateEventHandler.Interface`:** - -```typescript -interface FileBeforeUpdateEventHandler.Interface { - handle(event: FileBeforeUpdateEvent): Promise; -} -``` - -**Event payload `FileBeforeUpdatePayload`:** - -```typescript -interface FileBeforeUpdatePayload { - original: File; - file: File; - input: UpdateFileInput; -} -``` - -**Types:** - -```typescript -namespace FileBeforeUpdateEventHandler { - type Interface = IEventHandler; - type Event = FileBeforeUpdateEvent; -} -``` - -## Services - -### `FileUrlGenerator` - -**Abstraction** — imported from `webiny/api/file-manager/file` - -```typescript -import { FileUrlGenerator } from "webiny/api/file-manager/file"; -``` - -**Interface `FileUrlGenerator.Interface`:** - -```typescript -interface FileUrlGenerator.Interface { - generateUrl(file: File): string; -} -``` - -**Types:** - -```typescript -namespace FileUrlGenerator { - type Interface = IFileUrlGenerator; -} -``` diff --git a/docs/developer-docs/6.x/reference/api/file-manager/permissions.ai.txt b/docs/developer-docs/6.x/reference/api/file-manager/permissions.ai.txt deleted file mode 100644 index 4948e47c5..000000000 --- a/docs/developer-docs/6.x/reference/api/file-manager/permissions.ai.txt +++ /dev/null @@ -1,25 +0,0 @@ -AI Context: Permissions (reference/api/file-manager/permissions.mdx) - -Source of Information: -1. packages/webiny/src/api/file-manager/permissions.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/shared/abstractions.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -FmPermissions - -Import Path: webiny/api/file-manager/permissions - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/file-manager/permissions.mdx b/docs/developer-docs/6.x/reference/api/file-manager/permissions.mdx deleted file mode 100644 index 84583834b..000000000 --- a/docs/developer-docs/6.x/reference/api/file-manager/permissions.mdx +++ /dev/null @@ -1,29 +0,0 @@ ---- -id: yxbpl2zp -title: Permissions -description: "Reference for webiny/api/file-manager/permissions" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/api/file-manager/permissions`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/file-manager/permissions`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `FmPermissions` - -**Export** — imported from `webiny/api/file-manager/permissions` - -```typescript -import { FmPermissions } from "webiny/api/file-manager/permissions"; -``` diff --git a/docs/developer-docs/6.x/reference/api/file-manager/settings.ai.txt b/docs/developer-docs/6.x/reference/api/file-manager/settings.ai.txt deleted file mode 100644 index 3035038db..000000000 --- a/docs/developer-docs/6.x/reference/api/file-manager/settings.ai.txt +++ /dev/null @@ -1,27 +0,0 @@ -AI Context: Settings (reference/api/file-manager/settings.mdx) - -Source of Information: -1. packages/webiny/src/api/file-manager/settings.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/settings/GetSettings/abstractions.ts — originating source -3. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/settings/UpdateSettings/abstractions.ts — originating source -4. /Users/adrian/dev/wby-next/packages/api-file-manager/src/features/settings/UpdateSettings/events.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -GetSettingsUseCase, UpdateSettingsUseCase, SettingsAfterUpdateEventHandler, SettingsBeforeUpdateEventHandler - -Import Path: webiny/api/file-manager/settings - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/file-manager/settings.mdx b/docs/developer-docs/6.x/reference/api/file-manager/settings.mdx deleted file mode 100644 index 637812c0e..000000000 --- a/docs/developer-docs/6.x/reference/api/file-manager/settings.mdx +++ /dev/null @@ -1,166 +0,0 @@ ---- -id: yxbpl2zp -title: Settings -description: "Reference for webiny/api/file-manager/settings" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What use cases are available in `webiny/api/file-manager/settings`? -- Which event handlers can you implement? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/file-manager/settings`. Import any of the items below directly from this path in your Webiny extensions. - -**Use Cases** - - - -**Event Handlers** - - - -## Use Cases - -### `GetSettingsUseCase` - -**Use Case Abstraction** — imported from `webiny/api/file-manager/settings` - -```typescript -import { GetSettingsUseCase } from "webiny/api/file-manager/settings"; -``` - -**Interface `GetSettingsUseCase.Interface`:** - -GetSettings use case - retrieves file manager settings. - -```typescript -interface GetSettingsUseCase.Interface { - execute(): Promise>; -} -``` - -**Types:** - -```typescript -namespace GetSettingsUseCase { - type Interface = IGetSettingsUseCase; - type Error = UseCaseError; -} -``` - -### `UpdateSettingsUseCase` - -**Use Case Abstraction** — imported from `webiny/api/file-manager/settings` - -```typescript -import { UpdateSettingsUseCase } from "webiny/api/file-manager/settings"; -``` - -**Interface `UpdateSettingsUseCase.Interface`:** - -UpdateSettings use case interface - -```typescript -interface UpdateSettingsUseCase.Interface { - execute(input: UpdateSettingsInput): Promise>; -} -``` - -**Types:** - -```typescript -namespace UpdateSettingsUseCase { - type Interface = IUpdateSettingsUseCase; - type Error = UseCaseError; -} -``` - -## Event Handlers - -### `SettingsAfterUpdateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/file-manager/settings` - -```typescript -import { SettingsAfterUpdateEventHandler } from "webiny/api/file-manager/settings"; -``` - -**Interface `SettingsAfterUpdateEventHandler.Interface`:** - -```typescript -interface SettingsAfterUpdateEventHandler.Interface { - handle(event: SettingsAfterUpdateEvent): Promise; -} -``` - -**Event payload `SettingsAfterUpdatePayload`:** - -```typescript -interface SettingsAfterUpdatePayload { - original: FileManagerSettings; - settings: FileManagerSettings; - input: UpdateSettingsInput; -} -``` - -**Types:** - -```typescript -namespace SettingsAfterUpdateEventHandler { - type Interface = IEventHandler; - type Event = SettingsAfterUpdateEvent; -} -``` - -### `SettingsBeforeUpdateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/file-manager/settings` - -```typescript -import { SettingsBeforeUpdateEventHandler } from "webiny/api/file-manager/settings"; -``` - -**Interface `SettingsBeforeUpdateEventHandler.Interface`:** - -```typescript -interface SettingsBeforeUpdateEventHandler.Interface { - handle(event: SettingsBeforeUpdateEvent): Promise; -} -``` - -**Event payload `SettingsBeforeUpdatePayload`:** - -```typescript -interface SettingsBeforeUpdatePayload { - original: FileManagerSettings; - settings: FileManagerSettings; - input: UpdateSettingsInput; -} -``` - -**Types:** - -```typescript -namespace SettingsBeforeUpdateEventHandler { - type Interface = IEventHandler; - type Event = SettingsBeforeUpdateEvent; -} -``` diff --git a/docs/developer-docs/6.x/reference/api/graphql.ai.txt b/docs/developer-docs/6.x/reference/api/graphql.ai.txt deleted file mode 100644 index dcab68d0f..000000000 --- a/docs/developer-docs/6.x/reference/api/graphql.ai.txt +++ /dev/null @@ -1,27 +0,0 @@ -AI Context: GraphQL (reference/api/graphql.mdx) - -Source of Information: -1. packages/webiny/src/api/graphql.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-core/src/graphql/security/NotAuthorizedResponse.ts — originating source -3. /Users/adrian/dev/wby-next/packages/handler-graphql/src/graphql/abstractions.ts — originating source -4. /Users/adrian/dev/wby-next/packages/handler-graphql/src/responses.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -NotAuthorizedResponse, GraphQLSchemaFactory, ErrorResponse, ListResponse, Response, NotFoundResponse, ListErrorResponse - -Import Path: webiny/api/graphql - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/graphql.mdx b/docs/developer-docs/6.x/reference/api/graphql.mdx deleted file mode 100644 index c54dffcdb..000000000 --- a/docs/developer-docs/6.x/reference/api/graphql.mdx +++ /dev/null @@ -1,184 +0,0 @@ ---- -id: yxbpl2dy -title: GraphQL -description: "GraphQL schema factory and response helpers" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- How to use the builder and factory APIs? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/graphql`. Import any of the items below directly from this path in your Webiny extensions. - -**Services** - - - -**Types & Classes** - - - -## Services - -### `GraphQLSchemaFactory` - -**Abstraction** — imported from `webiny/api/graphql` - -```typescript -import { GraphQLSchemaFactory } from "webiny/api/graphql"; -``` - -**Interface `GraphQLSchemaFactory.Interface`:** - -Define custom GraphQL schema extensions. - -```typescript -interface GraphQLSchemaFactory.Interface { - execute(builder: GraphQLSchemaBuilder.Interface): Promise; -} -``` - -**Types:** - -```typescript -namespace GraphQLSchemaFactory { - type Interface = IGraphQLSchemaFactory; - type SchemaBuilder = GraphQLSchemaBuilder.Interface; - type Return = Promise; -} -``` - -**`SchemaBuilder` — `GraphQLSchemaBuilder.Interface`:** - -```typescript -interface GraphQLSchemaBuilder.Interface { - addTypeDefs(typeDefs: TypeDefs): this; - addResolver(config: ResolverConfig): this; - build(): IGraphQLSchema; -} -``` - -## Types & Classes - -### `ErrorResponse` - -**Class** — imported from `webiny/api/graphql` - -GraphQL error response helper. - -```typescript -import { ErrorResponse } from "webiny/api/graphql"; -``` - -```typescript -export class ErrorResponse { - public readonly data: null; - public readonly error:; - constructor(params: ErrorResponseParams); -} -``` - -### `ListErrorResponse` - -**Class** — imported from `webiny/api/graphql` - -GraphQL list error response helper. - -```typescript -import { ListErrorResponse } from "webiny/api/graphql"; -``` - -```typescript -export class ListErrorResponse { - public readonly data: null; - public readonly meta: null; - public readonly error:; - constructor(params: ErrorResponseParams); -} -``` - -### `ListResponse` - -**Class** — imported from `webiny/api/graphql` - -GraphQL list response helper. - -```typescript -import { ListResponse } from "webiny/api/graphql"; -``` - -```typescript -export class ListResponse { - public readonly data: Array; - public readonly meta: M; - public readonly error: null; - constructor(data: Array, meta?: M); -} -``` - -### `NotAuthorizedResponse` - -**Class** — imported from `webiny/api/graphql` - -GraphQL not-authorized response helper. - -```typescript -import { NotAuthorizedResponse } from "webiny/api/graphql"; -``` - -```typescript -export class NotAuthorizedResponse extends ErrorResponse { - constructor(; -} -``` - -### `NotFoundResponse` - -**Class** — imported from `webiny/api/graphql` - -GraphQL not-found response helper. - -```typescript -import { NotFoundResponse } from "webiny/api/graphql"; -``` - -```typescript -export class NotFoundResponse extends ErrorResponse { - constructor(message: string); -} -``` - -### `Response` - -**Class** — imported from `webiny/api/graphql` - -GraphQL response helper. - -```typescript -import { Response } from "webiny/api/graphql"; -``` - -```typescript -export class Response { - public readonly data: T; - public readonly error: null; - constructor(data: T); -} -``` diff --git a/docs/developer-docs/6.x/reference/api/key-value-store.ai.txt b/docs/developer-docs/6.x/reference/api/key-value-store.ai.txt deleted file mode 100644 index 30e31a928..000000000 --- a/docs/developer-docs/6.x/reference/api/key-value-store.ai.txt +++ /dev/null @@ -1,25 +0,0 @@ -AI Context: Key Value Store (reference/api/key-value-store.mdx) - -Source of Information: -1. packages/webiny/src/api/key-value-store.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-core/src/features/keyValueStore/index.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -GlobalKeyValueStore, KeyValueStore - -Import Path: webiny/api/key-value-store - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/key-value-store.mdx b/docs/developer-docs/6.x/reference/api/key-value-store.mdx deleted file mode 100644 index 177f40768..000000000 --- a/docs/developer-docs/6.x/reference/api/key-value-store.mdx +++ /dev/null @@ -1,92 +0,0 @@ ---- -id: yxbpl2tl -title: Key Value Store -description: "Reference for webiny/api/key-value-store" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/api/key-value-store`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/key-value-store`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `GlobalKeyValueStore` - -**Abstraction** — imported from `webiny/api/key-value-store` - -```typescript -import { GlobalKeyValueStore } from "webiny/api/key-value-store"; -``` - -**Interface `GlobalKeyValueStore.Interface`:** - -```typescript -interface GlobalKeyValueStore.Interface { - get( - key: string, - options?: IGlobalKeyValueStoreOptions - ): Promise>; - set( - key: string, - value: any, - options?: IGlobalKeyValueStoreOptions - ): Promise>; - delete( - key: string, - options?: IGlobalKeyValueStoreOptions - ): Promise>; -} -``` - -**Types:** - -```typescript -namespace GlobalKeyValueStore { - type Interface = IGlobalKeyValueStore; - type KeyValueRecord = IKeyValueRecord; - type Error = KeyValueStoreRepository.Error; -} -``` - -## `KeyValueStore` - -**Abstraction** — imported from `webiny/api/key-value-store` - -```typescript -import { KeyValueStore } from "webiny/api/key-value-store"; -``` - -**Interface `KeyValueStore.Interface`:** - -```typescript -interface KeyValueStore.Interface { - get(key: string): Promise>; - set(key: string, value: any): Promise>; - delete(key: string): Promise>; -} -``` - -**Types:** - -```typescript -namespace KeyValueStore { - type Interface = IKeyValueStore; - type KeyValueRecord = IKeyValueRecord; - type Error = KeyValueStoreRepository.Error; -} -``` diff --git a/docs/developer-docs/6.x/reference/api/logger.ai.txt b/docs/developer-docs/6.x/reference/api/logger.ai.txt deleted file mode 100644 index 0871bb9bc..000000000 --- a/docs/developer-docs/6.x/reference/api/logger.ai.txt +++ /dev/null @@ -1,25 +0,0 @@ -AI Context: Logger (reference/api/logger.mdx) - -Source of Information: -1. packages/webiny/src/api/logger.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-core/src/features/logger/index.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -Logger - -Import Path: webiny/api/logger - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/logger.mdx b/docs/developer-docs/6.x/reference/api/logger.mdx deleted file mode 100644 index 175e6bd3e..000000000 --- a/docs/developer-docs/6.x/reference/api/logger.mdx +++ /dev/null @@ -1,51 +0,0 @@ ---- -id: yxbpl2xv -title: Logger -description: "Logger abstraction for server-side logging" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/api/logger`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/logger`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `Logger` - -**Abstraction** — imported from `webiny/api/logger` - -```typescript -import { Logger } from "webiny/api/logger"; -``` - -**Interface `Logger.Interface`:** - -```typescript -interface Logger.Interface { - trace(objOrMsg: object | string, ...args: any[]): void; - debug(objOrMsg: object | string, ...args: any[]): void; - info(objOrMsg: object | string, ...args: any[]): void; - warn(objOrMsg: object | string, ...args: any[]): void; - error(objOrMsg: object | string, ...args: any[]): void; - fatal(objOrMsg: object | string, ...args: any[]): void; - log(objOrMsg: object | string, ...args: any[]): void; -} -``` - -**Types:** - -```typescript -namespace Logger { - type Interface = ILogger; -} -``` diff --git a/docs/developer-docs/6.x/reference/api/scheduler.ai.txt b/docs/developer-docs/6.x/reference/api/scheduler.ai.txt deleted file mode 100644 index a984bbc28..000000000 --- a/docs/developer-docs/6.x/reference/api/scheduler.ai.txt +++ /dev/null @@ -1,32 +0,0 @@ -AI Context: Scheduler (reference/api/scheduler.mdx) - -Source of Information: -1. packages/webiny/src/api/scheduler.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-scheduler/src/features/ScheduleAction/index.ts — originating source -3. /Users/adrian/dev/wby-next/packages/api-scheduler/src/features/GetScheduledAction/index.ts — originating source -4. /Users/adrian/dev/wby-next/packages/api-scheduler/src/features/ListScheduledActions/index.ts — originating source -5. /Users/adrian/dev/wby-next/packages/api-scheduler/src/features/CancelScheduledAction/index.ts — originating source -6. /Users/adrian/dev/wby-next/packages/api-scheduler/src/features/ExecuteScheduledAction/index.ts — originating source -7. /Users/adrian/dev/wby-next/packages/api-scheduler/src/features/NamespaceHandler/index.ts — originating source -8. /Users/adrian/dev/wby-next/packages/api-scheduler/src/shared/abstractions.ts — originating source -9. /Users/adrian/dev/wby-next/packages/api-scheduler/src/constants.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -ScheduleActionUseCase, ScheduleActionError, GetScheduledActionUseCase, ListScheduledActionsUseCase, CancelScheduledActionUseCase, ExecuteScheduledActionUseCase, NamespaceHandler, IScheduledAction, IScheduledActionEntry, ScheduledActionType, SchedulerService, ScheduledActionModel, ScheduledActionHandler, ScheduledActionTypePublish, ScheduledActionTypeUnpublish - -Import Path: webiny/api/scheduler - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/scheduler.mdx b/docs/developer-docs/6.x/reference/api/scheduler.mdx deleted file mode 100644 index 7b24f2200..000000000 --- a/docs/developer-docs/6.x/reference/api/scheduler.mdx +++ /dev/null @@ -1,399 +0,0 @@ ---- -id: yxbpl3nj -title: Scheduler -description: "Reference for webiny/api/scheduler" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What use cases are available in `webiny/api/scheduler`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/scheduler`. Import any of the items below directly from this path in your Webiny extensions. - -**Use Cases** - - - -**Event Handlers** - - - -**Services** - - - -**Types & Classes** - - - -## Use Cases - -### `CancelScheduledActionUseCase` - -**Use Case Abstraction** — imported from `webiny/api/scheduler` - -```typescript -import { CancelScheduledActionUseCase } from "webiny/api/scheduler"; -``` - -**Interface `CancelScheduledActionUseCase.Interface`:** - -```typescript -interface CancelScheduledActionUseCase.Interface { - execute( - params: ICancelScheduledActionUseCaseParams - ): Promise>; -} -``` - -**Types:** - -```typescript -namespace CancelScheduledActionUseCase { - type Interface = ICancelScheduledActionUseCase; - type Error = CancelScheduledActionError; - type Params = ICancelScheduledActionUseCaseParams; -} -``` - -### `ExecuteScheduledActionUseCase` - -**Use Case Abstraction** — imported from `webiny/api/scheduler` - -```typescript -import { ExecuteScheduledActionUseCase } from "webiny/api/scheduler"; -``` - -**Interface `ExecuteScheduledActionUseCase.Interface`:** - -```typescript -interface ExecuteScheduledActionUseCase.Interface { - execute( - params: IExecuteScheduledActionUseCaseParams - ): Promise>; -} -``` - -**Types:** - -```typescript -namespace ExecuteScheduledActionUseCase { - type Interface = IExecuteScheduledActionUseCase; - type Error = ExecuteScheduledActionError; - type Params = IExecuteScheduledActionUseCaseParams; -} -``` - -### `GetScheduledActionUseCase` - -**Use Case Abstraction** — imported from `webiny/api/scheduler` - -```typescript -import { GetScheduledActionUseCase } from "webiny/api/scheduler"; -``` - -**Interface `GetScheduledActionUseCase.Interface`:** - -```typescript -interface GetScheduledActionUseCase.Interface { - execute( - params: IGetScheduledActionUseCaseParams - ): Promise, GetScheduledActionError>>; -} -``` - -**Types:** - -```typescript -namespace GetScheduledActionUseCase { - type Interface = IGetScheduledActionUseCase; - type Error = GetScheduledActionError; - type Params = IGetScheduledActionUseCaseParams; -} -``` - -### `ListScheduledActionsUseCase` - -**Use Case Abstraction** — imported from `webiny/api/scheduler` - -```typescript -import { ListScheduledActionsUseCase } from "webiny/api/scheduler"; -``` - -**Interface `ListScheduledActionsUseCase.Interface`:** - -```typescript -interface ListScheduledActionsUseCase.Interface { - execute( - params: IListScheduledActionsParams - ): Promise, ListScheduledActionsError>>; -} -``` - -**Types:** - -```typescript -namespace ListScheduledActionsUseCase { - type Interface = IListScheduledActionsUseCase; - type Error = ListScheduledActionsError; - type Params = IListScheduledActionsParams; - type Where = IListScheduledActionsWhere; - type Sort = CmsEntryListSort; - type Meta = IListScheduledActionsMeta; - type Response = IListScheduledActionsResponse; -} -``` - -**`Meta` — `CmsEntryMeta`:** - -Meta information for GraphQL output. - -@category CmsEntry -@category GraphQL output - -| Field | Type | Required | Description | -| -------------- | ---------------- | -------- | ----------- | -| `cursor` | `string \| null` | yes | — | -| `hasMoreItems` | `boolean` | yes | — | -| `totalCount` | `number` | yes | — | - -### `ScheduleActionUseCase` - -**Use Case Abstraction** — imported from `webiny/api/scheduler` - -```typescript -import { ScheduleActionUseCase } from "webiny/api/scheduler"; -``` - -**Interface `ScheduleActionUseCase.Interface`:** - -```typescript -interface ScheduleActionUseCase.Interface { - execute( - params: IScheduleActionParams - ): Promise, ScheduleActionError>>; -} -``` - -**Types:** - -```typescript -namespace ScheduleActionUseCase { - type Interface = IScheduleActionUseCase; - type Params = IScheduleActionParams; - type Error = ScheduleActionError; -} -``` - -## Event Handlers - -### `NamespaceHandler` - -**Event Handler Abstraction** — imported from `webiny/api/scheduler` - -```typescript -import { NamespaceHandler } from "webiny/api/scheduler"; -``` - -**Interface `NamespaceHandler.Interface`:** - -```typescript -interface NamespaceHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace NamespaceHandler { - type Interface = INamespaceHandler; - type Response = Promise, NamespaceHandlerError>>; - type Params = INamespaceHandlerParams; -} -``` - -### `ScheduledActionHandler` - -**Event Handler Abstraction** — imported from `webiny/api/scheduler` - -```typescript -import { ScheduledActionHandler } from "webiny/api/scheduler"; -``` - -**Interface `ScheduledActionHandler.Interface`:** - -```typescript -interface ScheduledActionHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace ScheduledActionHandler { - type Interface = IScheduledActionHandler; -} -``` - -## Services - -### `ScheduledActionModel` - -**Abstraction** — imported from `webiny/api/scheduler` - -```typescript -import { ScheduledActionModel } from "webiny/api/scheduler"; -``` - -**Types:** - -```typescript -namespace ScheduledActionModel { - type Interface = CmsModel; -} -``` - -### `SchedulerService` - -**Abstraction** — imported from `webiny/api/scheduler` - -```typescript -import { SchedulerService } from "webiny/api/scheduler"; -``` - -**Interface `SchedulerService.Interface`:** - -```typescript -interface SchedulerService.Interface { - create(params: ISchedulerServiceCreateParams): Promise; - update(params: ISchedulerServiceUpdateParams): Promise; - delete(id: string): Promise; - exists(id: string): Promise; -} -``` - -**Types:** - -```typescript -namespace SchedulerService { - type Interface = ISchedulerService; -} -``` - -## Types & Classes - -### `IScheduledAction` - -**Type** — imported from `webiny/api/scheduler` - -```typescript -import type { IScheduledAction } from "webiny/api/scheduler"; -``` - -```typescript -export interface IScheduledAction - extends Omit, "scheduledFor"> { - id: string; - scheduledFor: Date; -} -``` - -### `IScheduledActionEntry` - -**Type** — imported from `webiny/api/scheduler` - -```typescript -import type { IScheduledActionEntry } from "webiny/api/scheduler"; -``` - -```typescript -export interface IScheduledActionEntry - extends CmsEntry> {} -``` - -### `ScheduleActionError` - -**Type** — imported from `webiny/api/scheduler` - -```typescript -import type { ScheduleActionError } from "webiny/api/scheduler"; -``` - -```typescript -export type ScheduleActionError = IScheduleActionErrors[keyof IScheduleActionErrors]; -``` - -### `ScheduledActionType` - -**Type** — imported from `webiny/api/scheduler` - -```typescript -import type { ScheduledActionType } from "webiny/api/scheduler"; -``` - -```typescript -export type ScheduledActionType = - | typeof SCHEDULED_ACTION_PUBLISH - | typeof SCHEDULED_ACTION_UNPUBLISH; -``` - -### `ScheduledActionTypePublish` - -**Constant** — imported from `webiny/api/scheduler` - -```typescript -import { ScheduledActionTypePublish } from "webiny/api/scheduler"; -``` - -```typescript -export const SCHEDULED_ACTION_PUBLISH = "publish" as const; -``` - -### `ScheduledActionTypeUnpublish` - -**Constant** — imported from `webiny/api/scheduler` - -```typescript -import { ScheduledActionTypeUnpublish } from "webiny/api/scheduler"; -``` - -```typescript -export const SCHEDULED_ACTION_UNPUBLISH = "unpublish" as const; -``` diff --git a/docs/developer-docs/6.x/reference/api/security.ai.txt b/docs/developer-docs/6.x/reference/api/security.ai.txt deleted file mode 100644 index fef552846..000000000 --- a/docs/developer-docs/6.x/reference/api/security.ai.txt +++ /dev/null @@ -1,32 +0,0 @@ -AI Context: Security (reference/api/security.mdx) - -Source of Information: -1. packages/webiny/src/api/security.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-core/src/features/security/IdentityContext/index.ts — originating source -3. /Users/adrian/dev/wby-next/packages/api-core/src/features/security/apiKeys/shared/abstractions.ts — originating source -4. /Users/adrian/dev/wby-next/packages/api-core/src/features/security/roles/shared/abstractions.ts — originating source -5. /Users/adrian/dev/wby-next/packages/api-core/src/features/security/teams/shared/abstractions.ts — originating source -6. /Users/adrian/dev/wby-next/packages/api-core/src/domain/security/ApiToken.ts — originating source -7. /Users/adrian/dev/wby-next/packages/api-core/src/idp/index.ts — originating source -8. /Users/adrian/dev/wby-next/packages/api-core/src/features/security/authentication/Authenticator/abstractions.ts — originating source -9. /Users/adrian/dev/wby-next/packages/api-core/src/features/security/authorization/Authorizer/index.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -IdentityContext, ApiKeyFactory, RoleFactory, TeamFactory, ApiToken, IdentityProvider, OidcIdentityProvider, JwtIdentityProvider, Authenticator, Authorizer - -Import Path: webiny/api/security - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/security.mdx b/docs/developer-docs/6.x/reference/api/security.mdx deleted file mode 100644 index 38362fc57..000000000 --- a/docs/developer-docs/6.x/reference/api/security.mdx +++ /dev/null @@ -1,308 +0,0 @@ ---- -id: yxbpl3nl -title: Security -description: "Security primitives: Identity, Authenticator, Authorizer" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- How to use the builder and factory APIs? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/security`. Import any of the items below directly from this path in your Webiny extensions. - -**Services** - - - -**Types & Classes** - - - -## Services - -### `ApiKeyFactory` - -**Abstraction** — imported from `webiny/api/security` - -```typescript -import { ApiKeyFactory } from "webiny/api/security"; -``` - -**Interface `ApiKeyFactory.Interface`:** - -```typescript -interface ApiKeyFactory.Interface { - execute(): Promise; -} -``` - -**Types:** - -```typescript -namespace ApiKeyFactory { - type Interface = IApiKeyFactory; - type Return = Promise; - type ApiKey = CodeApiKey; -} -``` - -### `Authenticator` - -**Abstraction** — imported from `webiny/api/security` - -```typescript -import { Authenticator } from "webiny/api/security"; -``` - -**Interface `Authenticator.Interface`:** - -```typescript -interface Authenticator.Interface { - authenticate(token: string): Promise; -} -``` - -**Types:** - -```typescript -namespace Authenticator { - type Interface = IAuthenticator; -} -``` - -### `Authorizer` - -**Abstraction** — imported from `webiny/api/security` - -```typescript -import { Authorizer } from "webiny/api/security"; -``` - -**Interface `Authorizer.Interface`:** - -```typescript -interface Authorizer.Interface { - authorize(identity: Identity): Promise; -} -``` - -**Types:** - -```typescript -namespace Authorizer { - type Interface = IAuthorizer; -} -``` - -### `IdentityContext` - -**Abstraction** — imported from `webiny/api/security` - -```typescript -import { IdentityContext } from "webiny/api/security"; -``` - -**Interface `IdentityContext.Interface`:** - -```typescript -interface IdentityContext.Interface { - getIdentity(): Identity; - setIdentity(identity: Identity | undefined): void; - withIdentity(identity: Identity | undefined, cb: () => Promise): Promise; - getPermission( - name: string - ): Promise; - getPermissions( - name: string - ): Promise; - listPermissions(): Promise; - hasFullAccess(): Promise; - withoutAuthorization(cb: () => Promise): Promise; - isAuthorizationEnabled(): boolean; -} -``` - -**Types:** - -```typescript -namespace IdentityContext { - type Interface = IIdentityContext; -} -``` - -### `IdentityProvider` - -**Abstraction** — imported from `webiny/api/security` - -```typescript -import { IdentityProvider } from "webiny/api/security"; -``` - -**Interface `IdentityProvider.Interface`:** - -```typescript -interface IdentityProvider.Interface { - isApplicable(token: string): boolean; - getIdentity(token: string): Promise; -} -``` - -**Types:** - -```typescript -namespace IdentityProvider { - type Interface = IIdentityProvider; - type IdentityData = IProviderIdentityData; - type JwtPayload = IJwtPayload; -} -``` - -### `JwtIdentityProvider` - -**Abstraction** — imported from `webiny/api/security` - -```typescript -import { JwtIdentityProvider } from "webiny/api/security"; -``` - -**Interface `JwtIdentityProvider.Interface`:** - -```typescript -interface JwtIdentityProvider.Interface { - isApplicable(token: IJwtPayload): boolean; - getIdentity(token: string, jwt: IJwt): Promise; -} -``` - -**Types:** - -```typescript -namespace JwtIdentityProvider { - type Interface = IJwtIdentityProvider; - type Jwt = IJwt; - type JwtPayload = IJwtPayload; - type JwtHeader = IJwtHeader; - type IdentityData = IProviderIdentityData; -} -``` - -### `OidcIdentityProvider` - -**Abstraction** — imported from `webiny/api/security` - -```typescript -import { OidcIdentityProvider } from "webiny/api/security"; -``` - -**Interface `OidcIdentityProvider.Interface`:** - -```typescript -interface OidcIdentityProvider.Interface { - issuer: string; - clientId: string; - isApplicable(token: IJwtPayload): boolean; - getIdentity(jwt: IJwtPayload): Promise; - verifyToken?(token: string): Promise; - verifyTokenClaims?(token: IJwtPayload): Promise; -} -``` - -**Types:** - -```typescript -namespace OidcIdentityProvider { - type Interface = IOidcIdentityProvider; - type JwtPayload = IJwtPayload; - type IdentityData = IProviderIdentityData; -} -``` - -### `RoleFactory` - -**Abstraction** — imported from `webiny/api/security` - -```typescript -import { RoleFactory } from "webiny/api/security"; -``` - -**Interface `RoleFactory.Interface`:** - -```typescript -interface RoleFactory.Interface { - execute(): Promise; -} -``` - -**Types:** - -```typescript -namespace RoleFactory { - type Interface = IRoleFactory; - type Return = Promise; - type Role = CodeRole; -} -``` - -### `TeamFactory` - -**Abstraction** — imported from `webiny/api/security` - -```typescript -import { TeamFactory } from "webiny/api/security"; -``` - -**Interface `TeamFactory.Interface`:** - -```typescript -interface TeamFactory.Interface { - execute(): Promise; -} -``` - -**Types:** - -```typescript -namespace TeamFactory { - type Interface = ITeamFactory; - type Return = Promise; - type Team = CodeTeam; -} -``` - -## Types & Classes - -### `ApiToken` - -**Class** — imported from `webiny/api/security` - -Represents an API token identity. - -```typescript -import { ApiToken } from "webiny/api/security"; -``` - -```typescript -export class ApiToken { - static validate(token: string): `wat_$; -} -``` diff --git a/docs/developer-docs/6.x/reference/api/security/api-key.ai.txt b/docs/developer-docs/6.x/reference/api/security/api-key.ai.txt deleted file mode 100644 index af354ac8e..000000000 --- a/docs/developer-docs/6.x/reference/api/security/api-key.ai.txt +++ /dev/null @@ -1,31 +0,0 @@ -AI Context: Api Key (reference/api/security/api-key.mdx) - -Source of Information: -1. packages/webiny/src/api/security/api-key.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-core/src/features/security/apiKeys/CreateApiKey/index.ts — originating source -3. /Users/adrian/dev/wby-next/packages/api-core/src/features/security/apiKeys/DeleteApiKey/index.ts — originating source -4. /Users/adrian/dev/wby-next/packages/api-core/src/features/security/apiKeys/GetApiKey/index.ts — originating source -5. /Users/adrian/dev/wby-next/packages/api-core/src/features/security/apiKeys/GetApiKeyByToken/index.ts — originating source -6. /Users/adrian/dev/wby-next/packages/api-core/src/features/security/apiKeys/ListApiKeys/index.ts — originating source -7. /Users/adrian/dev/wby-next/packages/api-core/src/features/security/apiKeys/UpdateApiKey/index.ts — originating source -8. /Users/adrian/dev/wby-next/packages/api-core/src/features/security/apiKeys/shared/abstractions.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -ApiKeyAfterCreateEventHandler, ApiKeyBeforeCreateEventHandler, CreateApiKeyUseCase, ApiKeyAfterDeleteEventHandler, ApiKeyBeforeDeleteEventHandler, DeleteApiKeyUseCase, GetApiKeyUseCase, GetApiKeyByTokenUseCase, ListApiKeysUseCase, ApiKeyAfterUpdateEventHandler, ApiKeyBeforeUpdateEventHandler, UpdateApiKeyUseCase, ApiKeyFactory - -Import Path: webiny/api/security/api-key - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/security/api-key.mdx b/docs/developer-docs/6.x/reference/api/security/api-key.mdx deleted file mode 100644 index 7b94bae07..000000000 --- a/docs/developer-docs/6.x/reference/api/security/api-key.mdx +++ /dev/null @@ -1,383 +0,0 @@ ---- -id: yxbpl3nl -title: Api Key -description: "Reference for webiny/api/security/api-key" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What use cases are available in `webiny/api/security/api-key`? -- Which event handlers can you implement? -- How to use the builder and factory APIs? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/security/api-key`. Import any of the items below directly from this path in your Webiny extensions. - -**Use Cases** - - - -**Event Handlers** - - - -**Services** - - - -## Use Cases - -### `CreateApiKeyUseCase` - -**Use Case Abstraction** — imported from `webiny/api/security/api-key` - -```typescript -import { CreateApiKeyUseCase } from "webiny/api/security/api-key"; -``` - -**Interface `CreateApiKeyUseCase.Interface`:** - -```typescript -interface CreateApiKeyUseCase.Interface { - execute(input: CreateApiKeyInput): Promise>; -} -``` - -**Types:** - -```typescript -namespace CreateApiKeyUseCase { - type Interface = ICreateApiKey; - type Error = CreateApiKeyError; -} -``` - -### `DeleteApiKeyUseCase` - -**Use Case Abstraction** — imported from `webiny/api/security/api-key` - -```typescript -import { DeleteApiKeyUseCase } from "webiny/api/security/api-key"; -``` - -**Interface `DeleteApiKeyUseCase.Interface`:** - -```typescript -interface DeleteApiKeyUseCase.Interface { - execute(id: string): Promise>; -} -``` - -**Types:** - -```typescript -namespace DeleteApiKeyUseCase { - type Interface = IDeleteApiKey; - type Error = DeleteApiKeyError; -} -``` - -### `GetApiKeyByTokenUseCase` - -**Use Case Abstraction** — imported from `webiny/api/security/api-key` - -```typescript -import { GetApiKeyByTokenUseCase } from "webiny/api/security/api-key"; -``` - -**Interface `GetApiKeyByTokenUseCase.Interface`:** - -```typescript -interface GetApiKeyByTokenUseCase.Interface { - execute(token: string): Promise>; -} -``` - -**Types:** - -```typescript -namespace GetApiKeyByTokenUseCase { - type Interface = IGetApiKeyByToken; - type Error = GetApiKeyByTokenError; -} -``` - -### `GetApiKeyUseCase` - -**Use Case Abstraction** — imported from `webiny/api/security/api-key` - -```typescript -import { GetApiKeyUseCase } from "webiny/api/security/api-key"; -``` - -**Interface `GetApiKeyUseCase.Interface`:** - -```typescript -interface GetApiKeyUseCase.Interface { - execute(id: string): Promise>; -} -``` - -**Types:** - -```typescript -namespace GetApiKeyUseCase { - type Interface = IGetApiKey; - type Error = GetApiKeyError; -} -``` - -### `ListApiKeysUseCase` - -**Use Case Abstraction** — imported from `webiny/api/security/api-key` - -```typescript -import { ListApiKeysUseCase } from "webiny/api/security/api-key"; -``` - -**Interface `ListApiKeysUseCase.Interface`:** - -```typescript -interface ListApiKeysUseCase.Interface { - execute(params?: ListApiKeysInput): Promise>; -} -``` - -**Types:** - -```typescript -namespace ListApiKeysUseCase { - type Interface = IListApiKeys; - type Error = ListApiKeysError; -} -``` - -### `UpdateApiKeyUseCase` - -**Use Case Abstraction** — imported from `webiny/api/security/api-key` - -```typescript -import { UpdateApiKeyUseCase } from "webiny/api/security/api-key"; -``` - -**Interface `UpdateApiKeyUseCase.Interface`:** - -```typescript -interface UpdateApiKeyUseCase.Interface { - execute(id: string, input: UpdateApiKeyInput): Promise>; -} -``` - -**Types:** - -```typescript -namespace UpdateApiKeyUseCase { - type Interface = IUpdateApiKey; - type Error = UpdateApiKeyError; -} -``` - -## Event Handlers - -### `ApiKeyAfterCreateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/security/api-key` - -```typescript -import { ApiKeyAfterCreateEventHandler } from "webiny/api/security/api-key"; -``` - -**Interface `ApiKeyAfterCreateEventHandler.Interface`:** - -```typescript -interface ApiKeyAfterCreateEventHandler.Interface { - handle(event: ApiKeyAfterCreateEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace ApiKeyAfterCreateEventHandler { - type Interface = IEventHandler; - type Event = ApiKeyAfterCreateEvent; -} -``` - -### `ApiKeyAfterDeleteEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/security/api-key` - -```typescript -import { ApiKeyAfterDeleteEventHandler } from "webiny/api/security/api-key"; -``` - -**Interface `ApiKeyAfterDeleteEventHandler.Interface`:** - -```typescript -interface ApiKeyAfterDeleteEventHandler.Interface { - handle(event: ApiKeyAfterDeleteEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace ApiKeyAfterDeleteEventHandler { - type Interface = IEventHandler; - type Event = ApiKeyAfterDeleteEvent; -} -``` - -### `ApiKeyAfterUpdateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/security/api-key` - -```typescript -import { ApiKeyAfterUpdateEventHandler } from "webiny/api/security/api-key"; -``` - -**Interface `ApiKeyAfterUpdateEventHandler.Interface`:** - -```typescript -interface ApiKeyAfterUpdateEventHandler.Interface { - handle(event: ApiKeyAfterUpdateEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace ApiKeyAfterUpdateEventHandler { - type Interface = IEventHandler; - type Event = ApiKeyAfterUpdateEvent; -} -``` - -### `ApiKeyBeforeCreateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/security/api-key` - -```typescript -import { ApiKeyBeforeCreateEventHandler } from "webiny/api/security/api-key"; -``` - -**Interface `ApiKeyBeforeCreateEventHandler.Interface`:** - -```typescript -interface ApiKeyBeforeCreateEventHandler.Interface { - handle(event: ApiKeyBeforeCreateEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace ApiKeyBeforeCreateEventHandler { - type Interface = IEventHandler; - type Event = ApiKeyBeforeCreateEvent; -} -``` - -### `ApiKeyBeforeDeleteEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/security/api-key` - -```typescript -import { ApiKeyBeforeDeleteEventHandler } from "webiny/api/security/api-key"; -``` - -**Interface `ApiKeyBeforeDeleteEventHandler.Interface`:** - -```typescript -interface ApiKeyBeforeDeleteEventHandler.Interface { - handle(event: ApiKeyBeforeDeleteEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace ApiKeyBeforeDeleteEventHandler { - type Interface = IEventHandler; - type Event = ApiKeyBeforeDeleteEvent; -} -``` - -### `ApiKeyBeforeUpdateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/security/api-key` - -```typescript -import { ApiKeyBeforeUpdateEventHandler } from "webiny/api/security/api-key"; -``` - -**Interface `ApiKeyBeforeUpdateEventHandler.Interface`:** - -```typescript -interface ApiKeyBeforeUpdateEventHandler.Interface { - handle(event: ApiKeyBeforeUpdateEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace ApiKeyBeforeUpdateEventHandler { - type Interface = IEventHandler; - type Event = ApiKeyBeforeUpdateEvent; -} -``` - -## Services - -### `ApiKeyFactory` - -**Abstraction** — imported from `webiny/api/security/api-key` - -```typescript -import { ApiKeyFactory } from "webiny/api/security/api-key"; -``` - -**Interface `ApiKeyFactory.Interface`:** - -```typescript -interface ApiKeyFactory.Interface { - execute(): Promise; -} -``` - -**Types:** - -```typescript -namespace ApiKeyFactory { - type Interface = IApiKeyFactory; - type Return = Promise; - type ApiKey = CodeApiKey; -} -``` diff --git a/docs/developer-docs/6.x/reference/api/security/authentication.ai.txt b/docs/developer-docs/6.x/reference/api/security/authentication.ai.txt deleted file mode 100644 index 553c1a4ea..000000000 --- a/docs/developer-docs/6.x/reference/api/security/authentication.ai.txt +++ /dev/null @@ -1,25 +0,0 @@ -AI Context: Authentication (reference/api/security/authentication.mdx) - -Source of Information: -1. packages/webiny/src/api/security/authentication.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-core/src/features/security/authentication/AuthenticationContext/index.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -AfterAuthenticationEventHandler, BeforeAuthenticationEventHandler - -Import Path: webiny/api/security/authentication - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/security/authentication.mdx b/docs/developer-docs/6.x/reference/api/security/authentication.mdx deleted file mode 100644 index e44c716ce..000000000 --- a/docs/developer-docs/6.x/reference/api/security/authentication.mdx +++ /dev/null @@ -1,76 +0,0 @@ ---- -id: yxbpl3nl -title: Authentication -description: "Authentication event handlers" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- Which event handlers can you implement? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/security/authentication`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `AfterAuthenticationEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/security/authentication` - -```typescript -import { AfterAuthenticationEventHandler } from "webiny/api/security/authentication"; -``` - -**Interface `AfterAuthenticationEventHandler.Interface`:** - -```typescript -interface AfterAuthenticationEventHandler.Interface { - handle(event: AfterAuthenticationEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace AfterAuthenticationEventHandler { - type Interface = IEventHandler; - type Event = AfterAuthenticationEvent; -} -``` - -## `BeforeAuthenticationEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/security/authentication` - -```typescript -import { BeforeAuthenticationEventHandler } from "webiny/api/security/authentication"; -``` - -**Interface `BeforeAuthenticationEventHandler.Interface`:** - -```typescript -interface BeforeAuthenticationEventHandler.Interface { - handle(event: BeforeAuthenticationEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace BeforeAuthenticationEventHandler { - type Interface = IEventHandler; - type Event = BeforeAuthenticationEvent; -} -``` diff --git a/docs/developer-docs/6.x/reference/api/security/role.ai.txt b/docs/developer-docs/6.x/reference/api/security/role.ai.txt deleted file mode 100644 index 7e9d51c80..000000000 --- a/docs/developer-docs/6.x/reference/api/security/role.ai.txt +++ /dev/null @@ -1,29 +0,0 @@ -AI Context: Role (reference/api/security/role.mdx) - -Source of Information: -1. packages/webiny/src/api/security/role.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-core/src/features/security/roles/CreateRole/index.ts — originating source -3. /Users/adrian/dev/wby-next/packages/api-core/src/features/security/roles/DeleteRole/index.ts — originating source -4. /Users/adrian/dev/wby-next/packages/api-core/src/features/security/roles/GetRole/index.ts — originating source -5. /Users/adrian/dev/wby-next/packages/api-core/src/features/security/roles/ListRoles/index.ts — originating source -6. /Users/adrian/dev/wby-next/packages/api-core/src/features/security/roles/UpdateRole/index.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -CreateRoleUseCase, RoleAfterCreateEventHandler, RoleBeforeCreateEventHandler, DeleteRoleUseCase, RoleAfterDeleteEventHandler, RoleBeforeDeleteEventHandler, GetRoleUseCase, ListRolesUseCase, UpdateRoleUseCase, RoleAfterUpdateEventHandler, RoleBeforeUpdateEventHandler - -Import Path: webiny/api/security/role - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/security/role.mdx b/docs/developer-docs/6.x/reference/api/security/role.mdx deleted file mode 100644 index 1f41d9d73..000000000 --- a/docs/developer-docs/6.x/reference/api/security/role.mdx +++ /dev/null @@ -1,327 +0,0 @@ ---- -id: yxbpl3nl -title: Role -description: "Role use cases and event handlers" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What use cases are available in `webiny/api/security/role`? -- Which event handlers can you implement? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/security/role`. Import any of the items below directly from this path in your Webiny extensions. - -**Use Cases** - - - -**Event Handlers** - - - -## Use Cases - -### `CreateRoleUseCase` - -**Use Case Abstraction** — imported from `webiny/api/security/role` - -```typescript -import { CreateRoleUseCase } from "webiny/api/security/role"; -``` - -**Interface `CreateRoleUseCase.Interface`:** - -```typescript -interface CreateRoleUseCase.Interface { - execute(input: CreateRoleInput): Promise>; -} -``` - -**Types:** - -```typescript -namespace CreateRoleUseCase { - type Interface = ICreateRole; - type Error = CreateRoleError; -} -``` - -### `DeleteRoleUseCase` - -**Use Case Abstraction** — imported from `webiny/api/security/role` - -```typescript -import { DeleteRoleUseCase } from "webiny/api/security/role"; -``` - -**Interface `DeleteRoleUseCase.Interface`:** - -```typescript -interface DeleteRoleUseCase.Interface { - execute(id: string): Promise>; -} -``` - -**Types:** - -```typescript -namespace DeleteRoleUseCase { - type Interface = IDeleteRole; - type Error = DeleteRoleError; -} -``` - -### `GetRoleUseCase` - -**Use Case Abstraction** — imported from `webiny/api/security/role` - -```typescript -import { GetRoleUseCase } from "webiny/api/security/role"; -``` - -**Interface `GetRoleUseCase.Interface`:** - -```typescript -interface GetRoleUseCase.Interface { - execute(params: GetRoleInput): Promise>; -} -``` - -**Types:** - -```typescript -namespace GetRoleUseCase { - type Interface = IGetRole; - type Error = GetRoleError; -} -``` - -### `ListRolesUseCase` - -**Use Case Abstraction** — imported from `webiny/api/security/role` - -```typescript -import { ListRolesUseCase } from "webiny/api/security/role"; -``` - -**Interface `ListRolesUseCase.Interface`:** - -```typescript -interface ListRolesUseCase.Interface { - execute(params?: ListRolesInput): Promise>; -} -``` - -**Types:** - -```typescript -namespace ListRolesUseCase { - type Interface = IListRoles; - type Error = ListRolesError; -} -``` - -### `UpdateRoleUseCase` - -**Use Case Abstraction** — imported from `webiny/api/security/role` - -```typescript -import { UpdateRoleUseCase } from "webiny/api/security/role"; -``` - -**Interface `UpdateRoleUseCase.Interface`:** - -```typescript -interface UpdateRoleUseCase.Interface { - execute( - id: string, - input: UpdateRoleUseCaseInput - ): Promise>; -} -``` - -**Types:** - -```typescript -namespace UpdateRoleUseCase { - type Interface = IUpdateRoleUseCase; - type Error = UpdateRoleUseCaseError; -} -``` - -## Event Handlers - -### `RoleAfterCreateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/security/role` - -```typescript -import { RoleAfterCreateEventHandler } from "webiny/api/security/role"; -``` - -**Interface `RoleAfterCreateEventHandler.Interface`:** - -```typescript -interface RoleAfterCreateEventHandler.Interface { - handle(event: RoleAfterCreateEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace RoleAfterCreateEventHandler { - type Interface = IEventHandler; - type Event = RoleAfterCreateEvent; -} -``` - -### `RoleAfterDeleteEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/security/role` - -```typescript -import { RoleAfterDeleteEventHandler } from "webiny/api/security/role"; -``` - -**Interface `RoleAfterDeleteEventHandler.Interface`:** - -```typescript -interface RoleAfterDeleteEventHandler.Interface { - handle(event: RoleAfterDeleteEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace RoleAfterDeleteEventHandler { - type Interface = IEventHandler; - type Event = RoleAfterDeleteEvent; -} -``` - -### `RoleAfterUpdateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/security/role` - -```typescript -import { RoleAfterUpdateEventHandler } from "webiny/api/security/role"; -``` - -**Interface `RoleAfterUpdateEventHandler.Interface`:** - -```typescript -interface RoleAfterUpdateEventHandler.Interface { - handle(event: RoleAfterUpdateEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace RoleAfterUpdateEventHandler { - type Interface = IEventHandler; - type Event = RoleAfterUpdateEvent; -} -``` - -### `RoleBeforeCreateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/security/role` - -```typescript -import { RoleBeforeCreateEventHandler } from "webiny/api/security/role"; -``` - -**Interface `RoleBeforeCreateEventHandler.Interface`:** - -```typescript -interface RoleBeforeCreateEventHandler.Interface { - handle(event: RoleBeforeCreateEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace RoleBeforeCreateEventHandler { - type Interface = IEventHandler; - type Event = RoleBeforeCreateEvent; -} -``` - -### `RoleBeforeDeleteEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/security/role` - -```typescript -import { RoleBeforeDeleteEventHandler } from "webiny/api/security/role"; -``` - -**Interface `RoleBeforeDeleteEventHandler.Interface`:** - -```typescript -interface RoleBeforeDeleteEventHandler.Interface { - handle(event: RoleBeforeDeleteEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace RoleBeforeDeleteEventHandler { - type Interface = IEventHandler; - type Event = RoleBeforeDeleteEvent; -} -``` - -### `RoleBeforeUpdateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/security/role` - -```typescript -import { RoleBeforeUpdateEventHandler } from "webiny/api/security/role"; -``` - -**Interface `RoleBeforeUpdateEventHandler.Interface`:** - -```typescript -interface RoleBeforeUpdateEventHandler.Interface { - handle(event: RoleBeforeUpdateEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace RoleBeforeUpdateEventHandler { - type Interface = IEventHandler; - type Event = RoleBeforeUpdateEvent; -} -``` diff --git a/docs/developer-docs/6.x/reference/api/security/user.ai.txt b/docs/developer-docs/6.x/reference/api/security/user.ai.txt deleted file mode 100644 index 51be42a3d..000000000 --- a/docs/developer-docs/6.x/reference/api/security/user.ai.txt +++ /dev/null @@ -1,30 +0,0 @@ -AI Context: User (reference/api/security/user.mdx) - -Source of Information: -1. packages/webiny/src/api/security/user.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-core/src/features/users/CreateUser/index.ts — originating source -3. /Users/adrian/dev/wby-next/packages/api-core/src/features/users/DeleteUser/index.ts — originating source -4. /Users/adrian/dev/wby-next/packages/api-core/src/features/users/UpdateUser/index.ts — originating source -5. /Users/adrian/dev/wby-next/packages/api-core/src/features/users/GetUser/index.ts — originating source -6. /Users/adrian/dev/wby-next/packages/api-core/src/features/users/ListUsers/index.ts — originating source -7. /Users/adrian/dev/wby-next/packages/api-core/src/features/users/ListUserTeams/index.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -CreateUserUseCase, UserAfterCreateEventHandler, UserBeforeCreateEventHandler, DeleteUserUseCase, UserAfterDeleteEventHandler, UserBeforeDeleteEventHandler, UpdateUserUseCase, UserAfterUpdateEventHandler, UserBeforeUpdateEventHandler, GetUserUseCase, ListUsersUseCase, ListUserTeamsUseCase - -Import Path: webiny/api/security/user - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/security/user.mdx b/docs/developer-docs/6.x/reference/api/security/user.mdx deleted file mode 100644 index b1f82f182..000000000 --- a/docs/developer-docs/6.x/reference/api/security/user.mdx +++ /dev/null @@ -1,351 +0,0 @@ ---- -id: yxbpl3nl -title: User -description: "User use cases and event handlers" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What use cases are available in `webiny/api/security/user`? -- Which event handlers can you implement? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/security/user`. Import any of the items below directly from this path in your Webiny extensions. - -**Use Cases** - - - -**Event Handlers** - - - -## Use Cases - -### `CreateUserUseCase` - -**Use Case Abstraction** — imported from `webiny/api/security/user` - -```typescript -import { CreateUserUseCase } from "webiny/api/security/user"; -``` - -**Interface `CreateUserUseCase.Interface`:** - -```typescript -interface CreateUserUseCase.Interface { - execute(input: CreateUserInput): Promise>; -} -``` - -**Types:** - -```typescript -namespace CreateUserUseCase { - type Interface = ICreateUser; - type Input = CreateUserInput; - type Error = CreateUserError; -} -``` - -### `DeleteUserUseCase` - -**Use Case Abstraction** — imported from `webiny/api/security/user` - -```typescript -import { DeleteUserUseCase } from "webiny/api/security/user"; -``` - -**Interface `DeleteUserUseCase.Interface`:** - -```typescript -interface DeleteUserUseCase.Interface { - execute(id: string): Promise>; -} -``` - -**Types:** - -```typescript -namespace DeleteUserUseCase { - type Interface = IDeleteUser; - type Error = DeleteUserError; -} -``` - -### `GetUserUseCase` - -**Use Case Abstraction** — imported from `webiny/api/security/user` - -```typescript -import { GetUserUseCase } from "webiny/api/security/user"; -``` - -**Interface `GetUserUseCase.Interface`:** - -```typescript -interface GetUserUseCase.Interface { - execute(input: GetUserInput): Promise>; -} -``` - -**Types:** - -```typescript -namespace GetUserUseCase { - type Interface = IGetUser; - type Error = GetUserError; -} -``` - -### `ListUsersUseCase` - -**Use Case Abstraction** — imported from `webiny/api/security/user` - -```typescript -import { ListUsersUseCase } from "webiny/api/security/user"; -``` - -**Interface `ListUsersUseCase.Interface`:** - -```typescript -interface ListUsersUseCase.Interface { - execute(input?: ListUsersInput): Promise>; -} -``` - -**Types:** - -```typescript -namespace ListUsersUseCase { - type Interface = IListUsers; - type Error = ListUsersError; -} -``` - -### `ListUserTeamsUseCase` - -**Use Case Abstraction** — imported from `webiny/api/security/user` - -```typescript -import { ListUserTeamsUseCase } from "webiny/api/security/user"; -``` - -**Interface `ListUserTeamsUseCase.Interface`:** - -```typescript -interface ListUserTeamsUseCase.Interface { - execute(userId: string): Promise>; -} -``` - -**Types:** - -```typescript -namespace ListUserTeamsUseCase { - type Interface = IListUserTeams; - type Error = ListUserTeamsError; -} -``` - -### `UpdateUserUseCase` - -**Use Case Abstraction** — imported from `webiny/api/security/user` - -```typescript -import { UpdateUserUseCase } from "webiny/api/security/user"; -``` - -**Interface `UpdateUserUseCase.Interface`:** - -```typescript -interface UpdateUserUseCase.Interface { - execute(id: string, input: UpdateUserInput): Promise>; -} -``` - -**Types:** - -```typescript -namespace UpdateUserUseCase { - type Interface = IUpdateUser; - type Error = UpdateUserError; -} -``` - -## Event Handlers - -### `UserAfterCreateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/security/user` - -```typescript -import { UserAfterCreateEventHandler } from "webiny/api/security/user"; -``` - -**Interface `UserAfterCreateEventHandler.Interface`:** - -```typescript -interface UserAfterCreateEventHandler.Interface { - handle(event: UserAfterCreateEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace UserAfterCreateEventHandler { - type Interface = IEventHandler; - type Event = UserAfterCreateEvent; -} -``` - -### `UserAfterDeleteEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/security/user` - -```typescript -import { UserAfterDeleteEventHandler } from "webiny/api/security/user"; -``` - -**Interface `UserAfterDeleteEventHandler.Interface`:** - -```typescript -interface UserAfterDeleteEventHandler.Interface { - handle(event: UserAfterDeleteEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace UserAfterDeleteEventHandler { - type Interface = IEventHandler; - type Event = UserAfterDeleteEvent; -} -``` - -### `UserAfterUpdateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/security/user` - -```typescript -import { UserAfterUpdateEventHandler } from "webiny/api/security/user"; -``` - -**Interface `UserAfterUpdateEventHandler.Interface`:** - -```typescript -interface UserAfterUpdateEventHandler.Interface { - handle(event: UserAfterUpdateEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace UserAfterUpdateEventHandler { - type Interface = IEventHandler; - type Event = UserAfterUpdateEvent; -} -``` - -### `UserBeforeCreateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/security/user` - -```typescript -import { UserBeforeCreateEventHandler } from "webiny/api/security/user"; -``` - -**Interface `UserBeforeCreateEventHandler.Interface`:** - -```typescript -interface UserBeforeCreateEventHandler.Interface { - handle(event: UserBeforeCreateEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace UserBeforeCreateEventHandler { - type Interface = IEventHandler; - type Event = UserBeforeCreateEvent; -} -``` - -### `UserBeforeDeleteEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/security/user` - -```typescript -import { UserBeforeDeleteEventHandler } from "webiny/api/security/user"; -``` - -**Interface `UserBeforeDeleteEventHandler.Interface`:** - -```typescript -interface UserBeforeDeleteEventHandler.Interface { - handle(event: UserBeforeDeleteEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace UserBeforeDeleteEventHandler { - type Interface = IEventHandler; - type Event = UserBeforeDeleteEvent; -} -``` - -### `UserBeforeUpdateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/security/user` - -```typescript -import { UserBeforeUpdateEventHandler } from "webiny/api/security/user"; -``` - -**Interface `UserBeforeUpdateEventHandler.Interface`:** - -```typescript -interface UserBeforeUpdateEventHandler.Interface { - handle(event: UserBeforeUpdateEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace UserBeforeUpdateEventHandler { - type Interface = IEventHandler; - type Event = UserBeforeUpdateEvent; -} -``` diff --git a/docs/developer-docs/6.x/reference/api/system.ai.txt b/docs/developer-docs/6.x/reference/api/system.ai.txt deleted file mode 100644 index 91ba7d58d..000000000 --- a/docs/developer-docs/6.x/reference/api/system.ai.txt +++ /dev/null @@ -1,25 +0,0 @@ -AI Context: System (reference/api/system.mdx) - -Source of Information: -1. packages/webiny/src/api/system.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-core/src/features/system/InstallSystem/index.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -InstallSystemUseCase, SystemInstalledEventHandler - -Import Path: webiny/api/system - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/system.mdx b/docs/developer-docs/6.x/reference/api/system.mdx deleted file mode 100644 index 00d6dbb44..000000000 --- a/docs/developer-docs/6.x/reference/api/system.mdx +++ /dev/null @@ -1,97 +0,0 @@ ---- -id: yxbpl3n5 -title: System -description: "System installation abstractions" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What use cases are available in `webiny/api/system`? -- Which event handlers can you implement? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/system`. Import any of the items below directly from this path in your Webiny extensions. - -**Use Cases** - - - -**Event Handlers** - - - -## Use Cases - -### `InstallSystemUseCase` - -**Use Case Abstraction** — imported from `webiny/api/system` - -```typescript -import { InstallSystemUseCase } from "webiny/api/system"; -``` - -**Interface `InstallSystemUseCase.Interface`:** - -Use Case Abstraction - -```typescript -interface InstallSystemUseCase.Interface { - execute( - input: InstallSystemInput - ): Promise>; -} -``` - -**Types:** - -```typescript -namespace InstallSystemUseCase { - type Interface = IInstallSystemUseCase; - type Input = InstallSystemInput; -} -``` - -**`Input` — `AppInstallationData[]`:** - -Types - -| Field | Type | Required | Description | -| ------ | --------------------- | -------- | ----------- | -| `app` | `string` | yes | — | -| `data` | `Record` | yes | — | - -## Event Handlers - -### `SystemInstalledEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/system` - -```typescript -import { SystemInstalledEventHandler } from "webiny/api/system"; -``` - -**Interface `SystemInstalledEventHandler.Interface`:** - -```typescript -interface SystemInstalledEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace SystemInstalledEventHandler { - type Interface = IEventHandler; - type Event = DomainEvent; -} -``` diff --git a/docs/developer-docs/6.x/reference/api/tasks.ai.txt b/docs/developer-docs/6.x/reference/api/tasks.ai.txt deleted file mode 100644 index fc5f1f0da..000000000 --- a/docs/developer-docs/6.x/reference/api/tasks.ai.txt +++ /dev/null @@ -1,26 +0,0 @@ -AI Context: Tasks (reference/api/tasks.mdx) - -Source of Information: -1. packages/webiny/src/api/tasks.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-core/src/features/task/TaskService/index.ts — originating source -3. /Users/adrian/dev/wby-next/packages/api-core/src/features/task/TaskDefinition/index.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -TaskService, TaskDefinition - -Import Path: webiny/api/tasks - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/tasks.mdx b/docs/developer-docs/6.x/reference/api/tasks.mdx deleted file mode 100644 index 74f1f27c4..000000000 --- a/docs/developer-docs/6.x/reference/api/tasks.mdx +++ /dev/null @@ -1,137 +0,0 @@ ---- -id: yxbpl3rh -title: Tasks -description: "Background task abstractions: TaskService, TaskDefinition" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/api/tasks`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/tasks`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `TaskDefinition` - -**Abstraction** — imported from `webiny/api/tasks` - -```typescript -import { TaskDefinition } from "webiny/api/tasks"; -``` - -**Interface `TaskDefinition.Interface`:** - -Core TaskDefinition - minimal interface - -```typescript -interface TaskDefinition.Interface { - id: string; - title: string; - description?: string; - maxIterations?: number; - databaseLogs?: boolean; - isPrivate?: boolean; - run(params: ITaskRunParams): Promise>; - onBeforeTrigger?(params: ITaskBeforeTriggerParams): Promise; - onDone?(params: ITaskLifecycleHook): Promise; - onError?(params: ITaskLifecycleHook): Promise; - onAbort?(params: ITaskLifecycleHook): Promise; - onMaxIterations?(params: ITaskLifecycleHook): Promise; - createInputValidation?( - params: ITaskCreateInputValidationParams - ): GenericRecord | zod.Schema; -} -``` - -| Method | Description | -| ----------------------------------------------------------------------------------- | -------------------------------------------------------- | -| `id: string()` | — | -| `title: string()` | — | -| `description?: string()` | — | -| `maxIterations?: number()` | — | -| `databaseLogs?: boolean()` | — | -| `isPrivate?: boolean()` | — | -| `run()` | Core run method - receives ONLY input params | -| All runtime dependencies (logging, state management, etc.) come from TaskController | -| `onBeforeTrigger?()` | Optional lifecycle hooks - receive task data, no context | -| `onDone?()` | — | -| `onError?()` | — | -| `onAbort?()` | — | -| `onMaxIterations?()` | — | -| `createInputValidation?()` | Create a validation schema for the task input. | -| This will be used to validate the input before the task is triggered. | - -**Types:** - -```typescript -namespace TaskDefinition { - type Interface = ITaskDefinition; - type TaskInput = ITaskInput; - type TaskOutput = ITaskOutput; - type Runnable = IRunnableTaskDefinition; - type RunParams = ITaskRunParams; - type Result = ITaskResult; - type Task = ITask; - type ResultDone = ITaskResultDone; - type ResultContinue = ITaskResultContinue; - type ResultError = ITaskResultError; - type ResultAborted = ITaskResultAborted; - type CreateInputValidationParams = ITaskCreateInputValidationParams; - type TaskCreateData = ITaskCreateData; - type BeforeTriggerParams = ITaskBeforeTriggerParams; - type LifecycleHookParams = ITaskLifecycleHook; -} -``` - -## `TaskService` - -**Abstraction** — imported from `webiny/api/tasks` - -```typescript -import { TaskService } from "webiny/api/tasks"; -``` - -**Interface `TaskService.Interface`:** - -```typescript -interface TaskService.Interface { - trigger: < - T extends TaskDefinition.TaskInput = TaskDefinition.TaskInput, - O extends IGenericOutput = IGenericOutput - >( - params: ITaskTriggerParams - ) => Promise, BaseError>>; - abort: < - T extends TaskDefinition.TaskInput = TaskDefinition.TaskInput, - O extends IGenericOutput = IGenericOutput - >( - params: ITaskAbortParams - ) => Promise, BaseError>>; - fetchServiceInfo: (input: ITask | string) => Promise>; -} -``` - -**Types:** - -```typescript -namespace TaskService { - type Interface = ITaskService; - type GenericOutput = IGenericOutput; - type TaskInput = TaskDefinition.TaskInput; - type Task = ITask; -} -``` diff --git a/docs/developer-docs/6.x/reference/api/tenancy.ai.txt b/docs/developer-docs/6.x/reference/api/tenancy.ai.txt deleted file mode 100644 index c4a842501..000000000 --- a/docs/developer-docs/6.x/reference/api/tenancy.ai.txt +++ /dev/null @@ -1,30 +0,0 @@ -AI Context: Tenancy (reference/api/tenancy.mdx) - -Source of Information: -1. packages/webiny/src/api/tenancy.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-core/src/features/tenancy/TenantContext/index.ts — originating source -3. /Users/adrian/dev/wby-next/packages/api-core/src/features/tenancy/CreateTenant/index.ts — originating source -4. /Users/adrian/dev/wby-next/packages/api-core/src/features/tenancy/GetTenantById/index.ts — originating source -5. /Users/adrian/dev/wby-next/packages/api-core/src/features/tenancy/UpdateTenant/index.ts — originating source -6. /Users/adrian/dev/wby-next/packages/api-core/src/features/tenancy/DeleteTenant/index.ts — originating source -7. /Users/adrian/dev/wby-next/packages/api-core/src/features/tenancy/InstallTenant/index.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -TenantContext, CreateTenantUseCase, CreateTenantRepository, TenantBeforeCreateEventHandler, TenantAfterCreateEventHandler, GetTenantByIdUseCase, UpdateTenantUseCase, UpdateTenantRepository, TenantAfterUpdateEventHandler, TenantBeforeUpdateEventHandler, DeleteTenantUseCase, DeleteTenantRepository, TenantAfterDeleteEventHandler, TenantBeforeDeleteEventHandler, InstallTenantUseCase, AppInstaller, TenantInstalledEventHandler - -Import Path: webiny/api/tenancy - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/tenancy.mdx b/docs/developer-docs/6.x/reference/api/tenancy.mdx deleted file mode 100644 index 645f392b6..000000000 --- a/docs/developer-docs/6.x/reference/api/tenancy.mdx +++ /dev/null @@ -1,513 +0,0 @@ ---- -id: yxbpl3rl -title: Tenancy -description: "Tenancy context and tenant management" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What use cases are available in `webiny/api/tenancy`? -- Which event handlers can you implement? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/tenancy`. Import any of the items below directly from this path in your Webiny extensions. - -**Use Cases** - - - -**Event Handlers** - - - -**Services** - - - -## Use Cases - -### `CreateTenantRepository` - -**Use Case Abstraction** — imported from `webiny/api/tenancy` - -```typescript -import { CreateTenantRepository } from "webiny/api/tenancy"; -``` - -**Interface `CreateTenantRepository.Interface`:** - -Repository - -```typescript -interface CreateTenantRepository.Interface { - create(tenant: Tenant): Promise; -} -``` - -**Types:** - -```typescript -namespace CreateTenantRepository { - type Interface = ICreateTenantRepository; -} -``` - -### `CreateTenantUseCase` - -**Use Case Abstraction** — imported from `webiny/api/tenancy` - -```typescript -import { CreateTenantUseCase } from "webiny/api/tenancy"; -``` - -**Interface `CreateTenantUseCase.Interface`:** - -Use Case - -```typescript -interface CreateTenantUseCase.Interface { - execute( - data: CreateTenantInput - ): Promise>; -} -``` - -**Types:** - -```typescript -namespace CreateTenantUseCase { - type Interface = ICreateTenantUseCase; - type Errors = ICreateTenantErrors[keyof ICreateTenantErrors]; -} -``` - -### `DeleteTenantRepository` - -**Use Case Abstraction** — imported from `webiny/api/tenancy` - -```typescript -import { DeleteTenantRepository } from "webiny/api/tenancy"; -``` - -**Interface `DeleteTenantRepository.Interface`:** - -```typescript -interface DeleteTenantRepository.Interface { - delete(id: string): Promise; -} -``` - -**Types:** - -```typescript -namespace DeleteTenantRepository { - type Interface = IDeleteTenantRepository; -} -``` - -### `DeleteTenantUseCase` - -**Use Case Abstraction** — imported from `webiny/api/tenancy` - -```typescript -import { DeleteTenantUseCase } from "webiny/api/tenancy"; -``` - -**Interface `DeleteTenantUseCase.Interface`:** - -```typescript -interface DeleteTenantUseCase.Interface { - execute(id: string): Promise; -} -``` - -**Types:** - -```typescript -namespace DeleteTenantUseCase { - type Interface = IDeleteTenantUseCase; -} -``` - -### `GetTenantByIdUseCase` - -**Use Case Abstraction** — imported from `webiny/api/tenancy` - -```typescript -import { GetTenantByIdUseCase } from "webiny/api/tenancy"; -``` - -**Interface `GetTenantByIdUseCase.Interface`:** - -```typescript -interface GetTenantByIdUseCase.Interface { - execute(id: string): Promise>; -} -``` - -**Types:** - -```typescript -namespace GetTenantByIdUseCase { - type Interface = IGetTenantByIdUseCase; - type Error = GetTenantByIdError; - type Result = ReturnType; -} -``` - -### `InstallTenantUseCase` - -**Use Case Abstraction** — imported from `webiny/api/tenancy` - -```typescript -import { InstallTenantUseCase } from "webiny/api/tenancy"; -``` - -**Interface `InstallTenantUseCase.Interface`:** - -```typescript -interface InstallTenantUseCase.Interface { - execute( - input: TenantInstallationInput - ): Promise>; -} -``` - -**Types:** - -```typescript -namespace InstallTenantUseCase { - type Interface = IInstallTenantUseCase; - type Input = TenantInstallationInput; - type Errors = IInstallTenantErrors[keyof IInstallTenantErrors]; -} -``` - -### `UpdateTenantRepository` - -**Use Case Abstraction** — imported from `webiny/api/tenancy` - -```typescript -import { UpdateTenantRepository } from "webiny/api/tenancy"; -``` - -**Interface `UpdateTenantRepository.Interface`:** - -```typescript -interface UpdateTenantRepository.Interface { - update(tenant: Tenant): Promise; -} -``` - -**Types:** - -```typescript -namespace UpdateTenantRepository { - type Interface = IUpdateTenantRepository; -} -``` - -### `UpdateTenantUseCase` - -**Use Case Abstraction** — imported from `webiny/api/tenancy` - -```typescript -import { UpdateTenantUseCase } from "webiny/api/tenancy"; -``` - -**Interface `UpdateTenantUseCase.Interface`:** - -```typescript -interface UpdateTenantUseCase.Interface { - execute(id: string, data: Partial): Promise>; -} -``` - -**Types:** - -```typescript -namespace UpdateTenantUseCase { - type Interface = IUpdateTenantUseCase; -} -``` - -## Event Handlers - -### `TenantAfterCreateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/tenancy` - -```typescript -import { TenantAfterCreateEventHandler } from "webiny/api/tenancy"; -``` - -**Interface `TenantAfterCreateEventHandler.Interface`:** - -```typescript -interface TenantAfterCreateEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace TenantAfterCreateEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; -} -``` - -### `TenantAfterDeleteEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/tenancy` - -```typescript -import { TenantAfterDeleteEventHandler } from "webiny/api/tenancy"; -``` - -**Interface `TenantAfterDeleteEventHandler.Interface`:** - -```typescript -interface TenantAfterDeleteEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace TenantAfterDeleteEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; -} -``` - -### `TenantAfterUpdateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/tenancy` - -```typescript -import { TenantAfterUpdateEventHandler } from "webiny/api/tenancy"; -``` - -**Interface `TenantAfterUpdateEventHandler.Interface`:** - -```typescript -interface TenantAfterUpdateEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace TenantAfterUpdateEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; -} -``` - -### `TenantBeforeCreateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/tenancy` - -```typescript -import { TenantBeforeCreateEventHandler } from "webiny/api/tenancy"; -``` - -**Interface `TenantBeforeCreateEventHandler.Interface`:** - -```typescript -interface TenantBeforeCreateEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace TenantBeforeCreateEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; -} -``` - -### `TenantBeforeDeleteEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/tenancy` - -```typescript -import { TenantBeforeDeleteEventHandler } from "webiny/api/tenancy"; -``` - -**Interface `TenantBeforeDeleteEventHandler.Interface`:** - -```typescript -interface TenantBeforeDeleteEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace TenantBeforeDeleteEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; -} -``` - -### `TenantBeforeUpdateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/tenancy` - -```typescript -import { TenantBeforeUpdateEventHandler } from "webiny/api/tenancy"; -``` - -**Interface `TenantBeforeUpdateEventHandler.Interface`:** - -```typescript -interface TenantBeforeUpdateEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace TenantBeforeUpdateEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; -} -``` - -### `TenantInstalledEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/tenancy` - -```typescript -import { TenantInstalledEventHandler } from "webiny/api/tenancy"; -``` - -**Interface `TenantInstalledEventHandler.Interface`:** - -```typescript -interface TenantInstalledEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Types:** - -```typescript -namespace TenantInstalledEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; -} -``` - -## Services - -### `AppInstaller` - -**Abstraction** — imported from `webiny/api/tenancy` - -```typescript -import { AppInstaller } from "webiny/api/tenancy"; -``` - -**Interface `AppInstaller.Interface`:** - -```typescript -interface AppInstaller.Interface { - readonly alwaysRun?: boolean; - readonly appName: string; - readonly dependsOn: string[]; - install(tenant: Tenant, data: TData): Promise; - uninstall(tenant: Tenant): Promise; -} -``` - -| Method | Description | -| ------------------------------------------------------- | ------------------------ | -| `readonly alwaysRun?: boolean()` | — | -| `readonly appName: string()` | — | -| `readonly dependsOn: string[]()` | — | -| `install()` | Perform the installation | -| If this succeeds, uninstall() MUST be able to revert it | -| `uninstall()` | Revert the installation | -| Called if any subsequent installer fails | - -**Types:** - -```typescript -namespace AppInstaller { - type Interface = IAppInstaller; -} -``` - -### `TenantContext` - -**Abstraction** — imported from `webiny/api/tenancy` - -```typescript -import { TenantContext } from "webiny/api/tenancy"; -``` - -**Interface `TenantContext.Interface`:** - -```typescript -interface TenantContext.Interface { - setTenant(tenant: Tenant): void; - getTenant(): Tenant; - withRootTenant(cb: () => T): Promise; - withEachTenant( - tenants: Tenant[], - cb: (tenant: Tenant) => Promise - ): Promise; - withTenant(tenant: Tenant, cb: (tenant: Tenant) => Promise): Promise; -} -``` - -**Types:** - -```typescript -namespace TenantContext { - type Interface = ITenantContext; -} -``` diff --git a/docs/developer-docs/6.x/reference/api/tenant-manager.ai.txt b/docs/developer-docs/6.x/reference/api/tenant-manager.ai.txt deleted file mode 100644 index c911614a1..000000000 --- a/docs/developer-docs/6.x/reference/api/tenant-manager.ai.txt +++ /dev/null @@ -1,26 +0,0 @@ -AI Context: Tenant Manager (reference/api/tenant-manager.mdx) - -Source of Information: -1. packages/webiny/src/api/tenant-manager.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/tenant-manager/src/api/domain/TenantModelExtension.ts — originating source -3. /Users/adrian/dev/wby-next/packages/tenant-manager/src/shared/Tenant.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -TenantModelExtension, TenantExtensions - -Import Path: webiny/api/tenant-manager - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/tenant-manager.mdx b/docs/developer-docs/6.x/reference/api/tenant-manager.mdx deleted file mode 100644 index dbb1acfb5..000000000 --- a/docs/developer-docs/6.x/reference/api/tenant-manager.mdx +++ /dev/null @@ -1,68 +0,0 @@ ---- -id: yxbpl3rl -title: Tenant Manager -description: "Tenant manager abstractions" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/api/tenant-manager`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/tenant-manager`. Import any of the items below directly from this path in your Webiny extensions. - -**Services** - - - -**Types & Classes** - - - -## Services - -### `TenantModelExtension` - -**Abstraction** — imported from `webiny/api/tenant-manager` - -```typescript -import { TenantModelExtension } from "webiny/api/tenant-manager"; -``` - -**Interface `TenantModelExtension.Interface`:** - -```typescript -interface TenantModelExtension.Interface { - execute(extension: IExtension): void; -} -``` - -**Types:** - -```typescript -namespace TenantModelExtension { - type Interface = ITenantModelExtension; - type Extension = IExtension; -} -``` - -## Types & Classes - -### `TenantExtensions` - -**Type** — imported from `webiny/api/tenant-manager` - -```typescript -import type { TenantExtensions } from "webiny/api/tenant-manager"; -``` - -```typescript -export interface TenantExtensions {} -``` diff --git a/docs/developer-docs/6.x/reference/api/website-builder/nextjs.ai.txt b/docs/developer-docs/6.x/reference/api/website-builder/nextjs.ai.txt deleted file mode 100644 index fe7b0116f..000000000 --- a/docs/developer-docs/6.x/reference/api/website-builder/nextjs.ai.txt +++ /dev/null @@ -1,25 +0,0 @@ -AI Context: Next.js (reference/api/website-builder/nextjs.mdx) - -Source of Information: -1. packages/webiny/src/api/website-builder/nextjs.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-website-builder/src/features/nextjs/abstractions.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -NextjsConfig - -Import Path: webiny/api/website-builder/nextjs - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/website-builder/nextjs.mdx b/docs/developer-docs/6.x/reference/api/website-builder/nextjs.mdx deleted file mode 100644 index 5a01f6d6b..000000000 --- a/docs/developer-docs/6.x/reference/api/website-builder/nextjs.mdx +++ /dev/null @@ -1,46 +0,0 @@ ---- -id: yxbpl3dl -title: Next.js -description: "Next.js configuration abstraction" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/api/website-builder/nextjs`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/website-builder/nextjs`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `NextjsConfig` - -**Abstraction** — imported from `webiny/api/website-builder/nextjs` - -```typescript -import { NextjsConfig } from "webiny/api/website-builder/nextjs"; -``` - -**Interface `NextjsConfig.Interface`:** - -```typescript -interface NextjsConfig.Interface { - execute(): Promise; -} -``` - -**Types:** - -```typescript -namespace NextjsConfig { - type Interface = INextjsConfig; - type Return = Promise; -} -``` diff --git a/docs/developer-docs/6.x/reference/api/website-builder/page.ai.txt b/docs/developer-docs/6.x/reference/api/website-builder/page.ai.txt deleted file mode 100644 index 8553fe287..000000000 --- a/docs/developer-docs/6.x/reference/api/website-builder/page.ai.txt +++ /dev/null @@ -1,36 +0,0 @@ -AI Context: Page (reference/api/website-builder/page.mdx) - -Source of Information: -1. packages/webiny/src/api/website-builder/page.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-website-builder/src/features/pages/CreatePage/abstractions.ts — originating source -3. /Users/adrian/dev/wby-next/packages/api-website-builder/src/features/pages/CreatePageRevisionFrom/abstractions.ts — originating source -4. /Users/adrian/dev/wby-next/packages/api-website-builder/src/features/pages/DeletePage/abstractions.ts — originating source -5. /Users/adrian/dev/wby-next/packages/api-website-builder/src/features/pages/DuplicatePage/abstractions.ts — originating source -6. /Users/adrian/dev/wby-next/packages/api-website-builder/src/features/pages/GetPageById/abstractions.ts — originating source -7. /Users/adrian/dev/wby-next/packages/api-website-builder/src/features/pages/GetPageByPath/abstractions.ts — originating source -8. /Users/adrian/dev/wby-next/packages/api-website-builder/src/features/pages/GetPageRevisions/abstractions.ts — originating source -9. /Users/adrian/dev/wby-next/packages/api-website-builder/src/features/pages/ListPages/abstractions.ts — originating source -10. /Users/adrian/dev/wby-next/packages/api-website-builder/src/features/pages/MovePage/abstractions.ts — originating source -11. /Users/adrian/dev/wby-next/packages/api-website-builder/src/features/pages/PublishPage/abstractions.ts — originating source -12. /Users/adrian/dev/wby-next/packages/api-website-builder/src/features/pages/UnpublishPage/abstractions.ts — originating source -13. /Users/adrian/dev/wby-next/packages/api-website-builder/src/features/pages/UpdatePage/abstractions.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -CreatePageUseCase, PageAfterCreateEventHandler, PageBeforeCreateEventHandler, CreatePageRevisionFromUseCase, PageAfterCreateRevisionFromEventHandler, PageBeforeCreateRevisionFromEventHandler, DeletePageUseCase, PageAfterDeleteEventHandler, PageBeforeDeleteEventHandler, DuplicatePageUseCase, PageAfterDuplicateEventHandler, PageBeforeDuplicateEventHandler, GetPageByIdUseCase, GetPageByPathUseCase, GetPageRevisionsUseCase, ListPagesUseCase, MovePageUseCase, PageAfterMoveEventHandler, PageBeforeMoveEventHandler, PublishPageUseCase, PageAfterPublishEventHandler, PageBeforePublishEventHandler, UnpublishPageUseCase, PageAfterUnpublishEventHandler, PageBeforeUnpublishEventHandler, UpdatePageUseCase, PageAfterUpdateEventHandler, PageBeforeUpdateEventHandler - -Import Path: webiny/api/website-builder/page - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/website-builder/page.mdx b/docs/developer-docs/6.x/reference/api/website-builder/page.mdx deleted file mode 100644 index dfbdd4207..000000000 --- a/docs/developer-docs/6.x/reference/api/website-builder/page.mdx +++ /dev/null @@ -1,968 +0,0 @@ ---- -id: yxbpl3dl -title: Page -description: "Website Builder page use cases and event handlers" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What use cases are available in `webiny/api/website-builder/page`? -- Which event handlers can you implement? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/website-builder/page`. Import any of the items below directly from this path in your Webiny extensions. - -**Use Cases** - - - -**Event Handlers** - - - -## Use Cases - -### `CreatePageRevisionFromUseCase` - -**Use Case Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { CreatePageRevisionFromUseCase } from "webiny/api/website-builder/page"; -``` - -**Interface `CreatePageRevisionFromUseCase.Interface`:** - -```typescript -interface CreatePageRevisionFromUseCase.Interface { - execute(params: ICreateWbPageRevisionFromParams): Promise>; -} -``` - -**Types:** - -```typescript -namespace CreatePageRevisionFromUseCase { - type Interface = ICreatePageRevisionFromUseCase; - type Params = ICreateWbPageRevisionFromParams; - type Return = Promise>; - type Error = UseCaseError; - type Page = WbPage; -} -``` - -### `CreatePageUseCase` - -**Use Case Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { CreatePageUseCase } from "webiny/api/website-builder/page"; -``` - -**Interface `CreatePageUseCase.Interface`:** - -```typescript -interface CreatePageUseCase.Interface { - execute(data: ICreateWbPageParams): Promise>; -} -``` - -**Types:** - -```typescript -namespace CreatePageUseCase { - type Interface = ICreatePageUseCase; - type Params = ICreateWbPageParams; - type Return = Promise>; - type Error = UseCaseError; - type Page = WbPage; -} -``` - -### `DeletePageUseCase` - -**Use Case Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { DeletePageUseCase } from "webiny/api/website-builder/page"; -``` - -**Interface `DeletePageUseCase.Interface`:** - -```typescript -interface DeletePageUseCase.Interface { - execute(params: IDeleteWbPageParams): Promise>; -} -``` - -**Types:** - -```typescript -namespace DeletePageUseCase { - type Interface = IDeletePageUseCase; - type Params = IDeleteWbPageParams; - type Return = Promise>; - type Error = UseCaseError; -} -``` - -### `DuplicatePageUseCase` - -**Use Case Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { DuplicatePageUseCase } from "webiny/api/website-builder/page"; -``` - -**Interface `DuplicatePageUseCase.Interface`:** - -```typescript -interface DuplicatePageUseCase.Interface { - execute(params: IDuplicateWbPageParams): Promise>; -} -``` - -**Types:** - -```typescript -namespace DuplicatePageUseCase { - type Interface = IDuplicatePageUseCase; - type Params = IDuplicateWbPageParams; - type Return = Promise>; - type Error = UseCaseError; - type Page = WbPage; -} -``` - -### `GetPageByIdUseCase` - -**Use Case Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { GetPageByIdUseCase } from "webiny/api/website-builder/page"; -``` - -**Interface `GetPageByIdUseCase.Interface`:** - -GetPageById use case interface - -```typescript -interface GetPageByIdUseCase.Interface { - execute(id: string): Promise>; -} -``` - -**Types:** - -```typescript -namespace GetPageByIdUseCase { - type Interface = IGetPageByIdUseCase; - type Return = Promise>; - type Error = UseCaseError; - type Page = WbPage; -} -``` - -### `GetPageByPathUseCase` - -**Use Case Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { GetPageByPathUseCase } from "webiny/api/website-builder/page"; -``` - -**Interface `GetPageByPathUseCase.Interface`:** - -GetPageByPath use case interface - -```typescript -interface GetPageByPathUseCase.Interface { - execute(path: string): Promise>; -} -``` - -**Types:** - -```typescript -namespace GetPageByPathUseCase { - type Interface = IGetPageByPathUseCase; - type Error = UseCaseError; - type Return = Promise>; - type Page = WbPage; -} -``` - -### `GetPageRevisionsUseCase` - -**Use Case Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { GetPageRevisionsUseCase } from "webiny/api/website-builder/page"; -``` - -**Interface `GetPageRevisionsUseCase.Interface`:** - -GetPageRevisions use case interface - -```typescript -interface GetPageRevisionsUseCase.Interface { - execute(entryId: string): Promise>; -} -``` - -**Types:** - -```typescript -namespace GetPageRevisionsUseCase { - type Interface = IGetPageRevisionsUseCase; - type Error = UseCaseError; - type Return = Promise>; - type Page = WbPage; -} -``` - -### `ListPagesUseCase` - -**Use Case Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { ListPagesUseCase } from "webiny/api/website-builder/page"; -``` - -**Interface `ListPagesUseCase.Interface`:** - -ListPages use case interface - -```typescript -interface ListPagesUseCase.Interface { - execute(params: IListPagesParams): Promise>; -} -``` - -**Types:** - -```typescript -namespace ListPagesUseCase { - type Interface = IListPagesUseCase; - type Error = UseCaseError; - type Params = IListPagesParams; - type Return = Promise>; -} -``` - -### `MovePageUseCase` - -**Use Case Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { MovePageUseCase } from "webiny/api/website-builder/page"; -``` - -**Interface `MovePageUseCase.Interface`:** - -```typescript -interface MovePageUseCase.Interface { - execute(params: IMoveWbPageParams): Promise>; -} -``` - -**Types:** - -```typescript -namespace MovePageUseCase { - type Interface = IMovePageUseCase; - type Params = IMoveWbPageParams; - type Return = Promise>; - type Error = UseCaseError; - type Page = WbPage; -} -``` - -### `PublishPageUseCase` - -**Use Case Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { PublishPageUseCase } from "webiny/api/website-builder/page"; -``` - -**Interface `PublishPageUseCase.Interface`:** - -```typescript -interface PublishPageUseCase.Interface { - execute(params: IPublishWbPageParams): Promise>; -} -``` - -**Types:** - -```typescript -namespace PublishPageUseCase { - type Interface = IPublishPageUseCase; - type Params = IPublishWbPageParams; - type Return = Promise>; - type Error = UseCaseError; - type Page = WbPage; -} -``` - -### `UnpublishPageUseCase` - -**Use Case Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { UnpublishPageUseCase } from "webiny/api/website-builder/page"; -``` - -**Interface `UnpublishPageUseCase.Interface`:** - -```typescript -interface UnpublishPageUseCase.Interface { - execute(params: IUnpublishWbPageParams): Promise>; -} -``` - -**Types:** - -```typescript -namespace UnpublishPageUseCase { - type Interface = IUnpublishPageUseCase; - type Params = IUnpublishWbPageParams; - type Return = Promise>; - type Error = UseCaseError; - type Page = WbPage; -} -``` - -### `UpdatePageUseCase` - -**Use Case Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { UpdatePageUseCase } from "webiny/api/website-builder/page"; -``` - -**Interface `UpdatePageUseCase.Interface`:** - -```typescript -interface UpdatePageUseCase.Interface { - execute(id: string, data: IUpdateWbPageData): Promise>; -} -``` - -**Types:** - -```typescript -namespace UpdatePageUseCase { - type Interface = IUpdatePageUseCase; - type UpdateData = IUpdateWbPageData; - type Return = Promise>; - type Error = UseCaseError; - type Page = WbPage; -} -``` - -## Event Handlers - -### `PageAfterCreateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { PageAfterCreateEventHandler } from "webiny/api/website-builder/page"; -``` - -**Interface `PageAfterCreateEventHandler.Interface`:** - -```typescript -interface PageAfterCreateEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Event payload `PageAfterCreatePayload`:** - -```typescript -interface PageAfterCreatePayload { - page: WbPage; -} -``` - -**Types:** - -```typescript -namespace PageAfterCreateEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; - type Page = WbPage; -} -``` - -### `PageAfterCreateRevisionFromEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { PageAfterCreateRevisionFromEventHandler } from "webiny/api/website-builder/page"; -``` - -**Interface `PageAfterCreateRevisionFromEventHandler.Interface`:** - -```typescript -interface PageAfterCreateRevisionFromEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Event payload `PageAfterCreateRevisionFromPayload`:** - -```typescript -interface PageAfterCreateRevisionFromPayload { - page: WbPage; -} -``` - -**Types:** - -```typescript -namespace PageAfterCreateRevisionFromEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; - type Page = WbPage; -} -``` - -### `PageAfterDeleteEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { PageAfterDeleteEventHandler } from "webiny/api/website-builder/page"; -``` - -**Interface `PageAfterDeleteEventHandler.Interface`:** - -```typescript -interface PageAfterDeleteEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Event payload `PageAfterDeletePayload`:** - -```typescript -interface PageAfterDeletePayload { - page: WbPage; -} -``` - -**Types:** - -```typescript -namespace PageAfterDeleteEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; - type Page = WbPage; -} -``` - -### `PageAfterDuplicateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { PageAfterDuplicateEventHandler } from "webiny/api/website-builder/page"; -``` - -**Interface `PageAfterDuplicateEventHandler.Interface`:** - -```typescript -interface PageAfterDuplicateEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Event payload `PageAfterDuplicatePayload`:** - -```typescript -interface PageAfterDuplicatePayload { - original: WbPage; - page: WbPage; -} -``` - -**Types:** - -```typescript -namespace PageAfterDuplicateEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; - type Page = WbPage; -} -``` - -### `PageAfterMoveEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { PageAfterMoveEventHandler } from "webiny/api/website-builder/page"; -``` - -**Interface `PageAfterMoveEventHandler.Interface`:** - -```typescript -interface PageAfterMoveEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Event payload `PageAfterMovePayload`:** - -```typescript -interface PageAfterMovePayload { - original: WbPage; - input: IMoveWbPageParams; - page: WbPage; -} -``` - -**Types:** - -```typescript -namespace PageAfterMoveEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; - type Page = WbPage; -} -``` - -### `PageAfterPublishEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { PageAfterPublishEventHandler } from "webiny/api/website-builder/page"; -``` - -**Interface `PageAfterPublishEventHandler.Interface`:** - -```typescript -interface PageAfterPublishEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Event payload `PageAfterPublishPayload`:** - -```typescript -interface PageAfterPublishPayload { - page: WbPage; -} -``` - -**Types:** - -```typescript -namespace PageAfterPublishEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; - type Page = WbPage; -} -``` - -### `PageAfterUnpublishEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { PageAfterUnpublishEventHandler } from "webiny/api/website-builder/page"; -``` - -**Interface `PageAfterUnpublishEventHandler.Interface`:** - -```typescript -interface PageAfterUnpublishEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Event payload `PageAfterUnpublishPayload`:** - -```typescript -interface PageAfterUnpublishPayload { - page: WbPage; -} -``` - -**Types:** - -```typescript -namespace PageAfterUnpublishEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; - type Page = WbPage; -} -``` - -### `PageAfterUpdateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { PageAfterUpdateEventHandler } from "webiny/api/website-builder/page"; -``` - -**Interface `PageAfterUpdateEventHandler.Interface`:** - -```typescript -interface PageAfterUpdateEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Event payload `PageAfterUpdatePayload`:** - -```typescript -interface PageAfterUpdatePayload { - original: WbPage; - input: { - id: string; - data: IUpdateWbPageData; - }; - page: WbPage; -} -``` - -**Types:** - -```typescript -namespace PageAfterUpdateEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; - type Page = WbPage; -} -``` - -### `PageBeforeCreateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { PageBeforeCreateEventHandler } from "webiny/api/website-builder/page"; -``` - -**Interface `PageBeforeCreateEventHandler.Interface`:** - -```typescript -interface PageBeforeCreateEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Event payload `PageBeforeCreatePayload`:** - -```typescript -interface PageBeforeCreatePayload { - input: ICreateWbPageParams; -} -``` - -**Types:** - -```typescript -namespace PageBeforeCreateEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; - type Page = WbPage; -} -``` - -### `PageBeforeCreateRevisionFromEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { PageBeforeCreateRevisionFromEventHandler } from "webiny/api/website-builder/page"; -``` - -**Interface `PageBeforeCreateRevisionFromEventHandler.Interface`:** - -```typescript -interface PageBeforeCreateRevisionFromEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Event payload `PageBeforeCreateRevisionFromPayload`:** - -```typescript -interface PageBeforeCreateRevisionFromPayload { - params: ICreateWbPageRevisionFromParams; -} -``` - -**Types:** - -```typescript -namespace PageBeforeCreateRevisionFromEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; - type Page = WbPage; -} -``` - -### `PageBeforeDeleteEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { PageBeforeDeleteEventHandler } from "webiny/api/website-builder/page"; -``` - -**Interface `PageBeforeDeleteEventHandler.Interface`:** - -```typescript -interface PageBeforeDeleteEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Event payload `PageBeforeDeletePayload`:** - -```typescript -interface PageBeforeDeletePayload { - page: WbPage; -} -``` - -**Types:** - -```typescript -namespace PageBeforeDeleteEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; - type Page = WbPage; -} -``` - -### `PageBeforeDuplicateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { PageBeforeDuplicateEventHandler } from "webiny/api/website-builder/page"; -``` - -**Interface `PageBeforeDuplicateEventHandler.Interface`:** - -```typescript -interface PageBeforeDuplicateEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Event payload `PageBeforeDuplicatePayload`:** - -```typescript -interface PageBeforeDuplicatePayload { - original: WbPage; -} -``` - -**Types:** - -```typescript -namespace PageBeforeDuplicateEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; - type Page = WbPage; -} -``` - -### `PageBeforeMoveEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { PageBeforeMoveEventHandler } from "webiny/api/website-builder/page"; -``` - -**Interface `PageBeforeMoveEventHandler.Interface`:** - -```typescript -interface PageBeforeMoveEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Event payload `PageBeforeMovePayload`:** - -```typescript -interface PageBeforeMovePayload { - original: WbPage; - input: IMoveWbPageParams; -} -``` - -**Types:** - -```typescript -namespace PageBeforeMoveEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; - type Page = WbPage; -} -``` - -### `PageBeforePublishEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { PageBeforePublishEventHandler } from "webiny/api/website-builder/page"; -``` - -**Interface `PageBeforePublishEventHandler.Interface`:** - -```typescript -interface PageBeforePublishEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Event payload `PageBeforePublishPayload`:** - -```typescript -interface PageBeforePublishPayload { - page: WbPage; -} -``` - -**Types:** - -```typescript -namespace PageBeforePublishEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; - type Page = WbPage; -} -``` - -### `PageBeforeUnpublishEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { PageBeforeUnpublishEventHandler } from "webiny/api/website-builder/page"; -``` - -**Interface `PageBeforeUnpublishEventHandler.Interface`:** - -```typescript -interface PageBeforeUnpublishEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Event payload `PageBeforeUnpublishPayload`:** - -```typescript -interface PageBeforeUnpublishPayload { - page: WbPage; -} -``` - -**Types:** - -```typescript -namespace PageBeforeUnpublishEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; - type Page = WbPage; -} -``` - -### `PageBeforeUpdateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/website-builder/page` - -```typescript -import { PageBeforeUpdateEventHandler } from "webiny/api/website-builder/page"; -``` - -**Interface `PageBeforeUpdateEventHandler.Interface`:** - -```typescript -interface PageBeforeUpdateEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Event payload `PageBeforeUpdatePayload`:** - -```typescript -interface PageBeforeUpdatePayload { - original: WbPage; - input: { - id: string; - data: IUpdateWbPageData; - }; -} -``` - -**Types:** - -```typescript -namespace PageBeforeUpdateEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; - type Page = WbPage; -} -``` diff --git a/docs/developer-docs/6.x/reference/api/website-builder/redirect.ai.txt b/docs/developer-docs/6.x/reference/api/website-builder/redirect.ai.txt deleted file mode 100644 index f8f539a9c..000000000 --- a/docs/developer-docs/6.x/reference/api/website-builder/redirect.ai.txt +++ /dev/null @@ -1,32 +0,0 @@ -AI Context: Redirect (reference/api/website-builder/redirect.mdx) - -Source of Information: -1. packages/webiny/src/api/website-builder/redirect.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-website-builder/src/features/redirects/CreateRedirect/abstractions.ts — originating source -3. /Users/adrian/dev/wby-next/packages/api-website-builder/src/features/redirects/DeleteRedirect/abstractions.ts — originating source -4. /Users/adrian/dev/wby-next/packages/api-website-builder/src/features/redirects/GetActiveRedirects/abstractions.ts — originating source -5. /Users/adrian/dev/wby-next/packages/api-website-builder/src/features/redirects/GetRedirectById/abstractions.ts — originating source -6. /Users/adrian/dev/wby-next/packages/api-website-builder/src/features/redirects/InvalidateRedirectsCache/abstractions.ts — originating source -7. /Users/adrian/dev/wby-next/packages/api-website-builder/src/features/redirects/ListRedirects/abstractions.ts — originating source -8. /Users/adrian/dev/wby-next/packages/api-website-builder/src/features/redirects/MoveRedirect/abstractions.ts — originating source -9. /Users/adrian/dev/wby-next/packages/api-website-builder/src/features/redirects/UpdateRedirect/abstractions.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -CreateRedirectUseCase, RedirectAfterCreateEventHandler, RedirectBeforeCreateEventHandler, DeleteRedirectUseCase, RedirectAfterDeleteEventHandler, RedirectBeforeDeleteEventHandler, GetActiveRedirectsUseCase, GetRedirectByIdUseCase, InvalidateRedirectsCacheUseCase, ListRedirectsUseCase, MoveRedirectUseCase, RedirectAfterMoveEventHandler, RedirectBeforeMoveEventHandler, UpdateRedirectUseCase, RedirectAfterUpdateEventHandler, RedirectBeforeUpdateEventHandler - -Import Path: webiny/api/website-builder/redirect - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/website-builder/redirect.mdx b/docs/developer-docs/6.x/reference/api/website-builder/redirect.mdx deleted file mode 100644 index 24f7ea5be..000000000 --- a/docs/developer-docs/6.x/reference/api/website-builder/redirect.mdx +++ /dev/null @@ -1,561 +0,0 @@ ---- -id: yxbpl3dl -title: Redirect -description: "Website Builder redirect use cases and event handlers" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What use cases are available in `webiny/api/website-builder/redirect`? -- Which event handlers can you implement? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/website-builder/redirect`. Import any of the items below directly from this path in your Webiny extensions. - -**Use Cases** - - - -**Event Handlers** - - - -## Use Cases - -### `CreateRedirectUseCase` - -**Use Case Abstraction** — imported from `webiny/api/website-builder/redirect` - -```typescript -import { CreateRedirectUseCase } from "webiny/api/website-builder/redirect"; -``` - -**Interface `CreateRedirectUseCase.Interface`:** - -```typescript -interface CreateRedirectUseCase.Interface { - execute(data: ICreateWbRedirectData): Promise>; -} -``` - -**Types:** - -```typescript -namespace CreateRedirectUseCase { - type Interface = ICreateRedirectUseCase; - type Params = ICreateWbRedirectData; - type Return = Promise>; - type Error = UseCaseError; - type Redirect = WbRedirect; -} -``` - -### `DeleteRedirectUseCase` - -**Use Case Abstraction** — imported from `webiny/api/website-builder/redirect` - -```typescript -import { DeleteRedirectUseCase } from "webiny/api/website-builder/redirect"; -``` - -**Interface `DeleteRedirectUseCase.Interface`:** - -```typescript -interface DeleteRedirectUseCase.Interface { - execute(params: IDeleteWbRedirectParams): Promise>; -} -``` - -**Types:** - -```typescript -namespace DeleteRedirectUseCase { - type Interface = IDeleteRedirectUseCase; - type Params = IDeleteWbRedirectParams; - type Return = Promise>; - type Error = UseCaseError; -} -``` - -### `GetActiveRedirectsUseCase` - -**Use Case Abstraction** — imported from `webiny/api/website-builder/redirect` - -```typescript -import { GetActiveRedirectsUseCase } from "webiny/api/website-builder/redirect"; -``` - -**Interface `GetActiveRedirectsUseCase.Interface`:** - -GetActiveRedirects use case interface - -```typescript -interface GetActiveRedirectsUseCase.Interface { - execute(): Promise>; -} -``` - -**Types:** - -```typescript -namespace GetActiveRedirectsUseCase { - type Interface = IGetActiveRedirectsUseCase; - type Return = Promise>; - type Error = UseCaseError; - type Redirect = WbRedirect; -} -``` - -### `GetRedirectByIdUseCase` - -**Use Case Abstraction** — imported from `webiny/api/website-builder/redirect` - -```typescript -import { GetRedirectByIdUseCase } from "webiny/api/website-builder/redirect"; -``` - -**Interface `GetRedirectByIdUseCase.Interface`:** - -GetRedirectById use case interface - -```typescript -interface GetRedirectByIdUseCase.Interface { - execute(id: string): Promise>; -} -``` - -**Types:** - -```typescript -namespace GetRedirectByIdUseCase { - type Interface = IGetRedirectByIdUseCase; - type Return = Promise>; - type Error = UseCaseError; - type Redirect = WbRedirect; -} -``` - -### `InvalidateRedirectsCacheUseCase` - -**Use Case Abstraction** — imported from `webiny/api/website-builder/redirect` - -```typescript -import { InvalidateRedirectsCacheUseCase } from "webiny/api/website-builder/redirect"; -``` - -**Interface `InvalidateRedirectsCacheUseCase.Interface`:** - -```typescript -interface InvalidateRedirectsCacheUseCase.Interface { - execute(): Promise>; -} -``` - -**Types:** - -```typescript -namespace InvalidateRedirectsCacheUseCase { - type Interface = IInvalidateRedirectsCacheUseCase; - type Return = Promise>; - type Error = UseCaseError; -} -``` - -### `ListRedirectsUseCase` - -**Use Case Abstraction** — imported from `webiny/api/website-builder/redirect` - -```typescript -import { ListRedirectsUseCase } from "webiny/api/website-builder/redirect"; -``` - -**Interface `ListRedirectsUseCase.Interface`:** - -```typescript -interface ListRedirectsUseCase.Interface { - execute(params: ListWbRedirectsParams): Promise>; -} -``` - -**Types:** - -```typescript -namespace ListRedirectsUseCase { - type Interface = IListRedirectsUseCase; - type Params = ListWbRedirectsParams; - type Return = Promise>; - type Error = UseCaseError; - type Redirect = WbRedirect; -} -``` - -### `MoveRedirectUseCase` - -**Use Case Abstraction** — imported from `webiny/api/website-builder/redirect` - -```typescript -import { MoveRedirectUseCase } from "webiny/api/website-builder/redirect"; -``` - -**Interface `MoveRedirectUseCase.Interface`:** - -```typescript -interface MoveRedirectUseCase.Interface { - execute(params: IMoveWbRedirectParams): Promise>; -} -``` - -**Types:** - -```typescript -namespace MoveRedirectUseCase { - type Interface = IMoveRedirectUseCase; - type Params = IMoveWbRedirectParams; - type Return = Promise>; - type Error = UseCaseError; - type Redirect = WbRedirect; -} -``` - -### `UpdateRedirectUseCase` - -**Use Case Abstraction** — imported from `webiny/api/website-builder/redirect` - -```typescript -import { UpdateRedirectUseCase } from "webiny/api/website-builder/redirect"; -``` - -**Interface `UpdateRedirectUseCase.Interface`:** - -```typescript -interface UpdateRedirectUseCase.Interface { - execute(id: string, data: IUpdateWbRedirectData): Promise>; -} -``` - -**Types:** - -```typescript -namespace UpdateRedirectUseCase { - type Interface = IUpdateRedirectUseCase; - type UpdateData = IUpdateWbRedirectData; - type Return = Promise>; - type Error = UseCaseError; - type Redirect = WbRedirect; -} -``` - -## Event Handlers - -### `RedirectAfterCreateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/website-builder/redirect` - -```typescript -import { RedirectAfterCreateEventHandler } from "webiny/api/website-builder/redirect"; -``` - -**Interface `RedirectAfterCreateEventHandler.Interface`:** - -```typescript -interface RedirectAfterCreateEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Event payload `RedirectAfterCreatePayload`:** - -```typescript -interface RedirectAfterCreatePayload { - redirect: WbRedirect; -} -``` - -**Types:** - -```typescript -namespace RedirectAfterCreateEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; - type Redirect = WbRedirect; -} -``` - -### `RedirectAfterDeleteEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/website-builder/redirect` - -```typescript -import { RedirectAfterDeleteEventHandler } from "webiny/api/website-builder/redirect"; -``` - -**Interface `RedirectAfterDeleteEventHandler.Interface`:** - -```typescript -interface RedirectAfterDeleteEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Event payload `RedirectAfterDeletePayload`:** - -```typescript -interface RedirectAfterDeletePayload { - redirect: WbRedirect; -} -``` - -**Types:** - -```typescript -namespace RedirectAfterDeleteEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; - type Redirect = WbRedirect; -} -``` - -### `RedirectAfterMoveEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/website-builder/redirect` - -```typescript -import { RedirectAfterMoveEventHandler } from "webiny/api/website-builder/redirect"; -``` - -**Interface `RedirectAfterMoveEventHandler.Interface`:** - -```typescript -interface RedirectAfterMoveEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Event payload `RedirectAfterMovePayload`:** - -```typescript -interface RedirectAfterMovePayload { - original: WbRedirect; - input: IMoveWbRedirectParams; - redirect: WbRedirect; -} -``` - -**Types:** - -```typescript -namespace RedirectAfterMoveEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; - type Redirect = WbRedirect; -} -``` - -### `RedirectAfterUpdateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/website-builder/redirect` - -```typescript -import { RedirectAfterUpdateEventHandler } from "webiny/api/website-builder/redirect"; -``` - -**Interface `RedirectAfterUpdateEventHandler.Interface`:** - -```typescript -interface RedirectAfterUpdateEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Event payload `RedirectAfterUpdatePayload`:** - -```typescript -interface RedirectAfterUpdatePayload { - original: WbRedirect; - input: { - id: string; - data: IUpdateWbRedirectData; - }; - redirect: WbRedirect; -} -``` - -**Types:** - -```typescript -namespace RedirectAfterUpdateEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; - type Redirect = WbRedirect; -} -``` - -### `RedirectBeforeCreateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/website-builder/redirect` - -```typescript -import { RedirectBeforeCreateEventHandler } from "webiny/api/website-builder/redirect"; -``` - -**Interface `RedirectBeforeCreateEventHandler.Interface`:** - -```typescript -interface RedirectBeforeCreateEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Event payload `RedirectBeforeCreatePayload`:** - -```typescript -interface RedirectBeforeCreatePayload { - input: ICreateWbRedirectData; -} -``` - -**Types:** - -```typescript -namespace RedirectBeforeCreateEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; - type Redirect = WbRedirect; -} -``` - -### `RedirectBeforeDeleteEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/website-builder/redirect` - -```typescript -import { RedirectBeforeDeleteEventHandler } from "webiny/api/website-builder/redirect"; -``` - -**Interface `RedirectBeforeDeleteEventHandler.Interface`:** - -```typescript -interface RedirectBeforeDeleteEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Event payload `RedirectBeforeDeletePayload`:** - -```typescript -interface RedirectBeforeDeletePayload { - redirect: WbRedirect; -} -``` - -**Types:** - -```typescript -namespace RedirectBeforeDeleteEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; - type Redirect = WbRedirect; -} -``` - -### `RedirectBeforeMoveEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/website-builder/redirect` - -```typescript -import { RedirectBeforeMoveEventHandler } from "webiny/api/website-builder/redirect"; -``` - -**Interface `RedirectBeforeMoveEventHandler.Interface`:** - -```typescript -interface RedirectBeforeMoveEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Event payload `RedirectBeforeMovePayload`:** - -```typescript -interface RedirectBeforeMovePayload { - original: WbRedirect; - input: IMoveWbRedirectParams; -} -``` - -**Types:** - -```typescript -namespace RedirectBeforeMoveEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; - type Redirect = WbRedirect; -} -``` - -### `RedirectBeforeUpdateEventHandler` - -**Event Handler Abstraction** — imported from `webiny/api/website-builder/redirect` - -```typescript -import { RedirectBeforeUpdateEventHandler } from "webiny/api/website-builder/redirect"; -``` - -**Interface `RedirectBeforeUpdateEventHandler.Interface`:** - -```typescript -interface RedirectBeforeUpdateEventHandler.Interface { - handle(event: DomainEvent): Promise; -} -``` - -**Event payload `RedirectBeforeUpdatePayload`:** - -```typescript -interface RedirectBeforeUpdatePayload { - original: WbRedirect; - input: { - id: string; - data: IUpdateWbRedirectData; - }; -} -``` - -**Types:** - -```typescript -namespace RedirectBeforeUpdateEventHandler { - type Interface = IEventHandler>; - type Event = DomainEvent; - type Redirect = WbRedirect; -} -``` diff --git a/docs/developer-docs/6.x/reference/api/website-builder/scheduler.ai.txt b/docs/developer-docs/6.x/reference/api/website-builder/scheduler.ai.txt deleted file mode 100644 index 388051b78..000000000 --- a/docs/developer-docs/6.x/reference/api/website-builder/scheduler.ai.txt +++ /dev/null @@ -1,28 +0,0 @@ -AI Context: Scheduler (reference/api/website-builder/scheduler.mdx) - -Source of Information: -1. packages/webiny/src/api/website-builder/scheduler.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/api-website-builder-scheduler/src/features/SchedulePublishPageUseCase/abstractions.ts — originating source -3. /Users/adrian/dev/wby-next/packages/api-website-builder-scheduler/src/features/ScheduleUnpublishPageUseCase/abstractions.ts — originating source -4. /Users/adrian/dev/wby-next/packages/api-website-builder-scheduler/src/features/SchedulePublishRedirectUseCase/abstractions.ts — originating source -5. /Users/adrian/dev/wby-next/packages/api-website-builder-scheduler/src/features/ScheduleUnpublishRedirectUseCase/abstractions.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -SchedulePublishPageUseCase, ScheduleUnpublishPageUseCase, SchedulePublishRedirectUseCase, ScheduleUnpublishRedirectUseCase - -Import Path: webiny/api/website-builder/scheduler - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/api/website-builder/scheduler.mdx b/docs/developer-docs/6.x/reference/api/website-builder/scheduler.mdx deleted file mode 100644 index d8696fce4..000000000 --- a/docs/developer-docs/6.x/reference/api/website-builder/scheduler.mdx +++ /dev/null @@ -1,138 +0,0 @@ ---- -id: yxbpl3dl -title: Scheduler -description: "Reference for webiny/api/website-builder/scheduler" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What use cases are available in `webiny/api/website-builder/scheduler`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/api/website-builder/scheduler`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `SchedulePublishPageUseCase` - -**Use Case Abstraction** — imported from `webiny/api/website-builder/scheduler` - -```typescript -import { SchedulePublishPageUseCase } from "webiny/api/website-builder/scheduler"; -``` - -**Interface `SchedulePublishPageUseCase.Interface`:** - -```typescript -interface SchedulePublishPageUseCase.Interface { - execute(params: ISchedulePublishPageUseCaseParams): ISchedulePublishPageUseCaseResponse; -} -``` - -**Types:** - -```typescript -namespace SchedulePublishPageUseCase { - type Interface = ISchedulePublishPageUseCase; - type Error = ScheduleActionError; - type Params = ISchedulePublishPageUseCaseParams; - type Result = ISchedulePublishPageUseCaseResponse; -} -``` - -## `SchedulePublishRedirectUseCase` - -**Use Case Abstraction** — imported from `webiny/api/website-builder/scheduler` - -```typescript -import { SchedulePublishRedirectUseCase } from "webiny/api/website-builder/scheduler"; -``` - -**Interface `SchedulePublishRedirectUseCase.Interface`:** - -```typescript -interface SchedulePublishRedirectUseCase.Interface { - execute(params: ISchedulePublishRedirectUseCaseParams): ISchedulePublishRedirectUseCaseResponse; -} -``` - -**Types:** - -```typescript -namespace SchedulePublishRedirectUseCase { - type Interface = ISchedulePublishRedirectUseCase; - type Error = ScheduleActionError; - type Params = ISchedulePublishRedirectUseCaseParams; - type Result = ISchedulePublishRedirectUseCaseResponse; -} -``` - -## `ScheduleUnpublishPageUseCase` - -**Use Case Abstraction** — imported from `webiny/api/website-builder/scheduler` - -```typescript -import { ScheduleUnpublishPageUseCase } from "webiny/api/website-builder/scheduler"; -``` - -**Interface `ScheduleUnpublishPageUseCase.Interface`:** - -```typescript -interface ScheduleUnpublishPageUseCase.Interface { - execute(params: IScheduleUnpublishPageUseCaseParams): IScheduleUnpublishPageUseCaseResponse; -} -``` - -**Types:** - -```typescript -namespace ScheduleUnpublishPageUseCase { - type Interface = IScheduleUnpublishPageUseCase; - type Error = ScheduleActionError; - type Params = IScheduleUnpublishPageUseCaseParams; - type Result = IScheduleUnpublishPageUseCaseResponse; -} -``` - -## `ScheduleUnpublishRedirectUseCase` - -**Use Case Abstraction** — imported from `webiny/api/website-builder/scheduler` - -```typescript -import { ScheduleUnpublishRedirectUseCase } from "webiny/api/website-builder/scheduler"; -``` - -**Interface `ScheduleUnpublishRedirectUseCase.Interface`:** - -```typescript -interface ScheduleUnpublishRedirectUseCase.Interface { - execute( - params: IScheduleUnpublishRedirectUseCaseParams - ): IScheduleUnpublishRedirectUseCaseResponse; -} -``` - -**Types:** - -```typescript -namespace ScheduleUnpublishRedirectUseCase { - type Interface = IScheduleUnpublishRedirectUseCase; - type Error = ScheduleActionError; - type Params = IScheduleUnpublishRedirectUseCaseParams; - type Result = IScheduleUnpublishRedirectUseCaseResponse; -} -``` diff --git a/docs/developer-docs/6.x/reference/cli.ai.txt b/docs/developer-docs/6.x/reference/cli.ai.txt deleted file mode 100644 index 7f9600287..000000000 --- a/docs/developer-docs/6.x/reference/cli.ai.txt +++ /dev/null @@ -1,26 +0,0 @@ -AI Context: CLI (reference/cli.mdx) - -Source of Information: -1. packages/webiny/src/cli.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/cli-core/src/abstractions/services/LoggerService.ts — originating source -3. /Users/adrian/dev/wby-next/packages/cli-core/src/abstractions/services/UiService.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -Logger, Ui - -Import Path: webiny/cli - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/cli.mdx b/docs/developer-docs/6.x/reference/cli.mdx deleted file mode 100644 index 23d17eb36..000000000 --- a/docs/developer-docs/6.x/reference/cli.mdx +++ /dev/null @@ -1,88 +0,0 @@ ---- -id: y2xp0000 -title: CLI -description: "Reference for webiny/cli" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/cli`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/cli`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `Logger` - -**Abstraction** — imported from `webiny/cli` - -```typescript -import { Logger } from "webiny/cli"; -``` - -**Interface `Logger.Interface`:** - -```typescript -interface Logger.Interface { - trace(objOrMsg: object | string, ...args: any[]): void; - debug(objOrMsg: object | string, ...args: any[]): void; - info(objOrMsg: object | string, ...args: any[]): void; - warn(objOrMsg: object | string, ...args: any[]): void; - error(objOrMsg: object | string, ...args: any[]): void; - fatal(objOrMsg: object | string, ...args: any[]): void; - log(objOrMsg: object | string, ...args: any[]): void; -} -``` - -**Types:** - -```typescript -namespace Logger { - type Interface = ILoggerService; -} -``` - -## `Ui` - -**Abstraction** — imported from `webiny/cli` - -```typescript -import { Ui } from "webiny/cli"; -``` - -**Interface `Ui.Interface`:** - -```typescript -interface Ui.Interface { - raw(text: string): void; - text(text: string): void; - textBold(text: string): void; - emptyLine(): void; - info(text: string, ...args: any[]): void; - success(text: string, ...args: any[]): void; - error(text: string, ...args: any[]): void; - warning(text: string, ...args: any[]): void; - debug(text: string, ...args: any[]): void; -} -``` - -**Types:** - -```typescript -namespace Ui { - type Interface = IUiService; -} -``` diff --git a/docs/developer-docs/6.x/reference/cli/command.ai.txt b/docs/developer-docs/6.x/reference/cli/command.ai.txt deleted file mode 100644 index f27041e88..000000000 --- a/docs/developer-docs/6.x/reference/cli/command.ai.txt +++ /dev/null @@ -1,25 +0,0 @@ -AI Context: Command (reference/cli/command.mdx) - -Source of Information: -1. packages/webiny/src/cli/command.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/cli-core/src/abstractions/features/CliCommand.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -CliCommandFactory - -Import Path: webiny/cli/command - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/cli/command.mdx b/docs/developer-docs/6.x/reference/cli/command.mdx deleted file mode 100644 index 3c3df8e89..000000000 --- a/docs/developer-docs/6.x/reference/cli/command.mdx +++ /dev/null @@ -1,40 +0,0 @@ ---- -id: y2xpl2nv -title: Command -description: "CLI command factory abstraction" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- How to use the builder and factory APIs? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/cli/command`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `CliCommandFactory` - -**Abstraction** — imported from `webiny/cli/command` - -```typescript -import { CliCommandFactory } from "webiny/cli/command"; -``` - -**Types:** - -```typescript -namespace CliCommandFactory { - type Interface = ICliCommand; - type ParamDefinition = ICliCommandParamDefinition; - type OptionDefinition = ICliCommandOptionDefinition; - type CommandDefinition = ICliCommandDefinition; -} -``` diff --git a/docs/developer-docs/6.x/reference/extensions.ai.txt b/docs/developer-docs/6.x/reference/extensions.ai.txt deleted file mode 100644 index c0a13101c..000000000 --- a/docs/developer-docs/6.x/reference/extensions.ai.txt +++ /dev/null @@ -1,29 +0,0 @@ -AI Context: Extensions (reference/extensions.mdx) - -Source of Information: -1. packages/webiny/src/extensions.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/project-aws/src/api.ts — originating source -3. /Users/adrian/dev/wby-next/packages/project-aws/src/admin.ts — originating source -4. /Users/adrian/dev/wby-next/packages/project-aws/src/cli.ts — originating source -5. /Users/adrian/dev/wby-next/packages/project-aws/src/infra.ts — originating source -6. /Users/adrian/dev/wby-next/packages/project-aws/src/project.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -Api, Admin, Cli, Infra, Project - -Import Path: webiny/extensions - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/extensions.mdx b/docs/developer-docs/6.x/reference/extensions.mdx deleted file mode 100644 index 716a0f757..000000000 --- a/docs/developer-docs/6.x/reference/extensions.mdx +++ /dev/null @@ -1,581 +0,0 @@ ---- -id: zxh0zw5z -title: Extensions -description: "Reference for all webiny/extensions exports — React components used in webiny.config.tsx to wire extensions into the project." ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What extension components are available in `webiny/extensions`? -- What parameters does each extension accept? -- How to use each extension in your `webiny.config.tsx`? - - - -## Overview - -The `webiny/extensions` package exports React components used inside `webiny.config.tsx` to wire extensions into your Webiny project. Each component corresponds to a `defineExtension()` call in the Webiny source and accepts typed props defined by its Zod schema. - -**Api** - - - -**Admin** - - - -**Cli** - - - -**Infra** - - - -**Project** - - - -## Api - -### `Extension` - -Add any API extension. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Api } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `BuildParam` - -Add build-time parameter to API app. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Api } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -## Admin - -### `Extension` - -Extend the Admin application with custom functionality. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Admin } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `BuildParam` - -Add build-time parameter to Admin app. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Admin } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -## Cli - -### `Command` - -An extension for defining CLI commands. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Cli } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -## Infra - -### `Vpc` - -Apply VPC settings to AWS resources during deployment. - -Can only be used **once**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `BlueGreenDeployments` - -Enable blue/green deployments for your Webiny project. - -Can only be used **once**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `OpenSearch` - -Enable and configure Opensearch integration with project-level setup. - -Can only be used **once**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `PulumiResourceNamePrefix` - -Adjust the prefix for Pulumi resource names (default: "wby-"). - -Can only be used **once**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `ProductionEnvironments` - -Provide names for environments that are considered production environments. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `EnvVar` - -Set an environment variable in the project context. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `Aws.DefaultRegion` - -Set the default AWS region for the project. - -Can only be used **once**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `Aws.Tags` - -Apply tags to AWS resources during deployment. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `Admin.BeforeBuild` - -Add custom logic to be executed before the ADMIN build process. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `Admin.BeforeDeploy` - -Add custom logic to be executed before the ADMIN deployment process. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `Admin.BeforeWatch` - -Add custom logic to be executed before the Admin watch process. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `Admin.AfterBuild` - -Add custom logic to be executed after the ADMIN build process. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `Admin.AfterDeploy` - -Add custom logic to be executed after the ADMIN deployment process. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `Admin.Pulumi` - -Modify Admin app's cloud infrastructure using Pulumi. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `Admin.CustomDomains` - -Configure custom domains for the Admin app. - -Can only be used **once**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `Admin.StackOutputValue` - -Add custom output values to the Admin stack. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `Api.BeforeBuild` - -Add custom logic to be executed before the API build process. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `Api.BeforeDeploy` - -Add custom logic to be executed before the API deployment process. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `Api.BeforeWatch` - -Add custom logic to be executed before the API watch process. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `Api.AfterBuild` - -Add custom logic to be executed after the API build process. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `Api.AfterDeploy` - -Add custom logic to be executed after the API deployment process. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `Api.Pulumi` - -Modify Api app's cloud infrastructure using Pulumi. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `Api.StackOutputValue` - -Add custom output values to the Api stack. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `Api.LambdaFunction` - -Add a custom Lambda function to the API app. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `Core.BeforeBuild` - -Add custom logic to be executed before the CORE build process. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `Core.BeforeDeploy` - -Add custom logic to be executed before the CORE deployment process. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `Core.BeforeWatch` - -Add custom logic to be executed before the CORE watch process. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `Core.AfterBuild` - -Add custom logic to be executed after the CORE build process. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `Core.AfterDeploy` - -Add custom logic to be executed after the CORE deployment process. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `Core.Pulumi` - -Modify Core app's cloud infrastructure using Pulumi. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `Core.StackOutputValue` - -Add custom output values to the Core stack. - -Can be used **multiple times**. - -```tsx webiny.config.tsx -import { Infra } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -## Project - -### `Id` - -An extension for defining the project ID. - -Can only be used **once**. - -```tsx webiny.config.tsx -import { Project } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `Telemetry` - -This extension allows you to enable or disable telemetry for the project. - -Can only be used **once**. - -```tsx webiny.config.tsx -import { Project } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `AutoInstall` - -Auto-install Webiny with admin user credentials on first deploy. - -Can only be used **once**. - -```tsx webiny.config.tsx -import { Project } from "webiny/extensions"; - -export const Extensions = () => ; -``` - -### `FeatureFlags` - -Enable or disable WCP features. - -Can only be used **once**. - -```tsx webiny.config.tsx -import { Project } from "webiny/extensions"; - -export const Extensions = () => ; -``` diff --git a/docs/developer-docs/6.x/reference/infra.ai.txt b/docs/developer-docs/6.x/reference/infra.ai.txt deleted file mode 100644 index 25d2425d4..000000000 --- a/docs/developer-docs/6.x/reference/infra.ai.txt +++ /dev/null @@ -1,33 +0,0 @@ -AI Context: Infrastructure (reference/infra.mdx) - -Source of Information: -1. packages/webiny/src/infra.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/project/src/abstractions/services/LoggerService.ts — originating source -3. /Users/adrian/dev/wby-next/packages/project/src/abstractions/services/UiService.ts — originating source -4. /Users/adrian/dev/wby-next/packages/project/src/abstractions/features/hooks/AfterBuild.ts — originating source -5. /Users/adrian/dev/wby-next/packages/project/src/abstractions/features/hooks/BeforeBuild.ts — originating source -6. /Users/adrian/dev/wby-next/packages/project/src/abstractions/features/hooks/AfterDeploy.ts — originating source -7. /Users/adrian/dev/wby-next/packages/project/src/abstractions/features/hooks/BeforeDeploy.ts — originating source -8. /Users/adrian/dev/wby-next/packages/project/src/abstractions/features/hooks/BeforeWatch.ts — originating source -9. /Users/adrian/dev/wby-next/packages/project/src/extensions/EnvVar.ts — originating source -10. /Users/adrian/dev/wby-next/packages/project-aws/src/abstractions/index.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -Logger, Ui, AfterBuildHook, BeforeBuildHook, AfterDeployHook, BeforeDeployHook, BeforeWatchHook, EnvVar, ApiStackOutput, CoreStackOutput, ApiGqlClient, AdminStackOutput, InvokeLambdaFunction - -Import Path: webiny/infra - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/infra.mdx b/docs/developer-docs/6.x/reference/infra.mdx deleted file mode 100644 index 346a356c4..000000000 --- a/docs/developer-docs/6.x/reference/infra.mdx +++ /dev/null @@ -1,377 +0,0 @@ ---- -id: aw5mcme0 -title: Infrastructure -description: "Reference for webiny/infra" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/infra`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/infra`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `AdminStackOutput` - -**Abstraction** — imported from `webiny/infra` - -```typescript -import { AdminStackOutput } from "webiny/infra"; -``` - -**Interface `AdminStackOutput.Interface`:** - -```typescript -interface AdminStackOutput.Interface { - execute(): Promise; -} -``` - -**Types:** - -```typescript -namespace AdminStackOutput { - type Interface = IAdminStackOutputService; - type Output = IAdminStackOutput; -} -``` - -## `AfterBuildHook` - -**Abstraction** — imported from `webiny/infra` - -```typescript -import { AfterBuildHook } from "webiny/infra"; -``` - -**Interface `AfterBuildHook.Interface`:** - -```typescript -interface AfterBuildHook.Interface { - execute(params: BuildApp.Params): void | Promise; -} -``` - -**Types:** - -```typescript -namespace AfterBuildHook { - type Interface = IAfterBuild; - type Params = BuildApp.Params; -} -``` - -## `AfterDeployHook` - -**Abstraction** — imported from `webiny/infra` - -```typescript -import { AfterDeployHook } from "webiny/infra"; -``` - -**Interface `AfterDeployHook.Interface`:** - -```typescript -interface AfterDeployHook.Interface { - execute(params: DeployApp.Params): void | Promise; -} -``` - -**Types:** - -```typescript -namespace AfterDeployHook { - type Interface = IAfterDeploy; - type Params = DeployApp.Params; -} -``` - -## `ApiGqlClient` - -**Abstraction** — imported from `webiny/infra` - -```typescript -import { ApiGqlClient } from "webiny/infra"; -``` - -**Interface `ApiGqlClient.Interface`:** - -```typescript -interface ApiGqlClient.Interface { - query(params: { - query: string; - variables?: Record; - }): Promise>; - mutation(params: { - mutation: string; - variables?: Record; - }): Promise>; -} -``` - -**Types:** - -```typescript -namespace ApiGqlClient { - type Interface = IApiGqlClient; - type Response = IApiGqlClientResponse; -} -``` - -## `ApiStackOutput` - -**Abstraction** — imported from `webiny/infra` - -```typescript -import { ApiStackOutput } from "webiny/infra"; -``` - -**Interface `ApiStackOutput.Interface`:** - -```typescript -interface ApiStackOutput.Interface { - execute(): Promise; -} -``` - -**Types:** - -```typescript -namespace ApiStackOutput { - type Interface = IApiStackOutputService; - type Output = IApiStackOutput; -} -``` - -## `BeforeBuildHook` - -**Abstraction** — imported from `webiny/infra` - -```typescript -import { BeforeBuildHook } from "webiny/infra"; -``` - -**Interface `BeforeBuildHook.Interface`:** - -```typescript -interface BeforeBuildHook.Interface { - execute(params: BuildApp.Params): void | Promise; -} -``` - -**Types:** - -```typescript -namespace BeforeBuildHook { - type Interface = IBeforeBuild; - type Params = BuildApp.Params; -} -``` - -## `BeforeDeployHook` - -**Abstraction** — imported from `webiny/infra` - -```typescript -import { BeforeDeployHook } from "webiny/infra"; -``` - -**Interface `BeforeDeployHook.Interface`:** - -```typescript -interface BeforeDeployHook.Interface { - execute(params: DeployApp.Params): void | Promise; -} -``` - -**Types:** - -```typescript -namespace BeforeDeployHook { - type Interface = IBeforeDeploy; - type Params = DeployApp.Params; -} -``` - -## `BeforeWatchHook` - -**Abstraction** — imported from `webiny/infra` - -```typescript -import { BeforeWatchHook } from "webiny/infra"; -``` - -**Interface `BeforeWatchHook.Interface`:** - -```typescript -interface BeforeWatchHook.Interface { - execute(params: Watch.Params): void | Promise; -} -``` - -**Types:** - -```typescript -namespace BeforeWatchHook { - type Interface = IBeforeWatch; - type Params = Watch.Params; -} -``` - -## `CoreStackOutput` - -**Abstraction** — imported from `webiny/infra` - -```typescript -import { CoreStackOutput } from "webiny/infra"; -``` - -**Interface `CoreStackOutput.Interface`:** - -```typescript -interface CoreStackOutput.Interface { - execute(): Promise; -} -``` - -**Types:** - -```typescript -namespace CoreStackOutput { - type Interface = ICoreStackOutputService; - type Output = ICoreStackOutput; -} -``` - -## `EnvVar` - -**Constant** — imported from `webiny/infra` - -```typescript -import { EnvVar } from "webiny/infra"; -``` - -```typescript -export const EnvVar = defineExtension({ - type: "Project/EnvVar", - tags: { runtimeContext: "project" }, - description: "Set an environment variable in the project context.", - multiple: true, - paramsSchema: z.object({ - // TODO: enable using `name` instead of `varName` for better consistency. - varName: z.string().describe("The environment variable name."), - value: z -``` - -## `InvokeLambdaFunction` - -**Abstraction** — imported from `webiny/infra` - -```typescript -import { InvokeLambdaFunction } from "webiny/infra"; -``` - -**Interface `InvokeLambdaFunction.Interface`:** - -```typescript -interface InvokeLambdaFunction.Interface { - execute(params: IInvokeLambdaFunctionParams): Promise>; -} -``` - -**Types:** - -```typescript -namespace InvokeLambdaFunction { - type Interface = IInvokeLambdaFunction; - type Params = IInvokeLambdaFunctionParams; - type Result = IInvokeLambdaFunctionResult; -} -``` - -## `Logger` - -**Abstraction** — imported from `webiny/infra` - -```typescript -import { Logger } from "webiny/infra"; -``` - -**Interface `Logger.Interface`:** - -```typescript -interface Logger.Interface { - trace(objOrMsg: object | string, ...args: any[]): void; - debug(objOrMsg: object | string, ...args: any[]): void; - info(objOrMsg: object | string, ...args: any[]): void; - warn(objOrMsg: object | string, ...args: any[]): void; - error(objOrMsg: object | string, ...args: any[]): void; - fatal(objOrMsg: object | string, ...args: any[]): void; - log(objOrMsg: object | string, ...args: any[]): void; -} -``` - -**Types:** - -```typescript -namespace Logger { - type Interface = ILoggerService; -} -``` - -## `Ui` - -**Abstraction** — imported from `webiny/infra` - -```typescript -import { Ui } from "webiny/infra"; -``` - -**Interface `Ui.Interface`:** - -```typescript -interface Ui.Interface { - raw(text: string): void; - text(text: string): void; - textBold(text: string): void; - emptyLine(): void; - info(text: string, ...args: any[]): void; - success(text: string, ...args: any[]): void; - error(text: string, ...args: any[]): void; - warning(text: string, ...args: any[]): void; - debug(text: string, ...args: any[]): void; -} -``` - -**Types:** - -```typescript -namespace Ui { - type Interface = IUiService; -} -``` diff --git a/docs/developer-docs/6.x/reference/infra/admin.ai.txt b/docs/developer-docs/6.x/reference/infra/admin.ai.txt deleted file mode 100644 index 82b32c1dd..000000000 --- a/docs/developer-docs/6.x/reference/infra/admin.ai.txt +++ /dev/null @@ -1,31 +0,0 @@ -AI Context: Admin (reference/infra/admin.mdx) - -Source of Information: -1. packages/webiny/src/infra/admin.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/project/src/abstractions/features/hooks/AdminAfterBuild.ts — originating source -3. /Users/adrian/dev/wby-next/packages/project/src/abstractions/features/hooks/AdminBeforeBuild.ts — originating source -4. /Users/adrian/dev/wby-next/packages/project/src/abstractions/features/hooks/AdminAfterDeploy.ts — originating source -5. /Users/adrian/dev/wby-next/packages/project/src/abstractions/features/hooks/AdminBeforeDeploy.ts — originating source -6. /Users/adrian/dev/wby-next/packages/project/src/abstractions/features/hooks/AdminBeforeWatch.ts — originating source -7. /Users/adrian/dev/wby-next/packages/project/src/abstractions/features/pulumi/AdminPulumi.ts — originating source -8. /Users/adrian/dev/wby-next/packages/project-aws/src/abstractions/services/AdminStackOutputService.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -AdminAfterBuildHook, AdminBeforeBuildHook, AdminAfterDeployHook, AdminBeforeDeployHook, AdminBeforeWatchHook, AdminPulumi, GetAdminStackOutput - -Import Path: webiny/infra/admin - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/infra/admin.mdx b/docs/developer-docs/6.x/reference/infra/admin.mdx deleted file mode 100644 index 52b6ce44a..000000000 --- a/docs/developer-docs/6.x/reference/infra/admin.mdx +++ /dev/null @@ -1,198 +0,0 @@ ---- -id: aw5mcmev -title: Admin -description: "Admin infrastructure lifecycle hooks and Pulumi abstraction" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/infra/admin`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/infra/admin`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `AdminAfterBuildHook` - -**Abstraction** — imported from `webiny/infra/admin` - -```typescript -import { AdminAfterBuildHook } from "webiny/infra/admin"; -``` - -**Interface `AdminAfterBuildHook.Interface`:** - -```typescript -interface AdminAfterBuildHook.Interface { - execute(params: BuildApp.Params): void | Promise; -} -``` - -**Types:** - -```typescript -namespace AdminAfterBuildHook { - type Interface = IAdminAfterBuild; - type Params = BuildApp.Params; -} -``` - -## `AdminAfterDeployHook` - -**Abstraction** — imported from `webiny/infra/admin` - -```typescript -import { AdminAfterDeployHook } from "webiny/infra/admin"; -``` - -**Interface `AdminAfterDeployHook.Interface`:** - -```typescript -interface AdminAfterDeployHook.Interface { - execute(params: DeployApp.Params): void | Promise; -} -``` - -**Types:** - -```typescript -namespace AdminAfterDeployHook { - type Interface = IAdminAfterDeploy; - type Params = DeployApp.Params; -} -``` - -## `AdminBeforeBuildHook` - -**Abstraction** — imported from `webiny/infra/admin` - -```typescript -import { AdminBeforeBuildHook } from "webiny/infra/admin"; -``` - -**Interface `AdminBeforeBuildHook.Interface`:** - -```typescript -interface AdminBeforeBuildHook.Interface { - execute(params: BuildApp.Params): void | Promise; -} -``` - -**Types:** - -```typescript -namespace AdminBeforeBuildHook { - type Interface = IAdminBeforeBuild; - type Params = BuildApp.Params; -} -``` - -## `AdminBeforeDeployHook` - -**Abstraction** — imported from `webiny/infra/admin` - -```typescript -import { AdminBeforeDeployHook } from "webiny/infra/admin"; -``` - -**Interface `AdminBeforeDeployHook.Interface`:** - -```typescript -interface AdminBeforeDeployHook.Interface { - execute(params: DeployApp.Params): void | Promise; -} -``` - -**Types:** - -```typescript -namespace AdminBeforeDeployHook { - type Interface = IAdminBeforeDeploy; - type Params = DeployApp.Params; -} -``` - -## `AdminBeforeWatchHook` - -**Abstraction** — imported from `webiny/infra/admin` - -```typescript -import { AdminBeforeWatchHook } from "webiny/infra/admin"; -``` - -**Interface `AdminBeforeWatchHook.Interface`:** - -```typescript -interface AdminBeforeWatchHook.Interface { - execute(params: Watch.WatchWithAppParams): void | Promise; -} -``` - -**Types:** - -```typescript -namespace AdminBeforeWatchHook { - type Interface = IAdminBeforeWatch; - type Params = Watch.WatchWithAppParams; -} -``` - -## `AdminPulumi` - -**Abstraction** — imported from `webiny/infra/admin` - -```typescript -import { AdminPulumi } from "webiny/infra/admin"; -``` - -**Types:** - -```typescript -namespace AdminPulumi { - type Interface = IAdminPulumi; - type Params = unknown; -} -``` - -## `GetAdminStackOutput` - -**Abstraction** — imported from `webiny/infra/admin` - -```typescript -import { GetAdminStackOutput } from "webiny/infra/admin"; -``` - -**Interface `GetAdminStackOutput.Interface`:** - -```typescript -interface GetAdminStackOutput.Interface { - execute(): Promise; -} -``` - -**Types:** - -```typescript -namespace GetAdminStackOutput { - type Interface = IAdminStackOutputService; - type Output = IAdminStackOutput; -} -``` diff --git a/docs/developer-docs/6.x/reference/infra/api.ai.txt b/docs/developer-docs/6.x/reference/infra/api.ai.txt deleted file mode 100644 index f0d65c33f..000000000 --- a/docs/developer-docs/6.x/reference/infra/api.ai.txt +++ /dev/null @@ -1,31 +0,0 @@ -AI Context: API (reference/infra/api.mdx) - -Source of Information: -1. packages/webiny/src/infra/api.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/project/src/abstractions/features/hooks/ApiAfterBuild.ts — originating source -3. /Users/adrian/dev/wby-next/packages/project/src/abstractions/features/hooks/ApiBeforeBuild.ts — originating source -4. /Users/adrian/dev/wby-next/packages/project/src/abstractions/features/hooks/ApiAfterDeploy.ts — originating source -5. /Users/adrian/dev/wby-next/packages/project/src/abstractions/features/hooks/ApiBeforeDeploy.ts — originating source -6. /Users/adrian/dev/wby-next/packages/project/src/abstractions/features/hooks/ApiBeforeWatch.ts — originating source -7. /Users/adrian/dev/wby-next/packages/project/src/abstractions/features/pulumi/ApiPulumi.ts — originating source -8. /Users/adrian/dev/wby-next/packages/project-aws/src/abstractions/services/ApiStackOutputService.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -ApiAfterBuildHook, ApiBeforeBuildHook, ApiAfterDeployHook, ApiBeforeDeployHook, ApiBeforeWatchHook, ApiPulumi, GetApiStackOutput - -Import Path: webiny/infra/api - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/infra/api.mdx b/docs/developer-docs/6.x/reference/infra/api.mdx deleted file mode 100644 index cb9614e18..000000000 --- a/docs/developer-docs/6.x/reference/infra/api.mdx +++ /dev/null @@ -1,198 +0,0 @@ ---- -id: aw5mcmev -title: API -description: "API infrastructure lifecycle hooks and Pulumi abstraction" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/infra/api`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/infra/api`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `ApiAfterBuildHook` - -**Abstraction** — imported from `webiny/infra/api` - -```typescript -import { ApiAfterBuildHook } from "webiny/infra/api"; -``` - -**Interface `ApiAfterBuildHook.Interface`:** - -```typescript -interface ApiAfterBuildHook.Interface { - execute(params: BuildApp.Params): void | Promise; -} -``` - -**Types:** - -```typescript -namespace ApiAfterBuildHook { - type Interface = IApiAfterBuild; - type Params = BuildApp.Params; -} -``` - -## `ApiAfterDeployHook` - -**Abstraction** — imported from `webiny/infra/api` - -```typescript -import { ApiAfterDeployHook } from "webiny/infra/api"; -``` - -**Interface `ApiAfterDeployHook.Interface`:** - -```typescript -interface ApiAfterDeployHook.Interface { - execute(params: DeployApp.Params): void | Promise; -} -``` - -**Types:** - -```typescript -namespace ApiAfterDeployHook { - type Interface = IApiAfterDeploy; - type Params = DeployApp.Params; -} -``` - -## `ApiBeforeBuildHook` - -**Abstraction** — imported from `webiny/infra/api` - -```typescript -import { ApiBeforeBuildHook } from "webiny/infra/api"; -``` - -**Interface `ApiBeforeBuildHook.Interface`:** - -```typescript -interface ApiBeforeBuildHook.Interface { - execute(params: BuildApp.Params): void | Promise; -} -``` - -**Types:** - -```typescript -namespace ApiBeforeBuildHook { - type Interface = IApiBeforeBuild; - type Params = BuildApp.Params; -} -``` - -## `ApiBeforeDeployHook` - -**Abstraction** — imported from `webiny/infra/api` - -```typescript -import { ApiBeforeDeployHook } from "webiny/infra/api"; -``` - -**Interface `ApiBeforeDeployHook.Interface`:** - -```typescript -interface ApiBeforeDeployHook.Interface { - execute(params: DeployApp.Params): void | Promise; -} -``` - -**Types:** - -```typescript -namespace ApiBeforeDeployHook { - type Interface = IApiBeforeDeploy; - type Params = DeployApp.Params; -} -``` - -## `ApiBeforeWatchHook` - -**Abstraction** — imported from `webiny/infra/api` - -```typescript -import { ApiBeforeWatchHook } from "webiny/infra/api"; -``` - -**Interface `ApiBeforeWatchHook.Interface`:** - -```typescript -interface ApiBeforeWatchHook.Interface { - execute(params: Watch.WatchWithAppParams): void | Promise; -} -``` - -**Types:** - -```typescript -namespace ApiBeforeWatchHook { - type Interface = IApiBeforeWatch; - type Params = Watch.WatchWithAppParams; -} -``` - -## `ApiPulumi` - -**Abstraction** — imported from `webiny/infra/api` - -```typescript -import { ApiPulumi } from "webiny/infra/api"; -``` - -**Types:** - -```typescript -namespace ApiPulumi { - type Interface = IApiPulumi; - type Params = unknown; -} -``` - -## `GetApiStackOutput` - -**Abstraction** — imported from `webiny/infra/api` - -```typescript -import { GetApiStackOutput } from "webiny/infra/api"; -``` - -**Interface `GetApiStackOutput.Interface`:** - -```typescript -interface GetApiStackOutput.Interface { - execute(): Promise; -} -``` - -**Types:** - -```typescript -namespace GetApiStackOutput { - type Interface = IApiStackOutputService; - type Output = IApiStackOutput; -} -``` diff --git a/docs/developer-docs/6.x/reference/infra/core.ai.txt b/docs/developer-docs/6.x/reference/infra/core.ai.txt deleted file mode 100644 index 1ed9c8652..000000000 --- a/docs/developer-docs/6.x/reference/infra/core.ai.txt +++ /dev/null @@ -1,30 +0,0 @@ -AI Context: Core (reference/infra/core.mdx) - -Source of Information: -1. packages/webiny/src/infra/core.ts — barrel re-export file -2. /Users/adrian/dev/wby-next/packages/project/src/abstractions/features/hooks/CoreAfterBuild.ts — originating source -3. /Users/adrian/dev/wby-next/packages/project/src/abstractions/features/hooks/CoreBeforeBuild.ts — originating source -4. /Users/adrian/dev/wby-next/packages/project/src/abstractions/features/hooks/CoreAfterDeploy.ts — originating source -5. /Users/adrian/dev/wby-next/packages/project/src/abstractions/features/hooks/CoreBeforeDeploy.ts — originating source -6. /Users/adrian/dev/wby-next/packages/project/src/abstractions/features/pulumi/CorePulumi.ts — originating source -7. /Users/adrian/dev/wby-next/packages/project-aws/src/abstractions/services/CoreStackOutputService.ts — originating source - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -CoreAfterBuildHook, CoreBeforeBuildHook, CoreAfterDeployHook, CoreBeforeDeployHook, CorePulumi, GetCoreStackOutput - -Import Path: webiny/infra/core - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those diff --git a/docs/developer-docs/6.x/reference/infra/core.mdx b/docs/developer-docs/6.x/reference/infra/core.mdx deleted file mode 100644 index 1951f6482..000000000 --- a/docs/developer-docs/6.x/reference/infra/core.mdx +++ /dev/null @@ -1,172 +0,0 @@ ---- -id: aw5mcmev -title: Core -description: "Core infrastructure lifecycle hooks and Pulumi abstraction" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is exported from `webiny/infra/core`? -- How to import and use each exported item? - - - -## Overview - -This page documents everything exported from `webiny/infra/core`. Import any of the items below directly from this path in your Webiny extensions. - - - -## `CoreAfterBuildHook` - -**Abstraction** — imported from `webiny/infra/core` - -```typescript -import { CoreAfterBuildHook } from "webiny/infra/core"; -``` - -**Interface `CoreAfterBuildHook.Interface`:** - -```typescript -interface CoreAfterBuildHook.Interface { - execute(params: BuildApp.Params): void | Promise; -} -``` - -**Types:** - -```typescript -namespace CoreAfterBuildHook { - type Interface = ICoreAfterBuild; - type Params = BuildApp.Params; -} -``` - -## `CoreAfterDeployHook` - -**Abstraction** — imported from `webiny/infra/core` - -```typescript -import { CoreAfterDeployHook } from "webiny/infra/core"; -``` - -**Interface `CoreAfterDeployHook.Interface`:** - -```typescript -interface CoreAfterDeployHook.Interface { - execute(params: DeployApp.Params): void | Promise; -} -``` - -**Types:** - -```typescript -namespace CoreAfterDeployHook { - type Interface = ICoreAfterDeploy; - type Params = DeployApp.Params; -} -``` - -## `CoreBeforeBuildHook` - -**Abstraction** — imported from `webiny/infra/core` - -```typescript -import { CoreBeforeBuildHook } from "webiny/infra/core"; -``` - -**Interface `CoreBeforeBuildHook.Interface`:** - -```typescript -interface CoreBeforeBuildHook.Interface { - execute(params: BuildApp.Params): void | Promise; -} -``` - -**Types:** - -```typescript -namespace CoreBeforeBuildHook { - type Interface = ICoreBeforeBuild; - type Params = BuildApp.Params; -} -``` - -## `CoreBeforeDeployHook` - -**Abstraction** — imported from `webiny/infra/core` - -```typescript -import { CoreBeforeDeployHook } from "webiny/infra/core"; -``` - -**Interface `CoreBeforeDeployHook.Interface`:** - -```typescript -interface CoreBeforeDeployHook.Interface { - execute(params: DeployApp.Params): void | Promise; -} -``` - -**Types:** - -```typescript -namespace CoreBeforeDeployHook { - type Interface = ICoreBeforeDeploy; - type Params = DeployApp.Params; -} -``` - -## `CorePulumi` - -**Abstraction** — imported from `webiny/infra/core` - -```typescript -import { CorePulumi } from "webiny/infra/core"; -``` - -**Types:** - -```typescript -namespace CorePulumi { - type Interface = ICorePulumi; - type Params = unknown; -} -``` - -## `GetCoreStackOutput` - -**Abstraction** — imported from `webiny/infra/core` - -```typescript -import { GetCoreStackOutput } from "webiny/infra/core"; -``` - -**Interface `GetCoreStackOutput.Interface`:** - -```typescript -interface GetCoreStackOutput.Interface { - execute(): Promise; -} -``` - -**Types:** - -```typescript -namespace GetCoreStackOutput { - type Interface = ICoreStackOutputService; - type Output = ICoreStackOutput; -} -``` diff --git a/docs/developer-docs/6.x/reference/sdk/cms.ai.txt b/docs/developer-docs/6.x/reference/sdk/cms.ai.txt deleted file mode 100644 index 9c97d1c4b..000000000 --- a/docs/developer-docs/6.x/reference/sdk/cms.ai.txt +++ /dev/null @@ -1,128 +0,0 @@ -AI Context: CMS (reference/sdk/cms.mdx) - -Source of Information: -1. CmsSdk.ts — class definition with all method signatures and type imports -2. methods/cms/getEntry.ts — getEntry method implementation and JSDoc -3. methods/cms/listEntries.ts — listEntries method implementation and JSDoc -4. methods/cms/createEntry.ts — createEntry method implementation and JSDoc -5. methods/cms/updateEntryRevision.ts — updateEntryRevision method implementation and JSDoc -6. methods/cms/publishEntryRevision.ts — publishEntryRevision method implementation and JSDoc -7. methods/cms/unpublishEntryRevision.ts — unpublishEntryRevision method implementation and JSDoc -8. methods/cms/deleteEntryRevision.ts — deleteEntryRevision method implementation and JSDoc -9. methods/cms/cmsTypes.ts — type definitions for CmsEntryData, CmsEntryValues, CmsIdentity, CmsEntryStatus -10. core-concepts/webiny-sdk.mdx — SDK overview, initialization, core concepts -11. headless-cms/using-webiny-sdk.mdx — practical examples of SDK usage with CMS - -Key Documentation Decisions: -1. Organized methods into "read methods" (getEntry, listEntries) and "write methods" (create, update, publish, unpublish, delete) for clarity -2. Documented that read methods use Read API by default (published content only), preview: true uses Preview API -3. Documented that all write methods use Manage API -4. Emphasized revisionId format ("entryId#revisionNumber" e.g. "abc123#0001") -5. Created comprehensive parameter tables for each method showing all nested parameters (e.g., params.where.id) -6. Included practical examples section covering common workflows: filtering+sorting+pagination, create+publish flow, TypeScript generics, error handling -7. Documented all related types (CmsEntryData, CmsEntryValues, CmsEntryStatus, CmsIdentity) in a dedicated Types section -8. Emphasized that createEntry creates a draft—publishEntryRevision required for public visibility -9. Highlighted that updateEntryRevision is a partial update (only specified fields change) -10. Documented soft delete vs. permanent delete behavior for deleteEntryRevision - -Understanding of CmsSdk: -- CmsSdk is the primary interface for Headless CMS operations from external applications -- Accessed via sdk.cms on a Webiny instance (not a standalone class users construct) -- All methods return Result types—never throw errors directly -- Read operations (getEntry, listEntries) default to Read API (published content only) -- preview: true parameter switches read operations to Preview API (includes unpublished/draft content) -- Write operations (create, update, publish, unpublish, delete) always use Manage API -- TypeScript generic provides type safety for entry.values field -- fields parameter controls response shape—use "values.fieldId" for entry fields, "id"/"createdOn" etc. for metadata -- Revision IDs have format "entryId#revisionNumber" (e.g., "abc123#0001") -- Entry lifecycle: create (draft) → updateEntryRevision (optional) → publishEntryRevision (public) → unpublishEntryRevision (back to draft) or deleteEntryRevision (soft/permanent delete) - -Code Patterns: -```typescript -// Initialization -import { Webiny } from "@webiny/sdk"; -const sdk = new Webiny({ token, endpoint, tenant }); - -// Type-safe query -interface Product { name: string; price: number; } -const result = await sdk.cms.listEntries({ - modelId: "product", - fields: ["id", "values.name", "values.price"] -}); - -// Result pattern -if (result.isOk()) { - const products = result.value.data; // CmsEntryData[] -} else { - console.error(result.error.message); -} - -// Create + publish workflow -const createResult = await sdk.cms.createEntry({ - modelId: "product", - data: { values: { name: "Laptop", price: 1299 } }, - fields: ["id", "entryId"] -}); - -if (createResult.isOk()) { - await sdk.cms.publishEntryRevision({ - modelId: "product", - revisionId: createResult.value.id!, - fields: ["id", "status"] - }); -} - -// Filtering and sorting -const result = await sdk.cms.listEntries({ - modelId: "product", - where: { "values.price_gte": 100 }, - sort: { "values.name": "asc" }, - limit: 20, - fields: ["id", "values.name", "values.price"] -}); - -// Pagination -if (result.isOk() && result.value.meta.hasMoreItems) { - const nextResult = await sdk.cms.listEntries({ - modelId: "product", - after: result.value.meta.cursor, - fields: ["id", "values.name"] - }); -} - -// Reference field resolution -const result = await sdk.cms.getEntry({ - modelId: "product", - where: { entryId: "abc123" }, - fields: [ - "id", - "values.name", - "values.category.id", - "values.category.values.name" - ] -}); -``` - -Related Documents: -- reference/sdk/webiny.mdx — Webiny class initialization and configuration -- reference/sdk/result.mdx — Result pattern details (isOk(), isFail(), value, error) -- reference/sdk/errors.mdx — Error types (HttpError, GraphQLError, NetworkError) -- core-concepts/webiny-sdk.mdx — SDK overview, installation, authentication -- headless-cms/using-webiny-sdk.mdx — Practical SDK usage examples - -Key Code Locations: -- packages/sdk/src/CmsSdk.ts — CmsSdk class definition -- packages/sdk/src/methods/cms/*.ts — Individual method implementations -- packages/sdk/src/methods/cms/cmsTypes.ts — Type definitions - -Tone Guidelines: -- Technical reference tone — concise, complete, API-focused -- Method signature blocks before each parameter table -- Parameter tables: name, type, required, description columns -- Minimal prose—let signatures and tables speak -- Examples show complete working code with type annotations -- Error handling always demonstrated (isOk() checks) -- Use TypeScript generics in all examples for type safety demonstration -- Emphasize Result pattern throughout—never suggest throwing/catching errors -- "When true/false" instead of "if true/false" for boolean parameter descriptions -- Active voice for method descriptions: "Retrieves", "Creates", "Publishes", "Deletes" \ No newline at end of file diff --git a/docs/developer-docs/6.x/reference/sdk/cms.mdx b/docs/developer-docs/6.x/reference/sdk/cms.mdx deleted file mode 100644 index 9c3545310..000000000 --- a/docs/developer-docs/6.x/reference/sdk/cms.mdx +++ /dev/null @@ -1,644 +0,0 @@ ---- -id: c2rrl2nt -title: CMS -description: CmsSdk class for querying and mutating Headless CMS entries from external applications ---- - -import { Alert } from "@/components/Alert"; - - - -- How to query entries from the Headless CMS using `sdk.cms`? -- How to create, update, publish, and delete CMS entries? -- How to use TypeScript generics for type-safe entry data? -- How to handle the Result pattern in CMS operations? - - - -## Overview - -The `CmsSdk` class provides methods for interacting with Headless CMS entries from external applications. Access it via `sdk.cms` on a `Webiny` instance. All read operations use the Read API by default (published content only), while write operations use the Manage API. Methods return `Result` objects—check for success with `isOk()` before accessing values. - -**Read Methods** - -- [`getEntry`](#get-entry) — fetch a single entry by ID or filter -- [`listEntries`](#list-entries) — list entries with filtering, sorting, and pagination - -**Write Methods** - -- [`createEntry`](#create-entry) — create a draft entry -- [`updateEntryRevision`](#update-entry-revision) — update specific fields on a revision -- [`publishEntryRevision`](#publish-entry-revision) — publish a revision to the Read API -- [`unpublishEntryRevision`](#unpublish-entry-revision) — revert a revision to draft -- [`deleteEntryRevision`](#delete-entry-revision) — delete a revision - -### CmsSdk - -The `CmsSdk` class is instantiated automatically when you create a `Webiny` instance. Access it via the `cms` property. - -```typescript -import { Webiny } from "@webiny/sdk"; - -const sdk = new Webiny({ - token: process.env.WEBINY_API_TOKEN!, - endpoint: process.env.WEBINY_API_ENDPOINT!, - tenant: "root" -}); - -// Access CMS methods -const result = await sdk.cms.listEntries({ - modelId: "product", - fields: ["id", "values.name"] -}); -``` - -### getEntry - -Retrieves a single entry from the CMS by ID, entry ID, or custom field values. - -```typescript -async getEntry( - params: GetEntryParams -): Promise, HttpError | GraphQLError | NetworkError>> -``` - -#### Parameters - -| Name | Type | Required | Description | -| ---------------------- | ------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------- | -| `params` | `GetEntryParams` | Yes | Parameters for retrieving the entry | -| `params.modelId` | `string` | Yes | The model ID of the entry to retrieve | -| `params.where` | `GetEntryWhere` | Yes | Filter conditions for finding the entry | -| `params.where.id` | `string` | No | The revision ID (e.g., `"abc123#0001"`) | -| `params.where.entryId` | `string` | No | The entry ID (e.g., `"abc123"`) | -| `params.where.values` | `Record` | No | Filter by entry field values | -| `params.fields` | `string[]` | Yes | Fields to include in response. Use `"values.fieldId"` for entry values or top-level fields like `"id"`, `"createdOn"` | -| `params.preview` | `boolean` | No | When `true`, uses Preview API to access unpublished/draft content. When `false` (default), uses Read API for published content only | - -#### Return Type - -`Result, HttpError | GraphQLError | NetworkError>` - -Returns a `Result` containing the entry data on success or an error on failure. - -#### Example - -```typescript -import type { CmsEntryData } from "@webiny/sdk"; - -interface Product { - name: string; - price: number; -} - -const result = await sdk.cms.getEntry({ - modelId: "product", - where: { entryId: "abc123" }, - fields: ["id", "entryId", "values.name", "values.price"] -}); - -if (result.isOk()) { - const product = result.value; - console.log(product.values.name); // string - console.log(product.values.price); // number -} -``` - -### listEntries - -Lists entries from the CMS with support for filtering, sorting, pagination, and full-text search. - -```typescript -async listEntries( - params: ListEntriesParams -): Promise, HttpError | GraphQLError | NetworkError>> -``` - -#### Parameters - -| Name | Type | Required | Description | -| ---------------- | --------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------- | -| `params` | `ListEntriesParams` | Yes | Parameters for listing entries | -| `params.modelId` | `string` | Yes | The model ID of entries to list | -| `params.where` | `Record` | No | Filter conditions using operators like `_eq`, `_gt`, `_contains`, etc. | -| `params.sort` | `Record` | No | Sort configuration (e.g., `{ "values.name": "asc" }`) | -| `params.limit` | `number` | No | Maximum number of entries to return (default: `10`) | -| `params.after` | `string` | No | Cursor for pagination from previous response | -| `params.search` | `string` | No | Full-text search term to filter entries across searchable fields (text, longText fields with `fullTextSearch` enabled) | -| `params.fields` | `string[]` | Yes | Fields to include in response. Use `"values.fieldId"` for entry values or top-level fields like `"id"`, `"createdOn"` | -| `params.preview` | `boolean` | No | When `true`, uses Preview API to access unpublished/draft content. When `false` (default), uses Read API for published content only | - -#### Return Type - -`Result, HttpError | GraphQLError | NetworkError>` - -Returns a `Result` containing an object with: - -- `data`: Array of `CmsEntryData` objects -- `meta`: Pagination metadata (`cursor`, `hasMoreItems`, `totalCount`) - -#### Example - -```typescript -interface Product { - name: string; - price: number; - inStock: boolean; -} - -const result = await sdk.cms.listEntries({ - modelId: "product", - where: { - "values.price_gte": 100, - "values.inStock": true - }, - sort: { "values.name": "asc" }, - limit: 20, - fields: ["id", "entryId", "values.name", "values.price"] -}); - -if (result.isOk()) { - const { data, meta } = result.value; - console.log(`Found ${meta.totalCount} products`); - - for (const product of data) { - console.log(product.values.name, product.values.price); - } - - if (meta.hasMoreItems) { - // Fetch next page using meta.cursor - } -} -``` - -### createEntry - -Creates a new entry in the CMS. The entry is created in draft status—call `publishEntryRevision` to make it publicly visible. - -```typescript -async createEntry( - params: CreateEntryParams -): Promise, HttpError | GraphQLError | NetworkError>> -``` - -#### Parameters - -| Name | Type | Required | Description | -| ---------------- | ----------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------- | -| `params` | `CreateEntryParams` | Yes | Parameters for creating the entry | -| `params.modelId` | `string` | Yes | The model ID for the entry | -| `params.data` | `CreateCmsEntryData` | Yes | The entry data to create. Must include `values` object with field data | -| `params.fields` | `string[]` | Yes | Fields to include in response. Use `"values.fieldId"` for entry values or top-level fields like `"id"`, `"createdOn"` | - -#### Return Type - -`Result, HttpError | GraphQLError | NetworkError>` - -Returns a `Result` containing the created entry data on success or an error on failure. - -#### Example - -```typescript -interface Product { - name: string; - price: number; - description: string; -} - -const result = await sdk.cms.createEntry({ - modelId: "product", - data: { - values: { - name: "Laptop", - price: 1299, - description: "High-performance laptop" - } - }, - fields: ["id", "entryId", "status", "values.name"] -}); - -if (result.isOk()) { - const product = result.value; - console.log(`Created entry: ${product.id}`); - console.log(`Status: ${product.status}`); // "draft" -} -``` - -### updateEntryRevision - -Updates an existing entry revision in the CMS. Only the specified fields in `data.values` are modified—other fields remain unchanged. - -```typescript -async updateEntryRevision( - params: UpdateEntryRevisionParams -): Promise, HttpError | GraphQLError | NetworkError>> -``` - -#### Parameters - -| Name | Type | Required | Description | -| ------------------- | ------------------------------------ | -------- | --------------------------------------------------------------------------------------------------------------------- | -| `params` | `UpdateEntryRevisionParams` | Yes | Parameters for updating the entry revision | -| `params.modelId` | `string` | Yes | The model ID for the entry | -| `params.revisionId` | `string` | Yes | The revision ID of the entry to update (e.g., `"abc123#0001"`) | -| `params.data` | `UpdateCmsEntryData` | Yes | The updated entry data. Use `values` for field updates | -| `params.fields` | `string[]` | Yes | Fields to include in response. Use `"values.fieldId"` for entry values or top-level fields like `"id"`, `"createdOn"` | - -#### Return Type - -`Result, HttpError | GraphQLError | NetworkError>` - -Returns a `Result` containing the updated entry data on success or an error on failure. - -#### Example - -```typescript -interface Product { - price: number; -} - -const result = await sdk.cms.updateEntryRevision({ - modelId: "product", - revisionId: "abc123#0001", - data: { - values: { - price: 1199 // Only update price field - } - }, - fields: ["id", "revisionId", "values.price"] -}); - -if (result.isOk()) { - console.log(`Updated price: ${result.value.values.price}`); -} -``` - -### publishEntryRevision - -Publishes an entry revision, making it available via the Read API. Published entries are visible to public consumers of your content. - -```typescript -async publishEntryRevision( - params: PublishEntryRevisionParams -): Promise, HttpError | GraphQLError | NetworkError>> -``` - -#### Parameters - -| Name | Type | Required | Description | -| ------------------- | ---------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------- | -| `params` | `PublishEntryRevisionParams` | Yes | Parameters for publishing the entry revision | -| `params.modelId` | `string` | Yes | The model ID of the entry to publish | -| `params.revisionId` | `string` | Yes | The revision ID of the entry to publish (e.g., `"abc123#0001"`) | -| `params.fields` | `string[]` | Yes | Fields to include in response. Use `"values.fieldId"` for entry values or top-level fields like `"id"`, `"createdOn"` | - -#### Return Type - -`Result, HttpError | GraphQLError | NetworkError>` - -Returns a `Result` containing the published entry data on success or an error on failure. - -#### Example - -```typescript -const result = await sdk.cms.publishEntryRevision({ - modelId: "product", - revisionId: "abc123#0001", - fields: ["id", "status", "values.name"] -}); - -if (result.isOk()) { - console.log(`Status: ${result.value.status}`); // "published" -} -``` - -### unpublishEntryRevision - -Unpublishes an entry revision, reverting it to draft status and removing it from the Read API. - -```typescript -async unpublishEntryRevision( - params: UnpublishEntryRevisionParams -): Promise, HttpError | GraphQLError | NetworkError>> -``` - -#### Parameters - -| Name | Type | Required | Description | -| ------------------- | ------------------------------ | -------- | --------------------------------------------------------------------------------------------------------------------- | -| `params` | `UnpublishEntryRevisionParams` | Yes | Parameters for unpublishing the entry revision | -| `params.modelId` | `string` | Yes | The model ID of the entry to unpublish | -| `params.revisionId` | `string` | Yes | The revision ID of the entry to unpublish (e.g., `"abc123#0001"`) | -| `params.fields` | `string[]` | Yes | Fields to include in response. Use `"values.fieldId"` for entry values or top-level fields like `"id"`, `"createdOn"` | - -#### Return Type - -`Result, HttpError | GraphQLError | NetworkError>` - -Returns a `Result` containing the unpublished entry data on success or an error on failure. - -#### Example - -```typescript -const result = await sdk.cms.unpublishEntryRevision({ - modelId: "product", - revisionId: "abc123#0001", - fields: ["id", "status"] -}); - -if (result.isOk()) { - console.log(`Status: ${result.value.status}`); // "unpublished" -} -``` - -### deleteEntryRevision - -Deletes an entry revision from the CMS. By default, performs a soft delete (entry can be restored). Pass `permanent: true` for permanent deletion. - -```typescript -async deleteEntryRevision( - params: DeleteEntryRevisionParams -): Promise> -``` - -#### Parameters - -| Name | Type | Required | Description | -| ------------------- | --------------------------- | -------- | -------------------------------------------------------------- | -| `params` | `DeleteEntryRevisionParams` | Yes | Parameters for deleting the entry revision | -| `params.modelId` | `string` | Yes | The model ID of the entry to delete | -| `params.revisionId` | `string` | Yes | The revision ID of the entry to delete (e.g., `"abc123#0001"`) | -| `params.permanent` | `boolean` | No | Whether to permanently delete the entry (default: `false`) | - -#### Return Type - -`Result` - -Returns a `Result` containing `true` on success or an error on failure. - -#### Example - -```typescript -// Soft delete (can be restored) -const result = await sdk.cms.deleteEntryRevision({ - modelId: "product", - revisionId: "abc123#0001" -}); - -if (result.isOk()) { - console.log("Entry deleted (soft delete)"); -} - -// Permanent delete -const permanentResult = await sdk.cms.deleteEntryRevision({ - modelId: "product", - revisionId: "abc123#0001", - permanent: true -}); - -if (permanentResult.isOk()) { - console.log("Entry permanently deleted"); -} -``` - -## Types - -### CmsEntryValues - -Base type for entry field values. Extend this interface to define your content model structure. - -```typescript -interface CmsEntryValues { - [key: string]: any; -} -``` - -### CmsEntryData - -Type representing a complete CMS entry with metadata and field values. - -```typescript -interface CmsEntryData { - id?: string; - entryId?: string; - status?: CmsEntryStatus; - - // Entry-level metadata - createdOn?: Date | string; - modifiedOn?: Date | string | null; - savedOn?: Date | string; - createdBy?: CmsIdentity; - modifiedBy?: CmsIdentity; - savedBy?: CmsIdentity; - firstPublishedOn?: Date | string; - lastPublishedOn?: Date | string; - firstPublishedBy?: CmsIdentity; - lastPublishedBy?: CmsIdentity; - - // Revision-level metadata - revisionCreatedOn?: Date | string; - revisionSavedOn?: Date | string; - revisionCreatedBy?: CmsIdentity; - revisionSavedBy?: CmsIdentity; - - location?: { - folderId?: string | null; - }; - - values?: TValues; -} -``` - -### CmsEntryStatus - -Entry publication status. - -```typescript -type CmsEntryStatus = "published" | "unpublished" | "draft"; -``` - -### CmsIdentity - -User identity information in entry metadata. - -```typescript -interface CmsIdentity { - id: string; - displayName: string; - type: string; -} -``` - -## Practical Examples - -### List with Filter, Sort, and Pagination - -```typescript -import type { CmsEntryData } from "@webiny/sdk"; - -interface Product { - name: string; - price: number; - category: string; -} - -async function fetchProducts(cursor?: string) { - const result = await sdk.cms.listEntries({ - modelId: "product", - where: { - "values.price_gte": 100, - "values.category": "electronics" - }, - sort: { "values.price": "asc" }, - limit: 20, - after: cursor, - fields: ["id", "entryId", "values.name", "values.price", "values.category"] - }); - - if (result.isFail()) { - console.error("Error:", result.error.message); - return; - } - - const { data, meta } = result.value; - - for (const product of data) { - console.log(`${product.values.name}: $${product.values.price}`); - } - - if (meta.hasMoreItems) { - await fetchProducts(meta.cursor); - } -} -``` - -### Get Entry by ID - -```typescript -interface Author { - name: string; - bio: string; - email: string; -} - -const result = await sdk.cms.getEntry({ - modelId: "author", - where: { entryId: "xyz789" }, - fields: ["id", "entryId", "createdOn", "values.name", "values.bio", "values.email"] -}); - -if (result.isOk()) { - const author = result.value; - console.log(`Author: ${author.values.name}`); - console.log(`Created: ${author.createdOn}`); -} -``` - -### Create and Publish Flow - -```typescript -interface BlogPost { - title: string; - content: string; - slug: string; -} - -// Step 1: Create draft entry -const createResult = await sdk.cms.createEntry({ - modelId: "blogPost", - data: { - values: { - title: "Getting Started with Webiny", - content: "This is the post content...", - slug: "getting-started" - } - }, - fields: ["id", "entryId", "status"] -}); - -if (createResult.isFail()) { - console.error("Create failed:", createResult.error.message); - return; -} - -const draft = createResult.value; -console.log(`Created draft: ${draft.id}`); - -// Step 2: Publish the entry -const publishResult = await sdk.cms.publishEntryRevision({ - modelId: "blogPost", - revisionId: draft.id!, - fields: ["id", "status"] -}); - -if (publishResult.isOk()) { - console.log(`Published: ${publishResult.value.id}`); -} -``` - -### TypeScript Generics Usage - -```typescript -import type { CmsEntryData } from "@webiny/sdk"; - -interface Product { - name: string; - price: number; - category: CmsEntryData; -} - -interface ProductCategory { - name: string; - slug: string; -} - -const result = await sdk.cms.getEntry({ - modelId: "product", - where: { entryId: "abc123" }, - fields: [ - "id", - "values.name", - "values.price", - "values.category.id", - "values.category.values.name", - "values.category.values.slug" - ] -}); - -if (result.isOk()) { - const product = result.value; - - // Full type safety with autocomplete - const name: string = product.values.name; - const price: number = product.values.price; - const categoryName: string = product.values.category.values.name; -} -``` - -### Error Handling Pattern - -```typescript -const result = await sdk.cms.getEntry({ - modelId: "product", - where: { entryId: "nonexistent" }, - fields: ["id", "values.name"] -}); - -if (result.isFail()) { - const error = result.error; - - if (error.name === "GraphQLError") { - console.error("GraphQL Error:", error.message); - console.error("Error Code:", error.code); - } else if (error.name === "HttpError") { - console.error("HTTP Error:", error.statusCode); - } else if (error.name === "NetworkError") { - console.error("Network Error:", error.message); - } - - return; -} - -// Safe to access value -const product = result.value; -``` diff --git a/docs/developer-docs/6.x/reference/sdk/file-manager.ai.txt b/docs/developer-docs/6.x/reference/sdk/file-manager.ai.txt deleted file mode 100644 index 0f3515512..000000000 --- a/docs/developer-docs/6.x/reference/sdk/file-manager.ai.txt +++ /dev/null @@ -1,157 +0,0 @@ -AI Context: File Manager (reference/sdk/file-manager.mdx) - -Source of Information: -1. FileManagerSdk.ts — class definition with all method signatures -2. methods/fileManager/getFile.ts — single file retrieval implementation -3. methods/fileManager/listFiles.ts — file listing with search, where, sort, pagination -4. methods/fileManager/createFile.ts — file creation with upload support (small/large files) -5. methods/fileManager/createFiles.ts — bulk file creation with concurrent uploads -6. methods/fileManager/updateFile.ts — file metadata update -7. methods/fileManager/deleteFile.ts — file deletion -8. methods/fileManager/listTags.ts — tag listing with counts -9. methods/fileManager/getPresignedPostPayload.ts — presigned POST URL for browser uploads -10. methods/fileManager/getPresignedPostPayloads.ts — bulk presigned POST URLs -11. methods/fileManager/createMultiPartUpload.ts — multipart upload initiation for large files -12. methods/fileManager/completeMultiPartUpload.ts — multipart upload completion -13. methods/fileManager/fileManagerTypes.ts — all type definitions - -Key Documentation Decisions: -1. Grouped methods into logical sections: Reading (get/list), Creating/Updating (CRUD), Upload Helpers (presigned/multipart) -2. Documented all method parameters in param tables with Required column -3. Included return types showing Result pattern with specific error types -4. Provided complete type reference section for key interfaces -5. Examples show both simple cases (metadata only) and complex cases (file upload, multipart, batch) -6. Highlighted automatic upload strategy selection (small vs large files) based on multiPartThreshold -7. Documented both fail-fast and continue strategies for batch operations -8. Showed complete flow for presigned POST and multipart upload patterns - -File Manager SDK Understanding: -- `FileManagerSdk` handles file metadata operations (CRUD) and upload orchestration -- File uploads happen in two stages: (1) upload to S3 via presigned URL, (2) create metadata record -- Small files (<100MB default) use simple presigned POST; large files use multipart upload -- `createFile()` intelligently selects upload strategy based on file size -- `createFiles()` uses p-map for controlled concurrency (default: 5 concurrent uploads) -- Presigned POST URLs allow direct browser→S3 uploads without proxying through API -- Multipart uploads split large files into chunks, upload in parallel, then finalize with completeMultiPartUpload -- All file operations return Result pattern — check isOk() before accessing value -- Fields parameter controls which properties are returned (same as CMS SDK pattern) -- Tags are freeform strings; listTags returns usage counts across all files -- File location uses folderId to organize files in hierarchical structure - -Code Patterns: -1. **Simple file retrieval:** - ```typescript - const result = await sdk.fileManager.getFile({ - id: "file-id", - fields: ["id", "name", "src", "size"] - }); - ``` - -2. **List with search and filters:** - ```typescript - const result = await sdk.fileManager.listFiles({ - fields: ["id", "name", "src"], - search: "logo", - where: { type_in: ["image/png", "image/jpeg"] }, - limit: 10, - sort: ["savedOn_DESC"] - }); - ``` - -3. **File upload (automatic strategy):** - ```typescript - const result = await sdk.fileManager.createFile({ - file: fileBlob, - data: { name: "photo.jpg", type: "image/jpeg" }, - fields: ["id", "src"], - onProgress: (p) => console.log(`${p.percentage}%`) - }); - ``` - -4. **Presigned POST upload (manual):** - ```typescript - // 1. Get presigned POST payload - const presigned = await sdk.fileManager.getPresignedPostPayload({ - name: "file.jpg", - type: "image/jpeg", - size: 102400 - }); - - // 2. Upload to S3 - const formData = new FormData(); - Object.entries(presigned.value.data.fields).forEach(([k, v]) => { - formData.append(k, v); - }); - formData.append("file", fileBlob); - await fetch(presigned.value.data.url, { method: "POST", body: formData }); - - // 3. Create file record - await sdk.fileManager.createFile({ - data: { - id: presigned.value.file.id, - key: presigned.value.file.key, - // ... other metadata - }, - fields: ["id", "src"] - }); - ``` - -5. **Multipart upload:** - ```typescript - // 1. Create multipart upload - const upload = await sdk.fileManager.createMultiPartUpload({ - data: { name: "large.mp4", type: "video/mp4", size: 500000000 }, - numberOfParts: 10 - }); - - // 2. Upload each part - for (const part of upload.value.parts) { - const chunk = getChunk(part.partNumber - 1); - await fetch(part.url, { method: "PUT", body: chunk }); - } - - // 3. Complete upload - await sdk.fileManager.completeMultiPartUpload({ - fileKey: upload.value.file.key, - uploadId: upload.value.uploadId - }); - ``` - -6. **Batch upload with error handling:** - ```typescript - const result = await sdk.fileManager.createFiles({ - files: [ - { file: file1, data: { name: "1.jpg", type: "image/jpeg" }, fields: ["id"] }, - { file: file2, data: { name: "2.jpg", type: "image/jpeg" }, fields: ["id"] } - ], - concurrency: 3, - strategy: "continue" // continue on errors - }); - - if (result.isOk()) { - console.log(`Success: ${result.value.successful.length}`); - console.log(`Failed: ${result.value.failed.length}`); - } - ``` - -Related Documents: -- /docs/developer-docs/6.0.x/core-concepts/webiny-sdk.mdx — SDK overview and initialization -- /docs/developer-docs/6.0.x/headless-cms/using-webiny-sdk.mdx — CMS SDK usage patterns -- /docs/developer-docs/6.0.x/reference/sdk/cms.mdx — CMS SDK reference (sibling reference page) - -Key Code Locations: -- packages/sdk/src/FileManagerSdk.ts — main class definition -- packages/sdk/src/methods/fileManager/*.ts — all method implementations -- packages/sdk/src/methods/fileManager/utils/uploadToS3.ts — S3 upload helper -- packages/sdk/src/methods/fileManager/utils/uploadLargeFile.ts — multipart upload logic -- packages/sdk/src/methods/fileManager/fileManagerTypes.ts — type definitions - -Tone Guidelines: -- Technical reference style — concise, API-focused, minimal prose -- Every method gets: signature + param table + return type + example -- Examples are practical and production-ready (error handling, progress callbacks) -- Highlight automatic behaviors (upload strategy selection, concurrent limits) -- Type reference section uses code blocks for interfaces (not param tables) -- No analogies or conceptual explanations — save those for about.mdx (none exists yet) -- Assume reader knows Result pattern from core-concepts/result.mdx -- All examples show Result error checking with if (result.isOk()) \ No newline at end of file diff --git a/docs/developer-docs/6.x/reference/sdk/file-manager.mdx b/docs/developer-docs/6.x/reference/sdk/file-manager.mdx deleted file mode 100644 index a6a2c3dd6..000000000 --- a/docs/developer-docs/6.x/reference/sdk/file-manager.mdx +++ /dev/null @@ -1,698 +0,0 @@ ---- -id: c2rrl2zp -title: File Manager -description: "FileManagerSdk: upload, retrieve, and manage files" ---- - -import { Alert } from "@/components/Alert"; - - - -- How to retrieve files and file metadata? -- How to upload files using presigned URLs? -- How to handle large file uploads with multipart upload? -- How to manage file records and tags? - - - -## Overview - -The `FileManagerSdk` provides methods for managing files in Webiny File Manager. Access it via `sdk.fileManager` on a `Webiny` instance. The SDK handles file metadata operations (create, read, update, delete) and provides helpers for uploading files to S3 using presigned URLs. For large files, multipart upload is supported automatically based on configurable size thresholds. - -## Reading Files - -### getFile - -Retrieves a single file by ID. - -```typescript -async getFile(params: GetFileParams): Promise> -``` - -**Parameters:** - -| Name | Type | Required | Description | -| --------------- | --------------- | -------- | -------------------------------------------------------- | -| `params` | `GetFileParams` | Yes | Parameters for getting the file | -| `params.id` | `string` | Yes | ID of the file to retrieve | -| `params.fields` | `string[]` | Yes | Fields to return (e.g., `["id", "name", "src", "size"]`) | - -**Returns:** - -`Result` — Result containing the file data or an error. - -**Example:** - -```typescript -const result = await sdk.fileManager.getFile({ - id: "67a8f2e1d26d020002c00456", - fields: ["id", "name", "src", "size", "type", "createdOn"] -}); - -if (result.isOk()) { - const file = result.value; - console.log(`File: ${file.name}, Size: ${file.size} bytes`); -} else { - console.error("Error:", result.error.message); -} -``` - -### listFiles - -Lists files with filtering, sorting, and pagination. - -```typescript -async listFiles(params: ListFilesParams): Promise> -``` - -**Parameters:** - -| Name | Type | Required | Description | -| --------------- | ---------------------- | -------- | ------------------------------------- | -| `params` | `ListFilesParams` | Yes | Parameters for listing files | -| `params.fields` | `string[]` | Yes | Fields to return for each file | -| `params.search` | `string` | No | Search query to filter files by name | -| `params.where` | `FmFileListWhereInput` | No | Filter conditions | -| `params.limit` | `number` | No | Maximum number of files to return | -| `params.after` | `string` | No | Cursor for pagination | -| `params.sort` | `FmFileListSorter[]` | No | Sort order (e.g., `["savedOn_DESC"]`) | - -**Returns:** - -`Result` — Result containing: - -- `data` — Array of `FmFile` objects -- `meta` — Pagination metadata (`cursor`, `hasMoreItems`, `totalCount`) - -**Example:** - -```typescript -const result = await sdk.fileManager.listFiles({ - fields: ["id", "name", "src", "size", "type", "tags"], - search: "logo", - where: { - type_in: ["image/png", "image/jpeg"], - tags_in: ["marketing"] - }, - limit: 10, - sort: ["savedOn_DESC"] -}); - -if (result.isOk()) { - const { data, meta } = result.value; - console.log(`Found ${data.length} files`); - - if (meta.hasMoreItems) { - console.log(`More items available. Cursor: ${meta.cursor}`); - } -} -``` - -**Available sort options:** - -- `savedOn_ASC` / `savedOn_DESC` -- `createdOn_ASC` / `createdOn_DESC` -- `name_ASC` / `name_DESC` -- `key_ASC` / `key_DESC` -- `type_ASC` / `type_DESC` -- `size_ASC` / `size_DESC` - -### listTags - -Lists all tags used on files with usage counts. - -```typescript -async listTags(params?: ListTagsParams): Promise> -``` - -**Parameters:** - -| Name | Type | Required | Description | -| ---------------------------------- | ---------------------- | -------- | ------------------------------------ | -| `params` | `ListTagsParams` | No | Parameters for listing tags | -| `params.where` | `FmTagsListWhereInput` | No | Filter conditions | -| `params.where.createdBy` | `string` | No | Filter by creator ID | -| `params.where.tags_startsWith` | `string` | No | Filter tags starting with prefix | -| `params.where.tags_not_startsWith` | `string` | No | Filter tags not starting with prefix | - -**Returns:** - -`Result` — Result containing array of tags with counts. - -**Example:** - -```typescript -const result = await sdk.fileManager.listTags({ - where: { - tags_startsWith: "prod" - } -}); - -if (result.isOk()) { - result.value.forEach(tag => { - console.log(`${tag.tag}: ${tag.count} files`); - }); -} -``` - -## Creating and Updating Files - -### createFile - -Creates a new file record in File Manager. If a file is provided, it uploads to S3 first using presigned POST (small files) or multipart upload (large files). - -```typescript -async createFile(params: CreateFileParams): Promise> -``` - -**Parameters:** - -| Name | Type | Required | Description | -| --------------------------- | ------------------------------------ | -------- | --------------------------------------------------- | -| `params` | `CreateFileParams` | Yes | Parameters for creating the file | -| `params.data` | `CreateFileData` | Yes | File metadata | -| `params.data.name` | `string` | Yes\* | File name | -| `params.data.type` | `string` | Yes\* | MIME type (e.g., `"image/png"`) | -| `params.data.size` | `number` | No | File size in bytes | -| `params.data.key` | `string` | No | Custom S3 key | -| `params.data.keyPrefix` | `string` | No | Custom key prefix | -| `params.data.location` | `FmLocationInput` | No | Folder location (`{ folderId: string }`) | -| `params.data.tags` | `string[]` | No | Tags for the file | -| `params.file` | `Buffer \| Blob \| File` | No | Actual file content to upload | -| `params.fields` | `string[]` | Yes | Fields to return for created file | -| `params.onProgress` | `(progress: UploadProgress) => void` | No | Upload progress callback | -| `params.multiPartThreshold` | `number` | No | Threshold in MB for multipart upload (default: 100) | -| `params.signal` | `AbortSignal` | No | AbortSignal for cancellation | - -\*Required when `file` is provided. - -**Returns:** - -`Result` — Result containing the created file data. - -**Example (metadata only):** - -```typescript -const result = await sdk.fileManager.createFile({ - data: { - name: "document.pdf", - type: "application/pdf", - size: 1024, - key: "files/document.pdf", - tags: ["legal", "contracts"] - }, - fields: ["id", "name", "key", "src"] -}); -``` - -**Example (with file upload):** - -```typescript -const file = new File([buffer], "photo.jpg", { type: "image/jpeg" }); - -const result = await sdk.fileManager.createFile({ - file, - data: { - name: "photo.jpg", - type: "image/jpeg", - location: { folderId: "root" }, - tags: ["photos"] - }, - fields: ["id", "name", "src", "size"], - onProgress: progress => { - console.log(`Upload progress: ${progress.percentage}%`); - } -}); - -if (result.isOk()) { - console.log(`File uploaded: ${result.value.src}`); -} -``` - -### createFiles - -Creates multiple file records in bulk with concurrent uploads. - -```typescript -async createFiles(params: CreateFilesParams): Promise> -``` - -**Parameters:** - -| Name | Type | Required | Description | -| --------------------------- | --------------------------------------------- | -------- | ------------------------------------------------------ | -| `params` | `CreateFilesParams` | Yes | Parameters for creating multiple files | -| `params.files` | `Array<{ file?, data, fields, onProgress? }>` | Yes | Array of files to create | -| `params.multiPartThreshold` | `number` | No | Threshold in MB for multipart upload (default: 100) | -| `params.concurrency` | `number` | No | Number of concurrent uploads (default: 5) | -| `params.strategy` | `BatchUploadStrategy` | No | `"fail-fast"` or `"continue"` (default: `"fail-fast"`) | -| `params.signal` | `AbortSignal` | No | AbortSignal for cancellation | - -**Returns:** - -`Result` — Result containing: - -- `successful` — Array of successfully created `FmFile` objects -- `failed` — Array of failed uploads with error details - -**Example:** - -```typescript -const result = await sdk.fileManager.createFiles({ - files: [ - { - file: file1, - data: { name: "image1.jpg", type: "image/jpeg" }, - fields: ["id", "name", "src"] - }, - { - file: file2, - data: { name: "image2.jpg", type: "image/jpeg" }, - fields: ["id", "name", "src"] - } - ], - concurrency: 3, - strategy: "continue" -}); - -if (result.isOk()) { - console.log(`Successful: ${result.value.successful.length}`); - console.log(`Failed: ${result.value.failed.length}`); - - result.value.failed.forEach(item => { - console.error(`Failed to upload ${item.data.name}:`, item.error.message); - }); -} -``` - -### updateFile - -Updates file metadata (does not re-upload file content). - -```typescript -async updateFile(params: UpdateFileParams): Promise> -``` - -**Parameters:** - -| Name | Type | Required | Description | -| ---------------------- | ------------------ | -------- | --------------------------------- | -| `params` | `UpdateFileParams` | Yes | Parameters for updating the file | -| `params.id` | `string` | Yes | ID of the file to update | -| `params.data` | `UpdateFileData` | Yes | Updated file metadata | -| `params.data.name` | `string` | No | Updated file name | -| `params.data.tags` | `string[]` | No | Updated tags | -| `params.data.location` | `FmLocationInput` | No | Updated folder location | -| `params.fields` | `string[]` | Yes | Fields to return for updated file | - -**Returns:** - -`Result` — Result containing the updated file data. - -**Example:** - -```typescript -const result = await sdk.fileManager.updateFile({ - id: "67a8f2e1d26d020002c00456", - data: { - name: "updated-name.jpg", - tags: ["archived", "2024"] - }, - fields: ["id", "name", "tags", "modifiedOn"] -}); -``` - -### deleteFile - -Deletes a file record from File Manager. - -```typescript -async deleteFile(params: DeleteFileParams): Promise> -``` - -**Parameters:** - -| Name | Type | Required | Description | -| ----------- | ------------------ | -------- | -------------------------------- | -| `params` | `DeleteFileParams` | Yes | Parameters for deleting the file | -| `params.id` | `string` | Yes | ID of the file to delete | - -**Returns:** - -`Result` — Result containing `true` on success. - -**Example:** - -```typescript -const result = await sdk.fileManager.deleteFile({ - id: "67a8f2e1d26d020002c00456" -}); - -if (result.isOk()) { - console.log("File deleted successfully"); -} -``` - -## Upload Helpers - -### getPresignedPostPayload - -Gets a presigned POST URL for uploading a file directly to S3 from a browser. - -```typescript -async getPresignedPostPayload(params: GetPresignedPostPayloadParams): Promise> -``` - -**Parameters:** - -| Name | Type | Required | Description | -| ------------------ | ------------------------------- | -------- | --------------------------------------------- | -| `params` | `GetPresignedPostPayloadParams` | Yes | Parameters for getting presigned POST payload | -| `params.name` | `string` | Yes | File name | -| `params.type` | `string` | Yes | MIME type | -| `params.size` | `number` | Yes | File size in bytes | -| `params.key` | `string` | No | Custom S3 key | -| `params.keyPrefix` | `string` | No | Custom key prefix | - -**Returns:** - -`Result` — Result containing: - -- `data` — Presigned POST payload with `url` and `fields` -- `file` — File metadata including generated `id` and `key` - -**Example:** - -```typescript -const result = await sdk.fileManager.getPresignedPostPayload({ - name: "upload.jpg", - type: "image/jpeg", - size: 102400 -}); - -if (result.isOk()) { - const { data, file } = result.value; - - // Upload to S3 using presigned POST - const formData = new FormData(); - Object.entries(data.fields).forEach(([key, value]) => { - formData.append(key, value); - }); - formData.append("file", fileBlob); - - await fetch(data.url, { - method: "POST", - body: formData - }); - - // Create file record after upload - await sdk.fileManager.createFile({ - data: { - id: file.id, - name: file.name, - type: file.type, - size: file.size, - key: file.key - }, - fields: ["id", "src"] - }); -} -``` - -### getPresignedPostPayloads - -Gets presigned POST URLs for multiple files in bulk. - -```typescript -async getPresignedPostPayloads(params: GetPresignedPostPayloadsParams): Promise> -``` - -**Parameters:** - -| Name | Type | Required | Description | -| -------------- | --------------------------------- | -------- | ---------------------------------------------- | -| `params` | `GetPresignedPostPayloadsParams` | Yes | Parameters for getting presigned POST payloads | -| `params.files` | `GetPresignedPostPayloadParams[]` | Yes | Array of file metadata | - -**Returns:** - -`Result` — Result containing array of presigned POST payloads. - -**Example:** - -```typescript -const result = await sdk.fileManager.getPresignedPostPayloads({ - files: [ - { name: "file1.jpg", type: "image/jpeg", size: 102400 }, - { name: "file2.jpg", type: "image/jpeg", size: 204800 } - ] -}); - -if (result.isOk()) { - result.value.forEach(({ data, file }) => { - console.log(`Upload URL for ${file.name}: ${data.url}`); - }); -} -``` - -### createMultiPartUpload - -Initiates a multipart upload for large files. - -```typescript -async createMultiPartUpload(params: CreateMultiPartUploadParams): Promise> -``` - -**Parameters:** - -| Name | Type | Required | Description | -| ----------------------- | ----------------------------- | -------- | ------------------------------------------------------- | -| `params` | `CreateMultiPartUploadParams` | Yes | Parameters for creating multipart upload | -| `params.data` | `object` | Yes | File metadata (same as `GetPresignedPostPayloadParams`) | -| `params.data.name` | `string` | Yes | File name | -| `params.data.type` | `string` | Yes | MIME type | -| `params.data.size` | `number` | Yes | File size in bytes | -| `params.data.key` | `string` | No | Custom S3 key | -| `params.data.keyPrefix` | `string` | No | Custom key prefix | -| `params.numberOfParts` | `number` | Yes | Number of parts to split file into | - -**Returns:** - -`Result` — Result containing: - -- `uploadId` — Upload ID for tracking -- `file` — File metadata including `id` and `key` -- `parts` — Array of presigned URLs for each part (`{ partNumber, url }`) - -**Example:** - -```typescript -const fileSize = 500 * 1024 * 1024; // 500 MB -const chunkSize = 50 * 1024 * 1024; // 50 MB chunks -const numberOfParts = Math.ceil(fileSize / chunkSize); - -const result = await sdk.fileManager.createMultiPartUpload({ - data: { - name: "large-file.mp4", - type: "video/mp4", - size: fileSize - }, - numberOfParts -}); - -if (result.isOk()) { - const { uploadId, file, parts } = result.value; - - // Upload each part to S3 - for (const part of parts) { - const chunk = getFileChunk(part.partNumber - 1, chunkSize); - await fetch(part.url, { - method: "PUT", - body: chunk - }); - } - - // Complete the upload - await sdk.fileManager.completeMultiPartUpload({ - fileKey: file.key, - uploadId - }); -} -``` - -### completeMultiPartUpload - -Completes a multipart upload after all parts are uploaded. - -```typescript -async completeMultiPartUpload(params: CompleteMultiPartUploadParams): Promise> -``` - -**Parameters:** - -| Name | Type | Required | Description | -| ----------------- | ------------------------------- | -------- | ----------------------------------------------- | -| `params` | `CompleteMultiPartUploadParams` | Yes | Parameters for completing multipart upload | -| `params.fileKey` | `string` | Yes | S3 key from `createMultiPartUpload` response | -| `params.uploadId` | `string` | Yes | Upload ID from `createMultiPartUpload` response | - -**Returns:** - -`Result` — Result containing `true` on success. - -**Example:** - -```typescript -const result = await sdk.fileManager.completeMultiPartUpload({ - fileKey: "files/67a8f2e1d26d020002c00456/large-file.mp4", - uploadId: "abc123xyz" -}); - -if (result.isOk()) { - console.log("Multipart upload completed"); - - // Create file record - await sdk.fileManager.createFile({ - data: { - id: fileId, - name: "large-file.mp4", - type: "video/mp4", - size: fileSize, - key: fileKey - }, - fields: ["id", "src"] - }); -} -``` - -## Type Reference - -### FmFile - -Represents a file in File Manager. - -```typescript -interface FmFile { - id: string; - createdOn: Date | string; - modifiedOn?: Date | string; - savedOn: Date | string; - createdBy: FmIdentity; - modifiedBy?: FmIdentity; - savedBy: FmIdentity; - location: FmLocation; - src?: string; - name?: string; - key?: string; - type?: string; - size?: number; - metadata?: FmFile_Metadata; - tags?: string[]; - accessControl?: FmFile_AccessControl; - [key: string]: any; -} -``` - -### FmTag - -Represents a tag with usage count. - -```typescript -interface FmTag { - tag: string; - count: number; -} -``` - -### FmListMeta - -Pagination metadata for list operations. - -```typescript -interface FmListMeta { - cursor: string | null; - hasMoreItems: boolean; - totalCount: number; -} -``` - -### FmFile_Metadata - -File metadata including image dimensions and EXIF data. - -```typescript -interface FmFile_Metadata { - image?: { - width?: number; - height?: number; - format?: string; - orientation?: number; - }; - exif?: Record; - iptc?: Record; - [key: string]: any; -} -``` - -### FmFile_AccessControl - -File access control settings. - -```typescript -type FmFile_AccessControl = { - type: "public" | "private-authenticated"; -}; -``` - -### PresignedPostPayloadResponse - -Response containing presigned POST data for S3 upload. - -```typescript -interface PresignedPostPayloadResponse { - data: { - url: string; - fields: Record; - }; - file: { - id: string; - name: string; - type: string; - size: number; - key: string; - }; -} -``` - -### MultiPartUploadResponse - -Response containing multipart upload data. - -```typescript -interface MultiPartUploadResponse { - uploadId: string; - file: { - id: string; - name: string; - type: string; - size: number; - key: string; - }; - parts: Array<{ - partNumber: number; - url: string; - }>; -} -``` - -### UploadProgress - -Upload progress callback data. - -```typescript -interface UploadProgress { - sent: number; - total: number; - percentage: number; -} -``` diff --git a/docs/developer-docs/6.x/reference/sdk/index.ai.txt b/docs/developer-docs/6.x/reference/sdk/index.ai.txt deleted file mode 100644 index ce2ecaa48..000000000 --- a/docs/developer-docs/6.x/reference/sdk/index.ai.txt +++ /dev/null @@ -1,140 +0,0 @@ -AI Context: Overview (reference/sdk/index.mdx) - -Source of Information: -1. @webiny/sdk/src/index.ts - Main export file listing all public exports -2. @webiny/sdk/src/Webiny.ts - Main Webiny class implementation -3. @webiny/sdk/src/types.ts - WebinyConfig interface definition -4. @webiny/sdk/src/Result.ts - Result class implementation with generics and functional methods -5. @webiny/sdk/src/BaseError.ts - Abstract base error class -6. @webiny/sdk/src/errors.ts - HttpError, GraphQLError, NetworkError implementations -7. docs/developer-docs/6.0.x/core-concepts/webiny-sdk.mdx - Existing SDK overview doc -8. docs/developer-docs/6.0.x/headless-cms/using-webiny-sdk.mdx - SDK usage examples - -Key Documentation Decisions: -1. Page structure: Overview → Installation → Initialization → Quick Start → Webiny class → WebinyConfig → Result class → Error classes -2. WebinyConfig documented with all five properties (endpoint, token, tenant, headers, fetch) and their purposes -3. Result class documented with all static methods (ok, fail), instance methods (isOk, isFail, value, error, map, mapError, flatMap, match), and namespace types (UnwrapResult, UnwrapError) -4. Error classes documented with their specific properties (HttpError.data.status, GraphQLError.data.code) and example usage patterns -5. Quick Start section shows the most common pattern: initialize → call method → check isOk()/isFail() -6. Import path emphasized as @webiny/sdk (not webiny/*) — this is an external package -7. "Finding Your API Endpoint" alert preserved from existing docs -8. Error handling pattern documented with switch statement for all three error types - -Understanding the Webiny SDK Architecture: -- External package pattern: @webiny/sdk is installed via npm, not part of the Webiny monorepo extensions system -- Single entry point: Webiny class constructor instantiates CmsSdk, TenantManagerSdk, FileManagerSdk -- Singleton pattern recommended: create one instance, reuse throughout application -- Authentication: token-based using API key from Webiny Admin (Settings → API Keys) -- API selection: SDK internally chooses Read API vs Manage API based on operation (hidden from user) -- Result pattern: all async methods return Result instead of throwing — forces explicit error handling -- Error hierarchy: BaseError → HttpError/GraphQLError/NetworkError with discriminated code property -- Type safety: generic type parameters on Result allow full type inference for success/error paths - -Result Pattern Design: -- Inspired by functional programming (Either, Result types from Rust/Haskell) -- Two states: ok (success with value) or fail (failure with error) -- Type guards: isOk() and isFail() narrow types for safe value/error access -- Functional methods: map, mapError, flatMap for composition without explicit if checks -- Pattern matching: match() provides exhaustive handling of both cases -- Namespace utilities: UnwrapResult and UnwrapError extract inner types from Result - -WebinyConfig Properties: -- endpoint: base CloudFront URL (yarn webiny info shows this) — NOT the full /graphql path -- token: optional but required for authenticated operations (all CMS ops require it) -- tenant: defaults to "root" — multi-tenancy support -- headers: optional custom headers merged with defaults (authorization, content-type) -- fetch: optional custom fetch implementation (useful for testing, proxying, server-side rendering) - -Error Classes: -- HttpError: HTTP transport failures (404, 500, etc.) — has data.status number -- GraphQLError: API-level errors (validation, permissions) — has optional data.code string -- NetworkError: fetch itself failed (no connection, DNS failure) — no data property -- All have code property for switch statements -- All extend BaseError which has message, data, optional stack - -Code Patterns: - -## Initialize SDK (singleton): -```typescript -import { Webiny } from "@webiny/sdk"; - -export const sdk = new Webiny({ - token: process.env.WEBINY_API_TOKEN!, - endpoint: process.env.WEBINY_API_ENDPOINT!, - tenant: process.env.WEBINY_API_TENANT || "root" -}); -``` - -## Basic usage with Result: -```typescript -const result = await sdk.cms.listEntries({ modelId: "product" }); - -if (result.isOk()) { - const entries = result.value.data; -} else { - console.error(result.error.message); -} -``` - -## Error handling with discriminated code: -```typescript -if (result.isFail()) { - switch (result.error.code) { - case "HTTP_ERROR": - console.error(`HTTP ${result.error.data.status}`); - break; - case "GRAPHQL_ERROR": - console.error(`API error: ${result.error.data.code || "unknown"}`); - break; - case "NETWORK_ERROR": - console.error("Network failure"); - break; - } -} -``` - -## Result functional methods: -```typescript -const result = await sdk.cms.getEntry({ modelId: "product", entryId: "123" }); - -// map transforms success value -const nameResult = result.map(entry => entry.values.name); - -// mapError transforms error -const httpResult = result.mapError(e => new HttpError(500, e.message)); - -// flatMap chains Result-returning functions -const detailsResult = result.flatMap(entry => getDetails(entry.id)); - -// match handles both cases -const message = result.match({ - ok: entry => `Found: ${entry.values.name}`, - fail: error => `Error: ${error.message}` -}); -``` - -Related Documents: -- reference/sdk/cms-sdk.mdx - CmsSdk class reference (listEntries, getEntry, createEntry, etc.) -- reference/sdk/tenant-manager-sdk.mdx - TenantManagerSdk class reference -- reference/sdk/file-manager-sdk.mdx - FileManagerSdk class reference -- core-concepts/webiny-sdk.mdx - Conceptual overview of SDK (when to use, core concepts) -- headless-cms/using-webiny-sdk.mdx - Practical examples and patterns - -Key Code Locations: -- packages/sdk/src/Webiny.ts - Main class constructor and property initialization -- packages/sdk/src/types.ts - WebinyConfig interface -- packages/sdk/src/Result.ts - Result class with all methods -- packages/sdk/src/errors.ts - Error class definitions -- packages/sdk/src/CmsSdk.ts - CMS operations implementation -- packages/sdk/src/TenantManagerSdk.ts - Tenant operations implementation -- packages/sdk/src/FileManagerSdk.ts - File operations implementation - -Tone Guidelines: -- Type: Technical reference -- Audience: External developers integrating Webiny into their applications -- Voice: Concise, accurate, API-focused -- Structure: Method signatures → param tables → return types → minimal examples -- Focus: What each property/method does, not why or when to use it (that's in core-concepts/webiny-sdk.mdx) -- Examples: Minimal, type-safe, showing correct usage patterns -- Emphasis: Result pattern (every method returns Result), error handling (explicit isOk/isFail checks), type safety (generics) -- Cross-references: Link to sibling reference pages (cms-sdk, tenant-manager-sdk, file-manager-sdk) for module-specific APIs \ No newline at end of file diff --git a/docs/developer-docs/6.x/reference/sdk/index.mdx b/docs/developer-docs/6.x/reference/sdk/index.mdx deleted file mode 100644 index 5ea4bb7cc..000000000 --- a/docs/developer-docs/6.x/reference/sdk/index.mdx +++ /dev/null @@ -1,523 +0,0 @@ ---- -id: c2rrl2lu -title: Overview -description: Webiny SDK configuration, Result pattern, and error classes ---- - -import { Alert } from "@/components/Alert"; - - - -- How to install and initialize the Webiny SDK? -- What is the `WebinyConfig` interface and its required fields? -- How does the `Result` pattern work for error handling? -- What error classes are available and when are they used? - - - -## Overview - -The Webiny SDK (`@webiny/sdk`) is a standalone TypeScript library that provides a programmatic interface for interacting with Webiny from external JavaScript or TypeScript applications. It is designed for use in Next.js, Node.js scripts, Vue, SvelteKit, or any JavaScript runtime outside the Webiny backend. Unlike internal Webiny extensions (which import from `webiny/*`), the SDK is installed via npm and imported from `@webiny/sdk`. - -All SDK methods return a `Result` type instead of throwing errors, making error handling explicit and predictable. The SDK automatically selects the correct API (Read or Manage) based on the operation and handles authentication using API key tokens. - -## Installation - -Install the SDK as a dependency in your project: - -```bash -npm install @webiny/sdk -``` - -## Initialization - -Create a singleton instance of the `Webiny` class and reuse it throughout your application: - -```typescript lib/webiny.ts -import { Webiny } from "@webiny/sdk"; - -export const sdk = new Webiny({ - token: process.env.WEBINY_API_TOKEN!, - endpoint: process.env.WEBINY_API_ENDPOINT!, - tenant: process.env.WEBINY_API_TENANT || "root" -}); -``` - -Store credentials in environment variables: - -```bash .env -WEBINY_API_TOKEN=your-api-token -WEBINY_API_ENDPOINT=https://xxx.cloudfront.net -WEBINY_API_TENANT=root -``` - - - -Run `yarn webiny info` in your Webiny project to find the API endpoint URL. Use the base CloudFront domain (e.g., `https://xxx.cloudfront.net`), not the full path with `/graphql`. - - - -## Quick Start - -```typescript -import { sdk } from "@/lib/webiny"; - -// List entries from a content model -const result = await sdk.cms.listEntries({ - modelId: "product", - fields: ["id", "entryId", "values.name", "values.price"] -}); - -// Check for errors using Result pattern -if (result.isOk()) { - const products = result.value.data; - console.log(`Found ${products.length} products`); -} else { - console.error("Error:", result.error.message); - console.error("Code:", result.error.code); -} -``` - -## Webiny Class - -The main entry point to the SDK. Create one instance per application and reuse it. - -### Constructor - -```typescript -constructor(config: WebinyConfig) -``` - -**Parameters:** - -| Name | Type | Required | Description | -| -------- | -------------- | -------- | ------------------------ | -| `config` | `WebinyConfig` | Yes | SDK configuration object | - -### Properties - -| Name | Type | Description | -| --------------- | ------------------ | ---------------------------- | -| `cms` | `CmsSdk` | Headless CMS operations | -| `tenantManager` | `TenantManagerSdk` | Tenant management operations | -| `fileManager` | `FileManagerSdk` | File Manager operations | - -**Example:** - -```typescript -import { Webiny } from "@webiny/sdk"; - -const sdk = new Webiny({ - token: "your-api-token", - endpoint: "https://xxx.cloudfront.net", - tenant: "root" -}); - -// Access different modules -const cmsResult = await sdk.cms.listEntries({ modelId: "product" }); -const fileResult = await sdk.fileManager.listFiles({ limit: 10 }); -``` - -## WebinyConfig Interface - -Configuration object passed to the `Webiny` constructor. - -### Properties - -| Name | Type | Required | Description | -| ---------- | ------------------------ | -------- | ---------------------------------------------------------------- | -| `endpoint` | `string` | Yes | Base URL of your Webiny API (e.g., `https://xxx.cloudfront.net`) | -| `token` | `string` | No | API key token from Webiny Admin (Settings → API Keys) | -| `tenant` | `string` | No | Tenant ID (defaults to `"root"`) | -| `headers` | `Record` | No | Custom HTTP headers to include in all requests | -| `fetch` | `typeof fetch` | No | Custom fetch implementation (useful for testing or proxying) | - -**Key points:** - -- `endpoint` must be the base domain, not the full GraphQL path -- `token` authenticates requests — API key must have appropriate permissions -- `tenant` defaults to `"root"` if omitted -- `headers` are merged with default headers (e.g., authorization, content-type) -- `fetch` allows custom implementations for testing or server-side rendering - -**Example:** - -```typescript -const sdk = new Webiny({ - endpoint: "https://xxx.cloudfront.net", - token: process.env.WEBINY_API_TOKEN, - tenant: "acme-corp", - headers: { - "X-Custom-Header": "value" - } -}); -``` - -## Result Class - -A container type representing either success (`ok`) or failure (`fail`). All SDK methods return `Result` instead of throwing errors. - -### Type Parameters - -| Name | Description | -| -------- | --------------------------------------- | -| `TValue` | Type of the success value | -| `TError` | Type of the error (defaults to `never`) | - -### Static Methods - -#### `Result.ok(value)` - -Creates a successful result containing the provided value. - -```typescript -public static ok(value: T): Result -public static ok(): Result -``` - -**Example:** - -```typescript -const success = Result.ok({ id: "123", name: "Product" }); -const voidSuccess = Result.ok(); -``` - -#### `Result.fail(error)` - -Creates a failed result containing the provided error. - -```typescript -public static fail(error: E): Result -``` - -**Example:** - -```typescript -const failure = Result.fail(new HttpError(404, "Not found")); -``` - -### Instance Methods - -#### `isOk()` - -Checks whether the result is successful. Acts as a type guard. - -```typescript -public isOk(): this is { _value: TValue } & Result -``` - -**Returns:** `true` if successful, `false` otherwise. - -**Example:** - -```typescript -if (result.isOk()) { - console.log(result.value); // Type-safe access to value -} -``` - -#### `isFail()` - -Checks whether the result is a failure. Acts as a type guard. - -```typescript -public isFail(): this is { _error: TError } & Result -``` - -**Returns:** `true` if failed, `false` otherwise. - -**Example:** - -```typescript -if (result.isFail()) { - console.error(result.error.message); // Type-safe access to error -} -``` - -#### `value` - -Gets the value from a successful result. - -```typescript -public get value(): TValue -``` - -**Throws:** Error if the result is a failure. - -**Example:** - -```typescript -if (result.isOk()) { - const data = result.value; // Safe after isOk() check -} -``` - -#### `error` - -Gets the error from a failed result. - -```typescript -public get error(): TError -``` - -**Throws:** Error if the result is successful. - -**Example:** - -```typescript -if (result.isFail()) { - const error = result.error; // Safe after isFail() check -} -``` - -#### `map(fn)` - -Transforms the success value using the provided function. If the result is a failure, returns the original error. - -```typescript -public map(fn: (value: TValue) => U): Result -``` - -**Parameters:** - -| Name | Type | Description | -| ---- | ---------------------- | ------------------------------- | -| `fn` | `(value: TValue) => U` | Function to transform the value | - -**Returns:** New `Result` with transformed value or original error. - -**Example:** - -```typescript -const result = Result.ok(5); -const doubled = result.map(n => n * 2); // Result.ok(10) - -const failure = Result.fail(new Error("Oops")); -const stillFailure = failure.map(n => n * 2); // Still Result.fail(error) -``` - -#### `mapError(fn)` - -Transforms the error value using the provided function. If the result is successful, returns the original value. - -```typescript -public mapError(fn: (error: TError) => F): Result -``` - -**Parameters:** - -| Name | Type | Description | -| ---- | ---------------------- | ------------------------------- | -| `fn` | `(error: TError) => F` | Function to transform the error | - -**Returns:** New `Result` with original value or transformed error. - -**Example:** - -```typescript -const result = Result.fail(new Error("Not found")); -const httpError = result.mapError(e => new HttpError(404, e.message)); -``` - -#### `flatMap(fn)` - -Chains another Result-producing function onto this result. If successful, applies the function; if failed, returns the original error. - -```typescript -public flatMap(fn: (value: TValue) => Result): Result -``` - -**Parameters:** - -| Name | Type | Description | -| ---- | -------------------------------------- | --------------------------------- | -| `fn` | `(value: TValue) => Result` | Function returning another Result | - -**Returns:** New `Result` from the function or original failure. - -**Example:** - -```typescript -const getUser = (id: string) => Result.ok({ id, name: "Alice" }); -const getEmail = (user: { id: string }) => Result.ok(`${user.id}@example.com`); - -const result = getUser("123").flatMap(user => getEmail(user)); // Result.ok("123@example.com") -``` - -#### `match(handlers)` - -Pattern-matches the result to handle both success and failure cases. - -```typescript -public match(handlers: { - ok: (value: TValue) => U; - fail: (error: TError) => U -}): U -``` - -**Parameters:** - -| Name | Type | Description | -| ---------- | ---------------------------------------------------------- | ------------------------------------ | -| `handlers` | `{ ok: (value: TValue) => U; fail: (error: TError) => U }` | Object with success/failure handlers | - -**Returns:** Result of the appropriate handler. - -**Example:** - -```typescript -const message = result.match({ - ok: data => `Success: ${data.length} items`, - fail: error => `Error: ${error.message}` -}); -console.log(message); -``` - -### Namespace Types - -#### `Result.UnwrapResult` - -Extracts the success type from a `Result`. - -```typescript -type UnwrapResult = Awaited extends Result ? Ok : never; -``` - -**Example:** - -```typescript -type MyResult = Result; -type Value = Result.UnwrapResult; // string -``` - -#### `Result.UnwrapError` - -Extracts the error type from a `Result`. - -```typescript -type UnwrapError = Awaited extends Result ? Err : never; -``` - -**Example:** - -```typescript -type MyResult = Result; -type ErrorType = Result.UnwrapError; // HttpError -``` - -## Error Classes - -The SDK defines three error classes for different failure scenarios. All extend `BaseError` and include a `code` property for programmatic error handling. - -### HttpError - -HTTP-level errors (e.g., 404 Not Found, 500 Internal Server Error). - -```typescript -class HttpError extends BaseError<{ status: number }> -``` - -**Properties:** - -| Name | Type | Description | -| --------- | -------- | -------------------------- | -| `code` | `string` | Always `"HTTP_ERROR"` | -| `message` | `string` | Error message | -| `data` | `object` | Contains `status` property | - -**Example:** - -```typescript -const result = await sdk.cms.getEntry({ modelId: "product", entryId: "999" }); - -if (result.isFail() && result.error.code === "HTTP_ERROR") { - console.error(`HTTP ${result.error.data.status}: ${result.error.message}`); -} -``` - -### GraphQLError - -GraphQL-level errors returned by the API (e.g., validation errors, permission errors). - -```typescript -class GraphQLError extends BaseError<{ code?: string }> -``` - -**Properties:** - -| Name | Type | Description | -| --------- | -------- | ----------------------------------- | -| `code` | `string` | Always `"GRAPHQL_ERROR"` | -| `message` | `string` | Error message from GraphQL response | -| `data` | `object` | Contains optional `code` property | - -**Example:** - -```typescript -const result = await sdk.cms.createEntry({ - modelId: "product", - data: { values: {} } -}); - -if (result.isFail() && result.error.code === "GRAPHQL_ERROR") { - console.error(`GraphQL error: ${result.error.message}`); - if (result.error.data.code) { - console.error(`Error code: ${result.error.data.code}`); - } -} -``` - -### NetworkError - -Network-level errors when the fetch request itself fails (e.g., no internet connection, DNS resolution failure). - -```typescript -class NetworkError extends BaseError -``` - -**Properties:** - -| Name | Type | Description | -| --------- | -------- | ------------------------ | -| `code` | `string` | Always `"NETWORK_ERROR"` | -| `message` | `string` | Error message | - -**Example:** - -```typescript -const result = await sdk.cms.listEntries({ modelId: "product" }); - -if (result.isFail() && result.error.code === "NETWORK_ERROR") { - console.error("Network error - check your connection"); -} -``` - -### Error Handling Pattern - -Use a switch or if-else chain to handle specific error types: - -```typescript -const result = await sdk.cms.getEntry({ - modelId: "product", - entryId: "abc123" -}); - -if (result.isFail()) { - switch (result.error.code) { - case "HTTP_ERROR": - if (result.error.data.status === 404) { - console.error("Entry not found"); - } - break; - case "GRAPHQL_ERROR": - console.error("API error:", result.error.message); - break; - case "NETWORK_ERROR": - console.error("Network failure - retry later"); - break; - } - return; -} - -const entry = result.value; -``` diff --git a/docs/developer-docs/6.x/reference/sdk/tenant-manager.ai.txt b/docs/developer-docs/6.x/reference/sdk/tenant-manager.ai.txt deleted file mode 100644 index 8fb234ea6..000000000 --- a/docs/developer-docs/6.x/reference/sdk/tenant-manager.ai.txt +++ /dev/null @@ -1,78 +0,0 @@ -AI Context: Tenant Manager (reference/sdk/tenant-manager.mdx) - -Source of Information: -1. TenantManagerSdk.ts - Class definition with all four methods -2. methods/tenantManager/createTenant.ts - createTenant implementation and types -3. methods/tenantManager/installTenant.ts - installTenant implementation -4. methods/tenantManager/disableTenant.ts - disableTenant implementation -5. methods/tenantManager/enableTenant.ts - enableTenant implementation -6. methods/tenantManager/tenantManagerTypes.ts - CreateTenantInput interface -7. AGENTS.md - Documentation conventions for SDK reference pages - -Key Documentation Decisions: -1. Emphasized the two-step create+install flow as the primary use case -2. Documented all four methods with consistent structure: signature, params table, returns, example -3. Included complete examples section showing: full provisioning flow, disable/enable, error handling -4. Highlighted that API key needs tenant manager permissions -5. Used Result pattern consistently across all examples -6. Kept method descriptions concise - no duplicate explanation between method signature and params table - -Understanding of Tenant Manager SDK: -- TenantManagerSdk is accessed via sdk.tenantManager namespace -- Four operations: createTenant, installTenant, disableTenant, enableTenant -- Creating a tenant is a two-step process: create registers the tenant, install provisions it -- All methods return Result -- Tenant ID can be auto-generated (omit id field) or explicitly set -- Disabled tenants block all access until re-enabled -- All operations require tenant manager permissions on the API key - -Method Signatures and Parameters: -```typescript -// createTenant -interface CreateTenantParams { - data: CreateTenantInput; -} -interface CreateTenantInput { - id?: string; // Optional - generated if omitted - name: string; // Required - description?: string; -} - -// installTenant -interface InstallTenantParams { - tenantId: string; // Required - must match created tenant -} - -// disableTenant -interface DisableTenantParams { - tenantId: string; // Required -} - -// enableTenant -interface EnableTenantParams { - tenantId: string; // Required -} -``` - -Return Types: -- All methods: Result -- Success: result.value is true -- Failure: result.error contains message and code - -Related Documents: -1. core-concepts/webiny-sdk.mdx - SDK initialization, authentication, Result pattern -2. core-concepts/result.mdx - Result type usage and error handling -3. tenant-manager/*.mdx - Multi-tenancy concepts and management -4. reference/sdk/headless-cms.mdx - Similar SDK reference structure - -Key Code Locations: -- packages/sdk/src/TenantManagerSdk.ts - Class definition -- packages/sdk/src/methods/tenantManager/ - All tenant manager method implementations - -Tone Guidelines: -- Technical reference tone - concise, accurate, no filler -- Method descriptions are brief - implementation details left to examples -- Params tables complete and precise -- Examples show real-world patterns: full flows, error handling, common operations -- Emphasize required permissions and two-step provisioning flow -- No analogies - direct technical explanation only \ No newline at end of file diff --git a/docs/developer-docs/6.x/reference/sdk/tenant-manager.mdx b/docs/developer-docs/6.x/reference/sdk/tenant-manager.mdx deleted file mode 100644 index 2c030199b..000000000 --- a/docs/developer-docs/6.x/reference/sdk/tenant-manager.mdx +++ /dev/null @@ -1,337 +0,0 @@ ---- -id: c2rrl3rl -title: Tenant Manager -description: TenantManagerSdk reference - create and manage tenants programmatically ---- - -import { Alert } from "@/components/Alert"; - - - -- How to access the Tenant Manager SDK? -- How to create and install new tenants? -- How to disable and enable existing tenants? -- How to handle tenant management errors? - - - -## Overview - -The `TenantManagerSdk` provides methods for creating, installing, disabling, and enabling tenants programmatically. Access it via the `tenantManager` namespace on your Webiny SDK instance. Creating a new tenant requires two steps: `createTenant()` to register the tenant, then `installTenant()` to provision its resources and configurations. - -All tenant management operations require an API key with tenant manager permissions. - -## Class Reference - -### TenantManagerSdk - -The Tenant Manager SDK is accessed via `sdk.tenantManager` on a `Webiny` instance: - -```typescript -import { Webiny } from "@webiny/sdk"; - -const sdk = new Webiny({ - token: process.env.WEBINY_API_TOKEN!, - endpoint: process.env.WEBINY_API_ENDPOINT!, - tenant: "root" -}); - -// Access tenant manager operations -const result = await sdk.tenantManager.createTenant({ - data: { - name: "Acme Corp", - description: "Acme Corporation tenant" - } -}); -``` - -## Methods - -### createTenant - -Creates a new tenant in the system. Returns the tenant ID on success. - -```typescript -async createTenant( - params: CreateTenantParams -): Promise> -``` - -**Parameters:** - -| Name | Type | Required | Description | -| ------------------------- | -------------------- | -------- | --------------------------------------- | -| `params` | `CreateTenantParams` | Yes | Tenant creation parameters | -| `params.data` | `CreateTenantInput` | Yes | Tenant data | -| `params.data.id` | `string` | No | Custom tenant ID (generated if omitted) | -| `params.data.name` | `string` | Yes | Tenant name | -| `params.data.description` | `string` | No | Tenant description | - -**Returns:** - -`Result` - Success returns `true`, failure returns error with message and code. - -**Example:** - -```typescript -const result = await sdk.tenantManager.createTenant({ - data: { - id: "acme", - name: "Acme Corp", - description: "Acme Corporation tenant" - } -}); - -if (result.isFail()) { - console.error("Failed to create tenant:", result.error.message); - return; -} - -console.log("Tenant created successfully"); -``` - -### installTenant - -Installs and provisions a tenant with default settings and configurations. Must be called after `createTenant()` before the tenant is usable. - -```typescript -async installTenant( - params: InstallTenantParams -): Promise> -``` - -**Parameters:** - -| Name | Type | Required | Description | -| ----------------- | --------------------- | -------- | --------------------------- | -| `params` | `InstallTenantParams` | Yes | Installation parameters | -| `params.tenantId` | `string` | Yes | ID of the tenant to install | - -**Returns:** - -`Result` - Success returns `true`, failure returns error with message and code. - -**Example:** - -```typescript -const result = await sdk.tenantManager.installTenant({ - tenantId: "acme" -}); - -if (result.isFail()) { - console.error("Failed to install tenant:", result.error.message); - return; -} - -console.log("Tenant installed successfully"); -``` - -### disableTenant - -Disables a tenant, preventing access to its resources. Disabled tenants cannot be accessed until re-enabled. - -```typescript -async disableTenant( - params: DisableTenantParams -): Promise> -``` - -**Parameters:** - -| Name | Type | Required | Description | -| ----------------- | --------------------- | -------- | --------------------------- | -| `params` | `DisableTenantParams` | Yes | Disable parameters | -| `params.tenantId` | `string` | Yes | ID of the tenant to disable | - -**Returns:** - -`Result` - Success returns `true`, failure returns error with message and code. - -**Example:** - -```typescript -const result = await sdk.tenantManager.disableTenant({ - tenantId: "acme" -}); - -if (result.isFail()) { - console.error("Failed to disable tenant:", result.error.message); - return; -} - -console.log("Tenant disabled successfully"); -``` - -### enableTenant - -Re-enables a previously disabled tenant, restoring access to its resources. - -```typescript -async enableTenant( - params: EnableTenantParams -): Promise> -``` - -**Parameters:** - -| Name | Type | Required | Description | -| ----------------- | -------------------- | -------- | -------------------------- | -| `params` | `EnableTenantParams` | Yes | Enable parameters | -| `params.tenantId` | `string` | Yes | ID of the tenant to enable | - -**Returns:** - -`Result` - Success returns `true`, failure returns error with message and code. - -**Example:** - -```typescript -const result = await sdk.tenantManager.enableTenant({ - tenantId: "acme" -}); - -if (result.isFail()) { - console.error("Failed to enable tenant:", result.error.message); - return; -} - -console.log("Tenant enabled successfully"); -``` - -## Error Handling - -All tenant manager methods return a `Result` type. Check for errors before accessing the value: - -```typescript -const result = await sdk.tenantManager.createTenant({ - data: { - name: "Acme Corp" - } -}); - -if (result.isFail()) { - console.error("Error:", result.error.message); - console.error("Code:", result.error.code); - return; -} - -// Success - result.value is true -console.log("Operation successful"); -``` - -**Common error scenarios:** - -- Permission denied (API key lacks tenant manager permissions) -- Tenant already exists (duplicate tenant ID) -- Tenant not found (invalid tenant ID) -- Network errors (API unreachable) - -## Examples - -### Creating and Installing a New Tenant - -The complete flow for provisioning a new tenant requires two steps: - -```typescript -import { Webiny } from "@webiny/sdk"; - -const sdk = new Webiny({ - token: process.env.WEBINY_API_TOKEN!, - endpoint: process.env.WEBINY_API_ENDPOINT!, - tenant: "root" -}); - -// Step 1: Create the tenant -const createResult = await sdk.tenantManager.createTenant({ - data: { - id: "acme", - name: "Acme Corp", - description: "Acme Corporation tenant" - } -}); - -if (createResult.isFail()) { - console.error("Failed to create tenant:", createResult.error.message); - return; -} - -console.log("Tenant created successfully"); - -// Step 2: Install the tenant -const installResult = await sdk.tenantManager.installTenant({ - tenantId: "acme" -}); - -if (installResult.isFail()) { - console.error("Failed to install tenant:", installResult.error.message); - return; -} - -console.log("Tenant installed and ready to use"); -``` - -### Disabling and Enabling a Tenant - -```typescript -// Disable a tenant -const disableResult = await sdk.tenantManager.disableTenant({ - tenantId: "acme" -}); - -if (disableResult.isFail()) { - console.error("Failed to disable tenant:", disableResult.error.message); - return; -} - -console.log("Tenant disabled - access blocked"); - -// Later, re-enable the tenant -const enableResult = await sdk.tenantManager.enableTenant({ - tenantId: "acme" -}); - -if (enableResult.isFail()) { - console.error("Failed to enable tenant:", enableResult.error.message); - return; -} - -console.log("Tenant re-enabled - access restored"); -``` - -### Error Handling Pattern - -```typescript -async function provisionTenant(tenantId: string, name: string) { - // Create tenant - const createResult = await sdk.tenantManager.createTenant({ - data: { id: tenantId, name } - }); - - if (createResult.isFail()) { - return { - success: false, - error: `Create failed: ${createResult.error.message}` - }; - } - - // Install tenant - const installResult = await sdk.tenantManager.installTenant({ - tenantId - }); - - if (installResult.isFail()) { - return { - success: false, - error: `Install failed: ${installResult.error.message}` - }; - } - - return { success: true }; -} - -// Usage -const result = await provisionTenant("acme", "Acme Corp"); -if (!result.success) { - console.error(result.error); -} -``` diff --git a/generateDocs.js b/generateDocs.js deleted file mode 100644 index c439145d0..000000000 --- a/generateDocs.js +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env node -process.env.NODE_PATH = process.cwd(); -const tsNode = require("ts-node"); -const { resolve } = require("path"); -const yargs = require("yargs"); - -tsNode.register({ - dir: resolve(__dirname, "./generator") -}); - -const { App, AppConfig } = require("@webiny/docs-generator"); -const { default: docsConfig } = require("./docs.config"); - -(async () => { - const { watch, watchOnly, version } = yargs - .version(false) - .option("v", { - alias: "version", - describe: "Whitelist versions to build.", - type: "array", - default: [] - }) - .option("watch", { - default: false, - description: "Run generator and watch for changes.", - type: "boolean" - }) - .option("watchOnly", { - default: false, - description: "Only watch for changes, without the initial generation.", - type: "boolean" - }).argv; - - const config = AppConfig.create({ - linkValidator: docsConfig.linkValidator, - mdxRemarkPlugins: docsConfig.mdxRemarkPlugins, - projectRootDir: docsConfig.projectRootDir, - devMode: process.env.NODE_ENV === "development", - documentRootConfigs: docsConfig.documentRoots.filter(Boolean), - outputVersions: version, - sitemapOutputPath: docsConfig.sitemapOutputPath - }); - - const app = new App(config); - - if (watchOnly) { - await app.watch(); - } - - try { - if (docsConfig.cleanOutputDir) { - const rimraf = require("rimraf"); - console.log("Cleaning output directory..."); - docsConfig.cleanOutputDir.forEach(dir => rimraf.sync(dir)); - } - await app.generate(); - } catch (err) { - process.exit(1); - } - - if (watch) { - await app.watch(); - } - - process.exit(); -})(); diff --git a/package.json b/package.json index 390c7507b..6b209db00 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,7 @@ ], "scripts": { "dev": "./scripts/dev.sh", - "generate": "node generateDocs.js", - "build": "yarn generate && node scripts/generate-v5-redirects.js && next build", + "build": "node scripts/generate-v5-redirects.js && next build", "build:next": "next build", "dev:next": "next dev", "start": "next start", @@ -17,12 +16,7 @@ "prepare-release-notes": "node scripts/prepareReleaseNotes.js", "lint:fix": "yarn format && yarn eslint", "get-id": "node -e 'console.log(require(\"@webiny/utils\").mdbid().slice(-8))'", - "validate:mdx": "tsx scripts/validate-mdx-pairing.ts", - "generate:reference": "tsx scripts/generate-reference.ts", - "generate:reference:ai": "tsx scripts/ref/sdk.ts", - "generate:reference:ai:force": "tsx scripts/ref/sdk.ts --force", - "generate:sdk": "tsx scripts/ref/webiny-sdk.ts", - "generate:sdk:force": "tsx scripts/ref/webiny-sdk.ts --force" + "validate:mdx": "tsx scripts/validate-mdx-pairing.ts" }, "browserslist": { "development": [ diff --git a/public/menu-icons/api.svg b/public/menu-icons/api.svg new file mode 100644 index 000000000..cfbe8dc3a --- /dev/null +++ b/public/menu-icons/api.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/scripts/generate-reference.ts b/scripts/generate-reference.ts deleted file mode 100644 index cd0e087e4..000000000 --- a/scripts/generate-reference.ts +++ /dev/null @@ -1,2478 +0,0 @@ -/** - * Reference Documentation Generator - * - * Reads every export path from packages/webiny/src/, resolves each exported - * symbol back to its originating @webiny/* source file, extracts TypeScript - * interface signatures + JSDoc comments + namespace types, and writes: - * - One .mdx page per webiny/* entry point - * - One .ai.txt companion per page - * - * Then rewrites the Reference in navigation.tsx with all generated pages. - * - * Usage: yarn generate:reference - */ - -import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs"; -import { join, dirname } from "path"; -import { Project, SourceFile, SyntaxKind, Node } from "ts-morph"; -import slugify from "@sindresorhus/slugify"; - -// --------------------------------------------------------------------------- -// Config -// --------------------------------------------------------------------------- - -const WEBINY_PKG = "/Users/adrian/dev/wby-next/packages/webiny"; -const WEBINY_MONOREPO = "/Users/adrian/dev/wby-next/packages"; -const DOCS_ROOT = join(process.cwd(), "docs/developer-docs/6.x"); -const REF_DIR = join(DOCS_ROOT, "reference"); -const NAV_FILE = join(DOCS_ROOT, "navigation.tsx"); - -// Module-level package path map, populated in main() before any extraction -let PKG_MAP: Map = new Map(); - -// --------------------------------------------------------------------------- -// Types -// --------------------------------------------------------------------------- - -interface ExportEntry { - /** The local alias used in the barrel (what consumers import) */ - exportedName: string; - /** Original name in the source file (before `as` rename) */ - originalName: string; - /** Absolute path to the originating source .ts file */ - sourceFile: string; - /** Whether it's a type-only export */ - isTypeOnly: boolean; -} - -interface InterfaceMember { - /** e.g. "execute(model: CmsModel, input: Input): Promise>" */ - signature: string; - /** JSDoc on this specific member */ - jsDoc: string; -} - -interface ResolvedTypeFields { - /** The interface/type name that was resolved (e.g. "AppInstallationData") */ - typeName: string; - /** Whether it was an array (e.g. InstallSystemInput = AppInstallationData[]) */ - isArray: boolean; - /** JSDoc on the resolved interface */ - jsDoc: string; - /** The fields of the resolved object interface */ - fields: EventPayloadField[]; -} - -interface NamespaceMember { - /** e.g. "Interface" */ - name: string; - /** e.g. "ICreateEntryUseCase" or "Promise>" */ - value: string; - /** Resolved fields if the type alias points to a plain object interface */ - resolvedFields?: ResolvedTypeFields; - /** Resolved interface members if the type alias points to a method interface (e.g. Foo.Interface) */ - resolvedMembers?: { members: InterfaceMember[]; jsDoc: string }; -} - -interface EventPayloadField { - name: string; - typeText: string; - optional: boolean; -} - -type AbstractionKind = "useCase" | "eventHandler" | "service"; - -interface ExtractedSymbol { - name: string; - kind: - | "abstraction" - | "interface" - | "class" - | "namespace" - | "function" - | "variable" - | "type" - | "enum" - | "other"; - isTypeOnly: boolean; - /** Full text of the declaration (interface body, class signature, etc.) */ - declarationText: string; - /** JSDoc comment attached to the declaration */ - jsDoc: string; - /** Namespace members if kind === 'namespace' */ - namespaceMembers: string[]; - sourceFile: string; - - // --- Abstraction-specific enrichment --- - /** Set when kind === 'abstraction' */ - abstractionKind?: AbstractionKind; - /** The resolved Interface members (from IFoo that createAbstraction wraps) */ - interfaceMembers?: InterfaceMember[]; - /** JSDoc on the IFoo interface itself (description paragraph) */ - interfaceJsDoc?: string; - /** Resolved namespace type members: Interface, Input, Return, Error, Event, etc. */ - namespaceTypes?: NamespaceMember[]; - /** For eventHandler: the payload fields of the event */ - eventPayloadFields?: EventPayloadField[]; - /** For eventHandler: the event type name e.g. "EntryBeforeCreateEvent" */ - eventTypeName?: string; - /** For eventHandler: the payload interface name */ - eventPayloadName?: string; -} - -interface EntryPointDoc { - /** e.g. "webiny/api/cms/entry" */ - importPath: string; - /** e.g. "api/cms/entry" */ - relPath: string; - /** Human-readable title */ - title: string; - /** Short description */ - description: string; - /** All symbols exported from this entry point */ - symbols: ExtractedSymbol[]; -} - -// --------------------------------------------------------------------------- -// Helpers -// --------------------------------------------------------------------------- - -function randomId(): string { - return Math.random().toString(36).slice(2, 10).padEnd(8, "0").slice(0, 8); -} - -/** Convert a barrel-relative path to a human title: "api/cms/entry" -> "CMS Entry" */ -function toTitle(relPath: string): string { - const parts = relPath.split("/"); - const last = parts[parts.length - 1]; - - const specialCases: Record = { - api: "API", - cms: "CMS", - graphql: "GraphQL", - ui: "UI", - aco: "ACO", - cli: "CLI", - infra: "Infrastructure", - extensions: "Extensions", - admin: "Admin", - index: "Overview", - buildParams: "Build Params", - eventPublisher: "Event Publisher", - keyValueStore: "Key-Value Store", - tenancy: "Tenancy", - security: "Security", - system: "System", - tasks: "Tasks", - logger: "Logger", - entry: "Entry", - group: "Group", - model: "Model", - field: "Field", - page: "Page", - redirect: "Redirect", - nextjs: "Next.js", - apiKey: "API Key", - authentication: "Authentication", - role: "Role", - user: "User", - lexical: "Lexical Editor", - form: "Form", - router: "Router", - localStorage: "Local Storage", - envConfig: "Env Config", - graphqlClient: "GraphQL Client", - configs: "Configs", - "website-builder": "Website Builder", - "tenant-manager": "Tenant Manager", - command: "Command", - core: "Core" - }; - - const section = - specialCases[last] ?? last.replace(/-/g, " ").replace(/\b\w/g, c => c.toUpperCase()); - const parentSection = - parts.length > 1 ? (specialCases[parts[parts.length - 2]] ?? parts[parts.length - 2]) : ""; - - // Compose a meaningful title from last two segments - if (parts.length === 1) return section; - if (last === "index") return parentSection; - return section; -} - -/** Derive a description string from the entry point path */ -function toDescription(relPath: string): string { - const map: Record = { - api: "Core API primitives: createFeature, createAbstraction, Result, BaseError", - "api/logger": "Logger abstraction for server-side logging", - "api/graphql": "GraphQL schema factory and response helpers", - "api/eventPublisher": "Domain event publishing primitives", - "api/keyValueStore": "Key-value store abstraction", - "api/buildParams": "API build parameter types", - "api/tasks": "Background task abstractions: TaskService, TaskDefinition", - "api/system": "System installation abstractions", - "api/tenancy": "Tenancy context and tenant management", - "api/tenant-manager": "Tenant manager abstractions", - "api/security": "Security primitives: Identity, Authenticator, Authorizer", - "api/security/apiKey": "API key use cases and event handlers", - "api/security/authentication": "Authentication event handlers", - "api/security/role": "Role use cases and event handlers", - "api/security/user": "User use cases and event handlers", - "api/cms/entry": "CMS entry use cases and event handlers", - "api/cms/group": "CMS group use cases and event handlers", - "api/cms/model": "CMS model builders, factories, use cases and event handlers", - "api/website-builder/page": "Website Builder page use cases and event handlers", - "api/website-builder/redirect": "Website Builder redirect use cases and event handlers", - "api/website-builder/nextjs": "Next.js configuration abstraction", - admin: "Admin app core: createFeature, createAbstraction, Provider, Plugin", - "admin/ui": "Admin UI component library", - "admin/form": "Form primitives: Bind, Form, useForm, validation", - "admin/aco": "ACO (Advanced Content Organisation) hooks and utilities", - "admin/buildParams": "Admin build parameter types", - "admin/cms": "CMS admin hooks, types and utilities", - "admin/cms/entry/editor": "Content entry editor components and hooks", - "admin/cms/entry/list": "Content entry list configuration", - "admin/cms/fieldRenderers/dynamicZone": "Dynamic zone field renderer components", - "admin/cms/fieldRenderers/object": "Object field renderer components", - "admin/cms/lexical": "CMS Lexical rich-text editor config", - "admin/configs": "Admin configuration types", - "admin/envConfig": "Environment configuration for admin", - "admin/graphqlClient": "GraphQL client hooks and utilities", - "admin/localStorage": "Local storage abstraction and hooks", - "admin/lexical": "Lexical editor components and hooks", - "admin/router": "Router components and hooks", - "admin/security": "Admin security: authentication, identity, permissions", - "admin/tenancy": "Admin tenancy hooks and context", - "admin/website-builder": "Website Builder admin utilities", - "admin/website-builder/lexical": "Website Builder Lexical editor config", - "admin/website-builder/page/editor": "Page editor components", - "admin/website-builder/page/list": "Page list configuration", - "admin/website-builder/redirect/list": "Redirect list configuration", - extensions: "Project extension wiring: Api, Admin, Cli, Infra, Project, EnvVar, FeatureFlags", - "infra/index": "Infrastructure primitives: Logger, Ui, lifecycle hooks", - "infra/api": "API infrastructure lifecycle hooks and Pulumi abstraction", - "infra/admin": "Admin infrastructure lifecycle hooks and Pulumi abstraction", - "infra/core": "Core infrastructure lifecycle hooks and Pulumi abstraction", - "cli/index": "CLI-scoped Logger and Ui abstractions", - "cli/command": "CLI command factory abstraction" - }; - return map[relPath] ?? `Reference for webiny/${relPath}`; -} - -// --------------------------------------------------------------------------- -// Path resolution: @webiny/pkg/path.js -> absolute filesystem path -// --------------------------------------------------------------------------- - -/** Build a map of @webiny/* package names to their src/ directories */ -function buildPackagePathMap(): Map { - const map = new Map(); - const entries = readFileSync(join(WEBINY_PKG, "tsconfig.json"), "utf-8"); - // strip comments from tsconfig (it's not valid JSON) - const cleaned = entries.replace(/\/\/[^\n]*/g, "").replace(/\/\*[\s\S]*?\*\//g, ""); - const tsconfig = JSON.parse(cleaned); - const paths: Record = tsconfig?.compilerOptions?.paths ?? {}; - - for (const [alias, targets] of Object.entries(paths)) { - if (!alias.startsWith("@webiny/")) continue; - const rawTarget = targets[0]; - if (!rawTarget) continue; - // e.g. "../api-core/src/*" -> /abs/path/to/api-core/src - const resolved = join(WEBINY_PKG, rawTarget.replace(/\/\*$/, "").replace(/\*$/, "")); - // strip trailing /src to get the package root, store both with and without - const pkgAlias = alias.replace(/\/\*$/, ""); - map.set(pkgAlias, resolved); - } - return map; -} - -/** Resolve "@webiny/api-core/features/task/TaskDefinition/index.js" to absolute path */ -function resolveWebinyImport(importPath: string, pkgMap: Map): string | null { - for (const [alias, srcDir] of Array.from(pkgMap.entries())) { - if (importPath.startsWith(alias + "/")) { - const rest = importPath.slice(alias.length + 1).replace(/\.js$/, ".ts"); - return join(srcDir, rest); - } - if (importPath === alias) { - return join(srcDir, "index.ts"); - } - } - return null; -} - -// --------------------------------------------------------------------------- -// Barrel parsing: collect all re-exported names from a barrel .ts file -// --------------------------------------------------------------------------- - -function parseBarrel(sf: SourceFile, pkgMap: Map): ExportEntry[] { - const entries: ExportEntry[] = []; - - for (const decl of sf.getExportDeclarations()) { - const moduleSpecifier = decl.getModuleSpecifierValue(); - if (!moduleSpecifier) continue; - - const resolvedPath = resolveWebinyImport(moduleSpecifier, pkgMap); - if (!resolvedPath) continue; - - const isTypeOnly = decl.isTypeOnly(); - const namedExports = decl.getNamedExports(); - - if (namedExports.length === 0) { - // export * from "..." - entries.push({ - exportedName: "*", - originalName: "*", - sourceFile: resolvedPath, - isTypeOnly - }); - } else { - for (const ne of namedExports) { - entries.push({ - exportedName: ne.getAliasNode()?.getText() ?? ne.getNameNode().getText(), - originalName: ne.getNameNode().getText(), - sourceFile: resolvedPath, - isTypeOnly: isTypeOnly || ne.isTypeOnly() - }); - } - } - } - - return entries; -} - -// --------------------------------------------------------------------------- -// Symbol extraction from a source file -// --------------------------------------------------------------------------- - -function extractJsDoc(node: Node): string { - const jsDocNodes = node.getChildrenOfKind(SyntaxKind.JSDoc); - if (jsDocNodes.length === 0) return ""; - return jsDocNodes - .map(jd => jd.getInnerText().trim()) - .filter(Boolean) - .join("\n"); -} - -/** Returns true if a node has an @internal JSDoc tag */ -function isInternalNode(node: Node): boolean { - const jsDocNodes = node.getChildrenOfKind(SyntaxKind.JSDoc); - return jsDocNodes.some(jd => jd.getText().includes("@internal")); -} - -function cleanDeclarationText(text: string): string { - return text - .replace(/\{[\s\S]*\}/g, match => { - if (match.length < 200 && !match.includes("return ") && !match.includes("const ")) { - return match; - } - return "{ ... }"; - }) - .trim(); -} - -// Isolated project for interface extraction (avoids cross-file resolution issues) -let _isolatedProject: Project | null = null; -function getIsolatedProject(): Project { - if (!_isolatedProject) { - _isolatedProject = new Project({ - useInMemoryFileSystem: false, - skipAddingFilesFromTsConfig: true - }); - } - return _isolatedProject; -} - -/** - * Search a source file (and any files it re-exports from) for an interface by name. - * Returns the interface members and interface-level JSDoc, or empty if not found. - */ -interface InterfaceResult { - members: InterfaceMember[]; - jsDoc: string; -} - -function extractInterfaceMembers( - sf: SourceFile, - interfaceName: string, - pkgMap?: Map, - visited = new Set() -): InterfaceResult { - const filePath = sf.getFilePath(); - if (visited.has(filePath)) return { members: [], jsDoc: "" }; - visited.add(filePath); - - // Search all interfaces in this file - const allIfaces = [ - ...sf.getInterfaces(), - ...sf.getStatements().filter(Node.isInterfaceDeclaration) - ].filter(Node.isInterfaceDeclaration); - - const iface = allIfaces.find(i => i.getName() === interfaceName); - if (iface) { - return { - members: iface - .getMembers() - .filter(m => !isInternalNode(m)) - .map(m => ({ - signature: m.getText().trim().replace(/;$/, ""), - jsDoc: extractJsDoc(m) - })), - jsDoc: extractJsDoc(iface) - }; - } - - // Raw text fallback for this file (no JSDoc available here) - const src = sf.getFullText(); - const rawMatch = src.match( - new RegExp(`interface\\s+${interfaceName}\\s*(?:<[^{]*>)?\\s*\\{([^}]+)\\}`) - ); - if (rawMatch) { - return { - members: rawMatch[1] - .split("\n") - .map(l => l.trim()) - .filter(l => l && !l.startsWith("//") && l !== "{" && l !== "}") - .map(l => ({ signature: l.replace(/;$/, ""), jsDoc: "" })), - jsDoc: "" - }; - } - - // Follow re-exports into sibling files (handles index.ts -> abstractions.ts pattern) - if (pkgMap) { - for (const decl of sf.getExportDeclarations()) { - const modSpec = decl.getModuleSpecifierValue(); - if (!modSpec) continue; - - let resolvedPath: string | null = null; - if (modSpec.startsWith(".")) { - const dir = sf.getDirectoryPath(); - resolvedPath = join(dir, modSpec.replace(/\.js$/, ".ts")); - } else { - resolvedPath = resolveWebinyImport(modSpec, pkgMap); - } - - if (!resolvedPath || !existsSync(resolvedPath)) continue; - - try { - const siblingSf = sf.getProject().addSourceFileAtPath(resolvedPath); - const result = extractInterfaceMembers(siblingSf, interfaceName, pkgMap, visited); - if (result.members.length > 0) return result; - } catch { - continue; - } - } - } - - return { members: [], jsDoc: "" }; -} - -/** Extract fields from an interface declaration as EventPayloadField[] */ -function extractPayloadFields(sf: SourceFile, interfaceName: string): EventPayloadField[] { - // Try AST first - const iface = [ - ...sf.getInterfaces(), - ...sf.getStatements().filter(Node.isInterfaceDeclaration) - ].find(i => Node.isInterfaceDeclaration(i) && i.getName() === interfaceName); - - if (iface && Node.isInterfaceDeclaration(iface)) { - return iface.getProperties().map(p => ({ - name: p.getName(), - typeText: p.getTypeNode()?.getText() ?? "unknown", - optional: p.hasQuestionToken() - })); - } - - // Raw text fallback - const src = sf.getFullText(); - const regex = new RegExp(`interface\\s+${interfaceName}\\s*\\{([^}]+)\\}`); - const match = src.match(regex); - if (!match) return []; - - return match[1] - .split("\n") - .map(l => l.trim()) - .filter(l => l && !l.startsWith("//")) - .map(l => { - const propMatch = l.match(/^(\w+)(\?)?:\s*(.+?);?$/); - if (!propMatch) return null; - return { name: propMatch[1], typeText: propMatch[3], optional: !!propMatch[2] }; - }) - .filter((f): f is EventPayloadField => f !== null); -} - -/** - * Resolve a module specifier to an absolute .ts file path. - * Handles: relative ("./" "../"), @webiny/* aliases, and "~/*" (local src alias). - */ -function resolveModuleSpecifier( - sf: SourceFile, - modSpec: string, - pkgMap: Map -): string | null { - if (modSpec.startsWith(".")) { - return join(sf.getDirectoryPath(), modSpec.replace(/\.js$/, ".ts")); - } - if (modSpec.startsWith("~/")) { - // "~/" maps to the "src/" root of the current package. - // Walk up from the current file to find the "src" directory boundary. - const parts = sf.getFilePath().split("/"); - const srcIdx = parts.lastIndexOf("src"); - if (srcIdx !== -1) { - const srcRoot = parts.slice(0, srcIdx + 1).join("/"); - return join(srcRoot, modSpec.slice(2).replace(/\.js$/, ".ts")); - } - return null; - } - return resolveWebinyImport(modSpec, pkgMap); -} - -/** - * Resolve a "Namespace.Interface" type reference to interface members. - * e.g. "GraphQLSchemaBuilder.Interface" → finds GraphQLSchemaBuilder's IGraphQLSchemaBuilder interface. - */ -function resolveNamespaceDotInterface( - sf: SourceFile, - typeText: string, - pkgMap: Map -): { members: InterfaceMember[]; jsDoc: string } | null { - // Only handle Foo.Interface pattern - const m = typeText.match(/^(\w+)\.Interface$/); - if (!m) return null; - const abstractionName = m[1]; - - // Find where abstractionName is imported from - for (const decl of sf.getImportDeclarations()) { - const named = decl.getNamedImports().find(n => n.getName() === abstractionName); - if (!named) continue; - const modSpec = decl.getModuleSpecifierValue(); - const resolvedPath = resolveModuleSpecifier(sf, modSpec, pkgMap); - if (!resolvedPath || !existsSync(resolvedPath)) continue; - try { - const targetSf = sf.getProject().addSourceFileAtPath(resolvedPath); - // In the target file, find createAbstraction for this name and extract IFoo - const exported = targetSf.getExportedDeclarations(); - const decls = exported.get(abstractionName); - if (!decls) continue; - const varDecl = decls.find(d => Node.isVariableDeclaration(d)); - if (!varDecl || !Node.isVariableDeclaration(varDecl)) continue; - const genericArg = getCreateAbstractionGeneric(varDecl); - if (!genericArg) continue; - const nodeSf = varDecl.getSourceFile(); - return extractInterfaceMembers(nodeSf, genericArg, pkgMap).members.length > 0 - ? extractInterfaceMembers(nodeSf, genericArg, pkgMap) - : null; - } catch { - continue; - } - } - return null; -} - -/** - * Given a type alias name (e.g. "InstallSystemInput") in a source file, resolves it to - * an object interface and returns its fields. Only resolves simple aliases: - * type Foo = SomeInterface → fields of SomeInterface - * type Foo = SomeInterface[] → fields of SomeInterface (isArray=true) - * Skips generics, unions, Promise<...>, primitives, etc. - * Follows re-exports into sibling files. - */ -function resolveTypeToFields( - sf: SourceFile, - typeName: string, - pkgMap: Map, - visited = new Set() -): ResolvedTypeFields | null { - const filePath = sf.getFilePath(); - if (visited.has(filePath)) return null; - visited.add(filePath); - - // Find the type alias in this file - const typeAlias = sf.getTypeAliases().find(t => t.getName() === typeName); - if (typeAlias) { - const typeNode = typeAlias.getTypeNode(); - if (!typeNode) return null; - const typeText = typeNode.getText().trim(); - - // Skip anything with generics, unions, intersections, Promise, or primitives - if ( - typeText.includes("<") || - typeText.includes("|") || - typeText.includes("&") || - typeText === "string" || - typeText === "number" || - typeText === "boolean" || - typeText === "any" || - typeText === "void" || - typeText === "unknown" - ) { - return null; - } - - // Array alias: type Foo = Bar[] - const arrayMatch = typeText.match(/^(\w+)\[\]$/); - if (arrayMatch) { - const innerName = arrayMatch[1]; - const inner = resolveInterfaceFields(sf, innerName, pkgMap); - if (!inner) return null; - return { typeName: innerName, isArray: true, jsDoc: inner.jsDoc, fields: inner.fields }; - } - - // Direct alias: type Foo = Bar - if (/^\w+$/.test(typeText)) { - const inner = resolveInterfaceFields(sf, typeText, pkgMap); - if (!inner) return null; - return { typeName: typeText, isArray: false, jsDoc: inner.jsDoc, fields: inner.fields }; - } - - return null; - } - - // Follow re-exports - for (const decl of sf.getExportDeclarations()) { - const modSpec = decl.getModuleSpecifierValue(); - if (!modSpec) continue; - const resolvedPath = resolveModuleSpecifier(sf, modSpec, pkgMap); - if (!resolvedPath || !existsSync(resolvedPath)) continue; - try { - const siblingSf = sf.getProject().addSourceFileAtPath(resolvedPath); - const result = resolveTypeToFields(siblingSf, typeName, pkgMap, visited); - if (result) return result; - } catch { - continue; - } - } - - return null; -} - -/** - * Find an interface by name in a source file (or via imports) and return its fields + JSDoc. - */ -function resolveInterfaceFields( - sf: SourceFile, - interfaceName: string, - pkgMap: Map, - visited = new Set() -): { fields: EventPayloadField[]; jsDoc: string } | null { - const filePath = sf.getFilePath(); - if (visited.has(filePath)) return null; - visited.add(filePath); - - // Look for the interface in this file - const allIfaces = [ - ...sf.getInterfaces(), - ...sf.getStatements().filter(Node.isInterfaceDeclaration) - ].filter(Node.isInterfaceDeclaration); - - const iface = allIfaces.find(i => i.getName() === interfaceName); - if (iface) { - const fields = iface - .getProperties() - .filter(p => !isInternalNode(p)) - .map(p => ({ - name: p.getName(), - typeText: p.getTypeNode()?.getText() ?? "unknown", - optional: p.hasQuestionToken() - })); - return { fields, jsDoc: extractJsDoc(iface) }; - } - - // Follow named imports - for (const decl of sf.getImportDeclarations()) { - const named = decl.getNamedImports().find(n => n.getName() === interfaceName); - if (!named) continue; - const modSpec = decl.getModuleSpecifierValue(); - const resolvedPath = resolveModuleSpecifier(sf, modSpec, pkgMap); - if (!resolvedPath || !existsSync(resolvedPath)) continue; - try { - const siblingSf = sf.getProject().addSourceFileAtPath(resolvedPath); - const result = resolveInterfaceFields(siblingSf, interfaceName, pkgMap, visited); - if (result) return result; - } catch { - continue; - } - } - - // Follow re-exports (export * from "..." or export { X } from "...") - for (const decl of sf.getExportDeclarations()) { - const namedExports = decl.getNamedExports(); - // Only follow if it's export * or exports our interface name - if (namedExports.length > 0 && !namedExports.some(n => n.getName() === interfaceName)) continue; - const modSpec = decl.getModuleSpecifierValue(); - if (!modSpec) continue; - const resolvedPath = resolveModuleSpecifier(sf, modSpec, pkgMap); - if (!resolvedPath || !existsSync(resolvedPath)) continue; - try { - const siblingSf = sf.getProject().addSourceFileAtPath(resolvedPath); - const result = resolveInterfaceFields(siblingSf, interfaceName, pkgMap, visited); - if (result) return result; - } catch { - continue; - } - } - - return null; -} - -/** Extract namespace type members as NamespaceMember[] */ -function extractNamespaceTypes(sf: SourceFile, namespaceName: string): NamespaceMember[] { - const allModules = sf.getModules(); - const ns = allModules.find(m => m.getName() === namespaceName); - if (!ns) return []; - - const body = ns.getBody(); - if (!body || !Node.isModuleBlock(body)) return []; - - const members: NamespaceMember[] = []; - for (const stmt of body.getStatements()) { - if (Node.isTypeAliasDeclaration(stmt)) { - const typeNode = stmt.getTypeNode(); - members.push({ - name: stmt.getName(), - value: typeNode?.getText() ?? stmt.getText() - }); - } else if (Node.isInterfaceDeclaration(stmt)) { - members.push({ name: stmt.getName() ?? "", value: "interface" }); - } else if (Node.isExportDeclaration(stmt)) { - members.push({ name: "", value: stmt.getText() }); - } - } - return members.filter(m => m.name); -} - -/** - * If a variable declaration is `createAbstraction(...)` or - * `createAbstraction>(...)`, return the generic arg text. - * Handles nested generics by counting angle brackets. - */ -function getCreateAbstractionGeneric(node: Node): string | null { - if (!Node.isVariableDeclaration(node)) return null; - const initializer = node.getInitializer(); - if (!initializer) return null; - - const txt = initializer.getText().replace(/\s+/g, " "); - const startKeyword = "createAbstraction<"; - const idx = txt.indexOf(startKeyword); - if (idx === -1) return null; - - // Walk from after the '<', counting depth to find the matching '>' - let depth = 1; - let i = idx + startKeyword.length; - let start = i; - while (i < txt.length && depth > 0) { - if (txt[i] === "<") depth++; - else if (txt[i] === ">") depth--; - i++; - } - if (depth !== 0) return null; - return txt.slice(start, i - 1).trim(); -} - -/** - * Classify an abstraction based on its name and generic type arg. - */ -function classifyAbstraction(name: string, genericArg: string): AbstractionKind { - if (name.endsWith("EventHandler") || name.endsWith("Handler")) return "eventHandler"; - if (name.endsWith("UseCase") || name.endsWith("Repository")) return "useCase"; - return "service"; -} - -/** - * For an IEventHandler generic arg, extract the event class name. - * e.g. "IEventHandler" -> "EntryBeforeCreateEvent" - * Also handles "IEventHandler>" -> "DomainEvent" - */ -function extractEventTypeName(genericArg: string): string | null { - // Simple case: IEventHandler - const simple = genericArg.match(/IEventHandler\s*<\s*(\w+)\s*>/); - if (simple) return simple[1]; - // Nested case: IEventHandler> - const nested = genericArg.match(/IEventHandler\s*<\s*(DomainEvent\s*<\s*\w+\s*>)\s*>/); - if (nested) return nested[1]; - return null; -} - -/** - * For an IEventHandler> generic arg, extract the payload name directly. - * e.g. "IEventHandler>" -> "PageBeforeCreatePayload" - */ -function extractPayloadNameFromGenericArg(genericArg: string): string | null { - const m = genericArg.match(/IEventHandler\s*<\s*DomainEvent\s*<\s*(\w+)\s*>/); - return m ? m[1] : null; -} - -/** - * Find the payload interface name from an event class in the source file. - * Looks for: class SomeEvent extends DomainEvent - */ -function extractEventPayloadInterfaceName(sf: SourceFile, eventClassName: string): string | null { - // Try AST first - const cls = sf.getClasses().find(c => c.getName() === eventClassName); - if (cls) { - const extendsClause = cls.getExtends(); - if (extendsClause) { - const m = extendsClause.getText().match(/DomainEvent\s*<\s*(\w+)\s*>/); - if (m) return m[1]; - } - } - // Raw text fallback: class SomeEvent extends DomainEvent - const src = sf.getFullText(); - const regex = new RegExp( - `class\\s+${eventClassName}\\s+extends\\s+DomainEvent\\s*<\\s*(\\w+)\\s*>` - ); - const m = src.match(regex); - return m ? m[1] : null; -} - -function extractSymbol(sf: SourceFile, name: string): ExtractedSymbol | null { - const allExported = sf.getExportedDeclarations(); - - for (const [exportName, decls] of Array.from(allExported.entries())) { - if (exportName !== name) continue; - if (decls.length === 0) continue; - - // When a name has both a VariableDeclaration and a ModuleDeclaration (namespace), - // prefer the variable and merge namespace types in below. - const varDecl = decls.find(d => Node.isVariableDeclaration(d)); - const nsDecl = decls.find(d => Node.isModuleDeclaration(d)); - const node = varDecl ?? decls[0]; - const jsDoc = extractJsDoc(node); - - // ----------------------------------------------------------------------- - // Interface - // ----------------------------------------------------------------------- - if (Node.isInterfaceDeclaration(node)) { - return { - name, - kind: "interface", - isTypeOnly: true, - declarationText: cleanDeclarationText(node.getText()), - jsDoc, - namespaceMembers: [], - sourceFile: sf.getFilePath() - }; - } - - // ----------------------------------------------------------------------- - // Class - // ----------------------------------------------------------------------- - if (Node.isClassDeclaration(node)) { - const members = node - .getMembers() - .map(m => { - const txt = m.getText().trim(); - return txt.replace(/\{[\s\S]*$/, "").trim() + (txt.includes("{") ? ";" : ""); - }) - .filter(Boolean); - - const classHead = node.getText().split("{")[0].trim(); - const body = members.length ? "\n " + members.join("\n ") + "\n" : ""; - return { - name, - kind: "class", - isTypeOnly: false, - declarationText: `${classHead} {${body}}`, - jsDoc, - namespaceMembers: [], - sourceFile: sf.getFilePath() - }; - } - - // ----------------------------------------------------------------------- - // Namespace — skip here, handled separately in enrichment pass - // ----------------------------------------------------------------------- - if (Node.isModuleDeclaration(node)) { - const members: string[] = []; - const body = node.getBody(); - if (body && Node.isModuleBlock(body)) { - for (const stmt of body.getStatements()) { - members.push(stmt.getText().trim()); - } - } - return { - name, - kind: "namespace", - isTypeOnly: true, - declarationText: node.getText().split("{")[0].trim(), - jsDoc, - namespaceMembers: members, - sourceFile: sf.getFilePath() - }; - } - - // ----------------------------------------------------------------------- - // Function - // ----------------------------------------------------------------------- - if ( - Node.isFunctionDeclaration(node) || - Node.isArrowFunction(node) || - Node.isFunctionExpression(node) - ) { - const txt = node.getText().trim(); - return { - name, - kind: "function", - isTypeOnly: false, - declarationText: txt.replace(/\{[\s\S]*$/, "").trim(), - jsDoc, - namespaceMembers: [], - sourceFile: sf.getFilePath() - }; - } - - // ----------------------------------------------------------------------- - // Variable — detect createAbstraction() and enrich - // ----------------------------------------------------------------------- - if (Node.isVariableDeclaration(node)) { - const genericArg = getCreateAbstractionGeneric(node); - - if (genericArg) { - // It's an abstraction token — resolve the wrapped interface - const abstractionKind = classifyAbstraction(name, genericArg); - const interfaceMembers: InterfaceMember[] = []; - const eventPayloadFields: EventPayloadField[] = []; - let eventTypeName: string | undefined; - let eventPayloadName: string | undefined; - let interfaceJsDoc: string | undefined; - - if (abstractionKind === "eventHandler") { - // IEventHandler or IEventHandler> - eventTypeName = extractEventTypeName(genericArg) ?? undefined; - if (eventTypeName) { - // If eventTypeName is a simple class name (e.g. EntryBeforeCreateEvent), - // find the payload via its extends clause. Otherwise (DomainEvent), - // extract payload name directly from the generic arg. - const isDomainEventWrapper = eventTypeName.startsWith("DomainEvent"); - if (isDomainEventWrapper) { - eventPayloadName = extractPayloadNameFromGenericArg(genericArg) ?? undefined; - } else { - eventPayloadName = extractEventPayloadInterfaceName(sf, eventTypeName) ?? undefined; - } - if (eventPayloadName) { - const fields = extractPayloadFields(sf, eventPayloadName); - eventPayloadFields.push(...fields); - } - } - // The handle() method signature — use the specific event type - interfaceMembers.push({ - signature: `handle(event: ${eventTypeName ?? "DomainEvent"}): Promise`, - jsDoc: "" - }); - } else { - // useCase or service — resolve the IFoo interface. - // Start from the file where createAbstraction is actually defined - // (which may be a deep source file, not the barrel re-exporting it). - const nodeSf = node.getSourceFile(); - const resolved = extractInterfaceMembers(nodeSf, genericArg, PKG_MAP); - interfaceMembers.push(...resolved.members); - if (resolved.jsDoc) interfaceJsDoc = resolved.jsDoc; - } - - // Extract namespace types — first try the co-located nsDecl, then search by name - let namespaceTypes = nsDecl - ? (() => { - const body = (nsDecl as any).getBody?.(); - if (!body || !Node.isModuleBlock(body)) return []; - const members: NamespaceMember[] = []; - for (const stmt of body.getStatements()) { - if (Node.isTypeAliasDeclaration(stmt)) { - const typeNode = stmt.getTypeNode(); - members.push({ - name: stmt.getName(), - value: typeNode?.getText() ?? stmt.getText() - }); - } - } - return members; - })() - : extractNamespaceTypes(sf, name); - - // For each namespace type, try to resolve its fields or members - const nodeSfForTypes = node.getSourceFile(); - namespaceTypes = namespaceTypes.map(t => { - // Skip Interface — it just aliases the abstraction itself - if (t.name === "Interface") return t; - const val = t.value.trim(); - - // Foo.Interface pattern → resolve as method interface - if (/^\w+\.Interface$/.test(val)) { - try { - const resolved = resolveNamespaceDotInterface(nodeSfForTypes, val, PKG_MAP); - if (resolved && resolved.members.length > 0) - return { ...t, resolvedMembers: resolved }; - } catch { - /* ignore */ - } - return t; - } - - // Simple identifier → try to resolve as plain object fields - if (/^\w+$/.test(val)) { - try { - const resolved = resolveTypeToFields(nodeSfForTypes, val, PKG_MAP); - if (resolved && resolved.fields.length > 0) return { ...t, resolvedFields: resolved }; - } catch { - /* ignore */ - } - } - - return t; - }); - - return { - name, - kind: "abstraction", - isTypeOnly: false, - declarationText: "", - jsDoc, - namespaceMembers: [], - sourceFile: sf.getFilePath(), - abstractionKind, - interfaceMembers, - interfaceJsDoc, - namespaceTypes, - eventPayloadFields, - eventTypeName, - eventPayloadName - }; - } - - // Regular variable - const parent = node.getParent(); - const gp = parent?.getParent(); - const txt = gp ? gp.getText().trim() : node.getText().trim(); - return { - name, - kind: "variable", - isTypeOnly: false, - declarationText: txt.slice(0, 400), - jsDoc, - namespaceMembers: [], - sourceFile: sf.getFilePath() - }; - } - - // ----------------------------------------------------------------------- - // Type alias - // ----------------------------------------------------------------------- - if (Node.isTypeAliasDeclaration(node)) { - return { - name, - kind: "type", - isTypeOnly: true, - declarationText: cleanDeclarationText(node.getText()), - jsDoc, - namespaceMembers: [], - sourceFile: sf.getFilePath() - }; - } - - // ----------------------------------------------------------------------- - // Enum - // ----------------------------------------------------------------------- - if (Node.isEnumDeclaration(node)) { - return { - name, - kind: "enum", - isTypeOnly: false, - declarationText: node.getText().trim(), - jsDoc, - namespaceMembers: [], - sourceFile: sf.getFilePath() - }; - } - - // Fallback - return { - name, - kind: "other", - isTypeOnly: false, - declarationText: node.getText().slice(0, 300).trim(), - jsDoc, - namespaceMembers: [], - sourceFile: sf.getFilePath() - }; - } - - return null; -} - -/** - * After all symbols for an entry point are collected, pair each abstraction - * with its corresponding namespace symbol (same name) to merge namespace types. - * Namespaces are exported separately from their abstraction constant — - * e.g. both `Logger` (variable) and `Logger` (namespace) are exported. - * ts-morph returns each separately; we collapse them here. - */ -function mergeNamespaceSymbols(symbols: ExtractedSymbol[]): ExtractedSymbol[] { - const merged: ExtractedSymbol[] = []; - const nsMap = new Map(); - - // First pass: collect namespaces - for (const sym of symbols) { - if (sym.kind === "namespace") { - nsMap.set(sym.name, sym); - } - } - - for (const sym of symbols) { - if (sym.kind === "namespace") continue; // will be merged into abstraction - - if (sym.kind === "abstraction") { - const ns = nsMap.get(sym.name); - if ( - ns && - ns.namespaceMembers.length > 0 && - (!sym.namespaceTypes || sym.namespaceTypes.length === 0) - ) { - // Parse namespace members into NamespaceMember[] - const parsed: NamespaceMember[] = []; - for (const m of ns.namespaceMembers) { - const typeMatch = m.match(/export\s+type\s+(\w+)\s*(?:<[^>]*>)?\s*=\s*([\s\S]+?);/); - if (typeMatch) { - parsed.push({ name: typeMatch[1], value: typeMatch[2].trim() }); - } - } - merged.push({ ...sym, namespaceTypes: parsed.length ? parsed : sym.namespaceTypes }); - } else { - merged.push(sym); - } - } else { - merged.push(sym); - } - } - - return merged; -} - -// --------------------------------------------------------------------------- -// MDX rendering -// --------------------------------------------------------------------------- - -interface SymbolGroup { - title: string; - symbols: ExtractedSymbol[]; -} - -/** - * Group symbols into logical sections depending on the entry point layer (api vs admin). - * Returns groups in display order, skipping empty groups. - */ -function groupSymbols(relPath: string, symbols: ExtractedSymbol[]): SymbolGroup[] { - const layer = relPath.split("/")[0]; // "api" | "admin" | "infra" | "cli" | "extensions" - - if (layer === "api") { - const useCases = symbols.filter( - s => s.kind === "abstraction" && s.abstractionKind === "useCase" - ); - const handlers = symbols.filter( - s => s.kind === "abstraction" && s.abstractionKind === "eventHandler" - ); - const services = symbols.filter( - s => s.kind === "abstraction" && s.abstractionKind === "service" - ); - const rest = symbols.filter(s => s.kind !== "abstraction"); - - return [ - { title: "Use Cases", symbols: useCases }, - { title: "Event Handlers", symbols: handlers }, - { title: "Services", symbols: services }, - { title: "Types & Classes", symbols: rest } - ].filter(g => g.symbols.length > 0); - } - - if (layer === "admin") { - const hooks = symbols.filter( - s => - (s.kind === "function" || s.kind === "variable") && - s.name.startsWith("use") && - s.name.length > 3 && - s.name[3] === s.name[3].toUpperCase() - ); - const hookNames = new Set(hooks.map(s => s.name)); - const components = symbols.filter( - s => - !hookNames.has(s.name) && - (s.kind === "variable" || s.kind === "function" || s.kind === "class") && - s.name[0] === s.name[0].toUpperCase() && - s.name[0] !== s.name[0].toLowerCase() - ); - const componentNames = new Set(components.map(s => s.name)); - const types = symbols.filter( - s => - !hookNames.has(s.name) && - !componentNames.has(s.name) && - (s.kind === "type" || s.kind === "interface") - ); - const typeNames = new Set(types.map(s => s.name)); - const rest = symbols.filter( - s => !hookNames.has(s.name) && !componentNames.has(s.name) && !typeNames.has(s.name) - ); - - return [ - { title: "Components", symbols: components }, - { title: "Hooks", symbols: hooks }, - { title: "Types", symbols: types }, - { title: "Other", symbols: rest } - ].filter(g => g.symbols.length > 0); - } - - // For infra, cli, extensions — no grouping, single flat group - return [{ title: "", symbols }]; -} - -function renderLearnBlock(relPath: string, symbols: ExtractedSymbol[]): string { - const useCases = symbols.filter(s => s.name.endsWith("UseCase")); - const handlers = symbols.filter(s => s.name.endsWith("EventHandler")); - const builders = symbols.filter(s => s.name.endsWith("Builder") || s.name.endsWith("Factory")); - const components = symbols.filter( - s => - s.kind === "class" || - (s.name[0] === s.name[0].toUpperCase() && - !s.name.endsWith("UseCase") && - !s.name.endsWith("EventHandler")) - ); - - const bullets: string[] = []; - - if (useCases.length > 0) bullets.push(`- What use cases are available in \`webiny/${relPath}\`?`); - if (handlers.length > 0) bullets.push(`- Which event handlers can you implement?`); - if (builders.length > 0) bullets.push(`- How to use the builder and factory APIs?`); - if (bullets.length === 0) bullets.push(`- What is exported from \`webiny/${relPath}\`?`); - bullets.push(`- How to import and use each exported item?`); - - return bullets.join("\n"); -} - -function kindLabel(sym: ExtractedSymbol): string { - if (sym.kind === "abstraction") { - if (sym.abstractionKind === "eventHandler") return "Event Handler Abstraction"; - if (sym.abstractionKind === "useCase") return "Use Case Abstraction"; - return "Abstraction"; - } - if (sym.isTypeOnly && sym.kind !== "namespace") return "Type"; - const map: Record = { - interface: "Interface", - class: "Class", - namespace: "Namespace", - function: "Function", - variable: "Constant", - type: "Type", - enum: "Enum", - other: "Export" - }; - return map[sym.kind] ?? "Export"; -} - -function renderUsageSnippet( - sym: ExtractedSymbol, - importPath: string -): { file: string; body: string } | null { - if (sym.kind !== "abstraction") return null; - - const lines: string[] = []; - - if (sym.abstractionKind === "eventHandler") { - lines.push(`import { ${sym.name} } from "${importPath}";`); - lines.push(``); - lines.push(`class MyHandler implements ${sym.name}.Interface {`); - lines.push(` public constructor(/* inject dependencies here */) {}`); - lines.push(``); - lines.push(` public async handle(event: ${sym.name}.Event): Promise {`); - if (sym.eventPayloadFields && sym.eventPayloadFields.length > 0) { - const fields = sym.eventPayloadFields.map(f => f.name).join(", "); - lines.push(` const { ${fields} } = event.payload;`); - } else { - lines.push(` // implementation`); - } - lines.push(` }`); - lines.push(`}`); - lines.push(``); - lines.push(`export default ${sym.name}.createImplementation({`); - lines.push(` implementation: MyHandler,`); - lines.push(` dependencies: []`); - lines.push(`});`); - } else { - // use case or service abstraction — show it being injected and called - const paramName = sym.name.charAt(0).toLowerCase() + sym.name.slice(1); - - // Pick a representative method to call: prefer common primary names, fall back to first - const PREFERRED = [ - "execute", - "handle", - "get", - "list", - "create", - "info", - "log", - "map", - "resolve", - "build" - ]; - const pick = - sym.interfaceMembers && sym.interfaceMembers.length > 0 - ? (PREFERRED.map(p => - sym.interfaceMembers!.find( - m => m.signature.startsWith(p + "(") || m.signature.startsWith(p + "<") - ) - ).find(Boolean) ?? sym.interfaceMembers[0]) - : null; - // Strip generic type params from call site (e.g. "map" -> "map") - const methodName = pick ? pick.signature.split("(")[0].split("<")[0].trim() : null; - const isAsync = pick ? pick.signature.includes("Promise<") : false; - - lines.push(`import { ${sym.name} } from "${importPath}";`); - lines.push(``); - lines.push(`class MyImpl implements MyUseCase.Interface {`); - lines.push(` public constructor(private ${paramName}: ${sym.name}.Interface) {}`); - lines.push(``); - lines.push(` public async execute(/* ... */): Promise {`); - if (methodName) { - lines.push(` ${isAsync ? "await " : ""}this.${paramName}.${methodName}(/* ... */);`); - } - lines.push(` }`); - lines.push(`}`); - lines.push(``); - lines.push(`export default MyUseCase.createImplementation({`); - lines.push(` implementation: MyImpl,`); - lines.push(` dependencies: [${sym.name}]`); - lines.push(`});`); - } - - // file is declared in each branch above - const file = - sym.abstractionKind === "eventHandler" ? "extensions/MyHandler.ts" : "extensions/MyImpl.ts"; - return { file, body: lines.join("\n") }; -} - -function renderSymbolSection( - sym: ExtractedSymbol, - importPath: string, - headingLevel: 2 | 3 | 4 = 2 -): string { - const label = kindLabel(sym); - const lines: string[] = []; - const hashes = "#".repeat(headingLevel); - - lines.push(`${hashes} \`${sym.name}\``); - lines.push(""); - lines.push(`**${label}** — imported from \`${importPath}\``); - lines.push(""); - - if (sym.jsDoc) { - lines.push(sym.jsDoc); - lines.push(""); - } - - // Import snippet - const importKeyword = sym.isTypeOnly && sym.kind !== "namespace" ? "import type" : "import"; - lines.push("```typescript"); - lines.push(`${importKeyword} { ${sym.name} } from "${importPath}";`); - lines.push("```"); - lines.push(""); - - // ------------------------------------------------------------------------- - // Abstraction: rich rendering - // ------------------------------------------------------------------------- - if (sym.kind === "abstraction") { - // Interface section — description, code block for signatures, table for descriptions - if (sym.interfaceMembers && sym.interfaceMembers.length > 0) { - lines.push(`**Interface \`${sym.name}.Interface\`:**`); - lines.push(""); - if (sym.interfaceJsDoc) { - lines.push(sym.interfaceJsDoc); - lines.push(""); - } - // Full signatures in a code block - lines.push("```typescript"); - lines.push(`interface ${sym.name}.Interface {`); - for (const m of sym.interfaceMembers) { - lines.push(` ${m.signature};`); - } - lines.push("}"); - lines.push("```"); - lines.push(""); - // Description table — only rendered if any member has JSDoc - const hasAnyJsDoc = sym.interfaceMembers.some(m => m.jsDoc); - if (hasAnyJsDoc) { - lines.push("| Method | Description |"); - lines.push("| ------ | ----------- |"); - for (const m of sym.interfaceMembers) { - const methodName = m.signature.split("(")[0].trim(); - const desc = m.jsDoc ? m.jsDoc.replace(/\|/g, "\\|") : "—"; - lines.push(`| \`${methodName}()\` | ${desc} |`); - } - lines.push(""); - } - } - - // Event payload section - if ( - sym.abstractionKind === "eventHandler" && - sym.eventPayloadFields && - sym.eventPayloadFields.length > 0 - ) { - lines.push(`**Event payload \`${sym.eventPayloadName ?? "payload"}\`:**`); - lines.push(""); - lines.push("```typescript"); - lines.push(`interface ${sym.eventPayloadName ?? "Payload"} {`); - for (const f of sym.eventPayloadFields) { - lines.push(` ${f.name}${f.optional ? "?" : ""}: ${f.typeText};`); - } - lines.push("}"); - lines.push("```"); - lines.push(""); - } - - // Namespace types section - if (sym.namespaceTypes && sym.namespaceTypes.length > 0) { - lines.push(`**Types:**`); - lines.push(""); - lines.push("```typescript"); - lines.push(`namespace ${sym.name} {`); - for (const t of sym.namespaceTypes) { - lines.push(` type ${t.name} = ${t.value};`); - } - lines.push("}"); - lines.push("```"); - lines.push(""); - - // For each resolved type, emit a field table or method table - for (const t of sym.namespaceTypes) { - if (t.resolvedFields && t.resolvedFields.fields.length > 0) { - const { typeName, isArray, jsDoc, fields } = t.resolvedFields; - const label = isArray ? `${typeName}[]` : typeName; - lines.push(`**\`${t.name}\` — \`${label}\`:**`); - lines.push(""); - if (jsDoc) { - lines.push(jsDoc); - lines.push(""); - } - lines.push("| Field | Type | Required | Description |"); - lines.push("| ----- | ---- | -------- | ----------- |"); - for (const f of fields) { - const req = f.optional ? "no" : "yes"; - lines.push(`| \`${f.name}\` | \`${f.typeText.replace(/\|/g, "\\|")}\` | ${req} | — |`); - } - lines.push(""); - } else if (t.resolvedMembers && t.resolvedMembers.members.length > 0) { - const { members, jsDoc } = t.resolvedMembers; - lines.push(`**\`${t.name}\` — \`${t.value}\`:**`); - lines.push(""); - if (jsDoc) { - lines.push(jsDoc); - lines.push(""); - } - lines.push("```typescript"); - lines.push(`interface ${t.value} {`); - for (const m of members) lines.push(` ${m.signature};`); - lines.push("}"); - lines.push("```"); - lines.push(""); - const hasJsDoc = members.some(m => m.jsDoc); - if (hasJsDoc) { - lines.push("| Method | Description |"); - lines.push("| ------ | ----------- |"); - for (const m of members) { - const methodName = m.signature.split("(")[0].trim(); - const desc = m.jsDoc ? m.jsDoc.replace(/\|/g, "\\|") : "—"; - lines.push(`| \`${methodName}()\` | ${desc} |`); - } - lines.push(""); - } - } - } - } - - return lines.join("\n"); - } - - // ------------------------------------------------------------------------- - // Plain declaration - // ------------------------------------------------------------------------- - if (sym.declarationText && sym.declarationText.length > 0) { - lines.push("```typescript"); - lines.push(sym.declarationText); - lines.push("```"); - lines.push(""); - } - - // Namespace members (raw, for non-abstraction namespaces) - if (sym.kind === "namespace" && sym.namespaceMembers.length > 0) { - lines.push("```typescript"); - lines.push(`namespace ${sym.name} {`); - for (const m of sym.namespaceMembers) { - lines.push(` ${m}`); - } - lines.push("}"); - lines.push("```"); - lines.push(""); - } - - return lines.join("\n"); -} - -// --------------------------------------------------------------------------- -// Extensions page — defineExtension-aware extraction + rendering -// --------------------------------------------------------------------------- - -interface ExtParamEntry { - name: string; - type: string; - required: boolean; - description: string; - /** Raw live Zod schema node — used to expand complex types in footnotes */ - schema?: any; -} - -interface ExtensionEntry { - /** Dot-notation namespace path, e.g. "Infra.Admin.BeforeBuild" */ - path: string; - /** Value of the `type` field, e.g. "Admin/BeforeBuild" */ - extensionType: string; - description: string; - multiple: boolean; - params: ExtParamEntry[]; -} - -// Minimal mock context for paramsSchema functions that receive ({ project }) => z.object(...) -const EXT_MOCK_CTX = { - project: { - paths: { - projectFolder: { toString: () => "/project", join: (...a: string[]) => a.join("/") }, - workspaceFolder: { toString: () => "/project", join: (...a: string[]) => a.join("/") } - }, - config: {} - } -}; - -/** Resolve a live Zod schema from a paramsSchema value (direct schema or function) */ -function resolveParamsSchema(paramsSchema: unknown): unknown { - if (!paramsSchema) return null; - if (typeof paramsSchema === "function") { - try { - return (paramsSchema as Function)(EXT_MOCK_CTX); - } catch { - return null; - } - } - return paramsSchema; -} - -/** Map a live Zod type instance to a readable type string */ -function liveZodTypeName(schema: any): string { - const t: string = schema?._def?.typeName ?? ""; - // Unwrap modifiers - if (t === "ZodOptional" || t === "ZodDefault") return liveZodTypeName(schema._def.innerType); - const map: Record = { - ZodString: "string", - ZodBoolean: "boolean", - ZodNumber: "number", - ZodArray: "array", - ZodObject: "object", - ZodUnion: "union", - ZodEnum: "enum", - ZodRecord: "record", - ZodAny: "any", - // zodSrcPath returns a ZodEffects (transform/refine wrapper around ZodString) - ZodEffects: "string" - }; - return map[t] ?? t.replace(/^Zod/, "").toLowerCase(); -} - -/** Unwrap ZodOptional/ZodDefault to get the inner schema */ -function unwrapZod(schema: any): any { - const t = schema?._def?.typeName; - if (t === "ZodOptional" || t === "ZodDefault") return unwrapZod(schema._def.innerType); - return schema; -} - -/** Recursively extract params from a live ZodObject schema, dot-notating nested objects */ -function liveZodObjectParams(schema: any, prefix: string): ExtParamEntry[] { - if (unwrapZod(schema)?._def?.typeName !== "ZodObject") return []; - const obj = unwrapZod(schema); - const results: ExtParamEntry[] = []; - for (const [key, val] of Object.entries(obj.shape as Record)) { - const name = prefix ? `${prefix}.${key}` : key; - const type = liveZodTypeName(val); - const optional = val.isOptional?.() ?? false; - const innerDef = unwrapZod(val)?._def; - const description = innerDef?.description ?? ""; - results.push({ name, type, required: !optional, description, schema: val }); - // Recurse into nested ZodObject (so nested fields also appear in the table) - if (type === "object") { - results.push(...liveZodObjectParams(unwrapZod(val), name)); - } - } - return results; -} - -/** Walk a live runtime namespace object, calling getDefinition() on each leaf */ -function walkRuntimeNamespace(obj: any, path: string, results: ExtensionEntry[]) { - if (!obj || (typeof obj !== "object" && typeof obj !== "function")) return; - if (typeof obj.getDefinition === "function") { - const def = obj.getDefinition(); - const schema = resolveParamsSchema(def.paramsSchema); - const params = schema ? liveZodObjectParams(schema, "") : []; - results.push({ - path, - extensionType: def.type ?? path, - description: def.description ?? "", - multiple: def.multiple ?? false, - params - }); - return; - } - // Plain object namespace — recurse - for (const [k, v] of Object.entries(obj)) { - if (v && (typeof v === "function" || typeof v === "object")) { - walkRuntimeNamespace(v, path ? `${path}.${k}` : k, results); - } - } -} - -/** - * Extract all defineExtension entries by dynamically importing the compiled dist files. - * Uses real Zod schema instances — no AST text parsing. - */ -async function extractExtensions(): Promise { - const PROJECT_DIST = `${WEBINY_MONOREPO}/project/dist`; - const PROJECT_AWS_DIST = `${WEBINY_MONOREPO}/project-aws/dist`; - - // Import compiled dist barrels — these use fully-resolved relative imports, no alias issues - const [projectAws, project] = await Promise.all([ - import(PROJECT_AWS_DIST + "/index.js"), - import(PROJECT_DIST + "/extensions/index.js") - ]); - - const namespaces: Record = { - Api: projectAws.Api, - Admin: projectAws.Admin, - Cli: projectAws.Cli, - Infra: projectAws.Infra, - Project: projectAws.Project - }; - - const results: ExtensionEntry[] = []; - for (const [name, val] of Object.entries(namespaces)) { - walkRuntimeNamespace(val, name, results); - } - return results; -} - -/** Render the param type as a readable string */ -function renderParamType(p: ExtParamEntry): string { - if (p.type === "unknown") return "string"; // zodSrcPath and similar are always strings - return p.type; -} - -/** - * Returns true if a Zod schema node is "complex" — i.e. needs its own sub-section - * rather than just a type name in the table. - */ -function isComplexZodType(schema: any): boolean { - const t: string = unwrapZod(schema)?._def?.typeName ?? ""; - if (t === "ZodObject") return Object.keys(unwrapZod(schema).shape as object).length > 0; - if (t === "ZodUnion") { - return unwrapZod(schema)._def.options.some((o: any) => isComplexZodType(o)); - } - if (t === "ZodArray") return isComplexZodType(unwrapZod(schema)._def.type); - if (t === "ZodTuple") return true; - return false; -} - -/** - * Render a short display type for the table cell — primitive types as-is, - * complex types as a link to their sub-section anchor. - */ -function renderParamTypeCell(p: ExtParamEntry, sectionAnchor: string): string { - if (!p.schema || !isComplexZodType(p.schema)) { - return `\`${renderParamType(p)}\``; - } - // Escape pipes in type labels so they don't break markdown table rendering - const label = renderParamType(p).replace(/\|/g, "\\|"); - return `[${label}](#${sectionAnchor})`; -} - -interface TypeSubSection { - /** Anchor id for the sub-section heading */ - anchor: string; - /** Display heading text */ - heading: string; - /** The live Zod schema to render */ - schema: any; - /** Sub-sections collected recursively from this one */ - children: TypeSubSection[]; -} - -/** - * Collect all TypeSubSections needed for a list of top-level params. - * Walks recursively — objects inside unions get their own sub-sections too. - */ -function collectSubSections(params: ExtParamEntry[], anchorPrefix: string): TypeSubSection[] { - const sections: TypeSubSection[] = []; - - for (const p of params) { - if (!p.schema || !isComplexZodType(p.schema)) continue; - const inner = unwrapZod(p.schema); - const t: string = inner?._def?.typeName ?? ""; - const anchor = slugify(`${anchorPrefix}-${p.name}`); - - if (t === "ZodObject") { - const childParams: ExtParamEntry[] = Object.entries(inner.shape as Record).map( - ([k, v]: [string, any]) => ({ - name: k, - type: liveZodTypeName(v), - required: !(v.isOptional?.() ?? false), - description: unwrapZod(v)?._def?.description ?? "", - schema: v - }) - ); - const children = collectSubSections(childParams, anchor); - sections.push({ anchor, heading: p.name, schema: inner, children }); - } else if (t === "ZodUnion") { - // Each complex union member gets its own sub-section - const children: TypeSubSection[] = []; - inner._def.options.forEach((opt: any, i: number) => { - const optInner = unwrapZod(opt); - const ot: string = optInner?._def?.typeName ?? ""; - if (ot === "ZodObject") { - const optAnchor = slugify(`${anchor}-option-${i + 1}`); - const childParams: ExtParamEntry[] = Object.entries( - optInner.shape as Record - ).map(([k, v]: [string, any]) => ({ - name: k, - type: liveZodTypeName(v), - required: !(v.isOptional?.() ?? false), - description: unwrapZod(v)?._def?.description ?? "", - schema: v - })); - const grandchildren = collectSubSections(childParams, optAnchor); - children.push({ - anchor: optAnchor, - heading: `${p.name} (option ${i + 1})`, - schema: optInner, - children: grandchildren - }); - } - }); - sections.push({ anchor, heading: p.name, schema: inner, children }); - } else if (t === "ZodArray") { - const el = unwrapZod(inner._def.type); - if (el?._def?.typeName === "ZodObject") { - const childParams: ExtParamEntry[] = Object.entries(el.shape as Record).map( - ([k, v]: [string, any]) => ({ - name: k, - type: liveZodTypeName(v), - required: !(v.isOptional?.() ?? false), - description: unwrapZod(v)?._def?.description ?? "", - schema: v - }) - ); - const children = collectSubSections(childParams, anchor); - sections.push({ anchor, heading: p.name, schema: el, children }); - } - } else if (t === "ZodTuple") { - sections.push({ anchor, heading: p.name, schema: inner, children: [] }); - } - } - - return sections; -} - -/** Render a short inline type label (for table cells and union member lists) */ -function renderZodTypeShort(schema: any): string { - const inner = unwrapZod(schema); - const t: string = inner?._def?.typeName ?? "unknown"; - if (t === "ZodString") return "string"; - if (t === "ZodBoolean") return "boolean"; - if (t === "ZodNumber") return "number"; - if (t === "ZodAny") return "any"; - if (t === "ZodEffects") return "string"; - if (t === "ZodEnum") return inner._def.values.map((v: string) => `"${v}"`).join(" | "); - if (t === "ZodArray") return `${renderZodTypeShort(inner._def.type)}[]`; - if (t === "ZodRecord") return `Record`; - if (t === "ZodUnion") - return inner._def.options.map((o: any) => renderZodTypeShort(o)).join(" | "); - if (t === "ZodTuple") - return `[${inner._def.items.map((i: any) => renderZodTypeShort(i)).join(", ")}]`; - if (t === "ZodObject") return "object"; - return t.replace(/^Zod/, "").toLowerCase(); -} - -/** Render a TypeSubSection and all its children recursively into lines */ -function renderSubSection(sec: TypeSubSection, headingLevel: number): string[] { - const lines: string[] = []; - const hashes = "#".repeat(headingLevel); - - lines.push(``); - lines.push(""); - lines.push(`${hashes} \`${sec.heading}\``); - lines.push(""); - - const inner = unwrapZod(sec.schema); - const t: string = inner?._def?.typeName ?? ""; - - if (t === "ZodObject") { - lines.push("| Field | Type | Required | Description |"); - lines.push("| ----- | ---- | -------- | ----------- |"); - for (const [key, val] of Object.entries(inner.shape as Record)) { - const req = (val.isOptional?.() ?? false) ? "no" : "yes"; - const desc = unwrapZod(val)?._def?.description ?? "—"; - // Find a child sub-section for this field if it's complex - const child = sec.children.find(c => c.heading === key); - const typeCell = child - ? `[${renderZodTypeShort(val).replace(/\|/g, "\\|")}](#${child.anchor})` - : `\`${renderZodTypeShort(val)}\``; - lines.push(`| \`${key}\` | ${typeCell} | ${req} | ${desc || "—"} |`); - } - lines.push(""); - } else if (t === "ZodUnion") { - // List each member with a link if it has a sub-section - const options: any[] = inner._def.options; - lines.push("Accepts one of:"); - lines.push(""); - options.forEach((opt: any, i: number) => { - const child = sec.children.find(c => c.heading === `${sec.heading} (option ${i + 1})`); - const label = child ? `[object](#${child.anchor})` : `\`${renderZodTypeShort(opt)}\``; - lines.push(`- ${label}`); - }); - lines.push(""); - } else if (t === "ZodTuple") { - const items: string[] = inner._def.items.map((i: any) => `\`${renderZodTypeShort(i)}\``); - lines.push(`A tuple: \`[${items.join(", ")}]\``); - lines.push(""); - } - - // Render children recursively - for (const child of sec.children) { - lines.push(...renderSubSection(child, headingLevel)); - } - - return lines; -} - -/** Render the extensions.mdx page from extracted defineExtension data */ -function renderExtensionsMdx(extensions: ExtensionEntry[], id: string): string { - const lines: string[] = []; - - lines.push("---"); - lines.push(`id: ${id}`); - lines.push("title: Extensions"); - lines.push( - `description: "Reference for all webiny/extensions exports — React components used in webiny.config.tsx to wire extensions into the project."` - ); - lines.push("---"); - lines.push(""); - lines.push(`import {Alert} from "@/components/Alert";`); - lines.push(`import {SymbolList} from "@/components/SymbolList";`); - lines.push(""); - lines.push(``); - lines.push(""); - lines.push("- What extension components are available in `webiny/extensions`?"); - lines.push("- What parameters does each extension accept?"); - lines.push("- How to use each extension in your `webiny.config.tsx`?"); - lines.push(""); - lines.push(""); - lines.push(""); - lines.push("## Overview"); - lines.push(""); - lines.push( - "The `webiny/extensions` package exports React components used inside `webiny.config.tsx` " + - "to wire extensions into your Webiny project. Each component corresponds to a `defineExtension()` " + - "call in the Webiny source and accepts typed props defined by its Zod schema." - ); - lines.push(""); - - // Group by top-level namespace (first segment of path) - const groups = new Map(); - for (const ext of extensions) { - const top = ext.path.split(".")[0]; - if (!groups.has(top)) groups.set(top, []); - groups.get(top)!.push(ext); - } - - // Chip lists grouped by namespace - for (const [groupName, exts] of Array.from(groups.entries())) { - if (groups.size > 1) { - lines.push(`**${groupName}**`); - lines.push(""); - } - const chips = exts.map(e => `{ name: "${e.path}", anchor: "${slugify(e.path)}" }`).join(", "); - lines.push(``); - lines.push(""); - } - - // Detail sections per namespace group - for (const [groupName, exts] of Array.from(groups.entries())) { - if (groups.size > 1) { - lines.push(`## ${groupName}`); - lines.push(""); - } - for (const ext of exts) { - // Heading: last two segments of path for nested (e.g. "Infra.Admin.BeforeBuild" → "### `Admin.BeforeBuild`") - // Top-level (e.g. "EnvVar") → "### `EnvVar`" - const parts = ext.path.split("."); - const headingName = parts.length > 2 ? parts.slice(1).join(".") : parts[parts.length - 1]; - lines.push(`### \`${headingName}\``); - lines.push(""); - if (ext.description) { - lines.push(ext.description); - lines.push(""); - } - // Badges - const badge = ext.multiple ? "Can be used **multiple times**." : "Can only be used **once**."; - lines.push(badge); - lines.push(""); - // Params table + sub-sections - const topLevelParams = ext.params.filter(p => !p.name.includes(".")); - const anchorPrefix = slugify(ext.path); - const subSections = collectSubSections(topLevelParams, anchorPrefix); - - // Usage example (before props table) - const usageParts = topLevelParams - .filter(p => p.required) - .map(p => { - if (p.type === "unknown" || p.name === "src") - return `${p.name}="/extensions/my-extension.ts"`; - if (p.type === "string") return `${p.name}="value"`; - if (p.type === "boolean") return `${p.name}={true}`; - if (p.type === "array") return `${p.name}={[]}`; - if (p.type === "object") return `${p.name}={{}}`; - return `${p.name}={...}`; - }); - const selfClosing = usageParts.length <= 2; - lines.push("```tsx webiny.config.tsx"); - lines.push(`import { ${ext.path.split(".")[0]} } from "webiny/extensions";`); - lines.push(""); - lines.push("export const Extensions = () => ("); - if (selfClosing) { - lines.push(` <${ext.path}${usageParts.length ? " " + usageParts.join(" ") : ""} />`); - } else { - lines.push(` <${ext.path}`); - for (const p of usageParts) lines.push(` ${p}`); - lines.push(` />`); - } - lines.push(");"); - lines.push("```"); - lines.push(""); - - // Props table - if (topLevelParams.length > 0) { - lines.push("**Props**"); - lines.push(""); - lines.push("| Prop | Type | Required | Description |"); - lines.push("| ---- | ---- | -------- | ----------- |"); - for (const p of topLevelParams) { - const req = p.required ? "yes" : "no"; - const desc = p.description || "—"; - const sec = subSections.find(s => s.heading === p.name); - const typeCell = sec - ? `[${renderParamType(p)}](#${sec.anchor})` - : `\`${renderParamType(p)}\``; - lines.push(`| \`${p.name}\` | ${typeCell} | ${req} | ${desc} |`); - } - lines.push(""); - } - - // Type detail sub-sections - if (subSections.length > 0) { - for (const sec of subSections) { - lines.push(...renderSubSection(sec, 4)); - } - } - } - } - - return lines.join("\n"); -} - -function renderMdx(doc: EntryPointDoc, id: string): string { - const lines: string[] = []; - - lines.push("---"); - lines.push(`id: ${id}`); - lines.push(`title: ${doc.title}`); - lines.push(`description: "${doc.description}"`); - lines.push("---"); - lines.push(""); - lines.push(`import {Alert} from "@/components/Alert";`); - lines.push(`import {SymbolList} from "@/components/SymbolList";`); - lines.push(""); - lines.push(``); - lines.push(""); - lines.push(renderLearnBlock(doc.relPath, doc.symbols)); - lines.push(""); - lines.push(""); - lines.push(""); - lines.push("## Overview"); - lines.push(""); - lines.push( - `This page documents everything exported from \`webiny/${doc.relPath}\`. Import any of the items below directly from this path in your Webiny extensions.` - ); - lines.push(""); - - if (doc.symbols.length === 0) { - lines.push("*No exported symbols found.*"); - lines.push(""); - } else { - const groups = groupSymbols(doc.relPath, doc.symbols); - const hasMultipleGroups = groups.length > 1; - - // Pre-sort symbols A-Z within each group - const sortedGroups = groups.map(g => ({ - ...g, - symbols: [...g.symbols].sort((a, b) => a.name.localeCompare(b.name)) - })); - - // --- All chip lists first, bold labels (visible on page, no sidebar sub-items) --- - for (const group of sortedGroups) { - if (hasMultipleGroups && group.title) { - lines.push(`**${group.title}**`); - lines.push(""); - } - const symbolsJson = group.symbols - .map(sym => { - const anchor = slugify(sym.name); - return `{ name: "${sym.name}", anchor: "${anchor}" }`; - }) - .join(", "); - lines.push(``); - lines.push(""); - } - - // --- Symbol detail sections below --- - // Group headings are H2 (peers of ## Overview), symbol headings are H3 (multi-group) or H2 (single-group). - const headingLevel = hasMultipleGroups ? 3 : 2; - for (const group of sortedGroups) { - if (hasMultipleGroups && group.title) { - lines.push(`## ${group.title}`); - lines.push(""); - } - for (const sym of group.symbols) { - lines.push(renderSymbolSection(sym, `webiny/${doc.relPath}`, headingLevel)); - } - } - } - - return lines.join("\n"); -} - -// --------------------------------------------------------------------------- -// .ai.txt rendering -// --------------------------------------------------------------------------- - -function renderAiTxt(doc: EntryPointDoc): string { - const symbolNames = doc.symbols.map(s => s.name).join(", "); - const sourceFiles = Array.from(new Set(doc.symbols.map(s => s.sourceFile))); - - return `AI Context: ${doc.title} (reference/${doc.relPath}.mdx) - -Source of Information: -1. packages/webiny/src/${doc.relPath}.ts — barrel re-export file -${sourceFiles.map((f, i) => `${i + 2}. ${f} — originating source`).join("\n")} - -Key Documentation Decisions: -- This file is auto-generated by scripts/generate-reference.ts — do not edit manually -- Symbols are documented in the order they appear in the barrel file -- Declaration text is extracted from the TypeScript AST; method bodies are stripped -- Type-only exports are labeled as "Type"; namespace exports include member listings - -Exported Symbols: -${symbolNames} - -Import Path: webiny/${doc.relPath} - -Related Documents: -- docs/developer-docs/6.x/basic/di.mdx — DI pattern used by all abstractions -- docs/developer-docs/6.x/basic/result.mdx — Result type used in use case returns - -Tone Guidelines: -- This is a reference page — terse, API-focused, no prose beyond what's necessary -- Code blocks are the primary content; descriptions serve only to clarify intent -- Do not add analogies or long explanations — link to guide pages for those -`; -} - -// --------------------------------------------------------------------------- -// Navigation generation -// --------------------------------------------------------------------------- - -interface NavPage { - link: string; - title?: string; -} - -interface NavGroup { - title: string; - pages: Array; -} - -function isNavGroup(x: NavPage | NavGroup): x is NavGroup { - return "pages" in x; -} - -// Sub-domains that get their own sub-group within a layer -// key: "layer/subdomain", value: preferred landing link -const SUBDOMAIN_LANDING: Record = { - "api/cms": "reference/api/cms/entry", - "api/website-builder": "reference/api/website-builder/page", - "api/security": "reference/api/security", - "admin/cms": "reference/admin/cms", - "admin/website-builder": "reference/admin/website-builder" -}; - -// Preferred landing page for each top-level layer group -const LAYER_LANDING: Record = { - api: "reference/api/cms/entry", - admin: "reference/admin", - infra: "reference/infra/overview", - cli: "reference/cli/overview" -}; - -/** - * Some relPaths end in "index" which Next.js treats as a directory index route, - * causing 404s. Map those to a non-index output path here. - * Key: relPath (e.g. "cli/index"), Value: output path WITHOUT extension (e.g. "cli/overview") - */ -const OUTPUT_PATH_OVERRIDE: Record = { - "cli/index": "cli/overview", - "infra/index": "infra/overview" -}; - -/** Return the output path for a given relPath (may be overridden to avoid index routes). */ -function toOutputPath(relPath: string): string { - return OUTPUT_PATH_OVERRIDE[relPath] ?? relPath; -} - -type NavGroupWithLink = NavGroup & { link: string }; - -function makeGroup(title: string, link: string): NavGroupWithLink { - return { title, link, pages: [] } as NavGroupWithLink; -} - -// Explicit layer order for navigation -const LAYER_ORDER = ["extensions", "admin", "api", "cli", "infra"]; - -function buildNavTree(entryPoints: EntryPointDoc[]): NavGroup { - const root: NavGroup = { title: "Reference", pages: [] }; - - // Layer map: "api" | "admin" | "infra" | "cli" | "extensions" - const byLayer = new Map(); - for (const ep of entryPoints) { - const layer = ep.relPath.split("/")[0]; - if (!byLayer.has(layer)) byLayer.set(layer, []); - byLayer.get(layer)!.push(ep); - } - - // Sort layers by explicit order, unknown layers go to the end alphabetically - const orderedLayers = Array.from(byLayer.keys()).sort((a, b) => { - const ai = LAYER_ORDER.indexOf(a); - const bi = LAYER_ORDER.indexOf(b); - if (ai === -1 && bi === -1) return a.localeCompare(b); - if (ai === -1) return 1; - if (bi === -1) return -1; - return ai - bi; - }); - - for (const layer of orderedLayers) { - const eps = byLayer.get(layer)!; - if (eps.length === 1) { - // Single entry (extensions) — flat page - root.pages.push({ link: `reference/${toOutputPath(eps[0].relPath)}` }); - continue; - } - - const layerGroup = makeGroup( - toTitle(layer), - LAYER_LANDING[layer] ?? `reference/${toOutputPath(eps[0].relPath)}` - ); - - // Within this layer, group by sub-domain (second segment) when applicable - // Sub-domains: cms, website-builder, security — anything else is flat - const SUB_DOMAINS = ["cms", "website-builder", "security"]; - const bySubDomain = new Map(); - const flat: EntryPointDoc[] = []; - - // Sub-domain index pages: 2-part paths where the second segment is a sub-domain - // e.g. "api/security" → becomes the "Overview" first child of the Security group - const subDomainIndex = new Map(); - - for (const ep of eps) { - const parts = ep.relPath.split("/"); // e.g. ["api","cms","entry"] - if (parts.length === 2 && SUB_DOMAINS.includes(parts[1])) { - subDomainIndex.set(parts[1], ep); - } else if (parts.length >= 3 && SUB_DOMAINS.includes(parts[1])) { - const subDomain = parts[1]; - if (!bySubDomain.has(subDomain)) bySubDomain.set(subDomain, []); - bySubDomain.get(subDomain)!.push(ep); - } else { - flat.push(ep); - } - } - - // Add flat items (e.g. api, api/logger, api/graphql…) - // Root page (landing) always goes first, rest in their natural order. - const layerLanding = LAYER_LANDING[layer] ?? `reference/${toOutputPath(eps[0].relPath)}`; - const rootFlat = flat.filter( - ep => `reference/${toOutputPath(ep.relPath)}` === layerLanding || ep.relPath === layer - ); - const otherFlat = flat.filter(ep => !rootFlat.includes(ep)); - - for (const ep of [...rootFlat, ...otherFlat]) { - const isLayerRoot = rootFlat.includes(ep); - const title = isLayerRoot ? "Root" : ep.title; - layerGroup.pages.push({ link: `reference/${toOutputPath(ep.relPath)}`, title }); - } - - // Add sub-domain groups — index page is "Overview" first child, then sub-pages - for (const [subDomain, subEps] of Array.from(bySubDomain.entries())) { - const key = `${layer}/${subDomain}`; - const subLanding = SUBDOMAIN_LANDING[key] ?? `reference/${toOutputPath(subEps[0].relPath)}`; - const subGroup = makeGroup(toTitle(subDomain), subLanding); - const indexEp = subDomainIndex.get(subDomain); - if (indexEp) { - subGroup.pages.push({ - link: `reference/${toOutputPath(indexEp.relPath)}`, - title: "Root" - }); - } - for (const ep of subEps) { - subGroup.pages.push({ link: `reference/${toOutputPath(ep.relPath)}`, title: ep.title }); - } - layerGroup.pages.push(subGroup); - } - - root.pages.push(layerGroup); - } - - return root; -} - -function renderNavGroup(group: NavGroup, indent: number): string { - const pad = " ".repeat(indent); - const lines: string[] = []; - - if (indent === 0) { - // root Reference group — already in navigation.tsx, we just emit children - for (const page of group.pages) { - lines.push(renderNavItem(page, indent + 1)); - } - } else { - const groupLink = (group as NavGroup & { link?: string }).link ?? findFirstLink(group); - lines.push(`${pad}`); - for (const page of group.pages) { - lines.push(renderNavItem(page, indent + 1)); - } - lines.push(`${pad}`); - } - - return lines.join("\n"); -} - -function findFirstLink(group: NavGroup): string { - for (const p of group.pages) { - if (!isNavGroup(p)) return p.link; - const nested = findFirstLink(p); - if (nested) return nested; - } - return ""; -} - -function renderNavItem(item: NavPage | NavGroup, indent: number): string { - const pad = " ".repeat(indent); - if (isNavGroup(item)) { - return renderNavGroup(item, indent); - } - if (item.title) { - return `${pad}`; - } - return `${pad}`; -} - -const NAV_MARKER_START = " {/* __REFERENCE_PAGES_START__ */}"; -const NAV_MARKER_END = " {/* __REFERENCE_PAGES_END__ */}"; - -function rewriteNavigation(entryPoints: EntryPointDoc[]): void { - const nav = readFileSync(NAV_FILE, "utf-8"); - const tree = buildNavTree(entryPoints); - - // Build inner content for the Reference group - const innerLines: string[] = []; - for (const page of tree.pages) { - innerLines.push(renderNavItem(page, 2)); - } - const inner = innerLines.join("\n"); - - // Replace between markers - const startIdx = nav.indexOf(NAV_MARKER_START); - const endIdx = nav.indexOf(NAV_MARKER_END); - - if (startIdx === -1 || endIdx === -1) { - console.warn(" [nav] Markers not found in navigation.tsx — skipping nav update"); - console.warn(` [nav] Add these markers inside the Reference :`); - console.warn(` ${NAV_MARKER_START}`); - console.warn(` ${NAV_MARKER_END}`); - return; - } - - const before = nav.slice(0, startIdx + NAV_MARKER_START.length); - const after = nav.slice(endIdx); - const updated = `${before}\n${inner}\n ${after}`; - - writeFileSync(NAV_FILE, updated, "utf-8"); - console.log(` [nav] Updated navigation.tsx Reference group`); -} - -// --------------------------------------------------------------------------- -// Main -// --------------------------------------------------------------------------- - -async function main(): Promise { - console.log("Reading webiny package..."); - - const pkgJson = JSON.parse(readFileSync(join(WEBINY_PKG, "package.json"), "utf-8")); - const exports: Record = pkgJson.exports ?? {}; - const pkgMap = buildPackagePathMap(); - PKG_MAP = pkgMap; - - console.log(` Found ${Object.keys(exports).length} export paths`); - console.log(` Found ${pkgMap.size} @webiny/* package aliases`); - - // Set up ts-morph project pointing at the webiny package tsconfig - const project = new Project({ - tsConfigFilePath: join(WEBINY_PKG, "tsconfig.json"), - skipAddingFilesFromTsConfig: true - }); - - // Entry points to process — derive from exports map - // Filter out non-JS entries (tsconfig.json, global.ts, icons/*) - const entryPaths: string[] = Object.keys(exports) - .filter(k => !k.includes("*") && !k.endsWith(".json") && !k.endsWith(".ts")) - .map(k => k.replace(/^\.\//, "")) // strip leading "./" - .sort(); - - console.log(` Processing ${entryPaths.length} entry points...`); - - const docs: EntryPointDoc[] = []; - - for (const relPath of entryPaths) { - const barrelSrc = join(WEBINY_PKG, "src", relPath + ".ts"); - - if (!existsSync(barrelSrc)) { - console.warn(` [skip] ${relPath} — barrel not found at ${barrelSrc}`); - continue; - } - - process.stdout.write(` [parse] ${relPath}...`); - - // Add barrel file to project - let barrelFile: SourceFile; - try { - barrelFile = project.addSourceFileAtPath(barrelSrc); - } catch { - console.log(" ERROR adding to project"); - continue; - } - - // Parse barrel to get all re-exported names + their source files - const exports_ = parseBarrel(barrelFile, pkgMap); - - // For each exported name, open the source file and extract the symbol - const symbols: ExtractedSymbol[] = []; - const loadedSourceFiles = new Map(); - - for (const entry of exports_) { - if (entry.exportedName === "*") { - // export * — we can't enumerate without resolving, skip for now - continue; - } - - let sourceSf = loadedSourceFiles.get(entry.sourceFile); - if (!sourceSf) { - if (!existsSync(entry.sourceFile)) continue; - try { - sourceSf = project.addSourceFileAtPath(entry.sourceFile); - loadedSourceFiles.set(entry.sourceFile, sourceSf); - } catch { - continue; - } - } - - const sym = extractSymbol(sourceSf, entry.originalName); - if (sym) { - symbols.push({ - ...sym, - name: entry.exportedName, - isTypeOnly: entry.isTypeOnly || sym.isTypeOnly - }); - } else { - // Symbol not found via exported declarations — add a stub - symbols.push({ - name: entry.exportedName, - kind: "other", - isTypeOnly: entry.isTypeOnly, - declarationText: "", - jsDoc: "", - namespaceMembers: [], - sourceFile: entry.sourceFile - }); - } - } - - const doc: EntryPointDoc = { - importPath: `webiny/${relPath}`, - relPath, - title: toTitle(relPath), - description: toDescription(relPath), - symbols: mergeNamespaceSymbols(symbols) - }; - - docs.push(doc); - console.log(` ${symbols.length} symbols`); - } - - // Pre-extract extensions data (used when writing the extensions page) - console.log("\nExtracting defineExtension metadata..."); - const extensionEntries = await extractExtensions(); - console.log(` Found ${extensionEntries.length} extension definitions`); - - // Write MDX + .ai.txt files - console.log("\nWriting documentation files..."); - - for (const doc of docs) { - const outputPath = toOutputPath(doc.relPath); - const dir = join(REF_DIR, dirname(outputPath)); - mkdirSync(dir, { recursive: true }); - - const mdxPath = join(REF_DIR, outputPath + ".mdx"); - const aiTxtPath = join(REF_DIR, outputPath + ".ai.txt"); - - // Generate stable ID from path (8 chars) - const id = Buffer.from(doc.relPath) - .toString("base64") - .replace(/[^a-z0-9]/gi, "") - .slice(0, 8) - .toLowerCase() - .padEnd(8, "0"); - - // Extensions page gets its own dedicated renderer - const mdxContent = - doc.relPath === "extensions" ? renderExtensionsMdx(extensionEntries, id) : renderMdx(doc, id); - const aiTxtContent = renderAiTxt(doc); - - writeFileSync(mdxPath, mdxContent, "utf-8"); - writeFileSync(aiTxtPath, aiTxtContent, "utf-8"); - console.log(` [write] reference/${outputPath}.mdx (${doc.symbols.length} symbols)`); - } - - // Rewrite navigation - console.log("\nUpdating navigation.tsx..."); - rewriteNavigation(docs); - - console.log(`\nDone. Generated ${docs.length} reference pages.`); -} - -main().catch(err => { - console.error("Fatal error:", err); - process.exit(1); -}); diff --git a/scripts/ref/_shared.ts b/scripts/ref/_shared.ts deleted file mode 100644 index 9e8c51a91..000000000 --- a/scripts/ref/_shared.ts +++ /dev/null @@ -1,698 +0,0 @@ -/** - * Shared utilities for the AI-powered reference generator. - * - * - Source collection (ts-morph barrel parsing + symbol extraction) - * - Claude API caller - * - Navigation rewriter - * - Common types - */ - -import { readFileSync, writeFileSync, existsSync } from "fs"; -import { join, dirname } from "path"; -import { Project, SourceFile, SyntaxKind, Node } from "ts-morph"; -import Anthropic from "@anthropic-ai/sdk"; - -// --------------------------------------------------------------------------- -// Config -// --------------------------------------------------------------------------- - -export const WEBINY_PKG = "/Users/adrian/dev/wby-next/packages/webiny"; -export const WEBINY_MONOREPO = "/Users/adrian/dev/wby-next/packages"; -export const DOCS_ROOT = join(process.cwd(), "docs/developer-docs/6.x"); -export const REF_DIR = join(DOCS_ROOT, "reference"); -export const NAV_FILE = join(DOCS_ROOT, "navigation.tsx"); - -// --------------------------------------------------------------------------- -// Types -// --------------------------------------------------------------------------- - -export interface ExportEntry { - exportedName: string; - originalName: string; - sourceFile: string; - isTypeOnly: boolean; -} - -export interface SymbolDecl { - name: string; - kind: string; - isTypeOnly: boolean; - declarationText: string; - jsDoc: string; - sourceFile: string; -} - -export interface EntryPointSource { - /** e.g. "api/logger" */ - relPath: string; - /** e.g. "webiny/api/logger" */ - importPath: string; - /** Resolved symbols with declaration text */ - symbols: SymbolDecl[]; - /** Raw TypeScript source of all originating files (keyed by file path) */ - sourceFiles: Map; - /** Contents of an .examples.md file if found */ - examplesContent?: string; -} - -// --------------------------------------------------------------------------- -// Package path map -// --------------------------------------------------------------------------- - -let _pkgMap: Map | null = null; - -export function getPackagePathMap(): Map { - if (_pkgMap) return _pkgMap; - const entries = readFileSync(join(WEBINY_PKG, "tsconfig.json"), "utf-8"); - const cleaned = entries.replace(/\/\/[^\n]*/g, "").replace(/\/\*[\s\S]*?\*\//g, ""); - const tsconfig = JSON.parse(cleaned); - const paths: Record = tsconfig?.compilerOptions?.paths ?? {}; - const map = new Map(); - for (const [alias, targets] of Object.entries(paths)) { - if (!alias.startsWith("@webiny/")) continue; - const rawTarget = targets[0]; - if (!rawTarget) continue; - const resolved = join(WEBINY_PKG, rawTarget.replace(/\/\*$/, "").replace(/\*$/, "")); - const pkgAlias = alias.replace(/\/\*$/, ""); - map.set(pkgAlias, resolved); - } - _pkgMap = map; - return map; -} - -export function resolveWebinyImport( - importPath: string, - pkgMap: Map -): string | null { - for (const [alias, srcDir] of Array.from(pkgMap.entries())) { - if (importPath.startsWith(alias + "/")) { - const rest = importPath.slice(alias.length + 1).replace(/\.js$/, ".ts"); - return join(srcDir, rest); - } - if (importPath === alias) { - return join(srcDir, "index.ts"); - } - } - return null; -} - -export function resolveModuleSpecifier( - sf: SourceFile, - modSpec: string, - pkgMap: Map -): string | null { - if (modSpec.startsWith(".")) { - return join(sf.getDirectoryPath(), modSpec.replace(/\.js$/, ".ts")); - } - if (modSpec.startsWith("~/")) { - const parts = sf.getFilePath().split("/"); - const srcIdx = parts.lastIndexOf("src"); - if (srcIdx !== -1) { - const srcRoot = parts.slice(0, srcIdx + 1).join("/"); - return join(srcRoot, modSpec.slice(2).replace(/\.js$/, ".ts")); - } - return null; - } - return resolveWebinyImport(modSpec, pkgMap); -} - -// --------------------------------------------------------------------------- -// Barrel parsing -// --------------------------------------------------------------------------- - -export function parseBarrel(sf: SourceFile, pkgMap: Map): ExportEntry[] { - const entries: ExportEntry[] = []; - for (const decl of sf.getExportDeclarations()) { - const moduleSpecifier = decl.getModuleSpecifierValue(); - if (!moduleSpecifier) continue; - const resolvedPath = resolveWebinyImport(moduleSpecifier, pkgMap); - if (!resolvedPath) continue; - const isTypeOnly = decl.isTypeOnly(); - const namedExports = decl.getNamedExports(); - if (namedExports.length === 0) { - entries.push({ exportedName: "*", originalName: "*", sourceFile: resolvedPath, isTypeOnly }); - } else { - for (const ne of namedExports) { - entries.push({ - exportedName: ne.getAliasNode()?.getText() ?? ne.getNameNode().getText(), - originalName: ne.getNameNode().getText(), - sourceFile: resolvedPath, - isTypeOnly: isTypeOnly || ne.isTypeOnly() - }); - } - } - } - return entries; -} - -// --------------------------------------------------------------------------- -// Symbol extraction (signatures only, no bodies) -// --------------------------------------------------------------------------- - -function extractJsDoc(node: Node): string { - const jsDocNodes = node.getChildrenOfKind(SyntaxKind.JSDoc); - if (jsDocNodes.length === 0) return ""; - return jsDocNodes - .map(jd => jd.getInnerText().trim()) - .filter(Boolean) - .join("\n"); -} - -function isInternalNode(node: Node): boolean { - return node.getChildrenOfKind(SyntaxKind.JSDoc).some(jd => jd.getText().includes("@internal")); -} - -function stripBody(node: Node): string { - // For functions / constructors / methods: return everything up to the body block - const txt = node.getText(); - const body = (node as any).getBody ? (node as any).getBody() : null; - if (body) { - const bodyStart = body.getStart(); - const nodeStart = node.getStart(); - return txt.substring(0, bodyStart - nodeStart).trim(); - } - return txt.trim(); -} - -export function extractSymbolDecl(sf: SourceFile, name: string): SymbolDecl | null { - const allExported = sf.getExportedDeclarations(); - for (const [exportName, decls] of Array.from(allExported.entries())) { - if (exportName !== name || decls.length === 0) continue; - - const varDecl = decls.find(d => Node.isVariableDeclaration(d)); - const node = varDecl ?? decls[0]; - const jsDoc = extractJsDoc(node); - - if (Node.isInterfaceDeclaration(node)) { - // Strip @internal members - const members = node - .getMembers() - .filter(m => !isInternalNode(m)) - .map(m => " " + m.getText().trim()) - .join("\n"); - return { - name, - kind: "interface", - isTypeOnly: true, - declarationText: `interface ${node.getName()} {\n${members}\n}`, - jsDoc, - sourceFile: sf.getFilePath() - }; - } - - if (Node.isClassDeclaration(node)) { - const members = node - .getMembers() - .filter(m => !isInternalNode(m)) - .map(m => { - if (Node.isPropertyDeclaration(m)) { - return " " + m.getText().trim().replace(/;?$/, ";"); - } - if (Node.isConstructorDeclaration(m) || Node.isMethodDeclaration(m)) { - return " " + stripBody(m) + ";"; - } - return " " + m.getText().trim(); - }) - .filter(Boolean); - const head = node.getText().split("{")[0].trim(); - const body = members.length ? "\n" + members.join("\n") + "\n" : ""; - return { - name, - kind: "class", - isTypeOnly: false, - declarationText: `${head} {${body}}`, - jsDoc, - sourceFile: sf.getFilePath() - }; - } - - if (Node.isTypeAliasDeclaration(node)) { - return { - name, - kind: "type", - isTypeOnly: true, - declarationText: node.getText().trim(), - jsDoc, - sourceFile: sf.getFilePath() - }; - } - - if (Node.isEnumDeclaration(node)) { - return { - name, - kind: "enum", - isTypeOnly: false, - declarationText: node.getText().trim(), - jsDoc, - sourceFile: sf.getFilePath() - }; - } - - if (Node.isFunctionDeclaration(node)) { - return { - name, - kind: "function", - isTypeOnly: false, - declarationText: stripBody(node), - jsDoc, - sourceFile: sf.getFilePath() - }; - } - - if (Node.isVariableDeclaration(node)) { - // Check if it's a createAbstraction call - const initializer = node.getInitializer(); - const initText = initializer?.getText() ?? ""; - const isAbstraction = initText.includes("createAbstraction<"); - if (isAbstraction) { - // Get the full var statement for context, but just the signature - const parent = node.getParent(); - const gp = parent?.getParent(); - const declText = gp ? gp.getText().trim() : node.getText().trim(); - return { - name, - kind: "abstraction", - isTypeOnly: false, - declarationText: declText.slice(0, 500), - jsDoc, - sourceFile: sf.getFilePath() - }; - } - // Regular variable - const parent = node.getParent(); - const gp = parent?.getParent(); - return { - name, - kind: "variable", - isTypeOnly: false, - declarationText: (gp ? gp.getText() : node.getText()).trim().slice(0, 500), - jsDoc, - sourceFile: sf.getFilePath() - }; - } - - if (Node.isModuleDeclaration(node)) { - return { - name, - kind: "namespace", - isTypeOnly: true, - declarationText: node.getText().trim(), - jsDoc, - sourceFile: sf.getFilePath() - }; - } - - // Fallback - return { - name, - kind: "other", - isTypeOnly: false, - declarationText: node.getText().trim().slice(0, 300), - jsDoc, - sourceFile: sf.getFilePath() - }; - } - return null; -} - -// --------------------------------------------------------------------------- -// Examples file finder -// --------------------------------------------------------------------------- - -export function findExamplesContent(relPath: string): string | undefined { - const pkgMap = getPackagePathMap(); - - // Check alongside the barrel in @webiny/* packages - for (const [alias, srcDir] of Array.from(pkgMap.entries())) { - const pkgName = alias.replace("@webiny/", ""); - const exportsDir = join(WEBINY_MONOREPO, pkgName.replace(/-/g, "-"), "src", "exports"); - const candidate = join(exportsDir, relPath + ".examples.md"); - if (existsSync(candidate)) { - return readFileSync(candidate, "utf-8"); - } - } - - // Also check api-core specifically (most common location) - const apiCoreExports = join(WEBINY_MONOREPO, "api-core", "src", "exports"); - const candidate2 = join(apiCoreExports, relPath + ".examples.md"); - if (existsSync(candidate2)) { - return readFileSync(candidate2, "utf-8"); - } - - return undefined; -} - -// --------------------------------------------------------------------------- -// Collect all source content for an entry point -// --------------------------------------------------------------------------- - -export function collectEntryPointSource( - relPath: string, - project: Project, - pkgMap: Map -): EntryPointSource | null { - const barrelSrc = join(WEBINY_PKG, "src", relPath + ".ts"); - if (!existsSync(barrelSrc)) return null; - - let barrelFile: SourceFile; - try { - barrelFile = project.addSourceFileAtPath(barrelSrc); - } catch { - return null; - } - - const exportEntries = parseBarrel(barrelFile, pkgMap); - const symbols: SymbolDecl[] = []; - const sourceFiles = new Map(); - const loadedSfs = new Map(); - - for (const entry of exportEntries) { - if (entry.exportedName === "*") continue; - if (!existsSync(entry.sourceFile)) continue; - - let sourceSf = loadedSfs.get(entry.sourceFile); - if (!sourceSf) { - try { - sourceSf = project.addSourceFileAtPath(entry.sourceFile); - loadedSfs.set(entry.sourceFile, sourceSf); - } catch { - continue; - } - } - - // Collect raw source (once per file) - if (!sourceFiles.has(entry.sourceFile)) { - sourceFiles.set(entry.sourceFile, sourceSf.getFullText()); - } - - const sym = extractSymbolDecl(sourceSf, entry.originalName); - if (sym) { - symbols.push({ - ...sym, - name: entry.exportedName, - isTypeOnly: entry.isTypeOnly || sym.isTypeOnly - }); - } else { - symbols.push({ - name: entry.exportedName, - kind: "other", - isTypeOnly: entry.isTypeOnly, - declarationText: "", - jsDoc: "", - sourceFile: entry.sourceFile - }); - } - } - - const examplesContent = findExamplesContent(relPath); - - return { - relPath, - importPath: `webiny/${relPath}`, - symbols, - sourceFiles, - examplesContent - }; -} - -// --------------------------------------------------------------------------- -// Claude caller -// --------------------------------------------------------------------------- - -let _claude: Anthropic | null = null; -function getClaude(): Anthropic { - if (!_claude) { - const apiKey = process.env.ANTHROPIC_API_KEY; - if (!apiKey) throw new Error("ANTHROPIC_API_KEY environment variable is not set"); - _claude = new Anthropic({ apiKey }); - } - return _claude; -} - -export async function callClaude(systemPrompt: string, userPrompt: string): Promise { - const claude = getClaude(); - const message = await claude.messages.create({ - model: "claude-sonnet-4-5", - max_tokens: 8192, - messages: [{ role: "user", content: userPrompt }], - system: systemPrompt - }); - - const textBlock = message.content.find(b => b.type === "text"); - if (!textBlock || textBlock.type !== "text") throw new Error("No text in Claude response"); - return textBlock.text; -} - -// --------------------------------------------------------------------------- -// ID generation (stable, path-based) -// --------------------------------------------------------------------------- - -export function stableId(relPath: string): string { - return Buffer.from(relPath) - .toString("base64") - .replace(/[^a-z0-9]/gi, "") - .slice(0, 8) - .toLowerCase() - .padEnd(8, "0"); -} - -// --------------------------------------------------------------------------- -// Title helper -// --------------------------------------------------------------------------- - -const TITLE_MAP: Record = { - api: "API", - cms: "CMS", - graphql: "GraphQL", - ui: "UI", - aco: "ACO", - cli: "CLI", - infra: "Infrastructure", - extensions: "Extensions", - admin: "Admin", - index: "Overview", - "build-params": "Build Params", - "event-publisher": "Event Publisher", - "key-value-store": "Key-Value Store", - tenancy: "Tenancy", - security: "Security", - system: "System", - tasks: "Tasks", - logger: "Logger", - entry: "Entry", - group: "Group", - model: "Model", - field: "Field", - page: "Page", - redirect: "Redirect", - nextjs: "Next.js", - "api-key": "API Key", - authentication: "Authentication", - role: "Role", - user: "User", - lexical: "Lexical Editor", - form: "Form", - router: "Router", - "local-storage": "Local Storage", - "env-config": "Env Config", - "graphql-client": "GraphQL Client", - configs: "Configs", - "website-builder": "Website Builder", - "tenant-manager": "Tenant Manager", - command: "Command", - core: "Core", - scheduler: "Scheduler", - flp: "FLP", - folder: "Folder", - "file-manager": "File Manager", - "build-params-api": "API Build Params" -}; - -export function toTitle(relPath: string): string { - const parts = relPath.split("/"); - const last = parts[parts.length - 1]; - const section = TITLE_MAP[last] ?? last.replace(/-/g, " ").replace(/\b\w/g, c => c.toUpperCase()); - if (parts.length === 1) return section; - if (last === "index") { - const parent = parts[parts.length - 2]; - return TITLE_MAP[parent] ?? parent.replace(/-/g, " ").replace(/\b\w/g, c => c.toUpperCase()); - } - return section; -} - -export function toOutputPath(relPath: string): string { - const overrides: Record = { - "cli/index": "cli/overview", - "infra/index": "infra/overview", - cli: "cli/overview", - infra: "infra/overview" - }; - return overrides[relPath] ?? relPath; -} - -// --------------------------------------------------------------------------- -// Navigation rewriter -// --------------------------------------------------------------------------- - -interface NavPage { - link: string; - title?: string; -} - -interface NavGroup { - title: string; - link?: string; - pages: (NavPage | NavGroup)[]; -} - -function isNavGroup(item: NavPage | NavGroup): item is NavGroup { - return "pages" in item; -} - -const LAYER_ORDER = ["api", "admin", "cli", "infra", "extensions"]; -const LAYER_LANDING: Record = { - api: "reference/api", - admin: "reference/admin", - cli: "reference/cli/overview", - infra: "reference/infra/overview" -}; -const SUBDOMAIN_LANDING: Record = { - "api/cms": "reference/api/cms/entry", - "api/security": "reference/api/security", - "api/website-builder": "reference/api/website-builder/page", - "admin/cms": "reference/admin/cms", - "admin/website-builder": "reference/admin/website-builder" -}; - -function makeGroup(title: string, link: string): NavGroup & { link: string } { - return { title, link, pages: [] }; -} - -function buildNavTree(entryPoints: { relPath: string; title: string }[]): NavGroup { - const root: NavGroup = { title: "Reference", pages: [] }; - const byLayer = new Map(); - - for (const ep of entryPoints) { - const layer = ep.relPath.split("/")[0]; - if (!byLayer.has(layer)) byLayer.set(layer, []); - byLayer.get(layer)!.push(ep); - } - - const orderedLayers = Array.from(byLayer.keys()).sort((a, b) => { - const ai = LAYER_ORDER.indexOf(a); - const bi = LAYER_ORDER.indexOf(b); - if (ai === -1 && bi === -1) return a.localeCompare(b); - if (ai === -1) return 1; - if (bi === -1) return -1; - return ai - bi; - }); - - for (const layer of orderedLayers) { - const eps = byLayer.get(layer)!; - if (eps.length === 1) { - root.pages.push({ link: `reference/${toOutputPath(eps[0].relPath)}` }); - continue; - } - - const layerLanding = LAYER_LANDING[layer] ?? `reference/${toOutputPath(eps[0].relPath)}`; - const layerGroup = makeGroup(toTitle(layer), layerLanding); - - const SUB_DOMAINS = ["cms", "website-builder", "security", "file-manager", "aco"]; - const bySubDomain = new Map(); - const flat: typeof entryPoints = []; - const subDomainIndex = new Map(); - - for (const ep of eps) { - const parts = ep.relPath.split("/"); - if (parts.length === 2 && SUB_DOMAINS.includes(parts[1])) { - subDomainIndex.set(parts[1], ep); - } else if (parts.length >= 3 && SUB_DOMAINS.includes(parts[1])) { - const sub = parts[1]; - if (!bySubDomain.has(sub)) bySubDomain.set(sub, []); - bySubDomain.get(sub)!.push(ep); - } else { - flat.push(ep); - } - } - - const rootFlat = flat.filter( - ep => `reference/${toOutputPath(ep.relPath)}` === layerLanding || ep.relPath === layer - ); - const otherFlat = flat.filter(ep => !rootFlat.includes(ep)); - for (const ep of [...rootFlat, ...otherFlat]) { - const isRoot = rootFlat.includes(ep); - layerGroup.pages.push({ - link: `reference/${toOutputPath(ep.relPath)}`, - title: isRoot ? "Root" : ep.title - }); - } - - for (const [subDomain, subEps] of Array.from(bySubDomain.entries())) { - const key = `${layer}/${subDomain}`; - const subLanding = SUBDOMAIN_LANDING[key] ?? `reference/${toOutputPath(subEps[0].relPath)}`; - const subGroup = makeGroup(toTitle(subDomain), subLanding); - const indexEp = subDomainIndex.get(subDomain); - if (indexEp) - subGroup.pages.push({ link: `reference/${toOutputPath(indexEp.relPath)}`, title: "Root" }); - for (const ep of subEps) { - subGroup.pages.push({ link: `reference/${toOutputPath(ep.relPath)}`, title: ep.title }); - } - layerGroup.pages.push(subGroup); - } - - root.pages.push(layerGroup); - } - return root; -} - -function findFirstLink(group: NavGroup): string { - for (const p of group.pages) { - if (!isNavGroup(p)) return p.link; - const nested = findFirstLink(p); - if (nested) return nested; - } - return ""; -} - -function renderNavItem(item: NavPage | NavGroup, indent: number): string { - const pad = " ".repeat(indent); - if (isNavGroup(item)) { - const groupLink = (item as NavGroup & { link?: string }).link ?? findFirstLink(item); - const lines = [ - `${pad}`, - ...item.pages.map(p => renderNavItem(p, indent + 1)), - `${pad}` - ]; - return lines.join("\n"); - } - if (item.title) return `${pad}`; - return `${pad}`; -} - -const NAV_MARKER_START = " {/* __REFERENCE_PAGES_START__ */}"; -const NAV_MARKER_END = " {/* __REFERENCE_PAGES_END__ */}"; - -export function rewriteNavigation(entryPoints: { relPath: string; title: string }[]): void { - const nav = readFileSync(NAV_FILE, "utf-8"); - const tree = buildNavTree(entryPoints); - - const innerLines: string[] = []; - for (const page of tree.pages) { - innerLines.push(renderNavItem(page, 2)); - } - const inner = innerLines.join("\n"); - - const startIdx = nav.indexOf(NAV_MARKER_START); - const endIdx = nav.indexOf(NAV_MARKER_END); - - if (startIdx === -1 || endIdx === -1) { - console.warn(" [nav] Markers not found in navigation.tsx — skipping nav update"); - return; - } - - const before = nav.slice(0, startIdx + NAV_MARKER_START.length); - const after = nav.slice(endIdx); - const updated = `${before}\n${inner}\n ${after}`; - writeFileSync(NAV_FILE, updated, "utf-8"); - console.log(` [nav] Updated navigation.tsx Reference group`); -} diff --git a/scripts/ref/sdk.ts b/scripts/ref/sdk.ts deleted file mode 100644 index 5a535e610..000000000 --- a/scripts/ref/sdk.ts +++ /dev/null @@ -1,472 +0,0 @@ -/** - * AI-powered Webiny SDK Reference Generator - * - * For each webiny/* entry point: - * 1. Resolves all exported symbols via ts-morph (declaration text + JSDoc) - * 2. Sends the source to Claude with a structured prompt - * 3. Claude writes the complete .mdx page and .ai.txt companion - * 4. Files are written to docs/developer-docs/6.x/reference/ - * - * Usage: - * tsx scripts/ref/sdk.ts # skip existing pages - * tsx scripts/ref/sdk.ts --force # regenerate all - * tsx scripts/ref/sdk.ts --only api/logger,api/graphql - */ - -import { readFileSync, writeFileSync, mkdirSync, existsSync, rmSync } from "fs"; -import { join, dirname } from "path"; -import { Project } from "ts-morph"; -import { - WEBINY_PKG, - DOCS_ROOT, - REF_DIR, - collectEntryPointSource, - getPackagePathMap, - callClaude, - stableId, - toTitle, - toOutputPath, - rewriteNavigation, - type EntryPointSource -} from "./_shared.js"; - -// --------------------------------------------------------------------------- -// Prompt construction -// --------------------------------------------------------------------------- - -const AGENTS_MD = readFileSync(join(process.cwd(), "AGENTS.md"), "utf-8"); - -const LOGGER_EXAMPLE = `--- -id: yxbpl2xv -title: Logger -description: "Logger abstraction for server-side logging" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- What is the \`Logger\` abstraction and when do you need it? -- How to inject and use \`Logger\` in your extensions? - - - -## Overview - -\`webiny/api/logger\` exports the \`Logger\` abstraction — a structured logger for server-side Webiny extensions. Inject it via the DI container to write log output at different severity levels without coupling your code to a specific logging library. - - - -## \`Logger\` - -**Abstraction** — imported from \`webiny/api/logger\` - -\`\`\`typescript -import { Logger } from "webiny/api/logger"; -\`\`\` - -**Interface \`Logger.Interface\`:** - -Structured logger with severity-level methods. The underlying implementation is Pino. - -\`\`\`typescript -interface Logger.Interface { - trace(objOrMsg: object | string, ...args: any[]): void; - debug(objOrMsg: object | string, ...args: any[]): void; - info(objOrMsg: object | string, ...args: any[]): void; - warn(objOrMsg: object | string, ...args: any[]): void; - error(objOrMsg: object | string, ...args: any[]): void; - fatal(objOrMsg: object | string, ...args: any[]): void; - log(objOrMsg: object | string, ...args: any[]): void; -} -\`\`\` - -| Method | Description | -| --------- | ------------------------------------------------------------------- | -| \`trace()\` | Log a trace-level message. Use for very verbose diagnostic output. | -| \`debug()\` | Log a debug-level message. Use for development-time diagnostics. | -| \`info()\` | Log an informational message. Use for normal operational events. | -| \`warn()\` | Log a warning. Use for recoverable issues that warrant attention. | -| \`error()\` | Log an error. Use when an operation fails. | -| \`fatal()\` | Log a fatal error. Use when the process cannot continue. | -| \`log()\` | Log at info level. Alias for \`info()\`. | - -**Types:** - -\`\`\`typescript -namespace Logger { - type Interface = ILogger; -} -\`\`\` - -## Examples - -### Basic Usage - -Simple logger injection and usage: - -\`\`\`typescript -import { ApiKeyAfterUpdateEventHandler } from "webiny/api/security/api-key"; -import { Logger } from "webiny/api/logger"; - -class MyApiKeyAfterUpdateImpl implements ApiKeyAfterUpdateEventHandler.Interface { - constructor(private logger: Logger.Interface) {} - - async handle() { - this.logger.debug("An API key was updated!"); - } -} - -const MyApiKeyAfterUpdate = ApiKeyAfterUpdateEventHandler.createImplementation({ - implementation: MyApiKeyAfterUpdateImpl, - dependencies: [Logger] -}); - -export default MyApiKeyAfterUpdate; -\`\`\``; - -const GRAPHQL_EXAMPLE = `--- -id: yxbpl2dy -title: GraphQL -description: "GraphQL schema factory and response helpers" ---- - -import { Alert } from "@/components/Alert"; -import { SymbolList } from "@/components/SymbolList"; - - - -- How to extend the Webiny GraphQL schema using \`GraphQLSchemaFactory\`? -- What response classes are available and when to use each? - - - -## Overview - -\`webiny/api/graphql\` provides the building blocks for extending Webiny's GraphQL API. Use \`GraphQLSchemaFactory\` to add custom type definitions and resolvers. The response classes (\`Response\`, \`ListResponse\`, \`ErrorResponse\`, etc.) standardize the shape of GraphQL resolver return values. - -**Services** - - - -**Types & Classes** - - - -## Services - -### \`GraphQLSchemaFactory\` - -**Abstraction** — imported from \`webiny/api/graphql\` - -Implement \`GraphQLSchemaFactory\` to add custom type definitions and resolvers to the Webiny GraphQL schema. The factory receives a \`GraphQLSchemaBuilder\` instance you use to register your schema extensions. - -\`\`\`typescript -import { GraphQLSchemaFactory } from "webiny/api/graphql"; -\`\`\` - -**Interface \`GraphQLSchemaFactory.Interface\`:** - -\`\`\`typescript -interface GraphQLSchemaFactory.Interface { - execute(builder: GraphQLSchemaBuilder.Interface): Promise; -} -\`\`\` - -**\`SchemaBuilder\` — \`GraphQLSchemaBuilder.Interface\`:** - -\`\`\`typescript -interface GraphQLSchemaBuilder.Interface { - addTypeDefs(typeDefs: TypeDefs): this; - addResolver(config: ResolverConfig): this; - build(): IGraphQLSchema; -} -\`\`\` - -| Method | Description | -| ------ | ----------- | -| \`addTypeDefs()\` | Add GraphQL SDL type definitions to the schema. | -| \`addResolver()\` | Register a resolver with optional middleware decorators. | -| \`build()\` | Build and return the final schema object. |`; - -function buildSystemPrompt(): string { - return `You are a technical documentation writer for Webiny, an open-source serverless CMS. You write concise, accurate API reference pages in MDX format. - -## Your task -For each webiny/* entry point you receive, write a complete reference page (.mdx) and a short .ai.txt companion file. The user will provide the TypeScript source and extracted symbol declarations. - -## MDX conventions (follow exactly) - -${AGENTS_MD} - -## Gold-standard example pages - -### Example 1: webiny/api/logger (simple, single abstraction) - -${LOGGER_EXAMPLE} - -### Example 2: webiny/api/graphql (mixed: abstraction + classes) - -${GRAPHQL_EXAMPLE} - -## Output format - -Respond with EXACTLY two sections separated by the delimiter \`---AI-TXT---\`: - -1. The complete .mdx content (frontmatter through last line) -2. The .ai.txt companion - -Do not include any other text, explanation, or markdown fences around the output. - -Example response structure: ---- -id: PLACEHOLDER_ID -title: ... ---- -[rest of mdx] ----AI-TXT--- -AI Context: Title (reference/path/to/file.mdx) -[rest of ai.txt] - -## Key rules -- The id field will be injected after — write PLACEHOLDER_ID and it will be replaced -- description field: ALWAYS wrap in double quotes (e.g. \`description: "My desc"\`) — required if it contains a colon -- Use "webiny/" prefix in import paths, NEVER "@webiny/" -- SymbolList anchors: slugify symbol name (camelCase → kebab-case, e.g. "GraphQLSchemaFactory" → "graph-ql-schema-factory") -- Do NOT use @example JSDoc — examples go in the Examples section -- Code blocks always have a language tag (typescript, graphql, tsx) -- No shell/bash code blocks -- No H1 in body (title comes from frontmatter) -- "WHAT YOU'LL LEARN" bullets must be specific to this entry point — not generic boilerplate -- Overview section: 1-3 paragraphs explaining what this entry point provides and when to use it -- For abstractions: show the Interface code block + a method table with descriptions -- For classes: show the class signature with public API only (no private members) -- If the entry point has many symbols (>5), group them with bold labels + SymbolList chips in Overview -- The .ai.txt must follow the format from AGENTS.md exactly`; -} - -function buildUserPrompt(src: EntryPointSource): string { - const lines: string[] = []; - - lines.push(`## Entry point: ${src.importPath}`); - lines.push(`Import path: \`import { ... } from "${src.importPath}"\``); - lines.push(`Output file: reference/${toOutputPath(src.relPath)}.mdx`); - lines.push(`Page title: ${toTitle(src.relPath)}`); - lines.push(``); - - lines.push(`## Exported symbols (${src.symbols.length} total)`); - lines.push(``); - for (const sym of src.symbols) { - lines.push(`### ${sym.name} (${sym.kind}${sym.isTypeOnly ? ", type-only" : ""})`); - if (sym.jsDoc) { - lines.push(`**JSDoc:** ${sym.jsDoc}`); - } - if (sym.declarationText) { - lines.push("```typescript"); - lines.push(sym.declarationText); - lines.push("```"); - } - lines.push(``); - } - - lines.push(`## Source files`); - lines.push(``); - for (const [filePath, content] of Array.from(src.sourceFiles.entries())) { - // Show a shortened path for readability - const shortPath = filePath.replace("/Users/adrian/dev/wby-next/packages/", "packages/"); - lines.push(`### ${shortPath}`); - lines.push("```typescript"); - // Trim very long files to avoid token limits - const trimmed = - content.length > 6000 ? content.slice(0, 6000) + "\n// ... (truncated)" : content; - lines.push(trimmed); - lines.push("```"); - lines.push(``); - } - - if (src.examplesContent) { - lines.push(`## Examples file content`); - lines.push(``); - lines.push(src.examplesContent); - lines.push(``); - lines.push( - `**Important:** Include these examples verbatim in an "## Examples" section at the bottom of the .mdx. Each H2 heading in the examples file becomes a "### Title" subsection.` - ); - } - - lines.push(`## Instructions`); - lines.push( - `Write the complete reference page for \`${src.importPath}\`. Follow all conventions from the system prompt exactly. Be specific and technical — this is a developer API reference.` - ); - - return lines.join("\n"); -} - -// --------------------------------------------------------------------------- -// Parse Claude response → {mdx, aiTxt} -// --------------------------------------------------------------------------- - -function parseClaudeResponse( - response: string, - relPath: string, - id: string -): { mdx: string; aiTxt: string } { - const delimiter = "---AI-TXT---"; - const delimIdx = response.indexOf(delimiter); - - let mdx: string; - let aiTxt: string; - - if (delimIdx === -1) { - // No delimiter — treat entire response as MDX, generate minimal ai.txt - mdx = response.trim(); - aiTxt = `AI Context: ${toTitle(relPath)} (reference/${toOutputPath( - relPath - )}.mdx)\n\nGenerated by AI reference generator.`; - } else { - mdx = response.slice(0, delimIdx).trim(); - aiTxt = response.slice(delimIdx + delimiter.length).trim(); - } - - // Replace PLACEHOLDER_ID with the actual stable ID - mdx = mdx.replace("PLACEHOLDER_ID", id); - - // Strip any accidental markdown code fences wrapping the output - if (mdx.startsWith("```")) { - mdx = mdx - .replace(/^```[a-z]*\n?/, "") - .replace(/```\s*$/, "") - .trim(); - } - - return { mdx, aiTxt }; -} - -// --------------------------------------------------------------------------- -// Main -// --------------------------------------------------------------------------- - -async function main(): Promise { - const args = process.argv.slice(2); - const force = args.includes("--force"); - const onlyArg = args.find(a => a.startsWith("--only=")); - const onlyPaths = onlyArg ? onlyArg.replace("--only=", "").split(",") : null; - - console.log(`\nWebiny SDK Reference Generator (AI-powered)`); - console.log(`Model: claude-sonnet-4-5`); - console.log(`Force: ${force}`); - if (onlyPaths) console.log(`Only: ${onlyPaths.join(", ")}`); - console.log(``); - - // Wipe reference/ on force mode if running full set - if (force && !onlyPaths) { - console.log("Clearing reference/ directory..."); - if (existsSync(REF_DIR)) { - rmSync(REF_DIR, { recursive: true }); - } - mkdirSync(REF_DIR, { recursive: true }); - } - - // Read webiny package exports - const pkgJson = JSON.parse(readFileSync(join(WEBINY_PKG, "package.json"), "utf-8")); - const exportsMap: Record = pkgJson.exports ?? {}; - const pkgMap = getPackagePathMap(); - - const entryPaths: string[] = Object.keys(exportsMap) - .filter(k => !k.includes("*") && !k.endsWith(".json") && !k.endsWith(".ts")) - .map(k => k.replace(/^\.\//, "")) - .sort(); - - console.log(`Found ${entryPaths.length} entry points`); - - // Filter to --only if specified - const pathsToProcess = onlyPaths - ? entryPaths.filter(p => onlyPaths.some(o => p === o || p.startsWith(o + "/"))) - : entryPaths; - - // Set up ts-morph project - const project = new Project({ - tsConfigFilePath: join(WEBINY_PKG, "tsconfig.json"), - skipAddingFilesFromTsConfig: true - }); - - const systemPrompt = buildSystemPrompt(); - - const processedEntryPoints: { relPath: string; title: string }[] = []; - let generated = 0; - let skipped = 0; - let failed = 0; - - for (const relPath of pathsToProcess) { - const outputPath = toOutputPath(relPath); - const mdxPath = join(REF_DIR, outputPath + ".mdx"); - const aiTxtPath = join(REF_DIR, outputPath + ".ai.txt"); - - // Skip if exists and not forcing - if (!force && existsSync(mdxPath)) { - console.log(` [skip] ${relPath} — already exists`); - processedEntryPoints.push({ relPath, title: toTitle(relPath) }); - skipped++; - continue; - } - - process.stdout.write(` [gen] ${relPath}... `); - - // Collect source - const src = collectEntryPointSource(relPath, project, pkgMap); - if (!src || src.symbols.length === 0) { - console.log(`SKIP (no symbols)`); - skipped++; - continue; - } - - // Build prompt - const userPrompt = buildUserPrompt(src); - - // Call Claude - let response: string; - try { - response = await callClaude(systemPrompt, userPrompt); - } catch (err) { - console.log(`FAILED (${(err as Error).message})`); - failed++; - continue; - } - - // Parse response - const id = stableId(relPath); - const { mdx, aiTxt } = parseClaudeResponse(response, relPath, id); - - // Write files - const dir = join(REF_DIR, dirname(outputPath)); - mkdirSync(dir, { recursive: true }); - writeFileSync(mdxPath, mdx, "utf-8"); - writeFileSync(aiTxtPath, aiTxt, "utf-8"); - - processedEntryPoints.push({ relPath, title: toTitle(relPath) }); - generated++; - console.log(`OK (${src.symbols.length} symbols)`); - } - - // Update navigation - console.log(`\nUpdating navigation...`); - rewriteNavigation(processedEntryPoints); - - console.log(`\nDone.`); - console.log(` Generated: ${generated}`); - console.log(` Skipped: ${skipped}`); - console.log(` Failed: ${failed}`); -} - -main().catch(err => { - console.error("Fatal:", err); - process.exit(1); -}); diff --git a/scripts/ref/webiny-sdk.ts b/scripts/ref/webiny-sdk.ts deleted file mode 100644 index 51bc40a44..000000000 --- a/scripts/ref/webiny-sdk.ts +++ /dev/null @@ -1,501 +0,0 @@ -/** - * AI-powered @webiny/sdk Reference Generator - * - * Generates 4 reference pages for the @webiny/sdk package: - * - reference/sdk/index.mdx — Overview, WebinyConfig, Result, error classes - * - reference/sdk/cms.mdx — CmsSdk: all CMS methods + param types - * - reference/sdk/file-manager.mdx — FileManagerSdk: all file methods + types - * - reference/sdk/tenant-manager.mdx — TenantManagerSdk: all tenant methods + types - * - * Usage: - * tsx scripts/ref/webiny-sdk.ts # skip existing pages - * tsx scripts/ref/webiny-sdk.ts --force # regenerate all - * tsx scripts/ref/webiny-sdk.ts --only=cms # regenerate one page - */ - -import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs"; -import { join } from "path"; -import { callClaude, REF_DIR, DOCS_ROOT, NAV_FILE, stableId } from "./_shared.js"; - -// --------------------------------------------------------------------------- -// SDK source root -// --------------------------------------------------------------------------- - -const SDK_SRC = "/Users/adrian/dev/wby-next/packages/sdk/src"; - -function src(relPath: string): string { - return readFileSync(join(SDK_SRC, relPath), "utf-8"); -} - -// --------------------------------------------------------------------------- -// Existing guide docs (context for Claude) -// --------------------------------------------------------------------------- - -const WEBINY_SDK_GUIDE = readFileSync(join(DOCS_ROOT, "core-concepts/webiny-sdk.mdx"), "utf-8"); - -const USING_SDK_GUIDE = readFileSync(join(DOCS_ROOT, "headless-cms/using-webiny-sdk.mdx"), "utf-8"); - -// --------------------------------------------------------------------------- -// Page definitions -// --------------------------------------------------------------------------- - -interface SdkPage { - key: string; // --only= filter key - outputPath: string; // relative to reference/ - title: string; - description: string; - sourceFiles: Record; // label -> content - pageInstruction: string; -} - -function buildPages(): SdkPage[] { - return [ - // ----------------------------------------------------------------------- - // Overview - // ----------------------------------------------------------------------- - { - key: "index", - outputPath: "sdk/index", - title: "Overview", - description: "Webiny SDK: WebinyConfig, Result, and error classes", - sourceFiles: { - "index.ts": src("index.ts"), - "Webiny.ts": src("Webiny.ts"), - "types.ts": src("types.ts"), - "Result.ts": src("Result.ts"), - "BaseError.ts": src("BaseError.ts"), - "errors.ts": src("errors.ts") - }, - pageInstruction: ` -Write the Overview reference page for \`@webiny/sdk\`. This page covers: - -1. **What the SDK is** — a standalone TypeScript library for calling Webiny APIs from external apps (Next.js, Node.js, etc.). Not for use inside Webiny extensions (use \`webiny/*\` for that). - -2. **Installation and initialization** — \`npm install @webiny/sdk\`, then instantiate with \`WebinyConfig\`. - -3. **\`WebinyConfig\`** — document all fields: \`endpoint\` (required), \`token\` (API key token from Admin → Settings → API Keys), \`tenant\` (defaults to "root"), \`headers\` (optional custom headers), \`fetch\` (optional custom fetch implementation). - -4. **\`Result\`** — the return type of all SDK methods. Document: \`isOk()\`, \`isFail()\`, \`value\`, \`error\`, \`map()\`, \`mapError()\`, \`flatMap()\`, \`match()\`. Also document the namespace types \`Result.UnwrapResult\` and \`Result.UnwrapError\`. - -5. **Error classes** — \`HttpError\` (HTTP-level failures, has \`data.status\`), \`GraphQLError\` (API returned an error, has \`data.code\`), \`NetworkError\` (fetch itself failed). All extend \`BaseError\`. - -6. **\`Webiny\` class** — the main entry point. Document properties: \`cms\` (\`CmsSdk\`), \`tenantManager\` (\`TenantManagerSdk\`), \`fileManager\` (\`FileManagerSdk\`). Document constructor params. - -Key facts from the existing docs: -- Authentication uses an API key token (not Basic auth or OAuth) -- Find API endpoint with \`yarn webiny info\` — use the base CloudFront domain -- Create a singleton instance and reuse it throughout the app -- Import path is \`@webiny/sdk\` (not \`webiny/\` — this is an external package) - -Include a "Quick Start" examples section showing: installation, initializing the \`Webiny\` class, and a simple \`isOk()\`/\`isFail()\` check pattern. -` - }, - - // ----------------------------------------------------------------------- - // CMS - // ----------------------------------------------------------------------- - { - key: "cms", - outputPath: "sdk/cms", - title: "CMS", - description: "CmsSdk: query and mutate Headless CMS entries", - sourceFiles: { - "CmsSdk.ts": src("CmsSdk.ts"), - "methods/cms/cmsTypes.ts": src("methods/cms/cmsTypes.ts"), - "methods/cms/getEntry.ts": src("methods/cms/getEntry.ts"), - "methods/cms/listEntries.ts": src("methods/cms/listEntries.ts"), - "methods/cms/createEntry.ts": src("methods/cms/createEntry.ts"), - "methods/cms/updateEntryRevision.ts": src("methods/cms/updateEntryRevision.ts"), - "methods/cms/publishEntryRevision.ts": src("methods/cms/publishEntryRevision.ts"), - "methods/cms/unpublishEntryRevision.ts": src("methods/cms/unpublishEntryRevision.ts"), - "methods/cms/deleteEntryRevision.ts": src("methods/cms/deleteEntryRevision.ts") - }, - pageInstruction: ` -Write the CMS reference page for \`sdk.cms\` (\`CmsSdk\`). Access via \`sdk.cms\` on a \`Webiny\` instance. - -Document every method on \`CmsSdk\` with: -- Method signature -- All parameters with types, required/optional, and descriptions -- Return type -- Key behavioral notes - -Methods to document (in this order): - -**Read methods** (use the Read API — published content only, unless \`preview: true\`): -- \`getEntry(params)\` — fetch a single entry by \`id\`, \`entryId\`, or \`values\` filter -- \`listEntries(params)\` — list entries with filtering, sorting, pagination, full-text search - -**Write methods** (use the Manage API): -- \`createEntry(params)\` — creates a draft entry -- \`updateEntryRevision(params)\` — partial update (only specified fields change) -- \`publishEntryRevision(params)\` — makes entry visible via Read API -- \`unpublishEntryRevision(params)\` — reverts to draft -- \`deleteEntryRevision(params)\` — soft delete by default; \`permanent: true\` for hard delete - -Key facts to include: -- \`fields\` parameter: use \`"values.fieldId"\` for entry values, \`"id"\`, \`"entryId"\`, \`"createdOn"\` etc. for metadata -- \`preview: true\` on read methods uses the Preview API (returns unpublished/draft content) -- \`createEntry\` always creates a draft — call \`publishEntryRevision\` to publish -- \`revisionId\` format is \`"entryId#revisionNumber"\` e.g. \`"abc123#0001"\` -- TypeScript generic \`\` types the \`values\` field on returned \`CmsEntryData\` -- Also document \`CmsEntryData\`, \`CmsEntryValues\`, \`CmsEntryStatus\`, \`CmsIdentity\` types - -Include a practical examples section covering: list with filter+sort+pagination, get by ID, create+publish flow, TypeScript generics usage, error handling pattern. -` - }, - - // ----------------------------------------------------------------------- - // File Manager - // ----------------------------------------------------------------------- - { - key: "file-manager", - outputPath: "sdk/file-manager", - title: "File Manager", - description: '"FileManagerSdk: upload, retrieve, and manage files"', - sourceFiles: { - "FileManagerSdk.ts": src("FileManagerSdk.ts"), - "methods/fileManager/fileManagerTypes.ts": src("methods/fileManager/fileManagerTypes.ts"), - "methods/fileManager/getFile.ts": src("methods/fileManager/getFile.ts"), - "methods/fileManager/listFiles.ts": src("methods/fileManager/listFiles.ts"), - "methods/fileManager/createFile.ts": src("methods/fileManager/createFile.ts"), - "methods/fileManager/createFiles.ts": src("methods/fileManager/createFiles.ts"), - "methods/fileManager/updateFile.ts": src("methods/fileManager/updateFile.ts"), - "methods/fileManager/deleteFile.ts": src("methods/fileManager/deleteFile.ts"), - "methods/fileManager/listTags.ts": src("methods/fileManager/listTags.ts"), - "methods/fileManager/getPresignedPostPayload.ts": src( - "methods/fileManager/getPresignedPostPayload.ts" - ), - "methods/fileManager/getPresignedPostPayloads.ts": src( - "methods/fileManager/getPresignedPostPayloads.ts" - ), - "methods/fileManager/createMultiPartUpload.ts": src( - "methods/fileManager/createMultiPartUpload.ts" - ), - "methods/fileManager/completeMultiPartUpload.ts": src( - "methods/fileManager/completeMultiPartUpload.ts" - ) - }, - pageInstruction: ` -Write the File Manager reference page for \`sdk.fileManager\` (\`FileManagerSdk\`). Access via \`sdk.fileManager\` on a \`Webiny\` instance. - -Document every method on \`FileManagerSdk\` with full param tables and return types. - -Group methods into logical sections: - -**Reading files:** -- \`getFile(params)\` — get a single file by ID -- \`listFiles(params)\` — list files with search, where filters, sort, pagination -- \`listTags(params)\` — list all tags used on files - -**Creating and updating files:** -- \`createFile(params)\` — register a file record (after upload) -- \`createFiles(params)\` — bulk register file records -- \`updateFile(params)\` — update file metadata -- \`deleteFile(params)\` — delete a file record - -**Upload helpers (S3 presigned uploads):** -- \`getPresignedPostPayload(params)\` — get a single S3 presigned POST URL for direct browser upload -- \`getPresignedPostPayloads(params)\` — get multiple presigned POST URLs in bulk -- \`createMultiPartUpload(params)\` — initiate a multipart upload for large files -- \`completeMultiPartUpload(params)\` — finalize a multipart upload after all parts are uploaded - -Key types to document: \`FmFile\`, \`FmTag\`, \`FmListMeta\`, \`FmFile_Metadata\`, \`FmFile_AccessControl\`, \`PresignedPostPayloadResponse\`, \`MultiPartUploadResponse\`. - -Include examples covering: listing files with search, single file get, basic upload flow (presigned POST → createFile), multipart upload flow for large files. -` - }, - - // ----------------------------------------------------------------------- - // Tenant Manager - // ----------------------------------------------------------------------- - { - key: "tenant-manager", - outputPath: "sdk/tenant-manager", - title: "Tenant Manager", - description: "TenantManagerSdk: create and manage tenants programmatically", - sourceFiles: { - "TenantManagerSdk.ts": src("TenantManagerSdk.ts"), - "methods/tenantManager/tenantManagerTypes.ts": src( - "methods/tenantManager/tenantManagerTypes.ts" - ), - "methods/tenantManager/createTenant.ts": src("methods/tenantManager/createTenant.ts"), - "methods/tenantManager/installTenant.ts": src("methods/tenantManager/installTenant.ts"), - "methods/tenantManager/disableTenant.ts": src("methods/tenantManager/disableTenant.ts"), - "methods/tenantManager/enableTenant.ts": src("methods/tenantManager/enableTenant.ts") - }, - pageInstruction: ` -Write the Tenant Manager reference page for \`sdk.tenantManager\` (\`TenantManagerSdk\`). Access via \`sdk.tenantManager\` on a \`Webiny\` instance. - -Document all 4 methods: -- \`createTenant(params)\` — creates a new tenant. \`CreateTenantInput\`: \`id?\`, \`name\` (required), \`description?\` -- \`installTenant(params)\` — provisions a tenant with default settings. Must be called after \`createTenant\` before the tenant is usable. -- \`disableTenant(params)\` — disables a tenant, blocking access to its resources -- \`enableTenant(params)\` — re-enables a previously disabled tenant - -Key facts: -- All methods return \`Result\` -- \`createTenant\` + \`installTenant\` is the required two-step flow for provisioning a new tenant -- Tenant \`id\` is optional in create — Webiny generates one if omitted -- The API key used must have tenant manager permissions - -Include an examples section showing: the full create+install flow, disabling/enabling a tenant, error handling. -` - } - ]; -} - -// --------------------------------------------------------------------------- -// System prompt -// --------------------------------------------------------------------------- - -const AGENTS_MD = readFileSync(join(process.cwd(), "AGENTS.md"), "utf-8"); - -function buildSystemPrompt(): string { - return `You are a technical documentation writer for Webiny, an open-source serverless CMS. You write concise, accurate API reference pages in MDX format. - -## Your task -Write a complete reference page (.mdx) and a companion .ai.txt file for a section of the \`@webiny/sdk\` package — the standalone Webiny JavaScript/TypeScript SDK for external applications. - -## MDX conventions (follow exactly) - -${AGENTS_MD} - -## IMPORTANT: Import paths for @webiny/sdk - -This is an EXTERNAL package — not part of the \`webiny/*\` internal extensions system. Use: -\`\`\`typescript -import { Webiny } from "@webiny/sdk"; -import type { CmsEntryData } from "@webiny/sdk"; -\`\`\` -NOT \`webiny/\` (that's for internal extensions). - -## Existing guide docs (use for tone, examples, and key facts) - -### core-concepts/webiny-sdk.mdx -${WEBINY_SDK_GUIDE} - -### headless-cms/using-webiny-sdk.mdx -${USING_SDK_GUIDE} - -## Output format - -Respond with EXACTLY two sections separated by \`---AI-TXT---\`: - -1. The complete .mdx content -2. The .ai.txt companion - -No other text, no markdown fences wrapping the output. - -Response structure: ---- -id: PLACEHOLDER_ID -title: ... -description: ... ---- -[rest of mdx] ----AI-TXT--- -AI Context: Title (reference/sdk/page.mdx) -[rest of ai.txt] - -## Key rules -- id field: write PLACEHOLDER_ID (replaced after) -- description field: ALWAYS wrap in double quotes (e.g. \`description: "My desc"\`) — required if it contains a colon -- NEVER use angle brackets in headings (e.g. \`#### \`Foo\`\` breaks MDX) — use \`#### \`Foo\`\` and mention the generic in prose instead -- Do NOT use \`\` as a wrapper around markdown lists — it expects a \`symbols\` prop array. For SDK pages, use plain markdown lists or bold group headers instead of SymbolList chips -- No H1 in body -- No shell/bash code blocks — use \`typescript\` or \`tsx\` instead -- Except in installation section where \`bash\` is acceptable for \`npm install\` -- "WHAT YOU'LL LEARN" bullets must be specific to this page -- Overview: 1-3 paragraphs — what this class/module provides, when to use it -- For each method: signature block + param table (name, type, required, description) + return type -- Use \`Result\` return type throughout — never \`Promise\` -- The .ai.txt follows the format from AGENTS.md exactly`; -} - -// --------------------------------------------------------------------------- -// User prompt per page -// --------------------------------------------------------------------------- - -function buildUserPrompt(page: SdkPage): string { - const lines: string[] = []; - - lines.push(`## Page to generate`); - lines.push(`Output: reference/${page.outputPath}.mdx`); - lines.push(`Title: ${page.title}`); - lines.push(`Description: ${page.description}`); - lines.push(``); - - lines.push(`## Source files`); - lines.push(``); - for (const [label, content] of Object.entries(page.sourceFiles)) { - lines.push(`### ${label}`); - lines.push("```typescript"); - lines.push(content); - lines.push("```"); - lines.push(``); - } - - lines.push(`## What to document`); - lines.push(page.pageInstruction.trim()); - - return lines.join("\n"); -} - -// --------------------------------------------------------------------------- -// Nav rewrite — appends SDK group, preserves existing webiny/* entries -// --------------------------------------------------------------------------- - -function rewriteNavWithSdk(pages: SdkPage[]): void { - const nav = readFileSync(NAV_FILE, "utf-8"); - - const SDK_NAV_START = " {/* __SDK_PAGES_START__ */}"; - const SDK_NAV_END = " {/* __SDK_PAGES_END__ */}"; - - const sdkLinks = pages - .filter(p => p.key !== "index") // index is the group landing, not a child page - .map(p => ` `) - .join("\n"); - - const sdkGroup = - ` \n` + - sdkLinks + - `\n `; - - // If markers already exist, replace between them - if (nav.includes(SDK_NAV_START) && nav.includes(SDK_NAV_END)) { - const startIdx = nav.indexOf(SDK_NAV_START); - const endIdx = nav.indexOf(SDK_NAV_END); - const before = nav.slice(0, startIdx + SDK_NAV_START.length); - const after = nav.slice(endIdx); - writeFileSync(NAV_FILE, `${before}\n${sdkGroup}\n ${after}`, "utf-8"); - console.log(` [nav] Updated SDK group in navigation.tsx`); - return; - } - - // Otherwise inject before the REFERENCE_PAGES_END marker - const REF_END = " {/* __REFERENCE_PAGES_END__ */}"; - const refEndIdx = nav.indexOf(REF_END); - if (refEndIdx === -1) { - console.warn(` [nav] Could not find __REFERENCE_PAGES_END__ marker — skipping nav update`); - return; - } - - const before = nav.slice(0, refEndIdx); - const after = nav.slice(refEndIdx); - const sdkBlock = ` ${SDK_NAV_START}\n` + sdkGroup + `\n ${SDK_NAV_END}\n `; - - writeFileSync(NAV_FILE, `${before}${sdkBlock}${after}`, "utf-8"); - console.log(` [nav] Injected SDK group into navigation.tsx`); -} - -// --------------------------------------------------------------------------- -// Parse Claude response -// --------------------------------------------------------------------------- - -function parseResponse(response: string, page: SdkPage): { mdx: string; aiTxt: string } { - const delimiter = "---AI-TXT---"; - const delimIdx = response.indexOf(delimiter); - - let mdx: string; - let aiTxt: string; - - if (delimIdx === -1) { - mdx = response.trim(); - aiTxt = `AI Context: ${page.title} (reference/${page.outputPath}.mdx)\n\nGenerated by AI reference generator.`; - } else { - mdx = response.slice(0, delimIdx).trim(); - aiTxt = response.slice(delimIdx + delimiter.length).trim(); - } - - // Replace placeholder ID - const id = stableId(`sdk/${page.key}`); - mdx = mdx.replace("PLACEHOLDER_ID", id); - - // Strip any accidental outer fences - if (mdx.startsWith("```")) { - mdx = mdx - .replace(/^```[a-z]*\n?/, "") - .replace(/```\s*$/, "") - .trim(); - } - - return { mdx, aiTxt }; -} - -// --------------------------------------------------------------------------- -// Main -// --------------------------------------------------------------------------- - -async function main(): Promise { - const args = process.argv.slice(2); - const force = args.includes("--force"); - const onlyArg = args.find(a => a.startsWith("--only=")); - const onlyKeys = onlyArg ? onlyArg.replace("--only=", "").split(",") : null; - - console.log(`\n@webiny/sdk Reference Generator (AI-powered)`); - console.log(`Model: claude-sonnet-4-5`); - console.log(`Force: ${force}`); - if (onlyKeys) console.log(`Only: ${onlyKeys.join(", ")}`); - console.log(``); - - const pages = buildPages(); - const pagesToProcess = onlyKeys ? pages.filter(p => onlyKeys.includes(p.key)) : pages; - - if (pagesToProcess.length === 0) { - console.error(`No matching pages found. Valid keys: ${pages.map(p => p.key).join(", ")}`); - process.exit(1); - } - - // Ensure output directory exists - mkdirSync(join(REF_DIR, "sdk"), { recursive: true }); - - const systemPrompt = buildSystemPrompt(); - let generated = 0; - let skipped = 0; - let failed = 0; - - for (const page of pagesToProcess) { - const mdxPath = join(REF_DIR, page.outputPath + ".mdx"); - const aiTxtPath = join(REF_DIR, page.outputPath + ".ai.txt"); - - if (!force && existsSync(mdxPath)) { - console.log(` [skip] ${page.outputPath} — already exists`); - skipped++; - continue; - } - - process.stdout.write(` [gen] ${page.outputPath}... `); - - const userPrompt = buildUserPrompt(page); - - let response: string; - try { - response = await callClaude(systemPrompt, userPrompt); - } catch (err) { - console.log(`FAILED (${(err as Error).message})`); - failed++; - continue; - } - - const { mdx, aiTxt } = parseResponse(response, page); - writeFileSync(mdxPath, mdx, "utf-8"); - writeFileSync(aiTxtPath, aiTxt, "utf-8"); - - generated++; - console.log(`OK`); - } - - // Update navigation with all pages (even skipped — they're already on disk) - console.log(`\nUpdating navigation...`); - rewriteNavWithSdk(pages); - - console.log(`\nDone.`); - console.log(` Generated: ${generated}`); - console.log(` Skipped: ${skipped}`); - console.log(` Failed: ${failed}`); -} - -main().catch(err => { - console.error("Fatal:", err); - process.exit(1); -});