@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appthreat/caxa",
3
- "version": "1.0.13",
3
+ "version": "2.0.1",
4
4
  "description": "Package Node.js applications into executable binaries",
5
5
  "author": "Team AppThreat <cloud@appthreat.com>",
6
6
  "homepage": "https://github.com/appthreat/caxa",
@@ -21,9 +21,17 @@
21
21
  "caxa": "build/index.mjs"
22
22
  },
23
23
  "scripts": {
24
- "prepare": "cd ./source/ && tsc",
25
- "prepare:stubs": "shx rm -f stubs/stub--win32--x64 && cross-env CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags \"-s -w -extldflags=-Wl,-z,now,-z,relro\" -o stubs/stub--win32--x64 stubs/stub.go && shx echo >> stubs/stub--win32--x64 && shx echo CAXACAXACAXA >> stubs/stub--win32--x64 && shx rm -f stubs/stub--win32--arm64 && cross-env CGO_ENABLED=0 GOOS=windows GOARCH=arm64 go build -ldflags \"-s -w -extldflags=-Wl,-z,now,-z,relro\" -o stubs/stub--win32--arm64 stubs/stub.go && shx echo >> stubs/stub--win32--arm64 && shx echo CAXACAXACAXA >> stubs/stub--win32--arm64 && shx rm -f stubs/stub--darwin--x64 && cross-env CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags \"-s -w -extldflags=-Wl,-z,now,-z,relro\" -o stubs/stub--darwin--x64 stubs/stub.go && shx echo >> stubs/stub--darwin--x64 && shx echo CAXACAXACAXA >> stubs/stub--darwin--x64 && shx rm -f stubs/stub--darwin--arm64 && cross-env CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -ldflags \"-s -w -extldflags=-Wl,-z,now,-z,relro\" -o stubs/stub--darwin--arm64 stubs/stub.go && shx echo >> stubs/stub--darwin--arm64 && shx echo CAXACAXACAXA >> stubs/stub--darwin--arm64 && shx rm -f stubs/stub--linux--x64 && cross-env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags \"-s -w -extldflags=-Wl,-z,now,-z,relro\" -o stubs/stub--linux--x64 stubs/stub.go && shx echo >> stubs/stub--linux--x64 && shx echo CAXACAXACAXA >> stubs/stub--linux--x64 && shx rm -f stubs/stub--linux--arm64 && cross-env CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags \"-s -w -extldflags=-Wl,-z,now,-z,relro\" -o stubs/stub--linux--arm64 stubs/stub.go && shx echo >> stubs/stub--linux--arm64 && shx echo CAXACAXACAXA >> stubs/stub--linux--arm64 && shx rm -f stubs/stub--linux--riscv64 && cross-env CGO_ENABLED=0 GOOS=linux GOARCH=riscv64 go build -ldflags \"-s -w -extldflags=-Wl,-z,now,-z,relro\" -o stubs/stub--linux--riscv64 stubs/stub.go && shx echo >> stubs/stub--linux--riscv64 && shx echo CAXACAXACAXA >> stubs/stub--linux--riscv64 && shx rm -f stubs/stub--linux--arm && cross-env CGO_ENABLED=0 GOOS=linux GOARCH=arm go build -ldflags \"-s -w -extldflags=-Wl,-z,now,-z,relro\" -o stubs/stub--linux--arm stubs/stub.go && shx echo >> stubs/stub--linux--arm && shx echo CAXACAXACAXA >> stubs/stub--linux--arm",
26
- "test": "prettier --check \"source/**/*.mts\" --end-of-line auto"
24
+ "prepare": "npm run prepare:stubs && tsc",
25
+ "prepare:stubs": "shx rm -f stubs/stub--* && npm run build:stub:win && npm run build:stub:mac && npm run build:stub:linux",
26
+ "build:stub:win": "cross-env CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -C stubs -ldflags \"-s -w\" -o stub--win32--x64 stub.go && npm run append:sig -- stubs/stub--win32--x64 && cross-env CGO_ENABLED=0 GOOS=windows GOARCH=arm64 go build -C stubs -ldflags \"-s -w\" -o stub--win32--arm64 stub.go && npm run append:sig -- stubs/stub--win32--arm64",
27
+ "build:stub:mac": "cross-env CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -C stubs -ldflags \"-s -w\" -o stub--darwin--x64 stub.go && npm run append:sig -- stubs/stub--darwin--x64 && cross-env CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -C stubs -ldflags \"-s -w\" -o stub--darwin--arm64 stub.go && npm run append:sig -- stubs/stub--darwin--arm64",
28
+ "build:stub:linux": "cross-env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -C stubs -ldflags \"-s -w\" -o stub--linux--x64 stub.go && npm run append:sig -- stubs/stub--linux--x64 && cross-env CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -C stubs -ldflags \"-s -w\" -o stub--linux--arm64 stub.go && npm run append:sig -- stubs/stub--linux--arm64 && cross-env CGO_ENABLED=0 GOOS=linux GOARCH=arm go build -C stubs -ldflags \"-s -w\" -o stub--linux--arm stub.go && npm run append:sig -- stubs/stub--linux--arm",
29
+ "append:sig": "node -e \"const fs=require('fs'); fs.appendFileSync(process.argv[1], '\\nCAXACAXACAXA\\n')\"",
30
+ "pretest": "npm run prepare:stubs",
31
+ "test": "npm run test:lint && npm run test:go && npm run test:e2e",
32
+ "test:lint": "prettier --check \"source/**/*.mts\" --end-of-line auto",
33
+ "test:go": "cd stubs && go test -v",
34
+ "test:e2e": "node test/e2e.test.mjs"
27
35
  },
