dt-toolbox 4.0.9 → 6.0.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.
Files changed (85) hide show
  1. package/Changelog.md +7 -12
  2. package/LICENSE +1 -1
  3. package/Migration.guide.md +14 -1
  4. package/README.md +976 -352
  5. package/README_v.2.x.x.md +0 -1
  6. package/README_v.4.x.x.md +532 -0
  7. package/package.json +24 -32
  8. package/src/convertors/index.js +44 -37
  9. package/src/convertors/midflat.js +77 -133
  10. package/src/convertors/standard.js +62 -87
  11. package/src/convertors/tuples.js +171 -0
  12. package/src/flatData/connect.js +50 -0
  13. package/src/flatData/export.js +46 -0
  14. package/src/flatData/filters/list.js +11 -0
  15. package/src/flatData/filters/listObject.js +13 -0
  16. package/src/flatData/filters/object.js +12 -0
  17. package/src/flatData/filters/root.js +12 -0
  18. package/src/flatData/find.js +20 -0
  19. package/src/flatData/from.js +33 -0
  20. package/src/flatData/get.js +29 -0
  21. package/src/flatData/index.js +101 -0
  22. package/src/flatData/insert.js +24 -0
  23. package/src/flatData/like.js +24 -0
  24. package/src/flatData/look.js +49 -0
  25. package/src/flatData/push.js +19 -0
  26. package/src/flatData/save.js +17 -0
  27. package/src/flatData/set.js +26 -0
  28. package/src/flatData/setupFilter.js +21 -0
  29. package/src/flatData/use.js +16 -0
  30. package/src/flatObject/copy.js +19 -0
  31. package/src/flatObject/export.js +13 -0
  32. package/src/flatObject/index.js +47 -0
  33. package/src/flatObject/insert.js +28 -0
  34. package/src/flatObject/model.js +32 -0
  35. package/src/flatObject/query.js +24 -0
  36. package/src/flatObject/setupFilter.js +12 -0
  37. package/src/main.js +21 -690
  38. package/src/mainLib.js +105 -0
  39. package/dist/dt-toolbox.min.js +0 -1
  40. package/dist/index.html +0 -65
  41. package/src/compareMethod/change.js +0 -21
  42. package/src/compareMethod/different.js +0 -18
  43. package/src/compareMethod/identical.js +0 -21
  44. package/src/compareMethod/index.js +0 -16
  45. package/src/compareMethod/missing.js +0 -18
  46. package/src/compareMethod/same.js +0 -18
  47. package/src/convertors/breadcrumbs.js +0 -148
  48. package/src/help/extractSelection.js +0 -12
  49. package/src/help/filterObject.js +0 -25
  50. package/src/help/hasNumbers.js +0 -14
  51. package/src/help/index.js +0 -37
  52. package/src/help/isItPrimitive.js +0 -10
  53. package/src/help/objectsByLevel.js +0 -16
  54. package/src/help/reduceTuples.js +0 -29
  55. package/src/help/sanitizeFlatKeys.js +0 -30
  56. package/src/help/toBreadcrumbsKeys.js +0 -28
  57. package/src/help/tuplesToBreadcrumbs.js +0 -25
  58. package/src/help/updateSelection.js +0 -14
  59. package/src/help/zipObject.js +0 -24
  60. package/src/lib/assemble.js +0 -45
  61. package/src/lib/attach.js +0 -20
  62. package/src/lib/block.js +0 -33
  63. package/src/lib/combine.js +0 -38
  64. package/src/lib/deep.js +0 -23
  65. package/src/lib/find.js +0 -36
  66. package/src/lib/folder.js +0 -42
  67. package/src/lib/index.js +0 -58
  68. package/src/lib/modify.js +0 -22
  69. package/src/lib/parent.js +0 -51
  70. package/src/lib/purify.js +0 -39
  71. package/src/lib/transform.js +0 -55
  72. package/src/modifiers/add.js +0 -18
  73. package/src/modifiers/append.js +0 -18
  74. package/src/modifiers/combineShallow.js +0 -119
  75. package/src/modifiers/flatten.js +0 -39
  76. package/src/modifiers/index.js +0 -34
  77. package/src/modifiers/insert.js +0 -21
  78. package/src/modifiers/keyPrefix.js +0 -27
  79. package/src/modifiers/mix.js +0 -25
  80. package/src/modifiers/overwrite.js +0 -18
  81. package/src/modifiers/prepend.js +0 -19
  82. package/src/modifiers/reverse.js +0 -23
  83. package/src/modifiers/update.js +0 -18
  84. package/src/simple.js +0 -49
  85. package/webpack.config.js +0 -28
package/README.md CHANGED
@@ -1,492 +1,947 @@
1
- # DT Toolbox v.4.x.x and v.3.x.x
1
+ # DT Toolbox v.6.x.x
2
2
 
