@mirinjs/cli 0.1.0-alpha.15 → 0.1.0-alpha.17

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mirinjs/cli",
3
- "version": "0.1.0-alpha.15",
3
+ "version": "0.1.0-alpha.17",
4
4
  "description": "CLI for mirin apps: dev, build, init.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -27,13 +27,15 @@
27
27
  "bun": ">=1.2.0"
28
28
  },
29
29
  "dependencies": {
30
- "create-mirinjs": "0.1.0-alpha.15",
31
- "mirinjs": "0.1.0-alpha.15"
30
+ "create-mirinjs": "0.1.0-alpha.17",
31
+ "mirinjs": "0.1.0-alpha.17"
32
32
  },
33
33
  "optionalDependencies": {
34
- "@mirinjs/darwin-arm64": "0.1.0-alpha.15",
35
- "@mirinjs/win32-x64": "0.1.0-alpha.15",
36
- "@mirinjs/linux-x64": "0.1.0-alpha.15"
34
+ "@mirinjs/darwin-arm64": "0.1.0-alpha.17",
35
+ "@mirinjs/win32-x64": "0.1.0-alpha.17",
36
+ "@mirinjs/win32-arm64": "0.1.0-alpha.17",
37
+ "@mirinjs/linux-arm64": "0.1.0-alpha.17",
38
+ "@mirinjs/linux-x64": "0.1.0-alpha.17"
37
39
  },
