@blocklet/meta 1.7.19 → 1.7.20

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/lib/fix.js CHANGED
@@ -77,10 +77,7 @@ const fixFiles = (data) => {
77
77
  delete data.files;
78
78
  } else if (data.files) {
79
79
  data.files = data.files.filter((file) => {
80
- if (!file || typeof file !== 'string') {
81
- return false;
82
- }
83
- return true;
80
+ return !(!file || typeof file !== 'string');
84
81
  });
85
82
  }
86
83
  };
@@ -93,10 +90,7 @@ const fixKeywords = (data) => {
93
90
  delete data.keywords;
94
91
  } else if (data.keywords) {
95
92
  data.keywords = data.keywords.filter((kw) => {
96
- if (typeof kw !== 'string' || !kw) {
97
- return false;
98
- }
99
- return true;
93
+ return !(typeof kw !== 'string' || !kw);
100
94
  });
101
95
  }
102
96
  };
@@ -109,10 +103,7 @@ const fixTags = (data) => {
109
103
  delete data.tags;
110
104
  } else if (data.tags) {
111
105
  data.tags = data.tags.filter((t) => {
112
- if (typeof t !== 'string' || !t) {
113
- return false;
114
- }
115
- return true;
106
+ return !(typeof t !== 'string' || !t);
116
107
  });
117
108
  }
118
109
  };
@@ -0,0 +1,17 @@
1
+ const crypto = require('crypto');
2
+
3
+ const md5 = (str) => crypto.createHash('md5').update(str).digest('hex');
4
+
5
+ const getComponentProcessId = (component, ancestors = []) => {
6
+ const name = !ancestors.length
7
+ ? component.meta.name
8
+ : `${ancestors.map((x) => encodeURIComponent(x.meta.name)).join('/')}/${encodeURIComponent(component.meta.name)}`;
9
+
10
+ if (name.length < 240) {
11
+ return name;
12
+ }
13
+
14
+ return md5(name);
15
+ };
16
+
17
+ module.exports = getComponentProcessId;
@@ -5,23 +5,31 @@ const normalizePathPrefix = require('@abtnode/util/lib/normalize-path-prefix');
5
5
  * @param {*} navigation src
6
6
  * @param {*} blocklet
7
7
  * @param {*} prefix prefix of link
8
- * @param {*} level 1 or 2. primary menu or secondary menu
8
+ * @param {*} _level 1: primary menu, >2: secondary menu
9
9
  */
