Files
OpenNoodl/dev-docs/tasks/phase-10-ai-powered-development/PROGRESS-dishant.md
dishant-kumar-thakur d54e2a55a0 feat(phase-10): STRUCT-003 import engine core
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
2026-02-19 01:07:22 +05:30

159 lines
6.9 KiB
Markdown

# 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.ts` SchemaValidator singleton, per-schema convenience methods, Ajv v8 + ajv-formats
- `index.ts` re-exports all schemas, validator, TypeScript interfaces
- `tests/schemas/schema-validator.test.ts` 33 test cases, all passing
### Key decisions
- `additionalProperties: true` on nodes/connections open-ended by design
- Port type is `oneOf [string, object]` Noodl uses both formats
- `strict: false` on Ajv schemas use `description` in `definitions`
- `require()` for `ajv-formats` avoids 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
1. Pure/filesystem-agnostic caller writes files
2. Node tree flattening recursive tree to flat array with parent/children IDs
3. Styles/routes files conditional only produced when content exists
4. Legacy `stateParamaters` typo normalised to `stateParameters`
5. Metadata split styles/routes extracted, rest stays in project file
6. Original legacy path preserved in `component.json` for round-trip fidelity
7. 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
1. Pure/filesystem-agnostic symmetric with ProjectExporter
2. `unflattenNodes` two-pass: build map, then wire children in order
3. `toLegacyName` prefers `component.path` (preserved original) for perfect round-trip; falls back to reconstruction
4. `stateParameters` `stateParamaters` reversal restores legacy typo
5. Metadata merge routes/styles merged back into `project.metadata`
6. Non-fatal warnings component failures collected, not thrown
7. Round-trip validated 20 round-trip tests covering all data types
### Test coverage (55 tests)
- `unflattenNodes` 11 cases (empty, single, parent-child, deep nesting, order, field restoration)
- `toLegacyName` 4 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 `stateParamaters` typo (missing 'e') is real must be preserved in round-trip. Exporter normalises to `stateParameters`, importer reverses it.
- **[2026-02-19]** `component.path` field is the key to perfect round-trip fidelity always preserve the original legacy name in the v2 component file
- **[2026-02-19]** `unflattenNodes` needs two passes first build the node map, then wire children in order using the children ID array