@monkeyplus/flow 5.0.0-rc.199 → 5.0.0-rc.2

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 (81) hide show
  1. package/build.config.ts +25 -0
  2. package/dist/app/entry.d.ts +2 -2
  3. package/dist/app/entry.mjs +2 -3
  4. package/dist/app/flow.d.ts +3 -12
  5. package/dist/app/flow.mjs +0 -3
  6. package/dist/core/runtime/nitro/flow.d.ts +0 -1
  7. package/dist/core/runtime/nitro/flow.mjs +14 -9
  8. package/dist/core/runtime/nitro/renderer.mjs +18 -82
  9. package/dist/head/runtime/plugin.mjs +1 -0
  10. package/dist/index.mjs +772 -543
  11. package/dist/pages/runtime/helpers/index.d.ts +1 -1
  12. package/dist/pages/runtime/helpers/index.mjs +3 -14
  13. package/dist/pages/runtime/index.d.ts +3 -10
  14. package/dist/pages/runtime/index.mjs +4 -12
  15. package/dist/pages/runtime/plugin.mjs +53 -0
  16. package/dist/vite-client/runtime/injectManifest.d.ts +26 -0
  17. package/dist/vite-client/runtime/injectManifest.mjs +104 -0
  18. package/dist/vite-client/runtime/plugin.d.ts +2 -0
  19. package/dist/vite-client/runtime/plugin.mjs +27 -0
  20. package/package.json +40 -55
  21. package/src/app/composables/index.ts +20 -0
  22. package/src/app/entry.ts +36 -0
  23. package/src/app/flow.ts +157 -0
  24. package/src/app/index.ts +5 -0
  25. package/src/auto-imports/module.ts +143 -0
  26. package/src/auto-imports/presets.ts +49 -0
  27. package/src/auto-imports/transform.ts +48 -0
  28. package/src/core/app.ts +90 -0
  29. package/src/core/builder.ts +60 -0
  30. package/src/core/flow.ts +93 -0
  31. package/src/core/modules.ts +32 -0
  32. package/src/core/nitro.ts +206 -0
  33. package/src/core/plugins/import-protection.ts +49 -0
  34. package/src/core/plugins/unctx.ts +31 -0
  35. package/src/core/runtime/nitro/flow.ts +43 -0
  36. package/src/core/runtime/nitro/paths.ts +20 -0
  37. package/src/core/runtime/nitro/renderer.ts +74 -0
  38. package/src/core/templates.ts +119 -0
  39. package/src/core/vite/builder/css.ts +28 -0
  40. package/src/core/vite/builder/dev-bundler.ts +248 -0
  41. package/src/core/vite/builder/index.ts +96 -0
  42. package/src/core/vite/builder/manifest.ts +33 -0
  43. package/src/core/vite/builder/plugins/analyze.ts +32 -0
  44. package/src/core/vite/builder/plugins/cache-dir.ts +13 -0
  45. package/src/core/vite/builder/plugins/dynamic-base.ts +64 -0
  46. package/src/core/vite/builder/plugins/virtual.ts +45 -0
  47. package/src/core/vite/builder/server.ts +164 -0
  48. package/src/core/vite/builder/types/index.ts +13 -0
  49. package/src/core/vite/builder/utils/index.ts +53 -0
  50. package/src/core/vite/builder/utils/warmup.ts +27 -0
  51. package/src/core/vite/builder/utils/wpfs.ts +7 -0
  52. package/src/core/vite/builder/vite-node.ts +110 -0
  53. package/src/core/vite/client/index.ts +63 -0
  54. package/src/dirs.ts +8 -0
  55. package/src/head/module.ts +37 -0
  56. package/src/head/runtime/composables.ts +16 -0
  57. package/src/head/runtime/index.ts +1 -0
  58. package/src/head/runtime/plugin.ts +12 -0
  59. package/src/index.ts +2 -0
  60. package/src/pages/module.ts +55 -0
  61. package/src/pages/runtime/helpers/chunks.ts +0 -0
  62. package/src/pages/runtime/helpers/index.ts +33 -0
  63. package/src/pages/runtime/index.ts +9 -0
  64. package/src/pages/runtime/plugin.ts +65 -0
  65. package/src/pages/templates.ts +20 -0
  66. package/src/pages/utils.ts +49 -0
  67. package/src/vite-client/module.ts +84 -0
  68. package/src/vite-client/runtime/injectManifest.ts +188 -0
  69. package/src/vite-client/runtime/plugin.ts +33 -0
  70. package/dist/app/entry.async.d.ts +0 -3
  71. package/dist/app/entry.async.mjs +0 -1
  72. package/dist/chunks/dev-bundler.mjs +0 -277
  73. package/dist/core/runtime/client.manifest.d.mts +0 -2
  74. package/dist/core/runtime/client.manifest.mjs +0 -6
  75. package/dist/core/runtime/vite-node-shared.d.mts +0 -1
  76. package/dist/core/runtime/vite-node-shared.d.ts +0 -8
  77. package/dist/core/runtime/vite-node-shared.mjs +0 -3
  78. package/dist/core/runtime/vite-node.d.mts +0 -2
  79. package/dist/core/runtime/vite-node.mjs +0 -41
  80. package/dist/pages/runtime/pages.mjs +0 -123
  81. /package/dist/pages/runtime/{pages.d.ts → plugin.d.ts} +0 -0
