threenative-asset-mcp 0.4.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 +441 -0
- package/dist/ambientcg/client.d.ts +61 -0
- package/dist/ambientcg/client.d.ts.map +1 -0
- package/dist/ambientcg/client.js +234 -0
- package/dist/ambientcg/client.js.map +1 -0
- package/dist/audio/catalog.d.ts +36 -0
- package/dist/audio/catalog.d.ts.map +1 -0
- package/dist/audio/catalog.js +169 -0
- package/dist/audio/catalog.js.map +1 -0
- package/dist/audio/client.d.ts +46 -0
- package/dist/audio/client.d.ts.map +1 -0
- package/dist/audio/client.js +196 -0
- package/dist/audio/client.js.map +1 -0
- package/dist/bundle/client.d.ts +89 -0
- package/dist/bundle/client.d.ts.map +1 -0
- package/dist/bundle/client.js +324 -0
- package/dist/bundle/client.js.map +1 -0
- package/dist/config.d.ts +20 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +130 -0
- package/dist/config.js.map +1 -0
- package/dist/download/direct-asset-downloader.d.ts +41 -0
- package/dist/download/direct-asset-downloader.d.ts.map +1 -0
- package/dist/download/direct-asset-downloader.js +232 -0
- package/dist/download/direct-asset-downloader.js.map +1 -0
- package/dist/fab/api-download.d.ts +30 -0
- package/dist/fab/api-download.d.ts.map +1 -0
- package/dist/fab/api-download.js +200 -0
- package/dist/fab/api-download.js.map +1 -0
- package/dist/fab/browser-transport.d.ts +79 -0
- package/dist/fab/browser-transport.d.ts.map +1 -0
- package/dist/fab/browser-transport.js +492 -0
- package/dist/fab/browser-transport.js.map +1 -0
- package/dist/fab/cache.d.ts +22 -0
- package/dist/fab/cache.d.ts.map +1 -0
- package/dist/fab/cache.js +55 -0
- package/dist/fab/cache.js.map +1 -0
- package/dist/fab/client.d.ts +61 -0
- package/dist/fab/client.d.ts.map +1 -0
- package/dist/fab/client.js +868 -0
- package/dist/fab/client.js.map +1 -0
- package/dist/fab/direct-transport.d.ts +68 -0
- package/dist/fab/direct-transport.d.ts.map +1 -0
- package/dist/fab/direct-transport.js +184 -0
- package/dist/fab/direct-transport.js.map +1 -0
- package/dist/fab/download-store.d.ts +21 -0
- package/dist/fab/download-store.d.ts.map +1 -0
- package/dist/fab/download-store.js +93 -0
- package/dist/fab/download-store.js.map +1 -0
- package/dist/fab/errors.d.ts +20 -0
- package/dist/fab/errors.d.ts.map +1 -0
- package/dist/fab/errors.js +65 -0
- package/dist/fab/errors.js.map +1 -0
- package/dist/fab/impersonate-fetch.d.ts +48 -0
- package/dist/fab/impersonate-fetch.d.ts.map +1 -0
- package/dist/fab/impersonate-fetch.js +228 -0
- package/dist/fab/impersonate-fetch.js.map +1 -0
- package/dist/fab/normalize.d.ts +3 -0
- package/dist/fab/normalize.d.ts.map +1 -0
- package/dist/fab/normalize.js +285 -0
- package/dist/fab/normalize.js.map +1 -0
- package/dist/fab/schemas.d.ts +10 -0
- package/dist/fab/schemas.d.ts.map +1 -0
- package/dist/fab/schemas.js +105 -0
- package/dist/fab/schemas.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +58 -0
- package/dist/index.js.map +1 -0
- package/dist/itch/catalog.d.ts +13 -0
- package/dist/itch/catalog.d.ts.map +1 -0
- package/dist/itch/catalog.js +50 -0
- package/dist/itch/catalog.js.map +1 -0
- package/dist/itch/client.d.ts +46 -0
- package/dist/itch/client.d.ts.map +1 -0
- package/dist/itch/client.js +175 -0
- package/dist/itch/client.js.map +1 -0
- package/dist/polyhaven/client.d.ts +55 -0
- package/dist/polyhaven/client.d.ts.map +1 -0
- package/dist/polyhaven/client.js +210 -0
- package/dist/polyhaven/client.js.map +1 -0
- package/dist/server.d.ts +25 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +448 -0
- package/dist/server.js.map +1 -0
- package/dist/sketchfab/client.d.ts +70 -0
- package/dist/sketchfab/client.d.ts.map +1 -0
- package/dist/sketchfab/client.js +255 -0
- package/dist/sketchfab/client.js.map +1 -0
- package/dist/smithsonian/client.d.ts +32 -0
- package/dist/smithsonian/client.d.ts.map +1 -0
- package/dist/smithsonian/client.js +142 -0
- package/dist/smithsonian/client.js.map +1 -0
- package/dist/tools/ambientcg.d.ts +296 -0
- package/dist/tools/ambientcg.d.ts.map +1 -0
- package/dist/tools/ambientcg.js +183 -0
- package/dist/tools/ambientcg.js.map +1 -0
- package/dist/tools/audio.d.ts +211 -0
- package/dist/tools/audio.d.ts.map +1 -0
- package/dist/tools/audio.js +156 -0
- package/dist/tools/audio.js.map +1 -0
- package/dist/tools/bundle.d.ts +237 -0
- package/dist/tools/bundle.d.ts.map +1 -0
- package/dist/tools/bundle.js +206 -0
- package/dist/tools/bundle.js.map +1 -0
- package/dist/tools/direct-download.d.ts +53 -0
- package/dist/tools/direct-download.d.ts.map +1 -0
- package/dist/tools/direct-download.js +68 -0
- package/dist/tools/direct-download.js.map +1 -0
- package/dist/tools/download-free-asset.d.ts +66 -0
- package/dist/tools/download-free-asset.d.ts.map +1 -0
- package/dist/tools/download-free-asset.js +60 -0
- package/dist/tools/download-free-asset.js.map +1 -0
- package/dist/tools/get-asset.d.ts +161 -0
- package/dist/tools/get-asset.d.ts.map +1 -0
- package/dist/tools/get-asset.js +131 -0
- package/dist/tools/get-asset.js.map +1 -0
- package/dist/tools/itch.d.ts +120 -0
- package/dist/tools/itch.d.ts.map +1 -0
- package/dist/tools/itch.js +120 -0
- package/dist/tools/itch.js.map +1 -0
- package/dist/tools/list-filters.d.ts +127 -0
- package/dist/tools/list-filters.d.ts.map +1 -0
- package/dist/tools/list-filters.js +68 -0
- package/dist/tools/list-filters.js.map +1 -0
- package/dist/tools/list-limited-time-free.d.ts +57 -0
- package/dist/tools/list-limited-time-free.d.ts.map +1 -0
- package/dist/tools/list-limited-time-free.js +47 -0
- package/dist/tools/list-limited-time-free.js.map +1 -0
- package/dist/tools/polyhaven.d.ts +266 -0
- package/dist/tools/polyhaven.d.ts.map +1 -0
- package/dist/tools/polyhaven.js +233 -0
- package/dist/tools/polyhaven.js.map +1 -0
- package/dist/tools/search-assets.d.ts +176 -0
- package/dist/tools/search-assets.d.ts.map +1 -0
- package/dist/tools/search-assets.js +172 -0
- package/dist/tools/search-assets.js.map +1 -0
- package/dist/tools/sketchfab.d.ts +325 -0
- package/dist/tools/sketchfab.d.ts.map +1 -0
- package/dist/tools/sketchfab.js +203 -0
- package/dist/tools/sketchfab.js.map +1 -0
- package/dist/tools/smithsonian.d.ts +189 -0
- package/dist/tools/smithsonian.d.ts.map +1 -0
- package/dist/tools/smithsonian.js +189 -0
- package/dist/tools/smithsonian.js.map +1 -0
- package/dist/tools/source-directory.d.ts +226 -0
- package/dist/tools/source-directory.d.ts.map +1 -0
- package/dist/tools/source-directory.js +583 -0
- package/dist/tools/source-directory.js.map +1 -0
- package/package.json +69 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const UpstreamSearchSchema = z
|
|
3
|
+
.object({
|
|
4
|
+
results: z.array(z.unknown()),
|
|
5
|
+
cursors: z
|
|
6
|
+
.object({
|
|
7
|
+
next: z.string().nullable().optional(),
|
|
8
|
+
previous: z.string().nullable().optional(),
|
|
9
|
+
})
|
|
10
|
+
.passthrough()
|
|
11
|
+
.optional(),
|
|
12
|
+
})
|
|
13
|
+
.passthrough();
|
|
14
|
+
export const UpstreamListingSchema = z
|
|
15
|
+
.record(z.string(), z.unknown())
|
|
16
|
+
.superRefine((value, context) => {
|
|
17
|
+
const id = value.uid ?? value.id ?? value.uuid;
|
|
18
|
+
const title = value.title ?? value.name;
|
|
19
|
+
if (typeof id !== "string" || id.length === 0) {
|
|
20
|
+
context.addIssue({
|
|
21
|
+
code: "custom",
|
|
22
|
+
message: "listing identity is missing",
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
if (typeof title !== "string" || title.length === 0) {
|
|
26
|
+
context.addIssue({
|
|
27
|
+
code: "custom",
|
|
28
|
+
message: "listing title is missing",
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
for (const key of [
|
|
32
|
+
"licenses",
|
|
33
|
+
"offers",
|
|
34
|
+
"assetFormats",
|
|
35
|
+
"asset_formats",
|
|
36
|
+
"formats",
|
|
37
|
+
"media",
|
|
38
|
+
"images",
|
|
39
|
+
"files",
|
|
40
|
+
"tags",
|
|
41
|
+
"categories",
|
|
42
|
+
]) {
|
|
43
|
+
if (value[key] !== undefined && !Array.isArray(value[key])) {
|
|
44
|
+
context.addIssue({
|
|
45
|
+
code: "custom",
|
|
46
|
+
message: `${key} must be an array when present`,
|
|
47
|
+
path: [key],
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const licenses = value.licenses ?? value.offers;
|
|
52
|
+
if (Array.isArray(licenses)) {
|
|
53
|
+
licenses.forEach((entry, index) => {
|
|
54
|
+
if (typeof entry !== "object" ||
|
|
55
|
+
entry === null ||
|
|
56
|
+
Array.isArray(entry)) {
|
|
57
|
+
context.addIssue({
|
|
58
|
+
code: "custom",
|
|
59
|
+
message: "license entries must be objects",
|
|
60
|
+
path: ["licenses", index],
|
|
61
|
+
});
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const license = entry;
|
|
65
|
+
for (const priceKey of [
|
|
66
|
+
"price",
|
|
67
|
+
"basePrice",
|
|
68
|
+
"pricing",
|
|
69
|
+
"discountedPrice",
|
|
70
|
+
"effectivePrice",
|
|
71
|
+
"salePrice",
|
|
72
|
+
]) {
|
|
73
|
+
const rawPrice = license[priceKey];
|
|
74
|
+
if (rawPrice === undefined)
|
|
75
|
+
continue;
|
|
76
|
+
if (typeof rawPrice !== "object" ||
|
|
77
|
+
rawPrice === null ||
|
|
78
|
+
Array.isArray(rawPrice)) {
|
|
79
|
+
context.addIssue({
|
|
80
|
+
code: "custom",
|
|
81
|
+
message: `${priceKey} must be an object`,
|
|
82
|
+
path: ["licenses", index, priceKey],
|
|
83
|
+
});
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const price = rawPrice;
|
|
87
|
+
const numeric = [
|
|
88
|
+
price.amount,
|
|
89
|
+
price.price,
|
|
90
|
+
price.value,
|
|
91
|
+
price.effectiveAmount,
|
|
92
|
+
price.discountedAmount,
|
|
93
|
+
].some((candidate) => typeof candidate === "number" && Number.isFinite(candidate));
|
|
94
|
+
if (!numeric) {
|
|
95
|
+
context.addIssue({
|
|
96
|
+
code: "custom",
|
|
97
|
+
message: `${priceKey} has no numeric price`,
|
|
98
|
+
path: ["licenses", index, priceKey],
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
//# sourceMappingURL=schemas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/fab/schemas.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { serveStdio } from "@modelcontextprotocol/server/stdio";
|
|
3
|
+
import { AmbientCgClient } from "./ambientcg/client.js";
|
|
4
|
+
import { AudioCatalogClient } from "./audio/client.js";
|
|
5
|
+
import { BundleAssetClient } from "./bundle/client.js";
|
|
6
|
+
import { DirectAssetDownloader } from "./download/direct-asset-downloader.js";
|
|
7
|
+
import { FabClient } from "./fab/client.js";
|
|
8
|
+
import { ItchAssetClient } from "./itch/client.js";
|
|
9
|
+
import { PolyHavenClient } from "./polyhaven/client.js";
|
|
10
|
+
import { SketchfabClient } from "./sketchfab/client.js";
|
|
11
|
+
import { createAssetServer } from "./server.js";
|
|
12
|
+
import { SmithsonianClient } from "./smithsonian/client.js";
|
|
13
|
+
const fab = new FabClient();
|
|
14
|
+
const polyhaven = new PolyHavenClient();
|
|
15
|
+
const ambientcg = new AmbientCgClient();
|
|
16
|
+
const smithsonian = new SmithsonianClient();
|
|
17
|
+
const sketchfab = new SketchfabClient();
|
|
18
|
+
const audio = new AudioCatalogClient();
|
|
19
|
+
const directDownloader = new DirectAssetDownloader();
|
|
20
|
+
const itch = new ItchAssetClient({ downloader: directDownloader });
|
|
21
|
+
const bundle = new BundleAssetClient({ itch });
|
|
22
|
+
void fab.prepareBrowser();
|
|
23
|
+
const handle = serveStdio(() => createAssetServer({
|
|
24
|
+
fab,
|
|
25
|
+
polyhaven,
|
|
26
|
+
ambientcg,
|
|
27
|
+
smithsonian,
|
|
28
|
+
sketchfab,
|
|
29
|
+
audio,
|
|
30
|
+
directDownloader,
|
|
31
|
+
itch,
|
|
32
|
+
bundle,
|
|
33
|
+
}), {
|
|
34
|
+
onerror(error) {
|
|
35
|
+
process.stderr.write(`${JSON.stringify({
|
|
36
|
+
level: "error",
|
|
37
|
+
message: "MCP transport error",
|
|
38
|
+
error: error.name,
|
|
39
|
+
})}\n`);
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
let closing = false;
|
|
43
|
+
async function shutdown() {
|
|
44
|
+
if (closing)
|
|
45
|
+
return;
|
|
46
|
+
closing = true;
|
|
47
|
+
await Promise.allSettled([fab.close(), handle.close()]);
|
|
48
|
+
}
|
|
49
|
+
process.once("SIGINT", () => {
|
|
50
|
+
void shutdown().finally(() => process.exit(0));
|
|
51
|
+
});
|
|
52
|
+
process.once("SIGTERM", () => {
|
|
53
|
+
void shutdown().finally(() => process.exit(0));
|
|
54
|
+
});
|
|
55
|
+
process.once("beforeExit", () => {
|
|
56
|
+
void shutdown();
|
|
57
|
+
});
|
|
58
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAC;AAEhE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAC9E,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D,MAAM,GAAG,GAAG,IAAI,SAAS,EAAE,CAAC;AAC5B,MAAM,SAAS,GAAG,IAAI,eAAe,EAAE,CAAC;AACxC,MAAM,SAAS,GAAG,IAAI,eAAe,EAAE,CAAC;AACxC,MAAM,WAAW,GAAG,IAAI,iBAAiB,EAAE,CAAC;AAC5C,MAAM,SAAS,GAAG,IAAI,eAAe,EAAE,CAAC;AACxC,MAAM,KAAK,GAAG,IAAI,kBAAkB,EAAE,CAAC;AACvC,MAAM,gBAAgB,GAAG,IAAI,qBAAqB,EAAE,CAAC;AACrD,MAAM,IAAI,GAAG,IAAI,eAAe,CAAC,EAAE,UAAU,EAAE,gBAAgB,EAAE,CAAC,CAAC;AACnE,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;AAC/C,KAAK,GAAG,CAAC,cAAc,EAAE,CAAC;AAC1B,MAAM,MAAM,GAAG,UAAU,CACvB,GAAG,EAAE,CACH,iBAAiB,CAAC;IAChB,GAAG;IACH,SAAS;IACT,SAAS;IACT,WAAW;IACX,SAAS;IACT,KAAK;IACL,gBAAgB;IAChB,IAAI;IACJ,MAAM;CACP,CAAC,EACJ;IACA,OAAO,CAAC,KAAK;QACX,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,GAAG,IAAI,CAAC,SAAS,CAAC;YAChB,KAAK,EAAE,OAAO;YACd,OAAO,EAAE,qBAAqB;YAC9B,KAAK,EAAE,KAAK,CAAC,IAAI;SAClB,CAAC,IAAI,CACP,CAAC;IACJ,CAAC;CACA,CACF,CAAC;AAEF,IAAI,OAAO,GAAG,KAAK,CAAC;AACpB,KAAK,UAAU,QAAQ;IACrB,IAAI,OAAO;QAAE,OAAO;IACpB,OAAO,GAAG,IAAI,CAAC;IACf,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE;IAC1B,KAAK,QAAQ,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AACjD,CAAC,CAAC,CAAC;AACH,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE;IAC3B,KAAK,QAAQ,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AACjD,CAAC,CAAC,CAAC;AACH,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,EAAE;IAC9B,KAAK,QAAQ,EAAE,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type ItchPackId = "tallbeard-music-loop-bundle" | "quaternius-universal-animation-library-1" | "quaternius-universal-animation-library-2" | "brackeys-vfx-bundle" | "kaykit-platformer";
|
|
2
|
+
export interface ItchPack {
|
|
3
|
+
id: ItchPackId;
|
|
4
|
+
name: string;
|
|
5
|
+
sourceId: string;
|
|
6
|
+
pageUrl: string;
|
|
7
|
+
kind: "music" | "animation" | "vfx" | "3d-model";
|
|
8
|
+
license: "CC0";
|
|
9
|
+
attributionRequired: false;
|
|
10
|
+
caution?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare const ITCH_PACKS: readonly ItchPack[];
|
|
13
|
+
//# sourceMappingURL=catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/itch/catalog.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAClB,6BAA6B,GAC7B,0CAA0C,GAC1C,0CAA0C,GAC1C,qBAAqB,GACrB,mBAAmB,CAAC;AAExB,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,UAAU,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,OAAO,GAAG,WAAW,GAAG,KAAK,GAAG,UAAU,CAAC;IACjD,OAAO,EAAE,KAAK,CAAC;IACf,mBAAmB,EAAE,KAAK,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,UAAU,EAAE,SAAS,QAAQ,EAgDhC,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export const ITCH_PACKS = [
|
|
2
|
+
{
|
|
3
|
+
id: "tallbeard-music-loop-bundle",
|
|
4
|
+
name: "Tallbeard Music Loop Bundle",
|
|
5
|
+
sourceId: "tallbeard",
|
|
6
|
+
pageUrl: "https://tallbeard.itch.io/music-loop-bundle",
|
|
7
|
+
kind: "music",
|
|
8
|
+
license: "CC0",
|
|
9
|
+
attributionRequired: false,
|
|
10
|
+
caution: "Credit to Abstraction is optional but appreciated by the creator.",
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
id: "quaternius-universal-animation-library-1",
|
|
14
|
+
name: "Quaternius Universal Animation Library 1",
|
|
15
|
+
sourceId: "quaternius",
|
|
16
|
+
pageUrl: "https://quaternius.itch.io/universal-animation-library",
|
|
17
|
+
kind: "animation",
|
|
18
|
+
license: "CC0",
|
|
19
|
+
attributionRequired: false,
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
id: "quaternius-universal-animation-library-2",
|
|
23
|
+
name: "Quaternius Universal Animation Library 2",
|
|
24
|
+
sourceId: "quaternius",
|
|
25
|
+
pageUrl: "https://quaternius.itch.io/universal-animation-library-2",
|
|
26
|
+
kind: "animation",
|
|
27
|
+
license: "CC0",
|
|
28
|
+
attributionRequired: false,
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
id: "brackeys-vfx-bundle",
|
|
32
|
+
name: "Brackeys VFX Bundle",
|
|
33
|
+
sourceId: "brackeys-vfx",
|
|
34
|
+
pageUrl: "https://brackeysgames.itch.io/brackeys-vfx-bundle",
|
|
35
|
+
kind: "vfx",
|
|
36
|
+
license: "CC0",
|
|
37
|
+
attributionRequired: false,
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: "kaykit-platformer",
|
|
41
|
+
name: "KayKit Platformer Pack",
|
|
42
|
+
sourceId: "kaykit",
|
|
43
|
+
pageUrl: "https://kaylousberg.itch.io/kaykit-platformer",
|
|
44
|
+
kind: "3d-model",
|
|
45
|
+
license: "CC0",
|
|
46
|
+
attributionRequired: false,
|
|
47
|
+
caution: "Do not resell the unmodified pack or claim it as your own.",
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
//# sourceMappingURL=catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/itch/catalog.ts"],"names":[],"mappings":"AAkBA,MAAM,CAAC,MAAM,UAAU,GAAwB;IAC7C;QACE,EAAE,EAAE,6BAA6B;QACjC,IAAI,EAAE,6BAA6B;QACnC,QAAQ,EAAE,WAAW;QACrB,OAAO,EAAE,6CAA6C;QACtD,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,KAAK;QACd,mBAAmB,EAAE,KAAK;QAC1B,OAAO,EAAE,mEAAmE;KAC7E;IACD;QACE,EAAE,EAAE,0CAA0C;QAC9C,IAAI,EAAE,0CAA0C;QAChD,QAAQ,EAAE,YAAY;QACtB,OAAO,EAAE,wDAAwD;QACjE,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,KAAK;QACd,mBAAmB,EAAE,KAAK;KAC3B;IACD;QACE,EAAE,EAAE,0CAA0C;QAC9C,IAAI,EAAE,0CAA0C;QAChD,QAAQ,EAAE,YAAY;QACtB,OAAO,EAAE,0DAA0D;QACnE,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,KAAK;QACd,mBAAmB,EAAE,KAAK;KAC3B;IACD;QACE,EAAE,EAAE,qBAAqB;QACzB,IAAI,EAAE,qBAAqB;QAC3B,QAAQ,EAAE,cAAc;QACxB,OAAO,EAAE,mDAAmD;QAC5D,IAAI,EAAE,KAAK;QACX,OAAO,EAAE,KAAK;QACd,mBAAmB,EAAE,KAAK;KAC3B;IACD;QACE,EAAE,EAAE,mBAAmB;QACvB,IAAI,EAAE,wBAAwB;QAC9B,QAAQ,EAAE,QAAQ;QAClB,OAAO,EAAE,+CAA+C;QACxD,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,KAAK;QACd,mBAAmB,EAAE,KAAK;QAC1B,OAAO,EAAE,4DAA4D;KACtE;CACO,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { DirectAssetDownloader } from "../download/direct-asset-downloader.js";
|
|
2
|
+
import { type ItchPack, type ItchPackId } from "./catalog.js";
|
|
3
|
+
export interface ItchDownloadEntry {
|
|
4
|
+
uploadId: string;
|
|
5
|
+
name: string;
|
|
6
|
+
sizeLabel?: string;
|
|
7
|
+
suggestedFileName: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ItchPackDownloads {
|
|
10
|
+
pack: ItchPack;
|
|
11
|
+
downloads: ItchDownloadEntry[];
|
|
12
|
+
}
|
|
13
|
+
export interface ResolvedItchUpload {
|
|
14
|
+
pack: ItchPack;
|
|
15
|
+
upload: ItchDownloadEntry;
|
|
16
|
+
signedFileUrl: string;
|
|
17
|
+
}
|
|
18
|
+
export declare class ItchAssetError extends Error {
|
|
19
|
+
readonly code: "ITCH_PACK_NOT_FOUND" | "ITCH_UPLOAD_NOT_FOUND" | "ITCH_UPSTREAM_DENIED" | "ITCH_UPSTREAM_CHANGED" | "ITCH_UNSAFE_URL";
|
|
20
|
+
readonly retryable: boolean;
|
|
21
|
+
constructor(code: "ITCH_PACK_NOT_FOUND" | "ITCH_UPLOAD_NOT_FOUND" | "ITCH_UPSTREAM_DENIED" | "ITCH_UPSTREAM_CHANGED" | "ITCH_UNSAFE_URL", message: string, retryable?: boolean);
|
|
22
|
+
}
|
|
23
|
+
export interface ItchAssetClientOptions {
|
|
24
|
+
fetch?: typeof globalThis.fetch;
|
|
25
|
+
downloader?: DirectAssetDownloader;
|
|
26
|
+
timeoutMs?: number;
|
|
27
|
+
}
|
|
28
|
+
export declare class ItchAssetClient {
|
|
29
|
+
private readonly fetch;
|
|
30
|
+
private readonly downloader;
|
|
31
|
+
private readonly timeoutMs;
|
|
32
|
+
constructor(options?: ItchAssetClientOptions);
|
|
33
|
+
getPack(packId: ItchPackId): ItchPack;
|
|
34
|
+
listDownloads(packId: ItchPackId): Promise<ItchPackDownloads>;
|
|
35
|
+
download(packId: ItchPackId, uploadId: string): Promise<{
|
|
36
|
+
pack: ItchPack;
|
|
37
|
+
upload: ItchDownloadEntry;
|
|
38
|
+
result: import("../download/direct-asset-downloader.js").DirectAssetDownloadResult;
|
|
39
|
+
}>;
|
|
40
|
+
resolveUpload(packId: ItchPackId, uploadId: string): Promise<ResolvedItchUpload>;
|
|
41
|
+
private resolveDownloadPage;
|
|
42
|
+
private requestJson;
|
|
43
|
+
private validateSignedPageUrl;
|
|
44
|
+
private validateSignedFileUrl;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/itch/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AAC/E,OAAO,EAAc,KAAK,QAAQ,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1E,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,QAAQ,CAAC;IACf,SAAS,EAAE,iBAAiB,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,iBAAiB,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,cAAe,SAAQ,KAAK;aAErB,IAAI,EAChB,qBAAqB,GACrB,uBAAuB,GACvB,sBAAsB,GACtB,uBAAuB,GACvB,iBAAiB;aAEL,SAAS;IAR3B,YACkB,IAAI,EAChB,qBAAqB,GACrB,uBAAuB,GACvB,sBAAsB,GACtB,uBAAuB,GACvB,iBAAiB,EACrB,OAAO,EAAE,MAAM,EACC,SAAS,UAAQ,EAIlC;CACF;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAChC,UAAU,CAAC,EAAE,qBAAqB,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA6CD,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA0B;IAChD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAwB;IACnD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IAEnC,YAAY,OAAO,GAAE,sBAA2B,EAI/C;IAED,OAAO,CAAC,MAAM,EAAE,UAAU,GAAG,QAAQ,CASpC;IAEK,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAGlE;IAEK,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM;;;;OAalD;IAEK,aAAa,CACjB,MAAM,EAAE,UAAU,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,kBAAkB,CAAC,CAwB7B;YAEa,mBAAmB;YAuCnB,WAAW;IAiCzB,OAAO,CAAC,qBAAqB;IAoB7B,OAAO,CAAC,qBAAqB;CAwB9B"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { DirectAssetDownloader } from "../download/direct-asset-downloader.js";
|
|
2
|
+
import { ITCH_PACKS } from "./catalog.js";
|
|
3
|
+
export class ItchAssetError extends Error {
|
|
4
|
+
code;
|
|
5
|
+
retryable;
|
|
6
|
+
constructor(code, message, retryable = false) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.code = code;
|
|
9
|
+
this.retryable = retryable;
|
|
10
|
+
this.name = "ItchAssetError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function decodeHtml(value) {
|
|
14
|
+
return value
|
|
15
|
+
.replace(/&/g, "&")
|
|
16
|
+
.replace(/"/g, '"')
|
|
17
|
+
.replace(/'|'/g, "'")
|
|
18
|
+
.replace(/</g, "<")
|
|
19
|
+
.replace(/>/g, ">");
|
|
20
|
+
}
|
|
21
|
+
function safeSuggestedFileName(name) {
|
|
22
|
+
const cleaned = name.replace(/[\\/:*?"<>|]/g, "_").trim().slice(0, 200);
|
|
23
|
+
return /\.[A-Za-z0-9]{2,5}$/.test(cleaned) ? cleaned : `${cleaned}.zip`;
|
|
24
|
+
}
|
|
25
|
+
function parseDownloads(html) {
|
|
26
|
+
const entries = [];
|
|
27
|
+
const uploadPattern = /data-upload_id="(\d+)"/g;
|
|
28
|
+
for (const match of html.matchAll(uploadPattern)) {
|
|
29
|
+
const uploadId = match[1];
|
|
30
|
+
if (!uploadId || match.index === undefined)
|
|
31
|
+
continue;
|
|
32
|
+
const window = html.slice(match.index, match.index + 2_000);
|
|
33
|
+
const nameMatch = window.match(/<strong[^>]*title="([^"]+)"[^>]*>/i);
|
|
34
|
+
if (!nameMatch?.[1])
|
|
35
|
+
continue;
|
|
36
|
+
const sizeMatch = window.match(/class="file_size"[^>]*>\s*<span[^>]*>([^<]+)<\/span>/i);
|
|
37
|
+
const name = decodeHtml(nameMatch[1]).trim();
|
|
38
|
+
entries.push({
|
|
39
|
+
uploadId,
|
|
40
|
+
name,
|
|
41
|
+
...(sizeMatch?.[1] ? { sizeLabel: decodeHtml(sizeMatch[1]).trim() } : {}),
|
|
42
|
+
suggestedFileName: safeSuggestedFileName(name),
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return entries;
|
|
46
|
+
}
|
|
47
|
+
function object(value) {
|
|
48
|
+
return typeof value === "object" && value !== null && !Array.isArray(value)
|
|
49
|
+
? value
|
|
50
|
+
: undefined;
|
|
51
|
+
}
|
|
52
|
+
export class ItchAssetClient {
|
|
53
|
+
fetch;
|
|
54
|
+
downloader;
|
|
55
|
+
timeoutMs;
|
|
56
|
+
constructor(options = {}) {
|
|
57
|
+
this.fetch = options.fetch ?? globalThis.fetch;
|
|
58
|
+
this.downloader = options.downloader ?? new DirectAssetDownloader();
|
|
59
|
+
this.timeoutMs = options.timeoutMs ?? 30_000;
|
|
60
|
+
}
|
|
61
|
+
getPack(packId) {
|
|
62
|
+
const pack = ITCH_PACKS.find((candidate) => candidate.id === packId);
|
|
63
|
+
if (!pack) {
|
|
64
|
+
throw new ItchAssetError("ITCH_PACK_NOT_FOUND", "The requested itch.io pack is not in the curated catalog.");
|
|
65
|
+
}
|
|
66
|
+
return pack;
|
|
67
|
+
}
|
|
68
|
+
async listDownloads(packId) {
|
|
69
|
+
const { pack, downloads } = await this.resolveDownloadPage(packId);
|
|
70
|
+
return { pack, downloads };
|
|
71
|
+
}
|
|
72
|
+
async download(packId, uploadId) {
|
|
73
|
+
const { pack, upload: selected, signedFileUrl } = await this.resolveUpload(packId, uploadId);
|
|
74
|
+
const result = await this.downloader.download({
|
|
75
|
+
provider: "itch",
|
|
76
|
+
url: signedFileUrl,
|
|
77
|
+
fileName: selected.suggestedFileName,
|
|
78
|
+
identity: `${pack.id}:${selected.uploadId}`,
|
|
79
|
+
reportedSourceUrl: pack.pageUrl,
|
|
80
|
+
});
|
|
81
|
+
return { pack, upload: selected, result };
|
|
82
|
+
}
|
|
83
|
+
async resolveUpload(packId, uploadId) {
|
|
84
|
+
const { pack, downloads, signedPageUrl } = await this.resolveDownloadPage(packId);
|
|
85
|
+
const selected = downloads.find((entry) => entry.uploadId === uploadId);
|
|
86
|
+
if (!selected) {
|
|
87
|
+
throw new ItchAssetError("ITCH_UPLOAD_NOT_FOUND", "The requested upload ID is not present on the freshly resolved itch.io download page.");
|
|
88
|
+
}
|
|
89
|
+
const fileResponse = await this.requestJson(`${pack.pageUrl}/file/${encodeURIComponent(uploadId)}?source=game_download`, signedPageUrl);
|
|
90
|
+
const signedFileUrl = fileResponse.url;
|
|
91
|
+
if (typeof signedFileUrl !== "string") {
|
|
92
|
+
throw new ItchAssetError("ITCH_UPSTREAM_CHANGED", "itch.io did not return a signed file URL.");
|
|
93
|
+
}
|
|
94
|
+
this.validateSignedFileUrl(signedFileUrl);
|
|
95
|
+
return { pack, upload: selected, signedFileUrl };
|
|
96
|
+
}
|
|
97
|
+
async resolveDownloadPage(packId) {
|
|
98
|
+
const pack = this.getPack(packId);
|
|
99
|
+
const response = await this.requestJson(`${pack.pageUrl}/download_url`);
|
|
100
|
+
const signedPageUrl = response.url;
|
|
101
|
+
if (typeof signedPageUrl !== "string") {
|
|
102
|
+
throw new ItchAssetError("ITCH_UPSTREAM_CHANGED", "itch.io did not return a signed download page URL.");
|
|
103
|
+
}
|
|
104
|
+
this.validateSignedPageUrl(pack, signedPageUrl);
|
|
105
|
+
const page = await this.fetch(signedPageUrl, {
|
|
106
|
+
redirect: "error",
|
|
107
|
+
signal: AbortSignal.timeout(this.timeoutMs),
|
|
108
|
+
headers: { "user-agent": "threenative-asset-mcp/0.4.0" },
|
|
109
|
+
});
|
|
110
|
+
if (!page.ok) {
|
|
111
|
+
throw new ItchAssetError("ITCH_UPSTREAM_DENIED", `itch.io returned HTTP ${page.status} for the signed download page.`, page.status === 429 || page.status >= 500);
|
|
112
|
+
}
|
|
113
|
+
const html = await page.text();
|
|
114
|
+
const downloads = parseDownloads(html);
|
|
115
|
+
if (downloads.length === 0) {
|
|
116
|
+
throw new ItchAssetError("ITCH_UPSTREAM_CHANGED", "itch.io returned a download page without recognizable uploads.");
|
|
117
|
+
}
|
|
118
|
+
return { pack, downloads, signedPageUrl };
|
|
119
|
+
}
|
|
120
|
+
async requestJson(url, referer) {
|
|
121
|
+
const response = await this.fetch(url, {
|
|
122
|
+
method: "POST",
|
|
123
|
+
redirect: "error",
|
|
124
|
+
signal: AbortSignal.timeout(this.timeoutMs),
|
|
125
|
+
headers: {
|
|
126
|
+
accept: "application/json",
|
|
127
|
+
"user-agent": "threenative-asset-mcp/0.4.0",
|
|
128
|
+
...(referer ? { referer } : {}),
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
if (!response.ok) {
|
|
132
|
+
throw new ItchAssetError("ITCH_UPSTREAM_DENIED", `itch.io returned HTTP ${response.status}.`, response.status === 429 || response.status >= 500);
|
|
133
|
+
}
|
|
134
|
+
try {
|
|
135
|
+
const parsed = object(await response.json());
|
|
136
|
+
if (!parsed)
|
|
137
|
+
throw new Error("not an object");
|
|
138
|
+
return parsed;
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
throw new ItchAssetError("ITCH_UPSTREAM_CHANGED", "itch.io returned invalid JSON.");
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
validateSignedPageUrl(pack, value) {
|
|
145
|
+
let signed;
|
|
146
|
+
const page = new URL(pack.pageUrl);
|
|
147
|
+
try {
|
|
148
|
+
signed = new URL(value);
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
throw new ItchAssetError("ITCH_UNSAFE_URL", "itch.io returned an invalid URL.");
|
|
152
|
+
}
|
|
153
|
+
if (signed.protocol !== "https:" ||
|
|
154
|
+
signed.origin !== page.origin ||
|
|
155
|
+
!signed.pathname.startsWith(`${page.pathname}/download/`)) {
|
|
156
|
+
throw new ItchAssetError("ITCH_UNSAFE_URL", "itch.io returned a signed page URL outside the curated pack origin.");
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
validateSignedFileUrl(value) {
|
|
160
|
+
let signed;
|
|
161
|
+
try {
|
|
162
|
+
signed = new URL(value);
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
throw new ItchAssetError("ITCH_UNSAFE_URL", "itch.io returned an invalid file URL.");
|
|
166
|
+
}
|
|
167
|
+
if (signed.protocol !== "https:" ||
|
|
168
|
+
!/^itchio-mirror\.[0-9a-f]+\.r2\.cloudflarestorage\.com$/i.test(signed.hostname) ||
|
|
169
|
+
!/^\/upload2\/game\/\d+\/\d+$/.test(signed.pathname) ||
|
|
170
|
+
!signed.searchParams.has("X-Amz-Signature")) {
|
|
171
|
+
throw new ItchAssetError("ITCH_UNSAFE_URL", "itch.io returned a signed file URL outside its official mirror contract.");
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/itch/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export type PolyHavenAssetType = "hdris" | "textures" | "models";
|
|
2
|
+
export interface PolyHavenAsset {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
type: PolyHavenAssetType;
|
|
7
|
+
category?: string;
|
|
8
|
+
categoryId?: string;
|
|
9
|
+
tags: string[];
|
|
10
|
+
authors: Record<string, string>;
|
|
11
|
+
attributes: Record<string, unknown>;
|
|
12
|
+
thumbnailUrl?: string;
|
|
13
|
+
maxResolution?: number[];
|
|
14
|
+
dimensions?: number[];
|
|
15
|
+
polycount?: number;
|
|
16
|
+
downloadCount?: number;
|
|
17
|
+
publishedAt?: string;
|
|
18
|
+
filesHash?: string;
|
|
19
|
+
donated?: boolean;
|
|
20
|
+
lods?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface PolyHavenFile {
|
|
23
|
+
path: string;
|
|
24
|
+
url: string;
|
|
25
|
+
sizeBytes: number;
|
|
26
|
+
md5: string;
|
|
27
|
+
dependencyOf?: string;
|
|
28
|
+
relativePath?: string;
|
|
29
|
+
}
|
|
30
|
+
export declare class PolyHavenClientError extends Error {
|
|
31
|
+
readonly code: "POLYHAVEN_INVALID_INPUT" | "POLYHAVEN_NOT_FOUND" | "POLYHAVEN_RATE_LIMITED" | "POLYHAVEN_UPSTREAM_UNAVAILABLE" | "POLYHAVEN_UPSTREAM_CHANGED";
|
|
32
|
+
readonly retryable: boolean;
|
|
33
|
+
constructor(code: "POLYHAVEN_INVALID_INPUT" | "POLYHAVEN_NOT_FOUND" | "POLYHAVEN_RATE_LIMITED" | "POLYHAVEN_UPSTREAM_UNAVAILABLE" | "POLYHAVEN_UPSTREAM_CHANGED", message: string, retryable?: boolean);
|
|
34
|
+
}
|
|
35
|
+
type FetchLike = typeof fetch;
|
|
36
|
+
export declare class PolyHavenClient {
|
|
37
|
+
private readonly fetchImpl;
|
|
38
|
+
private readonly cache;
|
|
39
|
+
private readonly timeoutMs;
|
|
40
|
+
private readonly userAgent;
|
|
41
|
+
constructor(fetchImpl?: FetchLike, options?: {
|
|
42
|
+
timeoutMs?: number;
|
|
43
|
+
userAgent?: string;
|
|
44
|
+
});
|
|
45
|
+
private request;
|
|
46
|
+
listAssets(type: PolyHavenAssetType | "all"): Promise<PolyHavenAsset[]>;
|
|
47
|
+
getAsset(id: string): Promise<PolyHavenAsset>;
|
|
48
|
+
listFiles(id: string): Promise<PolyHavenFile[]>;
|
|
49
|
+
listCategories(type: PolyHavenAssetType): Promise<Array<{
|
|
50
|
+
name: string;
|
|
51
|
+
assetCount: number;
|
|
52
|
+
}>>;
|
|
53
|
+
}
|
|
54
|
+
export {};
|
|
55
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/polyhaven/client.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,CAAC;AAEjE,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,kBAAkB,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,oBAAqB,SAAQ,KAAK;IAE3C,QAAQ,CAAC,IAAI,EACT,yBAAyB,GACzB,qBAAqB,GACrB,wBAAwB,GACxB,gCAAgC,GAChC,4BAA4B;IAEhC,QAAQ,CAAC,SAAS;IARpB,YACW,IAAI,EACT,yBAAyB,GACzB,qBAAqB,GACrB,wBAAwB,GACxB,gCAAgC,GAChC,4BAA4B,EAChC,OAAO,EAAE,MAAM,EACN,SAAS,UAAQ,EAI3B;CACF;AAED,KAAK,SAAS,GAAG,OAAO,KAAK,CAAC;AA+J9B,qBAAa,eAAe;IAMxB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAL5B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiC;IACvD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IAEnC,YACmB,SAAS,GAAE,SAAiB,EAC7C,OAAO,GAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAO,EAKzD;YAEa,OAAO;IAqDf,UAAU,CAAC,IAAI,EAAE,kBAAkB,GAAG,KAAK,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAY5E;IAEK,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAKlD;IAEK,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAIpD;IAEK,cAAc,CAClB,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAiBtD;CACF"}
|