Skip to content

W-21523405 feat: Add TypeScript component generation with intelligent defaulting#877

Merged
soridalac merged 15 commits intomainfrom
feat/typescript-component-generation
Mar 31, 2026
Merged

W-21523405 feat: Add TypeScript component generation with intelligent defaulting#877
soridalac merged 15 commits intomainfrom
feat/typescript-component-generation

Conversation

@shugo111
Copy link
Copy Markdown
Collaborator

@shugo111 shugo111 commented Mar 20, 2026

Summary

Enables TypeScript component generation with intelligent language detection - @W-21523405@

  • Add TypeScript templates for LWC components (.ts files)
  • Intelligent template defaulting based on sfdx-project.json defaultLWCLanguage
  • --template typescript flag for explicit TypeScript component creation
  • NUT tests for TypeScript component generation

Related Work Items

  • WI-011: Add TypeScript template for LWC components
  • WI-012: Add --template typescript flag to component generate command
  • WI-013: Implement intelligent template defaulting based on project preference
  • WI-015: Add NUT tests for TypeScript component generation

Test Plan

  • Components generate with .ts extension in TypeScript projects
  • Components respect --template typescript flag override
  • Default behavior maintained for JavaScript projects
  • NUT tests pass for all scenarios

Dependencies

IMPORTANT: This PR is built on top of #876 and must be merged AFTER #876.

Base PRs:

  1. W-21523324 feat:Add TypeScript project templates with dist/ folder strategy forcedotcom/salesforcedx-templates#758 (templates)
  2. W-21523376: feat: Add --lwc-language flag to project generate command #876 (project generation)

Note

⚠️ Snapshot files need to be updated for the new flags. This can be done during review.

Epic

Epic 2: CLI - Component Generation (Part of TypeScript for LWC initiative)

@shugo111 shugo111 requested a review from a team as a code owner March 20, 2026 16:49
@salesforce-cla
Copy link
Copy Markdown

Thanks for the contribution! Unfortunately we can't verify the commit author(s): Shubham Goyal <s***@s***.com>. One possible solution is to add that email to your GitHub account. Alternatively you can change your commits to another email and force push the change. After getting your commits associated with your GitHub account, refresh the status of this Pull Request.

@shugo111 shugo111 changed the title feat: Add TypeScript component generation with intelligent defaulting W-21523405 feat: Add TypeScript component generation with intelligent defaulting Mar 24, 2026
shugo111 added a commit that referenced this pull request Mar 26, 2026
Address PR #877 review comments:

- Fix naming convention: defaultLWCLanguage → defaultLwcLanguage
  (aligns with Salesforce camelCase convention like sfdcLoginUrl, sourceApiVersion)

- Update flag documentation:
  - Add "Default is 'javascript'" to summary
  - Remove dist/ folder references (in-place compilation)
  - Fix deployment strategy: deploy .js files, exclude .ts files

- Update intelligent defaulting to use correct field name

Files changed:
- component.ts: Fixed defaultLwcLanguage references
- messages/project.md: Updated flag summary and description
- messages/lightning.md: Fixed field name reference
- README.md: Updated all documentation (4 locations)
- Test files: Updated assertions to use correct field name

Related: @W-21523405@
shugo111 added a commit that referenced this pull request Mar 26, 2026
Address PR #877 review comments:

- Fix naming convention: defaultLWCLanguage → defaultLwcLanguage
  (aligns with Salesforce camelCase convention like sfdcLoginUrl, sourceApiVersion)

- Update flag documentation:
  - Add "Default is 'javascript'" to summary
  - Remove dist/ folder references (in-place compilation)
  - Fix deployment strategy: deploy .js files, exclude .ts files

- Update intelligent defaulting to use correct field name

Files changed:
- component.ts: Fixed defaultLwcLanguage references
- messages/project.md: Updated flag summary and description
- messages/lightning.md: Fixed field name reference
- README.md: Updated all documentation (4 locations)
- Test files: Updated assertions to use correct field name

