@cocreate/file 1.19.1 → 1.19.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ ## [1.19.3](https://github.com/CoCreate-app/CoCreate-file/compare/v1.19.2...v1.19.3) (2025-04-11)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * fire action end event on elememt instead of document ([3e78905](https://github.com/CoCreate-app/CoCreate-file/commit/3e789054e65e87c4f988d2041dfe8687684ebff5))
7
+ * update observer observe param to type and and attributeName to attributeFilter ([524a05e](https://github.com/CoCreate-app/CoCreate-file/commit/524a05e0080c4473f28fc9e5bd1414479e313eb7))
8
+
9
+ ## [1.19.2](https://github.com/CoCreate-app/CoCreate-file/compare/v1.19.1...v1.19.2) (2025-01-18)
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * formating ([65e9a91](https://github.com/CoCreate-app/CoCreate-file/commit/65e9a915b17f616abd5bed917fa7323b1f59bd28))
15
+
1
16
  ## [1.19.1](https://github.com/CoCreate-app/CoCreate-file/compare/v1.19.0...v1.19.1) (2024-12-14)
2
17
 
3
18
 
package/demo/index.html CHANGED
@@ -1,81 +1,81 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en">
3
- <head>
4
- <title>file | CoCreateJS</title>
3
+ <head>
4
+ <title>file | CoCreateJS</title>
5
5
 
6
- <!-- CoCreate Favicon -->
7
- <link
8
- rel="icon"
9
- type="image/png"
10
- sizes="32x32"
11
- href="../assets/favicon.ico" />
12
- <link rel="manifest" href="/manifest.webmanifest" />
13
- </head>
14
- <body>
15
- <form>
16
- <input type="file" import />
17
- <button actions="import">import</button>
18
- </form>
6
+ <!-- CoCreate Favicon -->
7
+ <link
8
+ rel="icon"
9
+ type="image/png"
10
+ sizes="32x32"
11
+ href="../assets/favicon.ico" />
12
+ <link rel="manifest" href="/manifest.webmanifest" />
13
+ </head>
14
+ <body>
15
+ <form>
16
+ <input type="file" import />
17
+ <button actions="import">import</button>
18
+ </form>
19
19
 
20
- <form>
21
- <input type="file" path="/assets/test" />
22
- <button actions="upload">upload</button>
23
- </form>
20
+ <form>
21
+ <input type="file" path="/assets/test" />
22
+ <button actions="upload">upload</button>
23
+ </form>
24
24
 
25
- <form>
26
- <input type="file" multiple />
27
- <button actions="upload">upload</button>
28
- </form>
25
+ <form>
26
+ <input type="file" multiple />
27
+ <button actions="upload">upload</button>
28
+ </form>
29
29
 
30
- <form>
31
- <input type="file" directory />
32
- <button actions="upload">upload</button>
33
- </form>
30
+ <form>
31
+ <input type="file" directory />
32
+ <button actions="upload">upload</button>
33
+ </form>
34
34
 
35
- <div
36
- type="file"
37
- array="test"
38
- object=""
39
- key="image"
40
- accept="image/*"
41
- placeholder="Upload Image or Video Thumbnail"
42
- class="floating-label min-height:40px active"
43
- render-selector="[template]"
44
- active>
45
- <div template>
46
- <img src="{{image.src}}" alt="image" width="100%" />
47
- </div>
48
- </div>
35
+ <div
36
+ type="file"
37
+ array="test"
38
+ object=""
39
+ key="image"
40
+ accept="image/*"
41
+ placeholder="Upload Image or Video Thumbnail"
42
+ class="floating-label min-height:40px active"
43
+ render-selector="[template]"
44
+ active>
45
+ <div template>
46
+ <img src="{{image.src}}" alt="image" width="100%" />
47
+ </div>
48
+ </div>
49
49
 
50
- <form>
51
- <input
52
- type="file"
53
- directory
54
- realtime="false"
55
- render-selector="document; [template]" />
50
+ <form>
51
+ <input
52
+ type="file"
53
+ directory
54
+ realtime="false"
55
+ render-document="[template]" />
56
56
 
57
- <button actions="saveLocally">saveLocally</button>
58
- </form>
57
+ <button actions="saveLocally">saveLocally</button>
58
+ </form>
59
59
 
60
- <div template file_id="{{id}}">
61
- <button actions="createFile" value="tesing.js">createFile</button>
62
- <button actions="deleteFile">deleteFile</button>
63
- <button actions="createDirectory">createDirectory</button>
64
- <button actions="deleteDirectory">deleteDirectory</button>
60
+ <div template file_id="{{id}}">
61
+ <button actions="createFile" value="tesing.js">createFile</button>
62
+ <button actions="deleteFile">deleteFile</button>
63
+ <button actions="createDirectory">createDirectory</button>
64
+ <button actions="deleteDirectory">deleteDirectory</button>
65
65
 
66
- <input file="name" value="{{name}}" />
67
- <input file="directory" value="{{directory}}" />
68
- <input file="content-type" value="{{content-type}}" />
69
- <textarea file="src" value-type="string">{{src}}</textarea>
70
- <div>id: {{id}}</div>
71
- </div>
66
+ <input file="name" value="{{name}}" />
67
+ <input file="directory" value="{{directory}}" />
68
+ <input file="content-type" value="{{content-type}}" />
69
+ <textarea file="src" value-type="string">{{src}}</textarea>
70
+ <div>id: {{id}}</div>
71
+ </div>
72
72
 
73
- <form>
74
- <button actions="export" array="files">export</button>
75
- </form>
73
+ <form>
74
+ <button actions="export" array="files">export</button>
75
+ </form>
76
76
 
77
- <!-- <script src="../dist/CoCreate-file.js"></script> -->
78
- <script src="../../../CoCreateJS/dist/CoCreate.js"></script>
79
- <!-- <script src="https://CoCreate.app/dist/CoCreate.js"></script> -->
80
- </body>
77
+ <!-- <script src="../dist/CoCreate-file.js"></script> -->
78
+ <script src="../../../CoCreateJS/dist/CoCreate.js"></script>
79
+ <!-- <script src="https://CoCreate.app/dist/CoCreate.js"></script> -->
80
+ </body>
81
81
  </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/file",
3
- "version": "1.19.1",
3
+ "version": "1.19.3",
4
4
  "description": "A versatile, configurable headless file uploader supporting local and server operations. Accessible via a JavaScript API and HTML5 attributes, it provides seamless file reading, writing, and uploading with fallbacks to the standard HTML5 file input API. Ideal for developers needing robust file management in headless environments.",
5
5
  "keywords": [
6
6
  "file-uploader",
package/src/client.js CHANGED
@@ -751,6 +751,7 @@ async function Import(element, data) {
751
751
  return data;
752
752
  }
753
753
 
754
+ // TODO: Export selected rows or entire table or entire array
754
755
  async function Export(element, data) {
755
756
  if (!data) data = [];
756
757
 
@@ -858,7 +859,7 @@ async function importURL(action) {
858
859
  queriedElement.setValue(data.file);
859
860
  }
860
861
 
861
- document.dispatchEvent(
862
+ action.element.dispatchEvent(
862
863
  new CustomEvent(action.name, {
863
864
  detail: {}
864
865
  })
@@ -894,7 +895,7 @@ async function fileRenderAction(action) {
894
895
  create(file, "directory", name);
895
896
  } else if (action.name === "deleteDirectory") Delete(file);
896
897
 
897
- document.dispatchEvent(
898
+ action.element.dispatchEvent(
898
899
  new CustomEvent(action.name, {
899
900
  detail: {}
900
901
  })
@@ -967,15 +968,15 @@ async function Delete(file) {
967
968
 
968
969
  Observer.init({
969
970
  name: "CoCreateFileAddedNodes",
970
- observe: ["addedNodes"],
971
+ types: ["addedNodes"],
971
972
  selector: '[type="file"]',
972
973
  callback: (mutation) => init(mutation.target)
973
974
  });
974
975
 
975
976
  Observer.init({
976
977
  name: "CoCreateFileAttributes",
977
- observe: ["attributes"],
978
- attributeName: ["type"],
978
+ types: ["attributes"],
979
+ attributeFilter: ["type"],
979
980
  selector: '[type="file"]',
980
981
  callback: (mutation) => init(mutation.target)
981
982
  });
@@ -1008,7 +1009,7 @@ Actions.init([
1008
1009
  // Something...
1009
1010
  }
1010
1011
 
1011
- document.dispatchEvent(
1012
+ action.element.dispatchEvent(
1012
1013
  new CustomEvent(action.name, {
1013
1014
  detail: {}
1014
1015
  })
package/src/server.js CHANGED
@@ -1,500 +1,531 @@
1
- const crud = require('@cocreate/crud-client')
2
- const Config = require('@cocreate/config')
3
- const fs = require('fs');
1
+ const crud = require("@cocreate/crud-client");
2
+ const Config = require("@cocreate/config");
3
+ const fs = require("fs");
4
4
  const realpathAsync = fs.promises.realpath;
5
5
 
6
- const path = require('path');
6
+ const path = require("path");
7
7
  const mimeTypes = {
8
- ".aac": "audio/aac",
9
- ".abw": "application/x-abiword",
10
- ".arc": "application/x-freearc",
11
- ".avi": "video/x-msvideo",
12
- ".azw": "application/vnd.amazon.ebook",
13
- ".bin": "application/octet-stream",
14
- ".bmp": "image/bmp",
15
- ".bz": "application/x-bzip",
16
- ".bz2": "application/x-bzip2",
17
- ".csh": "application/x-csh",
18
- ".css": "text/css",
19
- ".csv": "text/csv",
20
- ".doc": "application/msword",
21
- ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
22
- ".eot": "application/vnd.ms-fontobject",
23
- ".epub": "application/epub+zip",
24
- ".gif": "image/gif",
25
- ".htm": "text/html",
26
- ".html": "text/html",
27
- ".ico": "image/x-icon",
28
- ".ics": "text/calendar",
29
- ".jar": "application/java-archive",
30
- ".jpeg": "image/jpeg",
31
- ".jpg": "image/jpeg",
32
- ".js": "text/javascript",
33
- ".json": "application/json",
34
- ".jsonld": "application/ld+json",
35
- ".mid": "audio/midi",
36
- ".midi": "audio/midi",
37
- ".mjs": "text/javascript",
38
- ".mp3": "audio/mpeg",
39
- ".mp4": "video/mp4",
40
- ".mpeg": "video/mpeg",
41
- ".mpkg": "application/vnd.apple.installer+xml",
42
- ".odp": "application/vnd.oasis.opendocument.presentation",
43
- ".ods": "application/vnd.oasis.opendocument.spreadsheet",
44
- ".odt": "application/vnd.oasis.opendocument.text",
45
- ".oga": "audio/ogg",
46
- ".ogv": "video/ogg",
47
- ".ogx": "application/ogg",
48
- ".otf": "font/otf",
49
- ".png": "image/png",
50
- ".pdf": "application/pdf",
51
- ".ppt": "application/vnd.ms-powerpoint",
52
- ".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
53
- ".rar": "application/x-rar-compressed",
54
- ".rtf": "application/rtf",
55
- ".sh": "application/x-sh",
56
- ".svg": "image/svg+xml",
57
- ".swf": "application/x-shockwave-flash",
58
- ".tar": "application/x-tar",
59
- ".tif": "image/tiff",
60
- ".tiff": "image/tiff",
61
- ".ts": "video/mp2t",
62
- ".ttf": "font/ttf",
63
- ".txt": "text/plain",
64
- ".vsd": "application/vnd.visio",
65
- ".wav": "audio/wav",
66
- ".weba": "audio/webm",
67
- ".webm": "video/webm",
68
- ".webmanifest": "application/manifest+json",
69
- ".webp": "image/webp",
70
- ".woff": "font/woff",
71
- ".woff2": "font/woff2",
72
- ".xhtml": "application/xhtml+xml",
73
- ".xls": "application/vnd.ms-excel",
74
- ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
75
- ".xml": "application/xml",
76
- ".xul": "application/vnd.mozilla.xul+xml",
77
- ".zip": "application/zip",
78
- ".3gp": "video/3gpp",
79
- ".3g2": "video/3gpp2",
80
- ".7z": "application/x-7z-compressed"
81
- }
8
+ ".aac": "audio/aac",
9
+ ".abw": "application/x-abiword",
10
+ ".arc": "application/x-freearc",
11
+ ".avi": "video/x-msvideo",
12
+ ".azw": "application/vnd.amazon.ebook",
13
+ ".bin": "application/octet-stream",
14
+ ".bmp": "image/bmp",
15
+ ".bz": "application/x-bzip",
16
+ ".bz2": "application/x-bzip2",
17
+ ".csh": "application/x-csh",
18
+ ".css": "text/css",
19
+ ".csv": "text/csv",
20
+ ".doc": "application/msword",
21
+ ".docx":
22
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
23
+ ".eot": "application/vnd.ms-fontobject",
24
+ ".epub": "application/epub+zip",
25
+ ".gif": "image/gif",
26
+ ".htm": "text/html",
27
+ ".html": "text/html",
28
+ ".ico": "image/x-icon",
29
+ ".ics": "text/calendar",
30
+ ".jar": "application/java-archive",
31
+ ".jpeg": "image/jpeg",
32
+ ".jpg": "image/jpeg",
33
+ ".js": "text/javascript",
34
+ ".json": "application/json",
35
+ ".jsonld": "application/ld+json",
36
+ ".mid": "audio/midi",
37
+ ".midi": "audio/midi",
38
+ ".mjs": "text/javascript",
39
+ ".mp3": "audio/mpeg",
40
+ ".mp4": "video/mp4",
41
+ ".mpeg": "video/mpeg",
42
+ ".mpkg": "application/vnd.apple.installer+xml",
43
+ ".odp": "application/vnd.oasis.opendocument.presentation",
44
+ ".ods": "application/vnd.oasis.opendocument.spreadsheet",
45
+ ".odt": "application/vnd.oasis.opendocument.text",
46
+ ".oga": "audio/ogg",
47
+ ".ogv": "video/ogg",
48
+ ".ogx": "application/ogg",
49
+ ".otf": "font/otf",
50
+ ".png": "image/png",
51
+ ".pdf": "application/pdf",
52
+ ".ppt": "application/vnd.ms-powerpoint",
53
+ ".pptx":
54
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation",
55
+ ".rar": "application/x-rar-compressed",
56
+ ".rtf": "application/rtf",
57
+ ".sh": "application/x-sh",
58
+ ".svg": "image/svg+xml",
59
+ ".swf": "application/x-shockwave-flash",
60
+ ".tar": "application/x-tar",
61
+ ".tif": "image/tiff",
62
+ ".tiff": "image/tiff",
63
+ ".ts": "video/mp2t",
64
+ ".ttf": "font/ttf",
65
+ ".txt": "text/plain",
66
+ ".vsd": "application/vnd.visio",
67
+ ".wav": "audio/wav",
68
+ ".weba": "audio/webm",
69
+ ".webm": "video/webm",
70
+ ".webmanifest": "application/manifest+json",
71
+ ".webp": "image/webp",
72
+ ".woff": "font/woff",
73
+ ".woff2": "font/woff2",
74
+ ".xhtml": "application/xhtml+xml",
75
+ ".xls": "application/vnd.ms-excel",
76
+ ".xlsx":
77
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
78
+ ".xml": "application/xml",
79
+ ".xul": "application/vnd.mozilla.xul+xml",
80
+ ".zip": "application/zip",
81
+ ".3gp": "video/3gpp",
82
+ ".3g2": "video/3gpp2",
83
+ ".7z": "application/x-7z-compressed"
84
+ };
82
85
 
83
86
  module.exports = async function file(CoCreateConfig, configPath, match) {
84
- let directories = CoCreateConfig.directories
85
- let sources = CoCreateConfig.sources
86
- let configDirectoryPath = path.dirname(configPath)
87
-
88
- if (match && !Array.isArray(match))
89
- match = [match]
90
- else if (!match)
91
- match = []
92
-
93
- let config = await Config({
94
- organization_id: {
95
- prompt: 'Enter your organization_id: '
96
- },
97
- host: {
98
- prompt: 'Enter the host: '
99
- },
100
- prompt: {
101
- prompt: 'Choose an authentication option: \n1.apikey\n2.Sign In\n',
102
- choices: {
103
- '1': {
104
- apikey: {
105
- prompt: 'Enter your apikey: '
106
- }
107
- },
108
- '2': {
109
- email: {
110
- prompt: 'Enter your email: '
111
- },
112
- password: {
113
- prompt: 'Enter your password: '
114
- }
115
- }
116
- }
117
- }
118
- }, null, null, configPath)
119
-
120
- if (!config.organization_id || !config.apikey && (!config.password || config.email)) {
121
- console.log('One or more required config params could not be found')
122
- process.exit()
123
- }
124
-
125
- if (config.email && config.password) {
126
- let request = {
127
- method: 'signIn',
128
- array: 'users',
129
- $filter: {
130
- query: {
131
- email: config.email,
132
- password: config.password
133
- }
134
- },
135
- ...config
136
- }
137
-
138
- let response = await crud.send(request)
139
- let { success, token } = response;
140
-
141
- if (success) {
142
- console.log('succesful sign in')
143
- // apply token to socket
144
- } else {
145
- console.log('The email or password you entered is incorrect')
146
- process.exit()
147
-
148
- }
149
-
150
- }
151
-
152
- // console.log('Uploading files...')
153
-
154
- /**
155
- * Store files by config directories
156
- **/
157
- let errorLog = [];
158
-
159
- async function runDirectories() {
160
- for (const directory of directories) {
161
- const entry = directory.entry
162
- const exclude = directory.exclude || []
163
- await runFiles(directory, entry, exclude)
164
- }
165
- return
166
- }
167
-
168
- async function runFiles(directory, entry, exclude, Path, directoryName) {
169
- const entryPath = path.resolve(configDirectoryPath, entry)
170
- let files = fs.readdirSync(entryPath);
171
-
172
- for (let file of files) {
173
- let skip = false
174
- for (let i = 0; i < exclude.length; i++) {
175
- if (file.includes(exclude)) {
176
- skip = true
177
- break;
178
- }
179
- }
180
- if (skip) continue
181
-
182
- let isDirectory
183
- let isSymlink = fs.lstatSync(`${entryPath}/${file}`).isSymbolicLink()
184
- if (isSymlink) {
185
- let symlinkPath = await realpathAsync(`${entryPath}/${file}`)
186
- isDirectory = fs.existsSync(symlinkPath) && fs.lstatSync(symlinkPath).isDirectory()
187
- } else
188
- isDirectory = fs.existsSync(`${entryPath}/${file}`) && fs.lstatSync(`${entryPath}/${file}`).isDirectory()
189
-
190
- let name = file
191
- let source = ''
192
-
193
- for (let i = 0; i < match.length; i++) {
194
- skip = true
195
- const filePath = path.resolve(entryPath, file);
196
- if (filePath.startsWith(match[i])) {
197
- skip = false
198
- break;
199
- } else if (isDirectory && match[i].startsWith(filePath)) {
200
- skip = 'directory'
201
- break;
202
- }
203
- }
204
-
205
- if (skip === true) continue
206
-
207
- const fileExtension = path.extname(file);
208
- let mimeType = mimeTypes[fileExtension]
209
-
210
- if (!directoryName) {
211
- if (directory.object && directory.object.directory) {
212
- if (directory.object.directory === "{{directory}}") {
213
- directoryName = entry.split('/')
214
- directoryName = directoryName[directoryName.length - 1]
215
- } else
216
- directoryName = directory.object.directory
217
- } else
218
- directoryName = '/'
219
- }
220
-
221
- if (exclude && exclude.includes(directoryName)) continue
222
-
223
- if (!Path) {
224
- if (directoryName === '/')
225
- Path = directoryName
226
- else
227
- Path = '/' + directoryName
228
- }
229
-
230
- let pathname
231
- if (Path === '/')
232
- pathname = Path + name;
233
- else
234
- pathname = Path + '/' + name;
235
-
236
- if (isDirectory)
237
- mimeType = "text/directory"
238
- else
239
- source = await getSource(`${entryPath}/${file}`, mimeType, isSymlink)
240
-
241
- let values = {
242
- '{{name}}': name || '',
243
- '{{source}}': source || '',
244
- '{{directory}}': directoryName || '',
245
- '{{path}}': Path || '',
246
- '{{pathname}}': pathname,
247
- '{{content-type}}': mimeType || ''
248
- }
249
-
250
- let object = { ...directory.object }
251
- if (!object.name)
252
- object.name = "{{name}}"
253
- if (!object.src)
254
- object.src = "{{source}}"
255
- if (!object.directory)
256
- object.directory = "{{directory}}"
257
- if (!object.path)
258
- object.path = "{{path}}"
259
- if (!object.pathname)
260
- object.pathname = "{{pathname}}"
261
- if (!object["content-type"])
262
- object["content-type"] = '{{content-type}}'
263
- if (!object.public && object.public != false && object.public != 'false')
264
- object.public = 'true'
265
-
266
- let newObject = {
267
- array: directory.array || 'files',
268
- object
269
- }
270
-
271
- if (directory.storage)
272
- newObject.storage = directory.storage
273
- if (directory.database)
274
- newObject.database = directory.database
275
- if (directory.array)
276
- newObject.array = directory.array || 'files'
277
-
278
- for (const key of Object.keys(directory.object)) {
279
- if (typeof directory.object[key] == 'string') {
280
-
281
- let variables = directory.object[key].match(/{{([A-Za-z0-9_.,\[\]\-\/ ]*)}}/g);
282
- if (variables) {
283
- for (let variable of variables) {
284
- newObject.object[key] = newObject.object[key].replace(variable, values[variable]);
285
- }
286
- }
287
-
288
- }
289
- }
290
-
291
-
292
- if (skip !== 'directory') {
293
- if (!newObject.object._id)
294
- newObject.$filter = {
295
- query: {
296
- pathname
297
- }
298
- }
299
-
300
- response = await runStore(newObject);
301
- console.log(`Uploaded: ${entryPath}/${file}`, `To: ${pathname}`)
302
-
303
- if (response.error)
304
- errorLog.push(response.error)
305
- }
306
-
307
- if (isDirectory && pathname) {
308
- let newEntry
309
- if (entry.endsWith("/"))
310
- newEntry = entry + name
311
- else
312
- newEntry = entry + '/' + name
313
-
314
- await runFiles(directory, newEntry, exclude, pathname, name)
315
- }
316
- }
317
- // if (errorLog.length)
318
- // console.log(...errorLog)
319
-
320
- }
321
-
322
-
323
- async function getSource(path, mimeType, isSymlink) {
324
- let readType = 'utf8'
325
- if (mimeType === 'image/svg+xml') {
326
- readType = 'utf8';
327
- } else if (/^(image|audio|video)\/[-+.\w]+/.test(mimeType)) {
328
- readType = 'base64';
329
- }
330
-
331
- if (isSymlink)
332
- path = await realpathAsync(path)
333
-
334
- let binary = fs.readFileSync(path);
335
- let content = new Buffer.from(binary).toString(readType);
336
-
337
- return content;
338
- }
339
-
340
- /**
341
- * Store files by config sources
342
- **/
343
- async function runSources() {
344
- let updatedSources = [];
345
-
346
- for (let i = 0; i < sources.length; i++) {
347
- const { array, object } = sources[i];
348
-
349
- let source = { ...sources[i] };
350
- let keys = new Map()
351
- let response = {};
352
- let isMatch = false
353
-
354
- try {
355
- if (array) {
356
- if (!object)
357
- object = {};
358
- else
359
- for (const key of Object.keys(object)) {
360
- if (typeof object[key] != 'string')
361
- continue
362
-
363
- let variables = object[key].match(/{{([A-Za-z0-9_.,\[\]\-\/ ]*)}}/g);
364
- if (variables) {
365
- let originalValue = object[key]
366
- keys.set(key, originalValue)
367
- let value = ""
368
- for (let variable of variables) {
369
- let entry = /{{\s*([\w\W]+)\s*}}/g.exec(variable);
370
- entry = entry[1].trim()
371
- if (entry) {
372
- if (!fs.existsSync(entry))
373
- continue
374
-
375
- if (!isMatch) {
376
- const filePath = path.resolve(configDirectoryPath, entry);
377
- for (let i = 0; i < match.length; i++) {
378
- if (filePath.startsWith(match[i])) {
379
- console.log('Source saved', sources[i])
380
- isMatch = true
381
- break;
382
- }
383
- }
384
- }
385
-
386
- let read_type = 'utf8'
387
- const fileExtension = path.extname(entry);
388
- let mime_type = mimeTypes[fileExtension] || 'text/html'
389
-
390
- if (/^(image|audio|video)\/[-+.\w]+/.test(mime_type)) {
391
- read_type = 'base64'
392
- }
393
-
394
- let binary = fs.readFileSync(entry);
395
- let content = new Buffer.from(binary).toString(read_type);
396
- if (content)
397
- value += content
398
- // object[key] = object[key].replace(variable, content);
399
- }
400
- }
401
- object[key] = value
402
- }
403
-
404
- }
405
-
406
- let data = { array, object }
407
- if (!object._id && object.pathname)
408
- data.$filter = {
409
- query: {
410
- $or: [{ pathname: object.pathname }]
411
- }
412
- }
413
-
414
- if (match.length && isMatch)
415
- response = await runStore(data);
416
- }
417
- } catch (err) {
418
- console.log(err)
419
- process.exit()
420
- }
421
-
422
- if (response.object && response.object[0] && response.object[0]._id) {
423
- source.object._id = response.object[0]._id
424
- }
425
-
426
- for (const [key, value] of keys) {
427
- source.object[key] = value
428
- }
429
-
430
- updatedSources.push(source)
431
- }
432
-
433
- return updatedSources
434
- }
435
-
436
-
437
- async function runStore(data) {
438
- try {
439
- let response;
440
- if (!data.object._id && !data.$filter) {
441
- response = await crud.send({
442
- method: 'object.create',
443
- ...config,
444
- ...data
445
- })
446
- } else {
447
- response = await crud.send({
448
- method: 'object.update',
449
- ...config,
450
- ...data,
451
- upsert: true
452
- })
453
- }
454
- if (response) {
455
- return response;
456
- }
457
- } catch (err) {
458
- console.log(err);
459
- return null;
460
- }
461
- }
462
-
463
- async function run() {
464
- if (directories)
465
- await runDirectories()
466
-
467
- if (sources && sources.length) {
468
- let sources = await runSources()
469
- let newConfig = { ...CoCreateConfig }
470
- if (directories && directories.length)
471
- newConfig.directories = directories
472
-
473
- newConfig.sources = sources
474
-
475
- if (newConfig.repositories)
476
- newConfig.repositories.forEach(obj => {
477
- for (const key in obj) {
478
- if (!["path", "repo", "exclude"].includes(key)) {
479
- delete obj[key];
480
- }
481
- }
482
- });
483
-
484
- delete newConfig.url
485
- delete newConfig.broadcast
486
-
487
- fs.writeFileSync(configPath, `module.exports = ${JSON.stringify(newConfig, null, 4)};`);
488
- }
489
-
490
- if (!match.length) {
491
- console.log('upload complete!');
492
-
493
- setTimeout(function () {
494
- process.exit()
495
- }, 2000)
496
- }
497
- }
498
-
499
- run()
500
- }
87
+ let directories = CoCreateConfig.directories;
88
+ let sources = CoCreateConfig.sources;
89
+ let configDirectoryPath = path.dirname(configPath);
90
+
91
+ if (match && !Array.isArray(match)) match = [match];
92
+ else if (!match) match = [];
93
+
94
+ let config = await Config(
95
+ {
96
+ organization_id: {
97
+ prompt: "Enter your organization_id: "
98
+ },
99
+ host: {
100
+ prompt: "Enter the host: "
101
+ },
102
+ prompt: {
103
+ prompt: "Choose an authentication option: \n1.apikey\n2.Sign In\n",
104
+ choices: {
105
+ 1: {
106
+ apikey: {
107
+ prompt: "Enter your apikey: "
108
+ }
109
+ },
110
+ 2: {
111
+ email: {
112
+ prompt: "Enter your email: "
113
+ },
114
+ password: {
115
+ prompt: "Enter your password: "
116
+ }
117
+ }
118
+ }
119
+ }
120
+ },
121
+ null,
122
+ null,
123
+ configPath
124
+ );
125
+
126
+ if (
127
+ !config.organization_id ||
128
+ (!config.apikey && (!config.password || config.email))
129
+ ) {
130
+ console.log("One or more required config params could not be found");
131
+ process.exit();
132
+ }
133
+
134
+ if (config.email && config.password) {
135
+ let request = {
136
+ method: "signIn",
137
+ array: "users",
138
+ $filter: {
139
+ query: {
140
+ email: config.email,
141
+ password: config.password
142
+ }
143
+ },
144
+ ...config
145
+ };
146
+
147
+ let response = await crud.send(request);
148
+ let { success, token } = response;
149
+
150
+ if (success) {
151
+ console.log("succesful sign in");
152
+ // apply token to socket
153
+ } else {
154
+ console.log("The email or password you entered is incorrect");
155
+ process.exit();
156
+ }
157
+ }
158
+
159
+ // console.log('Uploading files...')
160
+
161
+ /**
162
+ * Store files by config directories
163
+ **/
164
+ let errorLog = [];
165
+
166
+ async function runDirectories() {
167
+ for (const directory of directories) {
168
+ const entry = directory.entry;
169
+ const exclude = directory.exclude || [];
170
+ await runFiles(directory, entry, exclude);
171
+ }
172
+ return;
173
+ }
174
+
175
+ async function runFiles(directory, entry, exclude, Path, directoryName) {
176
+ const entryPath = path.resolve(configDirectoryPath, entry);
177
+ let files = fs.readdirSync(entryPath);
178
+
179
+ for (let file of files) {
180
+ let skip = false;
181
+ for (let i = 0; i < exclude.length; i++) {
182
+ if (file.includes(exclude)) {
183
+ skip = true;
184
+ break;
185
+ }
186
+ }
187
+ if (skip) continue;
188
+
189
+ let isDirectory;
190
+ let isSymlink = fs
191
+ .lstatSync(`${entryPath}/${file}`)
192
+ .isSymbolicLink();
193
+ if (isSymlink) {
194
+ let symlinkPath = await realpathAsync(`${entryPath}/${file}`);
195
+ isDirectory =
196
+ fs.existsSync(symlinkPath) &&
197
+ fs.lstatSync(symlinkPath).isDirectory();
198
+ } else
199
+ isDirectory =
200
+ fs.existsSync(`${entryPath}/${file}`) &&
201
+ fs.lstatSync(`${entryPath}/${file}`).isDirectory();
202
+
203
+ let name = file;
204
+ let source = "";
205
+
206
+ for (let i = 0; i < match.length; i++) {
207
+ skip = true;
208
+ const filePath = path.resolve(entryPath, file);
209
+ if (filePath.startsWith(match[i])) {
210
+ skip = false;
211
+ break;
212
+ } else if (isDirectory && match[i].startsWith(filePath)) {
213
+ skip = "directory";
214
+ break;
215
+ }
216
+ }
217
+
218
+ if (skip === true) continue;
219
+
220
+ const fileExtension = path.extname(file);
221
+ let mimeType = mimeTypes[fileExtension];
222
+
223
+ if (!directoryName) {
224
+ if (directory.object && directory.object.directory) {
225
+ if (directory.object.directory === "{{directory}}") {
226
+ directoryName = entry.split("/");
227
+ directoryName = directoryName[directoryName.length - 1];
228
+ } else directoryName = directory.object.directory;
229
+ } else directoryName = "/";
230
+ }
231
+
232
+ if (exclude && exclude.includes(directoryName)) continue;
233
+
234
+ if (!Path) {
235
+ if (directoryName === "/") Path = directoryName;
236
+ else Path = "/" + directoryName;
237
+ }
238
+
239
+ let pathname;
240
+ if (Path === "/") pathname = Path + name;
241
+ else pathname = Path + "/" + name;
242
+
243
+ if (isDirectory) mimeType = "text/directory";
244
+ else
245
+ source = await getSource(
246
+ `${entryPath}/${file}`,
247
+ mimeType,
248
+ isSymlink
249
+ );
250
+
251
+ let values = {
252
+ "{{name}}": name || "",
253
+ "{{source}}": source || "",
254
+ "{{directory}}": directoryName || "",
255
+ "{{path}}": Path || "",
256
+ "{{pathname}}": pathname,
257
+ "{{content-type}}": mimeType || ""
258
+ };
259
+
260
+ let object = { ...directory.object };
261
+ if (!object.name) object.name = "{{name}}";
262
+ if (!object.src) object.src = "{{source}}";
263
+ if (!object.directory) object.directory = "{{directory}}";
264
+ if (!object.path) object.path = "{{path}}";
265
+ if (!object.pathname) object.pathname = "{{pathname}}";
266
+ if (!object["content-type"])
267
+ object["content-type"] = "{{content-type}}";
268
+ if (
269
+ !object.public &&
270
+ object.public != false &&
271
+ object.public != "false"
272
+ )
273
+ object.public = "true";
274
+
275
+ let newObject = {
276
+ array: directory.array || "files",
277
+ object
278
+ };
279
+
280
+ if (directory.storage) newObject.storage = directory.storage;
281
+ if (directory.database) newObject.database = directory.database;
282
+ if (directory.array) newObject.array = directory.array || "files";
283
+
284
+ for (const key of Object.keys(directory.object)) {
285
+ if (typeof directory.object[key] == "string") {
286
+ let variables = directory.object[key].match(
287
+ /{{([A-Za-z0-9_.,\[\]\-\/ ]*)}}/g
288
+ );
289
+ if (variables) {
290
+ for (let variable of variables) {
291
+ newObject.object[key] = newObject.object[
292
+ key
293
+ ].replace(variable, values[variable]);
294
+ }
295
+ }
296
+ }
297
+ }
298
+
299
+ if (skip !== "directory") {
300
+ if (!newObject.object._id)
301
+ newObject.$filter = {
302
+ query: {
303
+ pathname
304
+ }
305
+ };
306
+
307
+ response = await runStore(newObject);
308
+ console.log(
309
+ `Uploaded: ${entryPath}/${file}`,
310
+ `To: ${pathname}`
311
+ );
312
+
313
+ if (response.error) errorLog.push(response.error);
314
+ }
315
+
316
+ if (isDirectory && pathname) {
317
+ let newEntry;
318
+ if (entry.endsWith("/")) newEntry = entry + name;
319
+ else newEntry = entry + "/" + name;
320
+
321
+ await runFiles(directory, newEntry, exclude, pathname, name);
322
+ }
323
+ }
324
+ // if (errorLog.length)
325
+ // console.log(...errorLog)
326
+ }
327
+
328
+ async function getSource(path, mimeType, isSymlink) {
329
+ let readType = "utf8";
330
+ if (mimeType === "image/svg+xml") {
331
+ readType = "utf8";
332
+ } else if (/^(image|audio|video)\/[-+.\w]+/.test(mimeType)) {
333
+ readType = "base64";
334
+ }
335
+
336
+ if (isSymlink) path = await realpathAsync(path);
337
+
338
+ let binary = fs.readFileSync(path);
339
+ let content = new Buffer.from(binary).toString(readType);
340
+
341
+ return content;
342
+ }
343
+
344
+ /**
345
+ * Store files by config sources
346
+ **/
347
+ async function runSources() {
348
+ let updatedSources = [];
349
+
350
+ for (let i = 0; i < sources.length; i++) {
351
+ const { array, object } = sources[i];
352
+
353
+ let source = { ...sources[i] };
354
+ let keys = new Map();
355
+ let response = {};
356
+ let isMatch = false;
357
+
358
+ try {
359
+ if (array) {
360
+ if (!object) object = {};
361
+ else
362
+ for (const key of Object.keys(object)) {
363
+ if (typeof object[key] != "string") continue;
364
+
365
+ let variables = object[key].match(
366
+ /{{([A-Za-z0-9_.,\[\]\-\/ ]*)}}/g
367
+ );
368
+ if (variables) {
369
+ let originalValue = object[key];
370
+ keys.set(key, originalValue);
371
+ let value = "";
372
+ for (let variable of variables) {
373
+ let entry = /{{\s*([\w\W]+)\s*}}/g.exec(
374
+ variable
375
+ );
376
+ entry = entry[1].trim();
377
+ if (entry) {
378
+ if (!fs.existsSync(entry)) continue;
379
+
380
+ if (!isMatch) {
381
+ const filePath = path.resolve(
382
+ configDirectoryPath,
383
+ entry
384
+ );
385
+ for (
386
+ let i = 0;
387
+ i < match.length;
388
+ i++
389
+ ) {
390
+ if (
391
+ filePath.startsWith(
392
+ match[i]
393
+ )
394
+ ) {
395
+ console.log(
396
+ "Source saved",
397
+ sources[i]
398
+ );
399
+ isMatch = true;
400
+ break;
401
+ }
402
+ }
403
+ }
404
+
405
+ let read_type = "utf8";
406
+ const fileExtension =
407
+ path.extname(entry);
408
+ let mime_type =
409
+ mimeTypes[fileExtension] ||
410
+ "text/html";
411
+
412
+ if (
413
+ /^(image|audio|video)\/[-+.\w]+/.test(
414
+ mime_type
415
+ )
416
+ ) {
417
+ read_type = "base64";
418
+ }
419
+
420
+ let binary = fs.readFileSync(entry);
421
+ let content = new Buffer.from(
422
+ binary
423
+ ).toString(read_type);
424
+ if (content) value += content;
425
+ // object[key] = object[key].replace(variable, content);
426
+ }
427
+ }
428
+ object[key] = value;
429
+ }
430
+ }
431
+
432
+ let data = { array, object };
433
+ if (!object._id && object.pathname)
434
+ data.$filter = {
435
+ query: {
436
+ $or: [{ pathname: object.pathname }]
437
+ }
438
+ };
439
+
440
+ if (match.length && isMatch)
441
+ response = await runStore(data);
442
+ }
443
+ } catch (err) {
444
+ console.log(err);
445
+ process.exit();
446
+ }
447
+
448
+ if (
449
+ response.object &&
450
+ response.object[0] &&
451
+ response.object[0]._id
452
+ ) {
453
+ source.object._id = response.object[0]._id;
454
+ }
455
+
456
+ for (const [key, value] of keys) {
457
+ source.object[key] = value;
458
+ }
459
+
460
+ updatedSources.push(source);
461
+ }
462
+
463
+ return updatedSources;
464
+ }
465
+
466
+ async function runStore(data) {
467
+ try {
468
+ let response;
469
+ if (!data.object._id && !data.$filter) {
470
+ response = await crud.send({
471
+ method: "object.create",
472
+ ...config,
473
+ ...data
474
+ });
475
+ } else {
476
+ response = await crud.send({
477
+ method: "object.update",
478
+ ...config,
479
+ ...data,
480
+ upsert: true
481
+ });
482
+ }
483
+ if (response) {
484
+ return response;
485
+ }
486
+ } catch (err) {
487
+ console.log(err);
488
+ return null;
489
+ }
490
+ }
491
+
492
+ async function run() {
493
+ if (directories) await runDirectories();
494
+
495
+ if (sources && sources.length) {
496
+ let sources = await runSources();
497
+ let newConfig = { ...CoCreateConfig };
498
+ if (directories && directories.length)
499
+ newConfig.directories = directories;
500
+
501
+ newConfig.sources = sources;
502
+
503
+ if (newConfig.repositories)
504
+ newConfig.repositories.forEach((obj) => {
505
+ for (const key in obj) {
506
+ if (!["path", "repo", "exclude"].includes(key)) {
507
+ delete obj[key];
508
+ }
509
+ }
510
+ });
511
+
512
+ delete newConfig.url;
513
+ delete newConfig.broadcast;
514
+
515
+ fs.writeFileSync(
516
+ configPath,
517
+ `module.exports = ${JSON.stringify(newConfig, null, 4)};`
518
+ );
519
+ }
520
+
521
+ if (!match.length) {
522
+ console.log("upload complete!");
523
+
524
+ setTimeout(function () {
525
+ process.exit();
526
+ }, 2000);
527
+ }
528
+ }
529
+
530
+ run();
531
+ };