aboutsummaryrefslogtreecommitdiff
path: root/node_modules/nexe/lib/fs/bundle.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/nexe/lib/fs/bundle.js')
-rw-r--r--node_modules/nexe/lib/fs/bundle.js145
1 files changed, 145 insertions, 0 deletions
diff --git a/node_modules/nexe/lib/fs/bundle.js b/node_modules/nexe/lib/fs/bundle.js
new file mode 100644
index 0000000..74ed317
--- /dev/null
+++ b/node_modules/nexe/lib/fs/bundle.js
@@ -0,0 +1,145 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const fs = require("fs");
+const util_1 = require("util");
+const path_1 = require("path");
+const stream_1 = require("stream");
+const MultiStream = require("multistream");
+const lstat = util_1.promisify(fs.lstat), realpath = util_1.promisify(fs.realpath), createReadStream = fs.createReadStream, stat = util_1.promisify(fs.stat);
+function makeRelative(cwd, path) {
+ return './' + path_1.relative(cwd, path);
+}
+function sortEntry(a, b) {
+ return a[0] > b[0] ? 1 : -1;
+}
+function toStream(content) {
+ const readable = new stream_1.Readable({
+ read() {
+ this.push(content);
+ this.push(null);
+ },
+ });
+ return readable;
+}
+exports.toStream = toStream;
+function createFile(absoluteFileName) {
+ return __awaiter(this, void 0, void 0, function* () {
+ const stats = yield lstat(absoluteFileName), file = {
+ size: stats.size,
+ contents: '',
+ absPath: absoluteFileName,
+ deps: {},
+ };
+ if (stats.isSymbolicLink()) {
+ file.size = stats.size;
+ const [realPath, realStat] = yield Promise.all([
+ realpath(absoluteFileName),
+ stat(absoluteFileName),
+ ]);
+ file.realPath = realPath;
+ file.realSize = realStat.size;
+ }
+ return file;
+ });
+}
+class Bundle {
+ constructor({ cwd } = { cwd: process.cwd() }) {
+ this.size = 0;
+ this.rendered = false;
+ this.offset = 0;
+ this.index = {};
+ this.files = {};
+ this.streams = [];
+ this.cwd = cwd;
+ }
+ get list() {
+ return Object.keys(this.files);
+ }
+ addResource(absoluteFileName, content) {
+ return __awaiter(this, void 0, void 0, function* () {
+ if (this.files[absoluteFileName]) {
+ return this.size;
+ }
+ if (typeof content === 'string' || Buffer.isBuffer(content)) {
+ this.files[absoluteFileName] = {
+ size: Buffer.byteLength(content),
+ contents: content,
+ deps: {},
+ absPath: absoluteFileName,
+ };
+ }
+ else if (content) {
+ this.files[content.absPath] = content;
+ }
+ else {
+ this.files[absoluteFileName] = {
+ absPath: absoluteFileName,
+ contents: '',
+ deps: {},
+ size: 0,
+ };
+ this.files[absoluteFileName] = yield createFile(absoluteFileName);
+ }
+ return (this.size += this.files[absoluteFileName].size);
+ });
+ }
+ /**
+ * De-dupe files by absolute path, partition by symlink/real
+ * Iterate over real, add entries
+ * Iterate over symlinks, add symlinks
+ */
+ renderIndex() {
+ if (this.rendered) {
+ throw new Error('Bundle index already rendered');
+ }
+ const files = Object.entries(this.files), realFiles = [], symLinks = [];
+ for (const entry of files) {
+ if (entry[1].realPath) {
+ symLinks.push(entry);
+ }
+ else {
+ realFiles.push(entry);
+ }
+ }
+ realFiles.sort(sortEntry);
+ symLinks.sort(sortEntry);
+ for (const [absPath, file] of realFiles) {
+ this.addEntry(absPath, file);
+ }
+ for (const [absPath, file] of symLinks) {
+ this.addEntry(file.realPath, file);
+ this.addEntry(absPath, file, file.realPath);
+ }
+ this.rendered = true;
+ return this.index;
+ }
+ /**
+ * Add a stream if needed and an entry with the required offset and size
+ * Ensure the calling order of this method is idempotent (eg, while iterating a sorted set)
+ * @param entryPath
+ * @param file
+ * @param useEntry
+ */
+ addEntry(entryPath, file, useEntry) {
+ var _a;
+ const existingName = useEntry && makeRelative(this.cwd, useEntry), name = makeRelative(this.cwd, entryPath), size = (_a = file.realSize) !== null && _a !== void 0 ? _a : file.size, existingEntry = this.index[existingName !== null && existingName !== void 0 ? existingName : name];
+ this.index[name] = existingEntry || [this.offset, size];
+ if (!existingEntry) {
+ this.streams.push(() => file.contents ? toStream(file.contents) : createReadStream(file.absPath));
+ this.offset += size;
+ }
+ }
+ toStream() {
+ return new MultiStream(this.streams);
+ }
+}
+exports.Bundle = Bundle;