@emdash-cms/admin 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +9 -0
- package/dist/config-BHC21FmY.d.ts +34 -0
- package/dist/config-BHC21FmY.d.ts.map +1 -0
- package/dist/index.d.ts +44 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1538 -369
- package/dist/index.js.map +1 -1
- package/dist/locales/de/messages.mjs +1 -0
- package/dist/locales/en/messages.mjs +1 -0
- package/dist/locales/index.d.ts +2 -0
- package/dist/locales/index.js +3 -0
- package/dist/plugins-XhZqfegd.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/useLocale-CXsoFCFt.js +80 -0
- package/dist/useLocale-CXsoFCFt.js.map +1 -0
- package/package.json +19 -5
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/*eslint-disable*/export const messages=JSON.parse("{\"+ET/av\":[\"Verwenden Sie Ihren registrierten Passkey, um sich sicher anzumelden.\"],\"+Ni3Gv\":[\"Magic Link senden\"],\"/JPN+P\":[\"E-Mail-Anbieter-Status anzeigen und Test-E-Mails senden\"],\"352VU2\":[\"Noch kein Konto? <0>Registrieren</0>\"],\"4Ml90q\":[\"SEO\"],\"8NbHF7\":[\"Sprache\"],\"ATGYL1\":[\"E-Mail-Adresse\"],\"Cw9Xfg\":[\"Der Link ist 15 Minuten gültig.\"],\"DsZc8w\":[\"Benutzern von bestimmten Domains die Registrierung erlauben\"],\"FozKV6\":[\" (Standard)\"],\"HvU4EW\":[\"Falls ein Konto für <0>\",[\"email\"],\"</0> existiert, haben wir einen Anmeldelink gesendet.\"],\"IoAuJG\":[\"Wird gesendet...\"],\"JjOi48\":[\"Alle Sprachen\"],\"O3oNi5\":[\"E-Mail\"],\"OfnTKV\":[\"Passkeys und Authentifizierung verwalten\"],\"QjsOMP\":[\"Mit Passkey anmelden\"],\"RR0ADZ\":[\"Website-Identität, Logo, Favicon und Leseeinstellungen\"],\"RxerEl\":[\"Mit E-Mail-Link anmelden\"],\"Tllxyd\":[\"Selbstregistrierungs-Domains\"],\"Tz0i8g\":[\"Einstellungen\"],\"VCoEm+\":[\"Zurück zur Anmeldung\"],\"Weq9zb\":[\"Allgemein\"],\"Xeb2Gt\":[\"Authentifizierungsfehler: \",[\"error\"]],\"Y8S9QC\":[\"Wählen Sie Ihre bevorzugte Admin-Sprache\"],\"ZiooJI\":[\"API-Tokens\"],\"a3LDKx\":[\"Sicherheit\"],\"d0rUsW\":[\"Soziale Netzwerke\"],\"dhH+RW\":[\"Persönliche Zugangstokens für programmatischen API-Zugriff erstellen\"],\"dsPiA2\":[\"Magic Link konnte nicht gesendet werden\"],\"lE0wHD\":[\"Bei Ihrer Website anmelden\"],\"me9L29\":[\"Mit E-Mail anmelden\"],\"pv+wH3\":[\"Wir senden Ihnen einen Link, um sich ohne Passwort anzumelden.\"],\"qS3mgX\":[\"Links zu Social-Media-Profilen\"],\"t0m/8s\":[[\"label\"],\" — Übersetzung anzeigen\"],\"tfQcxX\":[\"Klicken Sie auf den Link in der E-Mail, um sich anzumelden.\"],\"v4fiSg\":[\"Überprüfen Sie Ihre E-Mail\"],\"vXIe7J\":[\"Sprache\"],\"zW+FpA\":[\"Oder fortfahren mit\"],\"zY0S+v\":[\"Suchmaschinenoptimierung und Verifizierung\"],\"zzGK7U\":[[\"label\"],\" — keine Übersetzung\"]}");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/*eslint-disable*/export const messages=JSON.parse("{\"+ET/av\":[\"Use your registered passkey to sign in securely.\"],\"+Ni3Gv\":[\"Send magic link\"],\"/JPN+P\":[\"View email provider status and send test emails\"],\"352VU2\":[\"Don't have an account? <0>Sign up</0>\"],\"4Ml90q\":[\"SEO\"],\"8NbHF7\":[\"Locale\"],\"ATGYL1\":[\"Email address\"],\"Cw9Xfg\":[\"The link will expire in 15 minutes.\"],\"DsZc8w\":[\"Allow users from specific domains to sign up\"],\"FozKV6\":[\" (default)\"],\"HvU4EW\":[\"If an account exists for <0>\",[\"email\"],\"</0>, we've sent a sign-in link.\"],\"IoAuJG\":[\"Sending...\"],\"JjOi48\":[\"All locales\"],\"O3oNi5\":[\"Email\"],\"OfnTKV\":[\"Manage your passkeys and authentication\"],\"QjsOMP\":[\"Sign in with Passkey\"],\"RR0ADZ\":[\"Site identity, logo, favicon, and reading preferences\"],\"RxerEl\":[\"Sign in with email link\"],\"Tllxyd\":[\"Self-Signup Domains\"],\"Tz0i8g\":[\"Settings\"],\"VCoEm+\":[\"Back to login\"],\"Weq9zb\":[\"General\"],\"Xeb2Gt\":[\"Authentication error: \",[\"error\"]],\"Y8S9QC\":[\"Choose your preferred admin language\"],\"ZiooJI\":[\"API Tokens\"],\"a3LDKx\":[\"Security\"],\"d0rUsW\":[\"Social Links\"],\"dhH+RW\":[\"Create personal access tokens for programmatic API access\"],\"dsPiA2\":[\"Failed to send magic link\"],\"lE0wHD\":[\"Sign in to your site\"],\"me9L29\":[\"Sign in with email\"],\"pv+wH3\":[\"We'll send you a link to sign in without a password.\"],\"qS3mgX\":[\"Social media profile links\"],\"t0m/8s\":[[\"label\"],\" — view translation\"],\"tfQcxX\":[\"Click the link in the email to sign in.\"],\"v4fiSg\":[\"Check your email\"],\"vXIe7J\":[\"Language\"],\"zW+FpA\":[\"Or continue with\"],\"zY0S+v\":[\"Search engine optimization and verification\"],\"zzGK7U\":[[\"label\"],\" — no translation\"]}");
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as getLocaleLabel, i as SupportedLocale, n as SUPPORTED_LOCALES, o as resolveLocale, r as SUPPORTED_LOCALE_CODES, s as useLocale, t as DEFAULT_LOCALE } from "../config-BHC21FmY.js";
|
|
2
|
+
export { DEFAULT_LOCALE, SUPPORTED_LOCALES, SUPPORTED_LOCALE_CODES, type SupportedLocale, getLocaleLabel, resolveLocale, useLocale };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { a as getLocaleLabel, i as SUPPORTED_LOCALE_CODES, n as DEFAULT_LOCALE, o as resolveLocale, r as SUPPORTED_LOCALES, t as useLocale } from "../useLocale-CXsoFCFt.js";
|
|
2
|
+
|
|
3
|
+
export { DEFAULT_LOCALE, SUPPORTED_LOCALES, SUPPORTED_LOCALE_CODES, getLocaleLabel, resolveLocale, useLocale };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugins-XhZqfegd.js","names":[],"sources":["../src/lib/api/client.ts","../src/lib/api/plugins.ts"],"sourcesContent":["/**\n * Base API client configuration and shared types\n */\n\nimport type { Element } from \"@emdash-cms/blocks\";\n\nexport const API_BASE = \"/_emdash/api\";\n\n/**\n * Fetch wrapper that adds the X-EmDash-Request CSRF protection header\n * to all requests. All API calls should use this instead of raw fetch().\n */\nexport function apiFetch(input: string | URL | Request, init?: RequestInit): Promise<Response> {\n\tconst headers = new Headers(init?.headers);\n\theaders.set(\"X-EmDash-Request\", \"1\");\n\treturn fetch(input, { ...init, headers });\n}\n\n/**\n * Throw an error with the message from the API response body if available,\n * falling back to a generic message. All API error responses use the shape\n * `{ error: { code, message } }`.\n */\nexport async function throwResponseError(res: Response, fallback: string): Promise<never> {\n\tconst body: unknown = await res.json().catch(() => ({}));\n\tlet message: string | undefined;\n\tif (typeof body === \"object\" && body !== null && \"error\" in body) {\n\t\tconst { error } = body;\n\t\tif (typeof error === \"object\" && error !== null && \"message\" in error) {\n\t\t\tconst { message: msg } = error;\n\t\t\tif (typeof msg === \"string\") message = msg;\n\t\t}\n\t}\n\tthrow new Error(message || `${fallback}: ${res.statusText}`);\n}\n\n/**\n * Generic paginated result\n */\nexport interface FindManyResult<T> {\n\titems: T[];\n\tnextCursor?: string;\n}\n\n/**\n * Admin manifest describing available collections and plugins\n */\nexport interface AdminManifest {\n\tversion: string;\n\thash: string;\n\tcollections: Record<\n\t\tstring,\n\t\t{\n\t\t\tlabel: string;\n\t\t\tlabelSingular: string;\n\t\t\tsupports: string[];\n\t\t\thasSeo: boolean;\n\t\t\tfields: Record<\n\t\t\t\tstring,\n\t\t\t\t{\n\t\t\t\t\tkind: string;\n\t\t\t\t\tlabel?: string;\n\t\t\t\t\trequired?: boolean;\n\t\t\t\t\twidget?: string;\n\t\t\t\t\toptions?: Array<{ value: string; label: string }>;\n\t\t\t\t}\n\t\t\t>;\n\t\t}\n\t>;\n\tplugins: Record<\n\t\tstring,\n\t\t{\n\t\t\tname?: string;\n\t\t\tversion?: string;\n\t\t\t/** Package name for dynamic import (e.g., \"@emdash-cms/plugin-audit-log\") */\n\t\t\tpackage?: string;\n\t\t\t/** Whether the plugin is enabled */\n\t\t\tenabled?: boolean;\n\t\t\t/**\n\t\t\t * How this plugin renders its admin UI:\n\t\t\t * - \"react\": Trusted plugin with React components\n\t\t\t * - \"blocks\": Declarative Block Kit UI via admin route handler\n\t\t\t * - \"none\": No admin UI\n\t\t\t */\n\t\t\tadminMode?: \"react\" | \"blocks\" | \"none\";\n\t\t\tadminPages?: Array<{\n\t\t\t\tpath: string;\n\t\t\t\tlabel?: string;\n\t\t\t\ticon?: string;\n\t\t\t}>;\n\t\t\tdashboardWidgets?: Array<{\n\t\t\t\tid: string;\n\t\t\t\ttitle?: string;\n\t\t\t\tsize?: \"full\" | \"half\" | \"third\";\n\t\t\t}>;\n\t\t\tfieldWidgets?: Array<{\n\t\t\t\tname: string;\n\t\t\t\tlabel: string;\n\t\t\t\tfieldTypes: string[];\n\t\t\t\telements?: import(\"@emdash-cms/blocks\").Element[];\n\t\t\t}>;\n\t\t\t/** Block types for Portable Text editor */\n\t\t\tportableTextBlocks?: Array<{\n\t\t\t\ttype: string;\n\t\t\t\tlabel: string;\n\t\t\t\ticon?: string;\n\t\t\t\tdescription?: string;\n\t\t\t\tplaceholder?: string;\n\t\t\t\tfields?: Element[];\n\t\t\t}>;\n\t\t}\n\t>;\n\t/**\n\t * Auth mode for the admin UI. When \"passkey\", the security settings\n\t * (passkey management, self-signup domains) are shown. When using\n\t * external auth (e.g., \"cloudflare-access\"), these are hidden since\n\t * authentication is handled externally.\n\t */\n\tauthMode: string;\n\t/**\n\t * Whether self-signup is enabled (at least one allowed domain is active).\n\t * Used by the login page to conditionally show the \"Sign up\" link.\n\t */\n\tsignupEnabled?: boolean;\n\t/**\n\t * i18n configuration. Present when multiple locales are configured.\n\t */\n\ti18n?: {\n\t\tdefaultLocale: string;\n\t\tlocales: string[];\n\t};\n\t/**\n\t * Marketplace registry URL. Present when `marketplace` is configured\n\t * in the EmDash integration. Enables marketplace features in the UI.\n\t */\n\tmarketplace?: string;\n}\n\n/**\n * Parse an API response with the { data: T } envelope.\n *\n * Handles error responses via throwResponseError, then unwraps the data envelope.\n * Replaces both bare `response.json()` and field-unwrap patterns.\n */\nexport async function parseApiResponse<T>(\n\tresponse: Response,\n\tfallbackMessage = \"Request failed\",\n): Promise<T> {\n\tif (!response.ok) await throwResponseError(response, fallbackMessage);\n\tconst body: { data: T } = await response.json();\n\treturn body.data;\n}\n\n/**\n * Fetch admin manifest\n */\nexport async function fetchManifest(): Promise<AdminManifest> {\n\tconst response = await apiFetch(`${API_BASE}/manifest`);\n\treturn parseApiResponse<AdminManifest>(response, \"Failed to fetch manifest\");\n}\n","/**\n * Plugin management APIs\n */\n\nimport { API_BASE, apiFetch, parseApiResponse, throwResponseError } from \"./client.js\";\n\nexport interface PluginInfo {\n\tid: string;\n\tname: string;\n\tversion: string;\n\tpackage?: string;\n\tenabled: boolean;\n\tstatus: \"installed\" | \"active\" | \"inactive\";\n\tcapabilities: string[];\n\thasAdminPages: boolean;\n\thasDashboardWidgets: boolean;\n\thasHooks: boolean;\n\tinstalledAt?: string;\n\tactivatedAt?: string;\n\tdeactivatedAt?: string;\n\t/** Plugin source: 'config' (declared in astro.config) or 'marketplace' */\n\tsource?: \"config\" | \"marketplace\";\n\t/** Installed marketplace version (set when source = 'marketplace') */\n\tmarketplaceVersion?: string;\n\t/** Description of what the plugin does */\n\tdescription?: string;\n\t/** URL to the plugin icon (marketplace plugins use the icon proxy) */\n\ticonUrl?: string;\n}\n\n/**\n * Fetch all plugins\n */\nexport async function fetchPlugins(): Promise<PluginInfo[]> {\n\tconst response = await apiFetch(`${API_BASE}/admin/plugins`);\n\tconst result = await parseApiResponse<{ items: PluginInfo[] }>(\n\t\tresponse,\n\t\t\"Failed to fetch plugins\",\n\t);\n\treturn result.items;\n}\n\n/**\n * Fetch a single plugin\n */\nexport async function fetchPlugin(pluginId: string): Promise<PluginInfo> {\n\tconst response = await apiFetch(`${API_BASE}/admin/plugins/${pluginId}`);\n\tif (!response.ok) {\n\t\tif (response.status === 404) {\n\t\t\tthrow new Error(`Plugin \"${pluginId}\" not found`);\n\t\t}\n\t\tawait throwResponseError(response, \"Failed to fetch plugin\");\n\t}\n\tconst result = await parseApiResponse<{ item: PluginInfo }>(response, \"Failed to fetch plugin\");\n\treturn result.item;\n}\n\n/**\n * Enable a plugin\n */\nexport async function enablePlugin(pluginId: string): Promise<PluginInfo> {\n\tconst response = await apiFetch(`${API_BASE}/admin/plugins/${pluginId}/enable`, {\n\t\tmethod: \"POST\",\n\t});\n\tconst result = await parseApiResponse<{ item: PluginInfo }>(response, \"Failed to enable plugin\");\n\treturn result.item;\n}\n\n/**\n * Disable a plugin\n */\nexport async function disablePlugin(pluginId: string): Promise<PluginInfo> {\n\tconst response = await apiFetch(`${API_BASE}/admin/plugins/${pluginId}/disable`, {\n\t\tmethod: \"POST\",\n\t});\n\tconst result = await parseApiResponse<{ item: PluginInfo }>(response, \"Failed to disable plugin\");\n\treturn result.item;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAMA,MAAa,WAAW;;;;;AAMxB,SAAgB,SAAS,OAA+B,MAAuC;CAC9F,MAAM,UAAU,IAAI,QAAQ,MAAM,QAAQ;AAC1C,SAAQ,IAAI,oBAAoB,IAAI;AACpC,QAAO,MAAM,OAAO;EAAE,GAAG;EAAM;EAAS,CAAC;;;;;;;AAQ1C,eAAsB,mBAAmB,KAAe,UAAkC;CACzF,MAAM,OAAgB,MAAM,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE;CACxD,IAAI;AACJ,KAAI,OAAO,SAAS,YAAY,SAAS,QAAQ,WAAW,MAAM;EACjE,MAAM,EAAE,UAAU;AAClB,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,aAAa,OAAO;GACtE,MAAM,EAAE,SAAS,QAAQ;AACzB,OAAI,OAAO,QAAQ,SAAU,WAAU;;;AAGzC,OAAM,IAAI,MAAM,WAAW,GAAG,SAAS,IAAI,IAAI,aAAa;;;;;;;;
|
|
1
|
+
{"version":3,"file":"plugins-XhZqfegd.js","names":[],"sources":["../src/lib/api/client.ts","../src/lib/api/plugins.ts"],"sourcesContent":["/**\n * Base API client configuration and shared types\n */\n\nimport type { Element } from \"@emdash-cms/blocks\";\n\nexport const API_BASE = \"/_emdash/api\";\n\n/**\n * Fetch wrapper that adds the X-EmDash-Request CSRF protection header\n * to all requests. All API calls should use this instead of raw fetch().\n */\nexport function apiFetch(input: string | URL | Request, init?: RequestInit): Promise<Response> {\n\tconst headers = new Headers(init?.headers);\n\theaders.set(\"X-EmDash-Request\", \"1\");\n\treturn fetch(input, { ...init, headers });\n}\n\n/**\n * Throw an error with the message from the API response body if available,\n * falling back to a generic message. All API error responses use the shape\n * `{ error: { code, message } }`.\n */\nexport async function throwResponseError(res: Response, fallback: string): Promise<never> {\n\tconst body: unknown = await res.json().catch(() => ({}));\n\tlet message: string | undefined;\n\tif (typeof body === \"object\" && body !== null && \"error\" in body) {\n\t\tconst { error } = body;\n\t\tif (typeof error === \"object\" && error !== null && \"message\" in error) {\n\t\t\tconst { message: msg } = error;\n\t\t\tif (typeof msg === \"string\") message = msg;\n\t\t}\n\t}\n\tthrow new Error(message || `${fallback}: ${res.statusText}`);\n}\n\n/**\n * Generic paginated result\n */\nexport interface FindManyResult<T> {\n\titems: T[];\n\tnextCursor?: string;\n}\n\n/**\n * Admin manifest describing available collections and plugins\n */\nexport interface AdminManifest {\n\tversion: string;\n\thash: string;\n\tcollections: Record<\n\t\tstring,\n\t\t{\n\t\t\tlabel: string;\n\t\t\tlabelSingular: string;\n\t\t\tsupports: string[];\n\t\t\thasSeo: boolean;\n\t\t\turlPattern?: string;\n\t\t\tfields: Record<\n\t\t\t\tstring,\n\t\t\t\t{\n\t\t\t\t\tkind: string;\n\t\t\t\t\tlabel?: string;\n\t\t\t\t\trequired?: boolean;\n\t\t\t\t\twidget?: string;\n\t\t\t\t\toptions?: Array<{ value: string; label: string }>;\n\t\t\t\t\tvalidation?: Record<string, unknown>;\n\t\t\t\t}\n\t\t\t>;\n\t\t}\n\t>;\n\tplugins: Record<\n\t\tstring,\n\t\t{\n\t\t\tname?: string;\n\t\t\tversion?: string;\n\t\t\t/** Package name for dynamic import (e.g., \"@emdash-cms/plugin-audit-log\") */\n\t\t\tpackage?: string;\n\t\t\t/** Whether the plugin is enabled */\n\t\t\tenabled?: boolean;\n\t\t\t/**\n\t\t\t * How this plugin renders its admin UI:\n\t\t\t * - \"react\": Trusted plugin with React components\n\t\t\t * - \"blocks\": Declarative Block Kit UI via admin route handler\n\t\t\t * - \"none\": No admin UI\n\t\t\t */\n\t\t\tadminMode?: \"react\" | \"blocks\" | \"none\";\n\t\t\tadminPages?: Array<{\n\t\t\t\tpath: string;\n\t\t\t\tlabel?: string;\n\t\t\t\ticon?: string;\n\t\t\t}>;\n\t\t\tdashboardWidgets?: Array<{\n\t\t\t\tid: string;\n\t\t\t\ttitle?: string;\n\t\t\t\tsize?: \"full\" | \"half\" | \"third\";\n\t\t\t}>;\n\t\t\tfieldWidgets?: Array<{\n\t\t\t\tname: string;\n\t\t\t\tlabel: string;\n\t\t\t\tfieldTypes: string[];\n\t\t\t\telements?: import(\"@emdash-cms/blocks\").Element[];\n\t\t\t}>;\n\t\t\t/** Block types for Portable Text editor */\n\t\t\tportableTextBlocks?: Array<{\n\t\t\t\ttype: string;\n\t\t\t\tlabel: string;\n\t\t\t\ticon?: string;\n\t\t\t\tdescription?: string;\n\t\t\t\tplaceholder?: string;\n\t\t\t\tfields?: Element[];\n\t\t\t}>;\n\t\t}\n\t>;\n\t/**\n\t * Auth mode for the admin UI. When \"passkey\", the security settings\n\t * (passkey management, self-signup domains) are shown. When using\n\t * external auth (e.g., \"cloudflare-access\"), these are hidden since\n\t * authentication is handled externally.\n\t */\n\tauthMode: string;\n\t/**\n\t * Whether self-signup is enabled (at least one allowed domain is active).\n\t * Used by the login page to conditionally show the \"Sign up\" link.\n\t */\n\tsignupEnabled?: boolean;\n\t/**\n\t * i18n configuration. Present when multiple locales are configured.\n\t */\n\ti18n?: {\n\t\tdefaultLocale: string;\n\t\tlocales: string[];\n\t};\n\t/**\n\t * Taxonomy definitions for the admin sidebar.\n\t */\n\ttaxonomies: Array<{\n\t\tname: string;\n\t\tlabel: string;\n\t\tlabelSingular?: string;\n\t\thierarchical: boolean;\n\t\tcollections: string[];\n\t}>;\n\t/**\n\t * Marketplace registry URL. Present when `marketplace` is configured\n\t * in the EmDash integration. Enables marketplace features in the UI.\n\t */\n\tmarketplace?: string;\n}\n\n/**\n * Parse an API response with the { data: T } envelope.\n *\n * Handles error responses via throwResponseError, then unwraps the data envelope.\n * Replaces both bare `response.json()` and field-unwrap patterns.\n */\nexport async function parseApiResponse<T>(\n\tresponse: Response,\n\tfallbackMessage = \"Request failed\",\n): Promise<T> {\n\tif (!response.ok) await throwResponseError(response, fallbackMessage);\n\tconst body: { data: T } = await response.json();\n\treturn body.data;\n}\n\n/**\n * Fetch admin manifest\n */\nexport async function fetchManifest(): Promise<AdminManifest> {\n\tconst response = await apiFetch(`${API_BASE}/manifest`);\n\treturn parseApiResponse<AdminManifest>(response, \"Failed to fetch manifest\");\n}\n","/**\n * Plugin management APIs\n */\n\nimport { API_BASE, apiFetch, parseApiResponse, throwResponseError } from \"./client.js\";\n\nexport interface PluginInfo {\n\tid: string;\n\tname: string;\n\tversion: string;\n\tpackage?: string;\n\tenabled: boolean;\n\tstatus: \"installed\" | \"active\" | \"inactive\";\n\tcapabilities: string[];\n\thasAdminPages: boolean;\n\thasDashboardWidgets: boolean;\n\thasHooks: boolean;\n\tinstalledAt?: string;\n\tactivatedAt?: string;\n\tdeactivatedAt?: string;\n\t/** Plugin source: 'config' (declared in astro.config) or 'marketplace' */\n\tsource?: \"config\" | \"marketplace\";\n\t/** Installed marketplace version (set when source = 'marketplace') */\n\tmarketplaceVersion?: string;\n\t/** Description of what the plugin does */\n\tdescription?: string;\n\t/** URL to the plugin icon (marketplace plugins use the icon proxy) */\n\ticonUrl?: string;\n}\n\n/**\n * Fetch all plugins\n */\nexport async function fetchPlugins(): Promise<PluginInfo[]> {\n\tconst response = await apiFetch(`${API_BASE}/admin/plugins`);\n\tconst result = await parseApiResponse<{ items: PluginInfo[] }>(\n\t\tresponse,\n\t\t\"Failed to fetch plugins\",\n\t);\n\treturn result.items;\n}\n\n/**\n * Fetch a single plugin\n */\nexport async function fetchPlugin(pluginId: string): Promise<PluginInfo> {\n\tconst response = await apiFetch(`${API_BASE}/admin/plugins/${pluginId}`);\n\tif (!response.ok) {\n\t\tif (response.status === 404) {\n\t\t\tthrow new Error(`Plugin \"${pluginId}\" not found`);\n\t\t}\n\t\tawait throwResponseError(response, \"Failed to fetch plugin\");\n\t}\n\tconst result = await parseApiResponse<{ item: PluginInfo }>(response, \"Failed to fetch plugin\");\n\treturn result.item;\n}\n\n/**\n * Enable a plugin\n */\nexport async function enablePlugin(pluginId: string): Promise<PluginInfo> {\n\tconst response = await apiFetch(`${API_BASE}/admin/plugins/${pluginId}/enable`, {\n\t\tmethod: \"POST\",\n\t});\n\tconst result = await parseApiResponse<{ item: PluginInfo }>(response, \"Failed to enable plugin\");\n\treturn result.item;\n}\n\n/**\n * Disable a plugin\n */\nexport async function disablePlugin(pluginId: string): Promise<PluginInfo> {\n\tconst response = await apiFetch(`${API_BASE}/admin/plugins/${pluginId}/disable`, {\n\t\tmethod: \"POST\",\n\t});\n\tconst result = await parseApiResponse<{ item: PluginInfo }>(response, \"Failed to disable plugin\");\n\treturn result.item;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAMA,MAAa,WAAW;;;;;AAMxB,SAAgB,SAAS,OAA+B,MAAuC;CAC9F,MAAM,UAAU,IAAI,QAAQ,MAAM,QAAQ;AAC1C,SAAQ,IAAI,oBAAoB,IAAI;AACpC,QAAO,MAAM,OAAO;EAAE,GAAG;EAAM;EAAS,CAAC;;;;;;;AAQ1C,eAAsB,mBAAmB,KAAe,UAAkC;CACzF,MAAM,OAAgB,MAAM,IAAI,MAAM,CAAC,aAAa,EAAE,EAAE;CACxD,IAAI;AACJ,KAAI,OAAO,SAAS,YAAY,SAAS,QAAQ,WAAW,MAAM;EACjE,MAAM,EAAE,UAAU;AAClB,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,aAAa,OAAO;GACtE,MAAM,EAAE,SAAS,QAAQ;AACzB,OAAI,OAAO,QAAQ,SAAU,WAAU;;;AAGzC,OAAM,IAAI,MAAM,WAAW,GAAG,SAAS,IAAI,IAAI,aAAa;;;;;;;;AA2H7D,eAAsB,iBACrB,UACA,kBAAkB,kBACL;AACb,KAAI,CAAC,SAAS,GAAI,OAAM,mBAAmB,UAAU,gBAAgB;AAErE,SAD0B,MAAM,SAAS,MAAM,EACnC;;;;;AAMb,eAAsB,gBAAwC;AAE7D,QAAO,iBADU,MAAM,SAAS,GAAG,SAAS,WAAW,EACN,2BAA2B;;;;;;;;;;;;;;;;;ACzI7E,eAAsB,eAAsC;AAM3D,SAJe,MAAM,iBADJ,MAAM,SAAS,GAAG,SAAS,gBAAgB,EAG3D,0BACA,EACa;;;;;AAMf,eAAsB,YAAY,UAAuC;CACxE,MAAM,WAAW,MAAM,SAAS,GAAG,SAAS,iBAAiB,WAAW;AACxE,KAAI,CAAC,SAAS,IAAI;AACjB,MAAI,SAAS,WAAW,IACvB,OAAM,IAAI,MAAM,WAAW,SAAS,aAAa;AAElD,QAAM,mBAAmB,UAAU,yBAAyB;;AAG7D,SADe,MAAM,iBAAuC,UAAU,yBAAyB,EACjF;;;;;AAMf,eAAsB,aAAa,UAAuC;AAKzE,SADe,MAAM,iBAHJ,MAAM,SAAS,GAAG,SAAS,iBAAiB,SAAS,UAAU,EAC/E,QAAQ,QACR,CAAC,EACoE,0BAA0B,EAClF;;;;;AAMf,eAAsB,cAAc,UAAuC;AAK1E,SADe,MAAM,iBAHJ,MAAM,SAAS,GAAG,SAAS,iBAAiB,SAAS,WAAW,EAChF,QAAQ,QACR,CAAC,EACoE,2BAA2B,EACnF"}
|