strapi-plugin-meilisearch 0.13.4 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -19,7 +19,6 @@
19
19
  <a href="https://github.com/meilisearch/strapi-plugin-meilisearch/actions"><img src="https://github.com/meilisearch/strapi-plugin-meilisearch/workflows/Tests/badge.svg" alt="Tests"></a>
20
20
  <a href="https://github.com/prettier/prettier"><img src="https://img.shields.io/badge/styled_with-prettier-ff69b4.svg" alt="Prettier"></a>
21
21
  <a href="https://github.com/meilisearch/strapi-plugin-meilisearch/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-informational" alt="License"></a>
22
- <a href="https://ms-bors.herokuapp.com/repositories/7"><img src="https://bors.tech/images/badge_small.svg" alt="Bors enabled"></a>
23
22
  </p>
24
23
 
25
24
  <p align="center">⚡ The Meilisearch plugin for Strapi</p>
@@ -614,7 +613,7 @@ yarn playground:build # Build the playground
614
613
  yarn playground:dev # Start the development server
615
614
  ```
616
615
 
617
- This command will install the required dependencies and launch the app in development mode. You should be able to reach it on the [port 8000 of your localhost](http://localhost:8000/admin/).
616
+ This command will install the required dependencies and launch the app in development mode. You should be able to reach it on the [port 1337 of your localhost](http://localhost:1337/admin/).
618
617
 
619
618
  ## 🤖 Compatibility with Meilisearch and Strapi
620
619
 
@@ -4,7 +4,7 @@ const jsxRuntime = require("react/jsx-runtime");
4
4
  const React = require("react");
5
5
  const reactRouterDom = require("react-router-dom");
6
6
  const admin = require("@strapi/strapi/admin");
7
- const index = require("./index-CMmYtjmc.js");
7
+ const index = require("./index-ClWytIVb.js");
8
8
  const designSystem = require("@strapi/design-system");
9
9
  function _interopNamespace(e) {
10
10
  if (e && e.__esModule) return e;
@@ -456,6 +456,21 @@ function useAlert() {
456
456
  blockTransition = true,
457
457
  title
458
458
  }) {
459
+ const docsLabel = i18n(
460
+ "plugin.message.error.meilisearchDocsLink",
461
+ "See more"
462
+ );
463
+ let normalizedLink = link;
464
+ if (link && link.label && typeof link.label === "object") {
465
+ const { id, defaultMessage } = link.label;
466
+ const normalizedId = id?.replace(new RegExp(`^${index.pluginId}\\.`), "") || id;
467
+ normalizedLink = {
468
+ ...link,
469
+ label: i18n(normalizedId, defaultMessage)
470
+ };
471
+ } else if (link && link.url && !link.label) {
472
+ normalizedLink = { ...link, label: docsLabel };
473
+ }
459
474
  toggleNotification({
460
475
  // optional
461
476
  title,
@@ -465,7 +480,7 @@ function useAlert() {
465
480
  // required
466
481
  message: i18n("notification.meilisearch.message", message),
467
482
  // optional
468
- link,
483
+ link: normalizedLink,
469
484
  // optional: default = false
470
485
  blockTransition,
471
486
  // optional
@@ -3,7 +3,7 @@ import * as React from "react";
3
3
  import { useState, useEffect, memo } from "react";
4
4
  import { Routes, Route } from "react-router-dom";
5
5
  import { useNotification, useFetchClient, useRBAC, private_useAutoReloadOverlayBlocker, private_AutoReloadOverlayBlockerProvider, Page, Layouts, BackButton } from "@strapi/strapi/admin";
6
- import { p as pluginId, P as PERMISSIONS } from "./index-BTlN9jCr.mjs";
6
+ import { p as pluginId, P as PERMISSIONS } from "./index-CpAkqqV6.mjs";
7
7
  import { Tr, Td, Checkbox, Typography, Flex, Box, Button, Thead, Th, VisuallyHidden, Table, Tbody, Field, Link, Tabs } from "@strapi/design-system";
8
8
  var __assign = function() {
9
9
  __assign = Object.assign || function __assign2(t) {
@@ -437,6 +437,21 @@ function useAlert() {
437
437
  blockTransition = true,
438
438
  title
439
439
  }) {
440
+ const docsLabel = i18n(
441
+ "plugin.message.error.meilisearchDocsLink",
442
+ "See more"
443
+ );
444
+ let normalizedLink = link;
445
+ if (link && link.label && typeof link.label === "object") {
446
+ const { id, defaultMessage } = link.label;
447
+ const normalizedId = id?.replace(new RegExp(`^${pluginId}\\.`), "") || id;
448
+ normalizedLink = {
449
+ ...link,
450
+ label: i18n(normalizedId, defaultMessage)
451
+ };
452
+ } else if (link && link.url && !link.label) {
453
+ normalizedLink = { ...link, label: docsLabel };
454
+ }
440
455
  toggleNotification({
441
456
  // optional
442
457
  title,
@@ -446,7 +461,7 @@ function useAlert() {
446
461
  // required
447
462
  message: i18n("notification.meilisearch.message", message),
448
463
  // optional
449
- link,
464
+ link: normalizedLink,
450
465
  // optional: default = false
451
466
  blockTransition,
452
467
  // optional
@@ -31,7 +31,8 @@ const en = {
31
31
  "plugin.message.success.credentials": "Credentials successfully updated!",
32
32
  "plugin.message.something": "Something occurred in Meilisearch",
33
33
  "plugin.message.forbidden.title": "Forbidden",
34
- "plugin.message.forbidden.description": "You do not have permission to do this action"
34
+ "plugin.message.forbidden.description": "You do not have permission to do this action",
35
+ "plugin.message.error.meilisearchDocsLink": "See more"
35
36
  };
36
37
  export {
37
38
  en as default
@@ -33,6 +33,7 @@ const en = {
33
33
  "plugin.message.success.credentials": "Credentials successfully updated!",
34
34
  "plugin.message.something": "Something occurred in Meilisearch",
35
35
  "plugin.message.forbidden.title": "Forbidden",
36
- "plugin.message.forbidden.description": "You do not have permission to do this action"
36
+ "plugin.message.forbidden.description": "You do not have permission to do this action",
37
+ "plugin.message.error.meilisearchDocsLink": "See more"
37
38
  };
38
39
  exports.default = en;
@@ -33,6 +33,7 @@ const es = {
33
33
  "plugin.message.success.credentials": "¡Credenciales actualizadas con éxito!",
34
34
  "plugin.message.something": "Algo ha ocurrido en Meilisearch",
35
35
  "plugin.message.forbidden.title": "Prohibido",
36
- "plugin.message.forbidden.description": "No tiene permiso para realizar esta acción"
36
+ "plugin.message.forbidden.description": "No tiene permiso para realizar esta acción",
37
+ "plugin.message.error.meilisearchDocsLink": "Ver más"
37
38
  };
38
39
  exports.default = es;
@@ -31,7 +31,8 @@ const es = {
31
31
  "plugin.message.success.credentials": "¡Credenciales actualizadas con éxito!",
32
32
  "plugin.message.something": "Algo ha ocurrido en Meilisearch",
33
33
  "plugin.message.forbidden.title": "Prohibido",
34
- "plugin.message.forbidden.description": "No tiene permiso para realizar esta acción"
34
+ "plugin.message.forbidden.description": "No tiene permiso para realizar esta acción",
35
+ "plugin.message.error.meilisearchDocsLink": "Ver más"
35
36
  };
36
37
  export {
37
38
  es as default
@@ -19,21 +19,23 @@ const __variableDynamicImportRuntimeHelper = (glob, path, segs) => {
19
19
  });
20
20
  };
21
21
  const name$1 = "strapi-plugin-meilisearch";
22
- const version = "0.13.4";
22
+ const version = "0.14.0";
23
23
  const description = "Synchronise and search in your Strapi content-types with Meilisearch";
24
24
  const scripts = {
25
25
  build: "strapi-plugin build",
26
26
  verify: "strapi-plugin verify",
27
27
  watch: "strapi-plugin watch",
28
28
  "watch:link": "strapi-plugin watch:link",
29
- "playground:dev": "yarn --cwd ./playground && yarn --cwd ./playground dev",
29
+ "playground:setup": "yarn --cwd ./playground setup",
30
+ "playground:dev": "yarn --cwd ./playground dev",
30
31
  "playground:build": "yarn --cwd ./playground && yarn --cwd ./playground build",
31
32
  "playground:ci": "yarn --cwd ./playground ci",
32
33
  style: "eslint --ext .js,.test.js .",
33
34
  "style:fix": "eslint --ext .js,.test.js . --fix",
34
35
  test: "jest --testPathPattern=tests",
35
36
  "test:watch": "jest --watch --testPathPattern=tests --verbose",
36
- "test:e2e:watch": 'concurrently --kill-others -s first "NODE_ENV=test yarn playground:dev" "cypress open --env env=watch"'
37
+ "test:e2e": 'concurrently --kill-others -s first "yarn playground:dev" "cypress run"',
38
+ "test:integrations": "jest -c jest.integration.config.js"
37
39
  };
38
40
  const strapi = {
39
41
  name: "meilisearch",
@@ -81,7 +83,7 @@ const devDependencies = {
81
83
  "@types/jest": "^29.5.12",
82
84
  "babel-jest": "^29.7.0",
83
85
  concurrently: "^8.2.2",
84
- cypress: "^14.0.1",
86
+ cypress: "^15.3.0",
85
87
  eslint: "^8.2.0",
86
88
  "eslint-config-prettier": "^9.1.0",
87
89
  "eslint-plugin-cypress": "^2.12.1",
@@ -211,7 +213,7 @@ const index = {
211
213
  defaultMessage: name
212
214
  },
213
215
  Component: async () => {
214
- const { App } = await Promise.resolve().then(() => require("./App-Dx-0FOiS.js"));
216
+ const { App } = await Promise.resolve().then(() => require("./App-Dn6EGme8.js"));
215
217
  return App;
216
218
  },
217
219
  permissions: PERMISSIONS.main
@@ -220,7 +222,7 @@ const index = {
220
222
  async registerTrads({ locales }) {
221
223
  const importedTranslations = await Promise.all(
222
224
  locales.map((locale) => {
223
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => Promise.resolve().then(() => require("./en-CByedxRT.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-DA_jpbS7.js")) }), `./translations/${locale}.json`, 3).then(({ default: data }) => {
225
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => Promise.resolve().then(() => require("./en-CQvxkk9b.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-D61ltG8N.js")) }), `./translations/${locale}.json`, 3).then(({ default: data }) => {
224
226
  return {
225
227
  data: getTranslation(data),
226
228
  locale
@@ -18,21 +18,23 @@ const __variableDynamicImportRuntimeHelper = (glob, path, segs) => {
18
18
  });
19
19
  };
20
20
  const name$1 = "strapi-plugin-meilisearch";
21
- const version = "0.13.4";
21
+ const version = "0.14.0";
22
22
  const description = "Synchronise and search in your Strapi content-types with Meilisearch";
23
23
  const scripts = {
24
24
  build: "strapi-plugin build",
25
25
  verify: "strapi-plugin verify",
26
26
  watch: "strapi-plugin watch",
27
27
  "watch:link": "strapi-plugin watch:link",
28
- "playground:dev": "yarn --cwd ./playground && yarn --cwd ./playground dev",
28
+ "playground:setup": "yarn --cwd ./playground setup",
29
+ "playground:dev": "yarn --cwd ./playground dev",
29
30
  "playground:build": "yarn --cwd ./playground && yarn --cwd ./playground build",
30
31
  "playground:ci": "yarn --cwd ./playground ci",
31
32
  style: "eslint --ext .js,.test.js .",
32
33
  "style:fix": "eslint --ext .js,.test.js . --fix",
33
34
  test: "jest --testPathPattern=tests",
34
35
  "test:watch": "jest --watch --testPathPattern=tests --verbose",
35
- "test:e2e:watch": 'concurrently --kill-others -s first "NODE_ENV=test yarn playground:dev" "cypress open --env env=watch"'
36
+ "test:e2e": 'concurrently --kill-others -s first "yarn playground:dev" "cypress run"',
37
+ "test:integrations": "jest -c jest.integration.config.js"
36
38
  };
37
39
  const strapi = {
38
40
  name: "meilisearch",
@@ -80,7 +82,7 @@ const devDependencies = {
80
82
  "@types/jest": "^29.5.12",
81
83
  "babel-jest": "^29.7.0",
82
84
  concurrently: "^8.2.2",
83
- cypress: "^14.0.1",
85
+ cypress: "^15.3.0",
84
86
  eslint: "^8.2.0",
85
87
  "eslint-config-prettier": "^9.1.0",
86
88
  "eslint-plugin-cypress": "^2.12.1",
@@ -210,7 +212,7 @@ const index = {
210
212
  defaultMessage: name
211
213
  },
212
214
  Component: async () => {
213
- const { App } = await import("./App-BPVMrqHd.mjs");
215
+ const { App } = await import("./App-d1i42zIj.mjs");
214
216
  return App;
215
217
  },
216
218
  permissions: PERMISSIONS.main
@@ -219,7 +221,7 @@ const index = {
219
221
  async registerTrads({ locales }) {
220
222
  const importedTranslations = await Promise.all(
221
223
  locales.map((locale) => {
222
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => import("./en-D4dIehJl.mjs"), "./translations/es.json": () => import("./es-B-4TrEJr.mjs") }), `./translations/${locale}.json`, 3).then(({ default: data }) => {
224
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => import("./en-BKKKU9na.mjs"), "./translations/es.json": () => import("./es-DvPal5Gh.mjs") }), `./translations/${locale}.json`, 3).then(({ default: data }) => {
223
225
  return {
224
226
  data: getTranslation(data),
225
227
  locale
@@ -1,3 +1,3 @@
1
1
  "use strict";
2
- const index = require("../_chunks/index-CMmYtjmc.js");
2
+ const index = require("../_chunks/index-ClWytIVb.js");
3
3
  module.exports = index.index;
@@ -1,4 +1,4 @@
1
- import { i } from "../_chunks/index-BTlN9jCr.mjs";
1
+ import { i } from "../_chunks/index-CpAkqqV6.mjs";
2
2
  export {
3
3
  i as default
4
4
  };
@@ -90,7 +90,84 @@ const bootstrap = async ({ strapi: strapi2 }) => {
90
90
  };
91
91
  const destroy = () => {
92
92
  };
93
- const register = () => {
93
+ async function registerDocumentMiddleware({ strapi: strapi2 }) {
94
+ if (!strapi2?.documents || typeof strapi2.documents.use !== "function") {
95
+ return;
96
+ }
97
+ strapi2.documents.use(async (ctx, next) => {
98
+ let result;
99
+ try {
100
+ const plugin = strapi2.plugin("meilisearch");
101
+ const store2 = plugin.service("store");
102
+ const meilisearch2 = plugin.service("meilisearch");
103
+ const contentTypeService2 = plugin.service("contentType");
104
+ const listenedContentTypes2 = await store2.getListenedContentTypes();
105
+ if (!listenedContentTypes2.includes(ctx.uid)) {
106
+ return next();
107
+ }
108
+ const contentType2 = ctx.uid;
109
+ const updateActions = ["create", "update", "publish"];
110
+ const deleteActions = [
111
+ "delete",
112
+ "deleteMany",
113
+ "deleteOne",
114
+ "deleteDocument",
115
+ "unpublish",
116
+ "discardDraft"
117
+ ];
118
+ const preDeleteDocumentId = deleteActions.includes(ctx.action) && (ctx?.params?.documentId ?? ctx?.params?.id) ? ctx.params.documentId ?? ctx.params.id : null;
119
+ const preDeleteEntry = preDeleteDocumentId != null ? await contentTypeService2.getEntry({
120
+ contentType: contentType2,
121
+ documentId: preDeleteDocumentId,
122
+ entriesQuery: {}
123
+ }) : null;
124
+ result = await next();
125
+ const id = result?.id ?? preDeleteEntry?.id;
126
+ const documentId = result?.documentId ?? preDeleteEntry?.documentId ?? preDeleteDocumentId ?? null;
127
+ if (updateActions.includes(ctx.action) && documentId != null) {
128
+ const entriesQuery = meilisearch2.entriesQuery({ contentType: contentType2 });
129
+ const entry = await contentTypeService2.getEntry({
130
+ contentType: contentType2,
131
+ documentId,
132
+ entriesQuery: { ...entriesQuery }
133
+ });
134
+ if (entry) {
135
+ await meilisearch2.updateEntriesInMeilisearch({
136
+ contentType: contentType2,
137
+ entries: [{ ...entry, id, documentId }]
138
+ });
139
+ } else if (id != null) {
140
+ await meilisearch2.deleteEntriesFromMeiliSearch({
141
+ contentType: contentType2,
142
+ entriesId: [id]
143
+ });
144
+ }
145
+ } else if (deleteActions.includes(ctx.action)) {
146
+ if (id != null) {
147
+ strapi2.log.info(
148
+ `Meilisearch document middleware deleting ${contentType2} ids=${id}`
149
+ );
150
+ await meilisearch2.deleteEntriesFromMeiliSearch({
151
+ contentType: contentType2,
152
+ entriesId: [id]
153
+ });
154
+ } else {
155
+ strapi2.log.info(
156
+ `Meilisearch document middleware could not delete ${contentType2} for action ${ctx.action}: missing id`
157
+ );
158
+ }
159
+ }
160
+ return result;
161
+ } catch (error2) {
162
+ strapi2.log.error(
163
+ `Meilisearch document middleware error: ${error2.message}`
164
+ );
165
+ return result;
166
+ }
167
+ });
168
+ }
169
+ const register = async ({ strapi: strapi2 }) => {
170
+ await registerDocumentMiddleware({ strapi: strapi2 });
94
171
  };
95
172
  function isObject(elem) {
96
173
  return typeof elem === "object" && !Array.isArray(elem) && elem !== null;
@@ -1372,7 +1449,7 @@ const configurationService = ({ strapi: strapi2 }) => {
1372
1449
  }
1373
1450
  };
1374
1451
  };
1375
- const version = "0.13.4";
1452
+ const version = "0.14.0";
1376
1453
  const Meilisearch = (config2) => {
1377
1454
  return new meilisearch$1.MeiliSearch({
1378
1455
  ...config2,
@@ -1812,137 +1889,11 @@ const lifecycleService = ({ strapi: strapi2 }) => {
1812
1889
  const contentTypeService2 = strapi2.plugin("meilisearch").service("contentType");
1813
1890
  const store2 = strapi2.plugin("meilisearch").service("store");
1814
1891
  return {
1815
- /**
1816
- * Subscribe the content type to all required lifecycles
1817
- *
1818
- * @param {object} options
1819
- * @param {string} options.contentType
1820
- *
1821
- * @returns {Promise<object>}
1822
- */
1823
1892
  async subscribeContentType({ contentType: contentType2 }) {
1824
1893
  const contentTypeUid = contentTypeService2.getContentTypeUid({
1825
1894
  contentType: contentType2
1826
1895
  });
1827
- await strapi2.db.lifecycles.subscribe({
1828
- models: [contentTypeUid],
1829
- async afterCreate(event) {
1830
- const { result } = event;
1831
- const meilisearch2 = strapi2.plugin("meilisearch").service("meilisearch");
1832
- const entry = await contentTypeService2.getEntry({
1833
- contentType: contentTypeUid,
1834
- documentId: result.documentId,
1835
- entriesQuery: {
1836
- ...meilisearch2.entriesQuery({ contentType: contentType2 }),
1837
- locale: result.locale,
1838
- status: "published"
1839
- }
1840
- });
1841
- await meilisearch2.addEntriesToMeilisearch({
1842
- contentType: contentTypeUid,
1843
- entries: [entry]
1844
- }).catch((e) => {
1845
- strapi2.log.error(
1846
- `Meilisearch could not add entry with id: ${result.id}: ${e.message}`
1847
- );
1848
- });
1849
- },
1850
- async afterCreateMany(event) {
1851
- const { result } = event;
1852
- const meilisearch2 = strapi2.plugin("meilisearch").service("meilisearch");
1853
- const nbrEntries = result.count;
1854
- const ids = result.ids;
1855
- const entries = [];
1856
- const BATCH_SIZE = 500;
1857
- for (let pos = 0; pos < nbrEntries; pos += BATCH_SIZE) {
1858
- const batch = await contentTypeService2.getEntries({
1859
- contentType: contentTypeUid,
1860
- start: pos,
1861
- limit: BATCH_SIZE,
1862
- filters: {
1863
- id: {
1864
- $in: ids
1865
- }
1866
- }
1867
- });
1868
- entries.push(...batch);
1869
- }
1870
- meilisearch2.updateEntriesInMeilisearch({
1871
- contentType: contentTypeUid,
1872
- entries
1873
- }).catch((e) => {
1874
- strapi2.log.error(
1875
- `Meilisearch could not update the entries: ${e.message}`
1876
- );
1877
- });
1878
- },
1879
- async afterUpdate(event) {
1880
- const { result } = event;
1881
- const meilisearch2 = strapi2.plugin("meilisearch").service("meilisearch");
1882
- const entry = await contentTypeService2.getEntry({
1883
- contentType: contentTypeUid,
1884
- documentId: result.documentId,
1885
- entriesQuery: {
1886
- ...meilisearch2.entriesQuery({ contentType: contentType2 }),
1887
- locale: result.locale,
1888
- status: "published"
1889
- }
1890
- });
1891
- await meilisearch2.updateEntriesInMeilisearch({
1892
- contentType: contentTypeUid,
1893
- entries: [entry]
1894
- }).catch((e) => {
1895
- strapi2.log.error(
1896
- `Meilisearch could not update entry with id: ${result.id}: ${e.message}`
1897
- );
1898
- });
1899
- },
1900
- async afterUpdateMany(event) {
1901
- const meilisearch2 = strapi2.plugin("meilisearch").service("meilisearch");
1902
- const nbrEntries = await contentTypeService2.numberOfEntries({
1903
- contentType: contentTypeUid,
1904
- filters: event.params.where
1905
- });
1906
- const entries = [];
1907
- const BATCH_SIZE = 500;
1908
- for (let pos = 0; pos < nbrEntries; pos += BATCH_SIZE) {
1909
- const batch = await contentTypeService2.getEntries({
1910
- contentType: contentTypeUid,
1911
- filters: event.params.where,
1912
- start: pos,
1913
- limit: BATCH_SIZE
1914
- });
1915
- entries.push(...batch);
1916
- }
1917
- meilisearch2.updateEntriesInMeilisearch({
1918
- contentType: contentTypeUid,
1919
- entries
1920
- }).catch((e) => {
1921
- strapi2.log.error(
1922
- `Meilisearch could not update the entries: ${e.message}`
1923
- );
1924
- });
1925
- },
1926
- async afterDelete(event) {
1927
- const { result, params } = event;
1928
- const meilisearch2 = strapi2.plugin("meilisearch").service("meilisearch");
1929
- let entriesId = [];
1930
- if (params?.where?.$and && params?.where?.$and[0] && params?.where?.$and[0].id?.$in)
1931
- entriesId = params?.where?.$and[0].id.$in;
1932
- else entriesId = [result.id];
1933
- meilisearch2.deleteEntriesFromMeiliSearch({
1934
- contentType: contentTypeUid,
1935
- entriesId
1936
- }).catch((e) => {
1937
- strapi2.log.error(
1938
- `Meilisearch could not delete entry with id: ${result.id}: ${e.message}`
1939
- );
1940
- });
1941
- },
1942
- async afterDeleteMany(event) {
1943
- this.afterDelete(event);
1944
- }
1945
- });
1896
+ if (!contentTypeUid) return;
1946
1897
  return store2.addListenedContentType({
1947
1898
  contentType: contentTypeUid
1948
1899
  });
@@ -1964,13 +1915,7 @@ const error$1 = ({ strapi: strapi2 }) => {
1964
1915
  return {
1965
1916
  error: {
1966
1917
  message: e.message,
1967
- link: {
1968
- url: e.link || "https://www.meilisearch.com/docs",
1969
- label: {
1970
- id: "notification.meilisearch",
1971
- defaultMessage: "See more"
1972
- }
1973
- }
1918
+ link: e.link ? { url: e.link } : { url: "https://www.meilisearch.com/docs" }
1974
1919
  }
1975
1920
  };
1976
1921
  } else if (e.type === "MeiliSearchCommunicationError") {
@@ -89,7 +89,84 @@ const bootstrap = async ({ strapi: strapi2 }) => {
89
89
  };
90
90
  const destroy = () => {
91
91
  };
92
- const register = () => {
92
+ async function registerDocumentMiddleware({ strapi: strapi2 }) {
93
+ if (!strapi2?.documents || typeof strapi2.documents.use !== "function") {
94
+ return;
95
+ }
96
+ strapi2.documents.use(async (ctx, next) => {
97
+ let result;
98
+ try {
99
+ const plugin = strapi2.plugin("meilisearch");
100
+ const store2 = plugin.service("store");
101
+ const meilisearch2 = plugin.service("meilisearch");
102
+ const contentTypeService2 = plugin.service("contentType");
103
+ const listenedContentTypes2 = await store2.getListenedContentTypes();
104
+ if (!listenedContentTypes2.includes(ctx.uid)) {
105
+ return next();
106
+ }
107
+ const contentType2 = ctx.uid;
108
+ const updateActions = ["create", "update", "publish"];
109
+ const deleteActions = [
110
+ "delete",
111
+ "deleteMany",
112
+ "deleteOne",
113
+ "deleteDocument",
114
+ "unpublish",
115
+ "discardDraft"
116
+ ];
117
+ const preDeleteDocumentId = deleteActions.includes(ctx.action) && (ctx?.params?.documentId ?? ctx?.params?.id) ? ctx.params.documentId ?? ctx.params.id : null;
118
+ const preDeleteEntry = preDeleteDocumentId != null ? await contentTypeService2.getEntry({
119
+ contentType: contentType2,
120
+ documentId: preDeleteDocumentId,
121
+ entriesQuery: {}
122
+ }) : null;
123
+ result = await next();
124
+ const id = result?.id ?? preDeleteEntry?.id;
125
+ const documentId = result?.documentId ?? preDeleteEntry?.documentId ?? preDeleteDocumentId ?? null;
126
+ if (updateActions.includes(ctx.action) && documentId != null) {
127
+ const entriesQuery = meilisearch2.entriesQuery({ contentType: contentType2 });
128
+ const entry = await contentTypeService2.getEntry({
129
+ contentType: contentType2,
130
+ documentId,
131
+ entriesQuery: { ...entriesQuery }
132
+ });
133
+ if (entry) {
134
+ await meilisearch2.updateEntriesInMeilisearch({
135
+ contentType: contentType2,
136
+ entries: [{ ...entry, id, documentId }]
137
+ });
138
+ } else if (id != null) {
139
+ await meilisearch2.deleteEntriesFromMeiliSearch({
140
+ contentType: contentType2,
141
+ entriesId: [id]
142
+ });
143
+ }
144
+ } else if (deleteActions.includes(ctx.action)) {
145
+ if (id != null) {
146
+ strapi2.log.info(
147
+ `Meilisearch document middleware deleting ${contentType2} ids=${id}`
148
+ );
149
+ await meilisearch2.deleteEntriesFromMeiliSearch({
150
+ contentType: contentType2,
151
+ entriesId: [id]
152
+ });
153
+ } else {
154
+ strapi2.log.info(
155
+ `Meilisearch document middleware could not delete ${contentType2} for action ${ctx.action}: missing id`
156
+ );
157
+ }
158
+ }
159
+ return result;
160
+ } catch (error2) {
161
+ strapi2.log.error(
162
+ `Meilisearch document middleware error: ${error2.message}`
163
+ );
164
+ return result;
165
+ }
166
+ });
167
+ }
168
+ const register = async ({ strapi: strapi2 }) => {
169
+ await registerDocumentMiddleware({ strapi: strapi2 });
93
170
  };
94
171
  function isObject(elem) {
95
172
  return typeof elem === "object" && !Array.isArray(elem) && elem !== null;
@@ -1371,7 +1448,7 @@ const configurationService = ({ strapi: strapi2 }) => {
1371
1448
  }
1372
1449
  };
1373
1450
  };
1374
- const version = "0.13.4";
1451
+ const version = "0.14.0";
1375
1452
  const Meilisearch = (config2) => {
1376
1453
  return new MeiliSearch({
1377
1454
  ...config2,
@@ -1811,137 +1888,11 @@ const lifecycleService = ({ strapi: strapi2 }) => {
1811
1888
  const contentTypeService2 = strapi2.plugin("meilisearch").service("contentType");
1812
1889
  const store2 = strapi2.plugin("meilisearch").service("store");
1813
1890
  return {
1814
- /**
1815
- * Subscribe the content type to all required lifecycles
1816
- *
1817
- * @param {object} options
1818
- * @param {string} options.contentType
1819
- *
1820
- * @returns {Promise<object>}
1821
- */
1822
1891
  async subscribeContentType({ contentType: contentType2 }) {
1823
1892
  const contentTypeUid = contentTypeService2.getContentTypeUid({
1824
1893
  contentType: contentType2
1825
1894
  });
1826
- await strapi2.db.lifecycles.subscribe({
1827
- models: [contentTypeUid],
1828
- async afterCreate(event) {
1829
- const { result } = event;
1830
- const meilisearch2 = strapi2.plugin("meilisearch").service("meilisearch");
1831
- const entry = await contentTypeService2.getEntry({
1832
- contentType: contentTypeUid,
1833
- documentId: result.documentId,
1834
- entriesQuery: {
1835
- ...meilisearch2.entriesQuery({ contentType: contentType2 }),
1836
- locale: result.locale,
1837
- status: "published"
1838
- }
1839
- });
1840
- await meilisearch2.addEntriesToMeilisearch({
1841
- contentType: contentTypeUid,
1842
- entries: [entry]
1843
- }).catch((e) => {
1844
- strapi2.log.error(
1845
- `Meilisearch could not add entry with id: ${result.id}: ${e.message}`
1846
- );
1847
- });
1848
- },
1849
- async afterCreateMany(event) {
1850
- const { result } = event;
1851
- const meilisearch2 = strapi2.plugin("meilisearch").service("meilisearch");
1852
- const nbrEntries = result.count;
1853
- const ids = result.ids;
1854
- const entries = [];
1855
- const BATCH_SIZE = 500;
1856
- for (let pos = 0; pos < nbrEntries; pos += BATCH_SIZE) {
1857
- const batch = await contentTypeService2.getEntries({
1858
- contentType: contentTypeUid,
1859
- start: pos,
1860
- limit: BATCH_SIZE,
1861
- filters: {
1862
- id: {
1863
- $in: ids
1864
- }
1865
- }
1866
- });
1867
- entries.push(...batch);
1868
- }
1869
- meilisearch2.updateEntriesInMeilisearch({
1870
- contentType: contentTypeUid,
1871
- entries
1872
- }).catch((e) => {
1873
- strapi2.log.error(
1874
- `Meilisearch could not update the entries: ${e.message}`
1875
- );
1876
- });
1877
- },
1878
- async afterUpdate(event) {
1879
- const { result } = event;
1880
- const meilisearch2 = strapi2.plugin("meilisearch").service("meilisearch");
1881
- const entry = await contentTypeService2.getEntry({
1882
- contentType: contentTypeUid,
1883
- documentId: result.documentId,
1884
- entriesQuery: {
1885
- ...meilisearch2.entriesQuery({ contentType: contentType2 }),
1886
- locale: result.locale,
1887
- status: "published"
1888
- }
1889
- });
1890
- await meilisearch2.updateEntriesInMeilisearch({
1891
- contentType: contentTypeUid,
1892
- entries: [entry]
1893
- }).catch((e) => {
1894
- strapi2.log.error(
1895
- `Meilisearch could not update entry with id: ${result.id}: ${e.message}`
1896
- );
1897
- });
1898
- },
1899
- async afterUpdateMany(event) {
1900
- const meilisearch2 = strapi2.plugin("meilisearch").service("meilisearch");
1901
- const nbrEntries = await contentTypeService2.numberOfEntries({
1902
- contentType: contentTypeUid,
1903
- filters: event.params.where
1904
- });
1905
- const entries = [];
1906
- const BATCH_SIZE = 500;
1907
- for (let pos = 0; pos < nbrEntries; pos += BATCH_SIZE) {
1908
- const batch = await contentTypeService2.getEntries({
1909
- contentType: contentTypeUid,
1910
- filters: event.params.where,
1911
- start: pos,
1912
- limit: BATCH_SIZE
1913
- });
1914
- entries.push(...batch);
1915
- }
1916
- meilisearch2.updateEntriesInMeilisearch({
1917
- contentType: contentTypeUid,
1918
- entries
1919
- }).catch((e) => {
1920
- strapi2.log.error(
1921
- `Meilisearch could not update the entries: ${e.message}`
1922
- );
1923
- });
1924
- },
1925
- async afterDelete(event) {
1926
- const { result, params } = event;
1927
- const meilisearch2 = strapi2.plugin("meilisearch").service("meilisearch");
1928
- let entriesId = [];
1929
- if (params?.where?.$and && params?.where?.$and[0] && params?.where?.$and[0].id?.$in)
1930
- entriesId = params?.where?.$and[0].id.$in;
1931
- else entriesId = [result.id];
1932
- meilisearch2.deleteEntriesFromMeiliSearch({
1933
- contentType: contentTypeUid,
1934
- entriesId
1935
- }).catch((e) => {
1936
- strapi2.log.error(
1937
- `Meilisearch could not delete entry with id: ${result.id}: ${e.message}`
1938
- );
1939
- });
1940
- },
1941
- async afterDeleteMany(event) {
1942
- this.afterDelete(event);
1943
- }
1944
- });
1895
+ if (!contentTypeUid) return;
1945
1896
  return store2.addListenedContentType({
1946
1897
  contentType: contentTypeUid
1947
1898
  });
@@ -1963,13 +1914,7 @@ const error$1 = ({ strapi: strapi2 }) => {
1963
1914
  return {
1964
1915
  error: {
1965
1916
  message: e.message,
1966
- link: {
1967
- url: e.link || "https://www.meilisearch.com/docs",
1968
- label: {
1969
- id: "notification.meilisearch",
1970
- defaultMessage: "See more"
1971
- }
1972
- }
1917
+ link: e.link ? { url: e.link } : { url: "https://www.meilisearch.com/docs" }
1973
1918
  }
1974
1919
  };
1975
1920
  } else if (e.type === "MeiliSearchCommunicationError") {
package/package.json CHANGED
@@ -1,20 +1,22 @@
1
1
  {
2
2
  "name": "strapi-plugin-meilisearch",
3
- "version": "0.13.4",
3
+ "version": "0.14.0",
4
4
  "description": "Synchronise and search in your Strapi content-types with Meilisearch",
5
5
  "scripts": {
6
6
  "build": "strapi-plugin build",
7
7
  "verify": "strapi-plugin verify",
8
8
  "watch": "strapi-plugin watch",
9
9
  "watch:link": "strapi-plugin watch:link",
10
- "playground:dev": "yarn --cwd ./playground && yarn --cwd ./playground dev",
10
+ "playground:setup": "yarn --cwd ./playground setup",
11
+ "playground:dev": "yarn --cwd ./playground dev",
11
12
  "playground:build": "yarn --cwd ./playground && yarn --cwd ./playground build",
12
13
  "playground:ci": "yarn --cwd ./playground ci",
13
14
  "style": "eslint --ext .js,.test.js .",
14
15
  "style:fix": "eslint --ext .js,.test.js . --fix",
15
16
  "test": "jest --testPathPattern=tests",
16
17
  "test:watch": "jest --watch --testPathPattern=tests --verbose",
17
- "test:e2e:watch": "concurrently --kill-others -s first \"NODE_ENV=test yarn playground:dev\" \"cypress open --env env=watch\""
18
+ "test:e2e": "concurrently --kill-others -s first \"yarn playground:dev\" \"cypress run\"",
19
+ "test:integrations": "jest -c jest.integration.config.js"
18
20
  },
19
21
  "strapi": {
20
22
  "name": "meilisearch",
@@ -62,7 +64,7 @@
62
64
  "@types/jest": "^29.5.12",
63
65
  "babel-jest": "^29.7.0",
64
66
  "concurrently": "^8.2.2",
65
- "cypress": "^14.0.1",
67
+ "cypress": "^15.3.0",
66
68
  "eslint": "^8.2.0",
67
69
  "eslint-config-prettier": "^9.1.0",
68
70
  "eslint-plugin-cypress": "^2.12.1",