verdaccio-memory 13.0.0-next-8.21 → 13.0.0-next-8.22

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.
@@ -1,5 +1,5 @@
1
1
  import { pluginUtils, searchUtils } from '@verdaccio/core';
2
- import { Logger, Token } from '@verdaccio/types';
2
+ import { Logger, Token, TokenFilter } from '@verdaccio/types';
3
3
  import MemoryHandler, { DataHandler } from './memory-handler';
4
4
  export type ConfigMemory = {
5
5
  limit?: number;
@@ -8,6 +8,9 @@ export interface MemoryLocalStorage {
8
8
  secret: string;
9
9
  list: string[];
10
10
  files: DataHandler;
11
+ tokens: {
12
+ [user: string]: Token[];
13
+ };
11
14
  }
12
15
  declare class LocalMemory extends pluginUtils.Plugin<ConfigMemory> implements pluginUtils.Storage<ConfigMemory> {
13
16
  private path;
@@ -21,14 +24,14 @@ declare class LocalMemory extends pluginUtils.Plugin<ConfigMemory> implements pl
21
24
  setSecret(secret: string): Promise<string | null>;
22
25
  add(name: string): Promise<void>;
23
26
  search(query: searchUtils.SearchQuery): Promise<searchUtils.SearchItem[]>;
27
+ private filterByQuery;
28
+ private getScore;
24
29
  remove(name: string): Promise<void>;
25
30
  get(): Promise<any>;
26
31
  getPackageStorage(packageInfo: string): MemoryHandler;
27
- hasTarball(): Promise<boolean>;
28
- hasPackage(): Promise<boolean>;
29
32
  private _createEmtpyDatabase;
30
- saveToken(): Promise<void>;
33
+ saveToken(token: Token): Promise<void>;
31
34
  deleteToken(user: string, tokenKey: string): Promise<void>;
32
- readTokens(): Promise<Token[]>;
35
+ readTokens(filter: TokenFilter): Promise<Token[]>;
33
36
  }
34
37
  export default LocalMemory;
@@ -11,8 +11,6 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
11
11
  const debug = (0, _debug.default)('verdaccio:plugin:storage:local-memory');
12
12
  const DEFAULT_LIMIT = 1000;
13
13
  class LocalMemory extends _core.pluginUtils.Plugin {
14
- // @ts-ignore
15
-
16
14
  constructor(config, options) {
17
15
  super(config, options);
18
16
  this.config = config;
@@ -52,11 +50,41 @@ class LocalMemory extends _core.pluginUtils.Plugin {
52
50
  }
53
51
  });
54
52
  }
53
+ async search(query) {
54
+ const results = [];
55
+ const packagesOnStorage = this.filterByQuery(this.data.list, query);
56
+ debug('memory search: packages found %o', packagesOnStorage.length);
57
+ for (const name of packagesOnStorage) {
58
+ const pkg = {
59
+ name
60
+ };
61
+ const isPrivate = this.data.list.includes(name);
62
+ const score = this.getScore(pkg);
63
+ results.push({
64
+ package: pkg,
65
+ verdaccioPrivate: isPrivate,
66
+ verdaccioPkgCached: !isPrivate,
67
+ score
68
+ });
69
+ }
70
+ return results;
71
+ }
72
+ filterByQuery(list, query) {
73
+ const safeText = query.text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
74
+ const regex = new RegExp(safeText, 'i');
75
+ return list.filter(name => regex.test(name));
76
+ }
55
77
 
