expo-desktop 1.0.0-beta.0 → 1.0.0-beta.2
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.
|
@@ -27,6 +27,7 @@ const require = createRequire(import.meta.url);
|
|
|
27
27
|
const JsonFile = require("@expo/json-file").default;
|
|
28
28
|
const debug = Debug("expo-desktop:create-app:template");
|
|
29
29
|
const isMacOS = process.platform === "darwin";
|
|
30
|
+
const isWindows = process.platform === "win32";
|
|
30
31
|
// keep this list in sync with the validation helper in WWW: src/utils/experienceParser.ts
|
|
31
32
|
const FORBIDDEN_NAMES = [
|
|
32
33
|
"react-native",
|
|
@@ -435,7 +436,6 @@ export async function sanitizeTemplateAsync({ displayName: displayNameArg, rdns:
|
|
|
435
436
|
android: {
|
|
436
437
|
package: androidPackage,
|
|
437
438
|
},
|
|
438
|
-
// @ts-expect-error macos and windows missing from types
|
|
439
439
|
windows: {
|
|
440
440
|
displayName,
|
|
441
441
|
namespace: windowsNamespace,
|
|
@@ -448,6 +448,10 @@ export async function sanitizeTemplateAsync({ displayName: displayNameArg, rdns:
|
|
|
448
448
|
CFBundleName: displayName,
|
|
449
449
|
},
|
|
450
450
|
},
|
|
451
|
+
experiments: {
|
|
452
|
+
// @ts-expect-error Earlier Expo SDKs don't provide typings for this.
|
|
453
|
+
outOfTreePlatforms: true,
|
|
454
|
+
},
|
|
451
455
|
};
|
|
452
456
|
const appFile = new JsonFile(path.join(projectRoot, "app.json"), { default: {} });
|
|
453
457
|
const appContent = (await appFile.readAsync());
|
|
@@ -613,13 +617,13 @@ export function logProjectReady({ cdPath, packageManager, }) {
|
|
|
613
617
|
console.log();
|
|
614
618
|
}
|
|
615
619
|
console.log(`- ${chalk.bold(formatRunCommand(packageManager, "android"))}`);
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
" # you need to use macOS to build the iOS or macOS projects - use the Expo app if you need to do Apple development without a Mac";
|
|
620
|
-
}
|
|
620
|
+
const macOSComment = isMacOS
|
|
621
|
+
? ""
|
|
622
|
+
: " # you need to use macOS to build the iOS or macOS projects - use the Expo app if you need to do Apple development without a Mac";
|
|
621
623
|
console.log(`- ${chalk.bold(formatRunCommand(packageManager, "ios"))}${macOSComment}`);
|
|
622
624
|
console.log(`- ${chalk.bold(formatRunCommand(packageManager, "macos"))}${macOSComment}`);
|
|
625
|
+
const windowsComment = isWindows ? "" : " # you need to use Windows to build the Windows project";
|
|
626
|
+
console.log(`- ${chalk.bold(formatRunCommand(packageManager, "windows"))}${windowsComment}`);
|
|
623
627
|
console.log(`- ${chalk.bold(formatRunCommand(packageManager, "web"))}`);
|
|
624
628
|
}
|
|
625
629
|
export async function installPodsAsync(projectRoot, platform) {
|
|
@@ -132,6 +132,16 @@ export function updatePkgScripts({ pkg }) {
|
|
|
132
132
|
pkg.scripts.ios = "expo run:ios";
|
|
133
133
|
hasChanged = true;
|
|
134
134
|
}
|
|
135
|
+
if (pkg.scripts.macos ===
|
|
136
|
+
"node -e \"console.log('Please run \\`npx expo-desktop prebuild\\` to set up the React Native macOS project.'); process.exit(1);\"") {
|
|
137
|
+
pkg.scripts.macos = "rnc-cli run-macos";
|
|
138
|
+
hasChanged = true;
|
|
139
|
+
}
|
|
140
|
+
if (pkg.scripts.windows ===
|
|
141
|
+
"node -e \"console.log('Please run \\`npx expo-desktop prebuild\\` to set up the React Native Windows project.'); process.exit(1);\"") {
|
|
142
|
+
pkg.scripts.windows = "rnc-cli run-windows";
|
|
143
|
+
hasChanged = true;
|
|
144
|
+
}
|
|
135
145
|
return hasChanged;
|
|
136
146
|
}
|
|
137
147
|
function normalizeDependencyMap(deps) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-desktop",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.2",
|
|
4
4
|
"description": "Best-effort desktop support for Expo",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"android",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"citty": "^0.2.2",
|
|
46
46
|
"debug": "^4.4.3",
|
|
47
47
|
"expo-desktop-config-plugins": "^1.2.0-beta.0",
|
|
48
|
-
"expo-desktop-prebuild-config": "^1.1.0-beta.
|
|
48
|
+
"expo-desktop-prebuild-config": "^1.1.0-beta.1",
|
|
49
49
|
"getenv": "^2.0.0",
|
|
50
50
|
"glob": "^10.5.0",
|
|
51
51
|
"kleur": "^4.1.5",
|
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
import { tasks } from "@clack/prompts";
|
|
2
|
-
import { getPackageJson } from "@expo/config";
|
|
3
|
-
import crypto from "crypto";
|
|
4
|
-
import fs from "fs";
|
|
5
|
-
import path from "path";
|
|
6
|
-
/** Modifies the `package.json` with `modifyPackageJson` and format/displays the results. */
|
|
7
|
-
export async function updatePackageJSONAsync(projectRoot, { templateDirectory, templatePkg = getPackageJson(templateDirectory), pkg, skipDependencyUpdate, }) {
|
|
8
|
-
let hasChanges;
|
|
9
|
-
let results;
|
|
10
|
-
await tasks([
|
|
11
|
-
{
|
|
12
|
-
title: "Updating package.json",
|
|
13
|
-
task: async (_message) => {
|
|
14
|
-
results = modifyPackageJson(projectRoot, {
|
|
15
|
-
templatePkg,
|
|
16
|
-
pkg,
|
|
17
|
-
skipDependencyUpdate,
|
|
18
|
-
});
|
|
19
|
-
hasChanges = !!results.changedDependencies.length || results.scriptsChanged;
|
|
20
|
-
// NOTE: This is effectively bundler caching and subject to breakage if the inputs don't match the mutations.
|
|
21
|
-
if (hasChanges) {
|
|
22
|
-
await fs.promises.writeFile(path.resolve(projectRoot, "package.json"),
|
|
23
|
-
// Add new line to match the format of running yarn.
|
|
24
|
-
// This prevents the `package.json` from changing when running `prebuild --no-install` multiple times.
|
|
25
|
-
JSON.stringify(pkg, null, 2) + "\n");
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
]);
|
|
30
|
-
return results;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Make required modifications to the `package.json` file as a JSON object.
|
|
34
|
-
*
|
|
35
|
-
* 1. Update `package.json` `scripts`.
|
|
36
|
-
* 2. Update `package.json` `dependencies` (not `devDependencies`).
|
|
37
|
-
* 3. Update `package.json` `main`.
|
|
38
|
-
*
|
|
39
|
-
* @param projectRoot The root directory of the project.
|
|
40
|
-
* @param templatePkg Template project package.json as JSON.
|
|
41
|
-
* @param pkg Current package.json as JSON.
|
|
42
|
-
* @param skipDependencyUpdate Array of dependencies to skip updating.
|
|
43
|
-
* @returns
|
|
44
|
-
*/
|
|
45
|
-
function modifyPackageJson(projectRoot, { templatePkg, pkg, skipDependencyUpdate, }) {
|
|
46
|
-
const scriptsChanged = updatePkgScripts({ pkg });
|
|
47
|
-
// TODO: Move to `npx expo-doctor`
|
|
48
|
-
return {
|
|
49
|
-
scriptsChanged,
|
|
50
|
-
...updatePkgDependencies(projectRoot, {
|
|
51
|
-
pkg,
|
|
52
|
-
templatePkg,
|
|
53
|
-
skipDependencyUpdate,
|
|
54
|
-
}),
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Update `package.json` dependencies by combining the `dependencies` in the
|
|
59
|
-
* project we are creating with the dependencies in the template project.
|
|
60
|
-
*
|
|
61
|
-
* > Exposed for testing.
|
|
62
|
-
*/
|
|
63
|
-
export function updatePkgDependencies(projectRoot, { pkg, templatePkg, skipDependencyUpdate = [], }) {
|
|
64
|
-
const { dependencies } = templatePkg;
|
|
65
|
-
// The default values come from the bare-minimum template's package.json.
|
|
66
|
-
// Users can change this by using different templates with the `--template` flag.
|
|
67
|
-
// The main reason for allowing the changing of dependencies would be to include
|
|
68
|
-
// dependencies that are required for the native project to build. For example,
|
|
69
|
-
// it does not need to include dependencies that are used in the JS-code only.
|
|
70
|
-
const defaultDependencies = createDependenciesMap(dependencies);
|
|
71
|
-
// NOTE: This is a hack to ensure this doesn't trigger an extraneous change in the `package.json`
|
|
72
|
-
// it isn't required for anything in the `ios` and `android` folders.
|
|
73
|
-
delete defaultDependencies["expo-status-bar"];
|
|
74
|
-
// NOTE: Expo splash screen is installed by default in the template but the config plugin also lives in prebuild-config
|
|
75
|
-
// so we can delete it to prevent an extraneous change in the `package.json`.
|
|
76
|
-
delete defaultDependencies["expo-splash-screen"];
|
|
77
|
-
const combinedDependencies = createDependenciesMap({
|
|
78
|
-
...defaultDependencies,
|
|
79
|
-
...pkg.dependencies,
|
|
80
|
-
});
|
|
81
|
-
// Only change the dependencies if the normalized hash changes, this helps to
|
|
82
|
-
// reduce meaningless changes.
|
|
83
|
-
const hasNewDependencies = hashForDependencyMap(pkg.dependencies) !== hashForDependencyMap(combinedDependencies);
|
|
84
|
-
// Save the dependencies
|
|
85
|
-
let changedDependencies = [];
|
|
86
|
-
if (hasNewDependencies) {
|
|
87
|
-
changedDependencies = diffKeys(combinedDependencies, pkg.dependencies ?? {}).sort();
|
|
88
|
-
// Use Object.assign to preserve the original order of dependencies, this
|
|
89
|
-
// makes it easier to see what changed in the git diff.
|
|
90
|
-
pkg.dependencies = Object.assign(pkg.dependencies ?? {}, combinedDependencies);
|
|
91
|
-
}
|
|
92
|
-
return {
|
|
93
|
-
changedDependencies,
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
function diffKeys(a, b) {
|
|
97
|
-
return Object.keys(a).filter((key) => a[key] !== b[key]);
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Create an object of type DependenciesMap a dependencies object or throw if not valid.
|
|
101
|
-
*
|
|
102
|
-
* @param dependencies - ideally an object of type {[key]: string} - if not then this will error.
|
|
103
|
-
*/
|
|
104
|
-
export function createDependenciesMap(dependencies) {
|
|
105
|
-
if (typeof dependencies !== "object") {
|
|
106
|
-
throw new Error(`Dependency map is invalid, expected object but got ${typeof dependencies}`);
|
|
107
|
-
}
|
|
108
|
-
else if (!dependencies) {
|
|
109
|
-
return {};
|
|
110
|
-
}
|
|
111
|
-
const outputMap = {};
|
|
112
|
-
for (const key of Object.keys(dependencies)) {
|
|
113
|
-
const value = dependencies[key];
|
|
114
|
-
if (typeof value === "string") {
|
|
115
|
-
outputMap[key] = value;
|
|
116
|
-
}
|
|
117
|
-
else {
|
|
118
|
-
throw new Error(`Dependency for key \`${key}\` should be a \`string\`, instead got: \`{ ${key}: ${JSON.stringify(value)} }\``);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
return outputMap;
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Updates the package.json scripts for prebuild if the scripts match
|
|
125
|
-
* the default values used in project templates.
|
|
126
|
-
*/
|
|
127
|
-
export function updatePkgScripts({ pkg }) {
|
|
128
|
-
let hasChanged = false;
|
|
129
|
-
if (!pkg.scripts) {
|
|
130
|
-
pkg.scripts = {};
|
|
131
|
-
}
|
|
132
|
-
if (pkg.scripts.android === "expo start --android" ||
|
|
133
|
-
pkg.scripts.android === "react-native run-android") {
|
|
134
|
-
pkg.scripts.android = "expo run:android";
|
|
135
|
-
hasChanged = true;
|
|
136
|
-
}
|
|
137
|
-
if (pkg.scripts.ios === "expo start --ios" || pkg.scripts.ios === "react-native run-ios") {
|
|
138
|
-
pkg.scripts.ios = "expo run:ios";
|
|
139
|
-
hasChanged = true;
|
|
140
|
-
}
|
|
141
|
-
if (pkg.scripts.macos ===
|
|
142
|
-
"node -e \"console.log('Please run \\`npx expo-desktop prebuild\\` to set up the React Native macOS project.'); process.exit(1);\"") {
|
|
143
|
-
pkg.scripts.macos = "rnc-cli run-macos";
|
|
144
|
-
hasChanged = true;
|
|
145
|
-
}
|
|
146
|
-
if (pkg.scripts.windows ===
|
|
147
|
-
"node -e \"console.log('Please run \\`npx expo-desktop prebuild\\` to set up the React Native Windows project.'); process.exit(1);\"") {
|
|
148
|
-
pkg.scripts.windows = "rnc-cli run-windows";
|
|
149
|
-
hasChanged = true;
|
|
150
|
-
}
|
|
151
|
-
return hasChanged;
|
|
152
|
-
}
|
|
153
|
-
function normalizeDependencyMap(deps) {
|
|
154
|
-
return Object.keys(deps)
|
|
155
|
-
.map((dependency) => `${dependency}@${deps[dependency]}`)
|
|
156
|
-
.sort();
|
|
157
|
-
}
|
|
158
|
-
export function hashForDependencyMap(deps = {}) {
|
|
159
|
-
const depsList = normalizeDependencyMap(deps);
|
|
160
|
-
const depsString = depsList.join("\n");
|
|
161
|
-
return createFileHash(depsString);
|
|
162
|
-
}
|
|
163
|
-
export function createFileHash(contents) {
|
|
164
|
-
// this doesn't need to be secure, the shorter the better.
|
|
165
|
-
return crypto.createHash("sha1").update(contents).digest("hex");
|
|
166
|
-
}
|