10
- const parseNavigation = (navigation, blocklet, prefix = '/', level = 1) => {
10
+ const parseNavigation = (navigation, blocklet, prefix = '/', _level = 1) => {
11
11
  const result = [];
12
12
 
13
13
  (navigation || []).forEach((nav) => {
14
14
  if (!nav.child) {
15
+ if (_level > 1 && nav.items?.length) {
16
+ const list = parseNavigation(nav.items, blocklet, prefix, _level + 1);
17
+ result.push(...list);
18
+ return;
19
+ }
20
+
15
21
  const item = {
16
22
  title: nav.title,
17
23
  };
18
24
 
19
25
  if (nav.link) {
20
26
  item.link = nav.link.startsWith('/') ? normalizePathPrefix(`${prefix}${nav.link || '/'}`) : nav.link;
27
+ } else {
28
+ item.link = '';
21
29
  }
22
30
 
23
- if (level === 1) {
24
- const list = parseNavigation(nav.items, blocklet, prefix, 2);
31
+ if (nav.items?.length) {
32
+ const list = parseNavigation(nav.items, blocklet, prefix, _level + 1);
25
33
  if (list.length) {
26
34
  item.items = list;
27
35
  }
@@ -57,16 +65,21 @@ const parseNavigation = (navigation, blocklet, prefix = '/', level = 1) => {
57
65
  });
58
66
  } else {
59
67
  // child declares multiple menus
60
- if (level === 1) { // eslint-disable-line
68
+ const list = parseNavigation(
69
+ childNavigation,
70
+ child,
71
+ normalizePathPrefix(`${prefix}${child.mountPoint}`),
72
+ _level + 1
73
+ );
74
+
75
+ if (_level === 1) { // eslint-disable-line
61
76
  // primary menu
62
- const item = {
77
+ result.push({
63
78
  title: nav.title || child.meta.title || child.meta.name,
64
- items: parseNavigation(childNavigation, null, normalizePathPrefix(`${prefix}${child.mountPoint}`), 2),
65
- };
66
- result.push(item);
79
+ items: list,
80
+ });
67
81
  } else {
68
82
  // secondary menu
69
- const list = parseNavigation(childNavigation, null, normalizePathPrefix(`${prefix}${child.mountPoint}`), 2);
70
83
  result.push(...list);
71
84
  }
72
85
  }
package/lib/util.js CHANGED
@@ -4,15 +4,58 @@ const slugify = require('slugify');
4
4
 
5
5
  const { NODE_SERVICES, SLOT_FOR_IP_DNS_SITE, WHO_CAN_ACCESS } = require('@abtnode/constant');
6
6
 
7
- const { BlockletGroup, fromBlockletStatus, fromBlockletSource, BLOCKLET_INTERFACE_TYPE_WEB } = require('./constants');
7
+ const {
8
+ BlockletGroup,
9
+ fromBlockletStatus,
10
+ fromBlockletSource,
11
+ BLOCKLET_INTERFACE_TYPE_WEB,
12
+ BLOCKLET_CONFIGURABLE_KEY,
13
+ } = require('./constants');
14
+
15
+ const getComponentId = (component, ancestors = []) =>
16
+ `${ancestors.map((x) => (x && x.meta ? x.meta.did : '')).join('/')}${ancestors.length ? '/' : ''}${
17
+ component && component.meta ? component.meta.did : ''
18
+ }`;
19
+
20
+ const getComponentName = (component, ancestors = []) =>
21
+ `${ancestors.map((x) => (x && x.meta ? x.meta.name : '')).join('/')}${ancestors.length ? '/' : ''}${
22
+ component && component.meta ? component.meta.name : ''
23
+ }`;
24
+
25
+ const getComponentBundleId = (component) => `${component.meta.bundleName}@${component.meta.version}`;
26
+
27
+ const forEachBlocklet = (
28
+ blocklet,
29
+ cb,
30
+ { parallel = false, sync, params: inputParams, _parent, _root, _level = 0, _tasks: inputTasks, _ancestors = [] } = {}
31
+ ) => {
32
+ const root = _root || _parent || blocklet;
33
+
34
+ // id maybe meaningless if no meta in blocklet or _ancestors
35
+ const id = getComponentId(blocklet, _ancestors);
36
+
37
+ const newAncestors = _ancestors.concat(blocklet);
8
38
 
9
- const forEachBlocklet = (blocklet, cb, { parallel = false, sync } = {}) => {
10
39
  // sync
11
40
  if (sync) {
12
- cb(blocklet);
41
+ const params = cb(blocklet, {
42
+ parent: _parent,
43
+ root,
44
+ level: _level,
45
+ params: inputParams,
46
+ ancestors: _ancestors,
47
+ id,
48
+ });
13
49
  if (blocklet.children) {
14
50
  for (const child of blocklet.children) {
15
- cb(child);
51
+ forEachBlocklet(child, cb, {
52
+ sync,
53
+ params,
54
+ _parent: blocklet,
55
+ _root: root,
56
+ _level: _level + 1,
57
+ _ancestors: newAncestors,
58
+ });
16
59
  }
17
60
  }
18
61
  return null;
@@ -23,10 +66,23 @@ const forEachBlocklet = (blocklet, cb, { parallel = false, sync } = {}) => {
23
66
  // eslint-disable-next-line no-async-promise-executor
24
67
  return new Promise(async (resolve, reject) => {
25
68
  try {
26
- await cb(blocklet);
69
+ const params = await cb(blocklet, {
70
+ parent: _parent,
71
+ root,
72
+ level: _level,
73
+ ancestors: _ancestors,
74
+ params: inputParams,
75
+ id,
76
+ });
27
77
  if (blocklet.children) {
28
78
  for (const child of blocklet.children) {
29
- await cb(child);
79
+ await forEachBlocklet(child, cb, {
80
+ params,
81
+ _parent: blocklet,
82
+ _root: root,
83
+ _level: _level + 1,
84
+ _ancestors: newAncestors,
85
+ });
30
86
  }
31
87
  }
32
88
 
@@ -38,38 +94,125 @@ const forEachBlocklet = (blocklet, cb, { parallel = false, sync } = {}) => {
38
94
  }
39
95
 
40
96
  // parallel
41
- const tasks = [];
42
- tasks.push(cb(blocklet));
97
+ const tasks = inputTasks || [];
98
+ tasks.push(cb(blocklet, { parent: _parent, root, level: _level, ancestors: _ancestors }));
43
99
  if (blocklet.children) {
44
100
  for (const child of blocklet.children) {
45
- tasks.push(cb(child));
101
+ forEachBlocklet(child, cb, {
102
+ parallel,
103
+ _parent: blocklet,
104
+ _root: root,
105
+ _level: _level + 1,
106
+ _tasks: tasks,
107
+ _ancestors: newAncestors,
108
+ id,
109
+ });
46
110
  }
47
111
  }
112
+ if (inputTasks) {
113
+ return null;
114
+ }
48
115
  return Promise.all(tasks);
49
116
  };
50
117
 
51
118
  const forEachBlockletSync = (blocklet, cb) => forEachBlocklet(blocklet, cb, { sync: true });
52
119
 
53
- const getRequiredMissingConfigs = (blocklet) => {
54
- const missingConfigs = [];
55
- const configs = blocklet.configs || [];
56
- configs.forEach((item) => {
57
- if (item.required && !item.value) {
58
- missingConfigs.push({ did: blocklet.meta.did, key: item.key, description: item.description });
120
+ const forEachChild = (blocklet, cb, params) => {
121
+ return forEachBlocklet(
122
+ blocklet,
123
+ (b, opt) => {
124
+ if (opt.level === 0) {
125
+ return {};
126
+ }
127
+ return cb(b, opt);
128
+ },
129
+ params
130
+ );
131
+ };
132
+
133
+ const forEachChildSync = (blocklet, cb) => forEachChild(blocklet, cb, { sync: true });
134
+
135
+ const findComponentById = (blocklet, componentId, { _ancestors = [], returnAncestors = false } = {}) => {
136
+ const id = getComponentId(blocklet, _ancestors);
137
+ if (componentId === id) {
138
+ if (returnAncestors) {
139
+ return {
140
+ component: blocklet,
141
+ ancestors: _ancestors,
142
+ };
59
143
  }
60
- });
61
144
 
62
- // eslint-disable-next-line no-restricted-syntax
145
+ return blocklet;
146
+ }
147
+
63
148
  for (const child of blocklet.children || []) {
64
- const childConfigs = child.configs || [];
65
- // configProp does not exist in root blocklet config
66
- // or value of configProp in root blocklet config is empty.
67
- childConfigs.forEach((x) => {
68
- if (x.required && !x.value && !configs.some((y) => y.key === x.key && y.value)) {
69
- missingConfigs.push({ did: child.meta.did, key: x.key, description: x.description });
149
+ const ancestors = _ancestors.concat(blocklet);
150
+ const component = findComponentById(child, componentId, { _ancestors: ancestors, returnAncestors });
151
+ if (component) {
152
+ return component;
153
+ }
154
+ }
155
+
156
+ return null;
157
+ };
158
+
159
+ const getSharedConfigObj = (component, ancestors) => {
160
+ const res = {};
161
+ if (!ancestors) {
162
+ return res;
163
+ }
164
+
165
+ for (let i = ancestors.length - 1; i >= 0; i--) {
166
+ const ancestor = ancestors[i];
167
+ if (Array.isArray(ancestor.configs)) {
168
+ ancestor.configs.forEach(({ key, value, secure, shared }) => {
169
+ if (res[key]) {
170
+ return;
171
+ }
172
+
173
+ if (!value || secure !== false || shared === false || BLOCKLET_CONFIGURABLE_KEY[key]) {
174
+ return;
175
+ }
176
+
177
+ const config = (component.configs || []).find((x) => x.key === key);
178
+ if (config && config.value) {
179
+ return;
180
+ }
181
+
182
+ res[key] = value;
183
+ });
184
+ }
185
+ }
186
+
187
+ return res;
188
+ };
189
+
190
+ const getAppMissingConfigs = (blocklet = {}) => {
191
+ const missingConfigs = [];
192
+
193
+ forEachBlockletSync(blocklet, (b, { ancestors }) => {
194
+ const configs = b.configs || [];
195
+ const sharedConfigObj = getSharedConfigObj(b, ancestors);
196
+ configs.forEach((item) => {
197
+ if (item.required && !item.value && !sharedConfigObj[item.key]) {
198
+ missingConfigs.push({ did: b.meta.did, key: item.key, description: item.description });
70
199
  }
71
200
  });
72
- }
201
+ });
202
+
203
+ return missingConfigs;
204
+ };
205
+
206
+ const getComponentMissingConfigs = (component = {}, ancestors = []) => {
207
+ const missingConfigs = [];
208
+
209
+ const configs = component.configs || [];
210
+ const sharedConfigObj = getSharedConfigObj(component, ancestors);
211
+ configs.forEach((item) => {
212
+ if (item.required && !item.value && !sharedConfigObj[item.key]) {
213
+ missingConfigs.push({ did: component.meta.did, key: item.key, description: item.description });
214
+ }
215
+ });
73
216
 
74
217
  return missingConfigs;
75
218
  };
@@ -163,20 +306,21 @@ const fixBlockletStatus = (blocklet) => {
163
306
  return;
164
307
  }
165
308
 
166
- blocklet.status = fromBlockletStatus(blocklet.status);
167
- blocklet.source = fromBlockletSource(blocklet.source);
168
- (blocklet.children || []).forEach((child) => {
169
- child.status = fromBlockletStatus(child.status);
170
- if (child.source !== undefined) {
171
- child.source = fromBlockletSource(child.source);
309
+ forEachBlockletSync(blocklet, (b) => {
310
+ b.status = fromBlockletStatus(b.status);
311
+ if (b.source !== undefined) {
312
+ b.source = fromBlockletSource(b.source);
172
313
  }
173
314
  });
315
+
174
316
  if (blocklet.settings) {
175
317
  (blocklet.settings.children || []).forEach((child) => {
176
- child.status = fromBlockletStatus(child.status);
177
- if (child.source !== undefined) {
178
- child.source = fromBlockletSource(child.source);
179
- }
318
+ forEachBlockletSync(child, (b) => {
319
+ b.status = fromBlockletStatus(b.status);
320
+ if (b.source !== undefined) {
321
+ b.source = fromBlockletSource(b.source);
322
+ }
323
+ });
180
324
  });
181
325
  }
182
326
  };
@@ -237,10 +381,14 @@ const urlFriendly = (name) => slugify(name.replace(/^[@./-]/, '').replace(/[@./_
237
381
  module.exports = {
238
382
  isFreeBlocklet,
239
383
  isComponentBlocklet,
384
+ forEachBlocklet,
240
385
  forEachBlockletSync,
386
+ forEachChild,
387
+ forEachChildSync,
241
388
  isDeletableBlocklet,
242
- forEachBlocklet,
243
- getRequiredMissingConfigs,
389
+ getSharedConfigObj,
390
+ getAppMissingConfigs,
391
+ getComponentMissingConfigs,
244
392
  wipeSensitiveData,
245
393
  hasRunnableComponent,
246
394
  getDisplayName,
@@ -250,4 +398,8 @@ module.exports = {
250
398
  getWhoCanAccess,
251
399
  replaceSlotToIp,
252
400
  urlFriendly,
401
+ getComponentId,
402
+ getComponentName,
403
+ getComponentBundleId,
404
+ findComponentById,
253
405
  };
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.7.19",
6
+ "version": "1.7.20",
7
7
  "description": "Library to parse/validate/fix blocklet meta",
8
8
  "main": "lib/index.js",
9
9
  "files": [
@@ -18,8 +18,8 @@
18
18
  "author": "wangshijun <wangshijun2020@gmail.com> (http://github.com/wangshijun)",
19
19
  "license": "MIT",
20
20
  "dependencies": {
21
- "@abtnode/constant": "1.7.19",
22
- "@abtnode/util": "1.7.19",
21
+ "@abtnode/constant": "1.7.20",
22
+ "@abtnode/util": "1.7.20",
23
23
  "@arcblock/did": "^1.16.15",
24
24
  "@arcblock/did-ext": "^1.16.15",
25
25
  "@arcblock/did-util": "^1.16.15",
@@ -47,5 +47,5 @@
47
47
  "devDependencies": {
48
48
  "jest": "^27.4.5"
49
49
  },
50
- "gitHead": "73c02fe34d02270e59c5edfeedd7e2a878b772c4"
50
+ "gitHead": "7e579415aa56cc422f3e26d902cf029fbc92e47a"
51
51
  }