3
- - [Documentation for old v.2.x.x is here](https://github.com/PeterNaydenov/dt-toolbox/blob/master/README_v.2.x.x.md)
3
+ - [Documentation for old v.4.x.x and 3.x.x is here](https://github.com/PeterNaydenov/dt-toolbox/blob/master/README_v.4.x.x.md)
4
4
 
5
- Execute operations over deep object structures without worries. Compare, modify, reshape or extract data. Immutability is taken as consideration by this library.
6
5
 
7
- What you can do:
8
- - Library knows some data-types and supports conversion among them;
9
- - Modify objects: add/update/overwrite/insert/combine/append/prepend;
10
- - Compare objects: identical/change/same/different/missing;
11
- - Accumulative data selections: find/parent/folder;
12
- - Accumulative filter selection: limit/keep/remove/deep;
13
- - Extract and manipulate data chunks;
14
6
 
7
+ ## About version 6.x.x
8
+ * Version 5 is full rethinking of the idea and rewrite from scratch;
9
+ * Simplified API interface;
10
+ * New internal data-model;
11
+ * Multiple data inserts;
12
+ * Predefined and custom filters for faster data scan;
13
+ * Model and query functions to shape results;
14
+
15
+
16
+
17
+ ## Description
18
+ DT-Toolbox is created to simplify the work with deep nested javascript objects. The library was created as an immutable data-storage(dt-object), internally based on data-model called `DT-model`.
19
+
20
+ ## What is DT-model?
21
+ It's an internal 'dt-object' data description. Data is an array of lines where each line has 4 components:
22
+ ```js
23
+ [ // dt-model
24
+ [ name, flatData, breadcrumbs, edges ] // dt-line
25
+ , [ name, flatData, breadcrumbs, edges ] // dt-line
26
+ // ...
27
+ ]
28
+ // Where ->
29
+ // name: string. Name of the dt-line;
30
+ // flatData: object or array of primitive types;
31
+ // breadcrumbs: string. Bredcrumbs description of the current dt-line;
32
+ // edges: string[]. List of breadcrumbs of the related dt-lines;
33
+ ```
34
+
35
+ This data-description is easy to read, saved, or transfered.
15
36
 
16
- ## Installation
17
37
 
38
+ ## Installation
18
39
  Install for node.js projects by writing in your terminal:
19
40
  ```
20
- npm install dt-toolbox --save
41
+ npm install dt-toolbox
21
42
  ```
22
43
 
23
44
  Once it has been installed, it can be used by writing this line of JavaScript:
24
45
  ```js
25
- let dtbox = require ( 'dt-toolbox')
46
+ import dtbox from 'dt-toolbox'
26
47
  ```
27
48
 
28
- **Installation for browsers**: Grab file 'dist/dt-toolbox.min.js' and put it inside the project. Request the file from HTML page. Global variable 'dtbox' is available for use.
29
49
 
30
50
 
31
- Note:
32
- Library is using 'generator functions'. If support for old browsers
33
- is required, add a polyfill for 'generators' or get back to version 2.x.x of
34
- the library.
51
+ ## How it works?
52
+
53
+ Use Dt-toolbox methods(init and load) to create a `dt-object`.
35
54
 
55
+ DT-object:
56
+ - Provides multiple insertion of data chunks. Data from each insertion stays differentiated;
57
+ - Has prebuilded filters for fast search of data;
58
+ - Can create and register a customized filters for fast search of data;
59
+ - Can apply `query functions` to find, extract and reshape the data;
60
+ - Can apply `model function` to reshape the final result;
61
+ - Can executes 'query' and 'model' function over all available data in the storage (All insertions);
62
+ - Execution of query/model functions will not change anything inside the host dt-object;
36
63
 
64
+ The **dt-object** contains internally a `dt-storage` object, that is available during call of the 'query' or 'model' functions. Dt-storage have couple of methods for searching data as well can create a new **DT-model** structures and fill them with data.
37
65
 
38
- ## APIs Reference
66
+ Query functions are returning a **new instance of dt-object** with the result, created by dt-storage. Remember - **data inside dt-object never get modified**.
39
67
 
40
- Dtbox API methods with a short description:
68
+ **Filters** can significantly improve the speed of searching information inside dt-objects by creating a shorter scan-list according some specific preferences. Library is coming with `list of predefined filters`:
69
+ ```js
70
+ 'list' : 'Scan only dt-lines where flatData is an array'
71
+ , 'listObject' : 'Scan objects that are members of array'
72
+ , 'object' : 'Scan just dt-lines where flatData is an object'
73
+ , 'root' : 'Scan only root dt-lines of each data insert'
74
+ ```
75
+ Filters are very simple functions to build. Here is one example of how we can create filter for finding object with specific key and value in it.
41
76
  ```js
42
- const API = {
43
- // DT I/O Operations
44
- init : 'Convert any object to flat data-type'
45
- , load : 'Load a flat data-type'
46
- , loadFast : 'Important! Method is depricated. Use load instead'
77
+ function findBlueEyesFn ({ // We have named arguments
78
+ name // Name of dt-line
79
+ , flatData // The data. Flat object or array
80
+ , breadcrumbs // Location description
81
+ , edges // List of breadcrumbs related to this dt-line
82
+ }) {
83
+ if ( flatData.eyes === 'blue' ) return true // confirm that dt-line should be in that filter list
84
+ return false // ignore this dt-line
85
+ }
86
+
87
+ // Register a filter to some dt-object:
88
+ dt.setupFilter (
89
+ 'blueEyes' // filter name
90
+ , findBlueEyesFn // provide a filter function
91
+ )
92
+ // Filter function will be executed on each dt-line to create a filter scan-list
93
+
94
+ // Using the filter during execution of query/model functions:
95
+ dt.query ( store => {
96
+ store
97
+ .use ( 'blueEyes' ) // Set the name of the filter
98
+ .look ( ({}) => {
99
+ // ... will scan only dt-lines selected by filter
100
+ })
101
+ })
102
+ ```
47
103
 
48
- , preprocess : 'Apply custom modifier to initial data.
49
- , add : 'Add data and keep existing data'
50
- , update : 'Updates only existing data fields'
51
- , overwrite : 'Add new data to DT object. Overwrite existing fields'
52
- , insert : 'Insert data on specified key, when the key represents an array'
53
- , combine : 'Combine values for simular keys in arrays'
54
- , append : 'Combine values for duplicated keys. main + update'
55
- , prepend : 'Combine values for duplicated keys. update + main'
56
- , log : 'Executes callback with errors list as argument'
57
- , empty : 'Empty object with export methods'
104
+ Take a look on the library APIs and see the '**Examples**' section bellow.
58
105
 
59
- // Provide Results
60
- , replace : 'Get this._selection.result as a main data'
61
- , attach : 'Attach this._selection.result to the main data. Set point of connection'
62
- , spread : 'Returns result of selection in a calback function'
63
- , spreadAll : 'Select all and returns it with one command in a callback function'
64
- , export : 'Returns result of selection'
65
- , exportAll : 'Select all and returns it with one command'
106
+ ### dt-toolbox API Fast Reference
66
107
 
67
- // Compare Operations
68
- , identical : 'Value compare. Reduce data to identical key/value pairs'
69
- , change : 'Value compare. Reduce to key/value pairs with different values'
70
- , same : 'Key compare. Returns key/value pairs where keys are the same'
71
- , different : 'Key compare. Returns key/value pairs where key does not exist'
72
- , missing : 'Key compare. Returns key/value pairs that are missing'
73
-
74
- // Selectors
75
- , select : 'Initialize a new selection'
76
- , parent : 'Selector. Apply conditions starting from parent level'
77
- , find : 'Selector. Fullfil select with list of arguments that contain specific string'
78
- , all : "Selector. Same as find ('root')"
79
- , folder : "Selector. Fullfil selection with 'midFlat' object props"
80
- , space : "Selector. Same as 'folder'"
81
- , deepObject : "Selector. Fullfil '_select' with deepest object elements"
82
- , deepArray : "Selector. Fullfil '_select' with deepest array elements"
83
- , invert : 'Selector. Invert existing selection'
84
- , assemble : "Converts selection into 'array of objects' or 'single flat object'"
85
- , purify : 'Removes all empty structures ( no props ) from the selection'
108
+ ```js
109
+ init : 'Create a new dt-object from data that is not a DT-model and needs a convertion'
110
+ , load : 'Create a new dt-object from data that is a DT-model'
111
+ , flat : 'Convert a data to DT-model without creation of dt-object'
112
+ , convert : 'Direct convertion from model to model without creation of dt-object'
113
+ , getWalk : 'Returns a instance of "walk" library'
114
+ ```
86
115
 
87
- // Filters
88
- , limit : 'Filter. Reduces amount of records in the selection'
89
- , keep : 'Filter. Keeps records in selection if check function returns true'
90
- , remove : 'Filter. Removes records from selection if check function returns true'
91
- , deep : "Filter. Arguments ( num, direction - optional). Num mean level of deep. Deep '0' mean root members"
116
+ ### dt-object API Fast Reference
92
117
 
93
- // Modifiers
94
- , withData : 'Generate "this._select.result" from the official data. Modifier will work with this data'
95
- , withSelection : 'Generate "this._select.result" content. Modifier will work with this data'
96
- , flatten : 'Mix existing objects in a single object'
97
- , mix : 'Mix objects in order. Start with a host and provide guests list []'
98
- , keyPrefix : 'Modify key as object name+key. Separator-symbol default: emptySpace. It can be modified'
99
- , reverse : 'Change place of keys and values'
100
- }; // API
118
+ ```js
119
+ insert : 'Inserts a new data in the dt-object. Insertion should be provided as dt-object.'
120
+ , 'export' : 'Returns the DT-model from dt-object - part or full'
121
+ , copy : 'Creates a copy of original provided data'
122
+ , query : 'Executes a "query" function on the dt-object. Returns a new dt-object with the result'
123
+ , model : 'Executes a "model" function on the dt-object. Returns a data model'
124
+ , setupFilter : 'Evaluate data according "filter" function and create a shorter scan list that can be used by "dt-storage" during execution of query and model functions'
125
+ , index : 'Provides a copy of specified dt-line by breadcrumbs'
101
126
  ```
102
127
 
128
+ ### dt-storage API Fast Reference
103
129
 
130
+ Object `dt-storage` is available as argument to '**query**' and '**model**' functions. Methods of
131
+ 'dt-storage' can scan DT-model for data and build a new DT-model structure and fields.
104
132
 
133
+ *Important*: Result of building a DT-model returns as a separate dt-object and will not modify anything inside actual dt-object.
105
134
 
135
+ ```js
136
+ // Scan methods
137
+ , from : 'Scan deeper from specified dt-line by location(breadcrumbs)'
138
+ , use : 'Use filter name to execute `look` on shorter list of dt-lines.'
139
+ , get : 'Take a single dt-line with specific breadcrumbs'
140
+ , find : 'String search for exact object name'
141
+ , like : 'String search in dt-line name'
142
+ , look : 'Executes on each object property in the selection list'
143
+
144
+ // DT-model structure and fields creation:
145
+ set : 'Define new dt-line record'
146
+ , connect : 'Creates a list of connections between two already existing dt-lines'
147
+ , save : 'Save a property to flatData object in existing dt-line'
148
+ , push : 'Save a value to flatData array of existing dt-line'
106
149
 
107
- # How it works?
150
+ ```
108
151
 
109
- 1. First: Insert data in dt-toolbox. Use `load` for `flat` data-type or `init` for other data-types. Mix with other objects by using 'add/update/overwrite/combine' if you need. Use 'preprocess' to change data-type before assimilate it.
110
152
 
111
- 2. Select! Without selection, dt-toolbox will return an empty object. Selection respresents the information that should be extracted from the data. Result of selectors is accumulative. Filters will be applied to already selected data.
112
153
 
113
- 3. Spread/Export the result. Create new data structure according selection and provide it in required data-type.
154
+ ## DT Toolbox API
114
155
 
115
- DT Toolbox supports chaining syntax and is that simple. Let's see some examples...
156
+ ### dtbox.init ()
157
+ Create a new dt-object from data that is not a DT-model and needs a convertion. Please take a look on section `Init/Export Data-Models` for more details.
116
158
 
159
+ ```js
160
+ const data = { // Standard JS object
161
+ name: 'Peter'
162
+ , familyMembers : [ 'Veselina', 'Iskra', 'Maria', 'Vasil', 'Vladimir', 'Petya' ]
163
+ , shoes : {
164
+ winter : [ 'Keen', 'Head']
165
+ , summer : [ 'Lotto', 'Asics' ]
166
+ }
167
+ };
168
+
169
+ const midData = { // Midflat model object
170
+ 'root' : { name: 'Peter' }
171
+ , 'familyMembers' : ['Veselina', 'Iskra', 'Maria', 'Vasil', 'Vladimir', 'Petya' ]
172
+ , 'shoes/winter' : [ 'Keen', 'Head' ]
173
+ , 'shoes/summer' : [ 'Lotto', 'Asics' ]
174
+ }
175
+
176
+ const dtS = dtbox.init ( data ) // Creates dt-object from 'standard'(std) data-model
177
+ // it's equal to this: const dtS = dtbox.init ( data, { model:'std' })
178
+ const dtMid = dtbox.init ( midData, { model : 'midFlat' }) // Creates a dt-object from midFlat data.
179
+ ```
117
180
 
118
181
 
119
182
 
183
+ ### dtbox.load ()
184
+ Create a new dt-object from data that is a DT-model.
120
185
 
186
+ ```js
187
+ const dtData = [
188
+ [
189
+ 'root',
190
+ { city: 'Varna', desc: 'Big city on the Black-sea seaside' },
191
+ 'root',
192
+ [ 'root/location', 'root/extra' ]
193
+ ],
194
+ [
195
+ 'location',
196
+ { continent: 'Europe', country: 'Bulgaria' },
197
+ 'root/location',
198
+ []
199
+ ],
200
+ [
201
+ 'extra',
202
+ { port: 'Yes', airport: 'Yes' },
203
+ 'root/extra',
204
+ [ 'root/extra/nearTo' ]
205
+ ],
206
+ [
207
+ 'nearTo',
208
+ [ 'Burgas', 'Shumen', 'Dobrich' ],
209
+ 'root/extra/nearTo',
210
+ []
211
+ ]
212
+ ];
121
213
 
214
+ const dtStore = dtbox.load ( dtData ); // Load DT-model data to dt-object
215
+ ```
122
216
 
123
217
 
124
218
 
219
+ ### dtbox.flat ()
220
+ Convert a data to DT-model without creation of dt-object.
221
+
222
+ ```js
223
+ const a = {
224
+ city : 'Varna'
225
+ , desc: 'Big city on the Black-sea seaside'
226
+ , location : {
227
+ continent: 'Europe'
228
+ , country : 'Bulgaria'
229
+
230
+ }
231
+ , extra : {
232
+ port : 'Yes'
233
+ , airport : 'Yes'
234
+ , 'nearTo' : [ 'Burgas', 'Shumen', 'Dobrich' ]
235
+ }
236
+ };
237
+
238
+ const inFlatModel = dtbox.flat ( a ) // Default data-model is set to 'standard'(std)
239
+ // it's equal to: const inFlatModel = dtbox.flat ( a, {model: 'std'})
240
+ /**
241
+ * inFlatModel = [
242
+ [
243
+ 'root',
244
+ { city: 'Varna', desc: 'Big city on the Black-sea seaside' },
245
+ 'root',
246
+ [ 'root/location', 'root/extra' ]
247
+ ],
248
+ [
249
+ 'location',
250
+ { continent: 'Europe', country: 'Bulgaria' },
251
+ 'root/location',
252
+ []
253
+ ],
254
+ [
255
+ 'extra',
256
+ { port: 'Yes', airport: 'Yes' },
257
+ 'root/extra',
258
+ [ 'root/extra/nearTo' ]
259
+ ],
260
+ [
261
+ 'nearTo',
262
+ [ 'Burgas', 'Shumen', 'Dobrich' ],
263
+ 'root/extra/nearTo',
264
+ []
265
+ ]
266
+ ]
267
+ */
268
+
269
+ ```
270
+
125
271
 
126
- ## Examples
127
272
 
128
- Here are some use cases, but if you're interested, test-cases are on your disposal.
129
- ### Basics
130
- Let's have a standard JS object:
273
+ ### dtbox.convert ()
274
+ Direct convertion from model to model without creation of dt-object.
131
275
 
132
276
  ```js
133
- let st = {
134
- name : {
135
- firstName : 'Peter'
136
- , surname : 'Naydenov'
137
- }
138
- , friends : [ 'Tisho', 'Dibo', 'Ivo', 'Vasil' ]
139
- }
140
277
 
278
+ let result = dtbox.convert ( a, {
279
+ model : 'std' // Model: Source data-model
280
+ , as : 'breadcrumbs' // as: Convert data to this data-model
281
+ })
282
+
283
+ /**
284
+ result = {
285
+ 'city': 'Varna'
286
+ , 'desc': 'Big city on the Black-sea seaside'
287
+ , 'location/continent': 'Europe'
288
+ , 'location/country': 'Bulgaria'
289
+ , 'extra/port': 'Yes'
290
+ , 'extra/airport': 'Yes'
291
+ , 'extra/nearTo/0': 'Burgas'
292
+ , 'extra/nearTo/1': 'Shumen'
293
+ , 'extra/nearTo/2': 'Dobrich'
294
+ }
295
+ */
141
296
  ```
142
- Put the **st** data into dt-toolbox:
297
+
298
+
299
+
300
+ ### dtbox.getWalk ()
301
+ Dt-Toolbox is using "walk" library. If you need to use it directly - get the version used by Dt-Toolbox.
143
302
 
144
303
  ```js
145
- let dt = dtbox.init ( standard )
304
+ const walk = dtbox.getWalk ();
305
+
146
306
  ```
147
307
 
148
- Internal representation of data is based on `flat` data-type. Type `flat` has two elements: value and structure.
149
- **Value** represents primitive values and their location. **Structure** represents existing flat objects and their relations.
150
- Our standard object inside the library will look like:
308
+
309
+
310
+
311
+
312
+ ## DT-object API
313
+
314
+
315
+ ### dt.insert ()
316
+ Extend the dt-object with a new data. Insertion should be provided as dt-object.
151
317
 
152
318
  ```js
153
- dt.structure = [
154
- // type i object descriptors [i, name]
155
- [ 'object', 0, [1, name], [2, friends] ] // Root object and relation with other objects
156
- , [ 'object', 1 ] // st.name object. Object has only primitive values.
157
- , [ 'array' , 2 ] // st.friends array. Array has only primitive values.
319
+ const a = [ // it's a 'file' data-model
320
+ 'name/Peter'
321
+ , 'familyMembers/Veselina'
322
+ , 'familyMembers/Iskra'
323
+ , 'familyMembers/Maria'
324
+ , 'familyMembers/Vasil'
325
+ , 'familyMembers/Vladimir'
326
+ , 'familyMembers/Petya'
327
+ , 'shoes/winter/Keen'
328
+ , 'shoes/winter/Head'
329
+ , 'shoes/summer/Lotto'
330
+ , 'shoes/summer/Asics'
331
+ ];
332
+ const b = { shoes: [ 'Puma', 'UA' ]}
333
+ const dt = dtbox.init ( a, { model : 'file' }) // create a dt-object
334
+ dt.insert (
335
+ 'extra' // object name
336
+ , dtbox.init(b) // the extra object
337
+ ) // insert to 'dt' storage extra
338
+
339
+ /**
340
+ dt internal interpretation:
341
+ [
342
+ [
343
+ 'root' // -> dt-line name
344
+ , {name:'Peter'} // -> flatData
345
+ , 'root' // -> location. For top element of each data segment breadcrumbs === name
346
+ , [ 'root/familyMembers', 'root/shoes' ] // -> edges
347
+ ]
348
+ , [
349
+ 'familyMembers' // -> dt-line name
350
+ , [ 'Veselina', 'Iskra', 'Maria', 'Vasil', 'Vladimir', 'Petya' ] // -> flatData
351
+ , 'root/familyMembers' // -> location
352
+ , [] // -> edges
353
+ ]
354
+ , [
355
+ 'shoes' // -> dt-line name
356
+ , {} // -> flatData
357
+ , 'root/shoes' // -> location
358
+ , [ 'root/shoes/winter', 'root/shoes/summer' ] // -> edges
359
+ ]
360
+ , [
361
+ 'winter' // -> dt-line name
362
+ , [ 'Keen', 'Head' ] // -> flatData
363
+ , 'root/shoes/winter' // -> location
364
+ , [] // -> edges
365
+ ]
366
+ , [
367
+ 'summer' // -> dt-line name
368
+ , [ 'Lotto', 'Asics' ] // -> flatData
369
+ , 'root/shoes/summer' // -> location
370
+ , [] // -> edges
371
+ ]
372
+ // ---> Here are the elements that are coming from 'insert'
373
+ , [
374
+ 'extra' // -> dt-line name. Object name of insert will become root element for data segment.
375
+ , {} // -> flatData
376
+ ,'extra' // -> location. For top element of each data segment breadcrumbs === name
377
+ , [ 'extra/shoes' ] // -> edges
378
+ ]
379
+ , [
380
+ 'shoes' // -> dt-line name
381
+ , [ 'Puma', 'UA'] // -> flatData
382
+ , 'extra/shoes' // -> location
383
+ , [] // -> edges
158
384
  ]
385
+ ]
159
386
 
160
- dt.value = { // Represents a primitive props and their location
161
- 'root/1/firstName' : 'Peter'
162
- , 'root/1/surname' : 'Naydenov'
163
- , 'root/2/0' : 'Tisho'
164
- , 'root/2/1' : 'Dibo'
165
- , 'root/2/2' : 'Ivo'
166
- , 'root/2/3' : 'Vasil'
167
- }
168
- }
387
+ */
169
388
  ```
170
389
 
171
- ::: warning
172
- Internal representation is '*LIKE*' flat data-type but not the data-type itself. Type `flat` is array with two elements: structure and value `[structure, value]`. Internal representation has these two elements but they are like props. `dt = { structure, value }`.
173
- :::
174
390
 
175
391
 
392
+ ### dt.export ()
393
+ Returns DT-model from dt-object.
176
394
 
177
- Extract a flat information:
178
395
  ```js
179
- dt.spreadAll ( 'flat', res => {
180
- // Data-type 'Flat': An array with 2 entries: [structure, value]
181
- })
182
- // other way to receive same result:
183
- let myFlat = dt.exportAll ( 'flat' )
396
+ const all = dt.export () // will return all data from the storage
397
+ const root = dt.export ( 'root' ) // will return only initial data segment
398
+ const extra = dt.export ( 'extra' ) // will return only 'extra' data segment
399
+ /**
400
+ extra = [
401
+ , [
402
+ 'root' // -> dt-line name was changed to 'root'. Name 'extra' has meaning just inside dt-object
403
+ , {} // -> flatData
404
+ ,'root' // -> location. For top element of each data segment breadcrumbs === name
405
+ , [ 'root/shoes' ] // -> edges
406
+ ]
407
+ , [
408
+ 'shoes' // -> dt-line name
409
+ , [ 'Puma', 'UA'] // -> flatData
410
+ , 'root/shoes' // -> location
411
+ , [] // -> edges
412
+ ]
413
+ ]
414
+ */
415
+
184
416
  ```
185
417
 
186
418
 
419
+ ### dt.copy ()
420
+ During the initialization process `dt-object` will save a deep copy of original data inside and can provide a deep copy in any time.
421
+ Function `copy` can't provide copy of all data segments together because they are not related to each other. By default, when there is no name as argument, function will return the copy of 'root' object.
422
+ ```js
423
+ const
424
+ b = { shoes: [ 'Puma', 'UA' ]}
425
+ , c = { vitamins : [ 'a', 'b', 'c' ]}
426
+ , dt = dtbox.init ( b )
427
+ ;
428
+ dt.insert ( 'extra', c )
429
+ const deepCopy = dt.copy ()
430
+ // it equal to: const deepCopy = dt.copy ('root')
431
+ const onlyExtra = dt.copy ( 'extra' )
432
+ // onlyExtra = { vitamins : [ 'a', 'b', 'c' ]}
433
+ ```
187
434
 
188
- Let's play with DT Toolbox:
189
435
 
190
- ```js
191
- let
192
- dtResult
193
- , stResult
194
- , friendList
195
- ;
196
436
 
197
- dtbox
198
- .init(st) // Init data. Converts ST to DT
199
- .select() // Starting new selection
200
- .all() // Select all data
201
- .spread ( 'flat', dt => dtResult = dt ) // Returns as `flat` data-type
202
- .spread ( 'std', dt => stResult = dt ) // Convert back to original 'st' object
203
- .select () // Start new selection. Will remove previous selection.
204
- .find ( 'friends' ) // select keys that contain 'friends'
205
- .spread ( 'std', dt => friendList = dt ) //= { friends :[ 'Tisho', 'Dibo', 'Ivo', 'Vasil' ] }
206
- .assemble ()
207
- .spread ( 'std' => friendList = dt ) // = [ 'Tisho', 'Dibo', 'Ivo', 'Vasil' ]
208
- // 'assemble' removes all duplicated elements in the keys and simplifies the result.
209
-
437
+ ### dt.query ()
438
+ Executes a "query" function on the dt-object. If there is something new, will return it. If there are no changes, it will return itself. For more details take a look on `store API` and especially **store.set(), store.save(), store.push(), store.connect()**.
439
+ ```js
440
+ function queryFn ( store, a, b ) { // optional arguments will come directly after 'store' api
441
+ // ... body of queryFn
442
+ }
443
+ const dtOther = dt.query ( queryFn, a, b ) // queryFn is required arguments. All other arguments are optional
210
444
  ```
211
445
 
212
- ### Convert ST to DT objects
213
446
 
447
+ ### dt.model ()
448
+ Executes a "model" function on the dt-object. Returns a data-model. Default choice is DT-model object. Change the response representation by returning an object as in example below:
214
449
  ```js
215
- let result;
216
- dtbox
217
- .init(st)
218
- .spreadAll ( 'flat', dt => result = dt );
450
+ function modelFn ( store, a,v,g ) { // optional arguments will come directly after 'store' api
451
+ // ... body of modelFn
452
+ // to convert result in some of predefined and supported models, function should return an object
453
+ return {
454
+ as : 'std' // property 'as' will execute final conversion. Model name should be from supported list of the library.
455
+ }
456
+ }
457
+
458
+ const result = dt.model ( modelFn, a,v,g ) // modelFn is the only required argument. All other arguments are optional.
459
+
219
460
  ```
220
461
 
221
- ### Mixing objects - Add/Update/Overwrite
462
+ ### dt.setupFilter ()
463
+ Evaluate data according "filter" function and create a shorter scan list that can be used by `dt-storage API` during the execution of query or model functions. For more details about filters look at function `store.use()` function.
222
464
 
223
- Add and update will consider existing data:
224
- - 'Add' method will be applied only for non-existing properties;
225
- - 'Update' method will works only on existing properties;
465
+ ```js
466
+ function blueFn ({
467
+ name // Name of dt-line
468
+ , flatData // The flat data
469
+ , breadcrumbs // Location description
470
+ , edges // List of breadcrumbs related to this dt-line
471
+ }) {
472
+ if ( flatData.hasOwnProperty('eyes') && flatData.eyes === 'blue' ) return true // confirm that dt-line should be in that filter list
473
+ return false // ignore this dt-line
474
+ // dt-lines that are
475
+ }
476
+
477
+ dt.setupFilter (
478
+ 'blue' // Name of the filter
479
+ , blueFn // Provide a filter function
480
+ )
481
+ ```
226
482
 
227
- Overwrite will 'add' and 'update'.
228
483
 
484
+ ### dt.index ()
485
+ Provides a copy of specified by breadcrumbs DT-line.
229
486
  ```js
487
+ const br = 'root/friends'
488
+ const data = {
489
+ name: 'Peter'
490
+ , friends : [ 'Ivan', 'Dobroslav', 'Stefan' ]
491
+ , personal : {
492
+ age : 49
493
+ , eyes : 'blue'
494
+ , sizes : [ 10, 44, 'm', 'mid' ]
495
+ , hobbies : {
496
+ music : [ 'punk', 'ska', 'metal', 'guitar' ]
497
+ , sport : [ 'fencing', 'skating', 'ski' ]
498
+ }
499
+ }
500
+ }
501
+ const [ name, flatData, breadcrumbs, edges ] = dt.index ( br )
502
+ // name = friends
503
+ // flatData = [ 'Ivan', 'Dobroslav', 'Stefan' ]
504
+ // breadcrumbs === br
505
+ // edges === []
506
+ ```
230
507
 
231
- let user = {
232
- name : 'Peter'
233
- , age : 42
234
- }
235
508
 
236
- dtbox
237
- .init ( user )
238
- .add ({
239
- age : 25 // 'add' will ignore this. Age is already defined.
240
- , gender : 'male' // Will add this.
241
- }, { type: 'std'})
242
- .update ({
243
- age : 50 // Will update
244
- eyes : 'blue' // Will ignore this.
245
- }, { type: 'std'})
246
- .overwrite ({
247
- age : 43 // Will update
248
- , hobby : 'skating' // Will add
249
- }, { type: 'std'})
250
509
 
251
- // The object (dtbox.value) will look like:
252
- /*
253
- {
254
- 'root/0/name' : 'Peter'
255
- , 'root/0/age' : 43
256
- , 'root/0/gender' : 'male'
257
- , 'root/0/hobby' : 'skating'
258
- }
259
510
 
260
- /*
261
511
 
512
+
513
+
514
+
515
+
516
+ ## DT-store API
517
+
518
+ As we already mentioned, store is available in query/model functions and coming as the first argument.
519
+
520
+ ### store.look ()
521
+ Function that will be executed on each object key/value from the selection list.
522
+ If selection is not explicitly mentioned, executes function on each dt-line data segments.
523
+
524
+ ```js
525
+ const data = {
526
+ name: 'Peter'
527
+ , friends : [ 'Ivan', 'Dobroslav', 'Stefan' ]
528
+ , personal : {
529
+ age : 49
530
+ , eyes : 'blue'
531
+ , sizes : [ 10, 44, 'm', 'mid' ]
532
+ , hobbies : {
533
+ music : [ 'punk', 'ska', 'metal', 'guitar' ]
534
+ , sport : [ 'fencing', 'skating', 'ski' ]
535
+ }
536
+ }
537
+ };
538
+ const dt = dtbox.init ( data );
539
+
540
+ const result = dt.query ( store => {
541
+ // Direct call of look on store will be executed on each dt-line
542
+ store.look ( ({ // Named arguments. All available argument-names are listed here:
543
+ value
544
+ , key
545
+ , name // dt-line name;
546
+ , flatData // full flatData for specified dt-line;
547
+ , breadcrumbs // breadcrumbs for dt-line;
548
+ , links // List of tuples [[parent, child],...]. Parent and child are the dt-line names;
549
+ , empty // Will present only if object has no properties. Empty flatData for dt-line.
550
+ }) => {
551
+ //... body of look function
552
+ // Move fast to next dt-line by returning a string 'next'
553
+ return 'next'
554
+ // unconditional return 'next' will executes the 'look' function once per dt-line
555
+ })
556
+ })
557
+ ```
558
+
559
+ ### store.from ()
560
+ Scan deeper from specified dt-line by location(breadcrumbs).
561
+
562
+ ```js
563
+ const data = {
564
+ name: 'Peter'
565
+ , friends : [ 'Ivan', 'Dobroslav', 'Stefan' ]
566
+ , personal : {
567
+ age : 49
568
+ , eyes : 'blue'
569
+ , sizes : [ 10, 44, 'm', 'mid' ]
570
+ , hobbies : {
571
+ music : [ 'punk', 'ska', 'metal', 'guitar' ]
572
+ , sport : [ 'fencing', 'skating', 'ski' ]
573
+ }
574
+ }
575
+ };
576
+ const
577
+ dt = dtbox.init ( data )
578
+ , res = dt.query ( store => {
579
+ store
580
+ .from ( 'root/personal/hobbies' )
581
+ .look ( ({name}) => {
582
+ console.log ( name )
583
+ // -> hobbies, music, sport
584
+ return 'next' // because we want to iterate once on each dt-line
585
+ })
586
+ });
262
587
  ```
263
588
 
264
589
 
265
- ### Parent
590
+ ### store.use ()
591
+ Use filter to execute `look` on shorter list of dt-lines. Use the predefined or your own filters.
592
+ List of predefined filters:
593
+ - 'list' : Scan only dt-lines where flatData is an array;
594
+ - 'listObject' : Scan objects that are members of array;
595
+ - 'object' : Scan just dt-lines where flatData is an object;
596
+ - 'root' : Scan only root dt-lines of each data insert;
597
+
598
+ If filter do not exist, look function will be executed on each dt-line.
266
599
 
267
600
  ```js
601
+ const data = {
602
+ name: 'Peter'
603
+ , friends : [ 'Ivan', 'Dobroslav', 'Stefan' ]
604
+ , personal : {
605
+ age : 49
606
+ , eyes : 'blue'
607
+ , sizes : [ 10, 44, 'm', 'mid' ]
608
+ , hobbies : {
609
+ music : [ 'punk', 'ska', 'metal', 'guitar' ]
610
+ , sport : [ 'fencing', 'skating', 'ski' ]
611
+ }
612
+ }
613
+ };
614
+ const
615
+ dt = dtbox.init ( data )
616
+ , res = dt.query ( store => {
617
+ store
618
+ .use ( 'object' ) // predefined filter 'object'
619
+ .look ( ({name}) => {
620
+ console.log ( name )
621
+ // -> root, personal, hobbies
622
+ return 'next' // because we want to iterate once on each dt-line
623
+ })
624
+ });
625
+ ```
268
626
 
269
- let result;
270
- let data = {
271
- 'school' : [
272
- { name: 'Ivan', age: 14 }
273
- , { name: 'Georgy', age: 15 }
274
- , { name: 'Adi', age: 11 }
275
- , { name: 'Kati', age: 11 }
276
- ]
277
- , 'sports' : [
278
- { name: 'Iva', age: 28 }
279
- , { name: 'Stoyan', age: 36 }
280
- ]
281
- , 'work' : [
282
- { name: 'Hristo', age: 38 }
283
- , { name: 'Lachezar', age: 33 }
284
- , { name: 'Veselina', age: 35 }
285
-
286
- ]
287
- , 'recent' : {
288
- 'classmates' : [
289
- { name: 'Anton', age: 42 }
290
- , { name: 'Miroslava', age: 42 }
291
- ]
292
- , 'social' : [
293
- { name: 'Iliana', age: 61 }
294
- , { name: 'Tzvetan', age: 19 }
295
- ]
296
- }
297
- }
298
627
 
299
- // Let's create list of all contacts uder 40 years old:
300
-
301
- dtbox
302
- .init ( data )
303
- .select ()
304
- .parent ( 'name', person => person.age < 40 )
305
- .assemble ()
306
- .spread ( 'std' , dt => result = dt )
307
-
308
- /*
309
- result will look like this:
310
-
311
- [
312
- { name: 'Tzvetan', age: 19 },
313
- { name: 'Ivan', age: 14 },
314
- { name: 'Iva', age: 28 },
315
- { name: 'Hristo', age: 38 },
316
- { name: 'Georgy', age: 15 },
317
- { name: 'Stoyan', age: 36 },
318
- { name: 'Lachezar', age: 33 },
319
- { name: 'Adi', age: 11 },
320
- { name: 'Veselina', age: 35 },
321
- { name: 'Kati', age: 11 }
322
- ]
323
628
 
324
- */
629
+
630
+
631
+ ### store.get ()
632
+ Take a single dt-line with specific breadcrumbs.
633
+
634
+ ```js
635
+ const data = {
636
+ name: 'Peter'
637
+ , friends : [ 'Ivan', 'Dobroslav', 'Stefan' ]
638
+ , personal : {
639
+ age : 49
640
+ , eyes : 'blue'
641
+ , sizes : [ 10, 44, 'm', 'mid' ]
642
+ , hobbies : {
643
+ music : [ 'punk', 'ska', 'metal', 'guitar' ]
644
+ , sport : [ 'fencing', 'skating', 'ski' ]
645
+ }
646
+ }
647
+ };
648
+ const
649
+ dt = dtbox.init ( data )
650
+ , res = dt.query ( store => {
651
+ store
652
+ .get ( 'root/friends' )
653
+ .look ( ({flatData}) => {
654
+ console.log ( flatData )
655
+ // -> [ 'Ivan', 'Dobroslav', 'Stefan' ]
656
+ return 'next' // because we want to iterate once on each dt-line
657
+ })
658
+ });
325
659
  ```
326
660
 
327
661
 
328
662
 
329
- ### Purify
663
+ ### store.find ()
664
+ String search for exact object name
665
+
666
+ ```js
667
+ const data = {
668
+ name: 'Peter'
669
+ , friends : [ 'Ivan', 'Dobroslav', 'Stefan' ]
670
+ , personal : {
671
+ age : 49
672
+ , eyes : 'blue'
673
+ , sizes : [ 10, 44, 'm', 'mid' ]
674
+ , hobbies : {
675
+ music : [ 'punk', 'ska', 'metal', 'guitar' ]
676
+ , sport : [ 'fencing', 'skating', 'ski' ]
677
+ }
678
+ }
679
+ };
680
+ const
681
+ dt = dtbox.init ( data )
682
+ , res = dt.query ( store => {
683
+ store
684
+ .find ( 'music' )
685
+ .look ( ({flatData}) => {
686
+ console.log ( flatData )
687
+ // -> [ 'punk', 'ska', 'metal', 'guitar' ]
688
+ return 'next' // because we want to iterate once on each dt-line
689
+ })
690
+ });
691
+ ```
330
692
 
331
- Cleaning empty structures till version 3 of the library was without alternative. Keep empty structures was recognized as a need and it's now a default behaviour. Remove empty structures by using 'purify' function as in this example:
693
+
694
+
695
+ ### store.like ()
696
+ String search in dt-line name
332
697
 
333
698
  ```js
334
- const test = {
335
- name : 'Peter'
336
- , arr : [ 1, 15 ]
337
- , de : { me: ['eho', 'ha'] }
338
- , se : { le: {} }
339
- , ze : []
340
- };
341
- dtbox
342
- .init ( test )
343
- .select ()
344
- .all ()
345
- .purify ()
346
- .spread ( 'std', x => {
347
- /** Result after purify will be:
348
- * x = {
349
- * name: Peter
350
- * , arr : [1,15]
351
- * , de : { me: ['eho','ha']}
352
- * }
353
- */
354
- })
355
- }) // it purify
699
+ const data = {
700
+ name: 'Peter'
701
+ , friends : [ 'Ivan', 'Dobroslav', 'Stefan' ]
702
+ , personal : {
703
+ age : 49
704
+ , eyes : 'blue'
705
+ , sizes : [ 10, 44, 'm', 'mid' ]
706
+ , hobbies : {
707
+ music : [ 'punk', 'ska', 'metal', 'guitar' ]
708
+ , sport : [ 'fencing', 'skating', 'ski' ]
709
+ }
710
+ }
711
+ };
712
+ const
713
+ dt = dtbox.init ( data )
714
+ , res = dt.query ( store => {
715
+ store
716
+ .like ( 'per' )
717
+ .look ( ({flatData, breadcrumbs}) => {
718
+ console.log ( flatData )
719
+ // -> { age: 49, eyes: 'blue' }
720
+ console.log ( breadcrumbs )
721
+ // -> 'root/personal'
722
+ return 'next' // because we want to iterate once on each dt-line
723
+ })
724
+ });
356
725
  ```
357
726
 
358
727
 
359
- ## Data-types
360
728
 
361
- The library can spread data-selection as different data-types. Let's see how initial data will be interpreted in available data-types. Here is our initial `standard`(std) data:
729
+ // DT-model structure and fields creation:
730
+ ### store.set ()
731
+ Define new dt-line record
732
+
362
733
  ```js
