@drawcall/market 0.6.14 → 0.7.0
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/client.d.ts.map +1 -1
- package/dist/client.js +7 -4
- package/dist/client.js.map +1 -1
- package/dist/commands/install.d.ts.map +1 -1
- package/dist/commands/install.js +6 -4
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/preview.d.ts +2 -14
- package/dist/commands/preview.d.ts.map +1 -1
- package/dist/commands/preview.js +4 -8
- package/dist/commands/preview.js.map +1 -1
- package/dist/commands/upload.d.ts.map +1 -1
- package/dist/commands/upload.js +5 -6
- package/dist/commands/upload.js.map +1 -1
- package/dist/install.d.ts.map +1 -1
- package/dist/install.js +11 -12
- package/dist/install.js.map +1 -1
- package/dist/pack.d.ts.map +1 -1
- package/dist/pack.js +10 -17
- package/dist/pack.js.map +1 -1
- package/dist/refs.d.ts +20 -0
- package/dist/refs.d.ts.map +1 -0
- package/dist/refs.js +25 -0
- package/dist/refs.js.map +1 -0
- package/dist/resolve.d.ts +3 -0
- package/dist/resolve.d.ts.map +1 -1
- package/dist/resolve.js +27 -42
- package/dist/resolve.js.map +1 -1
- package/dist/v1/contract.d.ts +1 -0
- package/dist/v1/contract.d.ts.map +1 -1
- package/dist/v1/contract.js.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +7 -4
- package/src/commands/install.ts +6 -4
- package/src/commands/preview.ts +10 -24
- package/src/commands/upload.ts +5 -6
- package/src/install.ts +12 -15
- package/src/pack.ts +16 -22
- package/src/refs.ts +44 -0
- package/src/resolve.ts +44 -61
- package/src/v1/contract.ts +1 -0
package/src/resolve.ts
CHANGED
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
|
|
12
12
|
import * as semver from 'semver'
|
|
13
13
|
import type { MarketClient } from './client.js'
|
|
14
|
-
import type {
|
|
14
|
+
import type { AssetFileEntry } from './contract.js'
|
|
15
|
+
import { lookupAssets } from './refs.js'
|
|
16
|
+
import type { AssetRefEntry } from './v1/index.js'
|
|
15
17
|
import {
|
|
16
18
|
assetDependencyAlias,
|
|
17
19
|
type AssetDependencyAlias,
|
|
@@ -28,6 +30,8 @@ export interface ResolvedAsset {
|
|
|
28
30
|
npmDependencies: Record<string, string>
|
|
29
31
|
assetDependencies: AssetDependencies
|
|
30
32
|
skillDependencies: Record<string, string>
|
|
33
|
+
/** The resolved version's file index, carried from resolution so install needs no further reads. */
|
|
34
|
+
files: AssetFileEntry[]
|
|
31
35
|
}
|
|
32
36
|
|
|
33
37
|
export interface ResolveResult {
|
|
@@ -74,7 +78,7 @@ export async function resolve(
|
|
|
74
78
|
requests: AssetRequest[],
|
|
75
79
|
opts: { includeUnapproved?: boolean; key?: string } = {},
|
|
76
80
|
): Promise<ResolveResult> {
|
|
77
|
-
const metaCache = new Map<string,
|
|
81
|
+
const metaCache = new Map<string, AssetRefEntry>()
|
|
78
82
|
const includeUnapproved = opts.includeUnapproved ?? false
|
|
79
83
|
let exactPins = exactPinsFor(rootConstraints(requests))
|
|
80
84
|
const seenPinSets = new Set<string>()
|
|
@@ -122,7 +126,7 @@ async function resolvePass(
|
|
|
122
126
|
requests: AssetRequest[],
|
|
123
127
|
initialPins: ExactPins,
|
|
124
128
|
includeUnapproved: boolean,
|
|
125
|
-
metaCache: Map<string,
|
|
129
|
+
metaCache: Map<string, AssetRefEntry>,
|
|
126
130
|
key?: string,
|
|
127
131
|
): Promise<ResolutionPass> {
|
|
128
132
|
const constraints = rootConstraints(requests)
|
|
@@ -138,19 +142,34 @@ async function resolvePass(
|
|
|
138
142
|
const names = [...new Set(wave)].filter((name) => !resolved.has(name))
|
|
139
143
|
wave = []
|
|
140
144
|
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
assetName,
|
|
147
|
-
exactVersion,
|
|
148
|
-
meta: await fetchMeta(client, metaCache, assetName, exactVersion, includeUnapproved, key),
|
|
149
|
-
}
|
|
150
|
-
}),
|
|
151
|
-
)
|
|
145
|
+
const wanted = names.map((assetName) => {
|
|
146
|
+
const constrainedExact = requiredExactVersion(assetName, constraints.get(assetName) ?? [])
|
|
147
|
+
const exactVersion = constrainedExact ?? initialPins.get(assetName) ?? null
|
|
148
|
+
return { assetName, exactVersion }
|
|
149
|
+
})
|
|
152
150
|
|
|
153
|
-
|
|
151
|
+
// One collection read per wave; the cache spans convergence passes, so a
|
|
152
|
+
// re-pass that pins already-seen versions makes no further requests.
|
|
153
|
+
const misses = wanted.filter(
|
|
154
|
+
({ assetName, exactVersion }) => !metaCache.has(metaKey(assetName, exactVersion)),
|
|
155
|
+
)
|
|
156
|
+
const fetched = await lookupAssets(
|
|
157
|
+
client,
|
|
158
|
+
misses.map(({ assetName, exactVersion }) => ({
|
|
159
|
+
name: assetName,
|
|
160
|
+
version: exactVersion ?? undefined,
|
|
161
|
+
})),
|
|
162
|
+
{ includeUnapproved, key },
|
|
163
|
+
)
|
|
164
|
+
misses.forEach(({ assetName, exactVersion }, index) => {
|
|
165
|
+
const entry = fetched[index]
|
|
166
|
+
if (!entry) return
|
|
167
|
+
metaCache.set(metaKey(assetName, exactVersion), entry)
|
|
168
|
+
metaCache.set(metaKey(assetName, entry.version), entry)
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
for (const { assetName, exactVersion } of wanted) {
|
|
172
|
+
const meta = metaCache.get(metaKey(assetName, exactVersion)) ?? null
|
|
154
173
|
if (!meta) {
|
|
155
174
|
if (exactVersion) {
|
|
156
175
|
throw new ResolutionError(
|
|
@@ -166,12 +185,13 @@ async function resolvePass(
|
|
|
166
185
|
throw new ResolutionError(`Asset "${assetName}" has no approved versions.`)
|
|
167
186
|
}
|
|
168
187
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
188
|
+
if (exactVersion && meta.version !== exactVersion) {
|
|
189
|
+
throw new ResolutionError(
|
|
190
|
+
`Market API did not return requested version "${assetName}@${exactVersion}". ` +
|
|
191
|
+
'Refusing to fall back to a different version.',
|
|
192
|
+
)
|
|
193
|
+
}
|
|
194
|
+
const selectedVersion = meta.version
|
|
175
195
|
const assetDependencies = meta.assetDependencies
|
|
176
196
|
resolved.set(assetName, {
|
|
177
197
|
name: assetName,
|
|
@@ -181,6 +201,7 @@ async function resolvePass(
|
|
|
181
201
|
npmDependencies: meta.npmDependencies,
|
|
182
202
|
assetDependencies,
|
|
183
203
|
skillDependencies: meta.skillDependencies,
|
|
204
|
+
files: meta.files,
|
|
184
205
|
})
|
|
185
206
|
|
|
186
207
|
for (const [dependencyName, dependencyValue] of Object.entries(assetDependencies)) {
|
|
@@ -293,28 +314,8 @@ function pinSignature(pins: ExactPins): string {
|
|
|
293
314
|
return JSON.stringify([...pins].sort(([left], [right]) => left.localeCompare(right)))
|
|
294
315
|
}
|
|
295
316
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
cache: Map<string, AssetExactResult>,
|
|
299
|
-
name: string,
|
|
300
|
-
version: string | null,
|
|
301
|
-
includeUnapproved: boolean,
|
|
302
|
-
key?: string,
|
|
303
|
-
): Promise<AssetExactResult | null> {
|
|
304
|
-
const cacheKey = version ? `${name}@${version}` : name
|
|
305
|
-
const cached = cache.get(cacheKey)
|
|
306
|
-
if (cached) return cached
|
|
307
|
-
// The key is sent with every lookup in the tree; it only unlocks the asset it belongs to and is
|
|
308
|
-
// inert for the rest, so no per-asset routing is needed.
|
|
309
|
-
const meta = await client.exact({
|
|
310
|
-
name,
|
|
311
|
-
...(version ? { version } : {}),
|
|
312
|
-
includeUnapproved,
|
|
313
|
-
...(key ? { key } : {}),
|
|
314
|
-
})
|
|
315
|
-
if (meta) cache.set(cacheKey, meta)
|
|
316
|
-
return meta
|
|
317
|
-
}
|
|
317
|
+
const metaKey = (name: string, version: string | null): string =>
|
|
318
|
+
version ? `${name}@${version}` : name
|
|
318
319
|
|
|
319
320
|
function requiredExactVersion(assetName: string, constraints: Constraint[]): string | null {
|
|
320
321
|
const exactVersions = new Set(
|
|
@@ -335,24 +336,6 @@ function exactVersion(range: string): string | null {
|
|
|
335
336
|
return semverSchema.safeParse(candidate).success ? candidate : null
|
|
336
337
|
}
|
|
337
338
|
|
|
338
|
-
function exactMetadataVersion(
|
|
339
|
-
meta: AssetExactResult,
|
|
340
|
-
assetName: string,
|
|
341
|
-
requestedVersion: string,
|
|
342
|
-
): string {
|
|
343
|
-
if (meta.version === requestedVersion) return meta.version
|
|
344
|
-
throw new ResolutionError(
|
|
345
|
-
`Market API did not return requested version "${assetName}@${requestedVersion}". ` +
|
|
346
|
-
'Refusing to fall back to a different version.',
|
|
347
|
-
)
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
function latestMetadataVersion(meta: AssetExactResult): string {
|
|
351
|
-
// Older workers do not return `version`. Range requests can retain their established latest-
|
|
352
|
-
// version behavior; exact requests instead fail closed in exactMetadataVersion above.
|
|
353
|
-
return meta.version ?? meta.latestVersion
|
|
354
|
-
}
|
|
355
|
-
|
|
356
339
|
/**
|
|
357
340
|
* Merge npm dependency ranges from all resolved assets.
|
|
358
341
|
* For each package, check that all declared ranges are compatible
|