@monkeyplus/flow 4.0.0-beta.9 → 5.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.
Files changed (90) hide show
  1. package/app.d.ts +1 -0
  2. package/bin/flow.mjs +2 -0
  3. package/build.config.ts +25 -0
  4. package/dist/app/composables/index.d.ts +4 -0
  5. package/dist/app/composables/index.mjs +12 -0
  6. package/dist/app/entry.d.ts +3 -0
  7. package/dist/app/entry.mjs +23 -0
  8. package/dist/app/flow.d.ts +73 -0
  9. package/dist/app/flow.mjs +85 -0
  10. package/dist/app/index.d.ts +3 -0
  11. package/dist/app/index.mjs +3 -0
  12. package/dist/core/runtime/nitro/flow.d.ts +3 -0
  13. package/dist/core/runtime/nitro/flow.mjs +32 -0
  14. package/dist/core/runtime/nitro/paths.d.ts +4 -0
  15. package/dist/core/runtime/nitro/paths.mjs +15 -0
  16. package/dist/core/runtime/nitro/renderer.d.ts +2 -0
  17. package/dist/core/runtime/nitro/renderer.mjs +59 -0
  18. package/dist/head/runtime/composables.d.ts +9 -0
  19. package/dist/head/runtime/composables.mjs +2 -0
  20. package/dist/head/runtime/index.d.ts +1 -0
  21. package/dist/head/runtime/index.mjs +1 -0
  22. package/dist/head/runtime/plugin.d.ts +2 -0
  23. package/dist/head/runtime/plugin.mjs +6 -0
  24. package/dist/index.d.ts +8 -61
  25. package/dist/index.mjs +1275 -954
  26. package/dist/pages/runtime/helpers/chunks.d.ts +0 -0
  27. package/dist/pages/runtime/helpers/chunks.mjs +0 -0
  28. package/dist/pages/runtime/helpers/index.d.ts +5 -0
  29. package/dist/pages/runtime/helpers/index.mjs +28 -0
  30. package/dist/pages/runtime/plugin.d.ts +2 -0
  31. package/dist/pages/runtime/plugin.mjs +51 -0
  32. package/dist/vite-client/runtime/injectManifest.d.ts +26 -0
  33. package/dist/vite-client/runtime/injectManifest.mjs +104 -0
  34. package/dist/vite-client/runtime/plugin.d.ts +2 -0
  35. package/dist/vite-client/runtime/plugin.mjs +27 -0
  36. package/package.json +55 -36
  37. package/src/app/composables/index.ts +20 -0
  38. package/src/app/entry.ts +36 -0
  39. package/src/app/flow.ts +157 -0
  40. package/src/app/index.ts +5 -0
  41. package/src/auto-imports/module.ts +143 -0
  42. package/src/auto-imports/presets.ts +49 -0
  43. package/src/auto-imports/transform.ts +48 -0
  44. package/src/core/app.ts +90 -0
  45. package/src/core/builder.ts +59 -0
  46. package/src/core/flow.ts +93 -0
  47. package/src/core/modules.ts +32 -0
  48. package/src/core/nitro.ts +206 -0
  49. package/src/core/plugins/import-protection.ts +49 -0
  50. package/src/core/plugins/unctx.ts +31 -0
  51. package/src/core/runtime/nitro/flow.ts +43 -0
  52. package/src/core/runtime/nitro/paths.ts +20 -0
  53. package/src/core/runtime/nitro/renderer.ts +72 -0
  54. package/src/core/templates.ts +119 -0
  55. package/src/core/vite/builder/css.ts +28 -0
  56. package/src/core/vite/builder/dev-bundler.ts +247 -0
  57. package/src/core/vite/builder/index.ts +92 -0
  58. package/src/core/vite/builder/manifest.ts +33 -0
  59. package/src/core/vite/builder/plugins/analyze.ts +32 -0
  60. package/src/core/vite/builder/plugins/cache-dir.ts +13 -0
  61. package/src/core/vite/builder/plugins/dynamic-base.ts +64 -0
  62. package/src/core/vite/builder/plugins/virtual.ts +45 -0
  63. package/src/core/vite/builder/server.ts +163 -0
  64. package/src/core/vite/builder/types/index.ts +13 -0
  65. package/src/core/vite/builder/utils/index.ts +53 -0
  66. package/src/core/vite/builder/utils/warmup.ts +27 -0
  67. package/src/core/vite/builder/utils/wpfs.ts +7 -0
  68. package/src/core/vite/builder/vite-node.ts +110 -0
  69. package/src/core/vite/client/index.ts +48 -0
  70. package/src/dirs.ts +8 -0
  71. package/src/head/module.ts +37 -0
  72. package/src/head/runtime/composables.ts +16 -0
  73. package/src/head/runtime/index.ts +1 -0
  74. package/src/head/runtime/plugin.ts +12 -0
  75. package/src/index.ts +2 -0
  76. package/src/pages/module.ts +55 -0
  77. package/src/pages/runtime/helpers/chunks.ts +0 -0
  78. package/src/pages/runtime/helpers/index.ts +33 -0
  79. package/src/pages/runtime/plugin.ts +58 -0
  80. package/src/pages/templates.ts +20 -0
  81. package/src/pages/utils.ts +49 -0
  82. package/src/vite-client/module.ts +70 -0
  83. package/src/vite-client/runtime/injectManifest.ts +188 -0
  84. package/src/vite-client/runtime/plugin.ts +33 -0
  85. package/types.d.ts +2 -0
  86. package/dist/index.cjs +0 -1061
  87. package/types/core.d.ts +0 -143
  88. package/types/flow.d.ts +0 -239
  89. package/types/index.d.ts +0 -38
  90. package/types/interfaces.d.ts +0 -61