@@ -0,0 +1,164 @@
1
+ import { join, normalize, resolve } from 'pathe';
2
+ import * as vite from 'vite';
3
+ import fse from 'fs-extra';
4
+ import { withoutTrailingSlash } from 'ufo';
5
+ import { logger } from '@monkeyplus/flow-kit';
6
+ import { debounce } from 'perfect-debounce';
7
+ import { cacheDirPlugin } from './plugins/cache-dir';
8
+ import type { ViteBuildContext, ViteOptions } from './types';
9
+ import { wpfs } from './utils/wpfs';
10
+ import { bundleRequest } from './dev-bundler';
11
+ import { writeManifest } from './manifest';
12
+ import { isCSS, isDirectory, readDirRecursively } from './utils';
13
+
14
+ export const buildServer = async(ctx: ViteBuildContext) => {
15
+ // const _resolve = (id: string) => resolveModule(id, { paths: ctx.flow.options.modulesDir });
16
+
17
+ const serverConfig: vite.InlineConfig = vite.mergeConfig(ctx.config, {
18
+ configFile: false,
19
+ define: {
20
+ 'process.server': true,
21
+ 'typeof window': '"undefined"',
22
+ 'typeof document': '"undefined"',
23
+ 'typeof navigator': '"undefined"',
24
+ 'typeof location': '"undefined"',
25
+ 'typeof XMLHttpRequest': '"undefined"',
26
+ },
27
+ ssr: {
28
+ noExternal: [
29
+ ...ctx.flow.options.build.transpile,
30
+ // TODO: Use externality for production (rollup) build
31
+ /\/esm\/.*\.js$/,
32
+ /\.(es|esm|esm-browser|esm-bundler).js$/,
33
+ '/__vue-jsx',
34
+ '#app',
35
+ /(nuxt|nuxt3)\/(dist|src|app)/,
36
+ /@monkeyplus\/flow\/(dist|src|app)/,
37
+ /@nuxt\/nitro\/(dist|src)/,
38
+ ],
39
+ },
40
+ build: {
41
+ outDir: resolve(ctx.flow.options.buildDir, 'dist/server'),
42
+ manifest: true,
43
+ rollupOptions: {
44
+ external: ['#internal/nitro'],
45
+ output: {
46
+ entryFileNames: 'server.mjs',
47
+ preferConst: true,
48
+ format: 'module',
49
+ },
50
+ onwarn(warning, rollupWarn) {
51
+ if (!['UNUSED_EXTERNAL_IMPORT'].includes(warning.code))
52
+ rollupWarn(warning);
53
+ },
54
+ },
55
+ },
56
+ server: {
57
+ // https://github.com/vitest-dev/vitest/issues/229#issuecomment-1002685027
58
+ preTransformRequests: false,
59
+ cors: true,
60
+ },
61
+ plugins: [
62
+ cacheDirPlugin(ctx.flow.options.rootDir, 'server'),
63
+ ],
64
+ } as ViteOptions);
65
+
66
+ await ctx.flow.callHook('vite:extendConfig', serverConfig, { isClient: false, isServer: true });
67
+
68
+ ctx.flow.hook('nitro:build:before', async() => {
69
+ if (ctx.flow.options.dev)
70
+ return;
71
+
72
+ const clientDist = resolve(ctx.flow.options.buildDir, 'dist/client');
73
+
74
+ // Remove public files that have been duplicated into buildAssetsDir
75
+ // TODO: Add option to configure this behavior in vite
76
+ const publicDir = join(ctx.flow.options.srcDir, ctx.flow.options.dir.public);
77
+ let publicFiles: string[] = [];
78
+ if (await isDirectory(publicDir)) {
79
+ publicFiles = readDirRecursively(publicDir).map((r) => r.replace(publicDir, ''));
80
+ for (const file of publicFiles) {
81
+ try {
82
+ fse.rmSync(join(clientDist, file));
83
+ }
84
+ catch {}
85
+ }
86
+ }
87
+
88
+ // Copy doubly-nested /_nuxt/_nuxt files into buildAssetsDir
89
+ // TODO: Workaround vite issue
90
+ if (await isDirectory(clientDist)) {
91
+ const nestedAssetsPath = withoutTrailingSlash(join(clientDist, ctx.flow.options.app.buildAssetsDir));
92
+
93
+ if (await isDirectory(nestedAssetsPath)) {
94
+ await fse.copy(nestedAssetsPath, clientDist, { recursive: true });
95
+ await fse.remove(nestedAssetsPath);
96
+ }
97
+ }
98
+ });
99
+
100
+ const onBuild = () => ctx.flow.callHook('build:resources', wpfs);
101
+
102
+ // Production build
103
+ if (!ctx.flow.options.dev) {
104
+ const start = Date.now();
105
+ logger.info('Building server...');
106
+ await vite.build(serverConfig);
107
+ await onBuild();
108
+ logger.success(`Server built in ${Date.now() - start}ms`);
109
+ return;
110
+ }
111
+
112
+ // if (!ctx.flow.options.ssr) {
113
+ // await onBuild();
114
+ // return;
115
+ // }
116
+ // console.log(serverConfig.plugins);
117
+
118
+ // Start development server
119
+ const viteServer = await vite.createServer(serverConfig);
120
+ ctx.ssrServer = viteServer;
121
+
122
+ await ctx.flow.callHook('vite:serverCreated', viteServer, { isClient: false, isServer: true });
123
+
124
+ // Close server on exit
125
+ ctx.flow.hook('close', () => viteServer.close());
126
+
127
+ // Initialize plugins
128
+ await viteServer.pluginContainer.buildStart({});
129
+ // console.log(viteServer.1);
130
+
131
+ // if (ctx.flow.options.experimental.viteNode) {
132
+ // logger.info('Vite server using experimental `vite-node`...');
133
+ // await prepareDevServerEntry(ctx);
134
+ // }
135
+ // else {
136
+ // Build and watch
137
+ const _doBuild = async() => {
138
+ const start = Date.now();
139
+ const { code, ids } = await bundleRequest({ viteServer }, resolve(ctx.flow.options.appDir, 'entry'));
140
+ await fse.ensureFile(resolve(ctx.flow.options.buildDir, 'dist/server/server.mjs'));
141
+ await fse.writeFile(resolve(ctx.flow.options.buildDir, 'dist/server/server.mjs'), code, 'utf-8');
142
+ // Have CSS in the manifest to prevent FOUC on dev SSR
143
+ await writeManifest(ctx, ids.filter(isCSS).map((i) => i.slice(1)));
144
+ const time = (Date.now() - start);
145
+ logger.success(`Vite server built in ${time}ms`);
146
+ await onBuild();
147
+ ctx.flow.callHook('bundler:change', {} as any);
148
+ };
149
+ const doBuild = debounce(_doBuild);
150
+
151
+ // Initial build
152
+ await _doBuild();
153
+
154
+ // Watch
155
+ viteServer.watcher.on('all', (_event, file) => {
156
+ file = normalize(file); // Fix windows paths
157
+ if (file.indexOf(ctx.flow.options.buildDir) === 0) return;
158
+ doBuild();
159
+ });
160
+ ctx.flow.hook('app:templatesGenerated', () => doBuild());
161
+
162
+ // ctx.nuxt.hook('builder:watch', () => doBuild())
163
+ // }
164
+ };
@@ -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,63 @@
1
+ import { resolve } from 'pathe';
2
+ import type { Flow } from '@monkeyplus/flow-schema';
3
+ import type { ViteDevServer } from 'vite';
4
+ import { build, createServer } from 'vite';
5
+ import { debounce } from 'perfect-debounce';
6
+
7
+ export const createClient = async(flow: Flow) => {
8
+ let vite: ViteDevServer;
9
+ if (globalThis.viteClient) {
10
+ vite = globalThis.viteClient as ViteDevServer;
11
+ }
12
+ else {
13
+ vite = await createServer({
14
+ root: resolve(flow.options.rootDir),
15
+ base: '/_vite/',
16
+ build: {
17
+ manifest: true,
18
+ },
19
+ server: {
20
+ watch: {
21
+ ignored: ['**/.env/**', '**/.env*'],
22
+ },
23
+ middlewareMode: 'ssr',
24
+ //
25
+ },
26
+ });
27
+ globalThis.viteClient = vite;
28
+ }
29
+
30
+ const _doReload = () => {
31
+ if (vite)
32
+ vite?.ws?.send({ type: 'full-reload' });
33
+ };
34
+
35
+ const doReload = debounce(_doReload, 60);
36
+
37
+ // Use this to refresh page
38
+ flow.hook('bundler:change', () => {
39
+ doReload();
40
+ });
41
+
42
+ flow.hook('close', async() => {
43
+ vite.restart();
44
+ // await vite.close();
45
+ });
46
+
47
+ return vite;
48
+ };
49
+
50
+ export const builClient = async(flow: Flow) => {
51
+ return await build({
52
+ root: flow.options.rootDir,
53
+ mode: 'production',
54
+ build: {
55
+ assetsDir: 'scripts',
56
+ target: 'es2017',
57
+ outDir: '.vite',
58
+ manifest: true,
59
+ },
60
+ });
61
+ };
62
+
63
+ // 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: page.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,9 @@
1
+ import type { DynamicPage, SimplePage } from '@monkeyplus/flow-schema';
2
+
3
+ export function definePage(page: SimplePage) {
4
+ return page;
5
+ }
6
+
7
+ export function defineDinamycPage(page: DynamicPage) {
8
+ return page;
9
+ }