363
734
  const data = {
364
- name: 'Peter'
365
- , familyMembers : [ 'Veselina', 'Iskra', 'Maria', 'Vasil', 'Vladimir', 'Petya' ]
366
- , shoes : {
367
- winter : [ 'Keen', 'Head']
368
- , summer : [ 'Lotto', 'Asics' ]
369
- }
735
+ name: 'Peter'
736
+ , friends : [ 'Ivan', 'Dobroslav', 'Stefan' ]
737
+ , personal : {
738
+ age : 49
739
+ , eyes : 'blue'
740
+ , sizes : [ 10, 44, 'm', 'mid' ]
741
+ , hobbies : {
742
+ music : [ 'punk', 'ska', 'metal', 'guitar' ]
743
+ , sport : [ 'fencing', 'skating', 'ski' ]
744
+ }
745
+ }
746
+ };
747
+ const dt = dtbox.init ( data );
748
+
749
+ const result = dt
750
+ .query ( store => {
751
+ store.set ( 'root', [2,4,15]) // new dt-line structure was created
752
+ })
753
+ .model ( () => ({as:'std'}) )
754
+ console.log ( result )
755
+ // -> [2,4,15]
756
+
757
+ const result2 = dt
758
+ .query ( store => {}) // If there is no new dt-line, query will return itself
759
+ .model ( () => ({as:'std'}) )
760
+ console.log ( result2 )
761
+ /**
762
+ {
763
+ name: 'Peter'
764
+ , friends : [ 'Ivan', 'Dobroslav', 'Stefan' ]
765
+ , personal : {
766
+ age : 49
767
+ , eyes : 'blue'
768
+ , sizes : [ 10, 44, 'm', 'mid' ]
769
+ , hobbies : {
770
+ music : [ 'punk', 'ska', 'metal', 'guitar' ]
771
+ , sport : [ 'fencing', 'skating', 'ski' ]
772
+ }
773
+ }
370
774
  }
775
+ */
371
776
  ```
372
777
 
373
- ### Standard ( std )
374
- Standard data-type will look exactly as initial data.
778
+
779
+
780
+ ### store.connect ()
781
+ Creates a list of connections between two already existing dt-lines
782
+
375
783
  ```js