38
40
  "publishConfig": {
39
41
  "access": "public"
package/src/artifacts.ts CHANGED
@@ -9,7 +9,7 @@
9
9
  * entry from the `mirin` package, and a CEF framework downloaded once from
10
10
  * the matching GitHub Release into `~/.mirinjs/cef/<version>`. No Rust needed.
11
11
  *
12
- * Alpha supports macOS arm64, Windows x64, and Linux x64.
12
+ * Alpha supports macOS arm64, Windows x64/arm64, and Linux x64/arm64.
13
13
  */
14
14
 
15
15
  import {
@@ -35,6 +35,8 @@ const IN_REPO = existsSync(join(REPO_ROOT, "crates", "mirin-core"));
35
35
  export interface Artifacts {
36
36
  /** libmirin_core.dylib — dlopened by the host. */
37
37
  coreDylib: string;
38
+ /** Standalone updater codec used by `mirin release`. */
39
+ codecBin: string;
38
40
  /** mirin-helper — the CEF subprocess binary. */
39
41
  helperBin: string;
40
42
  /** host entry (TS/JS) compiled with `bun build --compile`. */
@@ -53,12 +55,13 @@ export async function resolveArtifacts(opts: { release: boolean }): Promise<Arti
53
55
 
54
56
  if (IN_REPO) {
55
57
  const profile = opts.release ? "release" : "debug";
56
- console.log(`[mirin] building native core + helper (${profile})…`);
58
+ console.log(`[mirin] building native core + helpers (${profile})…`);
57
59
  const flags = opts.release ? ["--release"] : [];
58
- await $`cargo build -p mirin-core -p mirin-helper ${flags}`.cwd(REPO_ROOT);
60
+ await $`cargo build -p mirin-codec -p mirin-core -p mirin-helper ${flags}`.cwd(REPO_ROOT);
59
61
  const target = join(REPO_ROOT, "target", profile);
60
62
  return {
61
63
  coreDylib: join(target, coreFileName()),
64
+ codecBin: join(target, codecFileName()),
62
65
  helperBin: join(target, helperFileName()),
63
66
  hostEntry: join(REPO_ROOT, "packages", "mirin", "src", "host.ts"),
64
67
  cefPath,
@@ -68,6 +71,7 @@ export async function resolveArtifacts(opts: { release: boolean }): Promise<Arti
68
71
  const nativeDir = resolveNativeDir();
69
72
  return {
70
73
  coreDylib: join(nativeDir, coreFileName()),
74
+ codecBin: join(nativeDir, codecFileName()),
71
75
  helperBin: join(nativeDir, helperFileName()),
72
76
  hostEntry: resolvePackageFile("mirinjs/host"),
73
77
  cefPath,
@@ -86,14 +90,18 @@ function helperFileName(): string {
86
90
  return process.platform === "win32" ? "mirin-helper.exe" : "mirin-helper";
87
91
  }
88
92
 
93
+ function codecFileName(): string {
94
+ return process.platform === "win32" ? "mirin-codec.exe" : "mirin-codec";
95
+ }
96
+
89
97
  function assertSupportedPlatform(): void {
90
98
  const supported =
91
99
  (process.platform === "darwin" && process.arch === "arm64") ||
92
- (process.platform === "win32" && process.arch === "x64") ||
93
- (process.platform === "linux" && process.arch === "x64");
100
+ (process.platform === "win32" && (process.arch === "x64" || process.arch === "arm64")) ||
101
+ (process.platform === "linux" && (process.arch === "x64" || process.arch === "arm64"));
94
102
  if (!supported) {
95
103
  throw new Error(
96
- "mirin alpha supports macOS arm64, Windows x64, and Linux x64 " +
104
+ "mirin alpha supports macOS arm64, Windows x64/arm64, and Linux x64/arm64 " +
97
105
  `(got ${process.platform}/${process.arch}).`,
98
106
  );
99
107
  }
package/src/build.ts CHANGED
@@ -121,8 +121,12 @@ export interface BuildResult {
121
121
  channel: string;
122
122
  /** Update baseUrl, if `release` is configured. */
123
123
  baseUrl?: string;
124
+ /** Markdown release notes embedded in the updater manifest, if configured. */
125
+ releaseNotes?: string;
124
126
  /** libmirin_core path (for the updater codec at release time). */
125
127
  coreDylib: string;
128
+ /** Standalone updater codec executable used at release time. */
129
+ codecBin: string;
126
130
  /** Project root (so `mirin release` can resolve relative asset paths). */
127
131
  projectDir: string;
128
132
  /** DMG config from mirin.config.ts (`true`/object/`false`); default `true`. */
@@ -183,6 +187,7 @@ export async function build(
183
187
  const version = opts.version ?? appVersion(projectDir);
184
188
  const channel: string = config.release?.channel ?? "stable";
185
189
  const baseUrl: string | undefined = config.release?.baseUrl;
190
+ const releaseNotes: string | undefined = config.release?.notes;
186
191
  const dmg: boolean | import("mirinjs").DmgConfig = config.dmg ?? true;
187
192
  const nsis: boolean | import("mirinjs").NsisConfig = config.nsis ?? true;
188
193
  const inno: boolean | import("mirinjs").InnoConfig = config.inno ?? true;
@@ -320,7 +325,9 @@ export async function build(
320
325
  version,
321
326
  channel,
322
327
  baseUrl,
328
+ releaseNotes,
323
329
  coreDylib: artifacts.coreDylib,
330
+ codecBin: artifacts.codecBin,
324
331
  projectDir,
325
332
  dmg,
326
333
  nsis,
@@ -137,7 +137,7 @@ async function buildFpm(
137
137
  kind: "deb" | "rpm",
138
138
  ): Promise<LinuxPackageResult> {
139
139
  const fpm = resolveFpm();
140
- const arch = kind === "deb" ? "amd64" : "x86_64";
140
+ const arch = linuxPackageArch(kind);
141
141
  const fileName =
142
142
  kind === "deb"
143
143
  ? `${binName}_${input.version}_${arch}.deb`
@@ -242,7 +242,8 @@ async function buildAppImage(
242
242
  stageHicolorIcon(appDirRoot, input);
243
243
  }
244
244
 
245
- const fileName = `${input.appName}-${input.version}-x86_64.AppImage`;
245
+ const arch = linuxPackageArch("appimage");
246
+ const fileName = `${input.appName}-${input.version}-${arch}.AppImage`;
246
247
  const out = join(input.outDir, fileName);
247
248
  rmSync(out, { force: true });
248
249
 
@@ -250,7 +251,7 @@ async function buildAppImage(
250
251
  // --appimage-extract-and-run: run appimagetool without FUSE. ARCH is required by
251
252
  // appimagetool; NO_STRIP avoids stripping the Bun-compiled host (which would break it).
252
253
  const res = await $`${appimagetool} --appimage-extract-and-run ${appDirRoot} ${out}`
253
- .env({ ...process.env, ARCH: "x86_64", NO_STRIP: "1" })
254
+ .env({ ...process.env, ARCH: arch, NO_STRIP: "1" })
254
255
  .nothrow()
255
256
  .quiet();
256
257
  rmSync(appDirRoot, { recursive: true, force: true });
@@ -261,6 +262,13 @@ async function buildAppImage(
261
262
  return { format: "appimage", path: out, size: size(out) };
262
263
  }
263
264
 
265
+ function linuxPackageArch(kind: "appimage" | "deb" | "rpm"): string {
266
+ if (process.arch === "arm64") {
267
+ return kind === "deb" ? "arm64" : "aarch64";
268
+ }
269
+ return kind === "deb" ? "amd64" : "x86_64";
270
+ }
271
+
264
272
  /** Resolve the effective set of formats from config + an optional CLI/caller override. */
265
273
  export function resolveLinuxFormats(
266
274
  linux: boolean | LinuxConfig | undefined,
package/src/release.ts CHANGED
@@ -20,7 +20,6 @@ import { existsSync, mkdirSync, mkdtempSync, rmSync, statSync } from "node:fs";
20
20
  import { tmpdir } from "node:os";
21
21
  import { join } from "node:path";
22
22
  import { $ } from "bun";
23
- import { loadCodec } from "mirinjs/codec";
24
23
  import { build } from "./build.ts";
25
24
  import { notarizeAndStaple } from "./dmg.ts";
26
25
  import { buildReleaseInstaller } from "./release/installers.ts";
@@ -35,6 +34,37 @@ import {
35
34
  // The native codec uses multiple workers, so this scales across CI runner cores.
36
35
  const RELEASE_COMPRESSION_LEVEL = 10;
37
36
 
37
+ interface ReleaseCodec {
38
+ compress(src: string, dst: string, level: number): void;
39
+ decompress(src: string, dst: string): void;
40
+ diff(oldPath: string, newPath: string, patchPath: string): void;
41
+ }
42
+
43
+ export function createReleaseCodec(binary: string): ReleaseCodec {
44
+ const run = (operation: string, ...args: string[]) => {
45
+ const result = Bun.spawnSync({
46
+ cmd: [binary, operation, ...args],
47
+ stdout: "inherit",
48
+ stderr: "pipe",
49
+ });
50
+ if (result.exitCode !== 0) {
51
+ const detail = new TextDecoder().decode(result.stderr).trim();
52
+ throw new Error(`codec ${operation} failed${detail ? `: ${detail}` : ""}`);
53
+ }
54
+ };
55
+ return {
56
+ compress(src, dst, level) {
57
+ run("compress", src, dst, String(level));
58
+ },
59
+ decompress(src, dst) {
60
+ run("decompress", src, dst);
61
+ },
62
+ diff(oldPath, newPath, patchPath) {
63
+ run("diff", oldPath, newPath, patchPath);
64
+ },
65
+ };
66
+ }
67
+
38
68
  async function sha256File(path: string): Promise<string> {
39
69
  const hasher = new Bun.CryptoHasher("sha256");
40
70
  for await (const chunk of Bun.file(path).stream()) {
@@ -83,20 +113,10 @@ export async function release(projectDir = process.cwd()): Promise<number> {
83
113
  isLinux,
84
114
  });
85
115
 
86
- // Load the codec (zstd/bsdiff) from the *bundled* core, not the raw build output:
87
- // on Windows mirin_core.dll imports libcef.dll. The DLL loader resolves imports
88
- // from PATH (and the loader exe's dir), not the dll's own dir, so prepend the
89
- // bundle dir to PATH so libcef.dll is found. On Linux libmirin_core.so has a
90
- // NEEDED libcef.so (RUNPATH $ORIGIN), so load the *bundled* .so where libcef.so
91
- // sits beside it — the raw native package has no libcef.so and dlopen fails.
92
- // (On macOS the framework loads at runtime, so result.coreDylib works directly.)
93
- const codecCore = isWindows
94
- ? join(result.app, "mirin_core.dll")
95
- : isLinux
96
- ? join(result.app, "libmirin_core.so")
97
- : result.coreDylib;
98
- if (isWindows) process.env.PATH = `${result.app};${process.env.PATH ?? ""}`;
99
- const codec = loadCodec(codecCore);
116
+ // Release tooling runs in plain Bun, including Windows arm64 builds where
117
+ // bun:ffi is unavailable. The standalone helper also avoids loading CEF merely
118
+ // to compress updater artifacts.
119
+ const codec = createReleaseCodec(result.codecBin);
100
120
 
101
121
  // Uncompressed tar — the identity + diff/patch basis (BSD tar keeps symlinks).
102
122
  const newTar = join(outDir, "_new.tar");
@@ -166,6 +186,7 @@ export async function release(projectDir = process.cwd()): Promise<number> {
166
186
  channel: result.channel,
167
187
  platform,
168
188
  arch,
189
+ body: result.releaseNotes,
169
190
  tarHash,
170
191
  bundle: { url: bundleName, sha256: bundleSha, size: bundleSize },
171
192
  patches,