jsgui3-server 0.0.84 → 0.0.87

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.
@@ -1,6 +1,9 @@
1
1
  const Bundler = require('./bundler');
2
2
 
3
3
  const JS_Bundler = require('./js-bundler');
4
+ const CSS_Bundler = require('./css-bundler');
5
+
6
+ const {bundle_css_from_js_str} = CSS_Bundler;
4
7
 
5
8
  const Bundle = require('./bundle');
6
9
  const {obs, prom_or_cb} = require('fnl');
@@ -14,6 +17,17 @@ const browserify = require('browserify');
14
17
  const babel = require('@babel/core');
15
18
  const stream_to_array = require('stream-to-array');
16
19
 
20
+
21
+ // Bundling maybe would not be proper SSR sometimes.
22
+ // SSR is needed when the server needs to generate the specific info to start the page with.
23
+ // However, specific info could be quickly updated too.
24
+ // In many cases bundling would be more efficient that per-page SSR.
25
+
26
+
27
+
28
+
29
+
30
+
17
31
  // Maybe some web pages should be unbundlable? Or we note that they are dynamic (somehow).
18
32
  // Perhaps another fn should do that check. Don't assume all pages will bundle OK. Could raise obs error if needed.
19
33
 
@@ -34,137 +48,254 @@ const {bundle_js} = JS_Bundler;
34
48
 
