Skip to content

🎉 @ast-grep/all-langs #74

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: main
Choose a base branch
from

Conversation

NatoBoram
Copy link
Collaborator

@NatoBoram NatoBoram commented Apr 24, 2025

So this isn't exactly what I had in mind at first in #71. What I imagined was just being able to call a single function and having all built-in languages registered at once. When I tested it, the languages don't register if the registration is done in a dependency, which is weird. I don't know what could be causing this, but even if the registration is made in the main package, a lib that re-exports the big DynamicLangRegistrations is welcome.

Using this package, we go from something like this:

import angular from "@ast-grep/lang-angular"
import bash from "@ast-grep/lang-bash"
import c from "@ast-grep/lang-c"
import cpp from "@ast-grep/lang-cpp"
import csharp from "@ast-grep/lang-csharp"
import css from "@ast-grep/lang-css"
import dart from "@ast-grep/lang-dart"
import elixir from "@ast-grep/lang-elixir"
import go from "@ast-grep/lang-go"
import haskell from "@ast-grep/lang-haskell"
import html from "@ast-grep/lang-html"
import java from "@ast-grep/lang-java"
import javascript from "@ast-grep/lang-javascript"
import json from "@ast-grep/lang-json"
import kotlin from "@ast-grep/lang-kotlin"
import lua from "@ast-grep/lang-lua"
import php from "@ast-grep/lang-php"
import python from "@ast-grep/lang-python"
import ruby from "@ast-grep/lang-ruby"
import rust from "@ast-grep/lang-rust"
import scala from "@ast-grep/lang-scala"
import sql from "@ast-grep/lang-sql"
import swift from "@ast-grep/lang-swift"
import toml from "@ast-grep/lang-toml"
import tsx from "@ast-grep/lang-tsx"
import typescript from "@ast-grep/lang-typescript"
import { registerDynamicLanguage } from "@ast-grep/napi"

const register = Object.freeze({
	Angular: angular,
	Bash: bash,
	C: c,
	Cpp: cpp,
	CSharp: csharp,
	Css: css,
	Dart: dart,
	Elixir: elixir,
	Go: go,
	Haskell: haskell,
	Html: html,
	Java: java,
	JavaScript: javascript,
	Json: json,
	Kotlin: kotlin,
	Lua: lua,
	Php: php,
	Python: python,
	Ruby: ruby,
	Rust: rust,
	Scala: scala,
	Sql: sql,
	Swift: swift,
	Toml: toml,
	Tsx: tsx,
	TypeScript: typescript,
})

// @ts-expect-error Missing the following properties from type `LangRegistration`: `libraryPath`, `extensions`
registerDynamicLanguage(register)

To this:

import { langs } from "@ast-grep/all-langs"
import { registerDynamicLanguage } from "@ast-grep/napi"

registerDynamicLanguage(langs)

And I think it's close enough.

There's the potential issue of this thing bring written in pure JS + .d.ts files, which makes the typing of the exported langs extremely brittle. We can see in the issue in the first TypeScript example. Maybe it would be better to write it in TypeScript? Moved to TypeScript. Much simpler.

  • Exports a langs object with all first-party supported languages
  • Exports a Lang enum with the names of all first-party supported languages
  • Unit tests to make sure the new enum is compatible with the old and built-in enums
  • Unit tests for registering languages and making sure they're actually available once registered
  • Closes A package that exports all langs at once? #71

Summary by CodeRabbit

  • New Features

    • Introduced the @ast-grep/all-langs package, providing unified access to all officially supported languages.
    • Added a centralized registry for language parsers, enabling easier language module management.
    • Exposed a comprehensive language enumeration and type-safe language support.
  • Tests

    • Added tests to verify language compatibility and correct parsing for supported languages.
  • Chores

    • Updated CI and release workflows to require Node.js version 21 or higher.
    • Added recommended VS Code extension and workspace settings for consistent formatting.
    • Improved .gitignore handling for package source directories.
    • Added TypeScript configuration for strict type checking and modern module support.

Copy link

coderabbitai bot commented Apr 24, 2025

Walkthrough

This update introduces a new package, @ast-grep/all-langs, which aggregates and re-exports all officially supported language modules for the ast-grep ecosystem. The update includes new TypeScript source files, type definitions, and test suites to ensure compatibility and correct integration of all language modules. Supporting files such as package.json, TypeScript configuration, and .gitignore are added for package management and development workflow. Additionally, Visual Studio Code workspace settings and extension recommendations are introduced. The CI and release workflows are updated to require Node.js version 21 or higher.

Changes

