@contentstack/cli-cm-export 0.1.1-beta.9 → 1.1.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.
@@ -4,24 +4,23 @@
4
4
  * MIT Licensed
5
5
  */
6
6
 
7
- const mkdirp = require('mkdirp')
8
- const path = require('path')
9
- const chalk = require('chalk')
10
- const Promise = require('bluebird')
7
+ const mkdirp = require('mkdirp');
8
+ const path = require('path');
9
+ const chalk = require('chalk');
10
+ const Promise = require('bluebird');
11
11
 
12
- const helper = require('../util/helper')
13
- // const log = require('../util/log')
14
- const stack = require('../util/contentstack-management-sdk')
15
- const {addlogs} = require('../util/log')
12
+ const helper = require('../util/helper');
13
+ const stack = require('../util/contentstack-management-sdk');
14
+ const { addlogs } = require('../util/log');
16
15
 
17
- let config = require('../../config/default')
18
- const contentTypeConfig = config.modules.content_types
19
- const validKeys = contentTypeConfig.validKeys
20
- let client
21
- let contentTypesFolderPath
16
+ let config = require('../../config/default');
17
+ const contentTypeConfig = config.modules.content_types;
18
+ const validKeys = contentTypeConfig.validKeys;
19
+ let client;
20
+ let contentTypesFolderPath;
22
21
 
23
22
  function ExportContentTypes() {
24
- this.content_types = []
23
+ this.content_types = [];
25
24
 
26
25
  this.requestOptions = {
27
26
  qs: {
@@ -30,83 +29,88 @@ function ExportContentTypes() {
30
29
  limit: config.modules.content_types.limit,
31
30
  include_global_field_schema: true,
32
31
  },
33
- }
32
+ };
34
33
  }
35
34
 
36
35
  ExportContentTypes.prototype = {
37
36
  start: function (credentialConfig) {
38
- this.content_types = []
39
- let self = this
40
- config = credentialConfig
41
- contentTypesFolderPath = path.resolve(config.data, (config.branchName || ""), contentTypeConfig.dirName)
37
+ this.content_types = [];
38
+ let self = this;
39
+ config = credentialConfig;
40
+ contentTypesFolderPath = path.resolve(config.data, config.branchName || '', contentTypeConfig.dirName);
42
41
 
43
- client = stack.Client(config)
42
+ client = stack.Client(config);
44
43
  // If content type id is provided then use it as part of query
45
44
  if (Array.isArray(config.contentTypes) && config.contentTypes.length > 0) {
46
- self.requestOptions.qs.uid = {'$in': config.contentTypes}
45
+ self.requestOptions.qs.uid = { $in: config.contentTypes };
47
46
  }
48
47
  // Create folder for content types
49
- mkdirp.sync(contentTypesFolderPath)
50
- addlogs(config, 'Starting content type export', 'success')
48
+ mkdirp.sync(contentTypesFolderPath);
49
+ addlogs(config, 'Starting content type export', 'success');
51
50
  return new Promise(function (resolve, reject) {
52
- return self.getContentTypes().then(function () {
53
- return self.writeContentTypes()
54
- .then(result => {
55
- return resolve()
51
+ return self
52
+ .getContentTypes()
53
+ .then(function () {
54
+ return self
55
+ .writeContentTypes()
56
+ .then(() => {
57
+ return resolve();
58
+ })
59
+ .catch((error) => {
60
+ return reject(error);
61
+ });
56
62
  })
57
- .catch(error => {
58
- return reject(error)
59
- })
60
- }).catch(reject)
61
- })
63
+ .catch(reject);
64
+ });
62
65
  },
63
66
  getContentTypes: function (skip) {
64
- let self = this
67
+ let self = this;
65
68
  if (typeof skip !== 'number') {
66
- skip = 0
67
- self.requestOptions.qs.skip = skip
69
+ skip = 0;
70
+ self.requestOptions.qs.skip = skip;
68
71
  } else {
69
- self.requestOptions.qs.skip = skip
72
+ self.requestOptions.qs.skip = skip;
70
73
  }
71
74
 
72
75
  return new Promise(function (resolve, reject) {
73
- client.stack({api_key: config.source_stack, management_token: config.management_token}).contentType().query(self.requestOptions.qs).find()
74
- .then(contenttypeResponse => {
75
- if (contenttypeResponse.items.length === 0) {
76
- addlogs(config, 'No content types were found in the Stack', 'success')
77
- return resolve()
78
- }
79
- contenttypeResponse.items.forEach(function (content_type) {
80
- for (let key in content_type) {
81
- if (validKeys.indexOf(key) === -1) {
82
- delete content_type[key]
83
- }
76
+ client
77
+ .stack({ api_key: config.source_stack, management_token: config.management_token })
78
+ .contentType()
79
+ .query(self.requestOptions.qs)
80
+ .find()
81
+ .then((contenttypeResponse) => {
82
+ if (contenttypeResponse.items.length === 0) {
83
+ addlogs(config, 'No content types were found in the Stack', 'success');
84
+ return resolve();
84
85
  }
85
- self.content_types.push(content_type)
86
- })
86
+ contenttypeResponse.items.forEach(function (content_type) {
87
+ for (let key in content_type) {
88
+ if (validKeys.indexOf(key) === -1) {
89
+ delete content_type[key];
90
+ }
91
+ }
92
+ self.content_types.push(content_type);
93
+ });
87
94
 
88
- skip += config.modules.content_types.limit
89
- if (skip > contenttypeResponse.count) {
90
- return resolve()
91
- }
92
- return self.getContentTypes(skip)
93
- .then(resolve)
94
- .catch(reject)
95
- })
96
- })
95
+ skip += config.modules.content_types.limit;
96
+ if (skip > contenttypeResponse.count) {
97
+ return resolve();
98
+ }
99
+ return self.getContentTypes(skip).then(resolve).catch(reject);
100
+ });
101
+ });
97
102
  },
