Skip to content
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

Metro-Services Fixes #393

Merged
merged 4 commits into from
Jul 13, 2021
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Remove dependency on mkdirp, and use nodejs \"fs\" instead. Add a tolerance when finding a matching scale factor for android. Move \"throw\" statement into scale search routine, so that it always returns a real value (or throws). Add tests.",
"packageName": "@rnx-kit/metro-service",
"email": "afoxman@microsoft.com",
"dependentChangeType": "patch"
}
13 changes: 10 additions & 3 deletions packages/metro-service/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@
"format": "rnx-kit-scripts format",
"test": "rnx-kit-scripts test"
},
"engines": {
"node": ">= 10.12"
},
"dependencies": {
"chalk": "^4.1.0",
"mkdirp": "^0.5.3"
"chalk": "^4.1.0"
},
"peerDependencies": {
"metro": ">=0.66.1",
Expand All @@ -36,7 +38,6 @@
"@types/metro-babel-transformer": "*",
"@types/metro-config": "*",
"@types/metro-resolver": "*",
"@types/mkdirp": "^0.5.2",
"@types/node": "^14.15.0",
"metro": "^0.66.1",
"metro-config": "^0.66.1",
Expand All @@ -52,5 +53,11 @@
},
"eslintConfig": {
"extends": "@rnx-kit/eslint-config"
},
"jest": {
"roots": [
"test"
],
"testRegex": "/test/.*\\.test\\.ts$"
}
}
62 changes: 32 additions & 30 deletions packages/metro-service/src/asset/android.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,38 @@
import path from "path";
import type { PackagerAsset } from "./types";

