@struggler/cli 1.0.8 → 1.0.10
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/assets/logo.png +0 -0
- package/command/upload.js +4 -2
- package/index.js +1 -3
- package/lib/logo.js +1 -0
- package/lib/mime.js +55 -0
- package/package.json +5 -3
- package/test/upload.test.js +70 -0
package/assets/logo.png
ADDED
|
Binary file
|
package/command/upload.js
CHANGED
|
@@ -19,6 +19,7 @@ const { printMessage } = require('../lib/output');
|
|
|
19
19
|
const { computeFileMd5, readCache, writeCache, isCacheHit, updateCacheEntry } = require('../lib/cache');
|
|
20
20
|
const { createProgressBar } = require('../lib/progress');
|
|
21
21
|
const { getLocale } = require('../lib/i18n');
|
|
22
|
+
const { resolveMimeType } = require('../lib/mime');
|
|
22
23
|
|
|
23
24
|
async function main(options, runtime = {}) {
|
|
24
25
|
const qiniuConfig = getJsonData(getQiniuConfig(options))
|
|
@@ -89,9 +90,10 @@ async function main(options, runtime = {}) {
|
|
|
89
90
|
config.useCdnDomain = true;
|
|
90
91
|
|
|
91
92
|
var formUploader = new qiniu.form_up.FormUploader(config);
|
|
92
|
-
var putExtra = new qiniu.form_up.PutExtra();
|
|
93
|
-
|
|
94
93
|
function upload(plan, attempt = 1) {
|
|
94
|
+
var putExtra = new qiniu.form_up.PutExtra();
|
|
95
|
+
putExtra.mimeType = resolveMimeType(plan.localFile);
|
|
96
|
+
|
|
95
97
|
var uploadOptions = {
|
|
96
98
|
scope: `${qiniuConfig.Bucket}:${plan.key}`
|
|
97
99
|
};
|
package/index.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
#! /usr/bin/env node
|
|
2
|
-
const { magentaBright } = require("chalk")
|
|
3
|
-
const figlet = require("figlet")
|
|
4
2
|
const clear = require("clear")
|
|
5
3
|
const { program } = require("commander")
|
|
6
4
|
const command = require("./command")
|
|
@@ -19,7 +17,7 @@ if (!shouldUseJson({ json: isJsonMode })) {
|
|
|
19
17
|
|
|
20
18
|
// 输出Logo
|
|
21
19
|
if (!isJsonMode) {
|
|
22
|
-
console.log(
|
|
20
|
+
console.log(require('./lib/logo') + '\n')
|
|
23
21
|
}
|
|
24
22
|
|
|
25
23
|
function formatItems(items, getLeft, getRight) {
|
package/lib/logo.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = " \u001b[38;5;240m⡀\u001b[0m \u001b[38;5;196m⢀\u001b[0m\u001b[38;5;196m⣤\u001b[0m\u001b[38;5;196m⣶\u001b[0m\u001b[38;5;196m⡿\u001b[0m\n \u001b[38;5;240m⠈\u001b[0m\u001b[38;5;240m⢿\u001b[0m\u001b[38;5;240m⣷\u001b[0m\u001b[38;5;240m⣦\u001b[0m\u001b[38;5;240m⣀\u001b[0m \u001b[38;5;196m⣀\u001b[0m\u001b[38;5;196m⣴\u001b[0m\u001b[38;5;196m⣾\u001b[0m\u001b[38;5;196m⣿\u001b[0m\u001b[38;5;196m⣿\u001b[0m\u001b[38;5;196m⣿\u001b[0m\u001b[38;5;240m⠁\u001b[0m\n \u001b[38;5;240m⠘\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣶\u001b[0m\u001b[38;5;240m⣤\u001b[0m\u001b[38;5;240m⣀\u001b[0m \u001b[38;5;240m⢀\u001b[0m\u001b[38;5;240m⣠\u001b[0m\u001b[38;5;240m⣶\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;196m⣿\u001b[0m\u001b[38;5;196m⣿\u001b[0m\u001b[38;5;196m⣿\u001b[0m\u001b[38;5;196m⣿\u001b[0m\u001b[38;5;196m⣿\u001b[0m\u001b[38;5;196m⠃\u001b[0m\n \u001b[38;5;240m⠘\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣦\u001b[0m\u001b[38;5;240m⣄\u001b[0m\u001b[38;5;240m⡀\u001b[0m \u001b[38;5;240m⣀\u001b[0m\u001b[38;5;240m⣤\u001b[0m\u001b[38;5;240m⣾\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;196m⣿\u001b[0m\u001b[38;5;196m⣿\u001b[0m\u001b[38;5;196m⠏\u001b[0m\n \u001b[38;5;240m⠹\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⢿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⢸\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⢿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⡟\u001b[0m\n \u001b[38;5;240m⢹\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⢠\u001b[0m\u001b[38;5;240m⣈\u001b[0m\u001b[38;5;240m⠻\u001b[0m\u001b[38;5;240m⢿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⢸\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⠿\u001b[0m\u001b[38;5;240m⢋\u001b[0m\u001b[38;5;240m⣤\u001b[0m\u001b[38;5;240m⢸\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⡿\u001b[0m\n \u001b[38;5;240m⢻\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⢸\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣷\u001b[0m\u001b[38;5;240m⣤\u001b[0m\u001b[38;5;240m⡙\u001b[0m\u001b[38;5;240m⠈\u001b[0m\u001b[38;5;240m⣡\u001b[0m\u001b[38;5;240m⣴\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⢸\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⠁\u001b[0m\n \u001b[38;5;240m⢿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⢸\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⢸\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⠃\u001b[0m\n \u001b[38;5;240m⠈\u001b[0m\u001b[38;5;240m⢿\u001b[0m\u001b[38;5;240m⢸\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⢸\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⠏\u001b[0m\n \u001b[38;5;240m⠘\u001b[0m\u001b[38;5;240m⢸\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⢸\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⡟\u001b[0m\n \u001b[38;5;240m⢸\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⢸\u001b[0m\u001b[38;5;240m⡿\u001b[0m\u001b[38;5;240m⠁\u001b[0m\n \u001b[38;5;240m⢸\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⢸\u001b[0m\u001b[38;5;240m⠃\u001b[0m\n \u001b[38;5;240m⠘\u001b[0m\u001b[38;5;240m⢿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⠿\u001b[0m\n \u001b[38;5;240m⠉\u001b[0m\u001b[38;5;240m⠻\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⣿\u001b[0m\u001b[38;5;240m⡿\u001b[0m\u001b[38;5;240m⠛\u001b[0m\u001b[38;5;240m⠁\u001b[0m\n \u001b[38;5;240m⠉\u001b[0m";
|
package/lib/mime.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
|
|
3
|
+
const MIME_TYPES = {
|
|
4
|
+
'.js': 'application/javascript',
|
|
5
|
+
'.mjs': 'application/javascript',
|
|
6
|
+
'.cjs': 'application/javascript',
|
|
7
|
+
'.css': 'text/css',
|
|
8
|
+
'.html': 'text/html',
|
|
9
|
+
'.htm': 'text/html',
|
|
10
|
+
'.json': 'application/json',
|
|
11
|
+
'.map': 'application/json',
|
|
12
|
+
'.txt': 'text/plain',
|
|
13
|
+
'.xml': 'application/xml',
|
|
14
|
+
'.svg': 'image/svg+xml',
|
|
15
|
+
'.png': 'image/png',
|
|
16
|
+
'.jpg': 'image/jpeg',
|
|
17
|
+
'.jpeg': 'image/jpeg',
|
|
18
|
+
'.gif': 'image/gif',
|
|
19
|
+
'.webp': 'image/webp',
|
|
20
|
+
'.ico': 'image/x-icon',
|
|
21
|
+
'.woff': 'font/woff',
|
|
22
|
+
'.woff2': 'font/woff2',
|
|
23
|
+
'.ttf': 'font/ttf',
|
|
24
|
+
'.otf': 'font/otf',
|
|
25
|
+
'.eot': 'application/vnd.ms-fontobject',
|
|
26
|
+
'.wasm': 'application/wasm',
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
function loadMimeResolver() {
|
|
30
|
+
try {
|
|
31
|
+
const qiniuDir = path.dirname(require.resolve('qiniu'));
|
|
32
|
+
const mimePath = require.resolve('mime', { paths: [qiniuDir] });
|
|
33
|
+
return require(mimePath);
|
|
34
|
+
} catch (error) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const mimeResolver = loadMimeResolver();
|
|
40
|
+
|
|
41
|
+
function resolveMimeType(filePath) {
|
|
42
|
+
if (mimeResolver && typeof mimeResolver.getType === 'function') {
|
|
43
|
+
const detected = mimeResolver.getType(filePath);
|
|
44
|
+
if (detected) {
|
|
45
|
+
return detected;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const extension = path.extname(filePath).toLowerCase();
|
|
50
|
+
return MIME_TYPES[extension] || null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
module.exports = {
|
|
54
|
+
resolveMimeType,
|
|
55
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@struggler/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.10",
|
|
4
4
|
"description": "CLI to Upload vite packaged files to Qiniu Cloud OSS.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -16,14 +16,16 @@
|
|
|
16
16
|
],
|
|
17
17
|
"author": "moqi(str@li.cm)",
|
|
18
18
|
"license": "ISC",
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=16"
|
|
21
|
+
},
|
|
19
22
|
"dependencies": {
|
|
20
23
|
"chalk": "^v4.1.2",
|
|
21
24
|
"clear": "^0.1.0",
|
|
22
25
|
"commander": "^11.0.0",
|
|
23
|
-
"figlet": "^1.6.0",
|
|
24
26
|
"qiniu": "^7.8.0"
|
|
25
27
|
},
|
|
26
28
|
"publicConfig": {
|
|
27
29
|
"registry": "http://registry.npmjs.org/"
|
|
28
30
|
}
|
|
29
|
-
}
|
|
31
|
+
}
|
package/test/upload.test.js
CHANGED
|
@@ -3,8 +3,10 @@ const assert = require('node:assert/strict');
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const os = require('os');
|
|
5
5
|
const path = require('path');
|
|
6
|
+
const qiniu = require('qiniu');
|
|
6
7
|
const upload = require('../command/upload');
|
|
7
8
|
const deploy = require('../command/deploy');
|
|
9
|
+
const { resolveMimeType } = require('../lib/mime');
|
|
8
10
|
|
|
9
11
|
function createWorkspace() {
|
|
10
12
|
const workspace = fs.mkdtempSync(path.join(os.tmpdir(), 'struggler-cli-upload-'));
|
|
@@ -111,3 +113,71 @@ test('deploy dry-run supports skip-refresh and json-friendly summary data', asyn
|
|
|
111
113
|
fs.rmSync(workspace, { recursive: true, force: true });
|
|
112
114
|
}
|
|
113
115
|
});
|
|
116
|
+
|
|
117
|
+
test('upload sets explicit mimeType for web assets', async () => {
|
|
118
|
+
const previousCwd = process.cwd();
|
|
119
|
+
const workspace = createWorkspace();
|
|
120
|
+
const captured = [];
|
|
121
|
+
|
|
122
|
+
const originalMac = qiniu.auth.digest.Mac;
|
|
123
|
+
const originalPutPolicy = qiniu.rs.PutPolicy;
|
|
124
|
+
const originalFormUploader = qiniu.form_up.FormUploader;
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
process.chdir(workspace);
|
|
128
|
+
|
|
129
|
+
fs.writeFileSync(path.join(workspace, 'command/qiniu.json'), JSON.stringify({
|
|
130
|
+
accessKey: 'ak',
|
|
131
|
+
secretKey: 'sk',
|
|
132
|
+
Bucket: 'demo-bucket',
|
|
133
|
+
zone: 'Zone_z0',
|
|
134
|
+
path: 'demo-app',
|
|
135
|
+
domain: 'https://cdn.example.com/',
|
|
136
|
+
}, null, 2));
|
|
137
|
+
|
|
138
|
+
qiniu.auth.digest.Mac = function MockMac() {};
|
|
139
|
+
qiniu.rs.PutPolicy = function MockPutPolicy() {
|
|
140
|
+
this.uploadToken = () => 'mock-token';
|
|
141
|
+
};
|
|
142
|
+
qiniu.form_up.FormUploader = function MockFormUploader() {
|
|
143
|
+
this.putFile = (uploadToken, key, localFile, putExtra, callback) => {
|
|
144
|
+
captured.push({
|
|
145
|
+
uploadToken,
|
|
146
|
+
key,
|
|
147
|
+
localFile,
|
|
148
|
+
mimeType: putExtra.mimeType,
|
|
149
|
+
});
|
|
150
|
+
callback(null, { hash: `${path.basename(localFile)}-hash` }, { statusCode: 200 });
|
|
151
|
+
};
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const summary = await upload({
|
|
155
|
+
config: './command/qiniu.json',
|
|
156
|
+
dir: './dist',
|
|
157
|
+
concurrency: '1',
|
|
158
|
+
}, {
|
|
159
|
+
suppressOutput: true,
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
assert.equal(summary.failedCount, 0);
|
|
163
|
+
assert.deepEqual(
|
|
164
|
+
captured.map((item) => [path.basename(item.localFile), item.mimeType]).sort(),
|
|
165
|
+
[
|
|
166
|
+
['app.js', 'application/javascript'],
|
|
167
|
+
['index.html', 'text/html'],
|
|
168
|
+
]
|
|
169
|
+
);
|
|
170
|
+
} finally {
|
|
171
|
+
qiniu.auth.digest.Mac = originalMac;
|
|
172
|
+
qiniu.rs.PutPolicy = originalPutPolicy;
|
|
173
|
+
qiniu.form_up.FormUploader = originalFormUploader;
|
|
174
|
+
process.chdir(previousCwd);
|
|
175
|
+
fs.rmSync(workspace, { recursive: true, force: true });
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
test('resolveMimeType covers common assets and keeps safe fallback', () => {
|
|
180
|
+
assert.equal(resolveMimeType('/tmp/app.js'), 'application/javascript');
|
|
181
|
+
assert.equal(resolveMimeType('/tmp/logo.svg'), 'image/svg+xml');
|
|
182
|
+
assert.equal(resolveMimeType('/tmp/data.unknown-ext'), null);
|
|
183
|
+
});
|