@jhb.software/payload-alt-text-plugin 0.3.1 → 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.
Files changed (48) hide show
  1. package/README.md +86 -0
  2. package/dist/components/AltTextHealthWidget.d.ts +2 -0
  3. package/dist/components/AltTextHealthWidget.js +199 -0
  4. package/dist/components/AltTextHealthWidget.js.map +1 -0
  5. package/dist/components/BulkGenerateAltTextsButton.js +1 -1
  6. package/dist/components/BulkGenerateAltTextsButton.js.map +1 -1
  7. package/dist/components/GenerateAltTextButton.js +1 -1
  8. package/dist/components/GenerateAltTextButton.js.map +1 -1
  9. package/dist/endpoints/altTextHealth.d.ts +3 -0
  10. package/dist/endpoints/altTextHealth.js +30 -0
  11. package/dist/endpoints/altTextHealth.js.map +1 -0
  12. package/dist/endpoints/bulkGenerateAltTexts.d.ts +2 -1
  13. package/dist/endpoints/bulkGenerateAltTexts.js +89 -73
  14. package/dist/endpoints/bulkGenerateAltTexts.js.map +1 -1
  15. package/dist/endpoints/generateAltText.d.ts +8 -2
  16. package/dist/endpoints/generateAltText.js +112 -75
  17. package/dist/endpoints/generateAltText.js.map +1 -1
  18. package/dist/exports/server.d.ts +3 -0
  19. package/dist/exports/server.js +4 -0
  20. package/dist/exports/server.js.map +1 -0
  21. package/dist/hooks/revalidateAltTextHealth.d.ts +3 -0
  22. package/dist/hooks/revalidateAltTextHealth.js +32 -0
  23. package/dist/hooks/revalidateAltTextHealth.js.map +1 -0
  24. package/dist/plugin.js +86 -6
  25. package/dist/plugin.js.map +1 -1
  26. package/dist/translations/de.js +11 -1
  27. package/dist/translations/de.js.map +1 -1
  28. package/dist/translations/en.js +11 -1
  29. package/dist/translations/en.js.map +1 -1
  30. package/dist/translations/translation-schema.json +44 -26
  31. package/dist/types/AltTextPluginConfig.d.ts +23 -1
  32. package/dist/types/AltTextPluginConfig.js.map +1 -1
  33. package/dist/utilities/altTextHealth.d.ts +37 -0
  34. package/dist/utilities/altTextHealth.js +150 -0
  35. package/dist/utilities/altTextHealth.js.map +1 -0
  36. package/dist/utilities/altTextHealthCache.d.ts +11 -0
  37. package/dist/utilities/altTextHealthCache.js +8 -0
  38. package/dist/utilities/altTextHealthCache.js.map +1 -0
  39. package/dist/utilities/altTextHealthWidgetDisplay.d.ts +6 -0
  40. package/dist/utilities/altTextHealthWidgetDisplay.js +11 -0
  41. package/dist/utilities/altTextHealthWidgetDisplay.js.map +1 -0
  42. package/dist/utilities/getCollectionLabel.d.ts +2 -0
  43. package/dist/utilities/getCollectionLabel.js +17 -0
  44. package/dist/utilities/getCollectionLabel.js.map +1 -0
  45. package/dist/utilities/summarizeCollection.d.ts +17 -0
  46. package/dist/utilities/summarizeCollection.js +62 -0
  47. package/dist/utilities/summarizeCollection.js.map +1 -0
  48. package/package.json +59 -38
@@ -1,90 +1,106 @@
1
1
  import pMap from 'p-map';
2
- import { z } from 'zod';
2
+ import { z, ZodError } from 'zod';
3
3
  import { localesFromConfig } from '../utilities/localesFromConfig.js';