376
- {
377
- name: 'Peter'
378
- , familyMembers : [ 'Veselina', 'Iskra', 'Maria', 'Vasil', 'Vladimir', 'Petya' ]
379
- , shoes : {
380
- winter : [ 'Keen', 'Head']
381
- , summer : [ 'Lotto', 'Asics' ]
382
- }
383
- }
784
+ const data = {
785
+ name: 'Peter'
786
+ , friends : [ 'Ivan', 'Dobroslav', 'Stefan' ]
787
+ };
788
+ const
789
+ dt = dtbox.init ( data )
790
+ , result = dt
791
+ .query ( store => {
792
+ store.set ( 'root', { name: Stefan })
793
+ store.set ( 'friends', [ 'Stefan', 'Tommy', 'Maria'] )
794
+ store.connect (['root/friends'])
795
+ })
796
+ .model ( () => ({as:'std'}))
797
+ ;
798
+ console.log ( result )
799
+ /**
800
+ {
801
+ name: Stefan
802
+ , friends: ['Stefan', 'Tommy', 'Maria' ]
803
+ }
804
+ */
384
805
  ```
385
806
 
386
807
 
387
- ### Flat ( shortFlat )
388
- It's a flat description of the object. It's an array with two elements. First element describes the structure of the object, second element - the values.
389
- **Structure**: Array of flatDescriptions. FlatDescription is array where first element is the type of the object (object or array), second is the index. If there are more then 2 elements, we have connection descriptions. ConnectionDescription is array of 2 elements. First is the index of connected other object, second is the property name of the connection.
390
- In our example: We have object, that have property `familyMembers` that is array and other property `shoes` that is an object. Object `shoes` have 2 properties (winter,summer) that are arrays.
391
- **Value**: Key describes the position of the property that have a primitive value. Value is just that primitive value. Key always have 3 elements separated by '/'. First element is always `root`, second is the `id` of the object (from structure description), third is the name of the property. If structure object is 'array' then property name will be a number representing the position into the array.
808
+
809
+ ### store.save ()
810
+ Save a property to flatData object in existing dt-line.
811
+
392
812
  ```js
