Phase 3 successfully integrated the TypeScript transformer into the sync package, replacing JSON workflow storage with TypeScript .workflow.ts files.
File: packages/sync/src/services/workflow-transformer-adapter.ts
Adapter class bridging the sync package and transformer package:
convertToTypeScript(workflow, options)- Convert n8n JSON to TypeScriptcompileToJson(tsContent)- Compile TypeScript back to n8n JSONhashWorkflow(tsContent)- Hash TypeScript by compiling to normalized JSONhashWorkflowFromJson(workflow)- Hash remote workflows not yet savedconvertToIWorkflow(workflow)- Convert N8nWorkflow tags (string[]) to IWorkflow tags (ITag[])
File: packages/sync/src/services/sync-engine.ts
Modified to work with TypeScript files:
- Changed import:
WorkflowSanitizer→WorkflowTransformerAdapter executePull()- Now writes TypeScript files instead of JSONexecuteUpdate()- Compiles TS→JSON for API push, writes TS backexecuteCreate()- Compiles TS→JSON for API create, writes TS backreadJsonFile()→readTypeScriptFile()- Reads raw TypeScript content
File: packages/sync/src/services/watcher.ts
Modified to observe and hash TypeScript files:
- Changed import:
WorkflowSanitizer→WorkflowTransformerAdapter - File extension filter:
.json→.workflow.ts(5 occurrences) - Filename generation:
${name}.json→${name}.workflow.ts - Filename parsing:
.replace('.json', '')→.replace('.workflow.ts', '') readJsonFile()- Now extracts workflow ID via regex for TypeScript filesreadWorkflowFile()- New async method for full workflow compilationwriteWorkflowFile()- Now writes TypeScript instead of JSONrefreshLocalState()- UseshashWorkflow()for TypeScript files- Archive operations - Archives now saved as TypeScript
- All hash calculations - Replaced
WorkflowSanitizer.cleanForHash()withWorkflowTransformerAdapter.hashWorkflow()orhashWorkflowFromJson()
File: packages/sync/package.json
Added transformer dependency:
"dependencies": {
"@n8n-as-code/transformer": "0.1.0",
...
}To ensure consistent hashing between local TypeScript and remote JSON workflows:
- Local files: Read TS → Compile to JSON → Normalize → Hash
- Remote workflows: Normalize JSON → Hash
- Normalization: Removes volatile fields (versionId, projectId, etc.)
This guarantees that TypeScript and JSON representations of the same workflow produce identical hashes.
Many methods became async to support TypeScript compilation:
refreshLocalState()- Already async, now uses async hash computationonLocalChange()- Already async, now uses async hash computationresolveDuplicateIds()- Made async for hash computationwriteWorkflowFile()- Made async for TypeScript generation
For quick ID extraction (avoiding full compilation):
// Quick regex extraction from @workflow({ id: "..." })
const idMatch = content.match(/@workflow\s*\(\s*{\s*id:\s*["']([^"']+)["']/);- Before:
my-workflow.json(JSON format) - After:
my-workflow.workflow.ts(TypeScript with decorators)
- Existing
.jsonworkflow files will NOT be automatically migrated - Users need to manually convert or re-pull workflows
.n8n-state.jsonmay need reset if filenames change
- Archives in
.trash/now stored as TypeScript files - Existing JSON archives remain readable but new ones use
.workflow.ts
npm run build -w @n8n-as-code/transformer ✅
npm run build -w @n8n-as-code/sync ✅- No TypeScript compilation errors
- Proper type conversion between
N8nWorkflowandIWorkflow - Tag conversion:
string[]→ITag[]handled correctly
Phase 4: Adapt the skills package to:
- Generate TypeScript documentation instead of JSON
- Update workflow templates to TypeScript format
- Modify n8n-agent to work with
.workflow.tsfiles
Phase 5: Adapt CLI commands:
n8nac validate- Validate TypeScript syntaxn8nac convert- Convert JSON ↔ TypeScript
Phase 6: Documentation and integration testing:
- Update README with TypeScript examples
- Create migration guide for JSON → TypeScript
- E2E tests for pull/push/sync cycle with TypeScript files