@journeyapps-solutions/cc-util-sync-collective 0.0.1

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/.jsbeautifyrc ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "comment": "Configurations for [js, jsx, json] and Shared configurations",
3
+
4
+ "brace_style": "collapse-preserve-inline",
5
+ "break_chained_methods": false,
6
+ "comma_first": false,
7
+ "e4x": true,
8
+ "end_with_newline": true,
9
+ "eol": "\n",
10
+ "eval_code": false,
11
+ "keep_array_indentation": false,
12
+ "keep_function_indentation": false,
13
+ "indent_size": 4,
14
+ "indent_char": " ",
15
+ "indent_level": 0,
16
+ "indent_with_tabs": true,
17
+ "jslint_happy": false,
18
+ "max_preserve_newlines": 10,
19
+ "preserve_newlines": true,
20
+ "space_after_anon_function": false,
21
+ "space_before_conditional": false,
22
+ "space_in_paren": false,
23
+ "wrap_attributes": "auto",
24
+ "wrap_attributes_indent_size": 4,
25
+ "wrap_line_length": 0,
26
+ "unescape_strings": false,
27
+
28
+
29
+ "comment": "Configurations for [css] and its pre-processors [sass, scss, less]",
30
+
31
+ "newline_between_rules": true,
32
+ "selector_separator_newline": false,
33
+
34
+
35
+ "comment": "Configurations for [html, xml]",
36
+
37
+ "extra_liners": ["head", "body", "/html"],
38
+ "indent_inner_html": true,
39
+ "indent_scripts": "normal",
40
+ "unformatted": ["inline"]
41
+ }
package/.npmignore ADDED
@@ -0,0 +1,4 @@
1
+ .circleci
2
+ .babelrc
3
+ node_modules
4
+ src
package/README.md ADDED
@@ -0,0 +1,472 @@
1
+ # cc-util-sync-collective
2
+
3
+ This module allows you to move data between Journey Apps without having to use code outside of the Delivery framework. There are two supported models, Master / Slave replication and Master / Master replication.
4
+
5
+ The purpose of this module is to make the process as generic and seamless as possible.
6
+
7
+ Code origin is from JS Task with the original owner ***Eugene Louw***
8
+
9
+
10
+ ## Documentation
11
+ All code is clearly documented, please see code for more details.
12
+ You can view some example code below
13
+
14
+ #### Required Reading
15
+
16
+ To enable replication you are expected to have a decent understanding of how certain parts of the Journey System work. Please review the links below:
17
+
18
+ 1. Webhooks: http://resources.journeyapps.com/v4/webhooks
19
+ 2. JourneyApps Backend API: http://resources.journeyapps.com/v4/api
20
+ 3. Cloud Code : https://docs.journeyapps.com/docs/cloudcode-introduction
21
+
22
+
23
+ ## 1. Master / Slave Replication
24
+
25
+ ![alt text](/resources/Data_Sync_Setup_Master_Slave.png "Data Broker Setup")
26
+
27
+ Setup
28
+
29
+ 1. Ensure that the Model(s) exist on all Slaves.
30
+ 2. On the Master app, create the webhook on the Model(s) that you want replicated to the slave apps
31
+ 3. Add the CloudCode Task to the Master Journey App
32
+ 4. Add the collective on the Data Broker
33
+ 5. Add the endpoints to the Data Broker
34
+ 6. Add the tables to sync to the Data Broker
35
+ 7. Create the Model(s) in the Data Model of the Broker
36
+
37
+ #### 1. Ensure that the Model(s) exist on all Slaves.
38
+
39
+ Copy the model(s) that you want to sync from your Master Data Model XML to all of the Slave Data Model XML.
40
+
41
+ #### 2. Create the webhook on the Model of the Master Journey App
42
+
43
+ Open the Data Model view of the **Master** Journey App and add the following xml to the Model(s) that you want to sync:
44
+
45
+ ```xml
46
+ <!-- Required for Sync -->
47
+ <webhook type="update" receiver="cloudcode" action="sync_collective" />
48
+ ```
49
+
50
+ #### 3. Add the CloudCode to the Master Journey App
51
+
52
+ 1. Create a new CloudCode task in your Master Journey App.
53
+ 2. Create an config file with the credentials required.
54
+ ```js
55
+ module.exports = {
56
+ "collective": "testing",
57
+ "url": "https://run-testing-us.journeyapps.com/api/v4/577ec96be1a2ef691feaf19a",
58
+ "api_user": "<api_user>",
59
+ "api_pass": "<api_pass>",
60
+ "endpoint_api_user": "<endpoint_api_user>"
61
+ }
62
+ ```
63
+
64
+ Review the following fields and change as described:
65
+
66
+ 1. **collective**: The name that you have given the organization, only use alpha characters. The naming convention of a collective is built from the app url as follows, https://build.journeyapps.com/kaufmann/accrete-solutions-grupo-kaufmann-service-advisor
67
+ In the above example the collective will be called "kaufmann". In the case where the url might contain "-" as follow, "kauf-mann", then remove the "-" and the collective name becomes "kaufmann".
68
+
69
+ 2. **endpoint_api_user** : This must match Options.username
70
+
71
+ The following fields point to the Data Broker and correspond to the Testing Environment for the Data Broker and will not need changing.
72
+
73
+ 3. **url**: The url to the Data Broker
74
+ 4. **api_user**: The api_user of the Data Broker
75
+ 5. **api_pass**: The api_pass of the Data Broker
76
+
77
+ Ensure that you have checked "JourneyApps Webhooks" and named the task sync_collective.
78
+
79
+ #### 4. Add the collective on the Data Broker
80
+
81
+ Create the collective in, https://run-testing-us.journeyapps.com/app/journey-usa-data-broker/acc/577ec96be1a2ef691feaf19a/objects#/collective/new
82
+ NB. The name of the *collective* should match *collective* from the CloudCode task you created in step 2.
83
+
84
+ #### 5. Add the endpoints to the Data Broker
85
+
86
+ Endpoints are defined as all the Journey Apps that are part of the replication process. This includes all the Slave and the Master Journey Apps.
87
+
88
+ Create all the endpoints in, https://run-testing-us.journeyapps.com/app/journey-usa-data-broker/acc/577ec96be1a2ef691feaf19a/objects#/endpoint/new
89
+
90
+ 1. **Endpoint.name**: Name to reference the Journey App Name, the naming convention to be used comes from the Journey App url.
91
+ https://build.journeyapps.com/kaufmann/accrete-solutions-grupo-kaufmann-service-advisor
92
+
93
+ The following fields can all be found in the Deploy / Manage API section of your Journey App,
94
+
95
+ 2. **Endpoint.api_user**: The HTTP Auth Username field on the Journey App
96
+ 3. **Endpoint.api_pass**: The HTTP Auth Password field on the Journey App
97
+ 4. **Endpoint.url**: The Base URL field on the Journey App
98
+ 5. **Endpoint.collective**: Select the collective you created in Step 3.
99
+
100
+ #### 6. Add the models to sync to the Data Broker
101
+
102
+ In this step you need to create an entry for each endpoint and model that need to be synced. So if you had three endpoints and two models, you would create 3x2=6 entries in this step.
103
+
104
+ The naming convention for the Sync Model Name is
105
+ ```js
106
+ {collective_name}_{model_name}
107
+ ```
108
+
109
+ Create an entry (Sync Model Name) for each endpoint that forms part of the replication process (master and all slaves)
110
+ https://run-testing-us.journeyapps.com/app/journey-usa-data-broker/acc/577ec96be1a2ef691feaf19a/objects#/sync_table/new
111
+
112
+ #### 7. Create the model in the Data Model of the Broker
113
+
114
+ 1. Open the Data Broker Data Model XML, https://build.journeyapps.com/journey-usa/journey-usa-data-broker/schema/edit#/data_model/code
115
+
116
+ 2. a) Copy the data model from your Master Journey App Data Model XML view, scroll to the bottom of the Data Broker Data Model XML if the collective has never been used before and paste it there.
117
+
118
+ **OR**
119
+
120
+ b) If the collective has been used before find the collective within the XML document and paste the model structure there. Rename the pasted model to follow the naming convention defined in step 6.
121
+ ```
122
+ {collective_name}_{model_name}
123
+ ```
124
+
125
+ 3. The following fields must be added to your Data Broker Data Model XML that you are syncing, some of these fields might already exist and should not be duplicated,
126
+ ```xml
127
+ <!-- Required for Sync -->
128
+ <field name="synced" label="Synced" type="boolean" />
129
+ <field name="api_user" label="ApiUser" type="text" />
130
+ <field name="updated_at" label="UpdatedAt" type="datetime" />
131
+
132
+ <!-- Required for Sync -->
133
+ <webhook type="update" receiver="cloudcode" action="sync_collective" />
134
+ ```
135
+
136
+ > **Note on syncing relationships:** Remove all has-many fields and convert belongs-to fields to {field_name}_id. The editor will not like this very much but it will continue to work. See this quandora for further information about the warning.
137
+
138
+
139
+ ## 2. Master / Master Replication
140
+
141
+ Overview:
142
+ Changes to a Model can come from any of the associated Journey Apps within the collective and will be synced out to all of the other Journey Apps within the collective.
143
+
144
+ ![alt text](/resources/Data_Sync_Setup_Master_Master.png "Data Broker Setup")
145
+
146
+ Setup
147
+ 1. Create the webhook on the Model of the Master Journey App
148
+ 2. Add the CloudCode Task to the Master Journey App
149
+ 3. Copy the model and repeat step 2 for all Master Journey Apps
150
+ 4. Add the collective on the Data Broker
151
+ 5. Add the endpoints to the Data Broker
152
+ 6. Add the tables to sync to the Data Broker
153
+ 7. Create the model in the Data Model of the Broker
154
+ 8. Ensure that the table exists on all Master Apps.
155
+
156
+
157
+ #### 1. Create the webhook on the Model of the Master Journey App
158
+
159
+ Open the Data Model view of your app and add the following xml to the Model(s) that you want to sync,
160
+
161
+ ```xml
162
+ <!-- Required for Sync -->
163
+ <field name="synced" label="Synced" type="boolean" />
164
+ <webhook type="update" receiver="cloudcode" action="sync_collective" />
165
+ ```
166
+
167
+ #### 2. Add the CloudCode Task to the Master Journey App
168
+
169
+ 1. Create a new CloudCode in your Master Journey App.
170
+ https://us-be-js.journeyapps.com/admin/testing_usa/577eccd7ecc8cf1d48849d9c/577ece976cfe5403bd290f61
171
+
172
+ 2. Copy and paste from below section to your json config in the cloudcode that you are creating.
173
+ ```js
174
+ module.exports = {
175
+ "collective": "testing",
176
+ "url": "https://run-testing-us.journeyapps.com/api/v4/577ec96be1a2ef691feaf19a",
177
+ "api_user": "<api_user>",
178
+ "api_pass": "<api_pass>",
179
+ "endpoint_api_user": "<endpoint_api_user>"
180
+ }
181
+ ```
182
+
183
+ Review the following fields and change as described:
184
+
185
+ 1. **collective**: The name that you have given the organization, only use alpha characters. The naming convention of a collective is build from the app url as follows,
186
+ https://build.journeyapps.com/kaufmann/accrete-solutions-grupo-kaufmann-service-advisor
187
+
188
+ In the above example the collective will be called "kaufmann". In the case where the url might contain "-" as follow, "kauf-mann", then remove the "-" and the collective name becomes "kaufmann".
189
+
190
+ 2. **endpoint_api_user**: This must match Options.username
191
+
192
+ The following fields point to the Data Broker and correspond to the Testing Environment for the Data Broker and will not need changing.
193
+
194
+ 3. **url**: The url to the Data Broker
195
+ 4. **api_user**: The api_user of the Data Broker
196
+ 5. **api_pass**: The api_pass of the Data Broker
197
+
198
+ Ensure that you have checked "Webhook triggering" and named the Cloud Code Task sync_collective before saving.
199
+
200
+ #### 3. Copy the model and repeat step 2 for all Master Journey Apps
201
+
202
+ Copy the data model from step 1 to all of your Master Journey Apps and repeat step 2 for each of the apps that you copied the model to.
203
+
204
+ #### 4. Add the collective on the Data Broker
205
+
206
+ Create the collective in,
207
+ https://run-testing-us.journeyapps.com/app/journey-usa-data-broker/acc/577ec96be1a2ef691feaf19a/objects#/collective/new
208
+
209
+ NB. The name of the *collective* should match *collective* from the Cloud Code you created in step 2.
210
+
211
+ #### 5. Add the endpoints to the Data Broker
212
+
213
+ Endpoints are defined as all the Journey Apps that are part of the replication process. This includes all the Slave and the Master Journey Apps.
214
+
215
+ Create all the endpoints in,
216
+ https://run-testing-us.journeyapps.com/app/journey-usa-data-broker/acc/577ec96be1a2ef691feaf19a/objects#/endpoint/new
217
+
218
+ 1. **Endpoint.name**: Name to reference the Journey App Name, the naming convention to be used comes from the Journey App url.
219
+ https://build.journeyapps.com/kaufmann/accrete-solutions-grupo-kaufmann-service-advisor
220
+
221
+ The following fields can all be found in the Deploy / Manage API section of your Journey App,
222
+ 2. **Endpoint.api_user**: The HTTP Auth Username field on the Journey App
223
+ 3. **Endpoint.api_pass**: The HTTP Auth Password field on the Journey App
224
+ 4. **Endpoint.url**: The Base URL field on the Journey App
225
+ 5. **Endpoint.collective**: Select the collective you created in Step 4.
226
+
227
+ #### 6. Add the models to sync to the Data Broker
228
+
229
+ In this step you need to create an entry for each endpoint and model that need to be synced. So if you had three endpoints and two models, you would create 3x2=6 entries in this step.
230
+
231
+ The naming convention for the Sync Model Name is
232
+ ```
233
+ {collective_name}_{model_name}
234
+ ```
235
+
236
+ Create an entry (Sync Model Name) for each endpoint that forms part of the replication process (master and all slaves)
237
+
238
+ https://run-testing-us.journeyapps.com/app/journey-usa-data-broker/acc/577ec96be1a2ef691feaf19a/objects#/sync_table/new
239
+
240
+ #### 7. Create the model in the Data Model of the Broker
241
+
242
+ 1. Open the Data Broker Data Model XML,
243
+ https://build.journeyapps.com/journey-usa/journey-usa-data-broker/schema/edit#/data_model/code
244
+
245
+ 2. Copy the data model from your Journey App Data Model XML view, scroll to the bottom of the Data Broker Data Model XML if the collective has never been used before and paste it there.
246
+
247
+ 3. If the collective has been used before find the collective within the XML document and paste the model structure there. Rename the pasted model too follow the naming convention defined in step 6.
248
+ ```
249
+ {collective_name}_{model_name}
250
+ ```
251
+
252
+ 4. The following fields must be added to your Data Broker Data Model XML that you are syncing, some of these fields might already exist and should not be duplicated,
253
+ ```xml
254
+ <!-- Required for Sync -->
255
+ <field name="synced" label="Synced" type="boolean" />
256
+ <field name="api_user" label="ApiUser" type="text" />
257
+ <field name="updated_at" label="UpdatedAt" type="datetime" />
258
+
259
+ <!-- Required for Sync -->
260
+ <webhook type="update" receiver="cloudcode" action="sync_collective" />
261
+ ```
262
+
263
+ > **Note on syncing relationships** :
264
+ Remove all has-many fields and convert belongs-to fields to {field_name}_id. The editor will not like this very much but it will continue to work. See this quandora for further information about the warning.
265
+
266
+ #### 8. Ensure that the model exists on all Master Apps.
267
+
268
+
269
+ ## Installation
270
+
271
+ #### Per machine
272
+
273
+ ```
274
+ # Once as setup
275
+ npm login
276
+ > journeyapps-solutions-user
277
+ > see password on 1Password
278
+ > infrastructure+npmsolutions@journeyapps.com
279
+
280
+ yarn add @journeyapps-solutions/cc-util-sync-collective --save
281
+ ```
282
+
283
+ #### Per CloudCode app
284
+
285
+ ```
286
+ NPM_TOKEN=... # Token for journeyapps-solutions-user from 1Password
287
+ echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ./app/cloudcode/.npmrc
288
+ ```
289
+
290
+ #### Per CloudCode task
291
+
292
+ ```
293
+ yarn add @journeyapps-solutions/cc-util-sync-collective
294
+ ```
295
+
296
+ ## Deploying
297
+
298
+ ```
299
+ yarn version
300
+ ```
301
+
302
+ ## Usage
303
+
304
+ ### Data Model
305
+
306
+ Broker Data Model, The broker acts as the Master
307
+ ```xml
308
+ <!-- ADD OBJECT TYPES HERE: -->
309
+ <!-- Collective can be seen as the organization -->
310
+ <!-- for which we want to sync the data between -->
311
+ <model name="collective" label="Collective">
312
+ <field name="name" label="Name" type="text" />
313
+
314
+ <has-many model="endpoint" name="endpoints" />
315
+
316
+ <display>{name}</display>
317
+ </model>
318
+
319
+ <!-- Endpoint is where the data is coming from and where -->
320
+ <!-- data is going to. We will have two models here, master / slave and -->
321
+ <!-- master / master, think of it in terms of traditional replication -->
322
+ <!-- The data here should be found on the Deploy section of your app -->
323
+ <model name="endpoint" label="Endpoint">
324
+ <field name="name" label="Name" type="text" />
325
+
326
+ <field name="api_user" label="ApiUser" type="text" />
327
+ <field name="api_pass" label="ApiPass" type="text:password" />
328
+ <field name="url" label="Url" type="text" />
329
+
330
+ <belongs-to model="collective" />
331
+ <has-many model="sync_table" name="sync_tables" />
332
+
333
+ <display>{name}</display>
334
+ </model>
335
+
336
+ <!-- Endpoint might not want all the data tables synced that is associated with a collective -->
337
+ <!-- So this will give you a way to only set the tables the you require for the endpoint -->
338
+ <!-- table_name should be in the format of {collective}_{name_on_endpoint} -->
339
+ <model name="sync_table" label="SyncTable">
340
+ <field name="table_name" label="Sync Model Name" type="text" />
341
+
342
+ <belongs-to model="endpoint" />
343
+ <display>{endpoint.name}: {table_name}</display>
344
+ </model>
345
+ ```
346
+ Collective example. Broker side (Master)
347
+ ```xml
348
+ <!-- Collective:aviat -->
349
+ <model name="aviat_project" label="Aviat: Project">
350
+ <field name="number" label="Number" type="text"/> <!-- Identifier -->
351
+ <field name="customer_name" label="Customer Name" type="text"/>
352
+ <field name="project_name" label="Project Name" type="text"/> <!-- typically the name of the end-user e.g. Oracle Stadium, where the Aviat Customer would be Verizon installing wireless for the stadium -->
353
+ <field name="date_created" label="Date Created" type="date"/>
354
+ <field name="status" label="Status" type="single-choice">
355
+ <option key="draft">Draft</option>
356
+ <option key="compiling">Compiling</option>
357
+ <option key="survey">Survey</option>
358
+ <option key="review">Review</option>
359
+ <option key="archived">Archived</option>
360
+ </field>
361
+ <field name="archived" label="Archived?" type="boolean" />
362
+
363
+ <!-- Required for Sync -->
364
+ <field name="country_id" label="Country ID" type="text" />
365
+ <field name="created_by_account_id" label="Created By Account ID" type="text" />
366
+ <field name="synced" label="Synced" type="boolean" />
367
+ <field name="api_user" label="ApiUser" type="text" />
368
+ <field name="updated_at" label="UpdatedAt" type="datetime" />
369
+
370
+ <!-- Required for Sync -->
371
+ <webhook type="update" receiver="cloudcode" action="sync_collective" />
372
+
373
+ <display>{number} - {customer_name} ({status})</display>
374
+ </model>
375
+ ```
376
+
377
+ Collective example, Slave side.
378
+ ```xml
379
+ <model name="project" label="Project">
380
+ <!-- NB: This model is synced with other apps (Path Middleman, Install & COP, Data Broker). Any changes need to be replicated there if you want them in those apps. -->
381
+ <field name="number" label="Number" type="text"/> <!-- Identifier -->
382
+ <field name="customer_name" label="Customer Name" type="text"/>
383
+ <field name="project_name" label="Project Name" type="text"/> <!-- typically the name of the end-user e.g. Oracle Stadium, where the Aviat Customer would be Verizon installing wireless for the stadium -->
384
+ <field name="system_description" label="System Description" type="text:paragraph" />
385
+ <field name="system_diagram_photo" label="System Diagram Photo" type="photo" />
386
+ <field name="date_created" label="Date Created" type="date"/>
387
+ <field name="status" label="Status" type="single-choice">
388
+ <option key="draft">Draft</option>
389
+ <option key="compiling">Compiling</option>
390
+ <option key="survey">Survey</option>
391
+ <option key="review">Review</option>
392
+ <option key="archived">Archived</option>
393
+ </field>
394
+ <field name="archived" label="Archived?" type="boolean" />
395
+ <field name="previous_status" label="Previous Status" type="text" />
396
+ <!-- Required for sync with the data broker -->
397
+ <field name="synced" label="Synced" type="boolean" />
398
+
399
+ <belongs-to model="country" /> <!-- Required for i18n -->
400
+ <belongs-to model="user_account" name="created_by_account"/>
401
+ <belongs-to model="user_account" name="project_owner" />
402
+ <has-many model="assignment" name="assignments" />
403
+ <has-many model="site_survey" name="site_surveys"/>
404
+ <has-many model="path_survey" name="path_surveys"/>
405
+ <has-many model="site_information" name="site_informations" /> <!-- Will only have one -->
406
+
407
+ <index on="created_by_account" />
408
+ <index on="country" />
409
+
410
+ <!-- Required for sync with the data broker -->
411
+ <webhook type="update" receiver="cloudcode" action="sync_collective" />
412
+
413
+ <display>{number} - {customer_name} ({status})</display>
414
+ </model>
415
+ ```
416
+
417
+ ### Cloud Code:
418
+
419
+ index.js: - ***Master example***
420
+
421
+ ```js
422
+ // make sure config.js has the relevant credentials
423
+ const config = require('./config');
424
+ const SyncCollective = require('@journeyapps-solutions/cc-util-sync-collective');
425
+
426
+ export async function run() {
427
+
428
+ const SyncCollective = new SyncCollective({/*..Options..*/});
429
+
430
+ let _object = webhook.object;
431
+ let _operation = webhook.operation;
432
+ let _sync_tables = DB.sync_table.where("table_name = ?", _object.type).first();
433
+ let _endpoint = sync_table.endpoint();
434
+
435
+ SyncCollective.syncToSlave({
436
+ operation : SyncCollective.operation[_operation],
437
+ objectToSync : _object,
438
+ endpoint : _endpoint
439
+ });
440
+
441
+
442
+ }
443
+ ```
444
+
445
+ index.js: - ***Slave example***
446
+
447
+ ```js
448
+ // make sure config.js has the relevant credentials
449
+ const config = require('./config');
450
+ const SyncCollective = require('@journeyapps-solutions/cc-util-sync-collective');
451
+
452
+ export async function run() {
453
+
454
+ const SyncCollective = new SyncCollective({/*..Options..*/});
455
+
456
+ let _object = webhook.object;
457
+ let _operation = webhook.operation;
458
+
459
+ SyncCollective.syncToMaster({
460
+ operation : SyncCollective.operation[_operation],
461
+ objectToSync : _object
462
+ });
463
+
464
+ }
465
+ ```
466
+
467
+ ## Testing
468
+
469
+ ```js
470
+
471
+ yarn test
472
+ ```
package/index.js ADDED
@@ -0,0 +1,11 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Load support assets
5
+ */
6
+ const ccSyncCollective = require('./lib/index');
7
+
8
+ /**
9
+ * Export
10
+ */
11
+ module.exports = ccSyncCollective;