Skip to content

feat: Node.js server target — compile Dart APIs to Node.js#17

Merged
flutterjs-dev merged 6 commits intomasterfrom
feat/package_nav
Feb 17, 2026
Merged

feat: Node.js server target — compile Dart APIs to Node.js#17
flutterjs-dev merged 6 commits intomasterfrom
feat/package_nav

Conversation

@flutterjs-dev
Copy link
Collaborator

Adds a full Node.js server compilation target to FlutterJS, enabling developers to write Dart REST APIs and compile them directly to Node.js JavaScript. Includes the flutterjs_server package, a working dart_api example, and all the compiler fixes needed to make server-side code generation reliable.

🔗 Related Issue

Fixes # (none — new feature)

🏗️ Type of Change

  • ✨ New feature (non-breaking change which adds functionality)
  • 🐛 Bug fix (non-breaking change which fixes an issue)

What's New

flutterjs_server Package

A new Dart package + JS runtime for writing HTTP servers in Dart:

  • FlutterjsServer — HTTP server with port configuration
  • Router — route registration (add, mount)
  • Request / Response — request/response model with ok, created, notFound, badRequest, noContent factories
  • cors() / logger() / bearerAuth() — built-in middleware

dart_api Example

A complete REST API demo compiled from Dart → Node.js:

  • GET / — welcome message
  • GET /health — health check
  • GET /users / GET /users/:id — list and get users
  • POST /users — create user
  • DELETE /users/:id — delete user

Compiler Fixes

Import generation:

  • CascadeExpressionIR now scanned in ImportAnalyzer and FileCodeGen — cascade chains like server..use(cors())..use(logger()) now correctly detect and import cors/logger
  • GlobalSymbolTable wired to ModelToJSPipeline after package manifests load (was empty before, causing missing imports)
  • PackageRegistry.buildGlobalSymbolTable() maps symbols to full package: URIs for correct path resolution

Code generation:

  • Dart == null / != null now generates loose JS == null to catch both null and undefined
  • as Map<String, dynamic> cast uses typeof x === 'object' && !Array.isArray(x) instead of broken instanceof Map
  • Removed hardcoded identifier→this.identifier hacks that broke local variables
  • Added EnumDecl IR node and EnumCodeGenerator for proper enum → JS object output
  • Added ImportExportTracker and ImportExportModel for accurate cross-file import analysis

Node target pipeline:

  • PackageRegistry: skips web-only @flutterjs packages (material, widgets, vdom, seo, rendering, etc.) when --target node to prevent symbol table pollution
  • RuntimePackageManager: when linking @flutterjs/X, also links as flutterjs_X in root node_modules so generated import 'flutterjs_server' resolves
  • RunCommand: auto-creates node_modules junctions before starting the node server — no flutterjs get required for basic use

📋 Checklist

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • My changes generate no new warnings
  • The dart_api example compiles and all endpoints pass smoke tests

🧪 How to Test

# 1. From the repo root, run the dart_api example
cd examples/dart_api
dart run ../../bin/flutterjs.dart run --to-js --target node --serve --devtools-no-open

# 2. Test the endpoints
curl http://localhost:3000/
curl http://localhost:3000/health
curl http://localhost:3000/users
curl http://localhost:3000/users/1
curl http://localhost:3000/users/99          # → 404
curl -X POST http://localhost:3000/users \
     -H "Content-Type: application/json" \
     -d '{"name":"Dave","email":"dave@example.com"}'
curl -X DELETE http://localhost:3000/users/2

Expected: All endpoints return correct JSON with appropriate HTTP status codes (200, 201, 204, 404).

jaypal1046 and others added 6 commits February 9, 2026 00:50
Refactor package compiler to accept dependencyPaths and build a global symbol table from dependencies' exports.json (prefers explicit URIs, falls back to inferred package: URIs). Split file processing into _parseFile and _generateJS phases, populate local exports into the global table, and run JS generation with an updated importRewriter that preserves package: URIs (converts .dart -> .js). Add verbose/debug logging and diagnostics for symbol resolution and package scanning. Fix declaration extraction: propagate extension-type metadata, log debug info, and record generic typedefs. Also include many generated JS artifacts, source maps and package metadata updates (exports.json / package.json) across flutterjs_dart, foundation, services, widgets, engine, gen, runtime, tools and other packages.
… target

- run_command.dart: add _ensureNodeModulesForNodeTarget() — creates
  node_modules/flutterjs_X junctions before launching node server so
  `import 'flutterjs_server'` resolves without requiring `flutterjs get`
- code_pipleiline.dart: skip web-only @flutterjs packages (material,
  widgets, vdom, seo, etc.) from PackageRegistry when target is node,
  preventing symbol table pollution with browser-only widget names
- runtime_package_manager.dart: when linking @flutterjs/X SDK packages
  also link under the Dart name (flutterjs_X) in root node_modules

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…ge improvements

Core compiler:
- Add ImportExportTracker and ImportExportModel for accurate cross-file import analysis
- Add EnumDecl IR node and EnumCodeGenerator for proper enum → JS object translation
- Fix CascadeExpressionIR scanning in ImportAnalyzer and FileCodeGen
- Fix null comparison semantics (== null uses loose equality to catch undefined)
- Fix Map cast to use typeof check instead of instanceof Map
- Remove hardcoded identifier hacks in ExpressionCodeGenerator

Node.js server target:
- Add flutterjs_server package (Dart API + JS runtime with HTTP server, router, middleware)
- Add dart_api example: full REST API demo compiled from Dart to Node.js
- PackageRegistry: filter web-only @flutterjs packages for node target builds
- RuntimePackageManager: also link @flutterjs/X as flutterjs_X in root node_modules
- RunCommand: auto-link node_modules before starting node server (_ensureNodeModulesForNodeTarget)

Import generation:
- GlobalSymbolTable wired to ModelToJSPipeline after package manifests load
- PackageRegistry.buildGlobalSymbolTable() maps symbols to full package: URIs
- Fix hardcoded material imports registered in symbolToPath to prevent duplicates

Package updates:
- flutterjs_foundation, flutterjs_gestures, flutterjs_material, flutterjs_services,
  flutterjs_widgets: updated exports.json, build.js, src/index.js
- flutterjs_dart: add ui_web dist, pubspec.yaml
- flutter_web_plugins: add JS package
- Add tool/ scripts for build, check, fix-imports, reset

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@flutterjs-dev flutterjs-dev merged commit c48bcdf into master Feb 17, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants