feat(03-01): add Module SDK package and Prisma module registry schema

- Create @tessera/module-sdk with TesseraModule, ModuleRoute, ModuleManifest, ModuleCategory types
- Add Module and TenantModuleActivation Prisma models with tenant-scoped unique constraint
- Apply migration add-module-registry to PostgreSQL
- Framework-agnostic ComponentType for lazy-loaded module UIs
This commit is contained in:
2026-06-19 12:33:55 +02:00
parent 6e2f6e7c3e
commit 8c24c1e267
7 changed files with 183 additions and 0 deletions
+14
View File
@@ -0,0 +1,14 @@
/**
* @tessera/module-sdk
*
* Public API for the Tessera module system.
* All module implementations should import types from this package.
*/
export type {
ComponentType,
ModuleCategory,
HttpMethod,
ModuleRoute,
TesseraModule,
ModuleManifest,
} from './types';
+78
View File
@@ -0,0 +1,78 @@
/**
* @tessera/module-sdk
*
* Defines the contract for Tessera modules.
* All modules must implement the TesseraModule interface.
*/
/**
* Generic component type for lazy-loaded module UIs.
* Framework-agnostic — maps to React.ComponentType when consumed by the frontend.
*/
// biome-ignore lint: generic component type for framework independence
export type ComponentType = (props: any) => any;
/**
* Category classification for modules.
* Modules are grouped by category in the marketplace and sidebar.
*/
export type ModuleCategory =
| 'infrastructure'
| 'monitoring'
| 'development'
| 'security'
| 'communication'
| 'workflow'
| 'analytics'
| 'integration'
| string;
/**
* HTTP method for module-defined API routes.
*/
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
/**
* Defines a single API route that a module exposes.
*/
export interface ModuleRoute {
/** HTTP method */
method: HttpMethod;
/** Route path relative to the module's base path (e.g., '/check') */
path: string;
/** Handler identifier (maps to a controller method) */
handler: string;
}
/**
* Full module definition including frontend components.
* Used by the frontend to render module UIs.
*/
export interface TesseraModule {
/** Unique module identifier (UUID) */
id: string;
/** Human-readable module name */
name: string;
/** Semantic version string */
version: string;
/** URL-safe unique slug (e.g., 'domaincheck') */
slug: string;
/** Module category for grouping */
category: ModuleCategory;
/** i18n descriptions keyed by locale (e.g., { de: '...', en: '...' }) */
description: Record<string, string>;
/** Optional icon identifier (e.g., 'Globe', 'Shield') */
icon?: string;
/** Optional API routes the module exposes */
routes?: ModuleRoute[];
/** Lazy-loaded main component for the module page */
component: () => Promise<{ default: ComponentType }>;
/** Optional lazy-loaded card component for the dashboard */
cardComponent?: () => Promise<{ default: ComponentType }>;
}
/**
* Backend-only module metadata (no frontend component references).
* Used for module registration and API-side operations.
*/
export type ModuleManifest = Omit<TesseraModule, 'component' | 'cardComponent'>;