@monkeyplus/flow 4.0.0-beta.1 → 4.0.0-beta.11

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/dist/index.cjs CHANGED
@@ -10,6 +10,9 @@ const boom = require('@hapi/boom');
10
10
  const os = require('os');
11
11
  const chalk = require('chalk');
12
12
  const fs = require('fs-extra');
13
+ const fs$1 = require('fs');
14
+ const hookable = require('hookable');
15
+ const chokidar = require('chokidar');
13
16
 
14
17
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e["default"] : e; }
15
18
 
@@ -31,9 +34,11 @@ const R__namespace = /*#__PURE__*/_interopNamespace(R);
31
34
  const os__default = /*#__PURE__*/_interopDefaultLegacy(os);
32
35
  const chalk__default = /*#__PURE__*/_interopDefaultLegacy(chalk);
33
36
  const fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
37
+ const fs__default$1 = /*#__PURE__*/_interopDefaultLegacy(fs$1);
38
+ const chokidar__default = /*#__PURE__*/_interopDefaultLegacy(chokidar);
34
39
 
35
40
  const name = "@monkeyplus/flow";
36
- const version = "4.0.0-beta.1";
41
+ const version = "4.0.0-beta.11";
37
42
  const description = "Utils hapi";
38
43
  const author = "Andres Navarrete";
39
44
  const license = "MIT";
@@ -42,7 +47,8 @@ const module$1 = "./dist/index.mjs";
42
47
  const types = "./dist/index.d.ts";
43
48
  const files = [
44
49
  "dist/",
45
- "types/"
50
+ "types/",
51
+ "resources/"
46
52
  ];
