cloud-function-cli 1.1.2 → 1.1.3

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.
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.filesDelete = exports.filesDownload = exports.filesList = exports.filesUpload = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const form_data_1 = __importDefault(require("form-data"));
10
+ const apiClient_1 = require("../services/apiClient");
11
+ const logger_1 = require("../utils/logger");
12
+ const filesUpload = async (filePaths, options) => {
13
+ const resolvedFiles = filePaths
14
+ .map((p) => path_1.default.resolve(process.cwd(), p))
15
+ .filter((p) => fs_1.default.existsSync(p) && fs_1.default.statSync(p).isFile());
16
+ if (resolvedFiles.length === 0) {
17
+ logger_1.logger.error('No valid files to upload');
18
+ return;
19
+ }
20
+ const form = new form_data_1.default();
21
+ if (options.path)
22
+ form.append('path', options.path);
23
+ resolvedFiles.forEach((p) => {
24
+ form.append('file', fs_1.default.createReadStream(p), { filename: path_1.default.basename(p) });
25
+ });
26
+ try {
27
+ const res = await apiClient_1.apiClient.postRaw('/api/management/files/upload', form, {
28
+ headers: form.getHeaders()
29
+ });
30
+ const items = Array.isArray(res.data?.items) ? res.data.items : [];
31
+ logger_1.logger.success(`Uploaded ${items.length || resolvedFiles.length} file(s)`);
32
+ items.forEach((it) => logger_1.logger.info(` ${it.filename} -> ${it.fileId}`));
33
+ }
34
+ catch (error) {
35
+ logger_1.logger.error(`Upload failed: ${error.response?.data?.error || error.message}`);
36
+ }
37
+ };
38
+ exports.filesUpload = filesUpload;
39
+ const filesList = async (options) => {
40
+ const page = options.page ? Number(options.page) : 1;
41
+ const limit = options.limit ? Number(options.limit) : 20;
42
+ try {
43
+ const res = await apiClient_1.apiClient.get('/api/management/files/list', {
44
+ page,
45
+ limit,
46
+ pathPrefix: options.pathPrefix
47
+ });
48
+ const items = Array.isArray(res.data?.items) ? res.data.items : [];
49
+ if (items.length === 0) {
50
+ logger_1.logger.info('No files found');
51
+ return;
52
+ }
53
+ items.forEach((it) => {
54
+ const id = it?._id?.toString ? it._id.toString() : String(it?._id || '');
55
+ logger_1.logger.info(`${id} ${String(it?.filename || '')}`);
56
+ });
57
+ }
58
+ catch (error) {
59
+ logger_1.logger.error(`List failed: ${error.response?.data?.error || error.message}`);
60
+ }
61
+ };
62
+ exports.filesList = filesList;
63
+ const filesDownload = async (fileId, output) => {
64
+ const safeId = encodeURIComponent(fileId);
65
+ try {
66
+ const res = await apiClient_1.apiClient.getRaw(`/api/management/files/download/${safeId}`, {
67
+ responseType: 'stream'
68
+ });
69
+ const contentDisposition = String(res.headers?.['content-disposition'] || '');
70
+ const filename = parseFilenameFromContentDisposition(contentDisposition) || `${fileId}.bin`;
71
+ const target = output ? path_1.default.resolve(process.cwd(), output) : path_1.default.resolve(process.cwd(), filename);
72
+ await new Promise((resolve, reject) => {
73
+ const writer = fs_1.default.createWriteStream(target);
74
+ res.data.pipe(writer);
75
+ writer.on('finish', () => resolve());
76
+ writer.on('error', reject);
77
+ });
78
+ logger_1.logger.success(`Saved to ${target}`);
79
+ }
80
+ catch (error) {
81
+ logger_1.logger.error(`Download failed: ${error.response?.data?.error || error.message}`);
82
+ }
83
+ };
84
+ exports.filesDownload = filesDownload;
85
+ const filesDelete = async (fileId) => {
86
+ const safeId = encodeURIComponent(fileId);
87
+ try {
88
+ await apiClient_1.apiClient.delete(`/api/management/files/${safeId}`);
89
+ logger_1.logger.success('Deleted');
90
+ }
91
+ catch (error) {
92
+ logger_1.logger.error(`Delete failed: ${error.response?.data?.error || error.message}`);
93
+ }
94
+ };
95
+ exports.filesDelete = filesDelete;
96
+ const parseFilenameFromContentDisposition = (value) => {
97
+ const m = value.match(/filename\*\s*=\s*UTF-8''([^;]+)/i);
98
+ if (m && m[1]) {
99
+ try {
100
+ return decodeURIComponent(m[1]);
101
+ }
102
+ catch {
103
+ return m[1];
104
+ }
105
+ }
106
+ const m2 = value.match(/filename\s*=\s*"?([^"]+)"?/i);
107
+ return m2?.[1] ? m2[1] : '';
108
+ };
package/dist/index.js CHANGED
@@ -9,6 +9,7 @@ const get_1 = require("./cli/get");
9
9
  const history_1 = require("./cli/history");
