UNPKG

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
"use strict"; 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