@shwfed/config 3.0.1 → 3.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/components/actions/buttons/2026-07-13/com.shwfed.actions.button.state.write/config.d.vue.ts +53 -0
  3. package/dist/runtime/components/actions/buttons/2026-07-13/com.shwfed.actions.button.state.write/config.vue +174 -0
  4. package/dist/runtime/components/actions/buttons/2026-07-13/com.shwfed.actions.button.state.write/config.vue.d.ts +53 -0
  5. package/dist/runtime/components/actions/buttons/2026-07-13/com.shwfed.actions.button.state.write/runtime.d.vue.ts +8 -0
  6. package/dist/runtime/components/actions/buttons/2026-07-13/com.shwfed.actions.button.state.write/runtime.vue +70 -0
  7. package/dist/runtime/components/actions/buttons/2026-07-13/com.shwfed.actions.button.state.write/runtime.vue.d.ts +8 -0
  8. package/dist/runtime/components/actions/buttons/2026-07-13/com.shwfed.actions.button.state.write/schema.d.ts +49 -0
  9. package/dist/runtime/components/actions/buttons/2026-07-13/com.shwfed.actions.button.state.write/schema.js +90 -0
  10. package/dist/runtime/components/actions/components/triggers-field.d.vue.ts +9 -0
  11. package/dist/runtime/components/actions/components/triggers-field.vue +13 -15
  12. package/dist/runtime/components/actions/components/triggers-field.vue.d.ts +9 -0
  13. package/dist/runtime/components/actions/utils/steps.d.ts +26 -0
  14. package/dist/runtime/components/actions/utils/steps.js +9 -0
  15. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/config.d.vue.ts +68 -68
  16. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/config.vue.d.ts +68 -68
  17. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/runtime.d.vue.ts +68 -68
  18. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/runtime.vue.d.ts +68 -68
  19. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/schema.d.ts +34 -34
  20. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.d.vue.ts +6 -6
  21. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.vue.d.ts +6 -6
  22. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.d.vue.ts +8 -8
  23. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.vue.d.ts +8 -8
  24. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/config.d.vue.ts +2 -2
  25. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/config.vue.d.ts +2 -2
  26. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.monthrange/config.d.vue.ts +6 -6
  27. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.monthrange/config.vue.d.ts +6 -6
  28. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/runtime.vue +55 -51
  29. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/runtime.vue +54 -50
  30. package/dist/runtime/components/operations/2026-06-11/com.shwfed.operation.http.request.json/schema.d.ts +8 -2
  31. package/dist/runtime/components/operations/2026-06-11/com.shwfed.operation.http.request.json/schema.js +5 -4
  32. package/dist/runtime/components/operations/2026-06-15/com.shwfed.operation.http.download/schema.d.ts +8 -2
  33. package/dist/runtime/components/operations/2026-06-15/com.shwfed.operation.http.download/schema.js +5 -4
  34. package/dist/runtime/components/sidebar/index.vue +1 -1
  35. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-remote/config.d.vue.ts +2 -2
  36. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-remote/config.vue.d.ts +2 -2
  37. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-static/config.d.vue.ts +2 -2
  38. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-static/config.vue.d.ts +2 -2
  39. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-remote/config.d.vue.ts +2 -2
  40. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-remote/config.vue.d.ts +2 -2
  41. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-static/config.d.vue.ts +2 -2
  42. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-static/config.vue.d.ts +2 -2
  43. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/config.d.vue.ts +2 -2
  44. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/config.vue.d.ts +2 -2
  45. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single.remote/config.d.vue.ts +2 -2
  46. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single.remote/config.vue.d.ts +2 -2
  47. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +2 -2
  48. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +2 -2
  49. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +2 -2
  50. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +2 -2
  51. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/config.d.vue.ts +2 -2
  52. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/config.vue.d.ts +2 -2
  53. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/config.d.vue.ts +2 -2
  54. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/config.vue.d.ts +2 -2
  55. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +2 -2
  56. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +2 -2
  57. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +2 -2
  58. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +2 -2
  59. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.combobox-multi/config.d.vue.ts +2 -2
  60. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.combobox-multi/config.vue.d.ts +2 -2
  61. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.combobox-single/config.d.vue.ts +2 -2
  62. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.combobox-single/config.vue.d.ts +2 -2
  63. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +2 -2
  64. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +2 -2
  65. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-multi/runtime.vue +52 -48
  66. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +2 -2
  67. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +2 -2
  68. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-single/runtime.vue +51 -47
  69. package/dist/runtime/components/table/schema.d.ts +68 -68
  70. package/dist/runtime/components/ui/command/CommandList.d.vue.ts +2 -2
  71. package/dist/runtime/components/ui/command/CommandList.vue +12 -4
  72. package/dist/runtime/components/ui/command/CommandList.vue.d.ts +2 -2
  73. package/dist/runtime/components/ui/date-picker/DatePickerInput.d.vue.ts +1 -1
  74. package/dist/runtime/components/ui/date-picker/DatePickerInput.vue.d.ts +1 -1
  75. package/dist/runtime/components/ui/date-picker/DatePickerTimeInput.d.vue.ts +1 -1
  76. package/dist/runtime/components/ui/date-picker/DatePickerTimeInput.vue.d.ts +1 -1
  77. package/dist/runtime/components/ui/date-range-picker/DateRangePickerInput.d.vue.ts +1 -1
  78. package/dist/runtime/components/ui/date-range-picker/DateRangePickerInput.vue.d.ts +1 -1
  79. package/dist/runtime/components/ui/date-range-picker/DateRangePickerTimeInput.d.vue.ts +2 -2
  80. package/dist/runtime/components/ui/date-range-picker/DateRangePickerTimeInput.vue.d.ts +2 -2
  81. package/dist/runtime/components/ui/expression-editor/ExpressionEditor.vue +1 -1
  82. package/dist/runtime/components/ui/input-group/InputGroupCombobox.d.vue.ts +2 -2
  83. package/dist/runtime/components/ui/input-group/InputGroupCombobox.vue +6 -0
  84. package/dist/runtime/components/ui/input-group/InputGroupCombobox.vue.d.ts +2 -2
  85. package/dist/runtime/components/ui/scroll-area/ScrollArea.d.vue.ts +1 -0
  86. package/dist/runtime/components/ui/scroll-area/ScrollArea.vue +9 -3
  87. package/dist/runtime/components/ui/scroll-area/ScrollArea.vue.d.ts +1 -0
  88. package/dist/runtime/share/event-bus.d.ts +9 -1
  89. package/dist/runtime/share/event-bus.js +4 -4
  90. package/package.json +1 -1
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "shwfed",
3
3
  "configKey": "shwfed",
