auth0-deploy-cli 7.3.6 → 7.5.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 (113) hide show
  1. package/.circleci/config.yml +15 -0
  2. package/.github/CODEOWNERS +1 -0
  3. package/.husky/pre-commit +6 -0
  4. package/.husky/pre-push +4 -0
  5. package/.nyc_output/60b76a45-577b-4171-9982-a8e836ab7fd6.json +1 -0
  6. package/.nyc_output/processinfo/60b76a45-577b-4171-9982-a8e836ab7fd6.json +1 -0
  7. package/.nyc_output/processinfo/index.json +1 -1
  8. package/CHANGELOG.md +35 -2
  9. package/lib/args.js +89 -81
  10. package/lib/commands/export.js +51 -77
  11. package/lib/commands/import.js +45 -69
  12. package/lib/commands/index.js +11 -20
  13. package/lib/configFactory.js +19 -27
  14. package/lib/context/defaults.js +18 -41
  15. package/lib/context/directory/handlers/actions.js +77 -107
  16. package/lib/context/directory/handlers/attackProtection.js +59 -0
  17. package/lib/context/directory/handlers/clientGrants.js +45 -54
  18. package/lib/context/directory/handlers/clients.js +60 -79
  19. package/lib/context/directory/handlers/connections.js +65 -89
  20. package/lib/context/directory/handlers/databases.js +91 -123
  21. package/lib/context/directory/handlers/emailProvider.js +46 -57
  22. package/lib/context/directory/handlers/emailTemplates.js +67 -80
  23. package/lib/context/directory/handlers/guardianFactorProviders.js +41 -49
  24. package/lib/context/directory/handlers/guardianFactorTemplates.js +41 -49
  25. package/lib/context/directory/handlers/guardianFactors.js +41 -49
  26. package/lib/context/directory/handlers/guardianPhoneFactorMessageTypes.js +40 -50
  27. package/lib/context/directory/handlers/guardianPhoneFactorSelectedProvider.js +40 -50
  28. package/lib/context/directory/handlers/guardianPolicies.js +40 -50
  29. package/lib/context/directory/handlers/hooks.js +55 -70
  30. package/lib/context/directory/handlers/index.js +53 -123
  31. package/lib/context/directory/handlers/migrations.js +36 -41
  32. package/lib/context/directory/handlers/organizations.js +54 -69
  33. package/lib/context/directory/handlers/pages.js +72 -86
  34. package/lib/context/directory/handlers/resourceServers.js +41 -49
  35. package/lib/context/directory/handlers/roles.js +49 -62
  36. package/lib/context/directory/handlers/rules.js +52 -68
  37. package/lib/context/directory/handlers/rulesConfigs.js +33 -32
  38. package/lib/context/directory/handlers/tenant.js +52 -47
  39. package/lib/context/directory/handlers/triggers.js +39 -54
  40. package/lib/context/directory/index.js +113 -101
  41. package/lib/context/index.js +96 -105
  42. package/lib/context/yaml/handlers/actions.js +71 -88
  43. package/lib/context/yaml/handlers/attackProtection.js +29 -0
  44. package/lib/context/yaml/handlers/clientGrants.js +36 -29
  45. package/lib/context/yaml/handlers/clients.js +61 -76
  46. package/lib/context/yaml/handlers/connections.js +76 -103
  47. package/lib/context/yaml/handlers/databases.js +64 -79
  48. package/lib/context/yaml/handlers/emailProvider.js +33 -30
  49. package/lib/context/yaml/handlers/emailTemplates.js +45 -54
  50. package/lib/context/yaml/handlers/guardianFactorProviders.js +27 -18
  51. package/lib/context/yaml/handlers/guardianFactorTemplates.js +27 -18
  52. package/lib/context/yaml/handlers/guardianFactors.js +27 -18
  53. package/lib/context/yaml/handlers/guardianPhoneFactorMessageTypes.js +27 -20
  54. package/lib/context/yaml/handlers/guardianPhoneFactorSelectedProvider.js +27 -20
  55. package/lib/context/yaml/handlers/guardianPolicies.js +27 -20
  56. package/lib/context/yaml/handlers/hooks.js +57 -67
  57. package/lib/context/yaml/handlers/index.js +53 -123
  58. package/lib/context/yaml/handlers/migrations.js +23 -24
  59. package/lib/context/yaml/handlers/organizations.js +40 -38
  60. package/lib/context/yaml/handlers/pages.js +49 -58
  61. package/lib/context/yaml/handlers/resourceServers.js +27 -18
  62. package/lib/context/yaml/handlers/roles.js +34 -24
  63. package/lib/context/yaml/handlers/rules.js +48 -58
  64. package/lib/context/yaml/handlers/rulesConfigs.js +27 -18
  65. package/lib/context/yaml/handlers/tenant.js +44 -30
  66. package/lib/context/yaml/handlers/triggers.js +32 -23
  67. package/lib/context/yaml/index.js +127 -142
  68. package/lib/index.js +73 -79
  69. package/lib/logger.js +18 -22
  70. package/lib/readonly.js +74 -66
  71. package/lib/tools/ValidationError.js +8 -13
  72. package/lib/tools/auth0/client.js +143 -133
  73. package/lib/tools/auth0/handlers/actions.js +231 -241
  74. package/lib/tools/auth0/handlers/attackProtection.js +86 -0
  75. package/lib/tools/auth0/handlers/branding.js +47 -46
  76. package/lib/tools/auth0/handlers/clientGrants.js +118 -116
  77. package/lib/tools/auth0/handlers/clients.js +72 -90
  78. package/lib/tools/auth0/handlers/connections.js +150 -118
  79. package/lib/tools/auth0/handlers/databases.js +127 -124
  80. package/lib/tools/auth0/handlers/default.js +186 -189
  81. package/lib/tools/auth0/handlers/emailProvider.js +67 -78
  82. package/lib/tools/auth0/handlers/emailTemplates.js +116 -92
  83. package/lib/tools/auth0/handlers/guardianFactorProviders.js +66 -81
  84. package/lib/tools/auth0/handlers/guardianFactorTemplates.js +60 -71
  85. package/lib/tools/auth0/handlers/guardianFactors.js +56 -63
  86. package/lib/tools/auth0/handlers/guardianPhoneFactorMessageTypes.js +80 -79
  87. package/lib/tools/auth0/handlers/guardianPhoneFactorSelectedProvider.js +77 -76
  88. package/lib/tools/auth0/handlers/guardianPolicies.js +59 -62
  89. package/lib/tools/auth0/handlers/hooks.js +201 -227
  90. package/lib/tools/auth0/handlers/index.js +53 -111
  91. package/lib/tools/auth0/handlers/migrations.js +99 -79
  92. package/lib/tools/auth0/handlers/organizations.js +225 -247
  93. package/lib/tools/auth0/handlers/pages.js +116 -154
  94. package/lib/tools/auth0/handlers/prompts.js +47 -46
  95. package/lib/tools/auth0/handlers/resourceServers.js +88 -112
  96. package/lib/tools/auth0/handlers/roles.js +203 -220
  97. package/lib/tools/auth0/handlers/rules.js +168 -189
  98. package/lib/tools/auth0/handlers/rulesConfigs.js +54 -63
  99. package/lib/tools/auth0/handlers/tenant.js +88 -64
  100. package/lib/tools/auth0/handlers/triggers.js +126 -126
  101. package/lib/tools/auth0/index.js +92 -85
  102. package/lib/tools/auth0/schema.js +39 -31
  103. package/lib/tools/constants.js +111 -21
  104. package/lib/tools/deploy.js +35 -32
  105. package/lib/tools/index.js +19 -32
  106. package/lib/tools/logger.js +11 -12
  107. package/lib/tools/utils.js +258 -254
  108. package/lib/utils.js +167 -190
  109. package/package.json +6 -3
  110. package/tsconfig.json +96 -0
  111. package/typescript-migration-progress.sh +22 -0
  112. package/.nyc_output/8cf4dd0c-1f3a-4ac1-899c-8e453a64221e.json +0 -1
  113. package/.nyc_output/processinfo/8cf4dd0c-1f3a-4ac1-899c-8e453a64221e.json +0 -1