@@ -0,0 +1,13 @@
1
+ import type { InlineConfig, SSROptions, ViteDevServer } from 'vite';
2
+ import type { Flow, Nuxt } from '@monkeyplus/flow-schema';
3
+
4
+ export interface ViteOptions extends InlineConfig {
5
+ ssr?: SSROptions
6
+ }
7
+ export interface ViteBuildContext {
8
+ flow: Flow
9
+ nuxt: Nuxt
10
+ config: ViteOptions
11
+ // clientServer?: ViteDevServer
12
+ ssrServer?: ViteDevServer
13
+ }
@@ -0,0 +1,53 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { promises as fsp, readdirSync, statSync } from 'node:fs';
3
+ import { join } from 'pathe';
4
+
5
+ export function uniq<T>(arr: T[]): T[] {
6
+ return Array.from(new Set(arr));
7
+ }
8
+
9
+ // Copied from vue-bundle-renderer utils
10
+ const IS_JS_RE = /\.[cm]?js(\?[^.]+)?$/;
11
+ const IS_MODULE_RE = /\.mjs(\?[^.]+)?$/;
12
+ const HAS_EXT_RE = /[^./]+\.[^./]+$/;
13
+ const IS_CSS_RE = /\.(?:css|scss|sass|postcss|less|stylus|styl)(\?[^.]+)?$/;
14
+
15
+ export function isJS(file: string) {
16
+ return IS_JS_RE.test(file) || !HAS_EXT_RE.test(file);
17
+ }
18
+
19
+ export function isModule(file: string) {
20
+ return IS_MODULE_RE.test(file) || !HAS_EXT_RE.test(file);
21
+ }
22
+
23
+ export function isCSS(file: string) {
24
+ return IS_CSS_RE.test(file);
25
+ }
26
+
27
+ export function hashId(id: string) {
28
+ return `$id_${hash(id)}`;
29
+ }
30
+
31
+ export function hash(input: string, length = 8) {
32
+ return createHash('sha256')
33
+ .update(input)
34
+ .digest('hex')
35
+ .slice(0, length);
36
+ }
37
+
38
+ export function readDirRecursively(dir: string) {
39
+ return readdirSync(dir).reduce((files, file) => {
40
+ const name = join(dir, file);
41
+ const isDirectory = statSync(name).isDirectory();
42
+ return isDirectory ? [...files, ...readDirRecursively(name)] : [...files, name];
43
+ }, []);
44
+ }
45
+
46
+ export async function isDirectory(path: string) {
47
+ try {
48
+ return (await fsp.stat(path)).isDirectory();
49
+ }
50
+ catch (_err) {
51
+ return false;
52
+ }
53
+ }
@@ -0,0 +1,27 @@
1
+ import { logger } from '@monkeyplus/flow-kit';
2
+ import type { ViteDevServer } from 'vite';
3
+
4
+ export async function warmupViteServer(
5
+ server: ViteDevServer,
6
+ entries: string[],
7
+ ) {
8
+ const warmedUrls = new Set<String>();
9
+
10
+ const warmup = async(url: string) => {
11
+ if (warmedUrls.has(url))
12
+ return;
13
+
14
+ warmedUrls.add(url);
15
+ try {
16
+ await server.transformRequest(url);
17
+ }
18
+ catch (e) {
19
+ logger.debug('Warmup for %s failed with: %s', url, e);
20
+ }
21
+ const mod = await server.moduleGraph.getModuleByUrl(url);
22
+ const deps = Array.from(mod?.importedModules || []);
23
+ await Promise.all(deps.map((m) => warmup(m.url.replace('/@id/__x00__', '\0'))));
24
+ };
25
+
26
+ await Promise.all(entries.map((entry) => warmup(entry)));
27
+ }
@@ -0,0 +1,7 @@
1
+ import { join } from 'pathe';
2
+ import fse from 'fs-extra';
3
+
4
+ export const wpfs = {
5
+ ...fse,
6
+ join,
7
+ } as any;
@@ -0,0 +1,110 @@
1
+ // import { createApp, createError, defineEventHandler, defineLazyEventHandler } from 'h3';
2
+ // import { ViteNodeServer } from 'vite-node/server';
3
+ import fse from 'fs-extra';
4
+ import { resolve } from 'pathe';
5
+ import { distDir } from '../../../dirs';
6
+ import type { ViteBuildContext } from './types';
7
+ // import { addServerMiddleware } from '@nuxt/kit';
8
+ // import type { ViteDevServer, Plugin as VitePlugin } from 'vite';
9
+ // import { distDir } from './dirs';
10
+ // import type { ViteBuildContext } from './vite';
11
+ // import { isCSS } from './utils';
12
+
13
+ // // TODO: Remove this in favor of registerViteNodeMiddleware
14
+ // // after Nitropack or h3 fixed for adding middlewares after setup
15
+ // export function viteNodePlugin(ctx: ViteBuildContext): VitePlugin {
16
+ // return {
17
+ // name: 'nuxt:vite-node-server',
18
+ // enforce: 'pre',
19
+ // configureServer(server) {
20
+ // server.middlewares.use('/__nuxt_vite_node__', createViteNodeMiddleware(ctx));
21
+ // },
22
+ // };
23
+ // }
24
+
25
+ // export function registerViteNodeMiddleware(ctx: ViteBuildContext) {
26
+ // addServerMiddleware({
27
+ // route: '/__nuxt_vite_node__/',
28
+ // handler: createViteNodeMiddleware(ctx),
29
+ // });
30
+ // }
31
+
32
+ // function getManifest(server: ViteDevServer) {
33
+ // const ids = Array.from(server.moduleGraph.urlToModuleMap.keys())
34
+ // .filter((i) => isCSS(i));
35
+
36
+ // const entries = [
37
+ // '@vite/client',
38
+ // 'entry.mjs',
39
+ // ...ids.map((i) => i.slice(1)),
40
+ // ];
41
+
42
+ // return {
43
+ // publicPath: '',
44
+ // all: entries,
45
+ // initial: entries,
46
+ // async: [],
47
+ // modules: {},
48
+ // };
49
+ // }
50
+
51
+ // function createViteNodeMiddleware(ctx: ViteBuildContext) {
52
+ // const app = createApp();
53
+
54
+ // app.use('/manifest', defineEventHandler(async() => {
55
+ // const manifest = await getManifest(ctx.ssrServer);
56
+ // return manifest;
57
+ // }));
58
+
59
+ // app.use('/module', defineLazyEventHandler(() => {
60
+ // const node: ViteNodeServer = new ViteNodeServer(ctx.ssrServer, {
61
+ // deps: {
62
+ // inline: [
63
+ // /\/(nuxt|nuxt3)\//,
64
+ // /^#/,
65
+ // ...ctx.nuxt.options.build.transpile as string[],
66
+ // ],
67
+ // },
68
+ // });
69
+ // return async(event) => {
70
+ // const moduleId = decodeURI(event.req.url).substring(1);
71
+ // if (moduleId === '/')
72
+ // throw createError({ statusCode: 400 });
73
+
74
+ // const module = await node.fetchModule(moduleId) as any;
75
+ // return module;
76
+ // };
77
+ // }));
78
+
79
+ // return app.nodeHandler;
80
+ // }
81
+
82
+ export async function prepareDevServerEntry(ctx: ViteBuildContext) {
83
+ let entryPath = resolve(ctx.flow.options.appDir, 'entry.async.mjs');
84
+ if (!fse.existsSync(entryPath))
85
+ entryPath = resolve(ctx.flow.options.appDir, 'entry.async');
86
+
87
+ // TODO: Update me
88
+ const host = ctx.flow.options.server.host || 'localhost';
89
+ const port = ctx.flow.options.server.port || '3000';
90
+ const protocol = ctx.flow.options.server.https ? 'https' : 'http';
91
+
92
+ // Serialize and pass vite-node runtime options
93
+ const viteNodeServerOptions = {
94
+ baseURL: `${protocol}://${host}:${port}/__flow_vite_node__`,
95
+ rootDir: ctx.flow.options.rootDir,
96
+ entryPath,
97
+ base: '/_flow/',
98
+ // base: ctx.ssrServer.config.base || '/_nuxt/',
99
+ };
100
+ process.env.FLOW_VITE_NODE_OPTIONS = JSON.stringify(viteNodeServerOptions);
101
+
102
+ await fse.writeFile(
103
+ resolve(ctx.flow.options.buildDir, 'dist/server/server.mjs'),
104
+ `export { default } from ${JSON.stringify(resolve(distDir, 'runtime/vite-node.mjs'))}`,
105
+ );
106
+ await fse.writeFile(
107
+ resolve(ctx.flow.options.buildDir, 'dist/server/client.manifest.mjs'),
108
+ `export { default } from ${JSON.stringify(resolve(distDir, 'runtime/client.manifest.mjs'))}`,
109
+ );
110
+ }
@@ -0,0 +1,48 @@
1
+ import { resolve } from 'pathe';
2
+ import type { Flow } from '@monkeyplus/flow-schema';
3
+ import { build, createServer } from 'vite';
4
+ import { debounce } from 'perfect-debounce';
5
+
6
+ export const createClient = async(flow: Flow) => {
7
+ const vite = await createServer({
8
+ root: resolve(flow.options.rootDir),
9
+ base: '/_vite/',
10
+ build: {
11
+ manifest: true,
12
+ },
13
+ server: {
14
+ middlewareMode: 'ssr',
15
+ },
16
+ });
17
+ const _doReload = () => {
18
+ vite.ws.send({ type: 'full-reload' });
19
+ };
20
+
21
+ const doReload = debounce(_doReload, 50);
22
+
23
+ // Use this to refresh page
24
+ flow.hook('bundler:change', () => {
25
+ doReload();
26
+ });
27
+
28
+ flow.hook('close', async() => {
29
+ await vite.close();
30
+ });
31
+
32
+ return vite;
33
+ };
34
+
35
+ export const builClient = async(flow: Flow) => {
36
+ return await build({
37
+ root: flow.options.rootDir,
38
+ mode: 'production',
39
+ build: {
40
+ assetsDir: 'scripts',
41
+ target: 'es2017',
42
+ outDir: '.vite',
43
+ manifest: true,
44
+ },
45
+ });
46
+ };
47
+
48
+ // export default await runVite();
package/src/dirs.ts ADDED
@@ -0,0 +1,8 @@
1
+ import { fileURLToPath } from 'node:url';
2
+ import { dirname, resolve } from 'pathe';
3
+
4
+ let _distDir = dirname(fileURLToPath(import.meta.url));
5
+ if (_distDir.endsWith('chunks')) _distDir = dirname(_distDir);
6
+ export const distDir = _distDir;
7
+ export const pkgDir = resolve(distDir, '..');
8
+ export const runtimeDir = resolve(distDir, 'runtime');
@@ -0,0 +1,37 @@
1
+ import { addPlugin, defineFlowModule } from '@monkeyplus/flow-kit';
2
+ import { resolve } from 'pathe';
3
+ import type { FlowModule } from '@monkeyplus/flow-schema';
4
+
5
+ import { distDir } from '../dirs';
6
+
7
+ export default defineFlowModule({
8
+ meta: {
9
+ name: 'meta',
10
+ },
11
+ defaults: {
12
+ charset: 'utf-8',
13
+ viewport: 'width=device-width, initial-scale=1',
14
+ },
15
+ setup(options, flow) {
16
+ const runtimeDir = flow.options.alias['#head'] || resolve(distDir, 'head/runtime');
17
+ // Transpile @nuxt/meta and @vueuse/head
18
+ // flow.options.build.transpile.push('@vueuse/head');
19
+
20
+ flow.options.alias['#head'] = runtimeDir;
21
+
22
+ // Global meta -for Bridge, this is necessary to repeat here
23
+ // and in packages/schema/src/config/_app.ts
24
+ // const globalMeta: any = defu(flow.options.app.head, {
25
+ // charset: options.charset,
26
+ // viewport: options.viewport,
27
+ // });
28
+
29
+ // // Add global meta configuration
30
+ // addTemplate({
31
+ // filename: 'meta.config.mjs',
32
+ // getContents: () => `export default ${JSON.stringify({ globalMeta })}`,
33
+ // });
34
+ // Add generic plugin
35
+ addPlugin({ src: resolve(runtimeDir, 'plugin') });
36
+ },
37
+ }) as FlowModule<any>;
@@ -0,0 +1,16 @@
1
+
2
+ import type { MetaObject } from '@monkeyplus/flow-schema';
3
+ /**
4
+ * You can pass in a meta object, which has keys corresponding to meta tags:
5
+ * `title`, `base`, `script`, `style`, `meta` and `link`, as well as `htmlAttrs` and `bodyAttrs`.
6
+ *
7
+ * Alternatively, for reactive meta state, you can pass in a function
8
+ * that returns a meta object.
9
+ */
10
+ // TODO: fake use Head
11
+ export function useHead(meta: MetaObject) {
12
+ // console.log('meta', meta);
13
+
14
+ // const resolvedMeta = isFunction(meta) ? computed(meta) : meta;
15
+ // useFlowApp()._useHead(resolvedMeta);
16
+ }
@@ -0,0 +1 @@
1
+ export * from './composables';
@@ -0,0 +1,12 @@
1
+
2
+ import { defineFlowPlugin } from '#app';
3
+
4
+ export default defineFlowPlugin((flow) => {
5
+ // console.log('Pages plugin');
6
+ // flow.hook('page:scripts', (scripts) => {
7
+ // scripts.head.push('');
8
+ // });
9
+ flow._useHead = (_meta: any) => {
10
+ console.log(_meta);
11
+ };
12
+ });
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from './core/flow';
2
+ export * from './core/builder';
@@ -0,0 +1,55 @@
1
+ import { addPlugin, addTemplate, defineNuxtModule } from '@monkeyplus/flow-kit';
2
+ import { resolve } from 'pathe';
3
+ import escapeRE from 'escape-string-regexp';
4
+ import type { FlowModule } from '@monkeyplus/flow-schema';
5
+ import { distDir } from '../dirs';
6
+ import type{ Pages } from './utils';
7
+ import { normalizePages, resolvePagesRoutes } from './utils';
8
+ import { pagesTypeTemplate } from './templates';
9
+ export default defineNuxtModule({
10
+ meta: {
11
+ name: 'pages',
12
+ },
13
+
14
+ async setup(_options, flow) {
15
+ const runtimeDir = resolve(distDir, 'pages/runtime');
16
+ // flow.options.alias['#pages'] = runtimeDir;
17
+ const pages: Pages[] = [];
18
+ // Regenerate templates when adding or removing pages
19
+ flow.hook('builder:watch', async(event, path) => {
20
+ const dirs = [
21
+ flow.options.dir.pages,
22
+ flow.options.dir.layouts,
23
+ flow.options.dir.middleware,
24
+ ].filter(Boolean);
25
+
26
+ const pathPattern = new RegExp(`^(${dirs.map(escapeRE).join('|')})/`);
27
+ if (event !== 'change' && path.match(pathPattern))
28
+ await flow.callHook('builder:generateApp');
29
+ });
30
+ const options = { pages, buildDir: flow.options.buildDir };
31
+ addTemplate({
32
+ ...pagesTypeTemplate,
33
+ options,
34
+ });
35
+
36
+ flow.options.alias['#pages'] = resolve(flow.options.buildDir, 'pages.mjs');
37
+ addTemplate({
38
+ filename: 'pages.mjs',
39
+ async getContents({ options }) {
40
+ const { exports, imports } = normalizePages(options.pages);
41
+ return [imports, `export default {${exports}}`].join('\n');
42
+ },
43
+ options,
44
+ });
45
+
46
+ flow.hook('app:templates', async() => {
47
+ options.pages = await resolvePagesRoutes();
48
+ });
49
+ flow.hook('prepare:types', ({ references }) => {
50
+ references.push({ path: resolve(flow.options.buildDir, 'pages.d.ts') });
51
+ });
52
+ // Add generic plugin
53
+ addPlugin({ src: resolve(runtimeDir, 'plugin') });
54
+ },
55
+ }) as FlowModule<any>;
File without changes
@@ -0,0 +1,33 @@
1
+ import type { GetPages, PageDefinition } from '@monkeyplus/flow-schema';
2
+ import { joinURL, withTrailingSlash } from 'ufo';
3
+
4
+ const buildPages = (page: PageDefinition): GetPages => (location: string, language: string) => {
5
+ const locales = Object.entries(page.locales);
6
+ return locales.map(([locale, localePage]) => {
7
+ const [_language, _location] = locale.split('-');
8
+ const name = joinURL('/', _location, _language, page.name);
9
+ const defLocation = _location === location ? '' : _location;
10
+ const defLanguage = _language === language ? '' : _language;
11
+ const url = joinURL('/', defLocation, defLanguage, localePage.url);
12
+ const _locale = {
13
+ lang: _language,
14
+ loc: _location,
15
+ code: locale,
16
+ };
17
+
18
+ const path = localePage.url.endsWith('/') ? withTrailingSlash(url) : url;
19
+ return {
20
+ name,
21
+ url: path,
22
+ context: { page: localePage, locale: _locale, path, view: page.view, name },
23
+ // locale: _locale,
24
+ };
25
+ });
26
+ };
27
+
28
+ export function definePage(page: PageDefinition) {
29
+ return {
30
+ pages: [],
31
+ getPages: buildPages(page),
32
+ };
33
+ }
@@ -0,0 +1,58 @@
1
+
2
+ import { joinURL } from 'ufo';
3
+ import type { FlowPage } from '@monkeyplus/flow-schema';
4
+ import { definePage } from './helpers';
5
+ import { defineFlowPlugin, useRuntimeConfig } from '#app';
6
+ // @ts-ignore
7
+ import pages from '#pages';
8
+
9
+ export default defineFlowPlugin(async(flow) => {
10
+ const { app } = useRuntimeConfig();
11
+ const allPages: FlowPage['context'] [] = [];
12
+
13
+ Object.entries(pages).forEach(([name, page]) => {
14
+ const { getPages } = definePage({
15
+ name,
16
+ // @ts-expect-error
17
+ ...page,
18
+ });
19
+ const _pages = getPages(app.locale.location!, app.locale.language!);
20
+ _pages.forEach((page) => {
21
+ flow.router.byUrl.insert(page.url, page.context);
22
+ flow.router.byName.insert(page.name, page.context);
23
+ allPages.push(page.context);
24
+ });
25
+ });
26
+
27
+ function getUrl(namePage: string, localeCode?: string): string {
28
+ const code: string = localeCode || this?.getLocale()?.code;
29
+ const [lang, loc] = code.split('-');
30
+ const name = joinURL('/', loc, lang, namePage);
31
+ const { path } = flow.router.byName.lookup(name) || {};
32
+ return path || '/404';
33
+ }
34
+
35
+ async function getUrls() {
36
+ const urls: string[] = [];
37
+ for (const page of allPages) {
38
+ if (!page.path.includes('/**')) { urls.push(page.path); }
39
+ else {
40
+ const dPages = await page.page.dynamic.method({
41
+ locale: page.locale,
42
+ utils: Object.assign({ getLocale: () => page.locale }, flow.app.utils),
43
+ });
44
+ dPages.forEach((dPage) => {
45
+ urls.push(joinURL(page.path.replace('/**', ''), dPage.url));
46
+ });
47
+ }
48
+ }
49
+ return urls.sort();
50
+ }
51
+ flow.setUtil('getUrl', getUrl);
52
+ flow.setUtil('getUrls', getUrls);
53
+ return {
54
+ provide: {
55
+ pages: { allPages },
56
+ },
57
+ };
58
+ });
@@ -0,0 +1,20 @@
1
+ import { genDynamicImport } from 'knitwork';
2
+ import { isAbsolute, relative } from 'pathe';
3
+ import { pascalCase } from 'scule';
4
+ import type { Pages } from './utils';
5
+ export interface PagesTemplateOptions {
6
+ buildDir?: string
7
+ pages: Pages[]
8
+ }
9
+ // TODO: include localeDefault
10
+ export const pagesTypeTemplate = {
11
+ filename: 'pages.d.ts',
12
+ getContents: ({ options }: { options: PagesTemplateOptions }) => `// Generated by pages discovery
13
+ export {}
14
+ declare global {
15
+
16
+ ${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')}
17
+ }
18
+ export const pagesNames: string[]
19
+ `.replaceAll('.ts', ''),
20
+ };
@@ -0,0 +1,49 @@
1
+
2
+ import { resolveFiles, useNuxt } from '@monkeyplus/flow-kit';
3
+ import { extname, relative, resolve } from 'pathe';
4
+ import escapeRE from 'escape-string-regexp';
5
+ import { camelCase } from 'scule';
6
+ import { genImport } from 'knitwork';
7
+
8
+ // import {} from
9
+
10
+ export interface Pages{ file: string; name: string }
11
+ export async function resolvePagesRoutes(): Promise<Pages[]> {
12
+ const nuxt = useNuxt();
13
+
14
+ const pagesDirs = [...new Set(nuxt.options._layers.map(
15
+ (layer) => resolve(layer.config.srcDir, layer.config.dir?.pages || 'pages'),
16
+ ))];
17
+
18
+ const allRoutes: Pages[] = (await Promise.all(
19
+ pagesDirs.map(async(dir) => {
20
+ const files = await resolveFiles(dir, `**/*{${nuxt.options.extensions.join(',')}}`);
21
+
22
+ // Sort to make sure parent are listed first
23
+
24
+ files.sort();
25
+ return files.map((file) => {
26
+ const segments = relative(dir, file).replace(new RegExp(`${escapeRE(extname(file))}$`), '')
27
+ .split('/').join('_');
28
+
29
+ return {
30
+ file,
31
+ name: camelCase(segments),
32
+ };
33
+ });
34
+ }),
35
+ )).flat();
36
+
37
+ return allRoutes;
38
+
39
+ // return uniqueBy(allRoutes, 'path');
40
+ }
41
+
42
+ export function normalizePages(pages: Pages[]) {
43
+ const imports = pages.map((page) => genImport(page.file, [{ name: 'pages', as: page.name }])).join('\n');
44
+ return {
45
+ imports,
46
+ exports: pages.reduce((acc, curr) => `${curr.name || ''},${acc}`, ''),
47
+
48
+ };
49
+ }
@@ -0,0 +1,70 @@
1
+ import { addDevServerHandler, addPlugin, addTemplate, defineFlowModule } from '@monkeyplus/flow-kit';
2
+ import type { FlowModule } from '@monkeyplus/flow-schema';
3
+ import { resolve } from 'pathe';
4
+ // import { genImport } from 'knitwork';
5
+ import fse from 'fs-extra';
6
+ import logger from 'consola';
7
+ import { builClient, createClient } from '../core/vite/client';
8
+ import { distDir } from '../dirs';
9
+
10
+ interface OptionsViteClient{
11
+ route: string
12
+ }
13
+ export default defineFlowModule<OptionsViteClient>({
14
+
15
+ meta: {
16
+ name: 'viteClient',
17
+ },
18
+ defaults: {
19
+ route: '/_vite/',
20
+ },
21
+ async setup(_options, flow) {
22
+ const runtimeDir = resolve(distDir, 'vite-client/runtime');
23
+ flow.options.alias['#viteManifest'] = resolve(flow.options.buildDir, 'viteManifest.mjs');
24
+
25
+ if (flow.options.dev) {
26
+ const _vite = await createClient(flow);
27
+ addDevServerHandler({
28
+ handler: _vite.middlewares,
29
+ route: _options.route,
30
+ });
31
+ addTemplate({
32
+ filename: 'viteManifest.mjs',
33
+ async getContents() {
34
+ return ['export default {',
35
+ 'head:()=>`<script type="module" src="/_vite/@vite/client"></script>`',
36
+ ',',
37
+ // eslint-disable-next-line no-template-curly-in-string
38
+ 'body: (bundle)=>`<script type="module" src="/_vite/client/pages/${bundle}.ts"></script>`',
39
+ '}',
40
+ ].join('\n');
41
+ },
42
+ });
43
+ }
44
+ else {
45
+ flow.hook('modules:done', async() => {
46
+ const start = Date.now();
47
+ logger.info('Building client...');
48
+ await builClient(flow);
49
+
50
+ const file = resolve(flow.options.rootDir, '.vite/manifest.json');
51
+ const manifest = await fse.readFile(file, 'utf8');
52
+ logger.success(`Client build in ${Date.now() - start}ms`);
53
+
54
+ addTemplate({
55
+ filename: 'viteManifest.mjs',
56
+ async getContents() {
57
+ return ['export default ()=>(', manifest, ')',
58
+ ].join('\n');
59
+ },
60
+ });
61
+ // Manifest json
62
+ });
63
+ flow.hook('generate:before', async() => {
64
+ const files = resolve(flow.options.rootDir, '.vite/scripts');
65
+ await fse.copy(files, resolve(flow.options.generate.dir, 'assets'));
66
+ });
67
+ }
68
+ addPlugin({ src: resolve(runtimeDir, 'plugin') });
69
+ },
70
+ }) as FlowModule<OptionsViteClient>;