feat: custom runtime package + info in package.json#6039
Conversation
📝 WalkthroughWalkthroughThis PR enables NativeScript projects to override the default scoped runtime package names per platform. Type definitions add optional ChangesPlatform-scoped runtime configuration
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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 |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (5)
lib/services/android-plugin-build-service.ts (3)
575-634:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winCritical: Using wrong project config for gradle version queries.
The method reads
this.$projectData.nsConfig.android?.runtimePackageName(line 588) from the injected singleton. This should use theprojectDataparameter added in the previous fix.🐛 Proposed fix (continuation of previous fix)
After applying the parameter changes from the previous segment:
private async getGradleVersions( runtimeVersion: string, + projectData: IProjectData ): Promise<IRuntimeGradleVersions> { let runtimeGradleVersions: { versions: { gradle: string; gradleAndroid: string }; } = null; - const localVersionInfo = this.getLocalGradleVersions(); + const localVersionInfo = this.getLocalGradleVersions(projectData); if (localVersionInfo) { return localVersionInfo; } - const packageName = this.$projectData.nsConfig.android?.runtimePackageName || SCOPED_ANDROID_RUNTIME_NAME; + const packageName = projectData.nsConfig.android?.runtimePackageName || SCOPED_ANDROID_RUNTIME_NAME; // fallback to reading from npm...And update the other call site at line 478:
if (!runtimeGradleVersions) { const latestRuntimeVersion = await this.getLatestRuntimeVersion(projectData); runtimeGradleVersions = await this.getGradleVersions( - latestRuntimeVersion + latestRuntimeVersion, + projectData );🤖 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 `@lib/services/android-plugin-build-service.ts` around lines 575 - 634, In getGradleVersions(...) replace references to the injected singleton this.$projectData.nsConfig.android?.runtimePackageName with the function parameter projectData.nsConfig.android?.runtimePackageName so packageName is derived from the passed-in projectData (falling back to SCOPED_ANDROID_RUNTIME_NAME as before); also update any other call-sites that were changed to pass projectData so the method uses that parameter instead of this.$projectData.
491-514:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winCritical: Using wrong project config for runtime version lookup.
The method reads
this.$projectData.nsConfig.android?.runtimePackageNamefrom the injected singleton, but should use the config from theprojectDirbeing processed. The callergetRuntimeGradleVersions()correctly retrievesprojectDataat line 459 but doesn't pass it to this method.🐛 Proposed fix to accept and use correct project data
- private async getLatestRuntimeVersion(): Promise<string> { + private async getLatestRuntimeVersion(projectData: IProjectData): Promise<string> { let runtimeVersion: string = null; - const packageName = this.$projectData.nsConfig.android?.runtimePackageName || SCOPED_ANDROID_RUNTIME_NAME; + const packageName = projectData.nsConfig.android?.runtimePackageName || SCOPED_ANDROID_RUNTIME_NAME; try {Then update the call site at line 477:
if (!runtimeGradleVersions) { - const latestRuntimeVersion = await this.getLatestRuntimeVersion(); + const latestRuntimeVersion = await this.getLatestRuntimeVersion(projectData); runtimeGradleVersions = await this.getGradleVersions(🤖 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 `@lib/services/android-plugin-build-service.ts` around lines 491 - 514, The getLatestRuntimeVersion method uses the injected singleton this.$projectData instead of the per-project data; change its signature (e.g., getLatestRuntimeVersion(projectData: IProjectData) or getLatestRuntimeVersion(projectDir: string) and use the project-specific config when resolving package name (use projectData.nsConfig.android?.runtimePackageName || SCOPED_ANDROID_RUNTIME_NAME), and update the caller getRuntimeGradleVersions to pass the projectData it already obtains; keep the existing try/catch lookup logic but reference the passed-in projectData for the runtimePackageName lookup.
516-573:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winCritical: Using wrong project config and directory for local gradle versions.
The method reads both
this.$projectData.nsConfig.android?.runtimePackageName(line 532) andthis.$projectData.projectDir(line 537) from the injected singleton. It should use the config and directory from the project being built.🐛 Proposed fix to accept and use correct project data
- private getLocalGradleVersions(): IRuntimeGradleVersions { + private getLocalGradleVersions(projectData: IProjectData): IRuntimeGradleVersions { // partial interface of the runtime package.json // including new 8.2+ format and legacy interface IRuntimePackageJSON { // 8.2+ version_info?: { gradle: string; gradleAndroid: string; }; // legacy gradle?: { version: string; android: string; }; } - const packageName = this.$projectData.nsConfig.android?.runtimePackageName || SCOPED_ANDROID_RUNTIME_NAME; + const packageName = projectData.nsConfig.android?.runtimePackageName || SCOPED_ANDROID_RUNTIME_NAME; // try reading from installed runtime first before reading from the npm registry... const installedRuntimePackageJSONPath = resolvePackageJSONPath( packageName, { - paths: [this.$projectData.projectDir], + paths: [projectData.projectDir], } );Then update the call site at line 582:
- const localVersionInfo = this.getLocalGradleVersions(); + const localVersionInfo = this.getLocalGradleVersions(projectData);And pass
projectDatatogetGradleVersionsfrom line 466:runtimeGradleVersions = await this.getGradleVersions( - projectRuntimeVersion + projectRuntimeVersion, + projectData );And update the method signature at line 575:
private async getGradleVersions( - runtimeVersion: string + runtimeVersion: string, + projectData: IProjectData ): Promise<IRuntimeGradleVersions> {🤖 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 `@lib/services/android-plugin-build-service.ts` around lines 516 - 573, The method getLocalGradleVersions is using this.$projectData (this.$projectData.nsConfig.android?.runtimePackageName and this.$projectData.projectDir) which reads the singleton instead of the project being built; change getLocalGradleVersions to accept a ProjectData parameter (e.g., projectData) and use projectData.nsConfig.android?.runtimePackageName and projectData.projectDir when resolving and reading the runtime package.json, then update any callers (notably the getGradleVersions call site) to pass the current projectData through to getLocalGradleVersions and adjust the getGradleVersions signature if it proxies this call so the correct project config/directory is used for local gradle version resolution.lib/services/project-data-service.ts (2)
687-706:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winCritical: Using wrong project config in fallback return.
The fallback return values also read from
this.$projectData.nsConfiginstead of the config for the providedprojectDirparameter. This is the same contract violation as the previous segment.🐛 Proposed fix to read config from the correct project
// default to the scoped runtimes this.$logger.trace( "Could not find an installed runtime, falling back to default runtimes" ); + const projectData = this.getProjectData(projectDir); if (platform === constants.PlatformTypes.ios) { return { - name: this.$projectData.nsConfig.ios?.runtimePackageName || constants.SCOPED_IOS_RUNTIME_NAME, + name: projectData.nsConfig.ios?.runtimePackageName || constants.SCOPED_IOS_RUNTIME_NAME, version: null, }; } else if (platform === constants.PlatformTypes.android) { return { - name: this.$projectData.nsConfig.android?.runtimePackageName || constants.SCOPED_ANDROID_RUNTIME_NAME, + name: projectData.nsConfig.android?.runtimePackageName || constants.SCOPED_ANDROID_RUNTIME_NAME, version: null, };🤖 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 `@lib/services/project-data-service.ts` around lines 687 - 706, The fallback branch is incorrectly reading nsConfig from this.$projectData instead of the project-specific config for the provided projectDir; update the returns to use the local projectData.nsConfig (the same projectData used earlier in this function) rather than this.$projectData.nsConfig so iOS/Android runtimePackageName is read from the correct project; keep the existing names (SCOPED_IOS_RUNTIME_NAME, SCOPED_ANDROID_RUNTIME_NAME, SCOPED_VISIONOS_RUNTIME_NAME) and null version unchanged.
624-646:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winCritical: Using wrong project config for runtime package resolution.
The method accepts
projectDiras a parameter but reads runtime package names from the injectedthis.$projectData.nsConfigsingleton. WhengetRuntimePackage()is called with aprojectDirdifferent from the default project, the method will use the wrong configuration.🐛 Proposed fix to read config from the correct project
private getInstalledRuntimePackage( projectDir: string, platform: constants.SupportedPlatform ): IBasePluginData { + const projectData = this.getProjectData(projectDir); const runtimePackage = this.$pluginsService .getDependenciesFromPackageJson(projectDir) .devDependencies.find((d) => { if (platform === constants.PlatformTypes.ios) { - const packageName = this.$projectData.nsConfig.ios?.runtimePackageName || constants.SCOPED_IOS_RUNTIME_NAME; + const packageName = projectData.nsConfig.ios?.runtimePackageName || constants.SCOPED_IOS_RUNTIME_NAME; return [ packageName, constants.TNS_IOS_RUNTIME_NAME, ].includes(d.name); } else if (platform === constants.PlatformTypes.android) { - const packageName = this.$projectData.nsConfig.android?.runtimePackageName || constants.SCOPED_ANDROID_RUNTIME_NAME; + const packageName = projectData.nsConfig.android?.runtimePackageName || constants.SCOPED_ANDROID_RUNTIME_NAME; return [ packageName, constants.TNS_ANDROID_RUNTIME_NAME, ].includes(d.name);🤖 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 `@lib/services/project-data-service.ts` around lines 624 - 646, getInstalledRuntimePackage reads runtime package names from the global this.$projectData.nsConfig which is wrong for arbitrary projectDir; load the project-specific project data for the supplied projectDir (e.g. obtain a local projectData variable by calling the service that returns project metadata for projectDir) and replace all uses of this.$projectData.nsConfig with that projectData.nsConfig so runtimePackageName resolution for ios/android/visionos uses the correct config when called with a non-default projectDir.
🤖 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.
Outside diff comments:
In `@lib/services/android-plugin-build-service.ts`:
- Around line 575-634: In getGradleVersions(...) replace references to the
injected singleton this.$projectData.nsConfig.android?.runtimePackageName with
the function parameter projectData.nsConfig.android?.runtimePackageName so
packageName is derived from the passed-in projectData (falling back to
SCOPED_ANDROID_RUNTIME_NAME as before); also update any other call-sites that
were changed to pass projectData so the method uses that parameter instead of
this.$projectData.
- Around line 491-514: The getLatestRuntimeVersion method uses the injected
singleton this.$projectData instead of the per-project data; change its
signature (e.g., getLatestRuntimeVersion(projectData: IProjectData) or
getLatestRuntimeVersion(projectDir: string) and use the project-specific config
when resolving package name (use
projectData.nsConfig.android?.runtimePackageName ||
SCOPED_ANDROID_RUNTIME_NAME), and update the caller getRuntimeGradleVersions to
pass the projectData it already obtains; keep the existing try/catch lookup
logic but reference the passed-in projectData for the runtimePackageName lookup.
- Around line 516-573: The method getLocalGradleVersions is using
this.$projectData (this.$projectData.nsConfig.android?.runtimePackageName and
this.$projectData.projectDir) which reads the singleton instead of the project
being built; change getLocalGradleVersions to accept a ProjectData parameter
(e.g., projectData) and use projectData.nsConfig.android?.runtimePackageName and
projectData.projectDir when resolving and reading the runtime package.json, then
update any callers (notably the getGradleVersions call site) to pass the current
projectData through to getLocalGradleVersions and adjust the getGradleVersions
signature if it proxies this call so the correct project config/directory is
used for local gradle version resolution.
In `@lib/services/project-data-service.ts`:
- Around line 687-706: The fallback branch is incorrectly reading nsConfig from
this.$projectData instead of the project-specific config for the provided
projectDir; update the returns to use the local projectData.nsConfig (the same
projectData used earlier in this function) rather than
this.$projectData.nsConfig so iOS/Android runtimePackageName is read from the
correct project; keep the existing names (SCOPED_IOS_RUNTIME_NAME,
SCOPED_ANDROID_RUNTIME_NAME, SCOPED_VISIONOS_RUNTIME_NAME) and null version
unchanged.
- Around line 624-646: getInstalledRuntimePackage reads runtime package names
from the global this.$projectData.nsConfig which is wrong for arbitrary
projectDir; load the project-specific project data for the supplied projectDir
(e.g. obtain a local projectData variable by calling the service that returns
project metadata for projectDir) and replace all uses of
this.$projectData.nsConfig with that projectData.nsConfig so runtimePackageName
resolution for ios/android/visionos uses the correct config when called with a
non-default projectDir.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: da1377bb-8935-42da-bd83-74f1ea9e69b1
📒 Files selected for processing (4)
lib/controllers/prepare-controller.tslib/definitions/project.d.tslib/services/android-plugin-build-service.tslib/services/project-data-service.ts
As we discussed this PR adds custom android/ios runtime package support.
It also adds those informations + version inside the packaged package.json. This is useful if you want to show the info in your app.
Please test it
Summary by CodeRabbit
Release Notes