cross-packer 0.1.0

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.
Files changed (126) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +151 -0
  3. package/README.zh-CN.md +151 -0
  4. package/dist/archive/ar.d.ts +12 -0
  5. package/dist/archive/seven-za.d.ts +32 -0
  6. package/dist/archive/tar.d.ts +30 -0
  7. package/dist/archive/zip-reader.d.ts +17 -0
  8. package/dist/asar/dependency/collect.d.ts +2 -0
  9. package/dist/asar/dependency/detector.d.ts +8 -0
  10. package/dist/asar/dependency/hoister.d.ts +27 -0
  11. package/dist/asar/dependency/utils.d.ts +59 -0
  12. package/dist/asar/fileset/matcher.d.ts +12 -0
  13. package/dist/asar/fileset/platform-fileset.d.ts +36 -0
  14. package/dist/asar/fileset/transformer.d.ts +2 -0
  15. package/dist/asar/fileset/unpack-detector.d.ts +10 -0
  16. package/dist/asar/fileset/walker.d.ts +14 -0
  17. package/dist/asar/pack.d.ts +23 -0
  18. package/dist/asar/packer/app-collector.d.ts +2 -0
  19. package/dist/asar/packer/collector.d.ts +18 -0
  20. package/dist/asar/packer/concurrency.d.ts +1 -0
  21. package/dist/asar/packer/integrity.d.ts +8 -0
  22. package/dist/asar/packer/nm-collector.d.ts +7 -0
  23. package/dist/asar/packer/stream-builder.d.ts +18 -0
  24. package/dist/cli.d.ts +2 -0
  25. package/dist/config/index.d.ts +97 -0
  26. package/dist/electron/dist-zip.d.ts +18 -0
  27. package/dist/electron/download.d.ts +21 -0
  28. package/dist/index.d.ts +11 -0
  29. package/dist/packer/common/app-update-yml.d.ts +5 -0
  30. package/dist/packer/common/extra-resources.d.ts +39 -0
  31. package/dist/packer/common/staging.d.ts +3 -0
  32. package/dist/packer/common/template.d.ts +2 -0
  33. package/dist/packer/linux/linux.d.ts +2 -0
  34. package/dist/packer/mac/mac.d.ts +23 -0
  35. package/dist/packer/win/nsis.d.ts +24 -0
  36. package/dist/packer/win/resedit.d.ts +5 -0
  37. package/dist/packer/win/toolchain.d.ts +8 -0
  38. package/dist/packer/win/win.d.ts +12 -0
  39. package/dist/pipeline/pipeline.d.ts +41 -0
  40. package/dist/pipeline/targets.d.ts +28 -0
  41. package/dist/shared/hash.d.ts +2 -0
  42. package/dist/shared/logger.d.ts +39 -0
  43. package/dist/shared/platform.d.ts +26 -0
  44. package/dist/shared/types.d.ts +68 -0
  45. package/dist/update/blockmap.d.ts +13 -0
  46. package/dist/update/metadata.d.ts +20 -0
  47. package/dist/update/version.d.ts +7 -0
  48. package/package.json +71 -0
  49. package/src/archive/ar.ts +41 -0
  50. package/src/archive/seven-za.ts +160 -0
  51. package/src/archive/tar.ts +142 -0
  52. package/src/archive/zip-reader.ts +61 -0
  53. package/src/asar/dependency/collect.ts +437 -0
  54. package/src/asar/dependency/detector.ts +73 -0
  55. package/src/asar/dependency/hoister.ts +714 -0
  56. package/src/asar/dependency/utils.ts +225 -0
  57. package/src/asar/fileset/matcher.ts +101 -0
  58. package/src/asar/fileset/platform-fileset.ts +416 -0
  59. package/src/asar/fileset/transformer.ts +154 -0
  60. package/src/asar/fileset/unpack-detector.ts +38 -0
  61. package/src/asar/fileset/walker.ts +115 -0
  62. package/src/asar/pack.ts +186 -0
  63. package/src/asar/packer/app-collector.ts +74 -0
  64. package/src/asar/packer/collector.ts +134 -0
  65. package/src/asar/packer/concurrency.ts +24 -0
  66. package/src/asar/packer/integrity.ts +53 -0
  67. package/src/asar/packer/nm-collector.ts +194 -0
  68. package/src/asar/packer/stream-builder.ts +723 -0
  69. package/src/cli.ts +182 -0
  70. package/src/config/index.ts +365 -0
  71. package/src/electron/dist-zip.ts +65 -0
  72. package/src/electron/download.ts +121 -0
  73. package/src/index.ts +14 -0
  74. package/src/packer/common/app-update-yml.ts +21 -0
  75. package/src/packer/common/extra-resources.ts +83 -0
  76. package/src/packer/common/staging.ts +33 -0
  77. package/src/packer/common/template.ts +24 -0
  78. package/src/packer/linux/linux.ts +329 -0
  79. package/src/packer/mac/mac.ts +495 -0
  80. package/src/packer/win/nsis.ts +244 -0
  81. package/src/packer/win/resedit.ts +60 -0
  82. package/src/packer/win/toolchain.ts +63 -0
  83. package/src/packer/win/win.ts +421 -0
  84. package/src/pipeline/pipeline.ts +149 -0
  85. package/src/pipeline/targets.ts +67 -0
  86. package/src/shared/hash.ts +15 -0
  87. package/src/shared/logger.ts +91 -0
  88. package/src/shared/platform.ts +41 -0
  89. package/src/shared/types.ts +82 -0
  90. package/src/update/blockmap.ts +247 -0
  91. package/src/update/metadata.ts +97 -0
  92. package/src/update/version.ts +59 -0
  93. package/templates/linux/app.desktop +11 -0
  94. package/templates/linux/control +9 -0
  95. package/templates/linux/postinst +10 -0
  96. package/templates/linux/postrm +8 -0
  97. package/templates/linux/preinst +49 -0
  98. package/templates/linux/prerm +43 -0
  99. package/templates/mac/Info.plist +18 -0
  100. package/templates/mac/app-update.yml +4 -0
  101. package/templates/win/nsis/README.md +51 -0
  102. package/templates/win/nsis/THIRD-PARTY-NOTICES.md +20 -0
  103. package/templates/win/nsis/assistedInstaller.nsh +154 -0
  104. package/templates/win/nsis/assistedMessages.yml +368 -0
  105. package/templates/win/nsis/common.nsh +147 -0
  106. package/templates/win/nsis/empty-license.txt +1 -0
  107. package/templates/win/nsis/include/FileAssociation.nsh +123 -0
  108. package/templates/win/nsis/include/StdUtils.nsh +496 -0
  109. package/templates/win/nsis/include/StrContains.nsh +48 -0
  110. package/templates/win/nsis/include/UAC.nsh +299 -0
  111. package/templates/win/nsis/include/allowOnlyOneInstallerInstance.nsh +164 -0
  112. package/templates/win/nsis/include/extractAppPackage.nsh +138 -0
  113. package/templates/win/nsis/include/getProcessInfo.nsh +157 -0
  114. package/templates/win/nsis/include/installUtil.nsh +248 -0
  115. package/templates/win/nsis/include/installer.nsh +247 -0
  116. package/templates/win/nsis/include/nsProcess.nsh +28 -0
  117. package/templates/win/nsis/include/webPackage.nsh +64 -0
  118. package/templates/win/nsis/installSection.nsh +110 -0
  119. package/templates/win/nsis/installer.nsi +132 -0
  120. package/templates/win/nsis/messages.yml +240 -0
  121. package/templates/win/nsis/multiUser.nsh +134 -0
  122. package/templates/win/nsis/multiUserUi.nsh +230 -0
  123. package/templates/win/nsis/oneClick.nsh +19 -0
  124. package/templates/win/nsis/portable.nsi +91 -0
  125. package/templates/win/nsis/uninstaller.nsh +263 -0
  126. package/templates/win/nsis-header.nsh +57 -0
