jsgui3-server 0.0.128 → 0.0.131

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.
@@ -7,7 +7,7 @@ if (require.main === module) {
7
7
 
8
8
  const server = new Server({
9
9
  Ctrl: Demo_UI,
10
- debug: true,
10
+ //debug: true,
11
11
 
12
12
 
13
13
  //'js_mode': 'debug',
@@ -37,16 +37,16 @@ Square_Box.css = `
37
37
  }
38
38
  `;
39
39
 
40
-
41
40
  // Relies on extracting CSS from JS files.
42
41
 
42
+ // want to have an easy way to put this inside an HTML document (rendered webpage);
43
+
43
44
  class Demo_UI extends Control {
44
45
  constructor(spec = {}) {
45
46
  spec.__type_name = spec.__type_name || 'demo_ui';
46
47
  super(spec);
47
48
  const {context} = this;
48
49
  this.add_class('demo-ui');
49
-
50
50
  const compose = () => {
51
51
  const box = new Square_Box({
52
52
  context: context
@@ -58,7 +58,6 @@ class Demo_UI extends Control {
58
58
  });
59
59
  //box2.background_color = '#6655CC';
60
60
  //box2.background.color = '#6655CC';
61
-
62
61
  // or even box2.color = ... and it would know which color was meant
63
62
  // or be able to access the .color reference / property name when asked for.
64
63
 
@@ -1,8 +1,6 @@
1
1
  const jsgui = require('./client');
2
-
3
- const {Demo_UI} = jsgui.controls;
4
2
  const Server = require('../../../server');
5
-
3
+ const {Demo_UI} = jsgui.controls;
6
4
 
7
5
  // what would be the (best?) way to include the whole thing in one JS file?
8
6
  // Maybe don't try that right now.
@@ -20,7 +20,7 @@ class Demo_UI extends Active_HTML_Document {
20
20
  const color_palette = new Color_Palette({
21
21
  context,
22
22
  //grid_size: [10, 10],
23
- size: [200, 200]
23
+ size: [280, 180]
24
24
  })
25
25
  window.inner.add(color_palette);
26
26
  this.body.add(window);
@@ -4,82 +4,8 @@ const {Demo_UI} = jsgui.controls;
4
4
  const Server = require('../../../server');
5
5
 
6
6
 
7
- // what would be the (best?) way to include the whole thing in one JS file?
8
- // Maybe don't try that right now.
9
- // maybe standardise on the dir, then client.js and server.js inside.
10
-
11
-
12
-
13
- // Want to exclude this from the client bundle.
14
- // Some kind of marking to say that it's server-side only?
15
-
16
- // Need to include JSGUI3 js within the client document.
17
- // Seems like an earlier code simplification removed this functionality?
18
- // Just specifying a Ctrl for the server - and giving it the 'disk_path_client_js'.
19
- // May as well fix that....
20
-
21
-
22
- // The server code may be tiny, it seems best not to abstract it away totally though.
23
- // At least not for the moment.
24
-
25
-
26
-
27
-
28
-
29
7
  if (require.main === module) {
30
8
 
31
- // By default should include the JS and the CSS.
32
- // By reference, serving them from their respective paths.
33
-
34
-
35
- // This API is not working right now.
36
-
37
- // A very simple syntax for running a single control would be great.
38
-
39
- // Need to in the default (server) configuration build and serve the client-side app.
40
- // Want to be able to make interactive apps quickly with minimal server side code that needs to be written as boilerplate to
41
- // get the app running.
42
-
43
- // Though maybe defining a webpage, that serves the client js, and renders the control on the server, and activates it on the client,
44
- // would be the right approach.
45
-
46
- // Want to make the code really explicit, in a simple way.
47
-
48
-
49
- // eg { '/': Demo_UI }
50
- // eg { '*': Demo_UI }
51
- // as at least it explicitly assigns it to the '/' route
52
-
53
-
54
- // But worth keeping the '/' Ctrl property?
55
- // Could change it to explicitly setting the route(s).
56
-
57
- // Do want it to build the client js on start.
58
-
59
- // Could extract the CSS from the file itself, or maybe better reading it from the classes and objects that are loaded / referenced.
60
- // All kinds of complex server program structures exist already, so could use Publishers if needed for some things.
61
- // But need to keep the surface-level API really simple.
62
-
63
- // Maybe define a Webpage and maybe use / define an HTML_Webpage_Publisher for example too.
64
- // The clearest code would be really explicit about what it does, but in terms of almost English idioms
65
- // and on the surface-level not spelling out in great detail what it's doing, but referencing objects and
66
- // instructions with clear purposes, though details could be obscure at the top level. Eg it's the publisher's responsibility
67
- // to include the CSS and JS that's needed to get it to run. A publisher is referenced and used, and it does its thing.
68
-
69
- // The Server could automatically involk the use of a Publisher.
70
- // May be better to either require or recommend more explicit code, have them in the examples,
71
- // but also to document some shortcuts, defaults, and abbreviations (though they may omit some essential info, so not recommended for beginners)
72
-
73
- // Could have a tabbed view for examples for 'explicit' and 'short' notations when there are multiple.
74
-
75
- // jsgui3-html-suite may be of use, for some more extended controls that are built on top of jsgui3-html, but not specifically
76
- // client or server.
77
-
78
-
79
-
80
-
81
-
82
-
83
9
  const server = new Server({
84
10
  Ctrl: Demo_UI,
85
11
  //debug: true,
@@ -0,0 +1,26 @@
1
+
2
+ const Server = require('../../server');
3
+
4
+
5
+
6
+ if (require.main === module) {
7
+
8
+ const server = new Server({
9
+ 'port': 8088
10
+
11
+ });
12
+ console.log('server.resource_names', server.resource_names);
13
+
14
+ /*
15
+ server.website.api.publish('time', () => {
16
+ return new Date().toISOString();
17
+ });
18
+ */
19
+
20
+ server.publish('time', () => {
21
+ return new Date().toISOString();
22
+ });
23
+
24
+ server.start(8088);
25
+
26
+ }
package/package.json CHANGED
@@ -3,15 +3,15 @@
3
3
  "main": "module.js",
4
4
  "license": "MIT",
5
5
  "dependencies": {
6
- "@babel/core": "^7.27.7",
7
- "@babel/generator": "^7.27.5",
8
- "@babel/parser": "7.27.7",
6
+ "@babel/core": "^7.28.3",
7
+ "@babel/generator": "^7.28.3",
8
+ "@babel/parser": "^7.28.3",
9
9
  "cookies": "^0.9.1",
10
- "esbuild": "^0.25.5",
10
+ "esbuild": "^0.25.9",
11
11
  "fnl": "^0.0.36",
12
12
  "fnlfs": "^0.0.33",
13
- "jsgui3-client": "^0.0.117",
14
- "jsgui3-html": "^0.0.163",
13
+ "jsgui3-client": "^0.0.119",
14
+ "jsgui3-html": "^0.0.165",
15
15
  "jsgui3-webpage": "^0.0.8",
16
16
  "jsgui3-website": "^0.0.8",
17
17
  "lang-tools": "^0.0.36",
@@ -38,5 +38,5 @@
38
38
  "type": "git",
39
39
  "url": "https://github.com/metabench/jsgui3-server.git"
40
40
  },
41
- "version": "0.0.128"
41
+ "version": "0.0.131"
42
42
  }
@@ -0,0 +1,16 @@
1
+
2
+
3
+ const Publishers = {
4
+ 'css': require('./http-css-publisher'),
5
+ 'function': require('./http-function-publisher'),
6
+ 'html_page': require('./http-html-page-publisher'),
7
+ 'html': require('./http-html-publisher'),
8
+ 'jpeg': require('./http-jpeg-publisher'),
9
+ 'js': require('./http-js-publisher'),
10
+ 'observable': require('./http-observable-publisher'),
11
+ 'png': require('./http-png-publisher'),
12
+ 'resource': require('./http-resource-publisher'),
13
+ 'svg': require('./http-svg-publisher')
14
+ }
15
+
16
+ module.exports = Publishers;
@@ -86,16 +86,9 @@ class Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner
86
86
  if (item.text) {
87
87
 
88
88
  // Async compression definitely seems much better here.
89
-
90
-
91
89
  const buf_gzipped = await gzip_compress(item.response_buffers.identity);
92
-
93
90
  item.response_buffers.gzip = buf_gzipped;
94
91
 
95
- // Maybe should be 11 in many cases.
96
- // Seems right when publishing static JS resources.???
97
- // Compromise with 10 for the moment.
98
-
99
92
  const buf_br = await br_compress(item.response_buffers.identity, {
100
93
  params: {
101
94
  //[zlib.constants.BROTLI_PARAM_MODE]: zlib.constants.BROTLI_MODE_TEXT,
@@ -105,28 +98,9 @@ class Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner
105
98
  });
106
99
 
107
100
  item.response_buffers.br = buf_br;
108
-
109
-
110
- // The gzip response
111
- // The brotli response
112
-
113
- // promisifying these calls would help.
114
-
115
-
116
- /*
117
-
118
-
119
- const buf_identity_response = Buffer.from(item.text, 'utf-8');
120
-
121
- item.response_buffers = item.response_buffers || {};
122
- item.response_buffers.identity = buf_identity_response;
123
- */
124
101
  } else {
125
102
 
126
103
  }
127
-
128
-
129
-
130
104
  //console.trace();
131
105
  //throw 'stop';
132
106
  }
@@ -135,13 +109,7 @@ class Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner
135
109
  console.trace();
136
110
  throw 'stop';
137
111
  }
138
-
139
-
140
-
141
-
142
112
  }
143
-
144
-
145
113
  }
146
114
 
147
115
 
@@ -1,52 +1,20 @@
1
1
 
2
2
 
3
3
  const Assigner = require('../Assigner');
4
-
5
4
  const {is_array} = require('lang-tools');
6
5
 
7
- // And will have some very or less specific assigners for some other things.
8
- // Like the compressed (text?) response headers.
9
-
10
-
11
-
12
-
13
6
  class Single_Control_Webpage_Server_Static_Routes_Assigner extends Assigner {
14
7
 
15
8
  constructor(spec = {}) {
16
9
  super(spec);
17
10
  }
18
11
 
19
- // assign to bundle....
20
- // or array would be better.
21
-
22
- // assign to (bundle) items in array.
23
-
24
12
  async assign(arr_bundled_items) {
25
- // go through them....
26
-
27
- // Maybe check that the correct items are in the bundle.
28
-
29
- // Perhaps check for 1 of each js, css, html
30
- // And could use a specific other class to assign these.
31
-
32
- // Should be OK to make classes for really specific things.
33
- // At this part of the system / API, it's not necessary / important to limit complexity in that way.
34
-
35
- // The goal is to provide a very simple high level interface. Powerful too.
36
-
37
- // Could assign a static_route property to the items in the bundles.
38
-
39
-
40
-
41
-
42
13
 
43
14
  if (is_array(arr_bundled_items)) {
44
15
 
45
16
  for (const item of arr_bundled_items) {
46
17
  //console.log('item', item);
47
-
48
-
49
-
50
18
  const {type} = item;
51
19
 
52
20
  // Just very simple for the moment.
@@ -56,13 +24,9 @@ class Single_Control_Webpage_Server_Static_Routes_Assigner extends Assigner {
56
24
  if (type === 'JavaScript') {
57
25
  item.route = '/js/js.js';
58
26
 
59
-
60
-
61
27
  } else if (type === 'CSS') {
62
28
  item.route = '/css/css.css';
63
29
 
64
-
65
-
66
30
  } else if (type === 'HTML') {
67
31
  item.route = '/';
68
32
 
@@ -79,13 +43,7 @@ class Single_Control_Webpage_Server_Static_Routes_Assigner extends Assigner {
79
43
  console.trace();
80
44
  throw 'stop';
81
45
  }
82
-
83
-
84
-
85
-
86
46
  }
87
-
88
-
89
47
  }
90
48
 
91
49
 
@@ -41,35 +41,9 @@ class Single_Control_Webpage_Server_Static_Uncompressed_Response_Buffers_Assigne
41
41
  // assign to (bundle) items in array.
42
42
 
43
43
  async assign(arr_bundled_items) {
44
- // go through them....
45
-
46
- // Maybe check that the correct items are in the bundle.
47
-
48
- // Perhaps check for 1 of each js, css, html
49
- // And could use a specific other class to assign these.
50
-
51
- // Should be OK to make classes for really specific things.
52
- // At this part of the system / API, it's not necessary / important to limit complexity in that way.
53
-
54
- // The goal is to provide a very simple high level interface. Powerful too.
55
-
56
- // Could assign a static_route property to the items in the bundles.
57
-
58
-
59
-
60
-
61
-
62
44
  if (is_array(arr_bundled_items)) {
63
-
64
45
  for (const item of arr_bundled_items) {
65
- //console.log('item', item);
66
-
67
46
  const {type} = item;
68
-
69
- // And need to create the uncompressed response buffer.
70
-
71
- // // response_buffers.identity I think....
72
-
73
47
  if (item.text) {
74
48
  const buf_identity_response = Buffer.from(item.text, 'utf-8');
75
49
 
@@ -78,11 +52,6 @@ class Single_Control_Webpage_Server_Static_Uncompressed_Response_Buffers_Assigne
78
52
  } else {
79
53
 
80
54
  }
81
-
82
-
83
-
84
- //console.trace();
85
- //throw 'stop';
86
55
  }
87
56
 
88
57
  } else {
@@ -40,6 +40,7 @@ class Function_Publisher extends HTTP_Publisher {
40
40
  fn = spec;
41
41
  } else {
42
42
  fn = spec.fn;
43
+ this.name = spec.name;
43
44
  if (spec.schema) {
44
45
  this.schema = spec.schema;
45
46
  } else {
@@ -50,6 +51,7 @@ class Function_Publisher extends HTTP_Publisher {
50
51
  //let fn = spec;
51
52
  //console.log('Function_Publisher constructor fn', fn);
52
53
  //console.log('Function_Publisher constructor fn', fn.toString());
54
+ // But will need to route to the function publisher.
53
55
 
54
56
  this.handle_http = (req, res) => {
55
57
  // need to handle observable http request.
@@ -64,8 +66,8 @@ class Function_Publisher extends HTTP_Publisher {
64
66
 
65
67
  const {method, headers} = req;
66
68
 
67
- console.log('Function Publisher handle_http method', method);
68
- console.log('headers', headers);
69
+ //console.log('Function Publisher handle_http method', method);
70
+ //console.log('headers', headers);
69
71
 
70
72
  // Need to get the incoming parameters.
71
73
  // Need to use formidable or whatever else...?
@@ -88,12 +90,21 @@ class Function_Publisher extends HTTP_Publisher {
88
90
 
89
91
  req.on('end', () => {
90
92
  const buf_input = Buffer.concat(chunks);
91
- console.log('buf_input', buf_input);
93
+ //console.log('buf_input', buf_input);
92
94
 
93
95
  // then interpret it according to the content_type
94
96
  let obj_input;
97
+ //console.log('content_type', content_type);
98
+ if (!content_type) {
99
+ console.log('buf_input.length', buf_input.length);
100
+ if (buf_input.length === 0) {
95
101
 
96
- if (content_type.startsWith('text/plain')) {
102
+ } else {
103
+ console.trace();
104
+ throw 'NYI';
105
+ }
106
+ } else {
107
+ if (content_type.startsWith('text/plain')) {
97
108
  obj_input = buf_input.toString();
98
109
 
99
110
  } else {
@@ -106,6 +117,9 @@ class Function_Publisher extends HTTP_Publisher {
106
117
  }
107
118
  // decode / parse JSON.
108
119
  }
120
+ }
121
+
122
+
109
123
 
110
124
 
111
125
  const output_all = (call_res) => {
@@ -129,6 +143,7 @@ class Function_Publisher extends HTTP_Publisher {
129
143
 
130
144
  const fn_res = fn(obj_input);
131
145
  const tfr = tf(fn_res);
146
+ //console.log('fn_res', fn_res);
132
147
 
133
148
  //console.log('tfr', tfr);
134
149
 
@@ -145,6 +160,20 @@ class Function_Publisher extends HTTP_Publisher {
145
160
  });
146
161
 
147
162
 
163
+ } else if (tfr === 's') {
164
+ // Just write it as a string for the moment I think?
165
+ // Or always encode as JSON?
166
+
167
+ // text/plain;charset=UTF-8
168
+
169
+ res.writeHead(200, {
170
+ 'Content-Type': 'text/plain;charset=UTF-8'//,
171
+ //'Transfer-Encoding': 'chunked',
172
+ //'Trailer': 'Content-MD5'
173
+ });
174
+ res.end(fn_res);
175
+
176
+
148
177
  } else {
149
178
 
150
179
  console.trace();
@@ -173,10 +202,6 @@ class Function_Publisher extends HTTP_Publisher {
173
202
 
174
203
 
175
204
 
176
-
177
-
178
-
179
-
180
205
  });
181
206
 
182
207
 
@@ -0,0 +1,46 @@
1
+ const fs = require('fs');
2
+ const HTTP_Publisher = require('./http-publisher');
3
+
4
+ class PNG_Publisher extends HTTP_Publisher {
5
+ constructor(spec) {
6
+ super(spec);
7
+ this.filePath = spec.filePath;
8
+ this.resource = spec.resource;
9
+ }
10
+
11
+ handle_http(req, res) {
12
+ if (req.method !== 'GET') {
13
+ res.writeHead(405, { 'Allow': 'GET' });
14
+ return res.end('Method Not Allowed');
15
+ }
16
+
17
+ const sendBuffer = buf => {
18
+ res.setHeader('Content-Type', 'image/png');
19
+ res.setHeader('Content-Length', buf.length);
20
+ res.setHeader('Cache-Control', 'public, max-age=31536000');
21
+ res.end(buf);
22
+ };
23
+
24
+ if (this.resource && typeof this.resource.getPNG === 'function') {
25
+ Promise.resolve(this.resource.getPNG())
26
+ .then(buf => sendBuffer(buf))
27
+ .catch(() => {
28
+ res.writeHead(500);
29
+ res.end('Internal Server Error');
30
+ });
31
+ } else if (this.filePath) {
32
+ fs.readFile(this.filePath, (err, buf) => {
33
+ if (err) {
34
+ res.writeHead(404);
35
+ return res.end('Not Found');
36
+ }
37
+ sendBuffer(buf);
38
+ });
39
+ } else {
40
+ res.writeHead(500);
41
+ res.end('No PNG resource configured');
42
+ }
43
+ }
44
+ }
45
+
46
+ module.exports = PNG_Publisher;
@@ -1,34 +1,4 @@
1
- // Want to get it (back) working as a server easily serving simple controls and pages and sites.
2
- // Need to tame some of the more complex layers inside it to get it to easily serve the app.
3
- // Then should work on making / improving some of the specific controls.
4
- // Make the code idiomatic and DRY. The more complex lower and middle level abstractions will help with that.
5
- // Use polymorphism and run-time checks to allow for some more flexibility.
6
1
 
7
-
8
-
9
- // Later on will probably make some new very specific classes to encapsulate things the HTTP_Webpage_Publisher does.
10
-
11
- // Maybe have the publisher use Preparer or other (slightly) more specific classes.
12
-
13
-
14
-
15
-
16
- // The publisher will need to do a few things / have some things done, but make it rely on the helpers
17
- // and bundlers and extractors.
18
-
19
- // The helpers maybe could call the bundlers and extractors.
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
- // A publisher handles HTTP requests.
29
-
30
- // This is going to take over some of the responsibilities of the old website resource, which was unfocused code that was
31
- // doing some of the main / most important parts of serving the website.
32
2
  const jsgui_client = require('jsgui3-client');
33
3
 
34
4
  const HTTP_Publisher = require('./http-publisher');
@@ -37,82 +7,10 @@ const Server_Static_Page_Context = require('../static-page-context');
37
7
  const HTTP_Webpageorsite_Publisher = require('./http-webpageorsite-publisher');
38
8
  const {obs} = require('fnl');
39
9
 
40
- // May want / need to more carefully and specifically define APIs.
41
- // It's nice to have classes for specific things like this, but need to make them do what is needed.
42
- // Maybe get a 'Website' object or control ready to be served.
43
- //
44
10
  const Static_Routes_Responses_Webpage_Bundle_Preparer = require('./helpers/preparers/static/bundle/Static_Routes_Responses_Webpage_Bundle_Preparer');
45
11
 
46
-
47
-
48
- // Named observables?
49
- /*
50
-
51
- obs((next, complete, error) => {
52
-
53
- */
54
-
55
-
56
- // HTTP_Webpage_Publisher could be interesting.
57
- // The Website Publisher could make use of some of its functionality.
58
-
59
- // Handling HTTP / bundling for a specific page could be cool.
60
-
61
- // A Webpage Publisher may be simpler and better to work on in the short term.
62
- // Maybe would not need to be (as) concerned with routing.
63
- // Could be useful for publishing a SPA of course, kind of a website but as a single page.
64
-
65
- // Should have more concerning bundling / compilation.
66
-
67
-
68
- // There could be 'bundle' functionality for the webpage.
69
-
70
- // The webpage itself could know what client js it needs to use.
71
-
72
- // Seems like bundling a specified webpage earlier on in the process makes sense.
73
-
74
- // And a Bundler as well?
75
- // Perhaps HTTP_Webpage_Bundler would be an important class to have here.
76
- // Considering how it could be interchangable from the publisher if it's a different class.
77
-
78
- // Possibly a Publisher should be called to provide something over HTTP.
79
- // So the call is routed to a Webpage object, through the Publisher.
80
- // Publisher could maintain a cache.
81
- // Maybe the publisher should read the bundle?
82
- // Maybe the publisher should do the bundling?
83
- // Perhaps there should be a bit more coordination of the bundling process, possibly accessed once needed.
84
- //
85
-
86
-
87
- // Should include or use various other publishers, such as html or js?
88
-
89
-
90
- // HTTP_Static_Webpage_Publisher perhaps....
91
-
92
-
93
- // Also have various Authorisers ...
94
- // Have Authenticators ...
95
-
96
-
97
-
98
-
99
-
100
-
101
12
  class HTTP_Webpage_Publisher extends HTTP_Webpageorsite_Publisher {
102
13
 
103
- // Website generally serves JS from a single address.
104
- // Webpage could have its specific JS.
105
- // This component may need to handle the JS building.
106
- // webpage-bundler within the 'bundler' directory.
107
-
108
- // But not sure if babel or esbuild is better here.
109
- // Babel has obviously improved since I had to switch to esbuild years ago.
110
- // Being able to use either would help.
111
-
112
-
113
-
114
-
115
-
116
14
  constructor(spec = {}) {
117
15
  super(spec)
118
16
 
@@ -125,74 +23,9 @@ class HTTP_Webpage_Publisher extends HTTP_Webpageorsite_Publisher {
125
23
  return webpage;
126
24
  }
127
25
  });
128
-
129
-
130
-
131
-
132
- // But like the website publisher, this would need to bundle the page (JS, CSS, maybe more).
133
- // Consider that an SPA may reference images. May not exactly be one page in some ways.
134
-
135
-
136
-
137
-
138
-
139
- // Probably best to come up with a bundle here, or at an early stage.
140
-
141
- // .prepare_bundle?
142
-
143
- // .prepare_bundle would be a good function to have here.
144
-
145
-
146
-
147
- // .bundle?
148
- // seems clearest that we will be getting / preparing multiple files.
149
-
150
- // Bundling and compiling web content seems like a better thing to get working before serving (or attempting to serve) it.
151
- // .build?
152
-
153
- /*
154
- setTimeout(() => {
155
-
156
-
157
- this.raise('ready');
158
- }, 0);
159
-
160
- */
161
-
162
26
  this.static_routes_responses_webpage_bundle_preparer = new Static_Routes_Responses_Webpage_Bundle_Preparer();
163
-
164
27
  (async() => {
165
-
166
28
  const res_get_ready = await this.get_ready();
167
-
168
-
169
- // Is the HTML to be static or regenerated on page calls?
170
- // Want an easy way to specify it.
171
-
172
-
173
-
174
- // Then set things (a single static route???) up for the webpage.
175
- // Be very explicit with classes to do specific things like this so they will be easier to find and change.
176
-
177
- // Should render the webpage (once)
178
- // Maybe use a class on a higher level to choose this important rendering / caching setting.
179
-
180
- // Maybe the server could render multiple times over a few minutes before deciding it's not going to change.
181
-
182
- // Though telling the server it's static would help in some / many cases.
183
- // Have it as a sensible default depending on the situation.
184
-
185
- // Could even look at the controls to see if anything is non-static.
186
- // Or mark things somehow.
187
-
188
- // At least want to make this setting very clear in the future.
189
-
190
-
191
-
192
-
193
-
194
-
195
-
196
29
  this.raise('ready', res_get_ready);
197
30
 
198
31
  })();
@@ -208,33 +41,9 @@ class HTTP_Webpage_Publisher extends HTTP_Webpageorsite_Publisher {
208
41
  // Its a bundle....
209
42
  const webpage_or_website_res_get_ready = await super.get_ready();
210
43
 
211
- //console.log('webpage_or_website_res_get_ready', webpage_or_website_res_get_ready);
212
-
213
-
214
-
215
44
 
216
45
  const render_webpage = async () => {
217
46
 
218
- // Activate it or not.... As in serve active JSGUI control content. HTML ready to be activated on the client.
219
-
220
- // .active();
221
- // Generally would want that as standard.
222
-
223
- // Need to be very clear about generating active content on the server side.
224
- // Ready to be activated on the client-side.
225
- // Though could possibly activate using CSS classes.
226
-
227
-
228
-
229
-
230
- // Probably best to make a Server_Page_Context here.
231
- // Server_Static_Page_Context perhaps.
232
-
233
-
234
-
235
- // Maybe a class to render the single page into the bundle?
236
- // Maybe only worth doing when there become (many) more options and divisions seem clearer.
237
-
238
47
  const {webpage} = this;
239
48
  const Ctrl = webpage.content;
240
49
 
@@ -250,107 +59,27 @@ class HTTP_Webpage_Publisher extends HTTP_Webpageorsite_Publisher {
250
59
 
251
60
  if (ctrl.head && ctrl.body) {
252
61
 
253
-
254
- // Create the CSS link control
255
-
256
- //console.log('jsgui_client.controls', jsgui_client.controls);
257
-
258
- //console.log('jsgui_client.controls', Object.keys(jsgui_client.controls));
259
-
260
62
  const ctrl_css_link = new jsgui_client.controls.link({
261
63
  context: static_page_context
262
64
  });
263
65
  ctrl_css_link.dom.attributes.rel = 'stylesheet';
264
66
  ctrl_css_link.dom.attributes.href = '/css/css.css';
265
-
266
67
  ctrl.head.add(ctrl_css_link);
267
-
268
-
269
- // Then add the JS Script ref (with href) to the (end of the) body.
270
-
271
- // Content_Incorporator perhaps???
272
- // Bundle_Content_Incorporator?
273
-
274
- // Will be worth making classes to do this when there is more variety of settings and operations.
275
-
68
+
276
69
  const ctrl_js_script_link = new jsgui_client.controls.script({
277
70
  context: static_page_context
278
71
  });
279
72
 
280
73
  ctrl_js_script_link.dom.attributes.src = '/js/js.js';
281
-
282
74
  ctrl.body.add(ctrl_js_script_link);
283
-
284
- // <script src="myscripts.js"></script>
285
-
286
-
287
- //console.log('!!ctrl.head', !!ctrl.head);
288
- //console.log('!!ctrl.body', !!ctrl.body);
289
-
290
- // add the css ref to the head, then the script ref to the body.
291
-
292
- // ctrl.body????
293
-
294
- // or add it to the body....
295
- // ctrl.head.add(new jsgui.script(...))
296
-
297
-
298
- // Adding script references...?
299
-
300
- // or .activate with it working on the server...?
301
-
302
-
303
-
304
- // Could have settings which determine which HTML elements get activated into controls, which don't.
75
+
305
76
  ctrl.active();
306
-
307
-
308
-
309
- // .active should do enough I think....
310
-
311
- // Server_Page_Context being the context of a publisher doing a one-time static rendering of a only page's HTML
312
- // Does seem like the Servier_Page_Context will be needed for this to work properly.
313
- // Want to hide some details that won't need changing from the top level API.
314
- // All kinds of things like page contexts will help in the background, they should be there to make
315
- // things easier.
316
-
317
-
318
-
319
-
320
-
321
-
322
- // do we need a Server_Page_Context first?
323
-
324
77
  const html = await ctrl.all_html_render();
325
-
326
- // Produces the HTML fairly well here....
327
-
328
-
329
- // Want to provide these as static resources to the server / router.
330
- // The publisher itself should not need to handle HTTP requests each time.
331
- // Keep the option for that though, it may help with some systems, more dynamic, not static responses.
332
-
333
- // Focus a lot on ease of use to set up servers with sensible and powerful defaults.
334
- // Also not requiring a specific directory or project structure.
335
- // Serving a simple app with a simple JS file.
336
-
337
-
338
-
339
-
340
-
341
-
342
-
343
-
344
- //console.log('html', html);
345
-
346
- //console.trace();
347
- //throw 'NYI';
348
-
349
78
  return html;
79
+ } else {
350
80
 
81
+ // C reate doc and put control inside that?
351
82
 
352
-
353
- } else {
354
83
  console.trace();
355
84
  throw 'NYI';
356
85
  }
@@ -381,279 +110,25 @@ class HTTP_Webpage_Publisher extends HTTP_Webpageorsite_Publisher {
381
110
  // Then publish it to the router...?
382
111
  // server.serve_prepared_static_routes_bundle ?????
383
112
  return webpage_or_website_res_get_ready;
384
-
385
-
386
-
387
- // But then the bundle with static routes should be given / provided to the server.
388
- // Would be nice to end the responsibility of the Publisher once the final prepared bundle with static
389
- // routes and static content (compressed in different ways, uncompressed buffer there too) and have the
390
- // Server or Server Router do the rest.
391
-
392
- // Improve handling of prepared to serve (HTTP response) bundles, making it easy to tell the server to use them.
393
-
394
- // Maybe make a more advanced HTTP_Responder baked into the server.
395
- // Or an interchagable class that does it, used within the server.
396
-
397
-
398
-
399
-
400
-
401
-
402
-
403
-
404
-
405
- // Then send it off to the final stage bundler / Final_Stage_Bundle_Preparer_That_Prepares_Static_Routes_Responses
406
-
407
- // Some very long and explicit class names seem appropriate.
408
-
409
- // Final_Stage_Webpage_Bundle_Preparer_Of_Static_Routes_Responses
410
-
411
- // Static_Routes_Responses_Webpage_Bundle_Preparer
412
- // That should be fine doing the very last part.
413
-
414
- // But then another component to assign these static routes to the router?
415
- // Or maybe that's easy enough to do with a function call (or a few).
416
-
417
- // Prepared_Responses_Cache???
418
-
419
- // Don't want to make big changes to the router and server itself right now.
420
- // Though an extra function (or a few) could help within Server_Router.
421
- // Or not the router, but do it here in the handle_http function call.
422
- // With the router just routing those URLs here.
423
-
424
- // Does seem better architecture for the publisher to hand the responsibility off to some (other) server component.
425
-
426
-
427
-
428
-
429
-
430
-
431
-
432
-
433
- // then add that webpage html to the bundle.
434
-
435
-
436
-
437
- // Then add a new static HTML item to the bundle.
438
-
439
-
440
-
441
- //console.log('webpage_html', webpage_html);
442
-
443
-
444
- // Add it to the bundle
445
- // Prepare the bundle to serve with static routes
446
- // Give the prepared bundle to the server (router).
447
-
448
- // Then see it running small and increasingly large apps.
449
-
450
-
451
-
452
-
453
-
454
- // Add the webpage HTML to the bundle.
455
- // Then call the static routes assigner on the array in the bundle (._arr)
456
-
457
- // Then get server_static_route_prepared_responses.
458
-
459
- // Then maybe some other class assigns these prepared responses to the server or server router.
460
-
461
- // When preparing static responses, should prepare them gzipped, brotlied, and uncompressed.
462
- // Though will (always?) use UTF8, will make that explicit and allow for other encoding types.
463
-
464
-
465
-
466
- // Preparer or Bundle_Perparer could be a final / further stage.
467
- // And would itself use other classes internally with very specific functionality
468
-
469
-
470
-
471
-
472
-
473
-
474
- // Then it will be about assembling the routing instructions.
475
-
476
- // So then different conventions / systems could be used to assign static routes.
477
- // And very clear in the code what is going on (through use of very explicit and specific class / classes that do this).
478
-
479
-
480
- // Server_Static_Routes_Assigner perhaps.
481
- // subclass:
482
- // Single_Control_Webpage_Server_Static_Routes_Assigner
483
-
484
- // Assigning the static routes with a class makes sense, could hard-code things here but want better options that can be interchanged
485
- // and modified and improved separately.
486
-
487
-
488
-
489
- // Bundle_To_Serve_Statically_Preparer
490
- // .prepare(bundle)
491
-
492
- // Really simple function calling syntax, really clear responsibilities, and if any wind up not being used then that will be
493
- // fine.
494
-
495
-
496
-
497
-
498
-
499
- // Server_Prepared_Static_Routes_Responses
500
-
501
-
502
- // publishers/publishing-tools perhaps....?
503
-
504
- // Or create a bundle that then includes the HTML document.
505
- // Could add headers and compressed buffers (to write to responses) to the existing bundle items.
506
113
 
507
-
508
- // The system as a whole here is not massively complex, but moderately.
509
- // Changable minute details will be finite in this implementation but infinite when it comes to extending and
510
- // making subcategories especially in terms of how things are done internally to that system.
511
-
512
-
513
-
514
-
515
-
516
-
517
-
518
-
519
-
520
- //console.trace();
521
- //throw 'NYI';
522
-
523
-
524
-
525
-
526
- // Probably need to call a preparer???
527
- // Need (something to) server the static things, but also if the rendered HTML itself is static, having that pre-rendered
528
- // would be best.
529
-
530
-
531
- // Should make the rendering more abstract (less specific code in Server itself) and be very clear indeed what the classes
532
- // do by naming them well.
533
-
534
- // But the publisher itself does handle the HTTP.
535
- // That possibly should not always be the case.
536
-
537
-
538
- // Website_Static_Responses_Preparer
539
- // Webpage_Static_Responses_Preparer
540
-
541
-
542
-
543
- // HTTP_Response_Preparer could be a useful class and one to subclass from.
544
-
545
- // HTTP_Static_Response_Preparer
546
-
547
-
548
-
549
-
550
-
551
-
552
-
553
-
554
- // Or maybe insert references to the bundled content appropriately into the HTML.
555
-
556
- // At the end of the body may be best for the JS???
557
- // Want nice options for this.
558
-
559
- // Then here we need to create static HTML....
560
-
561
-
562
-
563
114
  }
564
115
 
565
- // The publisher should not (always / usually) handle the HTTP calls.
566
- // It may be worth having architecture that allows for it when publishing dynamic content.
567
- // When publishing static content it's better to pass that static content onto the server. (specific static content for specific routes / urls)
568
- // Maybe dict or map lookup is better for those static content URLs.
569
-
570
-
571
-
572
-
573
-
574
116
 
575
117
  handle_http(req, res) {
576
-
577
-
578
- // Don't (automatically) connect this function.
579
-
580
118
  console.log('HTTP_Webpage_Publisher handle_http');
581
119
  console.log('req.url', req.url);
582
120
 
583
- // Should not (need to?) handle the HTTP here.
584
-
585
- // Ideally the Webpage Publisher will have already bundled all the static files.
586
-
587
-
588
- // HTTP_Webpage_Request_Handler perhaps?
589
-
590
-
591
-
592
-
593
-
594
- // Is the webpage rendered?
595
- // Does the webpage require rendering?
596
- // Seems like the main question to ask here.
597
-
598
-
599
-
600
-
601
- // returning an observable would make sense.
602
- // so other parts of the server could observe the request being processed.
603
-
604
-
605
-
606
-
607
- // This may be quite concerned with ensuring the bundle before handling any http requests to provide it or parts of it.
608
- // Could even unit test before running deployed code.
609
-
610
- // Could get info on what needs to be bundled from the webpage object itself.
611
- // A Webpage objects could have 'requirements', or 'build requirements'.
612
- // If such things are needed, then make classes for them.
613
-
614
-
615
-
616
-
617
-
618
-
619
-
620
-
621
-
622
-
623
-
624
-
625
- //console.log('HTTP_Webpage_Publisher handle_http');
626
- //console.log('req', req);
627
-
628
121
  const {webpage} = this;
629
- //console.log('webpage', webpage);
630
- //console.log('webpage.render()', webpage.render());
631
- //console.log('Object.keys (webpage)', Object.keys (webpage));
632
-
633
- //console.log('webpage.content', webpage.content);
634
-
122
+
635
123
  const Ctrl = webpage.content;
636
124
  const ctrl = new Ctrl();
637
-
638
- //console.log('webpage.content.render()', webpage.content.render());
639
- //console.log('webpage.content[0]', webpage.content[0]);
640
-
641
- //res.statusCode = 200;
642
- //response.setHeader('Content-Type', 'text/html');
125
+
643
126
  res.writeHead(200, {
644
127
  'Content-Type': 'text/html'
645
128
  });
646
129
 
647
130
  res.end(ctrl.all_html_render());
648
-
649
-
650
-
651
-
652
- // May have bundle already prepared anyway.
653
- // Possibly the Website or the Website_Resource could do the bundling / building.
654
- // Could even bundle into a ZIP file :)
655
-
656
- //throw 'NYI';
131
+
657
132
  }
658
133
  }
659
134
 
@@ -207,9 +207,11 @@ class HTTP_Website_Publisher extends HTTP_Webpageorsite_Publisher {
207
207
 
208
208
  // Will probably insert new bundling code here - but refer to advanced classes that handle the details.
209
209
 
210
+ /*
210
211
  console.log('\n\nskipping __old__setup_website_publishing');
211
212
  console.trace();
212
213
  console.log('\n\n');
214
+ */
213
215
 
214
216
 
215
217
  const __old__setup_website_publishing = (website) => {
@@ -491,10 +493,11 @@ class HTTP_Website_Publisher extends HTTP_Webpageorsite_Publisher {
491
493
  if (website) {
492
494
 
493
495
 
494
- console.trace();
496
+ //console.trace();
495
497
 
496
- throw 'NYI - HTTP_Website_Publisher needs to publish specified website';
498
+ //throw 'NYI - HTTP_Website_Publisher needs to publish specified website';
497
499
 
500
+ console.log('Possibly missing website publishing code.')
498
501
 
499
502
  // Website_Bundle class would help.
500
503
 
@@ -137,6 +137,7 @@ class CSS_And_JS_From_JS_String_Using_AST_Node_Extractor extends Extractor {
137
137
  //console.log('ae_nodes', ae_nodes);
138
138
  //console.log('ae_nodes.length', ae_nodes.length);
139
139
  //console.log('css_ae_nodes.length', css_ae_nodes.length);
140
+ console.log('arr_pos_spans_css_js_nodes.length', arr_pos_spans_css_js_nodes.length);
140
141
 
141
142
  const arr_css = [];
142
143
 
@@ -159,67 +160,17 @@ class CSS_And_JS_From_JS_String_Using_AST_Node_Extractor extends Extractor {
159
160
  }
160
161
 
161
162
  if (arr_css.length > 0) {
162
-
163
-
164
- // Needs to also return the JS, without the CSS.
165
-
166
-
167
-
168
-
169
163
  const str_css = arr_css.join('\n');
170
-
171
- //console.log('arr_pos_spans_css_js_nodes', arr_pos_spans_css_js_nodes);
172
-
173
- // Then see about removing the inverse of them from the original string.
174
-
175
164
  const str_js_without_css_assignments = pos_span_string_extractor.extract(js_str, arr_pos_spans_css_js_nodes, {invert: true});
176
-
177
-
178
- //console.log('str_js_without_css_assignments', str_js_without_css_assignments);
179
- //console.log('str_js_without_css_assignments.length', str_js_without_css_assignments.length);
180
-
181
-
182
- // return an array perhaps?
183
- // object with keys may be easier / better / simpler.
184
- // or even a Bundle object?
185
-
186
165
  const res = {
187
166
  css: str_css,
188
167
  js: str_js_without_css_assignments
189
168
  }
190
-
191
-
192
-
193
-
194
- //console.trace();
195
- //throw 'stop';
196
-
197
-
198
-
199
-
200
169
  complete(res);
201
170
  } else {
202
171
  complete();
203
172
  }
204
173
 
205
-
206
- // Can then do query to get all .css properties that are string templates.
207
- // is it a property of a Class object?
208
-
209
-
210
-
211
-
212
-
213
- // Need to get an AST from it....
214
- // Or could simply search (regex?) for .css = `...`?
215
-
216
-
217
-
218
-
219
- // Go through each file? Just the first?
220
-
221
- // Or should the whole bundled (browserified) JS be consulted?
222
-
223
174
  const [stop, pause, resume] = [() => {}, () => {}, () => {}];
224
175
  return [stop, pause, resume];
225
176
 
package/server.js CHANGED
@@ -22,9 +22,11 @@ const Website = require('./website/website');
22
22
  const HTTP_Website_Publisher = require('./publishers/http-website-publisher');
23
23
  const Webpage = require('./website/webpage');
24
24
  const HTTP_Webpage_Publisher = require('./publishers/http-webpage-publisher');
25
+ const HTTP_Function_Publisher = require('./publishers/http-function-publisher');
25
26
 
26
27
  const Static_Route_HTTP_Responder = require('./http/responders/static/Static_Route_HTTP_Responder');
27
28
 
29
+ const Publishers = require('./publishers/Publishers');
28
30
 
29
31
  class JSGUI_Single_Process_Server extends Evented_Class {
30
32
  constructor(spec = {
@@ -146,7 +148,7 @@ class JSGUI_Single_Process_Server extends Evented_Class {
146
148
  // See about making use of relevant shared abstractions.
147
149
 
148
150
 
149
- const ws_app = this.app = new Website(opts_website);
151
+ const ws_app = this.app = this.website = new Website(opts_website);
150
152
  // Be able to treat Webpage as an app?
151
153
 
152
154
  const opts_ws_publisher = {
@@ -156,6 +158,7 @@ class JSGUI_Single_Process_Server extends Evented_Class {
156
158
  opts_ws_publisher.disk_path_client_js = disk_path_client_js;
157
159
  }
158
160
  const ws_publisher = new HTTP_Website_Publisher(opts_ws_publisher);
161
+ this._ws_publisher = ws_publisher;
159
162
  ws_publisher.on('ready', () => {
160
163
  console.log('ws publisher is ready');
161
164
  const ws_resource = new Website_Resource({
@@ -172,11 +175,27 @@ class JSGUI_Single_Process_Server extends Evented_Class {
172
175
 
173
176
  Object.defineProperty(this, 'router', { get: () => server_router })
174
177
  }
178
+
179
+ publish(name, fn) {
180
+ // Get the function publisher.
181
+ // Possibly ensure it exists.
182
+ //const fn_publisher = this.function_publisher;
183
+ //fn_publisher.add(name, fn);
184
+ const fpub = new HTTP_Function_Publisher({name, fn});
185
+
186
+ this.function_publishers = this.function_publishers || [];
187
+ this.function_publishers.push(fpub);
188
+
189
+ this.server_router.set_route('/api/' + name, fpub, fpub.handle_http);
190
+ }
191
+
192
+
175
193
  get resource_names() {
176
194
  return this.resource_pool.resource_names;
177
195
  }
178
196
  'start' (port, callback, fnProcessRequest) {
179
197
  if (tof(port) !== 'number') {
198
+ console.log('Invalid port:', port);
180
199
  console.trace();
181
200
  throw 'stop';
182
201
  }
@@ -279,6 +298,7 @@ JSGUI_Single_Process_Server.Resource = Resource;
279
298
  JSGUI_Single_Process_Server.Page_Context = Server_Page_Context;
280
299
  JSGUI_Single_Process_Server.Server_Page_Context = Server_Page_Context;
281
300
  JSGUI_Single_Process_Server.Website_Resource = Website_Resource;
301
+ JSGUI_Single_Process_Server.Publishers = Publishers;
282
302
  module.exports = JSGUI_Single_Process_Server;
283
303
 
284
304