strapi-plugin-meilisearch-plus 0.1.0 → 0.1.2

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
@@ -188,6 +188,7 @@ The plugin supports custom data processing through `transformEntry` and `filterE
188
188
  ### transformEntry
189
189
 
190
190
  Apply custom transformations to entries before indexing. Useful for:
191
+
191
192
  - Flattening nested data structures
192
193
  - Enriching entries with computed fields
193
194
  - Extracting specific fields for search
@@ -224,6 +225,7 @@ Apply custom transformations to entries before indexing. Useful for:
224
225
  ### filterEntry
225
226
 
226
227
  Filter out entries that shouldn't be indexed. Useful for:
228
+
227
229
  - Excluding entries with certain conditions
228
230
  - Filtering by custom field values
229
231
  - Permission-based filtering
@@ -19,7 +19,7 @@ const bootstrap = ({ strapi }) => {
19
19
  );
20
20
  for (const contentType of indexedContentTypes) {
21
21
  try {
22
- lifecycleService.subscribeContentType(contentType);
22
+ lifecycleService.subscribeContentType({ contentType });
23
23
  } catch (error) {
24
24
  strapi.log.warn(`[meilisearch-plus] Failed to subscribe to ${contentType}:`, error);
25
25
  }
@@ -271,7 +271,7 @@ const contentTypes$1 = ({ strapi }) => ({
271
271
  const storeService = strapi.plugin("meilisearch-plus").service("store");
272
272
  const lifecycleService = strapi.plugin("meilisearch-plus").service("lifecycle");
273
273
  await storeService.addIndexedContentType(contentType);
274
- lifecycleService.subscribeContentType(contentType);
274
+ lifecycleService.subscribeContentType({ contentType });
275
275
  const indexedContentTypes = await storeService.getIndexedContentTypes();
276
276
  ctx.body = { data: indexedContentTypes };
277
277
  } catch (error) {
@@ -293,7 +293,7 @@ const contentTypes$1 = ({ strapi }) => ({
293
293
  const meilisearchService = strapi.plugin("meilisearch-plus").service("meilisearch");
294
294
  await meilisearchService.emptyOrDeleteIndex({ contentType });
295
295
  await storeService.removeIndexedContentType(contentType);
296
- lifecycleService.unsubscribeContentType(contentType);
296
+ lifecycleService.unsubscribeContentType({ contentType });
297
297
  const indexedContentTypes = await storeService.getIndexedContentTypes();
298
298
  ctx.body = { data: indexedContentTypes };
299
299
  } catch (error) {
@@ -864,11 +864,20 @@ const meilisearch = ({ strapi }) => ({
864
864
  );
865
865
  taskUids.push(response.taskUid);
866
866
  }
867
+ if (taskUids.length > 0) {
868
+ try {
869
+ await client.waitForTask(taskUids[taskUids.length - 1]);
870
+ strapi.log.debug(`[meilisearch-plus] All indexing tasks completed for ${contentType}`);
871
+ } catch (error) {
872
+ strapi.log.warn(`[meilisearch-plus] Error waiting for indexing tasks:`, error);
873
+ }
874
+ }
867
875
  await storeService.addIndexedContentType(contentType);
868
876
  return taskUids;
869
877
  },
870
878
  /**
871
879
  * Remove all documents for a content type from MeiliSearch
880
+ * Handles pagination in case there are more documents than the search limit
872
881
  */
873
882
  async emptyOrDeleteIndex({ contentType }) {
874
883
  const client = await this.initializeClient();
@@ -880,14 +889,31 @@ const meilisearch = ({ strapi }) => ({
880
889
  return;
881
890
  }
882
891
  const index2 = client.index(finalIndexName);
883
- const searchResult = await index2.search("", {
884
- filter: [`_contentType = "${contentType}"`],
885
- limit: 1e4
886
- });
887
- const ids = searchResult.hits.map((hit) => hit.id);
888
- if (ids.length > 0) {
889
- await index2.deleteDocuments(ids);
890
- strapi.log.info(`[meilisearch-plus] Deleted ${ids.length} documents for ${contentType}`);
892
+ let totalDeleted = 0;
893
+ let hasMore = true;
894
+ while (hasMore) {
895
+ const searchResult = await index2.search("", {
896
+ filter: [`_contentType = "${contentType}"`],
897
+ limit: 1e5,
898
+ offset: 0
899
+ });
900
+ const ids = searchResult.hits.map((hit) => hit.id);
901
+ if (ids.length > 0) {
902
+ const response = await index2.deleteDocuments(ids);
903
+ await client.waitForTask(response.taskUid);
904
+ totalDeleted += ids.length;
905
+ strapi.log.debug(
906
+ `[meilisearch-plus] Batch deleted ${ids.length} documents for ${contentType}`
907
+ );
908
+ }
909
+ hasMore = searchResult.estimatedTotalHits > 0;
910
+ }
911
+ if (totalDeleted > 0) {
912
+ strapi.log.info(
913
+ `[meilisearch-plus] Total deleted: ${totalDeleted} documents for ${contentType}`
914
+ );
915
+ } else {
916
+ strapi.log.info(`[meilisearch-plus] No documents found to delete for ${contentType}`);
891
917
  }
892
918
  await storeService.removeIndexedContentType(contentType);
893
919
  },
@@ -929,17 +955,20 @@ const meilisearch = ({ strapi }) => ({
929
955
  if (contentType) {
930
956
  const searchResult = await index2.search("", {
931
957
  filter: [`_contentType = "${contentType}"`],
932
- limit: 1e4
958
+ limit: 1e5
959
+ // Increased to handle larger datasets
933
960
  });
934
961
  const ids = searchResult.hits.map((hit) => hit.id);
935
962
  if (ids.length > 0) {
936
- await index2.deleteDocuments(ids);
963
+ const response = await index2.deleteDocuments(ids);
964
+ await client.waitForTask(response.taskUid);
937
965
  strapi.log.info(`[meilisearch-plus] Deleted ${ids.length} documents for ${contentType}`);
938
966
  } else {
939
967
  strapi.log.info(`[meilisearch-plus] No documents found for ${contentType} to delete.`);
940
968
  }
941
969
  } else {
942
- await index2.deleteAllDocuments();
970
+ const response = await index2.deleteAllDocuments();
971
+ await client.waitForTask(response.taskUid);
943
972
  strapi.log.info(`[meilisearch-plus] Deleted all documents in index`);
944
973
  }
945
974
  } catch (error) {
@@ -1398,11 +1427,18 @@ const config = ({ strapi }) => {
1398
1427
  },
1399
1428
  /**
1400
1429
  * Get the configuration for a specific content type
1401
- * @param contentType - The short name (e.g., 'page', 'job')
1430
+ * @param contentType - Can be short name (e.g., 'page') or full UID (e.g., 'api::page.page')
1402
1431
  */
1403
1432
  getContentTypeConfig(contentType) {
1404
1433
  const pluginConfig = this.getPluginConfig();
1405
- return pluginConfig[contentType] || {};
1434
+ if (pluginConfig[contentType]) {
1435
+ return pluginConfig[contentType] || {};
1436
+ }
1437
+ const shortName = contentType.split(".").pop();
1438
+ if (shortName && pluginConfig[shortName]) {
1439
+ return pluginConfig[shortName] || {};
1440
+ }
1441
+ return {};
1406
1442
  },
1407
1443
  /**
1408
1444
  * Transform entries using the transformEntry function from plugin config
@@ -18,7 +18,7 @@ const bootstrap = ({ strapi }) => {
18
18
  );
19
19
  for (const contentType of indexedContentTypes) {
20
20
  try {
21
- lifecycleService.subscribeContentType(contentType);
21
+ lifecycleService.subscribeContentType({ contentType });
22
22
  } catch (error) {
23
23
  strapi.log.warn(`[meilisearch-plus] Failed to subscribe to ${contentType}:`, error);
24
24
  }
@@ -270,7 +270,7 @@ const contentTypes$1 = ({ strapi }) => ({
270
270
  const storeService = strapi.plugin("meilisearch-plus").service("store");
271
271
  const lifecycleService = strapi.plugin("meilisearch-plus").service("lifecycle");
272
272
  await storeService.addIndexedContentType(contentType);
273
- lifecycleService.subscribeContentType(contentType);
273
+ lifecycleService.subscribeContentType({ contentType });
274
274
  const indexedContentTypes = await storeService.getIndexedContentTypes();
275
275
  ctx.body = { data: indexedContentTypes };
276
276
  } catch (error) {
@@ -292,7 +292,7 @@ const contentTypes$1 = ({ strapi }) => ({
292
292
  const meilisearchService = strapi.plugin("meilisearch-plus").service("meilisearch");
293
293
  await meilisearchService.emptyOrDeleteIndex({ contentType });
294
294
  await storeService.removeIndexedContentType(contentType);
295
- lifecycleService.unsubscribeContentType(contentType);
295
+ lifecycleService.unsubscribeContentType({ contentType });
296
296
  const indexedContentTypes = await storeService.getIndexedContentTypes();
297
297
  ctx.body = { data: indexedContentTypes };
298
298
  } catch (error) {
@@ -863,11 +863,20 @@ const meilisearch = ({ strapi }) => ({
863
863
  );
864
864
  taskUids.push(response.taskUid);
865
865
  }
866
+ if (taskUids.length > 0) {
867
+ try {
868
+ await client.waitForTask(taskUids[taskUids.length - 1]);
869
+ strapi.log.debug(`[meilisearch-plus] All indexing tasks completed for ${contentType}`);
870
+ } catch (error) {
871
+ strapi.log.warn(`[meilisearch-plus] Error waiting for indexing tasks:`, error);
872
+ }
873
+ }
866
874
  await storeService.addIndexedContentType(contentType);
867
875
  return taskUids;
868
876
  },
869
877
  /**
870
878
  * Remove all documents for a content type from MeiliSearch
879
+ * Handles pagination in case there are more documents than the search limit
871
880
  */
872
881
  async emptyOrDeleteIndex({ contentType }) {
873
882
  const client = await this.initializeClient();
@@ -879,14 +888,31 @@ const meilisearch = ({ strapi }) => ({
879
888
  return;
880
889
  }
881
890
  const index2 = client.index(finalIndexName);
882
- const searchResult = await index2.search("", {
883
- filter: [`_contentType = "${contentType}"`],
884
- limit: 1e4
885
- });
886
- const ids = searchResult.hits.map((hit) => hit.id);
887
- if (ids.length > 0) {
888
- await index2.deleteDocuments(ids);
889
- strapi.log.info(`[meilisearch-plus] Deleted ${ids.length} documents for ${contentType}`);
891
+ let totalDeleted = 0;
892
+ let hasMore = true;
893
+ while (hasMore) {
894
+ const searchResult = await index2.search("", {
895
+ filter: [`_contentType = "${contentType}"`],
896
+ limit: 1e5,
897
+ offset: 0
898
+ });
899
+ const ids = searchResult.hits.map((hit) => hit.id);
900
+ if (ids.length > 0) {
901
+ const response = await index2.deleteDocuments(ids);
902
+ await client.waitForTask(response.taskUid);
903
+ totalDeleted += ids.length;
904
+ strapi.log.debug(
905
+ `[meilisearch-plus] Batch deleted ${ids.length} documents for ${contentType}`
906
+ );
907
+ }
908
+ hasMore = searchResult.estimatedTotalHits > 0;
909
+ }
910
+ if (totalDeleted > 0) {
911
+ strapi.log.info(
912
+ `[meilisearch-plus] Total deleted: ${totalDeleted} documents for ${contentType}`
913
+ );
914
+ } else {
915
+ strapi.log.info(`[meilisearch-plus] No documents found to delete for ${contentType}`);
890
916
  }
891
917
  await storeService.removeIndexedContentType(contentType);
892
918
  },
@@ -928,17 +954,20 @@ const meilisearch = ({ strapi }) => ({
928
954
  if (contentType) {
929
955
  const searchResult = await index2.search("", {
930
956
  filter: [`_contentType = "${contentType}"`],
931
- limit: 1e4
957
+ limit: 1e5
958
+ // Increased to handle larger datasets
932
959
  });
933
960
  const ids = searchResult.hits.map((hit) => hit.id);
934
961
  if (ids.length > 0) {
935
- await index2.deleteDocuments(ids);
962
+ const response = await index2.deleteDocuments(ids);
963
+ await client.waitForTask(response.taskUid);
936
964
  strapi.log.info(`[meilisearch-plus] Deleted ${ids.length} documents for ${contentType}`);
937
965
  } else {
938
966
  strapi.log.info(`[meilisearch-plus] No documents found for ${contentType} to delete.`);
939
967
  }
940
968
  } else {
941
- await index2.deleteAllDocuments();
969
+ const response = await index2.deleteAllDocuments();
970
+ await client.waitForTask(response.taskUid);
942
971
  strapi.log.info(`[meilisearch-plus] Deleted all documents in index`);
943
972
  }
944
973
  } catch (error) {
@@ -1397,11 +1426,18 @@ const config = ({ strapi }) => {
1397
1426
  },
1398
1427
  /**
1399
1428
  * Get the configuration for a specific content type
1400
- * @param contentType - The short name (e.g., 'page', 'job')
1429
+ * @param contentType - Can be short name (e.g., 'page') or full UID (e.g., 'api::page.page')
1401
1430
  */
1402
1431
  getContentTypeConfig(contentType) {
1403
1432
  const pluginConfig = this.getPluginConfig();
1404
- return pluginConfig[contentType] || {};
1433
+ if (pluginConfig[contentType]) {
1434
+ return pluginConfig[contentType] || {};
1435
+ }
1436
+ const shortName = contentType.split(".").pop();
1437
+ if (shortName && pluginConfig[shortName]) {
1438
+ return pluginConfig[shortName] || {};
1439
+ }
1440
+ return {};
1405
1441
  },
1406
1442
  /**
1407
1443
  * Transform entries using the transformEntry function from plugin config
@@ -28,7 +28,7 @@ declare const _default: ({ strapi }: {
28
28
  getPluginConfig(): PluginConfig;
29
29
  /**
30
30
  * Get the configuration for a specific content type
31
- * @param contentType - The short name (e.g., 'page', 'job')
31
+ * @param contentType - Can be short name (e.g., 'page') or full UID (e.g., 'api::page.page')
32
32
  */
33
33
  getContentTypeConfig(contentType: string): ContentTypeConfig;
34
34
  /**
@@ -28,6 +28,7 @@ declare const _default: ({ strapi }: {
28
28
  }): Promise<any[]>;
29
29
  /**
30
30
  * Remove all documents for a content type from MeiliSearch
31
+ * Handles pagination in case there are more documents than the search limit
31
32
  */
32
33
  emptyOrDeleteIndex({ contentType }: {
33
34
  contentType: string;
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.1.0",
2
+ "version": "0.1.2",
3
3
  "keywords": [],
4
4
  "type": "commonjs",
5
5
  "exports": {