Skip to content

Latest commit

 

History

History
771 lines (568 loc) · 13.3 KB

File metadata and controls

771 lines (568 loc) · 13.3 KB
path docs/api/Widget_API.mdx
title Widget Management API
description Complete API reference for managing widgets in SveltyCMS including installation, activation, and dependency management.
order 6
icon mdi:puzzle
author admin
created 2025-10-05
updated 2025-10-05
tags
api
widgets
plugins
extensions

Widget Management API

Overview

The Widget API provides comprehensive endpoints for managing widgets (plugins/extensions) in SveltyCMS. Widgets extend functionality and can be core (built-in) or custom (user-installed).

Base Path: /api/widgets

Authentication

All widget endpoints require authentication:

Cookie: session=your-session-id

Permissions Required: api:widgets for all endpoints

Widget Architecture

SveltyCMS uses a 3-pillar widget architecture:

  1. Definition (index.ts) - Widget metadata, validation schema, and configuration
  2. Input (Input.svelte) - Edit/creation interface component
  3. Display (Display.svelte) - Read-only display component

Widget Types:

  • core - Built-in widgets in /src/widgets/core/
  • custom - User-created widgets in /src/widgets/custom/
  • marketplace - Runtime-installed widgets (planned feature)

Endpoints

1. List Widgets

Retrieves comprehensive information about all available widgets.

Request

GET /api/widgets/list

Query Parameters:

  • tenantId (string, optional) - Filter by tenant (multi-tenant mode)
  • category (string, optional) - Filter by widget category
  • status (string, optional) - Filter by status (active, inactive, core)

Headers:

Cookie: session=your-session-id

Permissions Required: api:widgets

Response

Success (200):

{
	"success": true,
	"widgets": {
		"widgetFunction": {
			"name": "widgetFunction",
			"version": "1.0.0",
			"description": "Core widget function component",
			"category": "core",
			"status": "active",
			"isCore": true,
			"dependencies": [],
			"metadata": {
				"author": "SveltyCMS",
				"license": "MIT",
				"icon": "mdi:puzzle"
			}
		},
		"mediaUpload": {
			"name": "mediaUpload",
			"version": "1.2.0",
			"description": "Media file upload widget",
			"category": "media",
			"status": "active",
			"isCore": true,
			"dependencies": ["widgetFunction"],
			"metadata": {
				"author": "SveltyCMS",
				"license": "MIT",
				"icon": "mdi:upload"
			}
		}
	},
	"summary": {
		"total": 25,
		"active": 18,
		"inactive": 5,
		"core": 15,
		"custom": 10
	},
	"tenantId": "default-tenant",
	"processingTime": "45ms"
}

Error Responses:

// 401 Unauthorized
{
  "success": false,
  "message": "Unauthorized"
}

// 403 Forbidden
{
  "success": false,
  "message": "Insufficient permissions"
}

2. Install Widget

⚠️ Status: Planned Feature - Currently returns mock response. Full marketplace integration is under development.

Installs a widget from the marketplace.

Request

POST /api/widgets/install

Headers:

Cookie: session=your-session-id
Content-Type: application/json

Body:

{
	"widgetId": "custom-widget-123",
	"tenantId": "tenant-xyz"
}

Permissions Required: api:widgets

Response

Success (200):

{
	"success": true,
	"widgetId": "custom-widget-123",
	"tenantId": "tenant-xyz",
	"installedAt": "2025-10-05T14:30:00Z",
	"message": "Widget installed successfully"
}

Note: This endpoint currently provides a mock implementation. The actual installation logic is planned for future development.

Error Responses:

// 400 Bad Request - Missing widget ID
{
  "error": "Widget ID is required"
}

// 401 Unauthorized
{
  "error": "Unauthorized"
}

// 403 Forbidden
{
  "error": "Insufficient permissions"
}

// 500 Internal Server Error
{
  "error": "Failed to install widget: <error message>"
}

3. Uninstall Widget

Uninstalls a previously installed widget.

Request

POST /api/widgets/uninstall

Headers:

Cookie: session=your-session-id
Content-Type: application/json

Body:

{
	"widgetName": "custom-widget",
	"tenantId": "tenant-xyz",
	"force": false
}

