1+ // @ts -check
2+ /**
3+ * @typedef {typeof defaultConfig } SolrConfig
4+ * @typedef {import(".").SolrDocument } SolrDocument
5+ * @typedef {import(".").SolrData } SolrData
6+ * @typedef {import(".").SolrResponse } SolrResponse
7+ * @typedef {import("axios").AxiosError } AxiosError
8+ * @typedef {import(".").SolrException } SolrException
9+ */
10+
111const url = require ( "url" )
2- const axios = require ( "axios" )
12+ const { default : axios } = require ( "axios" )
313
414const defaultConfig = {
515 hostname : "localhost" ,
616 port : 8983 ,
7- protocol : "http"
17+ protocol : "http" ,
18+ debug : false ,
19+ core : "" ,
20+ apiPrefix : "api/cores"
821}
922
10- const ensureArray = x => ( x instanceof Array ? x : [ x ] )
11-
12- const solrPost = config => path => ( data , coreOpt = "" ) => {
13- const core = coreOpt || config . core
14- if ( ! core ) {
15- throw new Error ( "core not specified" )
16- }
23+ /** @type {(x:object) => object|object[] } */
24+ const ensureArray = x => ( Object ( x ) instanceof Array ? x : [ x ] )
1725
26+ /**
27+ * @type {(config:SolrConfig) => (path:string) => (data:SolrData) => Promise<SolrResponse> }
28+ */
29+ const solrPost = config => path => async data => {
30+ const { core, apiPrefix } = config
1831 const solrUrl = url . format ( {
1932 ...defaultConfig ,
2033 ...config , // overrides defalt config
21- pathname : `solr /${ core } /${ path } ` ,
34+ pathname : `${ apiPrefix } /${ core } /${ path } ` ,
2235 query : {
2336 wt : "json" ,
2437 overwrite : true ,
2538 commitWithin : 1000
2639 }
2740 } )
2841
29- return axios
30- . post ( solrUrl , ensureArray ( data ) , {
31- headers : {
32- "content-type" : "application/json; charset=utf-8" ,
33- accept : "application/json; charset=utf-8"
34- }
35- } )
36- . then ( r => r . data )
42+ if ( config . debug ) {
43+ console . debug ( `\n$ curl '${ solrUrl } ' -d '${ JSON . stringify ( data ) } '\n` )
44+ }
45+
46+ const response = await axios . post ( solrUrl , data , {
47+ headers : {
48+ "content-type" : "application/json; charset=utf-8" ,
49+ accept : "application/json; charset=utf-8"
50+ }
51+ } )
52+
53+ return response . data
3754}
3855
39- const solrGet = config => path => ( query = { } , coreOpt = "" ) => {
40- const core = coreOpt || query . core || config . core
41- if ( ! core ) {
42- throw new Error ( "core not specified" )
43- }
56+ /**
57+ * @type {(config:SolrConfig) => (path:string) => (query:any) => Promise<SolrResponse> }
58+ */
59+ const solrGet = config => path => async query => {
60+ const core = query . core || config . core
61+ const { apiPrefix } = config
4462
4563 // we don't want to alter the query structure
4664 const queryWithoutCore = { ...query }
@@ -49,38 +67,73 @@ const solrGet = config => path => (query = {}, coreOpt = "") => {
4967 const solrUrl = url . format ( {
5068 ...defaultConfig ,
5169 ...config , // overrides defalt config
52- pathname : `solr /${ core } /${ path } ` ,
53- query : queryWithoutCore // DO NOT rename the query parameter!
70+ pathname : `${ apiPrefix } /${ core } /${ path } ` ,
71+ query : queryWithoutCore // DO NOT rename the " query" parameter!
5472 } )
5573
5674 if ( config . debug ) {
57- console . debug ( "SOLR QUERY:" )
58- console . debug ( query )
59- console . debug ( "SOLR HTTP GET: " + solrUrl )
75+ console . debug ( `\n$ curl '${ solrUrl } '\n` )
6076 }
6177
62- return axios ( solrUrl ) . then ( r => r . data )
78+ const response = await axios ( solrUrl )
79+ return response . data
6380}
6481
82+ /**
83+ * Perform an operation on solr schema.
84+ * @see https://lucene.apache.org/solr/guide/7_5/schema-api.html#modify-the-schema
85+ * @param {SolrConfig } config
86+ */
87+ const solrSchema = config => op => data =>
88+ solrPost ( config ) ( "schema" ) ( { [ op ] : data } )
89+
90+ /** @param {SolrConfig } config */
6591const prepareSolrClient = config => ( {
92+ ping : ( ) =>
93+ solrGet ( { ...config , apiPrefix : "solr" } ) ( "admin/ping" ) ( { } )
94+ . then ( value => {
95+ return value . status === "OK"
96+ } )
97+ . catch ( ( ) => false ) ,
98+
99+ /**
100+ * @param {SolrDocument } data */
101+ add : data => solrPost ( config ) ( "update" ) ( ensureArray ( data ) ) ,
102+
103+ /**
104+ * @type {(data: import(".").FieldProperties) => Promise<SolrResponse> }
105+ * @see https://lucene.apache.org/solr/guide/7_5/schema-api.html#add-a-new-field
106+ */
107+ addField : solrSchema ( config ) ( "add-field" ) ,
108+
109+ /**
110+ * @type {(data:import(".").FieldTypeProperties) => Promise<SolrResponse> }
111+ * @see https://lucene.apache.org/solr/guide/7_5/schema-api.html#add-a-new-field-type
112+ */
113+ addFieldType : solrSchema ( config ) ( "add-field-type" ) ,
114+
115+ /**
116+ * @type {({name:string}) => Promise<SolrResponse> }
117+ */
118+ deleteField : solrSchema ( config ) ( "delete-field" ) ,
119+
120+ /**
121+ * @type {({name:string}) => Promise<SolrResponse> }
122+ */
123+ deleteFieldType : solrSchema ( config ) ( "delete-field-type" ) ,
124+
125+ /**
126+ * @type {(query:import(".").SolrSelect) => Promise<SolrResponse> }
127+ */
66128 select : solrGet ( config ) ( "select" ) ,
67- ping : core => solrGet ( config ) ( "admin/ping" ) ( { core } ) ,
68- add : solrPost ( config ) ( "update" ) ,
69- delete : ( ) => Error ( "not implemented yet" ) ,
70- commit : ( ) => Error ( "not implemented yet" ) ,
71- rollback : ( ) => Error ( "not implemented yet" ) ,
72- spell : ( ) => Error ( "not implemented yet" ) ,
73- optimize : ( ) => Error ( "not implemented yet" ) ,
74- realTimeGet : ( ) => Error ( "not implemented yet" ) ,
75- facet : ( jsonFacet , coreOpt = "" ) =>
76- solrGet ( config ) ( "query" ) (
77- {
78- q : "*:*" , // filtering will be implemented later
79- rows : 0 ,
80- "json.facet" : JSON . stringify ( jsonFacet )
81- } ,
82- coreOpt
83- )
129+
130+ facet : ( facetMap , filterArr = [ ] ) =>
131+ solrPost ( config ) ( "query" ) ( {
132+ query : "*:*" ,
133+ limit : "0" ,
134+ filter : filterArr ,
135+ facet : facetMap
136+ } )
84137} )
85138
86139module . exports = {
0 commit comments