Skip to content

Latest commit

 

History

History
225 lines (172 loc) · 9.03 KB

File metadata and controls

225 lines (172 loc) · 9.03 KB
outline
2
3
title Dart Code Generation Configuration
titleTemplate NpgsqlRest
description Generate Dart client code for Flutter from your PostgreSQL API. Auto-create type-safe request/response models and fetch functions from your database schema.
head
meta
name content
keywords
npgsqlrest dart, postgresql flutter, generate dart api client, flutter api client, postgresql to dart, auto-generate dart models
meta
property content
og:title
NpgsqlRest Dart Code Generation Configuration
meta
property content
og:description
Generate Dart client code for Flutter projects from your PostgreSQL API with typed models.
meta
property content
og:type
article

Dart Code Generation

Configuration for generating Dart client code for NpgsqlRest endpoints, targeting Flutter projects. Available since version 3.20.0 (NpgsqlRest.DartClient plugin).

The generated code depends only on package:http and works on all Flutter targets (mobile, desktop, web).

Overview

{
  "NpgsqlRest": {
    "DartClientCodeGen": {
      "Enabled": false,
      "FilePath": null,
      "FileOverwrite": true,
      "IncludeHost": true,
      "CustomHost": null,
      "CommentHeader": "Simple",
      "CommentHeaderIncludeComments": true,
      "BySchema": true,
      "IncludeStatusCode": true,
      "SeparateModelsFile": false,
      "ImportBaseUrlFrom": null,
      "HeaderLines": ["// autogenerated at {0}", ""],
      "SkipRoutineNames": [],
      "SkipFunctionNames": [],
      "SkipPaths": [],
      "SkipSchemas": [],
      "DefaultJsonType": "dynamic",
      "UseRoutineNameInsteadOfEndpoint": false,
      "ExportUrls": false,
      "UniqueModels": false,
      "XsrfTokenHeaderName": null,
      "ExportEventSources": true,
      "IncludeParseUrlParam": false,
      "IncludeParseRequestParam": false,
      "CustomImports": [],
      "CustomHeaders": {},
      "IncludeSchemaInNames": true,
      "ErrorTypeName": "ApiError",
      "ResultTypeName": "ApiResult",
      "OmitAutomaticParameters": false,
      "ModelPrefix": null,
      "ModelSuffix": null,
      "UseDateTimeType": true
    }
  }
}

Set Enabled to true and point FilePath at your Flutter project, e.g. "../my_app/lib/api/{0}.dart"{0} is the PostgreSQL schema name (snake case) or the module name from the dartclient_module annotation.

Generated code

For every endpoint the generator emits:

  • A request class with a toJson() method — one field per routine parameter, all optional named constructor parameters. Parameters with PostgreSQL defaults are omitted from the JSON body and query string when null, so the database default applies.
  • A response class with a fromJson() factory — one field per column (or a plain Dart type for scalar responses). Composite type columns become nested model classes.
  • An async function wrapping the HTTP call — query string, path parameters and JSON body handled automatically.
// generated
Future<List<SearchItemsResponse>> searchItems(SearchItemsRequest request) async {
  final uri = Uri.parse('$baseUrl/api/search-items' + _query({
    'query': request.query,
    'page': request.page,
    if (request.limit != null) 'limit': request.limit,
  }));
  final response = await _send('GET', uri, ...);
  return (jsonDecode(utf8.decode(response.bodyBytes)) as List)
      .map((e) => SearchItemsResponse.fromJson(e as Map<String, dynamic>))
      .toList();
}

With IncludeStatusCode (or the dartclient_status_code annotation), responses are wrapped as ApiResult<T> with the HTTP status code and a problem-details ApiError:

final result = await searchItems(SearchItemsRequest(query: 'a', page: 1));
if (result.ok) {
  print(result.response);
} else {
  print('${result.status}: ${result.error?.title}');
}

Upload endpoints generate multipart functions (http.MultipartRequest, files sent as form field file, an optional progress callback reporting uploaded bytes, optional XSRF token header). Login endpoints return the token String; logout endpoints return void. proxy_out and void proxy pass-through endpoints return Future<http.Response> directly.

