Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ injector.requireCommand("run|ios", "./commands/run");
injector.requireCommand("run|android", "./commands/run");
injector.requireCommand("run|vision", "./commands/run");
injector.requireCommand("run|visionos", "./commands/run");
injector.requireCommand("run|macos", "./commands/run");
injector.requireCommand("typings", "./commands/typings");

injector.requireCommand("preview", "./commands/preview");
Expand All @@ -197,6 +198,7 @@ injector.requireCommand("build|ios", "./commands/build");
injector.requireCommand("build|android", "./commands/build");
injector.requireCommand("build|vision", "./commands/build");
injector.requireCommand("build|visionos", "./commands/build");
injector.requireCommand("build|macos", "./commands/build");
injector.requireCommand("deploy", "./commands/deploy");

injector.requireCommand("embed", "./commands/embedding/embed");
Expand Down
55 changes: 55 additions & 0 deletions lib/commands/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,3 +277,58 @@ export class BuildVisionOsCommand extends BuildIosCommand implements ICommand {

injector.registerCommand("build|vision", BuildVisionOsCommand);
injector.registerCommand("build|visionos", BuildVisionOsCommand);

export class BuildMacOSCommand extends BuildIosCommand implements ICommand {
constructor(
protected $options: IOptions,
$errors: IErrors,
$projectData: IProjectData,
$platformsDataService: IPlatformsDataService,
$devicePlatformsConstants: Mobile.IDevicePlatformsConstants,
$buildController: IBuildController,
$platformValidationService: IPlatformValidationService,
$logger: ILogger,
$buildDataService: IBuildDataService,
protected $migrateController: IMigrateController,
) {
super(
$options,
$errors,
$projectData,
$platformsDataService,
$devicePlatformsConstants,
$buildController,
$platformValidationService,
$logger,
$buildDataService,
$migrateController,
);
}

public async execute(args: string[]): Promise<void> {
await this.executeCore([
this.$devicePlatformsConstants.macOS.toLowerCase(),
]);
}

public async canExecute(args: string[]): Promise<boolean> {
const platform = this.$devicePlatformsConstants.macOS;
if (!this.$options.force) {
await this.$migrateController.validate({
projectDir: this.$projectData.projectDir,
platforms: [platform],
});
}

super.validatePlatform(platform);

let canExecute = await super.canExecuteCommandBase(platform);
if (canExecute) {
canExecute = await super.validateArgs(args, platform);
}

return canExecute;
}
}

injector.registerCommand("build|macos", BuildMacOSCommand);
69 changes: 68 additions & 1 deletion lib/commands/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,14 @@ import {
ANDROID_APP_BUNDLE_SIGNING_ERROR_MESSAGE,
ANDROID_RELEASE_BUILD_ERROR_MESSAGE,
} from "../constants";
import { IOptions, IPlatformValidationService } from "../declarations";
import {
IOpener,
IOptions,
IPlatformValidationService,
} from "../declarations";
import { IMigrateController } from "../definitions/migrate";
import { IProjectData, IProjectDataService } from "../definitions/project";
import { IBuildController, IBuildDataService } from "../definitions/build";

export class RunCommandBase implements ICommand {
private liveSyncCommandHelperAdditionalOptions: ILiveSyncCommandHelperAdditionalOptions =
Expand Down Expand Up @@ -223,3 +228,65 @@ export class RunVisionOSCommand extends RunIosCommand {

injector.registerCommand("run|vision", RunVisionOSCommand);
injector.registerCommand("run|visionos", RunVisionOSCommand);

export class RunMacOSCommand implements ICommand {
public allowedParameters: ICommandParameter[] = [];

public get platform(): string {
return this.$devicePlatformsConstants.macOS || "macOS";
}

constructor(
private $buildController: IBuildController,
private $buildDataService: IBuildDataService,
private $devicePlatformsConstants: Mobile.IDevicePlatformsConstants,
private $errors: IErrors,
private $migrateController: IMigrateController,
private $opener: IOpener,
private $options: IOptions,
private $platformValidationService: IPlatformValidationService,
private $projectDataService: IProjectDataService,
) {}

public async execute(args: string[]): Promise<void> {
const projectData = this.$projectDataService.getProjectData();
const buildData = this.$buildDataService.getBuildData(
projectData.projectDir,
this.platform.toLowerCase(),
this.$options,
);
const outputPath = await this.$buildController.prepareAndBuild(buildData);
await this.$opener.open(outputPath, projectData.projectName);
}

public async canExecute(args: string[]): Promise<boolean> {
const projectData = this.$projectDataService.getProjectData();

if (
!this.$platformValidationService.isPlatformSupportedForOS(
this.platform,
projectData,
)
) {
this.$errors.fail(
`Applications for platform ${this.platform} can not be built on this OS`,
);
}

if (!this.$options.force) {
await this.$migrateController.validate({
projectDir: projectData.projectDir,
platforms: [this.platform],
});
}

return this.$platformValidationService.validateOptions(
this.$options.provision,
this.$options.teamId,
projectData,
this.platform.toLowerCase(),
);
}
}

injector.registerCommand("run|macos", RunMacOSCommand);
3 changes: 3 additions & 0 deletions lib/common/definitions/mobile.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1197,6 +1197,7 @@ declare global {
isAndroidPlatform(platform: string): boolean;
isiOSPlatform(platform: string): boolean;
isvisionOSPlatform(platform: string): boolean;
ismacOSPlatform?(platform: string): boolean;
isApplePlatform(platform: string): boolean;
normalizePlatformName(platform: string): string;
validatePlatformName(platform: string): string;
Expand Down Expand Up @@ -1241,10 +1242,12 @@ declare global {
iOS: string;
Android: string;
visionOS: string;
macOS?: string;

isiOS(value: string): boolean;
isAndroid(value: string): boolean;
isvisionOS(value: string): boolean;
ismacOS?(value: string): boolean;
}

interface IDeviceApplication {
Expand Down
5 changes: 5 additions & 0 deletions lib/common/mobile/device-platforms-constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export class DevicePlatformsConstants
public iOS = "iOS";
public Android = "Android";
public visionOS = "visionOS";
public macOS = "macOS";

public isiOS(value: string) {
return value.toLowerCase() === this.iOS.toLowerCase();
Expand All @@ -18,5 +19,9 @@ export class DevicePlatformsConstants
public isvisionOS(value: string) {
return value.toLowerCase() === this.visionOS.toLowerCase();
}

public ismacOS(value: string) {
return value.toLowerCase() === this.macOS.toLowerCase();
}
}
injector.register("devicePlatformsConstants", DevicePlatformsConstants);
17 changes: 16 additions & 1 deletion lib/common/mobile/mobile-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export class MobileHelper implements Mobile.IMobileHelper {
this.$devicePlatformsConstants.iOS,
this.$devicePlatformsConstants.Android,
this.$devicePlatformsConstants.visionOS,
this.$devicePlatformsConstants.macOS || "macOS",
];
}

Expand Down Expand Up @@ -48,8 +49,20 @@ export class MobileHelper implements Mobile.IMobileHelper {
);
}

public ismacOSPlatform(platform: string): boolean {
const macOSPlatformName = this.$devicePlatformsConstants.macOS || "macOS";
return !!(
platform &&
macOSPlatformName.toLowerCase() === platform.toLowerCase()
);
}

public isApplePlatform(platform: string): boolean {
return this.isiOSPlatform(platform) || this.isvisionOSPlatform(platform);
return (
this.isiOSPlatform(platform) ||
this.isvisionOSPlatform(platform) ||
this.ismacOSPlatform(platform)
);
}

public normalizePlatformName(platform: string): string {
Expand All @@ -59,6 +72,8 @@ export class MobileHelper implements Mobile.IMobileHelper {
return "iOS";
} else if (this.isvisionOSPlatform(platform)) {
return "visionOS";
} else if (this.ismacOSPlatform(platform)) {
return "macOS";
}

return undefined;
Expand Down
5 changes: 4 additions & 1 deletion lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const TNS_IOS_RUNTIME_NAME = "tns-ios";
export const SCOPED_ANDROID_RUNTIME_NAME = "@nativescript/android";
export const SCOPED_IOS_RUNTIME_NAME = "@nativescript/ios";
export const SCOPED_VISIONOS_RUNTIME_NAME = "@nativescript/visionos";
export const SCOPED_MACOS_RUNTIME_NAME = "@nativescript/macos";
export const PACKAGE_JSON_FILE_NAME = "package.json";
export const PACKAGE_LOCK_JSON_FILE_NAME = "package-lock.json";
export const ANDROID_DEVICE_APP_ROOT_TEMPLATE = `/data/data/%s/files`;
Expand Down Expand Up @@ -348,12 +349,14 @@ export const enum PlatformTypes {
ios = "ios",
android = "android",
visionos = "visionos",
macos = "macos",
}

export type SupportedPlatform =
| PlatformTypes.ios
| PlatformTypes.android
| PlatformTypes.visionos;
| PlatformTypes.visionos
| PlatformTypes.macos;

export const PODFILE_NAME = "Podfile";

Expand Down
51 changes: 51 additions & 0 deletions lib/controllers/prepare-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ export class PrepareController extends EventEmitter {
};
}

this.syncMacOSBundleArtifacts(projectData, platformData);

await this.writeRuntimePackageJson(projectData, platformData, prepareData);

await this.$projectChangesService.savePrepareInfo(
Expand Down Expand Up @@ -518,6 +520,55 @@ export class PrepareController extends EventEmitter {
this.$fs.writeJson(packagePath, packageData);
}

private syncMacOSBundleArtifacts(
projectData: IProjectData,
platformData: IPlatformData,
): void {
if (platformData.platformNameLowerCase !== "macos") {
return;
}
if (process.env.NS_MACOS_IOS_BUNDLE_FALLBACK !== "1") {
return;
}

const macosAppPath = path.join(
platformData.projectRoot,
projectData.projectName,
"app",
);
const hasMacBundle =
this.$fs.exists(path.join(macosAppPath, "bundle.js")) ||
this.$fs.exists(path.join(macosAppPath, "bundle.mjs"));

if (hasMacBundle) {
return;
}

const iosAppPath = path.join(
projectData.platformsDir,
"ios",
projectData.projectName,
"app",
);
if (!this.$fs.exists(iosAppPath)) {
return;
}

this.$logger.trace(
`Copying bundle artifacts from ${iosAppPath} to ${macosAppPath} for macOS prepare.`,
);

this.$fs.ensureDirectoryExists(macosAppPath);
const emittedFiles = this.$fs.enumerateFilesInDirectorySync(iosAppPath);

emittedFiles.forEach((sourcePath) => {
const relativePath = path.relative(iosAppPath, sourcePath);
const destinationPath = path.join(macosAppPath, relativePath);
this.$fs.ensureDirectoryExists(path.dirname(destinationPath));
this.$fs.copyFile(sourcePath, destinationPath);
});
}

private emitPrepareEvent(filesChangeEventData: IFilesChangeEventData) {
if (this.isInitialPrepareReady) {
this.emit(PREPARE_READY_EVENT_NAME, filesChangeEventData);
Expand Down
2 changes: 2 additions & 0 deletions lib/definitions/project.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ interface INsConfigIOS extends INsConfigPlaform {
}

interface INSConfigVisionOS extends INsConfigIOS {}
interface INSConfigMacOS extends INsConfigIOS {}

interface INsConfigAndroid extends INsConfigPlaform {
v8Flags?: string;
Expand Down Expand Up @@ -188,6 +189,7 @@ interface INsConfig {
ios?: INsConfigIOS;
android?: INsConfigAndroid;
visionos?: INSConfigVisionOS;
macos?: INSConfigMacOS;
ignoredNativeDependencies?: string[];
hooks?: INsConfigHooks[];
projectName?: string;
Expand Down
1 change: 1 addition & 0 deletions lib/key-commands/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ injector.requireCommand("open|ios", path);
injector.requireCommand("open|android", path);
injector.requireCommand("open|visionos", path);
injector.requireCommand("open|vision", path);
injector.requireCommand("open|macos", path);
Loading