@refkit/provider-met 0.2.2 → 0.2.4

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/index.js CHANGED
@@ -4,7 +4,8 @@ import {
4
4
  referenceId,
5
5
  setIfBoolean,
6
6
  setIfInt,
7
- setIfString
7
+ setIfString,
8
+ offsetForPage
8
9
  } from "@refkit/core";
9
10
  var BASE = "https://collectionapi.metmuseum.org/public/collection/v1";
10
11
  function toReference(o) {
@@ -35,8 +36,7 @@ function met(config = {}) {
35
36
  return defineProvider({
36
37
  id: "met",
37
38
  modalities: ["image"],
38
- queryFeatures: ["keyword"],
39
- capabilities: { controls: [] },
39
+ capabilities: { controls: ["page"] },
40
40
  async search(q, ctx) {
41
41
  const searchUrl = new URL(`${BASE}/search`);
42
42
  searchUrl.searchParams.set("q", q.text);
@@ -57,7 +57,8 @@ function met(config = {}) {
57
57
  const { objectIDs } = await res.json();
58
58
  if (!objectIDs || objectIDs.length === 0) return [];
59
59
  const n = Math.min(config.maxObjects ?? q.limit ?? 12, 30);
60
- const objects = await Promise.all(objectIDs.slice(0, n).map(async (id) => {
60
+ const from = offsetForPage(q.controls?.page, n) ?? 0;
61
+ const objects = await Promise.all(objectIDs.slice(from, from + n).map(async (id) => {
61
62
  try {
62
63
  const r = await ctx.fetch(`${BASE}/objects/${id}`, { signal: ctx.signal });
63
64
  if (!r.ok) return null;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {\n defineProvider, referenceId,\n setIfBoolean, setIfInt, setIfString,\n type Reference, type RightsRecord, type NormalizedQuery, type ProviderContext,\n} from '@refkit/core'\n\nexport interface MetConfig {\n /** Max objects fetched per search. The Met search returns only IDs, so each\n * result costs one extra call — this bounds that N+1 fan-out. Default 12. */\n maxObjects?: number\n}\n\nexport interface MetSearchOptions {\n isHighlight?: boolean\n title?: boolean\n tags?: boolean\n departmentId?: number\n isOnView?: boolean\n artistOrCulture?: boolean\n medium?: string\n geoLocation?: string\n dateBegin?: number\n dateEnd?: number\n}\n\nconst BASE = 'https://collectionapi.metmuseum.org/public/collection/v1'\n\ninterface MetSearchResponse { total: number; objectIDs: number[] | null }\ninterface MetObject {\n objectID: number\n isPublicDomain: boolean\n primaryImage: string\n primaryImageSmall: string\n title: string\n artistDisplayName: string\n objectURL: string\n objectName: string\n medium: string\n}\n\nfunction toReference(o: MetObject): Reference | null {\n // The Met releases open-access (public-domain) images under CC0. Copyrighted\n // works return an empty primaryImage — nothing usable to surface.\n if (!o.isPublicDomain) return null\n const image = o.primaryImage || o.primaryImageSmall\n if (!image) return null\n const rights: RightsRecord = {\n license: 'CC0-1.0',\n author: o.artistDisplayName || undefined,\n rehostPolicy: 'cache-allowed',\n raw: { sourceTerms: 'https://www.metmuseum.org/information/terms-and-conditions', sourceUrl: o.objectURL },\n }\n return {\n id: referenceId('met', o.objectURL),\n modality: 'image',\n title: o.title || undefined,\n source: { providerId: 'met', sourceUrl: o.objectURL },\n canonicalUrl: o.objectURL,\n rights,\n verifiedAt: new Date().toISOString(),\n ...(o.primaryImageSmall ? { thumbnail: { url: o.primaryImageSmall } } : {}),\n preview: { url: image, mediaType: 'image/jpeg' },\n relevance: 0,\n raw: o,\n }\n}\n\nexport function met(config: MetConfig = {}) {\n return defineProvider({\n id: 'met',\n modalities: ['image'],\n queryFeatures: ['keyword'],\n capabilities: { controls: [] },\n async search(q: NormalizedQuery, ctx: ProviderContext): Promise<Reference[]> {\n const searchUrl = new URL(`${BASE}/search`)\n searchUrl.searchParams.set('q', q.text)\n searchUrl.searchParams.set('hasImages', 'true')\n const opts = q.providerOptions as MetSearchOptions | undefined\n setIfBoolean(searchUrl, 'isHighlight', opts?.isHighlight)\n setIfBoolean(searchUrl, 'title', opts?.title)\n setIfBoolean(searchUrl, 'tags', opts?.tags)\n setIfInt(searchUrl, 'departmentId', opts?.departmentId)\n setIfBoolean(searchUrl, 'isOnView', opts?.isOnView)\n setIfBoolean(searchUrl, 'artistOrCulture', opts?.artistOrCulture)\n setIfString(searchUrl, 'medium', opts?.medium)\n setIfString(searchUrl, 'geoLocation', opts?.geoLocation)\n setIfInt(searchUrl, 'dateBegin', opts?.dateBegin)\n setIfInt(searchUrl, 'dateEnd', opts?.dateEnd)\n const res = await ctx.fetch(searchUrl.toString(), { signal: ctx.signal })\n if (!res.ok) throw new Error(`met search failed: ${res.status}`)\n const { objectIDs } = (await res.json()) as MetSearchResponse\n if (!objectIDs || objectIDs.length === 0) return []\n const n = Math.min(config.maxObjects ?? q.limit ?? 12, 30)\n const objects = await Promise.all(objectIDs.slice(0, n).map(async (id) => {\n try {\n const r = await ctx.fetch(`${BASE}/objects/${id}`, { signal: ctx.signal })\n if (!r.ok) return null\n return (await r.json()) as MetObject\n } catch {\n return null // one bad object fetch must not drop the whole batch\n }\n }))\n return objects\n .map((o) => (o ? toReference(o) : null))\n .filter((r): r is Reference => r !== null)\n },\n })\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {\n defineProvider, referenceId,\n setIfBoolean, setIfInt, setIfString,\n type Reference, type RightsRecord, type NormalizedQuery, type ProviderContext,\n offsetForPage,\n} from '@refkit/core'\n\nexport interface MetConfig {\n /** Max objects fetched per search. The Met search returns only IDs, so each\n * result costs one extra call — this bounds that N+1 fan-out. Default 12. */\n maxObjects?: number\n}\n\nexport interface MetSearchOptions {\n isHighlight?: boolean\n title?: boolean\n tags?: boolean\n departmentId?: number\n isOnView?: boolean\n artistOrCulture?: boolean\n medium?: string\n geoLocation?: string\n dateBegin?: number\n dateEnd?: number\n}\n\nconst BASE = 'https://collectionapi.metmuseum.org/public/collection/v1'\n\ninterface MetSearchResponse { total: number; objectIDs: number[] | null }\ninterface MetObject {\n objectID: number\n isPublicDomain: boolean\n primaryImage: string\n primaryImageSmall: string\n title: string\n artistDisplayName: string\n objectURL: string\n objectName: string\n medium: string\n}\n\nfunction toReference(o: MetObject): Reference | null {\n // The Met releases open-access (public-domain) images under CC0. Copyrighted\n // works return an empty primaryImage — nothing usable to surface.\n if (!o.isPublicDomain) return null\n const image = o.primaryImage || o.primaryImageSmall\n if (!image) return null\n const rights: RightsRecord = {\n license: 'CC0-1.0',\n author: o.artistDisplayName || undefined,\n rehostPolicy: 'cache-allowed',\n raw: { sourceTerms: 'https://www.metmuseum.org/information/terms-and-conditions', sourceUrl: o.objectURL },\n }\n return {\n id: referenceId('met', o.objectURL),\n modality: 'image',\n title: o.title || undefined,\n source: { providerId: 'met', sourceUrl: o.objectURL },\n canonicalUrl: o.objectURL,\n rights,\n verifiedAt: new Date().toISOString(),\n ...(o.primaryImageSmall ? { thumbnail: { url: o.primaryImageSmall } } : {}),\n preview: { url: image, mediaType: 'image/jpeg' },\n relevance: 0,\n raw: o,\n }\n}\n\nexport function met(config: MetConfig = {}) {\n return defineProvider({\n id: 'met',\n modalities: ['image'],\n capabilities: { controls: ['page'] },\n async search(q: NormalizedQuery, ctx: ProviderContext): Promise<Reference[]> {\n const searchUrl = new URL(`${BASE}/search`)\n searchUrl.searchParams.set('q', q.text)\n searchUrl.searchParams.set('hasImages', 'true')\n const opts = q.providerOptions as MetSearchOptions | undefined\n setIfBoolean(searchUrl, 'isHighlight', opts?.isHighlight)\n setIfBoolean(searchUrl, 'title', opts?.title)\n setIfBoolean(searchUrl, 'tags', opts?.tags)\n setIfInt(searchUrl, 'departmentId', opts?.departmentId)\n setIfBoolean(searchUrl, 'isOnView', opts?.isOnView)\n setIfBoolean(searchUrl, 'artistOrCulture', opts?.artistOrCulture)\n setIfString(searchUrl, 'medium', opts?.medium)\n setIfString(searchUrl, 'geoLocation', opts?.geoLocation)\n setIfInt(searchUrl, 'dateBegin', opts?.dateBegin)\n setIfInt(searchUrl, 'dateEnd', opts?.dateEnd)\n const res = await ctx.fetch(searchUrl.toString(), { signal: ctx.signal })\n if (!res.ok) throw new Error(`met search failed: ${res.status}`)\n const { objectIDs } = (await res.json()) as MetSearchResponse\n if (!objectIDs || objectIDs.length === 0) return []\n const n = Math.min(config.maxObjects ?? q.limit ?? 12, 30)\n // the search endpoint returns every matching id — page = a window over that list\n const from = offsetForPage(q.controls?.page, n) ?? 0\n const objects = await Promise.all(objectIDs.slice(from, from + n).map(async (id) => {\n try {\n const r = await ctx.fetch(`${BASE}/objects/${id}`, { signal: ctx.signal })\n if (!r.ok) return null\n return (await r.json()) as MetObject\n } catch {\n return null // one bad object fetch must not drop the whole batch\n }\n }))\n return objects\n .map((o) => (o ? toReference(o) : null))\n .filter((r): r is Reference => r !== null)\n },\n })\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,9 +1,16 @@
1
1
  {
2
2
  "name": "@refkit/provider-met",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "The Metropolitan Museum of Art provider satellite for refkit.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/refkitjs/refkit.git",
10
+ "directory": "packages/provider-met"
11
+ },
12
+ "homepage": "https://github.com/refkitjs/refkit/tree/main/packages/provider-met#readme",
13
+ "bugs": "https://github.com/refkitjs/refkit/issues",
7
14
  "keywords": [
8
15
  "refkit",
9
16
  "reference-retrieval",
@@ -26,14 +33,14 @@
26
33
  }
27
34
  },
28
35
  "dependencies": {
29
- "@refkit/core": "0.6.0"
36
+ "@refkit/core": "0.7.0"
30
37
  },
31
38
  "files": [
32
39
  "dist",
33
40
  "LICENSE"
34
41
  ],
35
42
  "devDependencies": {
36
- "@refkit/provider-testkit": "0.0.1"
43
+ "@refkit/provider-testkit": "0.0.3"
37
44
  },
38
45
  "scripts": {
39
46
  "typecheck": "tsc --noEmit",