@drawcall/market 0.6.11 → 0.6.14

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.
Files changed (50) hide show
  1. package/README.md +8 -2
  2. package/dist/asset-implementation.d.ts.map +1 -1
  3. package/dist/asset-implementation.js +8 -2
  4. package/dist/asset-implementation.js.map +1 -1
  5. package/dist/cli.js +13 -2
  6. package/dist/cli.js.map +1 -1
  7. package/dist/commands/search.d.ts.map +1 -1
  8. package/dist/commands/search.js +3 -0
  9. package/dist/commands/search.js.map +1 -1
  10. package/dist/commands/upload.js +7 -5
  11. package/dist/commands/upload.js.map +1 -1
  12. package/dist/install.d.ts.map +1 -1
  13. package/dist/install.js +5 -18
  14. package/dist/install.js.map +1 -1
  15. package/dist/output.d.ts +0 -2
  16. package/dist/output.d.ts.map +1 -1
  17. package/dist/output.js +1 -5
  18. package/dist/output.js.map +1 -1
  19. package/dist/pack.d.ts +2 -2
  20. package/dist/pack.d.ts.map +1 -1
  21. package/dist/pack.js +4 -12
  22. package/dist/pack.js.map +1 -1
  23. package/dist/package-json.d.ts +12 -7
  24. package/dist/package-json.d.ts.map +1 -1
  25. package/dist/package-json.js +12 -4
  26. package/dist/package-json.js.map +1 -1
  27. package/dist/schemas.d.ts +5 -2
  28. package/dist/schemas.d.ts.map +1 -1
  29. package/dist/schemas.js +10 -2
  30. package/dist/schemas.js.map +1 -1
  31. package/dist/v1/contract.d.ts +14 -2
  32. package/dist/v1/contract.d.ts.map +1 -1
  33. package/dist/v1/contract.js +5 -2
  34. package/dist/v1/contract.js.map +1 -1
  35. package/dist/v1/index.d.ts +1 -1
  36. package/dist/v1/index.d.ts.map +1 -1
  37. package/dist/v1/index.js +1 -1
  38. package/dist/v1/index.js.map +1 -1
  39. package/package.json +3 -2
  40. package/src/asset-implementation.ts +7 -2
  41. package/src/cli.ts +16 -2
  42. package/src/commands/search.ts +3 -0
  43. package/src/commands/upload.ts +8 -5
  44. package/src/install.ts +8 -24
  45. package/src/output.ts +1 -6
  46. package/src/pack.ts +6 -21
  47. package/src/package-json.ts +14 -14
  48. package/src/schemas.ts +11 -2
  49. package/src/v1/contract.ts +16 -2
  50. package/src/v1/index.ts +7 -1
package/src/pack.ts CHANGED
@@ -3,6 +3,7 @@ import * as fs from 'fs/promises'
3
3
  import * as path from 'path'
4
4
  import { unzipSync, zipSync } from 'fflate'
5
5
  import ignore from 'ignore'
6
+ import pMap from 'p-map'
6
7
  import semver from 'semver'
