expo-desktop 0.1.34 → 0.1.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -26,6 +26,7 @@ export const AppJson = type({
26
26
  export const PackageJson = type({
27
27
  "name?": "string",
28
28
  "scripts?": "Record<string, string>",
29
+ "expo?": "Record<string, unknown.any>",
29
30
  "dependencies?": "Record<string, string>",
30
31
  "devDependencies?": "Record<string, string>",
31
32
  "peerDependencies?": "Record<string, string>",
@@ -0,0 +1,43 @@
1
+ import { spawn } from "node:child_process";
2
+ import fs from "node:fs/promises";
3
+ import path from "node:path";
4
+ /** True when the project root has its own `.git` (from create-expo-app's init). */
5
+ export async function hasProjectGitRepositoryAsync(projectPath) {
6
+ try {
7
+ await fs.lstat(path.join(projectPath, ".git"));
8
+ return true;
9
+ }
10
+ catch (error) {
11
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
12
+ return false;
13
+ }
14
+ throw error;
15
+ }
16
+ }
17
+ /** `git diff --cached --quiet` exits 1 when there are staged changes. */
18
+ export async function hasGitStagedChangesAsync(projectPath) {
19
+ try {
20
+ await runGitAsync(projectPath, ["diff", "--cached", "--quiet"]);
21
+ return false;
22
+ }
23
+ catch {
24
+ return true;
25
+ }
26
+ }
27
+ function runGitAsync(projectPath, args) {
28
+ return new Promise((resolve, reject) => {
29
+ const cp = spawn(`git ${args.join(" ")}`, {
30
+ cwd: projectPath,
31
+ shell: true,
32
+ stdio: "ignore",
33
+ });
34
+ cp.on("error", reject);
35
+ cp.on("close", (code) => {
36
+ if (code === 0) {
37
+ resolve();
38
+ return;
39
+ }
40
+ reject(new Error(`git ${args.join(" ")} exited with code ${code ?? "null"}`));
41
+ });
42
+ });
43
+ }
@@ -11,6 +11,7 @@ import { applyConfigPlugins } from "../common/apply-config-plugins.js";
11
11
  import { makePrettySummary } from "../common/arktype.js";
12
12
  import { promisifiedSpawnTask, SPAWN_DEBUG_LOG_GLOB } from "../common/child-process.js";
13
13
  import { title } from "../common/clack.js";
14
+ import { hasGitStagedChangesAsync, hasProjectGitRepositoryAsync } from "../common/git.js";
14
15
  import { packageManagerExec } from "../common/npm.js";
15
16
  import { preserveFile } from "../common/preserve-file.js";
16
17
  import { applySelectedTemplatesAsync } from "../common/template.js";
@@ -103,6 +104,10 @@ export async function createExpoDesktopApp({ localDev, name, packageManager, tem
103
104
  await improveMetroConfig({ projectPath });
104
105
  title("Adding Expo support to the Babel config…", { spacing: 1 });
105
106
  await writeBabelConfig({ projectPath });
107
+ title("Improving App.tsx…", { spacing: 1 });
108
+ await improveAppTsx({ projectPath });
109
+ title("Committing changes…", { spacing: 1 });
110
+ await commitChanges({ projectPath });
106
111
  logProjectReady({ cdPath: name.filesafeName, packageManager });
107
112
  }
108
113
  async function getBundleEntryFileCandidates({ projectPath }) {
@@ -363,6 +368,24 @@ async function updatePackageJson({ localDev, name, projectPath, task, versions,
363
368
  packageJson.overrides["react-native"] = packageJson.dependencies["react-native"];
364
369
  }
365
370
  }
371
+ if (!packageJson.expo) {
372
+ packageJson.expo = {};
373
+ }
374
+ if (!packageJson.expo.install) {
375
+ packageJson.expo.install = {};
376
+ }
377
+ if (!packageJson.expo.install.exclude) {
378
+ packageJson.expo.install.exclude = [];
379
+ }
380
+ // Stop `expo start` erroneously warning about our overrides.
381
+ // - https://github.com/shirakaba/expo-desktop/issues/15
382
+ // - https://docs.expo.dev/versions/latest/config/package-json/#installexclude
383
+ if (!packageJson.expo.install.exclude.includes("react")) {
384
+ packageJson.expo.install.exclude.push("react");
385
+ }
386
+ if (!packageJson.expo.install.exclude.includes("react-native")) {
387
+ packageJson.expo.install.exclude.push("react-native");
388
+ }
366
389
  }
367
390
  try {
368
391
  await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2), "utf-8");
@@ -622,6 +645,93 @@ module.exports = function (api) {
622
645
  }
623
646
  console.log(`\n${green("◆")} Wrote babel.config.js.\n`);
624
647
  }
648
+ /**
649
+ * Improve the App.tsx so that it's not white-on-white on macOS in dark mode.
650
+ * Here, we simply ensure that it's black-on-white in both light and dark modes.
651
+ *
652
+ * @see https://github.com/shirakaba/expo-desktop/pull/14#issuecomment-4614018796
653
+ * @see https://github.com/expo/expo/blob/sdk-54/templates/expo-template-blank-typescript/App.tsx
654
+ */
655
+ async function improveAppTsx({ projectPath }) {
656
+ const metroConfigPath = path.resolve(projectPath, "App.tsx");
657
+ console.log(`${cyan("◆")} Overwriting App.tsx…\n`);
658
+ try {
659
+ await fs.writeFile(metroConfigPath, `
660
+ import { StatusBar } from 'expo-status-bar';
661
+ import { StyleSheet, Text, View } from 'react-native';
662
+
663
+ export default function App() {
664
+ return (
665
+ <View style={styles.container}>
666
+ <Text style={styles.text}>Open up App.tsx to start working on your app!</Text>
667
+ <StatusBar style="auto" />
668
+ </View>
669
+ );
670
+ }
671
+
672
+ const styles = StyleSheet.create({
673
+ container: {
674
+ flex: 1,
675
+ backgroundColor: '#fff',
676
+ alignItems: 'center',
677
+ justifyContent: 'center',
678
+ },
679
+ text: {
680
+ color: '#000',
681
+ },
682
+ });
683
+ `.trim() + "\n", "utf-8");
684
+ }
685
+ catch (error) {
686
+ log.error(`Error improving ${yellow("App.tsx")} file${error instanceof Error ? `: ${error.message}` : "."}`);
687
+ process.exit(1);
688
+ }
689
+ console.log(`\n${green("◆")} Overwrote App.tsx.\n`);
690
+ }
691
+ /**
692
+ * Stage and commit all changes.
693
+ *
694
+ * @see https://github.com/expo/expo/blob/main/packages/create-expo/src/utils/git.ts
695
+ */
696
+ async function commitChanges({ projectPath }) {
697
+ if (!(await hasProjectGitRepositoryAsync(projectPath))) {
698
+ console.warn(`\n${yellow("⚠")} Skipping git commit: create-expo-app did not initialize a Git repository in this project (this happens when creating inside an existing repo, e.g. in a monorepo).\n`);
699
+ return;
700
+ }
701
+ try {
702
+ await tasks([
703
+ promisifiedSpawnTask({
704
+ title: "git add",
705
+ command: "git",
706
+ args: ["add", "-A"],
707
+ options: { cwd: projectPath, stdio: "ignore" },
708
+ }),
709
+ ]);
710
+ }
711
+ catch (error) {
712
+ log.error(`Error running ${yellow("git add -A")}${error instanceof Error ? `: ${error.message}` : "."}`);
713
+ process.exit(1);
714
+ }
715
+ if (!(await hasGitStagedChangesAsync(projectPath))) {
716
+ console.log(`\n${green("◆")} Nothing to commit.\n`);
717
+ return;
718
+ }
719
+ try {
720
+ await tasks([
721
+ promisifiedSpawnTask({
722
+ title: "git commit",
723
+ command: "git",
724
+ args: ["commit", "-m", "Set up with expo-desktop"],
725
+ options: { cwd: projectPath, stdio: "ignore" },
726
+ }),
727
+ ]);
728
+ }
729
+ catch (error) {
730
+ log.error(`Error running ${yellow("git commit")}${error instanceof Error ? `: ${error.message}` : "."}`);
731
+ process.exit(1);
732
+ }
733
+ console.log(`\n${green("◆")} Committed changes.\n`);
734
+ }
625
735
  /**
626
736
  * For now, this is just a convenience script to allow me to run the config
627
737
  * plugins again after creating the app, to help with development. But it is
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-desktop",
3
- "version": "0.1.34",
3
+ "version": "0.1.35",
4
4
  "description": "Best-effort desktop support for Expo",
5
5
  "keywords": [
6
6
  "android",
@@ -37,8 +37,8 @@
37
37
  "@clack/prompts": "^1.2.0",
38
38
  "arktype": "^2.2.0",
39
39
  "citty": "^0.2.2",
40
- "expo-desktop-config-plugins": "^1.1.31",
41
- "expo-desktop-prebuild-config": "^1.0.17",
40
+ "expo-desktop-config-plugins": "^1.1.32",
41
+ "expo-desktop-prebuild-config": "^1.0.18",
42
42
  "glob": "^10.5.0",
43
43
  "kleur": "^4.1.5",
44
44
  "mustache": "^4.2.0",