@cocreate/file 1.1.0 → 1.2.1
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/CHANGELOG.md +19 -0
- package/CoCreate.config.js +3 -5
- package/package.json +2 -2
- package/src/client.js +318 -0
- package/src/server.js +354 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
## [1.2.1](https://github.com/CoCreate-app/CoCreate-file/compare/v1.2.0...v1.2.1) (2023-06-10)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* Refactor authentication & update config file output format ([27da6f0](https://github.com/CoCreate-app/CoCreate-file/commit/27da6f06c832bb3e153074a96a42017f0f0a3c30))
|
|
7
|
+
|
|
8
|
+
# [1.2.0](https://github.com/CoCreate-app/CoCreate-file/compare/v1.1.0...v1.2.0) (2023-06-09)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* Update dependencies versions for [@cocreate](https://github.com/cocreate) libraries ([c86d68d](https://github.com/CoCreate-app/CoCreate-file/commit/c86d68d3ef7fa76e8f52867f7abecaa67bab8270))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Features
|
|
17
|
+
|
|
18
|
+
* client and server functions ([af50769](https://github.com/CoCreate-app/CoCreate-file/commit/af5076902607f52c51f5a4fcca4a4a5554617b92))
|
|
19
|
+
|
|
1
20
|
# [1.1.0](https://github.com/CoCreate-app/CoCreate-file/compare/v1.0.0...v1.1.0) (2023-06-08)
|
|
2
21
|
|
|
3
22
|
|
package/CoCreate.config.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cocreate/file",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "A headless file uploader that uses HTML5 attributes for customization. Allows easy upload of files to server.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"file",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"build": "NODE_ENV=production npx webpack --config webpack.config.js",
|
|
30
30
|
"dev": "npx webpack --config webpack.config.js --watch",
|
|
31
31
|
"docs": "node ./node_modules/@cocreate/docs/src/index.js",
|
|
32
|
-
"
|
|
32
|
+
"postinstal": "node ./node_modules/@cocreate/cli/check-coc.js"
|
|
33
33
|
},
|
|
34
34
|
"repository": {
|
|
35
35
|
"type": "git",
|
package/src/client.js
ADDED
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import observer from '@cocreate/observer';
|
|
2
|
+
import crud from '@cocreate/crud-client';
|
|
3
|
+
import action from '@cocreate/actions';
|
|
4
|
+
import render from '@cocreate/render';
|
|
5
|
+
import '@cocreate/element-prototype';
|
|
6
|
+
|
|
7
|
+
let inputs = new Map();
|
|
8
|
+
|
|
9
|
+
function init(elements) {
|
|
10
|
+
// Returns an array of elements.
|
|
11
|
+
if (!elements)
|
|
12
|
+
elements = document.querySelectorAll('[type="file"]')
|
|
13
|
+
|
|
14
|
+
// If elements is an array of elements returns an array of elements.
|
|
15
|
+
else if (!Array.isArray(elements))
|
|
16
|
+
elements = [elements]
|
|
17
|
+
for (let i = 0; i < elements.length; i++) {
|
|
18
|
+
if (elements[i].tagName !== 'INPUT') {
|
|
19
|
+
// TODO: create input and append to div if input dos not exist
|
|
20
|
+
}
|
|
21
|
+
elements[i].getValue = async () => await getSelectedFiles([elements[i]], true)
|
|
22
|
+
|
|
23
|
+
// elements[i].setValue = (value) => pickr.setColor(value);
|
|
24
|
+
if (elements[i].hasAttribute('directory')) {
|
|
25
|
+
if (window.showDirectoryPicker)
|
|
26
|
+
elements[i].addEventListener("click", selectDirectory);
|
|
27
|
+
else if ('webkitdirectory' in elements[i]) {
|
|
28
|
+
elements[i].webkitdirectory = true
|
|
29
|
+
elements[i].addEventListener("change", handleFileInputChange)
|
|
30
|
+
} else
|
|
31
|
+
console.error("Directory selection not supported in this browser.");
|
|
32
|
+
} else if (window.showOpenFilePicker)
|
|
33
|
+
elements[i].addEventListener("click", selectFile);
|
|
34
|
+
else
|
|
35
|
+
elements[i].addEventListener("change", handleFileInputChange);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
function handleFileInputChange(event) {
|
|
41
|
+
const input = event.target;
|
|
42
|
+
const files = input.files;
|
|
43
|
+
let selected = inputs.get(input) || []
|
|
44
|
+
selected.push(...files)
|
|
45
|
+
inputs.set(input, selected);
|
|
46
|
+
console.log("Files selected:", files);
|
|
47
|
+
renderFiles(input)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function selectFile(event) {
|
|
51
|
+
event.preventDefault()
|
|
52
|
+
const input = event.target;
|
|
53
|
+
let selected = inputs.get(input) || []
|
|
54
|
+
try {
|
|
55
|
+
const multiple = input.multiple
|
|
56
|
+
const selectedFiles = await window.showOpenFilePicker({ multiple });
|
|
57
|
+
|
|
58
|
+
for (const handle of selectedFiles) {
|
|
59
|
+
selected.push(handle)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (selected.length) {
|
|
63
|
+
inputs.set(input, selected);
|
|
64
|
+
console.log("Files selected:", selected);
|
|
65
|
+
renderFiles(input)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
} catch (error) {
|
|
69
|
+
if (error.name !== 'AbortError') {
|
|
70
|
+
console.error("Error selecting files:", error);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async function selectDirectory(event) {
|
|
76
|
+
event.preventDefault()
|
|
77
|
+
const input = event.target;
|
|
78
|
+
let selected = inputs.get(input) || []
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
const handle = await window.showDirectoryPicker();
|
|
82
|
+
selected.push(handle)
|
|
83
|
+
|
|
84
|
+
if (selected.length) {
|
|
85
|
+
inputs.set(input, selected);
|
|
86
|
+
console.log("Directory selected:", selected);
|
|
87
|
+
renderFiles(input)
|
|
88
|
+
}
|
|
89
|
+
} catch (error) {
|
|
90
|
+
if (error.name !== 'AbortError') {
|
|
91
|
+
console.error("Error selecting directory:", error);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async function getNewFileHandle() {
|
|
97
|
+
// const options = {
|
|
98
|
+
// types: [
|
|
99
|
+
// {
|
|
100
|
+
// description: 'Text Files',
|
|
101
|
+
// accept: {
|
|
102
|
+
// 'text/plain': ['.txt'],
|
|
103
|
+
// },
|
|
104
|
+
// },
|
|
105
|
+
// ],
|
|
106
|
+
// };
|
|
107
|
+
const handle = await window.showSaveFilePicker(options);
|
|
108
|
+
return handle;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async function getSelectedFiles(fileInputs, isObject) {
|
|
112
|
+
const files = [];
|
|
113
|
+
|
|
114
|
+
if (!Array.isArray(fileInputs))
|
|
115
|
+
fileInputs = [fileInputs]
|
|
116
|
+
|
|
117
|
+
for (let input of fileInputs) {
|
|
118
|
+
const selected = inputs.get(input) || []
|
|
119
|
+
|
|
120
|
+
for (let i = 0; i < selected.length; i++) {
|
|
121
|
+
let file
|
|
122
|
+
if (selected[i] instanceof FileSystemDirectoryHandle) {
|
|
123
|
+
// The object is an instance of FileSystemFileHandle
|
|
124
|
+
const handles = await getSelectedDirectoryFiles(selected[i], selected[i].name)
|
|
125
|
+
for (let handle of handles) {
|
|
126
|
+
if (handle.kind === 'file')
|
|
127
|
+
file = await handle.getFile();
|
|
128
|
+
else if (handle.kind === 'directory')
|
|
129
|
+
file = { ...handle, name: handle.name }
|
|
130
|
+
else continue
|
|
131
|
+
|
|
132
|
+
if (isObject)
|
|
133
|
+
file = await readFile(file)
|
|
134
|
+
|
|
135
|
+
files.push(file)
|
|
136
|
+
}
|
|
137
|
+
} else {
|
|
138
|
+
if (selected[i] instanceof FileSystemFileHandle) {
|
|
139
|
+
// The object is an instance of FileSystemFileHandle
|
|
140
|
+
file = await selected[i].getFile();
|
|
141
|
+
} else {
|
|
142
|
+
// The object is not an instance of FileSystemFileHandle
|
|
143
|
+
console.log("It's not a FileSystemFileHandle object");
|
|
144
|
+
file = selected[i]
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (isObject)
|
|
148
|
+
file = await readFile(file)
|
|
149
|
+
|
|
150
|
+
files.push(file)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return files
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async function getSelectedDirectoryFiles(handle, name) {
|
|
160
|
+
let files = [];
|
|
161
|
+
for await (const entry of handle.values()) {
|
|
162
|
+
entry.directory = '/' + name
|
|
163
|
+
entry.parentDirectory = name.split("/").pop();
|
|
164
|
+
entry.path = '/' + name + '/' + entry.name
|
|
165
|
+
if (!entry.webkitRelativePath)
|
|
166
|
+
entry.webkitRelativePath = name
|
|
167
|
+
|
|
168
|
+
if (entry.kind === 'file') {
|
|
169
|
+
files.push(entry);
|
|
170
|
+
} else if (entry.kind === 'directory') {
|
|
171
|
+
entry.type = 'text/directory'
|
|
172
|
+
files.push(entry);
|
|
173
|
+
const entries = await getSelectedDirectoryFiles(entry, name + '/' + entry.name);
|
|
174
|
+
files = files.concat(entries);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return files;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// This function reads the file and returns its src
|
|
181
|
+
function readFile(file) {
|
|
182
|
+
// Return a new promise that resolves the file object
|
|
183
|
+
return new Promise((resolve) => {
|
|
184
|
+
file["content-type"] = file.type
|
|
185
|
+
|
|
186
|
+
// Split the file type into an array
|
|
187
|
+
const fileType = file.type.split('/');
|
|
188
|
+
let readAs;
|
|
189
|
+
|
|
190
|
+
// Check if the file type is a directory
|
|
191
|
+
if (fileType[1] === 'directory') {
|
|
192
|
+
return resolve(file)
|
|
193
|
+
}
|
|
194
|
+
// Check if the file type is a image
|
|
195
|
+
else if (['jpg', 'jpeg', 'png', 'gif', 'bmp'].includes(fileType[1])
|
|
196
|
+
|| fileType[0] === 'image') {
|
|
197
|
+
readAs = 'readAsDataURL';
|
|
198
|
+
}
|
|
199
|
+
// Check if the file type is a video
|
|
200
|
+
else if (['mp4', 'avi', 'mov', 'mpeg', 'flv'].includes(fileType[1])
|
|
201
|
+
|| fileType[0] === 'video') {
|
|
202
|
+
readAs = 'readAsDataURL';
|
|
203
|
+
}
|
|
204
|
+
// Check if the file type is an audio
|
|
205
|
+
else if (['mp3', 'wav', 'wma', 'aac', 'ogg'].includes(fileType[1])
|
|
206
|
+
|| fileType[0] === 'audio') { // updated condition
|
|
207
|
+
readAs = 'readAsDataURL';
|
|
208
|
+
}
|
|
209
|
+
// Check if the file type is a pdf
|
|
210
|
+
else if (fileType[1] === 'pdf') {
|
|
211
|
+
readAs = 'readAsDataURL';
|
|
212
|
+
}
|
|
213
|
+
// Check if the file type is a document
|
|
214
|
+
else if (['doc', 'msword', 'docx', 'xlsx', 'pptx'].includes(fileType[1])) {
|
|
215
|
+
readAs = 'readAsBinaryString';
|
|
216
|
+
}
|
|
217
|
+
// Otherwise, assume the file type is text
|
|
218
|
+
else {
|
|
219
|
+
readAs = 'readAsText';
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Create a FileReader instance to read the file
|
|
223
|
+
const reader = new FileReader();
|
|
224
|
+
// Read the file based on the file type
|
|
225
|
+
reader[readAs](file);
|
|
226
|
+
// When the file is loaded, resolve the file object
|
|
227
|
+
reader.onload = () => {
|
|
228
|
+
file.src = reader.result;
|
|
229
|
+
// If the file type is a document, convert it to base64 encoding
|
|
230
|
+
if (['doc', 'msword', 'docx', 'xlsx', 'pptx'].includes(fileType)) {
|
|
231
|
+
file.src = btoa(file.src);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Resolve the file object
|
|
235
|
+
resolve(file);
|
|
236
|
+
};
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
async function fileAction(btn, params, action) {
|
|
241
|
+
const form = btn.closest('form')
|
|
242
|
+
let inputs = form.querySelectorAll('input[type="file"]')
|
|
243
|
+
let fileObjects = await getSelectedFiles(Array.from(inputs), true)
|
|
244
|
+
|
|
245
|
+
console.log('fileObjects', fileObjects)
|
|
246
|
+
document.dispatchEvent(new CustomEvent(action, {
|
|
247
|
+
detail: {}
|
|
248
|
+
}));
|
|
249
|
+
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// may be best to use getValue() so form so inputtype files can be can be managed in forms
|
|
253
|
+
async function save(inputs, collection, document_id) {
|
|
254
|
+
let files = await getSelectedFiles(inputs, true)
|
|
255
|
+
|
|
256
|
+
let response = await crud.updateDocument({
|
|
257
|
+
collection,
|
|
258
|
+
document: files,
|
|
259
|
+
upsert: true
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
if (response && (!document_id || document_id !== response.document_id)) {
|
|
263
|
+
crud.setDocumentId(element, collection, response.document_id);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return response
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
async function getFiles(inputs) {
|
|
270
|
+
let files = await getSelectedFiles(inputs)
|
|
271
|
+
return files
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
async function getObjects(inputs) {
|
|
275
|
+
let objects = await getSelectedFiles(inputs, true)
|
|
276
|
+
return objects
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function renderFiles(input) {
|
|
280
|
+
// TODO: support
|
|
281
|
+
let template_id = input.getAttribute('template_id')
|
|
282
|
+
if (template_id) {
|
|
283
|
+
// if data items are handle it will not yet have all the details
|
|
284
|
+
const data = inputs.get(input)
|
|
285
|
+
if (data.length) return
|
|
286
|
+
render.data({
|
|
287
|
+
selector: `[template='${template_id}']`,
|
|
288
|
+
data
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
observer.init({
|
|
294
|
+
name: 'CoCreateFileAddedNodes',
|
|
295
|
+
observe: ['addedNodes'],
|
|
296
|
+
target: 'input[type="file"]',
|
|
297
|
+
callback: mutation => init(mutation.target)
|
|
298
|
+
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
observer.init({
|
|
302
|
+
name: 'CoCreateFileAttributes',
|
|
303
|
+
observe: ['attributes'],
|
|
304
|
+
attributeName: ['type'],
|
|
305
|
+
target: 'input[type="file"]',
|
|
306
|
+
callback: mutation => init(mutation.target)
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
action.init({
|
|
310
|
+
name: "upload",
|
|
311
|
+
callback: (btn, params) => {
|
|
312
|
+
fileAction(btn, params, "upload")
|
|
313
|
+
}
|
|
314
|
+
})
|
|
315
|
+
|
|
316
|
+
init()
|
|
317
|
+
|
|
318
|
+
export default { getFiles, getObjects }
|
package/src/server.js
ADDED
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
const crud = require('@cocreate/crud-client')
|
|
2
|
+
const cli = require('@cocreate/cli')
|
|
3
|
+
const mime = require('mime-types')
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
module.exports = async function file(CoCreateConfig) {
|
|
9
|
+
|
|
10
|
+
let configFile = path.resolve(process.cwd(), 'CoCreate.config.js');
|
|
11
|
+
if (fs.existsSync(configFile)) {
|
|
12
|
+
CoCreateConfig = require(configFile);
|
|
13
|
+
} else {
|
|
14
|
+
console.log('CoCreate.config.js could not be found.')
|
|
15
|
+
process.exit()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let { directories, sources } = CoCreateConfig;
|
|
19
|
+
let config = await cli.config([
|
|
20
|
+
{
|
|
21
|
+
key: 'organization_id',
|
|
22
|
+
prompt: 'Enter your organization_id: '
|
|
23
|
+
}, {
|
|
24
|
+
key: 'host',
|
|
25
|
+
prompt: 'Enter the host: '
|
|
26
|
+
}, {
|
|
27
|
+
prompt: 'Choose an authentication option: \n1.key\n2.Sign In\n',
|
|
28
|
+
choices: {
|
|
29
|
+
'1': {
|
|
30
|
+
key: 'key',
|
|
31
|
+
prompt: 'Enter your key: '
|
|
32
|
+
},
|
|
33
|
+
'2': [
|
|
34
|
+
{
|
|
35
|
+
key: 'email',
|
|
36
|
+
prompt: 'Enter your email: '
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
key: 'password',
|
|
40
|
+
prompt: 'Enter your password: '
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
])
|
|
46
|
+
|
|
47
|
+
if (!config.organization_id || !config.host || !config.key && (!config.password || config.email)) {
|
|
48
|
+
console.log('One or more required config params could not be found')
|
|
49
|
+
process.exit()
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
crud.socket.create(config)
|
|
54
|
+
config.broadcast = false
|
|
55
|
+
|
|
56
|
+
if (config.email && config.password) {
|
|
57
|
+
let request = {
|
|
58
|
+
collection: 'users',
|
|
59
|
+
filter: {
|
|
60
|
+
query: [
|
|
61
|
+
{ name: 'email', value: config.email, operator: '$eq' },
|
|
62
|
+
{ name: 'password', value: config.password, operator: '$eq' }
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
let response = await crud.socket.send('signIn', request)
|
|
68
|
+
let { success, token } = response;
|
|
69
|
+
|
|
70
|
+
if (success) {
|
|
71
|
+
console.log('succesful sign in')
|
|
72
|
+
// apply token to socket
|
|
73
|
+
} else {
|
|
74
|
+
console.log('The email or password you entered is incorrect')
|
|
75
|
+
process.exit()
|
|
76
|
+
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
console.log('Uploading files...')
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Store files by config directories
|
|
85
|
+
**/
|
|
86
|
+
let errorLog = [];
|
|
87
|
+
|
|
88
|
+
async function runDirectories() {
|
|
89
|
+
for (const directory of directories) {
|
|
90
|
+
const entry = directory.entry
|
|
91
|
+
const exclude = directory.exclude
|
|
92
|
+
await runFiles(directory, entry, exclude)
|
|
93
|
+
}
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async function runFiles(directory, entry, exclude, parentDirectory = '') {
|
|
98
|
+
let files = fs.readdirSync(entry);
|
|
99
|
+
|
|
100
|
+
for (let file of files) {
|
|
101
|
+
if (exclude && exclude.includes(file)) continue
|
|
102
|
+
|
|
103
|
+
let isDirectory = fs.existsSync(`${entry}/${file}`) && fs.lstatSync(`${entry}/${file}`).isDirectory();
|
|
104
|
+
let name = file
|
|
105
|
+
let source = ''
|
|
106
|
+
let directoryName = parentDirectory || '';
|
|
107
|
+
let parentDirectoryOnly = parentDirectory || '';
|
|
108
|
+
let index = parentDirectoryOnly.lastIndexOf('/') + 1
|
|
109
|
+
if (parentDirectoryOnly && index) {
|
|
110
|
+
parentDirectoryOnly = parentDirectoryOnly.substring(index)
|
|
111
|
+
}
|
|
112
|
+
let mimeType = mime.lookup(`${file}`)
|
|
113
|
+
let pathName = '';
|
|
114
|
+
|
|
115
|
+
if (!directoryName && directory.document && directory.document.directory)
|
|
116
|
+
directoryName = directory.document.directory.replace('{{directory}}', '').trim()
|
|
117
|
+
else if (!directoryName)
|
|
118
|
+
directoryName = '/'
|
|
119
|
+
|
|
120
|
+
if (exclude && exclude.includes(directoryName)) continue
|
|
121
|
+
|
|
122
|
+
if (directoryName.endsWith("/"))
|
|
123
|
+
pathName = directoryName + name
|
|
124
|
+
else if (directoryName)
|
|
125
|
+
pathName = directoryName + '/' + name
|
|
126
|
+
else
|
|
127
|
+
pathName = '/' + name
|
|
128
|
+
|
|
129
|
+
if (exclude && exclude.includes(pathName)) continue
|
|
130
|
+
|
|
131
|
+
if (isDirectory)
|
|
132
|
+
mimeType = "text/directory"
|
|
133
|
+
else
|
|
134
|
+
source = getSource(`${entry}/${file}`, mimeType)
|
|
135
|
+
|
|
136
|
+
let values = {
|
|
137
|
+
'{{name}}': name,
|
|
138
|
+
'{{source}}': source,
|
|
139
|
+
'{{directory}}': directoryName,
|
|
140
|
+
'{{parentDirectory}}': parentDirectoryOnly,
|
|
141
|
+
'{{path}}': pathName,
|
|
142
|
+
'{{content-type}}': mimeType
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
let document = { ...directory.document }
|
|
146
|
+
if (!document.name)
|
|
147
|
+
document.name = "{{name}}"
|
|
148
|
+
if (!document.src)
|
|
149
|
+
document.src = "{{source}}"
|
|
150
|
+
if (!document.directory)
|
|
151
|
+
document.directory = "/{{directory}}"
|
|
152
|
+
if (!document.parentDirectory)
|
|
153
|
+
document.parentDirectory = "{{parentDirectory}}"
|
|
154
|
+
if (!document.path)
|
|
155
|
+
document.path = "{{path}}"
|
|
156
|
+
if (!document["content-type"])
|
|
157
|
+
document["content-type"] = '{{content-type}}'
|
|
158
|
+
if (!document.public && document.public != false && document.public != 'false')
|
|
159
|
+
document.public = 'true'
|
|
160
|
+
|
|
161
|
+
let object = {
|
|
162
|
+
collection: directory.collection || 'files',
|
|
163
|
+
document
|
|
164
|
+
}
|
|
165
|
+
for (const key of Object.keys(directory.document)) {
|
|
166
|
+
if (typeof directory.document[key] == 'string') {
|
|
167
|
+
|
|
168
|
+
let variables = directory.document[key].match(/{{([A-Za-z0-9_.,\[\]\-\/ ]*)}}/g);
|
|
169
|
+
if (variables) {
|
|
170
|
+
for (let variable of variables) {
|
|
171
|
+
if (variable == '{{directory}}') {
|
|
172
|
+
if (parentDirectory)
|
|
173
|
+
object.document[key] = values[variable]
|
|
174
|
+
else
|
|
175
|
+
object.document[key] = object.document[key].replace(variable, '');
|
|
176
|
+
}
|
|
177
|
+
else if (isDirectory && variable == '{{source}}')
|
|
178
|
+
delete object.document[key]
|
|
179
|
+
else
|
|
180
|
+
object.document[key] = object.document[key].replace(variable, values[variable]);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (!object.document._id)
|
|
188
|
+
object.filter = {
|
|
189
|
+
query: [{ name: 'path', value: pathName, operator: '$eq' }]
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
response = await runStore(object);
|
|
193
|
+
if (response.error)
|
|
194
|
+
errorLog.push(response.error)
|
|
195
|
+
|
|
196
|
+
if (isDirectory && pathName) {
|
|
197
|
+
let newEntry
|
|
198
|
+
if (entry.endsWith("/"))
|
|
199
|
+
newEntry = entry + name
|
|
200
|
+
else
|
|
201
|
+
newEntry = entry + '/' + name
|
|
202
|
+
|
|
203
|
+
await runFiles(directory, newEntry, exclude, pathName)
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (errorLog.length)
|
|
207
|
+
console.log(...errorLog)
|
|
208
|
+
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
function getSource(path, mimeType) {
|
|
213
|
+
let readType = 'utf8'
|
|
214
|
+
if (/^(image|audio|video)\/[-+.\w]+/.test(mimeType))
|
|
215
|
+
readType = 'base64'
|
|
216
|
+
|
|
217
|
+
let binary = fs.readFileSync(path);
|
|
218
|
+
let content = new Buffer.from(binary).toString(readType);
|
|
219
|
+
|
|
220
|
+
return content
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Store files by config sources
|
|
225
|
+
**/
|
|
226
|
+
async function runSources() {
|
|
227
|
+
let updatedSources = [];
|
|
228
|
+
|
|
229
|
+
for (let i = 0; i < sources.length; i++) {
|
|
230
|
+
const { collection, document } = sources[i];
|
|
231
|
+
|
|
232
|
+
let source = { ...sources[i] };
|
|
233
|
+
let keys = new Map()
|
|
234
|
+
let response = {};
|
|
235
|
+
|
|
236
|
+
try {
|
|
237
|
+
if (collection) {
|
|
238
|
+
if (!document)
|
|
239
|
+
document = {};
|
|
240
|
+
else
|
|
241
|
+
for (const key of Object.keys(document)) {
|
|
242
|
+
if (typeof document[key] != 'string')
|
|
243
|
+
continue
|
|
244
|
+
|
|
245
|
+
let variables = document[key].match(/{{([A-Za-z0-9_.,\[\]\-\/ ]*)}}/g);
|
|
246
|
+
if (variables) {
|
|
247
|
+
keys.set(key, `${document[key]}`)
|
|
248
|
+
let value = ""
|
|
249
|
+
for (let variable of variables) {
|
|
250
|
+
let entry = /{{\s*([\w\W]+)\s*}}/g.exec(variable);
|
|
251
|
+
entry = entry[1].trim()
|
|
252
|
+
if (entry) {
|
|
253
|
+
if (!fs.existsSync(entry))
|
|
254
|
+
continue
|
|
255
|
+
|
|
256
|
+
let read_type = 'utf8'
|
|
257
|
+
let mime_type = mime.lookup(entry) || 'text/html';
|
|
258
|
+
if (/^(image|audio|video)\/[-+.\w]+/.test(mime_type)) {
|
|
259
|
+
read_type = 'base64'
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
let binary = fs.readFileSync(entry);
|
|
263
|
+
let content = new Buffer.from(binary).toString(read_type);
|
|
264
|
+
if (content)
|
|
265
|
+
value += content
|
|
266
|
+
// document[key] = document[key].replace(variable, content);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
document[key] = value
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
let data = { collection, document }
|
|
275
|
+
if (!document._id && document.path)
|
|
276
|
+
data.filter = {
|
|
277
|
+
query: [{ name: 'path', value: document.path, operator: '$eq' }]
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
response = await runStore(data);
|
|
281
|
+
}
|
|
282
|
+
} catch (err) {
|
|
283
|
+
console.log(err)
|
|
284
|
+
process.exit()
|
|
285
|
+
}
|
|
286
|
+
if (response.document && response.document[0] && response.document[0]._id) {
|
|
287
|
+
for (const [key, value] of keys) {
|
|
288
|
+
source.document[key] = value
|
|
289
|
+
}
|
|
290
|
+
source.document._id = response.document[0]._id
|
|
291
|
+
} else {
|
|
292
|
+
console.log('_id could not be found')
|
|
293
|
+
process.exit()
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
updatedSources.push(source)
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
return updatedSources
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
async function runStore(data) {
|
|
304
|
+
try {
|
|
305
|
+
let response;
|
|
306
|
+
if (!data.document._id && !data.filter) {
|
|
307
|
+
response = await crud.createDocument({
|
|
308
|
+
...config,
|
|
309
|
+
...data
|
|
310
|
+
})
|
|
311
|
+
} else {
|
|
312
|
+
response = await crud.updateDocument({
|
|
313
|
+
...config,
|
|
314
|
+
...data,
|
|
315
|
+
upsert: true
|
|
316
|
+
})
|
|
317
|
+
}
|
|
318
|
+
if (response) {
|
|
319
|
+
return response;
|
|
320
|
+
}
|
|
321
|
+
} catch (err) {
|
|
322
|
+
console.log(err);
|
|
323
|
+
return null;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
async function run() {
|
|
328
|
+
if (directories)
|
|
329
|
+
await runDirectories()
|
|
330
|
+
|
|
331
|
+
if (sources) {
|
|
332
|
+
let sources = await runSources()
|
|
333
|
+
let newConfig = { ...CoCreateConfig }
|
|
334
|
+
if (directories)
|
|
335
|
+
newConfig.directories = directories
|
|
336
|
+
|
|
337
|
+
newConfig.sources = sources
|
|
338
|
+
|
|
339
|
+
delete newConfig.url
|
|
340
|
+
delete newConfig.broadcast
|
|
341
|
+
const write_str = `module.exports = ${JSON.stringify(newConfig, null, 4)};`;
|
|
342
|
+
|
|
343
|
+
fs.writeFileSync(configFile, write_str);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
console.log('upload complete!');
|
|
347
|
+
|
|
348
|
+
setTimeout(function () {
|
|
349
|
+
process.exit()
|
|
350
|
+
}, 2000)
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
run()
|
|
354
|
+
}
|