File(s) Change Summary
.changeset/green-turtles-jump.md Documents the addition of the new @ast-grep/all-langs package as a patch update.
.github/workflows/ci.yml, .github/workflows/release.yml Updates CI and release workflows to require Node.js version 21 or higher during setup.
.vscode/extensions.json, .vscode/settings.json Adds VS Code extension recommendation for "biomejs.biome" and sets it as the default formatter for JS/TS/JSON files; configures minimap column width.
packages/all/.gitignore Ensures the src directory is not ignored in the package.
packages/all/package.json Introduces the new package @ast-grep/all-langs with metadata, dependencies on all language modules, scripts, and configuration.
packages/all/tsconfig.json Adds strict TypeScript configuration for the new package with modern settings and strict type checks.
packages/all/src/index.ts Re-exports all public entities from lang.ts and langs.ts as the main entry point.
packages/all/src/lang.ts Defines and exports the Lang constant (enumeration of supported languages) and its corresponding type alias.
packages/all/src/langs.ts Imports and aggregates all language modules, exports a registry object langs, and defines related types/interfaces for language registration.
packages/all/src/lang.test.ts, packages/all/src/langs.test.ts Adds test files to verify compatibility between language enums and to validate parsing functionality for several languages using the aggregated exports.

Sequence Diagram(s)

sequenceDiagram
    participant Consumer
    participant AllLangsPkg as @ast-grep/all-langs
    participant Langs as Individual Language Modules

    Consumer->>AllLangsPkg: import { Lang, langs } from '@ast-grep/all-langs'
    AllLangsPkg->>Langs: Re-export all supported language modules
    Consumer->>AllLangsPkg: Use Lang enum/type and langs registry
Loading

Assessment against linked issues