28
36
  "dependencies": {
29
37
  "archiver": "^7.0.1",
@@ -43,4 +51,4 @@
43
51
  "shx": "^0.4.0",
44
52
  "typescript": "^5.8.3"
45
53
  }
46
- }
54
+ }
package/source/index.mts CHANGED
@@ -2,18 +2,15 @@
2
2
 
3
3
  import path from "node:path";
4
4
  import url from "node:url";
5
- import os from "node:os";
6
5
  import stream from "node:stream/promises";
7
6
  import fs from "fs-extra";
8
- import { globbySync } from "globby";
7
+ import { globby } from "globby";
9
8
  import cryptoRandomString from "crypto-random-string";
10
9
  import bash from "dedent";
11
- import dedent from "dedent";
12
10
  import archiver from "archiver";
13
11
  import * as commander from "commander";
14
12
  import process from "node:process";
15
13
 
16
- // Some default excludes
17
14
  const defaultExcludes = [
18
15
  ".*",
19
16
  "*.exe",
@@ -53,17 +50,6 @@ export default async function caxa({
53
50
  command,
54
51
  force = true,
55
52
  exclude = defaultExcludes,
56
- filter = (() => {
57
- if (!exclude.length) {
58
- exclude = defaultExcludes;
59
- }
60
- const pathsToExclude = globbySync(exclude, {
61
- expandDirectories: false,
62
- onlyFiles: false,
63
- }).map((pathToExclude: string) => path.normalize(pathToExclude));
64
- return (pathToCopy: string) =>
65
- !pathsToExclude.includes(path.normalize(pathToCopy));
66
- })(),
67
53
  includeNode = true,
68
54
  stub = url.fileURLToPath(
69
55
  new URL(
@@ -75,7 +61,6 @@ export default async function caxa({
75
61
  path.basename(path.basename(path.basename(output, ".exe"), ".app"), ".sh"),
76
62
  cryptoRandomString({ length: 10, type: "alphanumeric" }).toLowerCase(),
77
63
  ),
78
- removeBuildDirectory = true,
79
64
  uncompressionMessage,
80
65
  }: {
81
66
  input: string;
@@ -97,39 +82,144 @@ export default async function caxa({
97
82
  if (process.platform === "win32" && !output.endsWith(".exe"))
98
83
  throw new Error("Windows executable must end in ‘.exe’.");
99
84
 
100
- const buildDirectory = path.join(
101
- os.tmpdir(),
102
- "caxa",
103
- "builds",
104
- cryptoRandomString({ length: 10, type: "alphanumeric" }).toLowerCase(),
105
- );
106
- await fs.copy(input, buildDirectory, { filter });
107
- if (includeNode) {
108
- const node = path.join(
109
- buildDirectory,
110
- "node_modules",
111
- ".bin",
112
- path.basename(process.execPath),
113
- );
114
- await fs.ensureDir(path.dirname(node));
115
- await fs.copyFile(process.execPath, node);
116
- }
117
-
118
85
  await fs.ensureDir(path.dirname(output));
119
86
  await fs.remove(output);
120
87
 
88
+ if (!exclude) exclude = defaultExcludes;
89
+ const files = await globby(["**/*", ...exclude.map((e) => `!${e}`)], {
90
+ cwd: input,
91
+ onlyFiles: true,
92
+ dot: true,
93
+ followSymbolicLinks: false,
94
+ });
95
+
96
+ interface Component {
97
+ group: string;
98
+ name: string;
99
+ version: string;
100
+ purl: string;
101
+ _rawDeps?: Record<string, string>;
102
+ }
103
+
104
+ interface DependencyGraphEntry {
105
+ ref: string;
106
+ dependsOn: string[];
107
+ }
108
+
109
+ const components: Component[] = [];
110
+ const purlLookup = new Map<string, string>();
111
+
112
+ for (const file of files) {
113
+ if (path.basename(file) === "package.json") {
114
+ try {
115
+ const pkg = await fs.readJson(path.join(input, file));
116
+ if (pkg.name && pkg.version) {
117
+ let name = pkg.name;
118
+ let namespace = "";
119
+ if (name.startsWith("@")) {
120
+ const parts = name.split("/");
121
+ namespace = parts[0];
122
+ name = parts[1];
123
+ }
124
+
125
+ let purl = "pkg:npm/";
126
+ if (namespace) {
127
+ purl += `${encodeURIComponent(namespace)}/`;
128
+ }
129
+ purl += `${name}@${pkg.version}`;
130
+
131
+ purlLookup.set(pkg.name, purl);
132
+
133
+ components.push({
134
+ group: namespace,
135
+ name: name,
136
+ version: pkg.version,
137
+ purl: purl,
138
+ _rawDeps: pkg.dependencies,
139
+ });
140
+ }
141
+ } catch (e) {
142
+ // Ignore
143
+ }
144
+ }
145
+ }
146
+
147
+ const dependencies: DependencyGraphEntry[] = [];
148
+
149
+ for (const comp of components) {
150
+ const childPurls: string[] = [];
151
+ if (comp._rawDeps) {
152
+ for (const depName of Object.keys(comp._rawDeps)) {
153
+ const resolvedPurl = purlLookup.get(depName);
154
+ if (resolvedPurl) {
155
+ childPurls.push(resolvedPurl);
156
+ }
157
+ }
158
+ delete comp._rawDeps;
159
+ }
160
+
161
+ if (childPurls.length > 0) {
162
+ dependencies.push({
163
+ ref: comp.purl,
164
+ dependsOn: childPurls,
165
+ });
166
+ }
167
+ }
168
+
169
+ await fs.writeJson(
170
+ path.join(path.dirname(output), "binary-metadata.json"),
171
+ {
172
+ components,
173
+ dependencies,
174
+ },
175
+ { spaces: 0 },
176
+ );
177
+
178
+ const appendApplicationPayload = async (destination: string, prefix = "") => {
179
+ const archive = archiver("tar", {
180
+ gzip: true,
181
+ });
182
+ const outputStream = fs.createWriteStream(destination, { flags: "a" });
183
+ archive.pipe(outputStream);
184
+
185
+ for (const file of files) {
186
+ const absPath = path.join(input, file);
187
+ let name = path.join(prefix, file);
188
+ if (process.platform === "win32") {
189
+ name = name.replace(/\\/g, "/");
190
+ }
191
+ archive.file(absPath, { name });
192
+ }
193
+
194
+ if (includeNode) {
195
+ const nodePath = process.execPath;
196
+ let nodeDest = path.join(
197
+ prefix,
198
+ "node_modules",
199
+ ".bin",
200
+ path.basename(nodePath),
201
+ );
202
+ if (process.platform === "win32") {
203
+ nodeDest = nodeDest.replace(/\\/g, "/");
204
+ }
205
+ archive.file(nodePath, { name: nodeDest });
206
+ }
207
+
208
+ await archive.finalize();
209
+ await stream.finished(outputStream);
210
+ };
211
+
121
212
  if (output.endsWith(".app")) {
122
213
  if (process.platform !== "darwin")
123
214
  throw new Error(
124
215
  "macOS Application Bundles (.app) are supported in macOS only.",
125
216
  );
126
- await fs.ensureDir(path.join(output, "Contents", "Resources"));
127
- await fs.move(
128
- buildDirectory,
129
- path.join(output, "Contents", "Resources", "application"),
130
- );
217
+
131
218
  await fs.ensureDir(path.join(output, "Contents", "MacOS"));
219
+ await fs.ensureDir(path.join(output, "Contents", "Resources"));
220
+
132
221
  const name = path.basename(output, ".app");
222
+
133
223
  await fs.writeFile(
134
224
  path.join(output, "Contents", "MacOS", name),
135
225
  bash`
@@ -138,202 +228,127 @@ export default async function caxa({
138
228
  ` + "\n",
139
229
  { mode: 0o755 },
140
230
  );
231
+
141
232
  await fs.writeFile(
142
233
  path.join(output, "Contents", "Resources", name),
143
234
  bash`
144
235
  #!/usr/bin/env sh
145
236
  ${command
146
237
  .map(
147
- (part) =>
148
- `"${part.replace(
149
- /\{\{\s*caxa\s*\}\}/g,
150
- `$(dirname "$0")/application`,
151
- )}"`,
238
+ (p) =>
239
+ `"${p.replace(/\{\{\s*caxa\s*}}/g, `$(dirname "$0")/application`)}"`,
152
240
  )
153
241
  .join(" ")}
154
242
  ` + "\n",
155
243
  { mode: 0o755 },
156
244
  );
245
+
246
+ const appDest = path.join(output, "Contents", "Resources", "application");
247
+ await fs.ensureDir(appDest);
248
+
249
+ for (const file of files) {
250
+ const src = path.join(input, file);
251
+ const dest = path.join(appDest, file);
252
+ await fs.copy(src, dest);
253
+ }
254
+
255
+ if (includeNode) {
256
+ const nodeDest = path.join(
257
+ appDest,
258
+ "node_modules",
259
+ ".bin",
260
+ path.basename(process.execPath),
261
+ );
262
+ await fs.ensureDir(path.dirname(nodeDest));
263
+ await fs.copyFile(process.execPath, nodeDest);
264
+ }
157
265
  } else if (output.endsWith(".sh")) {
158
266
  if (process.platform === "win32")
159
267
  throw new Error("The Shell Stub (.sh) isn’t supported in Windows.");
160
- let stub =
268
+
269
+ let shellStub =
161
270
  bash`
162
271
  #!/usr/bin/env sh
163
- export CAXA_TEMPORARY_DIRECTORY="$(dirname $(mktemp))/caxa"
164
- export CAXA_EXTRACTION_ATTEMPT=-1
272
+ export CAXA_TMP="$(dirname $(mktemp))/caxa"
273
+ export CAXA_ID="${identifier}"
165
274
  while true
166
275
  do
167
- export CAXA_EXTRACTION_ATTEMPT=$(( CAXA_EXTRACTION_ATTEMPT + 1 ))
168
- export CAXA_LOCK="$CAXA_TEMPORARY_DIRECTORY/locks/${identifier}/$CAXA_EXTRACTION_ATTEMPT"
169
- export CAXA_APPLICATION_DIRECTORY="$CAXA_TEMPORARY_DIRECTORY/applications/${identifier}/$CAXA_EXTRACTION_ATTEMPT"
170
- if [ -d "$CAXA_APPLICATION_DIRECTORY" ]
171
- then
172
- if [ -d "$CAXA_LOCK" ]
173
- then
174
- continue
175
- else
176
- break
177
- fi
178
- else
179
- ${
180
- uncompressionMessage === undefined
181
- ? bash``
182
- : bash`echo "${uncompressionMessage}" >&2`
183
- }
184
- mkdir -p "$CAXA_LOCK"
185
- mkdir -p "$CAXA_APPLICATION_DIRECTORY"
186
- tail -n+{{caxa-number-of-lines}} "$0" | tar -xz -C "$CAXA_APPLICATION_DIRECTORY"
187
- rmdir "$CAXA_LOCK"
188
- break
276
+ export CAXA_LOCK="$CAXA_TMP/locks/$CAXA_ID"
277
+ export CAXA_APP="$CAXA_TMP/apps/$CAXA_ID"
278
+ if [ -d "$CAXA_APP" ] && [ ! -d "$CAXA_LOCK" ]; then
279
+ break
189
280
  fi
281
+
282
+ ${uncompressionMessage ? bash`echo "${uncompressionMessage}" >&2` : ""}
283
+ mkdir -p "$CAXA_LOCK" "$CAXA_APP"
284
+ tail -n+{{lines}} "$0" | tar -xz -C "$CAXA_APP"
285
+ rmdir "$CAXA_LOCK"
286
+ break
190
287
  done
191
288
  exec ${command
192
- .map(
193
- (commandPart) =>
194
- `"${commandPart.replace(
195
- /\{\{\s*caxa\s*\}\}/g,
196
- `"$CAXA_APPLICATION_DIRECTORY"`,
197
- )}"`,
198
- )
289
+ .map((p) => `"${p.replace(/\{\{\s*caxa\s*}}/g, `"$CAXA_APP"`)}"`)
199
290
  .join(" ")} "$@"
200
291
  ` + "\n";
201
- stub = stub.replace(
202
- "{{caxa-number-of-lines}}",
203
- String(stub.split("\n").length),
292
+
293
+ shellStub = shellStub.replace(
294
+ "{{lines}}",
295
+ String(shellStub.split("\n").length),
204
296
  );
205
- await fs.writeFile(output, stub, { mode: 0o755 });
206
- await appendTarballOfBuildDirectoryToOutput();
297
+ await fs.writeFile(output, shellStub, { mode: 0o755 });
298
+ await appendApplicationPayload(output);
207
299
  } else {
208
300
  if (!(await fs.pathExists(stub)))
209
301
  throw new Error(
210
302
  `Stub not found (your operating system / architecture may be unsupported): ‘${stub}’`,
211
303
  );
304
+
212
305
  await fs.copyFile(stub, output);
213
306
  await fs.chmod(output, 0o755);
214
- await appendTarballOfBuildDirectoryToOutput();
307
+
308
+ await appendApplicationPayload(output);
309
+
215
310
  await fs.appendFile(
216
311
  output,
217
312
  "\n" + JSON.stringify({ identifier, command, uncompressionMessage }),
218
313
  );
219
314
  }
220
-
221
- if (removeBuildDirectory) await fs.remove(buildDirectory);
222
-
223
- async function appendTarballOfBuildDirectoryToOutput(): Promise<void> {
224
- const archive = archiver("tar", { gzip: true });
225
- const archiveStream = fs.createWriteStream(output, { flags: "a" });
226
- archive.pipe(archiveStream);
227
- archive.directory(buildDirectory, false);
228
- await archive.finalize();
229
- await stream.finished(archiveStream);
230
- }
231
315
  }
232
316
 
233
317
  if (url.fileURLToPath(import.meta.url) === (await fs.realpath(process.argv[1])))
234
318
  await commander.program
235
319
  .name("caxa")
236
320
  .description("Package Node.js applications into executable binaries")
237
- .requiredOption(
238
- "-i, --input <input>",
239
- "[Required] The input directory to package.",
240
- )
321
+ .requiredOption("-i, --input <input>", "Input directory to package.")
241
322
  .requiredOption(
242
323
  "-o, --output <output>",
243
- "[Required] The path where the executable will be produced. On Windows, must end in ‘.exe’. In macOS and Linux, may have no extension to produce regular binary. In macOS and Linux, may end in ‘.sh’ to use the Shell Stub, which is a bit smaller, but depends on some tools being installed on the end-user machine, for example, ‘tar’, ‘tail’, and so forth. In macOS, may end in ‘.app’ to generate a macOS Application Bundle.",
244
- )
245
- .option("-F, --no-force", "[Advanced] Don’t overwrite output if it exists.")
246
- .option(
247
- "-e, --exclude <path...>",
248
- `[Advanced] Paths to exclude from the build. The paths are passed to https://github.com/sindresorhus/globby and paths that match will be excluded. [Super-Advanced, Please don’t use] If you wish to emulate ‘--include’, you may use ‘--exclude "*" ".*" "!path-to-include" ...’. The problem with ‘--include’ is that if you change your project structure but forget to change the caxa invocation, then things will subtly fail only in the packaged version.`,
249
- )
250
- .option(
251
- "-N, --no-include-node",
252
- "[Advanced] Don’t copy the Node.js executable to ‘{{caxa}}/node_modules/.bin/node’.",
253
- )
254
- .option("-s, --stub <path>", "[Advanced] Path to the stub.")
255
- .option(
256
- "--identifier <identifier>",
257
- "[Advanced] Build identifier, which is part of the path in which the application will be unpacked.",
324
+ "Path where the executable will be produced.",
258
325
  )
326
+ .option("-F, --no-force", "Don’t overwrite output if it exists.")
327
+ .option("-e, --exclude <path...>", "Paths to exclude from the build.")
328
+ .option("-N, --no-include-node", "Don’t copy the Node.js executable.")
329
+ .option("-s, --stub <path>", "Path to the stub.")
330
+ .option("--identifier <id>", "Build identifier.")
259
331
  .option(
260
332
  "-B, --no-remove-build-directory",
261
- "[Advanced] Remove the build directory after the build.",
333
+ "Ignored in v2 (streaming build).",
262
334
  )
263
335
  .option(
264
- "-m, --uncompression-message <message>",
265
- "[Advanced] A message to show when uncompressing, for example, ‘This may take a while to run the first time, please wait...’.",
266
- )
267
- .argument(
268
- "<command...>",
269
- "The command to run and optional arguments to pass to the command every time the executable is called. Paths must be absolute. The ‘{{caxa}}’ placeholder is substituted for the folder from which the package runs. The ‘node’ executable is available at ‘{{caxa}}/node_modules/.bin/node’. Use double quotes to delimit the command and each argument.",
336
+ "-m, --uncompression-message <msg>",
337
+ "Message to show during extraction.",
270
338
  )
339
+ .argument("<command...>", "Command to run.")
271
340
  .version(
272
341
  JSON.parse(
273
342
  await fs.readFile(new URL("../package.json", import.meta.url), "utf8"),
274
343
  ).version,
275
344
  )
276
- .addHelpText(
277
- "after",
278
- "\n" +
279
- dedent`
280
- Examples:
281
- Windows:
282
- > 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"
283
-
284
- macOS/Linux:
285
- $ 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"
286
-
287
- macOS/Linux (Shell Stub):
288
- $ 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"
289
-
290
- macOS (Application Bundle):
291
- $ 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"
292
- `,
293
- )
294
- .action(
295
- async (
296
- command: string[],
297
- {
298
- input,
299
- output,
300
- force,
301
- exclude,
302
- includeNode,
303
- stub,
304
- identifier,
305
- removeBuildDirectory,
306
- uncompressionMessage,
307
- }: {
308
- input: string;
309
- output: string;
310
- force?: boolean;
311
- exclude?: string[];
312
- includeNode?: boolean;
313
- stub?: string;
314
- identifier?: string;
315
- removeBuildDirectory?: boolean;
316
- uncompressionMessage?: string;
317
- },
318
- ) => {
319
- try {
320
- await caxa({
321
- input,
322
- output,
323
- command,
324
- force,
325
- exclude,
326
- includeNode,
327
- stub,
328
- identifier,
329
- removeBuildDirectory,
330
- uncompressionMessage,
331
- });
332
- } catch (error: any) {
333
- console.error(error.message);
334
- process.exit(1);
335
- }
336
- },
337
- )
345
+ .action(async (command, opts) => {
346
+ try {
347
+ await caxa({ command, ...opts });
348
+ } catch (error: any) {
349
+ console.error(error.message);
350
+ process.exit(1);
351
+ }
352
+ })
338
353
  .showHelpAfterError()
339
354
  .parseAsync();
package/stubs/go.mod ADDED
@@ -0,0 +1,5 @@
1
+ module caxa-stubs
2
+
3
+ go 1.25.6
4
+
5
+ require github.com/klauspost/compress v1.18.3
package/stubs/go.sum ADDED
@@ -0,0 +1,2 @@
1
+ github.com/klauspost/compress v1.18.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw=
2
+ github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file