vxrn 2.15.0 → 2.15.1
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.
- package/dist/exports/prebuild.mjs +37 -0
- package/dist/exports/prebuild.mjs.map +1 -1
- package/dist/exports/prebuild.native.js +55 -0
- package/dist/exports/prebuild.native.js.map +1 -1
- package/dist/exports/prebuildWithoutExpo.mjs +197 -12
- package/dist/exports/prebuildWithoutExpo.mjs.map +1 -1
- package/dist/exports/prebuildWithoutExpo.native.js +197 -10
- package/dist/exports/prebuildWithoutExpo.native.js.map +1 -1
- package/package.json +13 -13
- package/src/exports/prebuild.ts +30 -0
- package/src/exports/prebuildWithoutExpo.test.ts +74 -2
- package/src/exports/prebuildWithoutExpo.ts +204 -12
- package/types/exports/prebuild.d.ts.map +1 -1
- package/types/exports/prebuildWithoutExpo.d.ts.map +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { detectPackageManager } from "@vxrn/utils";
|
|
2
|
+
import { existsSync, lstatSync, readFileSync, readdirSync, renameSync, rmSync } from "node:fs";
|
|
2
3
|
import { readFile, writeFile } from "node:fs/promises";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
import { fillOptions } from "../config/getOptionsFilled.mjs";
|
|
@@ -29,6 +30,14 @@ const prebuild = async ({ root, platform, "no-install": noInstall = false, app,
|
|
|
29
30
|
} catch (error) {
|
|
30
31
|
throw new Error("package.json checks are failing:\n" + error);
|
|
31
32
|
}
|
|
33
|
+
const ios = path.join(root, "ios");
|
|
34
|
+
const previousIos = `${ios}.previous`;
|
|
35
|
+
rmSync(previousIos, {
|
|
36
|
+
recursive: true,
|
|
37
|
+
force: true
|
|
38
|
+
});
|
|
39
|
+
const reusesIos = (platform == "ios" || !platform) && existsSync(ios);
|
|
40
|
+
if (reusesIos) renameSync(ios, previousIos);
|
|
32
41
|
if (platform == "ios" || !platform) {
|
|
33
42
|
await generateForPlatform(root, "ios", app);
|
|
34
43
|
}
|
|
@@ -36,6 +45,7 @@ const prebuild = async ({ root, platform, "no-install": noInstall = false, app,
|
|
|
36
45
|
await generateForPlatform(root, "android", app);
|
|
37
46
|
}
|
|
38
47
|
await beforeInstall?.();
|
|
48
|
+
if (reusesIos) reuseUnchangedIosProject(previousIos, ios);
|
|
39
49
|
const inventory = await getNativeDependencyInventory(root);
|
|
40
50
|
console.info(`[vxrn] native dependencies discovered through community autolinking: ${inventory.map((entry) => entry.name).join(", ") || "(none)"}`);
|
|
41
51
|
if (platform == "android" || !platform) {
|
|
@@ -78,6 +88,33 @@ Android:
|
|
|
78
88
|
`);
|
|
79
89
|
}
|
|
80
90
|
};
|
|
91
|
+
function reuseUnchangedIosProject(previous, next) {
|
|
92
|
+
for (const entry of readdirSync(next, {
|
|
93
|
+
recursive: true,
|
|
94
|
+
withFileTypes: true
|
|
95
|
+
})) {
|
|
96
|
+
if (!entry.isFile()) continue;
|
|
97
|
+
const file = path.join(entry.parentPath, entry.name);
|
|
98
|
+
const old = path.join(previous, path.relative(next, file));
|
|
99
|
+
if (!existsSync(old) || !lstatSync(old).isFile()) continue;
|
|
100
|
+
if (lstatSync(old).size !== lstatSync(file).size) continue;
|
|
101
|
+
if (!readFileSync(old).equals(readFileSync(file))) continue;
|
|
102
|
+
renameSync(old, file);
|
|
103
|
+
}
|
|
104
|
+
for (const name of [
|
|
105
|
+
"Pods",
|
|
106
|
+
"Podfile.lock",
|
|
107
|
+
"build"
|
|
108
|
+
]) {
|
|
109
|
+
const from = path.join(previous, name);
|
|
110
|
+
const to = path.join(next, name);
|
|
111
|
+
if (existsSync(from) && !existsSync(to)) renameSync(from, to);
|
|
112
|
+
}
|
|
113
|
+
rmSync(previous, {
|
|
114
|
+
recursive: true,
|
|
115
|
+
force: true
|
|
116
|
+
});
|
|
117
|
+
}
|
|
81
118
|
async function replaceInUTF8File(filePath, findThis, replaceWith) {
|
|
82
119
|
const fileContent = await readFile(filePath, "utf8");
|
|
83
120
|
const replacedFileContent = fileContent.replace(findThis, replaceWith);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prebuild.js","names":[],"sources":["exports/prebuild.js"],"sourcesContent":["import { detectPackageManager } from \"@vxrn/utils\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { fillOptions } from \"../config/getOptionsFilled\";\nimport { applyBuiltInPatches } from \"../utils/patches\";\nimport {\n applyAndroidDependencyPatches,\n generateForPlatform,\n getNativeDependencyInventory,\n installNativeDependencies,\n validatePrebuildApp\n} from \"./prebuildWithoutExpo\";\nconst prebuild = async ({\n root,\n platform,\n \"no-install\": noInstall = false,\n app,\n beforeInstall\n}) => {\n validatePrebuildApp(app, platform);\n const options = await fillOptions({ root });\n await applyBuiltInPatches(options);\n try {\n const packageJsonPath = path.join(root, \"package.json\");\n const packageJsonContents = await readFile(packageJsonPath, \"utf8\");\n const { devDependencies } = JSON.parse(packageJsonContents);\n if (!devDependencies?.[\"@react-native-community/template\"]) {\n const installCommand = await (async () => {\n const found = await detectPackageManager();\n switch (true) {\n case found.bun:\n return `bun add -D @react-native-community/template`;\n case found.pnpm:\n return `pnpm install -D @react-native-community/template`;\n case found.yarn:\n return `yarn add -D @react-native-community/template`;\n default:\n return `npm install -D @react-native-community/template`;\n }\n })();\n throw new Error(\n `\"@react-native-community/template\" is not found in package.json, please install \"@react-native-community/template\" as dev dependency:\n\\`${installCommand}\\``\n );\n }\n } catch (error) {\n throw new Error(\"package.json checks are failing:\\n\" + error);\n }\n if (platform == \"ios\" || !platform) {\n await generateForPlatform(root, \"ios\", app);\n }\n if (platform == \"android\" || !platform) {\n await generateForPlatform(root, \"android\", app);\n }\n await beforeInstall?.();\n const inventory = await getNativeDependencyInventory(root);\n console.info(\n `[vxrn] native dependencies discovered through community autolinking: ${inventory.map((entry) => entry.name).join(\", \") || \"(none)\"}`\n );\n if (platform == \"android\" || !platform) {\n applyAndroidDependencyPatches({ root, app, inventory });\n }\n if (!noInstall) {\n installNativeDependencies({ root, platform });\n } else if (!platform || platform === \"ios\") {\n console.info(`Run cd ios && pod install`);\n console.info(\n \"Then run `open *.xcworkspace` in your terminal to open the prebuilt iOS project, then you can either run it via Xcode or archive it for distribution.\"\n );\n }\n if (!platform || platform === \"ios\") {\n console.info(\n `\niOS:\n\n Run \\`open ios/*.xcworkspace\\` in your terminal to open the prebuilt iOS project.\n Then you can either run it via Xcode or archive it for distribution.\n\n See https://onestack.dev/docs/guides-ios-native for more information.\n\n---\n`\n );\n }\n if (!platform || platform === \"android\") {\n console.info(\n `\nAndroid:\n\n \\`cd android\\` and run \\`./gradlew generateCodegenArtifactsFromSchema\\`, then \\`./gradlew assembleRelease\\` or \\`./gradlew assembleDebug\\` to build the Android project.\n\n Afterwards, you can find the built APK at \\`android/app/build/outputs/apk/release/app-release.apk\\` or\n \\`android/app/build/outputs/apk/debug/app-debug.apk\\`.\n\n`\n );\n }\n};\nasync function replaceInUTF8File(filePath, findThis, replaceWith) {\n const fileContent = await readFile(filePath, \"utf8\");\n const replacedFileContent = fileContent.replace(findThis, replaceWith);\n if (replacedFileContent !== fileContent) {\n await writeFile(filePath, replacedFileContent, \"utf8\");\n }\n}\nexport {\n prebuild,\n replaceInUTF8File\n};\n//# sourceMappingURL=prebuild.js.map\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"prebuild.js","names":[],"sources":["exports/prebuild.js"],"sourcesContent":["import { detectPackageManager } from \"@vxrn/utils\";\nimport { existsSync, lstatSync, readdirSync, readFileSync, renameSync, rmSync } from \"node:fs\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { fillOptions } from \"../config/getOptionsFilled\";\nimport { applyBuiltInPatches } from \"../utils/patches\";\nimport {\n applyAndroidDependencyPatches,\n generateForPlatform,\n getNativeDependencyInventory,\n installNativeDependencies,\n validatePrebuildApp\n} from \"./prebuildWithoutExpo\";\nconst prebuild = async ({\n root,\n platform,\n \"no-install\": noInstall = false,\n app,\n beforeInstall\n}) => {\n validatePrebuildApp(app, platform);\n const options = await fillOptions({ root });\n await applyBuiltInPatches(options);\n try {\n const packageJsonPath = path.join(root, \"package.json\");\n const packageJsonContents = await readFile(packageJsonPath, \"utf8\");\n const { devDependencies } = JSON.parse(packageJsonContents);\n if (!devDependencies?.[\"@react-native-community/template\"]) {\n const installCommand = await (async () => {\n const found = await detectPackageManager();\n switch (true) {\n case found.bun:\n return `bun add -D @react-native-community/template`;\n case found.pnpm:\n return `pnpm install -D @react-native-community/template`;\n case found.yarn:\n return `yarn add -D @react-native-community/template`;\n default:\n return `npm install -D @react-native-community/template`;\n }\n })();\n throw new Error(\n `\"@react-native-community/template\" is not found in package.json, please install \"@react-native-community/template\" as dev dependency:\n\\`${installCommand}\\``\n );\n }\n } catch (error) {\n throw new Error(\"package.json checks are failing:\\n\" + error);\n }\n const ios = path.join(root, \"ios\");\n const previousIos = `${ios}.previous`;\n rmSync(previousIos, { recursive: true, force: true });\n const reusesIos = (platform == \"ios\" || !platform) && existsSync(ios);\n if (reusesIos) renameSync(ios, previousIos);\n if (platform == \"ios\" || !platform) {\n await generateForPlatform(root, \"ios\", app);\n }\n if (platform == \"android\" || !platform) {\n await generateForPlatform(root, \"android\", app);\n }\n await beforeInstall?.();\n if (reusesIos) reuseUnchangedIosProject(previousIos, ios);\n const inventory = await getNativeDependencyInventory(root);\n console.info(\n `[vxrn] native dependencies discovered through community autolinking: ${inventory.map((entry) => entry.name).join(\", \") || \"(none)\"}`\n );\n if (platform == \"android\" || !platform) {\n applyAndroidDependencyPatches({ root, app, inventory });\n }\n if (!noInstall) {\n installNativeDependencies({ root, platform });\n } else if (!platform || platform === \"ios\") {\n console.info(`Run cd ios && pod install`);\n console.info(\n \"Then run `open *.xcworkspace` in your terminal to open the prebuilt iOS project, then you can either run it via Xcode or archive it for distribution.\"\n );\n }\n if (!platform || platform === \"ios\") {\n console.info(\n `\niOS:\n\n Run \\`open ios/*.xcworkspace\\` in your terminal to open the prebuilt iOS project.\n Then you can either run it via Xcode or archive it for distribution.\n\n See https://onestack.dev/docs/guides-ios-native for more information.\n\n---\n`\n );\n }\n if (!platform || platform === \"android\") {\n console.info(\n `\nAndroid:\n\n \\`cd android\\` and run \\`./gradlew generateCodegenArtifactsFromSchema\\`, then \\`./gradlew assembleRelease\\` or \\`./gradlew assembleDebug\\` to build the Android project.\n\n Afterwards, you can find the built APK at \\`android/app/build/outputs/apk/release/app-release.apk\\` or\n \\`android/app/build/outputs/apk/debug/app-debug.apk\\`.\n\n`\n );\n }\n};\nfunction reuseUnchangedIosProject(previous, next) {\n for (const entry of readdirSync(next, { recursive: true, withFileTypes: true })) {\n if (!entry.isFile()) continue;\n const file = path.join(entry.parentPath, entry.name);\n const old = path.join(previous, path.relative(next, file));\n if (!existsSync(old) || !lstatSync(old).isFile()) continue;\n if (lstatSync(old).size !== lstatSync(file).size) continue;\n if (!readFileSync(old).equals(readFileSync(file))) continue;\n renameSync(old, file);\n }\n for (const name of [\"Pods\", \"Podfile.lock\", \"build\"]) {\n const from = path.join(previous, name);\n const to = path.join(next, name);\n if (existsSync(from) && !existsSync(to)) renameSync(from, to);\n }\n rmSync(previous, { recursive: true, force: true });\n}\nasync function replaceInUTF8File(filePath, findThis, replaceWith) {\n const fileContent = await readFile(filePath, \"utf8\");\n const replacedFileContent = fileContent.replace(findThis, replaceWith);\n if (replacedFileContent !== fileContent) {\n await writeFile(filePath, replacedFileContent, \"utf8\");\n }\n}\nexport {\n prebuild,\n replaceInUTF8File\n};\n//# sourceMappingURL=prebuild.js.map\n"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { detectPackageManager } from "@vxrn/utils";
|
|
2
|
+
import { existsSync, lstatSync, readFileSync, readdirSync, renameSync, rmSync } from "fs";
|
|
2
3
|
import { readFile, writeFile } from "fs/promises";
|
|
3
4
|
import path from "path";
|
|
4
5
|
import { fillOptions } from "../config/getOptionsFilled.native.js";
|
|
@@ -30,6 +31,14 @@ var prebuild = async function prebuild2(param) {
|
|
|
30
31
|
} catch (error) {
|
|
31
32
|
throw new Error("package.json checks are failing:\n" + error);
|
|
32
33
|
}
|
|
34
|
+
var ios = path.join(root, "ios");
|
|
35
|
+
var previousIos = `${ios}.previous`;
|
|
36
|
+
rmSync(previousIos, {
|
|
37
|
+
recursive: true,
|
|
38
|
+
force: true
|
|
39
|
+
});
|
|
40
|
+
var reusesIos = (platform == "ios" || !platform) && existsSync(ios);
|
|
41
|
+
if (reusesIos) renameSync(ios, previousIos);
|
|
33
42
|
if (platform == "ios" || !platform) {
|
|
34
43
|
await generateForPlatform(root, "ios", app);
|
|
35
44
|
}
|
|
@@ -37,6 +46,7 @@ var prebuild = async function prebuild2(param) {
|
|
|
37
46
|
await generateForPlatform(root, "android", app);
|
|
38
47
|
}
|
|
39
48
|
await (beforeInstall === null || beforeInstall === void 0 ? void 0 : beforeInstall());
|
|
49
|
+
if (reusesIos) reuseUnchangedIosProject(previousIos, ios);
|
|
40
50
|
var inventory = await getNativeDependencyInventory(root);
|
|
41
51
|
console.info(`[vxrn] native dependencies discovered through community autolinking: ${inventory.map(function(entry) {
|
|
42
52
|
return entry.name;
|
|
@@ -81,6 +91,51 @@ Android:
|
|
|
81
91
|
`);
|
|
82
92
|
}
|
|
83
93
|
};
|
|
94
|
+
function reuseUnchangedIosProject(previous, next) {
|
|
95
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
|
|
96
|
+
try {
|
|
97
|
+
for (var _iterator = readdirSync(next, {
|
|
98
|
+
recursive: true,
|
|
99
|
+
withFileTypes: true
|
|
100
|
+
})[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
|
101
|
+
var entry = _step.value;
|
|
102
|
+
if (!entry.isFile()) continue;
|
|
103
|
+
var file = path.join(entry.parentPath, entry.name);
|
|
104
|
+
var old = path.join(previous, path.relative(next, file));
|
|
105
|
+
if (!existsSync(old) || !lstatSync(old).isFile()) continue;
|
|
106
|
+
if (lstatSync(old).size !== lstatSync(file).size) continue;
|
|
107
|
+
if (!readFileSync(old).equals(readFileSync(file))) continue;
|
|
108
|
+
renameSync(old, file);
|
|
109
|
+
}
|
|
110
|
+
} catch (err) {
|
|
111
|
+
_didIteratorError = true;
|
|
112
|
+
_iteratorError = err;
|
|
113
|
+
} finally {
|
|
114
|
+
try {
|
|
115
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
116
|
+
_iterator.return();
|
|
117
|
+
}
|
|
118
|
+
} finally {
|
|
119
|
+
if (_didIteratorError) {
|
|
120
|
+
throw _iteratorError;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
for (var _i = 0, _iter = [
|
|
125
|
+
"Pods",
|
|
126
|
+
"Podfile.lock",
|
|
127
|
+
"build"
|
|
128
|
+
]; _i < _iter.length; _i++) {
|
|
129
|
+
var name = _iter[_i];
|
|
130
|
+
var from = path.join(previous, name);
|
|
131
|
+
var to = path.join(next, name);
|
|
132
|
+
if (existsSync(from) && !existsSync(to)) renameSync(from, to);
|
|
133
|
+
}
|
|
134
|
+
rmSync(previous, {
|
|
135
|
+
recursive: true,
|
|
136
|
+
force: true
|
|
137
|
+
});
|
|
138
|
+
}
|
|
84
139
|
async function replaceInUTF8File(filePath, findThis, replaceWith) {
|
|
85
140
|
var fileContent = await readFile(filePath, "utf8");
|
|
86
141
|
var replacedFileContent = fileContent.replace(findThis, replaceWith);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prebuild.native.js","names":[],"sources":["exports/prebuild.native.js"],"sourcesContent":["import { detectPackageManager } from \"@vxrn/utils\";\nimport { readFile, writeFile } from \"fs/promises\";\nimport path from \"path\";\nimport { fillOptions } from \"../config/getOptionsFilled\";\nimport { applyBuiltInPatches } from \"../utils/patches\";\nimport { applyAndroidDependencyPatches, generateForPlatform, getNativeDependencyInventory, installNativeDependencies, validatePrebuildApp } from \"./prebuildWithoutExpo\";\nvar prebuild = async function prebuild2(param) {\n var { root, platform, \"no-install\": noInstall = false, app, beforeInstall } = param;\n validatePrebuildApp(app, platform);\n var options = await fillOptions({\n root\n });\n await applyBuiltInPatches(options);\n try {\n var packageJsonPath = path.join(root, \"package.json\");\n var packageJsonContents = await readFile(packageJsonPath, \"utf8\");\n var { devDependencies } = JSON.parse(packageJsonContents);\n if (!(devDependencies === null || devDependencies === void 0 ? void 0 : devDependencies[\"@react-native-community/template\"])) {\n var installCommand = await (async function() {\n var found = await detectPackageManager();\n switch (true) {\n case found.bun:\n return `bun add -D @react-native-community/template`;\n case found.pnpm:\n return `pnpm install -D @react-native-community/template`;\n case found.yarn:\n return `yarn add -D @react-native-community/template`;\n default:\n return `npm install -D @react-native-community/template`;\n }\n })();\n throw new Error(`\"@react-native-community/template\" is not found in package.json, please install \"@react-native-community/template\" as dev dependency:\n\\`${installCommand}\\``);\n }\n } catch (error) {\n throw new Error(\"package.json checks are failing:\\n\" + error);\n }\n if (platform == \"ios\" || !platform) {\n await generateForPlatform(root, \"ios\", app);\n }\n if (platform == \"android\" || !platform) {\n await generateForPlatform(root, \"android\", app);\n }\n await (beforeInstall === null || beforeInstall === void 0 ? void 0 : beforeInstall());\n var inventory = await getNativeDependencyInventory(root);\n console.info(`[vxrn] native dependencies discovered through community autolinking: ${inventory.map(function(entry) {\n return entry.name;\n }).join(\", \") || \"(none)\"}`);\n if (platform == \"android\" || !platform) {\n applyAndroidDependencyPatches({\n root,\n app,\n inventory\n });\n }\n if (!noInstall) {\n installNativeDependencies({\n root,\n platform\n });\n } else if (!platform || platform === \"ios\") {\n console.info(`Run cd ios && pod install`);\n console.info(\"Then run `open *.xcworkspace` in your terminal to open the prebuilt iOS project, then you can either run it via Xcode or archive it for distribution.\");\n }\n if (!platform || platform === \"ios\") {\n console.info(`\niOS:\n\n Run \\`open ios/*.xcworkspace\\` in your terminal to open the prebuilt iOS project.\n Then you can either run it via Xcode or archive it for distribution.\n\n See https://onestack.dev/docs/guides-ios-native for more information.\n\n---\n`);\n }\n if (!platform || platform === \"android\") {\n console.info(`\nAndroid:\n\n \\`cd android\\` and run \\`./gradlew generateCodegenArtifactsFromSchema\\`, then \\`./gradlew assembleRelease\\` or \\`./gradlew assembleDebug\\` to build the Android project.\n\n Afterwards, you can find the built APK at \\`android/app/build/outputs/apk/release/app-release.apk\\` or\n \\`android/app/build/outputs/apk/debug/app-debug.apk\\`.\n\n`);\n }\n};\nasync function replaceInUTF8File(filePath, findThis, replaceWith) {\n var fileContent = await readFile(filePath, \"utf8\");\n var replacedFileContent = fileContent.replace(findThis, replaceWith);\n if (replacedFileContent !== fileContent) {\n await writeFile(filePath, replacedFileContent, \"utf8\");\n }\n}\nexport {\n prebuild,\n replaceInUTF8File\n};\n//# sourceMappingURL=prebuild.js.map\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"prebuild.native.js","names":[],"sources":["exports/prebuild.native.js"],"sourcesContent":["import { detectPackageManager } from \"@vxrn/utils\";\nimport { existsSync, lstatSync, readdirSync, readFileSync, renameSync, rmSync } from \"fs\";\nimport { readFile, writeFile } from \"fs/promises\";\nimport path from \"path\";\nimport { fillOptions } from \"../config/getOptionsFilled\";\nimport { applyBuiltInPatches } from \"../utils/patches\";\nimport { applyAndroidDependencyPatches, generateForPlatform, getNativeDependencyInventory, installNativeDependencies, validatePrebuildApp } from \"./prebuildWithoutExpo\";\nvar prebuild = async function prebuild2(param) {\n var { root, platform, \"no-install\": noInstall = false, app, beforeInstall } = param;\n validatePrebuildApp(app, platform);\n var options = await fillOptions({\n root\n });\n await applyBuiltInPatches(options);\n try {\n var packageJsonPath = path.join(root, \"package.json\");\n var packageJsonContents = await readFile(packageJsonPath, \"utf8\");\n var { devDependencies } = JSON.parse(packageJsonContents);\n if (!(devDependencies === null || devDependencies === void 0 ? void 0 : devDependencies[\"@react-native-community/template\"])) {\n var installCommand = await (async function() {\n var found = await detectPackageManager();\n switch (true) {\n case found.bun:\n return `bun add -D @react-native-community/template`;\n case found.pnpm:\n return `pnpm install -D @react-native-community/template`;\n case found.yarn:\n return `yarn add -D @react-native-community/template`;\n default:\n return `npm install -D @react-native-community/template`;\n }\n })();\n throw new Error(`\"@react-native-community/template\" is not found in package.json, please install \"@react-native-community/template\" as dev dependency:\n\\`${installCommand}\\``);\n }\n } catch (error) {\n throw new Error(\"package.json checks are failing:\\n\" + error);\n }\n var ios = path.join(root, \"ios\");\n var previousIos = `${ios}.previous`;\n rmSync(previousIos, {\n recursive: true,\n force: true\n });\n var reusesIos = (platform == \"ios\" || !platform) && existsSync(ios);\n if (reusesIos) renameSync(ios, previousIos);\n if (platform == \"ios\" || !platform) {\n await generateForPlatform(root, \"ios\", app);\n }\n if (platform == \"android\" || !platform) {\n await generateForPlatform(root, \"android\", app);\n }\n await (beforeInstall === null || beforeInstall === void 0 ? void 0 : beforeInstall());\n if (reusesIos) reuseUnchangedIosProject(previousIos, ios);\n var inventory = await getNativeDependencyInventory(root);\n console.info(`[vxrn] native dependencies discovered through community autolinking: ${inventory.map(function(entry) {\n return entry.name;\n }).join(\", \") || \"(none)\"}`);\n if (platform == \"android\" || !platform) {\n applyAndroidDependencyPatches({\n root,\n app,\n inventory\n });\n }\n if (!noInstall) {\n installNativeDependencies({\n root,\n platform\n });\n } else if (!platform || platform === \"ios\") {\n console.info(`Run cd ios && pod install`);\n console.info(\"Then run `open *.xcworkspace` in your terminal to open the prebuilt iOS project, then you can either run it via Xcode or archive it for distribution.\");\n }\n if (!platform || platform === \"ios\") {\n console.info(`\niOS:\n\n Run \\`open ios/*.xcworkspace\\` in your terminal to open the prebuilt iOS project.\n Then you can either run it via Xcode or archive it for distribution.\n\n See https://onestack.dev/docs/guides-ios-native for more information.\n\n---\n`);\n }\n if (!platform || platform === \"android\") {\n console.info(`\nAndroid:\n\n \\`cd android\\` and run \\`./gradlew generateCodegenArtifactsFromSchema\\`, then \\`./gradlew assembleRelease\\` or \\`./gradlew assembleDebug\\` to build the Android project.\n\n Afterwards, you can find the built APK at \\`android/app/build/outputs/apk/release/app-release.apk\\` or\n \\`android/app/build/outputs/apk/debug/app-debug.apk\\`.\n\n`);\n }\n};\nfunction reuseUnchangedIosProject(previous, next) {\n var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;\n try {\n for (var _iterator = readdirSync(next, {\n recursive: true,\n withFileTypes: true\n })[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {\n var entry = _step.value;\n if (!entry.isFile()) continue;\n var file = path.join(entry.parentPath, entry.name);\n var old = path.join(previous, path.relative(next, file));\n if (!existsSync(old) || !lstatSync(old).isFile()) continue;\n if (lstatSync(old).size !== lstatSync(file).size) continue;\n if (!readFileSync(old).equals(readFileSync(file))) continue;\n renameSync(old, file);\n }\n } catch (err) {\n _didIteratorError = true;\n _iteratorError = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion && _iterator.return != null) {\n _iterator.return();\n }\n } finally {\n if (_didIteratorError) {\n throw _iteratorError;\n }\n }\n }\n for (var _i = 0, _iter = [\n \"Pods\",\n \"Podfile.lock\",\n \"build\"\n ]; _i < _iter.length; _i++) {\n var name = _iter[_i];\n var from = path.join(previous, name);\n var to = path.join(next, name);\n if (existsSync(from) && !existsSync(to)) renameSync(from, to);\n }\n rmSync(previous, {\n recursive: true,\n force: true\n });\n}\nasync function replaceInUTF8File(filePath, findThis, replaceWith) {\n var fileContent = await readFile(filePath, \"utf8\");\n var replacedFileContent = fileContent.replace(findThis, replaceWith);\n if (replacedFileContent !== fileContent) {\n await writeFile(filePath, replacedFileContent, \"utf8\");\n }\n}\nexport {\n prebuild,\n replaceInUTF8File\n};\n//# sourceMappingURL=prebuild.js.map\n"],"mappings":"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"}
|
|
@@ -228,6 +228,9 @@ function swiftShortcutPhrase(value) {
|
|
|
228
228
|
function renderIosAppIntentsSwift(actions) {
|
|
229
229
|
const types = actions.map((action, index) => {
|
|
230
230
|
const summaryTitle = swiftLiteral(action.title).slice(1, -1);
|
|
231
|
+
const description = action.description === void 0 ? "" : `
|
|
232
|
+
static let description = IntentDescription(${swiftLiteral(action.description)})`;
|
|
233
|
+
const openAppWhenRun = action.openAppWhenRun === true ? "\n static let openAppWhenRun: Bool = true" : "";
|
|
231
234
|
const text = action.textParameterTitle === void 0 ? "" : `
|
|
232
235
|
@Parameter(title: ${swiftLiteral(action.textParameterTitle)}) var text: String
|
|
233
236
|
|
|
@@ -236,20 +239,23 @@ function renderIosAppIntentsSwift(actions) {
|
|
|
236
239
|
}
|
|
237
240
|
`;
|
|
238
241
|
return `struct OneAppIntent${index}: AppIntent {
|
|
239
|
-
static let title: LocalizedStringResource = ${swiftLiteral(action.title)}
|
|
242
|
+
static let title: LocalizedStringResource = ${swiftLiteral(action.title)}${description}${openAppWhenRun}
|
|
240
243
|
${text}
|
|
241
|
-
func perform() async throws -> some IntentResult & ReturnsValue<String> {
|
|
244
|
+
func perform() async throws -> some IntentResult & ReturnsValue<String> & ProvidesDialog {
|
|
242
245
|
let result = try await oneAppIntentsRun(${swiftLiteral(action.id)}, ${text ? "text" : "nil"})
|
|
243
|
-
return .result(value: result)
|
|
246
|
+
return .result(value: result, dialog: IntentDialog(stringLiteral: result))
|
|
244
247
|
}
|
|
245
248
|
}`;
|
|
246
249
|
});
|
|
247
|
-
const shortcuts = actions.map((action, index) =>
|
|
250
|
+
const shortcuts = actions.map((action, index) => {
|
|
251
|
+
const phrases = Array.from(/* @__PURE__ */ new Set([action.shortcutPhrase, ...action.shortcutPhrases ?? []])).map(swiftShortcutPhrase);
|
|
252
|
+
return ` AppShortcut(
|
|
248
253
|
intent: OneAppIntent${index}(),
|
|
249
|
-
phrases: [${
|
|
254
|
+
phrases: [${phrases.join(", ")}],
|
|
250
255
|
shortTitle: ${swiftLiteral(action.title)},
|
|
251
|
-
systemImageName: "bolt.fill"
|
|
252
|
-
)
|
|
256
|
+
systemImageName: ${swiftLiteral(action.systemImageName ?? "bolt.fill")}
|
|
257
|
+
)`;
|
|
258
|
+
}).join("\n");
|
|
253
259
|
return `import AppIntents
|
|
254
260
|
import Foundation
|
|
255
261
|
|
|
@@ -560,6 +566,7 @@ function generateIosWidgets(dest, app) {
|
|
|
560
566
|
<key>NSExtension</key><dict><key>NSExtensionPointIdentifier</key><string>com.apple.widgetkit-extension</string></dict>
|
|
561
567
|
</dict></plist>
|
|
562
568
|
`);
|
|
569
|
+
const supportedFamilies = (widgets.families ?? ["systemSmall", "systemMedium"]).map((family) => `.${family}`).join(", ");
|
|
563
570
|
writeFileSync(path.join(appDir, "OneWidgetContract.swift"), `import Foundation
|
|
564
571
|
import ActivityKit
|
|
565
572
|
|
|
@@ -567,6 +574,7 @@ enum OneWidgetContract {
|
|
|
567
574
|
static let appGroup = ${JSON.stringify(widgets.appGroup)}
|
|
568
575
|
static let kind = ${JSON.stringify(widgets.kind)}
|
|
569
576
|
static let dataKey = "one.widget.data"
|
|
577
|
+
static let actionKeyPrefix = "one.widget.action."
|
|
570
578
|
|
|
571
579
|
struct Data: Codable {
|
|
572
580
|
let title: String
|
|
@@ -575,6 +583,13 @@ enum OneWidgetContract {
|
|
|
575
583
|
let layout: String?
|
|
576
584
|
}
|
|
577
585
|
|
|
586
|
+
struct Action: Codable {
|
|
587
|
+
let id: String
|
|
588
|
+
let action: String
|
|
589
|
+
let value: String?
|
|
590
|
+
let timestampMs: Double
|
|
591
|
+
}
|
|
592
|
+
|
|
578
593
|
struct Attributes: ActivityAttributes {
|
|
579
594
|
struct ContentState: Codable, Hashable {
|
|
580
595
|
let status: String
|
|
@@ -588,6 +603,7 @@ enum OneWidgetContract {
|
|
|
588
603
|
writeFileSync(path.join(extensionDir, "OneWidget.swift"), `import SwiftUI
|
|
589
604
|
import WidgetKit
|
|
590
605
|
import ActivityKit
|
|
606
|
+
import AppIntents
|
|
591
607
|
|
|
592
608
|
struct OneWidgetNode: Decodable {
|
|
593
609
|
let type: String
|
|
@@ -595,11 +611,36 @@ struct OneWidgetNode: Decodable {
|
|
|
595
611
|
let style: Style?
|
|
596
612
|
let children: [OneWidgetNode]?
|
|
597
613
|
let systemName: String?
|
|
598
|
-
let value:
|
|
614
|
+
let value: Value?
|
|
599
615
|
let total: Double?
|
|
600
616
|
let fill: String?
|
|
601
617
|
let cornerRadius: Double?
|
|
602
618
|
let url: String?
|
|
619
|
+
let action: String?
|
|
620
|
+
|
|
621
|
+
enum Value: Decodable {
|
|
622
|
+
case number(Double)
|
|
623
|
+
case string(String)
|
|
624
|
+
|
|
625
|
+
var number: Double? {
|
|
626
|
+
if case .number(let value) = self { return value }
|
|
627
|
+
return nil
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
var string: String? {
|
|
631
|
+
if case .string(let value) = self { return value }
|
|
632
|
+
return nil
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
init(from decoder: Decoder) throws {
|
|
636
|
+
let container = try decoder.singleValueContainer()
|
|
637
|
+
if let number = try? container.decode(Double.self) {
|
|
638
|
+
self = .number(number)
|
|
639
|
+
} else {
|
|
640
|
+
self = .string(try container.decode(String.self))
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
}
|
|
603
644
|
|
|
604
645
|
struct Style: Decodable {
|
|
605
646
|
let color: String?
|
|
@@ -618,6 +659,43 @@ struct OneWidgetNode: Decodable {
|
|
|
618
659
|
}
|
|
619
660
|
}
|
|
620
661
|
|
|
662
|
+
struct OneWidgetButtonIntent: AppIntent {
|
|
663
|
+
static var title: LocalizedStringResource = "Widget Action"
|
|
664
|
+
|
|
665
|
+
@Parameter(title: "Action") var action: String
|
|
666
|
+
@Parameter(title: "Value") var value: String?
|
|
667
|
+
|
|
668
|
+
init() {}
|
|
669
|
+
|
|
670
|
+
init(action: String, value: String?) {
|
|
671
|
+
self.action = action
|
|
672
|
+
self.value = value
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
func perform() async throws -> some IntentResult {
|
|
676
|
+
if let defaults = UserDefaults(suiteName: OneWidgetContract.appGroup) {
|
|
677
|
+
let item = OneWidgetContract.Action(
|
|
678
|
+
id: UUID().uuidString,
|
|
679
|
+
action: action,
|
|
680
|
+
value: value,
|
|
681
|
+
timestampMs: Date().timeIntervalSince1970 * 1000
|
|
682
|
+
)
|
|
683
|
+
if let encoded = try? JSONEncoder().encode(item) {
|
|
684
|
+
defaults.set(encoded, forKey: OneWidgetContract.actionKeyPrefix + item.id)
|
|
685
|
+
}
|
|
686
|
+
CFNotificationCenterPostNotification(
|
|
687
|
+
CFNotificationCenterGetDarwinNotifyCenter(),
|
|
688
|
+
CFNotificationName("dev.onejs.widget.action" as CFString),
|
|
689
|
+
nil,
|
|
690
|
+
nil,
|
|
691
|
+
true
|
|
692
|
+
)
|
|
693
|
+
}
|
|
694
|
+
WidgetCenter.shared.reloadTimelines(ofKind: OneWidgetContract.kind)
|
|
695
|
+
return .result()
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
|
|
621
699
|
struct OneActivityView: Decodable {
|
|
622
700
|
let lockScreen: OneWidgetNode
|
|
623
701
|
let compactLeading: OneWidgetNode?
|
|
@@ -710,10 +788,10 @@ struct OneWidgetRendered: View {
|
|
|
710
788
|
.font(.system(size: CGFloat(node.style?.fontSize ?? 20), weight: weight))
|
|
711
789
|
}
|
|
712
790
|
case "progress":
|
|
713
|
-
ProgressView(value: node.value ?? 0, total: node.total ?? 1)
|
|
791
|
+
ProgressView(value: node.value?.number ?? 0, total: node.total ?? 1)
|
|
714
792
|
.tint(oneColor(node.style?.color))
|
|
715
793
|
case "gauge":
|
|
716
|
-
Gauge(value: node.value ?? 0, in: 0...(node.total ?? 1)) { EmptyView() }
|
|
794
|
+
Gauge(value: node.value?.number ?? 0, in: 0...(node.total ?? 1)) { EmptyView() }
|
|
717
795
|
.gaugeStyle(.accessoryCircular)
|
|
718
796
|
.tint(oneColor(node.style?.color))
|
|
719
797
|
case "circle":
|
|
@@ -731,6 +809,15 @@ struct OneWidgetRendered: View {
|
|
|
731
809
|
}
|
|
732
810
|
}
|
|
733
811
|
}
|
|
812
|
+
case "button":
|
|
813
|
+
if let action = node.action {
|
|
814
|
+
Button(intent: OneWidgetButtonIntent(action: action, value: node.value?.string)) {
|
|
815
|
+
ForEach(Array((node.children ?? []).enumerated()), id: \\.offset) { _, child in
|
|
816
|
+
OneWidgetRendered(node: child)
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
.buttonStyle(.plain)
|
|
820
|
+
}
|
|
734
821
|
default: EmptyView()
|
|
735
822
|
}
|
|
736
823
|
}
|
|
@@ -791,7 +878,7 @@ struct OneWidget: Widget {
|
|
|
791
878
|
}
|
|
792
879
|
.configurationDisplayName(${JSON.stringify(widgets.displayName)})
|
|
793
880
|
.description(${JSON.stringify(widgets.description)})
|
|
794
|
-
.supportedFamilies([
|
|
881
|
+
.supportedFamilies([${supportedFamilies}])
|
|
795
882
|
}
|
|
796
883
|
}
|
|
797
884
|
|
|
@@ -885,28 +972,117 @@ RCT_EXTERN_METHOD(update:(NSString *)identifier status:(NSString *)status value:
|
|
|
885
972
|
RCT_EXTERN_METHOD(updateView:(NSString *)identifier layout:(NSString *)layout resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
886
973
|
RCT_EXTERN_METHOD(end:(NSString *)identifier resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
887
974
|
RCT_EXTERN_METHOD(pushToken:(NSString *)identifier resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
975
|
+
RCT_EXTERN_METHOD(claimActions:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
888
976
|
@end
|
|
889
977
|
`);
|
|
890
978
|
writeFileSync(path.join(appDir, "OneWidgetsBridge.swift"), `import Foundation
|
|
979
|
+
import UIKit
|
|
891
980
|
import React
|
|
892
981
|
import WidgetKit
|
|
893
982
|
import ActivityKit
|
|
894
983
|
|
|
984
|
+
private func oneWidgetsDarwinCallback(
|
|
985
|
+
_ center: CFNotificationCenter?,
|
|
986
|
+
_ observer: UnsafeMutableRawPointer?,
|
|
987
|
+
_ name: CFNotificationName?,
|
|
988
|
+
_ object: UnsafeRawPointer?,
|
|
989
|
+
_ userInfo: CFDictionary?
|
|
990
|
+
) {
|
|
991
|
+
guard let observer else { return }
|
|
992
|
+
let bridge = Unmanaged<OneWidgetsBridge>.fromOpaque(observer).takeUnretainedValue()
|
|
993
|
+
bridge.flushObservedActions()
|
|
994
|
+
}
|
|
995
|
+
|
|
895
996
|
@objc(OneWidgetsBridge)
|
|
896
997
|
class OneWidgetsBridge: RCTEventEmitter {
|
|
897
998
|
private var tokenTasks: [String: Task<Void, Never>] = [:]
|
|
999
|
+
private var isObservingEvents = false
|
|
1000
|
+
private var foregroundObserver: NSObjectProtocol?
|
|
1001
|
+
private let actionLock = NSLock()
|
|
898
1002
|
|
|
899
|
-
override func supportedEvents() -> [String]! { ["oneLiveActivityPushToken"] }
|
|
1003
|
+
override func supportedEvents() -> [String]! { ["oneLiveActivityPushToken", "oneWidgetAction"] }
|
|
900
1004
|
|
|
901
1005
|
override func startObserving() {
|
|
1006
|
+
isObservingEvents = true
|
|
902
1007
|
for activity in Activity<OneWidgetContract.Attributes>.activities {
|
|
903
1008
|
observeToken(activity)
|
|
904
1009
|
}
|
|
1010
|
+
CFNotificationCenterAddObserver(
|
|
1011
|
+
CFNotificationCenterGetDarwinNotifyCenter(),
|
|
1012
|
+
Unmanaged.passUnretained(self).toOpaque(),
|
|
1013
|
+
oneWidgetsDarwinCallback,
|
|
1014
|
+
"dev.onejs.widget.action" as CFString,
|
|
1015
|
+
nil,
|
|
1016
|
+
.deliverImmediately
|
|
1017
|
+
)
|
|
1018
|
+
foregroundObserver = NotificationCenter.default.addObserver(
|
|
1019
|
+
forName: UIApplication.didBecomeActiveNotification,
|
|
1020
|
+
object: nil,
|
|
1021
|
+
queue: .main
|
|
1022
|
+
) { [weak self] _ in
|
|
1023
|
+
self?.flushObservedActions()
|
|
1024
|
+
}
|
|
1025
|
+
flushObservedActions()
|
|
905
1026
|
}
|
|
906
1027
|
|
|
907
1028
|
override func stopObserving() {
|
|
1029
|
+
isObservingEvents = false
|
|
908
1030
|
for task in tokenTasks.values { task.cancel() }
|
|
909
1031
|
tokenTasks.removeAll()
|
|
1032
|
+
CFNotificationCenterRemoveObserver(
|
|
1033
|
+
CFNotificationCenterGetDarwinNotifyCenter(),
|
|
1034
|
+
Unmanaged.passUnretained(self).toOpaque(),
|
|
1035
|
+
CFNotificationName("dev.onejs.widget.action" as CFString),
|
|
1036
|
+
nil
|
|
1037
|
+
)
|
|
1038
|
+
if let foregroundObserver {
|
|
1039
|
+
NotificationCenter.default.removeObserver(foregroundObserver)
|
|
1040
|
+
self.foregroundObserver = nil
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
deinit {
|
|
1045
|
+
CFNotificationCenterRemoveObserver(
|
|
1046
|
+
CFNotificationCenterGetDarwinNotifyCenter(),
|
|
1047
|
+
Unmanaged.passUnretained(self).toOpaque(),
|
|
1048
|
+
CFNotificationName("dev.onejs.widget.action" as CFString),
|
|
1049
|
+
nil
|
|
1050
|
+
)
|
|
1051
|
+
if let foregroundObserver {
|
|
1052
|
+
NotificationCenter.default.removeObserver(foregroundObserver)
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
fileprivate func flushObservedActions() {
|
|
1057
|
+
guard isObservingEvents else { return }
|
|
1058
|
+
for item in drainStoredActions() {
|
|
1059
|
+
sendEvent(withName: "oneWidgetAction", body: item)
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
private func drainStoredActions() -> [[String: Any]] {
|
|
1064
|
+
actionLock.lock()
|
|
1065
|
+
defer { actionLock.unlock() }
|
|
1066
|
+
guard let defaults = UserDefaults(suiteName: OneWidgetContract.appGroup) else {
|
|
1067
|
+
return []
|
|
1068
|
+
}
|
|
1069
|
+
var actions: [OneWidgetContract.Action] = []
|
|
1070
|
+
for key in defaults.dictionaryRepresentation().keys where key.hasPrefix(OneWidgetContract.actionKeyPrefix) {
|
|
1071
|
+
guard let data = defaults.data(forKey: key) else { continue }
|
|
1072
|
+
defaults.removeObject(forKey: key)
|
|
1073
|
+
if let action = try? JSONDecoder().decode(OneWidgetContract.Action.self, from: data) {
|
|
1074
|
+
actions.append(action)
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
actions.sort { $0.timestampMs < $1.timestampMs }
|
|
1078
|
+
return actions.map { action in
|
|
1079
|
+
[
|
|
1080
|
+
"id": action.id,
|
|
1081
|
+
"action": action.action,
|
|
1082
|
+
"value": action.value ?? NSNull(),
|
|
1083
|
+
"timestampMs": action.timestampMs,
|
|
1084
|
+
]
|
|
1085
|
+
}
|
|
910
1086
|
}
|
|
911
1087
|
|
|
912
1088
|
private func observeToken(_ activity: Activity<OneWidgetContract.Attributes>) {
|
|
@@ -1048,6 +1224,15 @@ class OneWidgetsBridge: RCTEventEmitter {
|
|
|
1048
1224
|
resolve(NSNull())
|
|
1049
1225
|
}
|
|
1050
1226
|
}
|
|
1227
|
+
|
|
1228
|
+
@objc(claimActions:rejecter:)
|
|
1229
|
+
func claimActions(_ resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) {
|
|
1230
|
+
guard UserDefaults(suiteName: OneWidgetContract.appGroup) != nil else {
|
|
1231
|
+
reject("app_group", "Cannot open the configured App Group", nil)
|
|
1232
|
+
return
|
|
1233
|
+
}
|
|
1234
|
+
resolve(drainStoredActions())
|
|
1235
|
+
}
|
|
1051
1236
|
}
|
|
1052
1237
|
`);
|
|
1053
1238
|
}
|