-
Notifications
You must be signed in to change notification settings - Fork 107
Expand file tree
/
Copy pathPackageVersionFileRepository.ts
More file actions
162 lines (151 loc) · 5.09 KB
/
PackageVersionFileRepository.ts
File metadata and controls
162 lines (151 loc) · 5.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import { AccessLevel, Inject, SingletonProto } from '@eggjs/tegg';
import { ModelConvertor } from './util/ModelConvertor.js';
import type { PackageVersionFile as PackageVersionFileModel } from './model/PackageVersionFile.js';
import type { Dist as DistModel } from './model/Dist.js';
import { Dist as DistEntity } from '../core/entity/Dist.js';
import { PackageVersionFile as PackageVersionFileEntity } from '../core/entity/PackageVersionFile.js';
import { AbstractRepository } from './AbstractRepository.js';
@SingletonProto({
accessLevel: AccessLevel.PUBLIC,
})
export class PackageVersionFileRepository extends AbstractRepository {
@Inject()
private readonly PackageVersionFile: typeof PackageVersionFileModel;
@Inject()
private readonly Dist: typeof DistModel;
async createPackageVersionFile(file: PackageVersionFileEntity) {
await this.PackageVersionFile.transaction(async transaction => {
await Promise.all([
ModelConvertor.convertEntityToModel(
file,
this.PackageVersionFile,
transaction
),
ModelConvertor.convertEntityToModel(file.dist, this.Dist, transaction),
]);
});
}
async findPackageVersionFile(
packageVersionId: string,
directory: string,
name: string
) {
const model = await this.PackageVersionFile.findOne({
packageVersionId,
directory,
name,
});
if (!model) return null;
const distModel = await this.Dist.findOne({ distId: model.distId });
const dist =
distModel && ModelConvertor.convertModelToEntity(distModel, DistEntity);
return ModelConvertor.convertModelToEntity(
model,
PackageVersionFileEntity,
{ dist }
);
}
async findPackageVersionFileDists(packageVersionId: string) {
const fileDists: DistEntity[] = [];
const queue = ['/'];
while (queue.length > 0) {
const directory = queue.shift();
if (!directory) {
continue;
}
const { files, directories } = await this.listPackageVersionFiles(
packageVersionId,
directory
);
fileDists.push(...files.map(file => file.dist));
queue.push(...directories);
}
return fileDists;
}
async listPackageVersionFiles(packageVersionId: string, directory: string) {
const isRoot = directory === '/';
const where = isRoot
? { packageVersionId }
: {
packageVersionId,
directory: { $or: [{ $eq: directory }, { $like: `${directory}/%` }] },
};
// only return current directory's files and directories
// https://github.com/cnpm/cnpmcore/issues/680
const models = await this.PackageVersionFile.find(where);
const distIds: string[] = [];
const prefix = isRoot ? directory : `${directory}/`;
const subDirectories = new Set<string>();
const needModels: PackageVersionFileModel[] = [];
for (const item of models) {
if (item.directory === directory) {
// sub file
distIds.push(item.distId);
needModels.push(item);
} else {
// only keep directory = '/' or sub directory like `/dist` but not `/dist/foo`
// sub directory
const subDirectoryName = item.directory
.slice(prefix.length)
.split('/')[0];
subDirectories.add(`${prefix}${subDirectoryName}`);
}
}
const distModels = await this.Dist.find({ distId: distIds });
const distEntitiesMap = new Map<string, DistEntity>();
for (const distModel of distModels) {
const dist = ModelConvertor.convertModelToEntity(distModel, DistEntity);
distEntitiesMap.set(distModel.distId, dist);
}
const files = needModels.map(model => {
const dist = distEntitiesMap.get(model.distId);
return ModelConvertor.convertModelToEntity(
model,
PackageVersionFileEntity,
{ dist }
);
});
return { files, directories: Array.from(subDirectories) };
}
async removePackageVersionFiles(
packageVersionId: string,
distIds?: string[]
) {
if (!distIds) {
const fileDists =
await this.findPackageVersionFileDists(packageVersionId);
distIds = fileDists.map(dist => dist.distId);
}
await this.PackageVersionFile.transaction(async transaction => {
const removeCount = await this.PackageVersionFile.remove(
{ packageVersionId },
true,
transaction
);
this.logger.info(
'[PackageVersionFileRepository:removePackageVersionFiles:remove] %d rows in PackageVersionFile, packageVersionId: %s',
removeCount,
packageVersionId
);
if (distIds.length > 0) {
const distCount = await this.Dist.remove(
{
distId: distIds,
},
true,
transaction
);
this.logger.info(
'[PackageVersionFileRepository:removePackageVersionFiles:remove] %d rows in Dist, packageVersionId: %s',
distCount,
packageVersionId
);
}
});
return distIds;
}
async hasPackageVersionFiles(packageVersionId: string) {
const model = await this.PackageVersionFile.findOne({ packageVersionId });
return !!model;
}
}