393
- [
394
- // the structure description
395
- [
396
- [ 'object', 0, [1,'familyMembers'], [2,'shoes'] ]
397
- , [ 'array' , 1 ]
398
- , [ 'object', 2 , [3, 'winter'], [4, 'summer'] ]
399
- , [ 'array' , 3 ]
400
- , [ 'array' , 4 ]
401
- ]
402
- // the value description
403
- , {
404
- 'root/0/name' : 'Peter'
405
- , 'root/1/0' : 'Veselina'
406
- , 'root/1/0' : 'Veselina'
407
- , 'root/1/1' : 'Iskra'
408
- , 'root/1/2' : 'Maria'
409
- , 'root/1/3' : 'Vasil'
410
- , 'root/1/4' : 'Vladimir'
411
- , 'root/1/5' : 'Petya'
412
- , 'root/3/0' : 'Keen'
413
- , 'root/3/1' : 'Head'
414
- , 'root/4/0' : 'Lotto'
415
- , 'root/4/1' : 'Asics'
416
- }
417
- ]
813
+ const data = {
814
+ name: 'Peter'
815
+ , friends : [ 'Ivan', 'Dobroslav', 'Stefan' ]
816
+ };
817
+ const
818
+ dt = dtbox.init ( data )
819
+ , result = dt
820
+ .query ( store => {
821
+ store.set ( 'root', { name: Stefan })
822
+ store.set ( 'friends', [ 'Stefan', 'Tommy', 'Maria'] )
823
+ store.connect (['root/friends'])
824
+ store.save ( 'root', 'age', 35 )
825
+ })
826
+ .model ( () => ({as:'std'}))
827
+ ;
828
+ console.log ( result )
829
+ /**
830
+ {
831
+ name: Stefan
832
+ , age : 35
833
+ , friends: ['Stefan', 'Tommy', 'Maria' ]
834
+ }
835
+ */
418
836
  ```
419
837
 
420
838
 
839
+
840
+ ### store.push ()
841
+ Save a value to flatData of existing dt-line. FlatData should be an array.
842
+
843
+ ```js
844
+ const data = {
845
+ name: 'Peter'
846
+ , friends : [ 'Ivan', 'Dobroslav', 'Stefan' ]
847
+ };
848
+ const
849
+ dt = dtbox.init ( data )
850
+ , result = dt
851
+ .query ( store => {
852
+ store.set ( 'root', { name: Stefan })
853
+ store.set ( 'friends', [ 'Stefan', 'Tommy', 'Maria'] )
854
+ store.connect (['root/friends'])
855
+ store.push ( 'friends', 'Lily' )
856
+ })
857
+ .model ( () => ({as:'std'}))
858
+ ;
859
+ console.log ( result )
860
+ /**
861
+ {
862
+ name: Stefan
863
+ , friends: ['Stefan', 'Tommy', 'Maria', 'Lily' ]
864
+ }
865
+ */
866
+ ```
867
+
868
+
869
+
870
+
871
+
872
+
873
+
874
+
875
+
876
+
877
+ ## Init/Export Data-Models
878
+ The library has some predefined data-models and can read and convert data among them.
879
+
880
+ ### Standard ( std )
881
+ Standard data model is a standard deep javascript object.
882
+ ```js
883
+ const data = {
884
+ name: 'Peter'
885
+ , familyMembers : [ 'Veselina', 'Iskra', 'Maria', 'Vasil', 'Vladimir', 'Petya' ]
886
+ , shoes : {
887
+ winter : [ 'Keen', 'Head']
888
+ , summer : [ 'Lotto', 'Asics' ]
889
+ }
890
+ }
891
+ ```
892
+
421
893
  ### MidFlat
422
- Object where keys represents "location" of the flat object. Value is always an object. Props are names. If data-structure is array, props are numbers:
894
+ It's a two level deep javascript object. First object properties represent the location of the data, value is a flat object or array:
423
895
 
424
896
  ```js
