@legendapp/spark 0.0.1-next.3 → 0.0.1-next.4
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/camera.ts +13 -0
- package/package.json +21 -11
- package/patches/camera/react-native-nitro-image.patch +320 -0
- package/patches/camera/react-native-nitro-modules.patch +50 -0
- package/patches/camera/react-native-vision-camera.patch +2662 -0
- package/patches/camera/upstream.json +22 -0
- package/patches/dependencies.json +8 -0
- package/patches/react-native-enriched-markdown@1.0.2.patch +8684 -0
- package/postinstall.cjs +1 -0
- package/ui-swipe.ts +1 -0
- package/vendor/node_modules/@legendapp/spark-ai/package.json +3 -3
- package/vendor/node_modules/@legendapp/spark-audio/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-auth-session/package.json +3 -3
- package/vendor/node_modules/@legendapp/spark-cli/dist/build.js +62 -11
- package/vendor/node_modules/@legendapp/spark-cli/dist/cli-arguments.js +2 -1
- package/vendor/node_modules/@legendapp/spark-cli/dist/commands.js +3 -2
- package/vendor/node_modules/@legendapp/spark-cli/dist/create.js +6 -3
- package/vendor/node_modules/@legendapp/spark-cli/dist/credentials.js +41 -26
- package/vendor/node_modules/@legendapp/spark-cli/dist/dependency-pins.js +132 -0
- package/vendor/node_modules/@legendapp/spark-cli/dist/dev-command.js +1 -1
- package/vendor/node_modules/@legendapp/spark-cli/dist/dev.js +1 -1
- package/vendor/node_modules/@legendapp/spark-cli/dist/errors.js +100 -0
- package/vendor/node_modules/@legendapp/spark-cli/dist/examples.js +1 -1
- package/vendor/node_modules/@legendapp/spark-cli/dist/expo-native.cjs +5 -1
- package/vendor/node_modules/@legendapp/spark-cli/dist/helpers.js +1 -1
- package/vendor/node_modules/@legendapp/spark-cli/dist/index.js +43 -7
- package/vendor/node_modules/@legendapp/spark-cli/dist/json.js +16 -0
- package/vendor/node_modules/@legendapp/spark-cli/dist/native-patch-preflight.js +3 -1
- package/vendor/node_modules/@legendapp/spark-cli/dist/process.js +7 -0
- package/vendor/node_modules/@legendapp/spark-cli/dist/project.js +27 -22
- package/vendor/node_modules/@legendapp/spark-cli/dist/release.js +2 -1
- package/vendor/node_modules/@legendapp/spark-cli/dist/release.json +19 -19
- package/vendor/node_modules/@legendapp/spark-cli/dist/universal.cjs +2 -1
- package/vendor/node_modules/@legendapp/spark-cli/dist/windows.js +1 -8
- package/vendor/node_modules/@legendapp/spark-cli/package.json +3 -3
- package/vendor/node_modules/@legendapp/spark-cli/templates/blank-typescript/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-cli/templates/universal/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-cli/templates/windows/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-clipboard/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-codex/package.json +3 -3
- package/vendor/node_modules/@legendapp/spark-commands/package.json +5 -5
- package/vendor/node_modules/@legendapp/spark-context-menu/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-desktop-app/package.json +1 -1
- package/vendor/node_modules/@legendapp/spark-desktop-app/src/contracts/menu.ts +6 -4
- package/vendor/node_modules/@legendapp/spark-desktop-config/config.cjs +2 -0
- package/vendor/node_modules/@legendapp/spark-desktop-config/expo.cjs +1 -0
- package/vendor/node_modules/@legendapp/spark-desktop-config/native-patches.cjs +106 -0
- package/vendor/node_modules/@legendapp/spark-desktop-config/native-patches.d.cts +1 -0
- package/vendor/node_modules/@legendapp/spark-desktop-config/package.json +5 -4
- package/vendor/node_modules/@legendapp/spark-desktop-host/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-desktop-links/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-desktop-windows/macos/window-manager/RNWindowManager.mm +39 -0
- package/vendor/node_modules/@legendapp/spark-desktop-windows/package.json +3 -3
- package/vendor/node_modules/@legendapp/spark-desktop-windows/src/api.ts +3 -1
- package/vendor/node_modules/@legendapp/spark-desktop-windows/src/macos-adapter.ts +1 -1
- package/vendor/node_modules/@legendapp/spark-documents/package.json +7 -7
- package/vendor/node_modules/@legendapp/spark-drag-drop/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-file-dialog/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-file-system/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-global-shortcuts/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-message-dialog/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-native-menu/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-notifications/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-notifications/windows/SparkNotifications/SparkNotifications.h +16 -11
- package/vendor/node_modules/@legendapp/spark-processes/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-secure-storage/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-settings/package.json +3 -3
- package/vendor/node_modules/@legendapp/spark-settings-ui/package.json +4 -4
- package/vendor/node_modules/@legendapp/spark-sqlite/package.json +3 -3
- package/vendor/node_modules/@legendapp/spark-system/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-tray/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-ui/macos/appkit-split-view/RNSidebarSplitViewComponent.mm +263 -26
- package/vendor/node_modules/@legendapp/spark-ui/macos/swipe-actions/RNSwipeActions.h +10 -0
- package/vendor/node_modules/@legendapp/spark-ui/macos/swipe-actions/RNSwipeActions.mm +422 -0
- package/vendor/node_modules/@legendapp/spark-ui/package.json +3 -2
- package/vendor/node_modules/@legendapp/spark-ui/src/appkit-split-view/SidebarSplitViewNativeComponent.ts +6 -0
- package/vendor/node_modules/@legendapp/spark-ui/src/appkit-split-view/index.tsx +20 -11
- package/vendor/node_modules/@legendapp/spark-ui/src/swipe-actions/SwipeActionsNativeComponent.ts +11 -0
- package/vendor/node_modules/@legendapp/spark-ui/src/swipe-actions/index.tsx +41 -0
- package/vendor/node_modules/@legendapp/spark-updates/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-webview/package.json +2 -2
- package/vendor/node_modules/@legendapp/spark-window-options/package.json +1 -1
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
// Command failures retain diagnostics without making callers parse their message.
|
|
4
|
+
export class CommandError extends Error {
|
|
5
|
+
argv;
|
|
6
|
+
code;
|
|
7
|
+
output;
|
|
8
|
+
log;
|
|
9
|
+
constructor(argv, code, output, log) {
|
|
10
|
+
super(`${argv.join(" ")} exited ${code}${log ? `. See ${log}` : ""}${output ? `\n${output.slice(-1800)}` : ""}`);
|
|
11
|
+
this.argv = argv;
|
|
12
|
+
this.code = code;
|
|
13
|
+
this.output = output;
|
|
14
|
+
this.log = log;
|
|
15
|
+
this.name = "CommandError";
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function isNetworkError(error) {
|
|
19
|
+
const message = error instanceof CommandError ? error.output : error instanceof Error ? error.message : String(error);
|
|
20
|
+
return /NSURLErrorDomain Code=-(?:1001|1005|1009)|internet connection appears to be offline|\b(?:ENOTFOUND|EAI_AGAIN|ETIMEDOUT|ECONNRESET|ENETUNREACH)\b|could not resolve host|failed to connect|network is unreachable/i.test(message);
|
|
21
|
+
}
|
|
22
|
+
export function errorPresentation(error) {
|
|
23
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
24
|
+
const command = error instanceof CommandError ? error.argv.join(" ") : "";
|
|
25
|
+
const details = error instanceof CommandError ? error.output : message;
|
|
26
|
+
let summary = message.split("\n")[0] || "An unexpected error occurred.";
|
|
27
|
+
let next;
|
|
28
|
+
if (isNetworkError(error)) {
|
|
29
|
+
summary = command.includes("notarytool") ? "Could not reach Apple’s notarization service." : "Could not reach the remote service.";
|
|
30
|
+
next = "Check your internet connection or VPN, then retry the same command.";
|
|
31
|
+
}
|
|
32
|
+
else if ((/\b(?:E401|ENEEDAUTH)\b|401 Unauthorized/i.test(details) && /npm/.test(command || message)) || command === "npm whoami") {
|
|
33
|
+
summary = "npm authentication failed.";
|
|
34
|
+
next = "Run npm login, then retry the same release command.";
|
|
35
|
+
}
|
|
36
|
+
else if (command === "gh auth status" || /gh auth login/.test(details)) {
|
|
37
|
+
summary = "GitHub authentication failed.";
|
|
38
|
+
next = "Run gh auth login, then retry the same command.";
|
|
39
|
+
}
|
|
40
|
+
else if (/No Keychain password item found for profile:/.test(details)) {
|
|
41
|
+
summary = "The selected notarization Keychain profile was not found.";
|
|
42
|
+
next = "Run spark credentials to select an existing profile or explicitly create one.";
|
|
43
|
+
}
|
|
44
|
+
else if (/notarytool/.test(command) && /\b401\b|invalid credentials|authentication/i.test(details)) {
|
|
45
|
+
summary = "Apple rejected the notarization credentials.";
|
|
46
|
+
next = "Run spark credentials to select or explicitly create a valid Keychain profile.";
|
|
47
|
+
}
|
|
48
|
+
else if (error instanceof CommandError) {
|
|
49
|
+
const checks = { "bun run test": "Tests failed.", "bun run typecheck": "Type checking failed.", "bun install --frozen-lockfile": "Dependency installation failed." };
|
|
50
|
+
summary = checks[command] ?? `${command} failed (exit ${error.code}).`;
|
|
51
|
+
next = "Review the diagnostic log or output above, fix the problem, then retry the same command.";
|
|
52
|
+
}
|
|
53
|
+
return { summary, next };
|
|
54
|
+
}
|
|
55
|
+
function diagnostics(error, seen = new Set()) {
|
|
56
|
+
let result = String(error);
|
|
57
|
+
if (error instanceof Error && !seen.has(error)) {
|
|
58
|
+
seen.add(error);
|
|
59
|
+
result = error.stack ?? error.message;
|
|
60
|
+
if (error instanceof CommandError && error.output)
|
|
61
|
+
result += `\n\nCommand output:\n${error.output}`;
|
|
62
|
+
if (error.cause)
|
|
63
|
+
result += `\n\nCaused by:\n${diagnostics(error.cause, seen)}`;
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
export function reportError(root, error, label = "Release") {
|
|
68
|
+
const { summary, next } = errorPresentation(error);
|
|
69
|
+
console.error(`\n${label} stopped: ${summary}`);
|
|
70
|
+
if (next)
|
|
71
|
+
console.error(`Next: ${next}`);
|
|
72
|
+
let log;
|
|
73
|
+
try {
|
|
74
|
+
const folder = path.join(root, ".spark/logs");
|
|
75
|
+
mkdirSync(folder, { recursive: true });
|
|
76
|
+
const destination = path.join(folder, `${Date.now()}-${crypto.randomUUID()}-error.log`);
|
|
77
|
+
writeFileSync(destination, diagnostics(error));
|
|
78
|
+
log = destination;
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// Reporting must still work when the original failure was a full disk.
|
|
82
|
+
if (error instanceof CommandError)
|
|
83
|
+
log = error.log;
|
|
84
|
+
}
|
|
85
|
+
if (log)
|
|
86
|
+
console.error(`Details: ${log}`);
|
|
87
|
+
else
|
|
88
|
+
console.error("Could not save diagnostics. Set SPARK_DEBUG=1 to print them.");
|
|
89
|
+
if (process.env.SPARK_DEBUG === "1")
|
|
90
|
+
console.error(diagnostics(error));
|
|
91
|
+
}
|
|
92
|
+
export async function releaseCommand(root, action) {
|
|
93
|
+
try {
|
|
94
|
+
await action();
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
reportError(root, error);
|
|
98
|
+
process.exitCode = 1;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { packageManager, managerCommand } from "./package-manager.js";
|
|
2
2
|
import { cpSync, writeFileSync } from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import { readJson, writeJson } from "./
|
|
4
|
+
import { readJson, writeJson } from "./json.js";
|
|
5
5
|
import { run } from "./commands.js";
|
|
6
6
|
export const examples = ["document-editor", "notes-lite", "music-lite", "diff-lite"];
|
|
7
7
|
export async function configureExample(root, example) {
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
exports.withSparkNative = (original, root) => {
|
|
2
|
-
if (!['macos', 'windows'].includes(process.env.SPARK_PLATFORM))
|
|
2
|
+
if (!['macos', 'windows'].includes(process.env.SPARK_PLATFORM)) {
|
|
3
|
+
const patched = require('@legendapp/spark-desktop-config/native-patches.cjs').prepareNativePatches(root);
|
|
4
|
+
if (!Object.keys(patched).length) return original;
|
|
5
|
+
return { ...original, dependencies: { ...patched, ...original.dependencies } };
|
|
6
|
+
}
|
|
3
7
|
const generated = require('./universal.cjs').nativeConfig(root);
|
|
4
8
|
const dependencies = { ...original.dependencies };
|
|
5
9
|
for (const [name, config] of Object.entries(generated.dependencies ?? {})) {
|
|
@@ -2,8 +2,8 @@ import { copyFileSync, lstatSync, mkdirSync, realpathSync, chmodSync, readdirSyn
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { architecture } from "./platform.js";
|
|
5
|
-
const { validateHelpers } = createRequire(import.meta.url)("@legendapp/spark-desktop-config/helpers.cjs");
|
|
6
5
|
export function resolveHelpers(root, helpers = {}, platform = "macos", arch = architecture(platform)) {
|
|
6
|
+
const { validateHelpers } = createRequire(import.meta.url)("@legendapp/spark-desktop-config/helpers.cjs");
|
|
7
7
|
validateHelpers(helpers);
|
|
8
8
|
const base = realpathSync(root);
|
|
9
9
|
function inspect(file) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { spawnProcess } from "./process.js";
|
|
1
|
+
import { nodeCommand, spawnProcess } from "./process.js";
|
|
2
2
|
import { examples } from "./examples.js";
|
|
3
3
|
import { prepareGoProfile } from "./go-profile.js";
|
|
4
4
|
import { exportSDK, importSDK } from "./sdk-transfer.js";
|
|
@@ -7,7 +7,7 @@ import path from "node:path";
|
|
|
7
7
|
import { cliArguments } from "./cli-arguments.js";
|
|
8
8
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
9
9
|
import { prepareConfig, readConfig, isExpoProject } from "@legendapp/spark-desktop-config/config.cjs";
|
|
10
|
-
import {
|
|
10
|
+
import { prepareWindows } from "./windows.js";
|
|
11
11
|
import { create, refreshLocalPackages } from "./create.js";
|
|
12
12
|
import { addDesktop } from "./add-desktop.js";
|
|
13
13
|
import { buildMode } from "./build-mode.js";
|
|
@@ -20,6 +20,8 @@ import { doctor, run } from "./commands.js";
|
|
|
20
20
|
import { findFramework, findProject, sparkHome, creationManifest, packageManifest, registerRuntime } from "./local.js";
|
|
21
21
|
import { readJson, stateFile, VERSION, writeJson } from "./project.js";
|
|
22
22
|
import { devCommand } from "./dev-command.js";
|
|
23
|
+
import { printDependencyPins, upgradeDependencyPins } from "./dependency-pins.js";
|
|
24
|
+
import { reportError } from "./errors.js";
|
|
23
25
|
async function main() {
|
|
24
26
|
const argv = process.argv.slice(2);
|
|
25
27
|
if (argv[0] === "dev")
|
|
@@ -78,6 +80,8 @@ async function main() {
|
|
|
78
80
|
spark build Build a standalone desktop app
|
|
79
81
|
spark prebuild Generate a Windows/mobile native project
|
|
80
82
|
spark package Sign and notarize a distribution archive
|
|
83
|
+
spark doctor Check app dependency pins and native tooling (exits 1 on issues)
|
|
84
|
+
spark upgrade Align app dependency pins with Spark (--dry-run previews changes)
|
|
81
85
|
|
|
82
86
|
Inside an app: npm run dev, npm run build, npm run package (or pnpm, yarn, bun)
|
|
83
87
|
|
|
@@ -99,8 +103,6 @@ Overrides: --project <directory>, --port <number>, dev --runner-binary <runtime
|
|
|
99
103
|
case "create": {
|
|
100
104
|
if (!positionals[1])
|
|
101
105
|
throw new Error("Usage: spark create MyApp");
|
|
102
|
-
if (!(values.universal || values.example) && !["macos", "windows"].includes(platform))
|
|
103
|
-
throw new Error("Use create --universal for mobile/web targets");
|
|
104
106
|
await create(path.resolve(positionals[1]), creationManifest(values.packages), platform, !!values.universal || !!values.example, values.example, values["package-manager"]);
|
|
105
107
|
break;
|
|
106
108
|
}
|
|
@@ -173,10 +175,44 @@ Overrides: --project <directory>, --port <number>, dev --runner-binary <runtime
|
|
|
173
175
|
throw new Error("For macOS, spark build --dev generates and builds the native project.");
|
|
174
176
|
await prepareWindows(project(), "dev");
|
|
175
177
|
break;
|
|
176
|
-
case "doctor":
|
|
177
|
-
|
|
178
|
+
case "doctor": {
|
|
179
|
+
let root;
|
|
180
|
+
let pinIssues = false;
|
|
181
|
+
try {
|
|
182
|
+
root = project();
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
console.log("No Spark app found; skipping dependency pin check.");
|
|
186
|
+
}
|
|
187
|
+
if (root) {
|
|
188
|
+
try {
|
|
189
|
+
const issues = upgradeDependencyPins(root, true);
|
|
190
|
+
printDependencyPins(issues);
|
|
191
|
+
if (issues.length) {
|
|
192
|
+
process.exitCode = 1;
|
|
193
|
+
pinIssues = true;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
console.error(`Dependency pin check failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
198
|
+
process.exitCode = 1;
|
|
199
|
+
pinIssues = true;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
await doctor(root ?? start);
|
|
178
203
|
console.log("Native toolchain available.");
|
|
204
|
+
if (pinIssues)
|
|
205
|
+
console.log("Dependency pin issues found; run spark upgrade.");
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
case "upgrade": {
|
|
209
|
+
const issues = upgradeDependencyPins(project(), !!values["dry-run"]);
|
|
210
|
+
console.log(values["dry-run"] ? "Dependency pin changes (dry run):" : "Dependency pin changes:");
|
|
211
|
+
printDependencyPins(issues);
|
|
212
|
+
if (issues.length)
|
|
213
|
+
console.log(values["dry-run"] ? "No files changed. Run spark upgrade, then run your package manager's install command (npm/pnpm/yarn/bun install)." : "Updated package.json. Run your package manager's install command (npm/pnpm/yarn/bun install).");
|
|
179
214
|
break;
|
|
215
|
+
}
|
|
180
216
|
case "updates": {
|
|
181
217
|
if (positionals[1] !== "init" || !positionals[2])
|
|
182
218
|
throw new Error("Usage: spark updates init https://example.com/updates/appcast.xml");
|
|
@@ -230,6 +266,6 @@ try {
|
|
|
230
266
|
await main();
|
|
231
267
|
}
|
|
232
268
|
catch (error) {
|
|
233
|
-
|
|
269
|
+
reportError(process.cwd(), error, "Spark");
|
|
234
270
|
process.exitCode = 1;
|
|
235
271
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, renameSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
export function readJson(file) {
|
|
4
|
+
return JSON.parse(readFileSync(file, "utf8"));
|
|
5
|
+
}
|
|
6
|
+
export function writeJson(file, value) {
|
|
7
|
+
const content = JSON.stringify(value, null, 2) + "\n";
|
|
8
|
+
// Metro watches JSON too: rewriting unchanged session state on every runtime
|
|
9
|
+
// check causes empty Fast Refresh updates even when app code has not changed.
|
|
10
|
+
if (existsSync(file) && readFileSync(file, "utf8") === content)
|
|
11
|
+
return;
|
|
12
|
+
mkdirSync(path.dirname(file), { recursive: true });
|
|
13
|
+
const temporary = `${file}.${process.pid}.tmp`;
|
|
14
|
+
writeFileSync(temporary, content);
|
|
15
|
+
renameSync(temporary, file);
|
|
16
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { existsSync, readFileSync } from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
|
+
import { prepareNativePatches } from "@legendapp/spark-desktop-config/native-patches.cjs";
|
|
4
5
|
import { findFramework } from "./local.js";
|
|
5
6
|
import { installedPackages, readJson, VERSION } from "./project.js";
|
|
6
7
|
const required = ["@react-native-runtimes/core", "react-native-nitro-modules", "@op-engineering/op-sqlite", "react-native-webview"];
|
|
@@ -67,6 +68,7 @@ export function validateWorkspaceNativePatches(root, packages) {
|
|
|
67
68
|
return errors;
|
|
68
69
|
}
|
|
69
70
|
export function assertNativePatchPreflight(root) {
|
|
71
|
+
prepareNativePatches(root);
|
|
70
72
|
const packages = installedPackages(root);
|
|
71
73
|
const framework = findFramework(root);
|
|
72
74
|
let errors;
|
|
@@ -80,5 +82,5 @@ export function assertNativePatchPreflight(root) {
|
|
|
80
82
|
errors = validatePackedNativePatches(packages, requirements);
|
|
81
83
|
}
|
|
82
84
|
if (errors.length)
|
|
83
|
-
throw new Error(`Native preparation stopped before changing project files:\n${errors.map(error => `- ${error}`).join("\n")}`);
|
|
85
|
+
throw new Error(`Native patch preparation stopped before changing project files:\n${errors.map(error => `- ${error}`).join("\n")}`);
|
|
84
86
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { readJson } from "./json.js";
|
|
1
2
|
import path from "node:path";
|
|
2
3
|
import { spawn as nodeSpawn } from "node:child_process";
|
|
3
4
|
import { createRequire } from "node:module";
|
|
@@ -55,3 +56,9 @@ export function spawnProcess(argv, options = {}) {
|
|
|
55
56
|
return result;
|
|
56
57
|
}
|
|
57
58
|
export { which } from "./executable.js";
|
|
59
|
+
// Windows .cmd shims are shell programs; run the package's actual JS entry.
|
|
60
|
+
export function nodeCommand(root, name, bin, args = []) {
|
|
61
|
+
const req = createRequire(path.join(root, "package.json"));
|
|
62
|
+
const file = req.resolve(`${name}/package.json`), pkg = readJson(file);
|
|
63
|
+
return ["node", path.resolve(path.dirname(file), typeof pkg.bin === "string" ? pkg.bin : pkg.bin[bin]), ...args];
|
|
64
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { nativeWindowOptions } from "@legendapp/spark-window-options";
|
|
2
|
+
import { prepareNativePatches } from "@legendapp/spark-desktop-config/native-patches.cjs";
|
|
2
3
|
import { macOSReleaseSettings } from "./macos-release.js";
|
|
3
4
|
import { projectPlatform, architecture } from "./platform.js";
|
|
4
5
|
import { resolveHelpers } from "./helpers.js";
|
|
@@ -6,23 +7,11 @@ import { readConfig as readAppConfig, prepareConfig, writeUpdates, statePath, is
|
|
|
6
7
|
export { readAppConfig, prepareConfig, writeUpdates, statePath, isUniversal };
|
|
7
8
|
import { createHash } from "node:crypto";
|
|
8
9
|
import { createRequire } from "node:module";
|
|
9
|
-
import { existsSync,
|
|
10
|
+
import { existsSync, readFileSync, readdirSync, realpathSync, } from "node:fs";
|
|
10
11
|
import path from "node:path";
|
|
11
|
-
|
|
12
|
-
export
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
export function writeJson(file, value) {
|
|
16
|
-
const content = JSON.stringify(value, null, 2) + "\n";
|
|
17
|
-
// Metro watches JSON too: rewriting unchanged session state on every runtime
|
|
18
|
-
// check causes empty Fast Refresh updates even when app code has not changed.
|
|
19
|
-
if (existsSync(file) && readFileSync(file, "utf8") === content)
|
|
20
|
-
return;
|
|
21
|
-
mkdirSync(path.dirname(file), { recursive: true });
|
|
22
|
-
const temporary = `${file}.${process.pid}.tmp`;
|
|
23
|
-
writeFileSync(temporary, content);
|
|
24
|
-
renameSync(temporary, file);
|
|
25
|
-
}
|
|
12
|
+
import { readJson, writeJson } from "./json.js";
|
|
13
|
+
export { readJson, writeJson };
|
|
14
|
+
export const VERSION = "0.0.1-next.4";
|
|
26
15
|
export function digest(value) {
|
|
27
16
|
return createHash("sha256").update(value).digest("hex");
|
|
28
17
|
}
|
|
@@ -134,17 +123,31 @@ export function hashFiles(root, entries, windows = false) {
|
|
|
134
123
|
visit(entry);
|
|
135
124
|
return hash.digest("hex");
|
|
136
125
|
}
|
|
137
|
-
export function nativePackages(root) {
|
|
126
|
+
export function nativePackages(root, { applyExcludes = true } = {}) {
|
|
127
|
+
prepareNativePatches(root);
|
|
138
128
|
const installed = installedPackages(root);
|
|
139
129
|
if (projectPlatform(root) === "windows")
|
|
140
130
|
return windowsNativePackages(root, installed);
|
|
131
|
+
const excluded = ["app.json", "desktop.config.json"].some(file => existsSync(path.join(root, file)))
|
|
132
|
+
? readAppConfig(root).expo?.autolinking?.exclude ?? [] : [];
|
|
133
|
+
if (!applyExcludes) {
|
|
134
|
+
const appRequire = createRequire(path.join(root, "package.json"));
|
|
135
|
+
for (const name of excluded) {
|
|
136
|
+
if (installed.some(pkg => pkg.name === name))
|
|
137
|
+
continue;
|
|
138
|
+
const file = appRequire.resolve.paths(name)?.map(base => path.join(base, name, "package.json")).find(file => existsSync(file));
|
|
139
|
+
if (!file)
|
|
140
|
+
continue;
|
|
141
|
+
const json = readJson(file);
|
|
142
|
+
installed.push({ name: json.name, root: realpathSync(path.dirname(file)), json });
|
|
143
|
+
}
|
|
144
|
+
installed.sort((a, b) => a.name.localeCompare(b.name));
|
|
145
|
+
}
|
|
141
146
|
// Host/CNG code can change the native ABI without adding a TurboModule.
|
|
142
147
|
// Fold it into the mandatory app module's compatibility signature for Go.
|
|
143
148
|
const adapters = installed.filter(pkg => ["@legendapp/spark-desktop-host", "@legendapp/spark-desktop-config"].includes(pkg.name))
|
|
144
149
|
.map(pkg => hashFiles(pkg.root, ["package.json", "AppDelegate.mm", ...readdirSync(pkg.root).filter(name => name.endsWith(".cjs"))])).join(":");
|
|
145
|
-
|
|
146
|
-
? readAppConfig(root).expo?.autolinking?.exclude ?? [] : [];
|
|
147
|
-
return installed.filter(pkg => !excluded.includes(pkg.name))
|
|
150
|
+
return installed.filter(pkg => !applyExcludes || !excluded.includes(pkg.name))
|
|
148
151
|
.filter((pkg) => pkg.json.codegenConfig ||
|
|
149
152
|
pkg.json.spark?.nativeModules ||
|
|
150
153
|
readdirSync(pkg.root).some((name) => name.endsWith(".podspec") || name === "expo-module.config.json"))
|
|
@@ -181,12 +184,12 @@ export function dependencyStamp(root) {
|
|
|
181
184
|
"react-native.config.js",
|
|
182
185
|
]);
|
|
183
186
|
}
|
|
184
|
-
export function selection(packages, used, include = []) {
|
|
187
|
+
export function selection(packages, used, include = [], excluded = []) {
|
|
185
188
|
const selected = new Set([
|
|
186
189
|
...packages.filter((p) => !p.sdk).map((p) => p.name),
|
|
187
190
|
...used,
|
|
188
191
|
...include,
|
|
189
|
-
]);
|
|
192
|
+
].filter(name => !excluded.includes(name)));
|
|
190
193
|
const reasons = {};
|
|
191
194
|
for (const pkg of packages)
|
|
192
195
|
if (selected.has(pkg.name))
|
|
@@ -209,6 +212,8 @@ export function selection(packages, used, include = []) {
|
|
|
209
212
|
for (const name of nativeDeps) {
|
|
210
213
|
if (!packages.some((p) => p.name === name))
|
|
211
214
|
throw new Error(`${pkg.name} requires missing native package ${name}`);
|
|
215
|
+
if (excluded.includes(name))
|
|
216
|
+
continue;
|
|
212
217
|
if (!selected.has(name)) {
|
|
213
218
|
selected.add(name);
|
|
214
219
|
reasons[name] = `native dependency of ${pkg.name}`;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
2
|
import { closeSync, existsSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, writeSync } from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import { readJson
|
|
4
|
+
import { readJson } from "./json.js";
|
|
5
5
|
import { localArchive } from "./package-manager.js";
|
|
6
|
+
const VERSION = readJson(path.resolve(import.meta.dirname, "../package.json")).version;
|
|
6
7
|
export const releaseBase = (version) => `https://github.com/LegendApp/legend-spark/releases/download/v${version}`;
|
|
7
8
|
export function validateRelease(value) {
|
|
8
9
|
if (value?.schema !== 1 || value.version !== VERSION || !/^[a-f0-9]{40}$/.test(value.revision) || !value.packages || !value.runners)
|
|
@@ -1,42 +1,42 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": 1,
|
|
3
|
-
"version": "0.0.1-next.
|
|
4
|
-
"revision": "
|
|
3
|
+
"version": "0.0.1-next.4",
|
|
4
|
+
"revision": "23bfaba5d57e9eda98422f1187fd65037ac11d01",
|
|
5
5
|
"packages": {
|
|
6
6
|
"@react-native-runtimes/core": {
|
|
7
|
-
"url": "https://github.com/LegendApp/legend-spark/releases/download/v0.0.1-next.
|
|
7
|
+
"url": "https://github.com/LegendApp/legend-spark/releases/download/v0.0.1-next.4/runtimes-985164a87eb0.tgz",
|
|
8
8
|
"size": 53886,
|
|
9
|
-
"sha256": "
|
|
9
|
+
"sha256": "138644fcfaf60b172c9f206c66c6d160515dd8803c70264687d0f503294c9c0b"
|
|
10
10
|
},
|
|
11
11
|
"react-native-nitro-modules": {
|
|
12
|
-
"url": "https://github.com/LegendApp/legend-spark/releases/download/v0.0.1-next.
|
|
13
|
-
"size":
|
|
14
|
-
"sha256": "
|
|
12
|
+
"url": "https://github.com/LegendApp/legend-spark/releases/download/v0.0.1-next.4/react-native-nitro-modules-0.37.0-56a36548e4e3.tgz",
|
|
13
|
+
"size": 145386,
|
|
14
|
+
"sha256": "56a36548e4e3236d3805dc75774a1c293034318d2825580c0b86d4079cce80ae"
|
|
15
15
|
},
|
|
16
16
|
"@op-engineering/op-sqlite": {
|
|
17
|
-
"url": "https://github.com/LegendApp/legend-spark/releases/download/v0.0.1-next.
|
|
18
|
-
"size":
|
|
19
|
-
"sha256": "
|
|
17
|
+
"url": "https://github.com/LegendApp/legend-spark/releases/download/v0.0.1-next.4/op-engineering-op-sqlite-18.2.1-809aacdae6a3.tgz",
|
|
18
|
+
"size": 112508531,
|
|
19
|
+
"sha256": "809aacdae6a375f1524022533800253ee89beb931cdb5ab02781acecfa53aeac"
|
|
20
20
|
},
|
|
21
21
|
"react-native-webview": {
|
|
22
|
-
"url": "https://github.com/LegendApp/legend-spark/releases/download/v0.0.1-next.
|
|
22
|
+
"url": "https://github.com/LegendApp/legend-spark/releases/download/v0.0.1-next.4/react-native-webview-16.0.0-bc2c08eb8de7.tgz",
|
|
23
23
|
"size": 116287,
|
|
24
|
-
"sha256": "
|
|
24
|
+
"sha256": "bc2c08eb8de7b979d90a641ce63b3241c034f836c76c77b794716473b3b43216"
|
|
25
25
|
},
|
|
26
26
|
"expo-audio": {
|
|
27
|
-
"url": "https://github.com/LegendApp/legend-spark/releases/download/v0.0.1-next.
|
|
28
|
-
"size":
|
|
29
|
-
"sha256": "
|
|
27
|
+
"url": "https://github.com/LegendApp/legend-spark/releases/download/v0.0.1-next.4/expo-audio-1.1.1-c4ae56565c36.tgz",
|
|
28
|
+
"size": 381084,
|
|
29
|
+
"sha256": "c4ae56565c365086e134ab9edd15ce981a2149bda07d9e9553e151def5fe7fec"
|
|
30
30
|
}
|
|
31
31
|
},
|
|
32
32
|
"runners": {
|
|
33
33
|
"macos-arm64": {
|
|
34
|
-
"url": "https://github.com/LegendApp/legend-spark/releases/download/v0.0.1-next.
|
|
35
|
-
"size":
|
|
36
|
-
"sha256": "
|
|
34
|
+
"url": "https://github.com/LegendApp/legend-spark/releases/download/v0.0.1-next.4/spark-runner-macos-arm64.zip",
|
|
35
|
+
"size": 17395353,
|
|
36
|
+
"sha256": "6334c66020c8ddd0ff3f6c154b8fb97e01ceb952a26254765b816bd6055dabb1",
|
|
37
37
|
"app": "SparkRunner.app",
|
|
38
38
|
"teamId": "56DD97VT22",
|
|
39
|
-
"fingerprint": "
|
|
39
|
+
"fingerprint": "64932dc5718a49253e5f76a9ae26c3553059893b1e0c6dcff7b05f86c2c787e2"
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
}
|
|
@@ -2,13 +2,14 @@ const fs = require("node:fs");
|
|
|
2
2
|
const { readConfig, statePath, supportedPlatforms } = require("@legendapp/spark-desktop-config/config.cjs");
|
|
3
3
|
|
|
4
4
|
exports.nativeConfig = root => {
|
|
5
|
+
const patched = require("@legendapp/spark-desktop-config/native-patches.cjs").prepareNativePatches(root);
|
|
5
6
|
const { expo } = readConfig(root);
|
|
6
7
|
const platform = expo.platforms[0];
|
|
7
8
|
const platforms = process.platform === "win32" ? {} : { windows: { npmPackageName: "react-native-windows" } };
|
|
8
9
|
// Expo autolinking and React Native codegen have separate exclusion inputs.
|
|
9
10
|
// An excluded desktop provider must not enter an iOS module registry either.
|
|
10
11
|
const excluded = (expo.autolinking?.exclude ?? []).map(name => [name, { platforms: { ios: null, macos: null, android: null, windows: null } }]);
|
|
11
|
-
if (!["macos", "windows"].includes(platform)) return { platforms, dependencies: Object.fromEntries(excluded) };
|
|
12
|
+
if (!["macos", "windows"].includes(platform)) return { platforms, dependencies: { ...patched, ...Object.fromEntries(excluded) } };
|
|
12
13
|
const file = statePath(root, "native-selection.json");
|
|
13
14
|
const selection = fs.existsSync(file) ? JSON.parse(fs.readFileSync(file, "utf8")) : { included: [], excluded: [] };
|
|
14
15
|
return { platforms, dependencies: Object.fromEntries([
|
|
@@ -1,20 +1,13 @@
|
|
|
1
|
-
import { which } from "./process.js";
|
|
1
|
+
import { which, nodeCommand } from "./process.js";
|
|
2
2
|
import { prepareWindowsGeometry } from "./windows-geometry.js";
|
|
3
3
|
import { copyHelpers } from "./helpers.js";
|
|
4
4
|
import { registerWindowsAssociations } from "./windows-associations.js";
|
|
5
5
|
import { checkExpoDesktopNode } from "./expo-node.js";
|
|
6
6
|
import { cpSync, existsSync, mkdirSync, mkdtempSync, readdirSync, renameSync, rmSync, readFileSync, writeFileSync } from "node:fs";
|
|
7
7
|
import path from "node:path";
|
|
8
|
-
import { createRequire } from "node:module";
|
|
9
8
|
import { run } from "./commands.js";
|
|
10
9
|
import { prepareConfig, nativePackages, runtimeFor, stateFile, readJson, writeJson, validateBuildModules, goConfigurationIssues, readAppConfig } from "./project.js";
|
|
11
10
|
import { assertNativePatchPreflight } from "./native-patch-preflight.js";
|
|
12
|
-
// Windows .cmd shims are shell programs; run the package's actual JS entry.
|
|
13
|
-
export function nodeCommand(root, name, bin, args = []) {
|
|
14
|
-
const req = createRequire(path.join(root, "package.json"));
|
|
15
|
-
const file = req.resolve(`${name}/package.json`), pkg = readJson(file);
|
|
16
|
-
return ["node", path.resolve(path.dirname(file), typeof pkg.bin === "string" ? pkg.bin : pkg.bin[bin]), ...args];
|
|
17
|
-
}
|
|
18
11
|
export async function preserveWindowsBuildOutputs(root, prepare) {
|
|
19
12
|
const windows = path.join(root, "windows");
|
|
20
13
|
const outputs = [];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@legendapp/spark-cli",
|
|
3
|
-
"version": "0.0.1-next.
|
|
3
|
+
"version": "0.0.1-next.4",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -11,13 +11,13 @@
|
|
|
11
11
|
"node": ">=24.19.0"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@legendapp/spark-desktop-config": "0.0.1-next.
|
|
14
|
+
"@legendapp/spark-desktop-config": "0.0.1-next.4",
|
|
15
15
|
"ws": "8.21.0",
|
|
16
16
|
"expo-desktop": "1.0.0",
|
|
17
17
|
"npm": "11.21.0",
|
|
18
18
|
"typescript": "5.9.3",
|
|
19
19
|
"cross-spawn": "7.0.6",
|
|
20
|
-
"@legendapp/spark-window-options": "0.0.1-next.
|
|
20
|
+
"@legendapp/spark-window-options": "0.0.1-next.4"
|
|
21
21
|
},
|
|
22
22
|
"private": true
|
|
23
23
|
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"postinstall": "node node_modules/@legendapp/spark/init-template.cjs"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@legendapp/spark": "0.0.1-next.
|
|
16
|
+
"@legendapp/spark": "0.0.1-next.4",
|
|
17
17
|
"expo": "54.0.37",
|
|
18
18
|
"expo-desktop": "1.0.0",
|
|
19
19
|
"expo-desktop-prebuild-config": "1.1.0",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"overrides": {
|
|
32
32
|
"@expo/cli": "54.0.27",
|
|
33
|
-
"react-native-nitro-modules": "0.
|
|
33
|
+
"react-native-nitro-modules": "0.37.0",
|
|
34
34
|
"react-native-webview": "16.0.0",
|
|
35
35
|
"@op-engineering/op-sqlite": "18.2.1",
|
|
36
36
|
"expo-asset": "12.0.13",
|
|
@@ -41,11 +41,11 @@
|
|
|
41
41
|
"react-native-web": "0.21.0",
|
|
42
42
|
"uniwind": "1.6.3",
|
|
43
43
|
"tailwindcss": "4.2.4",
|
|
44
|
-
"@legendapp/spark": "0.0.1-next.
|
|
44
|
+
"@legendapp/spark": "0.0.1-next.4"
|
|
45
45
|
},
|
|
46
46
|
"overrides": {
|
|
47
47
|
"@expo/cli": "54.0.27",
|
|
48
|
-
"react-native-nitro-modules": "0.
|
|
48
|
+
"react-native-nitro-modules": "0.37.0",
|
|
49
49
|
"react-native-webview": "16.0.0",
|
|
50
50
|
"@op-engineering/op-sqlite": "18.2.1",
|
|
51
51
|
"expo-asset": "12.0.13",
|
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
"react-native-windows": "0.81.35",
|
|
28
28
|
"expo-desktop-modules-core": "54.0.14",
|
|
29
29
|
"expo-desktop-stubs": "54.0.14",
|
|
30
|
-
"@legendapp/spark": "0.0.1-next.
|
|
30
|
+
"@legendapp/spark": "0.0.1-next.4"
|
|
31
31
|
},
|
|
32
32
|
"overrides": {
|
|
33
33
|
"@expo/cli": "54.0.27",
|
|
34
|
-
"react-native-nitro-modules": "0.
|
|
34
|
+
"react-native-nitro-modules": "0.37.0",
|
|
35
35
|
"react-native-webview": "16.0.0",
|
|
36
36
|
"@op-engineering/op-sqlite": "18.2.1",
|
|
37
37
|
"expo-asset": "12.0.13",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@legendapp/spark-clipboard",
|
|
3
|
-
"version": "0.0.1-next.
|
|
3
|
+
"version": "0.0.1-next.4",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "src/index",
|
|
6
6
|
"react-native": "src/index",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
]
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@legendapp/spark-desktop-app": "0.0.1-next.
|
|
44
|
+
"@legendapp/spark-desktop-app": "0.0.1-next.4"
|
|
45
45
|
},
|
|
46
46
|
"peerDependenciesMeta": {
|
|
47
47
|
"expo-clipboard": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@legendapp/spark-codex",
|
|
3
|
-
"version": "0.0.1-next.
|
|
3
|
+
"version": "0.0.1-next.4",
|
|
4
4
|
"private": true,
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"react-native": "src/index.ts",
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
},
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@legendapp/spark-desktop-app": "0.0.1-next.
|
|
14
|
-
"react-native-nitro-modules": "0.
|
|
13
|
+
"@legendapp/spark-desktop-app": "0.0.1-next.4",
|
|
14
|
+
"react-native-nitro-modules": "0.37.0"
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
17
|
"src",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@legendapp/spark-commands",
|
|
3
|
-
"version": "0.0.1-next.
|
|
3
|
+
"version": "0.0.1-next.4",
|
|
4
4
|
"private": true,
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "src/index.tsx",
|
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
"src"
|
|
9
9
|
],
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@legendapp/spark-ui": "0.0.1-next.
|
|
12
|
-
"@legendapp/spark-desktop-shortcuts": "0.0.1-next.
|
|
13
|
-
"@legendapp/spark-settings": "0.0.1-next.
|
|
11
|
+
"@legendapp/spark-ui": "0.0.1-next.4",
|
|
12
|
+
"@legendapp/spark-desktop-shortcuts": "0.0.1-next.4",
|
|
13
|
+
"@legendapp/spark-settings": "0.0.1-next.4",
|
|
14
14
|
"@legendapp/state": "^3.0.0-beta.42",
|
|
15
|
-
"@legendapp/spark-desktop-app": "0.0.1-next.
|
|
15
|
+
"@legendapp/spark-desktop-app": "0.0.1-next.4"
|
|
16
16
|
},
|
|
17
17
|
"peerDependencies": {
|
|
18
18
|
"react": "19.1.4",
|