@powerhousedao/registry 6.2.3-dev.35 → 6.2.3-dev.37
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.d.mts +2 -0
- package/dist/cli.d.mts.map +1 -1
- package/dist/cli.mjs +66 -40
- package/dist/cli.mjs.map +1 -1
- package/package.json +3 -3
package/dist/cli.d.mts
CHANGED
|
@@ -22,6 +22,7 @@ export declare const registryCommand: Partial<import("cmd-ts/dist/cjs/argparser.
|
|
|
22
22
|
workers: number;
|
|
23
23
|
uplink: string | undefined;
|
|
24
24
|
uplinkMaxage: string | undefined;
|
|
25
|
+
trustProxy: string | undefined;
|
|
25
26
|
webEnabled: boolean;
|
|
26
27
|
publicUrl: string | undefined;
|
|
27
28
|
authRenown: boolean;
|
|
@@ -51,6 +52,7 @@ export declare const registryCommand: Partial<import("cmd-ts/dist/cjs/argparser.
|
|
|
51
52
|
workers: number;
|
|
52
53
|
uplink: string | undefined;
|
|
53
54
|
uplinkMaxage: string | undefined;
|
|
55
|
+
trustProxy: string | undefined;
|
|
54
56
|
webEnabled: boolean;
|
|
55
57
|
publicUrl: string | undefined;
|
|
56
58
|
authRenown: boolean;
|
package/dist/cli.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.mts","names":[],"sources":["../cli.ts"],"mappings":";qBA2Ia,iBAAe,+CAAA
|
|
1
|
+
{"version":3,"file":"cli.d.mts","names":[],"sources":["../cli.ts"],"mappings":";qBA2Ia,iBAAe,+CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA2I1B,6CAAA,iDAAA,mDAAA;qBAEW,eAAa,+CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAyCxB,6CAAA,iDAAA,mDAAA;qBAEW,gBAAc,+CAAA;;;;;;;;;;;;IAkBzB,6CAAA,iDAAA,mDAAA;qBAEW,6BAA2B,+CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAatC,6CAAA,iDAAA,mDAAA"}
|
package/dist/cli.mjs
CHANGED
|
@@ -1919,13 +1919,19 @@ function createS3ArtifactStore(config) {
|
|
|
1919
1919
|
},
|
|
1920
1920
|
async putFile(key, file, contentType) {
|
|
1921
1921
|
const { size } = await fs.promises.stat(file);
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1922
|
+
const body = fs.createReadStream(file);
|
|
1923
|
+
body.on("error", () => void 0);
|
|
1924
|
+
try {
|
|
1925
|
+
await s3.send(new PutObjectCommand({
|
|
1926
|
+
Bucket: config.bucket,
|
|
1927
|
+
Key: root + key,
|
|
1928
|
+
Body: body,
|
|
1929
|
+
ContentLength: size,
|
|
1930
|
+
ContentType: contentType
|
|
1931
|
+
}));
|
|
1932
|
+
} finally {
|
|
1933
|
+
body.destroy();
|
|
1934
|
+
}
|
|
1929
1935
|
},
|
|
1930
1936
|
async get(key) {
|
|
1931
1937
|
try {
|
|
@@ -2826,9 +2832,16 @@ function inside(root, relative) {
|
|
|
2826
2832
|
}
|
|
2827
2833
|
async function inBatches(items, size, fn) {
|
|
2828
2834
|
let cursor = 0;
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2835
|
+
let failed = false;
|
|
2836
|
+
const rejected = (await Promise.allSettled(Array.from({ length: Math.min(size, items.length) }, async () => {
|
|
2837
|
+
while (!failed && cursor < items.length) try {
|
|
2838
|
+
await fn(items[cursor++]);
|
|
2839
|
+
} catch (err) {
|
|
2840
|
+
failed = true;
|
|
2841
|
+
throw err;
|
|
2842
|
+
}
|
|
2843
|
+
}))).find((lane) => lane.status === "rejected");
|
|
2844
|
+
if (rejected) throw rejected.reason;
|
|
2832
2845
|
}
|
|
2833
2846
|
async function packDir(dir) {
|
|
2834
2847
|
const files = listFiles(dir);
|
|
@@ -4761,7 +4774,10 @@ function buildVerdaccioConfig(config) {
|
|
|
4761
4774
|
primary_color: "#38C780",
|
|
4762
4775
|
darkMode: true
|
|
4763
4776
|
},
|
|
4764
|
-
server: {
|
|
4777
|
+
server: {
|
|
4778
|
+
keepAliveTimeout: 60,
|
|
4779
|
+
...config.trustProxy !== void 0 && { trustProxy: config.trustProxy }
|
|
4780
|
+
},
|
|
4765
4781
|
log: {
|
|
4766
4782
|
type: "stdout",
|
|
4767
4783
|
format: "pretty",
|
|
@@ -4799,8 +4815,10 @@ async function enqueueSweep(db) {
|
|
|
4799
4815
|
return names.rows.length;
|
|
4800
4816
|
}
|
|
4801
4817
|
async function hasManifestIndex(db) {
|
|
4802
|
-
return (await db.query(
|
|
4818
|
+
return (await db.query(`SELECT to_regclass('verdaccio_manifests') IS NOT NULL
|
|
4819
|
+
AND to_regclass('verdaccio_packages') IS NOT NULL AS exists`)).rows[0]?.exists === true;
|
|
4803
4820
|
}
|
|
4821
|
+
const PUBLISHED = "EXISTS (SELECT 1 FROM verdaccio_packages l WHERE l.name = m.name)";
|
|
4804
4822
|
const UNPUBLISHED = `
|
|
4805
4823
|
SELECT p.name FROM registry_packages p
|
|
4806
4824
|
WHERE p.local AND p.updated_at < now() - interval '30 seconds'
|
|
@@ -4809,7 +4827,7 @@ const QUICK_CHANGED = `
|
|
|
4809
4827
|
SELECT m.name
|
|
4810
4828
|
FROM verdaccio_manifests m
|
|
4811
4829
|
LEFT JOIN registry_packages p ON p.name = m.name
|
|
4812
|
-
WHERE m.updated_at < now() - interval '30 seconds'
|
|
4830
|
+
WHERE m.updated_at < now() - interval '30 seconds' AND ${PUBLISHED}
|
|
4813
4831
|
AND (p.name IS NULL OR p.manifest_rev IS DISTINCT FROM m.rev)
|
|
4814
4832
|
UNION ${UNPUBLISHED}
|
|
4815
4833
|
LIMIT 1000`;
|
|
@@ -4826,7 +4844,7 @@ const FULL_MISSING = `
|
|
|
4826
4844
|
FROM verdaccio_manifests m
|
|
4827
4845
|
CROSS JOIN LATERAL jsonb_array_elements_text(m.versions) AS v(version)
|
|
4828
4846
|
LEFT JOIN registry_versions r ON r.package = m.name AND r.version = v.version
|
|
4829
|
-
WHERE m.updated_at < now() - interval '30 seconds'
|
|
4847
|
+
WHERE m.updated_at < now() - interval '30 seconds' AND ${PUBLISHED}
|
|
4830
4848
|
AND (r.package IS NULL
|
|
4831
4849
|
OR (r.status = 'pending' AND r.updated_at < now() - interval '5 minutes'
|
|
4832
4850
|
AND NOT EXISTS (SELECT 1 FROM registry_jobs j
|
|
@@ -4837,7 +4855,7 @@ const FULL_CHANGED = `
|
|
|
4837
4855
|
SELECT m.name
|
|
4838
4856
|
FROM verdaccio_manifests m
|
|
4839
4857
|
LEFT JOIN registry_packages p ON p.name = m.name
|
|
4840
|
-
WHERE m.updated_at < now() - interval '30 seconds'
|
|
4858
|
+
WHERE m.updated_at < now() - interval '30 seconds' AND ${PUBLISHED}
|
|
4841
4859
|
AND (p.name IS NULL OR p.dist_tags <> m.dist_tags
|
|
4842
4860
|
OR EXISTS (SELECT 1 FROM registry_versions r
|
|
4843
4861
|
WHERE r.package = m.name AND NOT m.versions ? r.version))
|
|
@@ -4853,6 +4871,22 @@ async function reconcile(db, options = {}) {
|
|
|
4853
4871
|
if (queued > 0) await wakeWorkers(db);
|
|
4854
4872
|
return queued;
|
|
4855
4873
|
}
|
|
4874
|
+
async function pruneCachedPackages(q, published) {
|
|
4875
|
+
if (!(await q.query("SELECT to_regclass('registry_jobs') IS NOT NULL AS exists")).rows[0]?.exists) return [];
|
|
4876
|
+
const pruned = (await q.query(`DELETE FROM verdaccio_packages p
|
|
4877
|
+
WHERE p.name <> ALL($1::text[])
|
|
4878
|
+
AND NOT EXISTS (SELECT 1 FROM registry_package_owners o
|
|
4879
|
+
WHERE o.package_name = p.name)
|
|
4880
|
+
AND NOT EXISTS (SELECT 1 FROM registry_packages r
|
|
4881
|
+
WHERE r.name = p.name AND r.listed_manifest IS NOT NULL)
|
|
4882
|
+
RETURNING p.name`, [published])).rows.map((row) => row.name);
|
|
4883
|
+
if (pruned.length) {
|
|
4884
|
+
await q.query("DELETE FROM registry_jobs WHERE package = ANY($1) AND locked_by IS NULL", [pruned]);
|
|
4885
|
+
await q.query("DELETE FROM registry_versions WHERE package = ANY($1)", [pruned]);
|
|
4886
|
+
await q.query("DELETE FROM registry_packages WHERE name = ANY($1)", [pruned]);
|
|
4887
|
+
}
|
|
4888
|
+
return pruned;
|
|
4889
|
+
}
|
|
4856
4890
|
function publisherOf(job) {
|
|
4857
4891
|
const by = job.payload.publishedBy;
|
|
4858
4892
|
return by?.address ? by : void 0;
|
|
@@ -5057,8 +5091,11 @@ async function seedVerdaccioSecret(databaseUrl, secret) {
|
|
|
5057
5091
|
const MIB = 1048576;
|
|
5058
5092
|
const DRAIN_DELAY_MS = 5e3;
|
|
5059
5093
|
const DRAIN_TIMEOUT_MS = 2e4;
|
|
5094
|
+
function parseTrustProxy(value) {
|
|
5095
|
+
return /^\d+$/.test(value) ? Number(value) : value;
|
|
5096
|
+
}
|
|
5060
5097
|
async function runRegistry(args) {
|
|
5061
|
-
const { port, storageDir, cdnCacheDir, uplink, uplinkMaxage, webEnabled, webhooks, publicUrl, authRenown, renownUrl, verdaccioSecret, localPackages, databaseUrl, pluginsDir, authStore } = args;
|
|
5098
|
+
const { port, storageDir, cdnCacheDir, uplink, uplinkMaxage, trustProxy, webEnabled, webhooks, publicUrl, authRenown, renownUrl, verdaccioSecret, localPackages, databaseUrl, pluginsDir, authStore } = args;
|
|
5062
5099
|
const storagePath = await resolveDir(storageDir);
|
|
5063
5100
|
const cdnCachePath = await resolveDir(cdnCacheDir);
|
|
5064
5101
|
const s3 = s3From(args);
|
|
@@ -5084,6 +5121,7 @@ async function runRegistry(args) {
|
|
|
5084
5121
|
uplink,
|
|
5085
5122
|
uplinkMaxage,
|
|
5086
5123
|
webEnabled,
|
|
5124
|
+
...trustProxy ? { trustProxy: parseTrustProxy(trustProxy) } : {},
|
|
5087
5125
|
...localPackagePatterns?.length ? { localPackagePatterns } : {},
|
|
5088
5126
|
...renownEnabled && publicUrl ? { renown: {
|
|
5089
5127
|
publicUrl,
|
|
@@ -5271,27 +5309,6 @@ async function runMigrate(databaseUrl, options) {
|
|
|
5271
5309
|
await db.close();
|
|
5272
5310
|
}
|
|
5273
5311
|
}
|
|
5274
|
-
async function storedPackageNames(s3, config) {
|
|
5275
|
-
const prefix = config.keyPrefix ?? "";
|
|
5276
|
-
const names = /* @__PURE__ */ new Set();
|
|
5277
|
-
let token;
|
|
5278
|
-
do {
|
|
5279
|
-
const page = await s3.send(new ListObjectsV2Command({
|
|
5280
|
-
Bucket: config.bucket,
|
|
5281
|
-
Prefix: prefix,
|
|
5282
|
-
ContinuationToken: token
|
|
5283
|
-
}));
|
|
5284
|
-
for (const { Key } of page.Contents ?? []) {
|
|
5285
|
-
const rel = Key?.slice(prefix.length) ?? "";
|
|
5286
|
-
if (!rel.endsWith("/package.json") || rel.startsWith("artifacts/")) continue;
|
|
5287
|
-
const name = rel.slice(0, -13);
|
|
5288
|
-
const depth = name.split("/").length;
|
|
5289
|
-
if (name.startsWith("@") ? depth === 2 : depth === 1) names.add(name);
|
|
5290
|
-
}
|
|
5291
|
-
token = page.IsTruncated ? page.NextContinuationToken : void 0;
|
|
5292
|
-
} while (token);
|
|
5293
|
-
return names;
|
|
5294
|
-
}
|
|
5295
5312
|
async function readStoredManifest(s3, config, name) {
|
|
5296
5313
|
try {
|
|
5297
5314
|
const res = await s3.send(new GetObjectCommand({
|
|
@@ -5327,9 +5344,9 @@ async function runImportVerdaccioState(args) {
|
|
|
5327
5344
|
const name = err.name;
|
|
5328
5345
|
if (name !== "NoSuchKey" && name !== "NotFound") throw err;
|
|
5329
5346
|
}
|
|
5330
|
-
const names =
|
|
5331
|
-
for (const name of legacy.list ?? []) names.add(name);
|
|
5347
|
+
const names = new Set(legacy.list ?? []);
|
|
5332
5348
|
const pool = new pg.Pool({ connectionString: args.databaseUrl });
|
|
5349
|
+
let pruned = [];
|
|
5333
5350
|
try {
|
|
5334
5351
|
const store = new S3DatabasePostgres(pool, pluginLogger);
|
|
5335
5352
|
await store.init();
|
|
@@ -5338,6 +5355,7 @@ async function runImportVerdaccioState(args) {
|
|
|
5338
5355
|
if (manifest) await store.record(name, manifest);
|
|
5339
5356
|
}
|
|
5340
5357
|
for (const name of names) await pool.query("INSERT INTO verdaccio_packages (name) VALUES ($1) ON CONFLICT (name) DO NOTHING", [name]);
|
|
5358
|
+
pruned = await pruneCachedPackages(pool, [...names]);
|
|
5341
5359
|
for (const token of legacy.tokens ?? []) await pool.query(`INSERT INTO verdaccio_tokens ("user", key, token) VALUES ($1, $2, $3)
|
|
5342
5360
|
ON CONFLICT ("user", key) DO NOTHING`, [
|
|
5343
5361
|
token.user,
|
|
@@ -5349,7 +5367,7 @@ async function runImportVerdaccioState(args) {
|
|
|
5349
5367
|
} finally {
|
|
5350
5368
|
await pool.end();
|
|
5351
5369
|
}
|
|
5352
|
-
console.log(`[registry] imported ${names.size} package name(s), ${legacy.tokens?.length ?? 0} token(s)${legacy.secret ? " and the secret" : ""}`);
|
|
5370
|
+
console.log(`[registry] imported ${names.size} package name(s), ${legacy.tokens?.length ?? 0} token(s)${legacy.secret ? " and the secret" : ""}; pruned ${pruned.length} cached package(s)`);
|
|
5353
5371
|
}
|
|
5354
5372
|
//#endregion
|
|
5355
5373
|
//#region cli.ts
|
|
@@ -5500,6 +5518,13 @@ const registryCommand = command({
|
|
|
5500
5518
|
defaultValue: () => process.env.PH_REGISTRY_UPLINK_MAXAGE,
|
|
5501
5519
|
defaultValueIsSerializable: true
|
|
5502
5520
|
}),
|
|
5521
|
+
trustProxy: option({
|
|
5522
|
+
long: "trust-proxy",
|
|
5523
|
+
type: optional(string),
|
|
5524
|
+
description: "Express `trust proxy` (e.g. 2 proxy hops), so rate limits key on client IPs; env PH_REGISTRY_TRUST_PROXY",
|
|
5525
|
+
defaultValue: () => process.env.PH_REGISTRY_TRUST_PROXY,
|
|
5526
|
+
defaultValueIsSerializable: true
|
|
5527
|
+
}),
|
|
5503
5528
|
webEnabled: flag({
|
|
5504
5529
|
long: "web-enabled",
|
|
5505
5530
|
defaultValue: () => process.env.REGISTRY_WEB !== "false",
|
|
@@ -5546,6 +5571,7 @@ const registryCommand = command({
|
|
|
5546
5571
|
databaseUrl: redact(args.databaseUrl),
|
|
5547
5572
|
listenDatabaseUrl: redact(args.listenDatabaseUrl),
|
|
5548
5573
|
verdaccioSecret: redact(args.verdaccioSecret),
|
|
5574
|
+
s3AccessKeyId: redact(args.s3AccessKeyId),
|
|
5549
5575
|
s3SecretAccessKey: redact(args.s3SecretAccessKey)
|
|
5550
5576
|
});
|
|
5551
5577
|
try {
|