@revojs/vue 0.1.56 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/index.d.ts +1 -35
- package/dist/client/index.js +4 -96
- package/dist/index.d.ts +30 -11
- package/dist/index.js +150 -43
- package/dist/module/index.d.ts +7 -0
- package/dist/module/index.js +62 -0
- package/dist/routes/[...]/get.d.ts +4 -0
- package/dist/routes/[...]/get.js +29 -0
- package/dist/{runtime/types → types}/index.d.ts +10 -10
- package/package.json +15 -9
- package/dist/runtime/app.d.ts +0 -7
- package/dist/runtime/app.js +0 -15
- package/dist/runtime/entry.d.ts +0 -1
- package/dist/runtime/entry.js +0 -5
- package/dist/runtime/main.vue +0 -74
- package/dist/runtime/routes/[...]/get.d.ts +0 -8
- package/dist/runtime/routes/[...]/get.js +0 -20
- package/dist/runtime/types/pages.d.ts +0 -7
package/dist/client/index.d.ts
CHANGED
|
@@ -1,35 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import * as _$revojs from "revojs";
|
|
3
|
-
import { RouterContext, Scope } from "revojs";
|
|
4
|
-
|
|
5
|
-
//#region src/client/index.d.ts
|
|
6
|
-
interface AsyncOptions<T> {
|
|
7
|
-
catch?: (error: T) => void | Promise<void>;
|
|
8
|
-
}
|
|
9
|
-
declare function useScope(): Scope;
|
|
10
|
-
declare function useError(scope?: Scope): ShallowRef<Error>;
|
|
11
|
-
declare function useRouter(): {
|
|
12
|
-
context: ShallowRef<RouterContext<Component>>;
|
|
13
|
-
navigate: (path: string) => void;
|
|
14
|
-
anchorNavigate: (event: Event) => void;
|
|
15
|
-
};
|
|
16
|
-
declare function useState<T>(name: MaybeRefOrGetter<string>): Ref<T | undefined>;
|
|
17
|
-
declare function useState<T>(name: MaybeRefOrGetter<string>, value: T): Ref<T>;
|
|
18
|
-
declare function useAsync<T, TError = Error>(name: MaybeRefOrGetter<string>, invoke: () => Promise<T>, defaultOptions?: AsyncOptions<TError>): Promise<{
|
|
19
|
-
state: Ref<T | undefined, T | undefined>;
|
|
20
|
-
isLoading: Ref<boolean, boolean>;
|
|
21
|
-
refresh: (options?: AsyncOptions<TError>) => Promise<T | undefined>;
|
|
22
|
-
}>;
|
|
23
|
-
declare function useFetch<T, TError = Error>(input: MaybeRefOrGetter<string>, options?: RequestInit & AsyncOptions<TError>): Promise<{
|
|
24
|
-
state: Ref<T | undefined, T | undefined>;
|
|
25
|
-
isLoading: Ref<boolean, boolean>;
|
|
26
|
-
refresh: (options?: AsyncOptions<TError> | undefined) => Promise<T | undefined>;
|
|
27
|
-
}>;
|
|
28
|
-
declare function refreshAsync(input?: string | Array<string>): Promise<void[] | undefined>;
|
|
29
|
-
declare const isServerSideRendering: any;
|
|
30
|
-
declare const NAVIGATE_HOOK: _$revojs.Descriptor<_$revojs.Invoke>;
|
|
31
|
-
declare const REFRESH_ASYNC_HOOK: _$revojs.Descriptor<(names?: Array<string>) => Promise<void>>;
|
|
32
|
-
declare const CLIENT_ERROR_CONTEXT: _$revojs.Descriptor<ShallowRef<Error>>;
|
|
33
|
-
declare const CLIENT_ROUTER_CONTEXT: _$revojs.Descriptor<ShallowRef<RouterContext<Component>>>;
|
|
34
|
-
//#endregion
|
|
35
|
-
export { AsyncOptions, CLIENT_ERROR_CONTEXT, CLIENT_ROUTER_CONTEXT, NAVIGATE_HOOK, REFRESH_ASYNC_HOOK, isServerSideRendering, refreshAsync, useAsync, useError, useFetch, useRouter, useScope, useState };
|
|
1
|
+
export {};
|
package/dist/client/index.js
CHANGED
|
@@ -1,98 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { createVueApp } from "../index.js";
|
|
2
|
+
import { createScope } from "revojs";
|
|
3
3
|
//#region src/client/index.ts
|
|
4
|
-
|
|
5
|
-
const scope = inject("REVOJS_SCOPE");
|
|
6
|
-
if (scope) return scope;
|
|
7
|
-
throw new Error();
|
|
8
|
-
}
|
|
9
|
-
function useError(scope = useScope()) {
|
|
10
|
-
return scope.getContext(CLIENT_ERROR_CONTEXT);
|
|
11
|
-
}
|
|
12
|
-
function useRouter() {
|
|
13
|
-
const scope = useScope();
|
|
14
|
-
const context = scope.getContext(CLIENT_ROUTER_CONTEXT);
|
|
15
|
-
const navigate = (path) => {
|
|
16
|
-
if (isClient) {
|
|
17
|
-
if (window.location.pathname != path) window.history.pushState(window.history.state, "", path);
|
|
18
|
-
scope.dispatchHook(NAVIGATE_HOOK);
|
|
19
|
-
}
|
|
20
|
-
if (isServer) throw sendRedirect(scope, path);
|
|
21
|
-
};
|
|
22
|
-
const anchorNavigate = (event) => {
|
|
23
|
-
event.preventDefault();
|
|
24
|
-
navigate(event.currentTarget?.getAttribute("href") ?? "/");
|
|
25
|
-
};
|
|
26
|
-
return {
|
|
27
|
-
context,
|
|
28
|
-
navigate,
|
|
29
|
-
anchorNavigate
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
function useState(name, value) {
|
|
33
|
-
const scope = useScope();
|
|
34
|
-
return customRef((track, trigger) => ({
|
|
35
|
-
get() {
|
|
36
|
-
track();
|
|
37
|
-
return getState(scope, toValue(name)) ?? value;
|
|
38
|
-
},
|
|
39
|
-
set(update) {
|
|
40
|
-
setState(scope, toValue(name), update);
|
|
41
|
-
trigger();
|
|
42
|
-
}
|
|
43
|
-
}));
|
|
44
|
-
}
|
|
45
|
-
async function useAsync(name, invoke, defaultOptions) {
|
|
46
|
-
const scope = useScope();
|
|
47
|
-
const state = useState(name);
|
|
48
|
-
const isLoading = ref(false);
|
|
49
|
-
const refresh = async (options) => {
|
|
50
|
-
const onCatch = options?.catch ?? defaultOptions?.catch;
|
|
51
|
-
isLoading.value = true;
|
|
52
|
-
try {
|
|
53
|
-
state.value = await invoke();
|
|
54
|
-
} catch (error) {
|
|
55
|
-
state.value = void 0;
|
|
56
|
-
onCatch?.(error);
|
|
57
|
-
} finally {
|
|
58
|
-
isLoading.value = false;
|
|
59
|
-
}
|
|
60
|
-
return state.value;
|
|
61
|
-
};
|
|
62
|
-
const task = refresh();
|
|
63
|
-
if (isServer) await task;
|
|
64
|
-
if (isClient) onScopeDispose(scope.registerHook(REFRESH_ASYNC_HOOK, async (names) => {
|
|
65
|
-
if (names === void 0 || names?.includes(toValue(name))) await refresh();
|
|
66
|
-
}));
|
|
67
|
-
return {
|
|
68
|
-
state,
|
|
69
|
-
isLoading,
|
|
70
|
-
refresh
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
async function useFetch(input, options) {
|
|
74
|
-
const scope = useScope();
|
|
75
|
-
const effectScope = getCurrentScope();
|
|
76
|
-
const { state, isLoading, refresh } = await useAsync(input, () => fetch(scope, toValue(input), options), options);
|
|
77
|
-
if (isClient && (isRef(input) || typeof input === "function")) effectScope?.run(() => {
|
|
78
|
-
watch(input, async (next, previous) => {
|
|
79
|
-
if (next !== previous) await refresh();
|
|
80
|
-
}, { flush: "post" });
|
|
81
|
-
});
|
|
82
|
-
return {
|
|
83
|
-
state,
|
|
84
|
-
isLoading,
|
|
85
|
-
refresh
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
async function refreshAsync(input) {
|
|
89
|
-
const scope = useScope();
|
|
90
|
-
if (isClient) return await scope.dispatchHook(REFRESH_ASYNC_HOOK, input === void 0 ? void 0 : Array.isArray(input) ? input : [input]);
|
|
91
|
-
}
|
|
92
|
-
const isServerSideRendering = import.meta.SERVER_SIDE_RENDERING ?? globalThis?.import?.meta?.SERVER_SIDE_RENDERING;
|
|
93
|
-
const NAVIGATE_HOOK = defineHook("NAVIGATE_HOOK");
|
|
94
|
-
const REFRESH_ASYNC_HOOK = defineHook("REFRESH_ASYNC_HOOK");
|
|
95
|
-
const CLIENT_ERROR_CONTEXT = defineContext("CLIENT_ERROR_CONTEXT");
|
|
96
|
-
const CLIENT_ROUTER_CONTEXT = defineContext("CLIENT_ROUTER_CONTEXT");
|
|
4
|
+
await createVueApp(await createScope()).then((app) => app.mount("#app"));
|
|
97
5
|
//#endregion
|
|
98
|
-
export {
|
|
6
|
+
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,31 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
serverSideRendering?: boolean;
|
|
7
|
-
compilerOption?: Options;
|
|
1
|
+
import { type RouterContext, type Scope } from "revojs";
|
|
2
|
+
import type { Awaitable } from "revojs/shared";
|
|
3
|
+
import { type Component, type MaybeRefOrGetter, type Ref, type ShallowRef } from "vue";
|
|
4
|
+
export interface AsyncOptions<T> {
|
|
5
|
+
catch?: (error: T) => Awaitable<void>;
|
|
8
6
|
}
|
|
9
|
-
declare function
|
|
10
|
-
declare function
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
export declare function useScope(): Scope;
|
|
8
|
+
export declare function useError(scope?: Scope): ShallowRef<Error>;
|
|
9
|
+
export declare function useRouter(): {
|
|
10
|
+
context: ShallowRef<RouterContext<Component>>;
|
|
11
|
+
navigate: <TRoute extends string>(route: TRoute) => void;
|
|
12
|
+
anchorNavigate: (event: Event) => void;
|
|
13
|
+
};
|
|
14
|
+
export declare function useState<T>(name: MaybeRefOrGetter<string>): Ref<T | undefined>;
|
|
15
|
+
export declare function useState<T>(name: MaybeRefOrGetter<string>, value: T): Ref<T>;
|
|
16
|
+
export declare function useAsync<T, TError = Error>(name: MaybeRefOrGetter<string>, invoke: () => Awaitable<T>, defaultOptions?: AsyncOptions<TError>): Promise<{
|
|
17
|
+
state: Ref<T | undefined, T | undefined>;
|
|
18
|
+
isLoading: Ref<boolean, boolean>;
|
|
19
|
+
refresh: (options?: AsyncOptions<TError>) => Promise<T | undefined>;
|
|
20
|
+
}>;
|
|
21
|
+
export declare function useFetch<T, TError = Error>(input: MaybeRefOrGetter<string>, options?: RequestInit & AsyncOptions<TError>): Promise<{
|
|
22
|
+
state: Ref<T | undefined, T | undefined>;
|
|
23
|
+
isLoading: Ref<boolean, boolean>;
|
|
24
|
+
refresh: (options?: AsyncOptions<TError> | undefined) => Promise<T | undefined>;
|
|
25
|
+
}>;
|
|
26
|
+
export declare function refreshAsync(input?: string | Array<string>): Promise<void[] | undefined>;
|
|
27
|
+
export declare function createVueApp(scope: Scope): Promise<import("vue").App<Element>>;
|
|
28
|
+
export declare const NAVIGATE_HOOK: import("revojs").Descriptor<import("revojs").Hook>;
|
|
29
|
+
export declare const REFRESH_ASYNC_HOOK: import("revojs").Descriptor<(names?: Array<string>) => Promise<void>>;
|
|
30
|
+
export declare const CLIENT_ERROR_CONTEXT: import("revojs").Descriptor<ShallowRef<Error>>;
|
|
31
|
+
export declare const CLIENT_ROUTER_CONTEXT: import("revojs").Descriptor<ShallowRef<RouterContext<Component>>>;
|
package/dist/index.js
CHANGED
|
@@ -1,47 +1,154 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import pages from "#pages";
|
|
2
|
+
import { isClient, isServer, isServerSideRendering } from "#variables";
|
|
3
|
+
import { fetch, getState, sendRedirect, setState, useUrl } from "@revojs/server";
|
|
4
|
+
import { Router, defineContext, defineHook, dispatchHook, getContext, registerHook, setContext } from "revojs";
|
|
5
|
+
import { Suspense, computed, createApp, createCommentVNode, createSSRApp, customRef, defineAsyncComponent, defineComponent, getCurrentScope, h, inject, isRef, onErrorCaptured, onScopeDispose, ref, shallowRef, toValue, warn, watch } from "vue";
|
|
3
6
|
//#region src/index.ts
|
|
4
|
-
function
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
7
|
+
function useScope() {
|
|
8
|
+
const scope = inject("REVOJS_SCOPE");
|
|
9
|
+
if (scope) return scope;
|
|
10
|
+
throw new Error("Vue scope is unavailable");
|
|
11
|
+
}
|
|
12
|
+
function useError(scope = useScope()) {
|
|
13
|
+
return getContext(scope, CLIENT_ERROR_CONTEXT);
|
|
14
|
+
}
|
|
15
|
+
function useRouter() {
|
|
16
|
+
const scope = useScope();
|
|
17
|
+
const context = getContext(scope, CLIENT_ROUTER_CONTEXT);
|
|
18
|
+
const navigate = (route) => {
|
|
19
|
+
if (isClient) {
|
|
20
|
+
if (globalThis.location.pathname !== route) globalThis.history.pushState(globalThis.history.state, "", route);
|
|
21
|
+
dispatchHook(scope, NAVIGATE_HOOK);
|
|
22
|
+
}
|
|
23
|
+
if (isServer) throw sendRedirect(scope, route);
|
|
24
|
+
};
|
|
25
|
+
const anchorNavigate = (event) => {
|
|
26
|
+
event.preventDefault();
|
|
27
|
+
navigate(event.currentTarget?.getAttribute("href") ?? "/");
|
|
28
|
+
};
|
|
29
|
+
return {
|
|
30
|
+
context,
|
|
31
|
+
navigate,
|
|
32
|
+
anchorNavigate
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function useState(name, value) {
|
|
36
|
+
const scope = useScope();
|
|
37
|
+
return customRef((track, trigger) => ({
|
|
38
|
+
get() {
|
|
39
|
+
track();
|
|
40
|
+
return getState(scope, toValue(name)) ?? value;
|
|
41
|
+
},
|
|
42
|
+
set(update) {
|
|
43
|
+
setState(scope, toValue(name), update);
|
|
44
|
+
trigger();
|
|
45
|
+
}
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
async function useAsync(name, invoke, defaultOptions) {
|
|
49
|
+
const scope = useScope();
|
|
50
|
+
const state = useState(name);
|
|
51
|
+
const isLoading = ref(false);
|
|
52
|
+
const refresh = async (options) => {
|
|
53
|
+
const onCatch = options?.catch ?? defaultOptions?.catch;
|
|
54
|
+
isLoading.value = true;
|
|
55
|
+
try {
|
|
56
|
+
state.value = await invoke();
|
|
57
|
+
} catch (error) {
|
|
58
|
+
state.value = void 0;
|
|
59
|
+
onCatch?.(error);
|
|
60
|
+
} finally {
|
|
61
|
+
isLoading.value = false;
|
|
62
|
+
}
|
|
63
|
+
return state.value;
|
|
64
|
+
};
|
|
65
|
+
const task = refresh();
|
|
66
|
+
if (isServer) await task;
|
|
67
|
+
if (isClient) onScopeDispose(registerHook(scope, REFRESH_ASYNC_HOOK, async (names) => {
|
|
68
|
+
if (names === void 0 || names?.includes(toValue(name))) await refresh();
|
|
69
|
+
}));
|
|
70
|
+
return {
|
|
71
|
+
state,
|
|
72
|
+
isLoading,
|
|
73
|
+
refresh
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
async function useFetch(input, options) {
|
|
77
|
+
const scope = useScope();
|
|
78
|
+
const effectScope = getCurrentScope();
|
|
79
|
+
const { state, isLoading, refresh } = await useAsync(input, () => fetch(scope, toValue(input), options), options);
|
|
80
|
+
if (isClient && (isRef(input) || typeof input === "function")) effectScope?.run(() => {
|
|
81
|
+
watch(input, async (next, previous) => {
|
|
82
|
+
if (next !== previous) await refresh();
|
|
83
|
+
}, { flush: "post" });
|
|
84
|
+
});
|
|
85
|
+
return {
|
|
86
|
+
state,
|
|
87
|
+
isLoading,
|
|
88
|
+
refresh
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
async function refreshAsync(input) {
|
|
92
|
+
const scope = useScope();
|
|
93
|
+
if (isClient) return await dispatchHook(scope, REFRESH_ASYNC_HOOK, input === void 0 ? void 0 : Array.isArray(input) ? input : [input]);
|
|
94
|
+
}
|
|
95
|
+
async function createVueApp(scope) {
|
|
96
|
+
const router = new Router();
|
|
97
|
+
const error = shallowRef();
|
|
98
|
+
const context = shallowRef();
|
|
99
|
+
for (const entries of Object.values(pages)) for (const [path, resolve] of Object.entries(entries)) {
|
|
100
|
+
const segments = path.split("/");
|
|
101
|
+
for (const attribute of segments.pop()?.split(".") ?? []) {
|
|
102
|
+
if (attribute === "page") continue;
|
|
103
|
+
segments.push(attribute);
|
|
104
|
+
}
|
|
105
|
+
router.use(segments, defineAsyncComponent(resolve));
|
|
106
|
+
}
|
|
107
|
+
const navigate = async () => {
|
|
108
|
+
const path = useUrl(scope).pathname.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
109
|
+
const segments = path === "" ? [] : path.split("/");
|
|
110
|
+
context.value = await router.resolve(scope, segments);
|
|
111
|
+
};
|
|
112
|
+
registerHook(scope, NAVIGATE_HOOK, navigate);
|
|
113
|
+
setContext(scope, CLIENT_ERROR_CONTEXT, error);
|
|
114
|
+
setContext(scope, CLIENT_ROUTER_CONTEXT, context);
|
|
115
|
+
await navigate();
|
|
116
|
+
const app = (isServerSideRendering ? createSSRApp(h(Main, { navigate })) : createApp(h(Main, { navigate }))).provide("REVOJS_SCOPE", scope);
|
|
117
|
+
app.config.warnHandler = (message, instance, trace) => {
|
|
118
|
+
if (message.includes("Invalid vnode type when creating vnode") || message.includes("Component <Anonymous> is missing template or render function")) return;
|
|
119
|
+
warn(message, instance, trace);
|
|
120
|
+
};
|
|
121
|
+
app.config.throwUnhandledErrorInProduction = true;
|
|
122
|
+
return app;
|
|
123
|
+
}
|
|
124
|
+
var Main = defineComponent({
|
|
125
|
+
name: "Main",
|
|
126
|
+
props: { navigate: {
|
|
127
|
+
type: Function,
|
|
128
|
+
required: true
|
|
129
|
+
} },
|
|
130
|
+
setup({ navigate }) {
|
|
131
|
+
const scope = useScope();
|
|
132
|
+
const error = getContext(scope, CLIENT_ERROR_CONTEXT);
|
|
133
|
+
const context = getContext(scope, CLIENT_ROUTER_CONTEXT);
|
|
134
|
+
const match = computed(() => {
|
|
135
|
+
if (!context.value?.match) return;
|
|
136
|
+
return context.value.hooks.reduceRight((child, hook) => h(hook, null, { default: () => child }), h(context.value.match, { key: context.value.segments.join("/") }));
|
|
21
137
|
});
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
138
|
+
if (isClient) {
|
|
139
|
+
globalThis.addEventListener("popstate", navigate);
|
|
140
|
+
onScopeDispose(() => globalThis.removeEventListener("popstate", navigate));
|
|
141
|
+
}
|
|
142
|
+
onErrorCaptured((value) => {
|
|
143
|
+
error.value = value;
|
|
144
|
+
return false;
|
|
26
145
|
});
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
} },
|
|
35
|
-
vite: {
|
|
36
|
-
plugins: [vueCompiler(options?.compilerOption)],
|
|
37
|
-
resolve: { alias: {
|
|
38
|
-
"#vue/app": fromModule("./runtime/app.js"),
|
|
39
|
-
"#vue/main": fromModule("./runtime/main.vue")
|
|
40
|
-
} },
|
|
41
|
-
optimizeDeps: { exclude: ["vue"] }
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
} };
|
|
45
|
-
}
|
|
146
|
+
return () => h(Suspense, void 0, { default: () => match.value ? h(match.value) : createCommentVNode() });
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
var NAVIGATE_HOOK = defineHook("NAVIGATE_HOOK");
|
|
150
|
+
var REFRESH_ASYNC_HOOK = defineHook("REFRESH_ASYNC_HOOK");
|
|
151
|
+
var CLIENT_ERROR_CONTEXT = defineContext("CLIENT_ERROR_CONTEXT");
|
|
152
|
+
var CLIENT_ROUTER_CONTEXT = defineContext("CLIENT_ROUTER_CONTEXT");
|
|
46
153
|
//#endregion
|
|
47
|
-
export {
|
|
154
|
+
export { CLIENT_ERROR_CONTEXT, CLIENT_ROUTER_CONTEXT, NAVIGATE_HOOK, REFRESH_ASYNC_HOOK, createVueApp, refreshAsync, useAsync, useError, useFetch, useRouter, useScope, useState };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type Options } from "@vitejs/plugin-vue";
|
|
2
|
+
export interface VueConfig {
|
|
3
|
+
serverSideRendering?: boolean;
|
|
4
|
+
compilerOption?: Options;
|
|
5
|
+
}
|
|
6
|
+
declare const _default: import("revojs/module").Module<"vue", VueConfig, readonly [import("revojs/module").Module<"server", Record<string, never>, []>, import("revojs/module").Module<"client", import("@revojs/client/module").ClientConfig, []>]>;
|
|
7
|
+
export default _default;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import client from "@revojs/client/module";
|
|
2
|
+
import server from "@revojs/server/module";
|
|
3
|
+
import vueCompiler from "@vitejs/plugin-vue";
|
|
4
|
+
import { addTypes, defineModule, useModule } from "revojs/module";
|
|
5
|
+
//#region src/module/index.ts
|
|
6
|
+
var module_default = defineModule({
|
|
7
|
+
name: "vue",
|
|
8
|
+
modules: [server, client],
|
|
9
|
+
config: () => ({ serverSideRendering: true }),
|
|
10
|
+
setup(config) {
|
|
11
|
+
const { fromModule } = useModule(import.meta.url);
|
|
12
|
+
addTypes(config, "vue", () => `import "${fromModule("../types/index.d.ts")}"`);
|
|
13
|
+
return {
|
|
14
|
+
variables: {
|
|
15
|
+
client: { isServerSideRendering: {
|
|
16
|
+
type: "boolean",
|
|
17
|
+
default: config.vue.serverSideRendering ?? true
|
|
18
|
+
} },
|
|
19
|
+
server: { isServerSideRendering: {
|
|
20
|
+
type: "boolean",
|
|
21
|
+
default: config.vue.serverSideRendering ?? true
|
|
22
|
+
} }
|
|
23
|
+
},
|
|
24
|
+
sources: {
|
|
25
|
+
routes: { from: [fromModule("../routes")] },
|
|
26
|
+
pages: {
|
|
27
|
+
match: ["**/page.vue", "**/+layout.vue"],
|
|
28
|
+
from: ["./routes"]
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
client: { html: {
|
|
32
|
+
head: { children: [{
|
|
33
|
+
tagName: "script",
|
|
34
|
+
attributes: { type: "module" },
|
|
35
|
+
children: [`import "${fromModule("../client/index.js")}"`]
|
|
36
|
+
}, {
|
|
37
|
+
tagName: "script",
|
|
38
|
+
attributes: {
|
|
39
|
+
id: "states",
|
|
40
|
+
type: "application/json"
|
|
41
|
+
},
|
|
42
|
+
children: ["<!-- STATES -->"]
|
|
43
|
+
}] },
|
|
44
|
+
body: { children: [{
|
|
45
|
+
tagName: "div",
|
|
46
|
+
attributes: { id: "app" },
|
|
47
|
+
children: ["<!-- APP -->"]
|
|
48
|
+
}, {
|
|
49
|
+
tagName: "div",
|
|
50
|
+
attributes: { id: "teleports" },
|
|
51
|
+
children: ["<!-- TELEPORTS -->"]
|
|
52
|
+
}] }
|
|
53
|
+
} },
|
|
54
|
+
vite: {
|
|
55
|
+
plugins: [vueCompiler(config.vue.compilerOption)],
|
|
56
|
+
optimizeDeps: { exclude: ["vue"] }
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
//#endregion
|
|
62
|
+
export { module_default as default };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { createVueApp, useError } from "../../index.js";
|
|
2
|
+
import { isServerSideRendering } from "#variables";
|
|
3
|
+
import { defineRoute, sendOk, useServer } from "@revojs/server";
|
|
4
|
+
import client from "#client";
|
|
5
|
+
import { renderToString } from "vue/server-renderer";
|
|
6
|
+
//#region src/routes/[...]/get.ts
|
|
7
|
+
var get_default = defineRoute({ async fetch(scope) {
|
|
8
|
+
const { states } = useServer(scope);
|
|
9
|
+
let content = client;
|
|
10
|
+
if (isServerSideRendering) {
|
|
11
|
+
const app = await createVueApp(scope);
|
|
12
|
+
const context = {};
|
|
13
|
+
try {
|
|
14
|
+
content = content.replace("<!-- APP -->", await renderToString(app, context));
|
|
15
|
+
} catch (error) {
|
|
16
|
+
throw useError(scope).value ?? error;
|
|
17
|
+
}
|
|
18
|
+
let body = "";
|
|
19
|
+
let container = "";
|
|
20
|
+
for (const [target, teleport] of Object.entries(context.teleports ?? {})) if (target.toLowerCase() === "body") body += teleport;
|
|
21
|
+
else container += teleport;
|
|
22
|
+
content = content.replace(/\s*<!-- TELEPORTS -->\s*/, () => container);
|
|
23
|
+
if (body) content = content.replace(/<body[^>]*>/i, (opening) => opening + body);
|
|
24
|
+
}
|
|
25
|
+
const value = JSON.stringify(states).replace(/</g, String.raw`\u003c`).replace(/>/g, String.raw`\u003e`).replace(/&/g, String.raw`\u0026`).replace(/\u2028/g, String.raw`\u2028`).replace(/\u2029/g, String.raw`\u2029`);
|
|
26
|
+
return sendOk(scope, content.replace(`<!-- STATES -->`, value));
|
|
27
|
+
} });
|
|
28
|
+
//#endregion
|
|
29
|
+
export { get_default as default };
|
|
@@ -5,14 +5,6 @@ declare module "#vue/app" {
|
|
|
5
5
|
export default function createApp(scope: Scope): Promise<App>;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
declare module "#vue/main" {
|
|
9
|
-
import type { Component } from "vue";
|
|
10
|
-
|
|
11
|
-
const main: Component;
|
|
12
|
-
|
|
13
|
-
export default app;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
8
|
declare module "*.vue" {
|
|
17
9
|
import type { DefineComponent } from "vue";
|
|
18
10
|
|
|
@@ -20,6 +12,14 @@ declare module "*.vue" {
|
|
|
20
12
|
export default component;
|
|
21
13
|
}
|
|
22
14
|
|
|
23
|
-
|
|
24
|
-
|
|
15
|
+
declare module "#pages" {
|
|
16
|
+
import type { Source } from "revojs";
|
|
17
|
+
import type { Component } from "vue";
|
|
18
|
+
|
|
19
|
+
const entries: Source<Component>;
|
|
20
|
+
export default entries;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
declare module "#variables" {
|
|
24
|
+
export const isServerSideRendering: boolean;
|
|
25
25
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@revojs/vue",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"repository":
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/tellua/revojs.git"
|
|
8
|
+
},
|
|
6
9
|
"files": [
|
|
7
10
|
"dist"
|
|
8
11
|
],
|
|
@@ -15,21 +18,24 @@
|
|
|
15
18
|
"types": "./dist/index.d.ts",
|
|
16
19
|
"import": "./dist/index.js"
|
|
17
20
|
},
|
|
18
|
-
"./
|
|
19
|
-
"types": "./dist/
|
|
20
|
-
"import": "./dist/
|
|
21
|
+
"./module": {
|
|
22
|
+
"types": "./dist/module/index.d.ts",
|
|
23
|
+
"import": "./dist/module/index.js"
|
|
21
24
|
},
|
|
22
25
|
"./types": {
|
|
23
|
-
"types": "./dist/
|
|
26
|
+
"types": "./dist/types/index.d.ts"
|
|
24
27
|
}
|
|
25
28
|
},
|
|
26
29
|
"scripts": {
|
|
27
|
-
"build": "
|
|
30
|
+
"build": "vite build",
|
|
31
|
+
"watch": "vite build --watch"
|
|
28
32
|
},
|
|
29
33
|
"dependencies": {
|
|
30
|
-
"@
|
|
34
|
+
"@revojs/client": "*",
|
|
35
|
+
"@revojs/server": "*",
|
|
36
|
+
"@vitejs/plugin-vue": "^6.0.8",
|
|
31
37
|
"revojs": "*",
|
|
32
|
-
"vue": "^3.5.
|
|
38
|
+
"vue": "^3.5.42"
|
|
33
39
|
},
|
|
34
40
|
"devDependencies": {
|
|
35
41
|
"@revojs/tsconfig": "*"
|
package/dist/runtime/app.d.ts
DELETED
package/dist/runtime/app.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import Main from "#vue/main";
|
|
2
|
-
import { createApp, createSSRApp, warn } from "vue";
|
|
3
|
-
import { isServerSideRendering } from "../client";
|
|
4
|
-
//#region src/runtime/app.ts
|
|
5
|
-
var app_default = async (scope) => {
|
|
6
|
-
const app = (isServerSideRendering ? createSSRApp(Main) : createApp(Main)).provide("REVOJS_SCOPE", scope);
|
|
7
|
-
app.config.warnHandler = (message, instance, trace) => {
|
|
8
|
-
if (message.includes("Invalid vnode type when creating vnode") || message.includes("Component <Anonymous> is missing template or render function")) return;
|
|
9
|
-
warn(message, instance, trace);
|
|
10
|
-
};
|
|
11
|
-
app.config.throwUnhandledErrorInProduction = true;
|
|
12
|
-
return app;
|
|
13
|
-
};
|
|
14
|
-
//#endregion
|
|
15
|
-
export { app_default as default };
|
package/dist/runtime/entry.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { };
|
package/dist/runtime/entry.js
DELETED
package/dist/runtime/main.vue
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<Suspense>
|
|
3
|
-
<component :is="route" v-if="route" />
|
|
4
|
-
</Suspense>
|
|
5
|
-
</template>
|
|
6
|
-
|
|
7
|
-
<script setup lang="ts">
|
|
8
|
-
import pages from "#pages";
|
|
9
|
-
import { isClient, Router, RouterContext, useUrl } from "revojs";
|
|
10
|
-
import { computed, h, onErrorCaptured, onScopeDispose, shallowRef, type Component } from "vue";
|
|
11
|
-
import { CLIENT_ERROR_CONTEXT, CLIENT_ROUTER_CONTEXT, NAVIGATE_HOOK, useScope } from "../client";
|
|
12
|
-
|
|
13
|
-
const scope = useScope();
|
|
14
|
-
|
|
15
|
-
const error = shallowRef<Error>();
|
|
16
|
-
const context = shallowRef<RouterContext<Component>>();
|
|
17
|
-
|
|
18
|
-
const router = new Router<Component>();
|
|
19
|
-
|
|
20
|
-
for (const path in pages) {
|
|
21
|
-
const segments = path.split("/");
|
|
22
|
-
|
|
23
|
-
for (const attribute of segments.pop()?.split(".") ?? []) {
|
|
24
|
-
if (attribute === "page" || attribute === "vue") {
|
|
25
|
-
continue;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
segments.push(attribute);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
for (const page of pages[path]) {
|
|
32
|
-
router.use(segments, page);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const route = computed(() => {
|
|
37
|
-
if (context.value?.route) {
|
|
38
|
-
const route = h(context.value.route);
|
|
39
|
-
|
|
40
|
-
return context.value.hooks.reduceRight(
|
|
41
|
-
(previous, hook) =>
|
|
42
|
-
h(hook, null, {
|
|
43
|
-
default: () => (error.value === undefined ? previous : undefined),
|
|
44
|
-
}),
|
|
45
|
-
route,
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
const fetch = () => {
|
|
51
|
-
const next = useUrl(scope);
|
|
52
|
-
|
|
53
|
-
const path = next.pathname.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
54
|
-
const segments = path === "" ? [] : path.split("/");
|
|
55
|
-
|
|
56
|
-
context.value = router.match(segments);
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
scope.registerHook(NAVIGATE_HOOK, fetch);
|
|
60
|
-
|
|
61
|
-
if (isClient) {
|
|
62
|
-
window.addEventListener("popstate", fetch);
|
|
63
|
-
onScopeDispose(() => window.removeEventListener("popstate", fetch));
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
fetch();
|
|
67
|
-
|
|
68
|
-
scope.setContext(CLIENT_ERROR_CONTEXT, error);
|
|
69
|
-
scope.setContext(CLIENT_ROUTER_CONTEXT, context);
|
|
70
|
-
|
|
71
|
-
onErrorCaptured((value) => {
|
|
72
|
-
error.value ??= value;
|
|
73
|
-
});
|
|
74
|
-
</script>
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { isServerSideRendering, useError } from "../../../client";
|
|
2
|
-
import createApp from "#vue/app";
|
|
3
|
-
import { defineRoute, sendOk, useServer } from "revojs";
|
|
4
|
-
import client from "#client";
|
|
5
|
-
import { renderToString } from "vue/server-renderer";
|
|
6
|
-
//#region src/runtime/routes/[...]/get.ts
|
|
7
|
-
var get_default = defineRoute({ async fetch(scope) {
|
|
8
|
-
const { states } = useServer(scope);
|
|
9
|
-
let content = client;
|
|
10
|
-
if (isServerSideRendering) {
|
|
11
|
-
const app = await createApp(scope);
|
|
12
|
-
content = content.replace("<!-- APP -->", await renderToString(app));
|
|
13
|
-
const error = useError(scope);
|
|
14
|
-
if (error.value) throw error.value;
|
|
15
|
-
}
|
|
16
|
-
const value = JSON.stringify(states).replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
17
|
-
return sendOk(scope, content.replace(`<!-- STATES -->`, value));
|
|
18
|
-
} });
|
|
19
|
-
//#endregion
|
|
20
|
-
export { get_default as default };
|