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
58 changes: 42 additions & 16 deletions lib/services/bundler/bundler-compiler-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,9 @@ export class BundlerCompilerService
}

// Copy Vite output files directly to platform destination
const distOutput = path.join(
projectData.projectDir,
".ns-vite-build",
);
const destDir = path.join(
platformData.appDestinationDirectoryPath,
this.$options.hostProjectModuleName,
const { distOutput, destDir } = this.getViteBuildPaths(
platformData,
projectData,
);

if (debugLog) {
Expand Down Expand Up @@ -380,7 +376,18 @@ export class BundlerCompilerService
delete this.bundlerProcesses[platformData.platformNameLowerCase];
const exitCode = typeof arg === "number" ? arg : arg && arg.code;
if (exitCode === 0) {
resolve();
try {
if (this.getBundler() === "vite") {
const { distOutput, destDir } = this.getViteBuildPaths(
platformData,
projectData,
);
this.copyViteBundleToNative(distOutput, destDir, null, true);
}
resolve();
} catch (error) {
reject(error);
}
} else {
const error: any = new Error(
`Executing ${projectData.bundler} failed with exit code ${exitCode}.`,
Expand Down Expand Up @@ -845,10 +852,24 @@ export class BundlerCompilerService
return this.$projectConfigService.getValue(`bundler`, "webpack");
}

private getViteBuildPaths(
platformData: IPlatformData,
projectData: IProjectData,
) {
return {
distOutput: path.join(projectData.projectDir, ".ns-vite-build"),
destDir: path.join(
platformData.appDestinationDirectoryPath,
this.$options.hostProjectModuleName,
),
};
}

private copyViteBundleToNative(
distOutput: string,
destDir: string,
specificFiles: string[] = null,
failOnError = false,
) {
// Clean and copy Vite output to native platform folder
if (debugLog) {
Expand Down Expand Up @@ -890,23 +911,28 @@ export class BundlerCompilerService
console.log("Full build: Copying all files.");
}

if (!this.$fs.exists(distOutput)) {
throw new Error(
`Vite output directory does not exist: ${distOutput}`,
);
}

// Clean destination directory
if (this.$fs.exists(destDir)) {
this.$fs.deleteDirectory(destDir);
}
this.$fs.createDirectory(destDir);

// Copy all files from dist to platform destination
if (this.$fs.exists(distOutput)) {
this.copyRecursiveSync(distOutput, destDir);
} else {
this.$logger.warn(
`Vite output directory does not exist: ${distOutput}`,
);
}
this.copyRecursiveSync(distOutput, destDir);
}
} catch (error) {
this.$logger.warn(`Failed to copy Vite bundle: ${error.message}`);
const copyError =
error instanceof Error ? error : new Error(String(error));
if (failOnError) {
throw copyError;
}
this.$logger.warn(`Failed to copy Vite bundle: ${copyError.message}`);
}
}

Expand Down
71 changes: 69 additions & 2 deletions test/services/bundler/bundler-compiler-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { assert } from "chai";
import { ErrorsStub } from "../../stubs";
import { IInjector } from "../../../lib/common/definitions/yok";
import { CONFIG_FILE_NAME_DISPLAY } from "../../../lib/constants";
import { EventEmitter } from "events";
import * as path from "path";

const iOSPlatformName = "ios";
const androidPlatformName = "android";
Expand All @@ -27,12 +29,14 @@ function createTestInjector(): IInjector {
testInjector.register("childProcess", {});
testInjector.register("hooksService", {});
testInjector.register("hostInfo", {});
testInjector.register("options", {});
testInjector.register("options", { hostProjectModuleName: "app" });
testInjector.register("logger", {});
testInjector.register("errors", ErrorsStub);
testInjector.register("packageInstallationManager", {});
testInjector.register("mobileHelper", {});
testInjector.register("cleanupService", {});
testInjector.register("cleanupService", {
removeKillProcess: async (): Promise<void> => undefined,
});
testInjector.register("projectConfigService", {
getValue: (key: string, defaultValue?: string) => defaultValue,
});
Expand Down Expand Up @@ -221,6 +225,69 @@ describe("BundlerCompilerService", () => {
});

describe("compileWithoutWatch", () => {
it("copies a successful Vite build to the native app", async () => {
const childProcess = Object.assign(new EventEmitter(), { pid: 1234 });
const copies: Array<{
distOutput: string;
destDir: string;
failOnError: boolean;
}> = [];
(<any>bundlerCompilerService).startBundleProcess = async () =>
childProcess;
(<any>bundlerCompilerService).copyViteBundleToNative = (
distOutput: string,
destDir: string,
_specificFiles: string[],
failOnError: boolean,
) => {
copies.push({ distOutput, destDir, failOnError });
};
(<any>testInjector.resolve("projectConfigService")).getValue = () =>
"vite";

const compilation = bundlerCompilerService.compileWithoutWatch(
<any>{
platformNameLowerCase: "android",
appDestinationDirectoryPath: "/project/platforms/android",
},
<any>{ projectDir: "/project" },
<any>{},
);
setImmediate(() => childProcess.emit("close", 0));
await compilation;

assert.deepEqual(copies, [
{
distOutput: path.join("/project", ".ns-vite-build"),
destDir: path.join("/project/platforms/android", "app"),
failOnError: true,
},
]);
});

it("fails when a successful Vite build cannot be copied", async () => {
const childProcess = Object.assign(new EventEmitter(), { pid: 1234 });
(<any>bundlerCompilerService).startBundleProcess = async () =>
childProcess;
(<any>bundlerCompilerService).copyViteBundleToNative = () => {
throw new Error("copy failed");
};
(<any>testInjector.resolve("projectConfigService")).getValue = () =>
"vite";

const compilation = bundlerCompilerService.compileWithoutWatch(
<any>{
platformNameLowerCase: "ios",
appDestinationDirectoryPath: "/project/platforms/ios",
},
<any>{ projectDir: "/project" },
<any>{},
);
setImmediate(() => childProcess.emit("close", 0));

await assert.isRejected(compilation, "copy failed");
});

it("fails when the value set for bundlerConfigPath is not existant file", async () => {
const bundlerConfigPath = "some path.js";
testInjector.resolve("fs").exists = (filePath: string) =>
Expand Down