35
49
  const bundle_web_page = (webpage, options = {}) => {
36
50
  const {content} = webpage;
51
+ //console.log('bundle web page');
52
+ //console.log('webpage', webpage);
53
+ //console.trace();
37
54
 
38
- let {disk_path_client_js} = options;
39
- //if (options.js_client) js_client_disk_path =
40
-
41
- // Then depending on the content type
42
-
43
-
44
- const t_content = tof(content);
45
-
46
- //console.log('content', content);
47
- //console.log('t_content', t_content);
48
-
49
- return obs((next, complete, error) => {
50
- const res = new Bundle();
51
-
52
- // The observable could / should return updates along the way, things that contribute to the full result.
53
-
54
- if (t_content === 'string') {
55
- // Hardly anything to bundle. No JS required, so it seems.
56
- // Maybe put it inside a basic JSGUI page control...?
57
55
 
58
- // Page may still have a title.
59
- const html = `<html><head><title>${webpage.title}</title></head><body>${content}</body></html>`;
60
- const buff = Buffer.from(html, "utf-8");
56
+ // What if there is no content in the webpage?
61
57
 
62
- // and value with different types of compression....
63
- // worth having them ready.
64
- res.push({
65
- 'path': webpage.path,
66
- 'value': buff,
67
- 'content-type': 'text/html'
68
- });
69
- complete(res);
70
-
71
- } else if (t_content === 'control') {
72
- //console.log ('content.context', content.context);
73
- //console.log('content', content);
74
-
75
- // May need to clone this control, putting it into new contexts.
76
- // Or render it with a temporary context?
58
+ let {disk_path_client_js} = options;
59
+ //console.log('disk_path_client_js', disk_path_client_js);
77
60
 
78
- // Controls with temportary contexts could be useful.
79
61
 
62
+ // Could use the CSS bundler to extract the css from the JS.
80
63
 
81
64
 
82
- if (content instanceof Control) {
83
- //console.log('content is control');
84
- //console.log('content.constructor.name', content.constructor.name);
85
- if (content instanceof HTML_Document) {
86
- console.log('content is an html document');
87
65
 
88
- throw 'NYI';
89
- } else {
66
+ // Could look for the css within disk_path_client_js.
90
67
 
91
- // create an HTML document
92
- // then put this control (or a clone of it) inside that HTML document.
93
68
 
94
- // We may be changing the construction / rendering order here.
95
- // Seem to be doing more construction of controls without a Page_Context.
96
- // That page_context may only be important at a later stage.
69
+ //if (options.js_client) js_client_disk_path =
97
70
 
98
- // Some pages will render differently depending on when they are rendered.
99
- // That may be why a server would need to individually build each page.
100
- // Eg if there is SSR of latest news items.
71
+ // Then depending on the content type
72
+
101
73
 
102
- // Question of pre-rendering or rendering on each page request.
103
- // Maybe we don't bundle it if it includes dynamic content.
104
- // Though we would need to bundle the JS.
74
+ const t_content = tof(content);
105
75
 
106
- // Could create a new page context.
76
+ //console.log('content', content);
77
+ //console.log('t_content', t_content);
107
78
 
108
- //const cloned_content = content.clone();
79
+ //console.log('');
109
80
 
110
- // Should be able to clone a control?
81
+ //console.log('pre return obs');
82
+ //console.trace();
111
83
 
112
- //console.log('cloned_content', cloned_content);
84
+ return obs((next, complete, error) => {
85
+ const res = new Bundle();
113
86
 
114
87
 
115
- // The page context may not have a request and response.
116
- // For bundling, won't have one (unless one were made).
88
+ (async () => {
117
89
 
118
- // Creating the JS bundle...
90
+ if (t_content === 'string') {
91
+ // Hardly anything to bundle. No JS required, so it seems.
92
+ // Maybe put it inside a basic JSGUI page control...?
93
+
94
+ // Page may still have a title.
95
+ const html = `<html><head><title>${webpage.title}</title></head><body>${content}</body></html>`;
96
+ const buff = Buffer.from(html, "utf-8");
97
+
98
+ // and value with different types of compression....
99
+ // worth having them ready.
100
+ res.push({
101
+ 'path': webpage.path,
102
+ 'value': buff,
103
+ 'content-type': 'text/html'
104
+ });
105
+ complete(res);
106
+
107
+ } else if (t_content === 'control') {
108
+ //console.log ('content.context', content.context);
109
+ //console.log('content', content);
110
+
111
+ // May need to clone this control, putting it into new contexts.
112
+ // Or render it with a temporary context?
113
+
114
+ // Controls with temportary contexts could be useful.
115
+ if (content instanceof Control) {
116
+ //console.log('content is control');
117
+ //console.log('content.constructor.name', content.constructor.name);
118
+ if (content instanceof HTML_Document) {
119
+ console.log('content is an html document');
120
+
121
+ throw 'NYI';
122
+ } else {
123
+
124
+ // create an HTML document
125
+ // then put this control (or a clone of it) inside that HTML document.
126
+
127
+ // We may be changing the construction / rendering order here.
128
+ // Seem to be doing more construction of controls without a Page_Context.
129
+ // That page_context may only be important at a later stage.
130
+
131
+ // Some pages will render differently depending on when they are rendered.
132
+ // That may be why a server would need to individually build each page.
133
+ // Eg if there is SSR of latest news items.
134
+
135
+ // Question of pre-rendering or rendering on each page request.
136
+ // Maybe we don't bundle it if it includes dynamic content.
137
+ // Though we would need to bundle the JS.
138
+
139
+ // Could create a new page context.
140
+
141
+ //const cloned_content = content.clone();
142
+
143
+ // Should be able to clone a control?
144
+
145
+ //console.log('cloned_content', cloned_content);
146
+
147
+ // The page context may not have a request and response.
148
+ // For bundling, won't have one (unless one were made).
149
+
150
+ // Creating the JS bundle...
151
+
152
+ // Make it require jsgui-html for the moment.
153
+ // Requiring specific JS of the client control may make more sense....
154
+
155
+ // First let's bundle the JS.
156
+ // Or get the JS bundle for 'jsgui3-html'.
157
+
158
+ // js.serve_package('/js/app.js', js_client, o_serve_package, (err, served) => {
159
+ // maybe should make a JS_Bundler class.
160
+
161
+ // May need to be told earlier what file path we are using for the client js bundle.
162
+
163
+ const diskpath_js_client = disk_path_client_js || require.resolve('jsgui3-html');
164
+ //const diskpath_js_client = require.resolve('./../controls/page/admin.js');
165
+
166
+ // Bundle js could be an observable
167
+ // So when it finds CSS, it can output that.
168
+ // A Control's CSS property, within the JS definition.
169
+ // That can be output to a CSS file, copied or removed from the JS file.
119
170
 
120
- // Make it require jsgui-html for the moment.
121
- // Requiring specific JS of the client control may make more sense....
171
+ // js_mode debug
172
+
173
+ res_bundle_js = await bundle_js(diskpath_js_client, {
174
+ 'js_mode': 'mini',
175
+ 'babel': 'mini'
176
+ });
177
+
178
+ console.log('res_bundle_js', res_bundle_js);
179
+
180
+ throw 'NYI';
181
+
182
+ /*
183
+
184
+ bundle_js(diskpath_js_client, {
185
+ 'js_mode': 'mini',
186
+ 'babel': 'mini'
187
+ }, (err, res_bundle_js) => {
188
+ if (err) {
189
+ console.trace();
190
+ throw err;
191
+ } else {
192
+ //console.log('res_bundle_js', res_bundle_js);
193
+
194
+ // Could search at this point for class.css properties.
195
+ res.push({
196
+ 'path': webpage.path + 'js/app.js',
197
+ 'value': res_bundle_js,
198
+ 'content-type': 'text/javascript'
199
+ });
200
+
201
+ const spc = new Server_Page_Context({
202
+ //request:
203
+ });
204
+
205
+
206
+ const doc = new Client_HTML_Document({
207
+ context: spc
208
+ });
209
+ doc.include_js('/js/app.js');
210
+ doc.body.add(content);
211
+
212
+ // Getting it to load the JS would be nice...
213
+ // But maybe only do it automatically if it's an active document.
214
+ // If it's just generated JS then best not to bundle JS to load.
215
+
216
+ // Could also make smaller bundles for some specific parts of the app. Could improve speed.
217
+ //console.log('doc.html', doc.html);
218
+ const buff_html = Buffer.from(doc.html, "utf-8");
219
+ // But add the client-side stuff to that doc.
220
+
221
+ // Remember, this part is about bundling rather than serving.
222
+
223
+ res.push({
224
+ 'path': webpage.path,
225
+ 'value': buff_html,
226
+ 'content-type': 'text/html'
227
+ });
228
+ //console.log('pre complete bundlejs');
229
+ //console.log('res.length()', res.length());
230
+ complete(res);
231
+ }
232
+ });
233
+ */
234
+
235
+ // Need to create a new control
236
+
237
+ //throw 'NYI';
238
+ }
239
+ } else {
240
+ throw 'NYI';
241
+ }
242
+ } else if (t_content === 'undefined') {
243
+ // Hardly anything to bundle. No JS required, so it seems.
244
+ // Maybe put it inside a basic JSGUI page control...?
245
+
246
+ // Page may still have a title.
247
+ const html = `<html><head></head><body></body></html>`;
248
+ const buff = Buffer.from(html, "utf-8");
249
+
250
+ // and value with different types of compression....
251
+ // worth having them ready.
252
+ res.push({
253
+ 'path': webpage.path,
254
+ 'value': buff,
255
+ 'content-type': 'text/html'
256
+ });
257
+ complete(res);
258
+
259
+ } else {
260
+ //console.log('t_content', t_content);
261
+ if (t_content === 'function') {
262
+
263
+ const spc = new Server_Page_Context({
264
+ //request:
265
+ });
266
+
267
+ const Ctrl = content;
268
+ const ctrl = new Ctrl({
269
+ 'context': spc
270
+ });
271
+
122
272
 
123
- // First let's bundle the JS.
124
- // Or get the JS bundle for 'jsgui3-html'.
273
+ // Or from a different chain maybe? Seems unorganised that way.
274
+
275
+ if (ctrl instanceof HTML_Document) {
276
+ console.trace();
277
+ throw 'NYI';
278
+ } else {
125
279
 
126
- // js.serve_package('/js/app.js', js_client, o_serve_package, (err, served) => {
127
- // maybe should make a JS_Bundler class.
280
+ console.log('Bundle path A');
128
281
 
129
- // May need to be told earlier what file path we are using for the client js bundle.
130
282
 
131
- const diskpath_js_client = disk_path_client_js || require.resolve('jsgui3-html');
132
- //const diskpath_js_client = require.resolve('./../controls/page/admin.js');
283
+ // is ctrl a Control instance?
133
284
 
134
- // Bundle js could be an observable
135
- // So when it finds CSS, it can output that.
136
- // A Control's CSS property, within the JS definition.
137
- // That can be output to a CSS file, copied or removed from the JS file.
285
+ // Is it a control in some other way?
138
286
 
139
-
140
287
 
141
288
 
142
- bundle_js(diskpath_js_client, {
143
- 'js_mode': 'mini',
144
- 'babel': 'mini'
145
- }, (err, res_bundle_js) => {
146
- if (err) {
147
- console.trace();
148
- throw err;
149
- } else {
150
- //console.log('res_bundle_js', res_bundle_js);
289
+ if (ctrl instanceof Control || tof(ctrl) === 'control') {
151
290
 
152
- res.push({
153
- 'path': webpage.path + 'js/app.js',
154
- 'value': res_bundle_js,
155
- 'content-type': 'text/javascript'
156
- });
157
291
 
158
- const spc = new Server_Page_Context({
159
- //request:
160
- });
161
-
162
-
163
292
  const doc = new Client_HTML_Document({
164
293
  context: spc
165
294
  });
166
295
  doc.include_js('/js/app.js');
167
- doc.body.add(content);
296
+ doc.include_css('/css/app.css');
297
+ ctrl.active();
298
+ doc.body.add(ctrl);
168
299
 
169
300
  // Getting it to load the JS would be nice...
170
301
  // But maybe only do it automatically if it's an active document.
@@ -173,102 +304,221 @@ const bundle_web_page = (webpage, options = {}) => {
173
304
  // Could also make smaller bundles for some specific parts of the app. Could improve speed.
174
305
  //console.log('doc.html', doc.html);
175
306
  const buff_html = Buffer.from(doc.html, "utf-8");
176
- // But add the client-side stuff to that doc.
177
-
178
- // Remember, this part is about bundling rather than serving.
179
307
 
180
308
  res.push({
181
309
  'path': webpage.path,
182
310
  'value': buff_html,
183
311
  'content-type': 'text/html'
184
312
  });
185
- //console.log('pre complete bundlejs');
186
- //console.log('res.length()', res.length());
187
- complete(res);
188
- }
189
- });
190
313
 
191
- // Need to create a new control
192
314
 
193
- //throw 'NYI';
194
- }
195
- } else {
196
- throw 'NYI';
197
- }
198
- } else {
315
+ const diskpath_js_client = disk_path_client_js || require.resolve('jsgui3-html');
199
316
 
200
- console.log('t_content', t_content);
317
+ let waiting_for_css_extraction = false, handle_css_extraction_complete = undefined;
201
318
 
202
- if (t_content === 'function') {
203
319
 
204
- const spc = new Server_Page_Context({
205
- //request:
206
- });
320
+ //const diskpath_js_client = require.resolve('./../controls/page/admin.js');
207
321
 
208
- const Ctrl = content;
209
- const ctrl = new Ctrl({
210
- 'context': spc
211
- });
322
+ // debug mode
212
323
 
213
- if (ctrl instanceof HTML_Document) {
214
- console.trace();
215
- throw 'NYI';
216
- } else {
217
324
 
325
+ const obs_bundle = bundle_js(diskpath_js_client, {
326
+ 'js_mode': 'debug',
327
+ 'babel': 'debug'
328
+ });
329
+
330
+
331
+
332
+
333
+ obs_bundle.on('next', data => {
334
+ //console.log('next data', data);
335
+ console.log('next Object.keys(data)', Object.keys(data));
336
+
337
+ // at this point, could go through the js to extract any CSS.
338
+
339
+ const {lang, operation, compress, type, value} = data;
340
+
341
+ if (lang === 'JavaScript') {
342
+ if (type === 'single-string') {
343
+
344
+ // Get the CSS classes (as a JS object) from the JS file.
345
+ // Or get them as a CSS file stored in a buffer?
346
+ // Or maybe better they get returned as a 'Bundle' object.
347
+
348
+ const obs_css_from_js = bundle_css_from_js_str(value);
349
+ console.log('post obs_css_from_js = bundle_css_from_js_str(value) call');
350
+
351
+ waiting_for_css_extraction = true;
352
+
353
+ obs_css_from_js.on('next', data => {
354
+ console.log('obs_css_from_js next data', data);
355
+ });
356
+ obs_css_from_js.on('complete', obs_css_from_js_res => {
357
+
358
+
359
+ console.log('obs_css_from_js complete obs_css_from_js_res', obs_css_from_js_res);
360
+
361
+ if (tof(obs_css_from_js_res) === 'string') {
362
+ // should be added to the page bundle.
363
+
364
+ res.push({
365
+ 'path': webpage.path + 'css/app.css',
366
+ 'value': Buffer.from(obs_css_from_js_res),
367
+ 'content-type': 'text/css'
368
+ });
369
+
370
+ waiting_for_css_extraction = false;
371
+ console.log('obs_css_from_js complete');
372
+
373
+ if (handle_css_extraction_complete) {
374
+ handle_css_extraction_complete();
375
+ } else {
376
+ console.trace();
377
+ throw 'stop';
378
+ }
379
+
380
+ }
381
+
382
+ //console.log('tof(res)', tof(res));
383
+ //throw 'stop';
384
+
385
+
386
+ });
387
+
388
+
389
+
390
+
391
+
392
+
393
+ }
394
+ }
395
+
396
+ })
397
+
398
+ obs_bundle.on('complete', res_bundle_js => {
399
+ // the result object is a buffer.
400
+ // maybe it should be a Bundle.
401
+
402
+ // Should only be considered complete once css extraction from js is complete (incl if nothing gets extracted).
403
+
404
+ const do_when_complete = () => {
405
+ console.log('js-bundler bundle is complete');
406
+
407
+ console.trace();
408
+ console.log('res_bundle_js', res_bundle_js);
409
+ console.log('res', res);
410
+ res.push({
411
+ 'path': webpage.path + 'js/app.js',
412
+ 'value': res_bundle_js,
413
+ 'content-type': 'text/javascript'
414
+ });
415
+ //throw 'stop';
416
+ complete(res);
417
+
418
+ }
419
+
420
+ if (waiting_for_css_extraction) {
421
+ handle_css_extraction_complete = do_when_complete;
422
+ } else {
423
+ do_when_complete();
424
+ }
425
+
426
+
427
+ //console.log('complete res', res);
428
+ //console.trace();
429
+ //throw 'stop';
430
+
431
+ })
218
432
 
219
- const diskpath_js_client = disk_path_client_js || require.resolve('jsgui3-html');
220
- //const diskpath_js_client = require.resolve('./../controls/page/admin.js');
221
433
 
222
- bundle_js(diskpath_js_client, {
223
- 'js_mode': 'mini',
224
- 'babel': 'mini'
225
- }, (err, res_bundle_js) => {
226
- if (err) {
227
- console.trace();
228
- throw err;
229
434
  } else {
230
- //console.log('res_bundle_js', res_bundle_js);
435
+ console.trace();
436
+ console.log('ctrl', ctrl);
437
+ throw 'NYI';
438
+ }
231
439
 
232
- res.push({
233
- 'path': webpage.path + 'js/app.js',
234
- 'value': res_bundle_js,
235
- 'content-type': 'text/javascript'
236
- });
440
+ // better to render the HTML document (control) first?
237
441
 
238
- const doc = new Client_HTML_Document({
239
- context: spc
240
- });
241
- doc.include_js('/js/app.js');
242
- doc.body.add(ctrl);
243
-
244
- // Getting it to load the JS would be nice...
245
- // But maybe only do it automatically if it's an active document.
246
- // If it's just generated JS then best not to bundle JS to load.
442
+
443
+
444
+
445
+
446
+
447
+
448
+ const old = () => {
449
+ bundle_js(diskpath_js_client, {
450
+ 'js_mode': 'mini',
451
+ 'babel': 'mini'
452
+ }, (err, res_bundle_js) => {
453
+ if (err) {
454
+ console.trace();
455
+ throw err;
456
+ } else {
457
+ //console.log('res_bundle_js', res_bundle_js);
247
458
 
248
- // Could also make smaller bundles for some specific parts of the app. Could improve speed.
249
- //console.log('doc.html', doc.html);
250
- const buff_html = Buffer.from(doc.html, "utf-8");
459
+ res.push({
460
+ 'path': webpage.path + 'js/app.js',
461
+ 'value': res_bundle_js,
462
+ 'content-type': 'text/javascript'
463
+ });
251
464
 
252
- res.push({
253
- 'path': webpage.path,
254
- 'value': buff_html,
255
- 'content-type': 'text/html'
465
+ const doc = new Client_HTML_Document({
466
+ context: spc
467
+ });
468
+ doc.include_js('/js/app.js');
469
+ doc.body.add(ctrl);
470
+
471
+ // Getting it to load the JS would be nice...
472
+ // But maybe only do it automatically if it's an active document.
473
+ // If it's just generated JS then best not to bundle JS to load.
474
+
475
+ // Could also make smaller bundles for some specific parts of the app. Could improve speed.
476
+ //console.log('doc.html', doc.html);
477
+ const buff_html = Buffer.from(doc.html, "utf-8");
478
+
479
+ res.push({
480
+ 'path': webpage.path,
481
+ 'value': buff_html,
482
+ 'content-type': 'text/html'
483
+ });
484
+ //console.log('pre complete bundlejs');
485
+ //console.log('res.length()', res.length());
486
+ complete(res);
487
+ }
256
488
  });
257
- //console.log('pre complete bundlejs');
258
- //console.log('res.length()', res.length());
259
- complete(res);
260
489
  }
261
- });
490
+
491
+ }
492
+
493
+ } else if (false) {
494
+ console.trace();
495
+ throw 'NYI';
496
+ } else {
497
+ console.log('t_content', t_content);
498
+ console.log('content', content);
499
+ console.trace();
500
+ throw 'NYI';
262
501
  }
263
-
264
- } else if (false) {
265
- console.trace();
266
- throw 'NYI';
267
- } else {
268
- console.trace();
269
- throw 'NYI';
270
502
  }
271
- }
503
+ })().catch(err => {
504
+ console.trace();
505
+
506
+ throw 'err';
507
+ //console.error(err);
508
+ });
509
+
510
+ // The observable could / should return updates along the way, things that contribute to the full result.
511
+
512
+
513
+
514
+
515
+
516
+ const stop = () => {throw 'NYI'};
517
+ const pause = () => {throw 'NYI'};
518
+ const resume = () => {throw 'NYI'};
519
+
520
+ return [stop, pause, resume];
521
+
272
522
  });
273
523
  //throw 'NYI';
274
524
  }