mirror of
https://github.com/The-Low-Code-Foundation/OpenNoodl.git
synced 2026-01-13 07:42:55 +01:00
257 lines
8.1 KiB
Markdown
257 lines
8.1 KiB
Markdown
# CONFIG-001: Core Infrastructure - CHANGELOG
|
|
|
|
**Status:** ✅ COMPLETE
|
|
**Date Completed:** January 7, 2026
|
|
**Implementation Time:** ~3 hours
|
|
|
|
## Overview
|
|
|
|
Implemented the complete backend infrastructure for the App Config System. This provides immutable, type-safe configuration values accessible via `Noodl.Config` at runtime.
|
|
|
|
---
|
|
|
|
## Files Created
|
|
|
|
### Core Config System
|
|
|
|
1. **`packages/noodl-runtime/src/config/types.ts`**
|
|
|
|
- TypeScript interfaces: `AppConfig`, `ConfigVariable`, `AppIdentity`, `AppSEO`, `AppPWA`
|
|
- `DEFAULT_APP_CONFIG` constant
|
|
- `RESERVED_CONFIG_KEYS` array (prevents variable naming conflicts)
|
|
|
|
2. **`packages/noodl-runtime/src/config/validation.ts`**
|
|
|
|
- `validateConfigKey()` - Validates JavaScript identifiers, checks reserved words
|
|
- `validateConfigValue()` - Type-specific validation (string, number, boolean, color, array, object)
|
|
- `validateAppConfig()` - Full config structure validation
|
|
- Support for: min/max ranges, regex patterns, required fields
|
|
|
|
3. **`packages/noodl-runtime/src/config/config-manager.ts`**
|
|
|
|
- Singleton `ConfigManager` class
|
|
- `initialize()` - Loads config from project metadata
|
|
- `getConfig()` - Returns deeply frozen/immutable config object
|
|
- `getRawConfig()` - Returns full structure (for editor)
|
|
- `getVariable()`, `getVariableKeys()` - Variable access helpers
|
|
- Smart defaults: SEO fields auto-populate from identity values
|
|
|
|
4. **`packages/noodl-runtime/src/config/index.ts`**
|
|
- Clean exports for all config modules
|
|
|
|
### API Integration
|
|
|
|
5. **`packages/noodl-viewer-react/src/api/config.ts`**
|
|
- `createConfigAPI()` - Returns immutable Proxy object
|
|
- Helpful error messages on write attempts
|
|
- Warns when accessing undefined config keys
|
|
|
|
### Runtime Integration
|
|
|
|
6. **Modified: `packages/noodl-viewer-react/src/noodl-js-api.js`**
|
|
- Added `configManager` import
|
|
- Initializes ConfigManager from `metadata.appConfig` at runtime startup
|
|
- Exposes `Noodl.Config` globally
|
|
|
|
### ProjectModel Integration
|
|
|
|
7. **Modified: `packages/noodl-editor/src/editor/src/models/projectmodel.ts`**
|
|
- `getAppConfig()` - Retrieves config from metadata
|
|
- `setAppConfig(config)` - Saves config to metadata
|
|
- `updateAppConfig(updates)` - Partial updates with smart merging
|
|
- `getConfigVariables()` - Returns all custom variables
|
|
- `setConfigVariable(variable)` - Adds/updates a variable
|
|
- `removeConfigVariable(key)` - Removes a variable by key
|
|
|
|
### Type Declarations
|
|
|
|
8. **Modified: `packages/noodl-viewer-react/typings/global.d.ts`**
|
|
- Added `Config: Readonly<Record<string, unknown>>` to `GlobalNoodl`
|
|
- Includes JSDoc with usage examples
|
|
|
|
### Tests
|
|
|
|
9. **`packages/noodl-runtime/src/config/validation.test.ts`**
|
|
|
|
- 150+ test cases covering all validation functions
|
|
- Tests for: valid/invalid keys, all value types, edge cases, error messages
|
|
|
|
10. **`packages/noodl-runtime/src/config/config-manager.test.ts`**
|
|
- 70+ test cases covering ConfigManager functionality
|
|
- Tests for: singleton pattern, initialization, immutability, smart defaults, variable access
|
|
|
|
---
|
|
|
|
## Technical Implementation Details
|
|
|
|
### Immutability Strategy
|
|
|
|
- **Deep Freeze:** Recursively freezes config object and all nested properties
|
|
- **Proxy Protection:** Proxy intercepts set/delete attempts with helpful errors
|
|
- **Read-Only TypeScript Types:** Enforces immutability at compile time
|
|
|
|
### Smart Defaults
|
|
|
|
SEO fields automatically default to identity values when not explicitly set:
|
|
|
|
- `ogTitle` → `identity.appName`
|
|
- `ogDescription` → `identity.description`
|
|
- `ogImage` → `identity.coverImage`
|
|
|
|
### Reserved Keys
|
|
|
|
Protected system keys that cannot be used for custom variables:
|
|
|
|
- Identity: `appName`, `description`, `coverImage`
|
|
- SEO: `ogTitle`, `ogDescription`, `ogImage`, `favicon`, `themeColor`
|
|
- PWA: `pwaEnabled`, `pwaShortName`, `pwaDisplay`, `pwaStartUrl`, `pwaBackgroundColor`
|
|
|
|
### Validation Rules
|
|
|
|
- **Keys:** Must be valid JavaScript identifiers (`/^[a-zA-Z_$][a-zA-Z0-9_$]*$/`)
|
|
- **String:** Optional regex pattern matching
|
|
- **Number:** Optional min/max ranges
|
|
- **Color:** Must be hex format (`#RRGGBB` or `#RRGGBBAA`)
|
|
- **Array/Object:** Type checking only
|
|
- **Required:** Enforced across all types
|
|
|
|
---
|
|
|
|
## Usage Example
|
|
|
|
```typescript
|
|
// In project.json metadata:
|
|
{
|
|
"metadata": {
|
|
"appConfig": {
|
|
"identity": {
|
|
"appName": "My App",
|
|
"description": "A great app"
|
|
},
|
|
"seo": {
|
|
"ogTitle": "My App - The Best",
|
|
"favicon": "/favicon.ico"
|
|
},
|
|
"variables": [
|
|
{ "key": "apiKey", "type": "string", "value": "abc123", "description": "API Key" },
|
|
{ "key": "maxRetries", "type": "number", "value": 3 },
|
|
{ "key": "debugMode", "type": "boolean", "value": false }
|
|
]
|
|
}
|
|
}
|
|
}
|
|
|
|
// In runtime/deployed app:
|
|
const apiKey = Noodl.Config.apiKey; // "abc123"
|
|
const appName = Noodl.Config.appName; // "My App"
|
|
const maxRetries = Noodl.Config.maxRetries; // 3
|
|
const debugMode = Noodl.Config.debugMode; // false
|
|
|
|
// Attempts to modify throw errors:
|
|
Noodl.Config.apiKey = "new"; // ❌ TypeError: Cannot assign to read-only property
|
|
```
|
|
|
|
---
|
|
|
|
## Success Criteria - All Met ✅
|
|
|
|
- [x] Config values stored in `project.json` metadata (`metadata.appConfig`)
|
|
- [x] Immutable at runtime (deep freeze + proxy protection)
|
|
- [x] Accessible via `Noodl.Config.variableName` syntax
|
|
- [x] Type-safe with full TypeScript definitions
|
|
- [x] Validation for keys (JS identifiers, reserved check)
|
|
- [x] Validation for values (type-specific rules)
|
|
- [x] ProjectModel methods for editor integration
|
|
- [x] Smart defaults for SEO fields
|
|
- [x] Comprehensive unit tests (220+ test cases)
|
|
- [x] Documentation and examples
|
|
|
|
---
|
|
|
|
## Testing
|
|
|
|
### Run Tests
|
|
|
|
```bash
|
|
# Run all config tests
|
|
npm test -- --testPathPattern=config
|
|
|
|
# Run specific test files
|
|
npm test packages/noodl-runtime/src/config/validation.test.ts
|
|
npm test packages/noodl-runtime/src/config/config-manager.test.ts
|
|
```
|
|
|
|
### Test Coverage
|
|
|
|
- **Validation:** 150+ tests
|
|
- **ConfigManager:** 70+ tests
|
|
- **Total:** 220+ test cases
|
|
- **Coverage:** All public APIs, edge cases, error conditions
|
|
|
|
---
|
|
|
|
## Next Steps
|
|
|
|
**CONFIG-002: UI Panel Implementation**
|
|
|
|
- App Setup panel in editor sidebar
|
|
- Identity tab (app name, description, cover image)
|
|
- SEO tab (Open Graph, favicon, theme color)
|
|
- PWA tab (enable PWA, configuration)
|
|
- Variables tab (add/edit/delete custom config variables)
|
|
- Real-time validation with helpful error messages
|
|
|
|
---
|
|
|
|
## Migration Notes
|
|
|
|
**For Existing Projects:**
|
|
|
|
- Config is optional - projects without `metadata.appConfig` use defaults
|
|
- No breaking changes - existing projects continue to work
|
|
- Config can be added gradually through editor UI (once CONFIG-002 is complete)
|
|
|
|
**For Developers:**
|
|
|
|
- Import types from `@noodl/runtime/src/config`
|
|
- Access config via `Noodl.Config` at runtime
|
|
- Use ProjectModel methods for editor integration
|
|
- Validation functions available for custom UIs
|
|
|
|
---
|
|
|
|
## Known Limitations
|
|
|
|
1. **No Runtime Updates:** Config is initialized once at app startup (by design - values are meant to be static)
|
|
2. **No Type Inference:** `Noodl.Config` returns `unknown` - developers must know types (can be improved with code generation in future)
|
|
3. **No Nested Objects:** Variables are flat (arrays/objects supported but not deeply nested structures)
|
|
|
|
---
|
|
|
|
## Performance Considerations
|
|
|
|
- **Initialization:** One-time cost at app startup (~1ms for typical configs)
|
|
- **Access:** O(1) property access (standard JS object lookup)
|
|
- **Memory:** Config frozen in memory (minimal overhead, shared across all accesses)
|
|
- **Validation:** Only runs in editor, not at runtime
|
|
|
|
---
|
|
|
|
## Related Files Modified
|
|
|
|
- `packages/noodl-viewer-react/src/noodl-js-api.js` - Added ConfigManager initialization
|
|
- `packages/noodl-editor/src/editor/src/models/projectmodel.ts` - Added config methods
|
|
- `packages/noodl-viewer-react/typings/global.d.ts` - Added Config type declaration
|
|
|
|
---
|
|
|
|
## Git Commits
|
|
|
|
All changes committed with descriptive messages following conventional commits format:
|
|
|
|
- `feat(config): add core config infrastructure`
|
|
- `feat(config): integrate ConfigManager with runtime`
|
|
- `feat(config): add ProjectModel config methods`
|
|
- `test(config): add comprehensive unit tests`
|
|
- `docs(config): add type declarations and examples`
|