Files
suaveplan/packages/devtools/tooling/electrobun/src/templates/features.ts
2026-05-27 23:29:53 +01:00

494 lines
12 KiB
TypeScript

import type {
FeatureModule,
ProjectOptions,
} from "../types/electrobun.types.js";
/** Render the i18n feature module. */
export function renderI18nFeature(): string {
return `import { MessageCatalog } from "@suaveplan/i18n";
const messages = {
en: {
greeting: "Hello, {name}!",
welcome: "Welcome to the app",
settings: "Settings",
language: "Language",
},
es: {
greeting: "Hola, {name}!",
welcome: "Bienvenido a la aplicación",
settings: "Configuración",
language: "Idioma",
},
fr: {
greeting: "Bonjour, {name} !",
welcome: "Bienvenue dans l'application",
settings: "Paramètres",
language: "Langue",
},
};
export const catalog = new MessageCatalog({
defaultLocale: "en",
fallbackLocale: "en",
messages,
});
export function setLocale(locale: string): void {
catalog.setLocale(locale);
}
export function t(key: string, params?: Record<string, string>): string {
return catalog.get(key, params);
}
`;
}
/** Render the basic-networking feature module. */
export function renderNetworkFeature(): string {
return `import { NetworkNode } from "@suaveplan/network";
let node: NetworkNode | null = null;
export async function initializeNetwork(): Promise<NetworkNode> {
node = new NetworkNode({
transport: "websocket",
discovery: {
enabled: true,
interval: 5000,
},
});
node.on("peer:connected", (peerId: string) => {
console.log(\`Peer connected: \${peerId}\`);
});
node.on("peer:disconnected", (peerId: string) => {
console.log(\`Peer disconnected: \${peerId}\`);
});
node.on("message", (message: { from: string; data: unknown }) => {
console.log(\`Message from \${message.from}:\`, message.data);
});
await node.start();
console.log("Network node started");
return node;
}
export function getNode(): NetworkNode | null {
return node;
}
export async function broadcast(data: unknown): Promise<void> {
if (node) {
await node.broadcast(data);
}
}
export async function shutdownNetwork(): Promise<void> {
if (node) {
await node.stop();
node = null;
}
}
`;
}
/** Render the full-mesh networking feature module. */
export function renderNetworkFullFeature(): string {
return `import { NetworkNode } from "@suaveplan/network";
let node: NetworkNode | null = null;
export async function initializeNetwork(): Promise<NetworkNode> {
node = new NetworkNode({
transport: "websocket",
discovery: {
enabled: true,
interval: 5000,
},
state: {
hierarchical: true,
vectorClocks: true,
conflictResolution: "last-write-wins",
},
governance: {
roles: ["leader", "follower"],
electionStrategy: "capability-based",
autoPromote: true,
},
});
node.on("peer:connected", (peerId: string) => {
console.log(\`Peer connected: \${peerId}\`);
});
node.on("peer:disconnected", (peerId: string) => {
console.log(\`Peer disconnected: \${peerId}\`);
});
node.on("message", (message: { from: string; data: unknown }) => {
console.log(\`Message from \${message.from}:\`, message.data);
});
node.on("state:sync", (state: unknown) => {
console.log("State synchronized:", state);
});
node.on("role:changed", (role: string) => {
console.log(\`Role changed to: \${role}\`);
});
await node.start();
console.log("Network node started (full mesh mode)");
return node;
}
export function getNode(): NetworkNode | null {
return node;
}
export async function broadcast(data: unknown): Promise<void> {
if (node) {
await node.broadcast(data);
}
}
export function getState<T>(key: string): T | undefined {
return node?.getState<T>(key);
}
export function setState<T>(key: string, value: T): void {
node?.setState(key, value);
}
export async function shutdownNetwork(): Promise<void> {
if (node) {
await node.stop();
node = null;
}
}
`;
}
/** Render the api feature module. */
export function renderApiFeature(): string {
return `import { defineApp } from "@suaveplan/api";
const app = defineApp({
name: "app-api",
port: 3001,
cors: {
origin: "*",
credentials: true,
},
});
app.route("GET", "/api/health", (c) => {
return c.json({ status: "ok", timestamp: Date.now() });
});
app.route("GET", "/api/info", (c) => {
return c.json({
name: "Electrobun App API",
version: "1.0.0",
});
});
export async function startApiServer(): Promise<void> {
await app.start();
console.log("API server started on port 3001");
}
export { app };
`;
}
/** Render the api-schemas feature module. */
export function renderApiSchemasFeature(): string {
return `import { z } from "@suaveplan/validation";
export const UserSchema = z.object({
id: z.string(),
email: z.string().email(),
name: z.string().min(1),
createdAt: z.string().datetime(),
});
export const CreateUserSchema = UserSchema.omit({
id: true,
createdAt: true,
});
export const MessageSchema = z.object({
id: z.string(),
from: z.string(),
to: z.string(),
content: z.string().min(1),
timestamp: z.string().datetime(),
});
export const PaginatedResponseSchema = <T extends z.ZodType>(itemSchema: T) =>
z.object({
items: z.array(itemSchema),
total: z.number(),
page: z.number(),
pageSize: z.number(),
});
export type User = z.infer<typeof UserSchema>;
export type CreateUser = z.infer<typeof CreateUserSchema>;
export type Message = z.infer<typeof MessageSchema>;
`;
}
/** Render the storage feature module. */
export function renderStorageFeature(): string {
return `import { createStorage } from "@suaveplan/storage";
export const appStorage = createStorage({
driver: "file",
options: {
directory: "./data",
namespace: "app",
},
});
export async function saveData<T>(key: string, value: T): Promise<void> {
await appStorage.set(key, value);
}
export async function loadData<T>(key: string): Promise<T | undefined> {
return appStorage.get<T>(key);
}
export async function removeData(key: string): Promise<void> {
await appStorage.delete(key);
}
export async function listKeys(pattern?: string): Promise<string[]> {
return appStorage.keys(pattern ?? "*");
}
`;
}
/** Render the auth feature module. */
export function renderAuthFeature(): string {
return `import { createAuth } from "@suaveplan/auth";
const auth = createAuth({
strategy: "jwt",
tokenExpiry: "24h",
refreshExpiry: "7d",
});
export interface AuthSession {
userId: string;
token: string;
expiresAt: number;
}
let currentSession: AuthSession | null = null;
export async function login(
email: string,
password: string,
): Promise<AuthSession> {
const result = await auth.authenticate({ email, password });
currentSession = {
userId: result.userId,
token: result.token,
expiresAt: result.expiresAt,
};
return currentSession;
}
export function getSession(): AuthSession | null {
return currentSession;
}
export function isAuthenticated(): boolean {
if (!currentSession) return false;
return currentSession.expiresAt > Date.now();
}
export async function logout(): Promise<void> {
if (currentSession) {
await auth.revoke(currentSession.token);
currentSession = null;
}
}
export { auth };
`;
}
/** Render the form-builder feature module. */
export function renderFormBuilderFeature(): string {
return `import { FormBuilder } from "@suaveplan/form-builder";
export const contactForm = new FormBuilder()
.section("personal", "Personal Information")
.field({
name: "firstName",
type: "text",
label: "First Name",
required: true,
validation: { minLength: 1, maxLength: 50 },
})
.field({
name: "lastName",
type: "text",
label: "Last Name",
required: true,
validation: { minLength: 1, maxLength: 50 },
})
.field({
name: "email",
type: "email",
label: "Email Address",
required: true,
})
.section("details", "Details")
.field({
name: "subject",
type: "select",
label: "Subject",
options: [
{ value: "general", label: "General Inquiry" },
{ value: "support", label: "Technical Support" },
{ value: "feedback", label: "Feedback" },
],
})
.field({
name: "message",
type: "textarea",
label: "Message",
required: true,
validation: { minLength: 10, maxLength: 1000 },
})
.build();
`;
}
/** Render the r3f feature module — output depends on selected r3fModules. */
export function renderR3fFeature(options: ProjectOptions): string {
const imports: string[] = [
'import React, { useRef } from "react";',
'import { Canvas, useFrame } from "@react-three/fiber";',
'import { OrbitControls } from "@react-three/drei";',
];
const r3fMods = options.r3fModules;
const extraComponents: string[] = [];
if (r3fMods.includes("camera")) {
imports.push(
'import { AdaptiveDpr, AdaptiveEvents } from "@react-three/drei";'
);
extraComponents.push(" <AdaptiveDpr pixelated />");
extraComponents.push(" <AdaptiveEvents />");
}
if (r3fMods.includes("physics")) {
imports.push(
'import { Physics, RigidBody } from "@react-three/rapier";'
);
}
if (r3fMods.includes("particles")) {
imports.push('import { Sparkles } from "@react-three/drei";');
extraComponents.push(
" <Sparkles count={100} scale={4} size={2} speed={0.4} />"
);
}
const meshContent = r3fMods.includes("physics")
? ` <Physics>
<RigidBody>
<RotatingBox />
</RigidBody>
<RigidBody type="fixed" position={[0, -2, 0]}>
<mesh>
<boxGeometry args={[10, 0.2, 10]} />
<meshStandardMaterial color="#334155" />
</mesh>
</RigidBody>
</Physics>`
: " <RotatingBox />";
return `${imports.join("\n")}
function RotatingBox() {
const meshRef = useRef<THREE.Mesh>(null);
useFrame((_, delta) => {
if (meshRef.current) {
meshRef.current.rotation.x += delta * 0.5;
meshRef.current.rotation.y += delta * 0.3;
}
});
return (
<mesh ref={meshRef}>
<boxGeometry args={[1, 1, 1]} />
<meshStandardMaterial color="#3b82f6" />
</mesh>
);
}
export function Scene() {
return (
<Canvas camera={{ position: [3, 3, 3], fov: 50 }}>
<ambientLight intensity={0.5} />
<directionalLight position={[5, 5, 5]} intensity={1} />
${meshContent}
${extraComponents.join("\n")}
<OrbitControls />
</Canvas>
);
}
`;
}
/**
* Render any feature module. The `networking` branch chooses between basic
* and full implementations based on `options.networkingComplexity`.
*/
export function renderFeature(
feature: FeatureModule,
options: ProjectOptions
): string {
switch (feature) {
case "i18n":
return renderI18nFeature();
case "networking":
return options.networkingComplexity === "full"
? renderNetworkFullFeature()
: renderNetworkFeature();
case "api":
return renderApiFeature();
case "api-schemas":
return renderApiSchemasFeature();
case "storage":
return renderStorageFeature();
case "auth":
return renderAuthFeature();
case "form-builder":
return renderFormBuilderFeature();
case "r3f":
return renderR3fFeature(options);
}
}
/** Filesystem path for a feature's output file. */
export function featurePath(feature: FeatureModule): string {
if (feature === "networking") {
return "src/features/network.ts";
}
if (feature === "api-schemas") {
return "src/features/schemas.ts";
}
if (feature === "r3f") {
return "src/features/r3f.tsx";
}
return `src/features/${feature}.ts`;
}