Parameters:

  • widgetName (string, required) - Name of widget to uninstall
  • tenantId (string, optional) - Tenant ID (defaults to user's tenant)
  • force (boolean, optional) - Force uninstall even with dependencies

Permissions Required: api:widgets

Response

Success (200):

{
	"success": true,
	"widgetName": "custom-widget",
	"tenantId": "tenant-xyz",
	"uninstalledAt": "2025-10-05T14:30:00Z",
	"message": "Widget uninstalled successfully"
}

Error Responses:

// 400 Bad Request - Missing widget name
{
  "success": false,
  "message": "Widget name is required"
}

// 400 Bad Request - Has dependencies
{
  "success": false,
  "message": "Cannot uninstall: Other widgets depend on this widget",
  "dependents": ["widget1", "widget2"]
}

// 409 Conflict - Core widget
{
  "success": false,
  "message": "Cannot uninstall core widget"
}

4. Activate Widget

Activates an installed but inactive widget.

Request

POST /api/widgets/activate

Headers:

Cookie: session=your-session-id
Content-Type: application/json

Body:

{
	"widgetName": "custom-widget",
	"tenantId": "tenant-xyz"
}

Permissions Required: api:widgets

Response

Success (200):

{
	"success": true,
	"widgetName": "custom-widget",
	"status": "active",
	"message": "Widget activated successfully"
}

5. Deactivate Widget

Deactivates an active widget without uninstalling it.

Request

POST /api/widgets/deactivate

Headers:

Cookie: session=your-session-id
Content-Type: application/json

Body:

{
	"widgetName": "custom-widget",
	"tenantId": "tenant-xyz"
}

Permissions Required: api:widgets

Response

Success (200):

{
	"success": true,
	"widgetName": "custom-widget",
	"status": "inactive",
	"message": "Widget deactivated successfully"
}

5. Validate Widget

Validates a widget's integrity and compatibility.

Request

POST /api/widgets/validate

Headers:

Cookie: session=your-session-id
Content-Type: application/json

Body:

{
	"widgetName": "custom-widget",
	"tenantId": "tenant-xyz"
}

Permissions Required: api:widgets

Response

Success (200):

{
	"success": true,
	"valid": true,
	"checks": {
		"fileIntegrity": "passed",
		"dependencies": "passed",
		"compatibility": "passed",
		"permissions": "passed"
	},
	"message": "Widget validation successful"
}

Validation Failure (200 with warnings):

{
	"success": true,
	"valid": false,
	"checks": {
		"fileIntegrity": "passed",
		"dependencies": "failed",
		"compatibility": "warning",
		"permissions": "passed"
	},
	"errors": ["Missing dependency: widgetFunction v2.0.0"],
	"warnings": ["Newer version available: 1.3.0"]
}

6. Sync Widgets

Synchronizes widget registry with filesystem.

Request

POST /api/widgets/sync

Headers:

Cookie: session=your-session-id
Content-Type: application/json

Body:

{
	"tenantId": "tenant-xyz",
	"force": false
}

Permissions Required: api:widgets

Response

Success (200):

{
	"success": true,
	"syncedAt": "2025-10-05T14:30:00Z",
	"changes": {
		"added": 2,
		"removed": 1,
		"updated": 3
	},
	"message": "Widget registry synchronized"
}

7. Get Required Widgets

Retrieves widgets currently used by collections (cannot be deactivated).

Request

GET /api/widgets/required

Headers:

Cookie: session=your-session-id

Permissions Required: Not required (uses locals)

Response

Success (200):

{
	"requiredWidgets": ["String", "RichText", "Media", "Relation"],
	"collectionsAnalyzed": 5,
	"tenantId": "default-tenant"
}

8. Get Active Widgets

Retrieves currently active widgets with 3-pillar architecture metadata.

Request

GET /api/widgets/active

Query Parameters:

  • refresh (boolean, optional) - Force cache refresh (?refresh=true)

Headers:

Cookie: session=your-session-id

Permissions Required: Not required (uses locals)

Response

Success (200):

{
	"widgets": [
		{
			"name": "String",
			"isCore": true,
			"icon": "mdi:text",
			"description": "Single-line text input widget",
			"inputComponentPath": "/src/widgets/core/string/Input.svelte",
			"displayComponentPath": "/src/widgets/core/string/Display.svelte",
			"dependencies": []
		}
	],
	"tenantId": "default-tenant"
}

Widget Lifecycle

  1. Installation - Download and install widget files
  2. Validation - Check integrity, dependencies, compatibility
  3. Registration - Add to widget registry
  4. Activation - Enable widget functionality
  5. Usage - Widget is active and functional
  6. Deactivation - Disable without removing
  7. Uninstallation - Remove widget completely

Widget Dependencies

Widgets can depend on other widgets:

{
	"name": "imageGallery",
	"dependencies": ["widgetFunction", "mediaUpload"],
	"dependents": ["portfolioWidget"]
}

Dependency Rules:

  • Cannot uninstall widget if others depend on it
  • Dependencies must be installed before dependent
  • Circular dependencies are not allowed

Database-Agnostic Implementation

The Widget API uses permission-based authorization (no direct DB queries):

// Permission check only - no database operations
const hasPermission = hasPermissionWithRoles(user, 'api:widgets', roles);

Widget data is stored in:

  • File System - Widget code and assets
  • Widget Store - Runtime registry (Svelte store)
  • Configuration - Settings and metadata

Multi-Tenancy Support

When multi-tenant mode is enabled:

  • Each tenant has isolated widget installations
  • Core widgets are shared across tenants
  • Custom widgets are tenant-specific
  • Widget settings are tenant-scoped

Tenant-Scoped Installation:

POST /api/widgets/install
Content-Type: application/json

{
  "widgetId": "custom-widget",
  "tenantId": "tenant-abc"
}

Widget Categories

Widgets are organized by category:

  • Core - Essential system widgets
  • Media - Media management widgets
  • Content - Content creation/editing widgets
  • User - User management widgets
  • Analytics - Analytics and reporting widgets
  • Integration - Third-party integrations
  • Custom - User-created widgets

Security Considerations

Access Control

  • Only users with api:widgets permission can manage widgets
  • Widget installation requires admin rights
  • Tenant isolation in multi-tenant mode

Widget Validation

  • Code signing verification
  • Dependency validation
  • Permission declaration
  • Sandbox execution (planned)

Widget Sources

  • Official marketplace (verified)
  • Third-party marketplace (community)
  • Local installation (custom)

Widget Development

Widget Structure (3-Pillar Architecture)

my-widget/
├── index.ts          # Widget definition, validation schema, metadata
├── Input.svelte      # Edit/creation interface
├── Display.svelte    # Read-only display component
└── types.ts          # TypeScript types (optional)

Widget Definition (index.ts)

import { createWidget } from '@src/widgets/factory';
import { object, string } from 'valibot';
import * as m from '@src/paraglide/messages';

const validationSchema = object({
	value: string()
});

const MyWidget = createWidget({
	Name: 'MyWidget',
	Icon: 'mdi:puzzle',
	Description: m.widget_mywidget_description(),
	inputComponentPath: '/src/widgets/custom/mywidget/Input.svelte',
	displayComponentPath: '/src/widgets/custom/mywidget/Display.svelte',
	validationSchema,
	defaults: { placeholder: 'Enter value' },
	GuiSchema: {
		/* ... */
	},
	aggregations: {
		/* ... */
	},
	GraphqlSchema: () => ({ typeID: 'String', graphql: '' })
});

export default MyWidget;

Testing

JavaScript Example

// List all widgets
const response = await fetch('/api/widgets/list', {
	credentials: 'include'
});
const { widgets, summary } = await response.json();

// Install widget
const installResponse = await fetch('/api/widgets/install', {
	method: 'POST',
	credentials: 'include',
	headers: { 'Content-Type': 'application/json' },
	body: JSON.stringify({
		widgetId: 'custom-widget-123',
		tenantId: 'my-tenant'
	})
});

// Activate widget
await fetch('/api/widgets/activate', {
	method: 'POST',
	credentials: 'include',
	headers: { 'Content-Type': 'application/json' },
	body: JSON.stringify({
		widgetName: 'custom-widget'
	})
});

Related Documentation


Implementation Details

For implementation details, see:

  • src/routes/api/widgets/list/+server.ts - List widgets
  • src/routes/api/widgets/install/+server.ts - Install endpoint
  • src/routes/api/widgets/uninstall/+server.ts - Uninstall endpoint
  • src/stores/widgetStore.svelte.ts - Widget registry store
  • src/databases/auth/permissions.ts - Permission checking