Skip to content

Commit c916d11

Browse files
authored
Merge pull request #62 from tyulyukov/marcode/port-upstream-shell-typescript-ci
feat(desktop,build)!: adopt node-native typescript and add windows arm64 support
2 parents 8940163 + fd5ec16 commit c916d11

193 files changed

Lines changed: 6318 additions & 2339 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.devcontainer/devcontainer.json

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,22 @@
22
"name": "MarCode Dev",
33
"image": "debian:bookworm",
44
"features": {
5-
"ghcr.io/devcontainers-extra/features/bun:1": {},
5+
"ghcr.io/devcontainers/features/git:1": {},
6+
"ghcr.io/devcontainers-extra/features/bun:1": {
7+
"version": "1.3.11"
8+
},
69
"ghcr.io/devcontainers/features/node:1": {
7-
"version": "24",
8-
"nodeGypDependencies": true
10+
"version": "24.13.1"
911
},
1012
"ghcr.io/devcontainers/features/python:1": {
11-
"version": "3.12"
13+
"version": "3.10",
14+
"installTools": false
1215
}
1316
},
17+
"overrideFeatureInstallOrder": [
18+
"ghcr.io/devcontainers/features/git",
19+
"ghcr.io/devcontainers-extra/features/bun"
20+
],
1421
"postCreateCommand": {
1522
"bun-install": "bun install --backend=copyfile --frozen-lockfile"
1623
},

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ jobs:
7171

7272
- name: Verify preload bundle output
7373
run: |
74-
test -f apps/desktop/dist-electron/preload.js
75-
grep -nE "desktopBridge|getLocalEnvironmentBootstrap|PICK_FOLDER_CHANNEL|wsUrl" apps/desktop/dist-electron/preload.js
74+
test -f apps/desktop/dist-electron/preload.cjs
75+
grep -nE "desktopBridge|getLocalEnvironmentBootstrap|PICK_FOLDER_CHANNEL|wsUrl" apps/desktop/dist-electron/preload.cjs
7676
7777
release_smoke:
7878
name: Release Smoke

