Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 3ad71b4

Browse files
author
hulutter
committed
feat(privateNpmRegistry): add workspaceId support for cache directory structure
1 parent 89c0d38 commit 3ad71b4

File tree

1 file changed

+65
-32
lines changed
  • server/node-service/src/controllers

1 file changed

+65
-32
lines changed

‎server/node-service/src/controllers/npm.ts

Lines changed: 65 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
11
import "../common/logger";
22
import fs from "fs/promises";
33
import { spawn } from "child_process";
4-
import { response,Request as ServerRequest, Response as ServerResponse } from "express";
4+
import { Request as ServerRequest, Response as ServerResponse } from "express";
55
import { NpmRegistryService, NpmRegistryConfigEntry, NpmRegistryConfig } from "../services/npmRegistry";
66

77

8+
type RequestConfig = {
9+
workspaceId: string;
10+
npmRegistryConfig: NpmRegistryConfig;
11+
}
12+
13+
type InnerRequestConfig = {
14+
workspaceId?: string;
15+
registry: NpmRegistryConfigEntry;
16+
}
17+
818
type PackagesVersionInfo = {
919
"dist-tags": {
1020
latest: string
@@ -23,24 +33,24 @@ class PackageProcessingQueue {
2333
public static readonly promiseRegistry: {[packageId: string]: Promise<void>} = {};
2434
public static readonly resolveRegistry: {[packageId: string]:() => void} = {};
2535

26-
public static add(packageId: string) {
36+
public static add(packageId: string): void {
2737
PackageProcessingQueue.promiseRegistry[packageId] = new Promise<void>((resolve) => {
2838
PackageProcessingQueue.resolveRegistry[packageId] = resolve;
2939
});
3040
}
3141

32-
public static has(packageId: string) {
42+
public static has(packageId: string): boolean {
3343
return !!PackageProcessingQueue.promiseRegistry[packageId];
3444
}
3545

36-
public static wait(packageId: string) {
46+
public static wait(packageId: string): Promise<void> {
3747
if (!PackageProcessingQueue.has(packageId)) {
3848
return Promise.resolve();
3949
}
4050
return PackageProcessingQueue.promiseRegistry[packageId];
4151
}
4252

43-
public static resolve(packageId: string) {
53+
public static resolve(packageId: string): void {
4454
if (!PackageProcessingQueue.has(packageId)) {
4555
return;
4656
}
@@ -78,10 +88,18 @@ export async function fetchRegistryWithConfig(request: ServerRequest, response:
7888
return response.status(400).send(`Invalid package path: ${path}`);
7989
}
8090

81-
const registryConfig: NpmRegistryConfig = request.body;
82-
const config = NpmRegistryService.getRegistryEntryForPackageWithConfig(pathPackageInfo.packageId, registryConfig);
91+
if (!request.body.workspaceId && !request.body.npmRegistryConfig) {
92+
return response.status(400).send("Missing workspaceId and/or npmRegistryConfig");
93+
}
94+
95+
const {npmRegistryConfig}: RequestConfig = request.body;
96+
97+
const registry = NpmRegistryService.getRegistryEntryForPackageWithConfig(pathPackageInfo.packageId, npmRegistryConfig);
8398

84-
const registryResponse = await fetchFromRegistry(path, config);
99+
const registryResponse = await fetchFromRegistry(path, registry);
100+
if (!registryResponse.ok) {
101+
return response.status(registryResponse.status).send(await registryResponse.text());
102+
}
85103
response.json(await registryResponse.json());
86104
} catch (error) {
87105
logger.error("Error fetching registry", error);
@@ -99,8 +117,11 @@ export async function fetchRegistry(request: ServerRequest, response: ServerResp
99117
return response.status(400).send(`Invalid package path: ${path}`);
100118
}
101119

102-
const config = NpmRegistryService.getInstance().getRegistryEntryForPackage(pathPackageInfo.packageId);
103-
const registryResponse = await fetchFromRegistry(path, config);
120+
const registry = NpmRegistryService.getInstance().getRegistryEntryForPackage(pathPackageInfo.packageId);
121+
const registryResponse = await fetchFromRegistry(path, registry);
122+
if (!registryResponse.ok) {
123+
return response.status(registryResponse.status).send(await registryResponse.text());
124+
}
104125
response.json(await registryResponse.json());
105126
} catch (error) {
106127
logger.error("Error fetching registry", error);
@@ -124,10 +145,15 @@ export async function fetchPackageFileWithConfig(request: ServerRequest, respons
124145
return response.status(400).send(`Invalid package path: ${path}`);
125146
}
126147

127-
const registryConfig: NpmRegistryConfig = request.body;
128-
const config = NpmRegistryService.getRegistryEntryForPackageWithConfig(pathPackageInfo.packageId, registryConfig);
148+
if (!request.body.workspaceId && !request.body.npmRegistryConfig) {
149+
return response.status(400).send("Missing workspaceId and/or npmRegistryConfig");
150+
}
129151

130-
fetchPackageFileInner(request, response, config);
152+
const {workspaceId, npmRegistryConfig}: RequestConfig = request.body;
153+
const registryConfig: NpmRegistryConfig = npmRegistryConfig;
154+
const registry = NpmRegistryService.getRegistryEntryForPackageWithConfig(pathPackageInfo.packageId, registryConfig);
155+
156+
fetchPackageFileInner(request, response, {workspaceId, registry});
131157
}
132158

133159
export async function fetchPackageFile(request: ServerRequest, response: ServerResponse) {
@@ -139,12 +165,14 @@ export async function fetchPackageFile(request: ServerRequest, response: ServerR
139165
return response.status(400).send(`Invalid package path: ${path}`);
140166
}
141167

142-
const config = NpmRegistryService.getInstance().getRegistryEntryForPackage(pathPackageInfo.packageId);
143-
fetchPackageFileInner(request, response, config);
168+
const registry = NpmRegistryService.getInstance().getRegistryEntryForPackage(pathPackageInfo.packageId);
169+
fetchPackageFileInner(request, response, {registry});
144170
}
145171

146-
async function fetchPackageFileInner(request: ServerRequest, response: ServerResponse, config: NpmRegistryConfigEntry) {
172+
async function fetchPackageFileInner(request: ServerRequest, response: ServerResponse, config: InnerRequestConfig) {
147173
try {
174+
const {workspaceId, registry} = config
175+
logger.info(`Fetch file for workspaceId: ${workspaceId}`);
148176
const path = request.path.replace(fetchPackageFileBasePath, "");
149177
const pathPackageInfo = parsePackageInfoFromPath(path);
150178
if (!pathPackageInfo) {
@@ -157,7 +185,7 @@ async function fetchPackageFileInner(request: ServerRequest, response: ServerRes
157185

158186
let packageInfo: PackagesVersionInfo | null = null;
159187
if (version === "latest") {
160-
const packageInfo: PackagesVersionInfo|null = await fetchPackageInfo(packageId, config);
188+
const packageInfo: PackagesVersionInfo|null = await fetchPackageInfo(packageId, registry);
161189
if (packageInfo === null) {
162190
return response.status(404).send("Not found");
163191
}
@@ -170,14 +198,15 @@ async function fetchPackageFileInner(request: ServerRequest, response: ServerRes
170198
await PackageProcessingQueue.wait(packageId);
171199
}
172200

173-
const packageBaseDir = `${CACHE_DIR}/${packageId}/${packageVersion}/package`;
201+
const baseDir = `${CACHE_DIR}/${workspaceId ?? "default"}`;
202+
const packageBaseDir = `${baseDir}/${packageId}/${packageVersion}/package`;
174203
const packageExists = await fileExists(`${packageBaseDir}/package.json`)
175204
if (!packageExists) {
176205
try {
177206
logger.info(`Package does not exist, fetch from registy: ${packageId}@${packageVersion}`);
178207
PackageProcessingQueue.add(packageId);
179208
if (!packageInfo) {
180-
packageInfo = await fetchPackageInfo(packageId, config);
209+
packageInfo = await fetchPackageInfo(packageId, registry);
181210
}
182211

183212
if (!packageInfo || !packageInfo.versions || !packageInfo.versions[packageVersion]) {
@@ -186,9 +215,9 @@ async function fetchPackageFileInner(request: ServerRequest, response: ServerRes
186215

187216
const tarball = packageInfo.versions[packageVersion].dist.tarball;
188217
logger.info(`Fetching tarball: ${tarball}`);
189-
await fetchAndUnpackTarball(tarball, packageId, packageVersion, config);
218+
await fetchAndUnpackTarball(tarball, packageId, packageVersion, registry,baseDir);
190219
} catch (error) {
191-
logger.error("Error fetching package tarball",error);
220+
logger.error(`Error fetching package: ${error}${(erroras{stack: string}).stack}`);
192221
return response.status(500).send("Internal server error");
193222
} finally {
194223
PackageProcessingQueue.resolve(packageId);
@@ -224,6 +253,7 @@ function parsePackageInfoFromPath(path: string): {packageId: string, organizatio
224253
}
225254

226255
let {packageId, organization, name, version, file} = matches.groups;
256+
// also test for alpha and beta versions like 0.0.1-beta1
227257
version = /^\d+\.\d+\.\d+(-[\w\d]+)?/.test(version) ? version : "latest";
228258

229259
return {packageId, organization, name, version, file};
@@ -265,25 +295,28 @@ function fetchPackageInfo(packageName: string, config: NpmRegistryConfigEntry):
265295
});
266296
}
267297

268-
async function fetchAndUnpackTarball(url: string, packageId: string, packageVersion: string, config: NpmRegistryConfigEntry) {
298+
async function fetchAndUnpackTarball(url: string, packageId: string, packageVersion: string, config: NpmRegistryConfigEntry, baseDir: string) {
299+
if (!await fileExists(baseDir)) {
300+
await fs.mkdir(baseDir, { recursive: true });
301+
}
302+
303+
// Fetch tarball
269304
const response: Response = await fetchFromRegistry(url, config);
270305
const arrayBuffer = await response.arrayBuffer();
271306
const buffer = Buffer.from(arrayBuffer);
272-
const path = `${CACHE_DIR}/${url.split("/").pop()}`;
307+
const path = `${baseDir}/${url.split("/").pop()}`;
273308
await fs.writeFile(path, buffer);
274-
await unpackTarball(path, packageId, packageVersion);
275-
await fs.unlink(path);
276-
}
277-
278-
async function unpackTarball(path: string, packageId: string, packageVersion: string) {
279-
const destinationPath = `${CACHE_DIR}/${packageId}/${packageVersion}`;
309+
310+
// Unpack tarball
311+
const destinationPath = `${baseDir}/${packageId}/${packageVersion}`;
280312
await fs.mkdir(destinationPath, { recursive: true });
281313
await new Promise<void> ((resolve, reject) => {
282314
const tar = spawn("tar", ["-xvf", path, "-C", destinationPath]);
283-
tar.on("close", (code) => {
284-
code === 0 ? resolve() : reject();
285-
});
315+
tar.on("close", (code) => code === 0 ? resolve() : reject());
286316
});
317+
318+
// Cleanup
319+
await fs.unlink(path);
287320
}
288321

289322
async function fileExists(filePath: string): Promise<boolean> {

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /