Skip to content

feat: accept any string for open enum parameters - #1816

Merged
ChiragAgg5k merged 4 commits into
mainfrom
feat/open-enum-parameters
Aug 21, 2026
Merged

feat: accept any string for open enum parameters#1816
ChiragAgg5k merged 4 commits into
mainfrom
feat/open-enum-parameters

Conversation

@ChiragAgg5k

@ChiragAgg5k ChiragAgg5k commented Aug 20, 2026

Copy link
Copy Markdown
Member

What

An endpoint can document the values callers usually want without closing the set by declaring a parameter as anyOf over a string enum and an enum-free string branch.

The parser previously exposed the raw composite, and the generator treated it as an object. TypeScript array parameters consequently degraded to Record<string, any>[], losing both completions and the actual string type.

This PR now renders the TypeScript shape as:

(UsageEventMetric | (string & {}))[]

The intersection prevents string from absorbing the enum, retaining completions while accepting arbitrary strings.

No other generated SDK can say that without closing the set — a PHP/Dart/Kotlin/Swift enum rejects unknown values. Those languages type the parameter as a plain string and keep the documented values as optional constants:

Language Parameter type Generated artifact
Web / Node / RN / Deno (WebhookEvent | (string & {})) normal enum WebhookEvent { UserCreated = 'user.created' }
PHP string final class WebhookEvent { public const USERCREATED = 'user.created'; }
Dart / Flutter String class WebhookEvent { static const String userCreated = 'user.created'; }
Kotlin / Android String object WebhookEvent { const val USERCREATED = "user.created" }
Swift / Apple String enum WebhookEvent { public static let userCreated = "user.created" }
Python str a class with class attributes, not enum.Enum
Go / CLI / REST / GraphQL string no enum file

How

Shape recognition lives in utopia-php/openapi, not this generator:

The generator consumes CompositeSchema::openStringEnumBranch() and keeps only language-specific behavior locally:

  • Web, Node, React Native, and Deno expose the enum-plus-string TypeScript type
  • enum discovery emits the documented values (as a typed enum in TypeScript, as suggestion constants everywhere else that generates enum files)
  • scalar and array forms are supported
  • every other SDK types the parameter like an unrestricted string

There is no generator-side union parser or Concern class.

Test plan

The shared OpenAPI 3 fixture includes scalar and array open enum parameters.

Base::assertOpenEnumsAllowAnyString() runs as part of every existing language E2E test. For TypeScript SDKs it requires the widened enum-plus-string type. For every other SDK it requires scalar and array open enums to render exactly like equivalent unrestricted strings. This keeps the assertion centralized while applying it across the complete language matrix.

Generated SDK builds continue to verify that referenced Web enums are emitted and imported correctly.

Verified locally:

  • vendor/bin/phpunit tests/e2e/WebNodeTest.php — 1 test, 1275 assertions
  • vendor/bin/phpunit tests/e2e/DartStableTest.php — 1 test, 1760 assertions
  • all concrete language classes checked against the centralized scalar and array invariant
  • composer refactor:check
  • composer lint
  • composer lint-twig
  • composer validate --strict --no-check-publish

Generated and inspected Web, Node, React Native, and Dart outputs from the fixture.

@greptile-apps

greptile-apps Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR teaches the generator to recognize open string enums from the upgraded OpenAPI canonical model and render unrestricted string types while retaining documented enum suggestions.

  • Adds widened enum-plus-string types for TypeScript SDKs.
  • Emits suggestion constants instead of closed enums for other supported SDKs.
  • Adds centralized scalar and array open-enum assertions across the language matrix.

Confidence Score: 5/5

The PR appears safe to merge based on the currently established behavior.

No blocking failure remains established; the prior TypeScript declaration issue is fixed, while the Dart thread remains unknown rather than confirmed outstanding.

Important Files Changed

Filename Overview
src/SDK/Language.php Adds shared open-enum unwrapping and string/array classification; the Dart outcome depends on canonical-model open metadata that could not be conclusively established.
src/SDK/SDK.php Collects enum values from open-enum branches and preserves open metadata so declarations are generated and merged consistently.
src/SDK/Language/JS.php Produces widened TypeScript scalar and array types while retaining the named enum for completions.
src/SDK/Language/Web.php Delegates enum type construction to the shared JS implementation, aligning references with emitted enum declarations.
templates/dart/lib/src/enums/enum.dart.twig Renders open enums as static string constants rather than closed Dart enum values.
tests/e2e/Base.php Centralizes cross-language assertions for scalar and array open-enum typing and suggestion generation.
tests/resources/spec-openapi3.json Adds representative scalar and array open-enum schemas to the shared generation fixture.

Reviews (7): Last reviewed commit: "(refactor): let languages own open enum ..." | Re-trigger Greptile

Comment thread src/SDK/Language/Web.php Outdated
Comment thread src/SDK/Language.php Outdated
@ChiragAgg5k
ChiragAgg5k force-pushed the feat/open-enum-parameters branch 2 times, most recently from 9343724 to d8670e1 Compare August 20, 2026 14:00
Consume open string enum semantics from utopia-php/openapi instead of interpreting anyOf branches in the generator. Web, Node, and React Native retain enum completions while accepting arbitrary strings; other SDKs keep their ordinary string representation and serialization.\n\nCover scalar and array parameters through generated TypeScript compilation and a Dart runtime regression.
@ChiragAgg5k
ChiragAgg5k force-pushed the feat/open-enum-parameters branch from d8670e1 to 300a6a5 Compare August 20, 2026 14:10
@ChiragAgg5k
ChiragAgg5k merged commit 9359528 into main Aug 21, 2026
58 checks passed
@ChiragAgg5k
ChiragAgg5k deleted the feat/open-enum-parameters branch August 21, 2026 03:56
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