7
8
  import {
8
9
  ALWAYS_IGNORED_DIRS,
@@ -112,9 +113,9 @@ export function fileManifestForRange(asset: MarketClient['asset']): FetchFileMan
112
113
 
113
114
  // Oldest first, so a newer version's hash wins when a path recurs across versions.
114
115
  const merged: Record<string, string> = {}
115
- for (const hashes of await mapWithConcurrency(inRange, 4, (version) =>
116
- fileIndexHashes(asset, name, version),
117
- )) {
116
+ for (const hashes of await pMap(inRange, (version) => fileIndexHashes(asset, name, version), {
117
+ concurrency: 4,
118
+ })) {
118
119
  Object.assign(merged, hashes)
119
120
  }
120
121
  return merged
@@ -135,22 +136,6 @@ function exactRangeVersion(range: string): string | null {
135
136
  return semverSchema.safeParse(candidate).success ? candidate : null
136
137
  }
137
138
 
138
- async function mapWithConcurrency<T, R>(
139
- items: readonly T[],
140
- concurrency: number,
141
- fn: (item: T) => Promise<R>,
142
- ): Promise<R[]> {
143
- const results = new Array<R>(items.length)
144
- let next = 0
145
- async function worker(): Promise<void> {
146
- for (let index = next++; index < items.length; index = next++) {
147
- results[index] = await fn(items[index])
148
- }
149
- }
150
- await Promise.all(Array.from({ length: Math.min(concurrency, items.length) }, () => worker()))
151
- return results
152
- }
153
-
154
139
  export async function packAsset(zipFilter: string, opts: PackAssetOptions): Promise<PackedAsset> {
155
140
  const cwd = opts.cwd ?? process.cwd()
156
141
 
@@ -499,12 +484,12 @@ async function withoutInstalledDependencyFiles(
499
484
  }
500
485
  }
501
486
 
502
- export interface DependencyFile {
487
+ interface DependencyFile {
503
488
  name: string
504
489
  canonicalPath: string
505
490
  }
506
491
 
507
- export interface DependencyFileEntry extends DependencyFile {
492
+ interface DependencyFileEntry extends DependencyFile {
508
493
  /** md5 hex of the file's canonical content — its R2 etag, from the file index. */
509
494
  hash: string
510
495
  }
@@ -1,17 +1,18 @@
1
1
  import { z } from 'zod'
2
2
  import { assetDependencyValueSchema, type AssetDependencies } from './schemas.js'
3
3
 
4
- export interface PackageJson {
5
- name?: string
6
- private?: boolean
7
- dependencies?: Record<string, string>
8
- assetDependencies?: AssetDependencies
9
- [key: string]: unknown
10
- }
11
-
12
4
  const stringRecordSchema = z.record(z.string(), z.string())
13
-
14
5
  const assetDependenciesRecordSchema = z.record(z.string(), assetDependencyValueSchema)
6
+ const packageJsonSchema = z
7
+ .object({
8
+ name: z.string().optional(),
9
+ private: z.boolean().optional(),
10
+ dependencies: stringRecordSchema.optional(),
11
+ assetDependencies: assetDependenciesRecordSchema.optional(),
12
+ })
13
+ .catchall(z.unknown())
14
+
15
+ export type PackageJson = z.infer<typeof packageJsonSchema>
15
16
 
16
17
  export function packageJsonAssetDependenciesFromFiles(
17
18
  files: Record<string, Uint8Array>,
@@ -48,10 +49,9 @@ export function packageJsonNpmDependenciesFromFiles(
48
49
  }
49
50
 
50
51
  export function parsePackageJson(json: string, source: string): PackageJson {
51
- const parsed = JSON.parse(json) as unknown
52
- if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
53
- throw new Error(`${source} must contain a JSON object`)
52
+ const parsed = packageJsonSchema.safeParse(JSON.parse(json))
53
+ if (!parsed.success) {
54
+ throw new Error(`${source} must contain a valid package.json object`)
54
55
  }
55
-
56
- return parsed as PackageJson
56
+ return parsed.data
57
57
  }
package/src/schemas.ts CHANGED
@@ -111,7 +111,7 @@ export const listAssetsSchema = z.object({
111
111
  // An asset's capability key — embedded in file URL paths and in the preview URL's `?key=` query.
112
112
  // Accepted by exact reads as an alternative credential to identity, so "sharing an asset" is
113
113
  // sharing this one string.
114
- export const accessKeySchema = z.string().min(1).max(128)
114
+ const accessKeySchema = z.string().min(1).max(128)
115
115
 
116
116
  export const exactAssetSchema = z.object({
117
117
  name: assetNameSchema,
@@ -121,6 +121,15 @@ export const exactAssetSchema = z.object({
121
121
  key: accessKeySchema.optional(),
122
122
  })
123
123
 
124
+ // The refs mode of the collection read: `?refs=name[@version],…` returns exactly those assets —
125
+ // full entries with files and version history — order-preserved, null per miss. Reads are plural
126
+ // by default; a single asset is the plural of one.
127
+ export const assetRefsSchema = z.object({
128
+ refs: z.string().min(1).max(4000),
129
+ includeUnapproved: z.boolean().default(false),
130
+ key: accessKeySchema.optional(),
131
+ })
132
+
124
133
  export const uploadZipSchema = z.object({
125
134
  name: assetNameSchema,
126
135
  type: assetTypeSchema,
@@ -165,7 +174,7 @@ const MAX_REFERENCE_IMAGE_CHARS = 10_000_000
165
174
  // Reference images the generated asset should match, each an http(s) URL or a
166
175
  // `data:image/<type>;base64,<data>` URI. Only providers that declare
167
176
  // `acceptsReferenceImages` take them, and none takes more than four.
168
- export const referenceImagesSchema = z
177
+ const referenceImagesSchema = z
169
178
  .array(
170
179
  z
171
180
  .string()
@@ -16,6 +16,7 @@ import {
16
16
  agentStartSchema,
17
17
  agentStatusSchema,
18
18
  assetFilesSchema,
19
+ assetRefsSchema,
19
20
  assetVersionsSchema,
20
21
  exactAssetSchema,
21
22
  generateAssetSchema,
@@ -48,6 +49,16 @@ export interface AssetVersionManifest {
48
49
  zipUrl: string
49
50
  }
50
51
 
52
+ /** One entry of the refs read: the version's full manifest plus the asset's version history
53
+ * (oldest first), so range selection and multi-version hashing need no further calls. */
54
+ export interface AssetRefEntry extends AssetVersionManifest {
55
+ versions: string[]
56
+ }
57
+
58
+ export interface AssetRefsResult {
59
+ assets: (AssetRefEntry | null)[]
60
+ }
61
+
51
62
  /**
52
63
  * The v1 contract: the same procedure tree as the legacy RPC surface (so call sites migrate by
53
64
  * swapping only the client), with HTTP routes attached — served as plain REST under `/api/v1`.
@@ -55,10 +66,13 @@ export interface AssetVersionManifest {
55
66
  */
56
67
  export const contract = {
57
68
  asset: {
69
+ // The one collection read, discriminated by params: `?refs=name[@version],…`
70
+ // returns exactly those assets (full entries, order-preserved, null per
71
+ // miss); everything else is a search. Reads are plural by default.
58
72
  search: oc
59
73
  .route({ method: 'GET', path: '/assets' })
60
- .input(listAssetsSchema)
61
- .output(z.custom<PaginatedList<AssetSearchResult>>()),
74
+ .input(z.union([assetRefsSchema, listAssetsSchema]))
75
+ .output(z.custom<PaginatedList<AssetSearchResult> | AssetRefsResult>()),
62
76
 
63
77
  exact: oc
64
78
  .route({ method: 'GET', path: '/assets/{name}' })
package/src/v1/index.ts CHANGED
@@ -1,2 +1,8 @@
1
- export { contract, type V1Contract, type AssetVersionManifest } from './contract.js'
1
+ export {
2
+ contract,
3
+ type V1Contract,
4
+ type AssetVersionManifest,
5
+ type AssetRefEntry,
6
+ type AssetRefsResult,
7
+ } from './contract.js'
2
8
  export { createClient, type MarketV1Client, type MarketV1ClientOptions } from './client.js'