@drawcall/market 0.1.98 → 0.2.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/README.md +7 -4
- package/dist/asset-implementation.d.ts +3 -3
- package/dist/asset-implementation.d.ts.map +1 -1
- package/dist/cli.js +15 -3
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +14 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +18 -0
- package/dist/client.js.map +1 -1
- package/dist/commands/install.js +10 -7
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/list.d.ts +5 -5
- package/dist/commands/list.d.ts.map +1 -1
- package/dist/commands/list.js +22 -9
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/pack.d.ts.map +1 -1
- package/dist/commands/pack.js +2 -2
- package/dist/commands/pack.js.map +1 -1
- package/dist/commands/search.d.ts +2 -0
- package/dist/commands/search.d.ts.map +1 -1
- package/dist/commands/search.js +14 -2
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/sync.d.ts +6 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +22 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/upload.d.ts.map +1 -1
- package/dist/commands/upload.js +20 -10
- package/dist/commands/upload.js.map +1 -1
- package/dist/contract.d.ts +4 -6
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +1 -2
- package/dist/contract.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/install.d.ts.map +1 -1
- package/dist/install.js +69 -27
- package/dist/install.js.map +1 -1
- package/dist/output.d.ts +3 -4
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +40 -7
- package/dist/output.js.map +1 -1
- package/dist/pack.d.ts +36 -6
- package/dist/pack.d.ts.map +1 -1
- package/dist/pack.js +230 -57
- package/dist/pack.js.map +1 -1
- package/dist/package-json.d.ts +4 -3
- package/dist/package-json.d.ts.map +1 -1
- package/dist/package-json.js +3 -1
- package/dist/package-json.js.map +1 -1
- package/dist/resolve.d.ts +8 -1
- package/dist/resolve.d.ts.map +1 -1
- package/dist/resolve.js +35 -3
- package/dist/resolve.js.map +1 -1
- package/dist/schemas.d.ts +19 -7
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +22 -7
- package/dist/schemas.js.map +1 -1
- package/dist/skill.d.ts +1 -1
- package/dist/skill.d.ts.map +1 -1
- package/dist/skill.js +4 -2
- package/dist/skill.js.map +1 -1
- package/dist/v1/client.d.ts +15 -0
- package/dist/v1/client.d.ts.map +1 -0
- package/dist/v1/client.js +18 -0
- package/dist/v1/client.js.map +1 -0
- package/dist/v1/contract.d.ts +206 -0
- package/dist/v1/contract.d.ts.map +1 -0
- package/dist/v1/contract.js +77 -0
- package/dist/v1/contract.js.map +1 -0
- package/dist/v1/index.d.ts +3 -0
- package/dist/v1/index.d.ts.map +1 -0
- package/dist/v1/index.js +3 -0
- package/dist/v1/index.js.map +1 -0
- package/package.json +2 -1
- package/skills/market/SKILL.md +4 -2
- package/src/asset-implementation.ts +3 -3
- package/src/cli.ts +20 -4
- package/src/client.ts +26 -0
- package/src/commands/install.ts +11 -8
- package/src/commands/list.ts +28 -14
- package/src/commands/pack.ts +7 -2
- package/src/commands/search.ts +21 -2
- package/src/commands/sync.ts +30 -0
- package/src/commands/upload.ts +26 -11
- package/src/contract.ts +0 -3
- package/src/index.ts +13 -3
- package/src/install.ts +89 -35
- package/src/output.ts +52 -11
- package/src/pack.ts +317 -70
- package/src/package-json.ts +7 -4
- package/src/resolve.ts +47 -4
- package/src/schemas.ts +32 -8
- package/src/skill.ts +4 -2
- package/src/v1/client.ts +28 -0
- package/src/v1/contract.ts +140 -0
- package/src/v1/index.ts +2 -0
- package/dist/market-lock.d.ts +0 -16
- package/dist/market-lock.d.ts.map +0 -1
- package/dist/market-lock.js +0 -48
- package/dist/market-lock.js.map +0 -1
- package/src/market-lock.ts +0 -68
package/src/schemas.ts
CHANGED
|
@@ -39,7 +39,37 @@ export const assetNameSchema = z
|
|
|
39
39
|
|
|
40
40
|
export const npmDependenciesSchema = z.record(z.string(), z.string()).default({})
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
// An asset dependency is either a plain range ("^1.0.0") or an object carrying the range plus
|
|
43
|
+
// `alias`: a map of the dependency's canonical install paths to where this project keeps the file
|
|
44
|
+
// after renaming/moving it. Install writes each file at `alias[path] ?? path`; pack records the
|
|
45
|
+
// aliases it detects by content hash, so renamed installed files are omitted from packs and
|
|
46
|
+
// restored to their renamed locations on reinstall.
|
|
47
|
+
export const assetDependencyAliasSchema = z.record(z.string(), z.string())
|
|
48
|
+
|
|
49
|
+
export const assetDependencyValueSchema = z.union([
|
|
50
|
+
z.string(),
|
|
51
|
+
z.object({ version: z.string(), alias: assetDependencyAliasSchema.optional() }),
|
|
52
|
+
])
|
|
53
|
+
export type AssetDependencyValue = z.infer<typeof assetDependencyValueSchema>
|
|
54
|
+
export type AssetDependencies = Record<string, AssetDependencyValue>
|
|
55
|
+
|
|
56
|
+
export const assetDependenciesSchema = z.record(z.string(), assetDependencyValueSchema).default({})
|
|
57
|
+
|
|
58
|
+
export function assetDependencyRange(value: AssetDependencyValue): string {
|
|
59
|
+
return typeof value === 'string' ? value : value.version
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function assetDependencyAlias(value: AssetDependencyValue): Record<string, string> {
|
|
63
|
+
return typeof value === 'string' ? {} : (value.alias ?? {})
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** The slimmest value expressing `range` + `alias`: a plain string when there are no aliases. */
|
|
67
|
+
export function assetDependencyValue(
|
|
68
|
+
range: string,
|
|
69
|
+
alias: Record<string, string>,
|
|
70
|
+
): AssetDependencyValue {
|
|
71
|
+
return Object.keys(alias).length === 0 ? range : { version: range, alias }
|
|
72
|
+
}
|
|
43
73
|
|
|
44
74
|
// Maps a skill label to a `skills add` source: a remote ref (owner/repo,
|
|
45
75
|
// git/HTTP URL, tree/<branch>/<subpath>) or a local path to a skill directory
|
|
@@ -95,14 +125,8 @@ export const uploadZipSchema = z.object({
|
|
|
95
125
|
access: assetAccessSchema.optional(),
|
|
96
126
|
})
|
|
97
127
|
|
|
98
|
-
export const downloadZipSchema = z.object({
|
|
99
|
-
name: assetNameSchema,
|
|
100
|
-
version: semverSchema,
|
|
101
|
-
key: accessKeySchema.optional(),
|
|
102
|
-
})
|
|
103
|
-
|
|
104
128
|
// Input of `asset.files`: the derived file index of a version, for per-file installs from the data
|
|
105
|
-
// plane. Same credential rules as
|
|
129
|
+
// plane. Same credential rules as the `GET /download` zip view: an identified viewer or a `key`.
|
|
106
130
|
export const assetFilesSchema = z.object({
|
|
107
131
|
name: assetNameSchema,
|
|
108
132
|
version: semverSchema,
|
package/src/skill.ts
CHANGED
|
@@ -31,7 +31,9 @@ Install exact refs together in one call; names need no \`--type\`:
|
|
|
31
31
|
|
|
32
32
|
Install prints the exact files it wrote and records the dependency so packing and later rebuilds can restore it. It never searches or generates. With no refs it installs \`assetDependencies\` from the nearest \`package.json\`. Assets may install declared skill dependencies with \`npx skills add\`. Use \`--force\` only with permission to overwrite changed local files.
|
|
33
33
|
|
|
34
|
-
\`list --cwd "$PWD"\` is an offline, compact inventory
|
|
34
|
+
\`list --cwd "$PWD"\` is an offline, compact inventory of the \`assetDependencies\` in the nearest \`package.json\`, including file aliases. When selected refs are already installed, read this inventory instead of reinstalling them.
|
|
35
|
+
|
|
36
|
+
An \`assetDependencies\` entry is either a range string or \`{ "version": "<range>", "alias": { "<canonical path>": "<current path>" } }\`. An alias records where the project keeps a renamed installed file: install writes the file at the aliased path, and packing omits exactly that one copy (extra duplicates ship as project content). Run \`sync --cwd "$PWD"\` after renaming installed files to record aliases in \`package.json\`; template packing runs the same update automatically.
|
|
35
37
|
|
|
36
38
|
## Generate
|
|
37
39
|
|
|
@@ -47,7 +49,7 @@ Add \`--access public\` or \`--access private\` when visibility matters. Omitted
|
|
|
47
49
|
|
|
48
50
|
## Publish only when asked
|
|
49
51
|
|
|
50
|
-
Use \`pack <source> --out <zip>\` to create a Market zip and \`upload <name> <source> "<description>" --type <type>\` to publish it. Both accept repeatable \`--npm name@range\`, \`--asset name@range\`, and \`--skill label=source\` dependencies. Template packing reads root \`assetDependencies\` and may use the API to omit
|
|
52
|
+
Use \`pack <source> --out <zip>\` to create a Market zip and \`upload <name> <source> "<description>" --type <type>\` to publish it. Both accept repeatable \`--npm name@range\`, \`--asset name@range\`, and \`--skill label=source\` dependencies. Template packing reads root \`assetDependencies\` and may use the API to omit installed dependency files matched by content hash — even when renamed — recording renames as aliases. A skill source is \`owner/repo\`, a git URL, a full GitHub \`tree/<branch>/<subpath>\` URL, or a local skill directory inside the zip. Use the command's \`--help\` for syntax.
|
|
51
53
|
|
|
52
54
|
Use \`--unapproved\` only when explicitly requested. Do not install an unapproved asset without acceptance. If login is required, ask before running \`npx @drawcall/market login\`.
|
|
53
55
|
`
|
package/src/v1/client.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { createORPCClient } from '@orpc/client'
|
|
2
|
+
import { OpenAPILink } from '@orpc/openapi-client/fetch'
|
|
3
|
+
import type { ContractRouterClient } from '@orpc/contract'
|
|
4
|
+
import { contract, type V1Contract } from './contract.js'
|
|
5
|
+
|
|
6
|
+
export type MarketV1Client = ContractRouterClient<V1Contract>
|
|
7
|
+
|
|
8
|
+
const DEFAULT_BASE_URL = 'https://market.drawcall.ai'
|
|
9
|
+
|
|
10
|
+
export interface MarketV1ClientOptions {
|
|
11
|
+
baseUrl?: string
|
|
12
|
+
fetch?: typeof globalThis.fetch
|
|
13
|
+
authToken?: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A typed client for the v1 REST surface (`/api/v1`). Same call shapes as the legacy RPC client —
|
|
18
|
+
* `client.asset.exact({ name })` — but speaking plain HTTP: reads are GETs on resource URLs, so
|
|
19
|
+
* they are curl-able, shareable and cacheable.
|
|
20
|
+
*/
|
|
21
|
+
export function createClient(opts: MarketV1ClientOptions = {}): MarketV1Client {
|
|
22
|
+
const link = new OpenAPILink(contract, {
|
|
23
|
+
url: new URL('/api/v1', opts.baseUrl ?? DEFAULT_BASE_URL).href,
|
|
24
|
+
fetch: opts.fetch,
|
|
25
|
+
headers: opts.authToken ? { authorization: `Bearer ${opts.authToken}` } : undefined,
|
|
26
|
+
})
|
|
27
|
+
return createORPCClient<MarketV1Client>(link)
|
|
28
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { oc } from '@orpc/contract'
|
|
2
|
+
import { z } from 'zod'
|
|
3
|
+
import type { AssetFileManifest } from '../schemas.js'
|
|
4
|
+
import type {
|
|
5
|
+
AssetExactResult,
|
|
6
|
+
AssetFileEntry,
|
|
7
|
+
AssetInstallMetadata,
|
|
8
|
+
AssetSearchResult,
|
|
9
|
+
AssetVersion,
|
|
10
|
+
PaginatedList,
|
|
11
|
+
User,
|
|
12
|
+
} from '../contract.js'
|
|
13
|
+
import {
|
|
14
|
+
MAX_UPLOAD_ZIP_SIZE_BYTES,
|
|
15
|
+
agentRunStatusSchema,
|
|
16
|
+
agentStartSchema,
|
|
17
|
+
agentStatusSchema,
|
|
18
|
+
assetFilesSchema,
|
|
19
|
+
exactAssetSchema,
|
|
20
|
+
fileManifestSchema,
|
|
21
|
+
generateAssetSchema,
|
|
22
|
+
generateJobStatusSchema,
|
|
23
|
+
generateResponseSchema,
|
|
24
|
+
generateStatusInputSchema,
|
|
25
|
+
listAssetsSchema,
|
|
26
|
+
updateProfileSchema,
|
|
27
|
+
uploadZipSchema,
|
|
28
|
+
} from '../schemas.js'
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The v1 manifest of an asset version — the one linkable, cacheable answer to "what is this
|
|
32
|
+
* version": its metadata plus every stored file with a fetch-ready content-plane URL, the preview
|
|
33
|
+
* URL, and the zip URL. All URLs are minted by the server and MUST be treated as opaque by
|
|
34
|
+
* clients; that opacity is what lets the content plane evolve without client releases.
|
|
35
|
+
*/
|
|
36
|
+
export interface AssetVersionManifest {
|
|
37
|
+
name: string
|
|
38
|
+
type: string
|
|
39
|
+
version: string
|
|
40
|
+
description: string | null
|
|
41
|
+
approved: boolean
|
|
42
|
+
access: 'public' | 'private'
|
|
43
|
+
npmDependencies: string
|
|
44
|
+
assetDependencies: string
|
|
45
|
+
skillDependencies: string
|
|
46
|
+
files: AssetFileEntry[]
|
|
47
|
+
previewUrl: string | null
|
|
48
|
+
zipUrl: string
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The v1 contract: the same procedure tree as the legacy RPC surface (so call sites migrate by
|
|
53
|
+
* swapping only the client), with HTTP routes attached — served as plain REST under `/api/v1`.
|
|
54
|
+
* The route annotations here ARE the control-plane URL contract.
|
|
55
|
+
*/
|
|
56
|
+
export const contract = {
|
|
57
|
+
asset: {
|
|
58
|
+
search: oc
|
|
59
|
+
.route({ method: 'GET', path: '/assets' })
|
|
60
|
+
.input(listAssetsSchema)
|
|
61
|
+
.output(z.custom<PaginatedList<AssetSearchResult>>()),
|
|
62
|
+
|
|
63
|
+
exact: oc
|
|
64
|
+
.route({ method: 'GET', path: '/assets/{name}' })
|
|
65
|
+
.input(exactAssetSchema)
|
|
66
|
+
.output(z.custom<AssetExactResult | null>()),
|
|
67
|
+
|
|
68
|
+
// The manifest is new in v1 — it merges the legacy `files` + metadata into one GET.
|
|
69
|
+
manifest: oc
|
|
70
|
+
.route({ method: 'GET', path: '/assets/{name}/{version}' })
|
|
71
|
+
.input(assetFilesSchema)
|
|
72
|
+
.output(z.custom<AssetVersionManifest>()),
|
|
73
|
+
|
|
74
|
+
files: oc
|
|
75
|
+
.route({ method: 'GET', path: '/assets/{name}/{version}/files' })
|
|
76
|
+
.input(assetFilesSchema)
|
|
77
|
+
.output(z.custom<{ files: AssetFileEntry[] }>()),
|
|
78
|
+
|
|
79
|
+
fileManifest: oc
|
|
80
|
+
.route({ method: 'GET', path: '/assets/{name}/{version}/file-manifest' })
|
|
81
|
+
.input(fileManifestSchema)
|
|
82
|
+
.output(z.custom<AssetFileManifest>()),
|
|
83
|
+
|
|
84
|
+
uploadZip: oc
|
|
85
|
+
.route({ method: 'PUT', path: '/assets/{name}/{version}' })
|
|
86
|
+
.input(
|
|
87
|
+
uploadZipSchema
|
|
88
|
+
.extend({ zip: z.instanceof(File) })
|
|
89
|
+
.refine((input) => input.zip.size < MAX_UPLOAD_ZIP_SIZE_BYTES, {
|
|
90
|
+
message: 'Upload zip must be smaller than 1 GB',
|
|
91
|
+
path: ['zip'],
|
|
92
|
+
}),
|
|
93
|
+
)
|
|
94
|
+
.output(z.custom<AssetVersion>()),
|
|
95
|
+
|
|
96
|
+
installMetadata: oc
|
|
97
|
+
.route({ method: 'GET', path: '/types' })
|
|
98
|
+
.output(z.custom<Record<string, AssetInstallMetadata>>()),
|
|
99
|
+
|
|
100
|
+
generate: oc
|
|
101
|
+
.route({ method: 'POST', path: '/generations' })
|
|
102
|
+
.input(generateAssetSchema)
|
|
103
|
+
.output(generateResponseSchema),
|
|
104
|
+
|
|
105
|
+
generateStatus: oc
|
|
106
|
+
.route({ method: 'GET', path: '/generations/{jobId}' })
|
|
107
|
+
.input(generateStatusInputSchema)
|
|
108
|
+
.output(generateJobStatusSchema),
|
|
109
|
+
|
|
110
|
+
agent: {
|
|
111
|
+
start: oc
|
|
112
|
+
.route({ method: 'POST', path: '/agent-runs' })
|
|
113
|
+
.input(agentStartSchema)
|
|
114
|
+
.output(z.object({ runId: z.string() })),
|
|
115
|
+
status: oc
|
|
116
|
+
.route({ method: 'GET', path: '/agent-runs/{runId}' })
|
|
117
|
+
.input(agentStatusSchema)
|
|
118
|
+
.output(agentRunStatusSchema),
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
user: {
|
|
123
|
+
getProfile: oc.route({ method: 'GET', path: '/me' }).output(z.custom<User | null>()),
|
|
124
|
+
|
|
125
|
+
updateProfile: oc
|
|
126
|
+
.route({ method: 'PATCH', path: '/me' })
|
|
127
|
+
.input(updateProfileSchema)
|
|
128
|
+
.output(z.custom<User>()),
|
|
129
|
+
|
|
130
|
+
getAuthToken: oc
|
|
131
|
+
.route({ method: 'GET', path: '/me/auth-token' })
|
|
132
|
+
.output(z.custom<{ prefix: string; createdAt: Date } | null>()),
|
|
133
|
+
|
|
134
|
+
createAuthToken: oc
|
|
135
|
+
.route({ method: 'POST', path: '/me/auth-token' })
|
|
136
|
+
.output(z.object({ token: z.string(), prefix: z.string() })),
|
|
137
|
+
},
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export type V1Contract = typeof contract
|
package/src/v1/index.ts
ADDED
package/dist/market-lock.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export declare const MARKET_LOCK_PATH = ".drawcall/market-lock.json";
|
|
2
|
-
export interface MarketLockAsset {
|
|
3
|
-
version: string;
|
|
4
|
-
type: string;
|
|
5
|
-
/** Install paths of the asset's files. Content hashes now live on the server (`asset.fileManifest`). */
|
|
6
|
-
files: string[];
|
|
7
|
-
}
|
|
8
|
-
export interface MarketLock {
|
|
9
|
-
version: 1;
|
|
10
|
-
assets: Record<string, MarketLockAsset>;
|
|
11
|
-
}
|
|
12
|
-
export declare function readMarketLock(projectRoot: string): Promise<MarketLock>;
|
|
13
|
-
export declare function writeMarketLock(projectRoot: string, lock: MarketLock): Promise<void>;
|
|
14
|
-
export declare function emptyMarketLock(): MarketLock;
|
|
15
|
-
export declare function sha256(bytes: Uint8Array): string;
|
|
16
|
-
//# sourceMappingURL=market-lock.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"market-lock.d.ts","sourceRoot":"","sources":["../src/market-lock.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,gBAAgB,+BAA+B,CAAA;AAE5D,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,wGAAwG;IACxG,KAAK,EAAE,MAAM,EAAE,CAAA;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,CAAC,CAAA;IACV,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;CACxC;AAqBD,wBAAsB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAQ7E;AAED,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAI1F;AAED,wBAAgB,eAAe,IAAI,UAAU,CAK5C;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAEhD"}
|
package/dist/market-lock.js
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { createHash } from 'crypto';
|
|
2
|
-
import * as fs from 'fs/promises';
|
|
3
|
-
import * as path from 'path';
|
|
4
|
-
import { z } from 'zod';
|
|
5
|
-
export const MARKET_LOCK_PATH = '.drawcall/market-lock.json';
|
|
6
|
-
// Content hashes moved to the server, so the lock records only install paths. It still reads the
|
|
7
|
-
// legacy `{ path: { sha256 } }` shape and normalizes it to a path list, so an existing lock keeps
|
|
8
|
-
// working and is rewritten to the slim form on the next install.
|
|
9
|
-
const filesSchema = z
|
|
10
|
-
.union([z.array(z.string()), z.record(z.string(), z.object({ sha256: z.string() }))])
|
|
11
|
-
.transform((files) => (Array.isArray(files) ? files : Object.keys(files)));
|
|
12
|
-
const marketLockSchema = z.object({
|
|
13
|
-
version: z.literal(1),
|
|
14
|
-
assets: z.record(z.string(), z.object({
|
|
15
|
-
version: z.string(),
|
|
16
|
-
type: z.string(),
|
|
17
|
-
files: filesSchema,
|
|
18
|
-
})),
|
|
19
|
-
});
|
|
20
|
-
export async function readMarketLock(projectRoot) {
|
|
21
|
-
const lockPath = path.join(projectRoot, MARKET_LOCK_PATH);
|
|
22
|
-
try {
|
|
23
|
-
return marketLockSchema.parse(JSON.parse(await fs.readFile(lockPath, 'utf-8')));
|
|
24
|
-
}
|
|
25
|
-
catch (error) {
|
|
26
|
-
if (isMissingFile(error))
|
|
27
|
-
return emptyMarketLock();
|
|
28
|
-
throw error;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
export async function writeMarketLock(projectRoot, lock) {
|
|
32
|
-
const lockPath = path.join(projectRoot, MARKET_LOCK_PATH);
|
|
33
|
-
await fs.mkdir(path.dirname(lockPath), { recursive: true });
|
|
34
|
-
await fs.writeFile(lockPath, JSON.stringify(lock, null, 2) + '\n');
|
|
35
|
-
}
|
|
36
|
-
export function emptyMarketLock() {
|
|
37
|
-
return {
|
|
38
|
-
version: 1,
|
|
39
|
-
assets: {},
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
export function sha256(bytes) {
|
|
43
|
-
return createHash('sha256').update(bytes).digest('hex');
|
|
44
|
-
}
|
|
45
|
-
function isMissingFile(error) {
|
|
46
|
-
return error instanceof Error && 'code' in error && error.code === 'ENOENT';
|
|
47
|
-
}
|
|
48
|
-
//# sourceMappingURL=market-lock.js.map
|
package/dist/market-lock.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"market-lock.js","sourceRoot":"","sources":["../src/market-lock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AACnC,OAAO,KAAK,EAAE,MAAM,aAAa,CAAA;AACjC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAC5B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,MAAM,CAAC,MAAM,gBAAgB,GAAG,4BAA4B,CAAA;AAc5D,iGAAiG;AACjG,kGAAkG;AAClG,iEAAiE;AACjE,MAAM,WAAW,GAAG,CAAC;KAClB,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;KACpF,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;AAE5E,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACrB,MAAM,EAAE,CAAC,CAAC,MAAM,CACd,CAAC,CAAC,MAAM,EAAE,EACV,CAAC,CAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;QACnB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;QAChB,KAAK,EAAE,WAAW;KACnB,CAAC,CACH;CACF,CAAC,CAAA;AAEF,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,WAAmB;IACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAA;IACzD,IAAI,CAAC;QACH,OAAO,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IACjF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,aAAa,CAAC,KAAK,CAAC;YAAE,OAAO,eAAe,EAAE,CAAA;QAClD,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,WAAmB,EAAE,IAAgB;IACzE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAA;IACzD,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC3D,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;AACpE,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO;QACL,OAAO,EAAE,CAAC;QACV,MAAM,EAAE,EAAE;KACX,CAAA;AACH,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,KAAiB;IACtC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AACzD,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAA;AAC7E,CAAC"}
|
package/src/market-lock.ts
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { createHash } from 'crypto'
|
|
2
|
-
import * as fs from 'fs/promises'
|
|
3
|
-
import * as path from 'path'
|
|
4
|
-
import { z } from 'zod'
|
|
5
|
-
|
|
6
|
-
export const MARKET_LOCK_PATH = '.drawcall/market-lock.json'
|
|
7
|
-
|
|
8
|
-
export interface MarketLockAsset {
|
|
9
|
-
version: string
|
|
10
|
-
type: string
|
|
11
|
-
/** Install paths of the asset's files. Content hashes now live on the server (`asset.fileManifest`). */
|
|
12
|
-
files: string[]
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface MarketLock {
|
|
16
|
-
version: 1
|
|
17
|
-
assets: Record<string, MarketLockAsset>
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// Content hashes moved to the server, so the lock records only install paths. It still reads the
|
|
21
|
-
// legacy `{ path: { sha256 } }` shape and normalizes it to a path list, so an existing lock keeps
|
|
22
|
-
// working and is rewritten to the slim form on the next install.
|
|
23
|
-
const filesSchema = z
|
|
24
|
-
.union([z.array(z.string()), z.record(z.string(), z.object({ sha256: z.string() }))])
|
|
25
|
-
.transform((files) => (Array.isArray(files) ? files : Object.keys(files)))
|
|
26
|
-
|
|
27
|
-
const marketLockSchema = z.object({
|
|
28
|
-
version: z.literal(1),
|
|
29
|
-
assets: z.record(
|
|
30
|
-
z.string(),
|
|
31
|
-
z.object({
|
|
32
|
-
version: z.string(),
|
|
33
|
-
type: z.string(),
|
|
34
|
-
files: filesSchema,
|
|
35
|
-
}),
|
|
36
|
-
),
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
export async function readMarketLock(projectRoot: string): Promise<MarketLock> {
|
|
40
|
-
const lockPath = path.join(projectRoot, MARKET_LOCK_PATH)
|
|
41
|
-
try {
|
|
42
|
-
return marketLockSchema.parse(JSON.parse(await fs.readFile(lockPath, 'utf-8')))
|
|
43
|
-
} catch (error) {
|
|
44
|
-
if (isMissingFile(error)) return emptyMarketLock()
|
|
45
|
-
throw error
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export async function writeMarketLock(projectRoot: string, lock: MarketLock): Promise<void> {
|
|
50
|
-
const lockPath = path.join(projectRoot, MARKET_LOCK_PATH)
|
|
51
|
-
await fs.mkdir(path.dirname(lockPath), { recursive: true })
|
|
52
|
-
await fs.writeFile(lockPath, JSON.stringify(lock, null, 2) + '\n')
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export function emptyMarketLock(): MarketLock {
|
|
56
|
-
return {
|
|
57
|
-
version: 1,
|
|
58
|
-
assets: {},
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export function sha256(bytes: Uint8Array): string {
|
|
63
|
-
return createHash('sha256').update(bytes).digest('hex')
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function isMissingFile(error: unknown): boolean {
|
|
67
|
-
return error instanceof Error && 'code' in error && error.code === 'ENOENT'
|
|
68
|
-
}
|