nos-upload-cli 0.1.0 → 0.2.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.
- package/dist/index.d.ts +1 -0
- package/dist/index.js +231 -174
- package/dist/index.js.map +1 -0
- package/package.json +33 -31
- package/bin/index.js +0 -3
- package/dist/index.cjs +0 -259
- package/readme.md +0 -24
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,239 +1,296 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
1
3
|
// src/index.ts
|
|
2
4
|
import { program } from "commander";
|
|
3
5
|
import inquirer from "inquirer";
|
|
4
|
-
import url from "url";
|
|
5
6
|
|
|
6
7
|
// src/app.ts
|
|
7
8
|
import fs3 from "fs";
|
|
8
9
|
import path2 from "path";
|
|
9
10
|
|
|
10
|
-
//
|
|
11
|
-
import fs2 from "fs";
|
|
12
|
-
import { NosClient } from "@nos-sdk/nos-node-sdk";
|
|
13
|
-
|
|
14
|
-
// src/utils/config.ts
|
|
11
|
+
// ../core/dist/index.js
|
|
15
12
|
import nconf from "nconf";
|
|
16
13
|
import path from "path";
|
|
17
14
|
import fs from "fs";
|
|
18
15
|
import os from "os";
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
import url from "url";
|
|
17
|
+
import fs2 from "fs";
|
|
18
|
+
import { NosClient } from "@nos-sdk/nos-node-sdk";
|
|
19
|
+
var log = {
|
|
22
20
|
log: (message) => {
|
|
23
21
|
console.log(message);
|
|
24
22
|
},
|
|
25
23
|
error: (message) => {
|
|
26
|
-
console.
|
|
24
|
+
console.error(message);
|
|
25
|
+
},
|
|
26
|
+
warn: (message) => {
|
|
27
|
+
console.warn(message);
|
|
28
|
+
},
|
|
29
|
+
info: (message) => {
|
|
30
|
+
console.info(message);
|
|
27
31
|
}
|
|
28
32
|
};
|
|
29
|
-
|
|
30
|
-
// src/utils/config.ts
|
|
33
|
+
var log_default = log;
|
|
31
34
|
var NOS_CONF_PATH = path.resolve(os.homedir(), ".nos-conf", "config.json");
|
|
32
|
-
var
|
|
35
|
+
var ENV_KEY_MAP = {
|
|
36
|
+
"NOS_ACCESS_KEY": "accessKey",
|
|
37
|
+
"NOS_ACCESS_SECRET": "accessSecret",
|
|
38
|
+
"NOS_ENDPOINT": "endpoint",
|
|
39
|
+
"NOS_DEFAULT_BUCKET": "defaultBucket",
|
|
40
|
+
"NOS_HOST": "host",
|
|
41
|
+
"NOS_PROTOCOL": "protocol"
|
|
42
|
+
};
|
|
43
|
+
var REQUIRED_KEYS = ["accessKey", "accessSecret", "endpoint", "defaultBucket", "host"];
|
|
44
|
+
var SENSITIVE_KEYS = ["accessKey", "accessSecret"];
|
|
45
|
+
function maskValue(value, key) {
|
|
46
|
+
if (!value) return "";
|
|
47
|
+
if (SENSITIVE_KEYS.includes(key)) {
|
|
48
|
+
if (value.length <= 4) return "****";
|
|
49
|
+
return value.slice(0, 2) + "***" + value.slice(-2);
|
|
50
|
+
}
|
|
51
|
+
return value;
|
|
52
|
+
}
|
|
53
|
+
var NOSConf = class _NOSConf {
|
|
33
54
|
constructor() {
|
|
34
|
-
this.
|
|
35
|
-
this.
|
|
36
|
-
|
|
55
|
+
this.nconfInstance = nconf;
|
|
56
|
+
this.nconfInstance.env({
|
|
57
|
+
separator: "__",
|
|
58
|
+
match: /^NOS_/,
|
|
59
|
+
transform: (obj) => {
|
|
60
|
+
const newKey = ENV_KEY_MAP[obj.key];
|
|
61
|
+
if (newKey) {
|
|
62
|
+
return { key: newKey, value: obj.value };
|
|
63
|
+
}
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
}).file({ file: NOS_CONF_PATH });
|
|
67
|
+
_NOSConf.ensureConfigDir();
|
|
37
68
|
}
|
|
38
|
-
|
|
69
|
+
/**
|
|
70
|
+
* 确保配置目录存在(同步方式,避免竞态)
|
|
71
|
+
*/
|
|
72
|
+
static ensureConfigDir() {
|
|
39
73
|
const dirPath = path.dirname(NOS_CONF_PATH);
|
|
40
|
-
|
|
41
|
-
recursive: true
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
});
|
|
74
|
+
try {
|
|
75
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
76
|
+
} catch (err) {
|
|
77
|
+
log_default.error("\u521D\u59CB\u5316\u914D\u7F6E\u76EE\u5F55\u5931\u8D25");
|
|
78
|
+
}
|
|
47
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* 获取配置
|
|
82
|
+
*/
|
|
48
83
|
getConfig() {
|
|
49
84
|
return {
|
|
50
|
-
accessKey: this.
|
|
51
|
-
accessSecret: this.
|
|
52
|
-
endpoint: this.
|
|
53
|
-
defaultBucket: this.
|
|
54
|
-
host: this.
|
|
55
|
-
protocol: this.
|
|
85
|
+
accessKey: this.nconfInstance.get("accessKey"),
|
|
86
|
+
accessSecret: this.nconfInstance.get("accessSecret"),
|
|
87
|
+
endpoint: this.nconfInstance.get("endpoint"),
|
|
88
|
+
defaultBucket: this.nconfInstance.get("defaultBucket"),
|
|
89
|
+
host: this.nconfInstance.get("host"),
|
|
90
|
+
protocol: this.nconfInstance.get("protocol")
|
|
56
91
|
};
|
|
57
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* 设置配置(简化版,自动处理 protocol)
|
|
95
|
+
*/
|
|
58
96
|
setConfig(config) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
97
|
+
const validKeys = ["accessKey", "accessSecret", "endpoint", "defaultBucket", "host", "protocol"];
|
|
98
|
+
for (const [key, value] of Object.entries(config)) {
|
|
99
|
+
if (validKeys.includes(key) && value) {
|
|
100
|
+
this.nconfInstance.set(key, value);
|
|
101
|
+
}
|
|
64
102
|
}
|
|
65
|
-
if (config.endpoint) {
|
|
66
|
-
|
|
103
|
+
if (config.endpoint && !config.protocol) {
|
|
104
|
+
const parsedUrl = url.parse(config.endpoint);
|
|
105
|
+
const protocol = parsedUrl.protocol?.slice(0, -1) || "http";
|
|
106
|
+
this.nconfInstance.set("protocol", protocol);
|
|
67
107
|
}
|
|
68
|
-
|
|
69
|
-
|
|
108
|
+
this.nconfInstance.save(void 0);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* 重置配置
|
|
112
|
+
*/
|
|
113
|
+
reset() {
|
|
114
|
+
this.nconfInstance.reset();
|
|
115
|
+
this.nconfInstance.save(void 0);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* 获取配置状态(脱敏输出)
|
|
119
|
+
*/
|
|
120
|
+
getConfigStatus() {
|
|
121
|
+
const config = this.getConfig();
|
|
122
|
+
const items = [];
|
|
123
|
+
const missingKeys = [];
|
|
124
|
+
for (const key of REQUIRED_KEYS) {
|
|
125
|
+
const value = config[key];
|
|
126
|
+
const isSet = !!value;
|
|
127
|
+
if (!isSet) {
|
|
128
|
+
missingKeys.push(key);
|
|
129
|
+
}
|
|
130
|
+
let source;
|
|
131
|
+
const envKey = Object.entries(ENV_KEY_MAP).find(([, v]) => v === key)?.[0];
|
|
132
|
+
if (envKey && process.env[envKey]) {
|
|
133
|
+
source = "env";
|
|
134
|
+
} else if (isSet) {
|
|
135
|
+
source = "file";
|
|
136
|
+
}
|
|
137
|
+
items.push({
|
|
138
|
+
key,
|
|
139
|
+
isSet,
|
|
140
|
+
source,
|
|
141
|
+
preview: isSet ? maskValue(value, key) : void 0
|
|
142
|
+
});
|
|
70
143
|
}
|
|
71
|
-
|
|
72
|
-
|
|
144
|
+
return {
|
|
145
|
+
isComplete: missingKeys.length === 0,
|
|
146
|
+
missingKeys,
|
|
147
|
+
items
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* 验证配置完整性
|
|
152
|
+
*/
|
|
153
|
+
validateConfig() {
|
|
154
|
+
const config = this.getConfig();
|
|
155
|
+
const missingKeys = [];
|
|
156
|
+
for (const key of REQUIRED_KEYS) {
|
|
157
|
+
if (!config[key]) {
|
|
158
|
+
missingKeys.push(key);
|
|
159
|
+
}
|
|
73
160
|
}
|
|
74
|
-
if (
|
|
75
|
-
|
|
161
|
+
if (missingKeys.length === 0) {
|
|
162
|
+
return {
|
|
163
|
+
valid: true,
|
|
164
|
+
missingKeys: [],
|
|
165
|
+
message: "Configuration is complete"
|
|
166
|
+
};
|
|
76
167
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
168
|
+
return {
|
|
169
|
+
valid: false,
|
|
170
|
+
missingKeys,
|
|
171
|
+
message: `Missing required config: ${missingKeys.join(", ")}`
|
|
172
|
+
};
|
|
82
173
|
}
|
|
83
174
|
};
|
|
84
175
|
var nosConf = new NOSConf();
|
|
85
|
-
|
|
86
|
-
// src/utils/upload.ts
|
|
87
176
|
var client = null;
|
|
88
|
-
var
|
|
89
|
-
|
|
90
|
-
|
|
177
|
+
var lastConfigHash = "";
|
|
178
|
+
function getConfigHash(config) {
|
|
179
|
+
return JSON.stringify([
|
|
180
|
+
config.accessKey,
|
|
181
|
+
config.accessSecret,
|
|
182
|
+
config.endpoint,
|
|
183
|
+
config.defaultBucket,
|
|
184
|
+
config.host,
|
|
185
|
+
config.protocol
|
|
186
|
+
]);
|
|
187
|
+
}
|
|
188
|
+
function validateConfig(config) {
|
|
189
|
+
return Boolean(
|
|
190
|
+
config.accessKey && config.accessSecret && config.endpoint && config.defaultBucket && config.host
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
function getClient() {
|
|
194
|
+
const config = nosConf.getConfig();
|
|
195
|
+
if (!validateConfig(config)) {
|
|
196
|
+
throw new Error("NOS \u914D\u7F6E\u4E0D\u5B8C\u6574\uFF0C\u8BF7\u5148\u914D\u7F6E accessKey, accessSecret, endpoint, defaultBucket, host");
|
|
91
197
|
}
|
|
198
|
+
const currentHash = getConfigHash(config);
|
|
199
|
+
if (!client || currentHash !== lastConfigHash) {
|
|
200
|
+
client = new NosClient(config);
|
|
201
|
+
lastConfigHash = currentHash;
|
|
202
|
+
}
|
|
203
|
+
return client;
|
|
204
|
+
}
|
|
205
|
+
var upload = async (file) => {
|
|
206
|
+
const { pathName, name } = file;
|
|
92
207
|
try {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
208
|
+
const nosClient = getClient();
|
|
209
|
+
await nosClient.putObject({
|
|
210
|
+
objectKey: name,
|
|
211
|
+
body: fs2.createReadStream(decodeURIComponent(pathName))
|
|
96
212
|
});
|
|
213
|
+
const config = nosConf.getConfig();
|
|
214
|
+
const fileUrl = `${config.endpoint}/${name}`;
|
|
215
|
+
return {
|
|
216
|
+
success: true,
|
|
217
|
+
url: fileUrl,
|
|
218
|
+
filePath: pathName
|
|
219
|
+
};
|
|
97
220
|
} catch (error) {
|
|
98
|
-
|
|
99
|
-
|
|
221
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown upload error";
|
|
222
|
+
log_default.error(`Upload failed for ${pathName}: ${errorMessage}`);
|
|
223
|
+
return {
|
|
224
|
+
success: false,
|
|
225
|
+
error: errorMessage,
|
|
226
|
+
filePath: pathName
|
|
227
|
+
};
|
|
100
228
|
}
|
|
101
|
-
const fileUrl = `${nosConf.getConfig().endpoint}/${file.name}`;
|
|
102
|
-
return fileUrl;
|
|
103
229
|
};
|
|
104
230
|
|
|
105
231
|
// src/app.ts
|
|
106
232
|
var handleUploadFile = async (filePaths) => {
|
|
107
|
-
const
|
|
233
|
+
const timestamp = Date.now();
|
|
234
|
+
const prefix = `nos-upload-cli/${timestamp}`;
|
|
235
|
+
const uploadPromises = filePaths.map(async (filePath) => {
|
|
108
236
|
if (!fs3.existsSync(filePath)) {
|
|
109
|
-
|
|
110
|
-
return
|
|
237
|
+
log.error(`\u6587\u4EF6\u8DEF\u5F84\u4E0D\u5B58\u5728: ${filePath}`);
|
|
238
|
+
return null;
|
|
111
239
|
}
|
|
112
|
-
const
|
|
240
|
+
const result = await upload({
|
|
113
241
|
pathName: filePath,
|
|
114
|
-
name:
|
|
242
|
+
name: `${prefix}/${path2.basename(filePath)}`
|
|
115
243
|
});
|
|
116
|
-
return
|
|
244
|
+
return result;
|
|
117
245
|
});
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
".": {
|
|
138
|
-
types: "./dist/index.d.ts",
|
|
139
|
-
require: "./dist/index.cjs",
|
|
140
|
-
import: "./dist/index.mjs"
|
|
141
|
-
}
|
|
142
|
-
},
|
|
143
|
-
main: "./dist/index.cjs",
|
|
144
|
-
module: "./dist/index.mjs",
|
|
145
|
-
types: "./dist/index.d.ts",
|
|
146
|
-
files: [
|
|
147
|
-
"dist",
|
|
148
|
-
"bin"
|
|
149
|
-
],
|
|
150
|
-
bin: {
|
|
151
|
-
"nos-upload": "./bin/index.js"
|
|
152
|
-
},
|
|
153
|
-
engines: {
|
|
154
|
-
node: ">=14.16"
|
|
155
|
-
},
|
|
156
|
-
keywords: [],
|
|
157
|
-
license: "MIT",
|
|
158
|
-
devDependencies: {
|
|
159
|
-
"@changesets/cli": "^2.24.4",
|
|
160
|
-
"@types/inquirer": "^9.0.1",
|
|
161
|
-
"@types/nconf": "^0.10.3",
|
|
162
|
-
"@types/node": "^18.7.14",
|
|
163
|
-
eslint: "^8.22.0",
|
|
164
|
-
"eslint-config-lofter": "^2.8.2",
|
|
165
|
-
tsup: "^6.2.2",
|
|
166
|
-
typescript: "^4.7.4",
|
|
167
|
-
vitest: "^0.22.0"
|
|
168
|
-
},
|
|
169
|
-
dependencies: {
|
|
170
|
-
"@nos-sdk/nos-node-sdk": "^0.2.6",
|
|
171
|
-
commander: "^9.4.0",
|
|
172
|
-
inquirer: "^9.1.1",
|
|
173
|
-
nconf: "^0.12.0"
|
|
246
|
+
const results = await Promise.all(uploadPromises);
|
|
247
|
+
const successfulUploads = results.filter(
|
|
248
|
+
(result) => result !== null && result.success
|
|
249
|
+
);
|
|
250
|
+
const failedUploads = results.filter(
|
|
251
|
+
(result) => result !== null && !result.success
|
|
252
|
+
);
|
|
253
|
+
if (successfulUploads.length > 0) {
|
|
254
|
+
console.log("\u4E0A\u4F20\u6210\u529F\uFF1A");
|
|
255
|
+
console.log(successfulUploads.map((r) => r.url).join("\n"));
|
|
256
|
+
}
|
|
257
|
+
if (failedUploads.length > 0) {
|
|
258
|
+
console.log("\n\u4E0A\u4F20\u5931\u8D25\uFF1A");
|
|
259
|
+
failedUploads.forEach((r) => {
|
|
260
|
+
console.log(` ${r.filePath}: ${r.error}`);
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
if (successfulUploads.length === 0 && failedUploads.length === 0) {
|
|
264
|
+
log.error("\u6CA1\u6709\u6587\u4EF6\u88AB\u4E0A\u4F20");
|
|
174
265
|
}
|
|
175
266
|
};
|
|
176
267
|
|
|
177
268
|
// src/index.ts
|
|
178
|
-
var
|
|
179
|
-
type: "input",
|
|
180
|
-
message: "\u8BF7\u8F93\u5165 NOS
|
|
181
|
-
name: "
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
message: "\u8BF7\u8F93\u5165 NOS secretKey",
|
|
186
|
-
name: "accessSecret"
|
|
187
|
-
};
|
|
188
|
-
var nosEndpointPrompt = {
|
|
189
|
-
type: "input",
|
|
190
|
-
message: "\u8BF7\u8F93\u5165 NOS domain",
|
|
191
|
-
name: "endpoint"
|
|
192
|
-
};
|
|
193
|
-
var nosBucketPrompt = {
|
|
194
|
-
type: "input",
|
|
195
|
-
message: "\u8BF7\u8F93\u5165 NOS defaultBucket",
|
|
196
|
-
name: "defaultBucket"
|
|
197
|
-
};
|
|
198
|
-
var nosHostPrompt = {
|
|
199
|
-
type: "input",
|
|
200
|
-
message: "\u8BF7\u8F93\u5165 NOS endPoint",
|
|
201
|
-
name: "host"
|
|
202
|
-
};
|
|
269
|
+
var promptConfigs = [
|
|
270
|
+
{ type: "input", message: "\u8BF7\u8F93\u5165 NOS accessId", name: "accessKey" },
|
|
271
|
+
{ type: "input", message: "\u8BF7\u8F93\u5165 NOS secretKey", name: "accessSecret" },
|
|
272
|
+
{ type: "input", message: "\u8BF7\u8F93\u5165 NOS domain", name: "endpoint" },
|
|
273
|
+
{ type: "input", message: "\u8BF7\u8F93\u5165 NOS defaultBucket", name: "defaultBucket" },
|
|
274
|
+
{ type: "input", message: "\u8BF7\u8F93\u5165 NOS endPoint", name: "host" }
|
|
275
|
+
];
|
|
203
276
|
async function init(filePaths) {
|
|
204
|
-
|
|
205
|
-
const promptList =
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
if (!nosConf.getConfig().accessSecret) {
|
|
210
|
-
promptList.push(nosSecPrompt);
|
|
211
|
-
}
|
|
212
|
-
if (!nosConf.getConfig().endpoint) {
|
|
213
|
-
promptList.push(nosEndpointPrompt);
|
|
214
|
-
}
|
|
215
|
-
if (!nosConf.getConfig().defaultBucket) {
|
|
216
|
-
promptList.push(nosBucketPrompt);
|
|
217
|
-
}
|
|
218
|
-
if (!nosConf.getConfig().host) {
|
|
219
|
-
promptList.push(nosHostPrompt);
|
|
220
|
-
}
|
|
221
|
-
if (promptList.length) {
|
|
277
|
+
const currentConfig = nosConf.getConfig();
|
|
278
|
+
const promptList = promptConfigs.filter(
|
|
279
|
+
(prompt) => !currentConfig[prompt.name]
|
|
280
|
+
);
|
|
281
|
+
if (promptList.length > 0) {
|
|
222
282
|
const answers = await inquirer.prompt(promptList);
|
|
223
|
-
nosConf.setConfig(
|
|
224
|
-
...answers,
|
|
225
|
-
protocol: ((_a = url.parse(
|
|
226
|
-
answers.endpoint || nosConf.getConfig().endpoint
|
|
227
|
-
).protocol) == null ? void 0 : _a.slice(0, -1)) || "http"
|
|
228
|
-
});
|
|
283
|
+
nosConf.setConfig(answers);
|
|
229
284
|
}
|
|
230
285
|
await handleUploadFile(filePaths);
|
|
231
286
|
}
|
|
232
|
-
|
|
233
|
-
|
|
287
|
+
var version = "0.2.0";
|
|
288
|
+
program.version(version).name("nos-upload").argument("<filePath...>", "\u4E0A\u4F20\u6587\u4EF6\u8DEF\u5F84\uFF0C\u53EF\u4EE5\u662F\u591A\u4E2A\u3001\u7A7A\u683C\u5206\u9694").action(async (filePaths) => {
|
|
289
|
+
if (filePaths && filePaths.length > 0) {
|
|
234
290
|
await init(filePaths);
|
|
235
291
|
} else {
|
|
236
|
-
|
|
292
|
+
log.error("\u8BF7\u8F93\u5165\u8981\u5904\u7406\u7684\u6587\u4EF6\u8DEF\u5F84");
|
|
237
293
|
}
|
|
238
294
|
});
|
|
239
295
|
program.parseAsync(process.argv);
|
|
296
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/app.ts","../../core/dist/index.js"],"sourcesContent":["import { program } from 'commander'\nimport inquirer from 'inquirer'\n\nimport { handleUploadFile } from './app.js'\nimport { nosConf, log } from '@nos-upload/core'\nimport type { NOSConfig } from '@nos-upload/core'\n\n// 输入提示配置\n// 注:输入提示的名字为文档展示的参数名,实际存储的参数名为 SDK 所需的参数名\nconst promptConfigs = [\n { type: 'input', message: '请输入 NOS accessId', name: 'accessKey' },\n { type: 'input', message: '请输入 NOS secretKey', name: 'accessSecret' },\n { type: 'input', message: '请输入 NOS domain', name: 'endpoint' },\n { type: 'input', message: '请输入 NOS defaultBucket', name: 'defaultBucket' },\n { type: 'input', message: '请输入 NOS endPoint', name: 'host' },\n] as const\n\n/**\n * 初始化配置并上传文件\n */\nasync function init(filePaths: string[]): Promise<void> {\n // 缓存配置,避免重复调用 getConfig()\n const currentConfig = nosConf.getConfig()\n\n // 检查缺失的配置项\n const promptList = promptConfigs.filter(\n prompt => !currentConfig[prompt.name as keyof NOSConfig]\n )\n\n if (promptList.length > 0) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const answers = await inquirer.prompt(promptList as any)\n // 通过手动输入来更新配置\n // 注:protocol 解析逻辑已移至 core 模块的 setConfig 中自动处理\n nosConf.setConfig(answers)\n }\n\n // 文件上传\n await handleUploadFile(filePaths)\n}\n\n// 读取版本号\nconst version = '0.2.0'\n\nprogram\n .version(version)\n .name('nos-upload')\n .argument('<filePath...>', '上传文件路径,可以是多个、空格分隔')\n .action(async (filePaths: string[]) => {\n if (filePaths && filePaths.length > 0) {\n await init(filePaths)\n } else {\n log.error('请输入要处理的文件路径')\n }\n })\n\nprogram.parseAsync(process.argv)\n","import fs from 'fs'\nimport path from 'path'\nimport { upload, log } from '@nos-upload/core'\nimport type { UploadResult } from '@nos-upload/core'\n\n/**\n * 处理文件上传\n */\nexport const handleUploadFile = async (filePaths: string[]): Promise<void> => {\n // 提取时间戳到循环外,保证同批次文件使用相同时间戳\n const timestamp = Date.now()\n const prefix = `nos-upload-cli/${timestamp}`\n\n const uploadPromises = filePaths.map(async (filePath): Promise<UploadResult | null> => {\n // 检查文件是否存在\n if (!fs.existsSync(filePath)) {\n log.error(`文件路径不存在: ${filePath}`)\n return null\n }\n\n const result = await upload({\n pathName: filePath,\n name: `${prefix}/${path.basename(filePath)}`,\n })\n\n return result\n })\n\n const results = await Promise.all(uploadPromises)\n\n // 过滤空结果和失败的上传\n const successfulUploads = results.filter(\n (result): result is UploadResult => result !== null && result.success\n )\n const failedUploads = results.filter(\n (result): result is UploadResult => result !== null && !result.success\n )\n\n // 输出结果\n if (successfulUploads.length > 0) {\n console.log('上传成功:')\n console.log(successfulUploads.map(r => r.url).join('\\n'))\n }\n\n if (failedUploads.length > 0) {\n console.log('\\n上传失败:')\n failedUploads.forEach(r => {\n console.log(` ${r.filePath}: ${r.error}`)\n })\n }\n\n if (successfulUploads.length === 0 && failedUploads.length === 0) {\n log.error('没有文件被上传')\n }\n}\n","// src/config.ts\nimport nconf from \"nconf\";\nimport path from \"path\";\nimport fs from \"fs\";\nimport os from \"os\";\nimport url from \"url\";\n\n// src/log.ts\nvar log = {\n log: (message) => {\n console.log(message);\n },\n error: (message) => {\n console.error(message);\n },\n warn: (message) => {\n console.warn(message);\n },\n info: (message) => {\n console.info(message);\n }\n};\nvar log_default = log;\n\n// src/config.ts\nvar NOS_CONF_PATH = path.resolve(os.homedir(), \".nos-conf\", \"config.json\");\nvar ENV_KEY_MAP = {\n \"NOS_ACCESS_KEY\": \"accessKey\",\n \"NOS_ACCESS_SECRET\": \"accessSecret\",\n \"NOS_ENDPOINT\": \"endpoint\",\n \"NOS_DEFAULT_BUCKET\": \"defaultBucket\",\n \"NOS_HOST\": \"host\",\n \"NOS_PROTOCOL\": \"protocol\"\n};\nvar REQUIRED_KEYS = [\"accessKey\", \"accessSecret\", \"endpoint\", \"defaultBucket\", \"host\"];\nvar SENSITIVE_KEYS = [\"accessKey\", \"accessSecret\"];\nfunction maskValue(value, key) {\n if (!value) return \"\";\n if (SENSITIVE_KEYS.includes(key)) {\n if (value.length <= 4) return \"****\";\n return value.slice(0, 2) + \"***\" + value.slice(-2);\n }\n return value;\n}\nvar NOSConf = class _NOSConf {\n constructor() {\n this.nconfInstance = nconf;\n this.nconfInstance.env({\n separator: \"__\",\n match: /^NOS_/,\n transform: (obj) => {\n const newKey = ENV_KEY_MAP[obj.key];\n if (newKey) {\n return { key: newKey, value: obj.value };\n }\n return false;\n }\n }).file({ file: NOS_CONF_PATH });\n _NOSConf.ensureConfigDir();\n }\n /**\n * 确保配置目录存在(同步方式,避免竞态)\n */\n static ensureConfigDir() {\n const dirPath = path.dirname(NOS_CONF_PATH);\n try {\n fs.mkdirSync(dirPath, { recursive: true });\n } catch (err) {\n log_default.error(\"\\u521D\\u59CB\\u5316\\u914D\\u7F6E\\u76EE\\u5F55\\u5931\\u8D25\");\n }\n }\n /**\n * 获取配置\n */\n getConfig() {\n return {\n accessKey: this.nconfInstance.get(\"accessKey\"),\n accessSecret: this.nconfInstance.get(\"accessSecret\"),\n endpoint: this.nconfInstance.get(\"endpoint\"),\n defaultBucket: this.nconfInstance.get(\"defaultBucket\"),\n host: this.nconfInstance.get(\"host\"),\n protocol: this.nconfInstance.get(\"protocol\")\n };\n }\n /**\n * 设置配置(简化版,自动处理 protocol)\n */\n setConfig(config) {\n const validKeys = [\"accessKey\", \"accessSecret\", \"endpoint\", \"defaultBucket\", \"host\", \"protocol\"];\n for (const [key, value] of Object.entries(config)) {\n if (validKeys.includes(key) && value) {\n this.nconfInstance.set(key, value);\n }\n }\n if (config.endpoint && !config.protocol) {\n const parsedUrl = url.parse(config.endpoint);\n const protocol = parsedUrl.protocol?.slice(0, -1) || \"http\";\n this.nconfInstance.set(\"protocol\", protocol);\n }\n this.nconfInstance.save(void 0);\n }\n /**\n * 重置配置\n */\n reset() {\n this.nconfInstance.reset();\n this.nconfInstance.save(void 0);\n }\n /**\n * 获取配置状态(脱敏输出)\n */\n getConfigStatus() {\n const config = this.getConfig();\n const items = [];\n const missingKeys = [];\n for (const key of REQUIRED_KEYS) {\n const value = config[key];\n const isSet = !!value;\n if (!isSet) {\n missingKeys.push(key);\n }\n let source;\n const envKey = Object.entries(ENV_KEY_MAP).find(([, v]) => v === key)?.[0];\n if (envKey && process.env[envKey]) {\n source = \"env\";\n } else if (isSet) {\n source = \"file\";\n }\n items.push({\n key,\n isSet,\n source,\n preview: isSet ? maskValue(value, key) : void 0\n });\n }\n return {\n isComplete: missingKeys.length === 0,\n missingKeys,\n items\n };\n }\n /**\n * 验证配置完整性\n */\n validateConfig() {\n const config = this.getConfig();\n const missingKeys = [];\n for (const key of REQUIRED_KEYS) {\n if (!config[key]) {\n missingKeys.push(key);\n }\n }\n if (missingKeys.length === 0) {\n return {\n valid: true,\n missingKeys: [],\n message: \"Configuration is complete\"\n };\n }\n return {\n valid: false,\n missingKeys,\n message: `Missing required config: ${missingKeys.join(\", \")}`\n };\n }\n};\nvar nosConf = new NOSConf();\n\n// src/upload.ts\nimport fs2 from \"fs\";\nimport { NosClient } from \"@nos-sdk/nos-node-sdk\";\nvar client = null;\nvar lastConfigHash = \"\";\nfunction getConfigHash(config) {\n return JSON.stringify([\n config.accessKey,\n config.accessSecret,\n config.endpoint,\n config.defaultBucket,\n config.host,\n config.protocol\n ]);\n}\nfunction validateConfig(config) {\n return Boolean(\n config.accessKey && config.accessSecret && config.endpoint && config.defaultBucket && config.host\n );\n}\nfunction getClient() {\n const config = nosConf.getConfig();\n if (!validateConfig(config)) {\n throw new Error(\"NOS \\u914D\\u7F6E\\u4E0D\\u5B8C\\u6574\\uFF0C\\u8BF7\\u5148\\u914D\\u7F6E accessKey, accessSecret, endpoint, defaultBucket, host\");\n }\n const currentHash = getConfigHash(config);\n if (!client || currentHash !== lastConfigHash) {\n client = new NosClient(config);\n lastConfigHash = currentHash;\n }\n return client;\n}\nvar upload = async (file) => {\n const { pathName, name } = file;\n try {\n const nosClient = getClient();\n await nosClient.putObject({\n objectKey: name,\n body: fs2.createReadStream(decodeURIComponent(pathName))\n });\n const config = nosConf.getConfig();\n const fileUrl = `${config.endpoint}/${name}`;\n return {\n success: true,\n url: fileUrl,\n filePath: pathName\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : \"Unknown upload error\";\n log_default.error(`Upload failed for ${pathName}: ${errorMessage}`);\n return {\n success: false,\n error: errorMessage,\n filePath: pathName\n };\n }\n};\nvar uploadBatch = async (files) => {\n const results = await Promise.all(files.map((file) => upload(file)));\n return results;\n};\nexport {\n NOSConf,\n log,\n log_default as logDefault,\n nosConf,\n upload,\n uploadBatch\n};\n"],"mappings":"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","names":["fs","path","fs","path"]}
|
package/package.json
CHANGED
|
@@ -1,52 +1,54 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nos-upload-cli",
|
|
3
|
+
"version": "0.2.0",
|
|
3
4
|
"type": "module",
|
|
4
|
-
"
|
|
5
|
-
"description": "",
|
|
5
|
+
"description": "CLI tool to upload files to NOS (Netease Object Storage)",
|
|
6
6
|
"author": "liushichuan <hzliushichuan@corp.netease.com>",
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/nicepkg/nos-upload-cli.git",
|
|
11
|
+
"directory": "packages/cli"
|
|
12
12
|
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"nos",
|
|
15
|
+
"netease",
|
|
16
|
+
"object-storage",
|
|
17
|
+
"upload",
|
|
18
|
+
"cli"
|
|
19
|
+
],
|
|
13
20
|
"exports": {
|
|
14
21
|
".": {
|
|
15
22
|
"types": "./dist/index.d.ts",
|
|
16
|
-
"
|
|
17
|
-
"import": "./dist/index.mjs"
|
|
23
|
+
"import": "./dist/index.js"
|
|
18
24
|
}
|
|
19
25
|
},
|
|
20
|
-
"main": "./dist/index.
|
|
21
|
-
"module": "./dist/index.mjs",
|
|
26
|
+
"main": "./dist/index.js",
|
|
22
27
|
"types": "./dist/index.d.ts",
|
|
23
|
-
"files": [
|
|
24
|
-
"dist",
|
|
25
|
-
"bin"
|
|
26
|
-
],
|
|
27
28
|
"bin": {
|
|
28
|
-
"nos-upload": "./
|
|
29
|
+
"nos-upload": "./dist/index.js"
|
|
29
30
|
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist"
|
|
33
|
+
],
|
|
30
34
|
"engines": {
|
|
31
|
-
"node": ">=
|
|
32
|
-
},
|
|
33
|
-
"keywords": [],
|
|
34
|
-
"license": "MIT",
|
|
35
|
-
"devDependencies": {
|
|
36
|
-
"@changesets/cli": "^2.24.4",
|
|
37
|
-
"@types/inquirer": "^9.0.1",
|
|
38
|
-
"@types/nconf": "^0.10.3",
|
|
39
|
-
"@types/node": "^18.7.14",
|
|
40
|
-
"eslint": "^8.22.0",
|
|
41
|
-
"eslint-config-lofter": "^2.8.2",
|
|
42
|
-
"tsup": "^6.2.2",
|
|
43
|
-
"typescript": "^4.7.4",
|
|
44
|
-
"vitest": "^0.22.0"
|
|
35
|
+
"node": ">=18"
|
|
45
36
|
},
|
|
46
37
|
"dependencies": {
|
|
47
38
|
"@nos-sdk/nos-node-sdk": "^0.2.6",
|
|
48
39
|
"commander": "^9.4.0",
|
|
49
40
|
"inquirer": "^9.1.1",
|
|
50
41
|
"nconf": "^0.12.0"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/inquirer": "^9.0.1",
|
|
45
|
+
"@types/nconf": "^0.10.3",
|
|
46
|
+
"tsup": "^8.0.0",
|
|
47
|
+
"@nos-upload/core": "0.2.0"
|
|
48
|
+
},
|
|
49
|
+
"scripts": {
|
|
50
|
+
"build": "tsup",
|
|
51
|
+
"dev": "tsup --watch",
|
|
52
|
+
"clean": "rm -rf dist"
|
|
51
53
|
}
|
|
52
|
-
}
|
|
54
|
+
}
|
package/bin/index.js
DELETED
package/dist/index.cjs
DELETED
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __copyProps = (to, from, except, desc) => {
|
|
9
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
-
for (let key of __getOwnPropNames(from))
|
|
11
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
12
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
13
|
-
}
|
|
14
|
-
return to;
|
|
15
|
-
};
|
|
16
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
17
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
18
|
-
mod
|
|
19
|
-
));
|
|
20
|
-
|
|
21
|
-
// src/index.ts
|
|
22
|
-
var import_commander = require("commander");
|
|
23
|
-
var import_inquirer = __toESM(require("inquirer"), 1);
|
|
24
|
-
var import_url = __toESM(require("url"), 1);
|
|
25
|
-
|
|
26
|
-
// src/app.ts
|
|
27
|
-
var import_fs3 = __toESM(require("fs"), 1);
|
|
28
|
-
var import_path2 = __toESM(require("path"), 1);
|
|
29
|
-
|
|
30
|
-
// src/utils/upload.ts
|
|
31
|
-
var import_fs2 = __toESM(require("fs"), 1);
|
|
32
|
-
var import_nos_node_sdk = require("@nos-sdk/nos-node-sdk");
|
|
33
|
-
|
|
34
|
-
// src/utils/config.ts
|
|
35
|
-
var import_nconf = __toESM(require("nconf"), 1);
|
|
36
|
-
var import_path = __toESM(require("path"), 1);
|
|
37
|
-
var import_fs = __toESM(require("fs"), 1);
|
|
38
|
-
var import_os = __toESM(require("os"), 1);
|
|
39
|
-
|
|
40
|
-
// src/utils/log.ts
|
|
41
|
-
var log_default = {
|
|
42
|
-
log: (message) => {
|
|
43
|
-
console.log(message);
|
|
44
|
-
},
|
|
45
|
-
error: (message) => {
|
|
46
|
-
console.log(message);
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
// src/utils/config.ts
|
|
51
|
-
var NOS_CONF_PATH = import_path.default.resolve(import_os.default.homedir(), ".nos-conf", "config.json");
|
|
52
|
-
var NOSConf = class {
|
|
53
|
-
constructor() {
|
|
54
|
-
this.nconf = import_nconf.default;
|
|
55
|
-
this.nconf.env().file({ file: NOS_CONF_PATH });
|
|
56
|
-
NOSConf.init();
|
|
57
|
-
}
|
|
58
|
-
static init() {
|
|
59
|
-
const dirPath = import_path.default.dirname(NOS_CONF_PATH);
|
|
60
|
-
import_fs.default.mkdir(dirPath, {
|
|
61
|
-
recursive: true
|
|
62
|
-
}, (err) => {
|
|
63
|
-
if (err) {
|
|
64
|
-
log_default.error("\u521D\u59CB\u5316\u914D\u7F6E\u5931\u8D25");
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
getConfig() {
|
|
69
|
-
return {
|
|
70
|
-
accessKey: this.nconf.get("accessKey"),
|
|
71
|
-
accessSecret: this.nconf.get("accessSecret"),
|
|
72
|
-
endpoint: this.nconf.get("endpoint"),
|
|
73
|
-
defaultBucket: this.nconf.get("defaultBucket"),
|
|
74
|
-
host: this.nconf.get("host"),
|
|
75
|
-
protocol: this.nconf.get("protocol")
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
setConfig(config) {
|
|
79
|
-
if (config.accessKey) {
|
|
80
|
-
this.nconf.set("accessKey", config.accessKey);
|
|
81
|
-
}
|
|
82
|
-
if (config.accessSecret) {
|
|
83
|
-
this.nconf.set("accessSecret", config.accessSecret);
|
|
84
|
-
}
|
|
85
|
-
if (config.endpoint) {
|
|
86
|
-
this.nconf.set("endpoint", config.endpoint);
|
|
87
|
-
}
|
|
88
|
-
if (config.defaultBucket) {
|
|
89
|
-
this.nconf.set("defaultBucket", config.defaultBucket);
|
|
90
|
-
}
|
|
91
|
-
if (config.host) {
|
|
92
|
-
this.nconf.set("host", config.host);
|
|
93
|
-
}
|
|
94
|
-
if (config.protocol) {
|
|
95
|
-
this.nconf.set("protocol", config.protocol);
|
|
96
|
-
}
|
|
97
|
-
this.nconf.save(void 0);
|
|
98
|
-
}
|
|
99
|
-
reset() {
|
|
100
|
-
this.nconf.reset();
|
|
101
|
-
this.nconf.save(void 0);
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
var nosConf = new NOSConf();
|
|
105
|
-
|
|
106
|
-
// src/utils/upload.ts
|
|
107
|
-
var client = null;
|
|
108
|
-
var upload = async (file) => {
|
|
109
|
-
if (!client) {
|
|
110
|
-
client = new import_nos_node_sdk.NosClient(nosConf.getConfig());
|
|
111
|
-
}
|
|
112
|
-
try {
|
|
113
|
-
await client.putObject({
|
|
114
|
-
objectKey: file.name,
|
|
115
|
-
body: import_fs2.default.createReadStream(decodeURIComponent(file.pathName))
|
|
116
|
-
});
|
|
117
|
-
} catch (error) {
|
|
118
|
-
console.log("Upload failed:", error);
|
|
119
|
-
return "";
|
|
120
|
-
}
|
|
121
|
-
const fileUrl = `${nosConf.getConfig().endpoint}/${file.name}`;
|
|
122
|
-
return fileUrl;
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
// src/app.ts
|
|
126
|
-
var handleUploadFile = async (filePaths) => {
|
|
127
|
-
const fileUploadPromise = filePaths.map(async (filePath) => {
|
|
128
|
-
if (!import_fs3.default.existsSync(filePath)) {
|
|
129
|
-
log_default.error("\u6587\u4EF6\u8DEF\u5F84\u4E0D\u5B58\u5728");
|
|
130
|
-
return "";
|
|
131
|
-
}
|
|
132
|
-
const url2 = await upload({
|
|
133
|
-
pathName: filePath,
|
|
134
|
-
name: `nos-upload-cli/${new Date().getTime()}/${import_path2.default.basename(filePath)}`
|
|
135
|
-
});
|
|
136
|
-
return url2;
|
|
137
|
-
});
|
|
138
|
-
const uploadedUrls = await Promise.all(fileUploadPromise);
|
|
139
|
-
console.log("\u4E0A\u4F20\u6210\u529F\uFF1A");
|
|
140
|
-
console.log(uploadedUrls.join("\n"));
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
// package.json
|
|
144
|
-
var package_default = {
|
|
145
|
-
name: "nos-upload-cli",
|
|
146
|
-
type: "module",
|
|
147
|
-
version: "0.1.0",
|
|
148
|
-
description: "",
|
|
149
|
-
author: "liushichuan <hzliushichuan@corp.netease.com>",
|
|
150
|
-
sideEffects: false,
|
|
151
|
-
scripts: {
|
|
152
|
-
"build-fast": "tsup src/index.ts --format cjs,esm",
|
|
153
|
-
build: "pnpm run build-fast --dts-resolve",
|
|
154
|
-
prepublishOnly: "pnpm run build"
|
|
155
|
-
},
|
|
156
|
-
exports: {
|
|
157
|
-
".": {
|
|
158
|
-
types: "./dist/index.d.ts",
|
|
159
|
-
require: "./dist/index.cjs",
|
|
160
|
-
import: "./dist/index.mjs"
|
|
161
|
-
}
|
|
162
|
-
},
|
|
163
|
-
main: "./dist/index.cjs",
|
|
164
|
-
module: "./dist/index.mjs",
|
|
165
|
-
types: "./dist/index.d.ts",
|
|
166
|
-
files: [
|
|
167
|
-
"dist",
|
|
168
|
-
"bin"
|
|
169
|
-
],
|
|
170
|
-
bin: {
|
|
171
|
-
"nos-upload": "./bin/index.js"
|
|
172
|
-
},
|
|
173
|
-
engines: {
|
|
174
|
-
node: ">=14.16"
|
|
175
|
-
},
|
|
176
|
-
keywords: [],
|
|
177
|
-
license: "MIT",
|
|
178
|
-
devDependencies: {
|
|
179
|
-
"@changesets/cli": "^2.24.4",
|
|
180
|
-
"@types/inquirer": "^9.0.1",
|
|
181
|
-
"@types/nconf": "^0.10.3",
|
|
182
|
-
"@types/node": "^18.7.14",
|
|
183
|
-
eslint: "^8.22.0",
|
|
184
|
-
"eslint-config-lofter": "^2.8.2",
|
|
185
|
-
tsup: "^6.2.2",
|
|
186
|
-
typescript: "^4.7.4",
|
|
187
|
-
vitest: "^0.22.0"
|
|
188
|
-
},
|
|
189
|
-
dependencies: {
|
|
190
|
-
"@nos-sdk/nos-node-sdk": "^0.2.6",
|
|
191
|
-
commander: "^9.4.0",
|
|
192
|
-
inquirer: "^9.1.1",
|
|
193
|
-
nconf: "^0.12.0"
|
|
194
|
-
}
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
// src/index.ts
|
|
198
|
-
var nosKeyPrompt = {
|
|
199
|
-
type: "input",
|
|
200
|
-
message: "\u8BF7\u8F93\u5165 NOS accessId",
|
|
201
|
-
name: "accessKey"
|
|
202
|
-
};
|
|
203
|
-
var nosSecPrompt = {
|
|
204
|
-
type: "input",
|
|
205
|
-
message: "\u8BF7\u8F93\u5165 NOS secretKey",
|
|
206
|
-
name: "accessSecret"
|
|
207
|
-
};
|
|
208
|
-
var nosEndpointPrompt = {
|
|
209
|
-
type: "input",
|
|
210
|
-
message: "\u8BF7\u8F93\u5165 NOS domain",
|
|
211
|
-
name: "endpoint"
|
|
212
|
-
};
|
|
213
|
-
var nosBucketPrompt = {
|
|
214
|
-
type: "input",
|
|
215
|
-
message: "\u8BF7\u8F93\u5165 NOS defaultBucket",
|
|
216
|
-
name: "defaultBucket"
|
|
217
|
-
};
|
|
218
|
-
var nosHostPrompt = {
|
|
219
|
-
type: "input",
|
|
220
|
-
message: "\u8BF7\u8F93\u5165 NOS endPoint",
|
|
221
|
-
name: "host"
|
|
222
|
-
};
|
|
223
|
-
async function init(filePaths) {
|
|
224
|
-
var _a;
|
|
225
|
-
const promptList = [];
|
|
226
|
-
if (!nosConf.getConfig().accessKey) {
|
|
227
|
-
promptList.push(nosKeyPrompt);
|
|
228
|
-
}
|
|
229
|
-
if (!nosConf.getConfig().accessSecret) {
|
|
230
|
-
promptList.push(nosSecPrompt);
|
|
231
|
-
}
|
|
232
|
-
if (!nosConf.getConfig().endpoint) {
|
|
233
|
-
promptList.push(nosEndpointPrompt);
|
|
234
|
-
}
|
|
235
|
-
if (!nosConf.getConfig().defaultBucket) {
|
|
236
|
-
promptList.push(nosBucketPrompt);
|
|
237
|
-
}
|
|
238
|
-
if (!nosConf.getConfig().host) {
|
|
239
|
-
promptList.push(nosHostPrompt);
|
|
240
|
-
}
|
|
241
|
-
if (promptList.length) {
|
|
242
|
-
const answers = await import_inquirer.default.prompt(promptList);
|
|
243
|
-
nosConf.setConfig({
|
|
244
|
-
...answers,
|
|
245
|
-
protocol: ((_a = import_url.default.parse(
|
|
246
|
-
answers.endpoint || nosConf.getConfig().endpoint
|
|
247
|
-
).protocol) == null ? void 0 : _a.slice(0, -1)) || "http"
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
await handleUploadFile(filePaths);
|
|
251
|
-
}
|
|
252
|
-
import_commander.program.version(package_default.version ?? "0.0.1").name("nos-upload").argument("<filePath...>", "\u4E0A\u4F20\u6587\u4EF6\u8DEF\u5F84\uFF0C\u53EF\u4EE5\u662F\u591A\u4E2A\u3001\u7A7A\u683C\u5206\u9694").action(async (filePaths) => {
|
|
253
|
-
if (filePaths) {
|
|
254
|
-
await init(filePaths);
|
|
255
|
-
} else {
|
|
256
|
-
log_default.error("\u8BF7\u8F93\u5165\u8981\u5904\u7406\u7684\u6587\u4EF6\u8DEF\u5F84");
|
|
257
|
-
}
|
|
258
|
-
});
|
|
259
|
-
import_commander.program.parseAsync(process.argv);
|
package/readme.md
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
## nos-upload-cli
|
|
2
|
-
|
|
3
|
-
使用本地存储的nos config上传指定文件
|
|
4
|
-
|
|
5
|
-
代码结构借鉴了[lofter-md](https://g.hz.netease.com/lofter-group/frontend/lofter-md)
|
|
6
|
-
|
|
7
|
-
## 安装
|
|
8
|
-
```bash
|
|
9
|
-
npm i nos-upload-cli -g
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
## 使用方式
|
|
13
|
-
```bash
|
|
14
|
-
nos-upload <input-file-1> <input-file-2> <input-file-...>
|
|
15
|
-
```
|
|
16
|
-
- 与`lofter-md`共用Nos config的配置存储位置
|
|
17
|
-
- 首次使用会要求输入Nos config的配置
|
|
18
|
-
- 上传完成的文件地址将会输出在控制台
|
|
19
|
-
```bash
|
|
20
|
-
上传成功:
|
|
21
|
-
https://lofter.lf127.net/nos-upload-cli/1665459290761/xxx.js
|
|
22
|
-
https://lofter.lf127.net/nos-upload-cli/1665459290780/xxx.png
|
|
23
|
-
```
|
|
24
|
-
输出上述上传成功格式是为了适配`Typora`编辑器的自动上传图片功能所需输出格式,如有需要,可以增加`Command`的`Option`,自定义其他输出格式
|