Skip to content

Add Flutter client factory surface#1510

Closed
ChiragAgg5k wants to merge 3 commits intomasterfrom
feat/flutter-client-auth-factories
Closed

Add Flutter client factory surface#1510
ChiragAgg5k wants to merge 3 commits intomasterfrom
feat/flutter-client-auth-factories

Conversation

@ChiragAgg5k
Copy link
Copy Markdown
Member

@ChiragAgg5k ChiragAgg5k commented May 6, 2026

Summary

Adds the same client-side auth factory pattern to the generated Flutter SDK, scoped only to Flutter client output. The new factories provide a narrower public ClientAuth surface for factory-created clients while preserving the existing Client() constructor/setter style for compatibility.

The recommended Flutter setup is now:

import 'package:appwrite/appwrite.dart';

final client = Client.fromBrowser(
  endPoint: 'https://<REGION>.cloud.appwrite.io/v1',
  projectId: '<PROJECT_ID>',
);

final account = Account(client);

The old syntax is still supported:

final client = Client()
  ..setEndpoint('https://<REGION>.cloud.appwrite.io/v1')
  ..setProject('<PROJECT_ID>');

Those legacy setter methods are now marked @Deprecated. They remain available from Client(), but factory-created clients are inferred as ClientAuth and do not expose legacy setters.

Auth Factories

All factories use named parameters. Common fields include endPoint, projectId, endPointRealtime, locale, and selfSigned.

Available Flutter client factories:

Factory Auth/runtime Notes
Client.fromBrowser(...) browser/mobile client Normal Flutter client setup. Sets endpoint and project, and optionally realtime endpoint, locale, and self-signed behavior.
Client.fromSession(...) session client Sends X-Appwrite-Session; useful when a session secret is explicitly available.
Client.fromDevKey(...) dev key client Client-tier dev key usage.
Client.fromImpersonation(...) impersonation client Requires session and exactly one of userId, userEmail, or userPhone.

This PR intentionally does not add server-side factories such as API key, JWT, or cookie factories to Flutter. It only updates the client-side Flutter SDK surface.

Type Safety

Dart does not have the same conditional type machinery used by the Web SDK, so this PR uses nominal interfaces instead:

abstract class ClientAuth {
  Map<String, String> get config;
  String get endPoint;
  String? get endPointRealtime;

  Future<Response> call(...);
  Future<Response> chunkedUpload(...);
  Future webAuth(...);
  Future<String> ping();
}

abstract class Client implements ClientAuth {
  factory Client(...);

  static ClientAuth fromBrowser(...);
  static ClientAuth fromSession(...);
  static ClientAuth fromDevKey(...);
  static ClientAuth fromImpersonation(...);

  @Deprecated(...)
  Client setProject(String value);
}

That means:

  • Client() keeps the full legacy Client type and can still call setters.
  • Client.fromBrowser(...) and the other factories return ClientAuth, so setters are not visible on inferred factory clients.
  • Generated services accept ClientAuth, so both legacy and factory-created clients keep the same service construction syntax.
  • Generated services store their client as private _client, so public .client access is hidden.
  • Realtime also accepts ClientAuth, so factory-created clients work with Realtime(client).

Examples:

final oldClient = Client()
  ..setEndpoint(endPoint)
  ..setProject(projectId); // OK, deprecated

final browserClient = Client.fromBrowser(
  endPoint: endPoint,
  projectId: projectId,
);

Account(oldClient);      // OK
Account(browserClient);  // OK
Realtime(browserClient); // OK

browserClient.setProject('other'); // Analyzer error
Account(browserClient).client;     // Analyzer error

Implementation Details

File Change
templates/flutter/lib/src/client.dart.twig Adds ClientAuth, static client factories, deprecated legacy setters, and keeps Client() compatibility.
templates/flutter/lib/src/client_base.dart.twig Marks generated setter overrides as deprecated while keeping chainable legacy behavior.
templates/flutter/lib/src/client_browser.dart.twig Marks browser runtime setters as deprecated.
templates/flutter/lib/src/client_io.dart.twig Marks IO runtime setters as deprecated.
templates/flutter/lib/src/service.dart.twig Adds a Flutter-specific service base that accepts ClientAuth and does not expose a public client field.
src/SDK/Language/Flutter.php Switches Flutter to the Flutter-specific service base template instead of the shared Dart service base.
templates/flutter/lib/services/service.dart.twig Generates services with private _client and ClientAuth constructors while preserving Service(client) syntax.
templates/flutter/base/requests/*.twig Updates generated service request code to use private _client.
templates/flutter/lib/src/realtime*.twig Updates Realtime factory/base/mixin implementations to accept ClientAuth.
templates/flutter/lib/package.dart.twig Imports src/client.dart into the library so service part files can reference ClientAuth.

Compatibility Notes

  • Client().setEndpoint(...).setProject(...) still works.
  • Legacy setters are deprecated to guide new code toward static factories.
  • Legacy setters are intentionally not visible on Client.fromBrowser(...), Client.fromSession(...), Client.fromDevKey(...), or Client.fromImpersonation(...) results.
  • Generated service construction syntax stays unchanged: Account(client), TablesDB(client), Realtime(client), etc.
  • Generated services no longer expose a public .client property.
  • This PR is Flutter-client-only. It does not modify the generated Dart server SDK behavior and does not introduce server auth factories for Flutter.

Validation

Validation performed on this branch:

  • php example.php flutter client
  • composer lint-twig
  • php -l src/SDK/Language/Flutter.php
  • git diff --check
  • flutter analyze --no-fatal-warnings --no-fatal-infos in examples/flutter
    • no analyzer errors from this change
    • existing warnings/infos remain in generated Flutter output
  • Focused Dart analyzer smoke checks covering:
    • legacy setters remain valid from Client() and are reported as deprecated
    • factory-created clients can be passed to generated services
    • factory-created clients can be passed to Realtime
    • Client.fromBrowser(...).setProject(...) is rejected
    • Account(Client.fromBrowser(...)).client is rejected

Full flutter test was also run. It currently fails in two generated OAuth service fixture tests:

  • Account.createOAuth2Session() expects Session but mocked webAuth returns null
  • Account.createOAuth2Token() expects Token but mocked webAuth returns null

Those failures are unrelated to the client surface changes in this PR.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 6, 2026

Greptile Summary

This PR adds a narrower ClientAuth public surface and four static factory constructors (fromBrowser, fromSession, fromDevKey, fromImpersonation) to the generated Flutter SDK, while deprecating the legacy mutable setter chain. Generated services and Realtime are updated to accept ClientAuth everywhere, hiding the public .client field from service instances.

  • ClientAuth interface carries only the read operations and HTTP primitives; Client retains the deprecated setters, preserving full backward compatibility while preventing new code from reaching them through factory-constructed clients.
  • RealtimeBrowser and RealtimeIO constructors now validate the concrete type at construction time with a descriptive ArgumentError, resolving the previously noted unsafe-downcast concern.
  • All _client renames across request templates align with the new private field on generated service classes.

Confidence Score: 5/5

Safe to merge — the factory surface is additive, the legacy setter path still works end-to-end, and the Realtime type guards address the previously flagged downcast issue.

All changed code paths have been validated: factory methods build on the same createClient foundation, deprecated setters remain functional, and the is!-guard pattern in both Realtime constructors ensures the previously unsafe casts are now reliably preceded by a descriptive error. No logic defects were found in the templates.

No files require special attention. The only notes are stylistic improvements to the repeated casts in realtime_io.dart.twig and realtime_browser.dart.twig.

Important Files Changed

Filename Overview
templates/flutter/lib/src/client.dart.twig Major rework: introduces ClientAuth narrow interface, Client as concrete legacy hierarchy, and four static factory methods. Deprecation annotations on all legacy setters; factory helper _fromBrowserClient is shared base for all factories.
templates/flutter/lib/src/service.dart.twig New Flutter-specific service base class that accepts ClientAuth and intentionally discards the parameter (named _); concrete services store their own _client.
templates/flutter/lib/services/service.dart.twig Generated services now declare final ClientAuth _client and pass client to super() via the // ignore: use_super_parameters pattern; removes public .client exposure.
templates/flutter/lib/src/realtime_browser.dart.twig Constructor widened to ClientAuth with an immediate is! ClientBrowser guard that throws a descriptive ArgumentError, resolving the previously flagged unsafe-downcast issue.
templates/flutter/lib/src/realtime_io.dart.twig Same pattern as realtime_browser.dart.twig: constructor widened to ClientAuth with is! ClientIO guard. _getWebSocket still uses repeated (client as ClientIO) casts which are now safe but verbose.
src/SDK/Language/Flutter.php Single line change: switches the lib/src/service.dart generation from the shared dart/ template to the new Flutter-specific flutter/lib/src/service.dart.twig.
templates/flutter/lib/package.dart.twig Adds import 'src/client.dart'; so part service files can reference ClientAuth directly; trailing-newline fix also included.
templates/flutter/lib/src/realtime_mixin.dart.twig late Client client field widened to late ClientAuth client; all mixin-level usage is within the ClientAuth contract.

Reviews (2): Last reviewed commit: "Address Flutter client surface review co..." | Re-trigger Greptile

Comment thread templates/flutter/lib/src/service.dart.twig
@ChiragAgg5k
Copy link
Copy Markdown
Member Author

Superseded by #1511, which now consolidates the Web, Flutter, and Apple isomorphic SDK changes.

@ChiragAgg5k ChiragAgg5k closed this May 7, 2026
This was referenced May 7, 2026
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.

1 participant