Objective Addressed Explanation
Provide a package that aggregates and exports all first-party language modules (#71)
Enable users to import and register all supported languages at once via a single package (#71)

Possibly related PRs

  • ✨ Elixir #49: Adds the standalone Elixir language package, which is included in the new aggregate package.
  • feat: add tree-sitter-c #35: Introduces the C language package, now aggregated in @ast-grep/all-langs.
  • ✨ JavaScript #53: Adds the JavaScript language package, which is re-exported by the new package.

Poem

In a warren of code, where the languages sprawl,
A rabbit assembled one package for all.
From Bash to Scala, and YAML to Dart,
Now one import brings every part!
With enums and tests, and a hop of delight—
All languages gathered, the future looks bright!
🐇✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8d96346 and f0dd9ca.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (2)
  • packages/all/package.json (1 hunks)
  • packages/all/src/langs.test.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • packages/all/src/langs.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/all/package.json
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (5)
packages/all/langs.d.ts (1)

1-9: Enhance Type-Safety of langs Declaration
Currently the mapping uses DynamicLangRegistrations[string], which yields a broad union of all registrations. To tighten the type, consider indexing by the Lang union directly:

-export declare const langs: Readonly<
-  Record<Lang, DynamicLangRegistrations[string]>
->
+export declare const langs: Readonly<
+  Record<Lang, DynamicLangRegistrations[Lang]>
+>

This ensures each key in langs precisely maps to its corresponding registration type.

packages/all/lang.js (1)

1-31: Consider Migrating to TypeScript for Stronger Typing
Defining the Lang enum in plain JavaScript with a separate .d.ts can lead to mismatches over time. You may want to convert this file to TypeScript (e.g., lang.ts) and export a true enum or as const object. That approach would eliminate the need for parallel .d.ts files and improve maintainability and type safety.

packages/all/package.json (2)

18-21: Enforce Node.js engine version for consistency.
Given that CI/workflows now require Node.js ≥ 21, consider adding an "engines": { "node": ">=21" } field to guard against incompatible runtimes.


52-57: Consider adding subpath exports for granular imports.
If consumers ever need to import modules directly (e.g. import { Lang } from '@ast-grep/all-langs/lang'), you could extend the exports field with entries for ./lang and ./langs.

packages/all/jsconfig.json (1)

27-30: Specify outDir to isolate build artifacts.
With "composite": true and emit options enabled (declaration, sourceMap, etc.), it’s recommended to set an "outDir" (for example, "dist"). This prevents emitted files from polluting the source tree and supports cleaner composite builds.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fea52a8 and e559ad3.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (16)
  • .changeset/green-turtles-jump.md (1 hunks)
  • .github/workflows/ci.yml (1 hunks)
  • .github/workflows/release.yml (2 hunks)
  • .vscode/extensions.json (1 hunks)
  • .vscode/settings.json (1 hunks)
  • packages/all/.gitignore (1 hunks)
  • packages/all/index.d.ts (1 hunks)
  • packages/all/index.js (1 hunks)
  • packages/all/jsconfig.json (1 hunks)
  • packages/all/lang.d.ts (1 hunks)
  • packages/all/lang.js (1 hunks)
  • packages/all/lang.test.js (1 hunks)
  • packages/all/langs.d.ts (1 hunks)
  • packages/all/langs.js (1 hunks)
  • packages/all/langs.test.js (1 hunks)
  • packages/all/package.json (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: HerringtonDarkholme
PR: ast-grep/langs#65
File: packages/typescript/index.js:6-6
Timestamp: 2025-04-10T19:47:06.210Z
Learning: In ast-grep, TypeScript and TSX are treated as two separate languages, each with their own language package, rather than TypeScript supporting both .ts and .tsx extensions in a single package.
🧬 Code Graph Analysis (6)
packages/all/langs.test.js (2)
packages/all/langs.js (2)
  • langs (32-59)
  • langs (32-59)
packages/all/lang.js (2)
  • Lang (4-31)
  • Lang (4-31)
packages/all/lang.js (1)
packages/all/lang.d.ts (1)
  • Lang (33-33)
packages/all/lang.test.js (2)
packages/all/lang.js (2)
  • Lang (4-31)
  • Lang (4-31)
packages/all/lang.d.ts (1)
  • Lang (33-33)
packages/all/langs.d.ts (3)
packages/all/langs.js (2)
  • langs (32-59)
  • langs (32-59)
packages/all/lang.js (2)
  • Lang (4-31)
  • Lang (4-31)
packages/all/lang.d.ts (1)
  • Lang (33-33)
packages/all/lang.d.ts (1)
packages/all/lang.js (2)
  • Lang (4-31)
  • Lang (4-31)
packages/all/langs.js (1)
packages/all/lang.js (2)
  • Lang (4-31)
  • Lang (4-31)
🔇 Additional comments (25)
packages/all/.gitignore (1)

1-1: Ignore node_modules directory as expected
The new .gitignore entry correctly prevents the node_modules folder in the packages/all package from being committed.

.vscode/extensions.json (1)

1-3: Recommend Biome extension for consistent formatting
This workspace recommendation of biomejs.biome aligns with the project's formatting standards and will prompt users to install the correct formatter.

.vscode/settings.json (1)

1-6: Configure Biome as default formatter
The settings file correctly sets "biomejs.biome" as the default formatter for JavaScript, JSON, JSONC, and TypeScript, and limits the minimap width to improve readability.

.changeset/green-turtles-jump.md (1)

1-6: Patch release configuration looks correct
The changeset properly declares the new @ast-grep/all-langs package as a patch update, following the repository’s changeset conventions.

.github/workflows/release.yml (2)

44-44: Ensure Consistent Node.js Version in Prebuild Job
The node-version: ">= 21" update aligns the prebuild environment with CI requirements. Confirm that all downstream scripts and dependencies are compatible with Node.js 21+ features.


78-78: Ensure Consistent Node.js Version in Package Job
The same version constraint in the package job maintains consistency across workflows. No further changes needed here.

packages/all/index.d.ts (1)

1-2: Re-export Entry Points
The declaration file cleanly re-exports both lang.js and langs.js, providing a single entry point for TypeScript consumers of the package.

packages/all/index.js (1)

1-2: Re-export Entry Points
This module correctly consolidates exports from lang.js and langs.js into one entry point, simplifying imports for end users.

packages/all/langs.test.js (4)

6-7: Good setup for language registration

Registering all dynamic languages before running tests using registerDynamicLanguage(langs) is a clean approach. This ensures all tests have access to the complete language set.


9-14: Good test structure for newly supported language

The test for Dart as a newly supported language correctly checks that the root node kind is 'program', verifying the parser is working as expected.


23-28: Good test coverage for built-in language

Testing TypeScript as a built-in language ensures compatibility with core language support.


1-5: Good imports and structure

The imports are clean and well-organized, correctly bringing in both the testing utilities and the language modules being tested.

packages/all/langs.js (3)

1-27: Clean organization of language module imports

The imports are well-organized and follow a consistent pattern, importing each language module from its respective package.


29-31: Good documentation

The JSDoc comment clearly describes what the langs object represents.


32-59: Well-structured language mapping

The langs object effectively maps each language key from the Lang enum to its corresponding imported module. Using Object.freeze() ensures immutability, which is good practice.

This implementation fulfills the PR objective of consolidating all language registrations in a single package for easier usage.

packages/all/lang.test.js (3)

5-31: Good backward compatibility reference

Defining a frozen previous object with the language set from @ast-grep/[email protected] provides a clear reference point for backwards compatibility testing. The commented out Yaml entry might indicate a language that was previously supported but is now excluded.


33-36: Good backwards compatibility test

This test ensures that the new Lang enum remains compatible with the previous version, which is essential for maintaining API stability.


38-40: Good current compatibility test

Testing compatibility with the current built-in enum from @ast-grep/napi ensures alignment between the new package and the core library.

packages/all/lang.d.ts (3)

1-3: Clear documentation

The JSDoc comment clearly describes what the Lang enum represents.


4-31: Well-defined TypeScript declaration

The Lang constant is correctly declared as a readonly object with all supported language identifiers, matching the JS implementation. This provides proper type safety when using the enum.


33-33: Good type extraction

The Lang type is correctly defined as a union of all string literal values from the Lang object. This creates a proper string literal union type that can be used for type checking language identifiers.

packages/all/package.json (3)

3-3: Verify package version before release.
The version is currently set to "0.0.0", which appears to be a placeholder. Please bump this to an appropriate version (e.g., 0.1.0 or 1.0.0) prior to publishing.


22-50: Confirm completeness of language dependencies.
This list should mirror every officially supported @ast-grep/lang-* package (including TSX and TypeScript as separate entries). Please verify that no languages have been omitted.


1-60: Overall package.json looks solid.
Metadata, file globs, module mappings, and the dependency declarations align with the PR objectives of aggregating all @ast-grep languages under one package.

packages/all/jsconfig.json (1)

1-65: Comprehensive TypeScript configuration.
The jsconfig.json provides strict type checking, accurate module resolution (NodeNext), and robust compiler options that fit the needs of a unified language‐registry package.

@@ -21,6 +21,7 @@ jobs:
uses: actions/setup-node@v4
with:
cache: pnpm
node-version: ">= 21"
Copy link

@coderabbitai coderabbitai bot Apr 24, 2025

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Validate Node.js version range in CI
Please confirm that the actions/setup-node action supports the semver range ">= 21". Also ensure that the release workflow (.github/workflows/release.yml) has been updated in the same way for consistency.


🏁 Script executed:

#!/bin/bash
# Verify Node.js version configuration in CI and release workflows
rg -n 'actions/setup-node' -C2 .github/workflows/ci.yml .github/workflows/release.yml

Length of output: 924


🌐 Web query:

Does GitHub actions/setup-node support semver ranges for the "node-version" input?

💡 Result:

Support for Semver Ranges in actions/setup-node

Yes, the GitHub Actions actions/setup-node action supports Semantic Versioning (semver) ranges for the node-version input.

Details

  • The node-version input accepts semver range notations, allowing you to specify versions like '14.x', '16', '>=16.0.0', and similar patterns. For example:

    • '16.x' will use the latest available patch version of Node.js 16.
    • '>=18.0.0' will resolve to the latest version matching the range[2][4][6].
  • This is explicitly supported in the official documentation and examples:

    The action will first check the local cache for a semver match. If unable to find a specific version in the cache, the action will attempt to download a version of Node.js[2][1][4].

  • You can also use other accepted notations such as:

    • 'lts/*' for the latest LTS version
    • 'latest' for the most recent Node.js release
    • Specific versions like '16.13.0'
    • Nightly and canary build notations[2][5]
  • The setup-node action internally uses semver resolution logic to pick the appropriate Node.js version based on the provided range, and this is compatible with the NPM ecosystem’s node-semver parser[3][4].

Example Usage

- uses: actions/setup-node@v4
  with:
    node-version: '18.x'      # Latest 18.x patch

or

- uses: actions/setup-node@v4
  with:
    node-version: '>=16.0.0'  # Latest version >= 16.0.0

Version Files and Ranges

  • The action also supports specifying the Node.js version via a file (.nvmrc, .node-version, package.json). If a semver range is provided in these files (e.g., via engines.node in package.json), that will be used as the version specification[1][6].

Summary Table

Syntax Example Result
'16.x' Latest patch of Node.js 16
'>=18.0.0' Latest available Node.js >= 18.0.0
'lts/*' Latest LTS version
'latest' Latest published Node.js version
'14', '14.x' Latest patch of Node.js 14

In conclusion, use semver ranges or aliases as the node-version input for flexibility in your GitHub Actions workflows[2][4][5][6].

Citations:


🌐 Web query:

What input parameters does actions/setup-node@v4 accept (e.g., node-version vs version)?

💡 Result:

Input Parameters for actions/setup-node@v4

actions/setup-node@v4 provides a range of input parameters to configure Node.js environments in GitHub Actions workflows. Below are the primary and advanced inputs you can use, with notes on precedence and intended use:

Core Version Selection Inputs

  • node-version
    Specifies the Node.js version to use (accepts SemVer, aliases like lts/*, latest, nightly, or canary builds).
    Example:

    with:
      node-version: '18'

    If both node-version and node-version-file are provided, node-version takes precedence[1][2][6][9].

  • node-version-file
    Path to a file containing the Node.js version (e.g., .nvmrc, .node-version, .tool-versions, or package.json).
    Example:

    with:
      node-version-file: '.nvmrc'

    Notable behavior: In a package.json, it checks volta.node first, then engines.node if volta.node is unspecified[1][6].

Update and Architecture Controls

  • check-latest
    Boolean (true or false). If true, downloads the latest available version matching the specification, bypassing local cache. Defaults to false, which favors cached versions for performance[1][6][9].
    Example:

    with:
      check-latest: true
  • architecture
    Target CPU architecture for Node.js (e.g., x86, x64, arm64). Defaults to the system architecture if unspecified[2][6][9].
    Example:

    with:
      architecture: 'x64'

Caching and Authentication (Advanced)

  • cache
    Specifies dependency manager to cache (npm, yarn, pnpm, or '' to disable)[2][6].

  • cache-dependency-path
    Sets the path to lock file(s) for cache key calculation (used if lock file is not in root).

  • registry-url and scope
    Used to set up npm registry authentication, particularly with private registries.

  • token
    Custom token for publishing/authenticating with npm/GitHub package registries.

Summary Table

Parameter Purpose/Example Value Notes
node-version '18', 'lts/*', '16.13.0' Main version selector; takes precedence over node-version-file.
node-version-file '.nvmrc', 'package.json' Uses version specified in file.
check-latest true, false Download the latest version if true. Default: false.
architecture 'x64', 'arm64' Target CPU architecture.
cache 'npm', 'yarn', 'pnpm' Enable caching of dependencies.
cache-dependency-path 'frontend/yarn.lock' Path(s) for dependency lock file(s).
registry-url 'https://npm.pkg.github.com' Custom registry URL.
scope '@my-org' Npm scope for authentication.
token '${{ secrets.NPM_TOKEN }}' Token for private registry auth.

No version Input

  • The parameter is named node-version (not just version). There is no version input; always use node-version when specifying the desired Node.js release[2][9].

Example Usage

- uses: actions/setup-node@v4
  with:
    node-version: '20'
    check-latest: true
    architecture: 'x64'
    cache: 'npm'

References

  • For a full list and the most current details, consult the official documentation[1][2][6][9].
  • The action supports multiple advanced workflows, including dependency caching, multi-architecture builds, and custom registry authentication.

In summary:
Use node-version to specify the Node.js version (not version). node-version-file can be used to read the version from a file, but is overridden by a direct node-version input. Additional parameters provide update, architecture, caching, and authentication controls for your workflow[1][2][6][9].

Citations:


Update release workflow to use node-version input
The actions/setup-node@v4 action does support SemVer ranges (e.g. ">= 21") via the node-version input. Your CI workflow already uses:

with:
  node-version: ">= 21"
  cache: pnpm

However, in your release workflow you’re still using the wrong parameter (version: 9) in two places. Please update both steps in .github/workflows/release.yml to:

- with:
-   version: 9
-   cache: pnpm
+ with:
+   node-version: ">= 21"
+   cache: pnpm

– once at line 39 (and its corresponding cache block) and again at line 73.
Ensure you’re using node-version (not version) for consistency with the CI workflow and the action’s documentation.

Choose a reason for hiding this comment

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

do we need this?

Copy link

Choose a reason for hiding this comment

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check the package.json files for Node.js requirements
echo "Checking package.json files for Node.js engine requirements:"
find . -name "package.json" -type f -exec grep -l "\"engines\"" {} \; | xargs cat 2>/dev/null | grep -A5 "\"engines\"" || echo "No engines field found"

echo -e "\nChecking all-langs package.json:"
cat packages/all/package.json | grep -A20 "dependencies" || echo "Could not find dependencies section"

echo -e "\nChecking release workflow file:"
cat .github/workflows/release.yml | grep -A10 "setup-node" || echo "No setup-node configuration found"

Length of output: 2101


🏁 Script executed:

#!/bin/bash
# Let's check for potential Node.js version requirements in the project or PR

# Check if there are any ESM features or other Node.js 21+ specific features in the new package
echo "Checking all-langs source files for potential Node.js 21+ features:"
find packages/all/src -type f -name "*.ts" -exec cat {} \; | grep -E "(import|export) type|import \{.*\} from"

# Check existing Node.js version in package.json at root level
echo -e "\nChecking root package.json for any Node.js related configuration:"
cat package.json | grep -E "\"(node|engines|volta)\"" -A3 -B3 || echo "No Node.js config found"

# Check if the Nodejs version constraint already exists in release workflow
echo -e "\nChecking if release workflow already has Node.js version constraint:"
grep -n "node-version" .github/workflows/release.yml

Length of output: 1218


🏁 Script executed:

#!/bin/bash
# Let's check more context about this PR

# Check the commit message when Node.js 21 was added to CI workflow
echo "Checking commit history for Node.js version changes:"
git log -p -- .github/workflows/ci.yml | grep -A10 -B10 "node-version" | head -30

# Check if there was discussion about Node.js version requirements in issues or PRs
echo -e "\nChecking for any Node.js version discussions in PRs:"
gh pr list --limit 20 --json title,url | jq '.[] | select(.title | test("node|Node|nodejs|version|v[0-9]+") | .url)'

# Check if any dependencies require Node.js 21+
echo -e "\nChecking package.json files for dependencies that might require Node.js 21+:"
find . -name "package.json" -type f -exec cat {} \; | grep -E "\"@types/node|node-api-headers|napi-rs"

# Let's see the current branch name and if it's related to Node.js version
echo -e "\nCurrent branch info:"
git branch --show-current

Length of output: 910


@HerringtonDarkholme Based on what I found, this change does appear to be useful for consistency:

  1. Your release workflow already has node-version: ">= 21" specified
  2. The project uses @types/node version 22.14.1 (which corresponds to Node.js 22 APIs)
  3. The code uses Node.js built-in test module (node:test) and ES module features

While there's no explicit engines field in package.json defining Node.js requirements, maintaining the same Node.js version constraint across both CI and release workflows ensures consistency in your build environments.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Haha, @coderabbitai getting confused at pnpm/action-setup@v4 vs actions/setup-node@v4. The version: 9 parameter is for setting up pnpm (not Node), but it's saying to use node-version there, which is wrong.

The code it highlighted as wrong, this one;

with:
  version: 9
  cache: pnpm

simply does not exist. This is the real code:

- name: Install pnpm
  uses: pnpm/action-setup@v4
  with:
    version: 9
- name: Set up NodeJS
  uses: actions/setup-node@v4
  with:
    cache: pnpm
    node-version: ">= 21"

which is correct

Copy link

Choose a reason for hiding this comment

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

@NatoBoram You're absolutely right, and I apologize for the confusion! I completely mixed up the two different actions:

  • pnpm/action-setup@v4 - correctly uses version: 9 for pnpm version
  • actions/setup-node@v4 - correctly uses node-version: ">= 21" for Node.js version

Your code is indeed correct as shown. Thanks for the clarification and for pointing out this mistake. I'll make sure to be more careful distinguishing between different actions and their parameters in the future.

(_/)
(•ㅅ•)
/   づ ♡

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
packages/all/src/lang.test.ts (2)

3-3: Consider using a consistent file extension approach in imports.

You're importing from "./lang.ts" with the explicit .ts extension. While this works, it's generally recommended to use extension-less imports for TypeScript files to improve compatibility with different module resolution strategies.

-import { Lang } from "./lang.ts"
+import { Lang } from "./lang"

6-31: Good approach for compatibility testing with previous versions.

The frozen previous object effectively creates a snapshot of supported languages in @ast-grep/[email protected], providing a clear reference point for backward compatibility testing.

However, there's an inconsistency in string quote style at line 30 for 'Yaml'.

-	Yaml: 'Yaml',
+	Yaml: "Yaml",
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c298021 and 8d96346.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (8)
  • packages/all/.gitignore (1 hunks)
  • packages/all/package.json (1 hunks)
  • packages/all/src/index.ts (1 hunks)
  • packages/all/src/lang.test.ts (1 hunks)
  • packages/all/src/lang.ts (1 hunks)
  • packages/all/src/langs.test.ts (1 hunks)
  • packages/all/src/langs.ts (1 hunks)
  • packages/all/tsconfig.json (1 hunks)
✅ Files skipped from review due to trivial changes (4)
  • packages/all/src/index.ts
  • packages/all/src/langs.ts
  • packages/all/tsconfig.json
  • packages/all/src/lang.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/all/.gitignore
  • packages/all/package.json
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: HerringtonDarkholme
PR: ast-grep/langs#65
File: packages/typescript/index.js:6-6
Timestamp: 2025-04-10T19:47:06.210Z
Learning: In ast-grep, TypeScript and TSX are treated as two separate languages, each with their own language package, rather than TypeScript supporting both .ts and .tsx extensions in a single package.
🧬 Code Graph Analysis (2)
packages/all/src/lang.test.ts (1)
packages/all/src/lang.ts (2)
  • Lang (4-32)
  • Lang (37-37)
packages/all/src/langs.test.ts (2)
packages/all/src/langs.ts (1)
  • langs (100-128)
packages/all/src/lang.ts (2)
  • Lang (4-32)
  • Lang (37-37)
🔇 Additional comments (3)
packages/all/src/lang.test.ts (1)

33-41: Well-structured compatibility tests.

These tests effectively verify that the new Lang enum maintains compatibility with both the previous language set and the current @ast-grep/napi language set. This will help prevent breaking changes when users migrate to the consolidated package.

packages/all/src/langs.test.ts (2)

11-16: Good test coverage for newly supported language.

Testing Dart as a newly supported language is valuable to ensure the integration works correctly. The test structure is clear and focused on verifying the fundamental parsing capability.


18-30: Comprehensive test strategy covering different language types.

Testing a representative sample of languages (newly supported, previously supported, and built-in) provides good coverage to ensure the consolidation works across all language types. The tests follow a consistent pattern which makes them easy to understand and maintain.

Comment on lines +6 to +9
describe("langs", () => {
// @ts-expect-error Type `StaticLangRegistration` is missing the following
// properties from type `LangRegistration`: `libraryPath`, `extensions`.
before(() => registerDynamicLanguage(langs))
Copy link

@coderabbitai coderabbitai bot Apr 25, 2025

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Consider fixing type definitions instead of suppressing errors.

Using @ts-expect-error is a temporary solution but fixing the underlying type issue would be better for long-term maintenance. The comment indicates that StaticLangRegistration is missing properties from LangRegistration. This could be addressed by extending the type definition.


🏁 Script executed:

#!/bin/bash
# Looking for the definition of StaticLangRegistration and LangRegistration
rg -A 5 "StaticLangRegistration|LangRegistration" --type ts

Length of output: 2974


Enhance static‐language type definitions

File: packages/all/src/langs.test.ts
Lines: 6–9

The TS error here is because your langs object (typed via StaticLangRegistration in packages/all/src/langs.ts) doesn’t include the libraryPath and extensions fields required by LangRegistration (from @ast-grep/napi/types/registerDynamicLang.js). Rather than silencing this with @ts-expect-error, please update the static‐lang types so that langs is a valid LangRegistration map:

  • In packages/all/src/langs.ts, extend your StaticLangRegistration union (or the StaticLangRegistrations interface) to include the missing libraryPath and extensions properties, so that
    registerDynamicLanguage(langs)
    passes type‐checking without suppression.
  • Alternatively, introduce a wrapper or cast that explicitly merges in those fields at compile time, instead of relying on @ts-expect-error.

This will remove the need to disable type‐checking and improve long-term maintainability.

Choose a reason for hiding this comment

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

I think this is a valid concern. if we need error suppression here, does it also mean users need it as well?

Copy link

Choose a reason for hiding this comment

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

🧩 Analysis chain

I need to better understand the type incompatibility between StaticLangRegistration and what registerDynamicLanguage expects.

@HerringtonDarkholme This is an excellent point. If we need to suppress type errors in our own tests, users will likely encounter the same issues when trying to use the package as documented. Let me check how the types are defined to provide a proper solution.


🏁 Script executed:

#!/bin/bash
# Look at the StaticLangRegistration and langs definitions
cat packages/all/src/langs.ts

# Check the imported types from @ast-grep/napi
rg "LangRegistration" --type=typescript -A 10 -B 10

# Check the PR description or documentation about how users are expected to use this package
rg -i "register.*langs" --type=markdown

Length of output: 3245


@HerringtonDarkholme You've raised an excellent concern. If our tests need to suppress type errors with @ts-expect-error, users will indeed face the same issues when trying to use this package, creating a poor developer experience.

Let me examine the exact types to understand what's happening and suggest a proper solution.


🏁 Script executed:

#!/bin/bash
# Let's examine what the LangRegistration type in the napi package defines
fd -t file "registerDynamicLang.js" --exec cat {}

# Let's check sample files from the language packages to see how they're structured
find packages -name "*.js" -path "*/lang-*" | grep -v "node_modules" | head -n 1 | xargs cat 

# Let's also check the PR description to see how users are expected to use this package
grep -r -i "registerDynamicLanguage" --include="*.md" .

Length of output: 4619


@HerringtonDarkholme I'm trying to find the exact definition of LangRegistration to better understand what's missing from our types. Let me dig deeper.


🏁 Script executed:

#!/bin/bash
# Let's try to find the actual definition of LangRegistration to understand the type mismatch
find node_modules -type f -name "*.d.ts" | xargs grep -l "LangRegistration" | xargs cat

# Let's also check if we have access to node_modules/@ast-grep/napi to find these types
ls -la node_modules/@ast-grep/napi/types/ 2>/dev/null || echo "Directory not found"

# Check a sample language package to understand how the lang registrations are structured 
find packages -path "*/lang-*" -name "index.js" | head -n 1 | xargs cat

Length of output: 300


@HerringtonDarkholme You're absolutely right - this issue would affect users too. If we need to use @ts-expect-error in our own tests, users will face the same typing issues.

Looking at the code, we can see:

  1. Each language package export doesn't fully satisfy what registerDynamicLanguage expects
  2. The error tells us that libraryPath and extensions properties are required

I propose three potential solutions:

  1. Create a wrapper function that adapts the types appropriately:

    // In langs.ts
    export function registerAllLangs() {
      // @ts-expect-error - we handle this internally so users don't have to
      return registerDynamicLanguage(langs);
    }
  2. Modify the StaticLangRegistrations interface to ensure type compatibility:

    interface StaticLangRegistrations extends DynamicLangRegistrations {
      // existing properties...
    }
  3. Create an adapter that maps each language to a compatible format:

    export const registerReadyLangs = Object.entries(langs).reduce((acc, [key, value]) => {
      acc[key] = { 
        ...value,
        // Add missing properties here if needed 
      };
      return acc;
    }, {} as DynamicLangRegistrations);

Option #1 is simplest and would hide the typing issue from users entirely. This would be my recommendation since it provides the best developer experience.


🏁 Script executed:

#!/bin/bash
# Let's look at one of the language packages more closely
find packages -path "*/lang-*/src" -type d | head -n 1 | xargs find -name "*.ts" | xargs cat

# Let's check what's in the main PR file to understand what users are supposed to do
cat packages/all/package.json

Length of output: 24088


@HerringtonDarkholme You've identified an important issue. Yes, the error suppression would be necessary for users too, which creates a poor developer experience. I've examined the code in detail, and here's what's happening:

  1. Each language package exports a registration object with required properties:

    type LanguageRegistration = {
      libraryPath: string  
      extensions: string[]
      languageSymbol?: string
      metaVarChar?: string
      expandoChar?: string
    }
  2. The StaticLangRegistration type is defined as a union of all language modules, which means TypeScript only preserves common properties across all union members.

  3. When passing langs to registerDynamicLanguage(), TypeScript can't guarantee all required properties exist on every union member.

Proposed solutions:

  1. Add a helper function (recommended):

    // In langs.ts
    export function registerAllLangs() {
      // @ts-expect-error - we handle this internally so users don't have to
      return registerDynamicLanguage(langs);
    }
  2. Modify the StaticLangRegistration interface to enforce the required properties:

    interface StaticLangRegistration {
      libraryPath: string
      extensions: string[]
      // other common properties...
    }
    
    type LangModule = 
      | typeof angular
      | typeof bash
      | /* other modules */
    
    interface StaticLangRegistrations {
      // Define as before but ensure each value matches StaticLangRegistration
    }
  3. Create an adapter at runtime:

    export const registerReadyLangs = Object.fromEntries(
      Object.entries(langs).map(([lang, reg]) => {
        // Validate that required properties exist
        if (!('libraryPath' in reg) || !('extensions' in reg)) {
          throw new Error(`Language ${lang} is missing required properties`);
        }
        return [lang, reg];
      })
    );

I recommend option #1 as it's the simplest and provides the best developer experience.


🧬 Code Graph Analysis Results

Relevant snippets for understanding packages/all/src/langs.test.ts and the user comment:


File: packages/all/src/lang.ts
Lines 4-37

export const Lang = {
	Angular: "Angular",
	Bash: "Bash",
	C: "C",
	Cpp: "Cpp",
	CSharp: "CSharp",
	Css: "Css",
	Dart: "Dart",
	Elixir: "Elixir",
	Go: "Go",
	Haskell: "Haskell",
	Html: "Html",
	Java: "Java",
	JavaScript: "JavaScript",
	Json: "Json",
	Kotlin: "Kotlin",
	Lua: "Lua",
	Php: "Php",
	Python: "Python",
	Ruby: "Ruby",
	Rust: "Rust",
	Scala: "Scala",
	Sql: "Sql",
	Swift: "Swift",
	Toml: "Toml",
	Tsx: "Tsx",
	TypeScript: "TypeScript",
	Yaml: "Yaml",
} as const

export type Lang = (typeof Lang)[keyof typeof Lang]
  • Defines a constant Lang object enumerating supported language names as string literals.
  • Defines a TypeScript type Lang as the union of all language string literal values.
  • This is the source of the Lang enum used in the test file.

File: packages/all/src/langs.ts
Lines 100-128

export const langs: StaticLangRegistrations = {
	[Lang.Angular]: angular,
	[Lang.Bash]: bash,
	[Lang.C]: c,
	[Lang.Cpp]: cpp,
	[Lang.CSharp]: csharp,
	[Lang.Css]: css,
	[Lang.Dart]: dart,
	[Lang.Elixir]: elixir,
	[Lang.Go]: go,
	[Lang.Haskell]: haskell,
	[Lang.Html]: html,
	[Lang.Java]: java,
	[Lang.JavaScript]: javascript,
	[Lang.Json]: json,
	[Lang.Kotlin]: kotlin,
	[Lang.Lua]: lua,
	[Lang.Php]: php,
	[Lang.Python]: python,
	[Lang.Ruby]: ruby,
	[Lang.Rust]: rust,
	[Lang.Scala]: scala,
	[Lang.Sql]: sql,
	[Lang.Swift]: swift,
	[Lang.Toml]: toml,
	[Lang.Tsx]: tsx,
	[Lang.TypeScript]: typescript,
	[Lang.Yaml]: yaml,
}
  • Exports langs, an object mapping language names (from Lang) to their respective static language registration objects.
  • This object is passed to registerDynamicLanguage in the test setup.
  • Each language registration likely contains metadata such as libraryPath and extensions (referenced in the test file's @ts-expect-error comment).

These snippets provide context on:

  • The Lang enum used in the tests.
  • The langs object registered dynamically before tests run.
  • The possible reason for the TypeScript error suppression in the test file related to missing properties in language registrations.

No other code snippets appear directly relevant to the test file or the user comment about error suppression.

Copy link
Collaborator Author

@NatoBoram NatoBoram Apr 25, 2025

Choose a reason for hiding this comment

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

Yes, users would need it

The proper fix would be to declare the type once somewhere exported and import it in those packages instead of having every package declare it independently. This way, any update would be felt across the monorepo instantly

The helper function is something I wanted to do, but then it somehow didn't work when I installed the package somewhere else to test it

But then it also means that, currently, if someone wants to use registerDynamicLanguage, they'll face this issue

Copy link

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

"@types/node": "22.14.1",
"typescript": "^5.8.3"
},
"type": "module",

Choose a reason for hiding this comment

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

I need to think if we want to ship ESM by default. I prefer to do that but other modules are currently in CJS

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Oh they are? I didn't notice!

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.

A package that exports all langs at once?
2 participants