@hakobu/hakobu 1.0.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.
- package/LICENSE +21 -0
- package/README.md +673 -0
- package/dictionary/angular-bridge.js +3 -0
- package/dictionary/any-promise.js +3 -0
- package/dictionary/async.js +3 -0
- package/dictionary/aws-sdk.js +7 -0
- package/dictionary/babel-core.js +3 -0
- package/dictionary/batch.js +3 -0
- package/dictionary/bcrypt.js +3 -0
- package/dictionary/better-sqlite3.js +3 -0
- package/dictionary/bignum.js +3 -0
- package/dictionary/bindings.js +3 -0
- package/dictionary/blessed.js +8 -0
- package/dictionary/body-parser.js +9 -0
- package/dictionary/browserify.js +7 -0
- package/dictionary/bson.js +3 -0
- package/dictionary/buffermaker.js +7 -0
- package/dictionary/bunyan.js +9 -0
- package/dictionary/busboy.js +7 -0
- package/dictionary/bytes.js +3 -0
- package/dictionary/callsites.js +3 -0
- package/dictionary/chokidar.js +3 -0
- package/dictionary/coffee-script.js +7 -0
- package/dictionary/colors.js +3 -0
- package/dictionary/compression.js +3 -0
- package/dictionary/compressjs.js +7 -0
- package/dictionary/connect-mongo.js +3 -0
- package/dictionary/connect-mongodb.js +3 -0
- package/dictionary/connect-redis.js +3 -0
- package/dictionary/connect.js +10 -0
- package/dictionary/consolidate.js +3 -0
- package/dictionary/cookie-parser.js +3 -0
- package/dictionary/cookie.js +3 -0
- package/dictionary/cors.js +3 -0
- package/dictionary/cron.js +3 -0
- package/dictionary/cross-env.js +11 -0
- package/dictionary/cross-spawn-async.js +3 -0
- package/dictionary/curve25519.js +3 -0
- package/dictionary/data-preflight.js +7 -0
- package/dictionary/debug.js +3 -0
- package/dictionary/denymount.js +3 -0
- package/dictionary/diff.js +3 -0
- package/dictionary/drivelist.js +22 -0
- package/dictionary/ed25519.js +3 -0
- package/dictionary/ejs.js +3 -0
- package/dictionary/elasticsearch.js +3 -0
- package/dictionary/electron.js +17 -0
- package/dictionary/emailjs.js +3 -0
- package/dictionary/engine.io.js +3 -0
- package/dictionary/epoll.js +3 -0
- package/dictionary/errorhandler.js +7 -0
- package/dictionary/errors.js +7 -0
- package/dictionary/eslint.js +7 -0
- package/dictionary/etcher-image-write.js +3 -0
- package/dictionary/exceljs.js +21 -0
- package/dictionary/exiftool.exe.js +13 -0
- package/dictionary/exiftool.pl.js +13 -0
- package/dictionary/express-load.js +12 -0
- package/dictionary/express-session.js +3 -0
- package/dictionary/express.js +14 -0
- package/dictionary/extender.js +11 -0
- package/dictionary/extsprintf.js +3 -0
- package/dictionary/faye-websocket.js +3 -0
- package/dictionary/feathers.js +3 -0
- package/dictionary/findup-sync.js +3 -0
- package/dictionary/floordate.js +3 -0
- package/dictionary/fmt.js +3 -0
- package/dictionary/formidable.js +3 -0
- package/dictionary/fs-extra.js +3 -0
- package/dictionary/fsevents.js +3 -0
- package/dictionary/geoip-lite.js +7 -0
- package/dictionary/github.js +7 -0
- package/dictionary/gm.js +3 -0
- package/dictionary/google-closure-compiler-java.js +13 -0
- package/dictionary/google-closure-compiler.js +13 -0
- package/dictionary/googleapis.js +7 -0
- package/dictionary/got.js +3 -0
- package/dictionary/graceful-fs.js +19 -0
- package/dictionary/grpc.js +11 -0
- package/dictionary/gulp.js +3 -0
- package/dictionary/hap-nodejs.js +3 -0
- package/dictionary/heapdump.js +3 -0
- package/dictionary/hoek.js +3 -0
- package/dictionary/homebridge.js +3 -0
- package/dictionary/http-proxy.js +3 -0
- package/dictionary/http-server.js +3 -0
- package/dictionary/image-size.js +3 -0
- package/dictionary/indexof.js +3 -0
- package/dictionary/inquirer.js +3 -0
- package/dictionary/j.js +16 -0
- package/dictionary/jade.js +3 -0
- package/dictionary/jsdom.js +3 -0
- package/dictionary/json-stringify-date.js +3 -0
- package/dictionary/json-stringify-safe.js +3 -0
- package/dictionary/jsonwebtoken.js +3 -0
- package/dictionary/kerberos.js +3 -0
- package/dictionary/knex.js +7 -0
- package/dictionary/later.js +7 -0
- package/dictionary/level.js +3 -0
- package/dictionary/leveldown.js +10 -0
- package/dictionary/levelup.js +3 -0
- package/dictionary/liftoff.js +12 -0
- package/dictionary/lodash.js +3 -0
- package/dictionary/log4js.js +7 -0
- package/dictionary/logform.js +7 -0
- package/dictionary/machinepack-urls.js +7 -0
- package/dictionary/markdown.js +3 -0
- package/dictionary/mdns.js +6 -0
- package/dictionary/method-override.js +3 -0
- package/dictionary/microjob.js +16 -0
- package/dictionary/mime-types.js +3 -0
- package/dictionary/mime.js +3 -0
- package/dictionary/minimatch.js +3 -0
- package/dictionary/minstache.js +3 -0
- package/dictionary/module-deps.js +3 -0
- package/dictionary/moment-timezone.js +3 -0
- package/dictionary/moment.js +7 -0
- package/dictionary/mongodb-core.js +22 -0
- package/dictionary/mongodb.js +7 -0
- package/dictionary/mongoose.js +7 -0
- package/dictionary/mongoskin.js +7 -0
- package/dictionary/ms.js +3 -0
- package/dictionary/msgpack.js +3 -0
- package/dictionary/multer.js +3 -0
- package/dictionary/muri.js +3 -0
- package/dictionary/native-or-bluebird.js +3 -0
- package/dictionary/natives.js +3 -0
- package/dictionary/nconf.js +7 -0
- package/dictionary/nedb.js +3 -0
- package/dictionary/negotiator.js +7 -0
- package/dictionary/newrelic.js +3 -0
- package/dictionary/nib.js +3 -0
- package/dictionary/nightmare.js +18 -0
- package/dictionary/node-forge.js +7 -0
- package/dictionary/node-libcurl.js +3 -0
- package/dictionary/node-notifier.js +30 -0
- package/dictionary/node-pre-gyp.js +7 -0
- package/dictionary/node-redis-pubsub.js +3 -0
- package/dictionary/node-sass.js +3 -0
- package/dictionary/node-uuid.js +3 -0
- package/dictionary/node-xlsx.js +3 -0
- package/dictionary/node-zookeeper-client.js +7 -0
- package/dictionary/nodegit.js +7 -0
- package/dictionary/nodemailer-sendmail-transport.js +3 -0
- package/dictionary/nodemailer.js +3 -0
- package/dictionary/npm-registry-client.js +7 -0
- package/dictionary/npm.js +7 -0
- package/dictionary/nssocket.js +3 -0
- package/dictionary/oauth2orize.js +7 -0
- package/dictionary/octobat.js +3 -0
- package/dictionary/open.js +13 -0
- package/dictionary/opn.js +4 -0
- package/dictionary/optimist.js +3 -0
- package/dictionary/passport-local.js +3 -0
- package/dictionary/passport.js +3 -0
- package/dictionary/pg-cursor.js +3 -0
- package/dictionary/pg-query-stream.js +3 -0
- package/dictionary/pg-types.js +7 -0
- package/dictionary/pg.js +7 -0
- package/dictionary/pg.js.js +7 -0
- package/dictionary/pgpass.js +7 -0
- package/dictionary/phantom.js +19 -0
- package/dictionary/phantomjs-prebuilt.js +16 -0
- package/dictionary/pkginfo.js +3 -0
- package/dictionary/pm2.js +7 -0
- package/dictionary/pmx.js +3 -0
- package/dictionary/pouchdb.js +3 -0
- package/dictionary/primus-emitter.js +3 -0
- package/dictionary/primus-spark-latency.js +3 -0
- package/dictionary/primus.js +3 -0
- package/dictionary/publicsuffixlist.js +15 -0
- package/dictionary/pug.js +3 -0
- package/dictionary/punt.js +3 -0
- package/dictionary/puppeteer.js +13 -0
- package/dictionary/pwd.js +3 -0
- package/dictionary/q.js +3 -0
- package/dictionary/raven.js +3 -0
- package/dictionary/rc.js +12 -0
- package/dictionary/readable-stream.js +3 -0
- package/dictionary/rechoir.js +3 -0
- package/dictionary/redis-parser.js +3 -0
- package/dictionary/redis.js +3 -0
- package/dictionary/regression.js +3 -0
- package/dictionary/reload.js +7 -0
- package/dictionary/request.js +3 -0
- package/dictionary/require-uncached.js +3 -0
- package/dictionary/require_optional.js +3 -0
- package/dictionary/s3.js +3 -0
- package/dictionary/safe_datejs.js +3 -0
- package/dictionary/sails.js +33 -0
- package/dictionary/sax.js +3 -0
- package/dictionary/scrypt.js +3 -0
- package/dictionary/semver.js +3 -0
- package/dictionary/sequelize.js +7 -0
- package/dictionary/serialport.js +3 -0
- package/dictionary/sha3.js +3 -0
- package/dictionary/sharp.js +11 -0
- package/dictionary/shelljs.js +7 -0
- package/dictionary/sinon.js +3 -0
- package/dictionary/socket.io-client.js +13 -0
- package/dictionary/socket.io.js +12 -0
- package/dictionary/sqip.js +7 -0
- package/dictionary/sqlite3.js +7 -0
- package/dictionary/steam-crypto.js +7 -0
- package/dictionary/steam-resources.js +19 -0
- package/dictionary/steam.js +3 -0
- package/dictionary/stripe-webhook-middleware.js +3 -0
- package/dictionary/stripe.js +3 -0
- package/dictionary/strong-globalize.js +3 -0
- package/dictionary/stylus.js +14 -0
- package/dictionary/supervisor.js +3 -0
- package/dictionary/svgo.js +8 -0
- package/dictionary/tabtab.js +3 -0
- package/dictionary/tesseract.js.js +7 -0
- package/dictionary/thread-stream.js +7 -0
- package/dictionary/throng.js +3 -0
- package/dictionary/time.js +3 -0
- package/dictionary/tinify.js +7 -0
- package/dictionary/tiny-worker.js +7 -0
- package/dictionary/tmp.js +3 -0
- package/dictionary/transformers.js +3 -0
- package/dictionary/uglify-js.js +9 -0
- package/dictionary/umd.js +19 -0
- package/dictionary/underscore.js +3 -0
- package/dictionary/union.js +3 -0
- package/dictionary/update-notifier.js +3 -0
- package/dictionary/usage.js +7 -0
- package/dictionary/v8flags.js +13 -0
- package/dictionary/verror.js +3 -0
- package/dictionary/voc.js +3 -0
- package/dictionary/webdriverio.js +7 -0
- package/dictionary/winston-uber.js +7 -0
- package/dictionary/winston.js +7 -0
- package/dictionary/ws.js +3 -0
- package/dictionary/xlsx.js +16 -0
- package/dictionary/xml2js.js +3 -0
- package/dictionary/yargs.js +3 -0
- package/dictionary/zeromq.js +13 -0
- package/lib-es5/addon-extract.js +164 -0
- package/lib-es5/analyzer.js +687 -0
- package/lib-es5/app-bundle.js +133 -0
- package/lib-es5/appdir.js +265 -0
- package/lib-es5/bin.js +304 -0
- package/lib-es5/bootstrap.js +179 -0
- package/lib-es5/bundler.js +496 -0
- package/lib-es5/chmod.js +15 -0
- package/lib-es5/colors.js +12 -0
- package/lib-es5/commands.js +376 -0
- package/lib-es5/common.js +328 -0
- package/lib-es5/compress_type.js +10 -0
- package/lib-es5/config.js +291 -0
- package/lib-es5/detector.js +421 -0
- package/lib-es5/esm-hooks.js +366 -0
- package/lib-es5/esm-resolver.js +292 -0
- package/lib-es5/esm-transformer.js +378 -0
- package/lib-es5/exports-resolver.js +184 -0
- package/lib-es5/external-artifacts.js +170 -0
- package/lib-es5/fabricator.js +137 -0
- package/lib-es5/follow.js +190 -0
- package/lib-es5/help.js +52 -0
- package/lib-es5/index.d.ts +2 -0
- package/lib-es5/index.js +552 -0
- package/lib-es5/log.js +7 -0
- package/lib-es5/mach-o.js +262 -0
- package/lib-es5/manifest.js +21 -0
- package/lib-es5/options.js +19 -0
- package/lib-es5/packager.js +1036 -0
- package/lib-es5/packer.js +137 -0
- package/lib-es5/pe-metadata.js +130 -0
- package/lib-es5/producer.js +378 -0
- package/lib-es5/refiner.js +87 -0
- package/lib-es5/resolver.js +142 -0
- package/lib-es5/runtime-diagnostics.js +172 -0
- package/lib-es5/sea.js +307 -0
- package/lib-es5/snapshot-fs-patch.js +396 -0
- package/lib-es5/snapshot-fs.js +255 -0
- package/lib-es5/snapshot-index.js +135 -0
- package/lib-es5/snapshot-path.js +168 -0
- package/lib-es5/types.js +9 -0
- package/lib-es5/walker.js +1019 -0
- package/lib-es5/windows-sign.js +139 -0
- package/package.json +99 -0
- package/prelude/bootstrap.js +2263 -0
- package/prelude/diagnostic.js +147 -0
|
@@ -0,0 +1,1036 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Hakobu Packager
|
|
4
|
+
*
|
|
5
|
+
* End-to-end packaging: project → analysis → executable.
|
|
6
|
+
*
|
|
7
|
+
* Uses the new manifest/analyzer for project analysis, then bridges
|
|
8
|
+
* into the inherited producer/packer for binary assembly. This is the
|
|
9
|
+
* pragmatic approach: the new analysis layers feed into the proven
|
|
10
|
+
* binary injection mechanism.
|
|
11
|
+
*/
|
|
12
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
13
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
14
|
+
};
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.packageApp = exports.packageMultiple = void 0;
|
|
17
|
+
const fs_1 = __importDefault(require("fs"));
|
|
18
|
+
const os_1 = __importDefault(require("os"));
|
|
19
|
+
const path_1 = __importDefault(require("path"));
|
|
20
|
+
const child_process_1 = require("child_process");
|
|
21
|
+
const hakobu_fetch_1 = require("@hakobu/hakobu-fetch");
|
|
22
|
+
const analyzer_1 = require("./analyzer");
|
|
23
|
+
const bundler_1 = require("./bundler");
|
|
24
|
+
const fabricator_1 = require("./fabricator");
|
|
25
|
+
const log_1 = require("./log");
|
|
26
|
+
const common_1 = require("./common");
|
|
27
|
+
const packer_1 = __importDefault(require("./packer"));
|
|
28
|
+
const producer_1 = __importDefault(require("./producer"));
|
|
29
|
+
const compress_type_1 = require("./compress_type");
|
|
30
|
+
const chmod_1 = require("./chmod");
|
|
31
|
+
const mach_o_1 = require("./mach-o");
|
|
32
|
+
const windows_sign_1 = require("./windows-sign");
|
|
33
|
+
const pe_metadata_1 = require("./pe-metadata");
|
|
34
|
+
const app_bundle_1 = require("./app-bundle");
|
|
35
|
+
const appdir_1 = require("./appdir");
|
|
36
|
+
function prepareBaseBinary(targetSpec, binaryPath) {
|
|
37
|
+
if (targetSpec.platform !== 'macos') {
|
|
38
|
+
return { effectiveBinaryPath: binaryPath, cleanup: () => { } };
|
|
39
|
+
}
|
|
40
|
+
const tmpDir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'hakobu-base-'));
|
|
41
|
+
const stripped = path_1.default.join(tmpDir, path_1.default.basename(binaryPath) + '.unsigned');
|
|
42
|
+
fs_1.default.copyFileSync(binaryPath, stripped);
|
|
43
|
+
try {
|
|
44
|
+
(0, child_process_1.execFileSync)('codesign', ['--remove-signature', stripped], { stdio: 'pipe' });
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// Some cache entries are already unsigned; stripping is best-effort.
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
effectiveBinaryPath: stripped,
|
|
51
|
+
cleanup: () => {
|
|
52
|
+
try {
|
|
53
|
+
fs_1.default.rmSync(tmpDir, { recursive: true, force: true });
|
|
54
|
+
}
|
|
55
|
+
catch { }
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
60
|
+
// Multi-target packaging
|
|
61
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
62
|
+
const ALL_TARGETS = [
|
|
63
|
+
'node24-linux-x64', 'node24-linux-arm64', 'node24-win-x64', 'node24-win-arm64',
|
|
64
|
+
'node24-macos-arm64', 'node24-macos-x64', 'node24-linuxstatic-x64',
|
|
65
|
+
];
|
|
66
|
+
async function packageMultiple(options) {
|
|
67
|
+
const { projectRoot } = options;
|
|
68
|
+
const outputDir = path_1.default.resolve(options.outputDir || '.');
|
|
69
|
+
// Expand 'all' target
|
|
70
|
+
const targetSpecs = options.targets.flatMap(t => t === 'all' ? ALL_TARGETS : t.split(',')).filter(Boolean);
|
|
71
|
+
if (targetSpecs.length === 0) {
|
|
72
|
+
throw new Error('No targets specified.');
|
|
73
|
+
}
|
|
74
|
+
// Single target → delegate to packageApp for backward compat
|
|
75
|
+
if (targetSpecs.length === 1) {
|
|
76
|
+
const result = await packageApp({
|
|
77
|
+
...options,
|
|
78
|
+
target: targetSpecs[0],
|
|
79
|
+
output: path_1.default.join(outputDir, defaultOutputName(appIdFromProject(projectRoot), parseTarget(targetSpecs[0]))),
|
|
80
|
+
});
|
|
81
|
+
return [{
|
|
82
|
+
target: result.target,
|
|
83
|
+
status: 'success',
|
|
84
|
+
outputPath: result.outputPath,
|
|
85
|
+
fileCount: result.fileCount,
|
|
86
|
+
}];
|
|
87
|
+
}
|
|
88
|
+
log_1.log.info(`Multi-target packaging: ${targetSpecs.length} targets`);
|
|
89
|
+
// ── Shared step: bundle (if requested) ──
|
|
90
|
+
let effectiveRoot = projectRoot;
|
|
91
|
+
let effectiveOptions = { ...options };
|
|
92
|
+
let bundleOutput = null;
|
|
93
|
+
if (options.bundle) {
|
|
94
|
+
log_1.log.info('Bundling project (shared across all targets)...');
|
|
95
|
+
const bundlerName = typeof options.bundle === 'string' ? options.bundle : 'rolldown';
|
|
96
|
+
const adapter = (0, bundler_1.getAdapter)(bundlerName);
|
|
97
|
+
const entry = options.entry || resolveEntryForBundle(projectRoot);
|
|
98
|
+
const appName = appIdFromProject(projectRoot);
|
|
99
|
+
bundleOutput = await adapter.bundle({
|
|
100
|
+
projectRoot, entry,
|
|
101
|
+
external: options.bundleExternal,
|
|
102
|
+
appName,
|
|
103
|
+
});
|
|
104
|
+
for (const w of bundleOutput.warnings) {
|
|
105
|
+
log_1.log.warn(`[bundle] ${w.message}`);
|
|
106
|
+
}
|
|
107
|
+
effectiveRoot = bundleOutput.projectRoot;
|
|
108
|
+
const bundleAssets = [
|
|
109
|
+
...(options.assets || []),
|
|
110
|
+
...bundleOutput.mapFiles,
|
|
111
|
+
];
|
|
112
|
+
effectiveOptions = {
|
|
113
|
+
...effectiveOptions,
|
|
114
|
+
entry: undefined,
|
|
115
|
+
assets: bundleAssets.length > 0 ? bundleAssets : undefined,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
// ── Shared step: analyze ──
|
|
119
|
+
log_1.log.info('Analyzing project (shared across all targets)...');
|
|
120
|
+
const manifest = await (0, analyzer_1.analyze)({
|
|
121
|
+
projectRoot: effectiveRoot,
|
|
122
|
+
entry: effectiveOptions.entry,
|
|
123
|
+
assets: effectiveOptions.assets,
|
|
124
|
+
externals: effectiveOptions.externals,
|
|
125
|
+
});
|
|
126
|
+
log_1.log.info(` entry: ${manifest.entry.snapshotPath} (${manifest.entry.format})`);
|
|
127
|
+
log_1.log.info(` files: ${Object.keys(manifest.files).length}`);
|
|
128
|
+
// ── Pre-fetch: download all base binaries in parallel ──
|
|
129
|
+
// Each target has a unique platform-arch, so no cache file races.
|
|
130
|
+
const parsedTargets = targetSpecs.map(spec => ({
|
|
131
|
+
spec,
|
|
132
|
+
...parseTarget(spec),
|
|
133
|
+
}));
|
|
134
|
+
log_1.log.info(`\nFetching ${parsedTargets.length} base binaries...`);
|
|
135
|
+
const fetchResults = await Promise.allSettled(parsedTargets.map(t => (0, hakobu_fetch_1.need)({ nodeRange: t.nodeRange, platform: t.platform, arch: t.arch, forceBuild: options.forceBuild })
|
|
136
|
+
.then(binaryPath => {
|
|
137
|
+
log_1.log.info(` fetched: ${t.platform}-${t.arch}`);
|
|
138
|
+
return binaryPath;
|
|
139
|
+
})));
|
|
140
|
+
// Map fetch results by spec for lookup during per-target assembly
|
|
141
|
+
const fetchedBinaries = new Map();
|
|
142
|
+
for (let i = 0; i < parsedTargets.length; i++) {
|
|
143
|
+
const result = fetchResults[i];
|
|
144
|
+
if (result.status === 'fulfilled') {
|
|
145
|
+
fetchedBinaries.set(parsedTargets[i].spec, result.value);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// ── Per-target: pack, produce ──
|
|
149
|
+
fs_1.default.mkdirSync(outputDir, { recursive: true });
|
|
150
|
+
const results = [];
|
|
151
|
+
for (const spec of targetSpecs) {
|
|
152
|
+
const targetSpec = parseTarget(spec);
|
|
153
|
+
const outputName = defaultOutputName(manifest.appId, targetSpec);
|
|
154
|
+
const outputPath = path_1.default.join(outputDir, outputName);
|
|
155
|
+
log_1.log.info(`\n [${targetSpec.platform}-${targetSpec.arch}]`);
|
|
156
|
+
// Check if fetch succeeded for this target
|
|
157
|
+
const prefetchedBinary = fetchedBinaries.get(spec);
|
|
158
|
+
if (!prefetchedBinary) {
|
|
159
|
+
const fetchResult = fetchResults[targetSpecs.indexOf(spec)];
|
|
160
|
+
const fetchError = fetchResult.status === 'rejected' ? fetchResult.reason?.message : 'unknown';
|
|
161
|
+
results.push({
|
|
162
|
+
target: targetSpec,
|
|
163
|
+
status: 'failed',
|
|
164
|
+
outputPath,
|
|
165
|
+
fileCount: 0,
|
|
166
|
+
error: `Base binary fetch failed: ${fetchError}`,
|
|
167
|
+
});
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
try {
|
|
171
|
+
const result = await packageAppForTarget(effectiveRoot, manifest, targetSpec, outputPath, effectiveOptions);
|
|
172
|
+
const sizeMB = fs_1.default.existsSync(result.outputPath)
|
|
173
|
+
? (fs_1.default.statSync(result.outputPath).size / 1024 / 1024).toFixed(0) + ' MB'
|
|
174
|
+
: '';
|
|
175
|
+
results.push({
|
|
176
|
+
target: targetSpec,
|
|
177
|
+
status: 'success',
|
|
178
|
+
outputPath: result.outputPath,
|
|
179
|
+
fileCount: result.fileCount,
|
|
180
|
+
sizeMB,
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
catch (err) {
|
|
184
|
+
results.push({
|
|
185
|
+
target: targetSpec,
|
|
186
|
+
status: 'failed',
|
|
187
|
+
outputPath,
|
|
188
|
+
fileCount: 0,
|
|
189
|
+
error: err.message,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
// Clean up bundle
|
|
194
|
+
if (bundleOutput)
|
|
195
|
+
bundleOutput.cleanup();
|
|
196
|
+
// Summary table
|
|
197
|
+
log_1.log.info('\n=== Packaging Results ===\n');
|
|
198
|
+
for (const r of results) {
|
|
199
|
+
const label = `${r.target.platform}-${r.target.arch}`;
|
|
200
|
+
if (r.status === 'success') {
|
|
201
|
+
log_1.log.info(` OK ${label.padEnd(20)} → ${r.outputPath} (${r.sizeMB})`);
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
log_1.log.error(` FAIL ${label.padEnd(20)} ${r.error}`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
const ok = results.filter(r => r.status === 'success').length;
|
|
208
|
+
const fail = results.filter(r => r.status === 'failed').length;
|
|
209
|
+
log_1.log.info(`\n${ok} succeeded, ${fail} failed`);
|
|
210
|
+
return results;
|
|
211
|
+
}
|
|
212
|
+
exports.packageMultiple = packageMultiple;
|
|
213
|
+
/**
|
|
214
|
+
* Package a single target using a pre-analyzed manifest.
|
|
215
|
+
* This is the per-target inner loop for multi-target packaging.
|
|
216
|
+
*/
|
|
217
|
+
async function packageAppForTarget(projectRoot, manifest, targetSpec, outputPath, options) {
|
|
218
|
+
// Fetch base binary
|
|
219
|
+
const binaryPath = await (0, hakobu_fetch_1.need)({
|
|
220
|
+
nodeRange: targetSpec.nodeRange,
|
|
221
|
+
platform: targetSpec.platform,
|
|
222
|
+
arch: targetSpec.arch,
|
|
223
|
+
forceBuild: options.forceBuild,
|
|
224
|
+
});
|
|
225
|
+
const preparedBase = prepareBaseBinary(targetSpec, binaryPath);
|
|
226
|
+
try {
|
|
227
|
+
// Build payload
|
|
228
|
+
const { records, entrypoint, symLinks } = manifestToRecords(manifest, options.bytecode);
|
|
229
|
+
const slash = targetSpec.platform === 'win' ? '\\' : '/';
|
|
230
|
+
const backpack = (0, packer_1.default)({ records, entrypoint, bytecode: !!options.bytecode, symLinks });
|
|
231
|
+
// In app-bundle/appdir mode, write the raw executable to a temp path
|
|
232
|
+
const usesTempOutput = (options.appBundle && targetSpec.platform === 'macos')
|
|
233
|
+
|| (options.appDir && (0, appdir_1.isLinuxPlatform)(targetSpec.platform));
|
|
234
|
+
const producerOutput = usesTempOutput
|
|
235
|
+
? path_1.default.join(os_1.default.tmpdir(), `hakobu-wrap-${manifest.appId}-${Date.now()}`)
|
|
236
|
+
: outputPath;
|
|
237
|
+
fs_1.default.mkdirSync(path_1.default.dirname(path_1.default.resolve(producerOutput)), { recursive: true });
|
|
238
|
+
const target = {
|
|
239
|
+
nodeRange: targetSpec.nodeRange,
|
|
240
|
+
platform: targetSpec.platform,
|
|
241
|
+
arch: targetSpec.arch,
|
|
242
|
+
binaryPath: preparedBase.effectiveBinaryPath,
|
|
243
|
+
output: path_1.default.resolve(producerOutput),
|
|
244
|
+
fabricator: {
|
|
245
|
+
nodeRange: targetSpec.nodeRange,
|
|
246
|
+
platform: hakobu_fetch_1.system.hostPlatform,
|
|
247
|
+
arch: hakobu_fetch_1.system.hostArch,
|
|
248
|
+
// For bytecode compilation, the fabricator must use the patched base binary
|
|
249
|
+
// (which has sourceless: true support). For source-only mode, it doesn't matter
|
|
250
|
+
// because STORE_BLOB stripes are removed by the packer.
|
|
251
|
+
binaryPath: options.bytecode ? binaryPath : process.execPath,
|
|
252
|
+
output: '',
|
|
253
|
+
fabricator: null,
|
|
254
|
+
},
|
|
255
|
+
};
|
|
256
|
+
log_1.log.debug(`Producer input:`, [
|
|
257
|
+
` target: ${JSON.stringify(target.output)}`,
|
|
258
|
+
` bakes: ${JSON.stringify(options.options || [])}`,
|
|
259
|
+
` compress: ${options.compress || 'none'}`,
|
|
260
|
+
` stripes: ${backpack.stripes.length}`,
|
|
261
|
+
]);
|
|
262
|
+
await (0, producer_1.default)({
|
|
263
|
+
backpack, bakes: options.options || [], slash, target, symLinks,
|
|
264
|
+
doCompress: resolveCompressType(options.compress), nativeBuild: false,
|
|
265
|
+
});
|
|
266
|
+
// Post-production
|
|
267
|
+
let finalOutputPath = path_1.default.resolve(outputPath);
|
|
268
|
+
if (targetSpec.platform === 'macos') {
|
|
269
|
+
// Mach-O patch is always needed (fixes __LINKEDIT after payload injection)
|
|
270
|
+
const buf = (0, mach_o_1.patchMachOExecutable)(fs_1.default.readFileSync(target.output));
|
|
271
|
+
fs_1.default.writeFileSync(target.output, buf);
|
|
272
|
+
await (0, chmod_1.plusx)(target.output);
|
|
273
|
+
if (options.appBundle) {
|
|
274
|
+
// Bundle mode: wrap first, then sign/notarize the bundle
|
|
275
|
+
finalOutputPath = (0, app_bundle_1.createAppBundle)({
|
|
276
|
+
executablePath: target.output,
|
|
277
|
+
outputPath: outputPath,
|
|
278
|
+
appName: manifest.appId,
|
|
279
|
+
macos: options.macos,
|
|
280
|
+
});
|
|
281
|
+
try {
|
|
282
|
+
(0, mach_o_1.signAppBundle)(finalOutputPath, options.signIdentity);
|
|
283
|
+
}
|
|
284
|
+
catch { }
|
|
285
|
+
if (options.notarize) {
|
|
286
|
+
await (0, mach_o_1.notarizeAppBundle)({ executable: finalOutputPath });
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
// Raw executable mode: sign/notarize the executable directly
|
|
291
|
+
try {
|
|
292
|
+
(0, mach_o_1.signMachOExecutable)(target.output, options.signIdentity);
|
|
293
|
+
}
|
|
294
|
+
catch { }
|
|
295
|
+
if (options.notarize) {
|
|
296
|
+
await (0, mach_o_1.notarizeMachOExecutable)({ executable: target.output });
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
else if (targetSpec.platform === 'win') {
|
|
301
|
+
// Metadata injection must happen BEFORE signing
|
|
302
|
+
if (options.metadata) {
|
|
303
|
+
await (0, pe_metadata_1.injectPeMetadata)(target.output, options.metadata);
|
|
304
|
+
}
|
|
305
|
+
if ((0, windows_sign_1.hasWindowsSigningCredentials)(options.winCertPath)) {
|
|
306
|
+
(0, windows_sign_1.signWindowsExecutable)({
|
|
307
|
+
executable: target.output,
|
|
308
|
+
certPath: options.winCertPath,
|
|
309
|
+
certPassword: options.winCertPassword,
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
await (0, chmod_1.plusx)(target.output);
|
|
315
|
+
// AppDir wrapping (Linux only, opt-in)
|
|
316
|
+
if (options.appDir && (0, appdir_1.isLinuxPlatform)(targetSpec.platform)) {
|
|
317
|
+
const appDirPath = (0, appdir_1.createAppDir)({
|
|
318
|
+
executablePath: target.output,
|
|
319
|
+
outputPath: outputPath,
|
|
320
|
+
appName: manifest.appId,
|
|
321
|
+
linux: options.linux,
|
|
322
|
+
});
|
|
323
|
+
if (options.appImage) {
|
|
324
|
+
// AppImage: build from AppDir, then clean up the AppDir
|
|
325
|
+
finalOutputPath = (0, appdir_1.createAppImage)({
|
|
326
|
+
appDirPath,
|
|
327
|
+
outputPath: outputPath,
|
|
328
|
+
arch: targetSpec.arch,
|
|
329
|
+
});
|
|
330
|
+
try {
|
|
331
|
+
fs_1.default.rmSync(appDirPath, { recursive: true, force: true });
|
|
332
|
+
}
|
|
333
|
+
catch { }
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
finalOutputPath = appDirPath;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
// Kill fabricator child processes (bytecode compilation spawns long-lived workers)
|
|
341
|
+
(0, fabricator_1.shutdown)();
|
|
342
|
+
return {
|
|
343
|
+
outputPath: finalOutputPath,
|
|
344
|
+
manifest,
|
|
345
|
+
fileCount: Object.keys(manifest.files).length,
|
|
346
|
+
target: targetSpec,
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
finally {
|
|
350
|
+
preparedBase.cleanup();
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
function appIdFromProject(projectRoot) {
|
|
354
|
+
const pkgJsonPath = path_1.default.join(projectRoot, 'package.json');
|
|
355
|
+
if (fs_1.default.existsSync(pkgJsonPath)) {
|
|
356
|
+
try {
|
|
357
|
+
const pkg = JSON.parse(fs_1.default.readFileSync(pkgJsonPath, 'utf8'));
|
|
358
|
+
return pkg.name || 'app';
|
|
359
|
+
}
|
|
360
|
+
catch { }
|
|
361
|
+
}
|
|
362
|
+
return 'app';
|
|
363
|
+
}
|
|
364
|
+
function defaultOutputName(appId, target) {
|
|
365
|
+
const ext = target.platform === 'win' ? '.exe' : '';
|
|
366
|
+
return `${appId}-${target.platform}-${target.arch}${ext}`;
|
|
367
|
+
}
|
|
368
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
369
|
+
// Core package function (single target — unchanged)
|
|
370
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
371
|
+
async function packageApp(options) {
|
|
372
|
+
// ── App bundle validation ──
|
|
373
|
+
if (options.appBundle) {
|
|
374
|
+
const targetSpec = parseTarget(options.target || '');
|
|
375
|
+
if (targetSpec.platform !== 'macos') {
|
|
376
|
+
throw new Error(`--app-bundle is only supported for macOS targets (got ${targetSpec.platform}).\n` +
|
|
377
|
+
'macOS .app bundles require a Mach-O executable.');
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
// ── AppImage implies AppDir ──
|
|
381
|
+
if (options.appImage) {
|
|
382
|
+
options.appDir = true;
|
|
383
|
+
}
|
|
384
|
+
// ── AppDir validation ──
|
|
385
|
+
if (options.appDir) {
|
|
386
|
+
const targetSpec = parseTarget(options.target || '');
|
|
387
|
+
if (!(0, appdir_1.isLinuxPlatform)(targetSpec.platform)) {
|
|
388
|
+
throw new Error(`--appdir is only supported for Linux targets (got ${targetSpec.platform}).\n` +
|
|
389
|
+
'AppDir requires an ELF executable.');
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
// ── Bytecode mode validation ──
|
|
393
|
+
if (options.bytecode && options.bundle) {
|
|
394
|
+
throw new Error('Bytecode mode (--bytecode) cannot be combined with bundle mode (--bundle).\n' +
|
|
395
|
+
'Bundle mode produces ESM output which is not compatible with V8 bytecode compilation.\n' +
|
|
396
|
+
'Use one or the other, not both.');
|
|
397
|
+
}
|
|
398
|
+
let { projectRoot } = options;
|
|
399
|
+
let bundleOutput = null;
|
|
400
|
+
// ── 0. Bundle mode (optional pre-processing) ──
|
|
401
|
+
if (options.bundle) {
|
|
402
|
+
log_1.log.info('Bundling project...');
|
|
403
|
+
const bundlerName = typeof options.bundle === 'string' ? options.bundle : 'rolldown';
|
|
404
|
+
const adapter = (0, bundler_1.getAdapter)(bundlerName);
|
|
405
|
+
// Determine entry for bundling
|
|
406
|
+
const entry = options.entry || resolveEntryForBundle(projectRoot);
|
|
407
|
+
// Determine app name from package.json
|
|
408
|
+
let appName = 'app';
|
|
409
|
+
const pkgJsonPath = path_1.default.join(projectRoot, 'package.json');
|
|
410
|
+
if (fs_1.default.existsSync(pkgJsonPath)) {
|
|
411
|
+
try {
|
|
412
|
+
const pkg = JSON.parse(fs_1.default.readFileSync(pkgJsonPath, 'utf8'));
|
|
413
|
+
appName = pkg.name || 'app';
|
|
414
|
+
}
|
|
415
|
+
catch { }
|
|
416
|
+
}
|
|
417
|
+
bundleOutput = await adapter.bundle({
|
|
418
|
+
projectRoot,
|
|
419
|
+
entry,
|
|
420
|
+
external: options.bundleExternal,
|
|
421
|
+
appName,
|
|
422
|
+
});
|
|
423
|
+
for (const w of bundleOutput.warnings) {
|
|
424
|
+
log_1.log.warn(`[bundle] ${w.message}`);
|
|
425
|
+
}
|
|
426
|
+
// Switch to the bundled project for the rest of the pipeline
|
|
427
|
+
projectRoot = bundleOutput.projectRoot;
|
|
428
|
+
// Clear entry override — the bundle's package.json has the right main
|
|
429
|
+
// Include source map files as assets so they end up in the snapshot
|
|
430
|
+
const bundleAssets = [
|
|
431
|
+
...(options.assets || []),
|
|
432
|
+
...bundleOutput.mapFiles,
|
|
433
|
+
];
|
|
434
|
+
options = { ...options, entry: undefined, assets: bundleAssets.length > 0 ? bundleAssets : undefined };
|
|
435
|
+
}
|
|
436
|
+
try {
|
|
437
|
+
return await packageAppInner(projectRoot, options, bundleOutput);
|
|
438
|
+
}
|
|
439
|
+
finally {
|
|
440
|
+
// Clean up bundle temp directory
|
|
441
|
+
if (bundleOutput)
|
|
442
|
+
bundleOutput.cleanup();
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
exports.packageApp = packageApp;
|
|
446
|
+
function resolveEntryForBundle(projectRoot) {
|
|
447
|
+
const pkgJsonPath = path_1.default.join(projectRoot, 'package.json');
|
|
448
|
+
if (fs_1.default.existsSync(pkgJsonPath)) {
|
|
449
|
+
try {
|
|
450
|
+
const pkg = JSON.parse(fs_1.default.readFileSync(pkgJsonPath, 'utf8'));
|
|
451
|
+
if (pkg.main)
|
|
452
|
+
return pkg.main;
|
|
453
|
+
if (pkg.module)
|
|
454
|
+
return pkg.module;
|
|
455
|
+
}
|
|
456
|
+
catch { }
|
|
457
|
+
}
|
|
458
|
+
// Fallback: common entry patterns
|
|
459
|
+
for (const candidate of ['src/index.ts', 'src/index.js', 'index.ts', 'index.js']) {
|
|
460
|
+
if (fs_1.default.existsSync(path_1.default.join(projectRoot, candidate)))
|
|
461
|
+
return candidate;
|
|
462
|
+
}
|
|
463
|
+
throw new Error('Cannot determine entry for bundling. Specify --entry.');
|
|
464
|
+
}
|
|
465
|
+
async function packageAppInner(projectRoot, options, bundleOutput) {
|
|
466
|
+
log_1.log.info('Analyzing project...');
|
|
467
|
+
// ── 1. Analyze using new manifest pipeline ──
|
|
468
|
+
const manifest = await (0, analyzer_1.analyze)({
|
|
469
|
+
projectRoot,
|
|
470
|
+
entry: options.entry,
|
|
471
|
+
assets: options.assets,
|
|
472
|
+
externals: options.externals,
|
|
473
|
+
});
|
|
474
|
+
log_1.log.info(` entry: ${manifest.entry.snapshotPath} (${manifest.entry.format})`);
|
|
475
|
+
log_1.log.info(` files: ${Object.keys(manifest.files).length}`);
|
|
476
|
+
log_1.log.debug('Manifest details:', [
|
|
477
|
+
` projectRoot: ${projectRoot}`,
|
|
478
|
+
` appId: ${manifest.appId}`,
|
|
479
|
+
` file count: ${Object.keys(manifest.files).length}`,
|
|
480
|
+
` warnings: ${manifest.warnings.length}`,
|
|
481
|
+
]);
|
|
482
|
+
if (manifest.warnings.length > 0) {
|
|
483
|
+
for (const w of manifest.warnings) {
|
|
484
|
+
if (w.severity === 'error') {
|
|
485
|
+
log_1.log.error(`[${w.category}] ${w.message}`);
|
|
486
|
+
}
|
|
487
|
+
else if (w.severity === 'warning') {
|
|
488
|
+
log_1.log.warn(`[${w.category}] ${w.message}`);
|
|
489
|
+
}
|
|
490
|
+
if (w.suggestion) {
|
|
491
|
+
log_1.log.info(` → ${w.suggestion}`);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
// ── 2. Parse target ──
|
|
496
|
+
const targetSpec = parseTarget(options.target);
|
|
497
|
+
log_1.log.info(`Target: ${targetSpec.nodeRange}-${targetSpec.platform}-${targetSpec.arch}`);
|
|
498
|
+
// ── 3. Fetch base binary ──
|
|
499
|
+
log_1.log.info('Fetching base binary...');
|
|
500
|
+
const binaryPath = await (0, hakobu_fetch_1.need)({
|
|
501
|
+
nodeRange: targetSpec.nodeRange,
|
|
502
|
+
platform: targetSpec.platform,
|
|
503
|
+
arch: targetSpec.arch,
|
|
504
|
+
forceBuild: options.forceBuild,
|
|
505
|
+
});
|
|
506
|
+
log_1.log.info(` base: ${binaryPath}`);
|
|
507
|
+
// ── 3b. Strip macOS code signature before payload injection ──
|
|
508
|
+
// The producer appends data past __LINKEDIT, which invalidates the adhoc
|
|
509
|
+
// signature and makes subsequent codesign operations fail. Stripping the
|
|
510
|
+
// signature first lets us patch + re-sign cleanly after production.
|
|
511
|
+
const preparedBase = prepareBaseBinary(targetSpec, binaryPath);
|
|
512
|
+
try {
|
|
513
|
+
// ── 4. Bridge: manifest → inherited FileRecords + Stripe format ──
|
|
514
|
+
log_1.log.info('Building payload...');
|
|
515
|
+
const { records, entrypoint, symLinks } = manifestToRecords(manifest, options.bytecode);
|
|
516
|
+
// ── 5. Pack using inherited packer ──
|
|
517
|
+
const slash = targetSpec.platform === 'win' ? '\\' : '/';
|
|
518
|
+
const backpack = (0, packer_1.default)({
|
|
519
|
+
records,
|
|
520
|
+
entrypoint,
|
|
521
|
+
bytecode: !!options.bytecode,
|
|
522
|
+
symLinks,
|
|
523
|
+
});
|
|
524
|
+
// ── 6. Build target object for producer ──
|
|
525
|
+
const requestedOutput = options.output || defaultOutputPath(manifest.appId, targetSpec);
|
|
526
|
+
// In app-bundle/appdir mode, the producer writes to a temp file; wrapper moves it in
|
|
527
|
+
const usesTempOutput = (options.appBundle && targetSpec.platform === 'macos')
|
|
528
|
+
|| (options.appDir && (0, appdir_1.isLinuxPlatform)(targetSpec.platform));
|
|
529
|
+
const outputPath = usesTempOutput
|
|
530
|
+
? path_1.default.join(os_1.default.tmpdir(), `hakobu-wrap-${manifest.appId}-${Date.now()}`)
|
|
531
|
+
: requestedOutput;
|
|
532
|
+
fs_1.default.mkdirSync(path_1.default.dirname(path_1.default.resolve(outputPath)), { recursive: true });
|
|
533
|
+
const target = {
|
|
534
|
+
nodeRange: targetSpec.nodeRange,
|
|
535
|
+
platform: targetSpec.platform,
|
|
536
|
+
arch: targetSpec.arch,
|
|
537
|
+
binaryPath: preparedBase.effectiveBinaryPath,
|
|
538
|
+
output: path_1.default.resolve(outputPath),
|
|
539
|
+
fabricator: {
|
|
540
|
+
nodeRange: targetSpec.nodeRange,
|
|
541
|
+
platform: hakobu_fetch_1.system.hostPlatform,
|
|
542
|
+
arch: hakobu_fetch_1.system.hostArch,
|
|
543
|
+
binaryPath: options.bytecode ? binaryPath : process.execPath,
|
|
544
|
+
output: '',
|
|
545
|
+
fabricator: null,
|
|
546
|
+
},
|
|
547
|
+
};
|
|
548
|
+
// ── 7. Produce executable using inherited producer ──
|
|
549
|
+
log_1.log.info(`Writing ${outputPath}...`);
|
|
550
|
+
log_1.log.debug('Producer input:', [
|
|
551
|
+
` output: ${path_1.default.resolve(outputPath)}`,
|
|
552
|
+
` bakes: ${JSON.stringify(options.options || [])}`,
|
|
553
|
+
` compress: ${options.compress || 'none'}`,
|
|
554
|
+
` bytecode: ${!!options.bytecode}`,
|
|
555
|
+
` stripes: ${backpack.stripes.length}`,
|
|
556
|
+
]);
|
|
557
|
+
await (0, producer_1.default)({
|
|
558
|
+
backpack,
|
|
559
|
+
bakes: options.options || [],
|
|
560
|
+
slash,
|
|
561
|
+
target,
|
|
562
|
+
symLinks,
|
|
563
|
+
doCompress: resolveCompressType(options.compress),
|
|
564
|
+
nativeBuild: false,
|
|
565
|
+
});
|
|
566
|
+
// ── 8. Post-production: signing + chmod ──
|
|
567
|
+
log_1.log.debug(`Post-production: platform=${targetSpec.platform}, appBundle=${!!options.appBundle}, appDir=${!!options.appDir}`);
|
|
568
|
+
let finalOutputPath = path_1.default.resolve(requestedOutput);
|
|
569
|
+
if (targetSpec.platform === 'macos') {
|
|
570
|
+
// Base was pre-stripped in step 3b, so __LINKEDIT patch + fresh sign works cleanly
|
|
571
|
+
const buf = (0, mach_o_1.patchMachOExecutable)(fs_1.default.readFileSync(target.output));
|
|
572
|
+
fs_1.default.writeFileSync(target.output, buf);
|
|
573
|
+
await (0, chmod_1.plusx)(target.output);
|
|
574
|
+
if (options.appBundle) {
|
|
575
|
+
// Bundle mode: wrap first, then sign/notarize the bundle
|
|
576
|
+
finalOutputPath = (0, app_bundle_1.createAppBundle)({
|
|
577
|
+
executablePath: target.output,
|
|
578
|
+
outputPath: requestedOutput,
|
|
579
|
+
appName: manifest.appId,
|
|
580
|
+
macos: options.macos,
|
|
581
|
+
});
|
|
582
|
+
try {
|
|
583
|
+
(0, mach_o_1.signAppBundle)(finalOutputPath, options.signIdentity);
|
|
584
|
+
}
|
|
585
|
+
catch {
|
|
586
|
+
if (targetSpec.arch === 'arm64') {
|
|
587
|
+
log_1.log.warn('Unable to sign the macOS app bundle — it may not run on ARM64.');
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
if (options.notarize) {
|
|
591
|
+
await (0, mach_o_1.notarizeAppBundle)({ executable: finalOutputPath });
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
else {
|
|
595
|
+
// Raw executable mode: sign/notarize the executable directly
|
|
596
|
+
try {
|
|
597
|
+
(0, mach_o_1.signMachOExecutable)(target.output, options.signIdentity);
|
|
598
|
+
}
|
|
599
|
+
catch {
|
|
600
|
+
if (targetSpec.arch === 'arm64') {
|
|
601
|
+
log_1.log.warn('Unable to sign the macOS executable — it may not run on ARM64.');
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
if (options.notarize) {
|
|
605
|
+
await (0, mach_o_1.notarizeMachOExecutable)({ executable: target.output });
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
else if (targetSpec.platform === 'win') {
|
|
610
|
+
// Metadata injection must happen BEFORE signing
|
|
611
|
+
if (options.metadata) {
|
|
612
|
+
await (0, pe_metadata_1.injectPeMetadata)(target.output, options.metadata);
|
|
613
|
+
}
|
|
614
|
+
if ((0, windows_sign_1.hasWindowsSigningCredentials)(options.winCertPath)) {
|
|
615
|
+
(0, windows_sign_1.signWindowsExecutable)({
|
|
616
|
+
executable: target.output,
|
|
617
|
+
certPath: options.winCertPath,
|
|
618
|
+
certPassword: options.winCertPassword,
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
else {
|
|
623
|
+
await (0, chmod_1.plusx)(target.output);
|
|
624
|
+
// AppDir wrapping (Linux only, opt-in)
|
|
625
|
+
if (options.appDir && (0, appdir_1.isLinuxPlatform)(targetSpec.platform)) {
|
|
626
|
+
const appDirPath = (0, appdir_1.createAppDir)({
|
|
627
|
+
executablePath: target.output,
|
|
628
|
+
outputPath: requestedOutput,
|
|
629
|
+
appName: manifest.appId,
|
|
630
|
+
linux: options.linux,
|
|
631
|
+
});
|
|
632
|
+
if (options.appImage) {
|
|
633
|
+
finalOutputPath = (0, appdir_1.createAppImage)({
|
|
634
|
+
appDirPath,
|
|
635
|
+
outputPath: requestedOutput,
|
|
636
|
+
arch: targetSpec.arch,
|
|
637
|
+
});
|
|
638
|
+
try {
|
|
639
|
+
fs_1.default.rmSync(appDirPath, { recursive: true, force: true });
|
|
640
|
+
}
|
|
641
|
+
catch { }
|
|
642
|
+
}
|
|
643
|
+
else {
|
|
644
|
+
finalOutputPath = appDirPath;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
(0, fabricator_1.shutdown)();
|
|
649
|
+
log_1.log.info(`Done. Packaged ${Object.keys(manifest.files).length} files → ${finalOutputPath}`);
|
|
650
|
+
return {
|
|
651
|
+
outputPath: finalOutputPath,
|
|
652
|
+
manifest,
|
|
653
|
+
fileCount: Object.keys(manifest.files).length,
|
|
654
|
+
target: targetSpec,
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
finally {
|
|
658
|
+
preparedBase.cleanup();
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
662
|
+
// Bridge: manifest → inherited FileRecords
|
|
663
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
664
|
+
function manifestToRecords(manifest, bytecode) {
|
|
665
|
+
const records = {};
|
|
666
|
+
const dirContents = new Map();
|
|
667
|
+
const isEsmEntry = manifest.entry.format === 'esm';
|
|
668
|
+
// Add all manifest files to records
|
|
669
|
+
for (const [snapshotPath, file] of Object.entries(manifest.files)) {
|
|
670
|
+
const absPath = file.absolutePath;
|
|
671
|
+
const content = fs_1.default.readFileSync(absPath);
|
|
672
|
+
const record = {
|
|
673
|
+
file: absPath,
|
|
674
|
+
body: content,
|
|
675
|
+
[common_1.STORE_CONTENT]: content,
|
|
676
|
+
[common_1.STORE_STAT]: {
|
|
677
|
+
size: content.length,
|
|
678
|
+
isFileValue: true,
|
|
679
|
+
isDirectoryValue: false,
|
|
680
|
+
isSocketValue: false,
|
|
681
|
+
isSymbolicLinkValue: false,
|
|
682
|
+
},
|
|
683
|
+
};
|
|
684
|
+
// Bytecode mode: add STORE_BLOB for CJS scripts.
|
|
685
|
+
// The fabricator will compile the source to V8 cached data.
|
|
686
|
+
// ESM scripts are NOT bytecode-compiled (vm.Script is CJS-only).
|
|
687
|
+
if (bytecode && file.kind === 'script' && file.format === 'cjs') {
|
|
688
|
+
record[common_1.STORE_BLOB] = content;
|
|
689
|
+
}
|
|
690
|
+
records[absPath] = record;
|
|
691
|
+
// Build the full directory tree — not just direct parents, but all
|
|
692
|
+
// intermediate dirs up to the project root. This is needed for CJS
|
|
693
|
+
// node_modules resolution: require('pkg') walks up directories
|
|
694
|
+
// checking node_modules/pkg, so the VFS must have directory entries
|
|
695
|
+
// at every level.
|
|
696
|
+
let dir = path_1.default.dirname(absPath);
|
|
697
|
+
if (!dirContents.has(dir))
|
|
698
|
+
dirContents.set(dir, []);
|
|
699
|
+
dirContents.get(dir).push(path_1.default.basename(absPath));
|
|
700
|
+
// Walk up and register intermediate directories as children of their parents
|
|
701
|
+
const projectRoot = fs_1.default.realpathSync(manifest.projectRoot || path_1.default.dirname(manifest.entry.absolutePath));
|
|
702
|
+
while (dir !== projectRoot && dir !== path_1.default.dirname(dir)) {
|
|
703
|
+
const parent = path_1.default.dirname(dir);
|
|
704
|
+
if (!dirContents.has(parent))
|
|
705
|
+
dirContents.set(parent, []);
|
|
706
|
+
const dirBasename = path_1.default.basename(dir);
|
|
707
|
+
if (!dirContents.get(parent).includes(dirBasename)) {
|
|
708
|
+
dirContents.get(parent).push(dirBasename);
|
|
709
|
+
}
|
|
710
|
+
dir = parent;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
// Inject CJS shim that registers ESM hooks for snapshot-aware resolution.
|
|
714
|
+
// Always needed: CJS entries may use import() to load ESM dependencies,
|
|
715
|
+
// and ESM entries need the hooks for all import resolution.
|
|
716
|
+
let entrypoint = manifest.entry.absolutePath;
|
|
717
|
+
const { shimPath, shimContent, shimDir } = buildEsmBridge(manifest, isEsmEntry);
|
|
718
|
+
records[shimPath] = {
|
|
719
|
+
file: shimPath,
|
|
720
|
+
body: shimContent,
|
|
721
|
+
[common_1.STORE_CONTENT]: shimContent,
|
|
722
|
+
[common_1.STORE_STAT]: {
|
|
723
|
+
size: shimContent.length,
|
|
724
|
+
isFileValue: true,
|
|
725
|
+
isDirectoryValue: false,
|
|
726
|
+
isSocketValue: false,
|
|
727
|
+
isSymbolicLinkValue: false,
|
|
728
|
+
},
|
|
729
|
+
};
|
|
730
|
+
entrypoint = shimPath;
|
|
731
|
+
// Add shim to its directory listing
|
|
732
|
+
if (!dirContents.has(shimDir))
|
|
733
|
+
dirContents.set(shimDir, []);
|
|
734
|
+
if (!dirContents.get(shimDir).includes(path_1.default.basename(shimPath))) {
|
|
735
|
+
dirContents.get(shimDir).push(path_1.default.basename(shimPath));
|
|
736
|
+
}
|
|
737
|
+
// Add directory records with STORE_LINKS
|
|
738
|
+
for (const [dir, files] of dirContents) {
|
|
739
|
+
if (!records[dir]) {
|
|
740
|
+
records[dir] = {
|
|
741
|
+
file: dir,
|
|
742
|
+
[common_1.STORE_LINKS]: files,
|
|
743
|
+
[common_1.STORE_STAT]: {
|
|
744
|
+
size: 0,
|
|
745
|
+
isFileValue: false,
|
|
746
|
+
isDirectoryValue: true,
|
|
747
|
+
isSocketValue: false,
|
|
748
|
+
isSymbolicLinkValue: false,
|
|
749
|
+
},
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
return { records, entrypoint, symLinks: {} };
|
|
754
|
+
}
|
|
755
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
756
|
+
// ESM Bridge
|
|
757
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
758
|
+
/**
|
|
759
|
+
* Build a CJS shim that registers ESM hooks and loads the real entry.
|
|
760
|
+
*
|
|
761
|
+
* Always injected (not just for ESM entries) because CJS code may use
|
|
762
|
+
* import() to load ESM dependencies — those calls need the snapshot-aware
|
|
763
|
+
* ESM resolver hooks to be registered first.
|
|
764
|
+
*
|
|
765
|
+
* For ESM entries: registers hooks + import()s the real entry
|
|
766
|
+
* For CJS entries: registers hooks + require()s the real entry
|
|
767
|
+
*/
|
|
768
|
+
function buildEsmBridge(manifest, isEsm = true) {
|
|
769
|
+
const entryAbsPath = manifest.entry.absolutePath;
|
|
770
|
+
const shimDir = path_1.default.dirname(entryAbsPath);
|
|
771
|
+
const shimPath = path_1.default.join(shimDir, '__hakobu_esm_shim__.cjs');
|
|
772
|
+
// Collect package.json paths for module format detection at runtime
|
|
773
|
+
const pkgJsonAbsPaths = Object.values(manifest.files)
|
|
774
|
+
.filter(f => f.kind === 'package-json')
|
|
775
|
+
.map(f => f.absolutePath);
|
|
776
|
+
const shimSource = `'use strict';
|
|
777
|
+
// Hakobu ESM Bridge — bootstraps ESM loading from the inherited CJS VFS
|
|
778
|
+
|
|
779
|
+
// Enable source maps before any module loading. The patched base binary is
|
|
780
|
+
// built with --without-node-options which ignores NODE_OPTIONS, so
|
|
781
|
+
// --enable-source-maps via env has no effect. This programmatic call
|
|
782
|
+
// ensures source maps work when .map files are present in the snapshot.
|
|
783
|
+
if (typeof process.setSourceMapsEnabled === 'function') {
|
|
784
|
+
process.setSourceMapsEnabled(true);
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
var { registerHooks } = require('node:module');
|
|
788
|
+
var fs = require('fs');
|
|
789
|
+
var pathMod = require('path');
|
|
790
|
+
var { pathToFileURL, fileURLToPath } = require('url');
|
|
791
|
+
|
|
792
|
+
// Platform detection: Windows uses C:\\snapshot, POSIX uses /snapshot
|
|
793
|
+
var isWin = process.platform === 'win32';
|
|
794
|
+
var snapRoot = isWin ? 'C:\\\\snapshot' : '/snapshot';
|
|
795
|
+
var sep = isWin ? '\\\\' : '/';
|
|
796
|
+
|
|
797
|
+
// Normalize a snapshot path to POSIX for URL/map keys (internal canonical form)
|
|
798
|
+
function toCanonical(p) {
|
|
799
|
+
if (isWin && p.startsWith('C:\\\\snapshot')) return p.slice(2).replace(/\\\\/g, '/');
|
|
800
|
+
return p;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
// Convert canonical back to native snapshot path for fs operations
|
|
804
|
+
function toNative(p) {
|
|
805
|
+
if (isWin && p.startsWith('/snapshot')) return 'C:' + p.replace(/\\//g, '\\\\');
|
|
806
|
+
return p;
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
// Read package.json data for module type detection (using patched fs)
|
|
810
|
+
// absPath is a host absolute path (e.g. /home/user/project/package.json or D:\\a\\project\\package.json)
|
|
811
|
+
// Convert to canonical snapshot path: strip drive letter, normalize to POSIX, prepend /snapshot
|
|
812
|
+
var pkgJsons = {};
|
|
813
|
+
${JSON.stringify(pkgJsonAbsPaths)}.forEach(function(absPath) {
|
|
814
|
+
var posix = absPath.replace(/\\\\/g, '/');
|
|
815
|
+
if (/^[A-Z]:/i.test(posix)) posix = posix.slice(2);
|
|
816
|
+
var canonical = '/snapshot' + posix;
|
|
817
|
+
var native = toNative(canonical);
|
|
818
|
+
try { pkgJsons[canonical] = JSON.parse(fs.readFileSync(native, 'utf8')); } catch {}
|
|
819
|
+
});
|
|
820
|
+
|
|
821
|
+
function isSnapshotUrl(url) {
|
|
822
|
+
if (url.startsWith('file:///snapshot/')) return true;
|
|
823
|
+
// Windows: file:///C:/snapshot/
|
|
824
|
+
if (isWin && /^file:\\/\\/\\/[A-Z]:\\/snapshot\\//i.test(url)) return true;
|
|
825
|
+
return false;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
function urlToCanonical(url) {
|
|
829
|
+
var p = fileURLToPath(url);
|
|
830
|
+
return toCanonical(p);
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
function canonicalToUrl(canonical) {
|
|
834
|
+
return pathToFileURL(toNative(canonical)).href;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
function getModuleFormat(canonical) {
|
|
838
|
+
if (canonical.endsWith('.mjs')) return 'module';
|
|
839
|
+
if (canonical.endsWith('.cjs')) return 'commonjs';
|
|
840
|
+
if (canonical.endsWith('.json')) return 'json';
|
|
841
|
+
var dir = canonical;
|
|
842
|
+
while (dir !== '/') {
|
|
843
|
+
dir = dir.substring(0, dir.lastIndexOf('/')) || '/';
|
|
844
|
+
var pkgPath = dir + '/package.json';
|
|
845
|
+
if (pkgJsons[pkgPath]) return pkgJsons[pkgPath].type === 'module' ? 'module' : 'commonjs';
|
|
846
|
+
}
|
|
847
|
+
return 'commonjs';
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
function snapshotExists(canonical) {
|
|
851
|
+
try { return fs.existsSync(toNative(canonical)); } catch { return false; }
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
function resolveFromSnapshot(specifier, parentCanonical) {
|
|
855
|
+
var parentDir = parentCanonical.substring(0, parentCanonical.lastIndexOf('/'));
|
|
856
|
+
var resolved;
|
|
857
|
+
if (specifier.startsWith('./') || specifier.startsWith('../')) {
|
|
858
|
+
var parts = (parentDir + '/' + specifier).split('/');
|
|
859
|
+
var normalized = [];
|
|
860
|
+
for (var i = 0; i < parts.length; i++) {
|
|
861
|
+
if (parts[i] === '..') normalized.pop();
|
|
862
|
+
else if (parts[i] !== '.' && parts[i] !== '') normalized.push(parts[i]);
|
|
863
|
+
}
|
|
864
|
+
resolved = '/' + normalized.join('/');
|
|
865
|
+
} else {
|
|
866
|
+
resolved = specifier;
|
|
867
|
+
}
|
|
868
|
+
if (snapshotExists(resolved)) return resolved;
|
|
869
|
+
if (snapshotExists(resolved + '.js')) return resolved + '.js';
|
|
870
|
+
if (snapshotExists(resolved + '.mjs')) return resolved + '.mjs';
|
|
871
|
+
if (snapshotExists(resolved + '/index.js')) return resolved + '/index.js';
|
|
872
|
+
if (snapshotExists(resolved + '/index.mjs')) return resolved + '/index.mjs';
|
|
873
|
+
return null;
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
registerHooks({
|
|
877
|
+
resolve: function(specifier, context, nextResolve) {
|
|
878
|
+
if (specifier.startsWith('node:') || specifier.startsWith('data:')) {
|
|
879
|
+
return nextResolve(specifier, context);
|
|
880
|
+
}
|
|
881
|
+
// Stub unsupported runtime-specific protocols (bun:, deno:, etc.)
|
|
882
|
+
if (specifier.startsWith('bun:') || specifier.startsWith('deno:')) {
|
|
883
|
+
return { url: 'data:text/javascript,export default undefined;export var Database=class{constructor(){throw new Error("' + specifier + ' not available")}};', shortCircuit: true };
|
|
884
|
+
}
|
|
885
|
+
// Resolve file:// URLs to snapshot paths
|
|
886
|
+
if (isSnapshotUrl(specifier)) {
|
|
887
|
+
var canonical = urlToCanonical(specifier);
|
|
888
|
+
if (snapshotExists(canonical)) {
|
|
889
|
+
return { url: canonicalToUrl(canonical), shortCircuit: true };
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
// Absolute snapshot path (POSIX)
|
|
893
|
+
if (specifier.startsWith('/snapshot/') && snapshotExists(specifier)) {
|
|
894
|
+
return { url: canonicalToUrl(specifier), shortCircuit: true };
|
|
895
|
+
}
|
|
896
|
+
// Relative/bare imports from snapshot
|
|
897
|
+
if (context.parentURL && isSnapshotUrl(context.parentURL)) {
|
|
898
|
+
var parentCanonical = urlToCanonical(context.parentURL);
|
|
899
|
+
if (specifier.startsWith('.')) {
|
|
900
|
+
var resolved = resolveFromSnapshot(specifier, parentCanonical);
|
|
901
|
+
if (resolved) return { url: canonicalToUrl(resolved), shortCircuit: true };
|
|
902
|
+
}
|
|
903
|
+
// #imports specifier — resolve from nearest package.json imports map
|
|
904
|
+
if (specifier.startsWith('#')) {
|
|
905
|
+
var dir = parentCanonical;
|
|
906
|
+
while (dir.startsWith('/snapshot/')) {
|
|
907
|
+
dir = dir.substring(0, dir.lastIndexOf('/')) || '/';
|
|
908
|
+
var pkgPath = dir + '/package.json';
|
|
909
|
+
if (pkgJsons[pkgPath] && pkgJsons[pkgPath].imports) {
|
|
910
|
+
var mapping = pkgJsons[pkgPath].imports[specifier];
|
|
911
|
+
if (typeof mapping === 'string') {
|
|
912
|
+
var target = resolveFromSnapshot(mapping, dir + '/dummy');
|
|
913
|
+
if (target) return { url: canonicalToUrl(target), shortCircuit: true };
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
// Bare specifier — resolve from node_modules with exports map support
|
|
919
|
+
if (!specifier.startsWith('.') && !specifier.startsWith('/') && !specifier.startsWith('#')) {
|
|
920
|
+
var parts = specifier.split('/');
|
|
921
|
+
var pkgName = parts[0].startsWith('@') ? parts[0] + '/' + parts[1] : parts[0];
|
|
922
|
+
var subpath = '.' + specifier.slice(pkgName.length);
|
|
923
|
+
if (subpath === '.') subpath = '.';
|
|
924
|
+
var searchDir = parentCanonical;
|
|
925
|
+
while (searchDir.startsWith('/snapshot/')) {
|
|
926
|
+
searchDir = searchDir.substring(0, searchDir.lastIndexOf('/')) || '/';
|
|
927
|
+
var nmPkgJson = searchDir + '/node_modules/' + pkgName + '/package.json';
|
|
928
|
+
if (pkgJsons[nmPkgJson]) {
|
|
929
|
+
var pkg = pkgJsons[nmPkgJson];
|
|
930
|
+
var pkgDir = nmPkgJson.substring(0, nmPkgJson.lastIndexOf('/'));
|
|
931
|
+
var resolved = null;
|
|
932
|
+
if (pkg.exports) {
|
|
933
|
+
var exportEntry = null;
|
|
934
|
+
if (typeof pkg.exports === 'string') {
|
|
935
|
+
if (subpath === '.') exportEntry = pkg.exports;
|
|
936
|
+
} else if (typeof pkg.exports === 'object') {
|
|
937
|
+
exportEntry = pkg.exports[subpath];
|
|
938
|
+
if (typeof exportEntry === 'object' && exportEntry !== null) {
|
|
939
|
+
exportEntry = exportEntry.import || exportEntry.node || exportEntry.default || null;
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
if (typeof exportEntry === 'string') {
|
|
943
|
+
resolved = resolveFromSnapshot(exportEntry, pkgDir + '/dummy');
|
|
944
|
+
}
|
|
945
|
+
} else if (subpath === '.' && pkg.main) {
|
|
946
|
+
resolved = resolveFromSnapshot('./' + pkg.main, pkgDir + '/dummy');
|
|
947
|
+
}
|
|
948
|
+
if (resolved) return { url: canonicalToUrl(resolved), shortCircuit: true };
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
return nextResolve(specifier, context);
|
|
954
|
+
},
|
|
955
|
+
load: function(url, context, nextLoad) {
|
|
956
|
+
if (isSnapshotUrl(url)) {
|
|
957
|
+
var canonical = urlToCanonical(url);
|
|
958
|
+
try {
|
|
959
|
+
var source = fs.readFileSync(toNative(canonical), 'utf8');
|
|
960
|
+
var format = getModuleFormat(canonical);
|
|
961
|
+
// Inline sidecar source maps so --enable-source-maps works in packaged mode.
|
|
962
|
+
// Node reads source maps from the source text, not from separate fs reads,
|
|
963
|
+
// when the map is a data: URL. This avoids depending on Node internals
|
|
964
|
+
// reading .map files through the prelude's patched fs.
|
|
965
|
+
var mapMatch = source.match(/\\/\\/# sourceMappingURL=([^\\n]+\\.map)\\s*$/);
|
|
966
|
+
if (mapMatch) {
|
|
967
|
+
var mapFile = mapMatch[1];
|
|
968
|
+
var mapCanonical = canonical.substring(0, canonical.lastIndexOf('/') + 1) + mapFile;
|
|
969
|
+
try {
|
|
970
|
+
var mapData = fs.readFileSync(toNative(mapCanonical), 'utf8');
|
|
971
|
+
var mapBase64 = Buffer.from(mapData).toString('base64');
|
|
972
|
+
source = source.replace(
|
|
973
|
+
mapMatch[0],
|
|
974
|
+
'//# sourceMappingURL=data:application/json;base64,' + mapBase64
|
|
975
|
+
);
|
|
976
|
+
} catch {}
|
|
977
|
+
}
|
|
978
|
+
return { format: format, source: source, shortCircuit: true };
|
|
979
|
+
} catch {}
|
|
980
|
+
}
|
|
981
|
+
return nextLoad(url, context);
|
|
982
|
+
}
|
|
983
|
+
});
|
|
984
|
+
|
|
985
|
+
// Load the real entry
|
|
986
|
+
var entryCanonical = '${(0, common_1.snapshotify)(entryAbsPath, '/').replace(/\\/g, '/')}';
|
|
987
|
+
${isEsm
|
|
988
|
+
? `var entryUrl = canonicalToUrl(entryCanonical);
|
|
989
|
+
import(entryUrl).catch(function(err) { console.error(err); process.exit(1); });`
|
|
990
|
+
: `require(toNative(entryCanonical));`}
|
|
991
|
+
`;
|
|
992
|
+
return {
|
|
993
|
+
shimPath,
|
|
994
|
+
shimContent: Buffer.from(shimSource),
|
|
995
|
+
shimDir,
|
|
996
|
+
};
|
|
997
|
+
}
|
|
998
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
999
|
+
// Helpers
|
|
1000
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
1001
|
+
function resolveCompressType(value) {
|
|
1002
|
+
if (!value)
|
|
1003
|
+
return compress_type_1.CompressType.None;
|
|
1004
|
+
switch (value) {
|
|
1005
|
+
case 'brotli': return compress_type_1.CompressType.Brotli;
|
|
1006
|
+
case 'gzip': return compress_type_1.CompressType.GZip;
|
|
1007
|
+
default: return compress_type_1.CompressType.None;
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
function parseTarget(spec) {
|
|
1011
|
+
if (!spec || spec === 'host') {
|
|
1012
|
+
return {
|
|
1013
|
+
nodeRange: 'node24',
|
|
1014
|
+
platform: hakobu_fetch_1.system.hostPlatform,
|
|
1015
|
+
arch: hakobu_fetch_1.system.hostArch,
|
|
1016
|
+
};
|
|
1017
|
+
}
|
|
1018
|
+
const parts = spec.split('-');
|
|
1019
|
+
let nodeRange = 'node24';
|
|
1020
|
+
let platform = hakobu_fetch_1.system.hostPlatform;
|
|
1021
|
+
let arch = hakobu_fetch_1.system.hostArch;
|
|
1022
|
+
for (const part of parts) {
|
|
1023
|
+
if (part.startsWith('node'))
|
|
1024
|
+
nodeRange = part;
|
|
1025
|
+
else if (['linux', 'macos', 'win', 'alpine', 'linuxstatic'].includes(part))
|
|
1026
|
+
platform = part;
|
|
1027
|
+
else if (['x64', 'arm64'].includes(part))
|
|
1028
|
+
arch = part;
|
|
1029
|
+
}
|
|
1030
|
+
return { nodeRange, platform, arch };
|
|
1031
|
+
}
|
|
1032
|
+
function defaultOutputPath(appId, target) {
|
|
1033
|
+
const ext = target.platform === 'win' ? '.exe' : '';
|
|
1034
|
+
return path_1.default.resolve(`${appId}-${target.platform}-${target.arch}${ext}`);
|
|
1035
|
+
}
|
|
1036
|
+
//# sourceMappingURL=packager.js.map
|