@makano/rew 1.0.22 → 1.1.1

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/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"