@shwfed/nuxt 0.1.47 → 0.1.49
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/module.d.mts +8 -0
- package/dist/module.json +1 -1
- package/dist/runtime/components/app.d.vue.ts +74 -2
- package/dist/runtime/components/app.vue +7 -4
- package/dist/runtime/components/app.vue.d.ts +74 -2
- package/dist/runtime/plugins/cel/context.d.ts +2 -0
- package/dist/runtime/plugins/cel/context.js +7 -0
- package/dist/runtime/plugins/cel/index.js +2 -1
- package/package.json +1 -1
package/dist/module.d.mts
CHANGED
package/dist/module.json
CHANGED
|
@@ -19,12 +19,84 @@ declare const _default: typeof __VLS_export;
|
|
|
19
19
|
export default _default;
|
|
20
20
|
declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
|
|
21
21
|
commands?: ReadonlyArray<Group>;
|
|
22
|
+
/**
|
|
23
|
+
* 应用的全局 DSL(CEL)执行上下文。传入一个 Effect,在应用启动时运行一次;
|
|
24
|
+
* 其解析结果(一个 record)会被永久设为全局上下文,供后续所有 CEL 求值(如 `$dsl.evaluate`)使用。
|
|
25
|
+
*
|
|
26
|
+
* 应用会等待该 effect 解析完成后才渲染;在整个应用生命周期内只会执行一次。
|
|
27
|
+
* 若未传入 `dsl`,全局上下文将被设为 `{}`。
|
|
28
|
+
*
|
|
29
|
+
* 适用于需要在首屏前就确定的、会话级稳定数据,例如:当前用户信息、用户所属组、
|
|
30
|
+
* 用户菜单列表、用户权限(或权限模块)等。此处加载的数据在整个应用内可通过 CEL 访问
|
|
31
|
+
*(如 `user`、`menu`、`permissions`)。强调「会话级」稳定即可,不必永久不变。
|
|
32
|
+
*
|
|
33
|
+
* 重要约束:
|
|
34
|
+
* - 加载时间至关重要:在该 effect 解析前,整应用不会加载,用户会看到白屏,因此必须保持非常快
|
|
35
|
+
* (如减少请求、缓存或并行拉取)。
|
|
36
|
+
* - 这是有意为之的权衡:菜单、用户等关键数据必须在此加载,否则可能出现空菜单、无用户等异常表现。
|
|
37
|
+
* - 该 effect 不得抛错(类型为 `never`):任何失败(如网络)应在 effect 内部处理,
|
|
38
|
+
* 返回空对象或安全默认值,保证应用仍能正常启动并得到一致的全局上下文。
|
|
39
|
+
*
|
|
40
|
+
* 返回的 `Record<string, unknown>` 会在通过 `$dsl.evaluate` 求值 CEL 表达式时,
|
|
41
|
+
* 与运行时上下文(如 `now`、`today` 及调用处传入的 context)合并使用。
|
|
42
|
+
*
|
|
43
|
+
* @example 最小示例:返回静态对象,键可在 CEL 中直接使用
|
|
44
|
+
* dsl: Effect.succeed({ hello: 'world' })
|
|
45
|
+
* // 之后在模板或逻辑中:$dsl.evaluate`hello`() 得到 'world'
|
|
46
|
+
*
|
|
47
|
+
* @example 实际场景:拉取会话数据(用户、菜单、权限)并返回,供 CEL 使用
|
|
48
|
+
* dsl: Effect.gen(function* () {
|
|
49
|
+
* const [user, menu, permissions] = yield* Effect.all([
|
|
50
|
+
* fetchUser().pipe(Effect.catchAll(() => Effect.succeed({ name: '', id: '' }))),
|
|
51
|
+
* fetchMenu().pipe(Effect.catchAll(() => Effect.succeed([]))),
|
|
52
|
+
* fetchPermissions().pipe(Effect.catchAll(() => Effect.succeed({ canEdit: false }))),
|
|
53
|
+
* ])
|
|
54
|
+
* return { user, menu, permissions }
|
|
55
|
+
* })
|
|
56
|
+
* // CEL 中可访问 user.name、permissions.canEdit 等;失败时在 effect 内兜底,不抛错
|
|
57
|
+
*/
|
|
58
|
+
dsl?: Effect.Effect<Record<string, unknown>, never, Scope.Scope>;
|
|
22
59
|
}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{
|
|
23
60
|
commands?: ReadonlyArray<Group>;
|
|
61
|
+
/**
|
|
62
|
+
* 应用的全局 DSL(CEL)执行上下文。传入一个 Effect,在应用启动时运行一次;
|
|
63
|
+
* 其解析结果(一个 record)会被永久设为全局上下文,供后续所有 CEL 求值(如 `$dsl.evaluate`)使用。
|
|
64
|
+
*
|
|
65
|
+
* 应用会等待该 effect 解析完成后才渲染;在整个应用生命周期内只会执行一次。
|
|
66
|
+
* 若未传入 `dsl`,全局上下文将被设为 `{}`。
|
|
67
|
+
*
|
|
68
|
+
* 适用于需要在首屏前就确定的、会话级稳定数据,例如:当前用户信息、用户所属组、
|
|
69
|
+
* 用户菜单列表、用户权限(或权限模块)等。此处加载的数据在整个应用内可通过 CEL 访问
|
|
70
|
+
*(如 `user`、`menu`、`permissions`)。强调「会话级」稳定即可,不必永久不变。
|
|
71
|
+
*
|
|
72
|
+
* 重要约束:
|
|
73
|
+
* - 加载时间至关重要:在该 effect 解析前,整应用不会加载,用户会看到白屏,因此必须保持非常快
|
|
74
|
+
* (如减少请求、缓存或并行拉取)。
|
|
75
|
+
* - 这是有意为之的权衡:菜单、用户等关键数据必须在此加载,否则可能出现空菜单、无用户等异常表现。
|
|
76
|
+
* - 该 effect 不得抛错(类型为 `never`):任何失败(如网络)应在 effect 内部处理,
|
|
77
|
+
* 返回空对象或安全默认值,保证应用仍能正常启动并得到一致的全局上下文。
|
|
78
|
+
*
|
|
79
|
+
* 返回的 `Record<string, unknown>` 会在通过 `$dsl.evaluate` 求值 CEL 表达式时,
|
|
80
|
+
* 与运行时上下文(如 `now`、`today` 及调用处传入的 context)合并使用。
|
|
81
|
+
*
|
|
82
|
+
* @example 最小示例:返回静态对象,键可在 CEL 中直接使用
|
|
83
|
+
* dsl: Effect.succeed({ hello: 'world' })
|
|
84
|
+
* // 之后在模板或逻辑中:$dsl.evaluate`hello`() 得到 'world'
|
|
85
|
+
*
|
|
86
|
+
* @example 实际场景:拉取会话数据(用户、菜单、权限)并返回,供 CEL 使用
|
|
87
|
+
* dsl: Effect.gen(function* () {
|
|
88
|
+
* const [user, menu, permissions] = yield* Effect.all([
|
|
89
|
+
* fetchUser().pipe(Effect.catchAll(() => Effect.succeed({ name: '', id: '' }))),
|
|
90
|
+
* fetchMenu().pipe(Effect.catchAll(() => Effect.succeed([]))),
|
|
91
|
+
* fetchPermissions().pipe(Effect.catchAll(() => Effect.succeed({ canEdit: false }))),
|
|
92
|
+
* ])
|
|
93
|
+
* return { user, menu, permissions }
|
|
94
|
+
* })
|
|
95
|
+
* // CEL 中可访问 user.name、permissions.canEdit 等;失败时在 effect 内兜底,不抛错
|
|
96
|
+
*/
|
|
97
|
+
dsl?: Effect.Effect<Record<string, unknown>, never, Scope.Scope>;
|
|
24
98
|
}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
|
|
25
99
|
menu?: (props: {}) => any;
|
|
26
|
-
} & {
|
|
27
|
-
'dropdown-trigger'?: (props: {}) => any;
|
|
28
100
|
} & {
|
|
29
101
|
default?: (props: {}) => any;
|
|
30
102
|
}>;
|
|
@@ -9,11 +9,13 @@ import { useI18n } from "vue-i18n";
|
|
|
9
9
|
import { Icon } from "@iconify/vue";
|
|
10
10
|
import { Effect } from "effect";
|
|
11
11
|
import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuGroup, DropdownMenuLabel } from "./ui/dropdown-menu";
|
|
12
|
+
import { setGlobalDslContext } from "../plugins/cel/context";
|
|
12
13
|
</script>
|
|
13
14
|
|
|
14
15
|
<script setup>
|
|
15
|
-
defineProps({
|
|
16
|
-
commands: { type: Array, required: false }
|
|
16
|
+
const props = defineProps({
|
|
17
|
+
commands: { type: Array, required: false },
|
|
18
|
+
dsl: { type: null, required: false }
|
|
17
19
|
});
|
|
18
20
|
const { t } = useI18n();
|
|
19
21
|
useHead({
|
|
@@ -32,6 +34,7 @@ const { meta_k } = useMagicKeys();
|
|
|
32
34
|
whenever(() => meta_k?.value, () => {
|
|
33
35
|
isCommandOpen.value = !isCommandOpen.value;
|
|
34
36
|
});
|
|
37
|
+
setGlobalDslContext(await props.dsl?.pipe(Effect.scoped).pipe(Effect.runPromise) ?? {});
|
|
35
38
|
</script>
|
|
36
39
|
|
|
37
40
|
<template>
|
|
@@ -87,7 +90,7 @@ whenever(() => meta_k?.value, () => {
|
|
|
87
90
|
</CommandList>
|
|
88
91
|
</CommandDialog>
|
|
89
92
|
</ClientOnly>
|
|
90
|
-
<main class="h-screen w-screen">
|
|
93
|
+
<main class="h-screen w-screen flex flex-col overflow-hidden">
|
|
91
94
|
<header class="bg-(--primary) h-12 w-full flex items-center justify-between px-4 gap-4">
|
|
92
95
|
<span class="flex items-center">
|
|
93
96
|
<svg
|
|
@@ -169,7 +172,7 @@ whenever(() => meta_k?.value, () => {
|
|
|
169
172
|
isDropdownOpen = true;
|
|
170
173
|
}"
|
|
171
174
|
>
|
|
172
|
-
|
|
175
|
+
{{ $md.inline`${$config.public.shwfed.profile.name}`() }}
|
|
173
176
|
</button>
|
|
174
177
|
</DropdownMenuTrigger>
|
|
175
178
|
<DropdownMenuContent
|
|
@@ -19,12 +19,84 @@ declare const _default: typeof __VLS_export;
|
|
|
19
19
|
export default _default;
|
|
20
20
|
declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
|
|
21
21
|
commands?: ReadonlyArray<Group>;
|
|
22
|
+
/**
|
|
23
|
+
* 应用的全局 DSL(CEL)执行上下文。传入一个 Effect,在应用启动时运行一次;
|
|
24
|
+
* 其解析结果(一个 record)会被永久设为全局上下文,供后续所有 CEL 求值(如 `$dsl.evaluate`)使用。
|
|
25
|
+
*
|
|
26
|
+
* 应用会等待该 effect 解析完成后才渲染;在整个应用生命周期内只会执行一次。
|
|
27
|
+
* 若未传入 `dsl`,全局上下文将被设为 `{}`。
|
|
28
|
+
*
|
|
29
|
+
* 适用于需要在首屏前就确定的、会话级稳定数据,例如:当前用户信息、用户所属组、
|
|
30
|
+
* 用户菜单列表、用户权限(或权限模块)等。此处加载的数据在整个应用内可通过 CEL 访问
|
|
31
|
+
*(如 `user`、`menu`、`permissions`)。强调「会话级」稳定即可,不必永久不变。
|
|
32
|
+
*
|
|
33
|
+
* 重要约束:
|
|
34
|
+
* - 加载时间至关重要:在该 effect 解析前,整应用不会加载,用户会看到白屏,因此必须保持非常快
|
|
35
|
+
* (如减少请求、缓存或并行拉取)。
|
|
36
|
+
* - 这是有意为之的权衡:菜单、用户等关键数据必须在此加载,否则可能出现空菜单、无用户等异常表现。
|
|
37
|
+
* - 该 effect 不得抛错(类型为 `never`):任何失败(如网络)应在 effect 内部处理,
|
|
38
|
+
* 返回空对象或安全默认值,保证应用仍能正常启动并得到一致的全局上下文。
|
|
39
|
+
*
|
|
40
|
+
* 返回的 `Record<string, unknown>` 会在通过 `$dsl.evaluate` 求值 CEL 表达式时,
|
|
41
|
+
* 与运行时上下文(如 `now`、`today` 及调用处传入的 context)合并使用。
|
|
42
|
+
*
|
|
43
|
+
* @example 最小示例:返回静态对象,键可在 CEL 中直接使用
|
|
44
|
+
* dsl: Effect.succeed({ hello: 'world' })
|
|
45
|
+
* // 之后在模板或逻辑中:$dsl.evaluate`hello`() 得到 'world'
|
|
46
|
+
*
|
|
47
|
+
* @example 实际场景:拉取会话数据(用户、菜单、权限)并返回,供 CEL 使用
|
|
48
|
+
* dsl: Effect.gen(function* () {
|
|
49
|
+
* const [user, menu, permissions] = yield* Effect.all([
|
|
50
|
+
* fetchUser().pipe(Effect.catchAll(() => Effect.succeed({ name: '', id: '' }))),
|
|
51
|
+
* fetchMenu().pipe(Effect.catchAll(() => Effect.succeed([]))),
|
|
52
|
+
* fetchPermissions().pipe(Effect.catchAll(() => Effect.succeed({ canEdit: false }))),
|
|
53
|
+
* ])
|
|
54
|
+
* return { user, menu, permissions }
|
|
55
|
+
* })
|
|
56
|
+
* // CEL 中可访问 user.name、permissions.canEdit 等;失败时在 effect 内兜底,不抛错
|
|
57
|
+
*/
|
|
58
|
+
dsl?: Effect.Effect<Record<string, unknown>, never, Scope.Scope>;
|
|
22
59
|
}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{
|
|
23
60
|
commands?: ReadonlyArray<Group>;
|
|
61
|
+
/**
|
|
62
|
+
* 应用的全局 DSL(CEL)执行上下文。传入一个 Effect,在应用启动时运行一次;
|
|
63
|
+
* 其解析结果(一个 record)会被永久设为全局上下文,供后续所有 CEL 求值(如 `$dsl.evaluate`)使用。
|
|
64
|
+
*
|
|
65
|
+
* 应用会等待该 effect 解析完成后才渲染;在整个应用生命周期内只会执行一次。
|
|
66
|
+
* 若未传入 `dsl`,全局上下文将被设为 `{}`。
|
|
67
|
+
*
|
|
68
|
+
* 适用于需要在首屏前就确定的、会话级稳定数据,例如:当前用户信息、用户所属组、
|
|
69
|
+
* 用户菜单列表、用户权限(或权限模块)等。此处加载的数据在整个应用内可通过 CEL 访问
|
|
70
|
+
*(如 `user`、`menu`、`permissions`)。强调「会话级」稳定即可,不必永久不变。
|
|
71
|
+
*
|
|
72
|
+
* 重要约束:
|
|
73
|
+
* - 加载时间至关重要:在该 effect 解析前,整应用不会加载,用户会看到白屏,因此必须保持非常快
|
|
74
|
+
* (如减少请求、缓存或并行拉取)。
|
|
75
|
+
* - 这是有意为之的权衡:菜单、用户等关键数据必须在此加载,否则可能出现空菜单、无用户等异常表现。
|
|
76
|
+
* - 该 effect 不得抛错(类型为 `never`):任何失败(如网络)应在 effect 内部处理,
|
|
77
|
+
* 返回空对象或安全默认值,保证应用仍能正常启动并得到一致的全局上下文。
|
|
78
|
+
*
|
|
79
|
+
* 返回的 `Record<string, unknown>` 会在通过 `$dsl.evaluate` 求值 CEL 表达式时,
|
|
80
|
+
* 与运行时上下文(如 `now`、`today` 及调用处传入的 context)合并使用。
|
|
81
|
+
*
|
|
82
|
+
* @example 最小示例:返回静态对象,键可在 CEL 中直接使用
|
|
83
|
+
* dsl: Effect.succeed({ hello: 'world' })
|
|
84
|
+
* // 之后在模板或逻辑中:$dsl.evaluate`hello`() 得到 'world'
|
|
85
|
+
*
|
|
86
|
+
* @example 实际场景:拉取会话数据(用户、菜单、权限)并返回,供 CEL 使用
|
|
87
|
+
* dsl: Effect.gen(function* () {
|
|
88
|
+
* const [user, menu, permissions] = yield* Effect.all([
|
|
89
|
+
* fetchUser().pipe(Effect.catchAll(() => Effect.succeed({ name: '', id: '' }))),
|
|
90
|
+
* fetchMenu().pipe(Effect.catchAll(() => Effect.succeed([]))),
|
|
91
|
+
* fetchPermissions().pipe(Effect.catchAll(() => Effect.succeed({ canEdit: false }))),
|
|
92
|
+
* ])
|
|
93
|
+
* return { user, menu, permissions }
|
|
94
|
+
* })
|
|
95
|
+
* // CEL 中可访问 user.name、permissions.canEdit 等;失败时在 effect 内兜底,不抛错
|
|
96
|
+
*/
|
|
97
|
+
dsl?: Effect.Effect<Record<string, unknown>, never, Scope.Scope>;
|
|
24
98
|
}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
|
|
25
99
|
menu?: (props: {}) => any;
|
|
26
|
-
} & {
|
|
27
|
-
'dropdown-trigger'?: (props: {}) => any;
|
|
28
100
|
} & {
|
|
29
101
|
default?: (props: {}) => any;
|
|
30
102
|
}>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { defineNuxtPlugin, useRuntimeConfig } from "#app";
|
|
2
2
|
import defu from "defu";
|
|
3
3
|
import { createEnvironment } from "./env.js";
|
|
4
|
+
import { getGlobalDslContext } from "./context.js";
|
|
4
5
|
export default defineNuxtPlugin({
|
|
5
6
|
name: "shwfed-nuxt:cel",
|
|
6
7
|
setup: () => {
|
|
@@ -21,7 +22,7 @@ export default defineNuxtPlugin({
|
|
|
21
22
|
* Will throw `TypeError` / `EvaluationError` on failure.
|
|
22
23
|
*/
|
|
23
24
|
evaluate: (...args) => (context) => {
|
|
24
|
-
return env.evaluate(String.raw(...args), defu(context, {
|
|
25
|
+
return env.evaluate(String.raw(...args), defu({}, getGlobalDslContext(), context, {
|
|
25
26
|
now: /* @__PURE__ */ new Date(),
|
|
26
27
|
today: /* @__PURE__ */ new Date()
|
|
27
28
|
}));
|