• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

coderaiser / cloudcmd / 26420142854

25 May 2026 09:17PM UTC coverage: 48.74% (-17.2%) from 65.962%
26420142854

push

github

coderaiser
feature: cloudcmd: rate limit: add support (#437)

320 of 424 branches covered (75.47%)

14 of 14 new or added lines in 2 files covered. (100.0%)

1481 existing lines in 47 files now uncovered.

3734 of 7661 relevant lines covered (48.74%)

1075.07 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.95
/common/cloudfunc.js
1
import {rendy} from 'rendy';
9✔
2
import currify from 'currify';
9✔
3
import {fullstore} from 'fullstore';
9✔
4
import {encode} from '#common/entity';
9✔
5

9✔
6
const id = (a) => a;
9✔
7
const NAME = 'Cloud Commander';
9✔
8

9✔
9
export const dateFormatter = fullstore(id);
9✔
10
export const getHeaderField = currify(_getHeaderField);
9✔
11
export const FS = '/fs';
9✔
12

9✔
13
const Path = fullstore();
9✔
14

9✔
15
Path('/');
9✔
16

9✔
17
const filterOutDotFiles = ({showDotFiles}) => ({name}) => {
9✔
18
    if (showDotFiles)
81,000✔
19
        return true;
81,000✔
UNCOV
20
    
×
UNCOV
21
    return !name.startsWith('.');
×
22
};
9✔
23

9✔
24
export const apiURL = '/api/v1';
9✔
25
export const MAX_FILE_SIZE = 500 * 1024;
9✔
26

9✔
27
export const formatMsg = (msg, name, status) => {
9✔
28
    status = status || 'ok';
36✔
29
    name = name || '';
36!
30
    
36✔
31
    if (name)
36✔
32
        name = `("${name}")`;
36✔
33
    
36✔
34
    return `${msg}: ${status}${name}`;
36✔
35
};
9✔
36

9✔
37
/**
9✔
38
 * Функция возвращает заголовок веб страницы
9✔
39
 * @path
9✔
40
 */
9✔
41
export const getTitle = (options) => {
9✔
42
    options = options || {};
3,000!
43
    
3,000✔
44
    const {path = Path(), name} = options;
3,000✔
45
    
3,000✔
46
    const array = [
3,000✔
47
        name || NAME,
3,000✔
48
        path,
3,000✔
49
    ];
3,000✔
50
    
3,000✔
51
    return array
3,000✔
52
        .filter(Boolean)
3,000✔
53
        .join(' - ');
3,000✔
54
};
9✔
55

9✔
56
/** Функция получает адреса каждого каталога в пути
9✔
57
 * возвращаеться массив каталогов
9✔
58
 * @param url -  адрес каталога
9✔
59
 */
9✔
60
export function getPathLink(url, prefix, template) {
9✔
61
    if (!url)
3,000✔
62
        throw Error('url could not be empty!');
3,000!
63
    
3,000✔
64
    if (!template)
3,000✔
65
        throw Error('template could not be empty!');
3,000!
66
    
3,000✔
67
    const names = url
3,000✔
68
        .split('/')
3,000✔
69
        .slice(1, -1);
3,000✔
70
    
3,000✔
71
    const allNames = [
3,000✔
72
        '/',
3,000✔
73
        ...names,
3,000✔
74
    ];
3,000✔
75
    
3,000✔
76
    const lines = [];
3,000✔
77
    const n = allNames.length;
3,000✔
78
    
3,000✔
79
    let path = '/';
3,000✔
80
    
3,000✔
81
    for (let i = 0; i < n; i++) {
3,000✔
82
        const name = allNames[i];
3,000✔
83
        const isLast = i === n - 1;
3,000✔
84
        
3,000✔
85
        if (i)
3,000✔
86
            path += `${name}/`;
3,000!
87
        
3,000✔
88
        if (i && isLast) {
3,000!
UNCOV
89
            lines.push(`${name}/`);
×
UNCOV
90
            continue;
×
UNCOV
91
        }
×
92
        
3,000✔
93
        const slash = i ? '/' : '';
3,000!
94
        
3,000✔
95
        lines.push(rendy(template, {
3,000✔
96
            path,
3,000✔
97
            name,
3,000✔
98
            slash,
3,000✔
99
            prefix,
3,000✔
100
        }));
3,000✔
101
    }
3,000✔
102
    
3,000✔
103
    return lines.join('');
3,000✔
104
}
3,000✔
105

9✔
106
export function _getDataName(name) {
9✔
107
    const encoded = btoa(encodeURI(name));
81,000✔
108
    return `data-name="js-file-${encoded}" `;
81,000✔
109
}
81,000✔
110

9✔
111
/**
9✔
112
 * Функция строит таблицу файлв из JSON-информации о файлах
9✔
113
 * @param params - информация о файлах
9✔
114
 *
9✔
115
 */
9✔
116
export const buildFromJSON = (params) => {
9✔
117
    const {
3,000✔
118
        prefix,
3,000✔
119
        template,
3,000✔
120
        sort = 'name',
3,000✔
121
        order = 'asc',
3,000✔
122
        showDotFiles,
3,000✔
123
    } = params;
3,000✔
124
    
3,000✔
125
    const formatDate = dateFormatter();
3,000✔
126
    
3,000✔
127
    const templateFile = template.file;
3,000✔
128
    const templateLink = template.link;
3,000✔
129
    const json = params.data;
3,000✔
130
    
3,000✔
131
    const path = encode(json.path);
3,000✔
132
    const {files} = json;
3,000✔
133
    
3,000✔
134
    /*
3,000✔
135
     * Строим путь каталога в котором мы находимся
3,000✔
136
     * со всеми подкаталогами
3,000✔
137
     */
3,000✔
138
    const htmlPath = getPathLink(path, prefix, template.pathLink);
3,000✔
139
    
3,000✔
140
    let fileTable = rendy(template.path, {
3,000✔
141
        link: prefix + FS + path,
3,000✔
142
        fullPath: path,
3,000✔
143
        path: htmlPath,
3,000✔
144
    });
3,000✔
145
    
3,000✔
146
    const owner = 'owner';
3,000✔
147
    const mode = 'mode';
3,000✔
148
    
3,000✔
149
    const getFieldName = getHeaderField(sort, order);
3,000✔
150
    
3,000✔
151
    const name = getFieldName('name');
3,000✔
152
    const size = getFieldName('size');
3,000✔
153
    const date = getFieldName('date');
3,000✔
154
    const time = getFieldName('time');
3,000✔
155
    
3,000✔
156
    const header = rendy(templateFile, {
3,000✔
157
        tag: 'div',
3,000✔
158
        attribute: 'data-name="js-fm-header" ',
3,000✔
159
        className: 'fm-header',
3,000✔
160
        type: '',
3,000✔
161
        name,
3,000✔
162
        size,
3,000✔
163
        date,
3,000✔
164
        time,
3,000✔
165
        owner,
3,000✔
166
        mode,
3,000✔
167
    });
3,000✔
168
    
3,000✔
169
    /* сохраняем путь */
3,000✔
170
    Path(path);
3,000✔
171
    
3,000✔
172
    fileTable += `${header}<ul data-name="js-files" class="files">`;
3,000✔
173
    
3,000✔
174
    /* Если мы не в корне */
3,000✔
175
    if (path !== '/') {
3,000!
UNCOV
176
        const dotDot = getDotDot(path);
×
UNCOV
177
        const link = prefix + FS + dotDot;
×
UNCOV
178
        
×
UNCOV
179
        const linkResult = rendy(template.link, {
×
UNCOV
180
            link,
×
UNCOV
181
            title: '..',
×
UNCOV
182
            name: '..',
×
UNCOV
183
        });
×
UNCOV
184
        
×
UNCOV
185
        const dataName = _getDataName('..');
×
UNCOV
186
        const attribute = `draggable="true" ${dataName}`;
×
UNCOV
187
        
×
UNCOV
188
        /* Сохраняем путь к каталогу верхнего уровня*/
×
UNCOV
189
        fileTable += rendy(template.file, {
×
UNCOV
190
            tag: 'li',
×
UNCOV
191
            attribute,
×
UNCOV
192
            className: '',
×
UNCOV
193
            type: 'directory',
×
UNCOV
194
            name: linkResult,
×
UNCOV
195
            size: '&lt;dir&gt;',
×
UNCOV
196
            date: '--.--.----',
×
UNCOV
197
            time: '--:--:--',
×
UNCOV
198
            owner: '.',
×
UNCOV
199
            mode: '--- --- ---',
×
UNCOV
200
        });
×
UNCOV
201
    }
×
202
    
3,000✔
203
    fileTable += files
3,000✔
204
        .filter(filterOutDotFiles({
3,000✔
205
            showDotFiles,
3,000✔
206
        }))
3,000✔
207
        .map(updateField)
3,000✔
208
        .map((file) => {
3,000✔
209
            const name = encode(file.name);
81,000✔
210
            const link = prefix + FS + path + name;
81,000✔
211
            
81,000✔
212
            const {
81,000✔
213
                type,
81,000✔
214
                mode,
81,000✔
215
                date,
81,000✔
216
                time,
81,000✔
217
                owner,
81,000✔
218
                size,
81,000✔
219
            } = file;
81,000✔
220
            
81,000✔
221
            const linkResult = rendy(templateLink, {
81,000✔
222
                link,
81,000✔
223
                title: name,
81,000✔
224
                name,
81,000✔
225
                attribute: getAttribute(file.type),
81,000✔
226
            });
81,000✔
227
            
81,000✔
228
            const dataName = _getDataName(file.name);
81,000✔
229
            const attribute = `draggable="true" ${dataName}`;
81,000✔
230
            
81,000✔
231
            return rendy(templateFile, {
81,000✔
232
                tag: 'li',
81,000✔
233
                attribute,
81,000✔
234
                className: '',
81,000✔
235
                type,
81,000✔
236
                name: linkResult,
81,000✔
237
                size,
81,000✔
238
                date: formatDate(date),
81,000✔
239
                time,
81,000✔
240
                owner,
81,000✔
241
                mode,
81,000✔
242
            });
81,000✔
243
        })
3,000✔
244
        .join('');
3,000✔
245
    
3,000✔
246
    fileTable += '</ul>';
3,000✔
247
    
3,000✔
248
    return fileTable;
3,000✔
249
};
9✔
250

9✔
251
const updateField = (file) => ({
9✔
252
    ...file,
81,000✔
253
    date: file.date || '--.--.----',
81,000!
254
    time: file.time || '--:--:--',
81,000!
255
    owner: file.owner || 'root',
81,000!
256
    size: getSize(file),
81,000✔
257
});
9✔
258

9✔
259
function getAttribute(type) {
81,000✔
260
    if (type === 'directory')
81,000✔
261
        return '';
81,000✔
262
    
18,000✔
263
    return 'target="_blank" ';
18,000✔
264
}
81,000✔
265

9✔
266
export const _getSize = getSize;
9✔
267

9✔
268
function getSize({size, type}) {
81,000✔
269
    if (type === 'directory')
81,000✔
270
        return '&lt;dir&gt;';
81,000✔
271
    
18,000✔
272
    if (/link/.test(type))
18,000✔
273
        return '&lt;link&gt;';
81,000✔
274
    
3,000✔
275
    return size;
3,000✔
276
}
81,000✔
277

9✔
278
function _getHeaderField(sort, order, name) {
12,000✔
279
    const arrow = order === 'asc' ? '↑' : '↓';
12,000!
280
    
12,000✔
281
    if (sort !== name)
12,000✔
282
        return name;
12,000✔
283
    
3,000✔
284
    if (sort === 'name' && order === 'asc')
12,000✔
285
        return name;
12,000✔
UNCOV
286
    
×
UNCOV
287
    return `${name}${arrow}`;
×
288
}
12,000✔
289

9✔
290
export function getDotDot(path) {
9✔
UNCOV
291
    // убираем последний слеш и каталог в котором мы сейчас находимся
×
UNCOV
292
    const lastSlash = path.substr(path, path.lastIndexOf('/'));
×
UNCOV
293
    const dotDot = lastSlash.substr(lastSlash, lastSlash.lastIndexOf('/'));
×
UNCOV
294
    
×
UNCOV
295
    if (!dotDot)
×
UNCOV
296
        return '/';
×
UNCOV
297
    
×
UNCOV
298
    return dotDot;
×
UNCOV
299
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc