@powerhousedao/registry 6.0.0-dev.190 → 6.0.0-dev.192
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +13 -14
- package/dist/cli.mjs.map +1 -1
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -193,19 +193,18 @@ var CdnCache = class {
|
|
|
193
193
|
* Read dist-tags, the full version list, and the local-publish flag for a
|
|
194
194
|
* package from verdaccio's on-disk storage (`{storagePath}/{name}/package.json`).
|
|
195
195
|
*
|
|
196
|
-
* `locallyPublished`
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
* missing or can't be read — callers should treat these as best-effort.
|
|
196
|
+
* `locallyPublished` is tri-state:
|
|
197
|
+
* - `true` → storage metadata has `_attachments` (tarball uploaded here).
|
|
198
|
+
* - `false` → storage metadata exists but `_attachments` is empty (proxy
|
|
199
|
+
* from the npm uplink only; no local publish at this registry).
|
|
200
|
+
* - `undefined` → metadata file wasn't readable. Happens with non-filesystem
|
|
201
|
+
* backends (S3, etc.) or if verdaccio stores metadata elsewhere.
|
|
202
|
+
* Callers should treat this as "unknown" and default to including
|
|
203
|
+
* the package, to avoid filtering the whole /packages list to an
|
|
204
|
+
* empty array on deployments where we can't observe _attachments.
|
|
206
205
|
*/
|
|
207
206
|
function readPackageMetadata(storagePath, packageName) {
|
|
208
|
-
if (!storagePath) return { locallyPublished:
|
|
207
|
+
if (!storagePath) return { locallyPublished: void 0 };
|
|
209
208
|
try {
|
|
210
209
|
const metadataPath = path.join(storagePath, packageName, "package.json");
|
|
211
210
|
const raw = fs.readFileSync(metadataPath, "utf-8");
|
|
@@ -219,7 +218,7 @@ function readPackageMetadata(storagePath, packageName) {
|
|
|
219
218
|
locallyPublished
|
|
220
219
|
};
|
|
221
220
|
} catch {
|
|
222
|
-
return { locallyPublished:
|
|
221
|
+
return { locallyPublished: void 0 };
|
|
223
222
|
}
|
|
224
223
|
}
|
|
225
224
|
function readManifest(dir) {
|
|
@@ -304,7 +303,7 @@ function scanPackages(cdnCachePath, storagePath) {
|
|
|
304
303
|
const manifest = readManifest(manifestDir);
|
|
305
304
|
const name = manifest?.name ?? dirName;
|
|
306
305
|
const { distTags, versions, locallyPublished } = readPackageMetadata(storagePath, name);
|
|
307
|
-
if (
|
|
306
|
+
if (locallyPublished === false) continue;
|
|
308
307
|
packages.push({
|
|
309
308
|
name,
|
|
310
309
|
path: `/-/cdn/${dirName}`,
|
|
@@ -321,7 +320,7 @@ function scanPackages(cdnCachePath, storagePath) {
|
|
|
321
320
|
const manifest = readManifest(manifestDir);
|
|
322
321
|
const name = manifest?.name ?? entry.name;
|
|
323
322
|
const { distTags, versions, locallyPublished } = readPackageMetadata(storagePath, name);
|
|
324
|
-
if (
|
|
323
|
+
if (locallyPublished === false) continue;
|
|
325
324
|
packages.push({
|
|
326
325
|
name,
|
|
327
326
|
path: `/-/cdn/${entry.name}`,
|
package/dist/cli.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.mjs","names":["#resolveFile","#extractWithLock","#extractionLocks","#channels","#clients","#storagePath","#predefined","#dynamic","#load","#save","#filePath"],"sources":["../src/constants.ts","../src/semver.ts","../src/cdn.ts","../src/packages.ts","../src/middleware.ts","../src/notifications/manager.ts","../src/notifications/sse.ts","../src/notifications/webhook.ts","../src/verdaccio-config.ts","../src/run.ts","../cli.ts"],"sourcesContent":["export const DEFAULT_PORT = 8080;\nexport const DEFAULT_STORAGE_DIR_NAME = \"./storage\" as const;\nexport const DEFAULT_REGISTRY_CDN_CACHE_DIR_NAME = \"./cdn-cache\" as const;\n","/**\n * Compare two semver version strings for sorting.\n * Returns negative if a < b, positive if a > b, 0 if equal.\n *\n * Handles numeric component comparison (so \"1.0.10\" > \"1.0.9\")\n * and prerelease ordering (release > prerelease).\n */\nexport function compareSemver(a: string, b: string): number {\n const [coreA, preA] = a.split(\"-\", 2);\n const [coreB, preB] = b.split(\"-\", 2);\n\n const partsA = coreA.split(\".\").map(Number);\n const partsB = coreB.split(\".\").map(Number);\n\n for (let i = 0; i < Math.max(partsA.length, partsB.length); i++) {\n const na = partsA[i] ?? 0;\n const nb = partsB[i] ?? 0;\n if (na !== nb) return na - nb;\n }\n\n // Equal core versions — release (no prerelease) sorts after prerelease\n if (!preA && preB) return 1;\n if (preA && !preB) return -1;\n if (preA && preB) return preA < preB ? -1 : preA > preB ? 1 : 0;\n\n return 0;\n}\n","import crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { Readable } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport { extract } from \"tar\";\nimport { compareSemver } from \"./semver.js\";\n\n/**\n * Parse a package specifier into name and version/tag.\n * Supports:\n * \"@scope/pkg\" -> { name: \"@scope/pkg\", tag: undefined }\n * \"@scope/pkg@dev\" -> { name: \"@scope/pkg\", tag: \"dev\" }\n * \"@scope/pkg@1.0.0\" -> { name: \"@scope/pkg\", tag: \"1.0.0\" }\n * \"pkg@latest\" -> { name: \"pkg\", tag: \"latest\" }\n */\nexport function parsePackageSpec(spec: string): {\n name: string;\n tag: string | undefined;\n} {\n // For scoped packages (@scope/name@tag), split on the last @\n // For unscoped packages (name@tag), split on the first @\n if (spec.startsWith(\"@\")) {\n // Scoped: find the @ after the scope/name portion\n const lastAt = spec.lastIndexOf(\"@\");\n if (lastAt > 0 && lastAt !== spec.indexOf(\"@\")) {\n return { name: spec.slice(0, lastAt), tag: spec.slice(lastAt + 1) };\n }\n return { name: spec, tag: undefined };\n }\n const atIndex = spec.indexOf(\"@\");\n if (atIndex > 0) {\n return { name: spec.slice(0, atIndex), tag: spec.slice(atIndex + 1) };\n }\n return { name: spec, tag: undefined };\n}\n\nexport class CdnCache {\n #extractionLocks = new Map<string, Promise<void>>();\n\n constructor(\n private registryUrl: string,\n private cdnCachePath: string,\n ) {}\n\n async getFileByVersion(\n packageName: string,\n version: string,\n filePath: string,\n ): Promise<string | null> {\n const versionDir = path.join(this.cdnCachePath, packageName, version);\n\n // Check all possible paths before attempting extraction\n const resolved = this.#resolveFile(versionDir, filePath);\n if (resolved) return resolved;\n\n // File not found in any location — extract tarball and try again\n await this.#extractWithLock(packageName, version);\n\n return this.#resolveFile(versionDir, filePath);\n }\n\n #resolveFile(versionDir: string, filePath: string): string | null {\n // Check direct path first, then fall back to cdn/ and dist/cdn/ subdirectories\n // (npm tarballs contain files under dist/, bun bundles go to cdn/)\n const candidates = [\n path.join(versionDir, filePath),\n path.join(versionDir, \"cdn\", filePath),\n path.join(versionDir, \"dist\", \"cdn\", filePath),\n path.join(versionDir, \"dist\", filePath),\n ];\n\n for (const candidate of candidates) {\n if (this.isSafePath(candidate) && fs.existsSync(candidate))\n return candidate;\n }\n\n return null;\n }\n\n async #extractWithLock(packageName: string, version: string): Promise<void> {\n const key = `${packageName}@${version}`;\n const existing = this.#extractionLocks.get(key);\n if (existing) return existing;\n\n const promise = this.extractTarball(packageName, version).finally(() => {\n this.#extractionLocks.delete(key);\n });\n this.#extractionLocks.set(key, promise);\n return promise;\n }\n\n getLatestCachedVersion(packageName: string): string | null {\n const pkgDir = path.join(this.cdnCachePath, packageName);\n try {\n const entries = fs.readdirSync(pkgDir, { withFileTypes: true });\n const versions = entries\n .filter((e) => e.isDirectory())\n .map((e) => e.name);\n if (versions.length === 0) return null;\n versions.sort(compareSemver);\n return versions[versions.length - 1];\n } catch {\n return null;\n }\n }\n\n /**\n * Resolve a version for a package. If tag is a semver version that exists\n * in the registry, return it directly. If tag is a dist-tag name (e.g.\n * \"dev\", \"latest\"), resolve it to the concrete version. If no tag is\n * provided, prefer \"latest\", then fall back to any available dist-tag.\n */\n async resolveVersion(\n packageName: string,\n tag?: string,\n ): Promise<string | null> {\n try {\n const url = `${this.registryUrl}/${encodeURIComponent(packageName)}`;\n const res = await fetch(url, {\n headers: { Accept: \"application/json\" },\n });\n if (!res.ok) return null;\n const metadata = (await res.json()) as Record<string, unknown>;\n const distTags = metadata[\"dist-tags\"] as\n | Record<string, string>\n | undefined;\n const versions = metadata[\"versions\"] as\n | Record<string, unknown>\n | undefined;\n\n if (tag) {\n // If the tag matches an exact version in the registry, use it directly\n if (versions && tag in versions) return tag;\n // Otherwise treat it as a dist-tag name\n if (distTags && tag in distTags) return distTags[tag];\n // Tag not found\n return null;\n }\n\n if (!distTags) return null;\n // No tag specified: prefer \"latest\", fall back to any available tag\n return distTags.latest ?? Object.values(distTags)[0] ?? null;\n } catch {\n return null;\n }\n }\n\n async extractTarball(packageName: string, version: string): Promise<void> {\n const shortName = packageName.startsWith(\"@\")\n ? packageName.split(\"/\")[1]\n : packageName;\n const tarballUrl = `${this.registryUrl}/${encodeURIComponent(packageName)}/-/${shortName}-${version}.tgz`;\n\n let res: Response;\n try {\n res = await fetch(tarballUrl);\n if (!res.ok || !res.body) return;\n } catch {\n return;\n }\n\n const destDir = path.join(this.cdnCachePath, packageName, version);\n fs.mkdirSync(destDir, { recursive: true });\n\n const tmpFile = path.join(\n destDir,\n `.tmp-tarball-${crypto.randomUUID()}.tgz`,\n );\n try {\n const fileStream = fs.createWriteStream(tmpFile);\n await pipeline(Readable.fromWeb(res.body as never), fileStream);\n await extract({ file: tmpFile, cwd: destDir, strip: 1 });\n } finally {\n fs.rmSync(tmpFile, { force: true });\n }\n }\n\n invalidate(packageName: string): void {\n const cacheDir = path.join(this.cdnCachePath, packageName);\n if (!this.isSafePath(cacheDir)) return;\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n\n /** Remove all cached version directories except the specified one. */\n pruneOldVersions(packageName: string, keepVersion: string): void {\n const pkgDir = path.join(this.cdnCachePath, packageName);\n try {\n const entries = fs.readdirSync(pkgDir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isDirectory() && entry.name !== keepVersion) {\n const dir = path.join(pkgDir, entry.name);\n if (this.isSafePath(dir)) {\n fs.rmSync(dir, { recursive: true, force: true });\n }\n }\n }\n } catch {\n // ignore — directory may not exist yet\n }\n }\n\n private isSafePath(filePath: string): boolean {\n const resolved = path.resolve(filePath);\n const cacheRoot = path.resolve(this.cdnCachePath);\n return resolved.startsWith(cacheRoot + path.sep) || resolved === cacheRoot;\n }\n}\n","import type { Manifest } from \"@powerhousedao/shared\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { compareSemver } from \"./semver.js\";\nimport type { PackageInfo } from \"./types.js\";\n\n/**\n * Read dist-tags, the full version list, and the local-publish flag for a\n * package from verdaccio's on-disk storage (`{storagePath}/{name}/package.json`).\n *\n * `locallyPublished` distinguishes packages that were `npm publish`-ed directly\n * at this registry (verdaccio stores the tarball as an `_attachments` entry)\n * from packages that were merely pulled through the uplink from npmjs.org\n * (no `_attachments`, but verdaccio may still have cached metadata). The\n * /packages listing only surfaces locally-published packages — npm passthroughs\n * remain installable via the \"fetch from npm\" fallback in the UI, but don't\n * pollute the default list.\n *\n * Returns `undefined` fields / `locallyPublished: false` if the file is\n * missing or can't be read — callers should treat these as best-effort.\n */\nfunction readPackageMetadata(\n storagePath: string | undefined,\n packageName: string,\n): {\n distTags?: Record<string, string>;\n versions?: string[];\n locallyPublished: boolean;\n} {\n if (!storagePath) return { locallyPublished: false };\n try {\n const metadataPath = path.join(storagePath, packageName, \"package.json\");\n const raw = fs.readFileSync(metadataPath, \"utf-8\");\n const parsed = JSON.parse(raw) as {\n \"dist-tags\"?: Record<string, string>;\n versions?: Record<string, unknown>;\n _attachments?: Record<string, unknown>;\n };\n const distTags = parsed[\"dist-tags\"];\n const rawVersions = parsed.versions ? Object.keys(parsed.versions) : [];\n const versions = rawVersions.slice().sort(compareSemver);\n const locallyPublished =\n !!parsed._attachments && Object.keys(parsed._attachments).length > 0;\n return {\n distTags:\n distTags && Object.keys(distTags).length > 0 ? distTags : undefined,\n versions: versions.length > 0 ? versions : undefined,\n locallyPublished,\n };\n } catch {\n return { locallyPublished: false };\n }\n}\n\nfunction readManifest(dir: string): Manifest | null {\n const candidates = [\n path.join(dir, \"powerhouse.manifest.json\"),\n path.join(dir, \"cdn\", \"powerhouse.manifest.json\"),\n path.join(dir, \"dist\", \"powerhouse.manifest.json\"),\n ];\n for (const manifestPath of candidates) {\n try {\n const raw = fs.readFileSync(manifestPath, \"utf-8\");\n return JSON.parse(raw) as Manifest;\n } catch {\n // try next candidate\n }\n }\n return null;\n}\n\nfunction readPackageJsonVersion(dir: string): string | undefined {\n try {\n const raw = fs.readFileSync(path.join(dir, \"package.json\"), \"utf-8\");\n const pkg = JSON.parse(raw) as { version?: unknown };\n return typeof pkg.version === \"string\" ? pkg.version : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction getLatestVersionDir(pkgDir: string): string | null {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(pkgDir, { withFileTypes: true });\n } catch {\n return null;\n }\n const versions = entries.filter((e) => e.isDirectory()).map((e) => e.name);\n if (versions.length === 0) return null;\n versions.sort(compareSemver);\n return path.join(pkgDir, versions[versions.length - 1]);\n}\n\nexport function loadPackage(\n cdnCachePath: string,\n name: string,\n version?: string,\n): PackageInfo | null {\n const pkgDir = path.join(cdnCachePath, name);\n const versionDir = version\n ? path.join(pkgDir, version)\n : getLatestVersionDir(pkgDir);\n const manifestDir = versionDir ?? pkgDir;\n const manifest = readManifest(manifestDir);\n\n if (!manifest) {\n return null;\n }\n return {\n name: manifest.name ?? name,\n path: `/-/cdn/${name}`,\n manifest,\n documentTypes: getDocumentTypesFromManifest(manifest),\n version: readPackageJsonVersion(manifestDir),\n };\n}\n\nfunction getDocumentTypesFromManifest(manifest: Manifest | undefined | null) {\n if (!manifest) return [];\n\n const documentTypes: string[] = [];\n const { apps, documentModels, editors, subgraphs } = manifest;\n\n if (apps?.length) {\n documentTypes.push(\"powerhouse/document-drive\");\n }\n documentTypes.push(\n ...(documentModels ?? []).map((dm) => dm.id),\n ...(editors ?? [])\n .flatMap((e) => e.documentTypes)\n .filter((dt) => dt !== undefined),\n ...(subgraphs ?? [])\n .flatMap((e) => e.documentTypes)\n .filter((dt) => dt !== undefined),\n );\n\n return documentTypes;\n}\n\nexport function scanPackages(\n cdnCachePath: string,\n storagePath?: string,\n): PackageInfo[] {\n const absDir = path.resolve(cdnCachePath);\n const packages: PackageInfo[] = [];\n\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(absDir, { withFileTypes: true });\n } catch {\n return packages;\n }\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n\n if (entry.name.startsWith(\"@\")) {\n const scopeDir = path.join(absDir, entry.name);\n let scopedEntries: fs.Dirent[];\n try {\n scopedEntries = fs.readdirSync(scopeDir, { withFileTypes: true });\n } catch (error) {\n console.log(error);\n continue;\n }\n for (const scopedEntry of scopedEntries) {\n if (!scopedEntry.isDirectory()) continue;\n const dirName = `${entry.name}/${scopedEntry.name}`;\n const pkgDir = path.join(scopeDir, scopedEntry.name);\n const versionDir = getLatestVersionDir(pkgDir);\n const manifestDir = versionDir ?? pkgDir;\n const manifest = readManifest(manifestDir);\n const name = manifest?.name ?? dirName;\n const { distTags, versions, locallyPublished } = readPackageMetadata(\n storagePath,\n name,\n );\n // Only surface packages that were `npm publish`-ed at THIS registry.\n // When storagePath is not wired through, we can't tell — fall back\n // to including the entry (preserves pre-filter behaviour).\n if (storagePath && !locallyPublished) continue;\n packages.push({\n name,\n path: `/-/cdn/${dirName}`,\n manifest,\n documentTypes: getDocumentTypesFromManifest(manifest),\n version: readPackageJsonVersion(manifestDir),\n distTags,\n versions,\n });\n }\n } else {\n const pkgDir = path.join(absDir, entry.name);\n const versionDir = getLatestVersionDir(pkgDir);\n const manifestDir = versionDir ?? pkgDir;\n const manifest = readManifest(manifestDir);\n const name = manifest?.name ?? entry.name;\n const { distTags, versions, locallyPublished } = readPackageMetadata(\n storagePath,\n name,\n );\n if (storagePath && !locallyPublished) continue;\n packages.push({\n name,\n path: `/-/cdn/${entry.name}`,\n manifest,\n documentTypes: getDocumentTypesFromManifest(manifest),\n version: readPackageJsonVersion(manifestDir),\n distTags,\n versions,\n });\n }\n }\n\n return packages;\n}\n\nexport function findPackagesByDocumentType(\n packagesDir: string,\n documentType: string,\n): PackageInfo[] {\n const allPackages = scanPackages(packagesDir);\n\n return allPackages.filter((pkg) => {\n if (!pkg.manifest?.documentModels) {\n return false;\n }\n return pkg.manifest.documentModels.some((dm) => dm.id === documentType);\n });\n}\n","import express, {\n Router,\n type NextFunction,\n type Request,\n type Response,\n} from \"express\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { CdnCache, parsePackageSpec } from \"./cdn.js\";\nimport type { SSEChannel } from \"./notifications/sse.js\";\nimport type { NotificationChannel } from \"./notifications/types.js\";\nimport type { WebhookChannel } from \"./notifications/webhook.js\";\nimport {\n findPackagesByDocumentType,\n loadPackage,\n scanPackages,\n} from \"./packages.js\";\nimport type { RegistryConfig } from \"./types.js\";\n\nconst MIME_TYPES: Record<string, string> = {\n \".js\": \"application/javascript\",\n \".mjs\": \"application/javascript\",\n \".css\": \"text/css\",\n \".json\": \"application/json\",\n \".wasm\": \"application/wasm\",\n \".map\": \"application/json\",\n \".html\": \"text/html\",\n \".svg\": \"image/svg+xml\",\n};\n\nfunction getContentType(filePath: string): string {\n const ext = path.extname(filePath).toLowerCase();\n return MIME_TYPES[ext] ?? \"application/octet-stream\";\n}\n\nexport function createPowerhouseRouter(\n config: RegistryConfig,\n sse: SSEChannel,\n webhooks: WebhookChannel,\n): Router {\n const cdn = new CdnCache(\n `http://localhost:${config.port}`,\n config.cdnCachePath,\n );\n const router = Router();\n\n // CORS on every response\n router.use((_req: Request, res: Response, next: NextFunction) => {\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n next();\n });\n\n // SSE endpoint for publish notifications\n router.get(\"/-/events\", (_req: Request, res: Response) => {\n sse.addClient(res);\n });\n\n // Webhook management\n router.get(\"/-/webhooks\", (_req: Request, res: Response) => {\n res.json(webhooks.getWebhooks());\n });\n\n router.post(\"/-/webhooks\", express.json(), (req: Request, res: Response) => {\n const { endpoint, headers } = req.body as {\n endpoint?: string;\n headers?: Record<string, string>;\n };\n if (!endpoint) {\n res.status(400).json({ error: \"Missing required field: endpoint\" });\n return;\n }\n webhooks.addWebhook({ endpoint, headers });\n res.status(201).json({ endpoint, headers });\n });\n\n router.delete(\n \"/-/webhooks\",\n express.json(),\n (req: Request, res: Response) => {\n const { endpoint } = req.body as { endpoint?: string };\n if (!endpoint) {\n res.status(400).json({ error: \"Missing required field: endpoint\" });\n return;\n }\n const removed = webhooks.removeWebhook(endpoint);\n if (!removed) {\n res.status(404).json({ error: \"Webhook not found\" });\n return;\n }\n res.status(204).end();\n },\n );\n\n // Package listing API\n router.get(\"/packages\", (req: Request, res: Response) => {\n const packages = scanPackages(config.cdnCachePath, config.storagePath);\n const documentType = req.query.documentType as string | undefined;\n if (documentType) {\n const filtered = packages.filter((pkg) =>\n pkg.manifest?.documentModels?.some((m) => m.id === documentType),\n );\n res.json(filtered);\n return;\n }\n res.json(packages);\n });\n\n // Find packages by document type - returns array of package names\n router.get(\"/packages/by-document-type\", (req: Request, res: Response) => {\n const documentType = req.query.type;\n\n if (typeof documentType !== \"string\" || !documentType) {\n res.status(400).json({ error: \"Missing required query parameter: type\" });\n return;\n }\n\n const packages = findPackagesByDocumentType(\n config.cdnCachePath,\n documentType,\n );\n const packageNames = packages.map((pkg) => pkg.name);\n res.json(packageNames);\n });\n\n // Single package info\n router.get(\"/packages/*name\", async (req: Request, res: Response) => {\n const raw = (req.params as Record<string, string[]>).name.join(\"/\");\n const { name, tag } = parsePackageSpec(raw);\n const version =\n (await cdn.resolveVersion(name, tag)) ?? cdn.getLatestCachedVersion(name);\n const pkg = loadPackage(config.cdnCachePath, name, version ?? undefined);\n if (!pkg) {\n res.status(404).send(\"Package not found\");\n return;\n }\n res.json(pkg);\n });\n\n // CDN file serving\n router.get(\"/-/cdn/*path\", async (req: Request, res: Response) => {\n const parts = (req.params as Record<string, string[]>).path;\n const fullPath = parts.join(\"/\");\n\n // Parse scoped or unscoped package specifier from the path\n let packageSpec: string;\n let filePath: string;\n\n if (fullPath.startsWith(\"@\")) {\n // Scoped: @scope/pkg@1.0.0/file.js -> packageSpec = @scope/pkg@1.0.0, filePath = file.js\n const segments = fullPath.split(\"/\");\n if (segments.length < 2) {\n res.status(400).send(\"Invalid package path\");\n return;\n }\n packageSpec = `${segments[0]}/${segments[1]}`;\n filePath = segments.slice(2).join(\"/\") || \"index.js\";\n } else {\n // Unscoped: pkg@1.0.0/file.js -> packageSpec = pkg@1.0.0, filePath = file.js\n const segments = fullPath.split(\"/\");\n packageSpec = segments[0];\n filePath = segments.slice(1).join(\"/\") || \"index.js\";\n }\n\n const { name: packageName, tag } = parsePackageSpec(packageSpec);\n const version =\n (await cdn.resolveVersion(packageName, tag)) ??\n cdn.getLatestCachedVersion(packageName);\n if (!version) {\n res.status(404).send(\"File not found\");\n return;\n }\n\n const resolved = await cdn.getFileByVersion(packageName, version, filePath);\n if (!resolved) {\n res.status(404).send(\"File not found\");\n return;\n }\n\n res.setHeader(\"Content-Type\", getContentType(filePath));\n const content = fs.readFileSync(resolved);\n res.send(content);\n });\n\n return router;\n}\n\nexport function createPublishHook(\n config: RegistryConfig,\n notifications: NotificationChannel,\n) {\n const cdn = new CdnCache(\n `http://localhost:${config.port}`,\n config.cdnCachePath,\n );\n\n return (req: Request, res: Response, next: NextFunction) => {\n // Only intercept PUT requests to npm publish endpoints\n if (req.method !== \"PUT\") {\n next();\n return;\n }\n\n const originalEnd = res.end.bind(res);\n res.end = function (\n this: Response,\n chunk?: unknown,\n encoding?: unknown,\n cb?: () => void,\n ) {\n const urlPath = req.path.replace(/^\\//, \"\");\n if (\n res.statusCode < 200 ||\n res.statusCode >= 300 ||\n !urlPath ||\n urlPath.startsWith(\"-\")\n ) {\n return originalEnd(chunk, encoding as BufferEncoding, cb);\n }\n const packageName = decodeURIComponent(urlPath);\n const versionsObj = (req.body as { versions: Record<string, unknown> })\n .versions;\n const versions = Object.keys(versionsObj);\n const version = versions.at(0);\n if (!version) {\n console.error(`[registry] No version found for ${packageName}`);\n return originalEnd(chunk, encoding as BufferEncoding, cb);\n }\n if (versions.length > 1) {\n console.warn(\n `[registry] Multiple versions published for ${packageName}: ${JSON.stringify(versions)}`,\n );\n }\n\n cdn\n .extractTarball(packageName, version)\n .then(() => {\n notifications.notifyPublish({ packageName, version });\n })\n .catch((err) => {\n console.error(\n `[registry] Failed to extract ${packageName} to CDN cache:`,\n err,\n );\n });\n\n return originalEnd(chunk, encoding as BufferEncoding, cb);\n };\n\n next();\n };\n}\n","import type { NotificationChannel, PublishEvent } from \"./types.js\";\n\nexport class NotificationManager implements NotificationChannel {\n #channels: NotificationChannel[];\n\n constructor(channels: NotificationChannel[]) {\n this.#channels = channels;\n }\n\n notifyPublish(event: PublishEvent): void {\n for (const channel of this.#channels) {\n channel.notifyPublish(event);\n }\n }\n}\n","import type { Response } from \"express\";\nimport type { NotificationChannel, PublishEvent } from \"./types.js\";\n\nexport class SSEChannel implements NotificationChannel {\n #clients = new Set<Response>();\n\n addClient(res: Response): void {\n res.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Access-Control-Allow-Origin\": \"*\",\n });\n res.write(\"event: connected\\ndata: {}\\n\\n\");\n\n this.#clients.add(res);\n res.on(\"close\", () => {\n this.#clients.delete(res);\n });\n }\n\n notifyPublish(event: PublishEvent): void {\n const payload = `event: publish\\ndata: ${JSON.stringify(event)}\\n\\n`;\n for (const client of this.#clients) {\n try {\n client.write(payload);\n } catch (err) {\n console.error(\"[registry] SSE client write failed:\", err);\n this.#clients.delete(client);\n }\n }\n }\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { NotifyConfig, WebhookConfig } from \"../types.js\";\nimport type { NotificationChannel, PublishEvent } from \"./types.js\";\n\nconst WEBHOOKS_FILE = \"webhooks.json\";\n\nexport class WebhookChannel implements NotificationChannel {\n #predefined: WebhookConfig[];\n #dynamic: WebhookConfig[];\n #storagePath: string;\n\n constructor(storagePath: string, config?: NotifyConfig) {\n this.#storagePath = storagePath;\n this.#predefined = config?.webhooks ?? [];\n this.#dynamic = this.#load();\n }\n\n getWebhooks(): WebhookConfig[] {\n return [...this.#predefined, ...this.#dynamic];\n }\n\n addWebhook(webhook: WebhookConfig): void {\n const exists = this.getWebhooks().some(\n (w) => w.endpoint === webhook.endpoint,\n );\n if (exists) return;\n this.#dynamic.push(webhook);\n this.#save();\n }\n\n removeWebhook(endpoint: string): boolean {\n const before = this.#dynamic.length;\n this.#dynamic = this.#dynamic.filter((w) => w.endpoint !== endpoint);\n if (this.#dynamic.length === before) return false;\n this.#save();\n return true;\n }\n\n notifyPublish(event: PublishEvent): void {\n for (const webhook of this.getWebhooks()) {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...webhook.headers,\n };\n\n fetch(webhook.endpoint, {\n method: \"POST\",\n headers,\n body: JSON.stringify(event),\n }).catch((err: unknown) => {\n console.error(`[registry] Webhook to ${webhook.endpoint} failed:`, err);\n });\n }\n }\n\n #filePath(): string {\n return path.join(this.#storagePath, WEBHOOKS_FILE);\n }\n\n #load(): WebhookConfig[] {\n try {\n const raw = fs.readFileSync(this.#filePath(), \"utf-8\");\n return JSON.parse(raw) as WebhookConfig[];\n } catch {\n return [];\n }\n }\n\n #save(): void {\n fs.mkdirSync(this.#storagePath, { recursive: true });\n fs.writeFileSync(this.#filePath(), JSON.stringify(this.#dynamic, null, 2));\n }\n}\n","import path from \"node:path\";\nimport type { RegistryConfig } from \"./types.js\";\n\nexport function buildVerdaccioConfig(config: RegistryConfig) {\n const htpasswdPath = path.join(config.storagePath, \"htpasswd\");\n\n const uplinkUrl = config.uplink ?? \"https://registry.npmjs.org/\";\n\n const base: Record<string, unknown> = {\n storage: config.storagePath,\n self_path: \"./\",\n auth: {\n htpasswd: {\n file: htpasswdPath,\n },\n },\n uplinks: {\n npmjs: {\n url: uplinkUrl,\n maxage: \"15m\",\n timeout: \"30s\",\n cache: true,\n },\n },\n packages: {\n \"@powerhousedao/*\": {\n access: \"$all\",\n publish: \"$authenticated\",\n unpublish: \"$authenticated\",\n proxy: \"npmjs\",\n },\n \"**\": {\n access: \"$all\",\n publish: \"$authenticated\",\n unpublish: \"$authenticated\",\n proxy: \"npmjs\",\n },\n },\n web: {\n enable: config.webEnabled !== false,\n title: \"Powerhouse Registry\",\n logo: \"https://raw.githubusercontent.com/powerhouse-inc/powerhouse/main/packages/registry/static/logo.svg\",\n favicon: \"/-/static/favicon.ico\",\n primary_color: \"#38C780\",\n darkMode: true,\n },\n server: {\n keepAliveTimeout: 60,\n },\n log: {\n type: \"stdout\",\n format: \"pretty\",\n level: \"warn\",\n },\n max_body_size: config.maxBodySize ?? \"300mb\",\n };\n\n if (config.s3) {\n base.store = {\n \"aws-s3-storage\": {\n bucket: config.s3.bucket,\n endpoint: config.s3.endpoint,\n region: config.s3.region,\n s3ForcePathStyle: config.s3.s3ForcePathStyle ?? true,\n ...(config.s3.keyPrefix && { keyPrefix: config.s3.keyPrefix }),\n ...(config.s3.accessKeyId && { accessKeyId: config.s3.accessKeyId }),\n ...(config.s3.secretAccessKey && {\n secretAccessKey: config.s3.secretAccessKey,\n }),\n },\n };\n }\n\n return base;\n}\n","import express from \"express\";\nimport { findUp } from \"find-up\";\nimport { mkdir } from \"node:fs/promises\";\nimport type { Server } from \"node:http\";\nimport path from \"node:path\";\nimport { runServer } from \"verdaccio\";\nimport { createPowerhouseRouter, createPublishHook } from \"./middleware.js\";\nimport { NotificationManager } from \"./notifications/manager.js\";\nimport { SSEChannel } from \"./notifications/sse.js\";\nimport { WebhookChannel } from \"./notifications/webhook.js\";\nimport type { RegistryCommandArgs, RegistryConfig } from \"./types.js\";\nimport { buildVerdaccioConfig } from \"./verdaccio-config.js\";\n\nasync function resolveDir(dir: string): Promise<string> {\n if (path.isAbsolute(dir)) {\n await mkdir(dir, { recursive: true });\n return dir;\n }\n const found = await findUp(dir, { type: \"directory\" });\n if (!found) {\n await mkdir(dir, { recursive: true });\n return dir;\n }\n return found;\n}\n\nexport async function runRegistry(args: RegistryCommandArgs) {\n const {\n port,\n storageDir,\n cdnCacheDir,\n uplink,\n webEnabled,\n webhooks,\n s3AccessKeyId,\n s3Bucket,\n s3Endpoint,\n s3ForcePathStyle,\n s3KeyPrefix,\n s3Region,\n s3SecretAccessKey,\n } = args;\n const storagePath = await resolveDir(storageDir);\n const cdnCachePath = await resolveDir(cdnCacheDir);\n\n console.log({\n storagePath,\n cdnCachePath,\n });\n\n const webhookConfigs = webhooks\n ?.split(\",\")\n .map((url) => url.trim())\n .filter(Boolean)\n .map((endpoint) => ({ endpoint }));\n\n const config: RegistryConfig = {\n port,\n storagePath,\n cdnCachePath,\n uplink,\n webEnabled,\n ...(webhookConfigs?.length && {\n notify: { webhooks: webhookConfigs },\n }),\n ...(s3Bucket &&\n s3Endpoint &&\n s3Region && {\n s3: {\n bucket: s3Bucket,\n endpoint: s3Endpoint,\n region: s3Region,\n accessKeyId: s3AccessKeyId,\n secretAccessKey: s3SecretAccessKey,\n keyPrefix: s3KeyPrefix,\n s3ForcePathStyle,\n },\n }),\n };\n // Ensure directories exist (for relative paths resolved via findUp)\n await mkdir(storagePath, { recursive: true });\n await mkdir(cdnCachePath, { recursive: true });\n\n const verdaccioConfig = buildVerdaccioConfig(config);\n\n // verdaccio's runServer returns Promise<any> (upstream type limitation)\n const verdaccioServer = (await runServer(verdaccioConfig)) as Server;\n const verdaccioHandler = verdaccioServer.listeners(\"request\")[0] as (\n ...args: unknown[]\n ) => void;\n\n const app = express();\n\n const sseChannel = new SSEChannel();\n const webhookChannel = new WebhookChannel(config.storagePath, config.notify);\n const notifications = new NotificationManager([sseChannel, webhookChannel]);\n\n // Serve static assets (logo, etc.)\n const staticDir = await findUp(\"static\", { type: \"directory\" });\n if (staticDir) {\n app.use(\"/-/static\", express.static(staticDir));\n }\n\n // Our routes take priority over Verdaccio\n app.use(createPowerhouseRouter(config, sseChannel, webhookChannel));\n app.use(createPublishHook(config, notifications));\n\n // Verdaccio handles everything else (npm protocol, web UI, auth)\n app.use((req, res) => verdaccioHandler(req, res));\n\n const server = app.listen(port, () => {\n console.log(`Powerhouse Registry running on http://localhost:${port}`);\n console.log(` CDN: http://localhost:${port}/-/cdn/`);\n console.log(` Packages: http://localhost:${port}/packages`);\n console.log(` npm: http://localhost:${port}/`);\n console.log(` Storage: ${storagePath}`);\n console.log(` CDN cache: ${cdnCachePath}`);\n if (config.s3) {\n console.log(` S3: ${config.s3.endpoint}/${config.s3.bucket}`);\n }\n });\n\n return server;\n}\n","import {\n binary,\n command,\n flag,\n number,\n option,\n optional,\n run,\n string,\n} from \"cmd-ts\";\nimport {\n DEFAULT_PORT,\n DEFAULT_REGISTRY_CDN_CACHE_DIR_NAME,\n DEFAULT_STORAGE_DIR_NAME,\n} from \"./src/constants.js\";\nimport { runRegistry } from \"./src/run.js\";\n\nexport const registryCommand = command({\n name: \"Package registry\",\n args: {\n port: option({\n long: \"port\",\n type: number,\n defaultValue: () => Number(process.env.PORT) || DEFAULT_PORT,\n defaultValueIsSerializable: true,\n }),\n storageDir: option({\n long: \"storage-dir\",\n type: string,\n defaultValue: () =>\n process.env.REGISTRY_STORAGE || DEFAULT_STORAGE_DIR_NAME,\n defaultValueIsSerializable: true,\n }),\n cdnCacheDir: option({\n long: \"cdn-cache-dir\",\n type: string,\n defaultValue: () =>\n process.env.REGISTRY_CDN_CACHE || DEFAULT_REGISTRY_CDN_CACHE_DIR_NAME,\n defaultValueIsSerializable: true,\n }),\n uplink: option({\n long: \"uplink\",\n type: optional(string),\n defaultValue: () => process.env.REGISTRY_UPLINK,\n defaultValueIsSerializable: true,\n }),\n s3Bucket: option({\n long: \"s3-bucket\",\n type: optional(string),\n defaultValue: () => process.env.S3_BUCKET,\n defaultValueIsSerializable: true,\n }),\n s3Endpoint: option({\n long: \"s3-endpoint\",\n type: optional(string),\n defaultValue: () => process.env.S3_ENDPOINT,\n defaultValueIsSerializable: true,\n }),\n s3Region: option({\n long: \"s3-region\",\n type: optional(string),\n defaultValue: () => process.env.S3_REGION,\n defaultValueIsSerializable: true,\n }),\n s3AccessKeyId: option({\n long: \"s3-access-key-id\",\n type: optional(string),\n defaultValue: () => process.env.S3_ACCESS_KEY_ID,\n defaultValueIsSerializable: true,\n }),\n s3SecretAccessKey: option({\n long: \"s3-secret-access-key\",\n type: optional(string),\n defaultValue: () => process.env.S3_SECRET_ACCESS_KEY,\n defaultValueIsSerializable: true,\n }),\n s3KeyPrefix: option({\n long: \"s3-key-prefix\",\n type: optional(string),\n defaultValue: () => process.env.S3_KEY_PREFIX,\n defaultValueIsSerializable: true,\n }),\n s3ForcePathStyle: flag({\n long: \"s3-force-path-style\",\n defaultValue: () => process.env.S3_FORCE_PATH_STYLE !== \"false\",\n defaultValueIsSerializable: true,\n }),\n webEnabled: flag({\n long: \"web-enabled\",\n defaultValue: () => process.env.REGISTRY_WEB !== \"false\",\n defaultValueIsSerializable: true,\n }),\n webhooks: option({\n long: \"webhook\",\n type: optional(string),\n description: \"Comma-separated webhook URLs to notify on publish\",\n defaultValue: () => process.env.REGISTRY_WEBHOOKS,\n defaultValueIsSerializable: true,\n }),\n },\n handler: async (args) => {\n console.log(args);\n\n try {\n await runRegistry(args);\n } catch (error) {\n console.error(\"Failed to start registry:\");\n console.error(error);\n process.exit(1);\n }\n },\n});\n\nconst registryCli = binary(registryCommand);\n\nawait run(registryCli, process.argv);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.mjs","names":["#resolveFile","#extractWithLock","#extractionLocks","#channels","#clients","#storagePath","#predefined","#dynamic","#load","#save","#filePath"],"sources":["../src/constants.ts","../src/semver.ts","../src/cdn.ts","../src/packages.ts","../src/middleware.ts","../src/notifications/manager.ts","../src/notifications/sse.ts","../src/notifications/webhook.ts","../src/verdaccio-config.ts","../src/run.ts","../cli.ts"],"sourcesContent":["export const DEFAULT_PORT = 8080;\nexport const DEFAULT_STORAGE_DIR_NAME = \"./storage\" as const;\nexport const DEFAULT_REGISTRY_CDN_CACHE_DIR_NAME = \"./cdn-cache\" as const;\n","/**\n * Compare two semver version strings for sorting.\n * Returns negative if a < b, positive if a > b, 0 if equal.\n *\n * Handles numeric component comparison (so \"1.0.10\" > \"1.0.9\")\n * and prerelease ordering (release > prerelease).\n */\nexport function compareSemver(a: string, b: string): number {\n const [coreA, preA] = a.split(\"-\", 2);\n const [coreB, preB] = b.split(\"-\", 2);\n\n const partsA = coreA.split(\".\").map(Number);\n const partsB = coreB.split(\".\").map(Number);\n\n for (let i = 0; i < Math.max(partsA.length, partsB.length); i++) {\n const na = partsA[i] ?? 0;\n const nb = partsB[i] ?? 0;\n if (na !== nb) return na - nb;\n }\n\n // Equal core versions — release (no prerelease) sorts after prerelease\n if (!preA && preB) return 1;\n if (preA && !preB) return -1;\n if (preA && preB) return preA < preB ? -1 : preA > preB ? 1 : 0;\n\n return 0;\n}\n","import crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { Readable } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport { extract } from \"tar\";\nimport { compareSemver } from \"./semver.js\";\n\n/**\n * Parse a package specifier into name and version/tag.\n * Supports:\n * \"@scope/pkg\" -> { name: \"@scope/pkg\", tag: undefined }\n * \"@scope/pkg@dev\" -> { name: \"@scope/pkg\", tag: \"dev\" }\n * \"@scope/pkg@1.0.0\" -> { name: \"@scope/pkg\", tag: \"1.0.0\" }\n * \"pkg@latest\" -> { name: \"pkg\", tag: \"latest\" }\n */\nexport function parsePackageSpec(spec: string): {\n name: string;\n tag: string | undefined;\n} {\n // For scoped packages (@scope/name@tag), split on the last @\n // For unscoped packages (name@tag), split on the first @\n if (spec.startsWith(\"@\")) {\n // Scoped: find the @ after the scope/name portion\n const lastAt = spec.lastIndexOf(\"@\");\n if (lastAt > 0 && lastAt !== spec.indexOf(\"@\")) {\n return { name: spec.slice(0, lastAt), tag: spec.slice(lastAt + 1) };\n }\n return { name: spec, tag: undefined };\n }\n const atIndex = spec.indexOf(\"@\");\n if (atIndex > 0) {\n return { name: spec.slice(0, atIndex), tag: spec.slice(atIndex + 1) };\n }\n return { name: spec, tag: undefined };\n}\n\nexport class CdnCache {\n #extractionLocks = new Map<string, Promise<void>>();\n\n constructor(\n private registryUrl: string,\n private cdnCachePath: string,\n ) {}\n\n async getFileByVersion(\n packageName: string,\n version: string,\n filePath: string,\n ): Promise<string | null> {\n const versionDir = path.join(this.cdnCachePath, packageName, version);\n\n // Check all possible paths before attempting extraction\n const resolved = this.#resolveFile(versionDir, filePath);\n if (resolved) return resolved;\n\n // File not found in any location — extract tarball and try again\n await this.#extractWithLock(packageName, version);\n\n return this.#resolveFile(versionDir, filePath);\n }\n\n #resolveFile(versionDir: string, filePath: string): string | null {\n // Check direct path first, then fall back to cdn/ and dist/cdn/ subdirectories\n // (npm tarballs contain files under dist/, bun bundles go to cdn/)\n const candidates = [\n path.join(versionDir, filePath),\n path.join(versionDir, \"cdn\", filePath),\n path.join(versionDir, \"dist\", \"cdn\", filePath),\n path.join(versionDir, \"dist\", filePath),\n ];\n\n for (const candidate of candidates) {\n if (this.isSafePath(candidate) && fs.existsSync(candidate))\n return candidate;\n }\n\n return null;\n }\n\n async #extractWithLock(packageName: string, version: string): Promise<void> {\n const key = `${packageName}@${version}`;\n const existing = this.#extractionLocks.get(key);\n if (existing) return existing;\n\n const promise = this.extractTarball(packageName, version).finally(() => {\n this.#extractionLocks.delete(key);\n });\n this.#extractionLocks.set(key, promise);\n return promise;\n }\n\n getLatestCachedVersion(packageName: string): string | null {\n const pkgDir = path.join(this.cdnCachePath, packageName);\n try {\n const entries = fs.readdirSync(pkgDir, { withFileTypes: true });\n const versions = entries\n .filter((e) => e.isDirectory())\n .map((e) => e.name);\n if (versions.length === 0) return null;\n versions.sort(compareSemver);\n return versions[versions.length - 1];\n } catch {\n return null;\n }\n }\n\n /**\n * Resolve a version for a package. If tag is a semver version that exists\n * in the registry, return it directly. If tag is a dist-tag name (e.g.\n * \"dev\", \"latest\"), resolve it to the concrete version. If no tag is\n * provided, prefer \"latest\", then fall back to any available dist-tag.\n */\n async resolveVersion(\n packageName: string,\n tag?: string,\n ): Promise<string | null> {\n try {\n const url = `${this.registryUrl}/${encodeURIComponent(packageName)}`;\n const res = await fetch(url, {\n headers: { Accept: \"application/json\" },\n });\n if (!res.ok) return null;\n const metadata = (await res.json()) as Record<string, unknown>;\n const distTags = metadata[\"dist-tags\"] as\n | Record<string, string>\n | undefined;\n const versions = metadata[\"versions\"] as\n | Record<string, unknown>\n | undefined;\n\n if (tag) {\n // If the tag matches an exact version in the registry, use it directly\n if (versions && tag in versions) return tag;\n // Otherwise treat it as a dist-tag name\n if (distTags && tag in distTags) return distTags[tag];\n // Tag not found\n return null;\n }\n\n if (!distTags) return null;\n // No tag specified: prefer \"latest\", fall back to any available tag\n return distTags.latest ?? Object.values(distTags)[0] ?? null;\n } catch {\n return null;\n }\n }\n\n async extractTarball(packageName: string, version: string): Promise<void> {\n const shortName = packageName.startsWith(\"@\")\n ? packageName.split(\"/\")[1]\n : packageName;\n const tarballUrl = `${this.registryUrl}/${encodeURIComponent(packageName)}/-/${shortName}-${version}.tgz`;\n\n let res: Response;\n try {\n res = await fetch(tarballUrl);\n if (!res.ok || !res.body) return;\n } catch {\n return;\n }\n\n const destDir = path.join(this.cdnCachePath, packageName, version);\n fs.mkdirSync(destDir, { recursive: true });\n\n const tmpFile = path.join(\n destDir,\n `.tmp-tarball-${crypto.randomUUID()}.tgz`,\n );\n try {\n const fileStream = fs.createWriteStream(tmpFile);\n await pipeline(Readable.fromWeb(res.body as never), fileStream);\n await extract({ file: tmpFile, cwd: destDir, strip: 1 });\n } finally {\n fs.rmSync(tmpFile, { force: true });\n }\n }\n\n invalidate(packageName: string): void {\n const cacheDir = path.join(this.cdnCachePath, packageName);\n if (!this.isSafePath(cacheDir)) return;\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n\n /** Remove all cached version directories except the specified one. */\n pruneOldVersions(packageName: string, keepVersion: string): void {\n const pkgDir = path.join(this.cdnCachePath, packageName);\n try {\n const entries = fs.readdirSync(pkgDir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isDirectory() && entry.name !== keepVersion) {\n const dir = path.join(pkgDir, entry.name);\n if (this.isSafePath(dir)) {\n fs.rmSync(dir, { recursive: true, force: true });\n }\n }\n }\n } catch {\n // ignore — directory may not exist yet\n }\n }\n\n private isSafePath(filePath: string): boolean {\n const resolved = path.resolve(filePath);\n const cacheRoot = path.resolve(this.cdnCachePath);\n return resolved.startsWith(cacheRoot + path.sep) || resolved === cacheRoot;\n }\n}\n","import type { Manifest } from \"@powerhousedao/shared\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { compareSemver } from \"./semver.js\";\nimport type { PackageInfo } from \"./types.js\";\n\n/**\n * Read dist-tags, the full version list, and the local-publish flag for a\n * package from verdaccio's on-disk storage (`{storagePath}/{name}/package.json`).\n *\n * `locallyPublished` is tri-state:\n * - `true` → storage metadata has `_attachments` (tarball uploaded here).\n * - `false` → storage metadata exists but `_attachments` is empty (proxy\n * from the npm uplink only; no local publish at this registry).\n * - `undefined` → metadata file wasn't readable. Happens with non-filesystem\n * backends (S3, etc.) or if verdaccio stores metadata elsewhere.\n * Callers should treat this as \"unknown\" and default to including\n * the package, to avoid filtering the whole /packages list to an\n * empty array on deployments where we can't observe _attachments.\n */\nfunction readPackageMetadata(\n storagePath: string | undefined,\n packageName: string,\n): {\n distTags?: Record<string, string>;\n versions?: string[];\n locallyPublished: boolean | undefined;\n} {\n if (!storagePath) return { locallyPublished: undefined };\n try {\n const metadataPath = path.join(storagePath, packageName, \"package.json\");\n const raw = fs.readFileSync(metadataPath, \"utf-8\");\n const parsed = JSON.parse(raw) as {\n \"dist-tags\"?: Record<string, string>;\n versions?: Record<string, unknown>;\n _attachments?: Record<string, unknown>;\n };\n const distTags = parsed[\"dist-tags\"];\n const rawVersions = parsed.versions ? Object.keys(parsed.versions) : [];\n const versions = rawVersions.slice().sort(compareSemver);\n const locallyPublished =\n !!parsed._attachments && Object.keys(parsed._attachments).length > 0;\n return {\n distTags:\n distTags && Object.keys(distTags).length > 0 ? distTags : undefined,\n versions: versions.length > 0 ? versions : undefined,\n locallyPublished,\n };\n } catch {\n return { locallyPublished: undefined };\n }\n}\n\nfunction readManifest(dir: string): Manifest | null {\n const candidates = [\n path.join(dir, \"powerhouse.manifest.json\"),\n path.join(dir, \"cdn\", \"powerhouse.manifest.json\"),\n path.join(dir, \"dist\", \"powerhouse.manifest.json\"),\n ];\n for (const manifestPath of candidates) {\n try {\n const raw = fs.readFileSync(manifestPath, \"utf-8\");\n return JSON.parse(raw) as Manifest;\n } catch {\n // try next candidate\n }\n }\n return null;\n}\n\nfunction readPackageJsonVersion(dir: string): string | undefined {\n try {\n const raw = fs.readFileSync(path.join(dir, \"package.json\"), \"utf-8\");\n const pkg = JSON.parse(raw) as { version?: unknown };\n return typeof pkg.version === \"string\" ? pkg.version : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction getLatestVersionDir(pkgDir: string): string | null {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(pkgDir, { withFileTypes: true });\n } catch {\n return null;\n }\n const versions = entries.filter((e) => e.isDirectory()).map((e) => e.name);\n if (versions.length === 0) return null;\n versions.sort(compareSemver);\n return path.join(pkgDir, versions[versions.length - 1]);\n}\n\nexport function loadPackage(\n cdnCachePath: string,\n name: string,\n version?: string,\n): PackageInfo | null {\n const pkgDir = path.join(cdnCachePath, name);\n const versionDir = version\n ? path.join(pkgDir, version)\n : getLatestVersionDir(pkgDir);\n const manifestDir = versionDir ?? pkgDir;\n const manifest = readManifest(manifestDir);\n\n if (!manifest) {\n return null;\n }\n return {\n name: manifest.name ?? name,\n path: `/-/cdn/${name}`,\n manifest,\n documentTypes: getDocumentTypesFromManifest(manifest),\n version: readPackageJsonVersion(manifestDir),\n };\n}\n\nfunction getDocumentTypesFromManifest(manifest: Manifest | undefined | null) {\n if (!manifest) return [];\n\n const documentTypes: string[] = [];\n const { apps, documentModels, editors, subgraphs } = manifest;\n\n if (apps?.length) {\n documentTypes.push(\"powerhouse/document-drive\");\n }\n documentTypes.push(\n ...(documentModels ?? []).map((dm) => dm.id),\n ...(editors ?? [])\n .flatMap((e) => e.documentTypes)\n .filter((dt) => dt !== undefined),\n ...(subgraphs ?? [])\n .flatMap((e) => e.documentTypes)\n .filter((dt) => dt !== undefined),\n );\n\n return documentTypes;\n}\n\nexport function scanPackages(\n cdnCachePath: string,\n storagePath?: string,\n): PackageInfo[] {\n const absDir = path.resolve(cdnCachePath);\n const packages: PackageInfo[] = [];\n\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(absDir, { withFileTypes: true });\n } catch {\n return packages;\n }\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n\n if (entry.name.startsWith(\"@\")) {\n const scopeDir = path.join(absDir, entry.name);\n let scopedEntries: fs.Dirent[];\n try {\n scopedEntries = fs.readdirSync(scopeDir, { withFileTypes: true });\n } catch (error) {\n console.log(error);\n continue;\n }\n for (const scopedEntry of scopedEntries) {\n if (!scopedEntry.isDirectory()) continue;\n const dirName = `${entry.name}/${scopedEntry.name}`;\n const pkgDir = path.join(scopeDir, scopedEntry.name);\n const versionDir = getLatestVersionDir(pkgDir);\n const manifestDir = versionDir ?? pkgDir;\n const manifest = readManifest(manifestDir);\n const name = manifest?.name ?? dirName;\n const { distTags, versions, locallyPublished } = readPackageMetadata(\n storagePath,\n name,\n );\n // Drop npm-uplink passthroughs from the default listing. Only\n // skip when we can affirmatively tell the package is a proxy\n // (no `_attachments` in filesystem-backed storage). When the flag\n // is `undefined` (no storagePath, or non-filesystem backend where\n // we can't read verdaccio's metadata) we include the entry — the\n // alternative would be filtering everything to `[]` on S3 deploys.\n if (locallyPublished === false) continue;\n packages.push({\n name,\n path: `/-/cdn/${dirName}`,\n manifest,\n documentTypes: getDocumentTypesFromManifest(manifest),\n version: readPackageJsonVersion(manifestDir),\n distTags,\n versions,\n });\n }\n } else {\n const pkgDir = path.join(absDir, entry.name);\n const versionDir = getLatestVersionDir(pkgDir);\n const manifestDir = versionDir ?? pkgDir;\n const manifest = readManifest(manifestDir);\n const name = manifest?.name ?? entry.name;\n const { distTags, versions, locallyPublished } = readPackageMetadata(\n storagePath,\n name,\n );\n if (locallyPublished === false) continue;\n packages.push({\n name,\n path: `/-/cdn/${entry.name}`,\n manifest,\n documentTypes: getDocumentTypesFromManifest(manifest),\n version: readPackageJsonVersion(manifestDir),\n distTags,\n versions,\n });\n }\n }\n\n return packages;\n}\n\nexport function findPackagesByDocumentType(\n packagesDir: string,\n documentType: string,\n): PackageInfo[] {\n const allPackages = scanPackages(packagesDir);\n\n return allPackages.filter((pkg) => {\n if (!pkg.manifest?.documentModels) {\n return false;\n }\n return pkg.manifest.documentModels.some((dm) => dm.id === documentType);\n });\n}\n","import express, {\n Router,\n type NextFunction,\n type Request,\n type Response,\n} from \"express\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { CdnCache, parsePackageSpec } from \"./cdn.js\";\nimport type { SSEChannel } from \"./notifications/sse.js\";\nimport type { NotificationChannel } from \"./notifications/types.js\";\nimport type { WebhookChannel } from \"./notifications/webhook.js\";\nimport {\n findPackagesByDocumentType,\n loadPackage,\n scanPackages,\n} from \"./packages.js\";\nimport type { RegistryConfig } from \"./types.js\";\n\nconst MIME_TYPES: Record<string, string> = {\n \".js\": \"application/javascript\",\n \".mjs\": \"application/javascript\",\n \".css\": \"text/css\",\n \".json\": \"application/json\",\n \".wasm\": \"application/wasm\",\n \".map\": \"application/json\",\n \".html\": \"text/html\",\n \".svg\": \"image/svg+xml\",\n};\n\nfunction getContentType(filePath: string): string {\n const ext = path.extname(filePath).toLowerCase();\n return MIME_TYPES[ext] ?? \"application/octet-stream\";\n}\n\nexport function createPowerhouseRouter(\n config: RegistryConfig,\n sse: SSEChannel,\n webhooks: WebhookChannel,\n): Router {\n const cdn = new CdnCache(\n `http://localhost:${config.port}`,\n config.cdnCachePath,\n );\n const router = Router();\n\n // CORS on every response\n router.use((_req: Request, res: Response, next: NextFunction) => {\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n next();\n });\n\n // SSE endpoint for publish notifications\n router.get(\"/-/events\", (_req: Request, res: Response) => {\n sse.addClient(res);\n });\n\n // Webhook management\n router.get(\"/-/webhooks\", (_req: Request, res: Response) => {\n res.json(webhooks.getWebhooks());\n });\n\n router.post(\"/-/webhooks\", express.json(), (req: Request, res: Response) => {\n const { endpoint, headers } = req.body as {\n endpoint?: string;\n headers?: Record<string, string>;\n };\n if (!endpoint) {\n res.status(400).json({ error: \"Missing required field: endpoint\" });\n return;\n }\n webhooks.addWebhook({ endpoint, headers });\n res.status(201).json({ endpoint, headers });\n });\n\n router.delete(\n \"/-/webhooks\",\n express.json(),\n (req: Request, res: Response) => {\n const { endpoint } = req.body as { endpoint?: string };\n if (!endpoint) {\n res.status(400).json({ error: \"Missing required field: endpoint\" });\n return;\n }\n const removed = webhooks.removeWebhook(endpoint);\n if (!removed) {\n res.status(404).json({ error: \"Webhook not found\" });\n return;\n }\n res.status(204).end();\n },\n );\n\n // Package listing API\n router.get(\"/packages\", (req: Request, res: Response) => {\n const packages = scanPackages(config.cdnCachePath, config.storagePath);\n const documentType = req.query.documentType as string | undefined;\n if (documentType) {\n const filtered = packages.filter((pkg) =>\n pkg.manifest?.documentModels?.some((m) => m.id === documentType),\n );\n res.json(filtered);\n return;\n }\n res.json(packages);\n });\n\n // Find packages by document type - returns array of package names\n router.get(\"/packages/by-document-type\", (req: Request, res: Response) => {\n const documentType = req.query.type;\n\n if (typeof documentType !== \"string\" || !documentType) {\n res.status(400).json({ error: \"Missing required query parameter: type\" });\n return;\n }\n\n const packages = findPackagesByDocumentType(\n config.cdnCachePath,\n documentType,\n );\n const packageNames = packages.map((pkg) => pkg.name);\n res.json(packageNames);\n });\n\n // Single package info\n router.get(\"/packages/*name\", async (req: Request, res: Response) => {\n const raw = (req.params as Record<string, string[]>).name.join(\"/\");\n const { name, tag } = parsePackageSpec(raw);\n const version =\n (await cdn.resolveVersion(name, tag)) ?? cdn.getLatestCachedVersion(name);\n const pkg = loadPackage(config.cdnCachePath, name, version ?? undefined);\n if (!pkg) {\n res.status(404).send(\"Package not found\");\n return;\n }\n res.json(pkg);\n });\n\n // CDN file serving\n router.get(\"/-/cdn/*path\", async (req: Request, res: Response) => {\n const parts = (req.params as Record<string, string[]>).path;\n const fullPath = parts.join(\"/\");\n\n // Parse scoped or unscoped package specifier from the path\n let packageSpec: string;\n let filePath: string;\n\n if (fullPath.startsWith(\"@\")) {\n // Scoped: @scope/pkg@1.0.0/file.js -> packageSpec = @scope/pkg@1.0.0, filePath = file.js\n const segments = fullPath.split(\"/\");\n if (segments.length < 2) {\n res.status(400).send(\"Invalid package path\");\n return;\n }\n packageSpec = `${segments[0]}/${segments[1]}`;\n filePath = segments.slice(2).join(\"/\") || \"index.js\";\n } else {\n // Unscoped: pkg@1.0.0/file.js -> packageSpec = pkg@1.0.0, filePath = file.js\n const segments = fullPath.split(\"/\");\n packageSpec = segments[0];\n filePath = segments.slice(1).join(\"/\") || \"index.js\";\n }\n\n const { name: packageName, tag } = parsePackageSpec(packageSpec);\n const version =\n (await cdn.resolveVersion(packageName, tag)) ??\n cdn.getLatestCachedVersion(packageName);\n if (!version) {\n res.status(404).send(\"File not found\");\n return;\n }\n\n const resolved = await cdn.getFileByVersion(packageName, version, filePath);\n if (!resolved) {\n res.status(404).send(\"File not found\");\n return;\n }\n\n res.setHeader(\"Content-Type\", getContentType(filePath));\n const content = fs.readFileSync(resolved);\n res.send(content);\n });\n\n return router;\n}\n\nexport function createPublishHook(\n config: RegistryConfig,\n notifications: NotificationChannel,\n) {\n const cdn = new CdnCache(\n `http://localhost:${config.port}`,\n config.cdnCachePath,\n );\n\n return (req: Request, res: Response, next: NextFunction) => {\n // Only intercept PUT requests to npm publish endpoints\n if (req.method !== \"PUT\") {\n next();\n return;\n }\n\n const originalEnd = res.end.bind(res);\n res.end = function (\n this: Response,\n chunk?: unknown,\n encoding?: unknown,\n cb?: () => void,\n ) {\n const urlPath = req.path.replace(/^\\//, \"\");\n if (\n res.statusCode < 200 ||\n res.statusCode >= 300 ||\n !urlPath ||\n urlPath.startsWith(\"-\")\n ) {\n return originalEnd(chunk, encoding as BufferEncoding, cb);\n }\n const packageName = decodeURIComponent(urlPath);\n const versionsObj = (req.body as { versions: Record<string, unknown> })\n .versions;\n const versions = Object.keys(versionsObj);\n const version = versions.at(0);\n if (!version) {\n console.error(`[registry] No version found for ${packageName}`);\n return originalEnd(chunk, encoding as BufferEncoding, cb);\n }\n if (versions.length > 1) {\n console.warn(\n `[registry] Multiple versions published for ${packageName}: ${JSON.stringify(versions)}`,\n );\n }\n\n cdn\n .extractTarball(packageName, version)\n .then(() => {\n notifications.notifyPublish({ packageName, version });\n })\n .catch((err) => {\n console.error(\n `[registry] Failed to extract ${packageName} to CDN cache:`,\n err,\n );\n });\n\n return originalEnd(chunk, encoding as BufferEncoding, cb);\n };\n\n next();\n };\n}\n","import type { NotificationChannel, PublishEvent } from \"./types.js\";\n\nexport class NotificationManager implements NotificationChannel {\n #channels: NotificationChannel[];\n\n constructor(channels: NotificationChannel[]) {\n this.#channels = channels;\n }\n\n notifyPublish(event: PublishEvent): void {\n for (const channel of this.#channels) {\n channel.notifyPublish(event);\n }\n }\n}\n","import type { Response } from \"express\";\nimport type { NotificationChannel, PublishEvent } from \"./types.js\";\n\nexport class SSEChannel implements NotificationChannel {\n #clients = new Set<Response>();\n\n addClient(res: Response): void {\n res.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Access-Control-Allow-Origin\": \"*\",\n });\n res.write(\"event: connected\\ndata: {}\\n\\n\");\n\n this.#clients.add(res);\n res.on(\"close\", () => {\n this.#clients.delete(res);\n });\n }\n\n notifyPublish(event: PublishEvent): void {\n const payload = `event: publish\\ndata: ${JSON.stringify(event)}\\n\\n`;\n for (const client of this.#clients) {\n try {\n client.write(payload);\n } catch (err) {\n console.error(\"[registry] SSE client write failed:\", err);\n this.#clients.delete(client);\n }\n }\n }\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { NotifyConfig, WebhookConfig } from \"../types.js\";\nimport type { NotificationChannel, PublishEvent } from \"./types.js\";\n\nconst WEBHOOKS_FILE = \"webhooks.json\";\n\nexport class WebhookChannel implements NotificationChannel {\n #predefined: WebhookConfig[];\n #dynamic: WebhookConfig[];\n #storagePath: string;\n\n constructor(storagePath: string, config?: NotifyConfig) {\n this.#storagePath = storagePath;\n this.#predefined = config?.webhooks ?? [];\n this.#dynamic = this.#load();\n }\n\n getWebhooks(): WebhookConfig[] {\n return [...this.#predefined, ...this.#dynamic];\n }\n\n addWebhook(webhook: WebhookConfig): void {\n const exists = this.getWebhooks().some(\n (w) => w.endpoint === webhook.endpoint,\n );\n if (exists) return;\n this.#dynamic.push(webhook);\n this.#save();\n }\n\n removeWebhook(endpoint: string): boolean {\n const before = this.#dynamic.length;\n this.#dynamic = this.#dynamic.filter((w) => w.endpoint !== endpoint);\n if (this.#dynamic.length === before) return false;\n this.#save();\n return true;\n }\n\n notifyPublish(event: PublishEvent): void {\n for (const webhook of this.getWebhooks()) {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...webhook.headers,\n };\n\n fetch(webhook.endpoint, {\n method: \"POST\",\n headers,\n body: JSON.stringify(event),\n }).catch((err: unknown) => {\n console.error(`[registry] Webhook to ${webhook.endpoint} failed:`, err);\n });\n }\n }\n\n #filePath(): string {\n return path.join(this.#storagePath, WEBHOOKS_FILE);\n }\n\n #load(): WebhookConfig[] {\n try {\n const raw = fs.readFileSync(this.#filePath(), \"utf-8\");\n return JSON.parse(raw) as WebhookConfig[];\n } catch {\n return [];\n }\n }\n\n #save(): void {\n fs.mkdirSync(this.#storagePath, { recursive: true });\n fs.writeFileSync(this.#filePath(), JSON.stringify(this.#dynamic, null, 2));\n }\n}\n","import path from \"node:path\";\nimport type { RegistryConfig } from \"./types.js\";\n\nexport function buildVerdaccioConfig(config: RegistryConfig) {\n const htpasswdPath = path.join(config.storagePath, \"htpasswd\");\n\n const uplinkUrl = config.uplink ?? \"https://registry.npmjs.org/\";\n\n const base: Record<string, unknown> = {\n storage: config.storagePath,\n self_path: \"./\",\n auth: {\n htpasswd: {\n file: htpasswdPath,\n },\n },\n uplinks: {\n npmjs: {\n url: uplinkUrl,\n maxage: \"15m\",\n timeout: \"30s\",\n cache: true,\n },\n },\n packages: {\n \"@powerhousedao/*\": {\n access: \"$all\",\n publish: \"$authenticated\",\n unpublish: \"$authenticated\",\n proxy: \"npmjs\",\n },\n \"**\": {\n access: \"$all\",\n publish: \"$authenticated\",\n unpublish: \"$authenticated\",\n proxy: \"npmjs\",\n },\n },\n web: {\n enable: config.webEnabled !== false,\n title: \"Powerhouse Registry\",\n logo: \"https://raw.githubusercontent.com/powerhouse-inc/powerhouse/main/packages/registry/static/logo.svg\",\n favicon: \"/-/static/favicon.ico\",\n primary_color: \"#38C780\",\n darkMode: true,\n },\n server: {\n keepAliveTimeout: 60,\n },\n log: {\n type: \"stdout\",\n format: \"pretty\",\n level: \"warn\",\n },\n max_body_size: config.maxBodySize ?? \"300mb\",\n };\n\n if (config.s3) {\n base.store = {\n \"aws-s3-storage\": {\n bucket: config.s3.bucket,\n endpoint: config.s3.endpoint,\n region: config.s3.region,\n s3ForcePathStyle: config.s3.s3ForcePathStyle ?? true,\n ...(config.s3.keyPrefix && { keyPrefix: config.s3.keyPrefix }),\n ...(config.s3.accessKeyId && { accessKeyId: config.s3.accessKeyId }),\n ...(config.s3.secretAccessKey && {\n secretAccessKey: config.s3.secretAccessKey,\n }),\n },\n };\n }\n\n return base;\n}\n","import express from \"express\";\nimport { findUp } from \"find-up\";\nimport { mkdir } from \"node:fs/promises\";\nimport type { Server } from \"node:http\";\nimport path from \"node:path\";\nimport { runServer } from \"verdaccio\";\nimport { createPowerhouseRouter, createPublishHook } from \"./middleware.js\";\nimport { NotificationManager } from \"./notifications/manager.js\";\nimport { SSEChannel } from \"./notifications/sse.js\";\nimport { WebhookChannel } from \"./notifications/webhook.js\";\nimport type { RegistryCommandArgs, RegistryConfig } from \"./types.js\";\nimport { buildVerdaccioConfig } from \"./verdaccio-config.js\";\n\nasync function resolveDir(dir: string): Promise<string> {\n if (path.isAbsolute(dir)) {\n await mkdir(dir, { recursive: true });\n return dir;\n }\n const found = await findUp(dir, { type: \"directory\" });\n if (!found) {\n await mkdir(dir, { recursive: true });\n return dir;\n }\n return found;\n}\n\nexport async function runRegistry(args: RegistryCommandArgs) {\n const {\n port,\n storageDir,\n cdnCacheDir,\n uplink,\n webEnabled,\n webhooks,\n s3AccessKeyId,\n s3Bucket,\n s3Endpoint,\n s3ForcePathStyle,\n s3KeyPrefix,\n s3Region,\n s3SecretAccessKey,\n } = args;\n const storagePath = await resolveDir(storageDir);\n const cdnCachePath = await resolveDir(cdnCacheDir);\n\n console.log({\n storagePath,\n cdnCachePath,\n });\n\n const webhookConfigs = webhooks\n ?.split(\",\")\n .map((url) => url.trim())\n .filter(Boolean)\n .map((endpoint) => ({ endpoint }));\n\n const config: RegistryConfig = {\n port,\n storagePath,\n cdnCachePath,\n uplink,\n webEnabled,\n ...(webhookConfigs?.length && {\n notify: { webhooks: webhookConfigs },\n }),\n ...(s3Bucket &&\n s3Endpoint &&\n s3Region && {\n s3: {\n bucket: s3Bucket,\n endpoint: s3Endpoint,\n region: s3Region,\n accessKeyId: s3AccessKeyId,\n secretAccessKey: s3SecretAccessKey,\n keyPrefix: s3KeyPrefix,\n s3ForcePathStyle,\n },\n }),\n };\n // Ensure directories exist (for relative paths resolved via findUp)\n await mkdir(storagePath, { recursive: true });\n await mkdir(cdnCachePath, { recursive: true });\n\n const verdaccioConfig = buildVerdaccioConfig(config);\n\n // verdaccio's runServer returns Promise<any> (upstream type limitation)\n const verdaccioServer = (await runServer(verdaccioConfig)) as Server;\n const verdaccioHandler = verdaccioServer.listeners(\"request\")[0] as (\n ...args: unknown[]\n ) => void;\n\n const app = express();\n\n const sseChannel = new SSEChannel();\n const webhookChannel = new WebhookChannel(config.storagePath, config.notify);\n const notifications = new NotificationManager([sseChannel, webhookChannel]);\n\n // Serve static assets (logo, etc.)\n const staticDir = await findUp(\"static\", { type: \"directory\" });\n if (staticDir) {\n app.use(\"/-/static\", express.static(staticDir));\n }\n\n // Our routes take priority over Verdaccio\n app.use(createPowerhouseRouter(config, sseChannel, webhookChannel));\n app.use(createPublishHook(config, notifications));\n\n // Verdaccio handles everything else (npm protocol, web UI, auth)\n app.use((req, res) => verdaccioHandler(req, res));\n\n const server = app.listen(port, () => {\n console.log(`Powerhouse Registry running on http://localhost:${port}`);\n console.log(` CDN: http://localhost:${port}/-/cdn/`);\n console.log(` Packages: http://localhost:${port}/packages`);\n console.log(` npm: http://localhost:${port}/`);\n console.log(` Storage: ${storagePath}`);\n console.log(` CDN cache: ${cdnCachePath}`);\n if (config.s3) {\n console.log(` S3: ${config.s3.endpoint}/${config.s3.bucket}`);\n }\n });\n\n return server;\n}\n","import {\n binary,\n command,\n flag,\n number,\n option,\n optional,\n run,\n string,\n} from \"cmd-ts\";\nimport {\n DEFAULT_PORT,\n DEFAULT_REGISTRY_CDN_CACHE_DIR_NAME,\n DEFAULT_STORAGE_DIR_NAME,\n} from \"./src/constants.js\";\nimport { runRegistry } from \"./src/run.js\";\n\nexport const registryCommand = command({\n name: \"Package registry\",\n args: {\n port: option({\n long: \"port\",\n type: number,\n defaultValue: () => Number(process.env.PORT) || DEFAULT_PORT,\n defaultValueIsSerializable: true,\n }),\n storageDir: option({\n long: \"storage-dir\",\n type: string,\n defaultValue: () =>\n process.env.REGISTRY_STORAGE || DEFAULT_STORAGE_DIR_NAME,\n defaultValueIsSerializable: true,\n }),\n cdnCacheDir: option({\n long: \"cdn-cache-dir\",\n type: string,\n defaultValue: () =>\n process.env.REGISTRY_CDN_CACHE || DEFAULT_REGISTRY_CDN_CACHE_DIR_NAME,\n defaultValueIsSerializable: true,\n }),\n uplink: option({\n long: \"uplink\",\n type: optional(string),\n defaultValue: () => process.env.REGISTRY_UPLINK,\n defaultValueIsSerializable: true,\n }),\n s3Bucket: option({\n long: \"s3-bucket\",\n type: optional(string),\n defaultValue: () => process.env.S3_BUCKET,\n defaultValueIsSerializable: true,\n }),\n s3Endpoint: option({\n long: \"s3-endpoint\",\n type: optional(string),\n defaultValue: () => process.env.S3_ENDPOINT,\n defaultValueIsSerializable: true,\n }),\n s3Region: option({\n long: \"s3-region\",\n type: optional(string),\n defaultValue: () => process.env.S3_REGION,\n defaultValueIsSerializable: true,\n }),\n s3AccessKeyId: option({\n long: \"s3-access-key-id\",\n type: optional(string),\n defaultValue: () => process.env.S3_ACCESS_KEY_ID,\n defaultValueIsSerializable: true,\n }),\n s3SecretAccessKey: option({\n long: \"s3-secret-access-key\",\n type: optional(string),\n defaultValue: () => process.env.S3_SECRET_ACCESS_KEY,\n defaultValueIsSerializable: true,\n }),\n s3KeyPrefix: option({\n long: \"s3-key-prefix\",\n type: optional(string),\n defaultValue: () => process.env.S3_KEY_PREFIX,\n defaultValueIsSerializable: true,\n }),\n s3ForcePathStyle: flag({\n long: \"s3-force-path-style\",\n defaultValue: () => process.env.S3_FORCE_PATH_STYLE !== \"false\",\n defaultValueIsSerializable: true,\n }),\n webEnabled: flag({\n long: \"web-enabled\",\n defaultValue: () => process.env.REGISTRY_WEB !== \"false\",\n defaultValueIsSerializable: true,\n }),\n webhooks: option({\n long: \"webhook\",\n type: optional(string),\n description: \"Comma-separated webhook URLs to notify on publish\",\n defaultValue: () => process.env.REGISTRY_WEBHOOKS,\n defaultValueIsSerializable: true,\n }),\n },\n handler: async (args) => {\n console.log(args);\n\n try {\n await runRegistry(args);\n } catch (error) {\n console.error(\"Failed to start registry:\");\n console.error(error);\n process.exit(1);\n }\n },\n});\n\nconst registryCli = binary(registryCommand);\n\nawait run(registryCli, process.argv);\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@powerhousedao/registry",
|
|
3
|
-
"version": "6.0.0-dev.
|
|
3
|
+
"version": "6.0.0-dev.192",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"tar": "^7.5.11",
|
|
26
26
|
"verdaccio": "^6.5.0",
|
|
27
27
|
"verdaccio-aws-s3-storage": "^10.4.0",
|
|
28
|
-
"@powerhousedao/shared": "6.0.0-dev.
|
|
28
|
+
"@powerhousedao/shared": "6.0.0-dev.192"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"tsdown": "0.21.1",
|