Related: @W-21523405@
@shugo111 shugo111 force-pushed the feat/typescript-component-generation branch from 0c59fca to aad95cd Compare March 26, 2026 12:06
const flagsAsOptions: LightningComponentOptions = {
componentname: flags.name,
template: flags.template,
template,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

why are we removing flag, flags.template here?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Good catch! The flags.template flag is still there (lines 35-43) - we're not removing it.

What changed is that we now use a local variable template instead of directly passing
flags.template. This allows us to apply intelligent defaulting:

  1. If user explicitly provides --template, we use their value
  2. If no template specified AND generating LWC AND project has defaultLwcLanguage: 'typescript', we
    automatically use the typeScript template
  3. Otherwise, use the default template

Line 85 uses ES6 shorthand: template, is equivalent to template: template,. This way we pass the
(possibly modified) template value instead of always using the flag's raw value.

aliases: ['loginurl'],
deprecateAliases: true,
}),
'lwc-language': Flags.option({
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Thanks for catching these! The duplicates are intentional for now because this PR is built on top
of PR #876 (feat/typescript-project-generation).

The plan:

  1. PR W-21523376: feat: Add --lwc-language flag to project generate command #876 gets merged first (contains the project generation changes)
  2. Once merged, I'll rebase this branch onto main
  3. The duplicate commits will automatically drop since they'll already be in main
  4. This PR will then show only the component-specific changes

I structured it this way to ensure the component generation builds on the project generation
foundation, but I understand it makes the diff harder to review. If you'd prefer, you can review
the changes by comparing against the project branch rather than main to see just the
component-specific additions.

Let me know if you'd like me to restructure the PRs differently!

"json",
"login-url",
"loglevel",
"lwc-language",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

duplicate.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

ns: flags.namespace,
defaultpackagedir: flags['default-package-dir'],
apiversion: flags['api-version'],
lwcLanguage: flags['lwc-language'],
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

duplicate.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

});
});

