@vedangiitb/qwintly-core 1.4.6 → 1.4.7
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.
|
@@ -49,7 +49,7 @@ export async function searchUnsplashImage(imgQuery) {
|
|
|
49
49
|
return cached;
|
|
50
50
|
}
|
|
51
51
|
const params = new URLSearchParams({
|
|
52
|
-
imgQuery,
|
|
52
|
+
query: imgQuery,
|
|
53
53
|
per_page: "10",
|
|
54
54
|
});
|
|
55
55
|
const response = await fetchWithTimeout(`${cfg.url}/search/photos?${params.toString()}`, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unsplash.service.js","sourceRoot":"","sources":["../../src/image/unsplash.service.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAoB5B,IAAI,cAAc,GAA0B,IAAI,CAAC;AAEjD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAyB,CAAC;AAE/C,KAAK,UAAU,gBAAgB,CAC7B,GAAW,EACX,UAAuB,EAAE;IAEzB,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,CAAC;IACtD,IAAI,CAAC;QACH,OAAO,MAAM,KAAK,CAAC,GAAG,EAAE;YACtB,GAAG,OAAO;YACV,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;IACL,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,EAAE,CAAC,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,MAAkD;IAElD,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC7C,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAEzD,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QACvB,cAAc,GAAG,IAAI,CAAC;QACtB,OAAO;IACT,CAAC;IAED,cAAc,GAAG;QACf,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QAC5B,SAAS;KACV,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,QAAgB;IAClC,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACpE,CAAC;AAED,SAAS,UAAU,CAAC,KAAU;IAC5B,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,KAAK,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC;IAElC,IAAI,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QAC/B,KAAK,IAAI,EAAE,CAAC;IACd,CAAC;IAED,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;IAE/C,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,QAAgB;IAEhB,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,QAAQ,CAAC,CAAC;IAC7C,MAAM,GAAG,GAAG,cAAc,CAAC;IAC3B,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAErD,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAEtC,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAEnC,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;QACjC,QAAQ;
|
|
1
|
+
{"version":3,"file":"unsplash.service.js","sourceRoot":"","sources":["../../src/image/unsplash.service.ts"],"names":[],"mappings":"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","sourcesContent":["import crypto from \"crypto\";\r\nimport { BuilderElement } from \"../types/elements.js\";\r\n\r\nexport interface ResolvedImage {\r\n id: string;\r\n alt: string;\r\n imageUrl: string;\r\n thumbUrl: string;\r\n photographer: string;\r\n photographerUrl: string;\r\n unsplashUrl: string;\r\n width: number;\r\n height: number;\r\n}\r\n\r\ntype UnsplashConfig = {\r\n url: string;\r\n accessKey: string;\r\n};\r\n\r\nlet unsplashConfig: UnsplashConfig | null = null;\r\n\r\nconst cache = new Map<string, ResolvedImage>();\r\n\r\nasync function fetchWithTimeout(\r\n url: string,\r\n options: RequestInit = {},\r\n): Promise<Response> {\r\n const controller = new AbortController();\r\n const id = setTimeout(() => controller.abort(), 5000);\r\n try {\r\n return await fetch(url, {\r\n ...options,\r\n signal: controller.signal,\r\n });\r\n } finally {\r\n clearTimeout(id);\r\n }\r\n}\r\n\r\nexport function initUnsplash(\r\n config: Partial<UnsplashConfig> | null | undefined,\r\n) {\r\n const url = String(config?.url ?? \"\").trim();\r\n const accessKey = String(config?.accessKey ?? \"\").trim();\r\n\r\n if (!url || !accessKey) {\r\n unsplashConfig = null;\r\n return;\r\n }\r\n\r\n unsplashConfig = {\r\n url: url.replace(/\\/+$/, \"\"),\r\n accessKey,\r\n };\r\n}\r\n\r\nfunction hashIntent(imgQuery: string) {\r\n return crypto.createHash(\"sha256\").update(imgQuery).digest(\"hex\");\r\n}\r\n\r\nfunction scoreImage(photo: any) {\r\n let score = 0;\r\n\r\n score += (photo.likes || 0) * 0.3;\r\n\r\n if (photo.width > photo.height) {\r\n score += 50;\r\n }\r\n\r\n score += (photo.user.total_photos || 0) * 0.05;\r\n\r\n return score;\r\n}\r\n\r\nexport async function searchUnsplashImage(\r\n imgQuery: string,\r\n): Promise<ResolvedImage | null> {\r\n console.log(\"searchUnsplashImage\", imgQuery);\r\n const cfg = unsplashConfig;\r\n if (!cfg) throw new Error(\"Unsplash not configured\");\r\n\r\n const cacheKey = hashIntent(imgQuery);\r\n\r\n const cached = cache.get(cacheKey);\r\n\r\n if (cached) {\r\n return cached;\r\n }\r\n\r\n const params = new URLSearchParams({\r\n query: imgQuery,\r\n per_page: \"10\",\r\n });\r\n\r\n const response = await fetchWithTimeout(\r\n `${cfg.url}/search/photos?${params.toString()}`,\r\n {\r\n headers: {\r\n Authorization: `Client-ID ${cfg.accessKey}`,\r\n },\r\n },\r\n );\r\n\r\n if (!response.ok) {\r\n throw new Error(`Unsplash API failed: ${response.status}`);\r\n }\r\n\r\n const data = await response.json();\r\n\r\n const photos = data.results;\r\n\r\n if (!photos.length) {\r\n return null;\r\n }\r\n\r\n const ranked = [...photos].sort((a, b) => {\r\n return scoreImage(b) - scoreImage(a);\r\n });\r\n\r\n const top3 = ranked.slice(0, 3);\r\n\r\n const selected = top3[Math.floor(Math.random() * top3.length)];\r\n\r\n // IMPORTANT:\r\n // Required by Unsplash API terms\r\n // Tracks image download usage\r\n if (selected.links.download_location) {\r\n await fetchWithTimeout(selected.links.download_location, {\r\n headers: {\r\n Authorization: `Client-ID ${cfg.accessKey}`,\r\n },\r\n });\r\n }\r\n\r\n const resolved: ResolvedImage = {\r\n id: selected.id,\r\n alt: imgQuery,\r\n\r\n imageUrl: selected.urls.regular,\r\n thumbUrl: selected.urls.small,\r\n\r\n photographer: selected.user.name,\r\n photographerUrl: selected.user.links.html,\r\n\r\n unsplashUrl: selected.links.html,\r\n\r\n width: selected.width,\r\n height: selected.height,\r\n };\r\n\r\n cache.set(cacheKey, resolved);\r\n\r\n return resolved;\r\n}\r\n\r\nexport const resolveUnsplashImageForElement = async (\r\n el: BuilderElement,\r\n alt: string,\r\n): Promise<void> => {\r\n if (!unsplashConfig) return;\r\n const query = String(alt ?? \"\").trim();\r\n if (!query) return;\r\n if (el.props?.src) {\r\n console.log(\"src already exists, skipping\");\r\n return;\r\n }\r\n try {\r\n const resolved = await searchUnsplashImage(query);\r\n if (!resolved?.imageUrl) {\r\n console.log(resolved);\r\n return;\r\n }\r\n\r\n const anyEl = el as any;\r\n if (!anyEl.props || typeof anyEl.props !== \"object\") anyEl.props = {};\r\n anyEl.props.src = resolved.imageUrl;\r\n anyEl.props.alt = query;\r\n } catch (error) {\r\n console.error(error);\r\n // Ignore Unsplash lookup errors and still allow prop updates.\r\n }\r\n};\r\n\r\nexport const resolveUnsplashImagesDeep = async (\r\n el: BuilderElement,\r\n): Promise<void> => {\r\n const anyEl = el as any;\r\n\r\n if (anyEl?.type === \"image\") {\r\n const alt = String(anyEl?.props?.alt ?? \"\").trim();\r\n await resolveUnsplashImageForElement(el, alt);\r\n }\r\n\r\n const kids = anyEl?.children;\r\n if (Array.isArray(kids)) {\r\n for (const child of kids) {\r\n await resolveUnsplashImagesDeep(child);\r\n }\r\n }\r\n};\r\n"]}
|
|
@@ -9,6 +9,8 @@ test("resolveUnsplashImagesDeep: resolves and inserts src for images", async ()
|
|
|
9
9
|
const urlString = String(url);
|
|
10
10
|
calls.push(urlString);
|
|
11
11
|
if (urlString.includes("/search/photos")) {
|
|
12
|
+
const urlObj = new URL(urlString);
|
|
13
|
+
assert.equal(urlObj.searchParams.get("query"), "rustic sourdough bread");
|
|
12
14
|
return {
|
|
13
15
|
ok: true,
|
|
14
16
|
status: 200,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unsplash.service.test.js","sourceRoot":"","sources":["../../src/tests/unsplash.service.test.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from \"node:assert/strict\";\nimport test from \"node:test\";\nimport { initUnsplash, resolveUnsplashImagesDeep } from \"../image/unsplash.service.js\";\n\ntest(\"resolveUnsplashImagesDeep: resolves and inserts src for images\", async () => {\n const originalFetch = globalThis.fetch;\n \n // Setup fetch mock\n const calls: string[] = [];\n globalThis.fetch = async (url: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const urlString = String(url);\n calls.push(urlString);\n \n if (urlString.includes(\"/search/photos\")) {\n return {\n ok: true,\n status: 200,\n json: async () => ({\n results: [\n {\n id: \"photo_1\",\n likes: 100,\n width: 800,\n height: 600,\n user: {\n total_photos: 10,\n name: \"Photographer Name\",\n links: {\n html: \"https://unsplash.com/@photographer\"\n }\n },\n links: {\n download_location: \"https://api.unsplash.com/photos/photo_1/download\",\n html: \"https://unsplash.com/photos/photo_1\"\n },\n urls: {\n regular: \"https://images.unsplash.com/photo_1_regular\",\n small: \"https://images.unsplash.com/photo_1_small\"\n }\n }\n ]\n })\n } as Response;\n }\n \n if (urlString.includes(\"/download\")) {\n return {\n ok: true,\n status: 200,\n json: async () => ({})\n } as Response;\n }\n \n return {\n ok: false,\n status: 404\n } as Response;\n };\n\n try {\n initUnsplash({\n url: \"https://api.unsplash.com\",\n accessKey: \"fake_key\",\n });\n\n const element = {\n type: \"div\",\n children: [\n {\n type: \"image\",\n props: {\n alt: \"rustic sourdough bread\"\n },\n className: \"w-full h-64\"\n },\n {\n type: \"text\",\n props: {\n text: \"Artisanal Breads, Baked Fresh Daily\"\n }\n }\n ]\n };\n\n // Before calling, image prop has no src\n const imageElement = element.children[0] as any;\n assert.ok(!imageElement.props.src);\n\n // Call and await resolution\n await resolveUnsplashImagesDeep(element as any);\n\n // After calling, image prop must have the resolved src\n assert.equal(imageElement.props.src, \"https://images.unsplash.com/photo_1_regular\");\n assert.equal(imageElement.props.alt, \"rustic sourdough bread\");\n\n // Make sure we have fetch calls\n assert.ok(calls.some(c => c.includes(\"/search/photos\")));\n assert.ok(calls.some(c => c.includes(\"/download\")));\n\n } finally {\n globalThis.fetch = originalFetch;\n initUnsplash(null);\n }\n});\n"]}
|
|
1
|
+
{"version":3,"file":"unsplash.service.test.js","sourceRoot":"","sources":["../../src/tests/unsplash.service.test.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from \"node:assert/strict\";\nimport test from \"node:test\";\nimport { initUnsplash, resolveUnsplashImagesDeep } from \"../image/unsplash.service.js\";\n\ntest(\"resolveUnsplashImagesDeep: resolves and inserts src for images\", async () => {\n const originalFetch = globalThis.fetch;\n \n // Setup fetch mock\n const calls: string[] = [];\n globalThis.fetch = async (url: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const urlString = String(url);\n calls.push(urlString);\n \n if (urlString.includes(\"/search/photos\")) {\n const urlObj = new URL(urlString);\n assert.equal(urlObj.searchParams.get(\"query\"), \"rustic sourdough bread\");\n return {\n ok: true,\n status: 200,\n json: async () => ({\n results: [\n {\n id: \"photo_1\",\n likes: 100,\n width: 800,\n height: 600,\n user: {\n total_photos: 10,\n name: \"Photographer Name\",\n links: {\n html: \"https://unsplash.com/@photographer\"\n }\n },\n links: {\n download_location: \"https://api.unsplash.com/photos/photo_1/download\",\n html: \"https://unsplash.com/photos/photo_1\"\n },\n urls: {\n regular: \"https://images.unsplash.com/photo_1_regular\",\n small: \"https://images.unsplash.com/photo_1_small\"\n }\n }\n ]\n })\n } as Response;\n }\n \n if (urlString.includes(\"/download\")) {\n return {\n ok: true,\n status: 200,\n json: async () => ({})\n } as Response;\n }\n \n return {\n ok: false,\n status: 404\n } as Response;\n };\n\n try {\n initUnsplash({\n url: \"https://api.unsplash.com\",\n accessKey: \"fake_key\",\n });\n\n const element = {\n type: \"div\",\n children: [\n {\n type: \"image\",\n props: {\n alt: \"rustic sourdough bread\"\n },\n className: \"w-full h-64\"\n },\n {\n type: \"text\",\n props: {\n text: \"Artisanal Breads, Baked Fresh Daily\"\n }\n }\n ]\n };\n\n // Before calling, image prop has no src\n const imageElement = element.children[0] as any;\n assert.ok(!imageElement.props.src);\n\n // Call and await resolution\n await resolveUnsplashImagesDeep(element as any);\n\n // After calling, image prop must have the resolved src\n assert.equal(imageElement.props.src, \"https://images.unsplash.com/photo_1_regular\");\n assert.equal(imageElement.props.alt, \"rustic sourdough bread\");\n\n // Make sure we have fetch calls\n assert.ok(calls.some(c => c.includes(\"/search/photos\")));\n assert.ok(calls.some(c => c.includes(\"/download\")));\n\n } finally {\n globalThis.fetch = originalFetch;\n initUnsplash(null);\n }\n});\n"]}
|