@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,376 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Hakobu diagnostic and inspection commands.
|
|
4
|
+
*
|
|
5
|
+
* These answer the questions developers ask before, during, and after packaging:
|
|
6
|
+
* - targets: What can I build for? What base binaries are cached?
|
|
7
|
+
* - inspect: What does Hakobu see in my project?
|
|
8
|
+
* - doctor: Is my project ready to package? What's wrong?
|
|
9
|
+
*/
|
|
10
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
11
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
12
|
+
};
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.commandDoctor = exports.commandInspect = exports.commandTargets = void 0;
|
|
15
|
+
const fs_1 = __importDefault(require("fs"));
|
|
16
|
+
const path_1 = __importDefault(require("path"));
|
|
17
|
+
const promises_1 = require("fs/promises");
|
|
18
|
+
const hakobu_fetch_1 = require("@hakobu/hakobu-fetch");
|
|
19
|
+
// These are internal to hakobu-fetch but we import the compiled JS
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
21
|
+
const { EXPECTED_HASHES } = require('@hakobu/hakobu-fetch/lib-es5/expected');
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
23
|
+
const { localPlace } = require('@hakobu/hakobu-fetch/lib-es5/places');
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
25
|
+
const fetchPkg = require('@hakobu/hakobu-fetch/package.json');
|
|
26
|
+
const analyzer_1 = require("./analyzer");
|
|
27
|
+
const { hostArch, hostPlatform, knownArchs, knownPlatforms, } = hakobu_fetch_1.system;
|
|
28
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
29
|
+
// Shared formatting
|
|
30
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
31
|
+
function bold(s) { return `\x1b[1m${s}\x1b[0m`; }
|
|
32
|
+
function green(s) { return `\x1b[32m${s}\x1b[0m`; }
|
|
33
|
+
function yellow(s) { return `\x1b[33m${s}\x1b[0m`; }
|
|
34
|
+
function red(s) { return `\x1b[31m${s}\x1b[0m`; }
|
|
35
|
+
function dim(s) { return `\x1b[2m${s}\x1b[0m`; }
|
|
36
|
+
function severityIcon(s) {
|
|
37
|
+
if (s === 'error')
|
|
38
|
+
return red('x');
|
|
39
|
+
if (s === 'warning')
|
|
40
|
+
return yellow('!');
|
|
41
|
+
return dim('i');
|
|
42
|
+
}
|
|
43
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
44
|
+
// hakobu targets
|
|
45
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
46
|
+
async function commandTargets() {
|
|
47
|
+
const nodeVersion = (0, hakobu_fetch_1.getNodeVersion)('node24');
|
|
48
|
+
const fetchVersion = fetchPkg.version;
|
|
49
|
+
console.log(bold('Hakobu Targets'));
|
|
50
|
+
console.log();
|
|
51
|
+
// Host
|
|
52
|
+
console.log(` Host: ${bold(`${hostPlatform}-${hostArch}`)} (Node ${process.version})`);
|
|
53
|
+
console.log(` Base: Node ${nodeVersion}`);
|
|
54
|
+
console.log();
|
|
55
|
+
// Published targets from expected-shas.json
|
|
56
|
+
const published = [];
|
|
57
|
+
for (const name of Object.keys(EXPECTED_HASHES)) {
|
|
58
|
+
// name format: hakobu-base-v24.14.0-linux-x64
|
|
59
|
+
const match = name.match(/^hakobu-base-(v[\d.]+)-([a-z]+)-([a-z0-9]+)$/);
|
|
60
|
+
if (!match)
|
|
61
|
+
continue;
|
|
62
|
+
const [, , platform, arch] = match;
|
|
63
|
+
// Check cache
|
|
64
|
+
const cachedPath = localPlace({
|
|
65
|
+
from: 'fetched',
|
|
66
|
+
arch,
|
|
67
|
+
nodeVersion,
|
|
68
|
+
platform,
|
|
69
|
+
version: fetchVersion,
|
|
70
|
+
});
|
|
71
|
+
let cached = false;
|
|
72
|
+
try {
|
|
73
|
+
const s = await (0, promises_1.stat)(cachedPath);
|
|
74
|
+
cached = s.size > 0;
|
|
75
|
+
}
|
|
76
|
+
catch { /* not cached */ }
|
|
77
|
+
published.push({ platform, arch, name, cached });
|
|
78
|
+
}
|
|
79
|
+
// Sort: host target first, then alphabetical
|
|
80
|
+
published.sort((a, b) => {
|
|
81
|
+
const aIsHost = a.platform === hostPlatform && a.arch === hostArch;
|
|
82
|
+
const bIsHost = b.platform === hostPlatform && b.arch === hostArch;
|
|
83
|
+
if (aIsHost && !bIsHost)
|
|
84
|
+
return -1;
|
|
85
|
+
if (!aIsHost && bIsHost)
|
|
86
|
+
return 1;
|
|
87
|
+
return `${a.platform}-${a.arch}`.localeCompare(`${b.platform}-${b.arch}`);
|
|
88
|
+
});
|
|
89
|
+
console.log(' Published base binaries:');
|
|
90
|
+
console.log();
|
|
91
|
+
for (const t of published) {
|
|
92
|
+
const isHost = t.platform === hostPlatform && t.arch === hostArch;
|
|
93
|
+
const label = `${t.platform}-${t.arch}`;
|
|
94
|
+
const hostTag = isHost ? dim(' (host)') : '';
|
|
95
|
+
const cacheTag = t.cached ? green(' cached') : dim(' remote');
|
|
96
|
+
console.log(` ${t.cached ? green('*') : ' '} ${label}${hostTag}${cacheTag}`);
|
|
97
|
+
}
|
|
98
|
+
console.log();
|
|
99
|
+
console.log(dim(' * = locally cached base binary'));
|
|
100
|
+
console.log(dim(` Cache: ${localPlace({ from: 'fetched', arch: 'x64', nodeVersion, platform: 'linux', version: fetchVersion }).replace(/fetched-.*$/, '')}`));
|
|
101
|
+
}
|
|
102
|
+
exports.commandTargets = commandTargets;
|
|
103
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
104
|
+
// hakobu inspect <projectRoot>
|
|
105
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
106
|
+
async function commandInspect(projectRoot) {
|
|
107
|
+
if (!projectRoot) {
|
|
108
|
+
console.error(red('Usage: hakobu inspect <project-root>'));
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
const resolved = path_1.default.resolve(projectRoot);
|
|
112
|
+
if (!fs_1.default.existsSync(resolved)) {
|
|
113
|
+
console.error(red(`Project root not found: ${resolved}`));
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
console.log(bold('Hakobu Project Inspection'));
|
|
117
|
+
console.log();
|
|
118
|
+
console.log(` Project: ${resolved}`);
|
|
119
|
+
let manifest;
|
|
120
|
+
try {
|
|
121
|
+
manifest = await (0, analyzer_1.analyze)({ projectRoot: resolved });
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
console.log();
|
|
125
|
+
console.log(red(` Analysis failed: ${err.message}`));
|
|
126
|
+
if (err.remediation) {
|
|
127
|
+
console.log(` Remediation: ${err.remediation}`);
|
|
128
|
+
}
|
|
129
|
+
process.exit(1);
|
|
130
|
+
}
|
|
131
|
+
// Entry
|
|
132
|
+
console.log();
|
|
133
|
+
console.log(` ${bold('Entry')}`);
|
|
134
|
+
console.log(` Path: ${manifest.entry.snapshotPath}`);
|
|
135
|
+
console.log(` Format: ${manifest.entry.format === 'esm' ? green('ESM') : 'CJS'}`);
|
|
136
|
+
console.log(` Detected: ${manifest.entry.formatSource}`);
|
|
137
|
+
// Files summary
|
|
138
|
+
const files = Object.values(manifest.files);
|
|
139
|
+
const byKind = {};
|
|
140
|
+
for (const f of files) {
|
|
141
|
+
byKind[f.kind] = (byKind[f.kind] || 0) + 1;
|
|
142
|
+
}
|
|
143
|
+
console.log();
|
|
144
|
+
console.log(` ${bold('Files')} (${files.length} total)`);
|
|
145
|
+
for (const [kind, count] of Object.entries(byKind).sort((a, b) => b[1] - a[1])) {
|
|
146
|
+
console.log(` ${kind}: ${count}`);
|
|
147
|
+
}
|
|
148
|
+
// Packages
|
|
149
|
+
const pkgs = Object.values(manifest.packages);
|
|
150
|
+
if (pkgs.length > 0) {
|
|
151
|
+
console.log();
|
|
152
|
+
console.log(` ${bold('Packages')} (${pkgs.length})`);
|
|
153
|
+
for (const pkg of pkgs.slice(0, 20)) {
|
|
154
|
+
const name = pkg.name || dim('(unnamed)');
|
|
155
|
+
const ver = pkg.version || '';
|
|
156
|
+
const type = pkg.type === 'module' ? green('ESM') : 'CJS';
|
|
157
|
+
console.log(` ${name}${ver ? `@${ver}` : ''} ${dim(type)}`);
|
|
158
|
+
}
|
|
159
|
+
if (pkgs.length > 20) {
|
|
160
|
+
console.log(dim(` ... and ${pkgs.length - 20} more`));
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// Native addons
|
|
164
|
+
if (manifest.nativeAddons.length > 0) {
|
|
165
|
+
console.log();
|
|
166
|
+
console.log(` ${bold('Native Addons')} (${manifest.nativeAddons.length})`);
|
|
167
|
+
for (const addon of manifest.nativeAddons) {
|
|
168
|
+
console.log(` ${addon.snapshotPath}`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// Externals
|
|
172
|
+
if (manifest.externals.length > 0) {
|
|
173
|
+
console.log();
|
|
174
|
+
console.log(` ${bold('External Artifacts')} (${manifest.externals.length})`);
|
|
175
|
+
for (const ext of manifest.externals) {
|
|
176
|
+
console.log(` ${ext.name} ${ext.required ? red('required') : dim('optional')}`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
// Warnings
|
|
180
|
+
printWarnings(manifest.warnings);
|
|
181
|
+
console.log();
|
|
182
|
+
}
|
|
183
|
+
exports.commandInspect = commandInspect;
|
|
184
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
185
|
+
// hakobu doctor <projectRoot>
|
|
186
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
187
|
+
async function commandDoctor(projectRoot, targetSpec) {
|
|
188
|
+
if (!projectRoot) {
|
|
189
|
+
console.error(red('Usage: hakobu doctor <project-root> [--target node24-macos-arm64]'));
|
|
190
|
+
process.exit(1);
|
|
191
|
+
}
|
|
192
|
+
const resolved = path_1.default.resolve(projectRoot);
|
|
193
|
+
if (!fs_1.default.existsSync(resolved)) {
|
|
194
|
+
console.error(red(`Project root not found: ${resolved}`));
|
|
195
|
+
process.exit(1);
|
|
196
|
+
}
|
|
197
|
+
console.log(bold('Hakobu Doctor'));
|
|
198
|
+
console.log();
|
|
199
|
+
const checks = [];
|
|
200
|
+
// Check 1: Project root has package.json
|
|
201
|
+
const pkgJsonPath = path_1.default.join(resolved, 'package.json');
|
|
202
|
+
if (fs_1.default.existsSync(pkgJsonPath)) {
|
|
203
|
+
const pkg = JSON.parse(fs_1.default.readFileSync(pkgJsonPath, 'utf8'));
|
|
204
|
+
checks.push({
|
|
205
|
+
name: 'package.json',
|
|
206
|
+
status: 'ok',
|
|
207
|
+
detail: `${pkg.name || '(unnamed)'}@${pkg.version || '0.0.0'}`,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
checks.push({
|
|
212
|
+
name: 'package.json',
|
|
213
|
+
status: 'fail',
|
|
214
|
+
detail: 'Not found. Hakobu needs a package.json to determine the project name and entry.',
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
// Check 2: Entrypoint exists
|
|
218
|
+
let manifest = null;
|
|
219
|
+
try {
|
|
220
|
+
manifest = await (0, analyzer_1.analyze)({ projectRoot: resolved });
|
|
221
|
+
checks.push({
|
|
222
|
+
name: 'Entrypoint',
|
|
223
|
+
status: 'ok',
|
|
224
|
+
detail: `${manifest.entry.snapshotPath} (${manifest.entry.format})`,
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
catch (err) {
|
|
228
|
+
checks.push({
|
|
229
|
+
name: 'Entrypoint',
|
|
230
|
+
status: 'fail',
|
|
231
|
+
detail: err.message,
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
// Check 3: Analysis warnings
|
|
235
|
+
if (manifest) {
|
|
236
|
+
const errors = manifest.warnings.filter(w => w.severity === 'error');
|
|
237
|
+
const warns = manifest.warnings.filter(w => w.severity === 'warning');
|
|
238
|
+
if (errors.length > 0) {
|
|
239
|
+
checks.push({
|
|
240
|
+
name: 'Analysis',
|
|
241
|
+
status: 'fail',
|
|
242
|
+
detail: `${errors.length} error(s): ${errors[0].message}`,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
else if (warns.length > 0) {
|
|
246
|
+
checks.push({
|
|
247
|
+
name: 'Analysis',
|
|
248
|
+
status: 'warn',
|
|
249
|
+
detail: `${warns.length} warning(s)`,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
checks.push({
|
|
254
|
+
name: 'Analysis',
|
|
255
|
+
status: 'ok',
|
|
256
|
+
detail: `${Object.keys(manifest.files).length} files, no issues`,
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
// Check 4: Target base binary
|
|
261
|
+
const target = parseTargetForDoctor(targetSpec);
|
|
262
|
+
const nodeVersion = (0, hakobu_fetch_1.getNodeVersion)('node24');
|
|
263
|
+
const fetchVersion = fetchPkg.version;
|
|
264
|
+
// Check if base is published
|
|
265
|
+
const expectedName = `hakobu-base-${nodeVersion}-${target.platform}-${target.arch}`;
|
|
266
|
+
const isPublished = !!EXPECTED_HASHES[expectedName];
|
|
267
|
+
if (isPublished) {
|
|
268
|
+
// Check if cached
|
|
269
|
+
const cachedPath = localPlace({
|
|
270
|
+
from: 'fetched',
|
|
271
|
+
arch: target.arch,
|
|
272
|
+
nodeVersion,
|
|
273
|
+
platform: target.platform,
|
|
274
|
+
version: fetchVersion,
|
|
275
|
+
});
|
|
276
|
+
let isCached = false;
|
|
277
|
+
try {
|
|
278
|
+
const s = await (0, promises_1.stat)(cachedPath);
|
|
279
|
+
isCached = s.size > 0;
|
|
280
|
+
}
|
|
281
|
+
catch { /* not cached */ }
|
|
282
|
+
if (isCached) {
|
|
283
|
+
checks.push({
|
|
284
|
+
name: `Base binary (${target.platform}-${target.arch})`,
|
|
285
|
+
status: 'ok',
|
|
286
|
+
detail: `Cached at ${cachedPath}`,
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
checks.push({
|
|
291
|
+
name: `Base binary (${target.platform}-${target.arch})`,
|
|
292
|
+
status: 'ok',
|
|
293
|
+
detail: 'Available remotely (will be fetched during packaging)',
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
checks.push({
|
|
299
|
+
name: `Base binary (${target.platform}-${target.arch})`,
|
|
300
|
+
status: 'fail',
|
|
301
|
+
detail: `No published base for ${target.platform}-${target.arch}. Available: ${Object.keys(EXPECTED_HASHES).map(n => n.replace(/^hakobu-base-v[\d.]+-/, '')).join(', ')}`,
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
// Check 5: Native addons (if any)
|
|
305
|
+
if (manifest && manifest.nativeAddons.length > 0) {
|
|
306
|
+
if (target.platform !== hostPlatform || target.arch !== hostArch) {
|
|
307
|
+
checks.push({
|
|
308
|
+
name: 'Native addons',
|
|
309
|
+
status: 'warn',
|
|
310
|
+
detail: `${manifest.nativeAddons.length} native addon(s) detected. Cross-platform packaging of native addons requires rebuilding for the target.`,
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
checks.push({
|
|
315
|
+
name: 'Native addons',
|
|
316
|
+
status: 'ok',
|
|
317
|
+
detail: `${manifest.nativeAddons.length} addon(s) — host-target match`,
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
// Print results
|
|
322
|
+
let hasFailure = false;
|
|
323
|
+
for (const check of checks) {
|
|
324
|
+
const icon = check.status === 'ok' ? green('OK') : check.status === 'warn' ? yellow('!!') : red('XX');
|
|
325
|
+
console.log(` ${icon} ${check.name}`);
|
|
326
|
+
console.log(` ${check.detail}`);
|
|
327
|
+
if (check.status === 'fail')
|
|
328
|
+
hasFailure = true;
|
|
329
|
+
}
|
|
330
|
+
// Print manifest warnings if available
|
|
331
|
+
if (manifest && manifest.warnings.length > 0) {
|
|
332
|
+
printWarnings(manifest.warnings);
|
|
333
|
+
}
|
|
334
|
+
console.log();
|
|
335
|
+
if (hasFailure) {
|
|
336
|
+
console.log(red(' Some checks failed. Fix the issues above before packaging.'));
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
console.log(green(' All checks passed. Ready to package.'));
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
exports.commandDoctor = commandDoctor;
|
|
343
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
344
|
+
// Shared helpers
|
|
345
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
346
|
+
function printWarnings(warnings) {
|
|
347
|
+
if (warnings.length === 0)
|
|
348
|
+
return;
|
|
349
|
+
console.log();
|
|
350
|
+
console.log(` ${bold('Warnings')} (${warnings.length})`);
|
|
351
|
+
for (const w of warnings) {
|
|
352
|
+
console.log(` ${severityIcon(w.severity)} [${w.category}] ${w.message}`);
|
|
353
|
+
if (w.file)
|
|
354
|
+
console.log(dim(` in ${w.file}`));
|
|
355
|
+
if (w.suggestion)
|
|
356
|
+
console.log(dim(` fix: ${w.suggestion}`));
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
function parseTargetForDoctor(spec) {
|
|
360
|
+
if (!spec) {
|
|
361
|
+
return { platform: hostPlatform, arch: hostArch };
|
|
362
|
+
}
|
|
363
|
+
const parts = spec.split('-');
|
|
364
|
+
let platform = hostPlatform;
|
|
365
|
+
let arch = hostArch;
|
|
366
|
+
for (const part of parts) {
|
|
367
|
+
if (part.startsWith('node'))
|
|
368
|
+
continue;
|
|
369
|
+
if (knownPlatforms.includes(part))
|
|
370
|
+
platform = part;
|
|
371
|
+
else if (knownArchs.includes(part))
|
|
372
|
+
arch = part;
|
|
373
|
+
}
|
|
374
|
+
return { platform, arch };
|
|
375
|
+
}
|
|
376
|
+
//# sourceMappingURL=commands.js.map
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.isESMFile = exports.isESMPackage = exports.toNormalizedRealPath = exports.removeUplevels = exports.stripSnapshot = exports.insideSnapshot = exports.snapshotify = exports.substituteDenominator = exports.retrieveDenominator = exports.unlikelyJavascript = exports.isDotNODE = exports.isDotJSON = exports.isDotJS = exports.isPackageJson = exports.normalizePath = exports.isRootPath = exports.ALIAS_AS_RESOLVABLE = exports.ALIAS_AS_RELATIVE = exports.STORE_STAT = exports.STORE_LINKS = exports.STORE_CONTENT = exports.STORE_BLOB = void 0;
|
|
7
|
+
const assert_1 = __importDefault(require("assert"));
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
exports.STORE_BLOB = 0;
|
|
11
|
+
exports.STORE_CONTENT = 1;
|
|
12
|
+
exports.STORE_LINKS = 2;
|
|
13
|
+
exports.STORE_STAT = 3;
|
|
14
|
+
exports.ALIAS_AS_RELATIVE = 0; // require("./file.js") // file or directory
|
|
15
|
+
exports.ALIAS_AS_RESOLVABLE = 1; // require("package")
|
|
16
|
+
const win32 = process.platform === 'win32';
|
|
17
|
+
const hasURL = typeof URL !== 'undefined';
|
|
18
|
+
function uppercaseDriveLetter(f) {
|
|
19
|
+
if (f.slice(1, 3) !== ':\\')
|
|
20
|
+
return f;
|
|
21
|
+
return f[0].toUpperCase() + f.slice(1);
|
|
22
|
+
}
|
|
23
|
+
function removeTrailingSlashes(f) {
|
|
24
|
+
if (f === '/') {
|
|
25
|
+
return f; // dont remove from "/"
|
|
26
|
+
}
|
|
27
|
+
if (f.slice(1) === ':\\') {
|
|
28
|
+
return f; // dont remove from "D:\"
|
|
29
|
+
}
|
|
30
|
+
let last = f.length - 1;
|
|
31
|
+
while (true) {
|
|
32
|
+
const char = f.charAt(last);
|
|
33
|
+
if (char === '\\') {
|
|
34
|
+
f = f.slice(0, -1);
|
|
35
|
+
last -= 1;
|
|
36
|
+
}
|
|
37
|
+
else if (char === '/') {
|
|
38
|
+
f = f.slice(0, -1);
|
|
39
|
+
last -= 1;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return f;
|
|
46
|
+
}
|
|
47
|
+
const isUrl = (p) => hasURL && p instanceof URL;
|
|
48
|
+
function pathToString(p, win) {
|
|
49
|
+
let result;
|
|
50
|
+
if (Buffer.isBuffer(p)) {
|
|
51
|
+
result = p.toString();
|
|
52
|
+
}
|
|
53
|
+
else if (isUrl(p)) {
|
|
54
|
+
result = win ? p.pathname.replace(/^\//, '') : p.pathname;
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
result = p;
|
|
58
|
+
}
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
function isRootPath(p) {
|
|
62
|
+
let file = pathToString(p, false);
|
|
63
|
+
if (file === '.') {
|
|
64
|
+
file = path_1.default.resolve(file);
|
|
65
|
+
}
|
|
66
|
+
return path_1.default.dirname(file) === p;
|
|
67
|
+
}
|
|
68
|
+
exports.isRootPath = isRootPath;
|
|
69
|
+
function normalizePath(f) {
|
|
70
|
+
let file = pathToString(f, win32);
|
|
71
|
+
if (!/^.:$/.test(file)) {
|
|
72
|
+
file = path_1.default.normalize(file);
|
|
73
|
+
} // 'c:' -> 'c:.'
|
|
74
|
+
if (win32) {
|
|
75
|
+
file = uppercaseDriveLetter(file);
|
|
76
|
+
}
|
|
77
|
+
return removeTrailingSlashes(file);
|
|
78
|
+
}
|
|
79
|
+
exports.normalizePath = normalizePath;
|
|
80
|
+
function isPackageJson(file) {
|
|
81
|
+
return path_1.default.basename(file) === 'package.json';
|
|
82
|
+
}
|
|
83
|
+
exports.isPackageJson = isPackageJson;
|
|
84
|
+
function isDotJS(file) {
|
|
85
|
+
return ['.js', '.cjs'].includes(path_1.default.extname(file));
|
|
86
|
+
}
|
|
87
|
+
exports.isDotJS = isDotJS;
|
|
88
|
+
function isDotJSON(file) {
|
|
89
|
+
return path_1.default.extname(file) === '.json';
|
|
90
|
+
}
|
|
91
|
+
exports.isDotJSON = isDotJSON;
|
|
92
|
+
function isDotNODE(file) {
|
|
93
|
+
return path_1.default.extname(file) === '.node';
|
|
94
|
+
}
|
|
95
|
+
exports.isDotNODE = isDotNODE;
|
|
96
|
+
function unlikelyJavascript(file) {
|
|
97
|
+
const ext = path_1.default.extname(file);
|
|
98
|
+
// Check single extensions
|
|
99
|
+
if (['.css', '.html', '.json', '.vue'].includes(ext)) {
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
// Check for .d.ts files (compound extension)
|
|
103
|
+
if (file.endsWith('.d.ts')) {
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
exports.unlikelyJavascript = unlikelyJavascript;
|
|
109
|
+
function replaceSlashes(file, slash) {
|
|
110
|
+
if (/^.:\\/.test(file)) {
|
|
111
|
+
if (slash === '/') {
|
|
112
|
+
return file.slice(2).replace(/\\/g, '/');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
else if (/^\//.test(file)) {
|
|
116
|
+
if (slash === '\\') {
|
|
117
|
+
return `C:${file.replace(/\//g, '\\')}`;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return file;
|
|
121
|
+
}
|
|
122
|
+
function injectSnapshot(file) {
|
|
123
|
+
if (/^.:\\/.test(file)) {
|
|
124
|
+
// C:\path\to
|
|
125
|
+
if (file.length === 3) {
|
|
126
|
+
// C:\
|
|
127
|
+
file = file.slice(0, -1);
|
|
128
|
+
}
|
|
129
|
+
// by convention, on windows we use C:\\snapshot
|
|
130
|
+
return `C:\\snapshot${file.slice(2)}`;
|
|
131
|
+
}
|
|
132
|
+
if (/^\//.test(file)) {
|
|
133
|
+
// /home/user/project
|
|
134
|
+
if (file.length === 1) {
|
|
135
|
+
// /
|
|
136
|
+
file = file.slice(0, -1);
|
|
137
|
+
}
|
|
138
|
+
return `/snapshot${file}`;
|
|
139
|
+
}
|
|
140
|
+
return file;
|
|
141
|
+
}
|
|
142
|
+
function longestCommonLength(s1, s2) {
|
|
143
|
+
const length = Math.min(s1.length, s2.length);
|
|
144
|
+
for (let i = 0; i < length; i += 1) {
|
|
145
|
+
if (s1.charCodeAt(i) !== s2.charCodeAt(i)) {
|
|
146
|
+
return i;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return length;
|
|
150
|
+
}
|
|
151
|
+
function withoutNodeModules(file) {
|
|
152
|
+
return file.split(`${path_1.default.sep}node_modules${path_1.default.sep}`)[0];
|
|
153
|
+
}
|
|
154
|
+
function retrieveDenominator(files) {
|
|
155
|
+
(0, assert_1.default)(files.length > 0);
|
|
156
|
+
let s1 = withoutNodeModules(files[0]) + path_1.default.sep;
|
|
157
|
+
for (let i = 1; i < files.length; i += 1) {
|
|
158
|
+
const s2 = withoutNodeModules(files[i]) + path_1.default.sep;
|
|
159
|
+
s1 = s1.slice(0, longestCommonLength(s1, s2));
|
|
160
|
+
}
|
|
161
|
+
if (s1 === '') {
|
|
162
|
+
return win32 ? 2 : 0;
|
|
163
|
+
}
|
|
164
|
+
return s1.lastIndexOf(path_1.default.sep);
|
|
165
|
+
}
|
|
166
|
+
exports.retrieveDenominator = retrieveDenominator;
|
|
167
|
+
function substituteDenominator(f, denominator) {
|
|
168
|
+
const rootLength = win32 ? 2 : 0;
|
|
169
|
+
return f.slice(0, rootLength) + f.slice(denominator);
|
|
170
|
+
}
|
|
171
|
+
exports.substituteDenominator = substituteDenominator;
|
|
172
|
+
function snapshotify(file, slash) {
|
|
173
|
+
return injectSnapshot(replaceSlashes(file, slash));
|
|
174
|
+
}
|
|
175
|
+
exports.snapshotify = snapshotify;
|
|
176
|
+
function insideSnapshot(f) {
|
|
177
|
+
f = pathToString(f, win32);
|
|
178
|
+
if (typeof f !== 'string') {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
if (win32) {
|
|
182
|
+
const slice112 = f.slice(1, 12);
|
|
183
|
+
return (slice112 === ':\\snapshot\\' ||
|
|
184
|
+
slice112 === ':/snapshot\\' ||
|
|
185
|
+
slice112 === ':\\snapshot/' ||
|
|
186
|
+
slice112 === ':/snapshot/' ||
|
|
187
|
+
slice112 === ':\\snapshot' ||
|
|
188
|
+
slice112 === ':/snapshot');
|
|
189
|
+
}
|
|
190
|
+
const slice010 = f.slice(0, 10);
|
|
191
|
+
return slice010 === '/snapshot/' || slice010 === '/snapshot';
|
|
192
|
+
}
|
|
193
|
+
exports.insideSnapshot = insideSnapshot;
|
|
194
|
+
function stripSnapshot(f) {
|
|
195
|
+
const file = normalizePath(f);
|
|
196
|
+
if (/^.:\\snapshot$/.test(file)) {
|
|
197
|
+
return `${file[0]}:\\**\\`;
|
|
198
|
+
}
|
|
199
|
+
if (/^.:\\snapshot\\/.test(file)) {
|
|
200
|
+
return `${file[0]}:\\**${file.slice(11)}`;
|
|
201
|
+
}
|
|
202
|
+
if (/^\/snapshot$/.test(file)) {
|
|
203
|
+
return '/**/';
|
|
204
|
+
}
|
|
205
|
+
if (/^\/snapshot\//.test(file)) {
|
|
206
|
+
return `/**${file.slice(9)}`;
|
|
207
|
+
}
|
|
208
|
+
return f; // not inside
|
|
209
|
+
}
|
|
210
|
+
exports.stripSnapshot = stripSnapshot;
|
|
211
|
+
function removeUplevels(f) {
|
|
212
|
+
if (win32) {
|
|
213
|
+
while (true) {
|
|
214
|
+
if (f.slice(0, 3) === '..\\') {
|
|
215
|
+
f = f.slice(3);
|
|
216
|
+
}
|
|
217
|
+
else if (f === '..') {
|
|
218
|
+
f = '.';
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return f;
|
|
225
|
+
}
|
|
226
|
+
while (true) {
|
|
227
|
+
if (f.slice(0, 3) === '../') {
|
|
228
|
+
f = f.slice(3);
|
|
229
|
+
}
|
|
230
|
+
else if (f === '..') {
|
|
231
|
+
f = '.';
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return f;
|
|
238
|
+
}
|
|
239
|
+
exports.removeUplevels = removeUplevels;
|
|
240
|
+
function toNormalizedRealPath(requestPath) {
|
|
241
|
+
const file = normalizePath(requestPath);
|
|
242
|
+
if (fs_1.default.existsSync(file)) {
|
|
243
|
+
return fs_1.default.realpathSync(file);
|
|
244
|
+
}
|
|
245
|
+
return file;
|
|
246
|
+
}
|
|
247
|
+
exports.toNormalizedRealPath = toNormalizedRealPath;
|
|
248
|
+
/**
|
|
249
|
+
* Find the nearest package.json file by walking up the directory tree
|
|
250
|
+
* @param filePath - Starting file path
|
|
251
|
+
* @returns Path to package.json or null if not found
|
|
252
|
+
*/
|
|
253
|
+
function findNearestPackageJson(filePath) {
|
|
254
|
+
let dir = path_1.default.dirname(filePath);
|
|
255
|
+
const { root } = path_1.default.parse(dir);
|
|
256
|
+
while (dir !== root) {
|
|
257
|
+
const packageJsonPath = path_1.default.join(dir, 'package.json');
|
|
258
|
+
if (fs_1.default.existsSync(packageJsonPath)) {
|
|
259
|
+
return packageJsonPath;
|
|
260
|
+
}
|
|
261
|
+
dir = path_1.default.dirname(dir);
|
|
262
|
+
}
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
// Caches for ESM detection performance optimization
|
|
266
|
+
const packageJsonCache = new Map();
|
|
267
|
+
const esmPackageCache = new Map();
|
|
268
|
+
/**
|
|
269
|
+
* Check if a package.json indicates an ESM package
|
|
270
|
+
* @param packageJsonPath - Path to package.json
|
|
271
|
+
* @returns true if "type": "module" is set
|
|
272
|
+
*/
|
|
273
|
+
function isESMPackage(packageJsonPath) {
|
|
274
|
+
// Check cache first
|
|
275
|
+
if (esmPackageCache.has(packageJsonPath)) {
|
|
276
|
+
return esmPackageCache.get(packageJsonPath);
|
|
277
|
+
}
|
|
278
|
+
try {
|
|
279
|
+
const content = fs_1.default.readFileSync(packageJsonPath, 'utf8');
|
|
280
|
+
const pkg = JSON.parse(content);
|
|
281
|
+
const result = pkg.type === 'module';
|
|
282
|
+
esmPackageCache.set(packageJsonPath, result);
|
|
283
|
+
return result;
|
|
284
|
+
}
|
|
285
|
+
catch {
|
|
286
|
+
esmPackageCache.set(packageJsonPath, false);
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
exports.isESMPackage = isESMPackage;
|
|
291
|
+
/**
|
|
292
|
+
* Determine if a file should be treated as ESM
|
|
293
|
+
* Based on file extension and nearest package.json "type" field
|
|
294
|
+
*
|
|
295
|
+
* @param filePath - The file path to check
|
|
296
|
+
* @returns true if file should be treated as ESM
|
|
297
|
+
*/
|
|
298
|
+
function isESMFile(filePath) {
|
|
299
|
+
// .mjs files are always ESM
|
|
300
|
+
if (filePath.endsWith('.mjs')) {
|
|
301
|
+
return true;
|
|
302
|
+
}
|
|
303
|
+
// .cjs files are never ESM
|
|
304
|
+
if (filePath.endsWith('.cjs')) {
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
307
|
+
// For .js files, check nearest package.json for "type": "module"
|
|
308
|
+
if (filePath.endsWith('.js')) {
|
|
309
|
+
const dir = path_1.default.dirname(filePath);
|
|
310
|
+
// Check cache first
|
|
311
|
+
if (packageJsonCache.has(dir)) {
|
|
312
|
+
const cached = packageJsonCache.get(dir);
|
|
313
|
+
if (cached) {
|
|
314
|
+
return isESMPackage(cached);
|
|
315
|
+
}
|
|
316
|
+
return false;
|
|
317
|
+
}
|
|
318
|
+
// Compute and cache
|
|
319
|
+
const packageJsonPath = findNearestPackageJson(filePath);
|
|
320
|
+
packageJsonCache.set(dir, packageJsonPath);
|
|
321
|
+
if (packageJsonPath) {
|
|
322
|
+
return isESMPackage(packageJsonPath);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
return false;
|
|
326
|
+
}
|
|
327
|
+
exports.isESMFile = isESMFile;
|
|
328
|
+
//# sourceMappingURL=common.js.map
|