@mdfriday/foundry
Version:
The core engine of MDFriday. Convert Markdown and shortcodes into fully themed static sites – Hugo-style, powered by TypeScript.
251 lines • 9.28 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MockZipExtractor = exports.WebZipExtractor = exports.JsZipExtractor = void 0;
exports.newZipExtractor = newZipExtractor;
exports.newMockZipExtractor = newMockZipExtractor;
const type_1 = require("../type");
const log_1 = require("../../../../pkg/log");
const jszip_1 = __importDefault(require("jszip"));
const path = __importStar(require("path"));
// Create domain-specific logger for zip operations
const log = (0, log_1.getDomainLogger)('module', { component: 'zipextractor' });
/**
* ZIP extractor implementation using JSZip
* Note: In a real implementation, you would use a library like JSZip or node-stream-zip
*/
class JsZipExtractor {
constructor(fs) {
this.fs = fs;
}
/**
* Extract ZIP file to target directory
*/
async extract(zipPath, targetDir) {
try {
// Read the ZIP file
const zipFile = await this.fs.open(zipPath);
const fileInfo = await zipFile.stat();
const zipSize = fileInfo.size();
const buffer = new Uint8Array(zipSize);
const result = await zipFile.read(buffer);
await zipFile.close();
// Use JSZip to extract the actual ZIP file
await this.extractZipData(result.buffer, targetDir);
}
catch (error) {
const message = error instanceof Error ? error.message : String(error);
log.error(`ZIP extraction failed for ${zipPath}: ${message}`);
throw new type_1.ModuleError(`ZIP extraction failed: ${message}`, 'EXTRACTION_FAILED');
}
}
/**
* List contents of ZIP file
*/
async list(zipPath) {
try {
// Read the ZIP file
const zipFile = await this.fs.open(zipPath);
const fileInfo = await zipFile.stat();
const buffer = new Uint8Array(fileInfo.size());
const result = await zipFile.read(buffer);
await zipFile.close();
// Use JSZip to list the actual ZIP contents
return await this.listZipContents(result.buffer);
}
catch (error) {
const message = error instanceof Error ? error.message : String(error);
throw new type_1.ModuleError(`ZIP listing failed: ${message}`, 'LIST_FAILED');
}
}
/**
* Real implementation of ZIP extraction using JSZip
*/
async extractZipData(zipData, targetDir) {
try {
// Ensure target directory exists
await this.fs.mkdirAll(targetDir, 0o755);
// Load ZIP file with JSZip
const zip = new jszip_1.default();
const zipContent = await zip.loadAsync(zipData);
// Count total files for progress tracking
const allFiles = [];
zipContent.forEach((relativePath, zipEntry) => {
if (!zipEntry.dir) {
allFiles.push(relativePath);
}
});
// Extract each file in the ZIP
const promises = [];
let extractedCount = 0;
zipContent.forEach((relativePath, zipEntry) => {
promises.push(this.extractSingleEntry(relativePath, zipEntry, targetDir).then(() => {
extractedCount++;
}));
});
// Wait for all extractions to complete
await Promise.all(promises);
}
catch (error) {
const message = error instanceof Error ? error.message : String(error);
log.error(`Failed to extract ZIP data: ${message}`);
throw new type_1.ModuleError(`Failed to extract ZIP data: ${message}`, 'EXTRACTION_FAILED');
}
}
/**
* Extract a single ZIP entry (file or directory)
*/
async extractSingleEntry(relativePath, zipEntry, targetDir) {
const fullPath = path.join(targetDir, relativePath);
if (zipEntry.dir) {
// Create directory
await this.fs.mkdirAll(fullPath, 0o755);
}
else {
// Extract file
const dir = path.dirname(fullPath);
// Ensure parent directory exists
if (dir !== targetDir) {
await this.fs.mkdirAll(dir, 0o755);
}
// Get file content as Uint8Array
const content = await zipEntry.async('uint8array');
// Write file
const file = await this.fs.create(fullPath);
await file.write(content);
await file.close();
}
}
/**
* Real implementation of ZIP content listing using JSZip
*/
async listZipContents(zipData) {
try {
// Load ZIP file with JSZip
const zip = new jszip_1.default();
const zipContent = await zip.loadAsync(zipData);
// Get all file paths
const paths = [];
zipContent.forEach((relativePath) => {
paths.push(relativePath);
});
return paths;
}
catch (error) {
const message = error instanceof Error ? error.message : String(error);
throw new type_1.ModuleError(`Failed to list ZIP contents: ${message}`, 'LIST_FAILED');
}
}
}
exports.JsZipExtractor = JsZipExtractor;
/**
* Browser-compatible ZIP extractor using Web APIs
*/
class WebZipExtractor {
constructor(fs) {
this.fs = fs;
}
async extract(zipPath, targetDir) {
try {
// In browser environment, you might use different APIs
// This is a placeholder for browser-specific implementation
throw new type_1.ModuleError('Web ZIP extraction not implemented', 'NOT_IMPLEMENTED');
}
catch (error) {
const message = error instanceof Error ? error.message : String(error);
throw new type_1.ModuleError(`Web ZIP extraction failed: ${message}`, 'WEB_EXTRACTION_FAILED');
}
}
async list(zipPath) {
try {
// Browser-specific ZIP listing would go here
throw new type_1.ModuleError('Web ZIP listing not implemented', 'NOT_IMPLEMENTED');
}
catch (error) {
const message = error instanceof Error ? error.message : String(error);
throw new type_1.ModuleError(`Web ZIP listing failed: ${message}`, 'WEB_LIST_FAILED');
}
}
}
exports.WebZipExtractor = WebZipExtractor;
/**
* Mock ZIP extractor for testing
*/
class MockZipExtractor {
constructor() {
this.mockContents = new Map();
}
setMockContents(zipPath, contents) {
this.mockContents.set(zipPath, contents);
}
async extract(zipPath, targetDir) {
const contents = this.mockContents.get(zipPath) || this.mockContents.get('/any/path');
if (!contents) {
return;
}
}
async list(zipPath) {
const contents = this.mockContents.get(zipPath) || this.mockContents.get('/any/path');
if (!contents) {
// Return empty list if no mock is set
return [];
}
return [...contents];
}
}
exports.MockZipExtractor = MockZipExtractor;
/**
* Factory function to create appropriate ZIP extractor
*/
function newZipExtractor(fs, environment = 'node') {
switch (environment) {
case 'node':
return new JsZipExtractor(fs);
case 'browser':
return new WebZipExtractor(fs);
default:
throw new Error(`Unsupported environment: ${environment}`);
}
}
/**
* Creates a mock ZIP extractor for testing
*/
function newMockZipExtractor() {
return new MockZipExtractor();
}
//# sourceMappingURL=zipextractor.js.map