@radiantabyss/neutralino 1.0.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/package.json +32 -0
- package/src/Bootstrap.js +31 -0
- package/src/ContextMenu.js +18 -0
- package/src/IPC.js +28 -0
- package/src/Invoke.js +13 -0
- package/src/Models.js +19 -0
- package/src/Request.js +173 -0
- package/src/Response.js +15 -0
- package/src/Routing/Actions.js +47 -0
- package/src/Routing/Middleware.js +45 -0
- package/src/Routing/Route.js +84 -0
- package/src/Routing/RouteCrud.js +19 -0
- package/src/Routing/RouteFiles.js +1 -0
- package/src/Routing/Router.js +109 -0
- package/src/Support/Config.js +40 -0
- package/src/Support/Env.js +46 -0
- package/src/Support/Helpers.js +98 -0
- package/src/Support/Item.js +63 -0
- package/src/Support/Items.js +363 -0
- package/src/Support/Str.js +209 -0
- package/src/Validator.js +27 -0
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@radiantabyss/neutralino",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"author": "radiantabyss.com",
|
|
5
|
+
"license": "ISC",
|
|
6
|
+
"eslintConfig": {
|
|
7
|
+
"root": true,
|
|
8
|
+
"env": {
|
|
9
|
+
"node": true
|
|
10
|
+
},
|
|
11
|
+
"extends": [
|
|
12
|
+
"eslint:recommended"
|
|
13
|
+
],
|
|
14
|
+
"rules": {},
|
|
15
|
+
"parserOptions": {
|
|
16
|
+
"parser": "babel-eslint"
|
|
17
|
+
},
|
|
18
|
+
"globals": {
|
|
19
|
+
"Alert": "writable",
|
|
20
|
+
"Cookie": "writable",
|
|
21
|
+
"Item": "writable",
|
|
22
|
+
"Items": "writable",
|
|
23
|
+
"Request": "writable",
|
|
24
|
+
"Response": "writable"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"type": "module",
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"axios": "1.7.*",
|
|
30
|
+
"validatorjs": "3.22.1"
|
|
31
|
+
}
|
|
32
|
+
}
|
package/src/Bootstrap.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import Request from './Request.js';
|
|
2
|
+
import Response from './Response.js';
|
|
3
|
+
import Invoke from './Invoke.js';
|
|
4
|
+
import Validator from './Validator.js';
|
|
5
|
+
import IPC from './IPC.js';
|
|
6
|
+
|
|
7
|
+
import Config from './Support/Config.js';
|
|
8
|
+
import Env from './Support/Env.js';
|
|
9
|
+
import Helpers from './Support/Helpers.js';
|
|
10
|
+
import Item from './Support/Item.js';
|
|
11
|
+
import Items from './Support/Items.js';
|
|
12
|
+
import Str from './Support/Str.js';
|
|
13
|
+
|
|
14
|
+
export default async () => {
|
|
15
|
+
//helpers
|
|
16
|
+
for ( let key in Helpers ) {
|
|
17
|
+
window[key] = Helpers[key];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
window.Config = Config;
|
|
21
|
+
window.Env = Env;
|
|
22
|
+
window.Item = Item;
|
|
23
|
+
window.Items = Items;
|
|
24
|
+
window.Str = Str;
|
|
25
|
+
|
|
26
|
+
window.Request = Request;
|
|
27
|
+
window.Response = Response;
|
|
28
|
+
window.Invoke = Invoke;
|
|
29
|
+
window.Validator = Validator;
|
|
30
|
+
window.IPC = IPC;
|
|
31
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
let ContextMenuActions = {};
|
|
2
|
+
let context = import.meta.glob('/app/ContextMenu/**/*.js');
|
|
3
|
+
|
|
4
|
+
//load context menu files
|
|
5
|
+
const loadModules = async () => {
|
|
6
|
+
const files = Object.keys(context);
|
|
7
|
+
|
|
8
|
+
for ( let i = 0; i < files.length; i++ ) {
|
|
9
|
+
let split = files[i].split('/');
|
|
10
|
+
let name = split[split.length - 1].replace('.js', '');
|
|
11
|
+
let module = await context[files[i]]();
|
|
12
|
+
ContextMenuActions[name] = module.default;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default async (list) => {
|
|
17
|
+
await loadModules();
|
|
18
|
+
};
|
package/src/IPC.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
let self = {
|
|
2
|
+
handlers: new Map(),
|
|
3
|
+
|
|
4
|
+
handle(channel, handler) {
|
|
5
|
+
self.handlers.set(channel, handler);
|
|
6
|
+
},
|
|
7
|
+
|
|
8
|
+
async invoke(channel, ...args) {
|
|
9
|
+
const handler = self.handlers.get(channel);
|
|
10
|
+
if ( !handler ) {
|
|
11
|
+
throw new Error(`No handler for channel: ${channel}`);
|
|
12
|
+
}
|
|
13
|
+
return await handler(...args);
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
send(channel, data) {
|
|
17
|
+
const event = new CustomEvent(channel, { detail: data });
|
|
18
|
+
window.dispatchEvent(event);
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
on(channel, callback) {
|
|
22
|
+
window.addEventListener(channel, (event) => {
|
|
23
|
+
callback(event.detail);
|
|
24
|
+
});
|
|
25
|
+
},
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export default self;
|
package/src/Invoke.js
ADDED
package/src/Models.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
let Model = {};
|
|
2
|
+
let context = import.meta.glob('/app/Models/**/*.js');
|
|
3
|
+
|
|
4
|
+
//load model files
|
|
5
|
+
const loadModules = async () => {
|
|
6
|
+
const files = Object.keys(context);
|
|
7
|
+
|
|
8
|
+
for ( let i = 0; i < files.length; i++ ) {
|
|
9
|
+
let split = files[i].split('/');
|
|
10
|
+
let name = split[split.length - 1].replace('.js', '');
|
|
11
|
+
let module = await context[files[i]]();
|
|
12
|
+
Model[name] = module.default;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default async () => {
|
|
17
|
+
await loadModules();
|
|
18
|
+
return Model;
|
|
19
|
+
};
|
package/src/Request.js
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
|
|
3
|
+
const formatErrors = function(response) {
|
|
4
|
+
let errors = [];
|
|
5
|
+
if ( response && response.errors ) {
|
|
6
|
+
for ( let i in response.errors ) {
|
|
7
|
+
if ( typeof response.errors[i] === 'object' ) {
|
|
8
|
+
for (let j in response.errors[i]) {
|
|
9
|
+
errors.push(response.errors[i][j]);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
errors.push(response.errors[i]);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
else if ( response.statusText ) {
|
|
18
|
+
errors.push(response.statusText);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return errors;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const serializeToURLEncoded = (obj, prefix) => {
|
|
25
|
+
const str = [];
|
|
26
|
+
for ( let p in obj ) {
|
|
27
|
+
if ( obj.hasOwnProperty(p) ) {
|
|
28
|
+
const key = prefix ? `${prefix}[${p}]` : p;
|
|
29
|
+
const value = obj[p];
|
|
30
|
+
|
|
31
|
+
if ( typeof value === "object" ) {
|
|
32
|
+
str.push(serializeToURLEncoded(value, key));
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
str.push(encodeURIComponent(key) + "=" + encodeURIComponent(value));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return str.join("&");
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const appendFormData = (formData, key, value) => {
|
|
43
|
+
if ( value instanceof Blob ) {
|
|
44
|
+
formData.append(key, value);
|
|
45
|
+
}
|
|
46
|
+
else if ( Array.isArray(value) ) {
|
|
47
|
+
value.forEach((v) => formData.append(`${key}[]`, v));
|
|
48
|
+
}
|
|
49
|
+
else if ( typeof value === 'object' && value !== null ) {
|
|
50
|
+
for ( let subKey in value ) {
|
|
51
|
+
appendFormData(formData, `${key}[${subKey}]`, value[subKey]);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
formData.append(key, value);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
axios.interceptors.request.use((request) => {
|
|
60
|
+
if (request.data ) {
|
|
61
|
+
if ( request.headers['Content-Type'] === 'application/x-www-form-urlencoded' ) {
|
|
62
|
+
request.data = serializeToURLEncoded(request.data).replace(/\&+$/, '');
|
|
63
|
+
}
|
|
64
|
+
else if ( request.headers['Content-Type'] === 'application/json' ) {
|
|
65
|
+
request.data = JSON.stringify(request.data);
|
|
66
|
+
request.headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return request;
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const request = function(method, edge, payload = {}, display_errors = false, base_url = null, auth_token = null, headers = {}, upload_progress = null) {
|
|
73
|
+
return new Promise((resolve, reject) => {
|
|
74
|
+
if ( !base_url ) {
|
|
75
|
+
base_url = process.env.BACK_URL;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if ( !auth_token ) {
|
|
79
|
+
auth_token = JWT_TOKEN;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if ( !Object.keys(headers).length ) {
|
|
83
|
+
headers = {
|
|
84
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
let data;
|
|
89
|
+
let url = base_url + edge;
|
|
90
|
+
|
|
91
|
+
if ( method === 'GET' ) {
|
|
92
|
+
url += '?' + new URLSearchParams(payload).toString();
|
|
93
|
+
}
|
|
94
|
+
else if ( method === 'POST' ) {
|
|
95
|
+
if ( headers['Content-Type'] === 'multipart/form-data' ) {
|
|
96
|
+
data = new FormData();
|
|
97
|
+
|
|
98
|
+
for (let key in payload) {
|
|
99
|
+
appendFormData(data, key, payload[key]);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
delete headers['Content-Type'];
|
|
103
|
+
}
|
|
104
|
+
else if ( headers['Content-Type'] === 'application/x-www-form-urlencoded' ) {
|
|
105
|
+
data = serializeToURLEncoded(payload).replace(/\&+$/, '');
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
data = JSON.stringify(payload);
|
|
109
|
+
headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if ( auth_token ) {
|
|
114
|
+
if ( typeof auth_token !== 'object' ) {
|
|
115
|
+
auth_token = { jwt_token: auth_token };
|
|
116
|
+
}
|
|
117
|
+
for ( let key in auth_token ) {
|
|
118
|
+
if ( auth_token[key] !== '' && auth_token[key] !== null ) {
|
|
119
|
+
url += url.includes('?') ? '&' : '?';
|
|
120
|
+
url += `${key}=${auth_token[key]}`;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
axios(url, {
|
|
126
|
+
headers,
|
|
127
|
+
method,
|
|
128
|
+
url,
|
|
129
|
+
data,
|
|
130
|
+
})
|
|
131
|
+
.then((request_response) => {
|
|
132
|
+
let response = request_response.data;
|
|
133
|
+
|
|
134
|
+
if ( response.success ) {
|
|
135
|
+
return resolve(response.data);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
let errors = formatErrors(response);
|
|
139
|
+
|
|
140
|
+
if ( display_errors ) {
|
|
141
|
+
ipc_send('request:error', errors.join('<br/>'));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
reject(response.data.errors);
|
|
145
|
+
})
|
|
146
|
+
.catch((error) => {
|
|
147
|
+
let errors = [error.message];
|
|
148
|
+
|
|
149
|
+
if ( display_errors ) {
|
|
150
|
+
ipc_send('request:error', errors.join('<br/>'));
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
reject(errors);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
let self = {
|
|
159
|
+
get(edge, payload = {}, display_errors = false, base_url = null, auth_token = null, headers = {}) {
|
|
160
|
+
return request('GET', edge, payload, display_errors, base_url, auth_token, headers);
|
|
161
|
+
},
|
|
162
|
+
|
|
163
|
+
post(edge, payload = {}, display_errors = true, base_url = null, auth_token = null, headers = {}) {
|
|
164
|
+
return request('POST', edge, payload, display_errors, base_url, auth_token, headers);
|
|
165
|
+
},
|
|
166
|
+
|
|
167
|
+
upload(edge, payload = {}, display_errors = true, upload_progress, base_url = null, auth_token = null, headers = {}) {
|
|
168
|
+
headers['Content-Type'] = 'multipart/form-data';
|
|
169
|
+
return request('POST', edge, payload, display_errors, base_url, auth_token, headers, upload_progress);
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
export default self;
|
package/src/Response.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
let Actions = {};
|
|
2
|
+
let context = import.meta.glob('/app/Domains/**/*.js');
|
|
3
|
+
|
|
4
|
+
const loadModules = async () => {
|
|
5
|
+
const files = Object.keys(context);
|
|
6
|
+
|
|
7
|
+
for ( let i = 0; i < files.length; i++ ) {
|
|
8
|
+
let split = files[i].split('/');
|
|
9
|
+
split.shift();
|
|
10
|
+
let name = split[split.length - 1].replace('.js', '');
|
|
11
|
+
split.pop();
|
|
12
|
+
split.pop();
|
|
13
|
+
split.shift();
|
|
14
|
+
split.shift();
|
|
15
|
+
|
|
16
|
+
if ( !name.match(/Action$/) || name == 'Action' ) {
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
let module = await context[files[i]]();
|
|
21
|
+
setNamespace(Actions, name, split, module);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function setNamespace(Actions, name, namespace, module) {
|
|
26
|
+
if ( !namespace.length ) {
|
|
27
|
+
Actions[name] = module.default;
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
let first = namespace[0].replace(/-/g, ' ').replace(/_/g, ' ').replace(/(^([a-zA-Z\p{M}]))|([ -][a-zA-Z\p{M}])/g,function(s) {
|
|
32
|
+
return s.toUpperCase();
|
|
33
|
+
}).replace(/ /g, '');
|
|
34
|
+
|
|
35
|
+
namespace.shift();
|
|
36
|
+
|
|
37
|
+
if ( !Actions[first] ) {
|
|
38
|
+
Actions[first] = {};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
setNamespace(Actions[first], name, namespace, module);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export default async () => {
|
|
45
|
+
await loadModules();
|
|
46
|
+
return Actions;
|
|
47
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// MIDDLEWARE IS NOT USED AT THE MOMENT
|
|
2
|
+
//
|
|
3
|
+
//
|
|
4
|
+
//
|
|
5
|
+
let Middleware = {};
|
|
6
|
+
let context = import.meta.glob('/app/Http/Middleware/**/*.js');
|
|
7
|
+
|
|
8
|
+
const loadModules = async () => {
|
|
9
|
+
const files = Object.keys(context);
|
|
10
|
+
|
|
11
|
+
for ( let i = 0; i < files.length; i++ ) {
|
|
12
|
+
let split = files[i].split('/');
|
|
13
|
+
let name = split[split.length - 1].replace('.js', '').replace('Middleware', '');
|
|
14
|
+
let module = await context[files[i]]();
|
|
15
|
+
Middleware[name] = module.default;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let runMiddleware = async (to, from, i = 0) => {
|
|
20
|
+
//reached end, then everything passed
|
|
21
|
+
if ( i == to.meta.middleware.length ) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
//middleware doesnt exist
|
|
26
|
+
if ( !Middleware[to.meta.middleware[i]] ) {
|
|
27
|
+
throw new Error(`${to.meta.middleware[i]} Middleware not found.`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
//run middleware
|
|
31
|
+
await Middleware[to.meta.middleware[i]](to, from);
|
|
32
|
+
await runMiddleware(to, from, i + 1);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export default async () => {
|
|
36
|
+
await loadModules();
|
|
37
|
+
|
|
38
|
+
return async (to, from) => {
|
|
39
|
+
if ( !to.meta || !to.meta.middleware ) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return runMiddleware(to, from);
|
|
44
|
+
};
|
|
45
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
let group_middleware = null;
|
|
2
|
+
|
|
3
|
+
function addRoute(method, path, action, middleware, name, throw_error) {
|
|
4
|
+
if ( !action ) {
|
|
5
|
+
throw `Action missing for ${path}`;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
//format path
|
|
9
|
+
path = path.replace(/\{([\s\S]+?)\}/g, ':$1');
|
|
10
|
+
|
|
11
|
+
//get action
|
|
12
|
+
action = action.replace(/\\/g, '.').replace(/\//g, '.');
|
|
13
|
+
let split = action.split('.');
|
|
14
|
+
let namespace = split.slice(0, -1);
|
|
15
|
+
let action_name = name || split[split.length - 1];
|
|
16
|
+
let domain = namespace.length ? Str.slug(namespace[0]) : '';
|
|
17
|
+
|
|
18
|
+
if ( namespace.length ) {
|
|
19
|
+
action_name = namespace.join('/') + '/' + action_name;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let component;
|
|
23
|
+
try {
|
|
24
|
+
component = getAction(Actions, split[split.length - 1], namespace, action_name);
|
|
25
|
+
}
|
|
26
|
+
catch(e) {
|
|
27
|
+
if ( throw_error ) {
|
|
28
|
+
throw `Action ${action_name} doesn't exist.`;
|
|
29
|
+
}
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
RouteFiles[__route_file].push({
|
|
34
|
+
name: action_name,
|
|
35
|
+
component,
|
|
36
|
+
path,
|
|
37
|
+
method,
|
|
38
|
+
meta: {
|
|
39
|
+
domain,
|
|
40
|
+
middleware,
|
|
41
|
+
settings: component.settings ? component.settings : {},
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function getAction(Actions, name, namespace, action_name) {
|
|
47
|
+
if ( !namespace.length ) {
|
|
48
|
+
let action = Actions[name];
|
|
49
|
+
|
|
50
|
+
action.name = action_name.replace(/\\/g, '.');
|
|
51
|
+
return action;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let first = namespace[0];
|
|
55
|
+
namespace.shift();
|
|
56
|
+
|
|
57
|
+
return getAction(Actions[first], name, namespace, action_name);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let self = {
|
|
61
|
+
get(path, action, middleware = [], name = '', throw_error = true) {
|
|
62
|
+
if ( group_middleware ) {
|
|
63
|
+
middleware = middleware.concat(group_middleware);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
addRoute('GET', path, action, middleware, name, throw_error);
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
post(path, action, middleware = [], name = '', throw_error = true) {
|
|
70
|
+
if ( group_middleware ) {
|
|
71
|
+
middleware = middleware.concat(group_middleware);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
addRoute('POST', path, action, middleware, name, throw_error);
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
group(middleware, callback) {
|
|
78
|
+
group_middleware = middleware;
|
|
79
|
+
callback();
|
|
80
|
+
group_middleware = null;
|
|
81
|
+
},
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export default self;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import Str from './../Support/Str';
|
|
2
|
+
|
|
3
|
+
let self = {
|
|
4
|
+
run(domain) {
|
|
5
|
+
domain = domain.replace(/\\/g, '.').replace(/\//g, '.');
|
|
6
|
+
let prefix = Str.kebab(domain).replace(/\./g, '/');
|
|
7
|
+
|
|
8
|
+
Route.get(`/${prefix}`, `${domain}/ListAction`, [], '', false);
|
|
9
|
+
Route.get(`/${prefix}/single/{id}`, `${domain}/SingleAction`, [], '', false);
|
|
10
|
+
Route.post(`/${prefix}/create`, `${domain}/CreateAction`, [], '', false);
|
|
11
|
+
Route.get(`/${prefix}/edit/{id}`, `${domain}/EditAction`, [], '', false);
|
|
12
|
+
Route.post(`/${prefix}/update/{id}`, `${domain}/UpdateAction`, [], '', false);
|
|
13
|
+
Route.post(`/${prefix}/patch/{id}`, `${domain}/PatchAction`, [], '', false);
|
|
14
|
+
Route.get(`/${prefix}/delete/{id}`, `${domain}/DeleteAction`, [], '', false);
|
|
15
|
+
Route.get(`/${prefix}/search`, `${domain}/SearchAction`, [], '', false);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default self;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default {};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import Actions from './Actions.js';
|
|
2
|
+
import Middleware from './Middleware.js';
|
|
3
|
+
import RouteFiles from './RouteFiles.js';
|
|
4
|
+
import Route from './Route.js';
|
|
5
|
+
import RouteCrud from './RouteCrud.js';
|
|
6
|
+
|
|
7
|
+
window.RouteFiles = RouteFiles;
|
|
8
|
+
window.Route = Route;
|
|
9
|
+
window.RouteCrud = RouteCrud;
|
|
10
|
+
|
|
11
|
+
let Routes = [];
|
|
12
|
+
|
|
13
|
+
//load route files
|
|
14
|
+
let context = import.meta.glob('/app/Routes/**/*.js');
|
|
15
|
+
|
|
16
|
+
const loadModules = async () => {
|
|
17
|
+
window.Actions = await Actions();
|
|
18
|
+
const files = Object.keys(context);
|
|
19
|
+
|
|
20
|
+
for ( let i = 0; i < files.length; i++ ) {
|
|
21
|
+
let file = files[i].replace('/app/Routes/', '').replace(/\.js$/, '');
|
|
22
|
+
window.__route_file = file;
|
|
23
|
+
|
|
24
|
+
if ( !RouteFiles[__route_file] ) {
|
|
25
|
+
RouteFiles[__route_file] = [];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
await context[files[i]]();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const match = async(args, event) => {
|
|
33
|
+
let matched = null;
|
|
34
|
+
let params = [];
|
|
35
|
+
|
|
36
|
+
//check for exact matches
|
|
37
|
+
for ( let Route of Routes ) {
|
|
38
|
+
if ( Route.path == args.path && Route.method == args.method ) {
|
|
39
|
+
matched = Route;
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
//check for routes with params
|
|
45
|
+
if ( !matched ) {
|
|
46
|
+
for ( let Route of Routes ) {
|
|
47
|
+
if ( !Route.path.match(/\{.*\}/) ) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
//check if route matches
|
|
52
|
+
let regex_string = Route.path.replace(/\{(.*?)\}/g, '([^\/]*?)') + '\/$';
|
|
53
|
+
let regex = new RegExp(regex_string, 'g');
|
|
54
|
+
|
|
55
|
+
//add trailing slash to path for regex
|
|
56
|
+
let path = args.path.replace(/\/$/, '') + '/';
|
|
57
|
+
let match = regex.exec(path);
|
|
58
|
+
if ( !match ) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
//check method
|
|
63
|
+
if ( Route.method != args.method ) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
matched = Route;
|
|
68
|
+
|
|
69
|
+
for (let i = 1; i < match.length; i++) {
|
|
70
|
+
params.push(match[i]);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
Invoke.data = args.payload;
|
|
76
|
+
params.push(event);
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
Route: matched,
|
|
80
|
+
params,
|
|
81
|
+
path: args.path,
|
|
82
|
+
payload: args.payload,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export default async () => {
|
|
87
|
+
// let runMiddleware = await Middleware();
|
|
88
|
+
await loadModules();
|
|
89
|
+
|
|
90
|
+
//handle route matching
|
|
91
|
+
window.IPC.handle('invoke', async (event, args) => {
|
|
92
|
+
args.payload = JSON.parse(args.payload);
|
|
93
|
+
|
|
94
|
+
let matched = await match(args, event);
|
|
95
|
+
if ( !matched.Route ) {
|
|
96
|
+
throw `Route ${matched.path} not found.`;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return await matched.Route.component.run(...matched.params);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
let Router = {
|
|
103
|
+
addRoute(Route) {
|
|
104
|
+
Routes.push(Route);
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
return { Router, RouteFiles };
|
|
109
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const self = {
|
|
2
|
+
async read(config) {
|
|
3
|
+
return JSON.parse(await Neutralino.filesystem.readFile(`${APP_PATH}/configs/${config}.json`));
|
|
4
|
+
},
|
|
5
|
+
|
|
6
|
+
async write(config, data) {
|
|
7
|
+
await Neutralino.filesystem.writeFile(`${APP_PATH}/configs/${config}.json`, JSON.stringify(data, null, 4));
|
|
8
|
+
},
|
|
9
|
+
|
|
10
|
+
get(config) {
|
|
11
|
+
return self.read(config);
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
getKey(config, key) {
|
|
15
|
+
let data = self.read(config);
|
|
16
|
+
return data[key];
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
set(config, data) {
|
|
20
|
+
self.write(config, data);
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
setKey(config, key, value) {
|
|
24
|
+
let data = self.read(config);
|
|
25
|
+
data[key] = value;
|
|
26
|
+
self.write(config, data);
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
deleteKey(config, key) {
|
|
30
|
+
let data = self.read(config);
|
|
31
|
+
delete data[key];
|
|
32
|
+
self.write(config, data);
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
clear(config) {
|
|
36
|
+
self.write(config, {});
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export default self;
|