describe('TypeScript project creation', () => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

duplicate test files.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

  @W-21523390@

  Add comprehensive documentation for TypeScript project creation covering
  architecture and usage patterns. Updates include TypeScript project
  generation examples, detailed explanation of dist/ folder strategy for
  local compilation vs. server-side type stripping, and enhanced CLI help
  text with flag descriptions.

  New "TypeScript Support for Lightning Web Components" section explains
  dual-mode approach: local type validation with npm run build (compiles
  to dist/) and server deployment of raw .ts files. Includes complete
  workflow example from project creation through deployment.
  @W-21523405@

  Add TypeScript template option to lightning component generation command,
  allowing developers to generate LWC components with .ts files instead of
  .js files. Component template generates TypeScript syntax with proper LWC
  decorators and type annotations. Test files are generated as .test.ts in
  __tests__/ folder.

  Updated CLI to accept --template typeScript flag and added example to
  help text. TypeScript template was already present in salesforcedx-templates
  repository, this change exposes it through the CLI command options.
  @W-21523414@

  Implement automatic template selection for Lightning Web Component
  generation based on project's defaultLWCLanguage preference in
  sfdx-project.json. When --template flag is not specified, CLI
  automatically selects TypeScript template for projects with
  "defaultLWCLanguage": "typescript" and JavaScript template for
  "defaultLWCLanguage": "javascript".

  Explicit --template flag always overrides project preference. Updated
  help text to document automatic template selection behavior. Only
  applies to LWC components, not Aura components.
  @W-21523425@

  Add comprehensive NUT test coverage for TypeScript Lightning Web
  Component generation including explicit template flag usage, automatic
  template selection based on project preference, and template override
  behavior. Tests verify .ts and .test.ts file creation, absence of .js
  files in TypeScript components, proper class naming conventions, and
  intelligent defaulting logic.

  Five new test cases cover: explicit TypeScript template generation,
  automatic TypeScript selection in TypeScript projects, automatic
  JavaScript selection in JavaScript projects, explicit template override
  in TypeScript projects, and proper PascalCase/camelCase naming. All
  162 NUT tests passing.
- Fix help text from 'Defaults to javascript' to 'If not specified, the project uses JavaScript'
- Add intelligent defaulting for LWC components based on sfdx-project.json defaultLWCLanguage
- Use this.argv to detect explicit --template flag instead of relying on flag defaults
- Add test coverage for TypeScript component generation and invalid lwc-language values
Address PR #877 review comments:

- Fix naming convention: defaultLWCLanguage → defaultLwcLanguage
  (aligns with Salesforce camelCase convention like sfdcLoginUrl, sourceApiVersion)

- Update flag documentation:
  - Add "Default is 'javascript'" to summary
  - Remove dist/ folder references (in-place compilation)
  - Fix deployment strategy: deploy .js files, exclude .ts files

- Update intelligent defaulting to use correct field name

Files changed:
- component.ts: Fixed defaultLwcLanguage references
- messages/project.md: Updated flag summary and description
- messages/lightning.md: Fixed field name reference
- README.md: Updated all documentation (4 locations)
- Test files: Updated assertions to use correct field name

Related: @W-21523405@
@shugo111 shugo111 force-pushed the feat/typescript-component-generation branch from aad95cd to 1d76655 Compare March 31, 2026 11:31
- Remove dist/ folder references (architecture changed to erasableSyntaxOnly)
- Fix camelCase: defaultLWCLanguage -> defaultLwcLanguage
- Fix ESLint parser check: tsparser -> tseslint.parser
- Update test assertions to match actual generated files

Fixes 6 failing NUT tests in CI
…ly provided

The default flag value shouldn't add the field to sfdx-project.json.
Only add defaultLwcLanguage when user explicitly specifies --lwc-language.

Fixes failing NUT test: 'should create default project without TypeScript files when no flag specified'
Changed from 'lwc-standalone' to 'standalone/lwc' to satisfy the
generator's requirement that LWC components must be in a directory
ending with 'lwc'.

Fixes 2 failing NUT tests for component generation outside project context
const { flags } = await this.parse(Project);

// Only include lwcLanguage if user explicitly provided the flag
const userProvidedLwcLanguage = this.argv.includes('--lwc-language');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

if (defaultLwcLanguage === 'typescript') {
template = 'typeScript';
} else if (defaultLwcLanguage === 'javascript') {
template = 'default'; // Explicit JavaScript template
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The default for this flag is already 'default'.

let template = flags.template;

// If template not explicitly provided and generating LWC, check project preference
if (!userExplicitlySetTemplate && flags.type === 'lwc') {
Copy link
Copy Markdown
Contributor

@iowillhoit iowillhoit Mar 31, 2026

Choose a reason for hiding this comment

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

I would much rather throw an error message that try to modify these flag values.

pseudocode:

  • flags.type === 'lwc'
  • Resolve project and get defaultLwcLanguage from sfdx-project.json
  • Validate
    - if (defaultLwcLanguage === 'typescript' && flags.template !== 'typeScript') throw error: Language in 'typeScript' detected in sfdx-project.json. This requires the "--template typescript" flag

@iowillhoit
Copy link
Copy Markdown
Contributor

Bump the @salesforce/templates version in both of your PRs (currently 66.7.6)
Be sure to run yarn install to update the yarn.lock

shugo111 added 2 commits April 1, 2026 01:23
Update @salesforce/templates and refresh yarn.lock via yarn install.

Made-with: Cursor
Only set lwcLanguage when the flag is provided.
Remove redundant default template reassignment logic.

Made-with: Cursor
# flags.template.description

Supplied parameter values or default values are filled into a copy of the template.
Supplied parameter values or default values are filled into a copy of the template. For Lightning Web Components, if not specified, the CLI automatically selects the template based on the project's sfdx-project.json "defaultLwcLanguage" field: TypeScript template for "typescript", JavaScript template for "javascript".
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This should also list the behavior if there's no defaultLwcLanguage.

const stderr = execCmd(
'template generate lightning component --outputdir aura --componentname foo --type aura --template typescript'
).shellOutput.stderr;
expect(stderr).to.contain(messages.getMessage('MissingLightningComponentTemplate', ['typeScript', 'aura']));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
expect(stderr).to.contain(messages.getMessage('MissingLightningComponentTemplate', ['typeScript', 'aura']));
expect(stderr).to.contain(messages.getMessage('MissingLightningComponentTemplate', ['typescript', 'aura']));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Good eyes. This is duplicating an error that comes from the library. It needs to stay as typeScript for now unfortunately.

Copy link
Copy Markdown
Contributor

@soridalac soridalac Mar 31, 2026

Choose a reason for hiding this comment

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

Got it!! LGTM, thanks Eric for making the changes❤️

Update project help and README text to state that TypeScript files are
deployed to Salesforce, while local compile is used for validation.

Made-with: Cursor
@soridalac soridalac merged commit 3b4fb42 into main Mar 31, 2026
15 checks passed
@soridalac soridalac deleted the feat/typescript-component-generation branch March 31, 2026 21:41
Copy link
Copy Markdown
Contributor

@jshackell-sfdc jshackell-sfdc left a comment

Choose a reason for hiding this comment

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

See my suggestions and comments.

# flags.template.description

Supplied parameter values or default values are filled into a copy of the template.
Supplied parameter values or default values are filled into a copy of the template. For Lightning Web Components, if not specified, the CLI automatically selects the template based on the project's sfdx-project.json "defaultLwcLanguage" field: TypeScript template for "typescript", JavaScript template for "javascript".
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
Supplied parameter values or default values are filled into a copy of the template. For Lightning Web Components, if not specified, the CLI automatically selects the template based on the project's sfdx-project.json "defaultLwcLanguage" field: TypeScript template for "typescript", JavaScript template for "javascript".
Supplied parameter values or default values are filled into a copy of the template. For Lightning Web Components, if this flag isn't specified, the CLI command automatically selects the template based on the "defaultLwcLanguage" field in the DX project's "sfdx-project.json" file.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No need to add the last part, because it's obvious :)


<%= config.bin %> <%= command.id %> --name mycomponent --type lwc --output-dir force-app/main/default/lwc

- Generate a TypeScript Lightning web component:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
- Generate a TypeScript Lightning web component:
- Generate a TypeScript Lightning Web Component:

# flags.lwc-language.summary

Default language for Lightning Web Components.
Language of the Lightning Web Components. Default is "javascript".
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is the flag coded for a default value? I can't tell. If so, then remove the last sentence. If the flag isn't coded that way, can it be? It's nice to have stuff like default values, list of possible values, etc, be in the code itself which is then automatically displayed in the --help.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The flag is not coded with a default. But that is how this is designed (for now)

# flags.lwc-language.description

Sets the default language for Lightning Web Components in this project. When set to 'typescript', generates TypeScript configuration files (tsconfig.json, package.json with TypeScript dependencies, and TypeScript-aware ESLint config). TypeScript projects compile locally to a dist/ folder for validation, but deploy raw .ts files to Salesforce for server-side type stripping. Defaults to 'javascript'.
Sets the default language for Lightning Web Components in this project. When set to `'typescript'`, generates TypeScript configuration files (tsconfig.json, package.json with TypeScript dependencies, and TypeScript-aware ESLint config). TypeScript files are compiled locally for validation, and the TypeScript (`.ts`) files are deployed to Salesforce for server-side type stripping. If not specified, the project uses JavaScript.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
Sets the default language for Lightning Web Components in this project. When set to `'typescript'`, generates TypeScript configuration files (tsconfig.json, package.json with TypeScript dependencies, and TypeScript-aware ESLint config). TypeScript files are compiled locally for validation, and the TypeScript (`.ts`) files are deployed to Salesforce for server-side type stripping. If not specified, the project uses JavaScript.
When set to `'typescript'`, generates TypeScript configuration files (tsconfig.json, package.json with TypeScript dependencies, and TypeScript-aware ESLint config). TypeScript files are compiled locally for validation, and the TypeScript (`.ts`) files are deployed to Salesforce for server-side type stripping.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Don't repeat what's in the summary.

Also, I don't understand the last sentence. Can you reword? I didn't understand it enough to try it myself. For example, something like this (but it might be wrong, so fix as needed):

When you deploy the TypeScript-based Lightning Web Components, the TypeScript files are first compiled locally for validation and then the .ts files are deployed to your org for server-side type stripping.

@iowillhoit iowillhoit mentioned this pull request Mar 31, 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.

5 participants