@@ -1,289 +1,293 @@
1
1
  "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.keywordReplace = keywordReplace;
7
- exports.convertClientNameToId = convertClientNameToId;
8
- exports.convertClientNamesToIds = convertClientNamesToIds;
9
- exports.loadFile = loadFile;
10
- exports.flatten = flatten;
11
- exports.dumpJSON = dumpJSON;
12
- exports.calcChanges = calcChanges;
13
- exports.stripFields = stripFields;
14
- exports.getEnabledClients = getEnabledClients;
15
- exports.duplicateItems = duplicateItems;
16
- exports.filterExcluded = filterExcluded;
17
- exports.areArraysEquals = areArraysEquals;
18
-
19
- var _path = require("path");
20
-
21
- var _path2 = _interopRequireDefault(_path);
22
-
23
- var _fs = require("fs");
24
-
25
- var _fs2 = _interopRequireDefault(_fs);
26
-
27
- var _dotProp = require("dot-prop");
28
-
29
- var _dotProp2 = _interopRequireDefault(_dotProp);
30
-
31
- var _lodash = require("lodash");
32
-
33
- var _lodash2 = _interopRequireDefault(_lodash);
34
-
35
- var _logger = require("./logger");
36
-
37
- var _logger2 = _interopRequireDefault(_logger);
38
-
39
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
40
-
41
- function keywordReplace(input, mappings) {
42
- if (mappings && Object.keys(mappings).length > 0) {
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.areArraysEquals = exports.filterExcluded = exports.duplicateItems = exports.getEnabledClients = exports.stripFields = exports.calcChanges = exports.processChangedObjectFields = exports.dumpJSON = exports.flatten = exports.loadFileAndReplaceKeywords = exports.convertClientNamesToIds = exports.convertClientNameToId = exports.keywordReplace = exports.keywordStringReplace = exports.keywordArrayReplace = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const dot_prop_1 = __importDefault(require("dot-prop"));
10
+ const lodash_1 = __importDefault(require("lodash"));
11
+ const logger_1 = __importDefault(require("./logger"));
12
+ function keywordArrayReplace(input, mappings) {
43
13
  Object.keys(mappings).forEach(function (key) {
44
- const re = new RegExp(`##${key}##`, 'g');
45
- input = input.replace(re, mappings[key]);
14
+ // Matching against two sets of patterns because a developer may provide their array replacement keyword with or without wrapping quotes. It is not obvious to the developer which to do depending if they're operating in YAML or JSON.
15
+ const pattern = `@@${key}@@`;
16
+ const patternWithQuotes = `"${pattern}"`;
17
+ const regex = new RegExp(`${patternWithQuotes}|${pattern}`, 'g');
18
+ input = input.replace(regex, JSON.stringify(mappings[key]));
46
19
  });
20
+ return input;
21
+ }
22
+ exports.keywordArrayReplace = keywordArrayReplace;
23
+ function keywordStringReplace(input, mappings) {
47
24
  Object.keys(mappings).forEach(function (key) {
48
- const re = new RegExp(`@@${key}@@`, 'g');
49
- input = input.replace(re, JSON.stringify(mappings[key]));
25
+ const regex = new RegExp(`##${key}##`, 'g');
26
+ input = input.replace(regex, mappings[key]);
50
27
  });
51
- }
52
-
53
- return input;
28
+ return input;
54
29
  }
55
-
30
+ exports.keywordStringReplace = keywordStringReplace;
31
+ function keywordReplace(input, mappings) {
32
+ // Replace keywords with mappings within input.
33
+ if (mappings && Object.keys(mappings).length > 0) {
34
+ input = keywordStringReplace(input, mappings);
35
+ input = keywordArrayReplace(input, mappings);
36
+ }
37
+ return input;
38
+ }
39
+ exports.keywordReplace = keywordReplace;
56
40
  function convertClientNameToId(name, clients) {
57
- const found = clients.find(c => c.name === name);
58
- return found && found.client_id || name;
41
+ const found = clients.find((c) => c.name === name);
42
+ return (found && found.client_id) || name;
59
43
  }
60
-
44
+ exports.convertClientNameToId = convertClientNameToId;
61
45
  function convertClientNamesToIds(names, clients) {
62
- const resolvedNames = names.map(name => ({
63
- name,
64
- resolved: false
65
- }));
66
- const result = clients.reduce((acc, client) => {
67
- if (names.includes(client.name)) {
68
- const index = resolvedNames.findIndex(item => item.name === client.name);
69
- resolvedNames[index].resolved = true;
70
- acc.push(client.client_id);
71
- }
72
-
73
- return acc;
74
- }, []);
75
- const unresolved = resolvedNames.filter(item => !item.resolved).map(item => item.name);
76
- return [...unresolved, ...result];
46
+ const resolvedNames = names.map((name) => ({ name, resolved: false }));
47
+ const result = clients.reduce((acc, client) => {
48
+ if (names.includes(client.name)) {
49
+ const index = resolvedNames.findIndex((item) => item.name === client.name);
50
+ resolvedNames[index].resolved = true;
51
+ acc.push(client.client_id);
52
+ }
53
+ return acc;
54
+ }, []);
55
+ const unresolved = resolvedNames.filter((item) => !item.resolved).map((item) => item.name);
56
+ return [...unresolved, ...result];
77
57
  }
78
-
79
- function loadFile(file, mappings) {
80
- const f = _path2.default.resolve(file);
81
-
82
- try {
83
- _fs2.default.accessSync(f, _fs2.default.F_OK);
84
-
85
- if (mappings) {
86
- return keywordReplace(_fs2.default.readFileSync(f, 'utf8'), mappings);
58
+ exports.convertClientNamesToIds = convertClientNamesToIds;
59
+ function loadFileAndReplaceKeywords(file, mappings) {
60
+ // Load file and replace keyword mappings
61
+ const f = path_1.default.resolve(file);
62
+ try {
63
+ fs_1.default.accessSync(f, fs_1.default.F_OK);
64
+ if (mappings) {
65
+ return keywordReplace(fs_1.default.readFileSync(f, 'utf8'), mappings);
66
+ }
67
+ return fs_1.default.readFileSync(f, 'utf8');
68
+ }
69
+ catch (error) {
70
+ throw new Error(`Unable to load file ${f} due to ${error}`);
87
71
  }
88
-
89
- return _fs2.default.readFileSync(f, 'utf8');
90
- } catch (error) {
91
- throw new Error(`Unable to load file ${f} due to ${error}`);
92
- }
93
72
  }
94
-
73
+ exports.loadFileAndReplaceKeywords = loadFileAndReplaceKeywords;
95
74
  function flatten(list) {
96
- return list.reduce((a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []);
75
+ // Flatten an multiple arrays to single array
76
+ return list.reduce((a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []);
97
77
  }
98
-
78
+ exports.flatten = flatten;
99
79
  function dumpJSON(obj, spacing = 0) {
100
- return JSON.stringify(obj, null, spacing);
80
+ return JSON.stringify(obj, null, spacing);
101
81
  }
102
-
103
- function processChangedObjectFields(handler, desiredAssetState, currentAssetState, objectFields = [], allowDelete = false) {
104
- const desiredAssetStateWithChanges = { ...desiredAssetState
105
- };
106
-
107
- for (const fieldName of objectFields) {
108
- if (desiredAssetState[fieldName] && Object.keys(desiredAssetState[fieldName]).length) {
109
- if (currentAssetState[fieldName]) {
110
- for (const currentObjectFieldPropertyName of Object.keys(currentAssetState[fieldName])) {
111
- if (desiredAssetState[fieldName][currentObjectFieldPropertyName] === undefined) {
112
- if (allowDelete) {
113
- desiredAssetStateWithChanges[fieldName][currentObjectFieldPropertyName] = null;
114
- } else {
115
- _logger2.default.warn(`Detected that the ${fieldName} of the following ${handler.name} should be deleted. Doing so may be destructive.\nYou can enable deletes by setting 'AUTH0_ALLOW_DELETE' to true in the config\n${handler.objString(currentAssetState)}`);
82
+ exports.dumpJSON = dumpJSON;
83
+ /**
84
+ * @template T
85
+ * @param {typeof import('./auth0/handlers/default').default} handler
86
+ * @param {T} desiredAssetState
87
+ * @param {T} currentAssetState
88
+ * @param {string[]} [objectFields=[]]
89
+ * @param {boolean} [allowDelete=false]
90
+ * @returns T
91
+ */
92
+ function processChangedObjectFields({ handler, desiredAssetState, currentAssetState, allowDelete = false }) {
93
+ const desiredAssetStateWithChanges = Object.assign({}, desiredAssetState);
94
+ // eslint-disable-next-line no-restricted-syntax
95
+ for (const fieldName of handler.objectFields) {
96
+ const areDesiredStateAndCurrentStateEmpty = Object.keys(desiredAssetState[fieldName] || {}).length === 0 && Object.keys(currentAssetState[fieldName] || {}).length === 0;
97
+ if (areDesiredStateAndCurrentStateEmpty) {
98
+ // If both the desired state and current state for a given object is empty, it is a no-op and can skip
99
+ // eslint-disable-next-line no-continue
100
+ continue;
101
+ }
102
+ // A desired state that omits the objectField OR that has it as an empty object should
103
+ // signal that all fields should be removed (subject to ALLOW_DELETE).
104
+ if (desiredAssetState[fieldName] && Object.keys(desiredAssetState[fieldName]).length) {
105
+ // Both the current and desired state have the object field. Here's where we need to map
106
+ // to the APIv2 protocol of setting `null` values for deleted fields.
107
+ // For new and modified properties of the object field, we can just pass them through to
108
+ // APIv2.
109
+ if (currentAssetState[fieldName]) {
110
+ // eslint-disable-next-line no-restricted-syntax
111
+ for (const currentObjectFieldPropertyName of Object.keys(currentAssetState[fieldName])) {
112
+ // Loop through each object property that exists currently
113
+ if (desiredAssetState[fieldName][currentObjectFieldPropertyName] === undefined) {
114
+ // If the object has a property that exists now but doesn't exist in the proposed state
115
+ if (allowDelete) {
116
+ desiredAssetStateWithChanges[fieldName][currentObjectFieldPropertyName] = null;
117
+ }
118
+ else {
119
+ // If deletes aren't allowed, do outright delete the property within the object
120
+ logger_1.default.warn(`Detected that the ${fieldName} of the following ${handler.name || handler.id || ''} should be deleted. Doing so may be destructive.\nYou can enable deletes by setting 'AUTH0_ALLOW_DELETE' to true in the config\n${handler.objString(currentAssetState)}`);
121
+ }
122
+ }
123
+ }
116
124
  }
117
- }
118
125
  }
119
- }
120
- } else if (allowDelete) {
121
- desiredAssetStateWithChanges[fieldName] = {};
122
- } else {
123
- delete desiredAssetStateWithChanges[fieldName];
124
-
125
- _logger2.default.warn(`Detected that the ${fieldName} of the following ${handler.name} should be emptied. Doing so may be destructive.\nYou can enable deletes by setting 'AUTH0_ALLOW_DELETE' to true in the config\n${handler.objString(currentAssetState)}`);
126
+ else if (allowDelete) {
127
+ // If the desired state does not have the object field and the current state does, we
128
+ // should mark *all* properties for deletion by specifying an empty object.
129
+ //
130
+ // See: https://auth0.com/docs/users/metadata/manage-metadata-api#delete-user-metadata
131
+ desiredAssetStateWithChanges[fieldName] = {};
132
+ }
133
+ else {
134
+ delete desiredAssetStateWithChanges[fieldName];
135
+ logger_1.default.warn(`Detected that the ${fieldName} of the following ${handler.name || handler.id || ''} should be emptied. Doing so may be destructive.\nYou can enable deletes by setting 'AUTH0_ALLOW_DELETE' to true in the config\n${handler.objString(currentAssetState)}`);
136
+ }
126
137
  }
127
- }
128
-
129
- return desiredAssetStateWithChanges;
138
+ return desiredAssetStateWithChanges;
130
139
  }
131
-
132
- function calcChanges(handler, assets, existing, identifiers = ['id', 'name'], objectFields = [], allowDelete = false) {
133
- const update = [];
134
- let del = [...existing];
135
- let create = [...assets];
136
- const conflicts = [];
137
-
138
- const findByKeyValue = (key, value, arr) => arr.find(e => {
139
- if (Array.isArray(key)) {
140
- const values = key.map(k => e[k]);
141
-
142
- if (values.every(v => v)) {
143
- return value === values.join('-');
144
- }
145
- } else {
146
- return e[key] === value;
147
- }
148
-
149
- return false;
150
- });
151
-
152
- const processAssets = (id, arr) => {
153
- arr.forEach(asset => {
154
- let assetIdValue;
155
-
156
- if (Array.isArray(id)) {
157
- const values = id.map(i => asset[i]);
158
-
159
- if (values.every(v => v)) {
160
- assetIdValue = values.join('-');
161
- }
162
- } else {
163
- assetIdValue = asset[id];
164
- }
165
-
166
- if (assetIdValue) {
167
- const found = findByKeyValue(id, assetIdValue, del);
168
-
169
- if (found) {
170
- del = del.filter(e => e !== found);
171
- create = create.filter(e => e !== asset);
172
- update.push({ ...identifiers.reduce((obj, i) => {
173
- if (found[i]) obj[i] = found[i];
174
- return obj;
175
- }, {}),
176
- ...(objectFields.length ? processChangedObjectFields(handler, asset, found, objectFields, allowDelete) : asset)
177
- });
140
+ exports.processChangedObjectFields = processChangedObjectFields;
141
+ function calcChanges(handler, assets, existing, identifiers = ['id', 'name'], allowDelete = false) {
142
+ // Calculate the changes required between two sets of assets.
143
+ const update = [];
144
+ let del = [...existing];
145
+ let create = [...assets];
146
+ const conflicts = [];
147
+ const findByKeyValue = (key, value, arr) => arr.find((e) => {
148
+ if (Array.isArray(key)) {
149
+ const values = key.map((k) => e[k]);
150
+ if (values.every((v) => v)) {
151
+ return value === values.join('-');
152
+ }
178
153
  }
179
- }
180
- });
181
- };
182
-
183
- for (const id of identifiers) {
184
- processAssets(id, [...create]);
185
- }
186
-
187
- if (identifiers.includes('name')) {
188
- const uniqueID = identifiers[0];
189
- const futureAssets = [...create, ...update];
190
- futureAssets.forEach(a => {
191
- const inDeleted = del.filter(e => e.name === a.name && e[uniqueID] !== a[uniqueID])[0];
192
-
193
- if (!inDeleted) {
194
- const conflict = existing.filter(e => e.name === a.name && e[uniqueID] !== a[uniqueID])[0];
195
-
196
- if (conflict) {
197
- const temp = Math.random().toString(36).substr(2, 5);
198
- conflicts.push({ ...conflict,
199
- name: `${conflict.name}-${temp}`
200
- });
154
+ else {
155
+ return e[key] === value;
201
156
  }
202
- }
157
+ return false;
203
158
  });
204
- }
205
-
206
- return {
207
- del,
208
- update,
209
- conflicts,
210
- create
211
- };
159
+ const processAssets = (id, arr) => {
160
+ arr.forEach((asset) => {
161
+ let assetIdValue;
162
+ if (Array.isArray(id)) {
163
+ const values = id.map((i) => asset[i]);
164
+ if (values.every((v) => v)) {
165
+ assetIdValue = values.join('-');
166
+ }
167
+ }
168
+ else {
169
+ assetIdValue = asset[id];
170
+ }
171
+ if (assetIdValue) {
172
+ const found = findByKeyValue(id, assetIdValue, del);
173
+ if (found) {
174
+ // Delete from existing
175
+ del = del.filter((e) => e !== found);
176
+ // Delete from create as it's an update
177
+ create = create.filter((e) => e !== asset);
178
+ // Append identifiers to asset
179
+ update.push(Object.assign(Object.assign({}, identifiers.reduce((obj, i) => {
180
+ if (found[i])
181
+ obj[i] = found[i];
182
+ return obj;
183
+ }, {})), (handler.objectFields.length
184
+ ? processChangedObjectFields({
185
+ handler, desiredAssetState: asset, currentAssetState: found, allowDelete
186
+ })
187
+ : asset)));
188
+ }
189
+ }
190
+ });
191
+ };
192
+ // Loop through identifiers (in order) to try match assets to existing
193
+ // If existing then update if not create
194
+ // The remainder will be deleted
195
+ for (const id of identifiers) { // eslint-disable-line
196
+ processAssets(id, [...create]);
197
+ }
198
+ // Check if there are assets with names that will conflict with existing names during the update process
199
+ // This will rename those assets to a temp random name first
200
+ // This assumes the first identifiers is the unique identifier
201
+ if (identifiers.includes('name')) {
202
+ const uniqueID = identifiers[0];
203
+ const futureAssets = [...create, ...update];
204
+ futureAssets.forEach((a) => {
205
+ // If the conflicting item is going to be deleted then skip
206
+ const inDeleted = del.filter((e) => e.name === a.name && e[uniqueID] !== a[uniqueID])[0];
207
+ if (!inDeleted) {
208
+ const conflict = existing.filter((e) => e.name === a.name && e[uniqueID] !== a[uniqueID])[0];
209
+ if (conflict) {
210
+ const temp = Math.random().toString(36).substr(2, 5);
211
+ conflicts.push(Object.assign(Object.assign({}, conflict), { name: `${conflict.name}-${temp}` }));
212
+ }
213
+ }
214
+ });
215
+ }
216
+ return {
217
+ del,
218
+ update,
219
+ conflicts,
220
+ create
221
+ };
212
222
  }
213
-
223
+ exports.calcChanges = calcChanges;
214
224
  function stripFields(obj, fields) {
215
- const stripped = [];
216
- const newObj = { ...obj
217
- };
218
- fields.forEach(f => {
219
- if (_dotProp2.default.get(newObj, f) !== undefined) {
220
- _dotProp2.default.delete(newObj, f);
221
-
222
- stripped.push(f);
225
+ // Strip object fields supporting dot notation (ie: a.deep.field)
226
+ const stripped = [];
227
+ const newObj = Object.assign({}, obj);
228
+ fields.forEach((f) => {
229
+ if (dot_prop_1.default.get(newObj, f) !== undefined) {
230
+ dot_prop_1.default.delete(newObj, f);
231
+ stripped.push(f);
232
+ }
233
+ });
234
+ if (stripped) {
235
+ const name = ['id', 'client_id', 'template', 'name'].reduce((n, k) => newObj[k] || n, '');
236
+ logger_1.default.debug(`Stripping "${name}" read-only fields ${JSON.stringify(stripped)}`);
223
237
  }
224
- });
225
-
226
- if (stripped) {
227
- const name = ['id', 'client_id', 'template', 'name'].reduce((n, k) => newObj[k] || n, '');
228
-
229
- _logger2.default.debug(`Stripping "${name}" read-only fields ${JSON.stringify(stripped)}`);
230
- }
231
-
232
- return newObj;
238
+ return newObj;
233
239
  }
234
-
240
+ exports.stripFields = stripFields;
235
241
  function getEnabledClients(assets, connection, existing, clients) {
236
- const excludedClientsByNames = assets.exclude && assets.exclude.clients || [];
237
- const excludedClients = convertClientNamesToIds(excludedClientsByNames, clients);
238
- const enabledClients = [...convertClientNamesToIds(connection.enabled_clients || [], clients).filter(item => ![...excludedClientsByNames, ...excludedClients].includes(item))];
239
- existing.forEach(conn => {
240
- if (conn.name === connection.name) {
241
- excludedClients.forEach(excludedClient => {
242
- if (conn.enabled_clients.includes(excludedClient)) {
243
- enabledClients.push(excludedClient);
242
+ // Convert enabled_clients by name to the id
243
+ const excludedClientsByNames = (assets.exclude && assets.exclude.clients) || [];
244
+ const excludedClients = convertClientNamesToIds(excludedClientsByNames, clients);
245
+ const enabledClients = [
246
+ ...convertClientNamesToIds(connection.enabled_clients || [], clients).filter((item) => ![...excludedClientsByNames, ...excludedClients].includes(item))
247
+ ];
248
+ // If client is excluded and in the existing connection this client is enabled, it should keep enabled
249
+ // If client is excluded and in the existing connection this client is disabled, it should keep disabled
250
+ existing.forEach((conn) => {
251
+ if (conn.name === connection.name) {
252
+ excludedClients.forEach((excludedClient) => {
253
+ if (conn.enabled_clients.includes(excludedClient)) {
254
+ enabledClients.push(excludedClient);
255
+ }
256
+ });
244
257
  }
245
- });
246
- }
247
- });
248
- return enabledClients;
258
+ });
259
+ return enabledClients;
249
260
  }
250
-
261
+ exports.getEnabledClients = getEnabledClients;
251
262
  function duplicateItems(arr, key) {
252
- const duplicates = arr.reduce((accum, obj) => {
253
- const keyValue = obj[key];
254
-
255
- if (keyValue) {
256
- if (!(keyValue in accum)) accum[keyValue] = [];
257
- accum[keyValue].push(obj);
258
- }
259
-
260
- return accum;
261
- }, {});
262
- return Object.values(duplicates).filter(g => g.length > 1);
263
+ // Find duplicates objects within array that have the same key value
264
+ const duplicates = arr.reduce((accum, obj) => {
265
+ const keyValue = obj[key];
266
+ if (keyValue) {
267
+ if (!(keyValue in accum))
268
+ accum[keyValue] = [];
269
+ accum[keyValue].push(obj);
270
+ }
271
+ return accum;
272
+ }, {});
273
+ return Object.values(duplicates).filter((g) => g.length > 1);
263
274
  }
264
-
275
+ exports.duplicateItems = duplicateItems;
265
276
  function filterExcluded(changes, exclude) {
266
- const {
267
- del,
268
- update,
269
- create,
270
- conflicts
271
- } = changes;
272
-
273
- if (!exclude.length) {
274
- return changes;
275
- }
276
-
277
- const filter = list => list.filter(item => !exclude.includes(item.name));
278
-
279
- return {
280
- del: filter(del),
281
- update: filter(update),
282
- create: filter(create),
283
- conflicts: filter(conflicts)
284
- };
277
+ const { del, update, create, conflicts } = changes;
278
+ if (!exclude.length) {
279
+ return changes;
280
+ }
281
+ const filter = (list) => list.filter((item) => !exclude.includes(item.name));
282
+ return {
283
+ del: filter(del),
284
+ update: filter(update),
285
+ create: filter(create),
286
+ conflicts: filter(conflicts)
287
+ };
285
288
  }
286
-
289
+ exports.filterExcluded = filterExcluded;
287
290
  function areArraysEquals(x, y) {
288
- return _lodash2.default.isEqual(x && x.sort(), y && y.sort());
289
- }
291
+ return lodash_1.default.isEqual(x && x.sort(), y && y.sort());
292
+ }
293
+ exports.areArraysEquals = areArraysEquals;