98
103
  writeContentTypes: function () {
99
- let self = this
104
+ let self = this;
100
105
  return new Promise(function (resolve) {
101
- helper.writeFile(path.join(contentTypesFolderPath, 'schema.json'), self.content_types)
106
+ helper.writeFile(path.join(contentTypesFolderPath, 'schema.json'), self.content_types);
102
107
  self.content_types.forEach(function (content_type) {
103
- helper.writeFile(path.join(contentTypesFolderPath, content_type.uid + '.json'),
104
- content_type)
105
- })
106
- addlogs(config, chalk.green('Content type(s) exported successfully'), 'success')
107
- return resolve()
108
- })
108
+ helper.writeFile(path.join(contentTypesFolderPath, content_type.uid + '.json'), content_type);
109
+ });
110
+ addlogs(config, chalk.green('Content type(s) exported successfully'), 'success');
111
+ return resolve();
112
+ });
109
113
  },
110
- }
114
+ };
111
115
 
112
- module.exports = new ExportContentTypes()
116
+ module.exports = new ExportContentTypes();
@@ -0,0 +1,91 @@
1
+ 'use strict';
2
+
3
+ const mkdirp = require('mkdirp');
4
+ const path = require('path');
5
+ const chalk = require('chalk');
6
+
7
+ const helper = require('../util/helper');
8
+ const { addlogs } = require('../util/log');
9
+
10
+ const stack = require('../util/contentstack-management-sdk');
11
+ let config = require('../../config/default');
12
+ const rolesConfig = config.modules.customRoles;
13
+
14
+ const EXISTING_ROLES = {
15
+ Admin: 1,
16
+ Developer: 1,
17
+ 'Content Manager': 1,
18
+ };
19
+
20
+ function ExportCustomRoles() {
21
+ this.client = null;
22
+ this.roles = {};
23
+ }
24
+
25
+ ExportCustomRoles.prototype.start = async function (credentialConfig) {
26
+ try {
27
+ addlogs(config, 'Starting roles export', 'success');
28
+ let self = this;
29
+ this.roles = {};
30
+ config = credentialConfig;
31
+ this.client = stack.Client(config);
32
+
33
+ const rolesFolderPath = path.resolve(config.data, config.branchName || '', rolesConfig.dirName);
34
+ mkdirp.sync(rolesFolderPath);
35
+
36
+ const roles = await this.client
37
+ .stack({ api_key: config.source_stack, management_token: config.management_token })
38
+ .role()
39
+ .fetchAll({ include_rules: true, include_permissions: true });
40
+
41
+ const customRoles = roles.items.filter(role => !EXISTING_ROLES[role.name]);
42
+
43
+ if (!customRoles.length) {
44
+ addlogs(config, 'No custom roles were found in the Stack', 'success');
45
+ return;
46
+ }
47
+
48
+ await getCustomRolesLocales(customRoles, path.join(rolesFolderPath, rolesConfig.customRolesLocalesFileName), this.client, config);
49
+ self.customRoles = {};
50
+ customRoles.forEach(role => {
51
+ addlogs(config, role.name + ' role was exported successfully', 'success');
52
+ self.customRoles[role.uid] = role;
53
+ });
54
+ helper.writeFile(path.join(rolesFolderPath, rolesConfig.fileName), self.customRoles);
55
+ addlogs(config, chalk.green('All the custom roles have been exported successfully'), 'success');
56
+ } catch (error) {
57
+ if (error.statusCode === 401) {
58
+ addlogs(config, chalk.red('You are not allowed to export roles, Unless you provide email and password in config'), 'error');
59
+ return;
60
+ }
61
+ addlogs(config, 'Error occurred in exporting roles. ' + error && error.message, 'error');
62
+ throw error;
63
+ }
64
+ };
65
+
66
+ async function getCustomRolesLocales(customRoles, customRolesLocalesFilepath, client, config) {
67
+ const localesMap = {};
68
+ for (const role of customRoles) {
69
+ const rulesLocales = role.rules.find(rule => rule.module === 'locale');
70
+ if (rulesLocales.locales && rulesLocales.locales.length) {
71
+ rulesLocales.locales.forEach(locale => {
72
+ localesMap[locale] = 1;
73
+ });
74
+ }
75
+ }
76
+
77
+ if (Object.keys(localesMap).length) {
78
+ const locales = await client.stack({ api_key: config.source_stack, management_token: config.management_token }).locale().query({}).find();
79
+ const sourceLocalesMap = {};
80
+ for (const locale of locales.items) {
81
+ sourceLocalesMap[locale.uid] = locale;
82
+ }
83
+ for (const locale in localesMap) {
84
+ delete sourceLocalesMap[locale]['stackHeaders'];
85
+ localesMap[locale] = sourceLocalesMap[locale];
86
+ }
87
+ helper.writeFile(customRolesLocalesFilepath, localesMap);
88
+ }
89
+ }
90
+
91
+ module.exports = new ExportCustomRoles();
@@ -4,28 +4,28 @@
4
4
  * MIT Licensed
