@elytracms/studio 0.0.86 → 0.0.87
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/convex/asset-revalidate.test.ts +186 -0
- package/convex/assets.ts +53 -19
- package/convex/cms.ts +22 -0
- package/convex/delivery.ts +33 -116
- package/convex/functions.ts +3 -3
- package/convex/rail-write-parity.test.ts +180 -0
- package/convex/redirects.ts +33 -11
- package/convex/revalidate.ts +7 -5
- package/convex/triggers.ts +53 -3
- package/dist/components/app-views/default-modules.d.ts +20 -20
- package/dist/components/app-views/default-modules.js +27 -48
- package/dist/components/app-views/default-modules.js.map +1 -1
- package/dist/components/app-views/studio-config.d.ts +5 -6
- package/dist/components/app-views/studio-config.js.map +1 -1
- package/dist/components/assets/asset-metadata.d.ts +28 -19
- package/dist/components/assets/asset-metadata.js +24 -31
- package/dist/components/assets/asset-metadata.js.map +1 -1
- package/dist/components/assets/asset-selection.d.ts +24 -5
- package/dist/components/assets/asset-selection.js +39 -9
- package/dist/components/assets/asset-selection.js.map +1 -1
- package/dist/components/assets/assets-collection-view-source.d.ts +17 -14
- package/dist/components/assets/assets-collection-view-source.js +25 -31
- package/dist/components/assets/assets-collection-view-source.js.map +1 -1
- package/dist/components/builder/blocks-panel.js +3 -3
- package/dist/components/builder/blocks-panel.js.map +1 -1
- package/dist/components/builder/builder-store.d.ts +25 -1
- package/dist/components/builder/builder-store.js +3 -2
- package/dist/components/builder/builder-store.js.map +1 -1
- package/dist/components/builder/canvas-chrome-css.js +0 -17
- package/dist/components/builder/canvas-chrome-css.js.map +1 -1
- package/dist/components/builder/canvas-chrome.d.ts +10 -12
- package/dist/components/builder/canvas-chrome.js +12 -13
- package/dist/components/builder/canvas-chrome.js.map +1 -1
- package/dist/components/builder/canvas-dnd.d.ts +8 -0
- package/dist/components/builder/canvas-dnd.js +5 -3
- package/dist/components/builder/canvas-dnd.js.map +1 -1
- package/dist/components/builder/canvas-render-context.d.ts +12 -24
- package/dist/components/builder/canvas-render-context.js +15 -44
- package/dist/components/builder/canvas-render-context.js.map +1 -1
- package/dist/components/builder/canvas.js +5 -11
- package/dist/components/builder/canvas.js.map +1 -1
- package/dist/components/builder/clipboard-actions.d.ts +14 -6
- package/dist/components/builder/clipboard-actions.js +29 -20
- package/dist/components/builder/clipboard-actions.js.map +1 -1
- package/dist/components/builder/composition-field-editor.d.ts +19 -26
- package/dist/components/builder/composition-field-editor.js +30 -52
- package/dist/components/builder/composition-field-editor.js.map +1 -1
- package/dist/components/builder/insert-context.d.ts +3 -1
- package/dist/components/builder/insert-context.js +15 -10
- package/dist/components/builder/insert-context.js.map +1 -1
- package/dist/components/builder/page-tree.d.ts +29 -0
- package/dist/components/builder/page-tree.js +56 -58
- package/dist/components/builder/page-tree.js.map +1 -1
- package/dist/components/builder/reuse.js +5 -2
- package/dist/components/builder/reuse.js.map +1 -1
- package/dist/components/cms/asset-field.js +20 -32
- package/dist/components/cms/asset-field.js.map +1 -1
- package/dist/components/cms/cms-composition-validators.js +11 -2
- package/dist/components/cms/cms-composition-validators.js.map +1 -1
- package/dist/components/cms/editable-cell.js +5 -2
- package/dist/components/cms/editable-cell.js.map +1 -1
- package/dist/components/cms/use-document-versions.js +1 -0
- package/dist/components/cms/use-document-versions.js.map +1 -1
- package/dist/components/cms/versions-model.d.ts +0 -12
- package/dist/components/cms/versions-model.js +3 -15
- package/dist/components/cms/versions-model.js.map +1 -1
- package/dist/components/components/component-detail.js +1 -1
- package/dist/components/components/component-detail.js.map +1 -1
- package/dist/components/components/transfer-dialog.js +2 -4
- package/dist/components/components/transfer-dialog.js.map +1 -1
- package/dist/components/components/transfer.d.ts +13 -10
- package/dist/components/components/transfer.js +21 -19
- package/dist/components/components/transfer.js.map +1 -1
- package/dist/components/project-session.d.ts +9 -0
- package/dist/components/project-session.js +1 -1
- package/dist/components/project-session.js.map +1 -1
- package/dist/components/redirects/redirects-collection-view-source.d.ts +17 -2
- package/dist/components/redirects/redirects-collection-view-source.js +20 -6
- package/dist/components/redirects/redirects-collection-view-source.js.map +1 -1
- package/dist/components/section-surface.js +3 -2
- package/dist/components/section-surface.js.map +1 -1
- package/dist/components/settings-form.js +1 -2
- package/dist/components/settings-form.js.map +1 -1
- package/dist/components/studio-context.js +1 -18
- package/dist/components/studio-context.js.map +1 -1
- package/dist/components/studio-project-screen.js +3 -5
- package/dist/components/studio-project-screen.js.map +1 -1
- package/dist/lib/ai/apply-content.js +73 -29
- package/dist/lib/ai/apply-content.js.map +1 -1
- package/dist/lib/ai/constraints.d.ts +35 -0
- package/dist/lib/ai/constraints.js +104 -4
- package/dist/lib/ai/constraints.js.map +1 -1
- package/dist/lib/ai/route.js +4 -1
- package/dist/lib/ai/route.js.map +1 -1
- package/dist/lib/ai/shape.d.ts +3 -2
- package/dist/lib/ai/shape.js +16 -24
- package/dist/lib/ai/shape.js.map +1 -1
- package/dist/lib/ai/types.d.ts +8 -0
- package/dist/lib/ai/types.js.map +1 -1
- package/dist/lib/ai/update-fields.js +33 -12
- package/dist/lib/ai/update-fields.js.map +1 -1
- package/dist/lib/assets/asset-placements.d.ts +35 -0
- package/dist/lib/assets/asset-placements.js +74 -0
- package/dist/lib/assets/asset-placements.js.map +1 -0
- package/dist/lib/assets/backfill-thumbs.d.ts +9 -8
- package/dist/lib/assets/backfill-thumbs.js +13 -25
- package/dist/lib/assets/backfill-thumbs.js.map +1 -1
- package/dist/lib/clipboard/paste-issues.d.ts +17 -15
- package/dist/lib/clipboard/paste-issues.js +8 -45
- package/dist/lib/clipboard/paste-issues.js.map +1 -1
- package/dist/lib/clipboard/paste-target.d.ts +25 -1
- package/dist/lib/clipboard/paste-target.js +13 -6
- package/dist/lib/clipboard/paste-target.js.map +1 -1
- package/dist/lib/cms/published-documents.js +1 -0
- package/dist/lib/cms/published-documents.js.map +1 -1
- package/dist/lib/cms-views/view-model.d.ts +3 -3
- package/dist/lib/data/index.d.ts +0 -3
- package/dist/lib/data/index.js +4 -6
- package/dist/lib/data/index.js.map +1 -1
- package/dist/lib/dnd/drop-rules.d.ts +45 -2
- package/dist/lib/dnd/drop-rules.js +64 -9
- package/dist/lib/dnd/drop-rules.js.map +1 -1
- package/dist/lib/engine-version.d.ts +1 -1
- package/dist/lib/engine-version.js +1 -1
- package/dist/lib/engine-version.js.map +1 -1
- package/dist/lib/i18n/messages.de.js +4 -56
- package/dist/lib/i18n/messages.de.js.map +1 -1
- package/dist/lib/i18n/messages.en.d.ts +4 -53
- package/dist/lib/i18n/messages.en.js +8 -57
- package/dist/lib/i18n/messages.en.js.map +1 -1
- package/dist/lib/locale/fallback.js +8 -2
- package/dist/lib/locale/fallback.js.map +1 -1
- package/dist/lib/locale/index.d.ts +0 -1
- package/dist/lib/locale/index.js +0 -1
- package/dist/lib/locale/index.js.map +1 -1
- package/dist/lib/locale/locale-store.d.ts +10 -3
- package/dist/lib/locale/locale-store.js +12 -5
- package/dist/lib/locale/locale-store.js.map +1 -1
- package/dist/lib/operations/session-hydration.d.ts +9 -5
- package/dist/lib/operations/session-hydration.js +10 -10
- package/dist/lib/operations/session-hydration.js.map +1 -1
- package/dist/lib/persistence/convex-adapter.js +63 -75
- package/dist/lib/persistence/convex-adapter.js.map +1 -1
- package/dist/lib/persona/labels.d.ts +0 -2
- package/dist/lib/persona/labels.js +1 -7
- package/dist/lib/persona/labels.js.map +1 -1
- package/dist/lib/registry/index.d.ts +4 -2
- package/dist/lib/registry/index.js +26 -21
- package/dist/lib/registry/index.js.map +1 -1
- package/dist/lib/registry/project-components.js +0 -3
- package/dist/lib/registry/project-components.js.map +1 -1
- package/dist/lib/routes/route-issues.js +4 -5
- package/dist/lib/routes/route-issues.js.map +1 -1
- package/dist/lib/theme.js +3 -2
- package/dist/lib/theme.js.map +1 -1
- package/dist/lib/webhooks/tags.js +11 -14
- package/dist/lib/webhooks/tags.js.map +1 -1
- package/dist/lib/workspace/index.d.ts +1 -1
- package/dist/lib/workspace/index.js +1 -1
- package/dist/lib/workspace/index.js.map +1 -1
- package/dist/previews/enumerate.d.ts +27 -9
- package/dist/previews/enumerate.js +27 -6
- package/dist/previews/enumerate.js.map +1 -1
- package/dist/previews/manifest-format.d.ts +9 -0
- package/dist/previews/manifest-format.js.map +1 -1
- package/dist/router/match.d.ts +0 -2
- package/dist/router/match.js +0 -2
- package/dist/router/match.js.map +1 -1
- package/dist/ui/badge.d.ts +1 -1
- package/package.json +2 -2
- package/src/styles/studio.css +5 -4
- package/src/styles/tokens.css +72 -55
- package/convex/content.ts +0 -291
- package/dist/components/collab/collab-context.d.ts +0 -27
- package/dist/components/collab/collab-context.js +0 -39
- package/dist/components/collab/collab-context.js.map +0 -1
- package/dist/components/collab/collab-seed.d.ts +0 -15
- package/dist/components/collab/collab-seed.js +0 -20
- package/dist/components/collab/collab-seed.js.map +0 -1
- package/dist/components/extensions/extensions-view.d.ts +0 -7
- package/dist/components/extensions/extensions-view.js +0 -127
- package/dist/components/extensions/extensions-view.js.map +0 -1
- package/dist/lib/bindings/section-bindings.d.ts +0 -24
- package/dist/lib/bindings/section-bindings.js +0 -9
- package/dist/lib/bindings/section-bindings.js.map +0 -1
- package/dist/lib/data/data-store.d.ts +0 -98
- package/dist/lib/data/data-store.js +0 -211
- package/dist/lib/data/data-store.js.map +0 -1
- package/dist/lib/data/providers.d.ts +0 -143
- package/dist/lib/data/providers.js +0 -255
- package/dist/lib/data/providers.js.map +0 -1
- package/dist/lib/data/sample-capture.d.ts +0 -30
- package/dist/lib/data/sample-capture.js +0 -70
- package/dist/lib/data/sample-capture.js.map +0 -1
- package/dist/lib/data/sources-store.d.ts +0 -42
- package/dist/lib/data/sources-store.js +0 -120
- package/dist/lib/data/sources-store.js.map +0 -1
- package/dist/lib/locale/binding-fallback.d.ts +0 -35
- package/dist/lib/locale/binding-fallback.js +0 -73
- package/dist/lib/locale/binding-fallback.js.map +0 -1
- package/dist/lib/starters/kit-session.d.ts +0 -5
- package/dist/lib/starters/kit-session.js +0 -17
- package/dist/lib/starters/kit-session.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"extensions-view.js","sourceRoot":"","sources":["../../../src/components/extensions/extensions-view.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useMemo, useReducer, useState } from 'react'\nimport {\n Boxes,\n Check,\n Database,\n Download,\n HardDrive,\n Lock,\n Package,\n Puzzle,\n Search,\n Share2,\n LayoutTemplate,\n Type,\n Webhook,\n} from 'lucide-react'\nimport {\n BUILTIN_FIELD_TYPES,\n BUILTIN_SOURCE_KINDS,\n HOOK_POINTS,\n MarketplaceClient,\n PluginHost,\n privateMarketplace,\n publicMarketplace,\n} from '@elytracms/core/plugins'\nimport type { ExtensionKind, ExtensionListing, InstalledPlugin, MarketplaceInstallResult } from '@elytracms/core/plugins'\nimport { Badge, Button, Code, Heading, Input, Row, Spacer, Stack, Text } from '@elytracms/studio/ui'\nimport { translate } from '@elytracms/studio/lib/i18n'\nimport { cn } from '@elytracms/studio/lib/utils'\n\ntype Tab = 'marketplace' | 'installed' | 'registered'\n\n/**\n * The Extensions surface (Phase 11, EC-130–137). A live, agent-inspectable view over the\n * extensibility layer: browse a public + private marketplace, install plugins into a host, and\n * inspect what each surface contributes (components, field types, data sources, asset storage,\n * export targets, hooks). All state is deterministic — driven by `@elytracms/core/plugins` fixtures.\n */\nexport function ExtensionsView() {\n // One host for the session; PluginHost mutates in place, so a bump reducer drives re-render.\n const [host] = useState(() => new PluginHost())\n const [, bump] = useReducer((n: number) => n + 1, 0)\n const [tab, setTab] = useState<Tab>('marketplace')\n const [token, setToken] = useState('')\n const [query, setQuery] = useState('')\n const [results, setResults] = useState<Record<string, MarketplaceInstallResult>>({})\n\n const client = useMemo(\n () => new MarketplaceClient([publicMarketplace, privateMarketplace], token.trim() ? { 'acme-private': token.trim() } : {}),\n [token],\n )\n\n const hits = client.search(query.trim() ? { query: query.trim() } : {})\n const privateUnlocked = client.accessibleRegistries().some((r) => r.id === 'acme-private')\n const installedCount = host.list().length\n\n function install(listing: ExtensionListing) {\n const result = client.install(host, listing.id)\n setResults((prev) => ({ ...prev, [listing.id]: result }))\n bump()\n }\n\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n <ExtensionsHeader\n tab={tab}\n onTab={setTab}\n installedCount={installedCount}\n marketCount={hits.length}\n />\n\n <div className=\"min-h-0 flex-1 overflow-auto px-4 py-5 sm:px-6\">\n <div className=\"mx-auto w-full max-w-5xl\">\n {tab === 'marketplace' ? (\n <MarketplaceTab\n hits={hits}\n query={query}\n onQuery={setQuery}\n token={token}\n onToken={setToken}\n privateUnlocked={privateUnlocked}\n isInstalled={(l) => host.isInstalled(l.plugin.id)}\n onInstall={install}\n results={results}\n />\n ) : tab === 'installed' ? (\n <InstalledTab installed={host.list()} />\n ) : (\n <RegisteredTab host={host} />\n )}\n </div>\n </div>\n </div>\n )\n}\n\n// --- Header + tabs ----------------------------------------------------------\n\nfunction ExtensionsHeader({\n tab,\n onTab,\n installedCount,\n marketCount,\n}: {\n tab: Tab\n onTab: (t: Tab) => void\n installedCount: number\n marketCount: number\n}) {\n const tabs: { id: Tab; label: string; count?: number }[] = [\n { id: 'marketplace', label: translate('extensions.tab.marketplace'), count: marketCount },\n { id: 'installed', label: translate('extensions.tab.installed'), count: installedCount },\n { id: 'registered', label: translate('extensions.tab.registered') },\n ]\n return (\n <div className=\"shrink-0 border-b border-border bg-gradient-to-b from-primary/[0.04] to-transparent px-4 py-3 sm:px-6\">\n <Row gap=\"3\">\n <span className=\"grid size-8 shrink-0 place-items-center rounded-lg bg-primary/15 text-primary\">\n <Puzzle className=\"size-4\" />\n </span>\n <Stack gap=\"none\" className=\"min-w-0\">\n <Text size=\"sm\" weight=\"semibold\">\n {translate('extensions.header.title')}\n </Text>\n <Text size=\"xs\" tone=\"subtle\">\n {translate('extensions.header.subtitle')}\n </Text>\n </Stack>\n <Spacer />\n <Row gap=\"1\" className=\"rounded-md bg-muted/50 p-0.5\">\n {tabs.map((t) => (\n <button\n key={t.id}\n type=\"button\"\n aria-pressed={tab === t.id}\n onClick={() => onTab(t.id)}\n className={cn(\n 'flex items-center gap-1.5 rounded-[5px] px-3 py-1 text-sm font-medium transition-colors',\n tab === t.id ? 'bg-background text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground',\n )}\n >\n {t.label}\n {t.count !== undefined ? (\n <span className=\"rounded-full bg-muted px-1.5 text-[0.7rem] font-semibold tabular-nums text-muted-foreground\">\n {t.count}\n </span>\n ) : null}\n </button>\n ))}\n </Row>\n </Row>\n </div>\n )\n}\n\n// --- Marketplace ------------------------------------------------------------\n\nfunction MarketplaceTab({\n hits,\n query,\n onQuery,\n token,\n onToken,\n privateUnlocked,\n isInstalled,\n onInstall,\n results,\n}: {\n hits: { registryId: string; listing: ExtensionListing }[]\n query: string\n onQuery: (q: string) => void\n token: string\n onToken: (t: string) => void\n privateUnlocked: boolean\n isInstalled: (l: ExtensionListing) => boolean\n onInstall: (l: ExtensionListing) => void\n results: Record<string, MarketplaceInstallResult>\n}) {\n return (\n <Stack gap=\"6\">\n <Row gap=\"3\" wrap>\n <div className=\"relative min-w-0 flex-1\">\n <Search className=\"pointer-events-none absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground\" />\n <Input\n value={query}\n onChange={(e) => onQuery(e.target.value)}\n placeholder={translate('extensions.search.placeholder')}\n className=\"pl-8\"\n aria-label={translate('extensions.search.aria')}\n />\n </div>\n <Row gap=\"2\" className=\"shrink-0\">\n <Lock className={cn('size-3.5', privateUnlocked ? 'text-success' : 'text-muted-foreground')} />\n <Input\n value={token}\n onChange={(e) => onToken(e.target.value)}\n placeholder={translate('extensions.token.placeholder')}\n aria-label={translate('extensions.token.placeholder')}\n className=\"w-52\"\n />\n {privateUnlocked ? <Badge variant=\"success\">{translate('extensions.token.unlocked')}</Badge> : null}\n </Row>\n </Row>\n\n {!privateUnlocked ? (\n <Text size=\"xs\" tone=\"subtle\">\n A private registry is available. Enter its access token (hint: <Code tone=\"muted\">acme-internal-token</Code>) to\n reveal private listings.\n </Text>\n ) : null}\n\n {hits.length === 0 ? (\n <EmptyHint\n icon={<Search className=\"size-5\" />}\n title={translate('extensions.empty.noMatch.title')}\n body={translate('extensions.empty.noMatch.body')}\n />\n ) : (\n <div className=\"grid gap-3 sm:grid-cols-2\">\n {hits.map(({ registryId, listing }) => (\n <ListingCard\n key={listing.id}\n listing={listing}\n registryId={registryId}\n installed={isInstalled(listing)}\n result={results[listing.id]}\n onInstall={() => onInstall(listing)}\n />\n ))}\n </div>\n )}\n </Stack>\n )\n}\n\nfunction ListingCard({\n listing,\n registryId,\n installed,\n result,\n onInstall,\n}: {\n listing: ExtensionListing\n registryId: string\n installed: boolean\n result: MarketplaceInstallResult | undefined\n onInstall: () => void\n}) {\n const failed = result && !result.ok\n return (\n <div className=\"flex flex-col rounded-xl border border-border bg-card/60 p-4 transition-colors hover:border-primary/40\">\n <Row gap=\"2\">\n <span className=\"grid size-9 shrink-0 place-items-center rounded-lg bg-muted text-foreground/80\">\n <KindIcon kind={listing.kind} />\n </span>\n <Stack gap=\"none\" className=\"min-w-0\">\n <Text size=\"sm\" weight=\"semibold\" className=\"truncate\">\n {listing.name}\n </Text>\n <Row gap=\"1\" className=\"text-muted-foreground\">\n <KindBadge kind={listing.kind} />\n <Code tone=\"muted\">v{listing.version}</Code>\n </Row>\n </Stack>\n <Spacer />\n {registryId === 'acme-private' ? (\n <Badge variant=\"outline\">\n <Lock className=\"size-3\" /> private\n </Badge>\n ) : null}\n </Row>\n\n <Text size=\"xs\" tone=\"muted\" className=\"mt-3 line-clamp-3 min-h-0 flex-1\">\n {listing.description ?? translate('extensions.listing.noDescription')}\n </Text>\n\n {listing.tags && listing.tags.length > 0 ? (\n <Row gap=\"1\" wrap className=\"mt-3\">\n {listing.tags.map((tag) => (\n <span key={tag} className=\"rounded-full bg-muted/70 px-2 py-0.5 text-[0.7rem] text-muted-foreground\">\n {tag}\n </span>\n ))}\n </Row>\n ) : null}\n\n <Row gap=\"2\" className=\"mt-4\">\n <Text size=\"xs\" tone=\"subtle\" className=\"truncate\">\n {listing.author ?? translate('extensions.listing.unknownAuthor')}\n </Text>\n <Spacer />\n {installed ? (\n <Button size=\"sm\" variant=\"ghost\" disabled>\n <Check /> {translate('extensions.action.installed')}\n </Button>\n ) : (\n <Button size=\"sm\" variant={failed ? 'destructive' : 'default'} onClick={onInstall}>\n <Download /> {failed ? translate('common.retry') : translate('extensions.action.install')}\n </Button>\n )}\n </Row>\n\n {failed ? (\n <Text size=\"xs\" className=\"mt-2 text-destructive\">\n {result?.blocked === 'access-denied'\n ? translate('extensions.error.accessDenied')\n : result?.issues[0]?.message ?? translate('extensions.error.installFailed')}\n </Text>\n ) : null}\n </div>\n )\n}\n\n// --- Installed --------------------------------------------------------------\n\nfunction InstalledTab({ installed }: { installed: InstalledPlugin[] }) {\n if (installed.length === 0) {\n return (\n <EmptyHint\n icon={<Boxes className=\"size-5\" />}\n title={translate('extensions.empty.installed.title')}\n body={translate('extensions.empty.installed.body')}\n />\n )\n }\n return (\n <Stack gap=\"3\">\n {installed.map((plugin) => (\n <div key={plugin.id} className=\"rounded-xl border border-border bg-card/60 p-4\">\n <Row gap=\"2\">\n <Package className=\"size-4 text-primary\" />\n <Text size=\"sm\" weight=\"semibold\">\n {plugin.name}\n </Text>\n <Code tone=\"muted\">v{plugin.version}</Code>\n <Spacer />\n <Text size=\"xs\" tone=\"subtle\">\n {plugin.author ?? ''}\n </Text>\n </Row>\n {plugin.description ? (\n <Text size=\"xs\" tone=\"muted\" className=\"mt-2\">\n {plugin.description}\n </Text>\n ) : null}\n <Row gap=\"2\" wrap className=\"mt-3\">\n <ContributionChip icon={<Boxes />} label={translate('extensions.contrib.components')} count={plugin.contributes.components} />\n <ContributionChip icon={<Type />} label={translate('extensions.contrib.fieldTypes')} count={plugin.contributes.fieldTypes} />\n <ContributionChip icon={<Database />} label={translate('extensions.contrib.dataSources')} count={plugin.contributes.dataSources} />\n <ContributionChip icon={<HardDrive />} label={translate('extensions.contrib.assetStorage')} count={plugin.contributes.assetStorage} />\n <ContributionChip icon={<Share2 />} label={translate('extensions.contrib.exportTargets')} count={plugin.contributes.exportTargets} />\n <ContributionChip icon={<LayoutTemplate />} label={translate('extensions.contrib.templates')} count={plugin.contributes.templates} />\n <ContributionChip icon={<Webhook />} label={translate('extensions.contrib.hooks')} count={plugin.contributes.hooks} />\n </Row>\n </div>\n ))}\n </Stack>\n )\n}\n\nfunction ContributionChip({ icon, label, count }: { icon: React.ReactNode; label: string; count: number }) {\n if (count === 0) return null\n return (\n <span className=\"inline-flex items-center gap-1.5 rounded-md border border-border/60 bg-muted/40 px-2 py-1 text-xs text-muted-foreground\">\n <span className=\"grid size-3.5 place-items-center text-primary [&_svg]:size-3.5\">{icon}</span>\n <span className=\"font-semibold tabular-nums text-foreground\">{count}</span>\n {label}\n </span>\n )\n}\n\n// --- Registered (inspect) ---------------------------------------------------\n\nfunction RegisteredTab({ host }: { host: PluginHost }) {\n const hookPoints = host.hooks.points()\n return (\n <Stack gap=\"6\">\n <Text size=\"xs\" tone=\"subtle\">\n {translate('extensions.registered.intro')}\n </Text>\n\n <InspectGroup icon={<Boxes />} title={translate('extensions.registered.components.title')} sub=\"base.* + project + vendor packages\">\n <ChipRow items={host.components.projectComponents().map((m) => m.id)} empty={translate('extensions.registered.components.empty')} />\n </InspectGroup>\n\n <InspectGroup icon={<Type />} title={translate('extensions.registered.fieldTypes.title')}>\n <ChipRow\n items={[...BUILTIN_FIELD_TYPES]}\n tone=\"builtin\"\n suffix={host.fieldTypes.list().map((f) => f.kind)}\n />\n </InspectGroup>\n\n <InspectGroup icon={<Database />} title={translate('extensions.registered.dataSources.title')}>\n <ChipRow items={[...BUILTIN_SOURCE_KINDS]} tone=\"builtin\" suffix={host.dataSources.list().map((a) => a.kind)} />\n </InspectGroup>\n\n <InspectGroup icon={<HardDrive />} title={translate('extensions.registered.assetStorage.title')}>\n <ChipRow items={host.assetStorage.list().map((a) => `${a.kind} · ${a.title}`)} empty={translate('extensions.registered.assetStorage.empty')} />\n </InspectGroup>\n\n <InspectGroup icon={<Share2 />} title={translate('extensions.registered.exportTargets.title')}>\n <ChipRow\n items={['next-app-router · reference']}\n tone=\"builtin\"\n suffix={host.exportTargets.list().map((t) => `${t.id} · ${t.title}`)}\n />\n </InspectGroup>\n\n <InspectGroup icon={<Webhook />} title={translate('extensions.registered.hookPoints.title')}>\n <ChipRow\n items={[...HOOK_POINTS]}\n tone=\"builtin\"\n suffix={hookPoints.flatMap((p) => host.hooks.list(p).map((t) => `${p}${t.plugin ? ` ← ${t.plugin}` : ''}`))}\n />\n </InspectGroup>\n </Stack>\n )\n}\n\nfunction InspectGroup({\n icon,\n title,\n sub,\n children,\n}: {\n icon: React.ReactNode\n title: string\n sub?: string\n children: React.ReactNode\n}) {\n return (\n <Stack gap=\"2\">\n <Row gap=\"2\">\n <span className=\"grid size-5 place-items-center text-primary [&_svg]:size-4\">{icon}</span>\n <Text size=\"sm\" weight=\"semibold\">\n {title}\n </Text>\n {sub ? (\n <Text size=\"xs\" tone=\"subtle\">\n {sub}\n </Text>\n ) : null}\n </Row>\n {children}\n </Stack>\n )\n}\n\nfunction ChipRow({\n items,\n suffix,\n tone,\n empty,\n}: {\n items: string[]\n suffix?: string[]\n tone?: 'builtin'\n empty?: string\n}) {\n const all = [...items.map((v) => ({ v, builtin: tone === 'builtin' })), ...(suffix ?? []).map((v) => ({ v, builtin: false }))]\n if (all.length === 0) {\n return (\n <Text size=\"xs\" tone=\"subtle\">\n {empty ?? translate('common.none')}\n </Text>\n )\n }\n return (\n <Row gap=\"1\" wrap>\n {all.map(({ v, builtin }) => (\n <span\n key={v}\n className={cn(\n 'rounded-md border px-2 py-0.5 font-mono text-xs',\n builtin\n ? 'border-border/60 bg-muted/40 text-muted-foreground'\n : 'border-primary/30 bg-primary/10 text-primary',\n )}\n >\n {v}\n </span>\n ))}\n </Row>\n )\n}\n\n// --- Shared bits -------------------------------------------------------------\n\nfunction EmptyHint({ icon, title, body }: { icon: React.ReactNode; title: string; body: string }) {\n return (\n <Stack gap=\"2\" align=\"center\" className=\"rounded-xl border border-dashed border-border/70 px-6 py-16 text-center\">\n <span className=\"grid size-10 place-items-center rounded-full bg-muted text-muted-foreground\">{icon}</span>\n <Heading level={3} size=\"h4\">\n {title}\n </Heading>\n <Text size=\"sm\" tone=\"muted\" className=\"max-w-sm\">\n {body}\n </Text>\n </Stack>\n )\n}\n\nconst KIND_LABEL_KEY: Record<ExtensionKind, string> = {\n plugin: 'extensions.kind.plugin',\n 'component-package': 'extensions.kind.componentPackage',\n 'field-type': 'extensions.kind.fieldType',\n 'data-source': 'extensions.kind.dataSource',\n 'asset-storage': 'extensions.kind.assetStorage',\n 'export-target': 'extensions.kind.exportTarget',\n template: 'extensions.kind.template',\n}\n\nfunction KindBadge({ kind }: { kind: ExtensionKind }) {\n const variant =\n kind === 'plugin'\n ? 'primary'\n : kind === 'field-type'\n ? 'success'\n : kind === 'data-source'\n ? 'warning'\n : kind === 'template'\n ? 'info'\n : 'outline'\n return <Badge variant={variant}>{translate(KIND_LABEL_KEY[kind])}</Badge>\n}\n\nfunction KindIcon({ kind }: { kind: ExtensionKind }) {\n const className = 'size-4'\n switch (kind) {\n case 'plugin':\n return <Puzzle className={className} />\n case 'component-package':\n return <Boxes className={className} />\n case 'field-type':\n return <Type className={className} />\n case 'data-source':\n return <Database className={className} />\n case 'asset-storage':\n return <HardDrive className={className} />\n case 'export-target':\n return <Share2 className={className} />\n case 'template':\n return <LayoutTemplate className={className} />\n default:\n return <Package className={className} />\n }\n}\n"]}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import type { CmsSource } from '@elytracms/core/data-binding';
|
|
2
|
-
import type { ListDocumentsQuery } from '@elytracms/core/content';
|
|
3
|
-
/**
|
|
4
|
-
* Stored repeating-section / template-page query config (EC-166), reduced to
|
|
5
|
-
* what survives the EC-190 v1 realignment.
|
|
6
|
-
*
|
|
7
|
-
* The editor surfaces that AUTHORED these queries — the repeating-section and
|
|
8
|
-
* template-page binding panels — are gone (the v1 canvas edits static props
|
|
9
|
-
* only). What remains is the read-only side the canvas preview and the
|
|
10
|
-
* locale-fallback marker still need: replaying a STORED query config as the
|
|
11
|
-
* exact delivery `listDocuments` query, so a parked section/template source
|
|
12
|
-
* previews through the same `@elytracms/core/content` resolution delivery runs. The
|
|
13
|
-
* query-building, picker-vocabulary, and plain-language description helpers were
|
|
14
|
-
* removed with the panels.
|
|
15
|
-
*/
|
|
16
|
-
/**
|
|
17
|
-
* The CMS source config of a section/template source — exactly the canonical
|
|
18
|
-
* `@elytracms/core/data-binding` cms config: the AD-3 `where` shape is valid JSON and
|
|
19
|
-
* stores verbatim in `filter`; `sort` and `limit` are first-class
|
|
20
|
-
* `cmsConfigSchema` fields, so the full query round-trips Zod validation.
|
|
21
|
-
*/
|
|
22
|
-
export type QueryCmsConfig = CmsSource['config'];
|
|
23
|
-
/** The `listDocuments` query a stored source config replays (delivery parity). */
|
|
24
|
-
export declare function listQueryOfConfig(config: QueryCmsConfig): ListDocumentsQuery;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/** The `listDocuments` query a stored source config replays (delivery parity). */
|
|
2
|
-
export function listQueryOfConfig(config) {
|
|
3
|
-
return {
|
|
4
|
-
...(Object.keys(config.filter).length > 0 ? { where: config.filter } : {}),
|
|
5
|
-
...(config.sort !== undefined ? { sort: config.sort } : {}),
|
|
6
|
-
...(config.limit !== undefined ? { limit: config.limit } : {}),
|
|
7
|
-
};
|
|
8
|
-
}
|
|
9
|
-
//# sourceMappingURL=section-bindings.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"section-bindings.js","sourceRoot":"","sources":["../../../src/lib/bindings/section-bindings.ts"],"names":[],"mappings":"AAyBA,kFAAkF;AAClF,MAAM,UAAU,iBAAiB,CAAC,MAAsB;IACtD,OAAO;QACL,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,MAAoB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxF,GAAG,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3D,GAAG,CAAC,MAAM,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC/D,CAAA;AACH,CAAC","sourcesContent":["import type { CmsSource } from '@elytracms/core/data-binding'\nimport type { ListDocumentsQuery, WhereInput } from '@elytracms/core/content'\n\n/**\n * Stored repeating-section / template-page query config (EC-166), reduced to\n * what survives the EC-190 v1 realignment.\n *\n * The editor surfaces that AUTHORED these queries — the repeating-section and\n * template-page binding panels — are gone (the v1 canvas edits static props\n * only). What remains is the read-only side the canvas preview and the\n * locale-fallback marker still need: replaying a STORED query config as the\n * exact delivery `listDocuments` query, so a parked section/template source\n * previews through the same `@elytracms/core/content` resolution delivery runs. The\n * query-building, picker-vocabulary, and plain-language description helpers were\n * removed with the panels.\n */\n\n/**\n * The CMS source config of a section/template source — exactly the canonical\n * `@elytracms/core/data-binding` cms config: the AD-3 `where` shape is valid JSON and\n * stores verbatim in `filter`; `sort` and `limit` are first-class\n * `cmsConfigSchema` fields, so the full query round-trips Zod validation.\n */\nexport type QueryCmsConfig = CmsSource['config']\n\n/** The `listDocuments` query a stored source config replays (delivery parity). */\nexport function listQueryOfConfig(config: QueryCmsConfig): ListDocumentsQuery {\n return {\n ...(Object.keys(config.filter).length > 0 ? { where: config.filter as WhereInput } : {}),\n ...(config.sort !== undefined ? { sort: config.sort } : {}),\n ...(config.limit !== undefined ? { limit: config.limit } : {}),\n }\n}\n"]}
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
2
|
-
import { SourceRegistry } from '@elytracms/core/data-binding';
|
|
3
|
-
import type { BindingResolution, ConditionResolution, DataSource, InferredSchema, PayloadStore, RepeaterItemContext } from '@elytracms/core/data-binding';
|
|
4
|
-
import type { BindingReference, Condition, JsonValue } from '@elytracms/core/project-graph';
|
|
5
|
-
/**
|
|
6
|
-
* The project's live data layer (brief §4.6, §7.5, EC-167). Holds the source
|
|
7
|
-
* registry the Builder's Content tab binds through, plus the captured payloads
|
|
8
|
-
* that drive binding resolution. One uniform model across CMS queries, data
|
|
9
|
-
* providers, and the built-in REST/Convex kinds — resolution, sampling,
|
|
10
|
-
* inference and tokenization treat them all identically.
|
|
11
|
-
*
|
|
12
|
-
* There is no source-authoring UI (EC-167): sources exist because code declared
|
|
13
|
-
* them (registered data providers), the schema implied them (per-collection CMS
|
|
14
|
-
* queries), or an editor flow provisioned them (repeating sections, template
|
|
15
|
-
* pages).
|
|
16
|
-
*
|
|
17
|
-
* Persistence: when mounted with a `projectId`, the store hydrates the
|
|
18
|
-
* project's persisted source records (the `cms-data-sources` system collection,
|
|
19
|
-
* see `sources-store.ts`) over the deterministic playground seeds — persisted
|
|
20
|
-
* wins by id, but never over a source provisioned/removed in THIS session —
|
|
21
|
-
* and every provision/remove writes through `@elytracms/core/operations`. Without a
|
|
22
|
-
* `projectId` (tests, fixtures) the store is pure session state, exactly as
|
|
23
|
-
* before.
|
|
24
|
-
*/
|
|
25
|
-
export interface DataStore {
|
|
26
|
-
sources: DataSource[];
|
|
27
|
-
registry: SourceRegistry;
|
|
28
|
-
payloads: PayloadStore;
|
|
29
|
-
knownSourceIds: ReadonlySet<string>;
|
|
30
|
-
getSource: (id: string) => DataSource | undefined;
|
|
31
|
-
removeSource: (id: string) => void;
|
|
32
|
-
/**
|
|
33
|
-
* Create or replace a source with a known id + config and capture its sample
|
|
34
|
-
* immediately (EC-166/EC-167): repeating sections and template pages
|
|
35
|
-
* provision their per-scope CMS query / provider sources through this.
|
|
36
|
-
*/
|
|
37
|
-
provisionSource: (source: DataSource) => void;
|
|
38
|
-
/**
|
|
39
|
-
* The latest persistence failure in plain language, or `null`. Persistence
|
|
40
|
-
* is best-effort on top of the live session (the canvas keeps working on
|
|
41
|
-
* session state), but a failure is recorded here — visible, never silent.
|
|
42
|
-
*/
|
|
43
|
-
persistError: string | null;
|
|
44
|
-
/** The stable path tokens a source exposes from its inferred schema (EC-085). */
|
|
45
|
-
tokensOf: (id: string) => string[];
|
|
46
|
-
schemaOf: (id: string) => InferredSchema | undefined;
|
|
47
|
-
sampleOf: (id: string) => JsonValue | undefined;
|
|
48
|
-
/** Resolve a binding to a renderer-ready resolution (value/props/condition/issue). */
|
|
49
|
-
resolve: (ref: BindingReference, item?: RepeaterItemContext) => BindingResolution;
|
|
50
|
-
/** Resolve a binding to the concrete value the renderer injects (EC-086–089). */
|
|
51
|
-
resolveValue: (ref: BindingReference, item?: RepeaterItemContext) => JsonValue | undefined;
|
|
52
|
-
/** Evaluate a condition against the captured payloads (EC-088). */
|
|
53
|
-
resolveCondition: (condition: Condition, item?: RepeaterItemContext) => ConditionResolution;
|
|
54
|
-
}
|
|
55
|
-
export interface DataState {
|
|
56
|
-
sources: DataSource[];
|
|
57
|
-
/**
|
|
58
|
-
* Ids provisioned or removed in THIS session. Hydration (which resolves
|
|
59
|
-
* asynchronously) never overrides them — the editor's latest action wins
|
|
60
|
-
* over whatever was persisted before it.
|
|
61
|
-
*/
|
|
62
|
-
sessionIds: ReadonlySet<string>;
|
|
63
|
-
}
|
|
64
|
-
export type DataAction = {
|
|
65
|
-
type: 'remove';
|
|
66
|
-
id: string;
|
|
67
|
-
} | {
|
|
68
|
-
type: 'provision';
|
|
69
|
-
source: DataSource;
|
|
70
|
-
}
|
|
71
|
-
/** Merge the project's persisted source records in (persisted wins over seeds). */
|
|
72
|
-
| {
|
|
73
|
-
type: 'hydrate';
|
|
74
|
-
sources: DataSource[];
|
|
75
|
-
};
|
|
76
|
-
/**
|
|
77
|
-
* The store's reducer, exported because hydration/session-precedence semantics
|
|
78
|
-
* live here and the app's test harness has no DOM to drive effects through.
|
|
79
|
-
*/
|
|
80
|
-
export declare function dataStateReducer(state: DataState, action: DataAction): DataState;
|
|
81
|
-
declare const useData: () => DataStore;
|
|
82
|
-
/**
|
|
83
|
-
* The session's starting state: EMPTY. The studio seeds no sample sources (Oli,
|
|
84
|
-
* 2026-06-19) — real sources arrive from the project's config collections (the
|
|
85
|
-
* hydrate effect, Convex mode) or are added by the author. Nothing is faked.
|
|
86
|
-
*/
|
|
87
|
-
export declare function initialDataState(): DataState;
|
|
88
|
-
export interface DataProviderProps {
|
|
89
|
-
children: ReactNode;
|
|
90
|
-
/**
|
|
91
|
-
* When set, the store hydrates from and persists to this project's
|
|
92
|
-
* `cms-data-sources` system collection (through `@elytracms/core/operations`).
|
|
93
|
-
* Without it the store is pure session state (tests, fixtures).
|
|
94
|
-
*/
|
|
95
|
-
projectId?: string;
|
|
96
|
-
}
|
|
97
|
-
export declare function DataProvider({ children, projectId }: DataProviderProps): import("react").JSX.Element;
|
|
98
|
-
export { useData };
|
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback, useEffect, useMemo, useReducer, useState } from 'react';
|
|
3
|
-
import { SourceRegistry, captureSample, inferSchema, resolveBinding, resolveCondition, tokensForSchema, } from '@elytracms/core/data-binding';
|
|
4
|
-
import { getStudioOperations } from '../operations/index.js';
|
|
5
|
-
import { useOperationCache, useOperationQuery } from '@elytracms/studio/lib/query';
|
|
6
|
-
import { createRequiredContext } from '@elytracms/studio/lib/required-context';
|
|
7
|
-
import { STUDIO_SYSTEM_COLLECTION_IDS } from '../operations/session-hydration.js';
|
|
8
|
-
import { resolveDeploymentCollections } from '../workspace/index.js';
|
|
9
|
-
import { hasContentSession } from './collection-content.js';
|
|
10
|
-
import { captureSourceSample, cmsSourceForCollection } from './sample-capture.js';
|
|
11
|
-
import { deleteDataSource, loadDataSources, saveDataSource } from './sources-store.js';
|
|
12
|
-
function upsert(sources, source) {
|
|
13
|
-
const exists = sources.some((s) => s.id === source.id);
|
|
14
|
-
return exists ? sources.map((s) => (s.id === source.id ? source : s)) : [...sources, source];
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* A persisted record hydrates as-is when it carries its captured sample;
|
|
18
|
-
* otherwise recapture. Exception (EC-177 gap 1): with a hydrated content
|
|
19
|
-
* session configured (Convex mode), CMS sources ALWAYS recapture by replaying
|
|
20
|
-
* their stored query over the live documents — a sample captured by an earlier
|
|
21
|
-
* session may carry stale (or fixture-derived) entries.
|
|
22
|
-
*/
|
|
23
|
-
function withSample(source) {
|
|
24
|
-
if (source.kind === 'cms' && hasContentSession()) {
|
|
25
|
-
const sample = captureSourceSample(source);
|
|
26
|
-
return sample !== undefined ? captureSample(source, sample) : source;
|
|
27
|
-
}
|
|
28
|
-
if (source.sample !== undefined)
|
|
29
|
-
return source;
|
|
30
|
-
// No persisted sample: try an honest capture (a provider runs; anything the
|
|
31
|
-
// studio can't fetch returns undefined) — never fabricate.
|
|
32
|
-
const sample = captureSourceSample(source);
|
|
33
|
-
return sample !== undefined ? captureSample(source, sample) : source;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* The store's reducer, exported because hydration/session-precedence semantics
|
|
37
|
-
* live here and the app's test harness has no DOM to drive effects through.
|
|
38
|
-
*/
|
|
39
|
-
export function dataStateReducer(state, action) {
|
|
40
|
-
switch (action.type) {
|
|
41
|
-
case 'remove':
|
|
42
|
-
return {
|
|
43
|
-
...state,
|
|
44
|
-
sources: state.sources.filter((s) => s.id !== action.id),
|
|
45
|
-
sessionIds: new Set([...state.sessionIds, action.id]),
|
|
46
|
-
};
|
|
47
|
-
case 'provision': {
|
|
48
|
-
// Upsert by id; attach a sample only if one can be captured honestly (a
|
|
49
|
-
// provider run, or live CMS content) — otherwise the source carries none.
|
|
50
|
-
const sample = captureSourceSample(action.source);
|
|
51
|
-
const provisioned = sample !== undefined ? captureSample(action.source, sample) : action.source;
|
|
52
|
-
return {
|
|
53
|
-
...state,
|
|
54
|
-
sources: upsert(state.sources, provisioned),
|
|
55
|
-
sessionIds: new Set([...state.sessionIds, provisioned.id]),
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
case 'hydrate': {
|
|
59
|
-
let sources = state.sources;
|
|
60
|
-
for (const source of action.sources) {
|
|
61
|
-
if (state.sessionIds.has(source.id))
|
|
62
|
-
continue; // this session already decided
|
|
63
|
-
sources = upsert(sources, withSample(source));
|
|
64
|
-
}
|
|
65
|
-
return sources === state.sources ? state : { ...state, sources };
|
|
66
|
-
}
|
|
67
|
-
default:
|
|
68
|
-
return state;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
const { Context: DataContext, useRequired: useData } = createRequiredContext('Data');
|
|
72
|
-
/**
|
|
73
|
-
* The session's starting state: EMPTY. The studio seeds no sample sources (Oli,
|
|
74
|
-
* 2026-06-19) — real sources arrive from the project's config collections (the
|
|
75
|
-
* hydrate effect, Convex mode) or are added by the author. Nothing is faked.
|
|
76
|
-
*/
|
|
77
|
-
export function initialDataState() {
|
|
78
|
-
return { sources: [], sessionIds: new Set() };
|
|
79
|
-
}
|
|
80
|
-
export function DataProvider({ children, projectId }) {
|
|
81
|
-
const [state, dispatch] = useReducer(dataStateReducer, undefined, initialDataState);
|
|
82
|
-
const [persistError, setPersistError] = useState(null);
|
|
83
|
-
// EC-192: surface every config-driven content collection as a pickable CMS
|
|
84
|
-
// source, so the binding/condition pickers list what actually exists — the
|
|
85
|
-
// same collection set the CMS uses (`resolveDeploymentCollections`) — rather
|
|
86
|
-
// than only the demo fixture sources. Merged additively (the `hydrate` upsert
|
|
87
|
-
// skips session-decided ids and recaptures live samples in Convex mode); studio
|
|
88
|
-
// SYSTEM collections (routes/redirects/saved views/data sources) are excluded.
|
|
89
|
-
useEffect(() => {
|
|
90
|
-
if (projectId === undefined)
|
|
91
|
-
return;
|
|
92
|
-
const collections = resolveDeploymentCollections().filter((collection) => !STUDIO_SYSTEM_COLLECTION_IDS.has(collection.id));
|
|
93
|
-
if (collections.length === 0)
|
|
94
|
-
return;
|
|
95
|
-
dispatch({ type: 'hydrate', sources: collections.map(cmsSourceForCollection) });
|
|
96
|
-
}, [projectId]);
|
|
97
|
-
// Hydrate the project's persisted sources through the one operations-backed
|
|
98
|
-
// query cache (EC-308/AD-17). Sources provisioned by other sessions on the
|
|
99
|
-
// same project show up here; the playground seeds stay for everything not
|
|
100
|
-
// persisted. The reducer's `hydrate` keeps session precedence — a source
|
|
101
|
-
// provisioned/removed in THIS session always wins over the hydrated list.
|
|
102
|
-
const cache = useOperationCache();
|
|
103
|
-
const sourcesQuery = useOperationQuery({
|
|
104
|
-
queryKey: ['dataSources', projectId ?? '∅'],
|
|
105
|
-
loader: async (operations) => {
|
|
106
|
-
const result = await loadDataSources(operations, projectId);
|
|
107
|
-
if (!result.ok)
|
|
108
|
-
throw new Error(result.error.message);
|
|
109
|
-
return result.value;
|
|
110
|
-
},
|
|
111
|
-
enabled: projectId !== undefined,
|
|
112
|
-
});
|
|
113
|
-
const hydratedSources = sourcesQuery.data;
|
|
114
|
-
useEffect(() => {
|
|
115
|
-
if (hydratedSources)
|
|
116
|
-
dispatch({ type: 'hydrate', sources: hydratedSources });
|
|
117
|
-
}, [hydratedSources]);
|
|
118
|
-
const sourcesError = sourcesQuery.isError ? sourcesQuery.error : null;
|
|
119
|
-
useEffect(() => {
|
|
120
|
-
if (sourcesError)
|
|
121
|
-
setPersistError(sourcesError instanceof Error ? sourcesError.message : 'Loading data sources failed.');
|
|
122
|
-
}, [sourcesError]);
|
|
123
|
-
// Best-effort persistence on top of the live session: the canvas keeps
|
|
124
|
-
// working on session state; a failed write surfaces via `persistError`. On a
|
|
125
|
-
// confirmed write, invalidate the hydration query so a later remount
|
|
126
|
-
// re-hydrates the provisioned/removed source rather than a stale list.
|
|
127
|
-
const persist = useCallback((write) => {
|
|
128
|
-
if (projectId === undefined)
|
|
129
|
-
return;
|
|
130
|
-
void getStudioOperations()
|
|
131
|
-
.then(({ operations }) => write(operations, projectId))
|
|
132
|
-
.then((result) => {
|
|
133
|
-
if (!result.ok) {
|
|
134
|
-
setPersistError(result.error.message);
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
void cache.invalidate(['dataSources', projectId]);
|
|
138
|
-
})
|
|
139
|
-
.catch((error) => {
|
|
140
|
-
setPersistError(error instanceof Error ? error.message : 'Saving the data source failed.');
|
|
141
|
-
});
|
|
142
|
-
}, [projectId, cache]);
|
|
143
|
-
const store = useMemo(() => {
|
|
144
|
-
const registry = SourceRegistry.from(state.sources);
|
|
145
|
-
const payloads = {};
|
|
146
|
-
for (const source of state.sources) {
|
|
147
|
-
if (source.sample !== undefined)
|
|
148
|
-
payloads[source.id] = source.sample;
|
|
149
|
-
}
|
|
150
|
-
const knownSourceIds = registry.knownSourceIds();
|
|
151
|
-
const ctx = { payloads, registry };
|
|
152
|
-
const getSource = (id) => registry.get(id);
|
|
153
|
-
const resolve = (ref, item) => resolveBinding(ref, ctx, item);
|
|
154
|
-
return {
|
|
155
|
-
sources: state.sources,
|
|
156
|
-
registry,
|
|
157
|
-
payloads,
|
|
158
|
-
knownSourceIds,
|
|
159
|
-
getSource,
|
|
160
|
-
removeSource: (id) => {
|
|
161
|
-
dispatch({ type: 'remove', id });
|
|
162
|
-
persist((operations, pid) => deleteDataSource(operations, pid, id));
|
|
163
|
-
},
|
|
164
|
-
provisionSource: (source) => {
|
|
165
|
-
dispatch({ type: 'provision', source });
|
|
166
|
-
// Persist exactly what the session resolves: the source plus any sample
|
|
167
|
-
// that can be captured honestly (a provider run / live CMS content) —
|
|
168
|
-
// never a fabricated one. Matches the `provision` reducer.
|
|
169
|
-
const sample = captureSourceSample(source);
|
|
170
|
-
const provisioned = sample !== undefined ? captureSample(source, sample) : source;
|
|
171
|
-
persist((operations, pid) => saveDataSource(operations, pid, provisioned));
|
|
172
|
-
},
|
|
173
|
-
persistError,
|
|
174
|
-
tokensOf: (id) => {
|
|
175
|
-
const schema = getSource(id)?.schema;
|
|
176
|
-
return schema ? tokensForSchema(schema) : [];
|
|
177
|
-
},
|
|
178
|
-
schemaOf: (id) => {
|
|
179
|
-
const source = getSource(id);
|
|
180
|
-
if (source?.schema)
|
|
181
|
-
return source.schema;
|
|
182
|
-
if (source?.sample !== undefined)
|
|
183
|
-
return inferSchema(source.sample);
|
|
184
|
-
return undefined;
|
|
185
|
-
},
|
|
186
|
-
sampleOf: (id) => getSource(id)?.sample,
|
|
187
|
-
resolve,
|
|
188
|
-
resolveValue: (ref, item) => {
|
|
189
|
-
const r = resolve(ref, item);
|
|
190
|
-
switch (r.kind) {
|
|
191
|
-
case 'value':
|
|
192
|
-
return r.value;
|
|
193
|
-
case 'props':
|
|
194
|
-
return r.props;
|
|
195
|
-
case 'condition':
|
|
196
|
-
return r.pass;
|
|
197
|
-
case 'issue':
|
|
198
|
-
return undefined;
|
|
199
|
-
default: {
|
|
200
|
-
const never = r;
|
|
201
|
-
return never;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
},
|
|
205
|
-
resolveCondition: (condition, item) => resolveCondition(condition, ctx, item),
|
|
206
|
-
};
|
|
207
|
-
}, [state, persist, persistError]);
|
|
208
|
-
return _jsx(DataContext.Provider, { value: store, children: children });
|
|
209
|
-
}
|
|
210
|
-
export { useData };
|
|
211
|
-
//# sourceMappingURL=data-store.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"data-store.js","sourceRoot":"","sources":["../../../src/lib/data/data-store.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useEffect, useMemo, useReducer, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport {\n SourceRegistry,\n captureSample,\n inferSchema,\n resolveBinding,\n resolveCondition,\n tokensForSchema,\n} from '@elytracms/core/data-binding'\nimport type {\n BindingResolution,\n ConditionResolution,\n DataSource,\n InferredSchema,\n PayloadStore,\n RepeaterItemContext,\n} from '@elytracms/core/data-binding'\nimport type { BindingReference, Condition, JsonValue } from '@elytracms/core/project-graph'\nimport { getStudioOperations } from '../operations'\nimport type { OperationResult, OperationsClient } from '../operations'\nimport { useOperationCache, useOperationQuery } from '@elytracms/studio/lib/query'\nimport { createRequiredContext } from '@elytracms/studio/lib/required-context'\nimport { STUDIO_SYSTEM_COLLECTION_IDS } from '../operations/session-hydration'\nimport { resolveDeploymentCollections } from '../workspace'\nimport { hasContentSession } from './collection-content'\nimport { captureSourceSample, cmsSourceForCollection } from './sample-capture'\nimport { deleteDataSource, loadDataSources, saveDataSource } from './sources-store'\n\n/**\n * The project's live data layer (brief §4.6, §7.5, EC-167). Holds the source\n * registry the Builder's Content tab binds through, plus the captured payloads\n * that drive binding resolution. One uniform model across CMS queries, data\n * providers, and the built-in REST/Convex kinds — resolution, sampling,\n * inference and tokenization treat them all identically.\n *\n * There is no source-authoring UI (EC-167): sources exist because code declared\n * them (registered data providers), the schema implied them (per-collection CMS\n * queries), or an editor flow provisioned them (repeating sections, template\n * pages).\n *\n * Persistence: when mounted with a `projectId`, the store hydrates the\n * project's persisted source records (the `cms-data-sources` system collection,\n * see `sources-store.ts`) over the deterministic playground seeds — persisted\n * wins by id, but never over a source provisioned/removed in THIS session —\n * and every provision/remove writes through `@elytracms/core/operations`. Without a\n * `projectId` (tests, fixtures) the store is pure session state, exactly as\n * before.\n */\nexport interface DataStore {\n sources: DataSource[]\n registry: SourceRegistry\n payloads: PayloadStore\n knownSourceIds: ReadonlySet<string>\n\n getSource: (id: string) => DataSource | undefined\n removeSource: (id: string) => void\n /**\n * Create or replace a source with a known id + config and capture its sample\n * immediately (EC-166/EC-167): repeating sections and template pages\n * provision their per-scope CMS query / provider sources through this.\n */\n provisionSource: (source: DataSource) => void\n\n /**\n * The latest persistence failure in plain language, or `null`. Persistence\n * is best-effort on top of the live session (the canvas keeps working on\n * session state), but a failure is recorded here — visible, never silent.\n */\n persistError: string | null\n\n /** The stable path tokens a source exposes from its inferred schema (EC-085). */\n tokensOf: (id: string) => string[]\n schemaOf: (id: string) => InferredSchema | undefined\n sampleOf: (id: string) => JsonValue | undefined\n\n /** Resolve a binding to a renderer-ready resolution (value/props/condition/issue). */\n resolve: (ref: BindingReference, item?: RepeaterItemContext) => BindingResolution\n /** Resolve a binding to the concrete value the renderer injects (EC-086–089). */\n resolveValue: (ref: BindingReference, item?: RepeaterItemContext) => JsonValue | undefined\n /** Evaluate a condition against the captured payloads (EC-088). */\n resolveCondition: (condition: Condition, item?: RepeaterItemContext) => ConditionResolution\n}\n\nexport interface DataState {\n sources: DataSource[]\n /**\n * Ids provisioned or removed in THIS session. Hydration (which resolves\n * asynchronously) never overrides them — the editor's latest action wins\n * over whatever was persisted before it.\n */\n sessionIds: ReadonlySet<string>\n}\n\nexport type DataAction =\n | { type: 'remove'; id: string }\n | { type: 'provision'; source: DataSource }\n /** Merge the project's persisted source records in (persisted wins over seeds). */\n | { type: 'hydrate'; sources: DataSource[] }\n\nfunction upsert(sources: DataSource[], source: DataSource): DataSource[] {\n const exists = sources.some((s) => s.id === source.id)\n return exists ? sources.map((s) => (s.id === source.id ? source : s)) : [...sources, source]\n}\n\n/**\n * A persisted record hydrates as-is when it carries its captured sample;\n * otherwise recapture. Exception (EC-177 gap 1): with a hydrated content\n * session configured (Convex mode), CMS sources ALWAYS recapture by replaying\n * their stored query over the live documents — a sample captured by an earlier\n * session may carry stale (or fixture-derived) entries.\n */\nfunction withSample(source: DataSource): DataSource {\n if (source.kind === 'cms' && hasContentSession()) {\n const sample = captureSourceSample(source)\n return sample !== undefined ? captureSample(source, sample) : source\n }\n if (source.sample !== undefined) return source\n // No persisted sample: try an honest capture (a provider runs; anything the\n // studio can't fetch returns undefined) — never fabricate.\n const sample = captureSourceSample(source)\n return sample !== undefined ? captureSample(source, sample) : source\n}\n\n/**\n * The store's reducer, exported because hydration/session-precedence semantics\n * live here and the app's test harness has no DOM to drive effects through.\n */\nexport function dataStateReducer(state: DataState, action: DataAction): DataState {\n switch (action.type) {\n case 'remove':\n return {\n ...state,\n sources: state.sources.filter((s) => s.id !== action.id),\n sessionIds: new Set([...state.sessionIds, action.id]),\n }\n case 'provision': {\n // Upsert by id; attach a sample only if one can be captured honestly (a\n // provider run, or live CMS content) — otherwise the source carries none.\n const sample = captureSourceSample(action.source)\n const provisioned = sample !== undefined ? captureSample(action.source, sample) : action.source\n return {\n ...state,\n sources: upsert(state.sources, provisioned),\n sessionIds: new Set([...state.sessionIds, provisioned.id]),\n }\n }\n case 'hydrate': {\n let sources = state.sources\n for (const source of action.sources) {\n if (state.sessionIds.has(source.id)) continue // this session already decided\n sources = upsert(sources, withSample(source))\n }\n return sources === state.sources ? state : { ...state, sources }\n }\n default:\n return state\n }\n}\n\nconst { Context: DataContext, useRequired: useData } = createRequiredContext<DataStore>('Data')\n\n/**\n * The session's starting state: EMPTY. The studio seeds no sample sources (Oli,\n * 2026-06-19) — real sources arrive from the project's config collections (the\n * hydrate effect, Convex mode) or are added by the author. Nothing is faked.\n */\nexport function initialDataState(): DataState {\n return { sources: [], sessionIds: new Set() }\n}\n\nexport interface DataProviderProps {\n children: ReactNode\n /**\n * When set, the store hydrates from and persists to this project's\n * `cms-data-sources` system collection (through `@elytracms/core/operations`).\n * Without it the store is pure session state (tests, fixtures).\n */\n projectId?: string\n}\n\nexport function DataProvider({ children, projectId }: DataProviderProps) {\n const [state, dispatch] = useReducer(dataStateReducer, undefined, initialDataState)\n const [persistError, setPersistError] = useState<string | null>(null)\n\n // EC-192: surface every config-driven content collection as a pickable CMS\n // source, so the binding/condition pickers list what actually exists — the\n // same collection set the CMS uses (`resolveDeploymentCollections`) — rather\n // than only the demo fixture sources. Merged additively (the `hydrate` upsert\n // skips session-decided ids and recaptures live samples in Convex mode); studio\n // SYSTEM collections (routes/redirects/saved views/data sources) are excluded.\n useEffect(() => {\n if (projectId === undefined) return\n const collections = resolveDeploymentCollections().filter(\n (collection) => !STUDIO_SYSTEM_COLLECTION_IDS.has(collection.id),\n )\n if (collections.length === 0) return\n dispatch({ type: 'hydrate', sources: collections.map(cmsSourceForCollection) })\n }, [projectId])\n\n // Hydrate the project's persisted sources through the one operations-backed\n // query cache (EC-308/AD-17). Sources provisioned by other sessions on the\n // same project show up here; the playground seeds stay for everything not\n // persisted. The reducer's `hydrate` keeps session precedence — a source\n // provisioned/removed in THIS session always wins over the hydrated list.\n const cache = useOperationCache()\n const sourcesQuery = useOperationQuery<DataSource[]>({\n queryKey: ['dataSources', projectId ?? '∅'],\n loader: async (operations) => {\n const result = await loadDataSources(operations, projectId as string)\n if (!result.ok) throw new Error(result.error.message)\n return result.value\n },\n enabled: projectId !== undefined,\n })\n const hydratedSources = sourcesQuery.data\n useEffect(() => {\n if (hydratedSources) dispatch({ type: 'hydrate', sources: hydratedSources })\n }, [hydratedSources])\n const sourcesError = sourcesQuery.isError ? sourcesQuery.error : null\n useEffect(() => {\n if (sourcesError)\n setPersistError(sourcesError instanceof Error ? sourcesError.message : 'Loading data sources failed.')\n }, [sourcesError])\n\n // Best-effort persistence on top of the live session: the canvas keeps\n // working on session state; a failed write surfaces via `persistError`. On a\n // confirmed write, invalidate the hydration query so a later remount\n // re-hydrates the provisioned/removed source rather than a stale list.\n const persist = useCallback(\n (write: (operations: OperationsClient, projectId: string) => Promise<OperationResult<void>>) => {\n if (projectId === undefined) return\n void getStudioOperations()\n .then(({ operations }) => write(operations, projectId))\n .then((result) => {\n if (!result.ok) {\n setPersistError(result.error.message)\n return\n }\n void cache.invalidate(['dataSources', projectId])\n })\n .catch((error: unknown) => {\n setPersistError(error instanceof Error ? error.message : 'Saving the data source failed.')\n })\n },\n [projectId, cache],\n )\n\n const store = useMemo<DataStore>(() => {\n const registry = SourceRegistry.from(state.sources)\n const payloads: Record<string, JsonValue> = {}\n for (const source of state.sources) {\n if (source.sample !== undefined) payloads[source.id] = source.sample\n }\n const knownSourceIds = registry.knownSourceIds()\n const ctx = { payloads, registry }\n\n const getSource = (id: string) => registry.get(id)\n const resolve = (ref: BindingReference, item?: RepeaterItemContext) =>\n resolveBinding(ref, ctx, item)\n\n return {\n sources: state.sources,\n registry,\n payloads,\n knownSourceIds,\n getSource,\n removeSource: (id) => {\n dispatch({ type: 'remove', id })\n persist((operations, pid) => deleteDataSource(operations, pid, id))\n },\n provisionSource: (source) => {\n dispatch({ type: 'provision', source })\n // Persist exactly what the session resolves: the source plus any sample\n // that can be captured honestly (a provider run / live CMS content) —\n // never a fabricated one. Matches the `provision` reducer.\n const sample = captureSourceSample(source)\n const provisioned = sample !== undefined ? captureSample(source, sample) : source\n persist((operations, pid) => saveDataSource(operations, pid, provisioned))\n },\n persistError,\n tokensOf: (id) => {\n const schema = getSource(id)?.schema\n return schema ? tokensForSchema(schema) : []\n },\n schemaOf: (id) => {\n const source = getSource(id)\n if (source?.schema) return source.schema\n if (source?.sample !== undefined) return inferSchema(source.sample)\n return undefined\n },\n sampleOf: (id) => getSource(id)?.sample,\n resolve,\n resolveValue: (ref, item) => {\n const r = resolve(ref, item)\n switch (r.kind) {\n case 'value':\n return r.value\n case 'props':\n return r.props\n case 'condition':\n return r.pass\n case 'issue':\n return undefined\n default: {\n const never: never = r\n return never\n }\n }\n },\n resolveCondition: (condition, item) => resolveCondition(condition, ctx, item),\n }\n }, [state, persist, persistError])\n\n return <DataContext.Provider value={store}>{children}</DataContext.Provider>\n}\n\nexport { useData }\n"]}
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import type { ConvexSource, DataSource } from '@elytracms/core/data-binding';
|
|
3
|
-
import type { JsonValue } from '@elytracms/core/project-graph';
|
|
4
|
-
/**
|
|
5
|
-
* Typed data providers (EC-167, vision AD-9). External data is a developer
|
|
6
|
-
* concern expressed exactly like a component: a provider is a plain function
|
|
7
|
-
* plus a manifest (id, title, description, output schema, optional params)
|
|
8
|
-
* registered in code. Editors never see providers as anything technical — the
|
|
9
|
-
* Content tab offers them next to CMS collections, labeled by their
|
|
10
|
-
* plain-language titles, and provider results resolve through the unchanged
|
|
11
|
-
* `@elytracms/core/data-binding` engine.
|
|
12
|
-
*
|
|
13
|
-
* Registration mirrors how component manifests register: project code defines
|
|
14
|
-
* providers and registers them in-process here. In a host repository the same
|
|
15
|
-
* definitions would be extracted into synced manifests (the EC-147 component
|
|
16
|
-
* manifest sync path) with the function itself executed behind the
|
|
17
|
-
* project-owned adapter — an honest gap today: this playground registry IS the
|
|
18
|
-
* project code, so "sync" is a direct import.
|
|
19
|
-
*
|
|
20
|
-
* Bridging into the engine: a provider is addressed as a `convex`-kind data
|
|
21
|
-
* source whose `functionRef` is `provider:<id>` — a provider is exactly a
|
|
22
|
-
* typed server function, and the engine's source vocabulary already models
|
|
23
|
-
* that. Resolution, sampling, inference, tokens, and broken-binding issues all
|
|
24
|
-
* apply unchanged. (See NOTES: the engine could gain a first-class `provider`
|
|
25
|
-
* source kind as a purely additive change.)
|
|
26
|
-
*/
|
|
27
|
-
/** A scalar an editor can put into a provider param control. */
|
|
28
|
-
export type ProviderParamValue = string | number | boolean;
|
|
29
|
-
/** One choice of a `choice`-kind param. */
|
|
30
|
-
export interface ProviderParamChoice {
|
|
31
|
-
value: string;
|
|
32
|
-
label: string;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* A provider param, surfaced to editors as one plain control (no syntax, no
|
|
36
|
-
* JSON): `choice` renders a select over {@link choices}; the scalar kinds
|
|
37
|
-
* render a matching input.
|
|
38
|
-
*/
|
|
39
|
-
export interface ProviderParamSpec {
|
|
40
|
-
name: string;
|
|
41
|
-
/** Plain-language control label, e.g. "Department". */
|
|
42
|
-
label: string;
|
|
43
|
-
kind: 'text' | 'number' | 'boolean' | 'choice';
|
|
44
|
-
/** For `choice` params: the closed set of offered values. */
|
|
45
|
-
choices?: ProviderParamChoice[];
|
|
46
|
-
defaultValue: ProviderParamValue;
|
|
47
|
-
}
|
|
48
|
-
/** Arguments a provider runs with (param name → value). */
|
|
49
|
-
export type ProviderArgs = Record<string, JsonValue>;
|
|
50
|
-
/** The manifest half of a provider — everything the builder surfaces. */
|
|
51
|
-
export interface DataProviderManifest {
|
|
52
|
-
/** Stable provider id, e.g. `pricing-plans`. */
|
|
53
|
-
id: string;
|
|
54
|
-
/** Plain-language title editors pick, e.g. "Pricing plans". */
|
|
55
|
-
title: string;
|
|
56
|
-
description: string;
|
|
57
|
-
/** Zod schema of the payload; every run is validated against it. */
|
|
58
|
-
output: z.ZodType<JsonValue>;
|
|
59
|
-
params?: ProviderParamSpec[];
|
|
60
|
-
}
|
|
61
|
-
/** A data provider: a typed function plus its manifest. */
|
|
62
|
-
export interface DataProvider {
|
|
63
|
-
manifest: DataProviderManifest;
|
|
64
|
-
/** Produce the payload. Deterministic here; a host repo may make this async behind its adapter. */
|
|
65
|
-
fetch: (args: ProviderArgs) => JsonValue;
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Define a provider with the output type checked against the schema — the
|
|
69
|
-
* provider-side mirror of `defineDataSourceAdapter` (EC-132) and component
|
|
70
|
-
* `ComponentManifest` definitions.
|
|
71
|
-
*/
|
|
72
|
-
export declare function defineDataProvider<T extends JsonValue>(provider: {
|
|
73
|
-
manifest: Omit<DataProviderManifest, 'output'> & {
|
|
74
|
-
output: z.ZodType<T>;
|
|
75
|
-
};
|
|
76
|
-
fetch: (args: ProviderArgs) => T;
|
|
77
|
-
}): DataProvider;
|
|
78
|
-
/** A structured registration issue — duplicates are reported, never thrown. */
|
|
79
|
-
export interface ProviderRegistrationIssue {
|
|
80
|
-
code: 'duplicate' | 'invalid-id';
|
|
81
|
-
message: string;
|
|
82
|
-
ref: string;
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Registry of data providers keyed by id. First registration wins; duplicates
|
|
86
|
-
* and malformed ids are recorded as structured issues (component-registry
|
|
87
|
-
* semantics).
|
|
88
|
-
*/
|
|
89
|
-
export declare class DataProviderRegistry {
|
|
90
|
-
private readonly byId;
|
|
91
|
-
readonly issues: ProviderRegistrationIssue[];
|
|
92
|
-
constructor(providers?: Iterable<DataProvider>);
|
|
93
|
-
register(provider: DataProvider): void;
|
|
94
|
-
get(id: string): DataProvider | undefined;
|
|
95
|
-
list(): DataProvider[];
|
|
96
|
-
get size(): number;
|
|
97
|
-
}
|
|
98
|
-
/** The outcome of one provider run: a validated payload or a plain-language issue. */
|
|
99
|
-
export type ProviderRun = {
|
|
100
|
-
ok: true;
|
|
101
|
-
value: JsonValue;
|
|
102
|
-
} | {
|
|
103
|
-
ok: false;
|
|
104
|
-
message: string;
|
|
105
|
-
};
|
|
106
|
-
/** Default args of a provider (its params' declared defaults). */
|
|
107
|
-
export declare function defaultProviderArgs(manifest: DataProviderManifest): ProviderArgs;
|
|
108
|
-
/**
|
|
109
|
-
* Run a provider and validate the result against its output schema. A thrown
|
|
110
|
-
* error or a schema mismatch comes back as a plain-language issue — the
|
|
111
|
-
* binding layer renders a visible fallback, never a crash.
|
|
112
|
-
*/
|
|
113
|
-
export declare function runProvider(provider: DataProvider, args?: ProviderArgs): ProviderRun;
|
|
114
|
-
/** Shared project-wide provider sources: `provider.<providerId>`. */
|
|
115
|
-
export declare const PROVIDER_SOURCE_PREFIX = "provider.";
|
|
116
|
-
export declare function providerSourceIdFor(providerId: string): string;
|
|
117
|
-
/** The provider a source is backed by, or undefined for non-provider sources. */
|
|
118
|
-
export declare function providerIdOfSource(source: DataSource | undefined): string | undefined;
|
|
119
|
-
/**
|
|
120
|
-
* The engine-shaped source addressing a provider. `args` carry the editor's
|
|
121
|
-
* param choices; `id` defaults to the shared project-wide source.
|
|
122
|
-
*/
|
|
123
|
-
export declare function providerSourceFor(provider: DataProvider, args?: ProviderArgs, id?: string, label?: string): ConvexSource;
|
|
124
|
-
/** Example provider: a static, code-owned pricing table (think Stripe prices). */
|
|
125
|
-
export declare const pricingPlansProvider: DataProvider;
|
|
126
|
-
/** Example provider with a param: job listings filterable by department. */
|
|
127
|
-
export declare const jobListingsProvider: DataProvider;
|
|
128
|
-
/**
|
|
129
|
-
* The project's provider registry. In a deployed studio this hydrates from
|
|
130
|
-
* synced provider manifests (the component-manifest sync path); in the
|
|
131
|
-
* playground the project code registers directly.
|
|
132
|
-
*/
|
|
133
|
-
export declare const projectDataProviders: DataProviderRegistry;
|
|
134
|
-
export declare function listDataProviders(): DataProvider[];
|
|
135
|
-
export declare function getDataProvider(id: string): DataProvider | undefined;
|
|
136
|
-
/**
|
|
137
|
-
* The payload a provider-backed source serves, or `null` when the provider is
|
|
138
|
-
* unregistered or failing — a `null` sample makes every binding against it a
|
|
139
|
-
* visible plain-language issue instead of a crash.
|
|
140
|
-
*/
|
|
141
|
-
export declare function providerPayload(providerId: string, args?: ProviderArgs): JsonValue;
|
|
142
|
-
/** A provider's canonical sample (its default-args run), or undefined when failing. */
|
|
143
|
-
export declare function providerSample(provider: DataProvider): JsonValue | undefined;
|