@blocklet/cli 1.16.33 → 1.16.34-beta-20241120-080738-bbbe036c
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/README.md +32 -25
- package/bin/blocklet.js +292 -1
- package/config.example.yml +33 -0
- package/lib/arcblock.js +53 -0
- package/lib/commands/blocklet/add.js +124 -0
- package/lib/commands/blocklet/assets/git-ignore +28 -0
- package/lib/commands/blocklet/assets/index.html +9 -0
- package/lib/commands/blocklet/assets/index.js +14 -0
- package/lib/commands/blocklet/assets/logo.png +0 -0
- package/lib/commands/blocklet/bundle/bundle.js +184 -0
- package/lib/commands/blocklet/bundle/bundlers/blocklet.js +138 -0
- package/lib/commands/blocklet/bundle/bundlers/changelog.js +100 -0
- package/lib/commands/blocklet/bundle/bundlers/logo.js +56 -0
- package/lib/commands/blocklet/bundle/bundlers/markdown.js +241 -0
- package/lib/commands/blocklet/bundle/bundlers/preference.js +50 -0
- package/lib/commands/blocklet/bundle/bundlers/readme.js +43 -0
- package/lib/commands/blocklet/bundle/bundlers/screenshots.js +94 -0
- package/lib/commands/blocklet/bundle/bundlers/simple.js +70 -0
- package/lib/commands/blocklet/bundle/compact/bundle-compact-file.js +48 -0
- package/lib/commands/blocklet/bundle/compact/bundle-merge-extra.js +66 -0
- package/lib/commands/blocklet/bundle/compact/default-external.js +5 -0
- package/lib/commands/blocklet/bundle/compact/index.js +88 -0
- package/lib/commands/blocklet/bundle/index.js +139 -0
- package/lib/commands/blocklet/bundle/pack.js +8 -0
- package/lib/commands/blocklet/bundle/parse-external-dependencies.js +97 -0
- package/lib/commands/blocklet/bundle/simple/index.js +62 -0
- package/lib/commands/blocklet/bundle/zip/archive.js +35 -0
- package/lib/commands/blocklet/bundle/zip/dependencies.js +333 -0
- package/lib/commands/blocklet/bundle/zip/index.js +165 -0
- package/lib/commands/blocklet/bundle/zip/main.js +124 -0
- package/lib/commands/blocklet/bundle/zip/node.js +59 -0
- package/lib/commands/blocklet/bundle/zip/resolve.js +93 -0
- package/lib/commands/blocklet/cleanup.js +52 -0
- package/lib/commands/blocklet/config.js +108 -0
- package/lib/commands/blocklet/connect.js +87 -0
- package/lib/commands/blocklet/create.js +38 -0
- package/lib/commands/blocklet/deploy.js +435 -0
- package/lib/commands/blocklet/dev.js +1000 -0
- package/lib/commands/blocklet/document.js +39 -0
- package/lib/commands/blocklet/exec.js +106 -0
- package/lib/commands/blocklet/init.js +300 -0
- package/lib/commands/blocklet/meta.js +22 -0
- package/lib/commands/blocklet/remove.js +35 -0
- package/lib/commands/blocklet/test.js +201 -0
- package/lib/commands/blocklet/upload.js +105 -0
- package/lib/commands/blocklet/version.js +81 -0
- package/lib/commands/server/cleanup.js +32 -0
- package/lib/commands/server/command.js +131 -0
- package/lib/commands/server/info.js +92 -0
- package/lib/commands/server/init.js +433 -0
- package/lib/commands/server/logs.js +99 -0
- package/lib/commands/server/rescue.js +71 -0
- package/lib/commands/server/start.js +821 -0
- package/lib/commands/server/status.js +107 -0
- package/lib/commands/server/stop.js +163 -0
- package/lib/commands/server/upgrade.js +123 -0
- package/lib/constant.js +21 -2
- package/lib/debug.js +20 -0
- package/lib/manager/config.js +122 -0
- package/lib/manager/deploy.js +75 -0
- package/lib/manager/index.js +23 -0
- package/lib/manager/process.js +47 -0
- package/lib/node.js +214 -0
- package/lib/port.js +19 -0
- package/lib/postinstall.js +3 -0
- package/lib/process/daemon.js +196 -0
- package/lib/process/service.js +86 -0
- package/lib/ui.js +137 -0
- package/lib/util/blocklet/config.js +78 -0
- package/lib/util/blocklet/env.js +172 -0
- package/lib/util/blocklet/meta.js +36 -0
- package/lib/util/blocklet/payment.js +88 -0
- package/lib/util/blocklet/sign.js +21 -0
- package/lib/util/blocklet/tar.js +119 -0
- package/lib/util/convert-to-nosources-sourcemap.js +37 -0
- package/lib/util/docker-status-log.js +17 -0
- package/lib/util/exit-when-server-stopped.js +44 -0
- package/lib/util/get-cli-binary-name.js +8 -0
- package/lib/util/get-download-bundle-step.js +36 -0
- package/lib/util/get-service-instance-number.js +12 -0
- package/lib/util/index.js +626 -0
- package/lib/util/print-error.js +11 -0
- package/lib/util/print.js +9 -0
- package/lib/util/what-uri.js +40 -0
- package/package.json +123 -27
- package/lib/run.d.ts +0 -2
- package/lib/run.js +0 -73
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { BLOCKLET_BUNDLE_FOLDER } = require('@blocklet/constant');
|
|
4
|
+
const fromMarkdown = require('mdast-util-from-markdown');
|
|
5
|
+
const toMarkdown = require('mdast-util-to-markdown');
|
|
6
|
+
const crypto = require('crypto');
|
|
7
|
+
const { parser } = require('posthtml-parser');
|
|
8
|
+
const { render } = require('posthtml-render');
|
|
9
|
+
const isEmpty = require('lodash/isEmpty');
|
|
10
|
+
const isArray = require('lodash/isArray');
|
|
11
|
+
const chalk = require('chalk');
|
|
12
|
+
const { isLocalUri } = require('../../../../util/what-uri');
|
|
13
|
+
const { printError } = require('../../../../util');
|
|
14
|
+
|
|
15
|
+
class MarkdownBundler {
|
|
16
|
+
/**
|
|
17
|
+
* Creates an instance of MarkdownBundler.
|
|
18
|
+
* @param {{
|
|
19
|
+
* blockletDir: string
|
|
20
|
+
* }} { blockletDir }
|
|
21
|
+
* @memberof MarkdownBundler
|
|
22
|
+
*/
|
|
23
|
+
constructor({ blockletDir }) {
|
|
24
|
+
this.blockletDir = blockletDir;
|
|
25
|
+
this.bundleDir = path.join(this.blockletDir, BLOCKLET_BUNDLE_FOLDER);
|
|
26
|
+
this.mediaBundleDir = path.join(this.bundleDir, 'media');
|
|
27
|
+
this.mediaBaseUrl = '/assets/media';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
*
|
|
32
|
+
* @return {string[]} blocklet.md files absolute path list
|
|
33
|
+
* @memberof MarkdownBundler
|
|
34
|
+
*/
|
|
35
|
+
_find() {
|
|
36
|
+
throw new Error('Not implemented');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
*
|
|
41
|
+
*
|
|
42
|
+
* @return {Promise<void>}
|
|
43
|
+
* @memberof MarkdownBundler
|
|
44
|
+
*/
|
|
45
|
+
bundle() {
|
|
46
|
+
return this._bundle();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
*
|
|
51
|
+
* @description 从本地所有的blocklet.md提取本地静态文件到当前目录的media文件夹下面
|
|
52
|
+
* @param {*} blockletDir
|
|
53
|
+
*/
|
|
54
|
+
async _bundle() {
|
|
55
|
+
const markdownAbsolutePaths = await this._find();
|
|
56
|
+
const cache = new Map();
|
|
57
|
+
|
|
58
|
+
while (!isEmpty(markdownAbsolutePaths)) {
|
|
59
|
+
const markdownAbsolutePath = markdownAbsolutePaths.shift();
|
|
60
|
+
const mdAstNode = fromMarkdown(fs.readFileSync(markdownAbsolutePath));
|
|
61
|
+
|
|
62
|
+
const done = this._handleMdAstNode(mdAstNode, (astNode) => {
|
|
63
|
+
const referenceFile = astNode?.url || astNode?.attrs?.src || astNode?.attrs?.href;
|
|
64
|
+
const localUrl = this._getLocalUrl(referenceFile);
|
|
65
|
+
|
|
66
|
+
// FIXME: 后续jest mock做一个单测吧
|
|
67
|
+
if (!fs.existsSync(localUrl)) {
|
|
68
|
+
printError(
|
|
69
|
+
`Referenced file ${chalk.red(referenceFile)} not found when bundling ${chalk.cyan(
|
|
70
|
+
path.basename(markdownAbsolutePath)
|
|
71
|
+
)}`
|
|
72
|
+
);
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// 如果路径指向了一个文件夹,应该通过报错告知用户,文件夹不能存在于markdown文件当中
|
|
77
|
+
if (fs.statSync(localUrl).isDirectory()) {
|
|
78
|
+
printError(
|
|
79
|
+
`Only files links are allowed in ${chalk.cyan(
|
|
80
|
+
path.basename(markdownAbsolutePath)
|
|
81
|
+
)}, found a folder ${chalk.red(referenceFile)}`
|
|
82
|
+
);
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (!cache.get(localUrl)) {
|
|
87
|
+
cache.set(localUrl, null);
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const { storeStaticUrl } = cache.get(localUrl);
|
|
92
|
+
|
|
93
|
+
if (astNode?.url) {
|
|
94
|
+
astNode.url = storeStaticUrl;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (astNode?.attrs?.src) {
|
|
98
|
+
astNode.attrs.src = storeStaticUrl;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (astNode?.attrs?.href) {
|
|
102
|
+
astNode.attrs.href = storeStaticUrl;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return true;
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
if (done) {
|
|
109
|
+
// eslint-disable-next-line no-await-in-loop
|
|
110
|
+
await this.writeFile(path.join(this.bundleDir, path.basename(markdownAbsolutePath)), toMarkdown(mdAstNode));
|
|
111
|
+
} else {
|
|
112
|
+
// 说明有些资源还没有计算好hash值和复制到bundle下,blocklet.md没处理完,当然也就不能直接修改blocklet.md里面的引用了
|
|
113
|
+
// eslint-disable-next-line no-await-in-loop
|
|
114
|
+
await this._batchHash(cache);
|
|
115
|
+
// eslint-disable-next-line no-await-in-loop
|
|
116
|
+
await this._batchCopy(cache);
|
|
117
|
+
// 还没处理完成,等到下一轮再处理即可
|
|
118
|
+
markdownAbsolutePaths.push(markdownAbsolutePath);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
*
|
|
125
|
+
*
|
|
126
|
+
* @param {string} dest
|
|
127
|
+
* @param {string | NodeJS.ArrayBufferView} data
|
|
128
|
+
* @memberof MarkdownBundler
|
|
129
|
+
*/
|
|
130
|
+
writeFile(dest, data) {
|
|
131
|
+
fs.writeFileSync(dest, data);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
_batchHash(cache) {
|
|
135
|
+
return Promise.all(
|
|
136
|
+
[...cache.keys()].map((localUrl) => {
|
|
137
|
+
return this._getTargetUrls(localUrl).then((targetUrls) => {
|
|
138
|
+
cache.set(localUrl, targetUrls);
|
|
139
|
+
});
|
|
140
|
+
})
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
_batchCopy(cache) {
|
|
145
|
+
return Promise.all(
|
|
146
|
+
[...cache.keys()].map((localUrl) => {
|
|
147
|
+
const { mediaBundleUrl } = cache.get(localUrl);
|
|
148
|
+
return fs.ensureDir(path.dirname(mediaBundleUrl)).then(() => fs.copy(localUrl, mediaBundleUrl));
|
|
149
|
+
})
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
_handleMdAstNode(mdAstNode, callback) {
|
|
154
|
+
let done = true;
|
|
155
|
+
|
|
156
|
+
if (this._isLocalUrl(mdAstNode?.url)) {
|
|
157
|
+
done = done && callback(mdAstNode);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (this._isHtmlNode(mdAstNode)) {
|
|
161
|
+
const hastNode = parser(mdAstNode?.value);
|
|
162
|
+
done = done && this._handleHastNode(hastNode, callback);
|
|
163
|
+
mdAstNode.value = render(hastNode);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (mdAstNode?.children) {
|
|
167
|
+
done = mdAstNode.children.reduce(
|
|
168
|
+
(preValue, astNode) => this._handleMdAstNode(astNode, callback) && preValue,
|
|
169
|
+
done
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return done;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
_handleHastNode(root, callback) {
|
|
177
|
+
let done = true;
|
|
178
|
+
|
|
179
|
+
const currentRoot = isArray(root) ? root : [root];
|
|
180
|
+
|
|
181
|
+
currentRoot.forEach((children) => {
|
|
182
|
+
if (this._isLocalUrl(children?.attrs?.src || children?.attrs?.href)) {
|
|
183
|
+
done = callback(children) && done;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (isArray(children?.content)) {
|
|
187
|
+
done = children.content.reduce((preValue, _root) => this._handleHastNode(_root, callback) && preValue, done);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
return done;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
*
|
|
196
|
+
*
|
|
197
|
+
* @param {string} url
|
|
198
|
+
* @return {boolean}
|
|
199
|
+
* @memberof BundleMarkdown
|
|
200
|
+
*/
|
|
201
|
+
_isLocalUrl(url) {
|
|
202
|
+
return isLocalUri(url);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
_isHtmlNode(node) {
|
|
206
|
+
return node?.type === 'html';
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
_getLocalUrl(url) {
|
|
210
|
+
return path.join(this.blockletDir, url);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
async _getTargetUrls(localUrl) {
|
|
214
|
+
const fileHash = await this._getFileHash(localUrl);
|
|
215
|
+
|
|
216
|
+
const fileDirNameAndFileName = path.join(fileHash.slice(0, 2), `${fileHash.slice(2)}${path.extname(localUrl)}`);
|
|
217
|
+
|
|
218
|
+
return {
|
|
219
|
+
mediaBundleUrl: path.join(this.mediaBundleDir, fileDirNameAndFileName),
|
|
220
|
+
storeStaticUrl: path.join(this.mediaBaseUrl, fileDirNameAndFileName),
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
_getFileHash(url) {
|
|
225
|
+
return new Promise((resolve, reject) => {
|
|
226
|
+
const hash = crypto.createHash('md5');
|
|
227
|
+
const stream = fs.createReadStream(url);
|
|
228
|
+
stream.on('error', (err) => {
|
|
229
|
+
stream?.destroy();
|
|
230
|
+
reject(err);
|
|
231
|
+
});
|
|
232
|
+
stream.on('data', (chunk) => hash.update(chunk));
|
|
233
|
+
stream.on('end', () => {
|
|
234
|
+
stream?.destroy();
|
|
235
|
+
resolve(hash.digest('hex'));
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
module.exports = MarkdownBundler;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const fs = require('fs-extra');
|
|
3
|
+
const { BLOCKLET_BUNDLE_FOLDER, BLOCKLET_PREFERENCE_FILE } = require('@blocklet/constant');
|
|
4
|
+
const fg = require('fast-glob');
|
|
5
|
+
const chalk = require('chalk');
|
|
6
|
+
const { printError } = require('../../../../util');
|
|
7
|
+
|
|
8
|
+
class PreferenceBundler {
|
|
9
|
+
constructor({ blockletDir }) {
|
|
10
|
+
this.blockletDir = blockletDir;
|
|
11
|
+
this.bundlerDir = path.join(this.blockletDir, BLOCKLET_BUNDLE_FOLDER);
|
|
12
|
+
this.fileName = BLOCKLET_PREFERENCE_FILE;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
_find() {
|
|
16
|
+
const found = fg.sync(this.fileName, {
|
|
17
|
+
cwd: this.blockletDir,
|
|
18
|
+
deep: 1,
|
|
19
|
+
caseSensitiveMatch: false,
|
|
20
|
+
onlyFiles: true,
|
|
21
|
+
absolute: true,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
if (found.length) {
|
|
25
|
+
const [filePath] = found;
|
|
26
|
+
try {
|
|
27
|
+
fs.readJsonSync(filePath);
|
|
28
|
+
return filePath;
|
|
29
|
+
} catch (err) {
|
|
30
|
+
printError(`Invalid ${chalk.red(this.fileName)} find ${chalk.cyan(this.blockletDir)}`);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async _bundle(filePath) {
|
|
39
|
+
if (filePath) {
|
|
40
|
+
await fs.copy(filePath, path.join(this.bundlerDir, this.fileName));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async bundle() {
|
|
45
|
+
const filePath = await this._find();
|
|
46
|
+
await this._bundle(filePath);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
module.exports = PreferenceBundler;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const fg = require('fast-glob');
|
|
2
|
+
const MarkdownBundler = require('./markdown');
|
|
3
|
+
|
|
4
|
+
class ReadmeMdBundler extends MarkdownBundler {
|
|
5
|
+
static README_MD_REGEX = /README\.[\S]*md$/i;
|
|
6
|
+
|
|
7
|
+
constructor({ blockletDir }) {
|
|
8
|
+
super({ blockletDir });
|
|
9
|
+
this.readmeMdFileName = 'README.md';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
*
|
|
14
|
+
*
|
|
15
|
+
* @return {string[]} blocklet.md absolute path
|
|
16
|
+
* @memberof BlockletMdBundler
|
|
17
|
+
*/
|
|
18
|
+
_find() {
|
|
19
|
+
const found = fg.sync(this.readmeMdFileName, {
|
|
20
|
+
cwd: this.blockletDir,
|
|
21
|
+
deep: 1,
|
|
22
|
+
caseSensitiveMatch: false,
|
|
23
|
+
onlyFiles: true,
|
|
24
|
+
absolute: true,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
if (found.length > 1) {
|
|
28
|
+
throw new Error(`Only one ${this.readmeMdFileName}(not case sensitive) can exist in ${this.blockletDir}`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return found;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
bundle() {
|
|
35
|
+
return super.bundle();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async writeFile(dest, data) {
|
|
39
|
+
await super.writeFile(dest.replace(ReadmeMdBundler.README_MD_REGEX, this.readmeMdFileName), data);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
module.exports = ReadmeMdBundler;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
const { pathExists, emptyDir, ensureDir, copy } = require('fs-extra');
|
|
2
|
+
const { join, extname } = require('path');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
const { createReadStream } = require('fs');
|
|
5
|
+
const { onlyHash } = require('@arcblock/ipfs-only-hash');
|
|
6
|
+
const { validateScreenshots } = require('@blocklet/images');
|
|
7
|
+
const { print, printWarning, printInfo, printError } = require('../../../../util');
|
|
8
|
+
|
|
9
|
+
class ScreenshotsBundler {
|
|
10
|
+
/**
|
|
11
|
+
* Creates an instance of ScreenshotsBundler.
|
|
12
|
+
* @param {{
|
|
13
|
+
* blockletDir: string,
|
|
14
|
+
* bundleDir: string,
|
|
15
|
+
* meta: import('@abtnode/client').BlockletMeta
|
|
16
|
+
* }} { blockletDir, bundleDir, meta }
|
|
17
|
+
* @memberof ScreenshotsBundler
|
|
18
|
+
*/
|
|
19
|
+
constructor({ blockletDir = '', bundleDir = '', meta }) {
|
|
20
|
+
this.blockletDir = blockletDir;
|
|
21
|
+
this.bundleDir = bundleDir;
|
|
22
|
+
this.meta = meta;
|
|
23
|
+
|
|
24
|
+
this.screenshotsBlockletFolder = join(this.blockletDir, 'screenshots');
|
|
25
|
+
this.screenshotsBundleFolder = join(this.bundleDir, 'screenshots');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
*
|
|
30
|
+
* @return {Promise<void>}
|
|
31
|
+
* @memberof ScreenshotsBundler
|
|
32
|
+
*/
|
|
33
|
+
async _bundle() {
|
|
34
|
+
await this._clean();
|
|
35
|
+
|
|
36
|
+
if (!this.meta?.screenshots?.length) {
|
|
37
|
+
printWarning('No screenshots found!');
|
|
38
|
+
} else {
|
|
39
|
+
const errorMessages = validateScreenshots(this.meta.screenshots, {
|
|
40
|
+
extractedFilepath: this.blockletDir,
|
|
41
|
+
minWidth: 600,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
if (errorMessages.length) {
|
|
45
|
+
print('');
|
|
46
|
+
printWarning('Blocklet bundle failed! Please check the following errors about screenshots:');
|
|
47
|
+
errorMessages.forEach((errorMessage) => printError(errorMessage));
|
|
48
|
+
printInfo(
|
|
49
|
+
`You can run the command "${chalk.cyan('blocklet dev studio')}" to help you generate more standard screenshots.`
|
|
50
|
+
);
|
|
51
|
+
print('');
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const entryList = await Promise.all(
|
|
56
|
+
this.meta.screenshots.map(async (fileName) => {
|
|
57
|
+
const source = join(this.screenshotsBlockletFolder, fileName);
|
|
58
|
+
if (pathExists(source)) {
|
|
59
|
+
const hash = await onlyHash(createReadStream(source));
|
|
60
|
+
const filename = `${hash}${extname(fileName)}`;
|
|
61
|
+
const target = join(this.screenshotsBundleFolder, filename);
|
|
62
|
+
return { source, target, filename };
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
})
|
|
66
|
+
);
|
|
67
|
+
await Promise.all(entryList.map((item) => item && copy(item.source, item.target)));
|
|
68
|
+
const filenames = [];
|
|
69
|
+
entryList.forEach((item) => {
|
|
70
|
+
if (item?.filename) {
|
|
71
|
+
filenames.push(item.filename);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
this.meta.screenshots = filenames;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @description 清理 screenshots bundle 的文件夹
|
|
80
|
+
* @memberof ScreenshotsBundler
|
|
81
|
+
*/
|
|
82
|
+
async _clean() {
|
|
83
|
+
if (await pathExists(this.screenshotsBundleFolder)) {
|
|
84
|
+
await emptyDir(this.screenshotsBundleFolder);
|
|
85
|
+
}
|
|
86
|
+
await ensureDir(this.screenshotsBundleFolder);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
bundle() {
|
|
90
|
+
return this._bundle();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
module.exports = ScreenshotsBundler;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
const ISO6391 = require('iso-639-1');
|
|
2
|
+
|
|
3
|
+
const { BLOCKLET_BUNDLE_FOLDER } = require('@blocklet/constant');
|
|
4
|
+
const { join } = require('path');
|
|
5
|
+
const BlockletMdBundler = require('./blocklet');
|
|
6
|
+
const ChangelogBundler = require('./changelog');
|
|
7
|
+
const LogoBundler = require('./logo');
|
|
8
|
+
const ReadmeMdBundler = require('./readme');
|
|
9
|
+
const PreferenceBundler = require('./preference');
|
|
10
|
+
const ScreenshotsBundler = require('./screenshots');
|
|
11
|
+
|
|
12
|
+
class SimpleBundler {
|
|
13
|
+
/**
|
|
14
|
+
* Creates an instance of SimpleBundler.
|
|
15
|
+
* @param {{
|
|
16
|
+
* blockletDir: string,
|
|
17
|
+
* inMonoRepo: boolean,
|
|
18
|
+
* withChangeLog: boolean,
|
|
19
|
+
* meta: {
|
|
20
|
+
* logo: string,
|
|
21
|
+
* }
|
|
22
|
+
* }} { blockletDir, inMonoRepo, withChangeLog, meta }
|
|
23
|
+
* @memberof SimpleBundler
|
|
24
|
+
*/
|
|
25
|
+
constructor({ blockletDir, inMonoRepo, withChangeLog, meta }) {
|
|
26
|
+
this.blockletDir = blockletDir;
|
|
27
|
+
this.inMonoRepo = inMonoRepo;
|
|
28
|
+
this.withChangeLog = withChangeLog;
|
|
29
|
+
this.meta = meta;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async bundle() {
|
|
33
|
+
const locales = ISO6391.getAllCodes();
|
|
34
|
+
const { blockletDir, inMonoRepo } = this;
|
|
35
|
+
const bundleDir = join(this.blockletDir, BLOCKLET_BUNDLE_FOLDER);
|
|
36
|
+
|
|
37
|
+
const blockletMdPromises = locales.map((locale) => {
|
|
38
|
+
if (locale === 'en') {
|
|
39
|
+
return new BlockletMdBundler({
|
|
40
|
+
blockletDir,
|
|
41
|
+
blockletMdFileName: 'blocklet.md',
|
|
42
|
+
backupMdFileNames: ['blocklet.en.md', 'README.md'],
|
|
43
|
+
duplicateMdFileName: 'blocklet.en.md',
|
|
44
|
+
required: true,
|
|
45
|
+
}).bundle();
|
|
46
|
+
}
|
|
47
|
+
return new BlockletMdBundler({
|
|
48
|
+
blockletDir,
|
|
49
|
+
blockletMdFileName: `blocklet.${locale}.md`,
|
|
50
|
+
}).bundle();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
await new ScreenshotsBundler({ blockletDir, bundleDir, meta: this.meta }).bundle();
|
|
54
|
+
await new LogoBundler({ blockletDir, logoFileName: this.meta.logo }).bundle();
|
|
55
|
+
|
|
56
|
+
await Promise.all([
|
|
57
|
+
...blockletMdPromises,
|
|
58
|
+
this.withChangeLog
|
|
59
|
+
? new ChangelogBundler({
|
|
60
|
+
blockletDir,
|
|
61
|
+
inMonoRepo,
|
|
62
|
+
}).bundle()
|
|
63
|
+
: Promise.resolve(null),
|
|
64
|
+
new ReadmeMdBundler({ blockletDir }).bundle(),
|
|
65
|
+
new PreferenceBundler({ blockletDir }).bundle(),
|
|
66
|
+
]);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
module.exports = SimpleBundler;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const ncc = require('@vercel/ncc');
|
|
2
|
+
const fs = require('fs-extra');
|
|
3
|
+
const { dirname, resolve } = require('path');
|
|
4
|
+
const convertToNoSourcesSourceMap = require('../../../../util/convert-to-nosources-sourcemap');
|
|
5
|
+
|
|
6
|
+
async function bundleCompactFile({
|
|
7
|
+
srcPath,
|
|
8
|
+
distDir,
|
|
9
|
+
enterFile,
|
|
10
|
+
sourceMap,
|
|
11
|
+
nosourcesSourceMap,
|
|
12
|
+
externals,
|
|
13
|
+
minify = true,
|
|
14
|
+
}) {
|
|
15
|
+
const { code, assets } = await ncc(resolve(srcPath, enterFile), {
|
|
16
|
+
sourceMap: sourceMap || nosourcesSourceMap,
|
|
17
|
+
externals,
|
|
18
|
+
minify,
|
|
19
|
+
quiet: true,
|
|
20
|
+
cache: false,
|
|
21
|
+
sourceMapBasePrefix: '',
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const codeFile = resolve(distDir, enterFile);
|
|
25
|
+
const outDir = dirname(codeFile);
|
|
26
|
+
if (!fs.existsSync(dirname(codeFile))) {
|
|
27
|
+
fs.mkdirSync(dirname(codeFile), { recursive: true });
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
fs.writeFileSync(codeFile, code);
|
|
31
|
+
|
|
32
|
+
Object.keys(assets).forEach((name) => {
|
|
33
|
+
const distDirByFile = dirname(resolve(outDir, name));
|
|
34
|
+
if (!fs.existsSync(distDirByFile)) {
|
|
35
|
+
fs.mkdirSync(distDirByFile, { recursive: true });
|
|
36
|
+
}
|
|
37
|
+
fs.writeFileSync(resolve(outDir, name), assets[name].source);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
if (!sourceMap && nosourcesSourceMap) {
|
|
41
|
+
const mapFilePath = resolve(distDir, 'index.js.map');
|
|
42
|
+
await convertToNoSourcesSourceMap(mapFilePath, mapFilePath);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
module.exports = {
|
|
47
|
+
bundleCompactFile,
|
|
48
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const pAll = require('p-all');
|
|
4
|
+
const { bundleCompactFile } = require('./bundle-compact-file');
|
|
5
|
+
const { parseExternalDependencies } = require('../parse-external-dependencies');
|
|
6
|
+
|
|
7
|
+
const compactFileName = 'blocklet-compact.js';
|
|
8
|
+
|
|
9
|
+
async function bundleMergeExtra({
|
|
10
|
+
extraFiles,
|
|
11
|
+
srcPath,
|
|
12
|
+
distDir,
|
|
13
|
+
sourceMap,
|
|
14
|
+
nosourcesSourceMap,
|
|
15
|
+
enterFile,
|
|
16
|
+
externals,
|
|
17
|
+
externalManager,
|
|
18
|
+
minify,
|
|
19
|
+
}) {
|
|
20
|
+
const entryFiles = [...extraFiles, enterFile];
|
|
21
|
+
|
|
22
|
+
const compactCode = `
|
|
23
|
+
module.exports = {
|
|
24
|
+
${entryFiles.map((file) => `'${file}':()=> require('${path.resolve(srcPath, file)}'),`).join('\n')}
|
|
25
|
+
};
|
|
26
|
+
`;
|
|
27
|
+
|
|
28
|
+
if (!fs.existsSync(distDir)) {
|
|
29
|
+
fs.mkdirpSync(distDir);
|
|
30
|
+
}
|
|
31
|
+
fs.writeFileSync(path.resolve(distDir, compactFileName), compactCode);
|
|
32
|
+
await bundleCompactFile({
|
|
33
|
+
minify,
|
|
34
|
+
externals,
|
|
35
|
+
srcPath: distDir,
|
|
36
|
+
distDir,
|
|
37
|
+
enterFile: compactFileName,
|
|
38
|
+
sourceMap,
|
|
39
|
+
nosourcesSourceMap,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const promises = entryFiles.map((file) => {
|
|
43
|
+
return async () => {
|
|
44
|
+
const distDirByFile = path.dirname(path.resolve(distDir, file));
|
|
45
|
+
try {
|
|
46
|
+
await fs.access(distDirByFile);
|
|
47
|
+
} catch (err) {
|
|
48
|
+
await fs.mkdir(distDirByFile, { recursive: true });
|
|
49
|
+
}
|
|
50
|
+
await fs.writeFile(
|
|
51
|
+
path.resolve(distDir, file),
|
|
52
|
+
`module.exports = require('${path.relative(
|
|
53
|
+
distDirByFile,
|
|
54
|
+
path.resolve(distDir, compactFileName)
|
|
55
|
+
)}')['${file}']();`
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
await pAll(promises, { concurrency: 4 });
|
|
60
|
+
|
|
61
|
+
parseExternalDependencies({ externals, distDir, externalManager });
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
module.exports = {
|
|
65
|
+
bundleMergeExtra,
|
|
66
|
+
};
|