@monkeyplus/flow 5.0.0-rc.6 → 5.0.0-rc.61

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,6 @@
1
1
  import type { RadixRouter } from 'radix3';
2
2
  import type { Hookable } from 'hookable';
3
- import type { FlowPage, RuntimeConfig } from '@monkeyplus/flow-schema';
3
+ import type { FlowAppUtils, FlowPage, RuntimeConfig } from '@monkeyplus/flow-schema';
4
4
  declare type HookResult = Promise<void> | void;
5
5
  export interface FlowAppHooks {
6
6
  'flow:pages': (page: FlowPage[]) => HookResult;
@@ -11,6 +11,10 @@ export interface FlowAppHooks {
11
11
  bodyStart: string[];
12
12
  }) => HookResult;
13
13
  'page:links': (links: string[]) => HookResult;
14
+ 'page:context': (ctx: {
15
+ page: string;
16
+ localeCode: string;
17
+ }, utils: any, data: Record<string, any>) => HookResult;
14
18
  'page:chunks': (bundle: string, scripts: {
15
19
  head: string[];
16
20
  body: string[];
@@ -27,11 +31,14 @@ export interface FlowApp {
27
31
  callHook: FlowApp['hooks']['callHook'];
28
32
  eta: any;
29
33
  app: {
30
- utils: Record<string, any>;
34
+ utils: FlowAppUtils;
31
35
  plugins: Record<string, any>;
32
36
  globals: Record<string, any>;
33
37
  };
34
38
  engine: string;
39
+ site: {
40
+ origin: string;
41
+ };
35
42
  engines: Record<string, (template: string) => string>;
36
43
  generate: boolean;
37
44
  render: (view: Record<string, string>, data: any) => Promise<string> | void | string;
package/dist/app/flow.mjs CHANGED
@@ -20,6 +20,9 @@ export function createFlowApp({ runtimeConfig }) {
20
20
  },
21
21
  engine: "eta",
22
22
  engines: {},
23
+ site: {
24
+ origin: `${process.env.URL || "http://localhost"}`
25
+ },
23
26
  generate: runtimeConfig.generate
24
27
  };
25
28
  flowApp.engines.eta = (template) => {
@@ -1,6 +1,6 @@
1
- import { defineEventHandler } from "h3";
2
1
  import "node-fetch-native/polyfill";
3
- import { useRuntimeConfig } from "#internal/nitro";
2
+ import { defineEventHandler } from "h3";
3
+ import { defineCachedFunction, useRuntimeConfig } from "#internal/nitro";
4
4
  const getServerApp = cachedImport(() => import("#server"));
5
5
  const getFlowRenderer = cachedResult(async () => {
6
6
  const createFlowApp = await getServerApp();
@@ -12,6 +12,7 @@ export default defineEventHandler(async ({ context }) => {
12
12
  const flow = await getFlowRenderer();
13
13
  context.flow = flow;
14
14
  context.render = flow.render;
15
+ context.defineCachedFunction = defineCachedFunction;
15
16
  });
16
17
  function _interopDefault(e) {
17
18
  return e && typeof e === "object" && "default" in e ? e.default : e;
@@ -1,4 +1,10 @@
1
1
  import { eventHandler, useQuery } from "h3";
2
+ import { joinURL } from "ufo";
3
+ const normalizeCall = async (seo, ctx) => {
4
+ if (typeof seo === "function")
5
+ return await seo(ctx);
6
+ return seo || {};
7
+ };
2
8
  export default eventHandler(async (event) => {
3
9
  const url = event.req.url?.split("?")[0];
4
10
  const flow = event.context.flow;
@@ -9,34 +15,57 @@ export default eventHandler(async (event) => {
9
15
  const scripts = { head: [], bodyStart: [], bodyEnd: [] };
10
16
  const chunks = { head: [], body: [] };
11
17
  const generate = {};
12
- const { page, locale, params, view } = flow.router.byUrl.lookup(url) || {};
18
+ const { page, locale, params, view, name: pageName } = flow.router.byUrl.lookup(url) || {};
13
19
  if (!page)
14
20
  return;
15
21
  await flow.callHook("page:scripts", scripts);
16
22
  if (view.bundle)
17
23
  await flow.callHook("page:chunks", view.bundle, chunks);
18
24
  const templateContext = {};
19
- const dynamyc = params?._;
20
- const contextPage = {};
21
- const utils = Object.assign({ getLocale: () => locale }, flow.app.utils);
25
+ const dynamic = params?._;
26
+ const contextPage = {
27
+ chunks,
28
+ locale
29
+ };
30
+ const contextInject = {};
31
+ const utils = Object.assign({ getLocale: () => locale, injectContext: (key, value) => contextInject[key] = value, defineCachedFunction: event.context.defineCachedFunction }, flow.app.utils);
32
+ const contextHooks = {};
33
+ await flow.callHook("page:context", { localeCode: locale.code, page: pageName }, utils, contextHooks);
22
34
  templateContext.url = url;
35
+ const pageObject = {
36
+ name: pageName,
37
+ pathname: url,
38
+ url: joinURL(flow.site.origin, `${url}`),
39
+ origin: flow.site.origin,
40
+ joinOrigin: (_url) => joinURL(flow.site.origin, _url)
41
+ };
42
+ templateContext.page = pageObject;
43
+ contextPage.page = pageObject;
23
44
  templateContext.locale = locale;
24
45
  templateContext.view = view;
25
- if (dynamyc && page.dynamic) {
46
+ if (dynamic && page.dynamic) {
26
47
  const pages = await page.dynamic.method({ locale, utils });
27
- const dynamicPage = pages.find((_page) => _page.url === dynamyc);
48
+ const dynamicPage = pages.find((_page) => _page.url === dynamic);
28
49
  if (!dynamicPage)
29
50
  return;
30
51
  if (page.dynamic.assign)
31
52
  templateContext[page.dynamic.assign] = dynamicPage.context;
32
- contextPage.dynamyc = dynamicPage;
53
+ contextPage.dynamic = dynamicPage;
33
54
  }
34
55
  templateContext.seo = {};
35
- templateContext.context = {};
36
- templateContext.sharedContext = {};
56
+ const sharedContext = await utils.getSharedContext({
57
+ ...contextHooks,
58
+ ...contextPage,
59
+ utils
60
+ });
61
+ templateContext.sharedContext = sharedContext || {};
37
62
  templateContext.utils = utils;
38
- templateContext.seo = await page.seo?.({ ...contextPage, utils }) || {};
39
- templateContext.context = await page.context?.({ ...contextPage, utils }) || {};
63
+ templateContext.seo = await normalizeCall(page?.seo, { ...contextHooks, ...contextPage, utils, sharedContext });
64
+ const contexData = await page.context?.({ ...contextHooks, ...contextPage, utils, sharedContext }) || {};
65
+ templateContext.context = {
66
+ ...contextHooks,
67
+ ...contexData
68
+ };
40
69
  templateContext.getHeadScripts = () => {
41
70
  return scripts.head.join("\n");
42
71
  };
@@ -46,11 +75,20 @@ export default eventHandler(async (event) => {
46
75
  templateContext.getBodyChunks = () => {
47
76
  return chunks.body.join("\n");
48
77
  };
78
+ templateContext.getInjectContext = () => {
79
+ return `<script id="__FLOW_DATA__" type="application/json">${JSON.stringify(contextInject)}<\/script>`;
80
+ };
49
81
  const query = useQuery(event);
50
82
  if (query?.context)
51
83
  return { ...templateContext, utils: Object.keys(utils) };
52
- const html = await flow.render(view, templateContext);
53
- event.res.setHeader("Content-Type", "text/html;charset=UTF-8");
84
+ let html;
85
+ if (view.render)
86
+ html = await view.render(templateContext, event);
87
+ else
88
+ html = await flow.render(view, templateContext);
89
+ event.res.setHeader("Content-Type", view.contentType || "text/html;charset=UTF-8");
90
+ if (view.postRender)
91
+ html = await view.postRender(html, event);
54
92
  if (flow.generate) {
55
93
  await flow.callHook("page:generate", generate);
56
94
  globalThis.generate = generate;
package/dist/index.mjs CHANGED
@@ -1,10 +1,12 @@
1
1
  import { createHooks } from 'hookable';
2
2
  import { dirname, resolve, normalize, join, isAbsolute, relative, extname } from 'pathe';
3
3
  import { defineFlowModule, addPlugin, defineNuxtModule, logger, addTemplate, addPluginTemplate, addVitePlugin, useNuxt, resolveAlias, resolveFilesFlow, nuxtCtx, installModule, loadFlowConfig, templateUtils, normalizeTemplate, compileTemplate, normalizePlugin, isIgnoredFlow } from '@monkeyplus/flow-kit';
4
- import { fileURLToPath, pathToFileURL } from 'node:url';
4
+ import { fileURLToPath } from 'url';
5
5
  import { defineUnimportPreset, createUnimport, toImports, scanDirExports } from 'unimport';
6
+ import { pathToFileURL } from 'node:url';
6
7
  import { createUnplugin } from 'unplugin';
7
8
  import { parseURL, parseQuery, joinURL, withoutTrailingSlash } from 'ufo';
9
+ import fs from 'fs';
8
10
  import escapeRE from 'escape-string-regexp';
9
11
  import { camelCase, pascalCase } from 'scule';
10
12
  import { genImport, genDynamicImport, genArrayFromRaw, genString, genObjectFromRawEntries } from 'knitwork';
@@ -27,7 +29,7 @@ import { isExternal as isExternal$1, ExternalsDefaults } from 'externality';
27
29
  import { createHash } from 'node:crypto';
28
30
  import MagicString from 'magic-string';
29
31
 
30
- const version = "5.0.0-rc.6";
32
+ const version = "5.0.0-rc.61";
31
33
 
32
34
  let _distDir = dirname(fileURLToPath(import.meta.url));
33
35
  if (_distDir.endsWith("chunks"))
@@ -92,7 +94,8 @@ const commonPresets = [
92
94
  from: "#_pages",
93
95
  imports: [
94
96
  "definePage",
95
- "defineDinamycPage"
97
+ "defineDynamicPage",
98
+ "defineSharedContext"
96
99
  ]
97
100
  })
98
101
  ];
@@ -228,14 +231,20 @@ ${ctx.generateTypeDecarations({ resolvePath: r })}`
228
231
  });
229
232
  }
230
233
 
231
- async function resolvePagesRoutes() {
234
+ async function resolveFiles(dir) {
232
235
  const nuxt = useNuxt();
233
- const pagesDirs = [...new Set(nuxt.options._layers.map((layer) => resolve(layer.config.srcDir, layer.config.dir?.pages || "pages")))];
234
- const allRoutes = (await Promise.all(pagesDirs.map(async (dir) => {
235
- const files = await resolveFilesFlow(dir, `**/*{${nuxt.options.extensions.join(",")}}`);
236
+ const dirs = [resolve(nuxt.options.srcDir, dir)];
237
+ const allRoutes = (await Promise.all(dirs.map(async (dir2) => {
238
+ const files = await resolveFilesFlow(dir2, `**/*{${nuxt.options.extensions.join(",")}}`);
236
239
  files.sort();
237
- return files.map((file) => {
238
- const segments = relative(dir, file).replace(new RegExp(`${escapeRE(extname(file))}$`), "").split("/").join("_");
240
+ return files.filter((file) => {
241
+ if (file.includes(" copy"))
242
+ return false;
243
+ if (!fs.readFileSync(file, "utf8").includes("export"))
244
+ return false;
245
+ return true;
246
+ }).map((file) => {
247
+ const segments = relative(dir2, file).replace(new RegExp(`${escapeRE(extname(file))}$`), "").split("/").join("_");
239
248
  return {
240
249
  file,
241
250
  name: camelCase(segments)
@@ -244,24 +253,31 @@ async function resolvePagesRoutes() {
244
253
  }))).flat();
245
254
  return allRoutes;
246
255
  }
247
- function normalizePages(pages) {
248
- const imports = pages.map((page) => genImport(page.file, [{ name: "pages", as: page.name }])).join("\n");
256
+ function normalizeExports(files) {
257
+ const imports = files.map((page) => genImport(page.file, page.name)).join("\n");
258
+ const exports = files.reduce((acc, curr) => {
259
+ const name = curr.name;
260
+ return `${name}:typeof ${name}==='function'?${name}():${name},${acc}`;
261
+ }, "");
249
262
  return {
250
263
  imports,
251
- exports: pages.reduce((acc, curr) => {
252
- const name = curr.name;
253
- return `${name}:typeof ${name}==='function'?${name}():${name},${acc}`;
254
- }, "")
264
+ exports
255
265
  };
256
266
  }
257
267
 
258
268
  const pagesTypeTemplate = {
259
- filename: "pages.d.ts",
269
+ filename: "types/pages.d.ts",
260
270
  getContents: ({ options }) => `// Generated by pages discovery
261
271
  export {}
262
272
  declare global {
273
+ type ArrElement<ArrType> = ArrType extends readonly (infer ElementType)[]
274
+ ? ElementType
275
+ : never;
263
276
 
264
- ${options.pages.map((c) => `export type ${pascalCase(c.name)}Context=Awaited<ReturnType<typeof ${genDynamicImport(isAbsolute(c.file) ? relative(options.buildDir, c.file) : c.file, { wrapper: false })}['pages']['locales']['es-ec']['context']>>`).join("\n")}
277
+ ${options.pages.map((c) => {
278
+ const _type = `ArrElement<typeof ${genDynamicImport(isAbsolute(c.file) ? relative(join(options.buildDir, "types"), c.file) : c.file, { wrapper: false })}['default']>`;
279
+ return `export type ${pascalCase(c.name)}Context=Awaited<ReturnType<${_type}['locales']['es-ec']['context']>>`;
280
+ }).join("\n")}
265
281
  }
266
282
  export const pagesNames: string[]
267
283
  `.replaceAll(".ts", "")
@@ -273,38 +289,54 @@ const pagesModule = defineNuxtModule({
273
289
  },
274
290
  async setup(_options, flow) {
275
291
  const runtimeDir = resolve(distDir, "pages/runtime");
292
+ flow.options.alias["#_pages"] = runtimeDir;
276
293
  const pages = [];
277
- flow.hook("builder:watch", async (event, path) => {
278
- const dirs = [
279
- flow.options.dir.pages,
280
- flow.options.dir.layouts,
281
- flow.options.dir.middleware
282
- ].filter(Boolean);
283
- const pathPattern = new RegExp(`^(${dirs.map(escapeRE).join("|")})/`);
284
- if (event !== "change" && path.match(pathPattern))
285
- await flow.callHook("builder:generateApp");
286
- });
287
- const options = { pages, buildDir: flow.options.buildDir };
294
+ const contexts = [];
295
+ const options = { pages, buildDir: flow.options.buildDir, contexts };
288
296
  addTemplate({
289
297
  ...pagesTypeTemplate,
290
298
  options
291
299
  });
300
+ const pagesDirs = [{ path: resolve(flow.options.srcDir, flow.options.dir.pages) }];
292
301
  flow.options.alias["#pages"] = resolve(flow.options.buildDir, "pages.mjs");
302
+ flow.options.alias["#pagesContexts"] = resolve(flow.options.buildDir, "pages.contexts.mjs");
293
303
  addTemplate({
294
304
  filename: "pages.mjs",
295
305
  async getContents({ options: options2 }) {
296
- const { exports, imports } = normalizePages(options2.pages);
297
- return [imports, `export default {${exports}}`].join("\n");
306
+ const { exports, imports } = normalizeExports(options2.pages);
307
+ const module = [imports, `export default {${exports}}`].join("\n");
308
+ return module;
309
+ },
310
+ options
311
+ });
312
+ addTemplate({
313
+ filename: "pages.contexts.mjs",
314
+ async getContents({ options: options2 }) {
315
+ const { exports, imports } = normalizeExports(options2.contexts);
316
+ const module = [imports, `export default {${exports}}`].join("\n");
317
+ return module;
298
318
  },
299
319
  options
300
320
  });
301
321
  flow.hook("app:templates", async () => {
302
- options.pages = await resolvePagesRoutes();
322
+ options.pages = await resolveFiles(flow.options.dir?.pages || "pages");
323
+ });
324
+ flow.hook("app:templates", async () => {
325
+ options.contexts = await resolveFiles("shared/contexts");
303
326
  });
304
327
  flow.hook("prepare:types", ({ references }) => {
305
- references.push({ path: resolve(flow.options.buildDir, "pages.d.ts") });
328
+ references.push({ path: resolve(flow.options.buildDir, "types/pages.d.ts") });
306
329
  });
307
- addPlugin({ src: resolve(runtimeDir, "plugin") });
330
+ flow.hook("builder:watch", async (event, path) => {
331
+ if (!["add", "unlink", "change"].includes(event))
332
+ return;
333
+ if (path.includes(" copy"))
334
+ return;
335
+ const fPath = resolve(flow.options.rootDir, path);
336
+ if (pagesDirs.find((dir) => fPath.startsWith(dir.path)))
337
+ await flow.callHook("builder:generateApp");
338
+ });
339
+ addPlugin(resolve(runtimeDir, "pages"));
308
340
  }
309
341
  });
310
342
 
@@ -332,7 +364,7 @@ const createClient = async (flow) => {
332
364
  if (vite)
333
365
  vite?.ws?.send({ type: "full-reload" });
334
366
  };
335
- const doReload = debounce(_doReload, 60);
367
+ const doReload = debounce(_doReload, 75);
336
368
  flow.hook("bundler:change", () => {
337
369
  doReload();
338
370
  });
@@ -347,7 +379,7 @@ const builClient = async (flow) => {
347
379
  mode: "production",
348
380
  build: {
349
381
  assetsDir: "scripts",
350
- target: "es2017",
382
+ target: "es2015",
351
383
  outDir: ".vite",
352
384
  manifest: true
353
385
  }
@@ -388,23 +420,24 @@ const viteModule = defineFlowModule({
388
420
  }
389
421
  });
390
422
  } else {
391
- flow.hook("modules:done", async () => {
423
+ const file = resolve(flow.options.rootDir, ".vite/manifest.json");
424
+ addTemplate({
425
+ filename: "viteManifest.mjs",
426
+ async getContents() {
427
+ return [
428
+ "import fs from 'fs';",
429
+ `export default ()=>{
430
+ const manifest =JSON.parse(fs.readFileSync("${file}", 'utf8'));
431
+ return {manifest,base:'${_options.dir}'}
432
+ }`
433
+ ].join("\n");
434
+ }
435
+ });
436
+ flow.hook("build:before", async () => {
392
437
  const start = Date.now();
393
438
  logger$1.info("Building client...");
394
439
  await builClient(flow);
395
- const file = resolve(flow.options.rootDir, ".vite/manifest.json");
396
- const manifest = await fse.readFile(file, "utf8");
397
440
  logger$1.success(`Client build in ${Date.now() - start}ms`);
398
- addTemplate({
399
- filename: "viteManifest.mjs",
400
- async getContents() {
401
- return [
402
- "export default ()=>(",
403
- manifest,
404
- ")"
405
- ].join("\n");
406
- }
407
- });
408
441
  });
409
442
  flow.hook("generate:before", async () => {
410
443
  const files = resolve(flow.options.rootDir, ".vite/scripts");
@@ -488,7 +521,8 @@ async function initNitro(flow) {
488
521
  externals: {
489
522
  inline: [
490
523
  ...flow.options.dev ? [] : ["eta", "@monkeyplus/", "@vue/", "@nuxt/", flow.options.buildDir],
491
- "@monkeyplus/flow/dist"
524
+ "@monkeyplus/flow/dist",
525
+ "C:/Users/gnu/Documents/GitHub/flow/packages/flow/dist/app"
492
526
  ]
493
527
  },
494
528
  alias: {
@@ -499,7 +533,8 @@ async function initNitro(flow) {
499
533
  ...flow.options.alias
500
534
  },
501
535
  rollupConfig: {
502
- plugins: []
536
+ plugins: [],
537
+ external: [""]
503
538
  }
504
539
  });
505
540
  await flow.callHook("nitro:config", nitroConfig);
@@ -1091,6 +1126,8 @@ const buildServer = async (ctx) => {
1091
1126
  "/__vue-jsx",
1092
1127
  "#app",
1093
1128
  /(nuxt|nuxt3)\/(dist|src|app)/,
1129
+ /flow\/(dist|src|app)/,
1130
+ /flow\/modules\/(content|icons|images|netlify|netlify-cms|seo|sitemap|vue)/,
1094
1131
  /@monkeyplus\/flow\/(dist|src|app)/,
1095
1132
  /@nuxt\/nitro\/(dist|src)/
1096
1133
  ]
@@ -1168,9 +1205,11 @@ const buildServer = async (ctx) => {
1168
1205
  await onBuild();
1169
1206
  ctx.flow.callHook("bundler:change", {});
1170
1207
  };
1171
- const doBuild = debounce(_doBuild);
1208
+ const doBuild = debounce(_doBuild, 50);
1172
1209
  await _doBuild();
1173
1210
  viteServer.watcher.on("all", (_event, file) => {
1211
+ if (file.includes("/pages/"))
1212
+ return;
1174
1213
  file = normalize(file);
1175
1214
  if (file.indexOf(ctx.flow.options.buildDir) === 0)
1176
1215
  return;
@@ -1290,6 +1329,7 @@ async function bundleVite(flow) {
1290
1329
  include: []
1291
1330
  },
1292
1331
  build: {
1332
+ ssr: true,
1293
1333
  rollupOptions: {
1294
1334
  output: { sanitizeFileName: sanitizeFilePath },
1295
1335
  input: resolve(flow.options.appDir, "entry")
@@ -1326,6 +1366,8 @@ async function bundleVite(flow) {
1326
1366
  flow.hook("vite:serverCreated", (server) => {
1327
1367
  ctx.nuxt.hook("app:templatesGenerated", () => {
1328
1368
  for (const [id, mod] of server.moduleGraph.idToModuleMap) {
1369
+ if (id.includes("pages.mjs"))
1370
+ server.moduleGraph.invalidateModule(mod);
1329
1371
  if (id.startsWith("\0virtual:"))
1330
1372
  server.moduleGraph.invalidateModule(mod);
1331
1373
  }
@@ -1367,8 +1409,7 @@ function watch(flow) {
1367
1409
  "node_modules"
1368
1410
  ]
1369
1411
  });
1370
- const watchHook = debounce((event, path) => flow.callHook("builder:watch", event, normalize(path)));
1371
- watcher.on("all", watchHook);
1412
+ watcher.on("all", (event, path) => flow.callHook("builder:watch", event, normalize(path)));
1372
1413
  flow.hook("close", () => watcher.close());
1373
1414
  return watcher;
1374
1415
  }
@@ -1,3 +1,9 @@
1
- import type { DynamicPage, SimplePage } from '@monkeyplus/flow-schema';
2
- export declare function definePage(page: SimplePage): SimplePage;
3
- export declare function defineDinamycPage(page: DynamicPage): DynamicPage;
1
+ import type { DynamicPage, PageCtx, SimplePage } from '@monkeyplus/flow-schema';
2
+ export declare function definePage<T>(...pages: SimplePage<T>[]): SimplePage<T>[];
3
+ export declare function defineDynamicPage<T>(...pages: DynamicPage<T>[]): DynamicPage<T>[];
4
+ interface SharedContext {
5
+ assign?: 'global' | 'local';
6
+ setup: (cxt: PageCtx) => any;
7
+ }
8
+ export declare function defineSharedContext(shared: SharedContext): SharedContext;
9
+ export {};
@@ -1,6 +1,13 @@
1
- export function definePage(page) {
2
- return page;
1
+ export function definePage(...pages) {
2
+ return pages;
3
3
  }
4
- export function defineDinamycPage(page) {
5
- return page;
4
+ export function defineDynamicPage(...pages) {
5
+ return pages.map((page) => {
6
+ if (!page.name.endsWith("/**"))
7
+ page.name = `${page.name}/**`;
8
+ return page;
9
+ });
10
+ }
11
+ export function defineSharedContext(shared) {
12
+ return shared;
6
13
  }
@@ -0,0 +1,90 @@
1
+ import { joinURL } from "ufo";
2
+ import consola from "consola";
3
+ import { definePage } from "./helpers/index.mjs";
4
+ import { defineFlowPlugin, useRuntimeConfig } from "#app";
5
+ import pages from "#build/pages";
6
+ import contexts from "#build/pages.contexts";
7
+ export default defineFlowPlugin(async (flow) => {
8
+ const { app } = useRuntimeConfig();
9
+ const allPages = [];
10
+ const basePages = Object.entries(pages);
11
+ consola.success("Parsed %i pages files", basePages.length);
12
+ basePages.forEach(([name, _pages]) => {
13
+ const __pages = Array.isArray(_pages) ? _pages : [_pages];
14
+ __pages.forEach((page) => {
15
+ const { getPages } = definePage({
16
+ name,
17
+ ...page
18
+ });
19
+ const _pages2 = getPages(app.locale.location, app.locale.language);
20
+ _pages2.forEach((page2) => {
21
+ flow.router.byUrl.insert(page2.url, page2.context);
22
+ flow.router.byName.insert(page2.name, page2.context);
23
+ allPages.push(page2.context);
24
+ });
25
+ });
26
+ });
27
+ const cache = {};
28
+ async function getUrl(namePage, localeCode) {
29
+ const code = localeCode || this?.getLocale()?.code;
30
+ const [lang, loc] = code.split("-");
31
+ const name = joinURL("/", loc, lang, namePage);
32
+ const { path, params, page } = flow.router.byName.lookup(name) || {};
33
+ if (params?._ && page.dynamic) {
34
+ if (!cache[path]) {
35
+ cache[path] = this.defineCachedFunction(async (_ctx) => {
36
+ return await page.dynamic.method(_ctx);
37
+ }, { maxAge: 8, getKey: () => path, swr: false });
38
+ }
39
+ const fn = cache[path];
40
+ const list = await fn({ utils: this, locale: this.getLocale() });
41
+ const dPage = list.find((el) => el.name === params._);
42
+ return dPage ? path.replace("**", dPage.url) : "/404";
43
+ }
44
+ return path || "/404";
45
+ }
46
+ async function getUrls(withLocale = false) {
47
+ const urls = [];
48
+ for (const page of allPages) {
49
+ if (page.path.includes("/**") && page.page.dynamic) {
50
+ const dPages = await page.page.dynamic.method({
51
+ locale: page.locale,
52
+ utils: Object.assign({ getLocale: () => page.locale }, flow.app.utils),
53
+ chunks: {}
54
+ });
55
+ dPages.forEach((dPage) => {
56
+ const _path = joinURL(page.path.replace("/**", ""), dPage.url);
57
+ urls.push(withLocale ? { url: _path, locale: page.locale.code, name: joinURL(page.name, dPage.name) } : _path);
58
+ });
59
+ } else {
60
+ const url = page.path.replaceAll("*", "");
61
+ urls.push(withLocale ? { url, locale: page.locale.code, name: page.name } : url);
62
+ }
63
+ }
64
+ return urls.sort();
65
+ }
66
+ async function getSharedContext(ctx) {
67
+ const entries = Object.entries(contexts);
68
+ if (!entries.length)
69
+ return {};
70
+ const _contexts = await Promise.all(entries.map(async ([key, method]) => {
71
+ const data = await method.setup(ctx);
72
+ return { [key]: data };
73
+ }));
74
+ return _contexts.reduce((acc, curr) => {
75
+ return {
76
+ ...acc,
77
+ ...curr
78
+ };
79
+ }, {});
80
+ }
81
+ flow.setUtil("getUrl", getUrl);
82
+ flow.setUtil("getUrls", getUrls);
83
+ flow.setUtil("getPages", () => allPages);
84
+ flow.setUtil("getSharedContext", getSharedContext);
85
+ return {
86
+ provide: {
87
+ pages: { allPages }
88
+ }
89
+ };
90
+ });
@@ -5,7 +5,8 @@ export const generateBundle = (config, bundle, _id) => {
5
5
  const chunks = [];
6
6
  chunk2.imports?.forEach((file) => {
7
7
  const importee = bundle[file];
8
- if (file.startsWith("_") && !seen.has(file)) {
8
+ const isChunk = file.startsWith("_") || importee.isEntry;
9
+ if (isChunk && !seen.has(file)) {
9
10
  seen.add(file);
10
11
  chunks.push(...getImportedChunks(importee, seen));
11
12
  chunks.push(importee);
@@ -36,7 +37,7 @@ export const generateBundle = (config, bundle, _id) => {
36
37
  analyzedChunk.set(chunk2, 1);
37
38
  chunk2.imports?.forEach((file) => {
38
39
  const importee = bundle[file];
39
- if (file.startsWith("_"))
40
+ if (file.startsWith("_") || importee.isEntry)
40
41
  tags.push(...getCssTagsForChunk(importee, publicBase2, seen));
41
42
  });
42
43
  }
@@ -1,13 +1,14 @@
1
1
  import logger from "consola";
2
+ import { joinURL } from "ufo";
2
3
  import { generateBundle } from "./injectManifest.mjs";
3
4
  import { defineFlowPlugin } from "#app";
4
5
  import manifest from "#viteManifest";
5
6
  export default defineFlowPlugin((flow) => {
6
7
  if (typeof manifest === "function") {
7
- const _manifest = manifest();
8
8
  flow.hook("page:chunks", (bundle, chunks) => {
9
9
  try {
10
- const chunk = generateBundle(flow.$config.app || {}, _manifest, `client/pages/${bundle}.ts`);
10
+ const data = manifest();
11
+ const chunk = generateBundle(flow.$config.app || {}, data.manifest, joinURL("/", data.base, `${bundle}.ts`).replace("/", ""));
11
12
  if (chunk) {
12
13
  chunks.head.push(chunk.head);
13
14
  chunks.body.push(chunk.body);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monkeyplus/flow",
3
- "version": "5.0.0-rc.6",
3
+ "version": "5.0.0-rc.61",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.mjs",
@@ -25,9 +25,9 @@
25
25
  "dist"
26
26
  ],
27
27
  "dependencies": {
28
- "@monkeyplus/flow-cli": "5.0.0-rc.6",
29
- "@monkeyplus/flow-kit": "5.0.0-rc.6",
30
- "@monkeyplus/flow-schema": "5.0.0-rc.6",
28
+ "@monkeyplus/flow-cli": "5.0.0-rc.61",
29
+ "@monkeyplus/flow-kit": "5.0.0-rc.61",
30
+ "@monkeyplus/flow-schema": "5.0.0-rc.61",
31
31
  "@rollup/plugin-replace": "^4.0.0",
32
32
  "@vueuse/head": "^0.7.6",
33
33
  "c12": "^0.2.7",
@@ -50,7 +50,7 @@
50
50
  "magic-string": "^0.26.2",
51
51
  "mlly": "^0.5.2",
52
52
  "mri": "^1.2.0",
53
- "nitropack": "^0.4.4",
53
+ "nitropack": "^0.4.8",
54
54
  "pathe": "^0.2.0",
55
55
  "perfect-debounce": "^0.1.3",
56
56
  "radix3": "^0.1.2",
@@ -1,53 +0,0 @@
1
- import { joinURL } from "ufo";
2
- import { definePage } from "./helpers/index.mjs";
3
- import { defineFlowPlugin, useRuntimeConfig } from "#app";
4
- import pages from "#pages";
5
- export default defineFlowPlugin(async (flow) => {
6
- const { app } = useRuntimeConfig();
7
- const allPages = [];
8
- Object.entries(pages).forEach(([name, page]) => {
9
- const { getPages } = definePage({
10
- name,
11
- ...page
12
- });
13
- const _pages = getPages(app.locale.location, app.locale.language);
14
- _pages.forEach((page2) => {
15
- flow.router.byUrl.insert(page2.url, page2.context);
16
- flow.router.byName.insert(page2.name, page2.context);
17
- allPages.push(page2.context);
18
- });
19
- });
20
- function getUrl(namePage, localeCode) {
21
- const code = localeCode || this?.getLocale()?.code;
22
- const [lang, loc] = code.split("-");
23
- const name = joinURL("/", loc, lang, namePage);
24
- const { path } = flow.router.byName.lookup(name) || {};
25
- return path || "/404";
26
- }
27
- async function getUrls(withLocale = false) {
28
- const urls = [];
29
- for (const page of allPages) {
30
- if (!page.path.includes("/**")) {
31
- urls.push(withLocale ? { url: page.path, locale: page.locale.code, name: page.name } : page.path);
32
- } else {
33
- const dPages = await page.page.dynamic.method({
34
- locale: page.locale,
35
- utils: Object.assign({ getLocale: () => page.locale }, flow.app.utils)
36
- });
37
- dPages.forEach((dPage) => {
38
- const _path = joinURL(page.path.replace("/**", ""), dPage.url);
39
- urls.push(withLocale ? { url: _path, locale: page.locale.code, name: joinURL(page.name, dPage.name) } : _path);
40
- });
41
- }
42
- }
43
- return urls.sort();
44
- }
45
- flow.setUtil("getUrl", getUrl);
46
- flow.setUtil("getUrls", getUrls);
47
- flow.setUtil("getPages", () => allPages);
48
- return {
49
- provide: {
50
- pages: { allPages }
51
- }
52
- };
53
- });
File without changes