mirror of
https://github.com/The-Low-Code-Foundation/OpenNoodl.git
synced 2026-03-07 17:43:28 +01:00
Task: STRUCT-003 Branch: cline-dev-dishant Cross-branch notes: none -- no shared dependencies with Richard phase 9/6 work - ProjectImporter class (pure, filesystem-agnostic) - Converts v2 multi-file format back to legacy project.json - unflattenNodes: reconstructs recursive tree from flat NodeV2 array (two-pass) - toLegacyName: uses preserved component.path for perfect round-trip fidelity - Metadata merge: routes/styles merged back into project.metadata - stateParameters -> stateParamaters reversal (legacy typo preserved) - Non-fatal warnings: component failures collected, not thrown - 55 unit tests in tests/io/ProjectImporter.test.ts - unflattenNodes: 11 cases - toLegacyName: 4 cases - ProjectImporter.import(): 20 cases - Round-trip (export -> import): 20 cases - Updated tests/io/index.ts to export importer tests - Updated PROGRESS-dishant.md: STRUCT-001/002/003 all marked complete
6.9 KiB
6.9 KiB
Phase 10A AI-Powered Development: Dishant Progress
Developer: Dishant
Branch: cline-dev-dishant
Last Updated: 2026-02-19
Task Status
| Task ID | Title | Status | Notes |
|---|---|---|---|
| STRUCT-001 | JSON Schema Definition | COMPLETE | 8 schemas + validator + tests (33/33 pass) |
| STRUCT-002 | Export Engine Core | COMPLETE | ProjectExporter + 50 unit tests |
| STRUCT-003 | Import Engine Core | COMPLETE | ProjectImporter + 55 unit tests incl. round-trip validation |
| STRUCT-004 | Editor Format Detection | TODO | Unblocked by STRUCT-003 |
| STRUCT-005 | Lazy Loading | TODO | Unblocked by STRUCT-004 |
| STRUCT-006 | Save Logic | TODO | Unblocked by STRUCT-005 |
| STRUCT-007 | Migration Wizard UI | TODO | Unblocked by STRUCT-006 |
| STRUCT-008 | Testing and Validation | TODO | Unblocked by STRUCT-007 |
| STRUCT-009 | Documentation | TODO | Unblocked by STRUCT-008 |
STRUCT-001 JSON Schema Definition COMPLETE
Completed: 2026-02-18
What was built
All files under packages/noodl-editor/src/editor/src/schemas/:
| File | Schema ID | Describes |
|---|---|---|
project-v2.schema.json |
https://opennoodl.dev/schemas/project-v2.json |
Root project metadata |
component.schema.json |
https://opennoodl.dev/schemas/component-v2.json |
Component metadata |
nodes.schema.json |
https://opennoodl.dev/schemas/nodes-v2.json |
Node graph definitions |
connections.schema.json |
https://opennoodl.dev/schemas/connections-v2.json |
Connection/wire definitions |
registry.schema.json |
https://opennoodl.dev/schemas/registry-v2.json |
Component index |
routes.schema.json |
https://opennoodl.dev/schemas/routes-v2.json |
URL route definitions |
styles.schema.json |
https://opennoodl.dev/schemas/styles-v2.json |
Global styles + variants |
model.schema.json |
https://opennoodl.dev/schemas/model-v2.json |
Backend data model definitions |
validator.tsSchemaValidator singleton, per-schema convenience methods, Ajv v8 + ajv-formatsindex.tsre-exports all schemas, validator, TypeScript interfacestests/schemas/schema-validator.test.ts33 test cases, all passing
Key decisions
additionalProperties: trueon nodes/connections open-ended by design- Port type is
oneOf [string, object]Noodl uses both formats strict: falseon Ajv schemas usedescriptionindefinitionsrequire()forajv-formatsavoids TS type conflict
STRUCT-002 Export Engine Core COMPLETE
Completed: 2026-02-19
What was built
| File | Purpose |
|---|---|
packages/noodl-editor/src/editor/src/io/ProjectExporter.ts |
Core exporter class + legacy types + helpers |
packages/noodl-editor/tests/io/ProjectExporter.test.ts |
50 unit tests |
packages/noodl-editor/tests/io/index.ts |
Test barrel export |
Architecture
ProjectExporter is pure no filesystem access. Takes LegacyProject, returns ExportResult { files[], stats }.
Output layout:
nodegx.project.json
nodegx.routes.json (conditional)
nodegx.styles.json (conditional)
components/
_registry.json
Header/
component.json
nodes.json
connections.json
Key decisions
- Pure/filesystem-agnostic caller writes files
- Node tree flattening recursive tree to flat array with parent/children IDs
- Styles/routes files conditional only produced when content exists
- Legacy
stateParamaterstypo normalised tostateParameters - Metadata split styles/routes extracted, rest stays in project file
- Original legacy path preserved in
component.jsonfor round-trip fidelity - Empty
parameters: {}omitted from output
STRUCT-003 Import Engine Core COMPLETE
Completed: 2026-02-19
What was built
| File | Purpose |
|---|---|
packages/noodl-editor/src/editor/src/io/ProjectImporter.ts |
Core importer class + helpers |
packages/noodl-editor/tests/io/ProjectImporter.test.ts |
55 unit tests incl. round-trip |
Architecture
ProjectImporter is pure no filesystem access. Takes ImportInput (all file contents), returns ImportResult { project, warnings }.
ImportInput {
project: ProjectV2File (nodegx.project.json)
registry: RegistryV2File (components/_registry.json)
routes?: RoutesV2File (nodegx.routes.json)
styles?: StylesV2File (nodegx.styles.json)
components: Record<path, { component, nodes, connections }>
}
Key functions exported
| Function | Purpose |
|---|---|
unflattenNodes(flat) |
Reconstructs recursive legacy node tree from flat NodeV2 array |
toLegacyName(componentFile, registryPath) |
Converts v2 path back to legacy name (uses preserved path field) |
Key decisions
- Pure/filesystem-agnostic symmetric with ProjectExporter
unflattenNodestwo-pass: build map, then wire children in ordertoLegacyNamepreferscomponent.path(preserved original) for perfect round-trip; falls back to reconstructionstateParametersstateParamatersreversal restores legacy typo- Metadata merge routes/styles merged back into
project.metadata - Non-fatal warnings component failures collected, not thrown
- Round-trip validated 20 round-trip tests covering all data types
Test coverage (55 tests)
unflattenNodes11 cases (empty, single, parent-child, deep nesting, order, field restoration)toLegacyName4 cases (path field, fallback, root, cloud)ProjectImporter.import()20 cases (basic, metadata, variants, components, nodes)- Round-trip (export import) 20 cases (all data types, edge cases)
Cross-branch note for Richard
No shared dependencies with Phase 9/6 work. STRUCT-003 is self-contained in packages/noodl-editor/src/editor/src/io/ and packages/noodl-editor/tests/io/. No cherry-pick needed.
Decisions and Learnings
- [2026-02-18] Ajv v8 + ajv-formats: use
require()for ajv-formats to avoid TS type conflict with root-level ajv-formats package - [2026-02-19] Legacy
stateParamaterstypo (missing 'e') is real must be preserved in round-trip. Exporter normalises tostateParameters, importer reverses it. - [2026-02-19]
component.pathfield is the key to perfect round-trip fidelity always preserve the original legacy name in the v2 component file - [2026-02-19]
unflattenNodesneeds two passes first build the node map, then wire children in order using the children ID array