@j0nnyboi/amman
Version:
A modern mandatory toolbelt to help test solana SDK libraries and apps on a locally running validator.
160 lines • 6.58 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 (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__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.MockStorageServer = exports.AMMAN_STORAGE_ROOT = void 0;
const amman_client_1 = require("@j0nnyboi/amman-client");
const fs_1 = __importDefault(require("fs"));
const http_1 = __importStar(require("http"));
const os_1 = require("os");
const path_1 = __importDefault(require("path"));
const fs_2 = require("../utils/fs");
const log_1 = require("../utils/log");
const types_1 = require("./types");
exports.AMMAN_STORAGE_ROOT = path_1.default.join((0, os_1.tmpdir)(), 'amman-storage');
const { logError, logDebug, logTrace } = (0, log_1.scopedLog)('mock-storage');
class MockStorageServer {
constructor(storageDir) {
this.storageDir = storageDir;
}
static get existingInstance() {
return MockStorageServer._instance;
}
static async createInstance(storageConfig) {
if (MockStorageServer._instance == null) {
const { storageId, clearOnStart } = {
...types_1.DEFAULT_STORAGE_CONFIG,
...storageConfig,
};
const storageDir = path_1.default.join(exports.AMMAN_STORAGE_ROOT, storageId);
await (0, fs_2.ensureDir)(storageDir, clearOnStart);
return (MockStorageServer._instance = new MockStorageServer(storageDir));
}
else {
throw new Error('MockStorageServer instance can only be created once');
}
}
start() {
this.server = http_1.default
.createServer(async (req, res) => {
var _a, _b, _c;
if (((_a = req.method) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === 'options') {
writeStatusHead(res, 200);
return res.end('OK');
}
const url = (_b = req.url) === null || _b === void 0 ? void 0 : _b.trim();
if (url == null || url.length === 0) {
return fail(res, 'Url is required');
}
if (url.startsWith('/upload')) {
if (((_c = req.method) === null || _c === void 0 ? void 0 : _c.toLowerCase()) !== 'post') {
return fail(res, 'Only POST is supported for uploads');
}
const resourceName = url.slice('/upload/'.length);
if (resourceName.length === 0) {
return fail(res, 'Resource to upload is required');
}
const resource = path_1.default.join(exports.AMMAN_STORAGE_ROOT, resourceName);
return handleUpload(req, res, resource);
}
const resourceName = url.slice(1);
if (resourceName.length === 0) {
return fail(res, 'Resource to load is required');
}
const resource = path_1.default.join(exports.AMMAN_STORAGE_ROOT, resourceName);
if (!(await (0, fs_2.canRead)(resource))) {
logError(`failed to find ${resource}`);
writeStatusHead(res, 404);
res.end();
}
else {
logDebug(`serving ${resource}`);
writeStatusHead(res, 200);
fs_1.default.createReadStream(resource)
.on('error', (err) => {
logError(err);
fail(res, 'Failed to read resource');
})
.pipe(res);
}
})
.unref();
const promise = new Promise((resolve, reject) => {
this.server.on('error', reject).on('listening', () => resolve(this.server));
});
this.server.listen(amman_client_1.AMMAN_STORAGE_PORT);
return promise;
}
stop() {
var _a;
(_a = this.server) === null || _a === void 0 ? void 0 : _a.close();
}
}
exports.MockStorageServer = MockStorageServer;
// -----------------
// Helpers
// -----------------
function writeStatusHead(res, status) {
res.writeHead(status, {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS, DELETE, PUT',
'Access-Control-Allow-Headers': '*',
'Access-Control-Max-Age': 2592000, // 30 days
});
}
function fail(res, msg, statusCode = 422) {
writeStatusHead(res, statusCode);
res.end(`${http_1.STATUS_CODES[statusCode]}: ${msg}`);
}
function handleUpload(req, res, resource) {
var _a, _b;
const contentLength = parseInt((_b = (_a = req.headers) === null || _a === void 0 ? void 0 : _a['content-length']) !== null && _b !== void 0 ? _b : '');
if (isNaN(contentLength) || contentLength <= 0) {
return fail(res, 'Missing File to Upload', 411);
}
logTrace(`uploading ${contentLength} bytes to ${resource}`);
const dstStream = fs_1.default.createWriteStream(resource);
let failed = false;
dstStream.on('error', (error) => {
logError(error);
failed = true;
fail(res, 'Upload failed', 500);
});
req.pipe(dstStream);
req.on('end', () => {
dstStream.close(() => {
if (!failed) {
writeStatusHead(res, 200);
const host = req.headers.host;
const assetUrl = `http://${host}${req.url.replace('upload/', '')}`;
res.write(assetUrl);
res.end();
}
});
});
}
//# sourceMappingURL=mock-server.js.map