425
897
  {
426
898
  'root' : { name: 'Peter' }
427
- , 'root/familyMembers' : {
428
- '0' : 'Veselina'
429
- , '1' : 'Iskra'
430
- , '2' : 'Maria'
431
- , '3' : 'Vasil'
432
- , '4' : 'Vladimir'
433
- , '5' : 'Petya'
434
- }
435
- , 'root/shoes/winter' : {
436
- '0' : 'Keen'
437
- , '1' : 'Head'
438
- }
439
- , 'root/shoes/summer' : {
440
- '0' : 'Lotto'
441
- '1' : 'Asics'
442
- }
899
+ , 'familyMembers' : ['Veselina', 'Iskra', 'Maria', 'Vasil', 'Vladimir', 'Petya' ]
900
+ , 'shoes/winter' : [ 'Keen', 'Head' ]
901
+ , 'shoes/summer' : [ 'Lotto', 'Asics' ]
443
902
  }
444
903
  ```
445
904
 
446
905
 
447
906
 
448
-
449
-
450
907
  ### Breadcrumbs
451
-
452
908
  It's a flat interpratation of the data and looks like this:
909
+
453
910
  ```js
454
911
  {
455
- 'root/name' : 'Peter'
456
- , 'root/familiMembers/0' : 'Veselina'
457
- , 'root/familyMembers/1' : 'Iskra'
458
- , 'root/familyMembers/2' : 'Maria'
459
- , 'root/familyMembers/3' : 'Vasil'
460
- , 'root/familyMembers/4' : 'Vladimir'
461
- , 'root/familyMembers/5' : 'Petya'
462
- , 'root/shoes/winter/0' : 'Keen'
463
- , 'root/shoes/winter/1' : 'Head'
464
- , 'root/shoes/summer/0' : 'Lotto'
465
- , 'root/shoes/summer/1' : 'Asics'
912
+ 'name' : 'Peter'
913
+ , 'familyMembers/0' : 'Veselina'
914
+ , 'familyMembers/1' : 'Iskra'
915
+ , 'familyMembers/2' : 'Maria'
916
+ , 'familyMembers/3' : 'Vasil'
917
+ , 'familyMembers/4' : 'Vladimir'
918
+ , 'familyMembers/5' : 'Petya'
919
+ , 'shoes/winter/0' : 'Keen'
920
+ , 'shoes/winter/1' : 'Head'
921
+ , 'shoes/summer/0' : 'Lotto'
922
+ , 'shoes/summer/1' : 'Asics'
466
923
  }
