@makano/rew 1.5.2 → 1.5.4

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.
@@ -6,7 +6,7 @@ const sleep = require('../functions/sleep');
6
6
  const { match } = require('../functions/match');
7
7
  const { map } = require('../functions/map');
8
8
  const { typex, typeis, typedef, typei, int, float, num, str, bool, typef } = require('../functions/types');
9
- const { isEmpty, clone, deepClone, merge, uniqueId, compose, curry, getters, setters } = require('../functions/core');
9
+ const { isEmpty, clone, deepClone, merge, uniqueId, compose, curry, getters, setters, deepMerge } = require('../functions/core');
10
10
  const { print, input, clear, printf } = require('../functions/stdout');
11
11
  const { curl } = require('../functions/curl');
12
12
  const { wait } = require('../functions/wait');
@@ -43,6 +43,7 @@ module.exports = {
43
43
  clone,
44
44
  deepClone,
45
45
  merge,
46
+ deepMerge,
46
47
  uniqueId,
47
48
  compose,
48
49
  curry,
@@ -1,3 +1,10 @@
1
1
  Function.prototype.wait = function(...args) {
2
2
  return wait(this, ...args);
3
- };
3
+ };
4
+ Object.without = function(object, ...keys){
5
+ let newObject = {...object};
6
+ for(let i = 0; i < keys.length; i++){
7
+ delete newObject[keys[i]];
8
+ }
9
+ return newObject;
10
+ }
@@ -34,6 +34,28 @@ function deepClone(value) {
34
34
  }
35
35
  }
36
36
 
37
+ function isObject(item) {
38
+ return (item && typeof item === 'object' && !Array.isArray(item));
39
+ }
40
+
41
+ function deepMerge(target, ...sources) {
42
+ if (!sources.length) return target;
43
+ const source = sources.shift();
44
+
45
+ if (isObject(target) && isObject(source)) {
46
+ for (const key in source) {
47
+ if (isObject(source[key])) {
48
+ if (!target[key]) Object.assign(target, { [key]: {} });
49
+ deepMerge(target[key], source[key]);
50
+ } else {
51
+ Object.assign(target, { [key]: source[key] });
52
+ }
53
+ }
54
+ }
55
+
56
+ return deepMerge(target, ...sources);
57
+ }
58
+
37
59
  function merge(obj1, obj2) {
38
60
  return Object.assign({}, obj1, obj2);
39
61
  }
