pixl-server-storage 3.1.7 → 3.1.9

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/docs/API.md CHANGED
@@ -1367,7 +1367,7 @@ storage.getFieldSummary( FIELD_ID, CONFIG, CALLBACK );
1367
1367
  The `getFieldSummary()` method fetches a summary of all word counts for an index field. This requires a field indexed with the [master list](Indexer.md#master-list) feature enabled. Then you can fetch a "summary" of the data values, which returns a hash containing all the unique words from the index, and their total counts (occurrences) in the data. Example use:
1368
1368
 
1369
1369
  ```js
1370
- stotage.getFieldSummary( 'status', config, function(err, values) {
1370
+ storage.getFieldSummary( 'status', config, function(err, values) {
1371
1371
  if (err) throw err;
1372
1372
 
1373
1373
  // values should contain a hash with word counts:
package/docs/Indexer.md CHANGED
@@ -231,6 +231,7 @@ Text filters provide a way to cleanup specific markup languages, leaving only se
231
231
  |--------|-------------|
232
232
  | `html` | This filter strips all HTML tags, and decodes all HTML entities prior to indexing. This also works for XML source. |
233
233
  | `markdown` | This filter is designed for [Markdown](https://en.wikipedia.org/wiki/Markdown) source text. It filters out [fenced code blocks](https://help.github.com/articles/creating-and-highlighting-code-blocks/) and also applies the `html` filter as well (you can embed HTML in markdown). |
234
+ | `alphanum` | This filter strips everything except for alphanumerics and underscores. It's designed to reduce a string to a single indexable value. |
234
235
 
235
236
  Note that URLs are always shortened so that only the hostname is indexed. Full URLs are notoriously difficult (and rather useless) to index for searching. See [Text Cleanup](#text-cleanup) below for details.
236
237
 
@@ -784,7 +785,7 @@ Given an array of your sorted record IDs, you can then implement your own pagina
784
785
  If you have any fields indexed with the [master list](#master-list) feature enabled, you can fetch a "summary" of the data values using the [getFieldSummary()](API.md#getfieldsummary) method. This returns a hash containing all the unique words from the index, and their total counts (occurrences) in the data. Example use:
785
786
 
786
787
  ```js
787
- stotage.getFieldSummary( 'status', config, function(err, values) {
788
+ storage.getFieldSummary( 'status', config, function(err, values) {
788
789
  if (err) throw err;
789
790
 
790
791
  // values will contain a hash with word counts:
package/engines/S3.js CHANGED
@@ -7,6 +7,7 @@ var Component = require("pixl-server/component");
7
7
  var Tools = require("pixl-tools");
8
8
  var Cache = require("pixl-cache");
9
9
  var S3 = require("@aws-sdk/client-s3");
10
+ var { Upload } = require("@aws-sdk/lib-storage");
10
11
  var { NodeHttpHandler } = require("@aws-sdk/node-http-handler");
11
12
  var streamToBuffer = require("fast-stream-to-buffer");
12
13
 
@@ -158,11 +159,11 @@ module.exports = Class.create({
158
159
  self.cache.set( orig_key, params.Body, { date: Tools.timeNow(true) } );
159
160
  }
160
161
 
161
- if (callback) callback(null, data);
162
+ if (callback) process.nextTick( function() { callback(null, data); });
162
163
  } )
163
164
  .catch( function(err) {
164
165
  self.logError('s3', "Failed to store object: " + key + ": " + (err.message || err), err);
165
- if (callback) callback(err);
166
+ if (callback) process.nextTick( function() { callback(err); });
166
167
  } );
167
168
  },
168
169
 
@@ -178,14 +179,19 @@ module.exports = Class.create({
178
179
 
179
180
  this.logDebug(9, "Storing S3 Binary Stream: " + key);
180
181
 
181
- this.s3.send( new S3.PutObjectCommand(params) )
182
+ var upload = new Upload({
183
+ client: this.s3,
184
+ params: params
185
+ });
186
+
187
+ upload.done()
182
188
  .then( function(data) {
183
189
  self.logDebug(9, "Stream store complete: " + key);
184
- if (callback) callback(null, data);
190
+ if (callback) process.nextTick( function() { callback(null, data); });
185
191
  } )
186
192
  .catch( function(err) {
187
193
  self.logError('s3', "Failed to store stream: " + key + ": " + (err.message || err), err);
188
- if (callback) callback(err);
194
+ if (callback) process.nextTick( function() { callback(err, null); });
189
195
  } );
190
196
  },
191
197
 
@@ -202,14 +208,19 @@ module.exports = Class.create({
202
208
 
203
209
  this.logDebug(9, "Storing S3 Binary Stream: " + key);
204
210
 
205
- this.s3.send( new S3.PutObjectCommand(params) )
211
+ var upload = new Upload({
212
+ client: this.s3,
213
+ params: params
214
+ });
215
+
216
+ upload.done()
206
217
  .then( function(data) {
207
218
  self.logDebug(9, "Stream store complete: " + key);
208
- if (callback) callback(null, data);
219
+ if (callback) process.nextTick( function() { callback(null, data); });
209
220
  } )
210
221
  .catch( function(err) {
211
222
  self.logError('s3', "Failed to store stream: " + key + ": " + (err.message || err), err);
212
- if (callback) callback(err);
223
+ if (callback) process.nextTick( function() { callback(err, null); });
213
224
  } );
214
225
  },
215
226
 
@@ -241,9 +252,11 @@ module.exports = Class.create({
241
252
  .then( function(data) {
242
253
  self.logDebug(9, "Head complete: " + key);
243
254
 
244
- callback( null, {
245
- mod: Math.floor( (new Date(data.LastModified)).getTime() / 1000 ),
246
- len: data.ContentLength
255
+ process.nextTick( function() {
256
+ callback( null, {
257
+ mod: Math.floor( (new Date(data.LastModified)).getTime() / 1000 ),
258
+ len: data.ContentLength
259
+ } );
247
260
  } );
248
261
  } )
249
262
  .catch( function(err) {
@@ -257,7 +270,7 @@ module.exports = Class.create({
257
270
  // some other error
258
271
  self.logError('s3', "Failed to head key: " + key + ": " + (err.message || err), err);
259
272
  }
260
- callback( err );
273
+ process.nextTick( function() { callback( err ); } );
261
274
  } );
262
275
  },
263
276
 
@@ -337,7 +350,7 @@ module.exports = Class.create({
337
350
  // some other error
338
351
  self.logError('s3', "Failed to fetch key: " + key + ": " + (err.message || err), err);
339
352
  }
340
- callback( err );
353
+ process.nextTick( function() { callback( err ); } );
341
354
  } );
342
355
  },
343
356
 
@@ -366,9 +379,11 @@ module.exports = Class.create({
366
379
  self.logDebug(9, "S3 stream download closed: " + key);
367
380
  } );
368
381
 
369
- callback( null, download, {
370
- mod: Math.floor( (new Date(data.LastModified)).getTime() / 1000 ),
371
- len: data.ContentLength
382
+ process.nextTick( function() {
383
+ callback( null, download, {
384
+ mod: Math.floor( (new Date(data.LastModified)).getTime() / 1000 ),
385
+ len: data.ContentLength
386
+ } );
372
387
  } );
373
388
  })
374
389
  .catch( function(err) {
@@ -382,7 +397,7 @@ module.exports = Class.create({
382
397
  // some other error
383
398
  self.logError('s3', "Failed to fetch key: " + key + ": " + (err.message || err), err);
384
399
  }
385
- callback( err );
400
+ process.nextTick( function() { callback( err ); } );
386
401
  });
387
402
  },
388
403
 
@@ -425,10 +440,12 @@ module.exports = Class.create({
425
440
  len = parseInt( RegExp.$1 );
426
441
  }
427
442
 
428
- callback( null, download, {
429
- mod: Math.floor( (new Date(data.LastModified)).getTime() / 1000 ),
430
- len: len,
431
- cr: data.ContentRange
443
+ process.nextTick( function() {
444
+ callback( null, download, {
445
+ mod: Math.floor( (new Date(data.LastModified)).getTime() / 1000 ),
446
+ len: len,
447
+ cr: data.ContentRange
448
+ } );
432
449
  } );
433
450
  })
434
451
  .catch( function(err) {
@@ -442,7 +459,7 @@ module.exports = Class.create({
442
459
  // some other error
443
460
  self.logError('s3', "Failed to fetch key: " + key + ": " + (err.message || err), err);
444
461
  }
445
- callback( err );
462
+ process.nextTick( function() { callback( err ); } );
446
463
  });
447
464
  },
448
465
 
@@ -466,11 +483,11 @@ module.exports = Class.create({
466
483
  self.cache.delete(orig_key);
467
484
  }
468
485
 
469
- if (callback) callback(null, data);
486
+ if (callback) process.nextTick( function() { callback(null, data); } );
470
487
  } )
471
488
  .catch( function(err) {
472
489
  self.logError('s3', "Failed to delete object: " + key + ": " + (err.message || err), err);
473
- if (callback) callback(err);
490
+ if (callback) process.nextTick( function() { callback(err); } );
474
491
  } );
475
492
  },
476
493
 
package/indexer.js CHANGED
@@ -239,7 +239,7 @@ module.exports = Class.create({
239
239
  if (checksum != old_data.checksum) {
240
240
  // must reindex
241
241
  state.changed[ def.id ] = 1;
242
- self.updateIndex( old_data, data, def, state, callback );
242
+ self.updateIndex( old_data, data, ''+value, def, state, callback );
243
243
  }
244
244
  else {
245
245
  // data not changed, no action required
@@ -250,7 +250,7 @@ module.exports = Class.create({
250
250
  else {
251
251
  // index doesn't exist for this record, create immediately
252
252
  state.changed[ def.id ] = 1;
253
- self.writeIndex( data, def, state, callback );
253
+ self.writeIndex( data, ''+value, def, state, callback );
254
254
  }
255
255
  }, // iterator
256
256
  function(err) {
@@ -454,7 +454,7 @@ module.exports = Class.create({
454
454
  } ); // lock
455
455
  },
456
456
 
457
- writeIndex: function(data, def, state, callback) {
457
+ writeIndex: function(data, raw_value, def, state, callback) {
458
458
  // create or update single field index
459
459
  var self = this;
460
460
  var words = data.words;
@@ -507,7 +507,8 @@ module.exports = Class.create({
507
507
  def: def,
508
508
  group: group,
509
509
  base_path: base_path,
510
- word_hash: word_hash
510
+ word_hash: word_hash,
511
+ raw_value: raw_value
511
512
  });
512
513
  } // master_list
513
514
 
@@ -585,6 +586,11 @@ module.exports = Class.create({
585
586
  for (var word in word_hash) {
586
587
  if (!summary.values[word]) summary.values[word] = 0;
587
588
  summary.values[word]++;
589
+
590
+ if (task.def.master_labels) {
591
+ if (!summary.labels) summary.labels = {};
592
+ summary.labels[word] = task.raw_value;
593
+ }
588
594
  } // foreach word
589
595
 
590
596
  // save summary back to storage
@@ -737,7 +743,10 @@ module.exports = Class.create({
737
743
 
738
744
  for (var word in word_hash) {
739
745
  if (summary.values[word]) summary.values[word]--;
740
- if (!summary.values[word]) delete summary.values[word];
746
+ if (!summary.values[word]) {
747
+ delete summary.values[word];
748
+ if (task.def.master_labels && summary.labels) delete summary.labels[word];
749
+ }
741
750
  } // foreach word
742
751
 
743
752
  // save summary back to storage
@@ -765,7 +774,7 @@ module.exports = Class.create({
765
774
  } ); // lock
766
775
  },
767
776
 
768
- updateIndex: function(old_data, new_data, def, state, callback) {
777
+ updateIndex: function(old_data, new_data, raw_value, def, state, callback) {
769
778
  // efficiently update single field index
770
779
  var self = this;
771
780
  var old_words = old_data.words;
@@ -825,6 +834,12 @@ module.exports = Class.create({
825
834
  callback: callback || null
826
835
  };
827
836
 
837
+ if (!group.count) {
838
+ this.logDebug(9, "Actually, nothing changed in index: " + def.id + " for record: " + state.id + ", skipping updateIndex");
839
+ if (callback) callback();
840
+ return;
841
+ }
842
+
828
843
  // lock index for this
829
844
  self.lock( base_path, true, function() {
830
845
  // update master list if applicable
@@ -838,7 +853,8 @@ module.exports = Class.create({
838
853
  def: def,
839
854
  group: group,
840
855
  base_path: base_path,
841
- word_hash: added_words
856
+ word_hash: added_words,
857
+ raw_value: raw_value
842
858
  });
843
859
  }
844
860
  if (Tools.numKeys(removed_words) > 0) {
@@ -954,6 +970,11 @@ module.exports = Class.create({
954
970
  return he.decode( value.replace(/<.+?>/g, '') );
955
971
  },
956
972
 
973
+ filterWords_alphanum: function(value) {
974
+ // filter out everything except alphanum + underscore
975
+ return value.replace(/\W+/g, '_').replace(/_+/g, '_');
976
+ },
977
+
957
978
  getWordList: function(value, def, config) {
958
979
  // clean and filter text down to list of alphanumeric words
959
980
  // return array of clean words
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pixl-server-storage",
3
- "version": "3.1.7",
3
+ "version": "3.1.9",
4
4
  "description": "A key/value/list storage component for the pixl-server framework.",
5
5
  "author": "Joseph Huckaby <jhuckaby@gmail.com>",
6
6
  "homepage": "https://github.com/jhuckaby/pixl-server-storage",
@@ -23,6 +23,8 @@
23
23
  ],
24
24
  "dependencies": {
25
25
  "@aws-sdk/client-s3": "3.186.0",
26
+ "@aws-sdk/lib-storage": "3.186.0",
27
+ "@aws-sdk/node-http-handler": "3.186.0",
26
28
  "async": "2.6.4",
27
29
  "fast-stream-to-buffer": "1.0.0",
28
30
  "he": "1.1.1",