package/README.md ADDED
@@ -0,0 +1,151 @@
1
+ # cross-packer
2
+
3
+ [**English**](README.md) | [**简体中文**](README.zh-CN.md)
4
+
5
+ Cross-platform Electron app packager: assemble **Windows (NSIS)**, **macOS (.app/.zip)**, and **Linux (.deb)** artifacts on any host operating system, with no dependency on `electron-builder`, `app-builder-bin`, or platform-specific toolchains.
6
+
7
+ ## How It Works
8
+
9
+ `cross-packer` is a Node.js command-line tool and library that turns a built Electron app payload into distributable artifacts:
10
+
11
+ ```
12
+ cross-packer.config.mjs
13
+ │ load & normalize config
14
+
15
+ Project file collection
16
+ │ app dist + package.json + pruned production node_modules,
17
+ │ smart-unpack detection, prebuilt native module substitution
18
+
19
+ Asar archive
20
+ │ packed per-target with integrity hashes and optional unpacked dir
21
+
22
+ Platform packers (run concurrently)
23
+ ├─ Windows: NSIS installer / portable exe (auto-acquired NSIS toolchain, rcedit-style icon & metadata)
24
+ ├─ macOS: renamed .app bundle in a zip, generated Info.plist, asar integrity, electron-updater metadata
25
+ └─ Linux: .deb package from templates (control, desktop entry, maintainer scripts)
26
+
27
+ Update artifacts (optional)
28
+ latest.yml + *.blockmap, electron-updater compatible
29
+ ```
30
+
31
+ Key design points:
32
+
33
+ - **Host-OS independent**: Windows, macOS, and Linux artifacts can all be built from any host operating system; the Electron distribution for each target is downloaded on demand, and the download mirror is configurable.
34
+ - **No electron-builder**: the NSIS toolchain is acquired automatically, .deb assembly is template-driven, and Info.plist generation uses structured `plist` data instead of string templating.
35
+ - **Pluggable signing**: signing is opt-in via hooks (`sign.win` / `sign.mac`); the packer itself never signs artifacts. Reference implementations for [osslsigncode](https://github.com/mtrojnar/osslsigncode) and a customized `rcodesign` fork are provided in `examples/signing-hooks.ts`.
36
+ - **Cross-platform macOS tooling**: macOS artifacts can be signed and packaged on any host operating system; cross-platform signing uses the customized [rcodesign](https://github.com/Sg4Dylan/zip2dmg) fork, and `.dmg` images are generated with [zip2dmg](https://github.com/Sg4Dylan/zip2dmg).
37
+ - **Prebuilt native modules**: projects shipping prebuilt native modules (such as `better-sqlite3` and `@napi-rs/canvas-*`) can declare substitution rules per platform and architecture without rebuilding from source.
38
+
39
+ ## Basic Usage
40
+
41
+ Create a config file at your project root (see `examples/basic.config.ts`):
42
+
43
+ ```js
44
+ // cross-packer.config.mjs
45
+ export default {
46
+ name: 'my-app',
47
+ productName: 'My App',
48
+ appId: 'com.example.my-app',
49
+ version: '1.0.0',
50
+ author: 'Example Team',
51
+ electronVersion: '33.2.0',
52
+
53
+ files: {
54
+ appDistDir: 'dist', // built app payload, collected together with package.json
55
+ },
56
+ asarUnpack: ['**/*.node'],
57
+
58
+ mac: {
59
+ bundleName: 'MyApp',
60
+ iconFile: 'build/icon.icns',
61
+ // Extra Info.plist entries merged on top of the generated keys
62
+ // plist: { NSCameraUsageDescription: 'Camera access is required' },
63
+ // urlSchemes: ['my-app'],
64
+ },
65
+ win: { iconFile: 'build/icon.ico' },
66
+ linux: { maintainer: 'Example Team <dev@example.com>' },
67
+
68
+ update: { channel: 'latest', generateMetadata: true },
69
+ }
70
+ ```
71
+
72
+ Build artifacts:
73
+
74
+ ```bash
75
+ # Windows NSIS installer (amd64)
76
+ npx cross-packer --win
77
+
78
+ # macOS .app zip (arm64)
79
+ npx cross-packer --mac --arm64
80
+
81
+ # All platforms, both architectures
82
+ npx cross-packer --all-platforms --all-arch
83
+
84
+ # Validate config and targets without building
85
+ npx cross-packer --linux --dry-run
86
+ ```
87
+
88
+ Main options:
89
+
90
+ | Option | Description |
91
+ | :--- | :--- |
92
+ | `--win` / `--mac` / `--linux` | Target platform(s) |
93
+ | `--all-platforms` | Equivalent to `--win --mac --linux` |
94
+ | `--amd64` / `--arm64` / `--all-arch` | Target architecture(s) |
95
+ | `--arch <list>` | Comma-separated architecture list, for example `--arch amd64,arm64` |
96
+ | `--config <path>` | Config file path (`.mjs` or `.json`), default `cross-packer.config.mjs` |
97
+ | `--output <path>` | Output directory (default: `dist-<timestamp>`) |
98
+ | `--channel <name>` | Update channel override (for example, `latest` or `beta`) |
99
+ | `--sign` | Enable code signing hooks (see `config.sign`) |
100
+ | `--dry-run` | Validate config and targets without building |
101
+
102
+ The packer is also usable as a library: `runPack`, `loadConfig`, `generateUpdateMetadata`, and `buildBlockMap` are exported from the package root (see `src/index.ts`).
103
+
104
+ Programmatic API usage:
105
+
106
+ ```ts
107
+ import { loadConfig, runPack } from 'cross-packer'
108
+
109
+ const config = await loadConfig('cross-packer.config.mjs')
110
+ const result = await runPack(config, {
111
+ platforms: ['win', 'mac', 'linux'],
112
+ arches: ['amd64'],
113
+ output: 'dist-release',
114
+ })
115
+ ```
116
+
117
+ ## Dependencies
118
+
119
+ Runtime dependencies (bundled with the command-line tool):
120
+
121
+ | Component | License | Usage |
122
+ | :--- | :--- | :--- |
123
+ | [archiver](https://github.com/archiverjs/node-archiver) | MIT | Streaming ZIP assembly (macOS .app zip) |
124
+ | [jszip](https://github.com/Stuk/jszip) | MIT / Apache-2.0 | Reading Electron distribution zips |
125
+ | [tar](https://github.com/isaacs/node-tar) | ISC | Electron dist archive handling |
126
+ | [7zip-bin](https://github.com/develar/7zip-bin) | MIT | Embedded 7za binary for archive extraction |
127
+ | [plist](https://github.com/TooTallNate/plist.js) | MIT | Structured Info.plist generation and rewriting |
128
+ | [resedit](https://github.com/lemon-s/resedit) | MIT | Windows PE resource editing (icon, version info) |
129
+ | [js-yaml](https://github.com/nodeca/js-yaml) | MIT | NSIS messages and app-update.yml rendering |
130
+ | [minimatch](https://github.com/isaacs/minimatch) | ISC | Glob matching for file sets and filters |
131
+ | [@noble/hashes](https://github.com/paulmillr/noble-hashes) | MIT | SHA-256 checksums for asar integrity and blockmaps |
132
+ | [fs-extra](https://github.com/jprichardson/node-fs-extra) | MIT | File system helpers |
133
+ | [chromium-pickle-js](https://github.com/electron/node-chromium-pickle-js) | MIT | Asar header (pickle) serialization |
134
+
135
+ The Windows packer acquires the NSIS toolchain automatically (downloaded on first use and cached locally), so no manual NSIS installation is required on the build host. macOS artifacts are produced unsigned by design; signing is opt-in via the `sign.mac` hook, using either the customized [rcodesign](https://github.com/Sg4Dylan/zip2dmg) fork on any host operating system or `codesign` on macOS (reference implementations are provided in `examples/signing-hooks.ts`). To produce a `.dmg` image from the generated `.app` zip on any host operating system, use [zip2dmg](https://github.com/Sg4Dylan/zip2dmg).
136
+
137
+ ## License
138
+
139
+ ### Project License
140
+ This project is licensed under the **AGPLv3 License**; see the [LICENSE](LICENSE) file for details.
141
+
142
+ ### AI Disclosure & Disclaimer
143
+ Parts of this project are generated or optimized by AI coding tools. While the maintainers strive for quality, the AI-generated code is provided **"AS IS" without warranty of any kind**, express or implied. The authors do not guarantee the absolute accuracy, security, or reliability of the AI-contributed logic. Users are encouraged to review the source code independently. In no event shall the authors be liable for any claim, damages, or other liability arising from the use of AI-generated content.
144
+
145
+ ### Third-Party Software Notices
146
+ This project integrates or makes use of the following open-source components, with gratitude to the original authors; see the table above under **Dependencies** for the full list with licenses.
147
+
148
+ ---
149
+
150
+ Copyright (c) 2026-Present project contributors.
151
+ Licensed under the AGPLv3 License.
@@ -0,0 +1,151 @@
1
+ # cross-packer
2
+
3
+ [**English**](README.md) | [**简体中文**](README.zh-CN.md)
4
+
5
+ 跨平台 Electron 应用打包器:在任意宿主操作系统上产出 **Windows(NSIS)**、**macOS(.app/.zip)** 与 **Linux(.deb)** 产物,不依赖 `electron-builder`、`app-builder-bin` 或任何平台专属工具链。
6
+
7
+ ## 工作原理
8
+
9
+ `cross-packer` 是一个 Node.js 命令行工具与程序库,可将构建完成的 Electron 应用载荷转换为可分发产物:
10
+
11
+ ```
12
+ cross-packer.config.mjs
13
+ │ 加载并归一化配置
14
+
15
+ 项目文件收集
16
+ │ 应用构建产物、package.json 与裁剪后的生产依赖 node_modules,
17
+ │ 智能 unpack 检测、预构建原生模块替换
18
+
19
+ Asar 归档
20
+ │ 按目标平台打包,附带完整性哈希与可选的 unpacked 目录
21
+
22
+ 平台打包器(并发执行)
23
+ ├─ Windows: NSIS 安装包 / 便携版 exe(自动获取 NSIS 工具链,rcedit 风格的图标与元数据)
24
+ ├─ macOS: 重命名后的 .app bundle(zip 格式)、生成的 Info.plist、asar 完整性、electron-updater 元数据
25
+ └─ Linux: 基于模板(control、desktop 入口、维护者脚本)组装的 .deb 包
26
+
27
+ 更新产物(可选)
28
+ latest.yml + *.blockmap,兼容 electron-updater
29
+ ```
30
+
31
+ 关键设计点:
32
+
33
+ - **宿主操作系统无关**:Windows、macOS、Linux 产物均可在任意宿主操作系统上构建;各目标的 Electron 发行版按需下载,下载镜像可配置。
34
+ - **不依赖 electron-builder**:NSIS 工具链自动获取,.deb 组装由模板驱动,Info.plist 生成基于结构化 `plist` 数据而非字符串模板。
35
+ - **可插拔签名**:签名通过钩子(`sign.win` / `sign.mac`)选配启用,打包器自身不执行签名。`examples/signing-hooks.ts` 提供了 [osslsigncode](https://github.com/mtrojnar/osslsigncode) 与定制版 `rcodesign` 分支的参考实现。
36
+ - **跨平台 macOS 工具链**:macOS 产物可在任意宿主操作系统上完成签名与镜像封装:跨平台签名使用定制版 [rcodesign](https://github.com/Sg4Dylan/zip2dmg),`.dmg` 镜像由 [zip2dmg](https://github.com/Sg4Dylan/zip2dmg) 生成。
37
+ - **预构建原生模块**:交付预构建原生模块(如 `better-sqlite3`、`@napi-rs/canvas-*`)的项目可按平台与架构声明替换规则,无需从源码重新编译。
38
+
39
+ ## 基本用法
40
+
41
+ 在项目根目录创建配置文件(参见 `examples/basic.config.ts`):
42
+
43
+ ```js
44
+ // cross-packer.config.mjs
45
+ export default {
46
+ name: 'my-app',
47
+ productName: 'My App',
48
+ appId: 'com.example.my-app',
49
+ version: '1.0.0',
50
+ author: 'Example Team',
51
+ electronVersion: '33.2.0',
52
+
53
+ files: {
54
+ appDistDir: 'dist', // 应用构建产物目录,与 package.json 共同收集
55
+ },
56
+ asarUnpack: ['**/*.node'],
57
+
58
+ mac: {
59
+ bundleName: 'MyApp',
60
+ iconFile: 'build/icon.icns',
61
+ // 额外的 Info.plist 条目,合并到生成的键之上
62
+ // plist: { NSCameraUsageDescription: '需要访问摄像头' },
63
+ // urlSchemes: ['my-app'],
64
+ },
65
+ win: { iconFile: 'build/icon.ico' },
66
+ linux: { maintainer: 'Example Team <dev@example.com>' },
67
+
68
+ update: { channel: 'latest', generateMetadata: true },
69
+ }
70
+ ```
71
+
72
+ 构建产物:
73
+
74
+ ```bash
75
+ # Windows NSIS 安装包(amd64)
76
+ npx cross-packer --win
77
+
78
+ # macOS .app zip(arm64)
79
+ npx cross-packer --mac --arm64
80
+
81
+ # 全平台、双架构
82
+ npx cross-packer --all-platforms --all-arch
83
+
84
+ # 仅校验配置与目标,不执行构建
85
+ npx cross-packer --linux --dry-run
86
+ ```
87
+
88
+ 主要选项:
89
+
90
+ | 选项 | 说明 |
91
+ | :--- | :--- |
92
+ | `--win` / `--mac` / `--linux` | 目标平台 |
93
+ | `--all-platforms` | 等价于 `--win --mac --linux` |
94
+ | `--amd64` / `--arm64` / `--all-arch` | 目标架构 |
95
+ | `--arch <list>` | 逗号分隔的架构列表,如 `--arch amd64,arm64` |
96
+ | `--config <path>` | 配置文件路径(`.mjs` 或 `.json`),默认 `cross-packer.config.mjs` |
97
+ | `--output <path>` | 输出目录(默认:`dist-<timestamp>`) |
98
+ | `--channel <name>` | 更新通道覆盖(如 `latest`、`beta`) |
99
+ | `--sign` | 启用代码签名钩子(见 `config.sign`) |
100
+ | `--dry-run` | 仅校验配置与目标,不执行构建 |
101
+
102
+ 本打包器亦可作为程序库使用:`runPack`、`loadConfig`、`generateUpdateMetadata`、`buildBlockMap` 均自包根导出(见 `src/index.ts`)。
103
+
104
+ 编程式 API 用法:
105
+
106
+ ```ts
107
+ import { loadConfig, runPack } from 'cross-packer'
108
+
109
+ const config = await loadConfig('cross-packer.config.mjs')
110
+ const result = await runPack(config, {
111
+ platforms: ['win', 'mac', 'linux'],
112
+ arches: ['amd64'],
113
+ output: 'dist-release',
114
+ })
115
+ ```
116
+
117
+ ## 依赖说明
118
+
119
+ 运行时依赖(随命令行工具一并提供):
120
+
121
+ | 组件 | 许可证 | 用途 |
122
+ | :--- | :--- | :--- |
123
+ | [archiver](https://github.com/archiverjs/node-archiver) | MIT | 流式 ZIP 组装(macOS .app zip) |
124
+ | [jszip](https://github.com/Stuk/jszip) | MIT / Apache-2.0 | 读取 Electron 发行版 zip |
125
+ | [tar](https://github.com/isaacs/node-tar) | ISC | Electron 发行版归档处理 |
126
+ | [7zip-bin](https://github.com/develar/7zip-bin) | MIT | 内嵌 7za 二进制,用于归档解压 |
127
+ | [plist](https://github.com/TooTallNate/plist.js) | MIT | 结构化 Info.plist 的生成与改写 |
128
+ | [resedit](https://github.com/lemon-s/resedit) | MIT | Windows PE 资源编辑(图标、版本信息) |
129
+ | [js-yaml](https://github.com/nodeca/js-yaml) | MIT | NSIS 消息与 app-update.yml 渲染 |
130
+ | [minimatch](https://github.com/isaacs/minimatch) | ISC | 文件集与过滤器的 glob 匹配 |
131
+ | [@noble/hashes](https://github.com/paulmillr/noble-hashes) | MIT | asar 完整性与 blockmap 的 SHA-256 校验和 |
132
+ | [fs-extra](https://github.com/jprichardson/node-fs-extra) | MIT | 文件系统辅助工具 |
133
+ | [chromium-pickle-js](https://github.com/electron/node-chromium-pickle-js) | MIT | Asar 头部(pickle)序列化 |
134
+
135
+ Windows 打包器自动获取 NSIS 工具链(首次使用时下载并缓存于本地),构建主机无需手动安装 NSIS。macOS 产物默认不签名,签名通过 `sign.mac` 钩子选配启用:可使用定制版 [rcodesign](https://github.com/Sg4Dylan/zip2dmg) 在任意宿主操作系统上完成签名,或在 macOS 上使用 `codesign`(参考实现见 `examples/signing-hooks.ts`)。如需在任意宿主操作系统上将生成的 `.app` zip 转换为 `.dmg` 镜像,请使用 [zip2dmg](https://github.com/Sg4Dylan/zip2dmg)。
136
+
137
+ ## 许可证
138
+
139
+ ### 项目许可证
140
+ 本项目基于 **AGPLv3 许可证**授权,详见 [LICENSE](LICENSE) 文件。
141
+
142
+ ### AI 披露与免责声明
143
+ 本项目的部分代码由 AI 编程工具生成或优化。维护者尽力保证质量,但 AI 生成的代码按**「原样」提供,不附带任何明示或默示的保证**。作者不保证 AI 贡献逻辑的绝对准确性、安全性或可靠性,建议用户自行审阅源代码。对于因使用 AI 生成内容而产生的任何索赔、损害或其他责任,作者概不负责。
144
+
145
+ ### 第三方软件声明
146
+ 本项目集成或使用了以下开源组件,谨向原作者致谢。完整清单及许可证见上方**「依赖说明」**表格。
147
+
148
+ ---
149
+
150
+ Copyright (c) 2026-Present 项目贡献者。
151
+ 基于 AGPLv3 许可证授权。
@@ -0,0 +1,12 @@
1
+ import { Buffer } from 'node:buffer';
2
+ export interface ArEntry {
3
+ name: string;
4
+ content: Buffer;
5
+ mode?: number;
6
+ mtime?: number;
7
+ }
8
+ /**
9
+ * Minimal `ar` archive writer, sufficient for .deb assembly
10
+ * (debian-binary + control.tar.xz + data.tar.xz).
11
+ */
12
+ export declare function createArArchive(files: ArEntry[]): Buffer;
@@ -0,0 +1,32 @@
1
+ export interface CompressOptions {
2
+ src: string;
3
+ dest: string;
4
+ format?: '7z' | 'xz';
5
+ level?: number;
6
+ threads?: number;
7
+ solid?: boolean;
8
+ sevenZipPath?: string;
9
+ }
10
+ export interface CompressResult {
11
+ level: number;
12
+ threads: number;
13
+ solid: boolean;
14
+ }
15
+ export declare function get7zaPath(): string;
16
+ /**
17
+ * Parses `7z l` output for the total uncompressed size, used for the
18
+ * NSIS ESTIMATED_SIZE define. Returns 0 when listing fails.
19
+ */
20
+ export declare function computeEstimatedSize(sevenZipPath: string, archiveFile: string): number;
21
+ export declare function compress({ src, dest, format, level, threads, solid, sevenZipPath: sevenZipPathOption, }: CompressOptions): CompressResult;
22
+ export declare function build7zaAddArgs({ src, dest, format, level, threads, solid, }: {
23
+ src: string;
24
+ dest: string;
25
+ format?: '7z' | 'xz';
26
+ level: number;
27
+ threads: number;
28
+ solid: boolean;
29
+ }): {
30
+ args: string[];
31
+ cwd: string | undefined;
32
+ };
@@ -0,0 +1,30 @@
1
+ export type TarEntry = {
2
+ type: 'dir';
3
+ path: string;
4
+ mode?: number;
5
+ } | {
6
+ type: 'file';
7
+ path: string;
8
+ mode?: number;
9
+ content?: Buffer;
10
+ filePath?: string;
11
+ getBuffer?: () => Promise<Buffer>;
12
+ } | {
13
+ type: 'link';
14
+ path: string;
15
+ mode?: number;
16
+ target?: string;
17
+ getTarget?: () => Promise<string>;
18
+ };
19
+ /** Packs entries into an uncompressed tar at destPath. */
20
+ export declare function writeTarFromEntries(entries: TarEntry[], destPath: string): Promise<void>;
21
+ export interface CollectDirectoryOptions {
22
+ includeSymlinks?: boolean;
23
+ resolveFileMode?: (input: {
24
+ filePath: string;
25
+ relativePath: string;
26
+ sourceMode: number;
27
+ }) => number | undefined | undefined;
28
+ }
29
+ /** Flattens a directory on disk into tar entries rooted at prefix. */
30
+ export declare function collectDirectoryEntries(dirPath: string, prefix: string, options?: CollectDirectoryOptions): Promise<TarEntry[]>;
@@ -0,0 +1,17 @@
1
+ import type { JSZipObject } from 'jszip';
2
+ import JSZip from 'jszip';
3
+ export interface ZipEntry {
4
+ path: string;
5
+ dir: boolean;
6
+ symlink: boolean;
7
+ mode: string | number;
8
+ entry: JSZipObject;
9
+ }
10
+ export declare function readZip(zipPath: string): Promise<{
11
+ entries: ZipEntry[];
12
+ zip: JSZip;
13
+ }>;
14
+ export declare function getEntryBuffer(entry: JSZipObject): Promise<Buffer>;
15
+ export declare function getSymlinkTarget(entry: JSZipObject): Promise<string>;
16
+ export declare function isSymlink(zipEntry: ZipEntry): boolean;
17
+ export declare function isDefaultAppEntry(entryPath: string): boolean;
@@ -0,0 +1,2 @@
1
+ import { type HoistedNodeModule } from './utils.ts';
2
+ export declare function collectProductionDeps(projectDir: string, workspaceRoot: string | undefined): Promise<HoistedNodeModule[]>;
@@ -0,0 +1,8 @@
1
+ export declare enum PackageManager {
2
+ NPM = "npm",
3
+ YARN = "yarn",
4
+ YARN_BERRY = "yarn-berry",
5
+ PNPM = "pnpm",
6
+ BUN = "bun"
7
+ }
8
+ export declare function detectPackageManager(projectDir: string): Promise<PackageManager>;
@@ -0,0 +1,27 @@
1
+ /** Input tree produced by transformToHoisterTree. */
2
+ export interface HoisterTreeNode {
3
+ name: string;
4
+ identName: string;
5
+ reference: string;
6
+ peerNames: Set<string>;
7
+ dependencies: Set<HoisterTreeNode>;
8
+ hoistPriority?: number;
9
+ dependencyKind?: number;
10
+ }
11
+ /** Immutable shrunk tree returned by hoist. */
12
+ export interface ShrunkNode {
13
+ name: string;
14
+ identName: string;
15
+ references: Set<string>;
16
+ dependencies: Set<ShrunkNode>;
17
+ }
18
+ interface HoistOptions {
19
+ debugLevel?: number;
20
+ check?: boolean;
21
+ hoistingLimits?: Map<string, Set<string>>;
22
+ }
23
+ export declare function hoist(tree: HoisterTreeNode, opts?: HoistOptions): ShrunkNode;
24
+ export declare function transformToHoisterTree(productionGraph: Record<string, {
25
+ dependencies?: string[];
26
+ }>, key: string, nodes?: Map<string, HoisterTreeNode>): HoisterTreeNode;
27
+ export {};
@@ -0,0 +1,59 @@
1
+ /** Raw dependency info extracted from a package manager's dependency graph. */
2
+ export interface RawDependencyInfo {
3
+ name: string;
4
+ version: string;
5
+ path?: string;
6
+ _dependencies?: Record<string, string>;
7
+ dependencies?: Record<string, RawDependencyInfo>;
8
+ optionalDependencies?: Record<string, RawDependencyInfo>;
9
+ }
10
+ /** Flattened dependency entry stored in allDependencies. */
11
+ export interface FlatDependency {
12
+ name: string;
13
+ version: string;
14
+ path: string;
15
+ _dependencies?: Record<string, string>;
16
+ dependencies?: Record<string, RawDependencyInfo>;
17
+ optionalDependencies?: Record<string, RawDependencyInfo>;
18
+ }
19
+ /** Node in the hoisted node_modules output tree. */
20
+ export interface HoistedNodeModule {
21
+ name: string;
22
+ version: string;
23
+ dir: string;
24
+ dependencies?: HoistedNodeModule[];
25
+ }
26
+ export declare function execCommand(command: string, args: string[], cwd?: string): Promise<{
27
+ stdout: string;
28
+ stderr: string;
29
+ error: Error | null;
30
+ }>;
31
+ /** Parse JSON from a command output, tolerating surrounding log noise. */
32
+ export declare function extractJsonFromOutput(output: string): unknown;
33
+ export declare function resolvePackageDir(nmDir: string, pkgName: string): string | null;
34
+ export declare function isProdDependency(depName: string, pkg: Pick<RawDependencyInfo, '_dependencies' | 'dependencies' | 'optionalDependencies'>): boolean;
35
+ /** Read the root package.json and derive its locator key. */
36
+ export declare function readRootPkgJson(projectDir: string): Promise<{
37
+ name: string;
38
+ version: string;
39
+ rootKey: string;
40
+ }>;
41
+ export declare function runHoistPipeline(allDependencies: Map<string, FlatDependency>, productionGraph: Record<string, {
42
+ dependencies: string[];
43
+ }>, rootKey: string): Promise<{
44
+ nodeModules: HoistedNodeModule[];
45
+ }>;
46
+ /** Detect npm's duplicated-dependency marker entries (no deps of their own). */
47
+ export declare function isDuplicatedNpmDependency(info: RawDependencyInfo | FlatDependency): boolean;
48
+ export declare function collectFromObjectTree(deps: Record<string, RawDependencyInfo> | undefined, allDependencies: Map<string, FlatDependency>): void;
49
+ export declare function extractProdGraphFromObjectTree(tree: RawDependencyInfo | undefined, dependencyId: string, productionGraph: Record<string, {
50
+ dependencies: string[];
51
+ }>, allDependencies: Map<string, FlatDependency>): void;
52
+ export declare function buildProductionGraphFromFlat(allDependencies: Map<string, FlatDependency>, productionGraph: Record<string, {
53
+ dependencies: string[];
54
+ }>, rootKey: string): void;
55
+ /** Split a "name@version" identifier into its parts. */
56
+ export declare function parseNameVersion(identifier: string): {
57
+ name: string;
58
+ version: string;
59
+ };
@@ -0,0 +1,12 @@
1
+ import type { Minimatch } from 'minimatch';
2
+ import { type FileFilter, type FileStat } from '../../shared/types.ts';
3
+ export declare const excludedNames: string;
4
+ export declare const excludedExts: string;
5
+ export declare const excludedFiles: Set<string>;
6
+ export declare const topLevelExcludedFiles: Set<string>;
7
+ export declare function hasMagic(pattern: Minimatch): boolean;
8
+ /** Ensure a path string ends with the platform separator. */
9
+ export declare function ensureEndSlash(s: string): string;
10
+ export declare function getRelativePath(file: string, srcWithEndSlash: string, stat: FileStat): string;
11
+ export declare function minimatchAll(p: string, patterns: Minimatch[], stat: FileStat): boolean;
12
+ export declare function createFilter(src: string, patterns: Minimatch[], excludePatterns?: Minimatch[] | null): FileFilter;
@@ -0,0 +1,36 @@
1
+ import { type Arch, NodePlatform } from '../../shared/platform.ts';
2
+ import { type FileSet } from '../../shared/types.ts';
3
+ /**
4
+ * A prebuilt native-module replacement rule: replace the node_modules copy
5
+ * of `moduleName` with files from `<projectDir>/<from>` in the packed fileset,
6
+ * optionally renaming the module directory.
7
+ */
8
+ export interface PrebuiltModuleRule {
9
+ /** Module name as it appears in node_modules (may be scoped). */
10
+ moduleName: string;
11
+ /** Source directory (relative to projectDir) holding the prebuilt files. */
12
+ from: string;
13
+ /**
14
+ * Rename the module directory in the packed fileset (e.g. `@napi-rs/canvas-darwin-arm64`
15
+ * → `@napi-rs/canvas-<suffix>`); omit to keep the original name.
16
+ */
17
+ renameTo?: string;
18
+ }
19
+ /**
20
+ * Resolver producing the replacement rules for a platform/arch. Returning
21
+ * undefined/null skips prebuilt replacement and node_modules copies are
22
+ * used as-is.
23
+ */
24
+ export type PrebuiltModuleRuleResolver = (platform: NodePlatform, arch: Arch) => ReadonlyArray<PrebuiltModuleRule> | null | undefined;
25
+ /**
26
+ * Install the resolver used to derive prebuilt module replacement rules.
27
+ * Hosts inject their own rules through config.nativeModules.prebuiltRules.
28
+ */
29
+ export declare function setPrebuiltDirResolver(resolver: PrebuiltModuleRuleResolver | null): void;
30
+ export declare function derivePlatformFileSet(fileSet: FileSet, platform: NodePlatform, arch: Arch, projectDir: string): FileSet;
31
+ /** Parse a file path inside node_modules into module name / subpath info. */
32
+ export declare function parseModuleInfo(filePath: string): {
33
+ moduleName: string;
34
+ moduleRootPath: string;
35
+ } | null;
36
+ export declare function isExcludedPlatformPath(filePath: string, moduleRootPath: string, targetPlatform: NodePlatform, moduleName: string): boolean;
@@ -0,0 +1,2 @@
1
+ import type { JsonObject } from '../../shared/types.ts';
2
+ export declare function createTransformer(srcDir: string, extraMetadata: JsonObject | undefined, extraTransformer?: (file: string) => Promise<string | null> | string | null): (file: string) => Promise<string | null> | string | null;
@@ -0,0 +1,10 @@
1
+ import type { FileStat } from '../../shared/types.ts';
2
+ /**
3
+ * Check whether a file is a native binary library or executable that
4
+ * should be unpacked from the asar archive by default.
5
+ */
6
+ export declare function isLibOrExe(file: string): boolean;
7
+ export declare function detectUnpackedDirs(fileSet: {
8
+ files: string[];
9
+ metadata: Map<string, FileStat>;
10
+ }, autoUnpackDirs: Set<string>): void;
@@ -0,0 +1,14 @@
1
+ import type { FileStat } from '../../shared/types.ts';
2
+ export declare function walkDirectory(dirPath: string, files: string[], metadata: Map<string, FileStat>, projectDir: string): void;
3
+ export declare function mergeFileSets(set1: {
4
+ files: string[];
5
+ metadata: Map<string, FileStat>;
6
+ }, set2: {
7
+ files: string[];
8
+ metadata: Map<string, FileStat>;
9
+ }): {
10
+ files: string[];
11
+ metadata: Map<string, FileStat>;
12
+ };
13
+ /** Derive the deepest common ancestor directory of a file list. */
14
+ export declare function deriveProjectDir(files: string[]): string;
@@ -0,0 +1,23 @@
1
+ import type { NormalizedConfig } from '../config/index.ts';
2
+ import { type Arch, Platform } from '../shared/platform.ts';
3
+ import type { FileSet } from '../shared/types.ts';
4
+ type Transformer = (file: string) => Promise<string | null> | string | null;
5
+ export declare function collectProjectFiles(projectDir: string, config: NormalizedConfig): Promise<{
6
+ appFileSet: FileSet;
7
+ nmFileSets: FileSet[];
8
+ transformer: (file: string) => Promise<string | null> | string | null;
9
+ }>;
10
+ export declare function packAsarForTarget({ platform, arch, appFileSet, nmFileSets, transformer, config, projectDir, stagingDir, }: {
11
+ platform: Platform;
12
+ arch: Arch;
13
+ appFileSet: FileSet;
14
+ nmFileSets: FileSet[];
15
+ transformer: Transformer;
16
+ config: NormalizedConfig;
17
+ projectDir: string;
18
+ stagingDir: string;
19
+ }): Promise<{
20
+ asarPath: string;
21
+ unpackedDir: string | undefined;
22
+ }>;
23
+ export {};
@@ -0,0 +1,2 @@
1
+ import { type FileSet } from '../../shared/types.ts';
2
+ export declare function collectAppFileSet(projectDir: string, distDir: string, includePdb: boolean): Promise<FileSet>;
@@ -0,0 +1,18 @@
1
+ import type { NodePlatform } from '../../shared/platform.ts';
2
+ import type { FileFilter, FileSet, FileVisitor } from '../../shared/types.ts';
3
+ export interface CollectAllFilesOptions {
4
+ platform: NodePlatform;
5
+ /** Directory under projectDir holding the built app (e.g. "out" for electron-vite). */
6
+ appDistDir: string;
7
+ includePdb: boolean;
8
+ disableDefaultIgnoredFiles: boolean;
9
+ workspaceRoot?: string;
10
+ extraMetadata?: Record<string, unknown>;
11
+ nodeModuleFileFilter?: FileFilter;
12
+ onNodeModuleFile?: FileVisitor;
13
+ }
14
+ export declare function collectAllFiles(projectDir: string, { platform, appDistDir, includePdb, disableDefaultIgnoredFiles, workspaceRoot, extraMetadata, nodeModuleFileFilter, onNodeModuleFile, }: CollectAllFilesOptions): Promise<{
15
+ appFileSet: FileSet;
16
+ nmFileSets: FileSet[];
17
+ transformer: (file: string) => Promise<string | null> | string | null;
18
+ }>;
@@ -0,0 +1 @@
1
+ export declare function mapWithConcurrency<T, R>(items: T[], concurrency: number, mapper: (item: T, index: number) => Promise<R>): Promise<R[]>;
@@ -0,0 +1,8 @@
1
+ export declare function readAsarHeader(archive: string): Promise<{
2
+ header: string;
3
+ size: number;
4
+ }>;
5
+ export declare function hashHeader(file: string): Promise<{
6
+ algorithm: string;
7
+ hash: string;
8
+ }>;
@@ -0,0 +1,7 @@
1
+ import { NodePlatform } from '../../shared/platform.ts';
2
+ import { type FileFilter, type FileStat, type FileVisitor } from '../../shared/types.ts';
3
+ export declare function getNodeModuleExcludedExts(platform: NodePlatform, includePdb: boolean): string[];
4
+ export declare function collectNodeModuleFiles(moduleDir: string, moduleName: string, moduleRootPath: string, platform: NodePlatform, includePdb: boolean, disableDefaultIgnoredFiles: boolean, filter?: FileFilter | undefined, onNodeModuleFile?: FileVisitor | undefined): Promise<{
5
+ files: string[];
6
+ metadata: Map<string, FileStat>;
7
+ }>;