56
78
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
57
- async search(query) {
58
- this.logger.warn('[verdaccio/memory]: search method not implemented, PR is welcome');
59
- return Promise.reject('not implemented');
79
+ getScore(_pkg) {
80
+ return {
81
+ final: 1,
82
+ detail: {
83
+ maintenance: 0,
84
+ popularity: 1,
85
+ quality: 1
86
+ }
87
+ };
60
88
  }
61
89
  async remove(name) {
62
90
  return new Promise(resolve => {
@@ -75,39 +103,63 @@ class LocalMemory extends _core.pluginUtils.Plugin {
75
103
  return Promise.resolve(this.data?.list);
76
104
  }
77
105
  getPackageStorage(packageInfo) {
106
+ // Ensure the package is in the list
107
+ if (!this.data.list.includes(packageInfo)) {
108
+ this.data.list.push(packageInfo);
109
+ }
78
110
  return new _memoryHandler.default(packageInfo, this.data.files, this.logger);
79
111
  }
80
- async hasTarball(/* fileName: string */
81
- ) {
82
- throw new Error('not implemented');
83
- }
84
- async hasPackage() {
85
- return false;
86
- }
87
112
  _createEmtpyDatabase() {
88
113
  const list = [];
89
114
  const files = {};
115
+ const tokens = {};
90
116
  const emptyDatabase = {
91
117
  list,
92
118
  files,
119
+ tokens,
93
120
  secret: ''
94
121
  };
95
122
  return emptyDatabase;
96
123
  }
97
- saveToken() {
98
- this.logger.warn('[verdaccio/memory][saveToken] save token has not been implemented yet');
99
- return Promise.reject(_core.errorUtils.getServiceUnavailable('method not implemented'));
124
+ saveToken(token) {
125
+ return new Promise(resolve => {
126
+ const {
127
+ tokens
128
+ } = this.data;
129
+ if (!tokens[token.user]) {
130
+ tokens[token.user] = [token];
131
+ } else {
132
+ tokens[token.user].push(token);
133
+ }
134
+ debug('token saved for user %o', token.user);
135
+ resolve();
136
+ });
100
137
  }
101
138
  deleteToken(user, tokenKey) {
102
- this.logger.warn({
103
- tokenKey,
104
- user
105
- }, '[verdaccio/memory][deleteToken] delete token has not been implemented yet @{user}');
106
- return Promise.reject(_core.errorUtils.getServiceUnavailable('method not implemented'));
139
+ return new Promise((resolve, reject) => {
140
+ const {
141
+ tokens
142
+ } = this.data;
143
+ const userTokens = tokens[user];
144
+ if (!userTokens) {
145
+ reject(new Error('user not found'));
146
+ return;
147
+ }
148
+ const remainingTokens = userTokens.filter(token => token.key !== tokenKey);
149
+ tokens[user] = remainingTokens;
150
+ debug('removed token key %o for user %o', tokenKey, user);
151
+ resolve();
152
+ });
107
153
  }
108
- readTokens() {
109
- this.logger.warn('[verdaccio/memory][readTokens] read tokens has not been implemented yet ');
110
- return Promise.reject(_core.errorUtils.getServiceUnavailable('method not implemented'));
154
+ readTokens(filter) {
155
+ return new Promise(resolve => {
156
+ const {
157
+ tokens
158
+ } = this.data;
159
+ const userTokens = tokens[filter.user] || [];
160
+ debug('read tokens for user %o: %o tokens', filter.user, userTokens.length);
161
+ resolve(userTokens);
162
+ });
111
163
  }
112
164
  }
113
165
  var _default = exports.default = LocalMemory;
@@ -1 +1 @@
1
- {"version":3,"file":"local-memory.js","names":["_debug","_interopRequireDefault","require","_core","_memoryHandler","e","__esModule","default","debug","buildDebug","DEFAULT_LIMIT","LocalMemory","pluginUtils","Plugin","constructor","config","options","limit","logger","data","_createEmtpyDatabase","path","init","Promise","resolve","getSecret","secret","setSecret","add","name","reject","list","length","indexOf","push","info","Error","search","query","warn","remove","item","splice","get","getPackageStorage","packageInfo","MemoryHandler","files","hasTarball","hasPackage","emptyDatabase","saveToken","errorUtils","getServiceUnavailable","deleteToken","user","tokenKey","readTokens","_default","exports"],"sources":["../src/local-memory.ts"],"sourcesContent":["import buildDebug from 'debug';\n\nimport { errorUtils, pluginUtils, searchUtils } from '@verdaccio/core';\nimport { Logger, Token } from '@verdaccio/types';\n\nimport MemoryHandler, { DataHandler } from './memory-handler';\n\nexport type ConfigMemory = { limit?: number };\nexport interface MemoryLocalStorage {\n secret: string;\n list: string[];\n files: DataHandler;\n}\n\nconst debug = buildDebug('verdaccio:plugin:storage:local-memory');\n\nconst DEFAULT_LIMIT = 1000;\n\nclass LocalMemory\n extends pluginUtils.Plugin<ConfigMemory>\n implements pluginUtils.Storage<ConfigMemory>\n{\n private path: string;\n private limit: number;\n public logger: Logger;\n private data: MemoryLocalStorage;\n // @ts-ignore\n public config: ConfigMemory;\n\n public constructor(config: ConfigMemory, options: pluginUtils.PluginOptions) {\n super(config, options);\n this.config = config;\n this.limit = config.limit || DEFAULT_LIMIT;\n this.logger = options.logger;\n this.data = this._createEmtpyDatabase();\n this.path = '/';\n debug('start plugin');\n }\n\n public init() {\n return Promise.resolve();\n }\n\n public getSecret(): Promise<string> {\n return Promise.resolve(this.data.secret);\n }\n\n public setSecret(secret: string): Promise<string | null> {\n return new Promise((resolve): void => {\n this.data.secret = secret;\n resolve(null);\n });\n }\n\n async add(name: string): Promise<void> {\n return new Promise((resolve, reject): void => {\n const { list } = this.data;\n\n if (list.length < this.limit) {\n if (list.indexOf(name) === -1) {\n list.push(name);\n }\n resolve();\n } else {\n this.logger.info(\n { limit: this.limit },\n 'Storage memory has reached limit of @{limit} packages'\n );\n reject(new Error(`Storage memory has reached limit of ${this.limit} packages`));\n }\n });\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n public async search(query: searchUtils.SearchQuery): Promise<searchUtils.SearchItem[]> {\n this.logger.warn('[verdaccio/memory]: search method not implemented, PR is welcome');\n return Promise.reject('not implemented');\n }\n\n async remove(name: string): Promise<void> {\n return new Promise((resolve): void => {\n const { list } = this.data;\n const item = list.indexOf(name);\n\n if (item !== -1) {\n list.splice(item, 1);\n }\n\n return resolve();\n });\n }\n\n async get(): Promise<any> {\n debug('data list length %o', this.data?.list?.length);\n return Promise.resolve(this.data?.list);\n }\n\n public getPackageStorage(packageInfo: string): MemoryHandler {\n return new MemoryHandler(packageInfo, this.data.files, this.logger);\n }\n\n public async hasTarball(/* fileName: string */): Promise<boolean> {\n throw new Error('not implemented');\n }\n\n public async hasPackage(): Promise<boolean> {\n return false;\n }\n\n private _createEmtpyDatabase(): MemoryLocalStorage {\n const list: string[] = [];\n const files = {};\n const emptyDatabase = {\n list,\n files,\n secret: '',\n };\n\n return emptyDatabase;\n }\n\n public saveToken(): Promise<void> {\n this.logger.warn('[verdaccio/memory][saveToken] save token has not been implemented yet');\n\n return Promise.reject(errorUtils.getServiceUnavailable('method not implemented'));\n }\n\n public deleteToken(user: string, tokenKey: string): Promise<void> {\n this.logger.warn(\n { tokenKey, user },\n '[verdaccio/memory][deleteToken] delete token has not been implemented yet @{user}'\n );\n\n return Promise.reject(errorUtils.getServiceUnavailable('method not implemented'));\n }\n\n public readTokens(): Promise<Token[]> {\n this.logger.warn('[verdaccio/memory][readTokens] read tokens has not been implemented yet ');\n\n return Promise.reject(errorUtils.getServiceUnavailable('method not implemented'));\n }\n}\n\nexport default LocalMemory;\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"local-memory.js","names":["_debug","_interopRequireDefault","require","_core","_memoryHandler","e","__esModule","default","debug","buildDebug","DEFAULT_LIMIT","LocalMemory","pluginUtils","Plugin","constructor","config","options","limit","logger","data","_createEmtpyDatabase","path","init","Promise","resolve","getSecret","secret","setSecret","add","name","reject","list","length","indexOf","push","info","Error","search","query","results","packagesOnStorage","filterByQuery","pkg","isPrivate","includes","score","getScore","package","verdaccioPrivate","verdaccioPkgCached","safeText","text","replace","regex","RegExp","filter","test","_pkg","final","detail","maintenance","popularity","quality","remove","item","splice","get","getPackageStorage","packageInfo","MemoryHandler","files","tokens","emptyDatabase","saveToken","token","user","deleteToken","tokenKey","userTokens","remainingTokens","key","readTokens","_default","exports"],"sources":["../src/local-memory.ts"],"sourcesContent":["import buildDebug from 'debug';\n\nimport { pluginUtils, searchUtils } from '@verdaccio/core';\nimport { Logger, Token, TokenFilter } from '@verdaccio/types';\n\nimport MemoryHandler, { DataHandler } from './memory-handler';\n\nexport type ConfigMemory = { limit?: number };\nexport interface MemoryLocalStorage {\n secret: string;\n list: string[];\n files: DataHandler;\n tokens: { [user: string]: Token[] };\n}\n\nconst debug = buildDebug('verdaccio:plugin:storage:local-memory');\n\nconst DEFAULT_LIMIT = 1000;\n\nclass LocalMemory\n extends pluginUtils.Plugin<ConfigMemory>\n implements pluginUtils.Storage<ConfigMemory>\n{\n private path: string;\n private limit: number;\n public logger: Logger;\n private data: MemoryLocalStorage;\n public config: ConfigMemory;\n\n public constructor(config: ConfigMemory, options: pluginUtils.PluginOptions) {\n super(config, options);\n this.config = config;\n this.limit = config.limit || DEFAULT_LIMIT;\n this.logger = options.logger;\n this.data = this._createEmtpyDatabase();\n this.path = '/';\n debug('start plugin');\n }\n\n public init() {\n return Promise.resolve();\n }\n\n public getSecret(): Promise<string> {\n return Promise.resolve(this.data.secret);\n }\n\n public setSecret(secret: string): Promise<string | null> {\n return new Promise((resolve): void => {\n this.data.secret = secret;\n resolve(null);\n });\n }\n\n async add(name: string): Promise<void> {\n return new Promise((resolve, reject): void => {\n const { list } = this.data;\n\n if (list.length < this.limit) {\n if (list.indexOf(name) === -1) {\n list.push(name);\n }\n resolve();\n } else {\n this.logger.info(\n { limit: this.limit },\n 'Storage memory has reached limit of @{limit} packages'\n );\n reject(new Error(`Storage memory has reached limit of ${this.limit} packages`));\n }\n });\n }\n\n public async search(query: searchUtils.SearchQuery): Promise<searchUtils.SearchItem[]> {\n const results: searchUtils.SearchItem[] = [];\n const packagesOnStorage = this.filterByQuery(this.data.list, query);\n debug('memory search: packages found %o', packagesOnStorage.length);\n for (const name of packagesOnStorage) {\n const pkg: searchUtils.SearchItemPkg = { name };\n const isPrivate = this.data.list.includes(name);\n const score = this.getScore(pkg);\n results.push({\n package: pkg,\n verdaccioPrivate: isPrivate,\n verdaccioPkgCached: !isPrivate,\n score,\n });\n }\n return results;\n }\n\n private filterByQuery(list: string[], query: searchUtils.SearchQuery): string[] {\n const safeText = query.text.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const regex = new RegExp(safeText, 'i');\n return list.filter((name) => regex.test(name));\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n private getScore(_pkg: searchUtils.SearchItemPkg): searchUtils.Score {\n return {\n final: 1,\n detail: {\n maintenance: 0,\n popularity: 1,\n quality: 1,\n },\n };\n }\n\n async remove(name: string): Promise<void> {\n return new Promise((resolve): void => {\n const { list } = this.data;\n const item = list.indexOf(name);\n\n if (item !== -1) {\n list.splice(item, 1);\n }\n\n return resolve();\n });\n }\n\n async get(): Promise<any> {\n debug('data list length %o', this.data?.list?.length);\n return Promise.resolve(this.data?.list);\n }\n\n public getPackageStorage(packageInfo: string): MemoryHandler {\n // Ensure the package is in the list\n if (!this.data.list.includes(packageInfo)) {\n this.data.list.push(packageInfo);\n }\n return new MemoryHandler(packageInfo, this.data.files, this.logger);\n }\n\n private _createEmtpyDatabase(): MemoryLocalStorage {\n const list: string[] = [];\n const files = {};\n const tokens = {};\n const emptyDatabase = {\n list,\n files,\n tokens,\n secret: '',\n };\n\n return emptyDatabase;\n }\n\n public saveToken(token: Token): Promise<void> {\n return new Promise((resolve): void => {\n const { tokens } = this.data;\n\n if (!tokens[token.user]) {\n tokens[token.user] = [token];\n } else {\n tokens[token.user].push(token);\n }\n\n debug('token saved for user %o', token.user);\n resolve();\n });\n }\n\n public deleteToken(user: string, tokenKey: string): Promise<void> {\n return new Promise((resolve, reject): void => {\n const { tokens } = this.data;\n const userTokens = tokens[user];\n\n if (!userTokens) {\n reject(new Error('user not found'));\n return;\n }\n\n const remainingTokens = userTokens.filter((token) => token.key !== tokenKey);\n tokens[user] = remainingTokens;\n\n debug('removed token key %o for user %o', tokenKey, user);\n resolve();\n });\n }\n\n public readTokens(filter: TokenFilter): Promise<Token[]> {\n return new Promise((resolve): void => {\n const { tokens } = this.data;\n const userTokens = tokens[filter.user] || [];\n\n debug('read tokens for user %o: %o tokens', filter.user, userTokens.length);\n resolve(userTokens);\n });\n }\n}\n\nexport default LocalMemory;\n"],"mappings":"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","ignoreList":[]}
@@ -1,5 +1,5 @@
1
1
  /// <reference types="node" />
2
- import { PassThrough, Writable } from 'node:stream';
2
+ import { Readable, Writable } from 'node:stream';
3
3
  import { pluginUtils } from '@verdaccio/core';
4
4
  import { Logger, Manifest } from '@verdaccio/types';
5
5
  export type DataHandler = {
@@ -7,22 +7,25 @@ export type DataHandler = {
7
7
  };
8
8
  declare class MemoryHandler implements pluginUtils.StorageHandler {
9
9
  private data;
10
- private name;
11
- private path;
10
+ private packageName;
12
11
  logger: Logger;
13
12
  constructor(packageName: string, data: DataHandler, logger: Logger);
14
13
  hasTarball(fileName: string): Promise<boolean>;
15
- hasPackage(): Promise<boolean>;
16
- deletePackage(pkgName: string): Promise<void>;
17
- removePackage(): Promise<void>;
18
- createPackage(name: string, value: Manifest): Promise<void>;
19
- savePackage(name: string, value: Manifest): Promise<void>;
20
- readPackage(name: string): Promise<Manifest>;
21
- writeTarball(name: string): Promise<Writable>;
22
- readTarball(pkgName: string, { signal }: {
23
- signal: any;
24
- }): Promise<PassThrough>;
25
- private _getStorage;
14
+ hasPackage(packageName: string): Promise<boolean>;
15
+ deletePackage(fileName: string): Promise<void>;
16
+ removePackage(packageName: string): Promise<void>;
17
+ createPackage(packageName: string, manifest: Manifest): Promise<void>;
18
+ savePackage(packageName: string, manifest: Manifest): Promise<void>;
19
+ readPackage(packageName: string): Promise<Manifest>;
20
+ private getStorageKey;
21
+ private getStoragePath;
22
+ private removeFile;
23
+ writeTarball(fileName: string, { signal }: {
24
+ signal: AbortSignal;
25
+ }): Promise<Writable>;
26
+ readTarball(fileName: string, { signal }: {
27
+ signal: AbortSignal;
28
+ }): Promise<Readable>;
26
29
  updatePackage(packageName: string, handleUpdate: (manifest: Manifest) => Promise<Manifest>): Promise<Manifest>;
27
30
  }
28
31
  export default MemoryHandler;
@@ -8,145 +8,256 @@ var _debug = _interopRequireDefault(require("debug"));
8
8
  var _memfs = require("memfs");
9
9
  var _nodePath = _interopRequireDefault(require("node:path"));
10
10
  var _nodeStream = require("node:stream");
11
- var _promises = require("node:stream/promises");
12
11
  var _core = require("@verdaccio/core");
13
12
  var _utils = require("./utils");
14
13
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
15
14
  /* eslint-disable @typescript-eslint/no-unused-vars */
16
15
 
17
16
  const debug = (0, _debug.default)('verdaccio:plugin:storage:memory-storage');
18
- function fstatPromise(fd) {
19
- return new Promise((resolve, reject) => {
20
- _memfs.fs.fstat(fd, function (err, stats) {
21
- if (err) {
22
- return reject(err);
23
- }
24
- return resolve(stats);
25
- });
26
- });
27
- }
28
- function mkdirPPromise(fileName) {
29
- return new Promise((resolve, reject) => {
30
- _memfs.fs.mkdirp(_nodePath.default.dirname(fileName), function (err) {
31
- if (err) {
32
- return reject(err);
33
- }
34
- return resolve(true);
35
- });
36
- });
37
- }
38
17
  class MemoryHandler {
39
18
  constructor(packageName, data, logger) {
40
- // this is not need it
41
19
  this.data = data;
42
- this.name = packageName;
43
20
  this.logger = logger;
44
- this.path = `/${packageName}`;
45
- debug('initialized');
21
+ this.packageName = packageName;
22
+ // Ensure the root directory exists in memfs
23
+ try {
24
+ _memfs.fs.mkdirSync('/');
25
+ } catch (e) {
26
+ // ignore if already exists
27
+ }
46
28
  }
47
29
  async hasTarball(fileName) {
48
- throw new Error('not implemented');
30
+ const exists = this.data[this.getStorageKey(fileName)] === 'true';
31
+ debug('hasTarball for %o: %s', fileName, exists);
32
+ return exists;
49
33
  }
50
- async hasPackage() {
51
- return false;
34
+ async hasPackage(packageName) {
35
+ return this.data[packageName] !== undefined;
52
36
  }
53
- async deletePackage(pkgName) {
54
- delete this.data[pkgName];
55
- return;
37
+ async deletePackage(fileName) {
38
+ // manifest is deleted by removePackage
39
+ if (fileName === 'package.json') {
40
+ return;
41
+ }
42
+ debug('delete tarball %o', fileName);
43
+ try {
44
+ const tarballName = this.getStoragePath(fileName);
45
+ const tarballKey = this.getStorageKey(fileName);
46
+ debug('deleting tarball with key: %s', tarballKey);
47
+ this.removeFile(tarballName);
48
+ delete this.data[tarballKey];
49
+ } catch (err) {
50
+ throw _core.errorUtils.getInternalError(err.message);
51
+ }
56
52
  }
57
- removePackage() {
58
- return Promise.resolve();
53
+ async removePackage(packageName) {
54
+ debug('remove package %o', packageName);
55
+ delete this.data[packageName];
59
56
  }
60
- async createPackage(name, value) {
61
- debug('create package %o', name);
62
- await this.savePackage(name, value);
57
+ async createPackage(packageName, manifest) {
58
+ debug('create package %o', packageName);
59
+ await this.savePackage(packageName, manifest);
63
60
  }
64
- async savePackage(name, value) {
61
+ async savePackage(packageName, manifest) {
62
+ debug('save package %o', packageName);
65
63
  try {
66
- debug('save package %o', name);
67
- this.data[name] = (0, _utils.stringifyPackage)(value);
64
+ this.data[packageName] = (0, _utils.stringifyPackage)(manifest);
68
65
  } catch (err) {
69
66
  throw _core.errorUtils.getInternalError(err.message);
70
67
  }
71
68
  }
72
- async readPackage(name) {
73
- debug('read package %o', name);
74
- const json = this._getStorage(name);
75
- const isJson = typeof json === 'undefined';
76
- if (isJson) {
69
+ async readPackage(packageName) {
70
+ debug('read package %o', packageName);
71
+ const json = this.data[packageName];
72
+ if (json === undefined) {
77
73
  throw _core.errorUtils.getNotFound();
78
74
  }
79
- return (0, _utils.parsePackage)(json);
75
+ try {
76
+ return (0, _utils.parsePackage)(json);
77
+ } catch (err) {
78
+ throw _core.errorUtils.getInternalError(err.message);
79
+ }
80
80
  }
81
- async writeTarball(name) {
82
- const temporalName = `${this.path}/${name}`;
83
- debug('write tarball %o', temporalName);
84
- await mkdirPPromise(temporalName);
85
- const writeStream = _memfs.fs.createWriteStream(temporalName);
86
- return writeStream;
81
+ getStorageKey(fileName) {
82
+ return `${this.packageName}/${fileName}`;
83
+ }
84
+ getStoragePath(fileName) {
85
+ // Use the complete package name for proper directory structure
86
+ // memfs works with Unix-style paths on all platforms, so use forward slashes consistently
87
+ const storagePath = _nodePath.default.posix.normalize(_nodePath.default.posix.join('/', this.packageName, fileName));
88
+ debug('storage path for %s: %s', fileName, storagePath);
89
+ return storagePath;
90
+ }
91
+ async removeFile(fileName) {
92
+ debug('remove file %o', fileName);
93
+ try {
94
+ _memfs.fs.unlinkSync(fileName);
95
+ } catch (err) {
96
+ // Ignore if file does not exist
97
+ if (err.code !== 'ENOENT') {
98
+ throw err;
99
+ }
100
+ }
87
101
  }
88
- async readTarball(pkgName, {
102
+ async writeTarball(fileName, {
89
103
  signal
90
104
  }) {
91
- const pathName = this._getStorage(pkgName);
92
- const passStream = new _nodeStream.PassThrough();
93
- const readStream = (0, _nodeStream.addAbortSignal)(signal, _memfs.fs.createReadStream(pathName));
94
- readStream.on('open', async function (fileDescriptor) {
95
- const stats = await fstatPromise(fileDescriptor);
96
- passStream.emit('content-length', stats?.size);
97
- });
98
- readStream.on('error', err => {
99
- passStream.emit('error', err);
100
- });
101
- await (0, _promises.pipeline)(readStream, passStream);
102
- return passStream;
103
- }
105
+ debug('write tarball %o', fileName);
106
+ const tarballName = this.getStoragePath(fileName);
107
+ const tarballKey = this.getStorageKey(fileName);
104
108
 
105
- // public readTarball(name: string): IReadTarball {
106
- // const pathName = `${this.path}/${name}`;
107
- // debug('read tarball %o', pathName);
109
+ // Create a temporary file path to avoid conflicts (similar to local-fs)
110
+ const temporalName = `${tarballName}.tmp-${String(Math.random()).replace(/^0\./, '')}`;
111
+ debug('using temporal file %o', temporalName);
108
112
 
109
- // const readTarballStream: IReadTarball = new ReadTarball({});
113
+ // Ensure the directory exists for the tarball BEFORE creating the stream
114
+ const dirName = _nodePath.default.posix.dirname(temporalName);
115
+ try {
116
+ // Make sure all directory levels are created
117
+ await _memfs.fs.promises.mkdir(dirName, {
118
+ recursive: true
119
+ });
120
+ debug('ensured directory exists %o', dirName);
121
+ } catch (err) {
122
+ debug('error creating directory %o: %s', dirName, err.message);
123
+ throw _core.errorUtils.getInternalError(`Failed to create directory: ${err.message}`);
124
+ }
125
+ let opened = false;
126
+ let closed = false;
127
+ // Create the write stream but don't rely on its built-in events entirely
128
+ const writeStream = _memfs.fs.createWriteStream(temporalName);
129
+
130
+ // Emit 'open' event in the next tick to ensure consistent behavior with fs streams
131
+ process.nextTick(() => {
132
+ opened = true;
133
+ debug('write stream opened for %o', temporalName);
134
+ writeStream.emit('open');
135
+ });
136
+ writeStream.on('error', err => {
137
+ debug('write stream error %o: %s', temporalName, err.message);
138
+ delete this.data[tarballKey];
139
+ if (opened) {
140
+ this.logger.error({
141
+ err,
142
+ fileName
143
+ }, 'error on open write tarball for @{fileName}: @{err.message}');
144
+ writeStream.on('close', () => {
145
+ this.removeFile(temporalName);
146
+ });
147
+ } else {
148
+ this.logger.error({
149
+ err,
150
+ fileName
151
+ }, 'error on writing tarball for @{fileName}: @{err.message}');
152
+ this.removeFile(temporalName);
153
+ }
154
+ });
155
+ writeStream.on('finish', () => {
156
+ debug('write stream finished for %o', fileName);
157
+ });
110
158
 
111
- // process.nextTick(function () {
112
- // fs.stat(pathName, function (error, stats) {
113
- // if (error && !stats) {
114
- // return readTarballStream.emit('error', errorUtils.getNotFound());
115
- // }
159
+ // This is called when the underlying file descriptor is closed
160
+ // which happens after the stream is finished/ended
161
+ writeStream.on('close', async () => {
162
+ // prevent double close event
163
+ if (closed) {
164
+ debug('close event already handled for %o', temporalName);
165
+ return;
166
+ }
167
+ closed = true;
168
+ try {
169
+ // Check if temporary file exists before trying to rename
170
+ if (!_memfs.fs.existsSync(temporalName)) {
171
+ debug('temporary file %o does not exist, skipping rename', temporalName);
172
+ delete this.data[tarballKey];
173
+ return;
174
+ }
116
175
 
117
- // try {
118
- // const readStream = fs.createReadStream(pathName);
176
+ // Rename the temporary file to the final location (atomic operation)
177
+ await _memfs.fs.promises.rename(temporalName, tarballName);
178
+ // Store the mapping of key to true (indicating it exists)
179
+ this.data[tarballKey] = 'true';
180
+ debug('write stream closed successfully, renamed %o to %o, stored with key %o', temporalName, tarballName, tarballKey);
181
+ } catch (err) {
182
+ debug('error renaming %o to %o: %s', temporalName, tarballName, err.message);
183
+ this.logger.error({
184
+ err,
185
+ temporalName,
186
+ finalTarballPath: tarballName
187
+ }, 'error renaming temporal file @{temporalName} to @{finalTarballPath}: @{err.message}');
188
+ // Clean up the mapping since rename failed
189
+ delete this.data[tarballKey];
190
+ this.removeFile(temporalName);
191
+ }
192
+ });
193
+ signal?.addEventListener('abort', () => {
194
+ debug('upload aborted for %o', fileName);
195
+ delete this.data[tarballKey];
196
+ if (opened) {
197
+ writeStream.once('close', () => {
198
+ this.removeFile(temporalName);
199
+ });
200
+ writeStream.destroy();
201
+ } else {
202
+ this.removeFile(temporalName);
203
+ }
204
+ }, {
205
+ once: true
206
+ });
207
+ return writeStream;
208
+ }
209
+ async readTarball(fileName, {
210
+ signal
211
+ }) {
212
+ debug('read tarball %o', fileName);
119
213
 
120
- // readTarballStream.emit('content-length', stats?.size);
121
- // readTarballStream.emit('open');
122
- // readStream.pipe(readTarballStream);
123
- // readStream.on('error', (error: VerdaccioError) => {
124
- // readTarballStream.emit('error', error);
125
- // });
214
+ // Check if the tarball exists in our mapping
215
+ if (!this.hasTarball(fileName)) {
216
+ debug('tarball not found: %s', fileName);
217
+ throw _core.errorUtils.getNotFound('no such package');
218
+ }
219
+ const tarballName = this.getStoragePath(fileName);
220
+ const tarballKey = this.getStorageKey(fileName);
126
221
 
127
- // readTarballStream.abort = function (): void {
128
- // readStream.destroy(errorUtils.getBadRequest('read has been aborted'));
129
- // };
130
- // return;
131
- // } catch (err: any) {
132
- // readTarballStream.emit('error', err);
133
- // return;
134
- // }
135
- // });
136
- // });
222
+ // Additional filesystem check
223
+ try {
224
+ const exists = _memfs.fs.existsSync(tarballName);
225
+ if (!exists) {
226
+ debug('tarball file does not exist on filesystem: %s', tarballName);
227
+ delete this.data[tarballKey]; // Clean up incorrect state
228
+ throw _core.errorUtils.getNotFound('no such package');
229
+ }
230
+ } catch (err) {
231
+ debug('error checking tarball existence: %s', err.message);
232
+ throw _core.errorUtils.getNotFound('no such package');
233
+ }
234
+ const readStream = (0, _nodeStream.addAbortSignal)(signal, _memfs.fs.createReadStream(tarballName));
137
235
 
138
- // return readTarballStream;
139
- // }
236
+ // Check stats before emitting open event to ensure content-length is available
237
+ const stats = _memfs.fs.statSync(tarballName);
140
238
 
141
- _getStorage(name = '') {
142
- debug('get storage %o', name);
143
- return this.data[name];
239
+ // Manually emit 'open' event in the next tick to ensure consistent behavior with fs streams
240
+ process.nextTick(() => {
241
+ debug('read stream opened for %o', tarballName);
242
+ readStream.emit('open');
243
+ debug('file size %o', stats.size);
244
+ readStream.emit('content-length', stats.size);
245
+ });
246
+ readStream.on('error', error => {
247
+ debug('error reading tarball %o: %s', tarballName, error.message);
248
+ });
249
+ return readStream;
144
250
  }
145
251
  async updatePackage(packageName, handleUpdate) {
146
- const json = this._getStorage(packageName);
147
- let pkg = (0, _utils.parsePackage)(json);
148
- const newManifest = await handleUpdate(pkg);
149
- return newManifest;
252
+ debug('update package %o', packageName);
253
+ try {
254
+ const json = this.data[packageName];
255
+ let manifest = (0, _utils.parsePackage)(json);
256
+ const newManifest = await handleUpdate(manifest);
257
+ return newManifest;
258
+ } catch (err) {
259
+ throw _core.errorUtils.getInternalError(err.message);
260
+ }
150
261
  }
151
262
  }
152
263
  var _default = exports.default = MemoryHandler;
@@ -1 +1 @@
1
- {"version":3,"file":"memory-handler.js","names":["_debug","_interopRequireDefault","require","_memfs","_nodePath","_nodeStream","_promises","_core","_utils","e","__esModule","default","debug","buildDebug","fstatPromise","fd","Promise","resolve","reject","fs","fstat","err","stats","mkdirPPromise","fileName","mkdirp","path","dirname","MemoryHandler","constructor","packageName","data","logger","name","hasTarball","Error","hasPackage","deletePackage","pkgName","removePackage","createPackage","value","savePackage","stringifyPackage","errorUtils","getInternalError","message","readPackage","json","_getStorage","isJson","getNotFound","parsePackage","writeTarball","temporalName","writeStream","createWriteStream","readTarball","signal","pathName","passStream","PassThrough","readStream","addAbortSignal","createReadStream","on","fileDescriptor","emit","size","pipeline","updatePackage","handleUpdate","pkg","newManifest","_default","exports"],"sources":["../src/memory-handler.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-unused-vars */\nimport buildDebug from 'debug';\nimport { fs } from 'memfs';\nimport { Stats } from 'memfs/lib/Stats';\nimport path from 'node:path';\nimport { PassThrough, Writable, addAbortSignal } from 'node:stream';\nimport { pipeline } from 'node:stream/promises';\n\nimport { errorUtils, pluginUtils } from '@verdaccio/core';\nimport { Logger, Manifest } from '@verdaccio/types';\n\nimport { parsePackage, stringifyPackage } from './utils';\n\nconst debug = buildDebug('verdaccio:plugin:storage:memory-storage');\n\nfunction fstatPromise(fd): Promise<Stats | undefined> {\n return new Promise((resolve, reject) => {\n fs.fstat(fd, function (err, stats) {\n if (err) {\n return reject(err);\n }\n return resolve(stats);\n });\n });\n}\n\nfunction mkdirPPromise(fileName) {\n return new Promise((resolve, reject) => {\n fs.mkdirp(path.dirname(fileName), function (err) {\n if (err) {\n return reject(err);\n }\n return resolve(true);\n });\n });\n}\n\nexport type DataHandler = {\n [key: string]: string;\n};\n\nclass MemoryHandler implements pluginUtils.StorageHandler {\n private data: DataHandler;\n private name: string;\n private path: string;\n public logger: Logger;\n\n public constructor(packageName: string, data: DataHandler, logger: Logger) {\n // this is not need it\n this.data = data;\n this.name = packageName;\n this.logger = logger;\n this.path = `/${packageName}`;\n debug('initialized');\n }\n\n public async hasTarball(fileName: string): Promise<boolean> {\n throw new Error('not implemented');\n }\n\n public async hasPackage(): Promise<boolean> {\n return false;\n }\n\n public async deletePackage(pkgName: string): Promise<void> {\n delete this.data[pkgName];\n return;\n }\n\n public removePackage() {\n return Promise.resolve();\n }\n\n public async createPackage(name: string, value: Manifest): Promise<void> {\n debug('create package %o', name);\n await this.savePackage(name, value);\n }\n\n public async savePackage(name: string, value: Manifest): Promise<void> {\n try {\n debug('save package %o', name);\n this.data[name] = stringifyPackage(value);\n } catch (err: any) {\n throw errorUtils.getInternalError(err.message);\n }\n }\n\n public async readPackage(name: string): Promise<Manifest> {\n debug('read package %o', name);\n const json = this._getStorage(name);\n const isJson = typeof json === 'undefined';\n if (isJson) {\n throw errorUtils.getNotFound();\n }\n return parsePackage(json);\n }\n\n public async writeTarball(name: string): Promise<Writable> {\n const temporalName = `${this.path}/${name}`;\n debug('write tarball %o', temporalName);\n await mkdirPPromise(temporalName);\n const writeStream = fs.createWriteStream(temporalName);\n return writeStream;\n }\n\n public async readTarball(pkgName: string, { signal }): Promise<PassThrough> {\n const pathName: string = this._getStorage(pkgName);\n const passStream = new PassThrough();\n const readStream = addAbortSignal(signal, fs.createReadStream(pathName));\n readStream.on('open', async function (fileDescriptor) {\n const stats = await fstatPromise(fileDescriptor);\n passStream.emit('content-length', stats?.size);\n });\n readStream.on('error', (err) => {\n passStream.emit('error', err);\n });\n\n await pipeline(readStream, passStream);\n\n return passStream;\n }\n\n // public readTarball(name: string): IReadTarball {\n // const pathName = `${this.path}/${name}`;\n // debug('read tarball %o', pathName);\n\n // const readTarballStream: IReadTarball = new ReadTarball({});\n\n // process.nextTick(function () {\n // fs.stat(pathName, function (error, stats) {\n // if (error && !stats) {\n // return readTarballStream.emit('error', errorUtils.getNotFound());\n // }\n\n // try {\n // const readStream = fs.createReadStream(pathName);\n\n // readTarballStream.emit('content-length', stats?.size);\n // readTarballStream.emit('open');\n // readStream.pipe(readTarballStream);\n // readStream.on('error', (error: VerdaccioError) => {\n // readTarballStream.emit('error', error);\n // });\n\n // readTarballStream.abort = function (): void {\n // readStream.destroy(errorUtils.getBadRequest('read has been aborted'));\n // };\n // return;\n // } catch (err: any) {\n // readTarballStream.emit('error', err);\n // return;\n // }\n // });\n // });\n\n // return readTarballStream;\n // }\n\n private _getStorage(name = ''): string {\n debug('get storage %o', name);\n return this.data[name];\n }\n\n public async updatePackage(\n packageName: string,\n handleUpdate: (manifest: Manifest) => Promise<Manifest>\n ): Promise<Manifest> {\n const json: string = this._getStorage(packageName);\n let pkg: Manifest = parsePackage(json) as Manifest;\n const newManifest = await handleUpdate(pkg);\n return newManifest;\n }\n}\n\nexport default MemoryHandler;\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"memory-handler.js","names":["_debug","_interopRequireDefault","require","_memfs","_nodePath","_nodeStream","_core","_utils","e","__esModule","default","debug","buildDebug","MemoryHandler","constructor","packageName","data","logger","fs","mkdirSync","hasTarball","fileName","exists","getStorageKey","hasPackage","undefined","deletePackage","tarballName","getStoragePath","tarballKey","removeFile","err","errorUtils","getInternalError","message","removePackage","createPackage","manifest","savePackage","stringifyPackage","readPackage","json","getNotFound","parsePackage","storagePath","path","posix","normalize","join","unlinkSync","code","writeTarball","signal","temporalName","String","Math","random","replace","dirName","dirname","promises","mkdir","recursive","opened","closed","writeStream","createWriteStream","process","nextTick","emit","on","error","existsSync","rename","finalTarballPath","addEventListener","once","destroy","readTarball","readStream","addAbortSignal","createReadStream","stats","statSync","size","updatePackage","handleUpdate","newManifest","_default","exports"],"sources":["../src/memory-handler.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-unused-vars */\nimport buildDebug from 'debug';\nimport { fs } from 'memfs';\nimport path from 'node:path';\nimport { Readable, Writable, addAbortSignal } from 'node:stream';\n\nimport { errorUtils, pluginUtils } from '@verdaccio/core';\nimport { Logger, Manifest } from '@verdaccio/types';\n\nimport { parsePackage, stringifyPackage } from './utils';\n\nconst debug = buildDebug('verdaccio:plugin:storage:memory-storage');\n\nexport type DataHandler = {\n [key: string]: string;\n};\n\nclass MemoryHandler implements pluginUtils.StorageHandler {\n private data: DataHandler;\n private packageName: string;\n public logger: Logger;\n\n public constructor(packageName: string, data: DataHandler, logger: Logger) {\n this.data = data;\n this.logger = logger;\n this.packageName = packageName;\n // Ensure the root directory exists in memfs\n try {\n fs.mkdirSync('/');\n } catch (e) {\n // ignore if already exists\n }\n }\n\n public async hasTarball(fileName: string): Promise<boolean> {\n const exists = this.data[this.getStorageKey(fileName)] === 'true';\n debug('hasTarball for %o: %s', fileName, exists);\n return exists;\n }\n\n public async hasPackage(packageName: string): Promise<boolean> {\n return this.data[packageName] !== undefined;\n }\n\n public async deletePackage(fileName: string): Promise<void> {\n // manifest is deleted by removePackage\n if (fileName === 'package.json') {\n return;\n }\n debug('delete tarball %o', fileName);\n try {\n const tarballName = this.getStoragePath(fileName);\n const tarballKey = this.getStorageKey(fileName);\n debug('deleting tarball with key: %s', tarballKey);\n this.removeFile(tarballName);\n delete this.data[tarballKey];\n } catch (err: any) {\n throw errorUtils.getInternalError(err.message);\n }\n }\n\n public async removePackage(packageName: string): Promise<void> {\n debug('remove package %o', packageName);\n delete this.data[packageName];\n }\n\n public async createPackage(packageName: string, manifest: Manifest): Promise<void> {\n debug('create package %o', packageName);\n await this.savePackage(packageName, manifest);\n }\n\n public async savePackage(packageName: string, manifest: Manifest): Promise<void> {\n debug('save package %o', packageName);\n try {\n this.data[packageName] = stringifyPackage(manifest);\n } catch (err: any) {\n throw errorUtils.getInternalError(err.message);\n }\n }\n\n public async readPackage(packageName: string): Promise<Manifest> {\n debug('read package %o', packageName);\n const json = this.data[packageName];\n if (json === undefined) {\n throw errorUtils.getNotFound();\n }\n try {\n return parsePackage(json);\n } catch (err: any) {\n throw errorUtils.getInternalError(err.message);\n }\n }\n\n private getStorageKey(fileName: string): string {\n return `${this.packageName}/${fileName}`;\n }\n\n private getStoragePath(fileName: string): string {\n // Use the complete package name for proper directory structure\n // memfs works with Unix-style paths on all platforms, so use forward slashes consistently\n const storagePath = path.posix.normalize(path.posix.join('/', this.packageName, fileName));\n debug('storage path for %s: %s', fileName, storagePath);\n return storagePath;\n }\n\n private async removeFile(fileName: string): Promise<void> {\n debug('remove file %o', fileName);\n try {\n fs.unlinkSync(fileName);\n } catch (err: any) {\n // Ignore if file does not exist\n if (err.code !== 'ENOENT') {\n throw err;\n }\n }\n }\n\n public async writeTarball(\n fileName: string,\n { signal }: { signal: AbortSignal }\n ): Promise<Writable> {\n debug('write tarball %o', fileName);\n const tarballName = this.getStoragePath(fileName);\n const tarballKey = this.getStorageKey(fileName);\n\n // Create a temporary file path to avoid conflicts (similar to local-fs)\n const temporalName = `${tarballName}.tmp-${String(Math.random()).replace(/^0\\./, '')}`;\n debug('using temporal file %o', temporalName);\n\n // Ensure the directory exists for the tarball BEFORE creating the stream\n const dirName = path.posix.dirname(temporalName);\n try {\n // Make sure all directory levels are created\n await fs.promises.mkdir(dirName, { recursive: true });\n debug('ensured directory exists %o', dirName);\n } catch (err: any) {\n debug('error creating directory %o: %s', dirName, err.message);\n throw errorUtils.getInternalError(`Failed to create directory: ${err.message}`);\n }\n\n let opened = false;\n let closed = false;\n // Create the write stream but don't rely on its built-in events entirely\n const writeStream = fs.createWriteStream(temporalName);\n\n // Emit 'open' event in the next tick to ensure consistent behavior with fs streams\n process.nextTick(() => {\n opened = true;\n debug('write stream opened for %o', temporalName);\n writeStream.emit('open');\n });\n\n writeStream.on('error', (err) => {\n debug('write stream error %o: %s', temporalName, err.message);\n delete this.data[tarballKey];\n if (opened) {\n this.logger.error(\n { err, fileName },\n 'error on open write tarball for @{fileName}: @{err.message}'\n );\n writeStream.on('close', () => {\n this.removeFile(temporalName);\n });\n } else {\n this.logger.error(\n { err, fileName },\n 'error on writing tarball for @{fileName}: @{err.message}'\n );\n this.removeFile(temporalName);\n }\n });\n\n writeStream.on('finish', () => {\n debug('write stream finished for %o', fileName);\n });\n\n // This is called when the underlying file descriptor is closed\n // which happens after the stream is finished/ended\n writeStream.on('close', async () => {\n // prevent double close event\n if (closed) {\n debug('close event already handled for %o', temporalName);\n return;\n }\n closed = true;\n try {\n // Check if temporary file exists before trying to rename\n if (!fs.existsSync(temporalName)) {\n debug('temporary file %o does not exist, skipping rename', temporalName);\n delete this.data[tarballKey];\n return;\n }\n\n // Rename the temporary file to the final location (atomic operation)\n await fs.promises.rename(temporalName, tarballName);\n // Store the mapping of key to true (indicating it exists)\n this.data[tarballKey] = 'true';\n debug(\n 'write stream closed successfully, renamed %o to %o, stored with key %o',\n temporalName,\n tarballName,\n tarballKey\n );\n } catch (err: any) {\n debug('error renaming %o to %o: %s', temporalName, tarballName, err.message);\n this.logger.error(\n { err, temporalName, finalTarballPath: tarballName },\n 'error renaming temporal file @{temporalName} to @{finalTarballPath}: @{err.message}'\n );\n // Clean up the mapping since rename failed\n delete this.data[tarballKey];\n this.removeFile(temporalName);\n }\n });\n\n signal?.addEventListener(\n 'abort',\n () => {\n debug('upload aborted for %o', fileName);\n delete this.data[tarballKey];\n if (opened) {\n writeStream.once('close', () => {\n this.removeFile(temporalName);\n });\n writeStream.destroy();\n } else {\n this.removeFile(temporalName);\n }\n },\n { once: true }\n );\n\n return writeStream;\n }\n\n public async readTarball(\n fileName: string,\n { signal }: { signal: AbortSignal }\n ): Promise<Readable> {\n debug('read tarball %o', fileName);\n\n // Check if the tarball exists in our mapping\n if (!this.hasTarball(fileName)) {\n debug('tarball not found: %s', fileName);\n throw errorUtils.getNotFound('no such package');\n }\n\n const tarballName = this.getStoragePath(fileName);\n const tarballKey = this.getStorageKey(fileName);\n\n // Additional filesystem check\n try {\n const exists = fs.existsSync(tarballName);\n if (!exists) {\n debug('tarball file does not exist on filesystem: %s', tarballName);\n delete this.data[tarballKey]; // Clean up incorrect state\n throw errorUtils.getNotFound('no such package');\n }\n } catch (err: any) {\n debug('error checking tarball existence: %s', err.message);\n throw errorUtils.getNotFound('no such package');\n }\n\n const readStream = addAbortSignal(signal, fs.createReadStream(tarballName));\n\n // Check stats before emitting open event to ensure content-length is available\n const stats = fs.statSync(tarballName);\n\n // Manually emit 'open' event in the next tick to ensure consistent behavior with fs streams\n process.nextTick(() => {\n debug('read stream opened for %o', tarballName);\n readStream.emit('open');\n debug('file size %o', stats.size);\n readStream.emit('content-length', stats.size);\n });\n\n readStream.on('error', (error) => {\n debug('error reading tarball %o: %s', tarballName, error.message);\n });\n\n return readStream;\n }\n\n public async updatePackage(\n packageName: string,\n handleUpdate: (manifest: Manifest) => Promise<Manifest>\n ): Promise<Manifest> {\n debug('update package %o', packageName);\n try {\n const json = this.data[packageName];\n let manifest = parsePackage(json);\n const newManifest = await handleUpdate(manifest);\n return newManifest;\n } catch (err: any) {\n throw errorUtils.getInternalError(err.message);\n }\n }\n}\n\nexport default MemoryHandler;\n"],"mappings":"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","ignoreList":[]}
package/build/utils.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import { Package } from '@verdaccio/types';
2
- export declare function stringifyPackage(pkg: Package): string;
3
- export declare function parsePackage(pkg: string): any;
1
+ import { Manifest } from '@verdaccio/types';
2
+ export declare function stringifyPackage(manifest: Manifest): string;
3
+ export declare function parsePackage(json: string): Manifest;
package/build/utils.js CHANGED
@@ -5,10 +5,10 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.parsePackage = parsePackage;
7
7
  exports.stringifyPackage = stringifyPackage;
8
- function stringifyPackage(pkg) {
9
- return JSON.stringify(pkg, null, '\t');
8
+ function stringifyPackage(manifest) {
9
+ return JSON.stringify(manifest, null, '\t');
10
10
  }
11
- function parsePackage(pkg) {
12
- return JSON.parse(pkg);
11
+ function parsePackage(json) {
12
+ return JSON.parse(json);
13
13
  }
14
14
  //# sourceMappingURL=utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","names":["stringifyPackage","pkg","JSON","stringify","parsePackage","parse"],"sources":["../src/utils.ts"],"sourcesContent":["import { Package } from '@verdaccio/types';\n\nexport function stringifyPackage(pkg: Package) {\n return JSON.stringify(pkg, null, '\\t');\n}\n\nexport function parsePackage(pkg: string) {\n return JSON.parse(pkg);\n}\n"],"mappings":";;;;;;;AAEO,SAASA,gBAAgBA,CAACC,GAAY,EAAE;EAC7C,OAAOC,IAAI,CAACC,SAAS,CAACF,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC;AACxC;AAEO,SAASG,YAAYA,CAACH,GAAW,EAAE;EACxC,OAAOC,IAAI,CAACG,KAAK,CAACJ,GAAG,CAAC;AACxB","ignoreList":[]}
1
+ {"version":3,"file":"utils.js","names":["stringifyPackage","manifest","JSON","stringify","parsePackage","json","parse"],"sources":["../src/utils.ts"],"sourcesContent":["import { Manifest } from '@verdaccio/types';\n\nexport function stringifyPackage(manifest: Manifest): string {\n return JSON.stringify(manifest, null, '\\t');\n}\n\nexport function parsePackage(json: string): Manifest {\n return JSON.parse(json);\n}\n"],"mappings":";;;;;;;AAEO,SAASA,gBAAgBA,CAACC,QAAkB,EAAU;EAC3D,OAAOC,IAAI,CAACC,SAAS,CAACF,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC;AAC7C;AAEO,SAASG,YAAYA,CAACC,IAAY,EAAY;EACnD,OAAOH,IAAI,CAACI,KAAK,CAACD,IAAI,CAAC;AACzB","ignoreList":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "verdaccio-memory",
3
- "version": "13.0.0-next-8.21",
3
+ "version": "13.0.0-next-8.22",
4
4
  "description": "Verdaccio Memory Storage Plugin",
5
5
  "keywords": [
6
6
  "private",
@@ -30,15 +30,15 @@
30
30
  "node": ">=18"
31
31
  },
32
32
  "dependencies": {
33
- "@verdaccio/core": "8.0.0-next-8.21",
33
+ "@verdaccio/core": "8.0.0-next-8.22",
34
34
  "debug": "4.4.1",
35
- "memfs": "3.5.3"
35
+ "memfs": "4.17.2"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@verdaccio/types": "13.0.0-next-8.7",
39
- "@verdaccio/config": "8.0.0-next-8.21",
40
- "@verdaccio/logger": "8.0.0-next-8.21",
41
- "vitest": "3.0.4"
39
+ "@verdaccio/config": "8.0.0-next-8.22",
40
+ "@verdaccio/logger": "8.0.0-next-8.22",
41
+ "vitest": "3.2.4"
42
42
  },
43
43
  "funding": {
44
44
  "type": "opencollective",