strapi-plugin-meilisearch 0.16.2 → 0.16.3

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.
@@ -322,88 +322,371 @@ const configurationService = ({ strapi: strapi2 }) => {
322
322
  }
323
323
  };
324
324
  };
325
- async function registerDocumentMiddleware({ strapi: strapi2 }) {
326
- if (!strapi2?.documents || typeof strapi2.documents.use !== "function") {
327
- return;
328
- }
329
- const extractEntryCandidates = (result) => {
330
- if (result == null) return [];
331
- const candidates = [];
332
- const appendCandidate = (data, source) => {
333
- if (data != null && typeof data === "object") {
334
- candidates.push({ data, source });
335
- }
336
- };
337
- if (Array.isArray(result)) {
338
- result.forEach((data) => appendCandidate(data, "root"));
339
- return candidates;
340
- }
341
- appendCandidate(result, "root");
342
- if (Array.isArray(result.versions)) {
343
- result.versions.forEach((data) => appendCandidate(data, "versions"));
344
- }
345
- if (Array.isArray(result.entries)) {
346
- result.entries.forEach((data) => appendCandidate(data, "entries"));
325
+ const resolveDocumentIdsFromActionParams = (actionParams) => {
326
+ const explicitDocumentIds = Array.isArray(actionParams?.documentIds) ? actionParams.documentIds.filter(
327
+ (documentId) => typeof documentId === "string" && documentId.length > 0
328
+ ) : [];
329
+ const singleDocumentId = typeof actionParams?.documentId === "string" && actionParams.documentId.length > 0 ? [actionParams.documentId] : [];
330
+ return [.../* @__PURE__ */ new Set([...explicitDocumentIds, ...singleDocumentId])];
331
+ };
332
+ const resolveDocumentIds = ({
333
+ actionParams,
334
+ result,
335
+ preActionSnapshots
336
+ }) => {
337
+ const ids = [...resolveDocumentIdsFromActionParams(actionParams)];
338
+ const appendDocumentId = (documentId) => {
339
+ if (typeof documentId === "string" && documentId.length > 0) {
340
+ ids.push(documentId);
347
341
  }
348
- if (result.entry != null) {
349
- appendCandidate(result.entry, "entry");
342
+ };
343
+ const inspectCandidate = (candidate) => {
344
+ if (!candidate || typeof candidate !== "object") return;
345
+ appendDocumentId(candidate.documentId);
346
+ };
347
+ if (Array.isArray(result)) {
348
+ result.forEach(inspectCandidate);
349
+ } else {
350
+ inspectCandidate(result);
351
+ }
352
+ (preActionSnapshots || []).forEach(
353
+ (snapshot) => appendDocumentId(snapshot?.documentId)
354
+ );
355
+ return [...new Set(ids)];
356
+ };
357
+ const extractStrapiEntryCandidates = (result) => {
358
+ if (result == null) return [];
359
+ const candidates = [];
360
+ const appendCandidate = (data, source) => {
361
+ if (data != null && typeof data === "object") {
362
+ candidates.push({ data, source });
350
363
  }
351
- return candidates;
352
364
  };
353
- const isPublishedEntry = (entry) => !(entry?.publishedAt === void 0 || entry?.publishedAt === null);
354
- const rankEntryCandidates = (candidates) => {
355
- return [...candidates].sort((a, b) => {
356
- const aHasPrimaryKey = a.data?.id != null;
357
- const bHasPrimaryKey = b.data?.id != null;
358
- if (aHasPrimaryKey && !bHasPrimaryKey) return -1;
359
- if (!aHasPrimaryKey && bHasPrimaryKey) return 1;
360
- const aIsRoot = a.source === "root";
361
- const bIsRoot = b.source === "root";
362
- if (!aIsRoot && bIsRoot) return -1;
363
- if (aIsRoot && !bIsRoot) return 1;
364
- return 0;
365
- });
365
+ if (Array.isArray(result)) {
366
+ result.forEach((data) => appendCandidate(data, "root"));
367
+ return candidates;
368
+ }
369
+ appendCandidate(result, "root");
370
+ if (Array.isArray(result.versions)) {
371
+ result.versions.forEach((data) => appendCandidate(data, "versions"));
372
+ }
373
+ if (Array.isArray(result.entries)) {
374
+ result.entries.forEach((data) => appendCandidate(data, "entries"));
375
+ }
376
+ if (result.entry != null) {
377
+ appendCandidate(result.entry, "entry");
378
+ }
379
+ return candidates;
380
+ };
381
+ const isPublishedStrapiEntry = (entry) => !(entry?.publishedAt === void 0 || entry?.publishedAt === null);
382
+ const rankStrapiEntryCandidates = (candidates) => {
383
+ return [...candidates].sort((a, b) => {
384
+ const aHasPrimaryKey = a.data?.id != null;
385
+ const bHasPrimaryKey = b.data?.id != null;
386
+ if (aHasPrimaryKey && !bHasPrimaryKey) return -1;
387
+ if (!aHasPrimaryKey && bHasPrimaryKey) return 1;
388
+ const aIsRoot = a.source === "root";
389
+ const bIsRoot = b.source === "root";
390
+ if (!aIsRoot && bIsRoot) return -1;
391
+ if (aIsRoot && !bIsRoot) return 1;
392
+ return 0;
393
+ });
394
+ };
395
+ const getActionLocale = (actionParams) => {
396
+ return typeof actionParams?.locale === "string" && actionParams.locale.length > 0 ? actionParams.locale : null;
397
+ };
398
+ const resolvePreferredConcreteLocale = ({ syncQuery, actionParams }) => {
399
+ const actionLocale = getActionLocale(actionParams);
400
+ if (actionLocale && !isWildcardLocale(actionLocale)) {
401
+ return actionLocale;
402
+ }
403
+ const syncLocale = typeof syncQuery?.locale === "string" && syncQuery.locale.length > 0 ? syncQuery.locale : null;
404
+ if (syncLocale && !isWildcardLocale(syncLocale)) {
405
+ return syncLocale;
406
+ }
407
+ return null;
408
+ };
409
+ const resolveLocaleScopedReadQuery = ({ syncQuery, actionParams }) => {
410
+ const actionLocale = getActionLocale(actionParams);
411
+ const baseQuery = { ...syncQuery || {} };
412
+ if (!isWildcardLocale(baseQuery.locale) || actionLocale == null) {
413
+ return baseQuery;
414
+ }
415
+ return {
416
+ ...baseQuery,
417
+ locale: actionLocale
366
418
  };
367
- const getEntryFromResult = ({
368
- resultCandidates,
369
- documentId,
370
- entriesQuery
371
- }) => {
372
- const documentCandidates = (resultCandidates || []).filter(
373
- (candidate) => candidate?.data?.documentId === documentId
374
- );
375
- if (documentCandidates.length === 0) return null;
376
- const rankedCandidates = rankEntryCandidates(documentCandidates);
377
- if (entriesQuery?.status === "draft") {
378
- const draftCandidate = rankedCandidates.find(
379
- (candidate) => !isPublishedEntry(candidate.data)
380
- );
381
- return draftCandidate?.data || rankedCandidates[0]?.data || null;
419
+ };
420
+ const resolveLocaleCodesToRemoveFromIndex = ({
421
+ actionParams,
422
+ preDeleteStrapiEntry,
423
+ localeVariants
424
+ }) => {
425
+ const actionLocale = getActionLocale(actionParams);
426
+ if (actionLocale && !isWildcardLocale(actionLocale)) {
427
+ return [actionLocale];
428
+ }
429
+ if (actionLocale == null) {
430
+ return typeof preDeleteStrapiEntry?.locale === "string" && preDeleteStrapiEntry.locale.length > 0 ? [preDeleteStrapiEntry.locale] : [];
431
+ }
432
+ return [
433
+ ...new Set(
434
+ (localeVariants || []).map((entry) => entry?.locale).filter((locale) => typeof locale === "string" && locale.length > 0)
435
+ )
436
+ ];
437
+ };
438
+ const resolveLocaleCodesToRemoveFromActionResult = ({
439
+ actionParams,
440
+ resultCandidates,
441
+ result,
442
+ documentId
443
+ }) => {
444
+ const entriesForDocument = (resultCandidates || []).map((candidate) => candidate?.data).filter((entry) => entry?.documentId === documentId);
445
+ const localeVariants = entriesForDocument.filter(
446
+ (entry) => typeof entry?.locale === "string" && entry.locale.length > 0
447
+ ).map((entry) => ({ documentId: entry.documentId, locale: entry.locale }));
448
+ const preDeleteStrapiEntry = entriesForDocument.find(
449
+ (entry) => typeof entry?.locale === "string" && entry.locale.length > 0
450
+ ) ?? (typeof result?.locale === "string" && result.locale.length > 0 ? result : entriesForDocument[0] ?? null);
451
+ return resolveLocaleCodesToRemoveFromIndex({
452
+ actionParams,
453
+ preDeleteStrapiEntry,
454
+ localeVariants
455
+ });
456
+ };
457
+ const collectLocaleCodesFromEntries = (entries) => {
458
+ return [
459
+ ...new Set(
460
+ (entries || []).map((entry) => entry?.locale).filter((locale) => typeof locale === "string" && locale.length > 0)
461
+ )
462
+ ];
463
+ };
464
+ const selectStrapiEntryToIndexFromResult = ({
465
+ resultCandidates,
466
+ documentId,
467
+ syncQuery,
468
+ actionParams
469
+ }) => {
470
+ const strapiDocumentEntryCandidates = (resultCandidates || []).filter(
471
+ (candidate) => candidate?.data?.documentId === documentId
472
+ );
473
+ if (strapiDocumentEntryCandidates.length === 0) return null;
474
+ const rankedEntryCandidates = rankStrapiEntryCandidates(
475
+ strapiDocumentEntryCandidates
476
+ );
477
+ const preferredConcreteLocale = resolvePreferredConcreteLocale({
478
+ syncQuery,
479
+ actionParams
480
+ });
481
+ const localeScopedEntryCandidate = preferredConcreteLocale ? rankedEntryCandidates.find(
482
+ (candidate) => candidate?.data?.locale === preferredConcreteLocale
483
+ ) : null;
484
+ if (syncQuery?.status === "draft") {
485
+ const isIndexableDraftEntryCandidate = (candidate) => candidate?.data?.id != null && !isPublishedStrapiEntry(candidate.data);
486
+ if (preferredConcreteLocale) {
487
+ return localeScopedEntryCandidate && isIndexableDraftEntryCandidate(localeScopedEntryCandidate) ? localeScopedEntryCandidate.data : null;
382
488
  }
383
- const publishedCandidate = rankedCandidates.find(
384
- (candidate) => isPublishedEntry(candidate.data)
489
+ const draftEntryCandidate = rankedEntryCandidates.find(
490
+ isIndexableDraftEntryCandidate
385
491
  );
386
- return publishedCandidate?.data || null;
387
- };
388
- const getEntryOutsideTransaction = ({
389
- contentTypeService: contentTypeService2,
492
+ return draftEntryCandidate?.data || null;
493
+ }
494
+ if (preferredConcreteLocale) {
495
+ return localeScopedEntryCandidate && isPublishedStrapiEntry(localeScopedEntryCandidate.data) ? localeScopedEntryCandidate.data : null;
496
+ }
497
+ const publishedEntryCandidate = rankedEntryCandidates.find(
498
+ (candidate) => isPublishedStrapiEntry(candidate.data)
499
+ );
500
+ return publishedEntryCandidate?.data || null;
501
+ };
502
+ const selectDraftEntriesForDiscardDraftResult = ({
503
+ resultCandidates,
504
+ documentId,
505
+ actionParams
506
+ }) => {
507
+ const actionLocale = getActionLocale(actionParams);
508
+ const rankedDraftEntryCandidates = rankStrapiEntryCandidates(
509
+ (resultCandidates || []).filter(
510
+ (candidate) => candidate?.data?.documentId === documentId && !isPublishedStrapiEntry(candidate.data)
511
+ )
512
+ );
513
+ const rankedLocalizedDraftEntryCandidates = rankedDraftEntryCandidates.filter(
514
+ (candidate) => typeof candidate?.data?.locale === "string" && candidate.data.locale.length > 0
515
+ );
516
+ if (rankedDraftEntryCandidates.length === 0) return [];
517
+ if (actionLocale && !isWildcardLocale(actionLocale)) {
518
+ const localeCandidate = rankedLocalizedDraftEntryCandidates.find(
519
+ (candidate) => candidate?.data?.locale === actionLocale
520
+ );
521
+ return localeCandidate ? [localeCandidate.data] : [];
522
+ }
523
+ if (actionLocale && isWildcardLocale(actionLocale)) {
524
+ const entriesByLocale = /* @__PURE__ */ new Map();
525
+ rankedLocalizedDraftEntryCandidates.forEach((candidate) => {
526
+ const locale = candidate.data.locale;
527
+ if (!entriesByLocale.has(locale)) {
528
+ entriesByLocale.set(locale, candidate.data);
529
+ }
530
+ });
531
+ return [...entriesByLocale.values()];
532
+ }
533
+ return [
534
+ rankedLocalizedDraftEntryCandidates[0]?.data || rankedDraftEntryCandidates[0].data
535
+ ];
536
+ };
537
+ const selectPublishedEntriesForWildcardPublish = ({
538
+ resultCandidates,
539
+ documentId,
540
+ actionParams,
541
+ syncQuery
542
+ }) => {
543
+ const actionLocale = getActionLocale(actionParams);
544
+ const syncLocale = syncQuery?.locale;
545
+ const syncStatusScope = syncQuery?.status;
546
+ const syncAllowsPublishedEntries = syncStatusScope == null || syncStatusScope !== "draft";
547
+ if (!actionLocale || !isWildcardLocale(actionLocale) || !isWildcardLocale(syncLocale) || !syncAllowsPublishedEntries) {
548
+ return [];
549
+ }
550
+ const rankedPublishedEntryCandidates = rankStrapiEntryCandidates(
551
+ (resultCandidates || []).filter(
552
+ (candidate) => candidate?.data?.documentId === documentId && isPublishedStrapiEntry(candidate.data)
553
+ )
554
+ );
555
+ if (rankedPublishedEntryCandidates.length === 0) return [];
556
+ const selectedEntries = [];
557
+ const seenKeys = /* @__PURE__ */ new Set();
558
+ rankedPublishedEntryCandidates.forEach((candidate) => {
559
+ const strapiEntry = candidate?.data;
560
+ if (!strapiEntry || typeof strapiEntry !== "object") return;
561
+ const localeKey = typeof strapiEntry.locale === "string" && strapiEntry.locale.length > 0 ? `locale:${strapiEntry.locale}` : null;
562
+ const idKey = strapiEntry.id != null ? `id:${strapiEntry.id}` : null;
563
+ const dedupeKey = localeKey || idKey;
564
+ if (!dedupeKey || seenKeys.has(dedupeKey)) return;
565
+ seenKeys.add(dedupeKey);
566
+ selectedEntries.push(strapiEntry);
567
+ });
568
+ return selectedEntries;
569
+ };
570
+ const getStrapiEntryAfterTransaction = ({
571
+ contentTypeService: contentTypeService2,
572
+ contentType: contentType2,
573
+ documentId,
574
+ syncQuery
575
+ }) => new Promise((resolve, reject) => {
576
+ setImmediate(async () => {
577
+ try {
578
+ const strapiEntry = await contentTypeService2.getEntry({
579
+ contentType: contentType2,
580
+ documentId,
581
+ entriesQuery: { ...syncQuery }
582
+ });
583
+ resolve(strapiEntry);
584
+ } catch (error2) {
585
+ reject(error2);
586
+ }
587
+ });
588
+ });
589
+ const buildPreActionSnapshot = async ({
590
+ contentTypeService: contentTypeService2,
591
+ contentType: contentType2,
592
+ documentId,
593
+ statusFilter,
594
+ actionParams,
595
+ indexSyncUsesWildcardLocale
596
+ }) => {
597
+ const preDeleteStrapiEntry = await contentTypeService2.getEntry({
390
598
  contentType: contentType2,
391
599
  documentId,
392
- entriesQuery
393
- }) => new Promise((resolve, reject) => {
394
- setImmediate(async () => {
395
- try {
396
- const entry = await contentTypeService2.getEntry({
397
- contentType: contentType2,
398
- documentId,
399
- entriesQuery: { ...entriesQuery }
400
- });
401
- resolve(entry);
402
- } catch (error2) {
403
- reject(error2);
404
- }
600
+ entriesQuery: { ...statusFilter || {} }
601
+ });
602
+ const shouldFetchLocaleVariants = indexSyncUsesWildcardLocale && isWildcardLocale(actionParams?.locale);
603
+ const localeVariants = shouldFetchLocaleVariants ? await contentTypeService2.getEntries({
604
+ contentType: contentType2,
605
+ fields: ["documentId", "locale"],
606
+ locale: "*",
607
+ ...statusFilter || {},
608
+ filters: {
609
+ documentId
610
+ }
611
+ }) : [];
612
+ const localeCodesToRemove = indexSyncUsesWildcardLocale ? resolveLocaleCodesToRemoveFromIndex({
613
+ actionParams,
614
+ preDeleteStrapiEntry,
615
+ localeVariants
616
+ }) : [];
617
+ return {
618
+ documentId,
619
+ preDeleteStrapiEntry,
620
+ localeVariants,
621
+ localeCodesToRemove
622
+ };
623
+ };
624
+ const collectPreActionSnapshots = async ({
625
+ documentIds,
626
+ contentTypeService: contentTypeService2,
627
+ contentType: contentType2,
628
+ statusFilter,
629
+ actionParams,
630
+ indexSyncUsesWildcardLocale
631
+ }) => {
632
+ return Promise.all(
633
+ documentIds.map(
634
+ (documentId) => buildPreActionSnapshot({
635
+ contentTypeService: contentTypeService2,
636
+ contentType: contentType2,
637
+ documentId,
638
+ statusFilter,
639
+ actionParams,
640
+ indexSyncUsesWildcardLocale
641
+ })
642
+ )
643
+ );
644
+ };
645
+ const normalizeLocaleCodes = (localeCodes) => {
646
+ return [
647
+ ...new Set(
648
+ (localeCodes || []).filter((locale) => typeof locale === "string" && locale.length > 0).map((locale) => locale.trim())
649
+ )
650
+ ];
651
+ };
652
+ const dispatchDeleteTargets = async ({
653
+ meilisearch: meilisearch2,
654
+ contentType: contentType2,
655
+ syncQuery,
656
+ indexSyncUsesWildcardLocale,
657
+ targets
658
+ }) => {
659
+ const validTargets = (targets || []).filter(
660
+ (target) => target && typeof target.documentId === "string" && target.documentId.length > 0
661
+ );
662
+ if (validTargets.length === 0) return;
663
+ const groupedTargets = /* @__PURE__ */ new Map();
664
+ validTargets.forEach((target) => {
665
+ const localeCodes = indexSyncUsesWildcardLocale ? normalizeLocaleCodes(target.localeCodes) : [];
666
+ const groupKey = localeCodes.length > 0 ? [...localeCodes].sort().join("|") : "__no-locales__";
667
+ const currentGroup = groupedTargets.get(groupKey);
668
+ if (currentGroup) {
669
+ currentGroup.documentIds.push(target.documentId);
670
+ return;
671
+ }
672
+ groupedTargets.set(groupKey, {
673
+ documentIds: [target.documentId],
674
+ localeCodes
405
675
  });
406
676
  });
677
+ for (const group of groupedTargets.values()) {
678
+ await meilisearch2.deleteEntriesFromMeiliSearch({
679
+ contentType: contentType2,
680
+ documentIds: [...new Set(group.documentIds)],
681
+ entriesQuery: syncQuery,
682
+ locales: indexSyncUsesWildcardLocale && group.localeCodes.length > 0 ? group.localeCodes : void 0
683
+ });
684
+ }
685
+ };
686
+ async function registerDocumentMiddleware({ strapi: strapi2 }) {
687
+ if (!strapi2?.documents || typeof strapi2.documents.use !== "function") {
688
+ return;
689
+ }
407
690
  strapi2.documents.use(async (ctx, next) => {
408
691
  let result;
409
692
  try {
@@ -425,83 +708,186 @@ async function registerDocumentMiddleware({ strapi: strapi2 }) {
425
708
  "unpublish",
426
709
  "discardDraft"
427
710
  ];
428
- const entriesQuery = meilisearch2.entriesQuery({ contentType: contentType2 });
429
- const shouldDeleteByLocale = isWildcardLocale(entriesQuery.locale);
430
- const { status } = entriesQuery || {};
711
+ const syncQuery = meilisearch2.entriesQuery({ contentType: contentType2 });
712
+ const indexSyncUsesWildcardLocale = isWildcardLocale(syncQuery.locale);
713
+ const { status } = syncQuery || {};
431
714
  const statusFilter = typeof status === "string" && status.length > 0 ? { status } : {};
432
- const preDeleteDocumentId = deleteActions.includes(ctx.action) && ctx?.params?.documentId ? ctx.params.documentId : null;
433
- let preDeleteEntry = null;
434
- let preDeleteLocales = [];
435
- if (preDeleteDocumentId != null) {
436
- preDeleteEntry = await contentTypeService2.getEntry({
437
- contentType: contentType2,
438
- documentId: preDeleteDocumentId,
439
- entriesQuery: { ...statusFilter }
440
- });
441
- if (shouldDeleteByLocale) {
442
- const localeVariants = await contentTypeService2.getEntries({
443
- contentType: contentType2,
444
- fields: ["documentId", "locale"],
445
- locale: "*",
446
- ...statusFilter,
447
- filters: {
448
- documentId: preDeleteDocumentId
715
+ const isDraftIndex = status === "draft";
716
+ const isPublishedIndex = status === "published";
717
+ const shouldSkipDeleteAction = ctx.action === "unpublish" && isDraftIndex || ctx.action === "discardDraft" && isPublishedIndex;
718
+ const shouldTreatAsUpdateAction = updateActions.includes(ctx.action) || ctx.action === "discardDraft" && isDraftIndex;
719
+ const shouldTreatAsDeleteAction = deleteActions.includes(ctx.action) && !shouldTreatAsUpdateAction && !shouldSkipDeleteAction;
720
+ const preActionDocumentIds = resolveDocumentIdsFromActionParams(
721
+ ctx?.params
722
+ );
723
+ const shouldCollectPreActionSnapshots = shouldTreatAsDeleteAction || ctx.action === "discardDraft" && isDraftIndex;
724
+ const preActionSnapshots = shouldCollectPreActionSnapshots ? await collectPreActionSnapshots({
725
+ documentIds: preActionDocumentIds,
726
+ contentTypeService: contentTypeService2,
727
+ contentType: contentType2,
728
+ statusFilter,
729
+ actionParams: ctx?.params,
730
+ indexSyncUsesWildcardLocale
731
+ }) : [];
732
+ const preActionSnapshotsByDocumentId = new Map(
733
+ preActionSnapshots.map((snapshot) => [snapshot.documentId, snapshot])
734
+ );
735
+ result = await next();
736
+ const documentIds = resolveDocumentIds({
737
+ actionParams: ctx?.params,
738
+ result,
739
+ preActionSnapshots
740
+ });
741
+ if (shouldTreatAsUpdateAction && documentIds.length > 0) {
742
+ const resultCandidates = extractStrapiEntryCandidates(result);
743
+ const entriesToUpdate = [];
744
+ const deleteTargets = [];
745
+ for (const documentId of documentIds) {
746
+ if (ctx.action === "discardDraft" && isDraftIndex) {
747
+ const preActionSnapshot = preActionSnapshotsByDocumentId.get(documentId) || null;
748
+ const actionLocale = getActionLocale(ctx?.params);
749
+ const shouldLoadDraftEntriesAcrossLocales = indexSyncUsesWildcardLocale && isWildcardLocale(actionLocale);
750
+ const draftEntriesFromResult = selectDraftEntriesForDiscardDraftResult({
751
+ resultCandidates,
752
+ documentId,
753
+ actionParams: ctx?.params
754
+ });
755
+ let draftEntriesToUpdate = shouldLoadDraftEntriesAcrossLocales ? await contentTypeService2.getEntries({
756
+ contentType: contentType2,
757
+ locale: "*",
758
+ ...statusFilter,
759
+ filters: {
760
+ documentId
761
+ }
762
+ }) : draftEntriesFromResult;
763
+ draftEntriesToUpdate = (draftEntriesToUpdate || []).filter(
764
+ (entry) => entry && !isPublishedStrapiEntry(entry)
765
+ );
766
+ if (draftEntriesToUpdate.length === 0 && shouldLoadDraftEntriesAcrossLocales) {
767
+ draftEntriesToUpdate = draftEntriesFromResult;
768
+ }
769
+ if (draftEntriesToUpdate.length === 0 && !shouldLoadDraftEntriesAcrossLocales) {
770
+ const fallbackStrapiEntry = await getStrapiEntryAfterTransaction({
771
+ contentTypeService: contentTypeService2,
772
+ contentType: contentType2,
773
+ documentId,
774
+ syncQuery: resolveLocaleScopedReadQuery({
775
+ syncQuery,
776
+ actionParams: ctx?.params
777
+ })
778
+ });
779
+ if (fallbackStrapiEntry && !isPublishedStrapiEntry(fallbackStrapiEntry)) {
780
+ draftEntriesToUpdate = [fallbackStrapiEntry];
781
+ }
449
782
  }
783
+ if (draftEntriesToUpdate.length > 0) {
784
+ const normalizedDraftEntries = draftEntriesToUpdate.map(
785
+ (entry) => entry.documentId === documentId ? entry : { ...entry, documentId }
786
+ );
787
+ entriesToUpdate.push(...normalizedDraftEntries);
788
+ }
789
+ const preActionLocaleCodes = resolveLocaleCodesToRemoveFromIndex({
790
+ actionParams: ctx?.params,
791
+ preDeleteStrapiEntry: preActionSnapshot?.preDeleteStrapiEntry || null,
792
+ localeVariants: preActionSnapshot?.localeVariants || []
793
+ });
794
+ const remainingLocaleCodes = collectLocaleCodesFromEntries(draftEntriesToUpdate);
795
+ const localeCodesToDelete = preActionLocaleCodes.filter(
796
+ (localeCode) => !remainingLocaleCodes.includes(localeCode)
797
+ );
798
+ if (localeCodesToDelete.length > 0) {
799
+ deleteTargets.push({
800
+ documentId,
801
+ localeCodes: localeCodesToDelete
802
+ });
803
+ }
804
+ continue;
805
+ }
806
+ let entriesForDocument = [];
807
+ const publishedEntriesFromWildcardPublish = selectPublishedEntriesForWildcardPublish({
808
+ resultCandidates,
809
+ documentId,
810
+ actionParams: ctx?.params,
811
+ syncQuery
450
812
  });
451
- preDeleteLocales = [
452
- ...new Set(
453
- localeVariants.map((entry) => entry?.locale).filter(
454
- (locale) => typeof locale === "string" && locale.length > 0
455
- )
456
- )
457
- ];
458
- }
459
- }
460
- result = await next();
461
- const contextDocumentId = typeof ctx?.params?.documentId === "string" && ctx.params.documentId.length > 0 ? ctx.params.documentId : null;
462
- const documentId = contextDocumentId ?? result?.documentId ?? preDeleteEntry?.documentId ?? preDeleteDocumentId ?? null;
463
- if (updateActions.includes(ctx.action) && documentId != null) {
464
- const resultCandidates = extractEntryCandidates(result);
465
- let entry = getEntryFromResult({
466
- resultCandidates,
467
- documentId,
468
- entriesQuery
469
- });
470
- if (!entry) {
471
- entry = await getEntryOutsideTransaction({
472
- contentTypeService: contentTypeService2,
473
- contentType: contentType2,
813
+ if (publishedEntriesFromWildcardPublish.length > 0) {
814
+ entriesForDocument = publishedEntriesFromWildcardPublish;
815
+ }
816
+ let strapiEntry = selectStrapiEntryToIndexFromResult({
817
+ resultCandidates,
474
818
  documentId,
475
- entriesQuery
819
+ syncQuery,
820
+ actionParams: ctx?.params
476
821
  });
822
+ if (entriesForDocument.length === 0 && !strapiEntry) {
823
+ strapiEntry = await getStrapiEntryAfterTransaction({
824
+ contentTypeService: contentTypeService2,
825
+ contentType: contentType2,
826
+ documentId,
827
+ syncQuery: resolveLocaleScopedReadQuery({
828
+ syncQuery,
829
+ actionParams: ctx?.params
830
+ })
831
+ });
832
+ }
833
+ if (entriesForDocument.length === 0 && strapiEntry) {
834
+ entriesForDocument = [strapiEntry];
835
+ }
836
+ if (entriesForDocument.length > 0) {
837
+ const normalizedEntries = entriesForDocument.map(
838
+ (entry) => entry.documentId === documentId ? entry : { ...entry, documentId }
839
+ );
840
+ entriesToUpdate.push(...normalizedEntries);
841
+ } else if (ctx.action === "create" || ctx.action === "publish") {
842
+ const createPublishLocaleCodesToRemove = indexSyncUsesWildcardLocale ? resolveLocaleCodesToRemoveFromActionResult({
843
+ actionParams: ctx?.params,
844
+ resultCandidates,
845
+ result,
846
+ documentId
847
+ }) : [];
848
+ deleteTargets.push({
849
+ documentId,
850
+ localeCodes: createPublishLocaleCodesToRemove
851
+ });
852
+ } else {
853
+ strapi2.log.info(
854
+ `Meilisearch document middleware skipped indexing ${contentType2} documentId=${documentId} for action ${ctx.action}: no indexable Strapi entry in action result`
855
+ );
856
+ }
477
857
  }
478
- if (entry) {
479
- const normalizedEntry = entry.documentId === documentId ? entry : { ...entry, documentId };
858
+ if (entriesToUpdate.length > 0) {
480
859
  await meilisearch2.updateEntriesInMeilisearch({
481
860
  contentType: contentType2,
482
- entries: [normalizedEntry]
861
+ entries: entriesToUpdate
483
862
  });
484
- } else if (ctx.action === "create" || ctx.action === "publish") {
485
- await meilisearch2.deleteEntriesFromMeiliSearch({
863
+ }
864
+ if (deleteTargets.length > 0) {
865
+ await dispatchDeleteTargets({
866
+ meilisearch: meilisearch2,
486
867
  contentType: contentType2,
487
- documentIds: [documentId],
488
- entriesQuery
868
+ syncQuery,
869
+ indexSyncUsesWildcardLocale,
870
+ targets: deleteTargets
489
871
  });
490
- } else {
491
- strapi2.log.info(
492
- `Meilisearch document middleware skipped indexing ${contentType2} documentId=${documentId} for action ${ctx.action}: no indexable entry in result payload`
493
- );
494
872
  }
495
- } else if (deleteActions.includes(ctx.action)) {
496
- if (documentId != null) {
873
+ } else if (shouldTreatAsDeleteAction) {
874
+ if (documentIds.length > 0) {
875
+ const deleteTargets = documentIds.map((documentId) => {
876
+ const preActionSnapshot = preActionSnapshotsByDocumentId.get(documentId) || null;
877
+ return {
878
+ documentId,
879
+ localeCodes: indexSyncUsesWildcardLocale ? preActionSnapshot?.localeCodesToRemove || [] : []
880
+ };
881
+ });
497
882
  strapi2.log.info(
498
- `Meilisearch document middleware deleting ${contentType2} documentId=${documentId}`
883
+ `Meilisearch document middleware deleting ${contentType2} documentIds=${documentIds.join(",")}`
499
884
  );
500
- await meilisearch2.deleteEntriesFromMeiliSearch({
885
+ await dispatchDeleteTargets({
886
+ meilisearch: meilisearch2,
501
887
  contentType: contentType2,
502
- documentIds: [documentId],
503
- entriesQuery,
504
- locales: shouldDeleteByLocale && preDeleteLocales.length > 0 ? preDeleteLocales : void 0
888
+ syncQuery,
889
+ indexSyncUsesWildcardLocale,
890
+ targets: deleteTargets
505
891
  });
506
892
  } else {
507
893
  strapi2.log.info(
@@ -1636,7 +2022,7 @@ const store = ({ strapi: strapi2 }) => {
1636
2022
  ...createStoreConnector({ strapi: strapi2 })
1637
2023
  };
1638
2024
  };
1639
- const version = "0.16.2";
2025
+ const version = "0.16.3";
1640
2026
  const Meilisearch = (config2) => {
1641
2027
  return new meilisearch$1.MeiliSearch({
1642
2028
  ...config2,