@monkeyplus/flow 3.7.5 → 4.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,871 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ const path = require('path');
6
+ const hoek = require('@hapi/hoek');
7
+ const consola = require('consola');
8
+ const R = require('ramda');
9
+ const boom = require('@hapi/boom');
10
+ const os = require('os');
11
+ const chalk = require('chalk');
12
+ const fs = require('fs-extra');
13
+
14
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e["default"] : e; }
15
+
16
+ function _interopNamespace(e) {
17
+ if (e && e.__esModule) return e;
18
+ const n = Object.create(null);
19
+ if (e) {
20
+ for (const k in e) {
21
+ n[k] = e[k];
22
+ }
23
+ }
24
+ n["default"] = e;
25
+ return n;
26
+ }
27
+
28
+ const path__default = /*#__PURE__*/_interopDefaultLegacy(path);
29
+ const consola__default = /*#__PURE__*/_interopDefaultLegacy(consola);
30
+ const R__namespace = /*#__PURE__*/_interopNamespace(R);
31
+ const os__default = /*#__PURE__*/_interopDefaultLegacy(os);
32
+ const chalk__default = /*#__PURE__*/_interopDefaultLegacy(chalk);
33
+ const fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
34
+
35
+ const name = "@monkeyplus/flow";
36
+ const version = "4.0.0-beta.1";
37
+ const description = "Utils hapi";
38
+ const author = "Andres Navarrete";
39
+ const license = "MIT";
40
+ const main = "./dist/index.cjs";
41
+ const module$1 = "./dist/index.mjs";
42
+ const types = "./dist/index.d.ts";
43
+ const files = [
44
+ "dist/",
45
+ "types/"
46
+ ];
47
+ const exports$1 = {
48
+ ".": {
49
+ "import": "./dist/index.mjs",
50
+ require: "./dist/index.cjs"
51
+ }
52
+ };
53
+ const scripts = {
54
+ build: "unbuild",
55
+ dev: "pnpm stub && pnpm types",
56
+ stub: "unbuild --stub",
57
+ types: "tsup ./src/index.ts --dts-only --external types && esno ../../scripts/replace",
58
+ lint: "eslint --ext .js,.ts .",
59
+ fix: "eslint --fix --ext .ts .",
60
+ prepublishOnly: "pnpm run build",
61
+ publish: "pnpm publish",
62
+ start: "esno src/index.ts",
63
+ test: "vitest"
64
+ };
65
+ const dependencies$1 = {
66
+ "@hapi/boom": "9.x.x",
67
+ "@hapi/hoek": "9.x.x",
68
+ chalk: "^5.0.0",
69
+ consola: "^2.15.3",
70
+ "fs-extra": "^10.0.0",
71
+ ramda: "^0.28.0"
72
+ };
73
+ const devDependencies = {
74
+ "@types/fs-extra": "^9.0.13",
75
+ "@types/hapi__hapi": "^20.0.10",
76
+ "@types/ramda": "^0.27.64"
77
+ };
78
+ const peerDependencies = {
79
+ "@hapi/hapi": "^20.x"
80
+ };
81
+ const gitHead = "1d5387b9c77909019f36d360a0ac53ddaa40e4af";
82
+ const pkg = {
83
+ name: name,
84
+ version: version,
85
+ description: description,
86
+ author: author,
87
+ license: license,
88
+ main: main,
89
+ module: module$1,
90
+ types: types,
91
+ files: files,
92
+ exports: exports$1,
93
+ scripts: scripts,
94
+ dependencies: dependencies$1,
95
+ devDependencies: devDependencies,
96
+ peerDependencies: peerDependencies,
97
+ gitHead: gitHead
98
+ };
99
+
100
+ const logger$1 = consola__default.withScope(pkg.name);
101
+ const dependencies = {
102
+ "@hapi/vision": "6.x.x"
103
+ };
104
+
105
+ const LifeCircle = {
106
+ register: (server) => {
107
+ server.ext("onPreStart", async () => {
108
+ await server.methods.flow.pages();
109
+ });
110
+ server.ext("onRequest", async (req, h) => {
111
+ await server.methods.flow.pages();
112
+ const stateRequest = {
113
+ global: {},
114
+ local: {},
115
+ context: {},
116
+ utils: {},
117
+ extensions: {}
118
+ };
119
+ req.plugins.flow = stateRequest;
120
+ const { flow: state } = server.app;
121
+ const pathRedirect = state.pages.redirects[req.path];
122
+ if (state.truncates[req.path])
123
+ return h.redirect("/").takeover();
124
+ if (pathRedirect)
125
+ return h.redirect(pathRedirect).takeover();
126
+ return h.continue;
127
+ });
128
+ server.ext("onPreHandler", async (req, h) => {
129
+ const { dynamic } = req.route.settings.plugins?.flow || {};
130
+ const flow = req.route.settings.app?.flow;
131
+ if (!dynamic)
132
+ return h.continue;
133
+ const pages = await dynamic.pages({
134
+ server,
135
+ route: req.route,
136
+ locale: flow?.locale
137
+ });
138
+ if (!pages || !pages.length)
139
+ return h.continue;
140
+ const page = pages.find((_page) => _page.url === req.params.url);
141
+ if (!page)
142
+ return boom.notFound();
143
+ Object.assign(req.plugins.flow.local, {
144
+ [dynamic.assign || "dynamic"]: page.context ?? { a: "" }
145
+ });
146
+ req.app.dynamic = R__namespace.omit(["context"], page);
147
+ return h.continue;
148
+ });
149
+ }
150
+ };
151
+
152
+ const ServerInfo = {
153
+ register: (server) => {
154
+ const serverInfo = () => {
155
+ const interfaces = os__default.networkInterfaces();
156
+ const hostname = "localhost";
157
+ const protocol = "http";
158
+ console.log("");
159
+ logger$1.success(chalk__default.green(`Flow v${pkg.version} dev server running at:`));
160
+ console.log("");
161
+ Object.keys(interfaces).forEach((key) => (interfaces[key] || []).filter((details) => details.family === "IPv4").map((detail) => {
162
+ return {
163
+ type: detail.address.includes("127.0.0.1") ? "Local: " : "Network: ",
164
+ host: detail.address.replace("127.0.0.1", hostname)
165
+ };
166
+ }).forEach(({ type, host }) => {
167
+ const url = `${protocol}://${host}:${chalk__default.bold(server.info.port)}`;
168
+ console.log(` > ${type} ${chalk__default.cyan(url)}`);
169
+ }));
170
+ };
171
+ return { serverInfo };
172
+ }
173
+ };
174
+
175
+ function getLocalDefaults(loc, opts) {
176
+ const bundle = R__namespace.path(["locales", loc, "view", "bundle"], opts);
177
+ const view = R__namespace.path(["locales", loc, "view"], opts);
178
+ const runContext = R__namespace.path(["locales", loc, "context"], opts);
179
+ const seo = R__namespace.path(["locales", loc, "seo"], opts);
180
+ const blogInfo = R__namespace.path(["locales", loc, "blogInfo"], opts);
181
+ return {
182
+ bundle,
183
+ view,
184
+ runContext,
185
+ seo: seo || {},
186
+ blogInfo
187
+ };
188
+ }
189
+ function getLevel(locale, defLevel) {
190
+ const level = typeof defLevel === "string" ? defLevel : typeof defLevel === "object" ? defLevel.locales[locale] || defLevel.default : "";
191
+ return level;
192
+ }
193
+ const definePages = (options) => (defaultLocale) => (levelOptions = {}) => {
194
+ const prefixName = levelOptions.prefixName || "";
195
+ const pages = (locales) => locales.map(({ locale, url, seo }) => {
196
+ const page = getLocalDefaults(locale, options);
197
+ const levelBase = getLevel(locale, levelOptions.level);
198
+ const level = getLevel(locale, options.level);
199
+ const [language, ubication] = locale.split("-");
200
+ const prefixLang = language === defaultLocale.language ? "" : language;
201
+ const prefixUbication = ubication === defaultLocale.ubication ? "" : ubication;
202
+ const prefixLevel = path__default.posix.join("/", prefixLang, prefixUbication, levelBase, level);
203
+ const publicPath = defaultLocale.publicPath || "/";
204
+ const fullPath = path__default.posix.join("/", publicPath, prefixLevel, url);
205
+ const redirect = R__namespace.last(fullPath) === "/" ? path__default.posix.join(fullPath, "index.html") : void 0;
206
+ const app = {
207
+ localeName: path__default.posix.join(prefixName, locale, options.name),
208
+ name: options.name,
209
+ locale,
210
+ language,
211
+ level,
212
+ redirect,
213
+ seo: R__namespace.mergeDeepLeft(seo || {}, page.seo),
214
+ blogInfo: page.blogInfo,
215
+ urlObject: {
216
+ publicPath,
217
+ level: prefixLevel,
218
+ url,
219
+ path: fullPath,
220
+ static: R__namespace.last(fullPath) === "/" ? `${fullPath}index.html` : `${fullPath}.html`
221
+ },
222
+ view: { ...options.view, ...page.view },
223
+ runSharedContext: options.context,
224
+ runLocalContext: page.runContext
225
+ };
226
+ return app;
227
+ });
228
+ return {
229
+ name: options.name,
230
+ pages
231
+ };
232
+ };
233
+
234
+ const handlerPage = async (req, h) => {
235
+ const { configs } = req.server.plugins.flow;
236
+ const { flow } = req.route.settings.app;
237
+ const { dynamic } = req.app;
238
+ const local = {};
239
+ const global = {};
240
+ const page = R__namespace.clone({
241
+ ...R__namespace.pick(["publicPath", "path"], flow.urlObject),
242
+ ...R__namespace.pick([
243
+ "name",
244
+ "localeName",
245
+ "locale",
246
+ "level",
247
+ "template",
248
+ "bundle",
249
+ "language"
250
+ ], flow)
251
+ });
252
+ if (dynamic) {
253
+ Object.assign(page, {
254
+ path: dynamic.url,
255
+ ...R__namespace.omit(["url"], dynamic)
256
+ });
257
+ }
258
+ const utils = {
259
+ ...req.plugins.flow.utils,
260
+ getLocalUrl: (name) => {
261
+ return h.getUrl(flow.locale, name);
262
+ },
263
+ getUrl: h.getUrl
264
+ };
265
+ const seo = {
266
+ ...flow.seo,
267
+ ...req.pre.seo,
268
+ url: configs.url,
269
+ pageUrl: `${configs.url}${req.url.pathname}`
270
+ };
271
+ const contextMethod = {
272
+ seo,
273
+ req,
274
+ h,
275
+ page,
276
+ extensions: req.plugins.flow.extensions,
277
+ global: req.plugins.flow.global,
278
+ utils
279
+ };
280
+ const extraContexts = req.plugins.flow.context;
281
+ for (const key in extraContexts) {
282
+ if (extraContexts[key]?.method) {
283
+ const assign = extraContexts[key].assign;
284
+ const data = await extraContexts[key].method(contextMethod);
285
+ const _context = { [key]: data };
286
+ if (assign === "global")
287
+ Object.assign(global, _context);
288
+ else if (assign === "local")
289
+ Object.assign(local, _context);
290
+ else
291
+ Object.assign(seo, _context);
292
+ }
293
+ }
294
+ if (flow.runSharedContext) {
295
+ const _context = await flow.runSharedContext(contextMethod);
296
+ Object.assign(local, _context);
297
+ }
298
+ if (flow.runLocalContext) {
299
+ const _context = await flow.runLocalContext(contextMethod);
300
+ Object.assign(local, _context);
301
+ }
302
+ const context = {
303
+ view: flow.view,
304
+ context: Object.freeze({ ...local, ...req.plugins.flow.local }),
305
+ seo,
306
+ page,
307
+ utils: {},
308
+ hapi: { req, h },
309
+ global: Object.freeze({ ...global, ...req.plugins.flow.global })
310
+ };
311
+ if (req.query.context) {
312
+ context.utils = Object.keys(utils);
313
+ context.hapi = ["req", "h"];
314
+ return context;
315
+ }
316
+ context.utils = utils;
317
+ return h.view(`${configs.dirTemplates}${flow.view.template}`, context);
318
+ };
319
+
320
+ const logger = consola__default.withScope("@monkeyplus/flow");
321
+ const defaults = {
322
+ locales: ["es-ec"],
323
+ defaultUbication: "ec",
324
+ defaultLanguage: "es",
325
+ publicPath: "/",
326
+ locale: "es-ec",
327
+ relativeTo: "",
328
+ dirTemplates: "",
329
+ outputDir: "build",
330
+ url: process.env.CUSTOM_URL || process.env.URL,
331
+ engines: ["eta"],
332
+ plugins: {}
333
+ };
334
+ function getConfigs(server, options) {
335
+ const relativeTo = path__default.resolve(options.relativeTo);
336
+ const getObject = (object) => {
337
+ const config = hoek.applyToDefaults(defaults, { ...object, ...options });
338
+ return {
339
+ ...config,
340
+ relativeTo,
341
+ locale: `${config.defaultLanguage}-${config.defaultUbication}`
342
+ };
343
+ };
344
+ try {
345
+ const pathWeb = path__default.resolve(options.relativeTo, "flow.config");
346
+ logger.info("Flow apply settings from file: flow.config");
347
+ const configBase = require(pathWeb);
348
+ const config = getObject(configBase);
349
+ return config;
350
+ } catch (error) {
351
+ logger.info("Flow no config file apply default settings");
352
+ return getObject({});
353
+ }
354
+ }
355
+ const isDinamyc = (url) => /\{url?(.+)\}/.test(url);
356
+
357
+ const Decorators = {
358
+ register: (server) => {
359
+ const { flow: state } = server.app;
360
+ const { configs, helpers } = server.plugins.flow;
361
+ const flowDecorate = (route, options) => {
362
+ const { plugins, app } = route.settings;
363
+ Object.assign(plugins, { generate: ".html" });
364
+ const flow = app.flow;
365
+ const runCommons = (pageInfo) => {
366
+ helpers.addStaticPage(pageInfo.localeName, {
367
+ url: route.path,
368
+ locale: pageInfo.locale,
369
+ localeName: pageInfo.localeName,
370
+ name: pageInfo.name
371
+ });
372
+ if (pageInfo.redirect)
373
+ helpers.addRedirect(pageInfo.redirect, route.path);
374
+ };
375
+ if (flow) {
376
+ runCommons(flow);
377
+ } else {
378
+ const routes = definePages({
379
+ name: options.name,
380
+ view: options.view,
381
+ locales: {
382
+ [options.locale || configs.locale]: {}
383
+ },
384
+ context: options.context
385
+ })({
386
+ language: configs.defaultLanguage,
387
+ ubication: configs.defaultUbication,
388
+ publicPath: configs.publicPath
389
+ })().pages([
390
+ { locale: options.locale || configs.locale, url: route.path }
391
+ ]);
392
+ const pageInfo = routes[0];
393
+ runCommons(pageInfo);
394
+ Object.assign(app, { flow: pageInfo, content: options.content });
395
+ }
396
+ const extensions = plugins?.flow?.extensions || {};
397
+ if (isDinamyc(route.path)) {
398
+ if (!route.settings.plugins?.flow?.dynamic)
399
+ throw new Error("Dynamic pages require a method");
400
+ helpers.addDynamicPages(flow.localeName, ((options2) => async () => {
401
+ const _pages = await route.settings.plugins?.flow?.dynamic?.pages(options2);
402
+ const obj = {};
403
+ for (const sPage of _pages || []) {
404
+ const localeName = `${app?.flow.localeName}/${sPage.name}`;
405
+ obj[localeName] = {
406
+ locale: app?.flow.locale,
407
+ localeName,
408
+ name: localeName.replace(`${app?.flow.locale}/`, ""),
409
+ url: route.path.replace("{url*}", sPage.url),
410
+ context: sPage.context,
411
+ dynamicSlug: sPage.dynamicSlug
412
+ };
413
+ }
414
+ return obj;
415
+ })({
416
+ server,
417
+ route,
418
+ locale: app?.flow.locale
419
+ }));
420
+ }
421
+ for (const extension in extensions) {
422
+ const optionExtension = plugins?.flow?.extensions[extension];
423
+ const routeMethod = state.extensions[extension]?.routeMethod;
424
+ if (routeMethod)
425
+ routeMethod({ pageInfo: app.flow, route }, optionExtension);
426
+ }
427
+ return handlerPage;
428
+ };
429
+ const getUrl = (_locale, _name) => {
430
+ try {
431
+ const pageName = path__default.posix.join(_locale, _name);
432
+ const page = state.pages.all[pageName];
433
+ if (page) {
434
+ return page.url;
435
+ } else {
436
+ logger$1.warn("Not found link with name: %s", pageName);
437
+ return "/404";
438
+ }
439
+ } catch (error) {
440
+ logger$1.error(error);
441
+ return "/";
442
+ }
443
+ };
444
+ server.method("flow.getUrl", getUrl, {});
445
+ server.decorate("handler", "flow", flowDecorate);
446
+ server.decorate("toolkit", "getUrl", server.methods.flow.getUrl);
447
+ }
448
+ };
449
+
450
+ const useGenerator = {
451
+ register: (server) => {
452
+ const { configs, helpers } = server.plugins.flow;
453
+ const getFlowPages = async () => {
454
+ const files = {};
455
+ const allPages = await server.methods.flow.pages();
456
+ const pages = Object.values(allPages);
457
+ logger.success("Read %i static pages", pages.length);
458
+ for (const page of pages)
459
+ files[page.url] = ".html";
460
+ const routes = server.table();
461
+ for (const route of routes) {
462
+ const isDynamic = /\{url?(.+)\}/.test(route.path);
463
+ const generate = route.settings.plugins?.generate;
464
+ if (!isDynamic && generate) {
465
+ if (!files[route.path])
466
+ files[route.path] = generate;
467
+ }
468
+ }
469
+ return files;
470
+ };
471
+ const writeFile = async (file, payload) => {
472
+ await fs__default.ensureFile(file);
473
+ await fs__default.writeFile(file, payload, "utf8");
474
+ };
475
+ const useCreateFile = (isVirtual = false) => async (dir, url, ext) => {
476
+ if (typeof ext === "object") {
477
+ if (!isVirtual) {
478
+ const dirFile = path__default.dirname(url);
479
+ await fs__default.ensureDir(path__default.join(dir, dirFile));
480
+ const file = await fs__default.readFile(ext.file);
481
+ await fs__default.writeFile(path__default.join(dir, url), file);
482
+ }
483
+ return { type: ext.type || "assets", url };
484
+ } else {
485
+ const r = await server.inject({
486
+ url,
487
+ method: "get"
488
+ });
489
+ let file = "";
490
+ if (typeof ext === "boolean") {
491
+ if (!isVirtual) {
492
+ file = path__default.join(dir, url);
493
+ await writeFile(file, r.payload);
494
+ }
495
+ return { type: "assets", url };
496
+ } else if (typeof ext === "string") {
497
+ if (ext === ".html") {
498
+ if (!isVirtual) {
499
+ const isIndex = R__namespace.last(url) === "/";
500
+ const nameFile = isIndex ? `${url}index.html` : `${url}.html`;
501
+ file = path__default.join(dir, nameFile);
502
+ await writeFile(file, r.payload);
503
+ }
504
+ return { type: "page", url };
505
+ }
506
+ }
507
+ return { type: "asset", url };
508
+ }
509
+ };
510
+ const injectAssets = (assets) => {
511
+ for (const asset of assets) {
512
+ const dirs = asset.dirs;
513
+ for (const dir of dirs) {
514
+ const dirFiles = fs__default.readdirSync(path__default.join(asset.relativeTo, dir));
515
+ for (const file of dirFiles) {
516
+ const pathFile = path__default.join(asset.relativeTo, dir, file);
517
+ const ext = path__default.extname(pathFile);
518
+ if (!!ext) {
519
+ const pathRoute = path__default.posix.join("/", asset.prefix, dir, file);
520
+ const pathRouteOverride = asset.override?.[pathRoute];
521
+ server.route({
522
+ path: pathRouteOverride || pathRoute,
523
+ method: "get",
524
+ options: {
525
+ plugins: {
526
+ generate: {
527
+ isAsset: true,
528
+ file: pathFile,
529
+ type: asset.type,
530
+ isRemane: !!pathRouteOverride
531
+ }
532
+ }
533
+ },
534
+ handler: {
535
+ file: {
536
+ path: pathFile,
537
+ confine: false
538
+ }
539
+ }
540
+ });
541
+ } else {
542
+ injectAssets([
543
+ {
544
+ dirs: [path__default.posix.join(dir, file)],
545
+ prefix: asset.prefix,
546
+ relativeTo: asset.relativeTo,
547
+ override: asset.override,
548
+ type: asset.type || file
549
+ }
550
+ ]);
551
+ }
552
+ }
553
+ }
554
+ }
555
+ };
556
+ const runGenerate = async ({
557
+ assets = [],
558
+ ommitAssets = [],
559
+ virtualGenerate = false
560
+ }) => {
561
+ await server.methods.flow.pages();
562
+ const _assetsApp = [...Object.values(server.app.flow.generate.folders)];
563
+ const _assets = [...assets, ..._assetsApp];
564
+ if (!virtualGenerate)
565
+ injectAssets(_assets);
566
+ const dirOutut = helpers.getPath(configs.outputDir ?? "build");
567
+ const staticDirs = Object.keys(server.app.flow.generate.staticFolders).map((dir) => helpers.getPath(dir));
568
+ const files = await getFlowPages();
569
+ const pairFiles = R__namespace.toPairs(files);
570
+ const ommit = ommitAssets;
571
+ try {
572
+ await fs__default.remove(dirOutut);
573
+ for (const dirStatic of staticDirs)
574
+ await fs__default.copy(dirStatic, dirOutut);
575
+ for (const omitFile of ommit)
576
+ await fs__default.remove(path__default.join(dirOutut, omitFile));
577
+ const createFile = useCreateFile(virtualGenerate);
578
+ const files2 = await Promise.all(pairFiles.map(async (v) => {
579
+ return await createFile(dirOutut, ...v);
580
+ }));
581
+ const groups = R__namespace.groupBy((file) => {
582
+ if (file.url.includes("images/"))
583
+ return "image";
584
+ else
585
+ return (path__default.extname(file.url) || file.type).toLowerCase();
586
+ }, files2);
587
+ const _groups = {
588
+ pages: 0,
589
+ js: 0,
590
+ css: 0,
591
+ images: 0,
592
+ fonts: 0,
593
+ others: 0
594
+ };
595
+ for (const type in groups) {
596
+ const cp = (ext) => ext === type;
597
+ const qty = groups[type].length;
598
+ if (type === "page")
599
+ _groups.pages += qty;
600
+ else if (type === ".js")
601
+ _groups.js += qty;
602
+ else if (type === ".css")
603
+ _groups.css += qty;
604
+ else if ([".gif", ".png", ".jpg", ".jpeg", "image"].find(cp))
605
+ _groups.images += qty;
606
+ else if ([".woff", ".eot", ".ttf"].find(cp))
607
+ _groups.fonts += qty;
608
+ else
609
+ _groups.others += qty;
610
+ }
611
+ for (const type in _groups)
612
+ logger.success("%i %s generated", _groups[type], type);
613
+ const bf = server.app.flow.generate.postGenerate;
614
+ if (Object.keys(bf).length) {
615
+ logger.info("Post generate");
616
+ }
617
+ for (const key in bf)
618
+ await bf[key]();
619
+ } catch (error) {
620
+ logger.error(error);
621
+ await fs__default.remove(dirOutut);
622
+ throw new Error(error);
623
+ }
624
+ };
625
+ return { runGenerate };
626
+ }
627
+ };
628
+
629
+ const definePage = (pageOptions) => (levelOptions) => (configs) => {
630
+ const pages = [];
631
+ for (const locale in pageOptions.locales) {
632
+ if (configs.locales.find((_locale) => _locale === locale)) {
633
+ const singlePage = pageOptions.locales[locale];
634
+ pages.push({ url: singlePage.url, locale });
635
+ }
636
+ }
637
+ const infoPages = definePages({
638
+ name: pageOptions.name,
639
+ view: pageOptions.view,
640
+ context: pageOptions.context,
641
+ level: pageOptions.level,
642
+ locales: pageOptions.locales
643
+ })({
644
+ language: configs.defaultLanguage,
645
+ ubication: configs.defaultUbication,
646
+ publicPath: configs.publicPath
647
+ })(levelOptions).pages(pages);
648
+ const {
649
+ options: sharedOptions,
650
+ rules: sharedRules,
651
+ vhost: sharedVHost
652
+ } = pageOptions;
653
+ const sharedPre = sharedOptions?.pre || [];
654
+ const routes = infoPages.map((page) => {
655
+ const localPage = pageOptions.locales[page.locale];
656
+ const route = {
657
+ path: page.urlObject.path,
658
+ method: "get",
659
+ options: {
660
+ app: {
661
+ flow: page
662
+ },
663
+ plugins: {
664
+ flow: {
665
+ extensions: pageOptions.extensions || {},
666
+ dynamic: localPage.dynamic
667
+ }
668
+ }
669
+ },
670
+ handler: {
671
+ flow: {
672
+ name: page.localeName,
673
+ locale: page.locale,
674
+ view: page.view
675
+ }
676
+ }
677
+ };
678
+ if (sharedRules || localPage.rules)
679
+ route.rules = localPage.rules || sharedRules;
680
+ if (sharedVHost || localPage.vhost)
681
+ route.vhost = localPage.vhost || sharedVHost;
682
+ if (sharedOptions || localPage.options) {
683
+ const localOptions = localPage?.options || {};
684
+ const localPre = localPage?.options?.pre || [];
685
+ const pre = [...sharedPre, ...localPre];
686
+ const options = R__namespace.mergeDeepRight(sharedOptions || {}, localOptions);
687
+ route.options = R__namespace.mergeDeepRight(options, route.options);
688
+ if (route.options && pre.length)
689
+ route.options.pre = pre;
690
+ }
691
+ return route;
692
+ });
693
+ return routes;
694
+ };
695
+
696
+ const RunMethods = {
697
+ register: (server) => {
698
+ const { flow: state } = server.app;
699
+ const { configs: config } = server.plugins.flow;
700
+ const registerRoute = (route) => {
701
+ const _routes = server.table();
702
+ const _route = _routes.find((v) => v.path === route.path);
703
+ if (_route)
704
+ logger$1.warn(`Duplicate route, the route ${route.path} already exists`);
705
+ else
706
+ server.route(route);
707
+ };
708
+ const addPage = (_page, extra) => {
709
+ const registerPages = (_pages2) => {
710
+ for (const _route of _pages2) {
711
+ if (state.routes[_route.path])
712
+ logger$1.warn("The route %s alredy exist", _route.path);
713
+ else
714
+ state.routes[_route.path] = _route;
715
+ }
716
+ };
717
+ let _pages;
718
+ if (typeof _page === "function") {
719
+ _pages = _page(config);
720
+ registerPages(_pages);
721
+ } else {
722
+ _pages = definePage(_page)()(config);
723
+ registerPages(_pages);
724
+ }
725
+ };
726
+ const init = async () => {
727
+ const pages = server.app.flow.routes;
728
+ for (const key in pages) {
729
+ const page = pages[key];
730
+ registerRoute(page);
731
+ }
732
+ for (const key in state.extensions) {
733
+ const ext = state.extensions[key];
734
+ if (ext.initMethod)
735
+ await ext.initMethod();
736
+ }
737
+ logger$1.debug("Register %s pages", `${Object.values(pages).length}`);
738
+ };
739
+ return { init, addPage };
740
+ }
741
+ };
742
+
743
+ const plugin = {
744
+ pkg,
745
+ dependencies,
746
+ register: async (server, _options) => {
747
+ const config = getConfigs(server, _options);
748
+ server.expose("configs", config);
749
+ const state = {
750
+ pages: { statics: {}, redirects: {}, dynamics: {}, all: {} },
751
+ truncates: {},
752
+ extensions: {},
753
+ generate: {
754
+ folders: {},
755
+ staticFolders: {},
756
+ postGenerate: {},
757
+ beforePackage: {}
758
+ },
759
+ engines: {},
760
+ routes: {},
761
+ plugins: {}
762
+ };
763
+ server.app.flow = state;
764
+ const { serverInfo } = ServerInfo.register(server);
765
+ const serverDecorate = {
766
+ serverInfo
767
+ };
768
+ const helpers = {
769
+ getPath: (...paths) => path__default.join(config.relativeTo, ...paths),
770
+ addRedirect: (key, urlPath) => {
771
+ state.pages.redirects[key] = urlPath;
772
+ },
773
+ addStaticPage: (key, url) => {
774
+ if (isDinamyc(url.url))
775
+ return void 0;
776
+ if (state.pages.statics[key]) {
777
+ logger$1.warn("The namePage %s already exist", state.pages.statics[key]);
778
+ } else {
779
+ state.pages.statics[key] = url;
780
+ }
781
+ },
782
+ addDynamicPages: (key, method) => {
783
+ if (state.pages.dynamics[key])
784
+ logger$1.warn("The dynamdcPages %s already exist", key);
785
+ else
786
+ state.pages.dynamics[key] = method;
787
+ }
788
+ };
789
+ server.expose("helpers", helpers);
790
+ server.method("flow.pages", async () => {
791
+ const pages = {
792
+ ...state.pages.statics
793
+ };
794
+ for (const key in state.pages.dynamics) {
795
+ if (Object.prototype.hasOwnProperty.call(state.pages.dynamics, key)) {
796
+ const element = state.pages.dynamics[key];
797
+ const dynamicPages = await element();
798
+ for (const keyPage in dynamicPages) {
799
+ if (Object.prototype.hasOwnProperty.call(dynamicPages, keyPage)) {
800
+ const page = dynamicPages[keyPage];
801
+ if (!pages[keyPage])
802
+ pages[keyPage] = page;
803
+ else
804
+ logger$1.warn("Duplicate page %s", keyPage);
805
+ }
806
+ }
807
+ }
808
+ }
809
+ state.pages.all = pages;
810
+ return pages;
811
+ }, {
812
+ cache: { expiresIn: 3e3, generateTimeout: 8e3 }
813
+ });
814
+ server.expose("pages", () => {
815
+ return state.pages.all;
816
+ });
817
+ server.decorate("server", "flow", serverDecorate);
818
+ Decorators.register(server);
819
+ LifeCircle.register(server);
820
+ const { runGenerate } = useGenerator.register(server);
821
+ serverDecorate.runGenerate = runGenerate;
822
+ const { addPage, init } = RunMethods.register(server);
823
+ serverDecorate.addPage = addPage;
824
+ serverDecorate.init = init;
825
+ serverDecorate.prepagePackage = async () => {
826
+ for (const key in state.generate.beforePackage)
827
+ await state.generate.beforePackage[key]();
828
+ };
829
+ serverDecorate.assignPluginOptions = (realm, options = {}, d = {}, _context) => {
830
+ const key = realm.plugin.replace("@monkeyplus/", "").replace("flow-", "");
831
+ const baseOptions = hoek.applyToDefaults(d, options);
832
+ const { plugins } = config;
833
+ if (plugins[key] && Object.values(plugins[key])) {
834
+ if (typeof plugins[key] === "boolean") {
835
+ try {
836
+ const module = require(path__default.resolve("./extensions", key))?.default;
837
+ if (typeof module === "function") {
838
+ const promise = module({ server, ..._context });
839
+ const isPromise = !!promise && typeof promise.then === "function";
840
+ if (isPromise) {
841
+ return promise.then((opts2) => {
842
+ const _opts = hoek.applyToDefaults(baseOptions, opts2 || {});
843
+ Object.assign(plugins, { [key]: _opts });
844
+ return _opts;
845
+ });
846
+ }
847
+ Object.assign(plugins, { [key]: promise });
848
+ return promise;
849
+ }
850
+ const opts = hoek.applyToDefaults(baseOptions, module || {});
851
+ Object.assign(plugins, { [key]: opts });
852
+ return opts;
853
+ } catch (error) {
854
+ logger$1.error("Error in load extension: %s", key);
855
+ return baseOptions;
856
+ }
857
+ } else {
858
+ const opts = hoek.applyToDefaults(baseOptions, plugins[key]);
859
+ Object.assign(plugins, { [key]: opts });
860
+ return opts;
861
+ }
862
+ } else {
863
+ Object.assign(plugins, { [key]: baseOptions });
864
+ return baseOptions;
865
+ }
866
+ };
867
+ }
868
+ };
869
+
870
+ exports.definePage = definePage;
871
+ exports.plugin = plugin;