5
5
  */
6
6
 
7
- const fs = require('fs')
8
- const path = require('path')
9
- const _ = require('lodash')
10
- const Promise = require('bluebird')
11
- const chalk = require('chalk')
12
- const mkdirp = require('mkdirp')
13
- const {addlogs} = require('../util/log')
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+ const _ = require('lodash');
10
+ const Promise = require('bluebird');
11
+ const chalk = require('chalk');
12
+ const mkdirp = require('mkdirp');
13
+ const { addlogs } = require('../util/log');
14
14
 
15
- const helper = require('../util/helper')
16
- const log = require('../util/log')
17
- const stack = require('../util/contentstack-management-sdk')
15
+ const helper = require('../util/helper');
16
+ const log = require('../util/log');
17
+ const stack = require('../util/contentstack-management-sdk');
18
18
 
19
- let config = require('../../config/default')
20
- let entriesConfig = config.modules.entries
21
- let invalidKeys = entriesConfig.invalidKeys
22
- let limit = entriesConfig.limit
23
- let content_types
24
- let locales
25
- let entryFolderPath
26
- let localesFilePath
27
- let schemaFilePath
28
- let client
19
+ let config = require('../../config/default');
20
+ let entriesConfig = config.modules.entries;
21
+ let invalidKeys = entriesConfig.invalidKeys;
22
+ let limit = entriesConfig.limit;
23
+ let content_types;
24
+ let locales;
25
+ let entryFolderPath;
26
+ let localesFilePath;
27
+ let schemaFilePath;
28
+ let client;
29
29
 
30
30
  function exportEntries() {
31
31
  this.requestOptions = {
@@ -36,52 +36,70 @@ function exportEntries() {
36
36
  limit: limit,
37
37
  },
38
38
  json: true,
39
- }
39
+ };
40
40
  }