10
10
  const rollback_1 = require("./cli/rollback");
11
11
  const list_1 = require("./cli/list");
12
+ const files_1 = require("./cli/files");
12
13
  const program = new commander_1.Command();
13
14
  program
14
15
  .name('cf')
@@ -48,4 +49,25 @@ program
48
49
  .description('List groups or APIs in a group')
49
50
  .option('-e, --env <env>', 'Environment (dev/prod)')
50
51
  .action(list_1.list);
52
+ const files = program.command('files').description('Manage uploaded files');
53
+ files
54
+ .command('upload <paths...>')
55
+ .description('Upload file(s) to server (management files)')
56
+ .option('-p, --path <path>', 'Remote path/folder (metadata.path)')
57
+ .action((paths, options) => (0, files_1.filesUpload)(paths, options));
58
+ files
59
+ .command('list')
60
+ .description('List uploaded files')
61
+ .option('--page <page>', 'Page number', '1')
62
+ .option('--limit <limit>', 'Page size', '20')
63
+ .option('--pathPrefix <pathPrefix>', 'Filter by path prefix (metadata.path)')
64
+ .action((options) => (0, files_1.filesList)(options));
65
+ files
66
+ .command('download <fileId> [output]')
67
+ .description('Download a file by fileId')
68
+ .action((fileId, output) => (0, files_1.filesDownload)(fileId, output));
69
+ files
70
+ .command('delete <fileId>')
71
+ .description('Delete a file by fileId')
72
+ .action((fileId) => (0, files_1.filesDelete)(fileId));
51
73
  program.parse(process.argv);
@@ -30,7 +30,9 @@ const getClient = () => {
30
30
  };
31
31
  exports.apiClient = {
32
32
  get: (url, params) => getClient().get(url, { params }),
33
+ getRaw: (url, config) => getClient().get(url, config),
33
34
  post: (url, data) => getClient().post(url, data),
35
+ postRaw: (url, data, config) => getClient().post(url, data, config),
34
36
  put: (url, data) => getClient().put(url, data),
35
37
  delete: (url) => getClient().delete(url)
36
38
  };
@@ -2,10 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.apiTemplate = void 0;
4
4
  exports.apiTemplate = `async function handler(context) {
5
- const { log, cacher, options, utils, mongo, http, https, request, response } = context
5
+ const { request, utils } = context
6
6
 
7
- let query = request.query
8
- let data = request.body
7
+ const query = request.query
8
+ const data = request.body
9
+ const uploadResult = await utils.files.handleUploadToGridFS(context, { path: 'uploads/', take: 1 })
10
+ if (uploadResult) return uploadResult
9
11
 
10
12
  return { code: 1, data: data || query }
11
13
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cloud-function-cli",
3
- "version": "1.1.2",
3
+ "version": "1.1.3",
4
4
  "description": "CLI for Cloud Function System - Create, deploy, and manage serverless functions",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -50,6 +50,7 @@
50
50
  "chalk": "^4.1.2",
51
51
  "commander": "^11.1.0",
52
52
  "dotenv": "^16.4.1",
53
+ "form-data": "^4.0.4",
53
54
  "inquirer": "^8.2.6"
54
55
  },
55
56
  "devDependencies": {