fhir-package-installer
Version:
A utility module for downloading, indexing, caching, and managing FHIR packages from the FHIR Package Registry and Simplifier
199 lines (198 loc) • 7.51 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/mock-artifactory-server.ts
var mock_artifactory_server_exports = {};
__export(mock_artifactory_server_exports, {
MOCK_ARTIFACTORY_VALID_TOKEN: () => MOCK_ARTIFACTORY_VALID_TOKEN,
createMockArtifactoryServer: () => createMockArtifactoryServer
});
module.exports = __toCommonJS(mock_artifactory_server_exports);
var import_http = __toESM(require("http"), 1);
var import_https = __toESM(require("https"), 1);
var import_url = require("url");
var InternalMockArtifactoryServer = class {
server;
port;
validToken = "test-token";
upstreamRegistryUrl;
upstreamTarballBaseUrl;
constructor(port, options = {}) {
this.port = port;
this.upstreamRegistryUrl = options.upstreamRegistryUrl ?? "https://packages.fhir.org";
this.upstreamTarballBaseUrl = options.upstreamTarballBaseUrl ?? "https://packages.simplifier.net";
this.server = this.createServer();
}
async start() {
if (this.server.listening) return;
await new Promise((resolve, reject) => {
this.server.once("error", reject);
this.server.listen(this.port, () => resolve());
});
const addr = this.server.address();
if (typeof addr === "object" && addr && "port" in addr) this.port = addr.port;
}
async stop() {
if (!this.server.listening) return;
await new Promise((resolve) => this.server.close(() => resolve()));
}
getBaseUrl() {
return `http://localhost:${this.port}`;
}
getValidToken() {
return this.validToken;
}
// ---- Internal implementation ----
createServer() {
return import_http.default.createServer(async (req, res) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
if (req.method === "OPTIONS") {
res.writeHead(200);
res.end();
return;
}
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith("Bearer ")) {
this.json(res, 401, { error: "Unauthorized" });
return;
}
const token = authHeader.substring("Bearer ".length);
if (token !== this.validToken) {
this.json(res, 403, { error: "Forbidden" });
return;
}
const url = new import_url.URL(req.url || "/", this.getBaseUrl());
try {
if (url.pathname.includes("/-/")) {
this.handleTarballRedirect(res, url);
return;
}
if (url.pathname.includes("/artifactory/api/npm/")) {
await this.handleArtifactoryMetadata(res, url);
return;
}
if (url.pathname.endsWith("/")) {
await this.handleSimplifierMetadata(res, url);
return;
}
this.json(res, 404, { error: "Not found" });
} catch {
this.json(res, 500, { error: "Internal server error" });
}
});
}
async handleArtifactoryMetadata(res, url) {
const segments = url.pathname.split("/").filter(Boolean);
const packageName = segments.at(-1) || segments.at(-2);
if (!packageName) {
this.json(res, 404, { error: "Package not found" });
return;
}
await this.fetchAndRewrite(packageName, res);
}
async handleSimplifierMetadata(res, url) {
const packageName = url.pathname.split("/").filter(Boolean)[0];
if (!packageName) {
this.json(res, 404, { error: "Package not found" });
return;
}
await this.fetchAndRewrite(packageName, res);
}
handleTarballRedirect(res, url) {
const parts = url.pathname.split("/").filter(Boolean);
const tgzFile = parts.at(-1);
const packageName = parts.at(-3);
if (!tgzFile || !packageName) {
this.json(res, 404, { error: "Tarball not found" });
return;
}
const base = this.upstreamTarballBaseUrl.replace(/\/+$/, "");
const redirectUrl = `${base}/${packageName}/-/${tgzFile}`;
res.writeHead(302, { Location: redirectUrl, "Content-Type": "application/json" });
res.end(JSON.stringify({ message: "Redirecting to Simplifier" }));
}
async fetchAndRewrite(packageName, res) {
try {
const base = this.upstreamRegistryUrl.replace(/\/+$/, "");
const sourceUrl = `${base}/${packageName}/`;
const { data } = await this.fetchRaw(sourceUrl);
const modified = this.rewriteTarballs(data);
this.json(res, 200, modified);
} catch {
this.json(res, 404, { error: "Package not found" });
}
}
fetchRaw(url) {
return new Promise((resolve, reject) => {
const parsed = new import_url.URL(url);
const client = parsed.protocol === "http:" ? import_http.default : import_https.default;
client.get(url, (resp) => {
let acc = "";
resp.on("data", (chunk) => acc += chunk);
resp.on("end", () => resolve({ statusCode: resp.statusCode || 0, data: acc }));
}).on("error", reject);
});
}
rewriteTarballs(raw) {
try {
const json = JSON.parse(raw);
if (json.versions) {
for (const v of Object.values(json.versions)) {
if (v.dist?.tarball) {
const original = new import_url.URL(v.dist.tarball);
const parts = original.pathname.split("/").filter(Boolean);
const packageName = parts[0];
const tgzFile = parts.at(-1);
if (packageName && tgzFile) {
v.dist.tarball = `${this.getBaseUrl()}/${packageName}/-/${tgzFile}`;
}
}
}
}
return json;
} catch {
return raw;
}
}
json(res, status, body) {
res.writeHead(status, { "Content-Type": "application/json" });
res.end(typeof body === "string" ? body : JSON.stringify(body));
}
};
function createMockArtifactoryServer(port = 3333, options = {}) {
return new InternalMockArtifactoryServer(port, options);
}
var MOCK_ARTIFACTORY_VALID_TOKEN = "test-token";
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
MOCK_ARTIFACTORY_VALID_TOKEN,
createMockArtifactoryServer
});
//# sourceMappingURL=mock-artifactory-server.cjs.map