feat(autolink): add native extension tooling#2582
Conversation
🦋 Changeset detectedLatest commit: 59f1be0 The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (28)
✅ Files skipped from review due to trivial changes (18)
🚧 Files skipped from review as they are similar to previous changes (10)
📝 WalkthroughWalkthroughAdds two Lynx packages: ChangesNative Autolink Tooling Packages
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. 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. Comment |
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
c95c0c4 to
1cd3754
Compare
There was a problem hiding this comment.
Pull request overview
This PR adds first-party Native Autolink extension tooling to the Lynx monorepo: a dedicated native codegen CLI/package and an interactive/non-interactive scaffolder for creating Native Module / Element / Service extension packages, and wires both into the repo’s TS/Vitest/Turbo/workflow setup.
Changes:
- Added
@lynx-js/autolink-codegen(CLI:lynx-autolink-codegen) to generate JS facade + Android/iOS native specs fromtypes/**/*.d.tsandlynx.ext.json. - Added
create-lynx-extensionto scaffold Native Autolink extension projects (module/element/service) with example app + templates. - Integrated new packages into TS project references, Vitest workspace config, CI cache key patterns, lockfile, and changesets.
Reviewed changes
Copilot reviewed 33 out of 34 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| vitest.config.ts | Expands Vitest workspace coverage to include all packages/lynx/* projects’ Vitest configs. |
| pnpm-lock.yaml | Adds the new Lynx package importers to the lockfile. |
| packages/lynx/tsconfig.json | Adds TS project references for autolink-codegen and create-lynx-extension. |
| packages/lynx/create-lynx-extension/vitest.config.ts | Adds Vitest configuration for the new scaffolding package. |
| packages/lynx/create-lynx-extension/turbo.json | Defines Turbo tasks/outputs for build/test in the scaffolding package. |
| packages/lynx/create-lynx-extension/tsconfig.test.json | Adds TS config for tests in the scaffolding package. |
| packages/lynx/create-lynx-extension/tsconfig.json | Adds solution-style TS references for build + test configs. |
| packages/lynx/create-lynx-extension/tsconfig.build.json | Adds TS build config used by the scaffolding package build tooling. |
| packages/lynx/create-lynx-extension/test/create.test.ts | Adds tests covering scaffolding behavior and generated template contents. |
| packages/lynx/create-lynx-extension/src/index.ts | Implements extension scaffolding + template generation logic. |
| packages/lynx/create-lynx-extension/src/cli.ts | Implements the create-lynx-extension CLI (interactive + flags). |
| packages/lynx/create-lynx-extension/rslib.config.ts | Configures rslib build for library + CLI outputs. |
| packages/lynx/create-lynx-extension/README.md | Documents usage (interactive and non-interactive) for scaffolding. |
| packages/lynx/create-lynx-extension/package.json | Defines package metadata and CLI bin entry. |
| packages/lynx/create-lynx-extension/CHANGELOG.md | Introduces initial changelog entry for the new package. |
| packages/lynx/autolink-codegen/vitest.config.ts | Adds Vitest configuration for the codegen package. |
| packages/lynx/autolink-codegen/turbo.json | Defines Turbo tasks/outputs for build/test in the codegen package. |
| packages/lynx/autolink-codegen/tsconfig.test.json | Adds TS config for tests in the codegen package. |
| packages/lynx/autolink-codegen/tsconfig.json | Adds solution-style TS references for build + test configs. |
| packages/lynx/autolink-codegen/tsconfig.build.json | Adds TS build config used by the codegen package build tooling. |
| packages/lynx/autolink-codegen/test/codegen.test.ts | Adds tests for parsing and generating JS/Android/iOS artifacts plus error cases. |
| packages/lynx/autolink-codegen/src/index.ts | Implements parsing of @lynxmodule declarations and multi-platform spec generation. |
| packages/lynx/autolink-codegen/src/cli.ts | Implements the lynx-autolink-codegen CLI wrapper around generation. |
| packages/lynx/autolink-codegen/rslib.config.ts | Configures rslib build for library + CLI outputs. |
| packages/lynx/autolink-codegen/README.md | Documents the codegen package behavior and CLI name. |
| packages/lynx/autolink-codegen/package.json | Defines package metadata and CLI bin entry. |
| packages/lynx/autolink-codegen/CHANGELOG.md | Introduces initial changelog entry for the new package. |
| .github/workflows/workflow-website.yml | Narrows Turbo cache key hashing inputs to specific Rust source trees. |
| .github/workflows/workflow-test.yml | Narrows Turbo cache key hashing inputs to specific Rust source trees. |
| .github/workflows/workflow-bundle-analysis.yml | Narrows Turbo cache key hashing inputs to specific Rust source trees. |
| .github/workflows/workflow-build.yml | Narrows Turbo cache key hashing inputs and restore keys to specific Rust source trees. |
| .github/workflows/workflow-bench.yml | Narrows Turbo cache key hashing inputs to specific Rust source trees. |
| .github/autolink-extension.instructions.md | Adds repo guidance for current Native Autolink package/CLI/marker names. |
| .changeset/native-autolink-codegen.md | Adds a changeset announcing the two new packages. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Actionable comments posted: 10
🧹 Nitpick comments (1)
packages/lynx/create-lynx-extension/package.json (1)
1-39: 💤 Low valueAdd
"sideEffects": falsefor consistency with the sibling package.
@lynx-js/autolink-codegendeclares"sideEffects": falsebut this package does not. Adding it makes the intent explicit and keeps the two packages consistent.✨ Proposed addition
"license": "Apache-2.0", + "sideEffects": false, "type": "module",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/lynx/create-lynx-extension/package.json` around lines 1 - 39, The package.json for the create-lynx-extension package is missing the "sideEffects": false field; add "sideEffects": false at the top-level of package.json (alongside "type" and "exports") to explicitly mark the package as side-effect-free, matching the sibling package `@lynx-js/autolink-codegen` and ensuring consistent bundler/tree-shaking behavior for the create-lynx-extension package.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/lynx/autolink-codegen/package.json`:
- Around line 37-39: The package.json "engines" field currently specifies
"node": "^22 || ^24", which excludes Node 20 LTS; either include Node 20 by
changing the "engines" value to include "^20 || ^22 || ^24" (or a suitable
semver range that covers Node 20) or, if Node 20 exclusion is deliberate, add a
short explanation referencing this decision (e.g., required runtime features or
flags) in the package README (or a nearby package.json-readable field) so
consumers understand why "engines" excludes Node 20; update the "engines" field
or add the explanatory note accordingly.
In `@packages/lynx/autolink-codegen/src/cli.ts`:
- Around line 26-36: The --root / -r handler currently accepts argv[index + 1]
even if it's another flag; update the guard in the CLI parsing loop so after
reading const value = argv[index + 1] you also reject values that look like
flags (e.g. start with '-' or '--') and throw an error (or show help) instead of
assigning; specifically modify the block that sets options.root (referencing
arg, argv, index, value, and options.root) to validate that value is not a flag
token before assigning and incrementing index.
In `@packages/lynx/autolink-codegen/src/index.ts`:
- Around line 143-146: The current loop writes outputs using path.join(root,
file.path) which can be escaped via ".." or absolute paths; update the logic in
the file-processing loop that computes target (used with fs.writeFileSync and
fs.mkdirSync) to resolve and validate the target before writing: compute an
absolute resolvedTarget using path.resolve(root, file.path) (or
path.join+path.normalize then path.resolve), verify that resolvedTarget is
inside the package root (e.g., ensure path.relative(root, resolvedTarget) does
not start with ".." and is not equal to ".." or that
resolvedTarget.startsWith(path.resolve(root) + path.sep)), and if the check
fails reject/throw and skip writing; only call fs.mkdirSync and fs.writeFileSync
when the resolvedTarget is confirmed safe.
- Around line 160-177: parseMethods() currently uses body.split(';') which
forces semicolons and rejects valid TS where class members are
newline-separated; replace that naive split with a tokenizer that iterates over
lines and accumulates into a declaration until it detects a complete signature
(balanced parentheses and optional return colon after the final ')' as checked
by openParen/closeParen/returnColon logic). Concretely, in parseMethods() stop
using body.split(';') and instead loop through body.split(/\r?\n/), append each
line to a buffer, skip empty buffers, and only treat the buffer as a declaration
when you can compute openParen/closeParen and returnColon to satisfy the
existing validity check; then reset the buffer and continue. This preserves the
existing validation logic (openParen/closeParen/returnColon) while supporting
semicolon-optional declarations.
In `@packages/lynx/autolink-codegen/tsconfig.build.json`:
- Around line 4-8: Remove the dead outDir setting from the tsconfig build file:
because composite: true and noEmit: true are intentionally used with rslib
(configured via rslib.config.ts) TypeScript will not emit artifacts, so delete
the "outDir": "dist" entry and keep composite and noEmit as-is to match the
established pattern used across packages.
In `@packages/lynx/create-lynx-extension/src/cli.ts`:
- Around line 123-147: fillInteractiveOptions currently always prompts via
readline which blocks CI; change it to fail fast when running non-interactively
by checking TTYs before asking. In fillInteractiveOptions (and any call-sites
like main that rely on it), if next.dir or next.types are missing and either
process.stdin.isTTY or process.stdout.isTTY is false, throw a clear Error (or
return a rejected Promise) instead of calling ask/creating readline; only create
the readline interface and call ask when both process.stdin.isTTY and
process.stdout.isTTY are true so prompts happen only in interactive sessions.
In `@packages/lynx/create-lynx-extension/src/index.ts`:
- Around line 66-70: The loop writing files currently joins user-controlled
file.path to targetDir and may allow directory traversal; before creating
directories or writing, resolve the intended destination with
path.resolve(targetDir, file.path) (replace the current path.join usage) and
verify it is inside targetDir (e.g., check that path.relative(targetDir,
resolvedPath) does not start with '..' or that
resolvedPath.startsWith(path.resolve(targetDir) + path.sep)); if the check
fails, throw or skip the file. Update references in this block (the for loop
handling files, the absolutePath variable, and the fs.mkdirSync/fs.writeFileSync
calls) to use the validated resolved path.
In `@packages/lynx/create-lynx-extension/test/create.test.ts`:
- Around line 44-90: The test asserts content of ios .h files (read(dir,
'ios/src/ButtonElement.h'), read(dir, 'ios/src/ButtonService.h'), and later
'ios/src/ViewService.h') but the expect.arrayContaining list in create.test.ts
only includes the .m files; update the expect.arrayContaining([...]) call (the
array inside the expect(files.map((file) =>
file.path)).toEqual(expect.arrayContaining(...))) to also include
'ios/src/ButtonElement.h', 'ios/src/ButtonService.h' (and
'ios/src/ViewService.h' where applicable) so the presence assertions match the
subsequent read(...) content checks; alternatively, if the generator produces .m
only, change the offending read(...) checks to target the .m files instead —
locate the arrayContaining usage and the read(...) lines in create.test.ts to
make the fix.
In `@packages/lynx/create-lynx-extension/tsconfig.build.json`:
- Around line 4-8: The tsconfig.build.json currently sets "composite": true
together with "noEmit": true which triggers TS5053; open the tsconfig.build.json
for this package and either remove "noEmit" or replace it with
"emitDeclarationOnly": true so declaration emission works with "composite": true
(alternatively remove "composite" if project references aren't needed); update
the JSON to use "emitDeclarationOnly": true (or delete "composite") and run a
local tsc -p tsconfig.build.json to verify the TS5053 error is resolved.
In `@packages/lynx/create-lynx-extension/tsconfig.test.json`:
- Around line 1-8: The test tsconfig (tsconfig.test.json) inherits "composite:
true" from tsconfig.build.json while also setting "noEmit": true, creating the
incompatible composite+noEmit combination; fix it by overriding the compiler
option in tsconfig.test.json to set "composite": false (or remove extends and
craft an explicit test config) so that the "noEmit" flag is compatible—update
the "compilerOptions" in tsconfig.test.json to explicitly set composite to false
to resolve the issue.
---
Nitpick comments:
In `@packages/lynx/create-lynx-extension/package.json`:
- Around line 1-39: The package.json for the create-lynx-extension package is
missing the "sideEffects": false field; add "sideEffects": false at the
top-level of package.json (alongside "type" and "exports") to explicitly mark
the package as side-effect-free, matching the sibling package
`@lynx-js/autolink-codegen` and ensuring consistent bundler/tree-shaking behavior
for the create-lynx-extension package.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: abbb493a-f99f-4c97-a3e0-8a5b6954e3dc
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (33)
.changeset/native-autolink-codegen.md.github/autolink-extension.instructions.md.github/workflows/workflow-bench.yml.github/workflows/workflow-build.yml.github/workflows/workflow-bundle-analysis.yml.github/workflows/workflow-test.yml.github/workflows/workflow-website.ymlpackages/lynx/autolink-codegen/CHANGELOG.mdpackages/lynx/autolink-codegen/README.mdpackages/lynx/autolink-codegen/package.jsonpackages/lynx/autolink-codegen/rslib.config.tspackages/lynx/autolink-codegen/src/cli.tspackages/lynx/autolink-codegen/src/index.tspackages/lynx/autolink-codegen/test/codegen.test.tspackages/lynx/autolink-codegen/tsconfig.build.jsonpackages/lynx/autolink-codegen/tsconfig.jsonpackages/lynx/autolink-codegen/tsconfig.test.jsonpackages/lynx/autolink-codegen/turbo.jsonpackages/lynx/autolink-codegen/vitest.config.tspackages/lynx/create-lynx-extension/CHANGELOG.mdpackages/lynx/create-lynx-extension/README.mdpackages/lynx/create-lynx-extension/package.jsonpackages/lynx/create-lynx-extension/rslib.config.tspackages/lynx/create-lynx-extension/src/cli.tspackages/lynx/create-lynx-extension/src/index.tspackages/lynx/create-lynx-extension/test/create.test.tspackages/lynx/create-lynx-extension/tsconfig.build.jsonpackages/lynx/create-lynx-extension/tsconfig.jsonpackages/lynx/create-lynx-extension/tsconfig.test.jsonpackages/lynx/create-lynx-extension/turbo.jsonpackages/lynx/create-lynx-extension/vitest.config.tspackages/lynx/tsconfig.jsonvitest.config.ts
1cd3754 to
bc9c92a
Compare
Web Explorer#9511 Bundle Size — 900.02KiB (0%).59f1be0(current) vs 5b6a33d main#9500(baseline) Bundle metrics
|
| Current #9511 |
Baseline #9500 |
|
|---|---|---|
44.46KiB |
44.46KiB |
|
2.22KiB |
2.22KiB |
|
0% |
0% |
|
9 |
9 |
|
11 |
11 |
|
229 |
229 |
|
11 |
11 |
|
27.28% |
27.28% |
|
10 |
10 |
|
0 |
0 |
Bundle size by type no changes
| Current #9511 |
Baseline #9500 |
|
|---|---|---|
495.88KiB |
495.88KiB |
|
401.92KiB |
401.92KiB |
|
2.22KiB |
2.22KiB |
Bundle analysis report Branch jianliang00:codex/native-autolin... Project dashboard
Generated by RelativeCI Documentation Report issue
React MTF Example#1069 Bundle Size — 206.69KiB (0%).59f1be0(current) vs 5b6a33d main#1058(baseline) Bundle metrics
|
| Current #1069 |
Baseline #1058 |
|
|---|---|---|
0B |
0B |
|
0B |
0B |
|
0% |
0% |
|
0 |
0 |
|
3 |
3 |
|
192 |
192 |
|
77 |
77 |
|
44.36% |
44.36% |
|
2 |
2 |
|
0 |
0 |
Bundle size by type no changes
| Current #1069 |
Baseline #1058 |
|
|---|---|---|
111.23KiB |
111.23KiB |
|
95.46KiB |
95.46KiB |
Bundle analysis report Branch jianliang00:codex/native-autolin... Project dashboard
Generated by RelativeCI Documentation Report issue
React External#1054 Bundle Size — 690.27KiB (0%).59f1be0(current) vs 5b6a33d main#1043(baseline) Bundle metrics
|
| Current #1054 |
Baseline #1043 |
|
|---|---|---|
0B |
0B |
|
0B |
0B |
|
0% |
0% |
|
0 |
0 |
|
3 |
3 |
|
17 |
17 |
|
5 |
5 |
|
8.59% |
8.59% |
|
0 |
0 |
|
0 |
0 |
Bundle analysis report Branch jianliang00:codex/native-autolin... Project dashboard
Generated by RelativeCI Documentation Report issue
React Example#7939 Bundle Size — 235.77KiB (0%).59f1be0(current) vs 5b6a33d main#7928(baseline) Bundle metrics
|
| Current #7939 |
Baseline #7928 |
|
|---|---|---|
0B |
0B |
|
0B |
0B |
|
0% |
0% |
|
0 |
0 |
|
4 |
4 |
|
197 |
197 |
|
80 |
80 |
|
44.85% |
44.85% |
|
2 |
2 |
|
0 |
0 |
Bundle size by type no changes
| Current #7939 |
Baseline #7928 |
|
|---|---|---|
145.76KiB |
145.76KiB |
|
90.01KiB |
90.01KiB |
Bundle analysis report Branch jianliang00:codex/native-autolin... Project dashboard
Generated by RelativeCI Documentation Report issue
React Example with Element Template#204 Bundle Size — 197.77KiB (0%).59f1be0(current) vs 5b6a33d main#193(baseline) Bundle metrics
Bundle size by type
|
| Current #204 |
Baseline #193 |
|
|---|---|---|
145.76KiB |
145.76KiB |
|
52.01KiB |
52.01KiB |
Bundle analysis report Branch jianliang00:codex/native-autolin... Project dashboard
Generated by RelativeCI Documentation Report issue
Merging this PR will degrade performance by 12.98%
|
| Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|
| ⚡ | 008-many-use-state-destroyBackground |
9.5 ms | 8 ms | +19.24% |
| ❌ | transform 1000 view elements |
40 ms | 46 ms | -12.98% |
Comparing jianliang00:codex/native-autolink-extension-codegen (59f1be0) with main (5b6a33d)
Footnotes
-
26 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩
7f798d3 to
a483288
Compare
a483288 to
59f1be0
Compare
|
Superseded by #2587 to remove the codex keyword from the head branch name. |
Summary
@lynx-js/autolink-codegenfor Native-only JS, Android, and iOS spec generationcreate-lynx-extensionscaffolding for Native Module, Element, and Service extensionslynx-autolink-codegenCLI name in package metadata, generated templates, docs, and testsValidation
pnpm --filter @lynx-js/autolink-codegen testpnpm --filter create-lynx-extension testpnpm --filter @lynx-js/autolink-codegen buildpnpm --filter create-lynx-extension buildpnpm dprint checkpnpm biome checkpnpm eslint --cache --fix --no-warn-ignored --flag v10_config_lookup_from_file packages/lynx/autolink-codegen packages/lynx/create-lynx-extensionSummary by CodeRabbit