@monkeyplus/flow 5.0.0-rc.99 → 6.0.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/README.md +34 -0
- package/entry-server.d.ts +1 -0
- package/entry-server.mjs +5 -0
- package/modules/content/module.d.ts +6 -0
- package/modules/content/module.mjs +32 -0
- package/modules/content/query.mjs +104 -0
- package/modules/sitemap/handler.mjs +17 -0
- package/modules/sitemap/module.d.ts +6 -0
- package/modules/sitemap/module.mjs +28 -0
- package/modules/strapi/README.md +235 -0
- package/modules/strapi/module.d.ts +11 -0
- package/modules/strapi/module.mjs +69 -0
- package/modules/strapi/proxy.mjs +54 -0
- package/modules/strapi/runtime/client.d.ts +30 -0
- package/modules/strapi/runtime/client.mjs +248 -0
- package/package.json +73 -77
- package/server/lib/handler.d.ts +1 -0
- package/server/lib/handler.mjs +43 -0
- package/server/lib/pages.d.ts +20 -0
- package/server/lib/pages.mjs +276 -0
- package/server/lib/render.d.ts +7 -0
- package/server/lib/render.mjs +156 -0
- package/server/plugins/00.lifecycle.d.ts +2 -0
- package/server/plugins/00.lifecycle.mjs +9 -0
- package/server/renderer.d.ts +3 -0
- package/server/renderer.mjs +14 -0
- package/server/routes/api/health.get.d.ts +2 -0
- package/server/routes/api/health.get.mjs +5 -0
- package/server.d.ts +1 -0
- package/server.mjs +32 -0
- package/src/main.d.ts +1 -0
- package/src/main.mjs +29 -0
- package/src/public/boot.d.ts +1 -0
- package/src/public/components.d.ts +1 -0
- package/src/public/components.mjs +1 -0
- package/src/public/head.d.ts +1 -0
- package/src/public/head.mjs +1 -0
- package/src/public/index.d.ts +5 -0
- package/src/public/index.mjs +2 -0
- package/src/public/modules/content.d.ts +2 -0
- package/src/public/modules/content.mjs +1 -0
- package/src/public/modules/sitemap.d.ts +2 -0
- package/src/public/modules/sitemap.mjs +1 -0
- package/src/public/modules/strapi.d.ts +2 -0
- package/src/public/modules/strapi.mjs +1 -0
- package/src/public/nitro.d.ts +6 -0
- package/src/public/nitro.mjs +78 -0
- package/src/public/shared.d.ts +2 -0
- package/src/public/shared.mjs +18 -0
- package/src/public/vite.d.ts +6 -0
- package/src/public/vite.mjs +273 -0
- package/src/public/vue.d.ts +1 -0
- package/src/public/vue.mjs +1 -0
- package/src/runtime/boot.d.ts +9 -0
- package/src/runtime/components/FlowIsland.d.ts +42 -0
- package/src/runtime/components/FlowIsland.mjs +35 -0
- package/src/runtime/config.d.ts +73 -0
- package/src/runtime/config.mjs +26 -0
- package/src/runtime/head.d.ts +3 -0
- package/src/runtime/head.mjs +7 -0
- package/src/runtime/islands.d.ts +2 -0
- package/src/runtime/islands.mjs +52 -0
- package/src/runtime/modules.d.ts +12 -0
- package/src/runtime/modules.mjs +115 -0
- package/src/runtime/page-discovery.d.ts +6 -0
- package/src/runtime/page-discovery.mjs +175 -0
- package/src/runtime/pages.d.ts +107 -0
- package/src/runtime/pages.mjs +3 -0
- package/src/runtime/ssg.d.ts +9 -0
- package/src/runtime/ssg.mjs +37 -0
- package/src/runtime/virtual-pages.d.ts +8 -0
- package/src/runtime/virtual-pages.mjs +151 -0
- package/src/runtime/virtual.d.ts +103 -0
- package/src/runtime/vite-assets.d.ts +9 -0
- package/src/runtime/vue.d.ts +6 -0
- package/src/runtime/vue.mjs +6 -0
- package/src/styles.css +1 -0
- package/app.d.ts +0 -1
- package/bin/flow.mjs +0 -2
- package/dist/app/composables/index.d.ts +0 -5
- package/dist/app/composables/index.mjs +0 -12
- package/dist/app/entry.async.d.ts +0 -3
- package/dist/app/entry.async.mjs +0 -1
- package/dist/app/entry.d.ts +0 -3
- package/dist/app/entry.mjs +0 -23
- package/dist/app/flow.d.ts +0 -80
- package/dist/app/flow.mjs +0 -88
- package/dist/app/index.d.ts +0 -3
- package/dist/app/index.mjs +0 -3
- package/dist/chunks/dev-bundler.mjs +0 -247
- package/dist/chunks/external.mjs +0 -37
- package/dist/chunks/index.mjs +0 -1140
- package/dist/chunks/vite-node.mjs +0 -155
- package/dist/core/runtime/client.manifest.d.mts +0 -2
- package/dist/core/runtime/client.manifest.mjs +0 -6
- package/dist/core/runtime/nitro/flow.d.ts +0 -3
- package/dist/core/runtime/nitro/flow.mjs +0 -33
- package/dist/core/runtime/nitro/paths.d.ts +0 -4
- package/dist/core/runtime/nitro/paths.mjs +0 -15
- package/dist/core/runtime/nitro/renderer.d.ts +0 -2
- package/dist/core/runtime/nitro/renderer.mjs +0 -101
- package/dist/core/runtime/vite-node-shared.d.mts +0 -1
- package/dist/core/runtime/vite-node-shared.d.ts +0 -8
- package/dist/core/runtime/vite-node-shared.mjs +0 -3
- package/dist/core/runtime/vite-node.d.mts +0 -2
- package/dist/core/runtime/vite-node.mjs +0 -42
- package/dist/head/runtime/composables.d.ts +0 -9
- package/dist/head/runtime/composables.mjs +0 -2
- package/dist/head/runtime/index.d.ts +0 -1
- package/dist/head/runtime/index.mjs +0 -1
- package/dist/head/runtime/plugin.mjs +0 -5
- package/dist/index.d.ts +0 -11
- package/dist/index.mjs +0 -27
- package/dist/pages/runtime/helpers/index.d.ts +0 -5
- package/dist/pages/runtime/helpers/index.mjs +0 -31
- package/dist/pages/runtime/index.d.ts +0 -10
- package/dist/pages/runtime/index.mjs +0 -13
- package/dist/pages/runtime/pages.mjs +0 -100
- package/dist/vite-client/runtime/injectManifest.d.ts +0 -26
- package/dist/vite-client/runtime/injectManifest.mjs +0 -110
- package/dist/vite-client/runtime/plugin.mjs +0 -28
- package/types.d.ts +0 -2
- /package/{dist/head/runtime/plugin.d.ts → modules/content/query.d.ts} +0 -0
- /package/{dist/pages/runtime/pages.d.ts → modules/sitemap/handler.d.ts} +0 -0
- /package/{dist/vite-client/runtime/plugin.d.ts → modules/strapi/proxy.d.ts} +0 -0
- /package/{dist/pages/runtime/helpers/chunks.d.ts → src/public/boot.mjs} +0 -0
- /package/{dist/pages/runtime/helpers/chunks.mjs → src/runtime/boot.mjs} +0 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { dirname, resolve } from "node:path";
|
|
2
|
+
import { createJiti } from "jiti";
|
|
3
|
+
function createNitroConfig() {
|
|
4
|
+
return {
|
|
5
|
+
plugins: [],
|
|
6
|
+
handlers: [],
|
|
7
|
+
routeRules: {},
|
|
8
|
+
runtimeConfig: {},
|
|
9
|
+
virtual: {}
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
function createViteConfig() {
|
|
13
|
+
return {
|
|
14
|
+
plugins: [],
|
|
15
|
+
resolve: {
|
|
16
|
+
alias: {}
|
|
17
|
+
},
|
|
18
|
+
server: {
|
|
19
|
+
watch: {
|
|
20
|
+
additionalPaths: []
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function normalizeModuleInput(entry) {
|
|
26
|
+
if (Array.isArray(entry)) {
|
|
27
|
+
return {
|
|
28
|
+
module: entry[0],
|
|
29
|
+
options: entry[1] || {}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
if (typeof entry === "string") {
|
|
33
|
+
return {
|
|
34
|
+
module: entry,
|
|
35
|
+
options: {}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
if ("module" in entry) {
|
|
39
|
+
return {
|
|
40
|
+
module: entry.module,
|
|
41
|
+
options: entry.options || {}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
module: entry,
|
|
46
|
+
options: {}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function resolveModuleSpecifier(specifier, projectRoot) {
|
|
50
|
+
if (specifier.startsWith("~/")) {
|
|
51
|
+
return resolve(projectRoot, specifier.slice(2));
|
|
52
|
+
}
|
|
53
|
+
if (specifier.startsWith("./") || specifier.startsWith("../") || specifier.startsWith("/")) {
|
|
54
|
+
return resolve(projectRoot, specifier);
|
|
55
|
+
}
|
|
56
|
+
return specifier;
|
|
57
|
+
}
|
|
58
|
+
function loadModuleDefinition(source, projectRoot, jiti = createJiti(resolve(projectRoot, "flow.config.ts"), { fsCache: false })) {
|
|
59
|
+
if (typeof source !== "string") {
|
|
60
|
+
return {
|
|
61
|
+
definition: source,
|
|
62
|
+
moduleRoot: projectRoot
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
const resolvedSource = resolveModuleSpecifier(source, projectRoot);
|
|
66
|
+
const loaded = jiti(resolvedSource);
|
|
67
|
+
const definition = loaded?.default ?? loaded;
|
|
68
|
+
const modulePath = typeof resolvedSource === "string" ? jiti.resolve(resolvedSource) : resolvedSource;
|
|
69
|
+
return {
|
|
70
|
+
definition,
|
|
71
|
+
moduleRoot: dirname(modulePath)
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function resolveModuleOptions(definition, flowConfig, inlineOptions) {
|
|
75
|
+
const configKey = definition.meta?.configKey;
|
|
76
|
+
const keyedOptions = configKey && typeof flowConfig[configKey] === "object" ? flowConfig[configKey] : {};
|
|
77
|
+
return {
|
|
78
|
+
...definition.defaults || {},
|
|
79
|
+
...keyedOptions,
|
|
80
|
+
...inlineOptions
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
export function loadFlowModules(projectRoot, flowConfig) {
|
|
84
|
+
const nitro = createNitroConfig();
|
|
85
|
+
const vite = createViteConfig();
|
|
86
|
+
const prerenderRoutes = /* @__PURE__ */ new Set();
|
|
87
|
+
const loadedModules = [];
|
|
88
|
+
const jiti = createJiti(resolve(projectRoot, "flow.config.ts"), { fsCache: false, moduleCache: false });
|
|
89
|
+
for (const entry of flowConfig.modules) {
|
|
90
|
+
const normalized = normalizeModuleInput(entry);
|
|
91
|
+
const { definition } = loadModuleDefinition(normalized.module, projectRoot, jiti);
|
|
92
|
+
if (!definition || typeof definition !== "object") {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const options = resolveModuleOptions(definition, flowConfig, normalized.options);
|
|
96
|
+
const context = {
|
|
97
|
+
projectRoot,
|
|
98
|
+
flowConfig,
|
|
99
|
+
nitro,
|
|
100
|
+
vite,
|
|
101
|
+
prerenderRoutes
|
|
102
|
+
};
|
|
103
|
+
definition.setup?.(options, context);
|
|
104
|
+
loadedModules.push({
|
|
105
|
+
name: definition.meta?.name || "anonymous",
|
|
106
|
+
options
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
modules: loadedModules,
|
|
111
|
+
nitro,
|
|
112
|
+
vite,
|
|
113
|
+
prerenderRoutes: [...prerenderRoutes]
|
|
114
|
+
};
|
|
115
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { FlowConfig } from './config';
|
|
2
|
+
import type { GetUrlOptions, PageDefinition, PageUrlInfo } from './pages';
|
|
3
|
+
export declare function loadPageDefinitions(projectRoot: string, flowConfig: FlowConfig): Promise<PageDefinition[]>;
|
|
4
|
+
export declare function getUrlFromDefinitions(definitions: PageDefinition[], flowConfig: FlowConfig, namePage: string, localeCode?: string, options?: GetUrlOptions): Promise<string | undefined>;
|
|
5
|
+
export declare function getUrlsFromDefinitions(definitions: PageDefinition[], flowConfig: FlowConfig, withLocale?: boolean, omitNoPublish?: boolean): Promise<(string | PageUrlInfo)[]>;
|
|
6
|
+
export declare function getPrerenderRoutes(projectRoot: string, flowConfig: FlowConfig): Promise<string[]>;
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { existsSync, readdirSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { createJiti } from "jiti";
|
|
4
|
+
const jiti = createJiti(import.meta.url, {
|
|
5
|
+
fsCache: false,
|
|
6
|
+
moduleCache: false
|
|
7
|
+
});
|
|
8
|
+
const dynamicRouteCache = /* @__PURE__ */ new Map();
|
|
9
|
+
function collectFiles(rootDir, currentDir = rootDir) {
|
|
10
|
+
const entries = readdirSync(currentDir, { withFileTypes: true });
|
|
11
|
+
const files = [];
|
|
12
|
+
for (const entry of entries) {
|
|
13
|
+
const fullPath = resolve(currentDir, entry.name);
|
|
14
|
+
if (entry.isDirectory()) {
|
|
15
|
+
files.push(...collectFiles(rootDir, fullPath));
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
if (!entry.isFile()) {
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
if (!entry.name.endsWith(".ts") || entry.name.endsWith(".d.ts")) {
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
files.push(fullPath);
|
|
25
|
+
}
|
|
26
|
+
return files.sort((left, right) => left.localeCompare(right));
|
|
27
|
+
}
|
|
28
|
+
function normalizePath(value) {
|
|
29
|
+
if (!value || value === "/") {
|
|
30
|
+
return "/";
|
|
31
|
+
}
|
|
32
|
+
return value.length > 1 && value.endsWith("/") ? value.slice(0, -1) : value;
|
|
33
|
+
}
|
|
34
|
+
function createLocale(flowConfig, code) {
|
|
35
|
+
const [lang = flowConfig.locale.language || "es", loc = flowConfig.locale.location || "ec"] = code.split("-");
|
|
36
|
+
return {
|
|
37
|
+
code,
|
|
38
|
+
lang,
|
|
39
|
+
loc
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function replacePath(pattern, url) {
|
|
43
|
+
let resolved = pattern;
|
|
44
|
+
if (typeof url === "string") {
|
|
45
|
+
return normalizePath(resolved.replace("/**", `/${url}`));
|
|
46
|
+
}
|
|
47
|
+
for (const [key, value] of Object.entries(url)) {
|
|
48
|
+
if (key === "_") {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
resolved = resolved.replace(`:${key}`, value);
|
|
52
|
+
}
|
|
53
|
+
if (url._ && resolved.endsWith("/**")) {
|
|
54
|
+
resolved = resolved.replace("/**", `/${url._}`);
|
|
55
|
+
}
|
|
56
|
+
return normalizePath(resolved.replaceAll("**", ""));
|
|
57
|
+
}
|
|
58
|
+
function toPublicRoutePattern(url) {
|
|
59
|
+
return normalizePath(url.replaceAll("*", ""));
|
|
60
|
+
}
|
|
61
|
+
function combineName(name, dynamicName) {
|
|
62
|
+
return `${name.replace(/\/*$/, "")}/${dynamicName.replace(/^\/*/, "")}`;
|
|
63
|
+
}
|
|
64
|
+
function createContext(definitions, flowConfig, definition, locale, localePage, pathname, params, dynamic) {
|
|
65
|
+
return {
|
|
66
|
+
dynamic,
|
|
67
|
+
locale,
|
|
68
|
+
path: pathname,
|
|
69
|
+
name: definition.name,
|
|
70
|
+
page: localePage,
|
|
71
|
+
params,
|
|
72
|
+
view: definition.view,
|
|
73
|
+
utils: {
|
|
74
|
+
getLocale() {
|
|
75
|
+
return locale;
|
|
76
|
+
},
|
|
77
|
+
async getUrl(namePage, localeCode, options) {
|
|
78
|
+
return await getUrlFromDefinitions(definitions, flowConfig, namePage, localeCode, options);
|
|
79
|
+
},
|
|
80
|
+
async getUrls(withLocale, omitNoPublish) {
|
|
81
|
+
return await getUrlsFromDefinitions(definitions, flowConfig, withLocale, omitNoPublish);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
async function getDynamicEntries(definitions, flowConfig, definition, localeCode, localePage) {
|
|
87
|
+
if (!localePage.dynamic) {
|
|
88
|
+
return [];
|
|
89
|
+
}
|
|
90
|
+
const cacheKey = `${definition.name}:${localeCode}:${localePage.url}`;
|
|
91
|
+
if (localePage.dynamic.options?.once) {
|
|
92
|
+
const cached = dynamicRouteCache.get(cacheKey);
|
|
93
|
+
if (cached) {
|
|
94
|
+
return await cached;
|
|
95
|
+
}
|
|
96
|
+
const locale2 = createLocale(flowConfig, localeCode);
|
|
97
|
+
const ctx2 = createContext(definitions, flowConfig, definition, locale2, localePage, localePage.url, {});
|
|
98
|
+
const pending = Promise.resolve(localePage.dynamic.method(ctx2));
|
|
99
|
+
dynamicRouteCache.set(cacheKey, pending);
|
|
100
|
+
return await pending;
|
|
101
|
+
}
|
|
102
|
+
const locale = createLocale(flowConfig, localeCode);
|
|
103
|
+
const ctx = createContext(definitions, flowConfig, definition, locale, localePage, localePage.url, {});
|
|
104
|
+
return await localePage.dynamic.method(ctx);
|
|
105
|
+
}
|
|
106
|
+
export async function loadPageDefinitions(projectRoot, flowConfig) {
|
|
107
|
+
const pageDirs = flowConfig.dir.pages.map((entry) => resolve(projectRoot, entry.dir)).filter((dirPath) => existsSync(dirPath));
|
|
108
|
+
const files = pageDirs.flatMap((pagesDir) => collectFiles(pagesDir));
|
|
109
|
+
const pages = [];
|
|
110
|
+
for (const filePath of files) {
|
|
111
|
+
const loaded = await jiti.import(filePath, { default: true });
|
|
112
|
+
const definitions = Array.isArray(loaded) ? loaded : [loaded];
|
|
113
|
+
for (const definition of definitions) {
|
|
114
|
+
if (definition) {
|
|
115
|
+
pages.push(definition);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return pages;
|
|
120
|
+
}
|
|
121
|
+
export async function getUrlFromDefinitions(definitions, flowConfig, namePage, localeCode = flowConfig.locale.locales[0], options = {}) {
|
|
122
|
+
const definition = definitions.find((candidate) => candidate.name === namePage);
|
|
123
|
+
if (!definition) {
|
|
124
|
+
return void 0;
|
|
125
|
+
}
|
|
126
|
+
const localePage = definition.locales[localeCode];
|
|
127
|
+
if (!localePage) {
|
|
128
|
+
return void 0;
|
|
129
|
+
}
|
|
130
|
+
if (options.url) {
|
|
131
|
+
return replacePath(localePage.url, options.url);
|
|
132
|
+
}
|
|
133
|
+
if (options.params) {
|
|
134
|
+
return replacePath(localePage.url, options.params);
|
|
135
|
+
}
|
|
136
|
+
if (localePage.dynamic && options.dynamicName) {
|
|
137
|
+
const entries = await getDynamicEntries(definitions, flowConfig, definition, localeCode, localePage);
|
|
138
|
+
const entry = entries.find((candidate) => candidate.name === options.dynamicName);
|
|
139
|
+
if (!entry) {
|
|
140
|
+
return void 0;
|
|
141
|
+
}
|
|
142
|
+
return replacePath(localePage.url, entry.url);
|
|
143
|
+
}
|
|
144
|
+
return toPublicRoutePattern(localePage.url);
|
|
145
|
+
}
|
|
146
|
+
export async function getUrlsFromDefinitions(definitions, flowConfig, withLocale = false, omitNoPublish = false) {
|
|
147
|
+
const urls = [];
|
|
148
|
+
for (const definition of definitions) {
|
|
149
|
+
if (omitNoPublish && definition.noPublish) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
for (const localeCode of flowConfig.locale.locales) {
|
|
153
|
+
const localePage = definition.locales[localeCode];
|
|
154
|
+
if (!localePage) {
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
if (localePage.dynamic) {
|
|
158
|
+
const entries = await getDynamicEntries(definitions, flowConfig, definition, localeCode, localePage);
|
|
159
|
+
for (const entry of entries) {
|
|
160
|
+
const url2 = replacePath(localePage.url, entry.url);
|
|
161
|
+
urls.push(withLocale ? { url: url2, locale: localeCode, name: combineName(definition.name, entry.name) } : url2);
|
|
162
|
+
}
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
const url = toPublicRoutePattern(localePage.url);
|
|
166
|
+
urls.push(withLocale ? { url, locale: localeCode, name: definition.name } : url);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return urls;
|
|
170
|
+
}
|
|
171
|
+
export async function getPrerenderRoutes(projectRoot, flowConfig) {
|
|
172
|
+
const definitions = await loadPageDefinitions(projectRoot, flowConfig);
|
|
173
|
+
const routes = await getUrlsFromDefinitions(definitions, flowConfig, false, true);
|
|
174
|
+
return routes.filter((route) => typeof route === "string").filter((route) => !route.includes(":") && !route.includes("*"));
|
|
175
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { UseHeadInput } from '@unhead/vue';
|
|
2
|
+
export type MaybePromise<T> = T | Promise<T>;
|
|
3
|
+
export interface FlowLocale {
|
|
4
|
+
code: string;
|
|
5
|
+
lang: string;
|
|
6
|
+
loc: string;
|
|
7
|
+
}
|
|
8
|
+
export interface LegacySeoDefinition {
|
|
9
|
+
title?: string;
|
|
10
|
+
/**
|
|
11
|
+
* @deprecated
|
|
12
|
+
*/
|
|
13
|
+
description?: string;
|
|
14
|
+
/**
|
|
15
|
+
* @deprecated
|
|
16
|
+
*/
|
|
17
|
+
keywords?: string;
|
|
18
|
+
/**
|
|
19
|
+
* @deprecated
|
|
20
|
+
*/
|
|
21
|
+
imageSocial?: string;
|
|
22
|
+
/**
|
|
23
|
+
* @deprecated
|
|
24
|
+
*/
|
|
25
|
+
twitterSite?: string;
|
|
26
|
+
/**
|
|
27
|
+
* @deprecated
|
|
28
|
+
*/
|
|
29
|
+
google?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* @deprecated
|
|
32
|
+
*/
|
|
33
|
+
twitter?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* @deprecated
|
|
36
|
+
*/
|
|
37
|
+
facebook?: boolean;
|
|
38
|
+
}
|
|
39
|
+
export type HeadDefinition = UseHeadInput & LegacySeoDefinition;
|
|
40
|
+
/**
|
|
41
|
+
* @deprecated Use HeadDefinition.
|
|
42
|
+
*/
|
|
43
|
+
export type SeoDefinition = HeadDefinition;
|
|
44
|
+
export type FlowHydrationMode = 'islands' | 'app';
|
|
45
|
+
export type DynamicRouteUrl = string | Record<string, string>;
|
|
46
|
+
export interface DynamicRouteEntry<TContext = Record<string, unknown>> {
|
|
47
|
+
url: DynamicRouteUrl;
|
|
48
|
+
name: string;
|
|
49
|
+
context?: TContext;
|
|
50
|
+
slug?: string;
|
|
51
|
+
}
|
|
52
|
+
export interface DynamicRouteOptions {
|
|
53
|
+
assign?: string;
|
|
54
|
+
method: (ctx: Omit<PageContextInput, 'dynamic'>) => MaybePromise<DynamicRouteEntry[]>;
|
|
55
|
+
options?: {
|
|
56
|
+
once?: boolean;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
export interface GetUrlOptions {
|
|
60
|
+
params?: Record<string, string>;
|
|
61
|
+
dynamicName?: string;
|
|
62
|
+
url?: DynamicRouteUrl;
|
|
63
|
+
}
|
|
64
|
+
export interface PageUrlInfo {
|
|
65
|
+
url: string;
|
|
66
|
+
locale: string;
|
|
67
|
+
name: string;
|
|
68
|
+
}
|
|
69
|
+
export interface PageViewDefinition {
|
|
70
|
+
bundle?: string;
|
|
71
|
+
template: string;
|
|
72
|
+
layout?: string;
|
|
73
|
+
base?: string;
|
|
74
|
+
mode?: FlowHydrationMode;
|
|
75
|
+
}
|
|
76
|
+
export interface PageContextUtils {
|
|
77
|
+
getLocale: () => FlowLocale;
|
|
78
|
+
getUrl: (namePage: string, localeCode?: string, options?: GetUrlOptions) => Promise<string | undefined>;
|
|
79
|
+
getUrls: (withLocale?: boolean, omitNoPublish?: boolean) => Promise<Array<string | PageUrlInfo>>;
|
|
80
|
+
}
|
|
81
|
+
export interface PageContextInput {
|
|
82
|
+
locale: FlowLocale;
|
|
83
|
+
path: string;
|
|
84
|
+
name: string;
|
|
85
|
+
view: PageViewDefinition;
|
|
86
|
+
page: PageLocaleDefinition;
|
|
87
|
+
params: Record<string, string>;
|
|
88
|
+
dynamic?: DynamicRouteEntry;
|
|
89
|
+
utils: PageContextUtils;
|
|
90
|
+
}
|
|
91
|
+
export interface PageLocaleDefinition {
|
|
92
|
+
url: string;
|
|
93
|
+
head?: (ctx: PageContextInput) => MaybePromise<HeadDefinition>;
|
|
94
|
+
/**
|
|
95
|
+
* @deprecated Use head.
|
|
96
|
+
*/
|
|
97
|
+
seo?: (ctx: PageContextInput) => MaybePromise<HeadDefinition>;
|
|
98
|
+
context?: (ctx: PageContextInput) => MaybePromise<Record<string, unknown>>;
|
|
99
|
+
dynamic?: DynamicRouteOptions;
|
|
100
|
+
}
|
|
101
|
+
export interface PageDefinition {
|
|
102
|
+
name: string;
|
|
103
|
+
view: PageViewDefinition;
|
|
104
|
+
locales: Record<string, PageLocaleDefinition>;
|
|
105
|
+
noPublish?: boolean;
|
|
106
|
+
}
|
|
107
|
+
export declare function definePage(...pages: PageDefinition[]): PageDefinition[];
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { FlowConfig } from './config.ts';
|
|
2
|
+
interface FlowBuildHooksOptions {
|
|
3
|
+
projectRoot: string;
|
|
4
|
+
flowConfig: FlowConfig;
|
|
5
|
+
modulePrerenderRoutes: string[];
|
|
6
|
+
existingHooks?: Record<string, unknown>;
|
|
7
|
+
}
|
|
8
|
+
export declare function createFlowBuildHooks(options: FlowBuildHooksOptions): Record<string, unknown>;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { extname } from "node:path";
|
|
2
|
+
import { getPrerenderRoutes } from "./page-discovery.mjs";
|
|
3
|
+
function isHtmlRoute(route) {
|
|
4
|
+
return extname(route) === "";
|
|
5
|
+
}
|
|
6
|
+
async function resolveFlowPrerenderRoutes(options) {
|
|
7
|
+
const discoveredRoutes = await getPrerenderRoutes(options.projectRoot, options.flowConfig);
|
|
8
|
+
return [.../* @__PURE__ */ new Set([
|
|
9
|
+
...discoveredRoutes,
|
|
10
|
+
...options.modulePrerenderRoutes
|
|
11
|
+
])];
|
|
12
|
+
}
|
|
13
|
+
export function createFlowBuildHooks(options) {
|
|
14
|
+
const hooks = {
|
|
15
|
+
...options.existingHooks || {}
|
|
16
|
+
};
|
|
17
|
+
if (options.flowConfig.build.preset !== "ssg") {
|
|
18
|
+
return hooks;
|
|
19
|
+
}
|
|
20
|
+
const userPrerenderRoutes = typeof hooks["prerender:routes"] === "function" ? hooks["prerender:routes"] : void 0;
|
|
21
|
+
const userPrerenderGenerate = typeof hooks["prerender:generate"] === "function" ? hooks["prerender:generate"] : void 0;
|
|
22
|
+
let prerenderRoutesPromise;
|
|
23
|
+
hooks["prerender:routes"] = async (routes) => {
|
|
24
|
+
prerenderRoutesPromise ||= resolveFlowPrerenderRoutes(options);
|
|
25
|
+
for (const route of await prerenderRoutesPromise) {
|
|
26
|
+
routes.add(route);
|
|
27
|
+
}
|
|
28
|
+
await userPrerenderRoutes?.(routes);
|
|
29
|
+
};
|
|
30
|
+
hooks["prerender:generate"] = async (route) => {
|
|
31
|
+
await userPrerenderGenerate?.(route);
|
|
32
|
+
if (route.route && isHtmlRoute(route.route)) {
|
|
33
|
+
route.contentType = "text/html; charset=utf-8";
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
return hooks;
|
|
37
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FlowConfig } from './config';
|
|
2
|
+
export declare function createVirtualPagesModule(projectRoot: string, flowConfig: FlowConfig): string;
|
|
3
|
+
export declare function createVirtualTemplatesModule(projectRoot: string): string;
|
|
4
|
+
export declare function createVirtualLayoutsModule(projectRoot: string): string;
|
|
5
|
+
export declare function createVirtualBaseTemplatesModule(projectRoot: string): string;
|
|
6
|
+
export declare function createVirtualIslandsModule(projectRoot: string): string;
|
|
7
|
+
export declare function createVirtualClientPagesModule(projectRoot: string): string;
|
|
8
|
+
export declare function createVirtualClientPageAssetsModule(projectRoot: string): string;
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
2
|
+
import { basename, extname, resolve } from "node:path";
|
|
3
|
+
function collectFiles(rootDir, extensions, currentDir = rootDir) {
|
|
4
|
+
const entries = readdirSync(currentDir, { withFileTypes: true });
|
|
5
|
+
const files = [];
|
|
6
|
+
for (const entry of entries) {
|
|
7
|
+
const fullPath = resolve(currentDir, entry.name);
|
|
8
|
+
if (entry.isDirectory()) {
|
|
9
|
+
files.push(...collectFiles(rootDir, extensions, fullPath));
|
|
10
|
+
continue;
|
|
11
|
+
}
|
|
12
|
+
if (!entry.isFile()) {
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
if (!extensions.some((extension) => entry.name.endsWith(extension))) {
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
if (entry.name.endsWith(".d.ts")) {
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
files.push(fullPath);
|
|
22
|
+
}
|
|
23
|
+
return files.sort((left, right) => left.localeCompare(right));
|
|
24
|
+
}
|
|
25
|
+
function toAbsoluteImport(filePath) {
|
|
26
|
+
return filePath.split("\\").join("/");
|
|
27
|
+
}
|
|
28
|
+
function createVirtualClientPageModuleSource(projectRoot, mapper) {
|
|
29
|
+
const clientPagesDir = resolve(projectRoot, "client/pages");
|
|
30
|
+
const files = existsSync(clientPagesDir) ? collectFiles(clientPagesDir, [".ts"]) : [];
|
|
31
|
+
const entries = files.map((filePath) => {
|
|
32
|
+
const key = basename(filePath, extname(filePath));
|
|
33
|
+
return `${JSON.stringify(key)}: ${mapper(filePath)}`;
|
|
34
|
+
});
|
|
35
|
+
return [
|
|
36
|
+
"const bundles = {",
|
|
37
|
+
...entries.map((entry) => ` ${entry},`),
|
|
38
|
+
"};",
|
|
39
|
+
"",
|
|
40
|
+
"export default bundles;",
|
|
41
|
+
""
|
|
42
|
+
].join("\n");
|
|
43
|
+
}
|
|
44
|
+
export function createVirtualPagesModule(projectRoot, flowConfig) {
|
|
45
|
+
const pageDirs = flowConfig.dir.pages.map((entry) => resolve(projectRoot, entry.dir)).filter((dirPath) => existsSync(dirPath));
|
|
46
|
+
const files = pageDirs.flatMap((pagesDir) => collectFiles(pagesDir, [".ts"]));
|
|
47
|
+
const imports = files.map((filePath, index) => {
|
|
48
|
+
return `import page_${index} from ${JSON.stringify(toAbsoluteImport(filePath))};`;
|
|
49
|
+
});
|
|
50
|
+
const values = files.map((_, index) => {
|
|
51
|
+
return `...(Array.isArray(page_${index}) ? page_${index} : [page_${index}])`;
|
|
52
|
+
});
|
|
53
|
+
const source = [
|
|
54
|
+
...imports,
|
|
55
|
+
"",
|
|
56
|
+
`const pages = [${values.join(", ")}];`,
|
|
57
|
+
"",
|
|
58
|
+
"export default pages;",
|
|
59
|
+
""
|
|
60
|
+
].join("\n");
|
|
61
|
+
return source;
|
|
62
|
+
}
|
|
63
|
+
function createVirtualVueModuleSource(files, variableName) {
|
|
64
|
+
const imports = files.map((filePath, index) => {
|
|
65
|
+
return `import item_${index} from ${JSON.stringify(toAbsoluteImport(filePath))};`;
|
|
66
|
+
});
|
|
67
|
+
const entries = files.map((filePath, index) => {
|
|
68
|
+
const key = basename(filePath, extname(filePath)).toLowerCase();
|
|
69
|
+
return `${JSON.stringify(key)}: item_${index}`;
|
|
70
|
+
});
|
|
71
|
+
return [
|
|
72
|
+
...imports,
|
|
73
|
+
"",
|
|
74
|
+
`const ${variableName} = {`,
|
|
75
|
+
...entries.map((entry) => ` ${entry},`),
|
|
76
|
+
"};",
|
|
77
|
+
"",
|
|
78
|
+
`export default ${variableName};`,
|
|
79
|
+
""
|
|
80
|
+
].join("\n");
|
|
81
|
+
}
|
|
82
|
+
export function createVirtualTemplatesModule(projectRoot) {
|
|
83
|
+
const templatesDir = resolve(projectRoot, "views/templates");
|
|
84
|
+
const files = existsSync(templatesDir) ? collectFiles(templatesDir, [".vue"]) : [];
|
|
85
|
+
return createVirtualVueModuleSource(files, "templates");
|
|
86
|
+
}
|
|
87
|
+
export function createVirtualLayoutsModule(projectRoot) {
|
|
88
|
+
const layoutsDir = resolve(projectRoot, "views/layouts");
|
|
89
|
+
const files = existsSync(layoutsDir) ? collectFiles(layoutsDir, [".vue"]) : [];
|
|
90
|
+
return createVirtualVueModuleSource(files, "layouts");
|
|
91
|
+
}
|
|
92
|
+
export function createVirtualBaseTemplatesModule(projectRoot) {
|
|
93
|
+
const baseDir = resolve(projectRoot, "views/base");
|
|
94
|
+
const files = existsSync(baseDir) ? collectFiles(baseDir, [".html"]) : [];
|
|
95
|
+
const entries = files.map((filePath) => {
|
|
96
|
+
const key = basename(filePath, extname(filePath)).toLowerCase();
|
|
97
|
+
const value = readFileSync(filePath, "utf8");
|
|
98
|
+
return `${JSON.stringify(key)}: ${JSON.stringify(value)}`;
|
|
99
|
+
});
|
|
100
|
+
return [
|
|
101
|
+
"const bases = {",
|
|
102
|
+
...entries.map((entry) => ` ${entry},`),
|
|
103
|
+
"};",
|
|
104
|
+
"",
|
|
105
|
+
"export default bases;",
|
|
106
|
+
""
|
|
107
|
+
].join("\n");
|
|
108
|
+
}
|
|
109
|
+
export function createVirtualIslandsModule(projectRoot) {
|
|
110
|
+
const islandsDir = resolve(projectRoot, "client/islands");
|
|
111
|
+
const files = existsSync(islandsDir) ? collectFiles(islandsDir, [".ts", ".vue"]) : [];
|
|
112
|
+
const entries = files.map((filePath) => {
|
|
113
|
+
const key = basename(filePath, extname(filePath)).toLowerCase();
|
|
114
|
+
return `${JSON.stringify(key)}: () => import(${JSON.stringify(toAbsoluteImport(filePath))})`;
|
|
115
|
+
});
|
|
116
|
+
return [
|
|
117
|
+
"const islands = {",
|
|
118
|
+
...entries.map((entry) => ` ${entry},`),
|
|
119
|
+
"};",
|
|
120
|
+
"",
|
|
121
|
+
"export default islands;",
|
|
122
|
+
""
|
|
123
|
+
].join("\n");
|
|
124
|
+
}
|
|
125
|
+
export function createVirtualClientPagesModule(projectRoot) {
|
|
126
|
+
return createVirtualClientPageModuleSource(
|
|
127
|
+
projectRoot,
|
|
128
|
+
(filePath) => `() => import(${JSON.stringify(toAbsoluteImport(filePath))})`
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
export function createVirtualClientPageAssetsModule(projectRoot) {
|
|
132
|
+
const clientPagesDir = resolve(projectRoot, "client/pages");
|
|
133
|
+
const files = existsSync(clientPagesDir) ? collectFiles(clientPagesDir, [".ts"]) : [];
|
|
134
|
+
const imports = files.map((filePath, index) => {
|
|
135
|
+
return `import bundle_${index} from ${JSON.stringify(`${toAbsoluteImport(filePath)}?assets=client`)};`;
|
|
136
|
+
});
|
|
137
|
+
const entries = files.map((filePath, index) => {
|
|
138
|
+
const key = basename(filePath, extname(filePath));
|
|
139
|
+
return `${JSON.stringify(key)}: bundle_${index}`;
|
|
140
|
+
});
|
|
141
|
+
return [
|
|
142
|
+
...imports,
|
|
143
|
+
"",
|
|
144
|
+
"const bundles = {",
|
|
145
|
+
...entries.map((entry) => ` ${entry},`),
|
|
146
|
+
"};",
|
|
147
|
+
"",
|
|
148
|
+
"export default bundles;",
|
|
149
|
+
""
|
|
150
|
+
].join("\n");
|
|
151
|
+
}
|