47
53
  const exports$1 = {
48
54
  ".": {
@@ -58,21 +64,24 @@ const scripts = {
58
64
  lint: "eslint --ext .js,.ts .",
59
65
  fix: "eslint --fix --ext .ts .",
60
66
  prepublishOnly: "pnpm run build",
61
- publish: "pnpm publish",
62
67
  start: "esno src/index.ts",
63
68
  test: "vitest"
64
69
  };
65
70
  const dependencies$1 = {
66
71
  "@hapi/boom": "9.x.x",
67
72
  "@hapi/hoek": "9.x.x",
68
- chalk: "^5.0.0",
69
73
  consola: "^2.15.3",
74
+ chalk: "^4.1.2",
75
+ chokidar: "^3.5.3",
76
+ hookable: "^5.1.1",
70
77
  "fs-extra": "^10.0.0",
71
78
  ramda: "^0.28.0"
72
79
  };
73
80
  const devDependencies = {
74
81
  "@types/fs-extra": "^9.0.13",
75
82
  "@types/hapi__hapi": "^20.0.10",
83
+ "@types/hapi__nes": "^11.0.5",
84
+ "@types/hapi__vision": "^5.5.3",
76
85
  "@types/ramda": "^0.27.64"
77
86
  };
78
87
  const peerDependencies = {
@@ -99,8 +108,13 @@ const pkg = {
99
108
 
100
109
  const logger$1 = consola__default.withScope(pkg.name);
101
110
  const dependencies = {
102
- "@hapi/vision": "6.x.x"
111
+ "@hapi/vision": "6.x.x",
112
+ "@hapi/inert": "6.x.x",
113
+ "@hapi/h2o2": "9.x.x",
114
+ "@hapi/nes": "12.x.x"
103
115
  };
116
+ const isProduction = process.env.NODE_ENV === "production";
117
+ const isGenerate = process.env.GENERATE;
104
118
 
105
119
  const LifeCircle = {
106
120
  register: (server) => {
@@ -314,7 +328,7 @@ const handlerPage = async (req, h) => {
314
328
  return context;
315
329
  }
316
330
  context.utils = utils;
317
- return h.view(`${configs.dirTemplates}${flow.view.template}`, context);
331
+ return h.view(`${configs.dirTemplates}${flow.view.layout || "default"}`, context);
318
332
  };
319
333
 
320
334
  const logger = consola__default.withScope("@monkeyplus/flow");
@@ -322,6 +336,10 @@ const defaults = {
322
336
  locales: ["es-ec"],
323
337
  defaultUbication: "ec",
324
338
  defaultLanguage: "es",
339
+ staticDir: "static",
340
+ hmr: {
341
+ dirs: ["views"]
342
+ },
325
343
  publicPath: "/",
326
344
  locale: "es-ec",
327
345
  relativeTo: "",
@@ -693,6 +711,47 @@ const definePage = (pageOptions) => (levelOptions) => (configs) => {
693
711
  return routes;
694
712
  };
695
713
 
714
+ const readPagesDir = (pathDir, folder) => {
715
+ const p = fs__default$1.readdirSync(pathDir);
716
+ return R.flatten(p.filter((f) => !f.includes(".js.map") && !f.includes(" copy.js.map") && !f.includes(" copy.js") && !f.includes(".model")).map((e) => {
717
+ if (e.includes(".js") || e.includes(".ts")) {
718
+ return {
719
+ path: path__default.join(pathDir, e),
720
+ prefix: folder
721
+ };
722
+ } else {
723
+ return readPagesDir(path__default.join(pathDir, e), e);
724
+ }
725
+ }));
726
+ };
727
+ const registerPages = async (server, dir) => {
728
+ const dirPages = path__default.resolve(dir || "./pages");
729
+ const listFiles = readPagesDir(dirPages);
730
+ const listPrePages = [];
731
+ for (const item of listFiles) {
732
+ try {
733
+ const module = require(item.path)?.default;
734
+ if (typeof module === "function") {
735
+ listPrePages.push(module());
736
+ } else if (typeof module === "object") {
737
+ if (Array.isArray(module)) {
738
+ module.forEach((el) => listPrePages.push(el()));
739
+ } else {
740
+ const _pages = await module.pages({ server });
741
+ if (Array.isArray(_pages))
742
+ _pages.forEach((page) => listPrePages.push(definePage(page)()));
743
+ else
744
+ listPrePages.push(definePage(_pages)());
745
+ }
746
+ }
747
+ } catch (details) {
748
+ logger$1.error(details);
749
+ }
750
+ }
751
+ for (const page of listPrePages)
752
+ await server.flow.addPage(page);
753
+ };
754
+
696
755
  const RunMethods = {
697
756
  register: (server) => {
698
757
  const { flow: state } = server.app;
@@ -706,7 +765,7 @@ const RunMethods = {
706
765
  server.route(route);
707
766
  };
708
767
  const addPage = (_page, extra) => {
709
- const registerPages = (_pages2) => {
768
+ const registerPages2 = (_pages2) => {
710
769
  for (const _route of _pages2) {
711
770
  if (state.routes[_route.path])
712
771
  logger$1.warn("The route %s alredy exist", _route.path);
@@ -717,13 +776,14 @@ const RunMethods = {
717
776
  let _pages;
718
777
  if (typeof _page === "function") {
719
778
  _pages = _page(config);
720
- registerPages(_pages);
779
+ registerPages2(_pages);
721
780
  } else {
722
781
  _pages = definePage(_page)()(config);
723
- registerPages(_pages);
782
+ registerPages2(_pages);
724
783
  }
725
784
  };
726
785
  const init = async () => {
786
+ await registerPages(server);
727
787
  const pages = server.app.flow.routes;
728
788
  for (const key in pages) {
729
789
  const page = pages[key];
@@ -740,6 +800,136 @@ const RunMethods = {
740
800
  }
741
801
  };
742
802
 
803
+ const createHmr = (options) => {
804
+ const state = {
805
+ dir: options.relativeTo || "",
806
+ dirs: options.dirs || [],
807
+ extensions: options.extensions || ["eta"]
808
+ };
809
+ let watcher;
810
+ const hooks = hookable.createHooks();
811
+ const watch = () => {
812
+ watcher = chokidar__default.watch(state.dirs.map((d) => path__default.join(d, `**/*.(${state.extensions.join("|")})`)), {
813
+ cwd: state.dir,
814
+ ignoreInitial: true,
815
+ ignored: "node_modules/**/*"
816
+ }).on("change", (path2) => {
817
+ logger$1.info("Changed file", path2);
818
+ hooks.callHook("page:refresh");
819
+ });
820
+ };
821
+ watch();
822
+ return { watcher, hooks };
823
+ };
824
+
825
+ const RegisterCommon = async (server, configs) => {
826
+ server.route({
827
+ method: "GET",
828
+ path: "/{param*}",
829
+ options: {
830
+ ext: {
831
+ onPreResponse: {
832
+ method: (req, h) => {
833
+ return h.continue;
834
+ }
835
+ }
836
+ }
837
+ },
838
+ handler: {
839
+ directory: {
840
+ path: configs.staticDir,
841
+ listing: true
842
+ }
843
+ }
844
+ });
845
+ if (!isGenerate) {
846
+ const hmr = createHmr({
847
+ dirs: configs.hmr.dirs,
848
+ relativeTo: configs.relativeTo
849
+ });
850
+ hmr.hooks.hook("page:refresh", () => {
851
+ setTimeout(() => {
852
+ logger$1.info("Refresh page");
853
+ server.publish("/_flow/hmr", { reload: true });
854
+ }, 40);
855
+ });
856
+ server.subscription("/_flow/hmr");
857
+ server.route({
858
+ path: "/_flow/hmr/client.js",
859
+ method: "get",
860
+ handler: {
861
+ file: {
862
+ path: path.join(__dirname, "../resources/client"),
863
+ confine: false
864
+ }
865
+ }
866
+ });
867
+ server.route({
868
+ path: "/_flow/hmr/connect.js",
869
+ method: "get",
870
+ handler: {
871
+ file: {
872
+ path: path.join(__dirname, "../resources/ws.js"),
873
+ confine: false
874
+ }
875
+ }
876
+ });
877
+ logger$1.debug("Enable development routes");
878
+ server.route({
879
+ path: "/_flow/sitemap",
880
+ method: "get",
881
+ handler: async () => {
882
+ const { pages: getPages } = server.methods.flow;
883
+ const urls = await getPages();
884
+ const pages = Object.values(urls).map((p) => R.dissoc("context", p));
885
+ return {
886
+ total: pages.length,
887
+ pages
888
+ };
889
+ }
890
+ });
891
+ server.route({
892
+ path: "/_flow/locales",
893
+ method: "get",
894
+ handler: async (req) => {
895
+ const { pages: getPages } = server.methods.flow;
896
+ const urls = await getPages();
897
+ const pages = Object.values(urls).map((p) => R.dissoc("context", p));
898
+ const locales = R.groupBy((page) => page.locale, pages);
899
+ return {
900
+ locales: req.server.plugins.flow.configs.locales,
901
+ all: R.mapObjIndexed((l) => {
902
+ return {
903
+ total: l.length,
904
+ pages: l
905
+ };
906
+ }, locales)
907
+ };
908
+ }
909
+ });
910
+ server.route({
911
+ path: "/_flow/configs",
912
+ method: "get",
913
+ handler: (req) => {
914
+ return req.server.plugins.flow.configs;
915
+ }
916
+ });
917
+ }
918
+ const HMR = {
919
+ head: ' <script src="/_flow/hmr/client.js"><\/script>',
920
+ body: ' <script src="/_flow/hmr/connect.js"><\/script>'
921
+ };
922
+ server.ext("onPreHandler", async (req, h) => {
923
+ if (req.route.settings.plugins?.generate === ".html") {
924
+ const { global } = req.plugins.flow;
925
+ Object.assign(global, {
926
+ hmr: isProduction || isGenerate ? { head: "", body: "" } : HMR
927
+ });
928
+ }
929
+ return h.continue;
930
+ });
931
+ };
932
+
743
933
  const plugin = {
744
934
  pkg,
745
935
  dependencies,
@@ -864,6 +1054,7 @@ const plugin = {
864
1054
  return baseOptions;
865
1055
  }
866
1056
  };
1057
+ await RegisterCommon(server, config);
867
1058
  }
868
1059
  };
869
1060
 
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Plugin } from '@hapi/hapi';
1
+ import { Server, Plugin } from '@hapi/hapi';
2
2
  import { PageInfo } from '../types/core';
3
3
  import { OptionsHapiPage, RunPreDefinePage, Flow, FlowExtensions, OptionDynamicLocalePages, GenerateOptions, FlowServerMethods, FlowOptions } from '../types';
4
4
  export { ContextHandler, Contexts, Extension, Flow, FlowContextPage, FlowContextSeo, FlowContextView, FlowEngines, FlowExtensions, FlowOptionPlugins, FlowOptions, FlowPluginExtension, FlowPluginGlobal, FlowPluginLocal, FlowPluginUtils, FlowServerMethods, FlowStatePlugins, GenerateFolder, OptionDynamicLocalePages, OptionsDynamicPages, OptionsHapiPage, RunDefinePage, RunPreDefinePage } from '../types';
@@ -6,7 +6,14 @@ export { ContextHandler, Contexts, Extension, Flow, FlowContextPage, FlowContext
6
6
  declare type DefinePage = (page: OptionsHapiPage) => RunPreDefinePage;
7
7
  declare const definePage: DefinePage;
8
8
 
9
+ declare type HapiPages = OptionsHapiPage | OptionsHapiPage[];
10
+ interface Context {
11
+ server: Server;
12
+ }
13
+ declare type Pages = (ctx: Context) => Promise<HapiPages>;
14
+
9
15
  declare const plugin: Plugin<FlowOptions>;
16
+
10
17
  declare module '@hapi/hapi' {
11
18
  interface ServerApplicationState {
12
19
  flow: Flow.AppState;
@@ -54,4 +61,4 @@ declare module '@hapi/hapi' {
54
61
  }
55
62
  }
56
63
 
57
- export { definePage, plugin };
64
+ export { Pages, definePage, plugin };
package/dist/index.mjs CHANGED
@@ -1,14 +1,18 @@
1
- import path from 'path';
1
+ import path, { join } from 'path';
2
2
  import { applyToDefaults } from '@hapi/hoek';
3
3
  import consola from 'consola';
4
4
  import * as R from 'ramda';
5
+ import { flatten, dissoc, groupBy, mapObjIndexed } from 'ramda';
5
6
  import { notFound } from '@hapi/boom';
6
7
  import os from 'os';
7
8
  import chalk from 'chalk';
8
9
  import fs from 'fs-extra';
10
+ import fs$1 from 'fs';
11
+ import { createHooks } from 'hookable';
12
+ import chokidar from 'chokidar';
9
13
 
10
14
  const name = "@monkeyplus/flow";
11
- const version = "4.0.0-beta.1";
15
+ const version = "4.0.0-beta.11";
12
16
  const description = "Utils hapi";
13
17
  const author = "Andres Navarrete";
14
18
  const license = "MIT";
@@ -17,7 +21,8 @@ const module = "./dist/index.mjs";
17
21
  const types = "./dist/index.d.ts";
18
22
  const files = [
19
23
  "dist/",
20
- "types/"
24
+ "types/",
25
+ "resources/"
21
26
  ];
22
27
  const exports = {
23
28
  ".": {
@@ -33,21 +38,24 @@ const scripts = {
33
38
  lint: "eslint --ext .js,.ts .",
34
39
  fix: "eslint --fix --ext .ts .",
35
40
  prepublishOnly: "pnpm run build",
36
- publish: "pnpm publish",
37
41
  start: "esno src/index.ts",
38
42
  test: "vitest"
39
43
  };
40
44
  const dependencies$1 = {
41
45
  "@hapi/boom": "9.x.x",
42
46
  "@hapi/hoek": "9.x.x",
43
- chalk: "^5.0.0",
44
47
  consola: "^2.15.3",
48
+ chalk: "^4.1.2",
49
+ chokidar: "^3.5.3",
50
+ hookable: "^5.1.1",
45
51
  "fs-extra": "^10.0.0",
46
52
  ramda: "^0.28.0"
47
53
  };
48
54
  const devDependencies = {
49
55
  "@types/fs-extra": "^9.0.13",
50
56
  "@types/hapi__hapi": "^20.0.10",
57
+ "@types/hapi__nes": "^11.0.5",
58
+ "@types/hapi__vision": "^5.5.3",
51
59
  "@types/ramda": "^0.27.64"
52
60
  };
53
61
  const peerDependencies = {
@@ -74,8 +82,13 @@ const pkg = {
74
82
 
75
83
  const logger$1 = consola.withScope(pkg.name);
76
84
  const dependencies = {
77
- "@hapi/vision": "6.x.x"
85
+ "@hapi/vision": "6.x.x",
86
+ "@hapi/inert": "6.x.x",
87
+ "@hapi/h2o2": "9.x.x",
88
+ "@hapi/nes": "12.x.x"
78
89
  };
90
+ const isProduction = process.env.NODE_ENV === "production";
91
+ const isGenerate = process.env.GENERATE;
79
92
 
80
93
  const LifeCircle = {
81
94
  register: (server) => {
@@ -289,7 +302,7 @@ const handlerPage = async (req, h) => {
289
302
  return context;
290
303
  }
291
304
  context.utils = utils;
292
- return h.view(`${configs.dirTemplates}${flow.view.template}`, context);
305
+ return h.view(`${configs.dirTemplates}${flow.view.layout || "default"}`, context);
293
306
  };
294
307
 
295
308
  const logger = consola.withScope("@monkeyplus/flow");
@@ -297,6 +310,10 @@ const defaults = {
297
310
  locales: ["es-ec"],
298
311
  defaultUbication: "ec",
299
312
  defaultLanguage: "es",
313
+ staticDir: "static",
314
+ hmr: {
315
+ dirs: ["views"]
316
+ },
300
317
  publicPath: "/",
301
318
  locale: "es-ec",
302
319
  relativeTo: "",
@@ -668,6 +685,47 @@ const definePage = (pageOptions) => (levelOptions) => (configs) => {
668
685
  return routes;
669
686
  };
670
687
 
688
+ const readPagesDir = (pathDir, folder) => {
689
+ const p = fs$1.readdirSync(pathDir);
690
+ return flatten(p.filter((f) => !f.includes(".js.map") && !f.includes(" copy.js.map") && !f.includes(" copy.js") && !f.includes(".model")).map((e) => {
691
+ if (e.includes(".js") || e.includes(".ts")) {
692
+ return {
693
+ path: path.join(pathDir, e),
694
+ prefix: folder
695
+ };
696
+ } else {
697
+ return readPagesDir(path.join(pathDir, e), e);
698
+ }
699
+ }));
700
+ };
701
+ const registerPages = async (server, dir) => {
702
+ const dirPages = path.resolve(dir || "./pages");
703
+ const listFiles = readPagesDir(dirPages);
704
+ const listPrePages = [];
705
+ for (const item of listFiles) {
706
+ try {
707
+ const module = require(item.path)?.default;
708
+ if (typeof module === "function") {
709
+ listPrePages.push(module());
710
+ } else if (typeof module === "object") {
711
+ if (Array.isArray(module)) {
712
+ module.forEach((el) => listPrePages.push(el()));
713
+ } else {
714
+ const _pages = await module.pages({ server });
715
+ if (Array.isArray(_pages))
716
+ _pages.forEach((page) => listPrePages.push(definePage(page)()));
717
+ else
718
+ listPrePages.push(definePage(_pages)());
719
+ }
720
+ }
721
+ } catch (details) {
722
+ logger$1.error(details);
723
+ }
724
+ }
725
+ for (const page of listPrePages)
726
+ await server.flow.addPage(page);
727
+ };
728
+
671
729
  const RunMethods = {
672
730
  register: (server) => {
673
731
  const { flow: state } = server.app;
@@ -681,7 +739,7 @@ const RunMethods = {
681
739
  server.route(route);
682
740
  };
683
741
  const addPage = (_page, extra) => {
684
- const registerPages = (_pages2) => {
742
+ const registerPages2 = (_pages2) => {
685
743
  for (const _route of _pages2) {
686
744
  if (state.routes[_route.path])
687
745
  logger$1.warn("The route %s alredy exist", _route.path);
@@ -692,13 +750,14 @@ const RunMethods = {
692
750
  let _pages;
693
751
  if (typeof _page === "function") {
694
752
  _pages = _page(config);
695
- registerPages(_pages);
753
+ registerPages2(_pages);
696
754
  } else {
697
755
  _pages = definePage(_page)()(config);
698
- registerPages(_pages);
756
+ registerPages2(_pages);
699
757
  }
700
758
  };
701
759
  const init = async () => {
760
+ await registerPages(server);
702
761
  const pages = server.app.flow.routes;
703
762
  for (const key in pages) {
704
763
  const page = pages[key];
@@ -715,6 +774,136 @@ const RunMethods = {
715
774
  }
716
775
  };
717
776
 
777
+ const createHmr = (options) => {
778
+ const state = {
779
+ dir: options.relativeTo || "",
780
+ dirs: options.dirs || [],
781
+ extensions: options.extensions || ["eta"]
782
+ };
783
+ let watcher;
784
+ const hooks = createHooks();
785
+ const watch = () => {
786
+ watcher = chokidar.watch(state.dirs.map((d) => path.join(d, `**/*.(${state.extensions.join("|")})`)), {
787
+ cwd: state.dir,
788
+ ignoreInitial: true,
789
+ ignored: "node_modules/**/*"
790
+ }).on("change", (path2) => {
791
+ logger$1.info("Changed file", path2);
792
+ hooks.callHook("page:refresh");
793
+ });
794
+ };
795
+ watch();
796
+ return { watcher, hooks };
797
+ };
798
+
799
+ const RegisterCommon = async (server, configs) => {
800
+ server.route({
801
+ method: "GET",
802
+ path: "/{param*}",
803
+ options: {
804
+ ext: {
805
+ onPreResponse: {
806
+ method: (req, h) => {
807
+ return h.continue;
808
+ }
809
+ }
810
+ }
811
+ },
812
+ handler: {
813
+ directory: {
814
+ path: configs.staticDir,
815
+ listing: true
816
+ }
817
+ }
818
+ });
819
+ if (!isGenerate) {
820
+ const hmr = createHmr({
821
+ dirs: configs.hmr.dirs,
822
+ relativeTo: configs.relativeTo
823
+ });
824
+ hmr.hooks.hook("page:refresh", () => {
825
+ setTimeout(() => {
826
+ logger$1.info("Refresh page");
827
+ server.publish("/_flow/hmr", { reload: true });
828
+ }, 40);
829
+ });
830
+ server.subscription("/_flow/hmr");
831
+ server.route({
832
+ path: "/_flow/hmr/client.js",
833
+ method: "get",
834
+ handler: {
835
+ file: {
836
+ path: join(__dirname, "../resources/client"),
837
+ confine: false
838
+ }
839
+ }
840
+ });
841
+ server.route({
842
+ path: "/_flow/hmr/connect.js",
843
+ method: "get",
844
+ handler: {
845
+ file: {
846
+ path: join(__dirname, "../resources/ws.js"),
847
+ confine: false
848
+ }
849
+ }
850
+ });
851
+ logger$1.debug("Enable development routes");
852
+ server.route({
853
+ path: "/_flow/sitemap",
854
+ method: "get",
855
+ handler: async () => {
856
+ const { pages: getPages } = server.methods.flow;
857
+ const urls = await getPages();
858
+ const pages = Object.values(urls).map((p) => dissoc("context", p));
859
+ return {
860
+ total: pages.length,
861
+ pages
862
+ };
863
+ }
864
+ });
865
+ server.route({
866
+ path: "/_flow/locales",
867
+ method: "get",
868
+ handler: async (req) => {
869
+ const { pages: getPages } = server.methods.flow;
870
+ const urls = await getPages();
871
+ const pages = Object.values(urls).map((p) => dissoc("context", p));
872
+ const locales = groupBy((page) => page.locale, pages);
873
+ return {
874
+ locales: req.server.plugins.flow.configs.locales,
875
+ all: mapObjIndexed((l) => {
876
+ return {
877
+ total: l.length,
878
+ pages: l
879
+ };
880
+ }, locales)
881
+ };
882
+ }
883
+ });
884
+ server.route({
885
+ path: "/_flow/configs",
886
+ method: "get",
887
+ handler: (req) => {
888
+ return req.server.plugins.flow.configs;
889
+ }
890
+ });
891
+ }
892
+ const HMR = {
893
+ head: ' <script src="/_flow/hmr/client.js"><\/script>',
894
+ body: ' <script src="/_flow/hmr/connect.js"><\/script>'
895
+ };
896
+ server.ext("onPreHandler", async (req, h) => {
897
+ if (req.route.settings.plugins?.generate === ".html") {
898
+ const { global } = req.plugins.flow;
899
+ Object.assign(global, {
900
+ hmr: isProduction || isGenerate ? { head: "", body: "" } : HMR
901
+ });
902
+ }
903
+ return h.continue;
904
+ });
905
+ };
906
+
718
907
  const plugin = {
719
908
  pkg,
720
909
  dependencies,
@@ -839,6 +1028,7 @@ const plugin = {
839
1028
  return baseOptions;
840
1029
  }
841
1030
  };
1031
+ await RegisterCommon(server, config);
842
1032
  }
843
1033
  };
844
1034
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monkeyplus/flow",
3
- "version": "4.0.0-beta.1",
3
+ "version": "4.0.0-beta.11",
4
4
  "description": "Utils hapi",
5
5
  "author": "Andres Navarrete",
6
6
  "license": "MIT",
@@ -9,7 +9,8 @@
9
9
  "types": "./dist/index.d.ts",
10
10
  "files": [
11
11
  "dist/",
12
- "types/"
12
+ "types/",
13
+ "resources/"
13
14
  ],
14
15
  "exports": {
15
16
  ".": {
@@ -20,14 +21,18 @@
20
21
  "dependencies": {
21
22
  "@hapi/boom": "9.x.x",
22
23
  "@hapi/hoek": "9.x.x",
23
- "chalk": "^5.0.0",
24
24
  "consola": "^2.15.3",
25
+ "chalk": "^4.1.2",
26
+ "chokidar": "^3.5.3",
27
+ "hookable": "^5.1.1",
25
28
  "fs-extra": "^10.0.0",
26
29
  "ramda": "^0.28.0"
27
30
  },
28
31
  "devDependencies": {
29
32
  "@types/fs-extra": "^9.0.13",
30
33
  "@types/hapi__hapi": "^20.0.10",
34
+ "@types/hapi__nes": "^11.0.5",
35
+ "@types/hapi__vision": "^5.5.3",
31
36
  "@types/ramda": "^0.27.64"
32
37
  },
33
38
  "peerDependencies": {
@@ -0,0 +1 @@
1
+ 'use strict';var _typeof='function'==typeof Symbol&&'symbol'==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&'function'==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?'symbol':typeof a};(function(a,b){'object'===('undefined'==typeof exports?'undefined':_typeof(exports))&&'object'===('undefined'==typeof module?'undefined':_typeof(module))?module.exports=b():'function'==typeof define&&define.amd?define(b):'object'===('undefined'==typeof exports?'undefined':_typeof(exports))?exports.nes=b():a.nes=b()})('undefined'==typeof window?global:window,function(){var a=function(){},b=function(a){try{return JSON.stringify(a)}catch(a){throw new e(a,d.USER)}},c=function(a){return function(b){setTimeout(function(){return a(b)},0)}},d={TIMEOUT:'timeout',DISCONNECT:'disconnect',SERVER:'server',PROTOCOL:'protocol',WS:'ws',USER:'user'},e=function(a,b){'string'==typeof a&&(a=new Error(a)),a.type=b,a.isNes=!0;try{throw a}catch(a){return a}},f={1000:'Normal closure',1001:'Going away',1002:'Protocol error',1003:'Unsupported data',1004:'Reserved',1005:'No status received',1006:'Abnormal closure',1007:'Invalid frame payload data',1008:'Policy violation',1009:'Message too big',1010:'Mandatory extension',1011:'Internal server error',1015:'TLS handshake'},g=function(b,c){c=c||{},this._isBrowser='undefined'!=typeof WebSocket,this._isBrowser||(c.ws=c.ws||{},void 0===c.ws.maxPayload&&(c.ws.maxPayload=0)),this._url=b,this._settings=c,this._heartbeatTimeout=!1,this._ws=null,this._reconnection=null,this._reconnectionTimer=null,this._ids=0,this._requests={},this._subscriptions={},this._heartbeat=null,this._packets=[],this._disconnectListeners=null,this._disconnectRequested=!1,this.onError=function(a){return console.error(a)},this.onConnect=a,this.onDisconnect=a,this.onHeartbeatTimeout=a,this.onUpdate=a,this.id=null};return g.WebSocket='undefined'==typeof WebSocket?null:WebSocket,g.prototype.connect=function(a){var b=this;return(a=a||{},this._reconnection)?Promise.reject(new e('Cannot connect while client attempts to reconnect',d.USER)):this._ws?Promise.reject(new e('Already connected',d.USER)):(this._reconnection=!1===a.reconnect?null:{wait:0,delay:a.delay||1e3,maxDelay:a.maxDelay||5e3,retries:a.retries||Infinity,settings:{auth:a.auth,timeout:a.timeout}},new Promise(function(c,d){b._connect(a,!0,function(a){return a?d(a):c()})}))},g.prototype._connect=function(a,b,h){var i=this,j=this._isBrowser?new g.WebSocket(this._url):new g.WebSocket(this._url,this._settings.ws);this._ws=j,clearTimeout(this._reconnectionTimer),this._reconnectionTimer=null;var k=function(a){j.onopen&&l(new e('Connection terminated while waiting to connect',d.WS));var b=i._disconnectRequested;i._cleanup();var c={code:a.code,explanation:f[a.code]||'Unknown',reason:a.reason,wasClean:a.wasClean,willReconnect:i._willReconnect(),wasRequested:b};i.onDisconnect(c.willReconnect,c),i._reconnect()},l=function(a){if(h){var b=h;return h=null,b(a)}return i.onError(a)},m=a.timeout?setTimeout(function timeoutHandler(){if(i._cleanup(),l(new e('Connection timed out',d.TIMEOUT)),b)return i._reconnect()},a.timeout):null;j.onopen=function(){clearTimeout(m),j.onopen=null,i._hello(a.auth).then(function(){i.onConnect(),l()}).catch(function(a){a.path&&delete i._subscriptions[a.path],i._disconnect(function(){return c(l)(a)},!0)})},j.onerror=function(a){if(clearTimeout(m),i._willReconnect())return k(a);i._cleanup();var b=new e('Socket error',d.WS);return l(b)},j.onclose=k,j.onmessage=function(a){return i._onMessage(a)}},g.prototype.overrideReconnectionAuth=function(a){return!!this._reconnection&&(this._reconnection.settings.auth=a,!0)},g.prototype.reauthenticate=function(a){this.overrideReconnectionAuth(a);return this._send({type:'reauth',auth:a},!0)},g.prototype.disconnect=function(){var a=this;return new Promise(function(b){return a._disconnect(b,!1)})},g.prototype._disconnect=function(a,b){this._reconnection=null,clearTimeout(this._reconnectionTimer),this._reconnectionTimer=null;var c=this._disconnectRequested||!b;return this._disconnectListeners?(this._disconnectRequested=c,void this._disconnectListeners.push(a)):this._ws&&(this._ws.readyState===g.WebSocket.OPEN||this._ws.readyState===g.WebSocket.CONNECTING)?void(this._disconnectRequested=c,this._disconnectListeners=[a],this._ws.close()):a()},g.prototype._cleanup=function(){if(this._ws){var k=this._ws;this._ws=null,k.readyState!==g.WebSocket.CLOSED&&k.readyState!==g.WebSocket.CLOSING&&k.close(),k.onopen=null,k.onclose=null,k.onerror=a,k.onmessage=null}this._packets=[],this.id=null,clearTimeout(this._heartbeat),this._heartbeat=null;var b=new e('Request failed - server disconnected',d.DISCONNECT),c=this._requests;this._requests={};for(var f=Object.keys(c),h=0;h<f.length;++h){var i=f[h],j=c[i];clearTimeout(j.timeout),j.reject(b)}if(this._disconnectListeners){var l=this._disconnectListeners;this._disconnectListeners=null,this._disconnectRequested=!1,l.forEach(function(a){return a()})}},g.prototype._reconnect=function(){var b=this,c=this._reconnection;if(c){if(1>c.retries)return this._disconnect(a,!0);--c.retries,c.wait+=c.delay;var d=Math.min(c.wait,c.maxDelay);this._reconnectionTimer=setTimeout(function(){b._connect(c.settings,!1,function(a){if(a)return b.onError(a),b._reconnect()})},d)}},g.prototype.request=function(a){'string'==typeof a&&(a={method:'GET',path:a});var b={type:'request',method:a.method||'GET',path:a.path,headers:a.headers,payload:a.payload};return this._send(b,!0)},g.prototype.message=function(a){return this._send({type:'message',message:a},!0)},g.prototype._isReady=function(){return this._ws&&this._ws.readyState===g.WebSocket.OPEN},g.prototype._send=function(a,c){if(!this._isReady())return Promise.reject(new e('Failed to send message - server disconnected',d.DISCONNECT));a.id=++this._ids;try{var f=b(a)}catch(a){return Promise.reject(a)}if(!c)try{return this._ws.send(f),Promise.resolve()}catch(a){return Promise.reject(new e(a,d.WS))}var g={resolve:null,reject:null,timeout:null},h=new Promise(function(a,b){g.resolve=a,g.reject=b});this._settings.timeout&&(g.timeout=setTimeout(function(){return g.timeout=null,g.reject(new e('Request timed out',d.TIMEOUT))},this._settings.timeout)),this._requests[a.id]=g;try{this._ws.send(f)}catch(b){return clearTimeout(this._requests[a.id].timeout),delete this._requests[a.id],Promise.reject(new e(b,d.WS))}return h},g.prototype._hello=function(a){var b={type:'hello',version:'2'};a&&(b.auth=a);var c=this.subscriptions();return c.length&&(b.subs=c),this._send(b,!0)},g.prototype.subscriptions=function(){return Object.keys(this._subscriptions)},g.prototype.subscribe=function(a,b){var c=this;if(!a||'/'!==a[0])return Promise.reject(new e('Invalid path',d.USER));var f=this._subscriptions[a];if(f)return-1===f.indexOf(b)&&f.push(b),Promise.resolve();if(this._subscriptions[a]=[b],!this._isReady())return Promise.resolve();var g=this._send({type:'sub',path:a},!0);return g.catch(function(){delete c._subscriptions[a]}),g},g.prototype.unsubscribe=function(b,c){if(!b||'/'!==b[0])return Promise.reject(new e('Invalid path',d.USER));var f=this._subscriptions[b];if(!f)return Promise.resolve();var g=!1;if(!c)delete this._subscriptions[b],g=!0;else{var i=f.indexOf(c);if(-1===i)return Promise.resolve();f.splice(i,1),f.length||(delete this._subscriptions[b],g=!0)}if(!g||!this._isReady())return Promise.resolve();var h=this._send({type:'unsub',path:b},!0);return h.catch(a),h},g.prototype._onMessage=function(b){this._beat();var c=b.data,f=c[0];if('{'!==f){if(this._packets.push(c.slice(1)),'!'!==f)return;c=this._packets.join(''),this._packets=[]}this._packets.length&&(this._packets=[],this.onError(new e('Received an incomplete message',d.PROTOCOL)));try{var g=JSON.parse(c)}catch(a){return this.onError(new e(a,d.PROTOCOL))}var h=null;if(g.statusCode&&400<=g.statusCode&&(h=new e(g.payload.message||g.payload.error||'Error',d.SERVER),h.statusCode=g.statusCode,h.data=g.payload,h.headers=g.headers,h.path=g.path),'ping'===g.type)return this._send({type:'ping'},!1).catch(a);if('update'===g.type)return this.onUpdate(g.message);if('pub'===g.type||'revoke'===g.type){var l=this._subscriptions[g.path];if('revoke'===g.type&&delete this._subscriptions[g.path],l&&void 0!==g.message){var m={};'revoke'===g.type&&(m.revoked=!0);for(var n=0;n<l.length;++n)l[n](g.message,m)}return}var j=this._requests[g.id];if(!j)return this.onError(new e('Received response for unknown request',d.PROTOCOL));clearTimeout(j.timeout),delete this._requests[g.id];var k=function(a,b){return a?j.reject(a):j.resolve(b)};return'request'===g.type?k(h,{payload:g.payload,statusCode:g.statusCode,headers:g.headers}):'message'===g.type?k(h,{payload:g.message}):'hello'===g.type?(this.id=g.socket,g.heartbeat&&(this._heartbeatTimeout=g.heartbeat.interval+g.heartbeat.timeout,this._beat()),k(h)):'reauth'===g.type?k(h,!0):'sub'===g.type||'unsub'===g.type?k(h):(k(new e('Received invalid response',d.PROTOCOL)),this.onError(new e('Received unknown response type: '+g.type,d.PROTOCOL)))},g.prototype._beat=function(){var a=this;this._heartbeatTimeout&&(clearTimeout(this._heartbeat),this._heartbeat=setTimeout(function(){a.onError(new e('Disconnecting due to heartbeat timeout',d.TIMEOUT)),a.onHeartbeatTimeout(a._willReconnect()),a._ws.close()},this._heartbeatTimeout))},g.prototype._willReconnect=function(){return!!(this._reconnection&&1<=this._reconnection.retries)},{Client:g}});
@@ -0,0 +1,15 @@
1
+ /* eslint-disable no-undef */
2
+ const client = new nes.Client("ws://" + location.host, {
3
+ timeout: 5000,
4
+ });
5
+ console.log("[flow] connecting...");
6
+ const start = async () => {
7
+ await client.connect({ delay: 5000 });
8
+ console.log("[flow] connected.");
9
+ const handler = (update, flags) => {
10
+ location.reload();
11
+ };
12
+ client.subscribe("/_flow/hmr", handler);
13
+ };
14
+
15
+ start();
package/types/flow.d.ts CHANGED
@@ -33,6 +33,10 @@ export interface FlowOptions {
33
33
  routeOptions?: RouteOptions
34
34
  dirTemplates?: string
35
35
  plugins: FlowOptionPlugins
36
+ staticDir: string
37
+ hmr: {
38
+ dirs: string[]
39
+ }
36
40
  engines?: ('eta' | 'nunjucks')[]
37
41
  }
38
42
 
@@ -118,6 +122,7 @@ export namespace Flow {
118
122
  }
119
123
  export interface Configs extends FlowOptions {
120
124
  relativeTo: string
125
+
121
126
  locales: string[]
122
127
  defaultUbication: string
123
128
  defaultLanguage: string