-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
Resolver.ts
162 lines (151 loc) Β· 6.95 KB
/
Resolver.ts
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 {FetchOptions} from './Fetcher';
import {Project} from './Project';
import {Report} from './Report';
import {Descriptor, Locator, Package} from './types';
export type MinimalResolveOptions = {
project: Project;
resolver: Resolver;
};
export type ResolveOptions = MinimalResolveOptions & {
fetchOptions?: FetchOptions | null;
report: Report;
};
/**
* Resolvers are the components that do all the lifting needed in order to
* produce a lockfile. In clear, they transfom the following:
*
* webpack@^4.0.0
*
* into this:
*
* webpack@4.28.0 | dependencies: ajv@^6.1.0, ajv-keyword@^3.1.0, ...
*
* In order to do this, they have three different data structures used to
* represents the various states of the package resolution:
*
* - **Descriptors** contain a package name and a range (for example, using
* the previous example, "^4.0.0" would be the range). This range might
* point to multiple possible resolutions, so a descriptor alone isn't
* enough to fetch the package data from its remote location.
*
* - **Locators** contain a package name and a reference that is used to
* both uniquely identify a package and fetch it from its remote location.
* To keep using the same example, "4.28.0" would be the reference. Note
* that locators have a funny property: they also are valid descriptors!
*
* - **Packages** are locators that made it big. While locators are quite
* small, package definitions are relatively fat and contain much more
* information than their cousins - for example the dependency list of the
* package.
*/
export interface Resolver {
/**
* This function must return true if the specified descriptor is meant to be
* turned into a locator by this resolver. The other functions (except its
* locator counterpart) won't be called if it returns false.
*
* @param descriptor The descriptor that needs to be validated.
* @param opts The resolution options.
*/
supportsDescriptor(descriptor: Descriptor, opts: MinimalResolveOptions): boolean;
/**
* This function must return true if the specified locator is meant to be
* turned into a package definition by this resolver. The other functions
* (except its locator counterpart) won't be called if it returns false.
*
* @param locator The locator that needs to be validated.
* @param opts The resolution options.
*/
supportsLocator(locator: Locator, opts: MinimalResolveOptions): boolean;
/**
* This function indicates whether the package definition for the specified
* locator must be kept between installs. You typically want to return true
* for all packages that are cached, but return false for all packages that
* hydrate packages directly from the filesystem (for example workspaces).
*
* Note that even packages returning false are stored within the lockfile!
* The difference is that when a new install is done, all package definitions
* that return false will be discarded and resolved again (their potential
* cache data will be kept, though).
*
* @param locator The queried package.
* @param opts The resolution options.
*/
shouldPersistResolution(locator: Locator, opts: MinimalResolveOptions): boolean;
/**
* This function is called for each dependency present in the dependency list
* of a package definition. If it returns a new descriptor, this new
* descriptor will be used
*
* Note that `fromLocator` is not necessarily a locator that's supported by
* the resolver. It simply is the locator of the package that depends on the
* specified descriptor, regardless who owns it.
*
* A typical case where you will want to use this function is when your
* resolver must support relative paths (for example the `link:` protocol).
* In this situation, you'll want to store the `fromLocator` in the bound
* descriptor in order to be able to access the right location during the
* next steps of the resolution.
*
* @param descriptor The depended descriptor.
* @param fromLocator The dependent locator.
* @param opts The resolution options.
*/
bindDescriptor(descriptor: Descriptor, fromLocator: Locator, opts: MinimalResolveOptions): Descriptor;
/**
* This function must return a set of other descriptors that must be
* transformed into locators before the subject descriptor can be transformed
* into a locator. This is typically only needed for transform packages, as
* you need to know the original resolution in order to copy it.
*/
getResolutionDependencies(descriptor: Descriptor, opts: MinimalResolveOptions): Record<string, Descriptor>;
/**
* This function will, given a descriptor, return the list of locators that
* potentially satisfy it.
*
* The returned array must be sorted in such a way that the preferred
* locators are first. This will cause the resolution algorithm to prioritize
* them if possible (it doesn't guarantee that they'll end up being used).
*
* @param descriptor The source descriptor.
* @param dependencies The resolution dependencies and their resolutions.
* @param opts The resolution options.
*/
getCandidates(descriptor: Descriptor, dependencies: Record<string, Package>, opts: ResolveOptions): Promise<Array<Locator>>;
/**
* This function will, given a descriptor and a list of locators,
* find out which of the locators potentially satisfy the descriptor.
*
* This function is different from `getCandidates`, as `getCandidates` will
* resolve the descriptor into a list of locators (potentially using the network),
* while `getSatisfying` will statically compute which known references potentially
* satisfy the target descriptor.
*
* Note that the parameter references aren't guaranteed to be supported by
* the resolver, so they'll probably need to be filtered beforehand.
*
* The returned array should be sorted in such a way that the preferred
* locators are first. This will cause the resolution algorithm to prioritize
* them if possible (it doesn't guarantee that they'll end up being used). If
* the resolver is unable to provide a definite order (for example like the
* `file:` protocol resolver, where ordering references would make no sense),
* the `sorted` field should be set to `false`.
*
* @param descriptor The target descriptor.
* @param dependencies The resolution dependencies and their resolutions.
* @param locators The candidate locators.
* @param opts The resolution options.
*/
getSatisfying(descriptor: Descriptor, dependencies: Record<string, Package>, locators: Array<Locator>, opts: ResolveOptions): Promise<{
locators: Array<Locator>;
sorted: boolean;
}>;
/**
* This function will, given a locator, return the full package definition
* for the package pointed at.
*
* @param locator The source locator.
* @param opts The resolution options.
*/
resolve(locator: Locator, opts: ResolveOptions): Promise<Package>;
}