@vegan-friendly/strapi-plugin-elasticsearch 0.0.11-alpha.6 → 0.0.11-alpha.7
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/.vscode/settings.json +3 -0
- package/README.md +0 -4
- package/admin/src/components/Initializer/index.js +26 -0
- package/admin/src/components/PluginIcon/index.js +12 -0
- package/admin/src/components/SubNavigation/index.js +48 -0
- package/admin/src/index.js +63 -0
- package/admin/src/pages/App/index.js +29 -0
- package/admin/src/pages/ConfigureCollection/index.js +225 -0
- package/admin/src/pages/ConfigureCollectionList/index.js +266 -0
- package/admin/src/pages/Homepage/index.js +168 -0
- package/admin/src/pages/ViewIndexingRunLog/index.js +124 -0
- package/admin/src/pluginId.js +5 -0
- package/admin/src/translations/en.json +1 -0
- package/admin/src/translations/fr.json +1 -0
- package/admin/src/utils/apiUrls.js +14 -0
- package/admin/src/utils/axiosInstance.js +40 -0
- package/admin/src/utils/getTrad.js +5 -0
- package/package.json +40 -80
- package/server/bootstrap.js +142 -0
- package/server/config/index.js +6 -0
- package/server/content-types/index.js +9 -0
- package/server/content-types/indexing-logs.js +35 -0
- package/server/content-types/name-prefix.js +0 -0
- package/server/content-types/tasks.js +52 -0
- package/server/controllers/configure-indexing.js +66 -0
- package/server/controllers/index.js +15 -0
- package/server/controllers/log-indexing.js +11 -0
- package/server/controllers/perform-indexing.js +28 -0
- package/server/controllers/perform-search.js +31 -0
- package/server/controllers/setup-info.js +14 -0
- package/server/destroy.js +5 -0
- package/server/index.js +25 -0
- package/server/middlewares/index.js +3 -0
- package/server/policies/index.js +3 -0
- package/server/register.js +5 -0
- package/server/routes/configure-indexing.js +42 -0
- package/server/routes/index.js +13 -0
- package/server/routes/perform-indexing.js +24 -0
- package/server/routes/perform-search.js +14 -0
- package/server/routes/run-log.js +12 -0
- package/server/routes/setup-info.js +12 -0
- package/server/services/configure-indexing.js +184 -0
- package/server/services/es-interface.js +187 -0
- package/server/services/helper.js +305 -0
- package/server/services/index.js +19 -0
- package/server/services/log-indexing.js +26 -0
- package/server/services/perform-indexing.js +173 -0
- package/server/services/schedule-indexing.js +65 -0
- package/server/services/transform-content.js +22 -0
- package/strapi-admin.js +3 -0
- package/strapi-server.js +3 -0
- package/dist/_chunks/App-Br53NnT1.mjs +0 -17315
- package/dist/_chunks/App-C3jMSu4l.js +0 -17314
- package/dist/_chunks/en-B4KWt_jN.js +0 -4
- package/dist/_chunks/en-Byx4XI2L.mjs +0 -4
- package/dist/_chunks/index-BlmgBQo2.js +0 -71
- package/dist/_chunks/index-CRnRLV0T.mjs +0 -72
- package/dist/admin/index.js +0 -3
- package/dist/admin/index.mjs +0 -4
- package/dist/server/index.js +0 -7330
- package/dist/server/index.mjs +0 -7307
@@ -0,0 +1,168 @@
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
2
|
+
import { SubNavigation } from '../../components/SubNavigation';;
|
3
|
+
import { Box, Flex, Tab } from '@strapi/design-system';
|
4
|
+
import { Typography } from '@strapi/design-system';
|
5
|
+
import { apiGetElasticsearchSetupInfo, apiRequestReIndexing,
|
6
|
+
apiTriggerIndexing } from '../../utils/apiUrls';
|
7
|
+
import axiosInstance from '../../utils/axiosInstance';
|
8
|
+
import { IconButton } from '@strapi/design-system';
|
9
|
+
import { Table, Tr, Td } from '@strapi/design-system';
|
10
|
+
import { Refresh } from '@strapi/icons';
|
11
|
+
import { TwoColsLayout, Button } from '@strapi/design-system';
|
12
|
+
import { Grid, GridItem, Divider } from '@strapi/design-system';
|
13
|
+
import {LoadingIndicatorPage, useNotification} from '@strapi/helper-plugin';
|
14
|
+
|
15
|
+
const loadElasticsearchSetupInfo = () => {
|
16
|
+
return axiosInstance.get(apiGetElasticsearchSetupInfo)
|
17
|
+
.then((resp) => resp.data)
|
18
|
+
.then((data) => {
|
19
|
+
return data;
|
20
|
+
});
|
21
|
+
}
|
22
|
+
|
23
|
+
const Homepage = () => {
|
24
|
+
const [setupInfo, setSetupInfo] = useState(null);
|
25
|
+
const [isInProgress, setIsInProgress] = useState(false);
|
26
|
+
const toggleNotification = useNotification();
|
27
|
+
|
28
|
+
const displayLabels = {'connected' : 'Connected',
|
29
|
+
'elasticCertificate' : 'Certificate',
|
30
|
+
'elasticHost' : 'Elasticsearch host',
|
31
|
+
'elasticIndexAlias' : 'Elasticsearch index Alias name',
|
32
|
+
'elasticUserName' : 'Elasticsearch username',
|
33
|
+
'indexingCronSchedule' : 'Indexing cron schedule',
|
34
|
+
'initialized' : 'Elasticsearch configuration loaded'};
|
35
|
+
|
36
|
+
const reloadElasticsearchSetupInfo = ({showNotification}) => {
|
37
|
+
setIsInProgress(true);
|
38
|
+
loadElasticsearchSetupInfo()
|
39
|
+
.then(setSetupInfo)
|
40
|
+
.then(() => {
|
41
|
+
if (showNotification)
|
42
|
+
toggleNotification({
|
43
|
+
type: "success", message: "Elasticsearch setup information reloaded.", timeout: 5000
|
44
|
+
});
|
45
|
+
})
|
46
|
+
.finally(() => setIsInProgress(false));
|
47
|
+
}
|
48
|
+
|
49
|
+
const requestFullSiteReindexing = () => {
|
50
|
+
setIsInProgress(true);
|
51
|
+
return axiosInstance.get(apiRequestReIndexing)
|
52
|
+
.then(() => {
|
53
|
+
toggleNotification({
|
54
|
+
type: "success", message: "Rebuilding the index is triggered.", timeout: 5000
|
55
|
+
});
|
56
|
+
})
|
57
|
+
.catch(() => {
|
58
|
+
toggleNotification({
|
59
|
+
type: "warning", message: "An error was encountered.", timeout: 5000
|
60
|
+
});
|
61
|
+
})
|
62
|
+
.finally(() => setIsInProgress(false));
|
63
|
+
}
|
64
|
+
|
65
|
+
const triggerIndexingRun = () => {
|
66
|
+
setIsInProgress(true);
|
67
|
+
return axiosInstance.get(apiTriggerIndexing)
|
68
|
+
.then(() => {
|
69
|
+
toggleNotification({
|
70
|
+
type: "success", message: "The indexing job to process the pending tasks is started.", timeout: 5000
|
71
|
+
});
|
72
|
+
})
|
73
|
+
.catch(() => {
|
74
|
+
toggleNotification({
|
75
|
+
type: "warning", message: "An error was encountered.", timeout: 5000
|
76
|
+
});
|
77
|
+
})
|
78
|
+
.finally(() => setIsInProgress(false));
|
79
|
+
}
|
80
|
+
useEffect(() => {
|
81
|
+
reloadElasticsearchSetupInfo({showNotification: false});
|
82
|
+
}, []);
|
83
|
+
|
84
|
+
if (setupInfo === null)
|
85
|
+
return <LoadingIndicatorPage />
|
86
|
+
else
|
87
|
+
return (
|
88
|
+
<Flex alignItems="stretch" gap={4}>
|
89
|
+
<SubNavigation />
|
90
|
+
<Box padding={8} background="neutral100" width="100%">
|
91
|
+
<Box paddingBottom={4}>
|
92
|
+
<Typography variant="alpha">Setup Information</Typography>
|
93
|
+
</Box>
|
94
|
+
<Box width="100%" paddingBottom={4}>
|
95
|
+
<TwoColsLayout startCol={
|
96
|
+
<>
|
97
|
+
<Table>
|
98
|
+
{
|
99
|
+
setupInfo && (
|
100
|
+
Object.keys(setupInfo).map((k, idx) => {
|
101
|
+
return (
|
102
|
+
<Tr key={idx}>
|
103
|
+
<Td><Box padding={2}>
|
104
|
+
<Typography textColor="neutral600">{displayLabels[k]} :</Typography>
|
105
|
+
</Box></Td>
|
106
|
+
<Td>
|
107
|
+
<Box padding={2}>
|
108
|
+
<Grid>
|
109
|
+
<GridItem padding={2}>
|
110
|
+
{
|
111
|
+
k === 'connected' && setupInfo[k] === true &&
|
112
|
+
(
|
113
|
+
<Typography fontWeight="bold" textColor="success500">Yes</Typography>
|
114
|
+
)
|
115
|
+
}
|
116
|
+
{
|
117
|
+
k === 'connected' && setupInfo[k] === false &&
|
118
|
+
(
|
119
|
+
<Typography fontWeight="bold" textColor="danger500">No</Typography>
|
120
|
+
)
|
121
|
+
}
|
122
|
+
{
|
123
|
+
k !== 'connected' &&
|
124
|
+
(
|
125
|
+
<Typography textColor="neutral600">{String(setupInfo[k])}</Typography>
|
126
|
+
)
|
127
|
+
}
|
128
|
+
</GridItem>
|
129
|
+
<GridItem padding={1}>
|
130
|
+
{
|
131
|
+
k === 'connected' ?
|
132
|
+
<IconButton disabled={isInProgress} onClick={() => reloadElasticsearchSetupInfo({showNotification: true})} label="Refresh" icon={<Refresh />} /> : null
|
133
|
+
}
|
134
|
+
</GridItem>
|
135
|
+
</Grid>
|
136
|
+
</Box>
|
137
|
+
</Td>
|
138
|
+
</Tr>
|
139
|
+
);
|
140
|
+
})
|
141
|
+
)
|
142
|
+
}
|
143
|
+
</Table></>}
|
144
|
+
endCol={<>
|
145
|
+
<Box paddingLeft={2} paddingRight={2} paddingTop={4} paddingBottom={4} >
|
146
|
+
<Box paddingTop={4} paddingBottom={4}>
|
147
|
+
<Typography variant="pi" fontWeight="bold" textColor="neutral600" >ACTIONS</Typography>
|
148
|
+
</Box>
|
149
|
+
<Divider />
|
150
|
+
<Box paddingTop={4} paddingBottom={4}>
|
151
|
+
<Box paddingTop={2} paddingBottom={2}>
|
152
|
+
<Button loading={isInProgress} fullWidth variant="secondary" onClick={requestFullSiteReindexing}>Rebuild Index</Button>
|
153
|
+
</Box>
|
154
|
+
<Box paddingTop={2} paddingBottom={2}>
|
155
|
+
<Button loading={isInProgress} fullWidth variant="secondary" onClick={triggerIndexingRun}>Trigger Indexing</Button>
|
156
|
+
</Box>
|
157
|
+
</Box>
|
158
|
+
</Box>
|
159
|
+
</>
|
160
|
+
} />
|
161
|
+
</Box>
|
162
|
+
</Box>
|
163
|
+
</Flex>
|
164
|
+
);
|
165
|
+
};
|
166
|
+
|
167
|
+
|
168
|
+
export default Homepage;
|
@@ -0,0 +1,124 @@
|
|
1
|
+
/*
|
2
|
+
*
|
3
|
+
* HomePage
|
4
|
+
*
|
5
|
+
*/
|
6
|
+
|
7
|
+
import React, { useState, useEffect } from 'react';
|
8
|
+
// import PropTypes from 'prop-types';
|
9
|
+
import pluginId from '../../pluginId';
|
10
|
+
import { SubNavigation } from '../../components/SubNavigation';;
|
11
|
+
import { Box, Flex } from '@strapi/design-system';
|
12
|
+
import { apiFetchRecentIndexingRunLog } from "../../utils/apiUrls";
|
13
|
+
import axiosInstance from '../../utils/axiosInstance';
|
14
|
+
import { Table, Thead, Tbody, Tr, Td, Th } from '@strapi/design-system';
|
15
|
+
import { Typography } from '@strapi/design-system';
|
16
|
+
import {LoadingIndicatorPage} from '@strapi/helper-plugin';
|
17
|
+
|
18
|
+
const loadRecentIndexingRuns = () => {
|
19
|
+
return axiosInstance.get(apiFetchRecentIndexingRunLog)
|
20
|
+
.then((resp) => resp.data)
|
21
|
+
.then((data) => {
|
22
|
+
return data;
|
23
|
+
});
|
24
|
+
}
|
25
|
+
|
26
|
+
const formattedDate = (dateString) => {
|
27
|
+
const date = new Date(dateString);
|
28
|
+
const options = {
|
29
|
+
weekday: 'long',
|
30
|
+
year: 'numeric',
|
31
|
+
month: 'numeric',
|
32
|
+
day: 'numeric',
|
33
|
+
hour: 'numeric',
|
34
|
+
minute: 'numeric',
|
35
|
+
};
|
36
|
+
|
37
|
+
const dateTimeFormat = new Intl.DateTimeFormat('en-US', options);
|
38
|
+
const parts = dateTimeFormat.formatToParts(date);
|
39
|
+
|
40
|
+
let formattedDate = '';
|
41
|
+
parts.forEach((part) => {
|
42
|
+
if (part.type === "weekday")
|
43
|
+
formattedDate+= `${part.value}, `;
|
44
|
+
if (part.type === "day")
|
45
|
+
formattedDate+= `${part.value}/`;
|
46
|
+
if (part.type === "month")
|
47
|
+
formattedDate+= `${part.value}/`;
|
48
|
+
if (part.type === "year")
|
49
|
+
formattedDate+= `${part.value} `;
|
50
|
+
if (part.type === "hour")
|
51
|
+
formattedDate+= `${part.value}:`;
|
52
|
+
if (part.type === "minute")
|
53
|
+
formattedDate+= `${part.value}`;
|
54
|
+
});
|
55
|
+
|
56
|
+
return formattedDate;
|
57
|
+
}
|
58
|
+
|
59
|
+
const ViewIndexingRunLog = () => {
|
60
|
+
const [logTable, setLogTable] = useState(null);
|
61
|
+
useEffect(() => {
|
62
|
+
loadRecentIndexingRuns()
|
63
|
+
.then(setLogTable)
|
64
|
+
}, []);
|
65
|
+
|
66
|
+
if (logTable === null)
|
67
|
+
return <LoadingIndicatorPage />
|
68
|
+
else
|
69
|
+
return (
|
70
|
+
<Flex alignItems="stretch" gap={4}>
|
71
|
+
<SubNavigation />
|
72
|
+
<Box padding={8} background="neutral100" width="100%">
|
73
|
+
<Box paddingBottom={4}>
|
74
|
+
<Typography variant="alpha">Recent Indexing Run Logs</Typography>
|
75
|
+
</Box>
|
76
|
+
{
|
77
|
+
logTable && logTable.length > 0 && (
|
78
|
+
<>
|
79
|
+
<Table colCount={3} rowCount={logTable.length}>
|
80
|
+
<Thead>
|
81
|
+
<Tr>
|
82
|
+
<Th>
|
83
|
+
<Typography variant="sigma">Date</Typography>
|
84
|
+
</Th>
|
85
|
+
<Th>
|
86
|
+
<Typography variant="sigma">Status</Typography>
|
87
|
+
</Th>
|
88
|
+
<Th>
|
89
|
+
<Typography variant="sigma">Details</Typography>
|
90
|
+
</Th>
|
91
|
+
</Tr>
|
92
|
+
</Thead>
|
93
|
+
<Tbody>
|
94
|
+
{
|
95
|
+
logTable.map((data, index) => {
|
96
|
+
return (
|
97
|
+
<Tr key={index}>
|
98
|
+
<Td>
|
99
|
+
<Typography textColor="neutral600">{formattedDate(data.createdAt)}</Typography>
|
100
|
+
</Td>
|
101
|
+
<Td>
|
102
|
+
<Typography textColor="neutral600">{data.status}</Typography>
|
103
|
+
</Td>
|
104
|
+
<Td>
|
105
|
+
<Typography textColor="neutral600">{data.details}</Typography>
|
106
|
+
</Td>
|
107
|
+
</Tr>
|
108
|
+
);
|
109
|
+
})
|
110
|
+
}
|
111
|
+
</Tbody>
|
112
|
+
</Table>
|
113
|
+
<Box paddingTop={2} paddingBottom={2}>
|
114
|
+
<Typography textColor="neutral600">This view lists the details of the 50 recent-most indexing runs.</Typography>
|
115
|
+
</Box>
|
116
|
+
</>
|
117
|
+
)
|
118
|
+
}
|
119
|
+
</Box>
|
120
|
+
</Flex>
|
121
|
+
);
|
122
|
+
};
|
123
|
+
|
124
|
+
export default ViewIndexingRunLog;
|
@@ -0,0 +1 @@
|
|
1
|
+
{}
|
@@ -0,0 +1 @@
|
|
1
|
+
{}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import { collectionName } from "../../../server/content-types/tasks";
|
2
|
+
import pluginId from "../pluginId";
|
3
|
+
export const apiGetContentConfig = `/${pluginId}/content-config/`
|
4
|
+
export const apiGetCollectionConfig = (collectionName) => `/${pluginId}/collection-config/${collectionName}`
|
5
|
+
export const apiSaveCollectionConfig = (collectionName) => `/${pluginId}/collection-config/${collectionName}`
|
6
|
+
export const apiGetElasticsearchSetupInfo = `/${pluginId}/setup-info`
|
7
|
+
export const apiFetchRecentIndexingRunLog = `/${pluginId}/indexing-run-log`
|
8
|
+
export const apiRequestReIndexing = `/${pluginId}/reindex`
|
9
|
+
export const apiRequestCollectionIndexing = (collectionName) => `/${pluginId}/collection-reindex/${collectionName}`
|
10
|
+
export const apiTriggerIndexing = `/${pluginId}/trigger-indexing/`
|
11
|
+
|
12
|
+
export const apiExportContentConfig = `/${pluginId}/export-content-config/`
|
13
|
+
export const apiImportContentConfig = `/${pluginId}/import-content-config/`
|
14
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
/**
|
2
|
+
* axios with a custom config.
|
3
|
+
*/
|
4
|
+
|
5
|
+
import axios from 'axios';
|
6
|
+
import { auth } from '@strapi/helper-plugin';
|
7
|
+
|
8
|
+
const instance = axios.create({
|
9
|
+
baseURL: process.env.STRAPI_ADMIN_BACKEND_URL,
|
10
|
+
});
|
11
|
+
|
12
|
+
instance.interceptors.request.use(
|
13
|
+
async config => {
|
14
|
+
config.headers = {
|
15
|
+
Authorization: `Bearer ${auth.getToken()}`,
|
16
|
+
Accept: 'application/json',
|
17
|
+
'Content-Type': 'application/json',
|
18
|
+
};
|
19
|
+
|
20
|
+
return config;
|
21
|
+
},
|
22
|
+
error => {
|
23
|
+
Promise.reject(error);
|
24
|
+
}
|
25
|
+
);
|
26
|
+
|
27
|
+
instance.interceptors.response.use(
|
28
|
+
response => response,
|
29
|
+
error => {
|
30
|
+
// whatever you want to do with the error
|
31
|
+
if (error.response?.status === 401) {
|
32
|
+
auth.clearAppStorage();
|
33
|
+
window.location.reload();
|
34
|
+
}
|
35
|
+
|
36
|
+
throw error;
|
37
|
+
}
|
38
|
+
);
|
39
|
+
|
40
|
+
export default instance;
|
package/package.json
CHANGED
@@ -1,80 +1,40 @@
|
|
1
|
-
{
|
2
|
-
"name": "@vegan-friendly/strapi-plugin-elasticsearch",
|
3
|
-
"
|
4
|
-
"
|
5
|
-
"
|
6
|
-
"
|
7
|
-
|
8
|
-
"
|
9
|
-
"
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
"
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
"
|
26
|
-
"
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
"
|
31
|
-
"
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
"dist"
|
42
|
-
],
|
43
|
-
"scripts": {
|
44
|
-
"build": "strapi-plugin build",
|
45
|
-
"watch": "strapi-plugin watch",
|
46
|
-
"watch:link": "strapi-plugin watch:link",
|
47
|
-
"verify": "strapi-plugin verify"
|
48
|
-
},
|
49
|
-
"dependencies": {
|
50
|
-
"@elastic/elasticsearch": "^8.17.1",
|
51
|
-
"@radix-ui/react-tooltip": "^1.1.8",
|
52
|
-
"@strapi/design-system": "^2.0.0-rc.18",
|
53
|
-
"@strapi/icons": "^2.0.0-rc.18",
|
54
|
-
"markdown-to-txt": "^2.0.1",
|
55
|
-
"react-intl": "^7.1.9"
|
56
|
-
},
|
57
|
-
"devDependencies": {
|
58
|
-
"@strapi/sdk-plugin": "^5.3.2 || ^4.0.0",
|
59
|
-
"@strapi/strapi": "^5.11.3 || ^4.0.0",
|
60
|
-
"prettier": "^3.5.3",
|
61
|
-
"react": "^18.3.1",
|
62
|
-
"react-dom": "^18.3.1",
|
63
|
-
"react-router-dom": "^6.30.0 || ^5",
|
64
|
-
"styled-components": "^6.1.16 || ^5"
|
65
|
-
},
|
66
|
-
"peerDependencies": {
|
67
|
-
"@strapi/sdk-plugin": "^5.3.2 || ^4.0.0",
|
68
|
-
"@strapi/strapi": "^5.11.3 || ^4.0.0",
|
69
|
-
"react": "^18.3.1",
|
70
|
-
"react-dom": "^18.3.1",
|
71
|
-
"react-router-dom": "^6.30.0 || ^5",
|
72
|
-
"styled-components": "^6.1.16 || ^5"
|
73
|
-
},
|
74
|
-
"strapi": {
|
75
|
-
"name": "elasticsearch",
|
76
|
-
"description": "A plugin to enable using Elasticsearch with Strapi CMS.",
|
77
|
-
"kind": "plugin",
|
78
|
-
"displayName": "Strapi <-> Elasticsearch"
|
79
|
-
}
|
80
|
-
}
|
1
|
+
{
|
2
|
+
"name": "@vegan-friendly/strapi-plugin-elasticsearch",
|
3
|
+
"version": "0.0.11-alpha.7",
|
4
|
+
"description": "A Strapi plugin to enable using Elasticsearch with Strapi CMS.",
|
5
|
+
"homepage": "https://github.com/vegan-friendly/strapi-plugin-elasticsearch",
|
6
|
+
"strapi": {
|
7
|
+
"name": "elasticsearch",
|
8
|
+
"description": "A plugin to enable using Elasticsearch with Strapi CMS.",
|
9
|
+
"kind": "plugin",
|
10
|
+
"displayName": "Strapi <-> Elasticsearch"
|
11
|
+
},
|
12
|
+
"repository": {
|
13
|
+
"type": "git",
|
14
|
+
"url": "git://github.com/vegan-friendly/strapi-plugin-elasticsearch.git"
|
15
|
+
},
|
16
|
+
"author": {
|
17
|
+
"name": "Punit Sethi",
|
18
|
+
"email": "punit@tezify.com",
|
19
|
+
"url": "https://punits.dev"
|
20
|
+
},
|
21
|
+
"dependencies": {
|
22
|
+
"@elastic/elasticsearch": "^8.9.0",
|
23
|
+
"markdown-to-txt": "^2.0.1"
|
24
|
+
},
|
25
|
+
"peerDependencies": {
|
26
|
+
"@strapi/strapi": "^4.0.0"
|
27
|
+
},
|
28
|
+
"maintainers": [
|
29
|
+
{
|
30
|
+
"name": "Punit Sethi",
|
31
|
+
"email": "punit@tezify.com",
|
32
|
+
"url": "https://punits.dev"
|
33
|
+
}
|
34
|
+
],
|
35
|
+
"engines": {
|
36
|
+
"node": ">=16.0.0 <=20.x.x",
|
37
|
+
"npm": ">=6.0.0"
|
38
|
+
},
|
39
|
+
"license": "MIT"
|
40
|
+
}
|
@@ -0,0 +1,142 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
module.exports = async ({ strapi }) => {
|
4
|
+
const pluginConfig = await strapi.config.get('plugin.elasticsearch');
|
5
|
+
const configureIndexingService = strapi.plugins['elasticsearch'].services.configureIndexing;
|
6
|
+
const scheduleIndexingService = strapi.plugins['elasticsearch'].services.scheduleIndexing;
|
7
|
+
const esInterface = strapi.plugins['elasticsearch'].services.esInterface;
|
8
|
+
const indexer = strapi.plugins['elasticsearch'].services.indexer;
|
9
|
+
const helper = strapi.plugins['elasticsearch'].services.helper;
|
10
|
+
try
|
11
|
+
{
|
12
|
+
await configureIndexingService.initializeStrapiElasticsearch();
|
13
|
+
|
14
|
+
if (!Object.keys(pluginConfig).includes('indexingCronSchedule'))
|
15
|
+
console.warn("The plugin strapi-plugin-elasticsearch is enabled but the indexingCronSchedule is not configured.");
|
16
|
+
else if (!Object.keys(pluginConfig).includes('searchConnector'))
|
17
|
+
console.warn("The plugin strapi-plugin-elasticsearch is enabled but the searchConnector is not configured.");
|
18
|
+
else
|
19
|
+
{
|
20
|
+
const connector = pluginConfig['searchConnector'];
|
21
|
+
await esInterface.initializeSearchEngine({host : connector.host, uname: connector.username,
|
22
|
+
password: connector.password, cert: connector.certificate});
|
23
|
+
strapi.cron.add({
|
24
|
+
elasticsearchIndexing: {
|
25
|
+
task: async ({ strapi }) => {
|
26
|
+
await indexer.indexPendingData();
|
27
|
+
},
|
28
|
+
options: {
|
29
|
+
rule: pluginConfig['indexingCronSchedule'],
|
30
|
+
},
|
31
|
+
},
|
32
|
+
});
|
33
|
+
|
34
|
+
if (await esInterface.checkESConnection())
|
35
|
+
{
|
36
|
+
//Attach the alias to the current index:
|
37
|
+
const idxName = await helper.getCurrentIndexName();
|
38
|
+
await esInterface.attachAliasToIndex(idxName);
|
39
|
+
}
|
40
|
+
|
41
|
+
}
|
42
|
+
|
43
|
+
strapi.db.lifecycles.subscribe(async (event) => {
|
44
|
+
if (event.action === 'afterCreate' || event.action === 'afterUpdate') {
|
45
|
+
if (strapi.elasticsearch.collections.includes(event.model.uid))
|
46
|
+
{
|
47
|
+
//collection without draft-publish
|
48
|
+
if (typeof event.model.attributes.publishedAt === "undefined")
|
49
|
+
{
|
50
|
+
await scheduleIndexingService.addItemToIndex({
|
51
|
+
collectionUid: event.model.uid,
|
52
|
+
recordId: event.result.id
|
53
|
+
});
|
54
|
+
}
|
55
|
+
else if (event.model.attributes.publishedAt)
|
56
|
+
{
|
57
|
+
if (event.result.publishedAt)
|
58
|
+
{
|
59
|
+
await scheduleIndexingService.addItemToIndex({
|
60
|
+
collectionUid: event.model.uid,
|
61
|
+
recordId: event.result.id
|
62
|
+
});
|
63
|
+
}
|
64
|
+
else
|
65
|
+
{
|
66
|
+
//unpublish
|
67
|
+
await scheduleIndexingService.removeItemFromIndex({
|
68
|
+
collectionUid: event.model.uid,
|
69
|
+
recordId: event.result.id
|
70
|
+
});
|
71
|
+
}
|
72
|
+
}
|
73
|
+
}
|
74
|
+
}
|
75
|
+
//bulk publish-unpublish from list view
|
76
|
+
if (event.action === 'afterCreateMany' || event.action === 'afterUpdateMany') {
|
77
|
+
if (strapi.elasticsearch.collections.includes(event.model.uid))
|
78
|
+
{
|
79
|
+
if (Object.keys(event.params.where.id).includes('$in'))
|
80
|
+
{
|
81
|
+
const updatedItemIds = event.params.where.id['$in']
|
82
|
+
//bulk unpublish
|
83
|
+
if (typeof event.params.data.publishedAt === "undefined" ||
|
84
|
+
event.params.data.publishedAt === null)
|
85
|
+
{
|
86
|
+
for (let k = 0; k< updatedItemIds.length; k++)
|
87
|
+
{
|
88
|
+
await scheduleIndexingService.removeItemFromIndex({
|
89
|
+
collectionUid: event.model.uid,
|
90
|
+
recordId: updatedItemIds[k]
|
91
|
+
});
|
92
|
+
}
|
93
|
+
}
|
94
|
+
else
|
95
|
+
{
|
96
|
+
for (let k = 0; k< updatedItemIds.length; k++)
|
97
|
+
{
|
98
|
+
await scheduleIndexingService.addItemToIndex({
|
99
|
+
collectionUid: event.model.uid,
|
100
|
+
recordId: updatedItemIds[k]
|
101
|
+
});
|
102
|
+
}
|
103
|
+
}
|
104
|
+
}
|
105
|
+
}
|
106
|
+
}
|
107
|
+
if (event.action === 'afterDelete') {
|
108
|
+
if (strapi.elasticsearch.collections.includes(event.model.uid))
|
109
|
+
{
|
110
|
+
await scheduleIndexingService.removeItemFromIndex({
|
111
|
+
collectionUid: event.model.uid,
|
112
|
+
recordId: event.result.id
|
113
|
+
});
|
114
|
+
}
|
115
|
+
}
|
116
|
+
if (event.action === 'afterDeleteMany') {
|
117
|
+
if (strapi.elasticsearch.collections.includes(event.model.uid))
|
118
|
+
{
|
119
|
+
if (Object.keys(event.params.where).includes('$and') &&
|
120
|
+
Array.isArray(event.params.where['$and']) &&
|
121
|
+
Object.keys(event.params.where['$and'][0]).includes('id') &&
|
122
|
+
Object.keys(event.params.where['$and'][0]['id']).includes('$in'))
|
123
|
+
{
|
124
|
+
const deletedItemIds = event.params.where['$and'][0]['id']['$in']
|
125
|
+
for (let k = 0; k< deletedItemIds.length; k++)
|
126
|
+
{
|
127
|
+
await scheduleIndexingService.removeItemFromIndex({
|
128
|
+
collectionUid: event.model.uid,
|
129
|
+
recordId: deletedItemIds[k]
|
130
|
+
});
|
131
|
+
}
|
132
|
+
}
|
133
|
+
}
|
134
|
+
}
|
135
|
+
});
|
136
|
+
configureIndexingService.markInitialized();
|
137
|
+
}
|
138
|
+
catch(err) {
|
139
|
+
console.error('An error was encountered while initializing the strapi-plugin-elasticsearch plugin.')
|
140
|
+
console.error(err);
|
141
|
+
}
|
142
|
+
};
|