41
41
 
42
42
  exportEntries.prototype.start = function (credentialConfig) {
43
- let self = this
44
- config = credentialConfig
45
- entryFolderPath = path.resolve(config.data, (config.branchName || ""), config.modules.entries.dirName)
46
- localesFilePath = path.resolve(config.data, (config.branchName || ""), config.modules.locales.dirName, config.modules.locales.fileName)
47
- schemaFilePath = path.resolve(config.data, (config.branchName || ""), config.modules.content_types.dirName, 'schema.json')
48
- client = stack.Client(config)
49
- addlogs(config, 'Starting entry migration', 'success')
50
- return new Promise(function (resolve, reject) {
51
- locales = helper.readFile(localesFilePath)
52
- let apiBucket = []
53
- content_types = helper.readFile(schemaFilePath)
43
+ let self = this;
44
+ config = credentialConfig;
45
+ entryFolderPath = path.resolve(config.data, config.branchName || '', config.modules.entries.dirName);
46
+ localesFilePath = path.resolve(
47
+ config.data,
48
+ config.branchName || '',
49
+ config.modules.locales.dirName,
50
+ config.modules.locales.fileName,
51
+ );
52
+ schemaFilePath = path.resolve(
53
+ config.data,
54
+ config.branchName || '',
55
+ config.modules.content_types.dirName,
56
+ 'schema.json',
57
+ );
58
+ client = stack.Client(config);
59
+ addlogs(config, 'Starting entry migration', 'success');
60
+ return new Promise(function (resolve) {
61
+ locales = helper.readFile(localesFilePath);
62
+ let apiBucket = [];
63
+ content_types = helper.readFile(schemaFilePath);
54
64
  if (content_types.length !== 0) {
55
- content_types.forEach(content_type => {
65
+ content_types.forEach((content_type) => {
56
66
  if (Object.keys(locales).length !== 0) {
57
67
  for (let _locale in locales) {
58
68
  apiBucket.push({
59
69
  content_type: content_type.uid,
60
70
  locale: locales[_locale].code,
61
- })
71
+ });
62
72
  }
63
73
  }
64
74
  apiBucket.push({
65
75
  content_type: content_type.uid,
66
76
  locale: config.master_locale.code,
77
+ });
78
+ });
79
+ return Promise.map(
80
+ apiBucket,
81
+ function (apiDetails) {
82
+ return self.getEntries(apiDetails);
83
+ },
84
+ {
85
+ concurrency: 1,
86
+ },
87
+ )
88
+ .then(function () {
89
+ addlogs(config, 'Entry migration completed successfully', 'success');
90
+ return resolve();
67
91
  })
68
- })
69
- return Promise.map(apiBucket, function (apiDetails) {
70
- return self.getEntries(apiDetails)
71
- }, {
72
- concurrency: 1,
73
- }).then(function () {
74
- addlogs(config, 'Entry migration completed successfully', 'success')
75
- return resolve()
76
- }).catch(reject)
92
+ .catch((error) => {
93
+ console.log('Error getting entries', error && error.message);
94
+ });
77
95
  }
78
- addlogs(config, 'No content_types were found in the Stack', 'success')
79
- return resolve()
80
- })
81
- }
96
+ addlogs(config, 'No content_types were found in the Stack', 'success');
97
+ return resolve();
98
+ });
99
+ };
82
100
 