4
4
  /**
5
5
  * Generates and updates alt text for multiple images in all locales.
6
- */ export const bulkGenerateAltTextsEndpoint = async (req)=>{
7
- try {
8
- if (!req.user) {
9
- return Response.json({
10
- error: 'Unauthorized'
11
- }, {
12
- status: 401
6
+ */ export const bulkGenerateAltTextsEndpoint = (access)=>async (req)=>{
7
+ try {
8
+ if (!await access({
9
+ req
10
+ })) {
11
+ return Response.json({
12
+ error: 'Unauthorized'
13
+ }, {
14
+ status: 401
15
+ });
16
+ }
17
+ const data = 'json' in req && typeof req.json === 'function' ? await req.json() : null;
18
+ const schema = z.object({
19
+ collection: z.string(),
20
+ ids: z.array(z.union([
21
+ z.string(),
22
+ z.number()
23
+ ]))
13
24
  });
14
- }
15
- const data = 'json' in req && typeof req.json === 'function' ? await req.json() : null;
16
- const schema = z.object({
17
- collection: z.string(),
18
- ids: z.array(z.string())
19
- });
20
- const { collection, ids } = schema.parse(data);
21
- let updatedDocs = 0;
22
- const erroredDocs = [];
23
- // Get plugin config from payload config
24
- const pluginConfig = req.payload.config.custom?.altTextPluginConfig;
25
- if (!pluginConfig) {
26
- return Response.json({
27
- error: 'Plugin config not found'
25
+ const { collection, ids } = schema.parse(data);
26
+ let updatedDocs = 0;
27
+ const erroredDocs = [];
28
+ // Get plugin config from payload config
29
+ const pluginConfig = req.payload.config.custom?.altTextPluginConfig;
30
+ if (!pluginConfig) {
31
+ return Response.json({
32
+ error: 'Plugin config not found'
33
+ }, {
34
+ status: 500
35
+ });
36
+ }
37
+ if (!pluginConfig.resolver) {
38
+ return Response.json({
39
+ error: 'No alt text resolver configured'
40
+ }, {
41
+ status: 500
42
+ });
43
+ }
44
+ const concurrency = pluginConfig.maxBulkGenerateConcurrency;
45
+ // determine target locales based on config
46
+ const locales = localesFromConfig(req.payload.config);
47
+ const targetLocales = locales ?? [
48
+ pluginConfig.locale
49
+ ];
50
+ if (!targetLocales) {
51
+ return Response.json({
52
+ error: 'Could not determine target locales for alt text generation. Please check your plugin configuration.'
53
+ }, {
54
+ status: 500
55
+ });
56
+ }
57
+ await pMap(ids, async (id)=>{
58
+ try {
59
+ await generateAndUpdateAltText({
60
+ id,
61
+ collection,
62
+ locales: targetLocales,
63
+ payload: req.payload,
64
+ pluginConfig,
65
+ req
66
+ });
67
+ updatedDocs++;
68
+ console.log(`${updatedDocs}/${ids.length} updated (${Math.round(updatedDocs / ids.length * 100)}%)`);
69
+ } catch (error) {
70
+ console.error(`Error generating alt text for ${id}:`, error);
71
+ erroredDocs.push(id);
72
+ }
28
73
  }, {
29
- status: 500
74
+ concurrency
30
75
  });
31
- }
32
- if (!pluginConfig.resolver) {
76
+ if (erroredDocs.length > 0) {
77
+ console.error(`Failed for: ${erroredDocs.join(', ')}`);
78
+ }
33
79
  return Response.json({
34
- error: 'No alt text resolver configured'
35
- }, {
36
- status: 500
80
+ erroredDocs,
81
+ totalDocs: ids.length,
82
+ updatedDocs
37
83
  });
38
- }
39
- const concurrency = pluginConfig.maxBulkGenerateConcurrency;
40
- // determine target locales based on config
41
- const locales = localesFromConfig(req.payload.config);
42
- const targetLocales = locales ?? [
43
- pluginConfig.locale
44
- ];
45
- if (!targetLocales) {
84
+ } catch (error) {
85
+ if (error instanceof ZodError) {
86
+ return Response.json({
87
+ details: error.issues.map((e)=>({
88
+ message: e.message,
89
+ path: e.path.join('.')
90
+ })),
91
+ error: 'Validation failed'
92
+ }, {
93
+ status: 400
94
+ });
95
+ }
96
+ console.error('Error in bulk generation:', error);
46
97
  return Response.json({
47
- error: 'Could not determine target locales for alt text generation. Please check your plugin configuration.'
98
+ error: `Error generating alt text: ${error instanceof Error ? error.message : 'Unknown error'}`
48
99
  }, {
49
100
  status: 500
50
101
  });
51
102
  }
52
- await pMap(ids, async (id)=>{
53
- try {
54
- await generateAndUpdateAltText({
55
- id,
56
- collection,
57
- locales: targetLocales,
58
- payload: req.payload,
59
- pluginConfig,
60
- req
61
- });
62
- updatedDocs++;
63
- console.log(`${updatedDocs}/${ids.length} updated (${Math.round(updatedDocs / ids.length * 100)}%)`);
64
- } catch (error) {
65
- console.error(`Error generating alt text for ${id}:`, error);
66
- erroredDocs.push(id);
67
- }
68
- }, {
69
- concurrency
70
- });
71
- if (erroredDocs.length > 0) {
72
- console.error(`Failed for: ${erroredDocs.join(', ')}`);
73
- }
74
- return Response.json({
75
- erroredDocs,
76
- totalDocs: ids.length,
77
- updatedDocs
78
- });
79
- } catch (error) {
80
- console.error('Error in bulk generation:', error);
81
- return Response.json({
82
- error: `Error generating alt text: ${error instanceof Error ? error.message : 'Unknown error'}`
83
- }, {
84
- status: 500
85
- });
86
- }
87
- };
103
+ };
88
104
  async function generateAndUpdateAltText({ id, collection, locales, payload, pluginConfig, req }) {
89
105
  const imageDoc = await payload.findByID({
90
106
  id,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/endpoints/bulkGenerateAltTexts.ts"],"sourcesContent":["import type { BasePayload, CollectionSlug, PayloadHandler, PayloadRequest } from 'payload'\n\nimport pMap from 'p-map'\nimport { z } from 'zod'\n\nimport type { AltTextPluginConfig } from '../types/AltTextPluginConfig.js'\n\nimport { localesFromConfig } from '../utilities/localesFromConfig.js'\n\n/**\n * Generates and updates alt text for multiple images in all locales.\n */\nexport const bulkGenerateAltTextsEndpoint: PayloadHandler = async (req: PayloadRequest) => {\n try {\n if (!req.user) {\n return Response.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const data = 'json' in req && typeof req.json === 'function' ? await req.json() : null\n\n const schema = z.object({\n collection: z.string(),\n ids: z.array(z.string()),\n })\n\n const { collection, ids } = schema.parse(data)\n\n let updatedDocs = 0\n const erroredDocs: string[] = []\n\n // Get plugin config from payload config\n const pluginConfig = req.payload.config.custom?.altTextPluginConfig as\n | AltTextPluginConfig\n | undefined\n\n if (!pluginConfig) {\n return Response.json({ error: 'Plugin config not found' }, { status: 500 })\n }\n\n if (!pluginConfig.resolver) {\n return Response.json({ error: 'No alt text resolver configured' }, { status: 500 })\n }\n\n const concurrency = pluginConfig.maxBulkGenerateConcurrency\n\n // determine target locales based on config\n const locales = localesFromConfig(req.payload.config)\n const targetLocales = locales ?? [pluginConfig.locale!]\n if (!targetLocales) {\n return Response.json(\n {\n error:\n 'Could not determine target locales for alt text generation. Please check your plugin configuration.',\n },\n { status: 500 },\n )\n }\n\n await pMap(\n ids,\n async (id) => {\n try {\n await generateAndUpdateAltText({\n id,\n collection,\n locales: targetLocales,\n payload: req.payload,\n pluginConfig,\n req,\n })\n updatedDocs++\n console.log(\n `${updatedDocs}/${ids.length} updated (${Math.round((updatedDocs / ids.length) * 100)}%)`,\n )\n } catch (error) {\n console.error(`Error generating alt text for ${id}:`, error)\n erroredDocs.push(id)\n }\n },\n { concurrency },\n )\n\n if (erroredDocs.length > 0) {\n console.error(`Failed for: ${erroredDocs.join(', ')}`)\n }\n\n return Response.json({\n erroredDocs,\n totalDocs: ids.length,\n updatedDocs,\n })\n } catch (error) {\n console.error('Error in bulk generation:', error)\n return Response.json(\n {\n error: `Error generating alt text: ${error instanceof Error ? error.message : 'Unknown error'}`,\n },\n { status: 500 },\n )\n }\n}\n\nasync function generateAndUpdateAltText({\n id,\n collection,\n locales,\n payload,\n pluginConfig,\n req,\n}: {\n collection: CollectionSlug\n id: string\n locales: string[]\n payload: BasePayload\n pluginConfig: AltTextPluginConfig\n req: PayloadRequest\n}) {\n const imageDoc = await payload.findByID({\n id,\n collection,\n depth: 0,\n })\n\n if (!imageDoc) {\n throw new Error('Image not found')\n }\n\n const imageThumbnailUrl = pluginConfig.getImageThumbnail(imageDoc)\n\n const result = await pluginConfig.resolver.resolveBulk({\n filename:\n 'filename' in imageDoc && typeof imageDoc.filename === 'string'\n ? imageDoc.filename\n : undefined,\n imageThumbnailUrl,\n locales,\n req,\n })\n\n if (!result.success) {\n throw new Error(result.error || 'Failed to generate alt text')\n }\n\n for (const locale of locales) {\n const localeResult = result.results[locale]\n if (localeResult) {\n await payload.update({\n id,\n collection,\n data: {\n alt: localeResult.altText,\n keywords: localeResult.keywords,\n },\n locale,\n })\n }\n }\n}\n"],"names":["pMap","z","localesFromConfig","bulkGenerateAltTextsEndpoint","req","user","Response","json","error","status","data","schema","object","collection","string","ids","array","parse","updatedDocs","erroredDocs","pluginConfig","payload","config","custom","altTextPluginConfig","resolver","concurrency","maxBulkGenerateConcurrency","locales","targetLocales","locale","id","generateAndUpdateAltText","console","log","length","Math","round","push","join","totalDocs","Error","message","imageDoc","findByID","depth","imageThumbnailUrl","getImageThumbnail","result","resolveBulk","filename","undefined","success","localeResult","results","update","alt","altText","keywords"],"mappings":"AAEA,OAAOA,UAAU,QAAO;AACxB,SAASC,CAAC,QAAQ,MAAK;AAIvB,SAASC,iBAAiB,QAAQ,oCAAmC;AAErE;;CAEC,GACD,OAAO,MAAMC,+BAA+C,OAAOC;IACjE,IAAI;QACF,IAAI,CAACA,IAAIC,IAAI,EAAE;YACb,OAAOC,SAASC,IAAI,CAAC;gBAAEC,OAAO;YAAe,GAAG;gBAAEC,QAAQ;YAAI;QAChE;QAEA,MAAMC,OAAO,UAAUN,OAAO,OAAOA,IAAIG,IAAI,KAAK,aAAa,MAAMH,IAAIG,IAAI,KAAK;QAElF,MAAMI,SAASV,EAAEW,MAAM,CAAC;YACtBC,YAAYZ,EAAEa,MAAM;YACpBC,KAAKd,EAAEe,KAAK,CAACf,EAAEa,MAAM;QACvB;QAEA,MAAM,EAAED,UAAU,EAAEE,GAAG,EAAE,GAAGJ,OAAOM,KAAK,CAACP;QAEzC,IAAIQ,cAAc;QAClB,MAAMC,cAAwB,EAAE;QAEhC,wCAAwC;QACxC,MAAMC,eAAehB,IAAIiB,OAAO,CAACC,MAAM,CAACC,MAAM,EAAEC;QAIhD,IAAI,CAACJ,cAAc;YACjB,OAAOd,SAASC,IAAI,CAAC;gBAAEC,OAAO;YAA0B,GAAG;gBAAEC,QAAQ;YAAI;QAC3E;QAEA,IAAI,CAACW,aAAaK,QAAQ,EAAE;YAC1B,OAAOnB,SAASC,IAAI,CAAC;gBAAEC,OAAO;YAAkC,GAAG;gBAAEC,QAAQ;YAAI;QACnF;QAEA,MAAMiB,cAAcN,aAAaO,0BAA0B;QAE3D,2CAA2C;QAC3C,MAAMC,UAAU1B,kBAAkBE,IAAIiB,OAAO,CAACC,MAAM;QACpD,MAAMO,gBAAgBD,WAAW;YAACR,aAAaU,MAAM;SAAE;QACvD,IAAI,CAACD,eAAe;YAClB,OAAOvB,SAASC,IAAI,CAClB;gBACEC,OACE;YACJ,GACA;gBAAEC,QAAQ;YAAI;QAElB;QAEA,MAAMT,KACJe,KACA,OAAOgB;YACL,IAAI;gBACF,MAAMC,yBAAyB;oBAC7BD;oBACAlB;oBACAe,SAASC;oBACTR,SAASjB,IAAIiB,OAAO;oBACpBD;oBACAhB;gBACF;gBACAc;gBACAe,QAAQC,GAAG,CACT,GAAGhB,YAAY,CAAC,EAAEH,IAAIoB,MAAM,CAAC,UAAU,EAAEC,KAAKC,KAAK,CAAC,AAACnB,cAAcH,IAAIoB,MAAM,GAAI,KAAK,EAAE,CAAC;YAE7F,EAAE,OAAO3B,OAAO;gBACdyB,QAAQzB,KAAK,CAAC,CAAC,8BAA8B,EAAEuB,GAAG,CAAC,CAAC,EAAEvB;gBACtDW,YAAYmB,IAAI,CAACP;YACnB;QACF,GACA;YAAEL;QAAY;QAGhB,IAAIP,YAAYgB,MAAM,GAAG,GAAG;YAC1BF,QAAQzB,KAAK,CAAC,CAAC,YAAY,EAAEW,YAAYoB,IAAI,CAAC,OAAO;QACvD;QAEA,OAAOjC,SAASC,IAAI,CAAC;YACnBY;YACAqB,WAAWzB,IAAIoB,MAAM;YACrBjB;QACF;IACF,EAAE,OAAOV,OAAO;QACdyB,QAAQzB,KAAK,CAAC,6BAA6BA;QAC3C,OAAOF,SAASC,IAAI,CAClB;YACEC,OAAO,CAAC,2BAA2B,EAAEA,iBAAiBiC,QAAQjC,MAAMkC,OAAO,GAAG,iBAAiB;QACjG,GACA;YAAEjC,QAAQ;QAAI;IAElB;AACF,EAAC;AAED,eAAeuB,yBAAyB,EACtCD,EAAE,EACFlB,UAAU,EACVe,OAAO,EACPP,OAAO,EACPD,YAAY,EACZhB,GAAG,EAQJ;IACC,MAAMuC,WAAW,MAAMtB,QAAQuB,QAAQ,CAAC;QACtCb;QACAlB;QACAgC,OAAO;IACT;IAEA,IAAI,CAACF,UAAU;QACb,MAAM,IAAIF,MAAM;IAClB;IAEA,MAAMK,oBAAoB1B,aAAa2B,iBAAiB,CAACJ;IAEzD,MAAMK,SAAS,MAAM5B,aAAaK,QAAQ,CAACwB,WAAW,CAAC;QACrDC,UACE,cAAcP,YAAY,OAAOA,SAASO,QAAQ,KAAK,WACnDP,SAASO,QAAQ,GACjBC;QACNL;QACAlB;QACAxB;IACF;IAEA,IAAI,CAAC4C,OAAOI,OAAO,EAAE;QACnB,MAAM,IAAIX,MAAMO,OAAOxC,KAAK,IAAI;IAClC;IAEA,KAAK,MAAMsB,UAAUF,QAAS;QAC5B,MAAMyB,eAAeL,OAAOM,OAAO,CAACxB,OAAO;QAC3C,IAAIuB,cAAc;YAChB,MAAMhC,QAAQkC,MAAM,CAAC;gBACnBxB;gBACAlB;gBACAH,MAAM;oBACJ8C,KAAKH,aAAaI,OAAO;oBACzBC,UAAUL,aAAaK,QAAQ;gBACjC;gBACA5B;YACF;QACF;IACF;AACF"}
1
+ {"version":3,"sources":["../../src/endpoints/bulkGenerateAltTexts.ts"],"sourcesContent":["import type { BasePayload, CollectionSlug, PayloadHandler, PayloadRequest } from 'payload'\n\nimport pMap from 'p-map'\nimport { z, ZodError } from 'zod'\n\nimport type { AltTextPluginConfig } from '../types/AltTextPluginConfig.js'\n\nimport { localesFromConfig } from '../utilities/localesFromConfig.js'\n\n/**\n * Generates and updates alt text for multiple images in all locales.\n */\nexport const bulkGenerateAltTextsEndpoint =\n (access: AltTextPluginConfig['access']): PayloadHandler =>\n async (req: PayloadRequest) => {\n try {\n if (!(await access({ req }))) {\n return Response.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const data = 'json' in req && typeof req.json === 'function' ? await req.json() : null\n\n const schema = z.object({\n collection: z.string(),\n ids: z.array(z.union([z.string(), z.number()])),\n })\n\n const { collection, ids } = schema.parse(data)\n\n let updatedDocs = 0\n const erroredDocs: (number | string)[] = []\n\n // Get plugin config from payload config\n const pluginConfig = req.payload.config.custom?.altTextPluginConfig as\n | AltTextPluginConfig\n | undefined\n\n if (!pluginConfig) {\n return Response.json({ error: 'Plugin config not found' }, { status: 500 })\n }\n\n if (!pluginConfig.resolver) {\n return Response.json({ error: 'No alt text resolver configured' }, { status: 500 })\n }\n\n const concurrency = pluginConfig.maxBulkGenerateConcurrency\n\n // determine target locales based on config\n const locales = localesFromConfig(req.payload.config)\n const targetLocales = locales ?? [pluginConfig.locale!]\n if (!targetLocales) {\n return Response.json(\n {\n error:\n 'Could not determine target locales for alt text generation. Please check your plugin configuration.',\n },\n { status: 500 },\n )\n }\n\n await pMap(\n ids,\n async (id) => {\n try {\n await generateAndUpdateAltText({\n id,\n collection,\n locales: targetLocales,\n payload: req.payload,\n pluginConfig,\n req,\n })\n updatedDocs++\n console.log(\n `${updatedDocs}/${ids.length} updated (${Math.round((updatedDocs / ids.length) * 100)}%)`,\n )\n } catch (error) {\n console.error(`Error generating alt text for ${id}:`, error)\n erroredDocs.push(id)\n }\n },\n { concurrency },\n )\n\n if (erroredDocs.length > 0) {\n console.error(`Failed for: ${erroredDocs.join(', ')}`)\n }\n\n return Response.json({\n erroredDocs,\n totalDocs: ids.length,\n updatedDocs,\n })\n } catch (error) {\n if (error instanceof ZodError) {\n return Response.json(\n {\n details: error.issues.map((e) => ({\n message: e.message,\n path: e.path.join('.'),\n })),\n error: 'Validation failed',\n },\n { status: 400 },\n )\n }\n console.error('Error in bulk generation:', error)\n return Response.json(\n {\n error: `Error generating alt text: ${error instanceof Error ? error.message : 'Unknown error'}`,\n },\n { status: 500 },\n )\n }\n }\n\nasync function generateAndUpdateAltText({\n id,\n collection,\n locales,\n payload,\n pluginConfig,\n req,\n}: {\n collection: CollectionSlug\n id: number | string\n locales: string[]\n payload: BasePayload\n pluginConfig: AltTextPluginConfig\n req: PayloadRequest\n}) {\n const imageDoc = await payload.findByID({\n id,\n collection,\n depth: 0,\n })\n\n if (!imageDoc) {\n throw new Error('Image not found')\n }\n\n const imageThumbnailUrl = pluginConfig.getImageThumbnail(imageDoc)\n\n const result = await pluginConfig.resolver.resolveBulk({\n filename:\n 'filename' in imageDoc && typeof imageDoc.filename === 'string'\n ? imageDoc.filename\n : undefined,\n imageThumbnailUrl,\n locales,\n req,\n })\n\n if (!result.success) {\n throw new Error(result.error || 'Failed to generate alt text')\n }\n\n for (const locale of locales) {\n const localeResult = result.results[locale]\n if (localeResult) {\n await payload.update({\n id,\n collection,\n data: {\n alt: localeResult.altText,\n keywords: localeResult.keywords,\n },\n locale,\n })\n }\n }\n}\n"],"names":["pMap","z","ZodError","localesFromConfig","bulkGenerateAltTextsEndpoint","access","req","Response","json","error","status","data","schema","object","collection","string","ids","array","union","number","parse","updatedDocs","erroredDocs","pluginConfig","payload","config","custom","altTextPluginConfig","resolver","concurrency","maxBulkGenerateConcurrency","locales","targetLocales","locale","id","generateAndUpdateAltText","console","log","length","Math","round","push","join","totalDocs","details","issues","map","e","message","path","Error","imageDoc","findByID","depth","imageThumbnailUrl","getImageThumbnail","result","resolveBulk","filename","undefined","success","localeResult","results","update","alt","altText","keywords"],"mappings":"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"}
@@ -1,6 +1,12 @@
1
1
  import type { PayloadHandler } from 'payload';
2
+ import type { AltTextPluginConfig } from '../types/AltTextPluginConfig.js';
2
3
  /**
3
4
  * Generates alt text for a single image using the configured resolver.
4
- * Returns result without updating the document.
5
+ *
6
+ * By default, returns the result without updating the document (preview mode).
7
+ * Pass `update: true` in the request body to also persist the generated alt text
8
+ * and keywords to the document — useful for programmatic/agent workflows.
9
+ *
10
+ * The response always includes the `id` and `collection` for easy correlation.
5
11
  */
6
- export declare const generateAltTextEndpoint: PayloadHandler;
12
+ export declare const generateAltTextEndpoint: (access: AltTextPluginConfig["access"]) => PayloadHandler;
@@ -1,89 +1,126 @@
1
- import { z } from 'zod';
1
+ import { z, ZodError } from 'zod';
2
2
  /**
3
3
  * Generates alt text for a single image using the configured resolver.
4
- * Returns result without updating the document.
5
- */ export const generateAltTextEndpoint = async (req)=>{
6
- try {
7
- if (!req.user) {
8
- return Response.json({
9
- error: 'Unauthorized'
10
- }, {
11
- status: 401
4
+ *
5
+ * By default, returns the result without updating the document (preview mode).
6
+ * Pass `update: true` in the request body to also persist the generated alt text
7
+ * and keywords to the document — useful for programmatic/agent workflows.
8
+ *
9
+ * The response always includes the `id` and `collection` for easy correlation.
10
+ */ export const generateAltTextEndpoint = (access)=>async (req)=>{
11
+ try {
12
+ if (!await access({
13
+ req
14
+ })) {
15
+ return Response.json({
16
+ error: 'Unauthorized'
17
+ }, {
18
+ status: 401
19
+ });
20
+ }
21
+ const data = 'json' in req && typeof req.json === 'function' ? await req.json() : null;
22
+ const requestSchema = z.object({
23
+ id: z.union([
24
+ z.string(),
25
+ z.number()
26
+ ]),
27
+ collection: z.string(),
28
+ locale: z.string().nullable(),
29
+ update: z.boolean().optional().default(false)
12
30
  });
13
- }
14
- const data = 'json' in req && typeof req.json === 'function' ? await req.json() : null;
15
- const requestSchema = z.object({
16
- id: z.string(),
17
- collection: z.string(),
18
- locale: z.string().nullable()
19
- });
20
- const { id, collection, locale } = requestSchema.parse(data);
21
- const imageDoc = await req.payload.findByID({
22
- id,
23
- collection,
24
- depth: 0
25
- });
26
- if (!imageDoc) {
27
- return Response.json({
28
- error: 'Image not found'
29
- }, {
30
- status: 404
31
+ const { id, collection, locale, update } = requestSchema.parse(data);
32
+ const imageDoc = await req.payload.findByID({
33
+ id,
34
+ collection,
35
+ depth: 0
31
36
  });
32
- }
33
- const pluginConfig = req.payload.config.custom?.altTextPluginConfig;
34
- if (!pluginConfig) {
35
- return Response.json({
36
- error: 'Plugin config not found'
37
- }, {
38
- status: 500
37
+ if (!imageDoc) {
38
+ return Response.json({
39
+ error: 'Image not found'
40
+ }, {
41
+ status: 404
42
+ });
43
+ }
44
+ const pluginConfig = req.payload.config.custom?.altTextPluginConfig;
45
+ if (!pluginConfig) {
46
+ return Response.json({
47
+ error: 'Plugin config not found'
48
+ }, {
49
+ status: 500
50
+ });
51
+ }
52
+ if (!pluginConfig.getImageThumbnail) {
53
+ return Response.json({
54
+ error: 'getImageThumbnail function not configured'
55
+ }, {
56
+ status: 500
57
+ });
58
+ }
59
+ if (!pluginConfig.resolver) {
60
+ return Response.json({
61
+ error: 'No alt text resolver configured'
62
+ }, {
63
+ status: 500
64
+ });
65
+ }
66
+ // determine target locale
67
+ const targetLocale = locale ?? pluginConfig.locale;
68
+ if (!targetLocale) {
69
+ return Response.json({
70
+ error: 'Could not determine target locale for alt text generation. Please check your plugin configuration.'
71
+ }, {
72
+ status: 500
73
+ });
74
+ }
75
+ const imageThumbnailUrl = pluginConfig.getImageThumbnail(imageDoc);
76
+ const result = await pluginConfig.resolver.resolve({
77
+ filename: 'filename' in imageDoc && typeof imageDoc.filename === 'string' ? imageDoc.filename : undefined,
78
+ imageThumbnailUrl,
79
+ locale: targetLocale,
80
+ req
39
81
  });
40
- }
41
- if (!pluginConfig.getImageThumbnail) {
82
+ if (!result.success) {
83
+ return Response.json({
84
+ error: result.error || 'Failed to generate alt text'
85
+ }, {
86
+ status: 500
87
+ });
88
+ }
89
+ if (update) {
90
+ await req.payload.update({
91
+ id,
92
+ collection,
93
+ data: {
94
+ alt: result.result.altText,
95
+ keywords: result.result.keywords
96
+ },
97
+ locale: targetLocale
98
+ });
99
+ }
42
100
  return Response.json({
43
- error: 'getImageThumbnail function not configured'
44
- }, {
45
- status: 500
101
+ id,
102
+ collection,
103
+ ...result.result
46
104
  });
47
- }
48
- if (!pluginConfig.resolver) {
49
- return Response.json({
50
- error: 'No alt text resolver configured'
51
- }, {
52
- status: 500
53
- });
54
- }
55
- // determine target locale
56
- const targetLocale = locale ?? pluginConfig.locale;
57
- if (!targetLocale) {
58
- return Response.json({
59
- error: 'Could not determine target locale for alt text generation. Please check your plugin configuration.'
60
- }, {
61
- status: 500
62
- });
63
- }
64
- const imageThumbnailUrl = pluginConfig.getImageThumbnail(imageDoc);
65
- const result = await pluginConfig.resolver.resolve({
66
- filename: 'filename' in imageDoc && typeof imageDoc.filename === 'string' ? imageDoc.filename : undefined,
67
- imageThumbnailUrl,
68
- locale: targetLocale,
69
- req
70
- });
71
- if (!result.success) {
105
+ } catch (error) {
106
+ if (error instanceof ZodError) {
107
+ return Response.json({
108
+ details: error.issues.map((e)=>({
109
+ message: e.message,
110
+ path: e.path.join('.')
111
+ })),
112
+ error: 'Validation failed'
113
+ }, {
114
+ status: 400
115
+ });
116
+ }
117
+ console.error('Error generating alt text:', error);
72
118
  return Response.json({
73
- error: result.error || 'Failed to generate alt text'
119
+ error: `Error generating alt text: ${error instanceof Error ? error.message : 'Unknown error'}`
74
120
  }, {
75
121
  status: 500
76
122
  });
77
123
  }
78
- return Response.json(result.result);
79
- } catch (error) {
80
- console.error('Error generating alt text:', error);
81
- return Response.json({
82
- error: `Error generating alt text: ${error instanceof Error ? error.message : 'Unknown error'}`
83
- }, {
84
- status: 500
85
- });
86
- }
87
- };
124
+ };
88
125
 
89
126
  //# sourceMappingURL=generateAltText.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/endpoints/generateAltText.ts"],"sourcesContent":["import type { PayloadHandler, PayloadRequest } from 'payload'\n\nimport { z } from 'zod'\n\nimport type { AltTextPluginConfig } from '../types/AltTextPluginConfig.js'\n\n/**\n * Generates alt text for a single image using the configured resolver.\n * Returns result without updating the document.\n */\nexport const generateAltTextEndpoint: PayloadHandler = async (req: PayloadRequest) => {\n try {\n if (!req.user) {\n return Response.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const data = 'json' in req && typeof req.json === 'function' ? await req.json() : null\n\n const requestSchema = z.object({\n id: z.string(),\n collection: z.string(),\n locale: z.string().nullable(),\n })\n\n const { id, collection, locale } = requestSchema.parse(data)\n\n const imageDoc = await req.payload.findByID({\n id,\n collection,\n depth: 0,\n })\n\n if (!imageDoc) {\n return Response.json({ error: 'Image not found' }, { status: 404 })\n }\n\n const pluginConfig = req.payload.config.custom?.altTextPluginConfig as\n | AltTextPluginConfig\n | undefined\n\n if (!pluginConfig) {\n return Response.json({ error: 'Plugin config not found' }, { status: 500 })\n }\n\n if (!pluginConfig.getImageThumbnail) {\n return Response.json({ error: 'getImageThumbnail function not configured' }, { status: 500 })\n }\n\n if (!pluginConfig.resolver) {\n return Response.json({ error: 'No alt text resolver configured' }, { status: 500 })\n }\n\n // determine target locale\n const targetLocale = locale ?? pluginConfig.locale\n if (!targetLocale) {\n return Response.json(\n {\n error:\n 'Could not determine target locale for alt text generation. Please check your plugin configuration.',\n },\n { status: 500 },\n )\n }\n\n const imageThumbnailUrl = pluginConfig.getImageThumbnail(imageDoc)\n\n const result = await pluginConfig.resolver.resolve({\n filename:\n 'filename' in imageDoc && typeof imageDoc.filename === 'string'\n ? imageDoc.filename\n : undefined,\n imageThumbnailUrl,\n locale: targetLocale,\n req,\n })\n\n if (!result.success) {\n return Response.json(\n { error: result.error || 'Failed to generate alt text' },\n { status: 500 },\n )\n }\n\n return Response.json(result.result)\n } catch (error) {\n console.error('Error generating alt text:', error)\n return Response.json(\n {\n error: `Error generating alt text: ${error instanceof Error ? error.message : 'Unknown error'}`,\n },\n { status: 500 },\n )\n }\n}\n"],"names":["z","generateAltTextEndpoint","req","user","Response","json","error","status","data","requestSchema","object","id","string","collection","locale","nullable","parse","imageDoc","payload","findByID","depth","pluginConfig","config","custom","altTextPluginConfig","getImageThumbnail","resolver","targetLocale","imageThumbnailUrl","result","resolve","filename","undefined","success","console","Error","message"],"mappings":"AAEA,SAASA,CAAC,QAAQ,MAAK;AAIvB;;;CAGC,GACD,OAAO,MAAMC,0BAA0C,OAAOC;IAC5D,IAAI;QACF,IAAI,CAACA,IAAIC,IAAI,EAAE;YACb,OAAOC,SAASC,IAAI,CAAC;gBAAEC,OAAO;YAAe,GAAG;gBAAEC,QAAQ;YAAI;QAChE;QAEA,MAAMC,OAAO,UAAUN,OAAO,OAAOA,IAAIG,IAAI,KAAK,aAAa,MAAMH,IAAIG,IAAI,KAAK;QAElF,MAAMI,gBAAgBT,EAAEU,MAAM,CAAC;YAC7BC,IAAIX,EAAEY,MAAM;YACZC,YAAYb,EAAEY,MAAM;YACpBE,QAAQd,EAAEY,MAAM,GAAGG,QAAQ;QAC7B;QAEA,MAAM,EAAEJ,EAAE,EAAEE,UAAU,EAAEC,MAAM,EAAE,GAAGL,cAAcO,KAAK,CAACR;QAEvD,MAAMS,WAAW,MAAMf,IAAIgB,OAAO,CAACC,QAAQ,CAAC;YAC1CR;YACAE;YACAO,OAAO;QACT;QAEA,IAAI,CAACH,UAAU;YACb,OAAOb,SAASC,IAAI,CAAC;gBAAEC,OAAO;YAAkB,GAAG;gBAAEC,QAAQ;YAAI;QACnE;QAEA,MAAMc,eAAenB,IAAIgB,OAAO,CAACI,MAAM,CAACC,MAAM,EAAEC;QAIhD,IAAI,CAACH,cAAc;YACjB,OAAOjB,SAASC,IAAI,CAAC;gBAAEC,OAAO;YAA0B,GAAG;gBAAEC,QAAQ;YAAI;QAC3E;QAEA,IAAI,CAACc,aAAaI,iBAAiB,EAAE;YACnC,OAAOrB,SAASC,IAAI,CAAC;gBAAEC,OAAO;YAA4C,GAAG;gBAAEC,QAAQ;YAAI;QAC7F;QAEA,IAAI,CAACc,aAAaK,QAAQ,EAAE;YAC1B,OAAOtB,SAASC,IAAI,CAAC;gBAAEC,OAAO;YAAkC,GAAG;gBAAEC,QAAQ;YAAI;QACnF;QAEA,0BAA0B;QAC1B,MAAMoB,eAAeb,UAAUO,aAAaP,MAAM;QAClD,IAAI,CAACa,cAAc;YACjB,OAAOvB,SAASC,IAAI,CAClB;gBACEC,OACE;YACJ,GACA;gBAAEC,QAAQ;YAAI;QAElB;QAEA,MAAMqB,oBAAoBP,aAAaI,iBAAiB,CAACR;QAEzD,MAAMY,SAAS,MAAMR,aAAaK,QAAQ,CAACI,OAAO,CAAC;YACjDC,UACE,cAAcd,YAAY,OAAOA,SAASc,QAAQ,KAAK,WACnDd,SAASc,QAAQ,GACjBC;YACNJ;YACAd,QAAQa;YACRzB;QACF;QAEA,IAAI,CAAC2B,OAAOI,OAAO,EAAE;YACnB,OAAO7B,SAASC,IAAI,CAClB;gBAAEC,OAAOuB,OAAOvB,KAAK,IAAI;YAA8B,GACvD;gBAAEC,QAAQ;YAAI;QAElB;QAEA,OAAOH,SAASC,IAAI,CAACwB,OAAOA,MAAM;IACpC,EAAE,OAAOvB,OAAO;QACd4B,QAAQ5B,KAAK,CAAC,8BAA8BA;QAC5C,OAAOF,SAASC,IAAI,CAClB;YACEC,OAAO,CAAC,2BAA2B,EAAEA,iBAAiB6B,QAAQ7B,MAAM8B,OAAO,GAAG,iBAAiB;QACjG,GACA;YAAE7B,QAAQ;QAAI;IAElB;AACF,EAAC"}
1
+ {"version":3,"sources":["../../src/endpoints/generateAltText.ts"],"sourcesContent":["import type { PayloadHandler, PayloadRequest } from 'payload'\n\nimport { z, ZodError } from 'zod'\n\nimport type { AltTextPluginConfig } from '../types/AltTextPluginConfig.js'\n\n/**\n * Generates alt text for a single image using the configured resolver.\n *\n * By default, returns the result without updating the document (preview mode).\n * Pass `update: true` in the request body to also persist the generated alt text\n * and keywords to the document — useful for programmatic/agent workflows.\n *\n * The response always includes the `id` and `collection` for easy correlation.\n */\nexport const generateAltTextEndpoint =\n (access: AltTextPluginConfig['access']): PayloadHandler =>\n async (req: PayloadRequest) => {\n try {\n if (!(await access({ req }))) {\n return Response.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const data = 'json' in req && typeof req.json === 'function' ? await req.json() : null\n\n const requestSchema = z.object({\n id: z.union([z.string(), z.number()]),\n collection: z.string(),\n locale: z.string().nullable(),\n update: z.boolean().optional().default(false),\n })\n\n const { id, collection, locale, update } = requestSchema.parse(data)\n\n const imageDoc = await req.payload.findByID({\n id,\n collection,\n depth: 0,\n })\n\n if (!imageDoc) {\n return Response.json({ error: 'Image not found' }, { status: 404 })\n }\n\n const pluginConfig = req.payload.config.custom?.altTextPluginConfig as\n | AltTextPluginConfig\n | undefined\n\n if (!pluginConfig) {\n return Response.json({ error: 'Plugin config not found' }, { status: 500 })\n }\n\n if (!pluginConfig.getImageThumbnail) {\n return Response.json(\n { error: 'getImageThumbnail function not configured' },\n { status: 500 },\n )\n }\n\n if (!pluginConfig.resolver) {\n return Response.json({ error: 'No alt text resolver configured' }, { status: 500 })\n }\n\n // determine target locale\n const targetLocale = locale ?? pluginConfig.locale\n if (!targetLocale) {\n return Response.json(\n {\n error:\n 'Could not determine target locale for alt text generation. Please check your plugin configuration.',\n },\n { status: 500 },\n )\n }\n\n const imageThumbnailUrl = pluginConfig.getImageThumbnail(imageDoc)\n\n const result = await pluginConfig.resolver.resolve({\n filename:\n 'filename' in imageDoc && typeof imageDoc.filename === 'string'\n ? imageDoc.filename\n : undefined,\n imageThumbnailUrl,\n locale: targetLocale,\n req,\n })\n\n if (!result.success) {\n return Response.json(\n { error: result.error || 'Failed to generate alt text' },\n { status: 500 },\n )\n }\n\n if (update) {\n await req.payload.update({\n id,\n collection,\n data: {\n alt: result.result.altText,\n keywords: result.result.keywords,\n },\n locale: targetLocale,\n })\n }\n\n return Response.json({ id, collection, ...result.result })\n } catch (error) {\n if (error instanceof ZodError) {\n return Response.json(\n {\n details: error.issues.map((e) => ({\n message: e.message,\n path: e.path.join('.'),\n })),\n error: 'Validation failed',\n },\n { status: 400 },\n )\n }\n console.error('Error generating alt text:', error)\n return Response.json(\n {\n error: `Error generating alt text: ${error instanceof Error ? error.message : 'Unknown error'}`,\n },\n { status: 500 },\n )\n }\n }\n"],"names":["z","ZodError","generateAltTextEndpoint","access","req","Response","json","error","status","data","requestSchema","object","id","union","string","number","collection","locale","nullable","update","boolean","optional","default","parse","imageDoc","payload","findByID","depth","pluginConfig","config","custom","altTextPluginConfig","getImageThumbnail","resolver","targetLocale","imageThumbnailUrl","result","resolve","filename","undefined","success","alt","altText","keywords","details","issues","map","e","message","path","join","console","Error"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { AltTextHealthWidget } from '../components/AltTextHealthWidget.js';
2
+ export { getAltTextHealth } from '../utilities/altTextHealth.js';
3
+ export type { AltTextHealthError, AltTextHealthErrorCode, AltTextHealthScan, AltTextHealthScanCollection, } from '../utilities/altTextHealth.js';
@@ -0,0 +1,4 @@
1
+ export { AltTextHealthWidget } from '../components/AltTextHealthWidget.js';
2
+ export { getAltTextHealth } from '../utilities/altTextHealth.js';
3
+
4
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/exports/server.ts"],"sourcesContent":["export { AltTextHealthWidget } from '../components/AltTextHealthWidget.js'\nexport { getAltTextHealth } from '../utilities/altTextHealth.js'\nexport type {\n AltTextHealthError,\n AltTextHealthErrorCode,\n AltTextHealthScan,\n AltTextHealthScanCollection,\n} from '../utilities/altTextHealth.js'\n"],"names":["AltTextHealthWidget","getAltTextHealth"],"mappings":"AAAA,SAASA,mBAAmB,QAAQ,uCAAsC;AAC1E,SAASC,gBAAgB,QAAQ,gCAA+B"}
@@ -0,0 +1,3 @@
1
+ import type { CollectionAfterChangeHook, CollectionAfterDeleteHook } from 'payload';
2
+ export declare const createRevalidateAltTextHealthAfterChangeHook: (collectionSlug: string) => CollectionAfterChangeHook;
3
+ export declare const createRevalidateAltTextHealthAfterDeleteHook: (collectionSlug: string) => CollectionAfterDeleteHook;
@@ -0,0 +1,32 @@
1
+ import { revalidateTag } from 'next/cache.js';
2
+ import { ALT_TEXT_HEALTH_PLUGIN_SLUG, getAltTextHealthCollectionTag } from '../utilities/altTextHealth.js';
3
+ function safeRevalidateTag(req, tag) {
4
+ try {
5
+ revalidateTag(tag);
6
+ } catch (error) {
7
+ const message = error instanceof Error ? error.message : String(error);
8
+ if (message.includes('static generation store missing')) {
9
+ req.payload.logger.warn({
10
+ msg: 'Skipping alt text health cache revalidation outside a Next.js request context.',
11
+ plugin: ALT_TEXT_HEALTH_PLUGIN_SLUG,
12
+ tag
13
+ });
14
+ return;
15
+ }
16
+ throw error;
17
+ }
18
+ }
19
+ export const createRevalidateAltTextHealthAfterChangeHook = (collectionSlug)=>({ doc, req })=>{
20
+ if (!req.context?.disableRevalidate) {
21
+ safeRevalidateTag(req, getAltTextHealthCollectionTag(collectionSlug));
22
+ }
23
+ return doc;
24
+ };
25
+ export const createRevalidateAltTextHealthAfterDeleteHook = (collectionSlug)=>({ doc, req })=>{
26
+ if (!req.context?.disableRevalidate) {
27
+ safeRevalidateTag(req, getAltTextHealthCollectionTag(collectionSlug));
28
+ }
29
+ return doc;
30
+ };
31
+
32
+ //# sourceMappingURL=revalidateAltTextHealth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hooks/revalidateAltTextHealth.ts"],"sourcesContent":["import type { CollectionAfterChangeHook, CollectionAfterDeleteHook, PayloadRequest } from 'payload'\n\nimport { revalidateTag } from 'next/cache.js'\n\nimport {\n ALT_TEXT_HEALTH_PLUGIN_SLUG,\n getAltTextHealthCollectionTag,\n} from '../utilities/altTextHealth.js'\n\nfunction safeRevalidateTag(req: PayloadRequest, tag: string): void {\n try {\n revalidateTag(tag)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n\n if (message.includes('static generation store missing')) {\n req.payload.logger.warn({\n msg: 'Skipping alt text health cache revalidation outside a Next.js request context.',\n plugin: ALT_TEXT_HEALTH_PLUGIN_SLUG,\n tag,\n })\n return\n }\n\n throw error\n }\n}\n\nexport const createRevalidateAltTextHealthAfterChangeHook =\n (collectionSlug: string): CollectionAfterChangeHook =>\n ({ doc, req }) => {\n if (!req.context?.disableRevalidate) {\n safeRevalidateTag(req, getAltTextHealthCollectionTag(collectionSlug))\n }\n\n return doc\n }\n\nexport const createRevalidateAltTextHealthAfterDeleteHook =\n (collectionSlug: string): CollectionAfterDeleteHook =>\n ({ doc, req }) => {\n if (!req.context?.disableRevalidate) {\n safeRevalidateTag(req, getAltTextHealthCollectionTag(collectionSlug))\n }\n\n return doc\n }\n"],"names":["revalidateTag","ALT_TEXT_HEALTH_PLUGIN_SLUG","getAltTextHealthCollectionTag","safeRevalidateTag","req","tag","error","message","Error","String","includes","payload","logger","warn","msg","plugin","createRevalidateAltTextHealthAfterChangeHook","collectionSlug","doc","context","disableRevalidate","createRevalidateAltTextHealthAfterDeleteHook"],"mappings":"AAEA,SAASA,aAAa,QAAQ,gBAAe;AAE7C,SACEC,2BAA2B,EAC3BC,6BAA6B,QACxB,gCAA+B;AAEtC,SAASC,kBAAkBC,GAAmB,EAAEC,GAAW;IACzD,IAAI;QACFL,cAAcK;IAChB,EAAE,OAAOC,OAAO;QACd,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMC,OAAO,GAAGE,OAAOH;QAEhE,IAAIC,QAAQG,QAAQ,CAAC,oCAAoC;YACvDN,IAAIO,OAAO,CAACC,MAAM,CAACC,IAAI,CAAC;gBACtBC,KAAK;gBACLC,QAAQd;gBACRI;YACF;YACA;QACF;QAEA,MAAMC;IACR;AACF;AAEA,OAAO,MAAMU,+CACX,CAACC,iBACD,CAAC,EAAEC,GAAG,EAAEd,GAAG,EAAE;QACX,IAAI,CAACA,IAAIe,OAAO,EAAEC,mBAAmB;YACnCjB,kBAAkBC,KAAKF,8BAA8Be;QACvD;QAEA,OAAOC;IACT,EAAC;AAEH,OAAO,MAAMG,+CACX,CAACJ,iBACD,CAAC,EAAEC,GAAG,EAAEd,GAAG,EAAE;QACX,IAAI,CAACA,IAAIe,OAAO,EAAEC,mBAAmB;YACnCjB,kBAAkBC,KAAKF,8BAA8Be;QACvD;QAEA,OAAOC;IACT,EAAC"}