Skip to content

codemods: model-to-schema typescript support#10474

Open
BobrImperator wants to merge 16 commits intowarp-drive-data:mainfrom
BobrImperator:codemod/typescript-support
Open

codemods: model-to-schema typescript support#10474
BobrImperator wants to merge 16 commits intowarp-drive-data:mainfrom
BobrImperator:codemod/typescript-support

Conversation

@BobrImperator
Copy link
Contributor

@BobrImperator BobrImperator commented Feb 17, 2026

Pulls changes from #10487

  • Remove remnants of previous Signature type generation
  • Fix and normalize type imports
  • Normalizes schema names for Traits and Extensions especially.
  • Normalizes interface names to always include Trait or Extension
    • Names without suffixes are reserved for Resource Brands
  • Adds a solution for constructing resource Brands using Typescript interface merging.
  • Fixes Mixin.create mixins being left over in generated traits code
  • Fixes incorrect path files being used depending on disableTypescriptSchemas and combineSchemasAndTypes settings
    This does rely on the fact that some imports are effectively circular, but Typescript appears to be fine with that.
// --
/*
 Generated Type Artifacts:

 For a Model:
 - just its fields and its traits fields (if any) (UserResource)
 - its fields, traits, extensions and WithLegacy (LegacyUserResource)


 For a Mixin: Updateable
 - just its fields and its traits fields (if any) (UpdateableTrait)
 - its fields, traits and extensions and WithLegacy (LegacyUpdateableTrait)
 
*/
type WithLegacy<T extends object> = T & { belongsTo(key: keyof T): void; hasMany(): void }

/**
 * Just the exact fields on this resource
 */
interface UserResource extends TimestamppedTrait {
  firstName: string;
  lastName: string;
  name: 'user fields'
  createdAt: number
}

// give people the nice import for just the "schema" bit
type User = WithLegacy<UserResource>;

// @ts-expect-error
interface UserExtension extends User, TimestamppedExtension {}
class UserExtension {
  get fullName(): string {
    return this.firstName + this.lastName;
  }
}

// give folks a nice import for the full thing
type UserWithExtensions = UserExtension;

// --

const a = {} as User;
a.createdAt;
a.belongsTo('firstName'); // expect works since in the resource schema
a.belongsTo('_firstName'); // expect error since not exists
a.belongsTo('deletedAt'); // expect works because inherited from trait of trait
a.belongsTo('fullName'); // expect error since from extension

interface DeleteableTrait {
    deletedAt: string;
}
interface DeleteableExtension extends DeleteableTrait {}
class DeleteableExtension {
    get timeSinceDeleted(): number {
     return 1;
    }
}

interface TimestamppedTrait extends DeleteableTrait {
  createdAt: string | number;
}

interface TimestamppedExtension extends TimestamppedTrait, DeleteableExtension {}
class TimestamppedExtension {
  get timeSince(): string | number {
    return this.createdAt;
  }

  name: string = 'user ext'
  
}
---

@github-project-automation github-project-automation bot moved this to needs triage in EmberData Feb 17, 2026
@BobrImperator BobrImperator force-pushed the codemod/typescript-support branch from 7d61f8b to 83d7f90 Compare February 17, 2026 18:28
collectTraitImports(extendedTraits, imports, options);

const traitSchemaName = traitInterfaceName;
const traitSchemaName = `${toPascalCase(baseName)}Schema`;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A recurring problem so far is shotgun surgeries like this which are also very error prone that Claude was very happy with. Additionally the codemod often lacks the ability to quickly refer from a file to it's dependencies for the exact same reason.

There's on-going effort to wrangle this up https://github.com/BobrImperator/data/compare/codemod/typescript-support...BobrImperator:data:codemod/poc-typescript?expand=1

@BobrImperator BobrImperator changed the title codemods: model-to-scheam typescript support codemods: model-to-schema typescript support Feb 17, 2026
@BobrImperator BobrImperator force-pushed the codemod/typescript-support branch 8 times, most recently from 6d62aed to 5894553 Compare February 23, 2026 09:39
@BobrImperator BobrImperator force-pushed the codemod/typescript-support branch from 5894553 to d5cec6a Compare February 25, 2026 12:45
@BobrImperator BobrImperator force-pushed the codemod/typescript-support branch 2 times, most recently from 260f072 to 640d45c Compare February 26, 2026 12:55
@BobrImperator BobrImperator marked this pull request as draft February 26, 2026 12:59
@BobrImperator BobrImperator force-pushed the codemod/typescript-support branch from 640d45c to 5801423 Compare February 26, 2026 13:02
@BobrImperator BobrImperator force-pushed the codemod/typescript-support branch from aa9411f to bf28e98 Compare February 26, 2026 14:43
readonly isForControlsAssessment: boolean | null;
readonly frameworks: HasMany<Framework>;
}",
// @ts-expect-error TS disallows it. However in real world \`Resource\` "wins" when merged.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps could contain a documentation link

@BobrImperator BobrImperator force-pushed the codemod/typescript-support branch 3 times, most recently from 0d94f23 to 23db85f Compare February 27, 2026 16:02
runspired and others added 2 commits February 27, 2026 19:49
Merges the codemod-tests branch which adds:
- SchemaArtifact config system (artifact.ts)
- createExtension utility for stripping schema fields from models
- New test harness with basic-native-model-class and extension tests
- Updated generateMergedSchemaCode to return GeneratedSchemaParts
- Refactored function signatures across schema-generation utils
Replace FIXME placeholder in mixin and model trait generation with
actual assembled code from generateMergedSchemaCode return value.
Add combineSchemasAndTypes, resourcesImport, and traitsImport to
DEFAULT_TEST_OPTIONS. Fix stale test assertions: .schema.js → .schema.ts,
unknown | null → unknown, import path extensions, and import prefix bug
in transformModelToResourceImport.
@BobrImperator BobrImperator force-pushed the codemod/typescript-support branch from 23db85f to 823ba15 Compare March 2, 2026 17:28
@BobrImperator BobrImperator marked this pull request as ready for review March 2, 2026 17:51
"resources/": "__dir__",
"resources/typed.ext.ts": "
import BaseModel from 'test-app/models/base-model';
import type { Typed } from './typed.type.ts';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typed.type.ts is used but not generated

Comment on lines -795 to +796
import type { Type } from '@ember-data/core-types/symbols';
import type { StaticBaseModelTraitTrait } from 'test-app/data/traits/static-base-model-trait.schema';
import type { TypedExtension } from 'test-app/data/resources/typed.ext';
import type { LegacyResourceSchema } from '@warp-drive/core-types/schema/fields';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removes the imports but there's no typed.ts file which would declare the merged interfaces

@BobrImperator BobrImperator force-pushed the codemod/typescript-support branch from 6183097 to 52248f6 Compare March 3, 2026 16:12
When a model like `class Foo extends BaseModel.extend(Mixin1, Mixin2)`
is transformed, the generated extension class now includes the mixins
in its extends clause: `export class FooExtension extends Mixin1, Mixin2`.

- Add heritageLocalNames to ParsedFile to track original mixin identifiers
- Thread heritageLocalNames through ModelAnalysisResult to extension generation
- Add extendsClause parameter to generateExtensionCode for class format
- Update snapshots to reflect new extends clause in extension classes
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