4
- "version": "3.0.1",
4
+ "version": "3.0.3",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "unknown"
@@ -0,0 +1,53 @@
1
+ import { type Value } from './schema.js';
2
+ type __VLS_ModelProps = {
3
+ modelValue: Value;
4
+ };
5
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
6
+ "update:modelValue": (value: {
7
+ readonly type: "com.shwfed.actions.button.state.write";
8
+ readonly compatibilityDate: "2026-07-13";
9
+ readonly before?: readonly {
10
+ readonly id?: string | undefined;
11
+ readonly params?: unknown;
12
+ readonly compatibilityDate?: string | undefined;
13
+ readonly target: string;
14
+ readonly operation: string;
15
+ }[] | undefined;
16
+ readonly onSuccess?: readonly {
17
+ readonly id?: string | undefined;
18
+ readonly params?: unknown;
19
+ readonly compatibilityDate?: string | undefined;
20
+ readonly target: string;
21
+ readonly operation: string;
22
+ }[] | undefined;
23
+ readonly writes: readonly {
24
+ readonly path: string;
25
+ readonly value: string;
26
+ }[];
27
+ }) => any;
28
+ }, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
29
+ "onUpdate:modelValue"?: ((value: {
30
+ readonly type: "com.shwfed.actions.button.state.write";
31
+ readonly compatibilityDate: "2026-07-13";
32
+ readonly before?: readonly {
33
+ readonly id?: string | undefined;
34
+ readonly params?: unknown;
35
+ readonly compatibilityDate?: string | undefined;
36
+ readonly target: string;
37
+ readonly operation: string;
38
+ }[] | undefined;
39
+ readonly onSuccess?: readonly {
40
+ readonly id?: string | undefined;
41
+ readonly params?: unknown;
42
+ readonly compatibilityDate?: string | undefined;
43
+ readonly target: string;
44
+ readonly operation: string;
45
+ }[] | undefined;
46
+ readonly writes: readonly {
47
+ readonly path: string;
48
+ readonly value: string;
49
+ }[];
50
+ }) => any) | undefined;
51
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
52
+ declare const _default: typeof __VLS_export;
53
+ export default _default;
@@ -0,0 +1,174 @@
1
+ <script setup>
2
+ import { computed } from "vue";
3
+ import { Icon } from "@iconify/vue";
4
+ import { Button } from "../../../../ui/button";
5
+ import { Field, FieldLabel } from "../../../../ui/field";
6
+ import { ExpressionEditor } from "../../../../ui/expression-editor";
7
+ import { Markdown } from "../../../../ui/markdown";
8
+ import { InputGroupButton } from "../../../../ui/input-group";
9
+ import { getStructFieldDescription, getStructFieldTitle } from "../../../schema";
10
+ import TriggersField from "../../../components/triggers-field.vue";
11
+ import TriggerRowScope from "../../../components/trigger-row-scope.vue";
12
+ import { publishingSteps } from "../../../utils/steps";
13
+ import { schema } from "./schema";
14
+ defineOptions({ name: "ShwfedStateWriteActionConfig" });
15
+ const value = defineModel({ type: null, ...{ required: true } });
16
+ const actionSchema = schema(() => {
17
+ });
18
+ const fieldTitle = (f) => getStructFieldTitle(actionSchema, f) ?? f;
19
+ const fieldDescription = (f) => getStructFieldDescription(actionSchema, f);
20
+ const writes = computed(() => value.value.writes ?? []);
21
+ const beforeSteps = computed(() => publishingSteps(value.value.before));
22
+ const writeRoster = computed(
23
+ () => beforeSteps.value.map((step) => ({
24
+ id: step.id,
25
+ label: `\u7B2C ${step.index + 1} \u6B65`,
26
+ valid: true,
27
+ description: step.output
28
+ }))
29
+ );
30
+ const afterInherited = computed(
31
+ () => beforeSteps.value.map((step) => ({
32
+ id: step.id,
33
+ label: `\u5199\u5165\u524D \u7B2C ${step.index + 1} \u6B65`,
34
+ valid: true,
35
+ description: step.output
36
+ }))
37
+ );
38
+ function patchWrites(next) {
39
+ value.value = { ...value.value, writes: next };
40
+ }
41
+ function updateRow(index, patch) {
42
+ patchWrites(writes.value.map((w, i) => i === index ? { ...w, ...patch } : w));
43
+ }
44
+ function addRow() {
45
+ patchWrites([...writes.value, { path: "", value: "" }]);
46
+ }
47
+ function removeRow(index) {
48
+ patchWrites(writes.value.filter((_, i) => i !== index));
49
+ }
50
+ function updateTriggers(key, next) {
51
+ const draft = { ...value.value };
52
+ if (next.length === 0) Reflect.deleteProperty(draft, key);
53
+ else draft[key] = next;
54
+ value.value = draft;
55
+ }
56
+ </script>
57
+
58
+ <template>
59
+ <div class="flex flex-col gap-3">
60
+ <Field orientation="vertical">
61
+ <FieldLabel class="text-xs text-zinc-500">
62
+ <template
63
+ v-if="fieldDescription('before')"
64
+ #tooltip
65
+ >
66
+ <Markdown
67
+ :source="fieldDescription('before')"
68
+ block
69
+ class="prose prose-sm prose-zinc"
70
+ />
71
+ </template>
72
+ {{ fieldTitle("before") }}
73
+ </FieldLabel>
74
+ <TriggersField
75
+ :triggers="value.before ?? []"
76
+ @update:triggers="(next) => updateTriggers('before', next)"
77
+ />
78
+ </Field>
79
+
80
+ <Field orientation="vertical">
81
+ <FieldLabel class="text-xs text-zinc-500">
82
+ <template
83
+ v-if="fieldDescription('writes')"
84
+ #tooltip
85
+ >
86
+ <Markdown
87
+ :source="fieldDescription('writes')"
88
+ block
89
+ class="prose prose-sm prose-zinc"
90
+ />
91
+ </template>
92
+ {{ fieldTitle("writes") }}
93
+ </FieldLabel>
94
+
95
+ <!-- Advertise the「写入前」steps to the value editors: they get the
96
+ 「第 N 步」picker chips + `steps` inline validation. -->
97
+ <TriggerRowScope :roster="writeRoster">
98
+ <div class="flex flex-col gap-3">
99
+ <!-- One write item per multiline editor: the monofont binding path as
100
+ a full-width `leading` header row, the value expression wrapping
101
+ below (its own `{x}` badge), and a destructive delete in the
102
+ `trailing` bottom row. Reuses the ExpressionEditor's own
103
+ InputGroup. -->
104
+ <ExpressionEditor
105
+ v-for="(row, index) in writes"
106
+ :key="index"
107
+ :model-value="row.value"
108
+ multiline
109
+ placeholder="值,如 selected[?0].?exchangeRate"
110
+ class="min-h-16"
111
+ @update:model-value="(v) => updateRow(index, { value: v })"
112
+ >
113
+ <template #leading>
114
+ <input
115
+ type="text"
116
+ data-slot="state-write-path"
117
+ :value="row.path"
118
+ placeholder="路径"
119
+ class="w-full min-w-0 bg-transparent font-mono text-sm text-zinc-700 outline-none placeholder:text-zinc-300"
120
+ :aria-label="`\u5199\u5165\u8DEF\u5F84 ${index + 1}`"
121
+ @input="updateRow(index, { path: $event.target.value })"
122
+ >
123
+ </template>
124
+ <template #trailing>
125
+ <InputGroupButton
126
+ variant="destructive"
127
+ size="icon-xs"
128
+ as-child
129
+ >
130
+ <button
131
+ type="button"
132
+ :aria-label="`\u79FB\u9664\u5199\u5165\u9879 ${index + 1}`"
133
+ @click="removeRow(index)"
134
+ >
135
+ <Icon icon="fluent:delete-20-regular" />
136
+ </button>
137
+ </InputGroupButton>
138
+ </template>
139
+ </ExpressionEditor>
140
+
141
+ <Button
142
+ type="button"
143
+ class="justify-center"
144
+ @click="addRow"
145
+ >
146
+ <Icon icon="fluent:add-20-regular" />
147
+ <span>添加写入项</span>
148
+ </Button>
149
+ </div>
150
+ </TriggerRowScope>
151
+ </Field>
152
+
153
+ <Field orientation="vertical">
154
+ <FieldLabel class="text-xs text-zinc-500">
155
+ <template
156
+ v-if="fieldDescription('onSuccess')"
157
+ #tooltip
158
+ >
159
+ <Markdown
160
+ :source="fieldDescription('onSuccess')"
161
+ block
162
+ class="prose prose-sm prose-zinc"
163
+ />
164
+ </template>
165
+ {{ fieldTitle("onSuccess") }}
166
+ </FieldLabel>
167
+ <TriggersField
168
+ :triggers="value.onSuccess ?? []"
169
+ :inherited="afterInherited"
170
+ @update:triggers="(next) => updateTriggers('onSuccess', next)"
171
+ />
172
+ </Field>
173
+ </div>
174
+ </template>
@@ -0,0 +1,53 @@
1
+ import { type Value } from './schema.js';
2
+ type __VLS_ModelProps = {
3
+ modelValue: Value;
4
+ };
5
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
6
+ "update:modelValue": (value: {
7
+ readonly type: "com.shwfed.actions.button.state.write";
8
+ readonly compatibilityDate: "2026-07-13";
9
+ readonly before?: readonly {
10
+ readonly id?: string | undefined;
11
+ readonly params?: unknown;
12
+ readonly compatibilityDate?: string | undefined;
13
+ readonly target: string;
14
+ readonly operation: string;
15
+ }[] | undefined;
16
+ readonly onSuccess?: readonly {
17
+ readonly id?: string | undefined;
18
+ readonly params?: unknown;
19
+ readonly compatibilityDate?: string | undefined;
20
+ readonly target: string;
21
+ readonly operation: string;
22
+ }[] | undefined;
23
+ readonly writes: readonly {
24
+ readonly path: string;
25
+ readonly value: string;
26
+ }[];
27
+ }) => any;
28
+ }, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
29
+ "onUpdate:modelValue"?: ((value: {
30
+ readonly type: "com.shwfed.actions.button.state.write";
31
+ readonly compatibilityDate: "2026-07-13";
32
+ readonly before?: readonly {
33
+ readonly id?: string | undefined;
34
+ readonly params?: unknown;
35
+ readonly compatibilityDate?: string | undefined;
36
+ readonly target: string;
37
+ readonly operation: string;
38
+ }[] | undefined;
39
+ readonly onSuccess?: readonly {
40
+ readonly id?: string | undefined;
41
+ readonly params?: unknown;
42
+ readonly compatibilityDate?: string | undefined;
43
+ readonly target: string;
44
+ readonly operation: string;
45
+ }[] | undefined;
46
+ readonly writes: readonly {
47
+ readonly path: string;
48
+ readonly value: string;
49
+ }[];
50
+ }) => any) | undefined;
51
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
52
+ declare const _default: typeof __VLS_export;
53
+ export default _default;
@@ -0,0 +1,8 @@
1
+ import type { Value } from './schema.js';
2
+ type __VLS_Props = {
3
+ buttonId: string;
4
+ config: Value;
5
+ };
6
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
7
+ declare const _default: typeof __VLS_export;
8
+ export default _default;
@@ -0,0 +1,70 @@
1
+ <script setup>
2
+ import { Effect } from "effect";
3
+ import { createDefu } from "defu";
4
+ import { cel as _rawCel } from "../../../../../utils/cel";
5
+ import { celBindings, injectCELContext } from "../../../../../utils/cel-context";
6
+ import { dispatchTriggers, useEventChannel } from "../../../../../share/event-bus";
7
+ import { useFormState } from "../../../../form/utils/state";
8
+ import ShwfedActionDefinition from "../../../components/definition.vue";
9
+ defineOptions({ name: "ShwfedStateWriteActionRuntime" });
10
+ const props = defineProps({
11
+ buttonId: { type: String, required: true },
12
+ config: { type: null, required: true }
13
+ });
14
+ const inherited = injectCELContext();
15
+ const $cel = (expression, context) => _rawCel(expression, { ...celBindings(inherited), ...context });
16
+ const nearestFormState = useFormState();
17
+ const formState = nearestFormState.kind === "form" && nearestFormState.parent ? nearestFormState.parent : nearestFormState;
18
+ const channel = useEventChannel();
19
+ const mergeObjects = createDefu((obj, key, value) => {
20
+ if (Array.isArray(obj[key]) && Array.isArray(value)) {
21
+ obj[key] = value;
22
+ return true;
23
+ }
24
+ });
25
+ function isPlainObject(v) {
26
+ return typeof v === "object" && v !== null && !Array.isArray(v);
27
+ }
28
+ function mergeAtPath(current, next) {
29
+ if (isPlainObject(current) && isPlainObject(next)) {
30
+ return mergeObjects({ ...next }, current);
31
+ }
32
+ return next;
33
+ }
34
+ const effect = Effect.suspend(() => {
35
+ const steps = {};
36
+ return dispatchTriggers(channel, props.config.before, $cel, steps).pipe(
37
+ // 写入前 halts (a failed request, a form 「校验」 that found errors) abort the
38
+ // whole click via a defect, so no write below runs — same guarantee the
39
+ // inline 2026-06-25 requests gave, now shared with every other op.
40
+ Effect.flatMap(
41
+ () => (
42
+ // Evaluate every row's `value` in list order. A row with a blank `path` is
43
+ // skipped (a half-authored row writes nowhere) but its value is never
44
+ // evaluated — `Effect.forEach` keeps the click sequential and short-circuits
45
+ // on the first failing expression.
46
+ Effect.forEach(
47
+ props.config.writes ?? [],
48
+ (write) => {
49
+ const path = write.path?.trim() ?? "";
50
+ if (path.length === 0) return Effect.void;
51
+ return Effect.map($cel(write.value, { steps }), (result) => {
52
+ const merged = mergeAtPath(formState.getAt(path), result);
53
+ formState.setAt(path, merged);
54
+ });
55
+ },
56
+ { discard: true }
57
+ )
58
+ )
59
+ ),
60
+ Effect.flatMap(() => dispatchTriggers(channel, props.config.onSuccess, $cel, steps))
61
+ );
62
+ });
63
+ </script>
64
+
65
+ <template>
66
+ <ShwfedActionDefinition
67
+ :action-id="buttonId"
68
+ :effect="effect"
69
+ />
70
+ </template>
@@ -0,0 +1,8 @@
1
+ import type { Value } from './schema.js';
2
+ type __VLS_Props = {
3
+ buttonId: string;
4
+ config: Value;
5
+ };
6
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
7
+ declare const _default: typeof __VLS_export;
8
+ export default _default;
@@ -0,0 +1,49 @@
1
+ import { Schema } from 'effect';
2
+ import type { Environment } from '../../../../../vendor/cel-js/lib/index.js';
3
+ import type { MigrateFn } from '../../../utils/resolve.js';
4
+ export declare const type: "com.shwfed.actions.button.state.write";
5
+ export declare const compatibilityDate: "2026-07-13";
6
+ export declare const metadata: {
7
+ readonly name: "写入表单状态";
8
+ readonly icon: "fluent:document-edit-20-regular";
9
+ };
10
+ export declare function schema(configure: (env: Environment) => void): Schema.Struct<{
11
+ type: Schema.Literal<["com.shwfed.actions.button.state.write"]>;
12
+ compatibilityDate: Schema.Literal<["2026-07-13"]>;
13
+ before: Schema.optional<Schema.Array$<Schema.Struct<{
14
+ id: Schema.optional<Schema.refine<string, typeof Schema.String>>;
15
+ target: Schema.refine<string, typeof Schema.String>;
16
+ operation: Schema.SchemaClass<string, string, never>;
17
+ compatibilityDate: Schema.optional<Schema.SchemaClass<string, string, never>>;
18
+ params: Schema.optional<Schema.SchemaClass<unknown, unknown, never>>;
19
+ }>>>;
20
+ writes: Schema.Array$<Schema.Struct<{
21
+ path: Schema.SchemaClass<string, string, never>;
22
+ value: Schema.Schema<string, string, never>;
23
+ }>>;
24
+ onSuccess: Schema.optional<Schema.Array$<Schema.Struct<{
25
+ id: Schema.optional<Schema.refine<string, typeof Schema.String>>;
26
+ target: Schema.refine<string, typeof Schema.String>;
27
+ operation: Schema.SchemaClass<string, string, never>;
28
+ compatibilityDate: Schema.optional<Schema.SchemaClass<string, string, never>>;
29
+ params: Schema.optional<Schema.SchemaClass<unknown, unknown, never>>;
30
+ }>>>;
31
+ }>;
32
+ export type Value = Schema.Schema.Type<ReturnType<typeof schema>>;
33
+ export type WriteValue = Value['writes'][number];
34
+ /**
35
+ * Adopts 2026-06-25 values, whose「写入前」was a `requests` list of bare
36
+ * HTTP-request expressions. Each row becomes one「发送请求」op trigger on the
37
+ * page target — the op the button now dispatches instead of fetching itself.
38
+ * The row's `id` is carried over verbatim, so every `steps["<id>"]` already
39
+ * written into a write value keeps resolving; the op publishes its parsed
40
+ * response under that same id and halts the chain on failure, which is what the
41
+ * old inline requests did.
42
+ *
43
+ * The date rule (same type, newest date) also points 2026-05-24 values here.
44
+ * Those store a single map `expression` instead of `writes` rows, and splitting
45
+ * an arbitrary map expression back into rows needs human judgement — the 2026-
46
+ * 06-25 entry deliberately shipped no migration for it, and this one keeps that
47
+ * call, failing with guidance rather than guessing.
48
+ */
49
+ export declare const migrate: MigrateFn;
@@ -0,0 +1,90 @@
1
+ import { Effect, Schema } from "effect";
2
+ import { Expression } from "../../../../../share/expression.js";
3
+ import { Triggers } from "../../../../../share/event-bus.js";
4
+ import { PAGE_TARGET_ID } from "../../../../../share/page-target.js";
5
+ import { md } from "../../../../../share/markdown.js";
6
+ import { registerStepsVariableIfAbsent } from "../../../../operations/utils/step-vars.js";
7
+ import * as httpRequestOperation from "../../../../operations/2026-06-11/com.shwfed.operation.http.request.json/schema.js";
8
+ export const type = "com.shwfed.actions.button.state.write";
9
+ export const compatibilityDate = "2026-07-13";
10
+ export const metadata = {
11
+ name: "\u5199\u5165\u8868\u5355\u72B6\u6001",
12
+ icon: "fluent:document-edit-20-regular"
13
+ };
14
+ export function schema(configure) {
15
+ const withSteps = (env) => {
16
+ configure(env);
17
+ registerStepsVariableIfAbsent(env);
18
+ };
19
+ const Write = Schema.Struct({
20
+ path: Schema.String.annotations({
21
+ title: "\u8DEF\u5F84",
22
+ description: "\u5199\u5165\u7684\u7ED1\u5B9A\u8DEF\u5F84\uFF0C\u5982 `dataJson.cus_currency`"
23
+ }),
24
+ value: Expression({ configure: withSteps }).annotations({
25
+ title: "\u503C",
26
+ description: "\u70B9\u51FB\u540E\u6C42\u503C\uFF0C\u7ED3\u679C\u5199\u5165\u8BE5\u8DEF\u5F84"
27
+ })
28
+ });
29
+ return Schema.Struct({
30
+ type: Schema.Literal(type),
31
+ compatibilityDate: Schema.Literal(compatibilityDate),
32
+ before: Schema.optional(Triggers.annotations({
33
+ title: "\u5199\u5165\u524D",
34
+ description: md`
35
+ 写入前按列表顺序执行的操作。任一操作中止(例如请求失败、表单校验未通过)
36
+ 将取消本次写入。
37
+
38
+ 发布输出的操作(如「发送请求」)可在「写入值」与「写入后」中经
39
+ \`steps["<第 N 步>"]\` 引用其输出。
40
+ `
41
+ })),
42
+ writes: Schema.Array(Write).annotations({
43
+ title: "\u5199\u5165\u503C",
44
+ description: md`
45
+ 点击后按列表顺序逐行求值并写入到最近祖先的表单状态:每行的 \`值\`
46
+ 表达式结果写入其 \`路径\`。对象值与当前值深合并(数组整体替换),
47
+ 其他类型直接替换。留空表示不进行任何写入。
48
+ `
49
+ }),
50
+ onSuccess: Schema.optional(Triggers.annotations({
51
+ title: "\u5199\u5165\u540E",
52
+ description: "\u5199\u5165\u5B8C\u6210\u540E\u6267\u884C\u7684\u64CD\u4F5C"
53
+ }))
54
+ }).annotations({
55
+ title: "StateWriteAction",
56
+ description: "\u70B9\u51FB\u540E\u6309\u987A\u5E8F\u5C06\u6BCF\u4E2A CEL \u8868\u8FBE\u5F0F\u7684\u7ED3\u679C\u5199\u56DE\u6700\u8FD1\u7956\u5148\u8868\u5355\u72B6\u6001\u7684\u5BF9\u5E94\u8DEF\u5F84"
57
+ });
58
+ }
59
+ export const migrate = (prev) => Effect.try({
60
+ try: () => {
61
+ if (!prev || typeof prev !== "object") {
62
+ throw new Error("\u5199\u5165\u8868\u5355\u72B6\u6001\u8FC1\u79FB\u5931\u8D25\uFF1A\u539F\u503C\u4E0D\u662F\u5BF9\u8C61");
63
+ }
64
+ const { type: _t, compatibilityDate: _c, requests, ...rest } = prev;
65
+ if (!Array.isArray(rest.writes)) {
66
+ throw new TypeError(
67
+ "\u5199\u5165\u8868\u5355\u72B6\u6001\u8FC1\u79FB\u5931\u8D25\uFF1A2026-05-24 \u7684\u300C\u5199\u5165\u503C\u300D\u662F\u5355\u4E2A map \u8868\u8FBE\u5F0F\uFF0C\u9700\u6309\u5199\u5165\u8DEF\u5F84\u4EBA\u5DE5\u62C6\u5206\u4E3A\u5199\u5165\u884C\uFF0C\u65E0\u6CD5\u81EA\u52A8\u8FC1\u79FB"
68
+ );
69
+ }
70
+ const before = (Array.isArray(requests) ? requests : []).map((row) => {
71
+ const { id, request } = row ?? {};
72
+ return {
73
+ id,
74
+ target: PAGE_TARGET_ID,
75
+ operation: httpRequestOperation.type,
76
+ compatibilityDate: httpRequestOperation.compatibilityDate,
77
+ params: { expression: request ?? "" }
78
+ };
79
+ });
80
+ return {
81
+ ...rest,
82
+ type,
83
+ compatibilityDate,
84
+ // Stay optional-absent when there was nothing to migrate, so an
85
+ // untouched button migrates to a config with no `before` key at all.
86
+ ...before.length > 0 ? { before } : {}
87
+ };
88
+ },
89
+ catch: (e) => e instanceof Error ? e : new Error(String(e))
90
+ });
@@ -1,6 +1,15 @@
1
1
  import { type TriggerValue } from '../../../share/event-bus.js';
