@makano/rew 1.4.0 → 1.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,5 @@
1
1
  const emitter = require('./emitter');
2
+ const { wait } = require('./wait');
2
3
 
3
4
  function future(callback, timeout = 0, defData = null) {
4
5
  const listener = emitter();
@@ -19,6 +20,8 @@ function future(callback, timeout = 0, defData = null) {
19
20
  resolve: (data) => listener.emit('resolve', data),
20
21
  reject: (data) => listener.emit('reject', data),
21
22
  wait: async () => await promise,
23
+ sync: (fn) => wait(async () => fn ? (await fn(promise)) : await promise),
24
+ _isfuture: true
22
25
  };
23
26
  };
24
27
 
@@ -117,6 +117,7 @@ module.exports.imp = function (runPath, context) {
117
117
  const pkg = getPackage(filename)(context, options);
118
118
  exports = pkg._onImport ? pkg._onImport() : pkg;
119
119
  if(options.useDefaultForPackages) exports = { default: exports };
120
+ // console.log(exports, options.useDefaultForPackages);
120
121
  } else if (foundCache) {
121
122
  } else if (type == REW_FILE_TYPE.TYPE || type == "coffee") {
122
123
  exports = exec({});
@@ -3,11 +3,21 @@ const deasync = require("deasync");
3
3
 
4
4
  module.exports.wait = (...args) => {
5
5
  const fn = args.shift();
6
- if(typeof fn !== "function") throw new TypeError("The first argument must be a function to use wait.");
6
+ if(typeof fn !== "function" && typeof fn?.then != "function" && !fn?._isfuture) throw new TypeError("The first argument must be a function, future or a Promise to use wait.");
7
7
  const df = deasync(async (cb) => {
8
- fn(...args)
9
- .then(d => cb(null, d))
10
- .catch(d => cb(d));
8
+ let result = typeof fn == "function" ? fn(...args) : fn;
9
+
10
+ if(result._isfuture){
11
+ result = result.wait();
12
+ }
13
+
14
+ if(typeof result.then == "function"){
15
+ result
16
+ .then(d => cb(null, d))
17
+ .catch(d => cb(d));
18
+ } else {
19
+ cb(null, result);
20
+ }
11
21
  });
12
22
  return df();
13
23
  }
@@ -497,6 +497,7 @@ function compileRewStuff(content, options) {
497
497
  straceLog('==> WARN: SLOWS DOWN COMPILATION');
498
498
  let ind = i + n + 2;
499
499
  let isAs = false;
500
+ let usedDefault = false;
500
501
 
501
502
  let defaultName;
502
503
  if (nextToken.type === 'STRING') {
@@ -514,7 +515,7 @@ function compileRewStuff(content, options) {
514
515
  if(next?.token?.value == 'as'){
515
516
  const ebraceOpen = gnextToken(next.token.ti, 1, tokens);
516
517
  const ebraceClose = fnextToken(ebraceOpen.ti, tokens, 'OTHER', ')');
517
- const exportsTokens = tokens.slice(ebraceOpen.ti+1, ebraceClose.ti);
518
+ const exportsTokens = tokens.slice(ebraceOpen.ti+1, ebraceClose?.ti);
518
519
  exports = mapTokensToStrings(exportsTokens.filter(token => token.type !== 'WHITESPACE'));
519
520
  lastindex = ebraceClose.ti;
520
521
  } else lastindex = closingBraceToken.ti;
@@ -573,10 +574,12 @@ function compileRewStuff(content, options) {
573
574
  if(useImp(nameToken, options)) updateAliases(aliases);
574
575
  result += `{ default: ${defaultName}, ${exports} } ${options.type == 'coffee' ? '=' : ':='} inc ${nameToken?.value || ''}`;
575
576
  i = closingBraceToken.ti + 4;
577
+ usedDefault = true;
576
578
  }
577
579
  } else {
578
580
  if(useImp(nameToken || {}, options)) updateAliases(aliases);
579
581
  result += `{ default: ${defaultName} } ${options.type == 'coffee' ? '=' : ':='} inc ${nameToken?.value || ''}`;
582
+ usedDefault = true;
580
583
  i = ind + 2;
581
584
  }
582
585
  }
@@ -590,14 +593,14 @@ function compileRewStuff(content, options) {
590
593
  if(assertionToken.token.type == 'OTHER' && assertionToken.token.value == '{'){
591
594
  hooks.push({
592
595
  index: assertionToken.token.ti,
593
- value: ' useDefaultForPackages: '+(isAs?'false':'true')+', '
596
+ value: ' useDefaultForPackages: '+(isAs?'false':usedDefault.toString())+', '
594
597
  })
595
598
  } else {
596
- result += 'useDefaultForPackages: '+(isAs?'false':'true')+', '
599
+ result += 'useDefaultForPackages: '+(isAs?'false':usedDefault.toString())+', '
597
600
  }
598
601
  i += 3;
599
602
  } else {
600
- result += ", { useDefaultForPackages: "+(isAs?'false':'true')+" }"
603
+ result += ", { useDefaultForPackages: "+(isAs?'false':usedDefault.toString())+" }"
601
604
  }
602
605
 
603
606
  continue;
@@ -789,7 +792,7 @@ module.exports.compileFile = function (filepath, options = {}) {
789
792
  f.content = from_qrew(readFileSync(f.path), options.package || findAppInfo(filepath)?.config.manifest.package || path.basename(filepath).split('.').slice(0, -1).join('.')).toString();
790
793
  options.type = f.content.split('\n')[0]?.match(/"initFile (.+)"/)?.[1]?.split('.').pop();
791
794
  straceLog('QREW_DECODE() as', options.type, 'for CURRENTFILE');
792
- }
795
+ }
793
796
 
794
797
  let compiled_code = cpl(f, { ...options });
795
798
 
@@ -39,7 +39,10 @@ module.exports.prepareContext = function (
39
39
  app: findAppInfo(filepath),
40
40
  ...fsLib(filepath),
41
41
  ...reval(filepath),
42
- __using__: {}
42
+ __using__: {},
43
+ get _(){
44
+ return void 0;
45
+ }
43
46
  };
44
47
  if (options.useContext) {
45
48
  context = {
@@ -0,0 +1,402 @@
1
+ const { typex } = require("../const/default");
2
+ const emitter = require("../functions/emitter");
3
+ const path = require('path');
4
+
5
+ module.exports = (context) => {
6
+ const svr = context.imp('serve');
7
+
8
+ let appOptions = {};
9
+
10
+ const mkRouter = (options = {}) => svr.prototype.router({ type: 'auto', ...appOptions, ...options });
11
+
12
+ class Events {
13
+ target = emitter();
14
+ on(...args){
15
+ this.target.on(...args);
16
+ return this;
17
+ }
18
+ off(...args){
19
+ this.target.off(...args);
20
+ return this;
21
+ }
22
+ emit(...args){
23
+ this.target.emit(...args);
24
+ return this;
25
+ }
26
+ }
27
+
28
+ const Context = (name, inherit = []) => {
29
+ const ctxC = class Context {
30
+
31
+ constructor(item){
32
+ this[name] = item;
33
+ }
34
+
35
+ on(evt, cb){
36
+ this[name].on(evt, cb);
37
+ return this;
38
+ }
39
+
40
+ off(evt, cb){
41
+ this[name].off(evt, cb);
42
+ return this;
43
+ }
44
+
45
+ emit(evt, ...data){
46
+ this[name].emit(evt, ...data);
47
+ return this;
48
+ }
49
+ };
50
+
51
+ inherit?.forEach(fname => {
52
+ ctxC.prototype[fname] = function(...args){
53
+ this[name][fname](...args);
54
+ return this;
55
+ }
56
+ });
57
+
58
+ return ctxC;
59
+ }
60
+
61
+ class AppContext extends Context('app', ['start', 'redirect']) {
62
+ inject(item){
63
+ this.app.inject(item);
64
+ return this;
65
+ }
66
+
67
+ module(...items){
68
+ return this.inject(...items);
69
+ }
70
+ }
71
+
72
+ class ServeApp extends Events {
73
+ #injectables = [];
74
+ server;
75
+ router;
76
+
77
+ constructor(options){
78
+ super();
79
+ appOptions = options;
80
+ this.router = mkRouter(options);
81
+ this.server = svr.prototype.create({
82
+ fetch: this.router.fetch
83
+ });
84
+ }
85
+
86
+ /** @param {Injectable[]} injectables */
87
+ inject(...injectables){
88
+ injectables.filter(i => i instanceof Injectable)
89
+ .forEach(injectable => {
90
+ this.#injectables.push(injectable);
91
+ injectable.emit('activate', this);
92
+ this.emit('activate', this);
93
+ });
94
+ return this;
95
+ }
96
+
97
+ redirect(at = '*', router){
98
+ this.router.all(at, typeof router == 'function' ? router : router.fetch);
99
+ return this;
100
+ }
101
+
102
+ new(options = {}){
103
+ return (cb) => new context.Usage('', () => {
104
+ const app = new ServeApp(options);
105
+ const appContext = new AppContext(app);
106
+ cb.call(appContext);
107
+ return app;
108
+ });
109
+ }
110
+
111
+ raw(){
112
+ return context.using(this.new(() => {}));
113
+ }
114
+
115
+ #setup(){
116
+ this.#injectables
117
+ .filter(injectable => injectable instanceof SModule)
118
+ .forEach(module => {
119
+ /** @type {SController[]} */
120
+ const controllers = module.getControllers();
121
+ controllers.forEach(controller => {
122
+ // console.log(path.join('/', controller.root, '*'), controller);
123
+ this.redirect(path.join('/', controller.root, '*'), controller.router);
124
+ })
125
+ });
126
+ }
127
+
128
+ start(port){
129
+ this.#setup();
130
+ this.server.port(port).listen;
131
+ this.emit('start', port);
132
+ return this;
133
+ }
134
+ }
135
+
136
+ class Injectable extends Events {
137
+ #injected = [];
138
+ forEachInjectable(cb, event, ...injectables){
139
+ injectables.filter(i => i instanceof Injectable)
140
+ .forEach(injectable => {
141
+ cb(injectable);
142
+ injectable.emit(event, this);
143
+ this.emit(event, this);
144
+ });
145
+ return this;
146
+ }
147
+ inject(...injectables){
148
+ return this.forEachInjectable(
149
+ (injectable) => this.#injected.push(injectable),
150
+ 'activate',
151
+ ...injectables
152
+ );
153
+ }
154
+ }
155
+
156
+
157
+ class SModuleContext extends Context('module') {
158
+
159
+ provider(...provider){
160
+ this.module.addProvider(...provider);
161
+ return this;
162
+ }
163
+
164
+ controller(...controller){
165
+ this.module.addController(...controller);
166
+ return this;
167
+ }
168
+ }
169
+
170
+ class SModule extends Injectable {
171
+ #providers = [];
172
+ #controllers = [];
173
+ #app = {};
174
+
175
+ constructor(){
176
+ super();
177
+ this.on('activate', (app) => {
178
+ this.#app = app;
179
+ this.#controllers.concat(
180
+ this.#providers
181
+ ).forEach(injectable => injectable.emit('activate:app', app));
182
+ });
183
+ }
184
+
185
+ addProvider(...providers){
186
+ return this.forEachInjectable(
187
+ (injectable) => this.#providers.push(injectable),
188
+ 'activate',
189
+ ...providers
190
+ );
191
+ }
192
+
193
+ hasProvider(provider){
194
+ return this.#providers.find(p => p == provider);
195
+ }
196
+
197
+ addController(...controllers){
198
+ return this.forEachInjectable(
199
+ (injectable) => this.#controllers.push(injectable),
200
+ 'activate',
201
+ ...controllers
202
+ );
203
+ }
204
+
205
+ getControllers(){
206
+ return this.#controllers;
207
+ }
208
+
209
+ new(cb){
210
+ return new context.Usage('', () => {
211
+ const module = new SModule();
212
+ const moduleContext = new SModuleContext(module);
213
+ cb.call(moduleContext);
214
+ return module;
215
+ });
216
+ }
217
+ }
218
+
219
+ class SServiceContext extends Context('service') {
220
+ function(name){
221
+ return (cb) => {
222
+ this[name] = (...args) => cb.call(this, ...args);
223
+ this.service[name] = this[name];
224
+ return this[name];
225
+ }
226
+ }
227
+ }
228
+ class SProvider {
229
+ constructor(name, injectable){
230
+ this.name = name;
231
+ this.injectable = injectable;
232
+ }
233
+ }
234
+ class SService extends Injectable {
235
+ new(cb){
236
+ return new context.Usage('', () => {
237
+ const service = new SService();
238
+ const serviceContext = new SServiceContext(service);
239
+ cb.call(serviceContext);
240
+ return service;
241
+ });
242
+ }
243
+
244
+ as(name){
245
+ return new SProvider(name, this);
246
+ }
247
+ }
248
+
249
+ const ggreq = (that, method, _path, middleWare) => (cb) => {
250
+ cb.parent = that;
251
+ that.controller.register(method, _path, cb, middleWare);
252
+ return cb;
253
+ }
254
+ const mkReq = (usage) => (req, ctx) => usage.call(req, req, ctx);
255
+ class SControllerContext extends Context('controller') {
256
+
257
+ middleWares = [];
258
+
259
+ getMiddleWares(md){
260
+ return (...args) => {
261
+ this.middleWares.forEach(middleWare => {
262
+ mkReq(middleWare)(...args);
263
+ });
264
+ if(md){
265
+ mkReq(md)(...args);
266
+ }
267
+ }
268
+ }
269
+
270
+ withCookies(){
271
+ return svr.prototype.withCookies;
272
+ }
273
+ withContent(){
274
+ return svr.prototype.withContent;
275
+ }
276
+
277
+ get(_path, middleWare){
278
+ return ggreq(this, 'get', _path, this.getMiddleWares(middleWare));
279
+ }
280
+ post(_path, middleWare){
281
+ return ggreq(this, 'post', _path, this.getMiddleWares(middleWare));
282
+ }
283
+ delete(_path, middleWare){
284
+ return ggreq(this, 'delete', _path, this.getMiddleWares(middleWare));
285
+ }
286
+ patch(_path, middleWare){
287
+ return ggreq(this, 'patch', _path, this.getMiddleWares(middleWare));
288
+ }
289
+ put(_path, middleWare){
290
+ return ggreq(this, 'put', _path, this.getMiddleWares(middleWare));
291
+ }
292
+ all(_path, middleWare){
293
+ return ggreq(this, 'all', _path, this.getMiddleWares(middleWare));
294
+ }
295
+
296
+ use(usage){
297
+ this.controller.router.all('*', mkReq(usage));
298
+ return this;
299
+ }
300
+
301
+ useEach(usage){
302
+ this.middleWares.push(usage);
303
+ return this;
304
+ }
305
+
306
+ usem(...middleWares){
307
+ return function(...args){
308
+ middleWares.forEach(middleWare => middleWare.call(this, ...args));
309
+ }
310
+ }
311
+
312
+ normal(cb){
313
+ return function(){
314
+ return cb(this.request, this);
315
+ }
316
+ }
317
+ }
318
+
319
+ function mkBody(req){
320
+ const type = req.headers.get('content-type');
321
+ if(type == 'application/json'){
322
+ return req.data.json();
323
+ } else {
324
+ try {
325
+ return req.data.json();
326
+ } catch(e){
327
+ return req.data.text();
328
+ }
329
+ }
330
+ }
331
+
332
+ class SController extends Injectable {
333
+
334
+ constructor(root){
335
+ super();
336
+ this.root = root;
337
+ this.router = mkRouter({ base: path.join('/', root) });
338
+ }
339
+
340
+ mkCallback(cb){
341
+ return async (req, ctx) => {
342
+ let context = {...{
343
+ request: req,
344
+ 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
+ }};
352
+ return await cb.call(context, ...Object.keys(context).map(i => context[i]));
353
+ }
354
+ }
355
+
356
+ register(method, url, cb, middleWare){
357
+ this.router[method](url || '/', middleWare || this.mkCallback(cb), middleWare ? this.mkCallback(cb) : undefined);
358
+ return this;
359
+ }
360
+
361
+ new(root = '/'){
362
+ const controller = new SController(root || '/');
363
+ const controllerContext = new SControllerContext(controller);
364
+ const cb = (cb) => new context.Usage('', () => {
365
+ cb.call(controllerContext);
366
+ return controller;
367
+ });
368
+ cb.with = (...args) => {
369
+ controller.on('activate', (parentModule) => {
370
+ args
371
+ .filter(arg => arg instanceof SProvider)
372
+ .filter(arg => parentModule.hasProvider(arg.injectable))
373
+ .forEach(e => {
374
+ controllerContext[e.name] = e.injectable;
375
+ });
376
+ });
377
+ return cb;
378
+ }
379
+ return cb;
380
+ }
381
+ }
382
+
383
+ class SControllerMiddleware extends Injectable {
384
+ constructor(root, router){
385
+ super();
386
+ this.root = root;
387
+ this.router = router;
388
+ }
389
+ }
390
+
391
+ function createSControllerMiddleware(root = '') {
392
+ return (cb) => new SControllerMiddleware(root, cb);
393
+ }
394
+
395
+ return {
396
+ ServeApp,
397
+ SModule,
398
+ SService,
399
+ SController,
400
+ SControllerMiddleware: createSControllerMiddleware
401
+ };
402
+ }
@@ -30,6 +30,35 @@ module.exports = (context) => {
30
30
  return new Request(url, options);
31
31
  }
32
32
 
33
+ function getBody(req){
34
+ return new Promise((resolve, reject) => {
35
+ const chunks = [];
36
+
37
+ req.on('data', chunk => {
38
+ chunks.push(chunk);
39
+ });
40
+
41
+ req.on('end', () => {
42
+ let buffer = chunks.length ? Buffer.concat(chunks) : null;
43
+ resolve(buffer ? {
44
+ text(){
45
+ return buffer.toString();
46
+ },
47
+ json(){
48
+ return JSON.parse(buffer.toString());
49
+ },
50
+ buffer(){
51
+ return buffer;
52
+ }
53
+ } : null);
54
+ });
55
+
56
+ req.on('error', (err) => {
57
+ reject(err);
58
+ });
59
+ });
60
+ }
61
+
33
62
  class Server {
34
63
  _server = {};
35
64
  routers = {};
@@ -47,12 +76,18 @@ module.exports = (context) => {
47
76
  async handleRequest(req, res){
48
77
  try {
49
78
  let response = new Response();
79
+ const context = {};
50
80
  const request = mkReq(req);
81
+
82
+ context.getRealRequest = () => req;
83
+
84
+ request.data = await getBody(req);
85
+
51
86
  if(this.options.fetch == 'router'){
52
87
  if(!Object.keys(this.options.routers).length) throw new Error('No fetch function nor routers found');
53
- response = await this.options.routers[Object.keys(this.options.routers)[0]].fetch(request);
88
+ response = await this.options.routers[Object.keys(this.options.routers)[0]].fetch(request, context).catch((e) => this.catch(e));
54
89
  } else {
55
- response = await this.options.fetch(request);
90
+ response = await this.options.fetch(request, context).catch((e) => this.catch(e));
56
91
  }
57
92
 
58
93
  if(!response){
@@ -60,6 +95,10 @@ module.exports = (context) => {
60
95
  return;
61
96
  }
62
97
 
98
+ if(typeof response == 'string'){
99
+ response = new Response(response);
100
+ }
101
+
63
102
  response.headers.forEach((value, name) => {
64
103
  res.setHeader(name, value);
65
104
  });
@@ -97,6 +136,23 @@ module.exports = (context) => {
97
136
  return this;
98
137
  }
99
138
 
139
+ _onError = (e) => {
140
+ console.error(e);
141
+ return json({
142
+ error: true,
143
+ exception: e.name,
144
+ message: e.message
145
+ });
146
+ };
147
+ onError(fn){
148
+ this._onError = fn;
149
+ return this;
150
+ }
151
+
152
+ catch(e){
153
+ return this._onError(e);
154
+ }
155
+
100
156
  port(port){
101
157
  this.listen = port;
102
158
  return this;
@@ -190,7 +246,6 @@ module.exports = (context) => {
190
246
  const routeParts = pathname.split('/').filter(Boolean);
191
247
  let routePath = root;
192
248
 
193
-
194
249
  Object.keys(params).forEach(key => delete params[key]);
195
250
 
196
251
  for (const part of routeParts) {
@@ -294,6 +349,7 @@ module.exports = (context) => {
294
349
  return async (req) => {
295
350
  const url = new URL(req.url);
296
351
  const pathname = basePath ? url.pathname.replace(new RegExp('^'+basePath), '') : url.pathname;
352
+
297
353
  const file = lookUp(pathname);
298
354
  cleanCache();
299
355
 
@@ -324,6 +380,8 @@ module.exports = (context) => {
324
380
  if(type == 'default') router = SvrRouter.new(IttyRouter, {...options}, { id });
325
381
  if(type == 'auto') router = SvrRouter.new(AutoRouter, {...options}, { id });
326
382
  if(type == 'normal') router = SvrRouter.new(Router, {...options}, { id });
383
+
384
+ router.auto = true;
327
385
 
328
386
  return router;
329
387
  }
@@ -241,8 +241,8 @@ function renderToString(element, js = false) {
241
241
  }
242
242
  delete eltJSON.parent;
243
243
  delete eltJSON._target;
244
-
245
- return js ? js === 'raw' ? eltJSON : JSON.stringify(eltJSON) : element instanceof TextNode ? `${type.text}` : `<${type.element}${propsString}>${selfClosingElements.has(type.element) ? '' : childrenHTML}${selfClosingElements.has(type.element) ? '' : `</${type.element}>`}`;
244
+
245
+ return js ? (js === 'raw' ? eltJSON : JSON.stringify(eltJSON)) : element instanceof TextNode ? `${type.text}` : `<${type.element}${propsString}>${selfClosingElements.has(type.element) ? '' : childrenHTML}${selfClosingElements.has(type.element) ? '' : `</${type.element}>`}`;
246
246
  }
247
247
 
248
248
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@makano/rew",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "description": "A simple coffescript runtime and app manager",
5
5
  "main": "main.js",
6
6
  "directories": {
@@ -50,5 +50,8 @@
50
50
  "vite": "^5.2.13",
51
51
  "vm": "^0.1.0",
52
52
  "yargs": "^17.7.2"
53
+ },
54
+ "devDependencies": {
55
+ "@danielx/civet": "^0.7.23"
53
56
  }
54
57
  }