mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-24 13:54:57 +00:00
docs: json,typescript,types (2 files)
This commit is contained in:
241
TYPESCRIPT_JSON_PATTERN.md
Normal file
241
TYPESCRIPT_JSON_PATTERN.md
Normal file
@@ -0,0 +1,241 @@
|
||||
# TypeScript JSON Abstraction Pattern
|
||||
|
||||
## Concept Overview
|
||||
|
||||
Just as we've abstracted CSS into declarative JSON schemas (`styles.json`), this demonstrates how TypeScript type definitions can be represented in a similar JSON format.
|
||||
|
||||
## Pattern Comparison
|
||||
|
||||
### CSS Pattern (styles.json V2)
|
||||
```
|
||||
Declarative JSON → StylesCompiler → CSS Output
|
||||
```
|
||||
|
||||
### TypeScript Pattern (types.json)
|
||||
```
|
||||
Declarative JSON → TypeScriptCompiler → .d.ts Output
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
### 1. Schema Structure
|
||||
|
||||
**File Location**: `packages/{package}/seed/types.json`
|
||||
|
||||
**Core Sections**:
|
||||
- **tokens**: Reusable primitive type aliases
|
||||
- **interfaces**: Object type definitions
|
||||
- **types**: Union types, literal types
|
||||
- **generics**: Generic type definitions
|
||||
- **rules**: Type constraints and modifiers
|
||||
- **exports**: Export configuration
|
||||
- **environments**: Target environments (ESM, CJS, TypeScript)
|
||||
- **composition**: Type intersections and combinations
|
||||
|
||||
### 2. Benefits of This Approach
|
||||
|
||||
1. **Non-Developer Friendly**: JSON is easier to read/edit than TypeScript syntax
|
||||
2. **Composable**: Build complex types from simple building blocks
|
||||
3. **Multi-Target**: Single source generates multiple output formats
|
||||
4. **Versionable**: Schema versioning allows evolution
|
||||
5. **Debuggable**: Can build visualization tools (like StylesPanel)
|
||||
6. **Consistent**: Mirrors the proven styles.json pattern
|
||||
|
||||
### 3. Example: From JSON to TypeScript
|
||||
|
||||
**Input** (`types.json`):
|
||||
```json
|
||||
{
|
||||
"interfaces": [
|
||||
{
|
||||
"name": "ButtonProps",
|
||||
"extends": ["BaseComponentProps"],
|
||||
"properties": {
|
||||
"variant": {
|
||||
"type": "'primary' | 'secondary'",
|
||||
"optional": false
|
||||
},
|
||||
"size": {
|
||||
"type": "'small' | 'medium' | 'large'",
|
||||
"default": "'medium'"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Output** (compiled TypeScript):
|
||||
```typescript
|
||||
export interface ButtonProps extends BaseComponentProps {
|
||||
variant: 'primary' | 'secondary';
|
||||
size?: 'small' | 'medium' | 'large';
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Compiler Implementation Sketch
|
||||
|
||||
```typescript
|
||||
class TypeScriptCompiler {
|
||||
private schema: TypeScriptSchema;
|
||||
|
||||
compile(): string {
|
||||
const output: string[] = [];
|
||||
|
||||
// Compile tokens
|
||||
if (this.schema.tokens) {
|
||||
output.push(this.compileTokens(this.schema.tokens));
|
||||
}
|
||||
|
||||
// Compile interfaces
|
||||
if (this.schema.interfaces) {
|
||||
output.push(...this.schema.interfaces.map(i => this.compileInterface(i)));
|
||||
}
|
||||
|
||||
// Compile types
|
||||
if (this.schema.types) {
|
||||
output.push(...this.schema.types.map(t => this.compileType(t)));
|
||||
}
|
||||
|
||||
// Apply rules/modifiers
|
||||
return this.applyRules(output.join('\n\n'));
|
||||
}
|
||||
|
||||
private compileInterface(def: InterfaceDefinition): string {
|
||||
const ext = def.extends?.length ? ` extends ${def.extends.join(', ')}` : '';
|
||||
const props = Object.entries(def.properties)
|
||||
.map(([key, prop]) => {
|
||||
const optional = prop.optional ? '?' : '';
|
||||
const readonly = prop.readonly ? 'readonly ' : '';
|
||||
return ` ${readonly}${key}${optional}: ${prop.type};`;
|
||||
})
|
||||
.join('\n');
|
||||
|
||||
return `export interface ${def.name}${ext} {\n${props}\n}`;
|
||||
}
|
||||
|
||||
private compileType(def: TypeDefinition): string {
|
||||
if (def.kind === 'union') {
|
||||
return `export type ${def.name} = ${def.values.join(' | ')};`;
|
||||
}
|
||||
return `export type ${def.name} = ${def.definition};`;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Integration Points
|
||||
|
||||
Following the styles.json pattern:
|
||||
|
||||
```typescript
|
||||
// Similar to loadPackageStyles()
|
||||
async function loadPackageTypes(packageId: string): Promise<string> {
|
||||
const response = await fetch(`/packages/${packageId}/seed/types.json`);
|
||||
const schema = await response.json();
|
||||
|
||||
const compiler = new TypeScriptCompiler(schema);
|
||||
return compiler.compile();
|
||||
}
|
||||
|
||||
// Generate .d.ts files at build time
|
||||
function generateTypeDefinitions() {
|
||||
const packages = getPackageList();
|
||||
|
||||
for (const pkg of packages) {
|
||||
const typeSchema = loadTypeSchema(pkg);
|
||||
const compiler = new TypeScriptCompiler(typeSchema);
|
||||
const output = compiler.compile();
|
||||
|
||||
fs.writeFileSync(
|
||||
`packages/${pkg}/dist/types.d.ts`,
|
||||
output
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 6. Advanced Features
|
||||
|
||||
**Composition** (like styles.json appearance layers):
|
||||
```json
|
||||
{
|
||||
"composition": [
|
||||
{
|
||||
"name": "EnhancedButtonProps",
|
||||
"kind": "intersection",
|
||||
"types": [
|
||||
"ButtonProps",
|
||||
"AccessibilityProps",
|
||||
"AnalyticsProps"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Rules** (like styles.json selector rules):
|
||||
```json
|
||||
{
|
||||
"rules": [
|
||||
{
|
||||
"selector": {
|
||||
"interfaceName": "UserData",
|
||||
"property": "id"
|
||||
},
|
||||
"modifiers": ["readonly", "required"],
|
||||
"priority": 10
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Environments** (like styles.json responsive environments):
|
||||
```json
|
||||
{
|
||||
"environments": {
|
||||
"node": {
|
||||
"moduleSystem": "CommonJS",
|
||||
"globals": ["process", "Buffer"]
|
||||
},
|
||||
"browser": {
|
||||
"moduleSystem": "ES2015",
|
||||
"globals": ["window", "document"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 7. Practical Use Cases
|
||||
|
||||
1. **Component Libraries**: Define all component prop types in JSON
|
||||
2. **API Contracts**: Generate TypeScript types from API schemas
|
||||
3. **Configuration**: Type-safe config objects defined declaratively
|
||||
4. **Theme Systems**: Type definitions for theme tokens and variants
|
||||
5. **State Management**: Action and state type definitions
|
||||
|
||||
### 8. Future Enhancements
|
||||
|
||||
- **Validation**: JSON Schema validation for types.json
|
||||
- **Visualization**: Storybook panel to explore type relationships (like StylesPanel)
|
||||
- **Code Generation**: Generate not just types but implementation stubs
|
||||
- **Documentation**: Auto-generate docs from type definitions
|
||||
- **Migration Tools**: Convert existing .ts files to types.json
|
||||
|
||||
## Example Files
|
||||
|
||||
See the demonstration in:
|
||||
- [packages/shared/seed/types.json](packages/shared/seed/types.json)
|
||||
|
||||
This mirrors the existing pattern:
|
||||
- [packages/shared/seed/styles.json](packages/shared/seed/styles.json)
|
||||
|
||||
## Conclusion
|
||||
|
||||
This pattern demonstrates that **any code abstraction can be represented declaratively in JSON** when you:
|
||||
1. Define a clear schema
|
||||
2. Build a compiler to transform it
|
||||
3. Support composition and rules
|
||||
4. Enable multi-target output
|
||||
5. Provide tooling for debugging/visualization
|
||||
|
||||
The same pattern used for CSS → styles.json applies perfectly to TypeScript → types.json.
|
||||
208
packages/shared/seed/types.json
Normal file
208
packages/shared/seed/types.json
Normal file
@@ -0,0 +1,208 @@
|
||||
{
|
||||
"schema_version": "1.0.0",
|
||||
"package": "shared",
|
||||
"description": "Type definitions abstraction - similar pattern to styles.json V2",
|
||||
|
||||
"tokens": {
|
||||
"primitives": {
|
||||
"StringType": "string",
|
||||
"NumberType": "number",
|
||||
"BooleanType": "boolean",
|
||||
"VoidType": "void",
|
||||
"UnknownType": "unknown",
|
||||
"NeverType": "never"
|
||||
},
|
||||
"common": {
|
||||
"ID": "string",
|
||||
"Timestamp": "number",
|
||||
"JSONValue": "string | number | boolean | null | JSONArray | JSONObject",
|
||||
"Callback": "(event: any) => void",
|
||||
"AsyncCallback": "(event: any) => Promise<void>"
|
||||
}
|
||||
},
|
||||
|
||||
"interfaces": [
|
||||
{
|
||||
"id": "base_component_props",
|
||||
"name": "BaseComponentProps",
|
||||
"description": "Base props for all components",
|
||||
"extends": [],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"optional": true,
|
||||
"description": "Unique identifier"
|
||||
},
|
||||
"className": {
|
||||
"type": "string",
|
||||
"optional": true,
|
||||
"description": "CSS class name"
|
||||
},
|
||||
"style": {
|
||||
"type": "React.CSSProperties",
|
||||
"optional": true,
|
||||
"description": "Inline styles"
|
||||
},
|
||||
"children": {
|
||||
"type": "React.ReactNode",
|
||||
"optional": true,
|
||||
"description": "Child elements"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "theme_config",
|
||||
"name": "ThemeConfig",
|
||||
"description": "Theme configuration object",
|
||||
"properties": {
|
||||
"mode": {
|
||||
"type": "'light' | 'dark'",
|
||||
"optional": false,
|
||||
"default": "'light'"
|
||||
},
|
||||
"primaryColor": {
|
||||
"type": "string",
|
||||
"optional": true,
|
||||
"description": "Primary theme color"
|
||||
},
|
||||
"spacing": {
|
||||
"type": "number",
|
||||
"optional": true,
|
||||
"default": 8,
|
||||
"description": "Base spacing unit in pixels"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
"types": [
|
||||
{
|
||||
"id": "component_type_enum",
|
||||
"name": "ComponentType",
|
||||
"kind": "union",
|
||||
"values": [
|
||||
"'div'",
|
||||
"'span'",
|
||||
"'button'",
|
||||
"'input'",
|
||||
"'section'",
|
||||
"'header'",
|
||||
"'footer'"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "size_variant",
|
||||
"name": "SizeVariant",
|
||||
"kind": "union",
|
||||
"values": ["'small'", "'medium'", "'large'"]
|
||||
},
|
||||
{
|
||||
"id": "color_variant",
|
||||
"name": "ColorVariant",
|
||||
"kind": "union",
|
||||
"values": ["'primary'", "'secondary'", "'success'", "'error'", "'warning'"]
|
||||
}
|
||||
],
|
||||
|
||||
"generics": [
|
||||
{
|
||||
"id": "generic_props",
|
||||
"name": "PropsWithType",
|
||||
"typeParams": ["T"],
|
||||
"definition": "BaseComponentProps & { type: T }"
|
||||
},
|
||||
{
|
||||
"id": "generic_state",
|
||||
"name": "StateWithData",
|
||||
"typeParams": ["D"],
|
||||
"definition": "{ loading: boolean; error?: string; data?: D }"
|
||||
}
|
||||
],
|
||||
|
||||
"rules": [
|
||||
{
|
||||
"id": "readonly_id_rule",
|
||||
"selector": {
|
||||
"interfaceName": "BaseComponentProps",
|
||||
"property": "id"
|
||||
},
|
||||
"modifiers": ["readonly"],
|
||||
"enabled": true,
|
||||
"priority": 10
|
||||
},
|
||||
{
|
||||
"id": "required_theme_mode",
|
||||
"selector": {
|
||||
"interfaceName": "ThemeConfig",
|
||||
"property": "mode"
|
||||
},
|
||||
"modifiers": ["required"],
|
||||
"enabled": true,
|
||||
"priority": 20
|
||||
}
|
||||
],
|
||||
|
||||
"exports": [
|
||||
{
|
||||
"id": "export_base_props",
|
||||
"name": "BaseComponentProps",
|
||||
"kind": "interface",
|
||||
"environments": ["esm", "cjs", "types"],
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"id": "export_theme_config",
|
||||
"name": "ThemeConfig",
|
||||
"kind": "interface",
|
||||
"environments": ["esm", "cjs", "types"],
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"id": "export_component_type",
|
||||
"name": "ComponentType",
|
||||
"kind": "type",
|
||||
"environments": ["esm", "cjs", "types"],
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"id": "export_size_variant",
|
||||
"name": "SizeVariant",
|
||||
"kind": "type",
|
||||
"environments": ["esm", "cjs", "types"],
|
||||
"default": false
|
||||
}
|
||||
],
|
||||
|
||||
"environments": {
|
||||
"esm": {
|
||||
"moduleSystem": "ES2015",
|
||||
"target": "ES2020"
|
||||
},
|
||||
"cjs": {
|
||||
"moduleSystem": "CommonJS",
|
||||
"target": "ES2015"
|
||||
},
|
||||
"types": {
|
||||
"moduleSystem": "ES2015",
|
||||
"target": "ESNext",
|
||||
"declarationOnly": true
|
||||
}
|
||||
},
|
||||
|
||||
"composition": [
|
||||
{
|
||||
"id": "button_props_composition",
|
||||
"name": "ButtonProps",
|
||||
"kind": "intersection",
|
||||
"types": [
|
||||
"BaseComponentProps",
|
||||
{
|
||||
"size": "SizeVariant",
|
||||
"variant": "ColorVariant",
|
||||
"disabled": "boolean",
|
||||
"onClick": "Callback"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user