Server-sent events

SSE endpoints generate a create{Name}EventSource factory returning an SseSubscription (built on streamed package:http responses — no extra dependency) and an SSE-aware function:

final result = await sseEndpoint(
  SseEndpointRequest(message: 'hello'),
  onMessage: (message) => print('event: $message'),
);

The function opens the event stream with a generated execution id, waits awaitConnectionMs, sends the request with the execution-id header attached, and closes the stream closeAfterMs milliseconds after the response — the same lifecycle as the TypeScript client. Use the factory directly for long-lived subscriptions:

final events = await createSseEndpointEventSource((message) => print(message));
// ...
await events.close();

baseUrl and testing

Each generated module declares:

String baseUrl = '';        // set per flavor/environment at app startup

/// Override to inject a custom [http.Client] (e.g. MockClient in tests).
http.Client? httpClient;

In widget or unit tests, assign a MockClient from package:http/testing.dart to httpClient to intercept all requests.

Type mapping

PostgreSQL Dart
smallint, integer, bigint int
real, double precision, numeric, money double
boolean bool
json, jsonb dynamic (configurable via DefaultJsonType)
date, timestamp, timestamptz DateTime (configurable via UseDateTimeType)
everything else (text, uuid, time, interval, ranges, ...) String
arrays List<T>

All model fields are nullable (T?). snake_case names become lowerCamelCase fields with the raw wire name kept as the JSON key. Dart reserved words and dart:core type names are escaped with a trailing underscore (classclass_).

Comment annotations

Per-endpoint overrides in routine comments:

Annotation Description
dartclient = off Exclude the endpoint from generation.
dartclient_module=name Group the endpoint into module file name. Falls back to tsclient_module, so SQL-file directory grouping applies to both generators.
dartclient_status_code=true Wrap this endpoint's response in ApiResult<T>.
dartclient_events=false Generate a plain function for an SSE endpoint (no event-source parameters).
dartclient_parse_url=true / dartclient_parse_request=true Add the per-call parseUrl/parseRequest rewrite hooks to this endpoint.
dartclient_export_url=true Also emit a {name}Url() URL-builder function.
dartclient_url_only=true Emit only the URL-builder function.

Options

Options mirror the TypeScript code generation options where applicable. Dart-specific options:

SeparateModelsFile

  • Type: boolean
  • Default: false

Emit request/response (and composite) model classes into a separate {name}_models.dart file. The client file imports and re-exports the models file so consumers keep a single import.

ModelPrefix / ModelSuffix

  • Type: string | null
  • Default: null

Prefix/suffix for generated model class names, useful to avoid class-name collisions when importing several generated modules into one file.

UseDateTimeType

  • Type: boolean
  • Default: true

When true, date, timestamp and timestamptz values map to Dart DateTime (parsed with DateTime.parse, serialized with toIso8601String). When false, they map to String.

ErrorTypeName / ResultTypeName

  • Type: string
  • Default: "ApiError" / "ApiResult"

Names of the generated status-wrapper classes. Only used when IncludeStatusCode is true.

ExportEventSources

  • Type: boolean
  • Default: true

Emit public create{Name}EventSource factory functions for SSE endpoints. When false, the factories get a private (underscore) name and are only used internally — the Dart analog of not exporting them.

IncludeParseUrlParam / IncludeParseRequestParam

  • Type: boolean
  • Default: false

Add optional named parameters Uri Function(Uri uri)? parseUrl and http.Request Function(http.Request request)? parseRequest (http.MultipartRequest variant for uploads) that can rewrite the URI or request before it is sent. For intercepting every request globally, prefer assigning a custom httpClient.

Known limits

  • numeric/money map to double — arbitrary precision beyond IEEE 754 is lost. Dart int on Flutter Web is limited to 2^53.
  • Multi-dimensional arrays are typed as one-dimensional List<T> (PostgreSQL does not expose array dimensionality — same limitation as the TypeScript client).

Related