/**
* FIXME: using number to represent discrete scale numbers is fragile in essence because of
* floating point numbers imprecision.
*/
function getAndroidAssetSuffix(scale: number): string {
switch (scale) {
case 0.75:
return "ldpi";
case 1:
return "mdpi";
case 1.5:
return "hdpi";
case 2:
return "xhdpi";
case 3:
return "xxhdpi";
case 4:
return "xxxhdpi";
default:
return "";
function isApproximatelyEqual(
f1: number,
f2: number,
tolerance: number
afoxman marked this conversation as resolved.
Show resolved Hide resolved
): boolean {
return Math.abs(f1 - f2) < tolerance;
}

export function getAndroidAssetSuffix(
asset: PackagerAsset,
scale: number
): string {
const tolerance = 0.01;
if (isApproximatelyEqual(scale, 0.75, tolerance)) {
return "ldpi";
} else if (isApproximatelyEqual(scale, 1, tolerance)) {
return "mdpi";
} else if (isApproximatelyEqual(scale, 1.5, tolerance)) {
return "hdpi";
} else if (isApproximatelyEqual(scale, 2, tolerance)) {
return "xhdpi";
} else if (isApproximatelyEqual(scale, 3, tolerance)) {
return "xxhdpi";
} else if (isApproximatelyEqual(scale, 4, tolerance)) {
return "xxxhdpi";
}

throw new Error(
`Don't know which android drawable suffix to use for asset: ${JSON.stringify(
asset
)}`
);
}

// See https://developer.android.com/guide/topics/resources/drawable-resource.html
Expand All @@ -41,16 +52,7 @@ function getAndroidResourceFolderName(
if (!drawableFileTypes.has(asset.type)) {
return "raw";
}
const suffix = getAndroidAssetSuffix(scale);
if (!suffix) {
throw new Error(
`Don't know which android drawable suffix to use for asset: ${JSON.stringify(
asset
)}`
);
}
const androidFolder = `drawable-${suffix}`;
return androidFolder;
return `drawable-${getAndroidAssetSuffix(asset, scale)}`;
}

function getBasePath(asset: PackagerAsset): string {
Expand Down
46 changes: 10 additions & 36 deletions packages/metro-service/src/asset/write.ts
Original file line number Diff line number Diff line change
@@ -1,55 +1,28 @@
import fs from "fs";
import path from "path";
import mkdirp from "mkdirp";

import type { AssetData } from "metro";

import { getAssetDestPathAndroid } from "./android";
import { getAssetDestPathIOS } from "./ios";
import { filterPlatformAssetScales } from "./filter";

function copy(
src: string,
dest: string,
callback: (error: NodeJS.ErrnoException) => void
): void {
function copy(src: string, dest: string): void {
const destDir = path.dirname(dest);
mkdirp(destDir, (err?: NodeJS.ErrnoException) => {
if (err) {
callback(err);
return;
}
fs.createReadStream(src)
.pipe(fs.createWriteStream(dest))
.on("finish", callback);
});
fs.mkdirSync(destDir, { recursive: true });
fs.copyFileSync(src, dest);
}

async function copyAll(filesToCopy: Record<string, string>): Promise<void> {
function copyAll(filesToCopy: Record<string, string>): void {
const queue = Object.keys(filesToCopy);
if (queue.length === 0) {
return Promise.resolve();
return;
}

console.info(`Copying ${queue.length} asset files`);
return new Promise((resolve, reject) => {
const copyNext = (error?: NodeJS.ErrnoException) => {
if (error) {
reject(error);
return;
}
if (queue.length === 0) {
console.info("Done copying assets");
resolve();
} else {
// queue.length === 0 is checked in previous branch, so this is string
const src = queue.shift() as string;
const dest = filesToCopy[src];
copy(src, dest, copyNext);
}
};
copyNext();
});
for (const src of queue) {
copy(src, filesToCopy[src]);
}
}

export async function saveAssets(
Expand Down Expand Up @@ -80,5 +53,6 @@ export async function saveAssets(
});
});

return copyAll(filesToCopy);
copyAll(filesToCopy);
return Promise.resolve();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`MetroService getAndroidAssetSuffix throw for invalid scale 0.70 1`] = `"Don't know which android drawable suffix to use for asset: {\\"httpServerLocation\\":\\"https://my-server.com/assets\\",\\"name\\":\\"logo\\",\\"type\\":\\"jpg\\"}"`;

exports[`MetroService getAndroidAssetSuffix throw for invalid scale 1.23 1`] = `"Don't know which android drawable suffix to use for asset: {\\"httpServerLocation\\":\\"https://my-server.com/assets\\",\\"name\\":\\"logo\\",\\"type\\":\\"jpg\\"}"`;
54 changes: 54 additions & 0 deletions packages/metro-service/test/asset/android.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import type { PackagerAsset } from "../../src/asset/types";
import { getAndroidAssetSuffix } from "../../src/asset/android";

describe("MetroService", () => {
const asset: PackagerAsset = {
httpServerLocation: "https://my-server.com/assets",
name: "logo",
type: "jpg",
};

test("getAndroidAssetSuffix returns ldpi for scale 0.75", () => {
expect(getAndroidAssetSuffix(asset, 0.75)).toEqual("ldpi");
});

test("getAndroidAssetSuffix returns mdpi for scale 1", () => {
expect(getAndroidAssetSuffix(asset, 1)).toEqual("mdpi");
});

test("getAndroidAssetSuffix returns hdpi for scale 1.5", () => {
expect(getAndroidAssetSuffix(asset, 1.5)).toEqual("hdpi");
});

test("getAndroidAssetSuffix returns xhdpi for scale 2", () => {
expect(getAndroidAssetSuffix(asset, 2)).toEqual("xhdpi");
});

test("getAndroidAssetSuffix returns xxhdpi for scale 3", () => {
expect(getAndroidAssetSuffix(asset, 3)).toEqual("xxhdpi");
});

test("getAndroidAssetSuffix returns xxxhdpi for scale 4", () => {
expect(getAndroidAssetSuffix(asset, 4)).toEqual("xxxhdpi");
});

test("getAndroidAssetSuffix returns ldpi for scale 0.741", () => {
expect(getAndroidAssetSuffix(asset, 0.741)).toEqual("ldpi");
});

test("getAndroidAssetSuffix returns ldpi for scale 0.759", () => {
expect(getAndroidAssetSuffix(asset, 0.759)).toEqual("ldpi");
});

test("getAndroidAssetSuffix throw for invalid scale 0.70", () => {
expect(() =>
getAndroidAssetSuffix(asset, 0.7)
).toThrowErrorMatchingSnapshot();
});

test("getAndroidAssetSuffix throw for invalid scale 1.23", () => {
expect(() =>
getAndroidAssetSuffix(asset, 1.23)
).toThrowErrorMatchingSnapshot();
});
});
9 changes: 1 addition & 8 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1911,13 +1911,6 @@
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.4.tgz#f0ec25dbf2f0e4b18647313ac031134ca5b24b21"
integrity sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA==

"@types/mkdirp@^0.5.2":
version "0.5.2"
resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-0.5.2.tgz#503aacfe5cc2703d5484326b1b27efa67a339c1f"
integrity sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg==
dependencies:
"@types/node" "*"

"@types/node-fetch@^2.5.0":
version "2.5.9"
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.9.tgz#c04a12115aa436f189e39579272b305e477621b4"
Expand Down Expand Up @@ -7468,7 +7461,7 @@ mkdirp@1.x, mkdirp@^1.0.3:
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==

mkdirp@^0.5.1, mkdirp@^0.5.3:
mkdirp@^0.5.1:
version "0.5.5"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
Expand Down