83
101
  exportEntries.prototype.getEntry = function (apiDetails) {
84
- let self = this
102
+ let self = this;
85
103
  return new Promise(function (resolve, reject) {
86
104
  let queryRequestObject = {
87
105
  locale: apiDetails.locale,
@@ -89,34 +107,42 @@ exportEntries.prototype.getEntry = function (apiDetails) {
89
107
  BASE: invalidKeys,
90
108
  },
91
109
  version: apiDetails.version,
92
-
93
- }
94
- client.stack({api_key: config.source_stack, management_token: config.management_token}).contentType(apiDetails.content_type).entry(apiDetails.uid).fetch(queryRequestObject)
95
- .then(singleEntry => {
96
- let entryPath = path.join(entryFolderPath, apiDetails.locale, apiDetails.content_type,
97
- singleEntry.uid)
98
- mkdirp.sync(entryPath)
99
- helper.writeFile(path.join(entryPath, 'version-' + singleEntry._version +
100
- '.json'), singleEntry)
101
- addlogs(config, 'Completed version backup of entry: ' + singleEntry.uid +
102
- ', version: ' + singleEntry._version + ', content type: ' + apiDetails.content_type, 'success')
103
- if (--apiDetails.version !== 0) {
104
- return self.getEntry(apiDetails)
105
- .then(resolve)
106
- .catch(reject)
107
- }
108
- return resolve()
109
- }).catch(error => {
110
- addlogs(config, error, 'error')
111
- })
112
- })
113
- }
110
+ };
111
+ client
112
+ .stack({ api_key: config.source_stack, management_token: config.management_token })
113
+ .contentType(apiDetails.content_type)
114
+ .entry(apiDetails.uid)
115
+ .fetch(queryRequestObject)
116
+ .then((singleEntry) => {
117
+ let entryPath = path.join(entryFolderPath, apiDetails.locale, apiDetails.content_type, singleEntry.uid);
118
+ mkdirp.sync(entryPath);
119
+ helper.writeFile(path.join(entryPath, 'version-' + singleEntry._version + '.json'), singleEntry);
120
+ addlogs(
121
+ config,
122
+ 'Completed version backup of entry: ' +
123
+ singleEntry.uid +
124
+ ', version: ' +
125
+ singleEntry._version +
126
+ ', content type: ' +
127
+ apiDetails.content_type,
128
+ 'success',
129
+ );
130
+ if (--apiDetails.version !== 0) {
131
+ return self.getEntry(apiDetails).then(resolve).catch(reject);
132
+ }
133
+ return resolve();
134
+ })
135
+ .catch((error) => {
136
+ addlogs(config, error, 'error');
137
+ });
138
+ });
139
+ };
114
140
 
