@makano/rew 1.0.22 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
package/README.md ADDED
@@ -0,0 +1,36 @@
1
+ <h3 align="center">
2
+ <img src="https://raw.githubusercontent.com/kevinJ045/rew/main/assets/logo.png" width="100" />
3
+ <br/>
4
+ Rew
5
+ <br/>
6
+ </h3>
7
+ <p align="center">
8
+ <a href="https://github.com/kevinj045/rew/stargazers"> <img src="https://img.shields.io/github/stars/kevinj045/rew?style=for-the-badge&logo=starship&color=cba6f7&logoColor=9399b2&labelColor=181825" alt="GitHub stars"/></a>
9
+ <a href="https://github.com/kevinj045/rew/issues">
10
+ <img src="https://img.shields.io/github/issues/kevinj045/guilib?style=for-the-badge&logo=gitbook&color=f5c2e7&logoColor=9399b2&labelColor=181825" alt="GitHub issues"/></a>
11
+ <a href="https://github.com/kevinj045/rew"> <img src="https://img.shields.io/github/forks/kevinj045/rew?style=for-the-badge&logo=git&color=94e2d5&logoColor=9399b2&labelColor=181825" alt="GitHub forks"/></a>
12
+ <a href="https://www.npmjs.com/package/rayous"> <img src="https://img.shields.io/npm/v/@makano/rew?style=for-the-badge&logo=npm&color=b4befe&logoColor=9399b2&labelColor=181825" alt="npm version" /></a>
13
+ </p>
14
+
15
+ Rayous is a simple lightweight coffeescript runtime, made to simply using coffescript and revive it
16
+ in the process.
17
+
18
+ ## Getting Started
19
+ 1. Install `rew` globally
20
+ ```bash
21
+ npm i @makano/rew -g
22
+ ```
23
+ > If you're using `nixos`, you can try with `npm config set prefix '~/.npm-global'` and add that to your path
24
+ 2. Create a `rew` project
25
+ ```bash
26
+ rew create myrewproj
27
+ ```
28
+ 3. Run your project as an app or file
29
+ ```bash
30
+ rew run .
31
+ ```
32
+ Optionally, you can run single files with `rew [filename]`
33
+
34
+ ## Author's Notes
35
+
36
+ Any suggestions, bug fixes or ideas are accepted, feel free to ask anything.
package/bin/ui CHANGED
Binary file
package/bin/ui_ws ADDED
Binary file
@@ -3,9 +3,11 @@
3
3
  const yargs = require('yargs/yargs');
4
4
  const path = require('path');
5
5
  const { hideBin } = require('yargs/helpers');
6
- const { fork } = require('child_process');
6
+ const { fork, exec } = require('child_process');
7
7
  const { watch } = require('chokidar');
8
8
  const utils = require('./utils');
9
+ const { existsSync } = require('fs');
10
+ const { log } = require('./log');
9
11
 
10
12
  yargs(hideBin(process.argv))
11
13
  .command(
@@ -25,6 +27,10 @@ yargs(hideBin(process.argv))
25
27
  },
26
28
  (argv) => {
27
29
  const filePath = path.resolve(process.cwd(), argv.file);
30
+ if(!existsSync(filePath)){
31
+ log('File not found:', argv.file, ':end');
32
+ return;
33
+ }
28
34
  const watching = [];
29
35
  const watchIt = (file) => {
30
36
  if(watching.includes(file)) return;
@@ -104,6 +110,18 @@ yargs(hideBin(process.argv))
104
110
  utils.runApp(argv.path);
105
111
  }
106
112
  )
