mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-24 13:54:57 +00:00
config: storybook,json,config (4 files)
This commit is contained in:
@@ -1,3 +1,3 @@
|
||||
export { ACLAdapter } from './acl-adapter'
|
||||
export { ACLAdapter } from './acl-adapter/acl-adapter'
|
||||
export type { ACLAdapterOptions, ACLContext, ACLRule, User } from './acl-adapter/types'
|
||||
export { defaultACLRules } from './acl/default-rules'
|
||||
|
||||
187
storybook/src/discovery/package-discovery.ts
Normal file
187
storybook/src/discovery/package-discovery.ts
Normal file
@@ -0,0 +1,187 @@
|
||||
/**
|
||||
* Package Discovery
|
||||
*
|
||||
* Reads package metadata from packages/index.json and script manifests
|
||||
* to auto-populate Storybook with all available Lua packages.
|
||||
*/
|
||||
|
||||
import type { LuaPackageMetadata, LuaRenderContext } from '../types/lua-types'
|
||||
|
||||
export interface StorybookConfig {
|
||||
packagesPath: string
|
||||
packagesIndex: string
|
||||
discovery: {
|
||||
enabled: boolean
|
||||
scanManifests: boolean
|
||||
includedCategories: string[]
|
||||
excludedPackages: string[]
|
||||
minLevel: number
|
||||
maxLevel: number
|
||||
}
|
||||
rendering: {
|
||||
defaultContext: LuaRenderContext
|
||||
contextVariants: Array<{
|
||||
name: string
|
||||
context: Partial<LuaRenderContext>
|
||||
}>
|
||||
}
|
||||
scripts: {
|
||||
renderFunctions: string[]
|
||||
ignoredScripts: string[]
|
||||
}
|
||||
manualOverrides: Record<string, {
|
||||
featured?: boolean
|
||||
renders?: Record<string, { description?: string }>
|
||||
}>
|
||||
}
|
||||
|
||||
export interface DiscoveredPackage {
|
||||
metadata: LuaPackageMetadata
|
||||
scripts: DiscoveredScript[]
|
||||
featured: boolean
|
||||
}
|
||||
|
||||
export interface DiscoveredScript {
|
||||
file: string
|
||||
name: string
|
||||
category?: string
|
||||
description?: string
|
||||
hasRenderFunction: boolean
|
||||
}
|
||||
|
||||
export interface PackageIndex {
|
||||
generatedAt: string
|
||||
packages: LuaPackageMetadata[]
|
||||
}
|
||||
|
||||
// Cache for loaded data
|
||||
let configCache: StorybookConfig | null = null
|
||||
let packagesCache: DiscoveredPackage[] | null = null
|
||||
|
||||
/**
|
||||
* Load the storybook config
|
||||
*/
|
||||
export async function loadConfig(): Promise<StorybookConfig> {
|
||||
if (configCache) return configCache
|
||||
|
||||
const response = await fetch('/storybook.config.json')
|
||||
configCache = await response.json()
|
||||
return configCache!
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the packages index
|
||||
*/
|
||||
export async function loadPackagesIndex(): Promise<PackageIndex> {
|
||||
const response = await fetch('/packages/index.json')
|
||||
return await response.json()
|
||||
}
|
||||
|
||||
/**
|
||||
* Load script manifest for a package
|
||||
*/
|
||||
export async function loadScriptManifest(packageId: string): Promise<DiscoveredScript[]> {
|
||||
try {
|
||||
const response = await fetch(`/packages/${packageId}/seed/scripts/manifest.json`)
|
||||
if (!response.ok) return []
|
||||
const manifest = await response.json()
|
||||
return manifest.scripts || []
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Discover all packages based on config
|
||||
*/
|
||||
export async function discoverPackages(): Promise<DiscoveredPackage[]> {
|
||||
if (packagesCache) return packagesCache
|
||||
|
||||
const config = await loadConfig()
|
||||
const index = await loadPackagesIndex()
|
||||
|
||||
const discovered: DiscoveredPackage[] = []
|
||||
|
||||
for (const pkg of index.packages) {
|
||||
// Apply filters
|
||||
if (config.discovery.excludedPackages.includes(pkg.packageId)) continue
|
||||
if (pkg.minLevel < config.discovery.minLevel) continue
|
||||
if (pkg.minLevel > config.discovery.maxLevel) continue
|
||||
if (!config.discovery.includedCategories.includes(pkg.category)) continue
|
||||
|
||||
// Load script manifest if enabled
|
||||
let scripts: DiscoveredScript[] = []
|
||||
if (config.discovery.scanManifests) {
|
||||
scripts = await loadScriptManifest(pkg.packageId)
|
||||
|
||||
// Filter out ignored scripts
|
||||
scripts = scripts.filter(s =>
|
||||
!config.scripts.ignoredScripts.some(ignored =>
|
||||
s.name.includes(ignored) || s.file.includes(ignored)
|
||||
)
|
||||
)
|
||||
|
||||
// Mark scripts that likely have render functions
|
||||
scripts = scripts.map(s => ({
|
||||
...s,
|
||||
hasRenderFunction: config.scripts.renderFunctions.some(fn =>
|
||||
s.name === fn || s.file.includes(fn)
|
||||
)
|
||||
}))
|
||||
}
|
||||
|
||||
// Check for manual overrides
|
||||
const override = config.manualOverrides[pkg.packageId]
|
||||
|
||||
discovered.push({
|
||||
metadata: pkg,
|
||||
scripts,
|
||||
featured: override?.featured || false,
|
||||
})
|
||||
}
|
||||
|
||||
// Sort: featured first, then by name
|
||||
discovered.sort((a, b) => {
|
||||
if (a.featured && !b.featured) return -1
|
||||
if (!a.featured && b.featured) return 1
|
||||
return a.metadata.name.localeCompare(b.metadata.name)
|
||||
})
|
||||
|
||||
packagesCache = discovered
|
||||
return discovered
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all context variants from config
|
||||
*/
|
||||
export async function getContextVariants(): Promise<Array<{ name: string; context: LuaRenderContext }>> {
|
||||
const config = await loadConfig()
|
||||
|
||||
return config.rendering.contextVariants.map(variant => ({
|
||||
name: variant.name,
|
||||
context: {
|
||||
...config.rendering.defaultContext,
|
||||
...variant.context,
|
||||
user: {
|
||||
...config.rendering.defaultContext.user,
|
||||
...variant.context.user,
|
||||
},
|
||||
} as LuaRenderContext,
|
||||
}))
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default context
|
||||
*/
|
||||
export async function getDefaultContext(): Promise<LuaRenderContext> {
|
||||
const config = await loadConfig()
|
||||
return config.rendering.defaultContext
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear caches (useful for hot reloading)
|
||||
*/
|
||||
export function clearCaches(): void {
|
||||
configCache = null
|
||||
packagesCache = null
|
||||
}
|
||||
98
storybook/storybook-config.schema.json
Normal file
98
storybook/storybook-config.schema.json
Normal file
@@ -0,0 +1,98 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "Storybook Config",
|
||||
"description": "Configuration for auto-discovering and rendering Lua packages in Storybook",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"$schema": { "type": "string" },
|
||||
"description": { "type": "string" },
|
||||
"packagesPath": {
|
||||
"type": "string",
|
||||
"description": "Relative path to packages directory"
|
||||
},
|
||||
"packagesIndex": {
|
||||
"type": "string",
|
||||
"description": "Relative path to packages/index.json"
|
||||
},
|
||||
"discovery": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": { "type": "boolean" },
|
||||
"scanManifests": { "type": "boolean" },
|
||||
"includedCategories": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"excludedPackages": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"minLevel": { "type": "integer", "minimum": 1, "maximum": 6 },
|
||||
"maxLevel": { "type": "integer", "minimum": 1, "maximum": 6 }
|
||||
}
|
||||
},
|
||||
"rendering": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"defaultContext": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"user": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": { "type": "string" },
|
||||
"username": { "type": "string" },
|
||||
"level": { "type": "integer" },
|
||||
"email": { "type": "string" }
|
||||
}
|
||||
},
|
||||
"nerdMode": { "type": "boolean" },
|
||||
"theme": { "type": "string", "enum": ["light", "dark"] }
|
||||
}
|
||||
},
|
||||
"contextVariants": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": { "type": "string" },
|
||||
"context": { "type": "object" }
|
||||
},
|
||||
"required": ["name", "context"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"renderFunctions": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"ignoredScripts": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"manualOverrides": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"featured": { "type": "boolean" },
|
||||
"renders": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"description": { "type": "string" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
74
storybook/storybook.config.json
Normal file
74
storybook/storybook.config.json
Normal file
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"$schema": "./storybook-config.schema.json",
|
||||
"description": "Auto-discovery configuration for Lua package Storybook",
|
||||
"packagesPath": "../packages",
|
||||
"packagesIndex": "../packages/index.json",
|
||||
|
||||
"discovery": {
|
||||
"enabled": true,
|
||||
"scanManifests": true,
|
||||
"includedCategories": ["ui", "admin", "gaming", "social", "editors"],
|
||||
"excludedPackages": ["shared", "lua_test"],
|
||||
"minLevel": 1,
|
||||
"maxLevel": 6
|
||||
},
|
||||
|
||||
"rendering": {
|
||||
"defaultContext": {
|
||||
"user": {
|
||||
"id": "storybook-user",
|
||||
"username": "demo_user",
|
||||
"level": 4,
|
||||
"email": "demo@example.com"
|
||||
},
|
||||
"nerdMode": false,
|
||||
"theme": "light"
|
||||
},
|
||||
"contextVariants": [
|
||||
{
|
||||
"name": "Guest",
|
||||
"context": { "user": { "username": "guest", "level": 1 } }
|
||||
},
|
||||
{
|
||||
"name": "Admin",
|
||||
"context": { "user": { "username": "admin", "level": 4 }, "nerdMode": false }
|
||||
},
|
||||
{
|
||||
"name": "Admin (Nerd Mode)",
|
||||
"context": { "user": { "username": "admin", "level": 4 }, "nerdMode": true }
|
||||
},
|
||||
{
|
||||
"name": "Supergod",
|
||||
"context": { "user": { "username": "supergod", "level": 6 } }
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"scripts": {
|
||||
"renderFunctions": ["render", "main", "layout", "init"],
|
||||
"ignoredScripts": ["test", "types", "utils"]
|
||||
},
|
||||
|
||||
"manualOverrides": {
|
||||
"dashboard": {
|
||||
"featured": true,
|
||||
"renders": {
|
||||
"stats.card": { "description": "Single stat card with trend indicator" },
|
||||
"stats.grid": { "description": "Grid of stat cards" },
|
||||
"layout.standard": { "description": "Standard dashboard layout" }
|
||||
}
|
||||
},
|
||||
"ui_level4": {
|
||||
"featured": true,
|
||||
"renders": {
|
||||
"layout.render": { "description": "Admin panel main layout" }
|
||||
}
|
||||
},
|
||||
"user_manager": {
|
||||
"featured": true,
|
||||
"renders": {
|
||||
"render_users": { "description": "User management table" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user