115
141
  exportEntries.prototype.getEntries = function (apiDetails) {
116
- let self = this
142
+ let self = this;
117
143
  return new Promise(function (resolve, reject) {
118
144
  if (typeof apiDetails.skip !== 'number') {
119
- apiDetails.skip = 0
145
+ apiDetails.skip = 0;
120
146
  }
121
147
 
122
148
  let queryrequestObject = {
@@ -128,70 +154,99 @@ exportEntries.prototype.getEntries = function (apiDetails) {
128
154
  query: {
129
155
  locale: apiDetails.locale,
130
156
  },
131
- }
132
- client.stack({api_key: config.source_stack, management_token: config.management_token}).contentType(apiDetails.content_type).entry().query(queryrequestObject).find()
133
- .then(entriesList => {
134
- // /entries/content_type_uid/locale.json
135
- if (!fs.existsSync(path.join(entryFolderPath, apiDetails.content_type))) {
136
- mkdirp.sync(path.join(entryFolderPath, apiDetails.content_type))
137
- }
138
- let entriesFilePath = path.join(entryFolderPath, apiDetails.content_type, apiDetails.locale + '.json')
139
- let entries = helper.readFile(entriesFilePath)
140
- entries = entries || {}
141
- entriesList.items.forEach(function (entry) {
142
- invalidKeys.forEach(e => delete entry[e])
143
- entries[entry.uid] = entry
144
- })
145
- helper.writeFile(entriesFilePath, entries)
146
-
147
- if (typeof config.versioning === 'boolean' && config.versioning) {
148
- for (let locale in locales) {
149
- // make folders for each language
150
- content_types.forEach(function (content_type) {
151
- // make folder for each content type
152
- let versionedEntryFolderPath = path.join(entryFolderPath, locales[locale].code,content_type.uid)
153
- mkdirp.sync(versionedEntryFolderPath)
154
- })
157
+ };
158
+ client
159
+ .stack({ api_key: config.source_stack, management_token: config.management_token })
160
+ .contentType(apiDetails.content_type)
161
+ .entry()
162
+ .query(queryrequestObject)
163
+ .find()
164
+ .then((entriesList) => {
165
+ // /entries/content_type_uid/locale.json
166
+ if (!fs.existsSync(path.join(entryFolderPath, apiDetails.content_type))) {
167
+ mkdirp.sync(path.join(entryFolderPath, apiDetails.content_type));
155
168
  }
156
- return Promise.map(entriesList.items, function (entry) {
157
- let entryDetails = {
158
- content_type: apiDetails.content_type,
159
- uid: entry.uid,
160
- version: entry._version,
161
- locale: apiDetails.locale,
162
- }
163
- return self.getEntry(entryDetails).then(function () {
169
+ let entriesFilePath = path.join(entryFolderPath, apiDetails.content_type, apiDetails.locale + '.json');
170
+ let entries = helper.readFile(entriesFilePath);
171
+ entries = entries || {};
172
+ entriesList.items.forEach(function (entry) {
173
+ invalidKeys.forEach((e) => delete entry[e]);
174
+ entries[entry.uid] = entry;
175
+ });
176
+ helper.writeFile(entriesFilePath, entries);
164
177
 
165
- }).catch(reject)
166
- }, {
167
- concurrency: 1,
168
- }).then(function () {
169
- if (apiDetails.skip > entriesList.items.length) {
170
- addlogs(config, 'Completed fetching ' + apiDetails.content_type +
171
- ' content type\'s entries in ' + apiDetails.locale + ' locale', 'success')
172
- return resolve()
178
+ if (typeof config.versioning === 'boolean' && config.versioning) {
179
+ for (let locale in locales) {
180
+ // make folders for each language
181
+ content_types.forEach(function (content_type) {
182
+ // make folder for each content type
183
+ let versionedEntryFolderPath = path.join(entryFolderPath, locales[locale].code, content_type.uid);
184
+ mkdirp.sync(versionedEntryFolderPath);
185
+ });
173
186
  }
174
- apiDetails.skip += limit
175
- return self.getEntries(apiDetails).then(function () {
176
- return resolve()
177
- }).catch(function (error) {
178
- return reject(error)
179
- })
180
- })
181
- }
182
- if (apiDetails.skip > entriesList.count) {
183
- addlogs(config, 'Exported entries of ' + apiDetails.content_type +
184
- ' to the ' + apiDetails.locale + ' language successfully', 'success')
185
- return resolve()
186
- }
187
- apiDetails.skip += limit
188
- return self.getEntries(apiDetails)
189
- .then(resolve)
190
- .catch(reject)
191
- }).catch(error => {
192
- addlogs(config, error, 'error')
193
- })
194
- })
195
- }
187
+ return Promise.map(
188
+ entriesList.items,
189
+ function (entry) {
190
+ let entryDetails = {
191
+ content_type: apiDetails.content_type,
192
+ uid: entry.uid,
193
+ version: entry._version,
194
+ locale: apiDetails.locale,
195
+ };
196
+ return self.getEntry(entryDetails).catch(reject);
197
+ },
198
+ {
199
+ concurrency: 1,
200
+ },
201
+ ).then(function () {
202
+ if (apiDetails.skip > entriesList.items.length) {
203
+ addlogs(
204
+ config,
205
+ 'Completed fetching ' +
206
+ apiDetails.content_type +
207
+ " content type's entries in " +
208
+ apiDetails.locale +
209
+ ' locale',
210
+ 'success',
211
+ );
212
+ return resolve();
213
+ }
214
+ apiDetails.skip += limit;
215
+ return self
216
+ .getEntries(apiDetails)
217
+ .then(function () {
218
+ return resolve();
219
+ })
220
+ .catch(function (error) {
221
+ return reject(error);
222
+ });
223
+ });
224
+ }
225
+ if (apiDetails.skip > entriesList.count) {
226
+ addlogs(
227
+ config,
228
+ 'Exported entries of ' +
229
+ apiDetails.content_type +
230
+ ' to the ' +
231
+ apiDetails.locale +
232
+ ' language successfully',
233
+ 'success',
234
+ );
235
+ return resolve();
236
+ }
237
+ apiDetails.skip += limit;
238
+ return self
239
+ .getEntries(apiDetails)
240
+ .then(resolve)
241
+ .catch((error) => {
242
+ console.log('Get Entries errror', error && error.message);
243
+ });
244
+ })
245
+ .catch((error) => {
246
+ console.log('Entries fetch errror', error && error.message);
247
+ addlogs(config, error, 'error');
248
+ });
249
+ });
250
+ };
196
251
 
197
- module.exports = new exportEntries()
252
+ module.exports = new exportEntries();