@@ -100,6 +122,7 @@ module.exports = {
100
122
  clone,
101
123
  deepClone,
102
124
  merge,
125
+ deepMerge,
103
126
  uniqueId,
104
127
  filter,
105
128
  reduce,
@@ -410,4 +410,26 @@ module.exports = (context) => ({
410
410
  push: runePush,
411
411
  pop: runePop,
412
412
  createDB,
413
+ localState(name, options){
414
+ const map = this.db('_' + name).map('_' + name + '_map');
415
+ const firstValue = map.get(name);
416
+ const _set = () => {
417
+ let item = options.get();
418
+ if(item.then){
419
+ item.then((i) => map.set(i));
420
+ } else {
421
+ map.set(name, item);
422
+ }
423
+ }
424
+ if(!firstValue) {
425
+ _set();
426
+ } else {
427
+ options.set(firstValue);
428
+ }
429
+ if(options.trigger){
430
+ options.trigger(() => {
431
+ _set();
432
+ });
433
+ }
434
+ }
413
435
  });
@@ -7,6 +7,14 @@ module.exports = (context) => {
7
7
 
8
8
  let appOptions = {};
9
9
 
10
+ const additionalParams = {
11
+ text: svr.prototype.text,
12
+ html: svr.prototype.html,
13
+ status: svr.prototype.status,
14
+ json: svr.prototype.json,
15
+ error: svr.prototype.error
16
+ };
17
+
10
18
  const mkRouter = (options = {}) => svr.prototype.router({ type: 'auto', ...appOptions, ...options });
11
19
 
12
20
  class Events {
@@ -251,7 +259,7 @@ module.exports = (context) => {
251
259
  that.controller.register(method, _path, cb, middleWare);
252
260
  return cb;
253
261
  }
254
- const mkReq = (usage) => (req, ctx) => usage.call(req, req, ctx);
262
+ const mkReq = (usage) => (req, ...args) => usage.call(req, req, ...args);
255
263
  class SControllerContext extends Context('controller') {
256
264
 
257
265
  middleWares = [];
@@ -317,18 +325,21 @@ module.exports = (context) => {
317
325
  }
318
326
 
319
327
  function mkBody(req){
328
+ if(!req.data) return null;
320
329
  const type = req.headers.get('content-type');
321
330
  if(type == 'application/json'){
322
331
  return req.data.json();
323
- } else {
324
- try {
325
- return req.data.json();
326
- } catch(e){
327
- return req.data.text();
328
- }
332
+ } else if(type.startsWith('multipart/form-data')){
333
+ return req.data.multipart();
334
+ } else if(type == 'multipart/form-data'){
335
+ return req.data;
336
+ } else try {
337
+ return req.data.json();
338
+ } catch(e){
339
+ return req.data?.text();
329
340
  }
330
341
  }
331
-
342
+ let f;
332
343
  class SController extends Injectable {
333
344
 
334
345
  constructor(root){
@@ -341,14 +352,9 @@ module.exports = (context) => {
341
352
  return async (req, ctx) => {
342
353
  let context = {...{
343
354
  request: req,
355
+ params: req.params || {},
344
356
  body: mkBody(req)
345
- },...ctx, ...(cb.parent || {}), ...{
346
- text: svr.prototype.text,
347
- html: svr.prototype.html,
348
- status: svr.prototype.status,
349
- json: svr.prototype.json,
350
- error: svr.prototype.error
351
- }};
357
+ },...ctx, ...(cb.parent || {}), ...additionalParams};
352
358
  return await cb.call(context, ...Object.keys(context).map(i => context[i]));
353
359
  }
354
360
  }
@@ -30,7 +30,65 @@ module.exports = (context) => {
30
30
  return new Request(url, options);
31
31
  }
32
32
 
33
- function getBody(req){
33
+
34
+ function parseMultipart(req, content) {
35
+ const contentType = req.headers.get('content-type');
36
+ const boundary = contentType.split('boundary=')[1];
37
+ if (!boundary) throw new Error('No boundary in multipart/form-data');
38
+
39
+ const body = content;
40
+ const parts = body.split(`--${boundary}`).filter(part => part.trim() !== '--' && part.trim() !== '');
41
+
42
+ const fields = {};
43
+ const files = {};
44
+
45
+ parts.forEach(part => {
46
+ const [headers, ...content] = part.split('\r\n\r\n');
47
+ const contentBody = content.join('\r\n\r\n').trim();
48
+ const headerLines = headers.split('\r\n');
49
+
50
+ let name, filename, contentType;
51
+ headerLines.forEach(line => {
52
+ if (line.startsWith('Content-Disposition')) {
53
+ const matchName = /name="([^"]+)"/.exec(line);
54
+ const matchFilename = /filename="([^"]+)"/.exec(line);
55
+ if (matchName) name = matchName[1];
56
+ if (matchFilename) filename = matchFilename[1];
57
+ }
58
+ if (line.startsWith('Content-Type')) {
59
+ contentType = line.split(': ')[1];
60
+ }
61
+ });
62
+
63
+ if (filename) {
64
+ files[name] = {
65
+ filename,
66
+ contentType,
67
+ ...handleBuffer(Buffer.from(contentBody, 'binary'))
68
+ };
69
+ } else {
70
+ fields[name] = contentBody;
71
+ }
72
+ });
73
+
74
+ return { ...fields, ...files };
75
+ }
76
+
77
+ function handleBuffer(buffer){
78
+ return {
79
+ text(){
80
+ return buffer.toString();
81
+ },
82
+ json(){
83
+ return JSON.parse(buffer.toString());
84
+ },
85
+ buffer(){
86
+ return buffer;
87
+ }
88
+ }
89
+ }
90
+
91
+ function getBody(req, request){
34
92
  return new Promise((resolve, reject) => {
35
93
  const chunks = [];
36
94
 
@@ -41,14 +99,9 @@ module.exports = (context) => {
41
99
  req.on('end', () => {
42
100
  let buffer = chunks.length ? Buffer.concat(chunks) : null;
43
101
  resolve(buffer ? {
44
- text(){
45
- return buffer.toString();
46
- },
47
- json(){
48
- return JSON.parse(buffer.toString());
49
- },
50
- buffer(){
51
- return buffer;
102
+ ...handleBuffer(buffer),
103
+ multipart(){
104
+ return parseMultipart(request, buffer.toString());
52
105
  }
53
106
  } : null);
54
107
  });
@@ -81,7 +134,7 @@ module.exports = (context) => {
81
134
 
82
135
  context.getRealRequest = () => req;
83
136
 
84
- request.data = await getBody(req);
137
+ request.data = await getBody(req, request);
85
138
 
86
139
  if(this.options.fetch == 'router'){
87
140
  if(!Object.keys(this.options.routers).length) throw new Error('No fetch function nor routers found');
@@ -1,88 +1,170 @@
1
1
 
2
- module.exports = () => ((styles) => {
3
- let css = "";
4
- const variables = {};
5
- const mixins = {};
2
+ function normalizeCamelCase (camelCase) {
3
+ let all = "";
4
+ for(let i of camelCase){
5
+ if(i.match(/[A-Z]/)){
6
+ all += '-';
7
+ i = i.toLowerCase();
8
+ }
9
+ all += i;
10
+ }
11
+ if(all.startsWith('-')) all = all.slice(1);
12
+ return all;
13
+ }
14
+ const known_states = [
15
+ 'hover',
16
+ 'active',
17
+ 'focus',
18
+ 'focus-within',
19
+ 'focus-visible',
20
+ 'visited',
21
+ 'link',
22
+ 'disabled',
23
+ 'checked',
24
+ 'unchecked',
25
+ 'first-child',
26
+ 'last-child',
27
+ 'nth-child',
28
+ 'nth-of-type',
29
+ 'empty',
30
+ 'not',
31
+ 'before',
32
+ 'after',
33
+ 'first-of-type',
34
+ 'last-of-type',
35
+ 'only-child',
36
+ 'only-of-type',
37
+ 'valid',
38
+ 'invalid',
39
+ 'in-range',
40
+ 'out-of-range',
41
+ 'required',
42
+ 'optional',
43
+ 'disabled',
44
+ 'enabled',
45
+ 'enabled',
46
+ 'default',
47
+ 'selection',
48
+ 'target',
49
+ 'lang',
50
+ 'dir',
51
+ ];
52
+
6
53
 
7
- const parseValue = (v, self, name, vars) => {
8
- const vs = {...variables, ...vars, name, ...Object.fromEntries(Object.entries(self).map(i => ['prop_'+i[0], i[1]]))};
9
- return v.startsWith('@v') ? vs[v.split('@v')[1].trim()] : v
10
- .toString()
11
- .replace(/\$([A-Za-z0-9-_]+)/g, (_, name) => (vs)[name])
54
+ const parseValue = (O, v, self, name, vars) => {
55
+ const vs = {...O.variables, ...vars, name, ...Object.fromEntries(Object.entries(self).map(i => ['prop_'+i[0], i[1]]))};
56
+ return v.startsWith('@v') ? vs[v.split('@v')[1].trim()] : v
57
+ .toString()
58
+ .replace(/\$([A-Za-z0-9-_]+)/g, (_, name) => (vs)[name])
59
+ }
60
+
61
+ const declectProp = (O, value, name, selector, start, parent, self, vars = {}) => {
62
+ let prop = "";
63
+ self.__parent = parent;
64
+ if (typeof value == 'object') {
65
+ for (let state in value) {
66
+ if (state == 'default') {
67
+ prop += `\n${selector}{ ${name}: ${parseValue(O, value.default || 'unset', self, name, vars) + ';'} }`;
68
+ } else if (state.startsWith('@media')) {
69
+ prop += `\n${state} { ${selector}: ${parseValue(O, value[state], self, name, vars)}; }`
70
+ } else if (state.startsWith(':') || known_states.includes(state)) {
71
+ prop += `\n${selector}${!state.startsWith(':') ? ':' : ''}${state} { ${name}: ${parseValue(O, value[state], self, name, vars)}; }`
72
+ }
73
+ }
74
+ } else {
75
+ prop += `\n${selector}{ ${name}: `;
76
+ let v = parseValue(O, value, self, name, vars);
77
+ if(typeof v == 'object') return declectProp(v, name, selector, start, parent, self, vars);
78
+ prop += v + ';';
79
+ prop += '}\n';
12
80
  }
81
+ return prop;
82
+ }
83
+
84
+ const declectNames = (O, names, $name, parent, values = {}, free = true) => {
85
+ const start = $name && free ? $name + ' {' : '';
86
+ let nameStyles = "";
87
+ for (let name in names) {
88
+ let selector = name.replace(/,/g, ', &').replace(/&/g, $name || '');
89
+ if (name == '@variables') {
90
+ for (let i in names[name]) {
91
+ O.variables[i] = names[name][i];
92
+ }
93
+ } else if (name.startsWith('@mixin')) {
94
+ const mame = name.split('@mixin')[1].trim();
95
+ const mname = mame.split('(')[0];
96
+ const args = mame.replace(mname, '').slice(1, -1);
97
+ O.mixins[mname] = {
98
+ args: args.split(','),
99
+ value: names[name]
100
+ }
101
+ } else if (name.startsWith('@keyframes')) {
102
+ nameStyles += $name ? '' : name + '{';
13
103
 
14
- const declectProp = (value, name, selector, start, parent, self, vars = {}) => {
15
- let prop = `${name}: `;
16
- self.__parent = parent;
17
- if (typeof value == 'object') {
18
- prop += parseValue(value.default || 'unset', self, name, vars) + ';';
19
- prop += '}\n';
20
- for (let state in value) {
21
- if (state == 'default') continue;
22
- else if (state.startsWith('@media')) {
23
- prop += `${state} { ${start} ${name}: ${parseValue(value[state], self, name, vars)}; } }\n`
24
- } else if (state.startsWith(':')) {
25
- prop += `${selector}${state} { ${name}: ${parseValue(value[state], self, name, vars)}; }\n`
104
+ for(let keyFrame in names[name]){
105
+ nameStyles += declectNames(O, names[name][keyFrame], keyFrame, names[name], values);
106
+ }
107
+
108
+ if(!$name) nameStyles += '}\n';
109
+ } else if ($name) {
110
+ if (name.startsWith('&')) {
111
+ nameStyles += '}\n';
112
+ nameStyles += declectNames(O, names[name], selector, names, values);
113
+ nameStyles += start;
114
+ } else if(name.startsWith('@include')) {
115
+ const mame = names[name];
116
+ const mname = mame.split('(')[0];
117
+ const args = mame.replace(mname, '').slice(1, -1).split(',');
118
+ if(O.mixins[mname]){
119
+ nameStyles += declectNames(O, O.mixins[mname].value, $name, parent, {...values, ...Object.fromEntries(O.mixins[mname].args.map((n, i) => [n, args[i]]))}, false).trim();
26
120
  }
121
+ } else {
122
+ nameStyles += declectProp(O, names[name], normalizeCamelCase(name), $name, start, parent || styles, names, values);
27
123
  }
28
- prop += start;
29
124
  } else {
30
- let v = parseValue(value, self, name, vars);
31
- if(typeof v == 'object') return declectProp(v, name, selector, start, parent, self, vars);
32
- prop += v + ';';
125
+ nameStyles += declectNames(O, names[name], selector, names, values);
33
126
  }
34
- return prop;
35
127
  }
128
+ return nameStyles;
129
+ }
36
130
 
37
- const declectNames = (names, $name, parent, values = {}) => {
38
- const start = $name ? $name + ' {' : '';
39
- let nameStyles = start;
40
- for (let name in names) {
41
- let selector = name.replace(/,/g, ', &').replace(/&/g, $name || '');
42
- if (name == '@variables') {
43
- for (let i in names[name]) {
44
- variables[i] = names[name][i];
45
- }
46
- } else if (name.startsWith('@mixin')) {
47
- const mame = name.split('@mixin')[1].trim();
48
- const mname = mame.split('(')[0];
49
- const args = mame.replace(mname, '').slice(1, -1);
50
- mixins[mname] = {
51
- args: args.split(','),
52
- value: names[name]
53
- }
54
- } else if (name.startsWith('@keyframes')) {
55
- nameStyles += $name ? '' : name + '{';
131
+ const collectAndCleanUp = (css) => {
132
+ const selectorMap = {};
133
+ const cleanedCSS = [];
56
134
 
57
- for(let keyFrame in names[name]){
58
- nameStyles += declectNames(names[name][keyFrame], keyFrame, names[name], values);
59
- }
135
+ const lines = css.split('\n');
60
136
 
61
- if(!$name) nameStyles += '}\n';
62
- } else if ($name) {
63
- if (name.startsWith('&')) {
64
- nameStyles += '}\n';
65
- nameStyles += declectNames(names[name], selector, names, values);
66
- nameStyles += start;
67
- } else if(name.startsWith('@include')) {
68
- const mame = names[name];
69
- const mname = mame.split('(')[0];
70
- const args = mame.replace(mname, '').slice(1, -1).split(',');
71
- if(mixins[mname]){
72
- nameStyles += declectNames(mixins[mname].value, selector, names, {...values, ...Object.fromEntries(mixins[mname].args.map((n, i) => [n, args[i]]))}).trim().replace('@include ', '').slice(1, -1);
73
- }
74
- } else {
75
- nameStyles += declectProp(names[name], name, $name, start, parent || styles, names, values);
76
- }
77
- } else {
78
- nameStyles += declectNames(names[name], selector, names, values);
137
+ lines.forEach(line => {
138
+ const match = line.match(/([^\{]+){(.+)}/);
139
+ if (match) {
140
+ const selector = match[1].trim();
141
+
142
+ if (!selectorMap[selector]) {
143
+ selectorMap[selector] = "";
79
144
  }
145
+
146
+ selectorMap[selector] += match[2];
80
147
  }
81
- if ($name) nameStyles += '}\n';
82
- return nameStyles;
148
+ });
149
+
150
+ for (const selector in selectorMap) {
151
+ const selectorBlock = selectorMap[selector];
152
+ cleanedCSS.push(`${selector} { ${selectorBlock} }`);
83
153
  }
84
154
 
85
- css += declectNames(styles);
155
+ return cleanedCSS.join('\n');
156
+ };
157
+
158
+
159
+ module.exports = () => ((styles) => {
160
+ let css = "";
161
+ const variables = {};
162
+ const mixins = {};
163
+
164
+ css += declectNames({
165
+ variables,
166
+ mixins
167
+ }, styles);
86
168
 
87
- return css.replace(/(.+) \{\}/g, '');
169
+ return collectAndCleanUp(css);
88
170
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@makano/rew",
3
- "version": "1.5.2",
3
+ "version": "1.5.4",
4
4
  "description": "A simple coffescript runtime and app manager",
5
5
  "main": "main.js",
6
6
  "directories": {