467
924
  ```
468
925
 
469
-
470
926
  ### Files
471
927
  Data is interpreted like file/folder description.
928
+
472
929
  ```js
473
930
  [
474
- 'root/name/Peter'
475
- , 'root/familiMembers/Veselina'
476
- , 'root/familyMembers/Iskra'
477
- , 'root/familyMembers/Maria'
478
- , 'root/familyMembers/Vasil'
479
- , 'root/familyMembers/Vladimir'
480
- , 'root/familyMembers/Petya'
481
- , 'root/shoes/winter/Keen'
482
- , 'root/shoes/winter/Head'
483
- , 'root/shoes/summer/Lotto'
484
- , 'root/shoes/summer/Asics'
931
+ 'name/Peter'
932
+ , 'familyMembers/Veselina'
933
+ , 'familyMembers/Iskra'
934
+ , 'familyMembers/Maria'
935
+ , 'familyMembers/Vasil'
936
+ , 'familyMembers/Vladimir'
937
+ , 'familyMembers/Petya'
938
+ , 'shoes/winter/Keen'
939
+ , 'shoes/winter/Head'
940
+ , 'shoes/summer/Lotto'
941
+ , 'shoes/summer/Asics'
485
942
  ]
486
943
  ```
487
944
 
488
-
489
-
490
945
  ### Tuples
491
946
 
492
947
  Array of tuples. First element represents location + property name, second is the value.
@@ -494,7 +949,7 @@ Array of tuples. First element represents location + property name, second is th
494
949
  ```js