2
+ import type { StepRef } from '../../../utils/cel-context.js';
2
3
  type __VLS_Props = {
3
4
  triggers: ReadonlyArray<TriggerValue>;
5
+ /**
6
+ * Steps published BEFORE this list runs, from a chain the host already
7
+ * dispatched — state.write's 写入前 rows, as seen by its 写入后 list. Prefixed
8
+ * (always valid — they ran before every row here) into every row's roster, so
9
+ * an op param can reference them. Omitted by every other host: a lone trigger
10
+ * list has nothing upstream of it.
11
+ */
12
+ inherited?: ReadonlyArray<StepRef>;
4
13
  };
5
14
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
6
15
  "update:triggers": (triggers: readonly {
@@ -3,6 +3,7 @@ import { computed, ref } from "vue";
3
3
  import { Icon } from "@iconify/vue";
4
4
  import { useEventAncestry } from "../../../share/event-bus";
5
5
  import { findOperation } from "../../operations/utils/resolve";
6
+ import { publishingSteps } from "../utils/steps";
6
7
  import TriggerRowScope from "./trigger-row-scope.vue";
7
8
  import {
8
9
  useTreeDnd
@@ -17,7 +18,8 @@ import {
17
18
  import { CommandGroup, CommandItem } from "../../ui/command";
18
19
  defineOptions({ name: "ShwfedTriggersField" });
19
20
  const props = defineProps({
20
- triggers: { type: Array, required: true }
21
+ triggers: { type: Array, required: true },
22
+ inherited: { type: Array, required: false }
21
23
  });
22
24
  const emit = defineEmits(["update:triggers"]);
23
25
  function keyOf(target, operation) {
@@ -90,21 +92,17 @@ function opConfigFor(trigger) {
90
92
  function removeTrigger(index) {
91
93
  emit("update:triggers", props.triggers.filter((_, i) => i !== index));
92
94
  }
93
- const publishingSteps = computed(
94
- () => props.triggers.flatMap((trigger, index) => {
95
- if (!trigger.id || !trigger.compatibilityDate) return [];
96
- const output = findOperation(trigger.operation, trigger.compatibilityDate)?.metadata.output;
97
- if (!output) return [];
98
- return [{ id: trigger.id, index, output }];
99
- })
100
- );
95
+ const ownSteps = computed(() => publishingSteps(props.triggers));
101
96
  function stepRosterFor(index) {
102
- return publishingSteps.value.map((step) => ({
103
- id: step.id,
104
- label: `\u7B2C ${step.index + 1} \u6B65`,
105
- valid: step.index < index,
106
- description: step.output
107
- }));
97
+ return [
98
+ ...props.inherited ?? [],
99
+ ...ownSteps.value.map((step) => ({
100
+ id: step.id,
101
+ label: `\u7B2C ${step.index + 1} \u6B65`,
102
+ valid: step.index < index,
103
+ description: step.output
104
+ }))
105
+ ];
108
106
  }
109
107
  const ROW_KIND = "shwfed-trigger-row";
110
108
  function moveTrigger(from, to) {
@@ -1,6 +1,15 @@
1
1
  import { type TriggerValue } from '../../../share/event-bus.js';
2
+ import type { StepRef } from '../../../utils/cel-context.js';
2
3
  type __VLS_Props = {
3
4
  triggers: ReadonlyArray<TriggerValue>;
5
+ /**
6
+ * Steps published BEFORE this list runs, from a chain the host already
7
+ * dispatched — state.write's 写入前 rows, as seen by its 写入后 list. Prefixed
8
+ * (always valid — they ran before every row here) into every row's roster, so
9
+ * an op param can reference them. Omitted by every other host: a lone trigger
10
+ * list has nothing upstream of it.
11
+ */
12
+ inherited?: ReadonlyArray<StepRef>;
4
13
  };
5
14
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
6
15
  "update:triggers": (triggers: readonly {
@@ -0,0 +1,26 @@
1
+ import type { TriggerValue } from '../../../share/event-bus.js';
2
+ /**
3
+ * One row of a trigger list that publishes a chain-step output — the rows a
4
+ * later expression can address as `steps["<id>"]`.
5
+ *
6
+ * A row qualifies on two counts, neither of them a type check: its operation's
7
+ * registry `metadata.output` marks it as publishing (so a new publishing op
8
+ * needs no edit here), and it carries a persisted `id` to publish under (rows
9
+ * authored before ids were minted simply can't be referenced). `index` is the
10
+ * row's CURRENT position, which is what the「第 N 步」labels are built from —
11
+ * so labels follow a dnd reorder.
12
+ */
13
+ export type PublishingStep = Readonly<{
14
+ id: string;
15
+ index: number;
16
+ /** Designer-facing label of what the op publishes (`metadata.output`). */
17
+ output: string;
18
+ }>;
19
+ /**
20
+ * The publishing rows of one trigger list. Shared by every step-roster builder
21
+ * — the trigger editor's per-row roster (earlier rows of the same list) and a
22
+ * button advertising a whole finished chain to a later field (state.write's
23
+ * 写入前 → 写入值 / 写入后) — so "which rows are referenceable" is decided in
24
+ * exactly one place.
25
+ */
26
+ export declare function publishingSteps(triggers: ReadonlyArray<TriggerValue> | undefined): ReadonlyArray<PublishingStep>;
@@ -0,0 +1,9 @@
1
+ import { findOperation } from "../../operations/utils/resolve.js";
2
+ export function publishingSteps(triggers) {
3
+ return (triggers ?? []).flatMap((trigger, index) => {
4
+ if (!trigger.id || !trigger.compatibilityDate) return [];
5
+ const output = findOperation(trigger.operation, trigger.compatibilityDate)?.metadata.output;
6
+ if (!output) return [];
7
+ return [{ id: trigger.id, index, output }];
8
+ });
9
+ }