.github/workflows/release.yml

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ jobs:
107107
platform: win
108108
target: nsis
109109
arch: x64
110+
- label: Windows arm64
111+
runner: windows-11-arm
112+
platform: win
113+
target: nsis
114+
arch: arm64
110115
steps:
111116
- name: Checkout
112117
uses: actions/checkout@v6
@@ -220,6 +225,17 @@ jobs:
220225
fi
221226
fi
222227
228+
# Windows updater metadata is channel-specific (for example
229+
# "latest.yml" or "nightly.yml"). Suffix each per-arch copy so the
230+
# release job can merge matching arm64/x64 manifests back into one
231+
# canonical manifest per channel.
232+
if [[ "${{ matrix.platform }}" == "win" ]]; then
233+
shopt -s nullglob
234+
for manifest in release-publish/*.yml; do
235+
mv "$manifest" "${manifest%.yml}-win-${{ matrix.arch }}.yml"
236+
done
237+
fi
238+
223239
- name: Upload build artifacts
224240
uses: actions/upload-artifact@v7
225241
with:
@@ -295,10 +311,39 @@ jobs:
295311

296312
- name: Merge macOS updater manifests
297313
run: |
298-
node scripts/merge-mac-update-manifests.ts \
299-
release-assets/latest-mac.yml \
300-
release-assets/latest-mac-x64.yml
301-
rm -f release-assets/latest-mac-x64.yml
314+
shopt -s nullglob
315+
for x64_manifest in release-assets/*-mac-x64.yml; do
316+
arm64_manifest="${x64_manifest%-x64.yml}.yml"
317+
if [[ -f "$arm64_manifest" ]]; then
318+
node scripts/merge-update-manifests.ts --platform mac "$arm64_manifest" "$x64_manifest"
319+
rm -f "$x64_manifest"
320+
fi
321+
done
322+
323+
- name: Merge Windows updater manifests
324+
run: |
325+
shopt -s nullglob
326+
found_windows_manifest=false
327+
for x64_manifest in release-assets/*-win-x64.yml; do
328+
arm64_manifest="${x64_manifest/-x64.yml/-arm64.yml}"
329+
output_manifest="${x64_manifest/-win-x64.yml/.yml}"
330+
if [[ ! -f "$arm64_manifest" ]]; then
331+
echo "Missing matching arm64 Windows manifest for $x64_manifest" >&2
332+
exit 1
333+
fi
334+
335+
found_windows_manifest=true
336+
node scripts/merge-update-manifests.ts --platform win \
337+
"$arm64_manifest" \
338+
"$x64_manifest" \
339+
"$output_manifest"
340+
rm -f "$arm64_manifest" "$x64_manifest"
341+
done
342+
343+
if [[ "$found_windows_manifest" != true ]]; then
344+
echo "No Windows updater manifests found to merge." >&2
345+
exit 1
346+
fi
302347
303348
- name: Publish release
304349
uses: softprops/action-gh-release@v2

.oxfmtrc.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,13 @@
1212
"apps/web/public/mockServiceWorker.js",
1313
"apps/web/src/lib/vendor/qrcodegen.ts"
1414
],
15-
"sortPackageJson": {}
15+
"sortPackageJson": {},
16+
"overrides": [
17+
{
18+
"files": [".devcontainer/devcontainer.json"],
19+
"options": {
20+
"trailingComma": "none"
21+
}
22+
}
23+
]
1624
}

.vscode/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55
"source.fixAll.oxc": "always"
66
},
77
"oxc.unusedDisableDirectives": "warn",
8-
"typescript.tsdk": "node_modules/typescript/lib"
8+
"js/ts.tsdk.path": "node_modules/typescript/lib"
99
}

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
AGENTS.md
1+
AGENTS.md

apps/desktop/package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22
"name": "@marcode/desktop",
33
"version": "1.3.2",
44
"private": true,
5-
"main": "dist-electron/main.js",
5+
"type": "module",
6+
"main": "dist-electron/main.cjs",
67
"scripts": {
78
"dev": "bun run --parallel dev:bundle dev:electron",
89
"dev:bundle": "tsdown --watch",
9-
"dev:electron": "bun run scripts/dev-electron.mjs",
10+
"dev:electron": "node scripts/dev-electron.mjs",
1011
"build": "tsdown",
11-
"start": "bun run scripts/start-electron.mjs",
12+
"start": "node scripts/start-electron.mjs",
1213
"typecheck": "tsc --noEmit",
1314
"test": "vitest run --passWithNoTests",
1415
"smoke-test": "node scripts/smoke-test.mjs"

apps/desktop/scripts/dev-electron.mjs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ if (!Number.isInteger(port) || port <= 0) {
1717
}
1818

1919
const requiredFiles = [
20-
"dist-electron/main.js",
21-
"dist-electron/preload.js",
20+
"dist-electron/main.cjs",
21+
"dist-electron/preload.cjs",
2222
"../server/dist/bin.mjs",
2323
];
2424
const watchedDirectories = [
25-
{ directory: "dist-electron", files: new Set(["main.js", "preload.js"]) },
25+
{ directory: "dist-electron", files: new Set(["main.cjs", "preload.cjs"]) },
2626
{ directory: "../server/dist", files: new Set(["bin.mjs"]) },
2727
];
2828
const forcedShutdownTimeoutMs = 1_500;
@@ -69,7 +69,7 @@ function startApp() {
6969

7070
const app = spawn(
7171
resolveElectronPath(),
72-
[`--marcode-dev-root=${desktopDir}`, "dist-electron/main.js"],
72+
[`--marcode-dev-root=${desktopDir}`, "dist-electron/main.cjs"],
7373
{
7474
cwd: desktopDir,
7575
env: childEnv,

apps/desktop/scripts/electron-launcher.mjs

Lines changed: 7 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {
77
existsSync,
88
mkdirSync,
99
readFileSync,
10-
readdirSync,
1110
rmSync,
1211
statSync,
1312
writeFileSync,
@@ -19,7 +18,7 @@ import { fileURLToPath } from "node:url";
1918
const isDevelopment = Boolean(process.env.VITE_DEV_SERVER_URL);
2019
const APP_DISPLAY_NAME = isDevelopment ? "MarCode (Dev)" : "MarCode (Alpha)";
2120
const APP_BUNDLE_ID = isDevelopment ? "com.marcode.marcode.dev" : "com.marcode.marcode";
22-
const LAUNCHER_VERSION = 1;
21+
const LAUNCHER_VERSION = 2;
2322

2423
const __dirname = dirname(fileURLToPath(import.meta.url));
2524
export const desktopDir = resolve(__dirname, "..");
@@ -55,40 +54,6 @@ function patchMainBundleInfoPlist(appBundlePath, iconPath) {
5554
copyFileSync(iconPath, join(resourcesDir, "electron.icns"));
5655
}
5756

58-
function patchHelperBundleInfoPlists(appBundlePath) {
59-
const frameworksDir = join(appBundlePath, "Contents", "Frameworks");
60-
if (!existsSync(frameworksDir)) {
61-
return;
62-
}
63-
64-
for (const entry of readdirSync(frameworksDir, { withFileTypes: true })) {
65-
if (!entry.isDirectory() || !entry.name.endsWith(".app")) {
66-
continue;
67-
}
68-
if (!entry.name.startsWith("Electron Helper")) {
69-
continue;
70-
}
71-
72-
const helperPlistPath = join(frameworksDir, entry.name, "Contents", "Info.plist");
73-
if (!existsSync(helperPlistPath)) {
74-
continue;
75-
}
76-
77-
const suffix = entry.name.replace("Electron Helper", "").replace(".app", "").trim();
78-
const helperName = suffix
79-
? `${APP_DISPLAY_NAME} Helper ${suffix}`
80-
: `${APP_DISPLAY_NAME} Helper`;
81-
const helperIdSuffix = suffix.replace(/[()]/g, "").trim().toLowerCase().replace(/\s+/g, "-");
82-
const helperBundleId = helperIdSuffix
83-
? `${APP_BUNDLE_ID}.helper.${helperIdSuffix}`
84-
: `${APP_BUNDLE_ID}.helper`;
85-
86-
setPlistString(helperPlistPath, "CFBundleDisplayName", helperName);
87-
setPlistString(helperPlistPath, "CFBundleName", helperName);
88-
setPlistString(helperPlistPath, "CFBundleIdentifier", helperBundleId);
89-
}
90-
}
91-
9257
function readJson(path) {
9358
try {
9459
return JSON.parse(readFileSync(path, "utf8"));
@@ -126,7 +91,6 @@ function buildMacLauncher(electronBinaryPath) {
12691
rmSync(targetAppBundlePath, { recursive: true, force: true });
12792
cpSync(sourceAppBundlePath, targetAppBundlePath, { recursive: true });
12893
patchMainBundleInfoPlist(targetAppBundlePath, iconPath);
129-
patchHelperBundleInfoPlists(targetAppBundlePath);
13094
writeFileSync(metadataPath, `${JSON.stringify(expectedMetadata, null, 2)}\n`);
13195

13296
return targetBinaryPath;
@@ -140,5 +104,11 @@ export function resolveElectronPath() {
140104
return electronBinaryPath;
141105
}
142106

107+
// Dev launches do not need a renamed app bundle badly enough to risk breaking
108+
// Electron helper resource lookup on macOS.
109+
if (isDevelopment) {
110+
return electronBinaryPath;
111+
}
112+
143113
return buildMacLauncher(electronBinaryPath);
144114
}

apps/desktop/scripts/smoke-test.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { fileURLToPath } from "node:url";
55
const __dirname = dirname(fileURLToPath(import.meta.url));
66
const desktopDir = resolve(__dirname, "..");
77
const electronBin = resolve(desktopDir, "node_modules/.bin/electron");
8-
const mainJs = resolve(desktopDir, "dist-electron/main.js");
8+
const mainJs = resolve(desktopDir, "dist-electron/main.cjs");
99

1010
console.log("\nLaunching Electron smoke test...");
1111

0 commit comments

Comments
 (0)