495
950
  [
496
951
  ['name', 'Peter' ]
497
- , ['familiMembers', 'Veselina']
952
+ , ['familyMembers', 'Veselina']
498
953
  , ['familyMembers', 'Iskra']
499
954
  , ['familyMembers', 'Maria']
500
955
  , ['familyMembers', 'Vasil']
@@ -508,25 +963,194 @@ Array of tuples. First element represents location + property name, second is th
508
963
  ```
509
964
 
510
965
 
966
+ ## Examples
511
967
 
968
+ ### Find people under 40
512
969
 
970
+ Find a people that are under 40 years old and provide the result as a list.
513
971
 
514
- ## External Links
972
+ ```js
973
+ let data = {
974
+ 'school' : [
975
+ { name: 'Ivan', age: 14 }
976
+ , { name: 'Georgy', age: 15 }
977
+ , { name: 'Adi', age: 11 }
978
+ , { name: 'Kati', age: 11 }
979
+ ]
980
+ , 'sports' : [
981
+ { name: 'Iva', age: 28 }
982
+ , { name: 'Stoyan', age: 36, sport: 'fencing' }
983
+ ]
984
+ , 'work' : [
985
+ { name: 'Hristo', age: 38 }
986
+ , { name: 'Lachezar', age: 33 }
987
+ , { name: 'Veselina', age: 35 }
988
+
989
+ ]
990
+ , 'recent' : {
991
+ 'classmates' : [
992
+ { name: 'Anton', age: 42 }
993
+ , { name: 'Miroslava', age: 42 }
994
+ ]
995
+ , 'social' : [
996
+ { name: 'Iliana', age: 61 }
997
+ , { name: 'Tzvetan', age: 19 }
998
+ ]
999
+ }
1000
+ }
515
1001
 
1002
+ const dt = dtbox.init ( data ); // creates a dt-object
1003
+
1004
+ const result = dt.query ( store => {
1005
+ let
1006
+ i = 0
1007
+ , connectBuffer = []
1008
+ ;
1009
+ store.set ( 'root', []) // setup a root array element
1010
+ store
1011
+ .use ( 'listObject' ) // use only objects that are members of array
1012
+ .look ( ({ name, flatData }) => {
1013
+ if ( flatData.age < 40 ) {
1014
+ store.set ( i, flatData )
1015
+ connectBuffer.push ( `root/${i}` )
1016
+ i++
1017
+ }
1018
+ return 'next'
1019
+ })
1020
+ store.connect ( connectBuffer )
1021
+ })
1022
+ .model ( () => ({ as : 'std'}))
1023
+ console.log ( result )
1024
+ /** ->
1025
+ [
1026
+ { name: 'Ivan', age: 14 },
1027
+ { name: 'Georgy', age: 15 },
1028
+ { name: 'Adi', age: 11 },
1029
+ { name: 'Kati', age: 11 },
1030
+ { name: 'Iva', age: 28 },
1031
+ { name: 'Stoyan', age: 36, sport: 'fencing' },
1032
+ { name: 'Hristo', age: 38 },
1033
+ { name: 'Lachezar', age: 33 },
1034
+ { name: 'Veselina', age: 35 },
1035
+ { name: 'Tzvetan', age: 19 }
1036
+ ]
1037
+ */
1038
+ ```
1039
+ ### Provide just a list of names
1040
+ Use the same data from previous example but return only the list of names.
1041
+
1042
+ ```js
1043
+ const result = dt.query ( store => {
1044
+ store.set ( 'root', [])
1045
+ store
1046
+ .use ( 'listObject' ) // use only objects that are members of array
1047
+ .look ( ({ flatData }) => {
1048
+ if ( flatData.age < 40 ) store.push ( 'root', flatData.name )
1049
+ return 'next'
1050
+ })
1051
+ })
1052
+ .model ( () => ({as:'std'}) )
1053
+ console.log ( result )
1054
+ /** ->
1055
+ [
1056
+ 'Ivan', 'Georgy',
1057
+ 'Adi', 'Kati',
1058
+ 'Iva', 'Stoyan',
1059
+ 'Hristo', 'Lachezar',
1060
+ 'Veselina', 'Tzvetan'
1061
+ ]
1062
+ */
1063
+ ```
1064
+
1065
+ ### Organize people in two groups
1066
+ Return an object with two groups
1067
+ - 'over40'
1068
+ - 'under40'
1069
+ Provide only the names.
1070
+ ```js
1071
+ const result = dt.query ( store => {
1072
+ store.set ( 'root', {} )
1073
+ store.set ( 'under40', [])
1074
+ store.set ( 'over40' , [])
1075
+ store.connect ([ 'root/under40', 'root/over40' ])
1076
+ store
1077
+ .use ( 'listObject' ) // use only objects that are members of array
1078
+ .look ( ({ flatData }) => {
1079
+ let location = ( flatData.age > 40 ) ? 'over40' : 'under40';
1080
+ store.push ( location, flatData.name )
1081
+ return 'next'
1082
+ })
1083
+ })
1084
+ .model ( () => ({ as : 'std'}))
1085
+ console.log ( result )
1086
+ /** ->
1087
+ {
1088
+ 'under40': [
1089
+ 'Ivan', 'Georgy',
1090
+ 'Adi', 'Kati',
1091
+ 'Iva', 'Stoyan',
1092
+ 'Hristo', 'Lachezar',
1093
+ 'Veselina', 'Tzvetan'
1094
+ ],
1095
+ 'over40': [ 'Anton', 'Miroslava', 'Iliana' ]
1096
+ }
1097
+ */
1098
+ ```
1099
+
1100
+
1101
+ ### Create a deep copy of dt-object
1102
+
1103
+ ```js
1104
+ const result = dt.query ( store => {
1105
+ store.look ( ({ name, flatData, breadcrumbs }) => {
1106
+ store.set ( name, flatData )
1107
+ if ( breadcrumbs.includes('/') ) store.connect ([breadcrumbs])
1108
+ return 'next'
1109
+ })
1110
+ })
1111
+ .model ( () => ({as:'std'}))
1112
+ console.log ( result )
1113
+ /** ->
1114
+ {
1115
+ school: [
1116
+ { name: 'Ivan', age: 14 },
1117
+ { name: 'Georgy', age: 15 },
1118
+ { name: 'Adi', age: 11 },
1119
+ { name: 'Kati', age: 11 }
1120
+ ],
1121
+ sports: [
1122
+ { name: 'Iva', age: 28 },
1123
+ { name: 'Stoyan', age: 36, sport: 'fencing' }
1124
+ ],
1125
+ work: [
1126
+ { name: 'Hristo', age: 38 },
1127
+ { name: 'Lachezar', age: 33 },
1128
+ { name: 'Veselina', age: 35 }
1129
+ ],
1130
+ recent: {
1131
+ classmates: [ { name: 'Anton', age: 42 }, { name: 'Miroslava', age: 42 } ],
1132
+ social: [ { name: 'Iliana', age: 61 }, { name: 'Tzvetan', age: 19 } ]
1133
+ }
1134
+ }
1135
+ */
1136
+ ```
1137
+
1138
+
1139
+
1140
+
1141
+ ## External Links
516
1142
  - [Migration guide](https://github.com/PeterNaydenov/dt-toolbox/blob/master/Migration.guide.md)
517
1143
  - [History of changes](https://github.com/PeterNaydenov/dt-toolbox/blob/master/Changelog.md)
1144
+ - [Documentation v.4.x.x](https://github.com/PeterNaydenov/dt-toolbox/blob/master/README_v.4.x.x.md)
518
1145
  - [Documentation v.2.x.x](https://github.com/PeterNaydenov/dt-toolbox/blob/master/README_v.2.x.x.md)
519
1146
 
520
1147
 
521
1148
 
522
-
523
1149
  ## Credits
524
1150
  'dt-toolbox' was created and supported by Peter Naydenov.
525
1151
 
526
1152
 
527
1153
 
528
-
529
-
530
1154
  ## License
531
1155
  'dt-toolbox' is released under the [MIT License](http://opensource.org/licenses/MIT).
532
1156