@appthreat/caxa 1.0.13 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +106 -71
- package/build/index.d.mts +1 -1
- package/build/index.d.mts.map +1 -1
- package/build/index.mjs +136 -100
- package/build/index.mjs.map +1 -1
- package/package.json +13 -5
- package/source/index.mts +196 -181
- package/stubs/go.mod +5 -0
- package/stubs/go.sum +2 -0
- package/stubs/stub--darwin--arm64 +0 -0
- package/stubs/stub--darwin--x64 +0 -0
- package/stubs/stub--linux--arm +0 -0
- package/stubs/stub--linux--arm64 +0 -0
- package/stubs/stub--linux--x64 +0 -0
- package/stubs/stub--win32--arm64 +0 -0
- package/stubs/stub--win32--x64 +0 -0
- package/stubs/stub.go +216 -230
- package/stubs/stub_test.go +144 -0
- package/tsconfig.json +28 -0
- package/source/tsconfig.json +0 -19
- package/stubs/stub--linux--riscv64 +0 -0
package/README.md
CHANGED
|
@@ -1,41 +1,34 @@
|
|
|
1
|
-
|
|
1
|
+
# caxa
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
- Added default excludes to ignore .git and some test directories.
|
|
5
|
-
- Removed broken unit tests from source/index.mts.
|
|
6
|
-
- Excluded build and binary stubs using .gitignore. The published package would include binary stubs not present in this git repository.
|
|
3
|
+
**Package Node.js applications into executable binaries.**
|
|
7
4
|
|
|
8
|
-
|
|
5
|
+
This is a high-performance fork of `caxa` (v3.0.1) maintained by AppThreat. Version 2.0 introduces significant architectural changes focused on build speed, runtime performance, and supply chain security.
|
|
9
6
|
|
|
10
|
-
|
|
11
|
-
<h3 align="center">📦 Package Node.js applications into executable binaries 📦</h3>
|
|
7
|
+
### Key Improvements in v2
|
|
12
8
|
|
|
13
|
-
|
|
9
|
+
- **Streaming Builds**: Eliminated the intermediate build directory. Files are streamed directly from the source to the compressed archive, halving disk I/O during the packaging process.
|
|
10
|
+
- **High-Performance Decompression**: Switched the runtime stub to use SIMD-accelerated Gzip (`klauspost/compress/gzip`). This significantly reduces the "Time to First Hello World" compared to standard implementations.
|
|
11
|
+
- **Parallel Extraction & Smart Buffering**: The runtime stub now utilizes a worker pool to extract small files (like `node_modules`) concurrently, maximizing disk I/O saturation. Large files (>1MB) are streamed synchronously to prevent memory spikes.
|
|
12
|
+
- **Atomic Extraction**: Implemented a lock-based extraction mechanism in the runtime stub. This prevents corruption if the application process is killed during the initial extraction.
|
|
13
|
+
- **SBOM Ready**: Automatically generates a `binary-metadata.json` sidecar file containing a full dependency graph (components and relationship tree). This facilitates high-fidelity SBOM generation using tools like [cdxgen](https://github.com/cdxgen/cdxgen).
|
|
14
|
+
- **Optimized Defaults**: Includes robust default exclusion patterns to prevent bundling git history, lock files, tests, and documentation, resulting in smaller binaries.
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
- Let users test an application even if they don’t have Node.js installed.
|
|
17
|
-
- Simple installation story for command-line applications.
|
|
18
|
-
- It’s like the much-praised distribution story of [Go](https://golang.org) programs but for Node.js.
|
|
16
|
+
### How it Works
|
|
19
17
|
|
|
20
|
-
|
|
18
|
+
caxa does not compile Node.js from source or mess with V8 internals. It works by concatenating three components into a single file:
|
|
21
19
|
|
|
22
|
-
|
|
23
|
-
-
|
|
24
|
-
|
|
25
|
-
- Works with any Node.js version.
|
|
26
|
-
- Packages in seconds.
|
|
27
|
-
- Relatively small binaries. A “Hello World!” application is ~30MB, which is terrible if compared to Go’s ~2MB, and worse still if compared to C’s ~50KB, but best-in-class if compared to other packaging solutions for Node.js.
|
|
28
|
-
- Produces `.exe`s for Windows, simple binaries for macOS/Linux, and macOS Application Bundles (`.app`).
|
|
29
|
-
- Based on a simple but powerful idea. Implemented in ~200 lines of code.
|
|
30
|
-
- No magic. No traversal of `require()`s trying to find which files to include; no patches to Node.js source.
|
|
20
|
+
1. **Go Stub**: A small, pre-compiled Go binary responsible for bootstrapping.
|
|
21
|
+
2. **Payload**: A Gzip-compressed TAR archive containing your application and the Node.js executable.
|
|
22
|
+
3. **Footer**: A JSON configuration block defining the command to execute.
|
|
31
23
|
|
|
32
|
-
|
|
24
|
+
When the binary is executed, the stub reads its own file content, locates the payload, extracts it to a temporary directory (if not already cached), and executes the Node.js process.
|
|
25
|
+
|
|
26
|
+
### Features
|
|
33
27
|
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
- Doesn’t hide your JavaScript source code in any way.
|
|
28
|
+
- **Cross-Platform**: Supports Windows, macOS (Intel & ARM), and Linux (Intel, ARM64, ARMv6/7).
|
|
29
|
+
- **Zero Config**: No need to manually define assets.
|
|
30
|
+
- **Native Modules**: Fully supports projects with native C++ bindings (`.node` files).
|
|
31
|
+
- **No Magic**: Does not patch `require()`. Filesystem access works exactly as it does in a standard Node.js environment.
|
|
39
32
|
|
|
40
33
|
### Installation
|
|
41
34
|
|
|
@@ -45,72 +38,114 @@ $ npm install --save-dev @appthreat/caxa
|
|
|
45
38
|
|
|
46
39
|
### Usage
|
|
47
40
|
|
|
48
|
-
#### Prepare the Project
|
|
41
|
+
#### 1. Prepare the Project
|
|
42
|
+
|
|
43
|
+
Ensure your project is built (e.g., TypeScript compiled to JavaScript) and dependencies are installed.
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npm ci
|
|
47
|
+
npm run build
|
|
48
|
+
```
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
- Build. For example, compile TypeScript with `tsc`, bundle with webpack, and whatever else you need to get the project ready to start. Typically this is the kind of thing that goes into an [npm `prepare` script](https://docs.npmjs.com/cli/v7/using-npm/scripts#prepare-and-prepublish), so the `npm ci` from the previous point may already have taken care of this.
|
|
52
|
-
- If there are files that shouldn’t be in the package, remove them from the directory. For example, you may wish to remove the `.git` directory.
|
|
53
|
-
- It’s recommended that you run caxa on a Continuous Integration server. (GitHub Actions, for example, does a shallow fetch of the repository, so removing the `.git` directory becomes negligible—but you can always do that with the `--exclude` advanced option.)
|
|
50
|
+
#### 2. Run caxa
|
|
54
51
|
|
|
55
|
-
|
|
52
|
+
Call `caxa` from the command line:
|
|
56
53
|
|
|
57
54
|
```console
|
|
58
|
-
$ npx caxa --
|
|
59
|
-
|
|
55
|
+
$ npx caxa --input "." --output "my-app" -- "{{caxa}}/node_modules/.bin/node" "{{caxa}}/dist/index.js"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### CLI Reference
|
|
60
59
|
|
|
61
|
-
|
|
60
|
+
```text
|
|
61
|
+
Usage: caxa [options] <command...>
|
|
62
62
|
|
|
63
63
|
Arguments:
|
|
64
|
-
command The command to run
|
|
64
|
+
command The command to run. Paths must be absolute.
|
|
65
|
+
The '{{caxa}}' placeholder is substituted for the extraction directory.
|
|
66
|
+
The 'node' executable is available at '{{caxa}}/node_modules/.bin/node'.
|
|
65
67
|
|
|
66
68
|
Options:
|
|
67
69
|
-i, --input <input> [Required] The input directory to package.
|
|
68
|
-
-o, --output <output> [Required] The path where the executable will be produced.
|
|
69
|
-
|
|
70
|
-
-
|
|
71
|
-
-
|
|
72
|
-
-
|
|
73
|
-
--
|
|
74
|
-
|
|
75
|
-
-
|
|
70
|
+
-o, --output <output> [Required] The path where the executable will be produced.
|
|
71
|
+
On Windows, must end in '.exe'.
|
|
72
|
+
-F, --no-force Don't overwrite output if it exists.
|
|
73
|
+
-e, --exclude <path...> Paths to exclude from the build (glob patterns).
|
|
74
|
+
-N, --no-include-node Don't copy the Node.js executable into the package.
|
|
75
|
+
-s, --stub <path> Path to a custom stub.
|
|
76
|
+
--identifier <identifier> Build identifier used for the extraction path.
|
|
77
|
+
-B, --no-remove-build-directory [Legacy] Ignored in v2 due to streaming build architecture.
|
|
78
|
+
-m, --uncompression-message <message> A message to show to the user while uncompressing.
|
|
76
79
|
-V, --version output the version number
|
|
77
80
|
-h, --help display help for command
|
|
78
|
-
|
|
79
|
-
Examples:
|
|
80
|
-
Windows:
|
|
81
|
-
> caxa --input "examples/echo-command-line-parameters" --output "echo-command-line-parameters.exe" -- "{{caxa}}/node_modules/.bin/node" "{{caxa}}/index.mjs" "some" "embedded arguments" "--an-option-thats-part-of-the-command"
|
|
82
|
-
|
|
83
|
-
macOS/Linux:
|
|
84
|
-
$ caxa --input "examples/echo-command-line-parameters" --output "echo-command-line-parameters" -- "{{caxa}}/node_modules/.bin/node" "{{caxa}}/index.mjs" "some" "embedded arguments" "--an-option-thats-part-of-the-command"
|
|
85
|
-
|
|
86
|
-
macOS/Linux (Shell Stub):
|
|
87
|
-
$ caxa --input "examples/echo-command-line-parameters" --output "echo-command-line-parameters.sh" -- "{{caxa}}/node_modules/.bin/node" "{{caxa}}/index.mjs" "some" "embedded arguments" "--an-option-thats-part-of-the-command"
|
|
88
|
-
|
|
89
|
-
macOS (Application Bundle):
|
|
90
|
-
$ caxa --input "examples/echo-command-line-parameters" --output "Echo Command Line Parameters.app" -- "{{caxa}}/node_modules/.bin/node" "{{caxa}}/index.mjs" "some" "embedded arguments" "--an-option-thats-part-of-the-command"
|
|
91
81
|
```
|
|
92
82
|
|
|
93
|
-
|
|
83
|
+
### Programmatic Usage
|
|
94
84
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
Instead of calling caxa from the command line, you may prefer to write a program that builds your application, for example:
|
|
85
|
+
You can invoke caxa directly from TypeScript or JavaScript build scripts.
|
|
98
86
|
|
|
99
87
|
```typescript
|
|
100
|
-
import caxa from "caxa";
|
|
88
|
+
import caxa from "@appthreat/caxa";
|
|
101
89
|
|
|
102
90
|
(async () => {
|
|
103
91
|
await caxa({
|
|
104
|
-
input: "
|
|
105
|
-
output: "
|
|
92
|
+
input: ".",
|
|
93
|
+
output: "bin/my-app",
|
|
106
94
|
command: [
|
|
107
95
|
"{{caxa}}/node_modules/.bin/node",
|
|
108
|
-
"{{caxa}}/index.
|
|
109
|
-
"
|
|
110
|
-
"embedded arguments",
|
|
96
|
+
"{{caxa}}/dist/index.js",
|
|
97
|
+
"--custom-flag",
|
|
111
98
|
],
|
|
99
|
+
exclude: ["*.log", "tmp/**"],
|
|
112
100
|
});
|
|
113
101
|
})();
|
|
114
102
|
```
|
|
115
103
|
|
|
116
|
-
|
|
104
|
+
### Runtime Behavior
|
|
105
|
+
|
|
106
|
+
#### Temporary Directory
|
|
107
|
+
|
|
108
|
+
By default, the application extracts to the system temporary directory (`os.tmpdir()` joined with `caxa`).
|
|
109
|
+
|
|
110
|
+
To override this location (e.g., for containerized environments with read-only `/tmp`), set the environment variable `CAXA_TEMP_DIR`:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
export CAXA_TEMP_DIR=/var/opt/my-app
|
|
114
|
+
./my-app
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
#### Supply Chain Security
|
|
118
|
+
|
|
119
|
+
Every build produces a `binary-metadata.json` file alongside the executable. This file captures the full dependency graph of the packaged application, structured to align with SBOM standards.
|
|
120
|
+
|
|
121
|
+
Example `binary-metadata.json`:
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"components": [
|
|
126
|
+
{
|
|
127
|
+
"group": "",
|
|
128
|
+
"name": "my-app",
|
|
129
|
+
"version": "1.0.0",
|
|
130
|
+
"purl": "pkg:npm/my-app@1.0.0"
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"group": "",
|
|
134
|
+
"name": "commander",
|
|
135
|
+
"version": "12.0.0",
|
|
136
|
+
"purl": "pkg:npm/commander@12.0.0"
|
|
137
|
+
}
|
|
138
|
+
],
|
|
139
|
+
"dependencies": [
|
|
140
|
+
{
|
|
141
|
+
"ref": "pkg:npm/my-app@1.0.0",
|
|
142
|
+
"dependsOn": ["pkg:npm/commander@12.0.0"]
|
|
143
|
+
}
|
|
144
|
+
]
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Anti-Features
|
|
149
|
+
|
|
150
|
+
- **No Source Hiding**: This is a packaging tool, not an obfuscator. The source code is extracted to the disk at runtime.
|
|
151
|
+
- **No Cross-Compilation**: The machine running `caxa` must have the same architecture/OS as the target if you want to bundle the _correct_ Node.js binary. You cannot bundle a Windows Node.js executable from a macOS machine (unless you provide it manually via custom scripts).
|
package/build/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import fs from "fs-extra";
|
|
3
|
-
export default function caxa({ input, output, command, force, exclude,
|
|
3
|
+
export default function caxa({ input, output, command, force, exclude, includeNode, stub, identifier, uncompressionMessage, }: {
|
|
4
4
|
input: string;
|
|
5
5
|
output: string;
|
|
6
6
|
command: string[];
|
package/build/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../source/index.mts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../source/index.mts"],"names":[],"mappings":";AAKA,OAAO,EAAE,MAAM,UAAU,CAAC;AAyC1B,wBAA8B,IAAI,CAAC,EACjC,KAAK,EACL,MAAM,EACN,OAAO,EACP,KAAY,EACZ,OAAyB,EACzB,WAAkB,EAClB,IAKC,EACD,UAGC,EACD,oBAAoB,GACrB,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE,EAAE,CAAC,cAAc,GAAG,EAAE,CAAC,eAAe,CAAC;IAChD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,GAAG,OAAO,CAAC,IAAI,CAAC,CA8OhB"}
|
package/build/index.mjs
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import url from "node:url";
|
|
4
|
-
import os from "node:os";
|
|
5
4
|
import stream from "node:stream/promises";
|
|
6
5
|
import fs from "fs-extra";
|
|
7
|
-
import {
|
|
6
|
+
import { globby } from "globby";
|
|
8
7
|
import cryptoRandomString from "crypto-random-string";
|
|
9
8
|
import bash from "dedent";
|
|
10
|
-
import dedent from "dedent";
|
|
11
9
|
import archiver from "archiver";
|
|
12
10
|
import * as commander from "commander";
|
|
13
11
|
import process from "node:process";
|
|
14
|
-
// Some default excludes
|
|
15
12
|
const defaultExcludes = [
|
|
16
13
|
".*",
|
|
17
14
|
"*.exe",
|
|
@@ -44,37 +41,110 @@ const defaultExcludes = [
|
|
|
44
41
|
"biome.json",
|
|
45
42
|
"jest.config.js",
|
|
46
43
|
];
|
|
47
|
-
export default async function caxa({ input, output, command, force = true, exclude = defaultExcludes,
|
|
48
|
-
if (!exclude.length) {
|
|
49
|
-
exclude = defaultExcludes;
|
|
50
|
-
}
|
|
51
|
-
const pathsToExclude = globbySync(exclude, {
|
|
52
|
-
expandDirectories: false,
|
|
53
|
-
onlyFiles: false,
|
|
54
|
-
}).map((pathToExclude) => path.normalize(pathToExclude));
|
|
55
|
-
return (pathToCopy) => !pathsToExclude.includes(path.normalize(pathToCopy));
|
|
56
|
-
})(), includeNode = true, stub = url.fileURLToPath(new URL(`../stubs/stub--${process.platform}--${process.arch}`, import.meta.url)), identifier = path.join(path.basename(path.basename(path.basename(output, ".exe"), ".app"), ".sh"), cryptoRandomString({ length: 10, type: "alphanumeric" }).toLowerCase()), removeBuildDirectory = true, uncompressionMessage, }) {
|
|
44
|
+
export default async function caxa({ input, output, command, force = true, exclude = defaultExcludes, includeNode = true, stub = url.fileURLToPath(new URL(`../stubs/stub--${process.platform}--${process.arch}`, import.meta.url)), identifier = path.join(path.basename(path.basename(path.basename(output, ".exe"), ".app"), ".sh"), cryptoRandomString({ length: 10, type: "alphanumeric" }).toLowerCase()), uncompressionMessage, }) {
|
|
57
45
|
if (!(await fs.pathExists(input)) || !(await fs.lstat(input)).isDirectory())
|
|
58
46
|
throw new Error(`Input isn’t a directory: ‘${input}’.`);
|
|
59
47
|
if ((await fs.pathExists(output)) && !force)
|
|
60
48
|
throw new Error(`Output already exists: ‘${output}’.`);
|
|
61
49
|
if (process.platform === "win32" && !output.endsWith(".exe"))
|
|
62
50
|
throw new Error("Windows executable must end in ‘.exe’.");
|
|
63
|
-
const buildDirectory = path.join(os.tmpdir(), "caxa", "builds", cryptoRandomString({ length: 10, type: "alphanumeric" }).toLowerCase());
|
|
64
|
-
await fs.copy(input, buildDirectory, { filter });
|
|
65
|
-
if (includeNode) {
|
|
66
|
-
const node = path.join(buildDirectory, "node_modules", ".bin", path.basename(process.execPath));
|
|
67
|
-
await fs.ensureDir(path.dirname(node));
|
|
68
|
-
await fs.copyFile(process.execPath, node);
|
|
69
|
-
}
|
|
70
51
|
await fs.ensureDir(path.dirname(output));
|
|
71
52
|
await fs.remove(output);
|
|
53
|
+
if (!exclude)
|
|
54
|
+
exclude = defaultExcludes;
|
|
55
|
+
const files = await globby(["**/*", ...exclude.map((e) => `!${e}`)], {
|
|
56
|
+
cwd: input,
|
|
57
|
+
onlyFiles: true,
|
|
58
|
+
dot: true,
|
|
59
|
+
followSymbolicLinks: false,
|
|
60
|
+
});
|
|
61
|
+
const components = [];
|
|
62
|
+
const purlLookup = new Map();
|
|
63
|
+
for (const file of files) {
|
|
64
|
+
if (path.basename(file) === "package.json") {
|
|
65
|
+
try {
|
|
66
|
+
const pkg = await fs.readJson(path.join(input, file));
|
|
67
|
+
if (pkg.name && pkg.version) {
|
|
68
|
+
let name = pkg.name;
|
|
69
|
+
let namespace = "";
|
|
70
|
+
if (name.startsWith("@")) {
|
|
71
|
+
const parts = name.split("/");
|
|
72
|
+
namespace = parts[0];
|
|
73
|
+
name = parts[1];
|
|
74
|
+
}
|
|
75
|
+
let purl = "pkg:npm/";
|
|
76
|
+
if (namespace) {
|
|
77
|
+
purl += `${encodeURIComponent(namespace)}/`;
|
|
78
|
+
}
|
|
79
|
+
purl += `${name}@${pkg.version}`;
|
|
80
|
+
purlLookup.set(pkg.name, purl);
|
|
81
|
+
components.push({
|
|
82
|
+
group: namespace,
|
|
83
|
+
name: name,
|
|
84
|
+
version: pkg.version,
|
|
85
|
+
purl: purl,
|
|
86
|
+
_rawDeps: pkg.dependencies,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch (e) {
|
|
91
|
+
// Ignore
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const dependencies = [];
|
|
96
|
+
for (const comp of components) {
|
|
97
|
+
const childPurls = [];
|
|
98
|
+
if (comp._rawDeps) {
|
|
99
|
+
for (const depName of Object.keys(comp._rawDeps)) {
|
|
100
|
+
const resolvedPurl = purlLookup.get(depName);
|
|
101
|
+
if (resolvedPurl) {
|
|
102
|
+
childPurls.push(resolvedPurl);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
delete comp._rawDeps;
|
|
106
|
+
}
|
|
107
|
+
if (childPurls.length > 0) {
|
|
108
|
+
dependencies.push({
|
|
109
|
+
ref: comp.purl,
|
|
110
|
+
dependsOn: childPurls,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
await fs.writeJson(path.join(path.dirname(output), "binary-metadata.json"), {
|
|
115
|
+
components,
|
|
116
|
+
dependencies,
|
|
117
|
+
}, { spaces: 0 });
|
|
118
|
+
const appendApplicationPayload = async (destination, prefix = "") => {
|
|
119
|
+
const archive = archiver("tar", {
|
|
120
|
+
gzip: true,
|
|
121
|
+
});
|
|
122
|
+
const outputStream = fs.createWriteStream(destination, { flags: "a" });
|
|
123
|
+
archive.pipe(outputStream);
|
|
124
|
+
for (const file of files) {
|
|
125
|
+
const absPath = path.join(input, file);
|
|
126
|
+
let name = path.join(prefix, file);
|
|
127
|
+
if (process.platform === "win32") {
|
|
128
|
+
name = name.replace(/\\/g, "/");
|
|
129
|
+
}
|
|
130
|
+
archive.file(absPath, { name });
|
|
131
|
+
}
|
|
132
|
+
if (includeNode) {
|
|
133
|
+
const nodePath = process.execPath;
|
|
134
|
+
let nodeDest = path.join(prefix, "node_modules", ".bin", path.basename(nodePath));
|
|
135
|
+
if (process.platform === "win32") {
|
|
136
|
+
nodeDest = nodeDest.replace(/\\/g, "/");
|
|
137
|
+
}
|
|
138
|
+
archive.file(nodePath, { name: nodeDest });
|
|
139
|
+
}
|
|
140
|
+
await archive.finalize();
|
|
141
|
+
await stream.finished(outputStream);
|
|
142
|
+
};
|
|
72
143
|
if (output.endsWith(".app")) {
|
|
73
144
|
if (process.platform !== "darwin")
|
|
74
145
|
throw new Error("macOS Application Bundles (.app) are supported in macOS only.");
|
|
75
|
-
await fs.ensureDir(path.join(output, "Contents", "Resources"));
|
|
76
|
-
await fs.move(buildDirectory, path.join(output, "Contents", "Resources", "application"));
|
|
77
146
|
await fs.ensureDir(path.join(output, "Contents", "MacOS"));
|
|
147
|
+
await fs.ensureDir(path.join(output, "Contents", "Resources"));
|
|
78
148
|
const name = path.basename(output, ".app");
|
|
79
149
|
await fs.writeFile(path.join(output, "Contents", "MacOS", name), bash `
|
|
80
150
|
#!/usr/bin/env sh
|
|
@@ -83,112 +153,78 @@ export default async function caxa({ input, output, command, force = true, exclu
|
|
|
83
153
|
await fs.writeFile(path.join(output, "Contents", "Resources", name), bash `
|
|
84
154
|
#!/usr/bin/env sh
|
|
85
155
|
${command
|
|
86
|
-
.map((
|
|
156
|
+
.map((p) => `"${p.replace(/\{\{\s*caxa\s*}}/g, `$(dirname "$0")/application`)}"`)
|
|
87
157
|
.join(" ")}
|
|
88
158
|
` + "\n", { mode: 0o755 });
|
|
159
|
+
const appDest = path.join(output, "Contents", "Resources", "application");
|
|
160
|
+
await fs.ensureDir(appDest);
|
|
161
|
+
for (const file of files) {
|
|
162
|
+
const src = path.join(input, file);
|
|
163
|
+
const dest = path.join(appDest, file);
|
|
164
|
+
await fs.copy(src, dest);
|
|
165
|
+
}
|
|
166
|
+
if (includeNode) {
|
|
167
|
+
const nodeDest = path.join(appDest, "node_modules", ".bin", path.basename(process.execPath));
|
|
168
|
+
await fs.ensureDir(path.dirname(nodeDest));
|
|
169
|
+
await fs.copyFile(process.execPath, nodeDest);
|
|
170
|
+
}
|
|
89
171
|
}
|
|
90
172
|
else if (output.endsWith(".sh")) {
|
|
91
173
|
if (process.platform === "win32")
|
|
92
174
|
throw new Error("The Shell Stub (.sh) isn’t supported in Windows.");
|
|
93
|
-
let
|
|
175
|
+
let shellStub = bash `
|
|
94
176
|
#!/usr/bin/env sh
|
|
95
|
-
export
|
|
96
|
-
export
|
|
177
|
+
export CAXA_TMP="$(dirname $(mktemp))/caxa"
|
|
178
|
+
export CAXA_ID="${identifier}"
|
|
97
179
|
while true
|
|
98
180
|
do
|
|
99
|
-
export
|
|
100
|
-
export
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
then
|
|
104
|
-
if [ -d "$CAXA_LOCK" ]
|
|
105
|
-
then
|
|
106
|
-
continue
|
|
107
|
-
else
|
|
108
|
-
break
|
|
109
|
-
fi
|
|
110
|
-
else
|
|
111
|
-
${uncompressionMessage === undefined
|
|
112
|
-
? bash ``
|
|
113
|
-
: bash `echo "${uncompressionMessage}" >&2`}
|
|
114
|
-
mkdir -p "$CAXA_LOCK"
|
|
115
|
-
mkdir -p "$CAXA_APPLICATION_DIRECTORY"
|
|
116
|
-
tail -n+{{caxa-number-of-lines}} "$0" | tar -xz -C "$CAXA_APPLICATION_DIRECTORY"
|
|
117
|
-
rmdir "$CAXA_LOCK"
|
|
118
|
-
break
|
|
181
|
+
export CAXA_LOCK="$CAXA_TMP/locks/$CAXA_ID"
|
|
182
|
+
export CAXA_APP="$CAXA_TMP/apps/$CAXA_ID"
|
|
183
|
+
if [ -d "$CAXA_APP" ] && [ ! -d "$CAXA_LOCK" ]; then
|
|
184
|
+
break
|
|
119
185
|
fi
|
|
186
|
+
|
|
187
|
+
${uncompressionMessage ? bash `echo "${uncompressionMessage}" >&2` : ""}
|
|
188
|
+
mkdir -p "$CAXA_LOCK" "$CAXA_APP"
|
|
189
|
+
tail -n+{{lines}} "$0" | tar -xz -C "$CAXA_APP"
|
|
190
|
+
rmdir "$CAXA_LOCK"
|
|
191
|
+
break
|
|
120
192
|
done
|
|
121
193
|
exec ${command
|
|
122
|
-
.map((
|
|
194
|
+
.map((p) => `"${p.replace(/\{\{\s*caxa\s*}}/g, `"$CAXA_APP"`)}"`)
|
|
123
195
|
.join(" ")} "$@"
|
|
124
196
|
` + "\n";
|
|
125
|
-
|
|
126
|
-
await fs.writeFile(output,
|
|
127
|
-
await
|
|
197
|
+
shellStub = shellStub.replace("{{lines}}", String(shellStub.split("\n").length));
|
|
198
|
+
await fs.writeFile(output, shellStub, { mode: 0o755 });
|
|
199
|
+
await appendApplicationPayload(output);
|
|
128
200
|
}
|
|
129
201
|
else {
|
|
130
202
|
if (!(await fs.pathExists(stub)))
|
|
131
203
|
throw new Error(`Stub not found (your operating system / architecture may be unsupported): ‘${stub}’`);
|
|
132
204
|
await fs.copyFile(stub, output);
|
|
133
205
|
await fs.chmod(output, 0o755);
|
|
134
|
-
await
|
|
206
|
+
await appendApplicationPayload(output);
|
|
135
207
|
await fs.appendFile(output, "\n" + JSON.stringify({ identifier, command, uncompressionMessage }));
|
|
136
208
|
}
|
|
137
|
-
if (removeBuildDirectory)
|
|
138
|
-
await fs.remove(buildDirectory);
|
|
139
|
-
async function appendTarballOfBuildDirectoryToOutput() {
|
|
140
|
-
const archive = archiver("tar", { gzip: true });
|
|
141
|
-
const archiveStream = fs.createWriteStream(output, { flags: "a" });
|
|
142
|
-
archive.pipe(archiveStream);
|
|
143
|
-
archive.directory(buildDirectory, false);
|
|
144
|
-
await archive.finalize();
|
|
145
|
-
await stream.finished(archiveStream);
|
|
146
|
-
}
|
|
147
209
|
}
|
|
148
210
|
if (url.fileURLToPath(import.meta.url) === (await fs.realpath(process.argv[1])))
|
|
149
211
|
await commander.program
|
|
150
212
|
.name("caxa")
|
|
151
213
|
.description("Package Node.js applications into executable binaries")
|
|
152
|
-
.requiredOption("-i, --input <input>", "
|
|
153
|
-
.requiredOption("-o, --output <output>", "
|
|
154
|
-
.option("-F, --no-force", "
|
|
155
|
-
.option("-e, --exclude <path...>",
|
|
156
|
-
.option("-N, --no-include-node", "
|
|
157
|
-
.option("-s, --stub <path>", "
|
|
158
|
-
.option("--identifier <
|
|
159
|
-
.option("-B, --no-remove-build-directory", "
|
|
160
|
-
.option("-m, --uncompression-message <
|
|
161
|
-
.argument("<command...>", "
|
|
214
|
+
.requiredOption("-i, --input <input>", "Input directory to package.")
|
|
215
|
+
.requiredOption("-o, --output <output>", "Path where the executable will be produced.")
|
|
216
|
+
.option("-F, --no-force", "Don’t overwrite output if it exists.")
|
|
217
|
+
.option("-e, --exclude <path...>", "Paths to exclude from the build.")
|
|
218
|
+
.option("-N, --no-include-node", "Don’t copy the Node.js executable.")
|
|
219
|
+
.option("-s, --stub <path>", "Path to the stub.")
|
|
220
|
+
.option("--identifier <id>", "Build identifier.")
|
|
221
|
+
.option("-B, --no-remove-build-directory", "Ignored in v2 (streaming build).")
|
|
222
|
+
.option("-m, --uncompression-message <msg>", "Message to show during extraction.")
|
|
223
|
+
.argument("<command...>", "Command to run.")
|
|
162
224
|
.version(JSON.parse(await fs.readFile(new URL("../package.json", import.meta.url), "utf8")).version)
|
|
163
|
-
.
|
|
164
|
-
dedent `
|
|
165
|
-
Examples:
|
|
166
|
-
Windows:
|
|
167
|
-
> caxa --input "examples/echo-command-line-parameters" --output "echo-command-line-parameters.exe" -- "{{caxa}}/node_modules/.bin/node" "{{caxa}}/index.mjs" "some" "embedded arguments" "--an-option-thats-part-of-the-command"
|
|
168
|
-
|
|
169
|
-
macOS/Linux:
|
|
170
|
-
$ caxa --input "examples/echo-command-line-parameters" --output "echo-command-line-parameters" -- "{{caxa}}/node_modules/.bin/node" "{{caxa}}/index.mjs" "some" "embedded arguments" "--an-option-thats-part-of-the-command"
|
|
171
|
-
|
|
172
|
-
macOS/Linux (Shell Stub):
|
|
173
|
-
$ caxa --input "examples/echo-command-line-parameters" --output "echo-command-line-parameters.sh" -- "{{caxa}}/node_modules/.bin/node" "{{caxa}}/index.mjs" "some" "embedded arguments" "--an-option-thats-part-of-the-command"
|
|
174
|
-
|
|
175
|
-
macOS (Application Bundle):
|
|
176
|
-
$ caxa --input "examples/echo-command-line-parameters" --output "Echo Command Line Parameters.app" -- "{{caxa}}/node_modules/.bin/node" "{{caxa}}/index.mjs" "some" "embedded arguments" "--an-option-thats-part-of-the-command"
|
|
177
|
-
`)
|
|
178
|
-
.action(async (command, { input, output, force, exclude, includeNode, stub, identifier, removeBuildDirectory, uncompressionMessage, }) => {
|
|
225
|
+
.action(async (command, opts) => {
|
|
179
226
|
try {
|
|
180
|
-
await caxa({
|
|
181
|
-
input,
|
|
182
|
-
output,
|
|
183
|
-
command,
|
|
184
|
-
force,
|
|
185
|
-
exclude,
|
|
186
|
-
includeNode,
|
|
187
|
-
stub,
|
|
188
|
-
identifier,
|
|
189
|
-
removeBuildDirectory,
|
|
190
|
-
uncompressionMessage,
|
|
191
|
-
});
|
|
227
|
+
await caxa({ command, ...opts });
|
|
192
228
|
}
|
|
193
229
|
catch (error) {
|
|
194
230
|
console.error(error.message);
|
package/build/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../source/index.mts"],"names":[],"mappings":";AAEA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,GAAG,MAAM,UAAU,CAAC;AAC3B,OAAO,
|
|
1
|
+
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../source/index.mts"],"names":[],"mappings":"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"}
|