113
+ .command('install <path>', 'Install an app', (yargs) => {
114
+ yargs
115
+ .positional('path', {
116
+ describe: 'Path of the app to install',
117
+ type: 'string',
118
+ });
119
+ },
120
+ async (argv) => {
121
+ if(argv.path.startsWith('github:')) utils.installApp(await utils.cloneGit(argv.path), true, true);
122
+ else utils.installApp(argv.path);
123
+ }
124
+ )
107
125
  .command('build <file>', 'Build the specified file', (yargs) => {
108
126
  yargs
109
127
  .positional('file', {
@@ -4,8 +4,9 @@ const conf = require('../pkgs/conf');
4
4
  const jsYaml = require('js-yaml');
5
5
  const readline = require('readline');
6
6
  const { log, logget } = require('./log');
7
- const { execSync } = require('child_process');
7
+ const { execSync, exec } = require('child_process');
8
8
  const { run } = require('../main');
9
+ const { generateRandomID } = require('../functions/id');
9
10
 
10
11
  const npm_package_name = '@makano/rew';
11
12
 
@@ -68,6 +69,7 @@ module.exports = {
68
69
  fs.writeFileSync(confPath, jsYaml.dump({ package: project.package, entry: 'main.coffee' }));
69
70
  fs.writeFileSync(entryFile, `print("Hello World!")`);
70
71
  if(project.git) {
72
+ fs.writeFileSync(path.join(projectPath, '.gitignore'), `node_modules/\npackage-lock.json`);
71
73
  execSync('cd '+projectPath+' && git init .');
72
74
  }
73
75
  log('Installing '+npm_package_name);
@@ -104,7 +106,14 @@ module.exports = {
104
106
  const runAppRoot = (root, confPath) => {
105
107
  const c = jsYaml.load(fs.readFileSync(confPath, { encoding: 'utf-8' }));
106
108
  if(c.entry){
107
- run(path.resolve(root, c.entry));
109
+ const r = path.resolve(root, c.entry);
110
+ const mod_path = path.resolve(root, 'node_modules/@makano/rew');
111
+ const mod_path_lib = path.join(mod_path, 'lib/rew/cli');
112
+ if(fs.existsSync(mod_path) && __dirname !== mod_path_lib){
113
+ const mod_path_utilsjs = path.join(mod_path_lib, '../main.js');
114
+ require(mod_path_utilsjs)
115
+ .run(r);
116
+ } else run(r);
108
117
  }
109
118
  }
110
119
 
@@ -112,11 +121,70 @@ module.exports = {
112
121
  runAppRoot(apppath, appConfpath);
113
122
  } else {
114
123
  const con = conf({});
115
- const apppath = path.resolve(con.CONFIG_PATH, pathOrPackage, '$app');
124
+ const apppath = path.resolve(con.CONFIG_PATH, pathOrPackage, 'app');
116
125
  const appConfpath = path.join(apppath, 'app.yaml');
117
126
  if(fs.existsSync(apppath) && fs.existsSync(appConfpath)){
118
127
  runAppRoot(apppath, appConfpath);
119
128
  }
120
129
  }
130
+ },
131
+ installApp(pathname, rmidir, rmidiri){
132
+ if(!pathname){
133
+ return;
134
+ }
135
+ const apppath = path.resolve(process.cwd(), pathname);
136
+ const appConfpath = path.join(apppath, 'app.yaml');
137
+ const appPackagepath = path.join(apppath, 'package.json');
138
+ if(fs.existsSync(apppath) && fs.existsSync(appConfpath)){
139
+ const c = jsYaml.load(fs.readFileSync(appConfpath, { encoding: 'utf-8' }));
140
+ const p = JSON.parse(fs.readFileSync(appPackagepath, { encoding: 'utf-8' }));
141
+ const pname = c.package;
142
+ const installPath = path.join(conf({}).create(pname).root, 'app');
143
+ const rl = readline.createInterface({
144
+ input: process.stdin,
145
+ output: process.stdout
146
+ });
147
+ log('Installing '+pname);
148
+ log("Package: "+p.name+'@'+p.version);
149
+ if(p.description){
150
+ log("Description: "+p.description);
151
+ }
152
+ rl.question(logget('Install '+pname+'? (y/N)'), (f) => {
153
+ if(f.toLowerCase() == 'y'){
154
+ if(fs.existsSync(installPath)){
155
+ execSync(`rm -r ${installPath}`);
156
+ }
157
+ execSync(`cp -r ${apppath} ${installPath}`);
158
+ if(rmidir){
159
+ execSync(`rm -r ${apppath}`);
160
+ }
161
+ log('Installed '+pname, ':end');
162
+ rl.close();
163
+ } else {
164
+ if(rmidiri){
165
+ execSync(`rm -r ${apppath}`);
166
+ }
167
+ log('Canceled install', ':end');
168
+ rl.close();
169
+ }
170
+ });
171
+ } else {
172
+ log('Path is not a rew app', ':end');
173
+ }
174
+ },
175
+ async cloneGit(gitpath){
176
+ const p = gitpath.split('github:')[1];
177
+ const url = `https://github.com/${p}`;
178
+ const apiurl = `https://api.github.com/repos/${p}`;
179
+ return await fetch(apiurl)
180
+ .then((r) => {
181
+ if(r.status !== 200) return log('Repo not found', ':end');
182
+ const tempPath = '/tmp/rew-git-clone-'+p.replace(/\//g, '_')+'-'+generateRandomID();
183
+ execSync(`git clone ${url} ${tempPath}`);
184
+ console.log('Installing deps...');
185
+ execSync(`cd ${tempPath} && npm i`);
186
+ return tempPath;
187
+ })
188
+ .catch(r => null);
121
189
  }
122
190
  }
@@ -14,9 +14,10 @@ module.exports = function future(callback, timeout = 0, defData = null) {
14
14
  });
15
15
  return {
16
16
  pipe: (callback) => promise.then(callback),
17
- pipex: (callback) => promise.finally(callback),
17
+ last: (callback) => promise.finally(callback),
18
18
  catch: (callback) => promise.catch(callback),
19
19
  resolve: (data) => listener.emit("resolve", data),
20
20
  reject: (data) => listener.emit("reject", data),
21
+ wait: async () => await promise
21
22
  };
22
23
  };
@@ -2,6 +2,23 @@ const path = require("path");
2
2
  const { getFile, file } = require("../modules/fs");
3
3
  const { importYaml } = require("../modules/yaml");
4
4
  const { findPackage, getPackage } = require("../pkgs/pkgs");
5
+ const { existsSync, readFileSync } = require("fs");
6
+ const conf = require("../pkgs/conf");
7
+ const jsYaml = require("js-yaml");
8
+
9
+ const lookUpInOtherApps = (fullPath) => {
10
+ const con = conf({});
11
+ const name = fullPath.indexOf('/') ? fullPath.split('/')[0] : fullPath;
12
+ let dpath = fullPath.indexOf('/') ? fullPath.split('/')[1] : '';
13
+ let ppath = path.join(con.CONFIG_PATH, name, 'app');
14
+ if(!existsSync(ppath)) return null;
15
+ if(!dpath){
16
+ dpath = jsYaml.load(readFileSync(path.join(ppath, 'app.yaml'), 'utf-8')).entry;
17
+ }
18
+ ppath = path.join(ppath, dpath);
19
+ if(existsSync(ppath)) return ppath;
20
+ else return null;
21
+ }
5
22
 
6
23
  module.exports.imp = function (runPath, context) {
7
24
  return function (filename, options = {}) {
@@ -9,10 +26,16 @@ module.exports.imp = function (runPath, context) {
9
26
  let exports,
10
27
  ispkg = findPackage(filename);
11
28
 
12
- const filepath = path.resolve(path.dirname(context.module.filepath), filename);
29
+ let filepath = path.resolve(path.dirname(context.module.filepath), filename);
13
30
 
14
31
  // console.log(typeof runPath);
15
32
 
33
+ if(!ispkg && !existsSync(filepath)){
34
+ const otherPath = lookUpInOtherApps(filename);
35
+ if(!otherPath) throw new Error('Module "'+filename+'" not found');
36
+ else filepath = otherPath;
37
+ }
38
+
16
39
  if (ispkg) {
17
40
  exports = getPackage(filename)(context);
18
41
  } else if (type == "coffee") {
@@ -7,213 +7,9 @@
7
7
 
8
8
  <style>/* $OPTIONS(style) */</style>
9
9
 
10
- <script>
11
- window.execContext = $OPTIONS(json.execContext);
12
- </script>
13
- <script>
14
- window.exec = $OPTIONS(exec);
15
- </script>
16
- <script>
17
- if(!window.execContext) window.execContext = {};
18
- window.addEventListener("load", () => {
19
- const ws = new WebSocket("ws://localhost:$OPTIONS(port)");
20
- const DOM = [];
21
-
22
- const findInDom = (id) =>
23
- DOM.find((el) => el.widgetOptions.uuid == id) ||
24
- DOM.find((el) => el.id == id);
25
-
26
- const parseStyleValue = (val) => val;
27
-
28
- const addTo = (el, parent) => {
29
- if (parent == "null") {
30
- document.body.appendChild(el);
31
- } else {
32
- findInDom(parent).appendChild(el);
33
- }
34
- };
35
-
36
- const initElement = (el, options, update = false) => {
37
- if(el.widgetOptions){
38
- if (el.widgetOptions.style) {
39
- for(let i in options.style){
40
- el.style.removeProperty(i, el.widgetOptions.style[i]);
41
- }
42
- }
43
- if (el.widgetOptions.attr) {
44
- for(let i in el.widgetOptions.attr){
45
- el.removeAttribute(i);
46
- }
47
- }
48
- }
49
-
50
- el.widgetOptions = options;
51
- el.id = options.id;
52
- el.textContent = options.data.text;
53
-
54
- if (options.style) {
55
- for(let i in options.style){
56
- el.style.setProperty(i, options.style[i]);
57
- }
58
- }
59
-
60
- if (options.attr) {
61
- for(let i in options.attr){
62
- el.setAttribute(i, options.attr[i]);
63
- }
64
- }
65
10
 
66
- if (options.children.length) {
67
- options.children.forEach((option) => {
68
- option.parent = options.uuid;
69
- if(update) updateElement(findInDom(option.uuid), option);
70
- else createElement(option);
71
- });
72
- }
73
-
74
- if (options.parent) {
75
- addTo(el, options.parent);
76
- }
77
- }
78
-
79
- const updateElement = (el, options) => {
80
- if(!el) return;
81
- initElement(el, options, true);
82
- return el;
83
- }
84
-
85
- const events = [
86
- "click", "dblclick", "mousedown", "mouseup", "mouseover", "mouseout",
87
- "mousemove", "mouseenter", "mouseleave", "keydown", "keypress", "keyup",
88
- "change", "input", "submit", "focus", "blur", "copy", "cut", "paste",
89
- "scroll", "wheel", "resize", "contextmenu", "drag", "dragstart", "dragend",
90
- "dragenter", "dragleave", "dragover", "drop", "error", "load", "abort"
91
- ];
92
- const handleListeners = (el) => {
93
- events.forEach(event => {
94
- el.addEventListener(event, (e) => {
95
- ws.send(JSON.stringify({
96
- action: 'hook:eventTrigger',
97
- data: {
98
- rid: 'event_trigger',
99
- object: {
100
- uuid: el.widgetOptions.uuid,
101
- event,
102
- data: {
103
- mouse: { x: e.clientX, y: e.clientY },
104
- key: { code: e.keyCode, key: e.key }
105
- }
106
- }
107
- }
108
- }))
109
- });
110
- });
111
- }
112
-
113
- function eventHandlerFunction({ uuid, hookID, event }){
114
- return function(e){
115
- ws.send(JSON.stringify({
116
- action: 'hook:event_'+event,
117
- data: {
118
- rid: hookID,
119
- object: {
120
- uuid,
121
- event,
122
- data: {
123
- mouse: { x: e.clientX, y: e.clientY },
124
- key: { code: e.keyCode, key: e.key }
125
- }
126
- }
127
- }
128
- }));
129
- }
130
- }
131
-
132
- const createElement = (options) => {
133
- const el = document.createElement(options.element);
134
- DOM.push(el);
135
- initElement(el, options);
136
- return el;
137
- };
138
-
139
- const stringifyJSON = (json) => {
140
- try {
141
- return JSON.stringify(json, null, 4);
142
- } catch (e) {
143
- return json.toString();
144
- }
145
- };
146
-
147
- const log = (...strings) => {
148
- window.webkit.messageHandlers.external.postMessage(
149
- JSON.stringify({"action": "log", "data": strings
150
- .map((r) =>
151
- typeof r == "object" ? stringifyJSON(r) : `${r.toString()}`,
152
- )
153
- // .map((i) => i.replace(/\"/g, '\\\\"').replace(/\n/g, "\\\\n"))
154
- .join("\n")}, null, 4)
155
- );
156
- };
157
-
158
- if (
159
- window.webkit &&
160
- window.webkit.messageHandlers &&
161
- window.webkit.messageHandlers.external &&
162
- window.RUNID == "$OPTIONS(runId)"
163
- ) {
164
-
165
- ws.onmessage = (event, cb) => {
166
- const edata = process_data(event.data);
167
- if (edata.action == "init") {
168
- document.title = edata.data.title;
169
- window.webkit.messageHandlers.external.postMessage(
170
- `{"action": "setTitle", "data": "${edata.data.title}"}`,
171
- );
172
- log("INIT::READY");
173
- if(window.exec){
174
- window.exec(window.execContext);
175
- }
176
- } else if(edata.action == 'eventListen') {
177
- const el = findInDom(edata.data.uuid);
178
- if(el){
179
- el.addEventListener(edata.data.event, eventHandlerFunction(edata.data))
180
- }
181
- } else if (edata.action == "createElement") {
182
- const options = edata.data;
183
- try {
184
- createElement(options);
185
- } catch (e) {
186
- log(e.toString());
187
- }
188
- } else if (edata.action == "addStyleSheet") {
189
- const style = document.createElement('style');
190
- style.textContent = edata.data;
191
- document.head.appendChild(style);
192
- } else if (edata.action == "updateElement") {
193
- const options = edata.data;
194
- try {
195
- updateElement(findInDom(options.uuid), options);
196
- } catch (e) {
197
- log(e.toString());
198
- }
199
- } else if (edata.action == "findElement") {
200
- const id = edata.data.id;
201
- const rid = edata.data.rid;
202
- try {
203
- ws.send(JSON.stringify({ action: 'hook:findElement', data: { rid, object: findInDom(id)?.widgetOptions } }))
204
- } catch (e) {
205
- log(e.toString());
206
- }
207
- }
208
- };
209
- } else {
210
- console.log("Not in a webkit window");
211
- }
212
-
213
- function process_data(data) {
214
- return JSON.parse(data);
215
- }
216
- });
11
+ <script>
12
+ window.onerror = () => alert('ERror');
217
13
  </script>
218
14
  </head>
219
15
 
@@ -0,0 +1,198 @@
1
+ try{
2
+ window.execContext = $OPTIONS(json.execContext);
3
+ } catch(e){
4
+ window.execContext = {};
5
+ }
6
+
7
+ try{
8
+ window.exec = $OPTIONS(exec);
9
+ } catch(e){
10
+ window.exec = function(){};
11
+ }
12
+
13
+ const DOM = [];
14
+
15
+ const findInDom = (id) =>
16
+ DOM.find((el) => el.widgetOptions.uuid == id) ||
17
+ DOM.find((el) => el.id == id);
18
+
19
+ const parseStyleValue = (val) => val;
20
+
21
+ const addTo = (el, parent) => {
22
+ if (parent == "null") {
23
+ document.body.appendChild(el);
24
+ } else {
25
+ findInDom(parent).appendChild(el);
26
+ }
27
+ };
28
+
29
+ const initElement = (el, options, update = false) => {
30
+ if(el.widgetOptions){
31
+ if (el.widgetOptions.style) {
32
+ for(let i in options.style){
33
+ el.style.removeProperty(i, el.widgetOptions.style[i]);
34
+ }
35
+ }
36
+ if (el.widgetOptions.attr) {
37
+ for(let i in el.widgetOptions.attr){
38
+ el.removeAttribute(i);
39
+ }
40
+ }
41
+ }
42
+
43
+ el.widgetOptions = options;
44
+ el.id = options.id;
45
+ el.textContent = options.data.text;
46
+
47
+ if (options.style) {
48
+ for(let i in options.style){
49
+ el.style.setProperty(i, options.style[i]);
50
+ }
51
+ }
52
+
53
+ if (options.attr) {
54
+ for(let i in options.attr){
55
+ el.setAttribute(i, options.attr[i]);
56
+ }
57
+ }
58
+
59
+ if (options.children.length) {
60
+ options.children.forEach((option) => {
61
+ option.parent = options.uuid;
62
+ if(update) updateElement(findInDom(option.uuid), option);
63
+ else createElement(option);
64
+ });
65
+ }
66
+
67
+ if (options.parent) {
68
+ addTo(el, options.parent);
69
+ }
70
+ }
71
+
72
+ const updateElement = (el, options) => {
73
+ if(!el) return;
74
+ initElement(el, options, true);
75
+ return el;
76
+ }
77
+
78
+ const events = [
79
+ "click", "dblclick", "mousedown", "mouseup", "mouseover", "mouseout",
80
+ "mousemove", "mouseenter", "mouseleave", "keydown", "keypress", "keyup",
81
+ "change", "input", "submit", "focus", "blur", "copy", "cut", "paste",
82
+ "scroll", "wheel", "resize", "contextmenu", "drag", "dragstart", "dragend",
83
+ "dragenter", "dragleave", "dragover", "drop", "error", "load", "abort"
84
+ ];
85
+ const handleListeners = (el) => {
86
+ events.forEach(event => {
87
+ el.addEventListener(event, (e) => {
88
+ sendData({
89
+ action: 'hook:eventTrigger',
90
+ data: {
91
+ rid: 'event_trigger',
92
+ object: {
93
+ uuid: el.widgetOptions.uuid,
94
+ event,
95
+ data: {
96
+ mouse: { x: e.clientX, y: e.clientY },
97
+ key: { code: e.keyCode, key: e.key }
98
+ }
99
+ }
100
+ }
101
+ });
102
+ });
103
+ });
104
+ }
105
+
106
+ function eventHandlerFunction({ uuid, hookID, event }){
107
+ return function(e){
108
+ sendData({
109
+ action: 'hook:event_'+event,
110
+ data: {
111
+ rid: hookID,
112
+ object: {
113
+ uuid,
114
+ event,
115
+ data: {
116
+ mouse: { x: e.clientX, y: e.clientY },
117
+ key: { code: e.keyCode, key: e.key }
118
+ }
119
+ }
120
+ }
121
+ });
122
+ }
123
+ }
124
+
125
+ const createElement = (options) => {
126
+ const el = document.createElement(options.element);
127
+ DOM.push(el);
128
+ initElement(el, options);
129
+ return el;
130
+ };
131
+
132
+ const stringifyJSON = (json) => {
133
+ try {
134
+ return JSON.stringify(json, null, 4);
135
+ } catch (e) {
136
+ return json.toString();
137
+ }
138
+ };
139
+
140
+ const log = (...strings) => {
141
+ window.webkit.messageHandlers.external.postMessage(
142
+ JSON.stringify({"action": "log", "data": strings
143
+ .map((r) =>
144
+ typeof r == "object" ? stringifyJSON(r) : `${r.toString()}`,
145
+ )
146
+ // .map((i) => i.replace(/\"/g, '\\\\"').replace(/\n/g, "\\\\n"))
147
+ .join("\n")}, null, 4)
148
+ );
149
+ };
150
+
151
+ const sendData = (data) => {
152
+ log("RESPONSE::"+stringifyJSON(data));
153
+ }
154
+
155
+ function process_data(data) {
156
+ return JSON.parse(data);
157
+ }
158
+
159
+ window.recieveMessage = (data) => {
160
+ const edata = data;
161
+ if(edata.action == 'eventListen') {
162
+ const el = findInDom(edata.data.uuid);
163
+ if(el){
164
+ el.addEventListener(edata.data.event, eventHandlerFunction(edata.data))
165
+ }
166
+ } else if (edata.action == "createElement") {
167
+ const options = edata.data;
168
+ try {
169
+ createElement(options);
170
+ } catch (e) {
171
+ log(e.toString());
172
+ }
173
+ } else if (edata.action == "addStyleSheet") {
174
+ const style = document.createElement('style');
175
+ style.textContent = edata.data;
176
+ document.head.appendChild(style);
177
+ } else if (edata.action == "updateElement") {
178
+ const options = edata.data;
179
+ try {
180
+ updateElement(findInDom(options.uuid), options);
181
+ } catch (e) {
182
+ log(e.toString());
183
+ }
184
+ } else if (edata.action == "findElement") {
185
+ const id = edata.data.id;
186
+ const rid = edata.data.rid;
187
+ try {
188
+ sendData({ action: 'hook:findElement', data: { rid, object: findInDom(id)?.widgetOptions } });
189
+ } catch (e) {
190
+ log(e.toString());
191
+ }
192
+ }
193
+ };
194
+
195
+ window.addEventListener('load', () => {
196
+ window.exec(window.execContext);
197
+ log('SETUP::READY');
198
+ });
@@ -2,7 +2,7 @@ const emitter = require("../../../functions/emitter");
2
2
  const { struct } = require("../../../models/struct");
3
3
  const { generateRandomID } = require("../../../functions/id");
4
4
 
5
- module.exports.uiClasses = (context, options, svr, send, hook, rmHook) => {
5
+ module.exports.uiClasses = (context, options, send, recieve, hook, rmHook) => {
6
6
  const _sanitizeOptions = (options) => {
7
7
  return {
8
8
  ...options,
@@ -33,7 +33,7 @@ module.exports.uiClasses = (context, options, svr, send, hook, rmHook) => {
33
33
  hook(hookID, 'event_'+event, (data) => {
34
34
  this.emit(event, data);
35
35
  }, false);
36
- send(JSON.stringify({ action: 'eventListen', data: { uuid: this.uuid, event, hookID } }))
36
+ send({ action: 'eventListen', data: { uuid: this.uuid, event, hookID } })
37
37
  return this;
38
38
  }
39
39
  off(event, callback){
@@ -56,7 +56,7 @@ module.exports.uiClasses = (context, options, svr, send, hook, rmHook) => {
56
56
  }
57
57
 
58
58
  init(){
59
- send(JSON.stringify({ action: 'createElement', data: _sanitizeOptions(this.options) }))
59
+ send({ action: 'createElement', data: _sanitizeOptions(this.options) })
60
60
  }
61
61
 
62
62
  parent = null;
@@ -86,7 +86,7 @@ module.exports.uiClasses = (context, options, svr, send, hook, rmHook) => {
86
86
  }
87
87
 
88
88
  update(){
89
- send(JSON.stringify({ action: 'updateElement', data: _sanitizeOptions(this.options) }));
89
+ send({ action: 'updateElement', data: _sanitizeOptions(this.options) });
90
90
  return this;
91
91
  }
92
92
 
@@ -140,7 +140,7 @@ module.exports.uiClasses = (context, options, svr, send, hook, rmHook) => {
140
140
 
141
141
  class StyleSheet {
142
142
  constructor(css = ''){
143
- send(JSON.stringify({ action: 'addStyleSheet', data: css }));
143
+ send({ action: 'addStyleSheet', data: css });
144
144
  }
145
145
  }
146
146
 
@@ -150,7 +150,7 @@ module.exports.uiClasses = (context, options, svr, send, hook, rmHook) => {
150
150
  hook(rid, 'findElement', (data) => {
151
151
  r(CreatedElements.find(e => e.uuid == data.uuid) || data);
152
152
  });
153
- send(JSON.stringify({ action: 'findElement', data: { id, rid } }));
153
+ send({ action: 'findElement', data: { id, rid } });
154
154
  });
155
155
  }
156
156
 
@@ -6,16 +6,22 @@ const fs = require("fs");
6
6
  const { uiClasses } = require("./modules/ui/classes");
7
7
  const { generateRandomID } = require("../functions/id");
8
8
  const { THEME_PATH } = require("../const/files");
9
-
9
+ const readline = require('readline');
10
+ const emitter = require("../functions/emitter");
10
11
 
11
12
  const BIN_PATH = path.resolve(__dirname, "../../../bin/ui");
12
13
  const HTML_STRING = fs.readFileSync(
13
14
  path.resolve(__dirname, "../html/ui.html"),
14
15
  { encoding: "utf-8" },
15
16
  );
17
+ const JS_STRING = fs.readFileSync(
18
+ path.resolve(__dirname, "../html/ui.js"),
19
+ { encoding: "utf-8" },
20
+ );
21
+
22
+ const replaceString = (string, options) => string.replace(/\$OPTIONS\(([^)]+)\)/g, (_, n) => n.startsWith('json.') ? JSON.stringify(options[n.split('json.')[1]] || '{}') : options[n] || _);
16
23
 
17
24
  const defaultOptions = {
18
- port: 14473,
19
25
  title: "Title",
20
26
  onExit: () => process.exit(),
21
27
  style: '',
@@ -34,6 +40,7 @@ module.exports = (context) => ({
34
40
  const hookedSocketListeners = {};
35
41
 
36
42
  const runId = generateRandomID();
43
+ const tmpFile = "/tmp/" + runId + ".ruw.ui.socket";
37
44
 
38
45
  options.runId = runId;
39
46
 
@@ -41,65 +48,95 @@ module.exports = (context) => ({
41
48
 
42
49
  options.style = ' */\n'+options.style+'\n/* ';
43
50
 
44
- const svr = http.createServer((req, res) => {
45
- res.write(
46
- HTML_STRING
47
- .replace(/\$OPTIONS\(([^)]+)\)/g, (_, n) => n.startsWith('json.') ? JSON.stringify(options[n.split('json.')[1]] || '{}') : options[n] || _)
48
- );
49
- res.end();
50
- });
51
+ const HTML = replaceString(HTML_STRING, options);
52
+ const JS = replaceString(JS_STRING, options);
51
53
 
52
- const wss = new WebSocket.Server({ server: svr });
53
- const sockets = [];
54
-
55
- wss.on("connection", (ws) => {
56
- ws.send(JSON.stringify({ action: "init", data: options }));
57
- sockets.push(ws);
58
- ws.on('message', (event) => {
59
- const edata = JSON.parse(event.toString());
60
- if(edata.action.startsWith('hook:')){
61
- const hook = hookedSocketListeners[edata.data.rid];
62
- const type = edata.action.split('hook:')[1];
63
- if(hook && hook.type == type) {
64
- hookedSocketListeners[edata.data.rid].cb(edata.data.object);
65
- if(hook.once) delete hookedSocketListeners[edata.data.rid];
66
- }
67
- }
68
- });
54
+ const queue = [];
55
+
56
+ const send = (data) => {
57
+ const content = fs.readFileSync(tmpFile, { encoding: 'utf-8' });
58
+ if(content) {
59
+ queue.push(data);
60
+ } else {
61
+ fs.writeFileSync(tmpFile, typeof data !== "string" ? JSON.stringify(data) : data);
62
+ }
63
+ }
64
+
65
+ const sendEvent = (data) => {
66
+ send({ action: 'JS', data: `window.recieveMessage(${JSON.stringify(data)})` })
67
+ }
68
+
69
+ const g_emitter = emitter();
70
+
71
+ const recieve = (data) => {
72
+ g_emitter.emit('recieve', data);
73
+ }
74
+
75
+ const rl = readline.createInterface({
76
+ input: process.stdin,
77
+ output: process.stdout
69
78
  });
70
79
 
71
- svr.listen(options.port);
80
+ rl.question('', () => {});
81
+
82
+ fs.writeFileSync(tmpFile, '');
83
+
84
+ fs.watch(tmpFile, { encoding: 'utf-8' })
85
+ .on('change', () => {
86
+ if(queue.length){
87
+ send(queue.pop());
88
+ }
89
+ });
72
90
 
73
- const url = new URL(`http://localhost:${options.port}`);
91
+ const p = spawn(BIN_PATH, [runId]);
74
92
 
75
- const p = spawn(BIN_PATH, [url.toString(), runId]);
93
+
76
94
 
77
95
  p.on("close", (code) => {
96
+ rl.close();
78
97
  options.onExit(code);
79
98
  });
80
99
 
81
- process.on("beforeExit", () => p.kill());
100
+ process.on("beforeExit", () => {
101
+ p.kill();
102
+ fs.unlinkSync(tmpFile);
103
+ });
104
+
105
+ g_emitter.on('recieve', (edata) => {
106
+ if(edata.action.startsWith('hook:')){
107
+ const hook = hookedSocketListeners[edata.data.rid];
108
+ const type = edata.action.split('hook:')[1];
109
+ if(hook && hook.type == type) {
110
+ hookedSocketListeners[edata.data.rid].cb(edata.data.object);
111
+ if(hook.once) delete hookedSocketListeners[edata.data.rid];
112
+ }
113
+ }
114
+ });
82
115
 
83
- // p.on('message', console.log);
84
- // p.on('error', console.log);
85
- // exec(BIN_PATH+' '+'http://localhost:' + port, console.log)
86
116
  return new Promise((r) => {
87
117
  p.stdout.on("data", (data) => {
88
- if (data.toString().trim() == "INIT::READY") {
89
- r(
90
- uiClasses(context, options, svr, (message, cb) => { // Send message
91
- sockets.forEach((socket) => socket.send(message, cb));
92
- }, (rid, type, cb, once = true) => { // Add hook
93
- hookedSocketListeners[rid] = { type, cb, once };
94
- }, (rid) => { // Remove hook
95
- delete hookedSocketListeners[rid];
96
- }),
97
- );
118
+ if (data.toString().startsWith("RESPONSE::")) {
119
+ const d = data.toString().split("RESPONSE::")[1];
120
+ const jd = JSON.parse(d);
121
+ recieve(jd);
122
+ } else if(data.toString().trim().endsWith('SETUP::READY')) {
123
+ console.log('READY');
124
+ r(uiClasses(context, options, sendEvent, (cb) => {
125
+ g_emitter.on('recieve', cb);
126
+ }, (rid, type, cb, once = true) => { // Add hook
127
+ hookedSocketListeners[rid] = { type, cb, once };
128
+ }, (rid) => { // Remove hook
129
+ delete hookedSocketListeners[rid];
130
+ }));
131
+ } else if(data.toString().endsWith('SETUP::HTML')) {
132
+ send({action: 'JS2', data: JS, isSetup: true});
133
+ } else if(data.toString() == 'INIT::READY') {
134
+ send({action: 'HTML', data: HTML});
98
135
  } else {
99
136
  console.log(data.toString());
100
137
  }
101
138
  });
102
-
139
+
103
140
  p.stderr.on("data", (data) => {
104
141
  console.error(data.toString());
105
142
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@makano/rew",
3
- "version": "1.0.22",
4
- "description": "",
3
+ "version": "1.1.1",
4
+ "description": "A simple coffescript runtime",
5
5
  "main": "lib/rew/main.js",
6
6
  "directories": {
7
7
  "lib": "lib"
@@ -14,7 +14,8 @@
14
14
  },
15
15
  "files": [
16
16
  "lib/",
17
- "bin/"
17
+ "bin/",
18
+ "README.md"
18
19
  ],
19
20
  "bin": {
20
21
  "rew": "bin/rew"