Skip to content

Migrate constructor/factory methods to MyType.factory.my_method#105

Open
rjhuijsman wants to merge 3 commits into
mainfrom
rjh.factory-namespaced-constructors
Open

Migrate constructor/factory methods to MyType.factory.my_method#105
rjhuijsman wants to merge 3 commits into
mainfrom
rjh.factory-namespaced-constructors

Conversation

@rjhuijsman

@rjhuijsman rjhuijsman commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Fixes #106

Before this change, constructors lived directly on state classes (e.g. Account.open()). A user-defined constructor named ref would have silently collided with the built-in MyType.ref(), and the framework could never add a new factory method without risking a clash with an existing user constructor — which a customer also can't rename or delete, leaving them permanently unable to upgrade.

This PR namespaces every state type's constructor (a.k.a. factory) methods under a factory attribute, so await MyType.create(context) becomes await MyType.factory.create(context). That frees the top level of the generated state class for framework methods we may want to add later (e.g. a future MyType.query(...)), and prevents naming collisions with built-in methods. How a constructor is declared (factory=True, or the constructor proto option) is unchanged — only the call surface moved.

Reviewer hint: the GitHub diff of the *.j2 template files looks big, but very little actually changed — it's ~all mechanical. In Python the constructor and idempotency-scope methods are simply indented into a new nested class _Factory (literally +4 spaces on everything). In TypeScript the same methods had to be moved to keep them contiguous. No control flow or logic changed in either language. The only "functional" changes are a new class to wrap these methods, and a .factory in places they're called. The *.golden.* files are regenerated codegen output.

I suggest you review the commits individually.

rjhuijsman and others added 3 commits July 21, 2026 22:57
Before this change, constructors lived directly on
the state class: a user-defined constructor named
`ref` silently collided with the built-in
`MyType.ref()`, and the framework could never add
a new factory method without risking a clash with
an existing user constructor — which a customer
could not rename or delete, leaving them
permanently unable to upgrade.

This commit namespaces every state type's
constructor (a.k.a. factory) methods under a
`factory` attribute, so `await
MyType.create(context)` becomes `await
MyType.factory.create(context)`. That frees the
top level of the generated state class for
framework methods we may want to add later (e.g. a
future `MyType.query(...)`), and prevents naming
collisions with built-in methods. The way a
constructor is declared (`factory=True`, or the
`constructor` proto option) is unchanged; only the
call surface moved.

IMPORTANT REVIEWER HINT: the GitHub diff of the
`*.j2` files is big, but very little actually
changed: a bunch of methods got indented inside a
new `_Factory` class, that's it. For Python that's
literally just 4 spaces added to everything, for
TS some code had to move to be contiguous but
still remains unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011xyvD8vLQ9dTwtFMexovJo
The `upgrade` skill rolls fragments from
`skills/upgrade/migrations/next/` into each release's migration notes.
This adds the fragment for the constructor-namespacing change so an app
upgrading past it knows to move its constructor calls: it gives
grep-able before/after patterns for `Foo.create(context, ...)` ->
`Foo.factory.create(context, ...)`, plus the idempotency-scope and
custom-constructor variants.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011xyvD8vLQ9dTwtFMexovJo
The previous commit changed where
constructor/factory methods live; this commit
changes all the callers to use the new syntax.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011xyvD8vLQ9dTwtFMexovJo
@aviator-app

aviator-app Bot commented Jul 21, 2026

Copy link
Copy Markdown

Current Aviator status

Aviator will automatically update this comment as the status of the PR changes.
Comment /aviator refresh to force Aviator to re-examine your PR (or learn about other /aviator commands).

This PR is not ready to merge (currently in state pending): this PR has not been approved.

Pending Status Checks

  • ✅ 8 tests passing!

See the real-time status of this PR on the Aviator webapp.
Use the Aviator Chrome Extension to see the status of your PR within GitHub.

@rjhuijsman
rjhuijsman requested a review from benh July 22, 2026 10:01
@rjhuijsman rjhuijsman self-assigned this Jul 22, 2026
@rjhuijsman
rjhuijsman marked this pull request as ready for review July 22, 2026 10:01
@aviator-app

aviator-app Bot commented Jul 22, 2026

Copy link
Copy Markdown

This pull request can't be queued because it's currently a draft.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Constructor/factory methods collide with type-class-level methods

1 participant