@shwfed/config 2.0.3 → 2.1.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/dist/module.json +1 -1
- package/dist/runtime/components/config/blocks/2026-05-17/{com.shwfed.block.chart.line → com.shwfed.block.chart.xy}/config.d.vue.ts +16 -6
- package/dist/runtime/components/config/blocks/2026-05-17/{com.shwfed.block.chart.line → com.shwfed.block.chart.xy}/config.vue +263 -76
- package/dist/runtime/components/config/blocks/2026-05-17/{com.shwfed.block.chart.line → com.shwfed.block.chart.xy}/config.vue.d.ts +16 -6
- package/dist/runtime/components/config/blocks/2026-05-17/{com.shwfed.block.chart.line → com.shwfed.block.chart.xy}/runtime.d.vue.ts +16 -6
- package/dist/runtime/components/config/blocks/2026-05-17/{com.shwfed.block.chart.line → com.shwfed.block.chart.xy}/runtime.vue +104 -12
- package/dist/runtime/components/config/blocks/2026-05-17/{com.shwfed.block.chart.line → com.shwfed.block.chart.xy}/runtime.vue.d.ts +16 -6
- package/dist/runtime/components/config/blocks/2026-05-17/{com.shwfed.block.chart.line → com.shwfed.block.chart.xy}/schema.d.ts +51 -15
- package/dist/runtime/components/config/blocks/2026-05-17/{com.shwfed.block.chart.line → com.shwfed.block.chart.xy}/schema.js +67 -22
- package/dist/runtime/components/form/ai/fields-button.d.vue.ts +13 -0
- package/dist/runtime/components/form/ai/fields-button.vue +458 -0
- package/dist/runtime/components/form/ai/fields-button.vue.d.ts +13 -0
- package/dist/runtime/components/form/ai/fields-task.md +71 -0
- package/dist/runtime/components/form/config.d.vue.ts +1 -1
- package/dist/runtime/components/form/config.vue +4 -36
- package/dist/runtime/components/form/config.vue.d.ts +1 -1
- package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.d.vue.ts +18 -18
- package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.vue.d.ts +18 -18
- package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetime/config.d.vue.ts +4 -4
- package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetime/config.vue.d.ts +4 -4
- package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.d.vue.ts +22 -22
- package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.vue.d.ts +22 -22
- package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.time/config.d.vue.ts +2 -2
- package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.time/config.vue.d.ts +2 -2
- package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/config.d.vue.ts +4 -4
- package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/config.vue.d.ts +4 -4
- package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.numberrange/config.d.vue.ts +12 -12
- package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.numberrange/config.vue +87 -11
- package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.numberrange/config.vue.d.ts +12 -12
- package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.numberrange/runtime.vue +18 -6
- package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.numberrange/schema.d.ts +1 -1
- package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.numberrange/schema.js +11 -4
- package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.switch/config.d.vue.ts +10 -10
- package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.switch/config.vue.d.ts +10 -10
- package/dist/runtime/components/form/fields/2026-05-12/com.shwfed.form.field.upload/config.d.vue.ts +12 -12
- package/dist/runtime/components/form/fields/2026-05-12/com.shwfed.form.field.upload/config.vue.d.ts +12 -12
- package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.list/config.d.vue.ts +2 -2
- package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.list/config.vue +15 -0
- package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.list/config.vue.d.ts +2 -2
- package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.list/row.d.vue.ts +1 -0
- package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.list/row.vue +13 -4
- package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.list/row.vue.d.ts +1 -0
- package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.list/runtime.vue +1 -0
- package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.list/schema.d.ts +1 -1
- package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.list/schema.js +5 -1
- package/dist/runtime/components/form/fields/2026-05-18/com.shwfed.form.field.table/config.d.vue.ts +131 -0
- package/dist/runtime/components/form/fields/2026-05-18/com.shwfed.form.field.table/config.vue +170 -0
- package/dist/runtime/components/form/fields/2026-05-18/com.shwfed.form.field.table/config.vue.d.ts +131 -0
- package/dist/runtime/components/form/fields/2026-05-18/com.shwfed.form.field.table/runtime.d.vue.ts +8 -0
- package/dist/runtime/components/form/fields/2026-05-18/com.shwfed.form.field.table/runtime.vue +52 -0
- package/dist/runtime/components/form/fields/2026-05-18/com.shwfed.form.field.table/runtime.vue.d.ts +8 -0
- package/dist/runtime/components/form/fields/2026-05-18/com.shwfed.form.field.table/schema.d.ts +112 -0
- package/dist/runtime/components/form/fields/2026-05-18/com.shwfed.form.field.table/schema.js +44 -0
- package/dist/runtime/components/form/index.vue +5 -4
- package/dist/runtime/components/form/schema.d.ts +10 -0
- package/dist/runtime/components/form/schema.js +6 -2
- package/dist/runtime/components/form/unit-config.d.vue.ts +16 -0
- package/dist/runtime/components/form/unit-config.vue +30 -3
- package/dist/runtime/components/form/unit-config.vue.d.ts +16 -0
- package/dist/runtime/components/form/utils/cel-scope.d.ts +13 -0
- package/dist/runtime/components/form/utils/cel-scope.js +32 -0
- package/dist/runtime/components/form/utils/schema-meta.d.ts +13 -0
- package/dist/runtime/components/form/utils/schema-meta.js +15 -0
- package/dist/runtime/components/table/ai/columns-task.md +10 -1
- package/dist/runtime/components/table/columns/2026-04-14/com.shwfed.table.column.markdown/config.vue +2 -2
- package/dist/runtime/components/table/columns/2026-04-14/com.shwfed.table.column.markdown/runtime.vue +14 -4
- package/dist/runtime/components/table/columns/2026-04-14/com.shwfed.table.column.markdown/schema.js +3 -2
- package/dist/runtime/components/table/columns/2026-04-14/com.shwfed.table.column.text/config.vue +2 -2
- package/dist/runtime/components/table/columns/2026-04-14/com.shwfed.table.column.text/runtime.vue +14 -4
- package/dist/runtime/components/table/columns/2026-04-14/com.shwfed.table.column.text/schema.js +3 -2
- package/dist/runtime/components/table/config.d.vue.ts +11 -1
- package/dist/runtime/components/table/config.vue +4 -0
- package/dist/runtime/components/table/config.vue.d.ts +11 -1
- package/dist/runtime/components/table/index.d.vue.ts +4 -0
- package/dist/runtime/components/table/index.vue +28 -2
- package/dist/runtime/components/table/index.vue.d.ts +4 -0
- package/dist/runtime/components/table/schema.d.ts +12 -0
- package/dist/runtime/components/table/schema.js +6 -1
- package/dist/runtime/components/table/utils/shared.d.ts +2 -1
- package/dist/runtime/components/ui/date-range-picker/DateRangePickerDateTimePanel.d.vue.ts +1 -1
- package/dist/runtime/components/ui/date-range-picker/DateRangePickerDateTimePanel.vue.d.ts +1 -1
- package/dist/runtime/components/ui/date-range-picker/DateRangePickerTimeInput.d.vue.ts +1 -1
- package/dist/runtime/components/ui/date-range-picker/DateRangePickerTimeInput.vue.d.ts +1 -1
- package/dist/runtime/share/expression.d.ts +1 -2
- package/dist/runtime/share/slot-renderer.vue +7 -6
- package/dist/runtime/vendor/cel-js/CLAUDE.md +1 -1
- package/dist/runtime/vendor/cel-js/PROMPT.md +12 -3
- package/dist/runtime/vendor/cel-js/lib/http-builder.d.ts +10 -3
- package/dist/runtime/vendor/cel-js/lib/http-builder.js +28 -5
- package/dist/runtime/vendor/cel-js/lib/http-builtins.d.ts +4 -3
- package/dist/runtime/vendor/cel-js/lib/http-builtins.js +4 -0
- package/package.json +1 -1
|
@@ -23,6 +23,18 @@ export declare const metadata: {
|
|
|
23
23
|
readonly id: "clear-selection";
|
|
24
24
|
readonly name: "清空所有选中行";
|
|
25
25
|
readonly icon: "fluent:select-all-off-20-regular";
|
|
26
|
+
}, {
|
|
27
|
+
readonly id: "add-row";
|
|
28
|
+
readonly name: "新增一行";
|
|
29
|
+
readonly icon: "fluent:add-20-regular";
|
|
30
|
+
}, {
|
|
31
|
+
readonly id: "duplicate-selected";
|
|
32
|
+
readonly name: "复制选中行";
|
|
33
|
+
readonly icon: "fluent:copy-20-regular";
|
|
34
|
+
}, {
|
|
35
|
+
readonly id: "delete-selected";
|
|
36
|
+
readonly name: "删除选中行";
|
|
37
|
+
readonly icon: "fluent:delete-20-regular";
|
|
26
38
|
}];
|
|
27
39
|
};
|
|
28
40
|
declare const InitialState: Schema.Struct<{
|
|
@@ -13,11 +13,16 @@ export const metadata = {
|
|
|
13
13
|
// Atomic operations — compose them on one button (ordered triggers) to get
|
|
14
14
|
// the legacy combined behaviours. Only `search` actually fetches data;
|
|
15
15
|
// `reset-query` / `reset-pagination` / `clear-selection` just prepare state.
|
|
16
|
+
// The `*-row` / `*-selected` trio edits the row list locally — no server
|
|
17
|
+
// round-trip — for tables wired up as an editable surface.
|
|
16
18
|
operations: [
|
|
17
19
|
{ id: "reset-query", name: "\u91CD\u7F6E\u641C\u7D22\u6761\u4EF6", icon: "fluent:arrow-reset-20-regular" },
|
|
18
20
|
{ id: "reset-pagination", name: "\u91CD\u7F6E\u5206\u9875\u5E76\u6267\u884C\u641C\u7D22", icon: "fluent:arrow-previous-20-regular" },
|
|
19
21
|
{ id: "search", name: "\u6267\u884C\u641C\u7D22", icon: "fluent:search-20-regular" },
|
|
20
|
-
{ id: "clear-selection", name: "\u6E05\u7A7A\u6240\u6709\u9009\u4E2D\u884C", icon: "fluent:select-all-off-20-regular" }
|
|
22
|
+
{ id: "clear-selection", name: "\u6E05\u7A7A\u6240\u6709\u9009\u4E2D\u884C", icon: "fluent:select-all-off-20-regular" },
|
|
23
|
+
{ id: "add-row", name: "\u65B0\u589E\u4E00\u884C", icon: "fluent:add-20-regular" },
|
|
24
|
+
{ id: "duplicate-selected", name: "\u590D\u5236\u9009\u4E2D\u884C", icon: "fluent:copy-20-regular" },
|
|
25
|
+
{ id: "delete-selected", name: "\u5220\u9664\u9009\u4E2D\u884C", icon: "fluent:delete-20-regular" }
|
|
21
26
|
]
|
|
22
27
|
};
|
|
23
28
|
const SortItem = Schema.Struct({
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Schema } from 'effect';
|
|
2
2
|
import type { Environment } from '../../../vendor/cel-js/lib/index.js';
|
|
3
|
+
import { type ResultType } from '../../../share/expression.js';
|
|
3
4
|
export declare const Align: Schema.Literal<["left", "center", "right"]>;
|
|
4
5
|
export declare function columnIdentityFields(): {
|
|
5
6
|
id: Schema.refine<string, typeof Schema.String>;
|
|
@@ -29,7 +30,7 @@ export declare function columnFields(configure: (env: Environment) => void): {
|
|
|
29
30
|
};
|
|
30
31
|
export declare function registerRowVariablesIfAbsent(env: Environment): void;
|
|
31
32
|
export declare function CelRowAccess(configure: (env: Environment) => void, options?: {
|
|
32
|
-
resultType?:
|
|
33
|
+
resultType?: ResultType;
|
|
33
34
|
}): Schema.Schema<string, string, never>;
|
|
34
35
|
export declare function LocaleMarkdownWithRow(configure: (env: Environment) => void): Schema.filter<Schema.TupleType<readonly [Schema.Struct<{
|
|
35
36
|
locale: Schema.Literal<["zh"]>;
|
|
@@ -14,10 +14,10 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
|
|
|
14
14
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
15
15
|
"onUpdate:modelValue"?: ((args_0: DateRange | undefined) => any) | undefined;
|
|
16
16
|
}>, {
|
|
17
|
+
rangeSeparatorIcon: string;
|
|
17
18
|
numberOfMonths: number;
|
|
18
19
|
granularity: "hour" | "minute" | "second";
|
|
19
20
|
hourCycle: 12 | 24;
|
|
20
|
-
rangeSeparatorIcon: string;
|
|
21
21
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
22
22
|
declare const _default: typeof __VLS_export;
|
|
23
23
|
export default _default;
|
|
@@ -14,10 +14,10 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
|
|
|
14
14
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
15
15
|
"onUpdate:modelValue"?: ((args_0: DateRange | undefined) => any) | undefined;
|
|
16
16
|
}>, {
|
|
17
|
+
rangeSeparatorIcon: string;
|
|
17
18
|
numberOfMonths: number;
|
|
18
19
|
granularity: "hour" | "minute" | "second";
|
|
19
20
|
hourCycle: 12 | 24;
|
|
20
|
-
rangeSeparatorIcon: string;
|
|
21
21
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
22
22
|
declare const _default: typeof __VLS_export;
|
|
23
23
|
export default _default;
|
|
@@ -24,11 +24,11 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
|
|
|
24
24
|
"onUpdate:endValue"?: ((args_0: Time | undefined) => any) | undefined;
|
|
25
25
|
}>, {
|
|
26
26
|
size: "sm" | "md" | "lg";
|
|
27
|
+
rangeSeparatorIcon: string;
|
|
27
28
|
granularity: "hour" | "minute" | "second";
|
|
28
29
|
hourCycle: 12 | 24;
|
|
29
30
|
clearable: boolean;
|
|
30
31
|
clearIcon: string;
|
|
31
|
-
rangeSeparatorIcon: string;
|
|
32
32
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
33
33
|
declare const _default: typeof __VLS_export;
|
|
34
34
|
export default _default;
|
|
@@ -24,11 +24,11 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
|
|
|
24
24
|
"onUpdate:endValue"?: ((args_0: Time | undefined) => any) | undefined;
|
|
25
25
|
}>, {
|
|
26
26
|
size: "sm" | "md" | "lg";
|
|
27
|
+
rangeSeparatorIcon: string;
|
|
27
28
|
granularity: "hour" | "minute" | "second";
|
|
28
29
|
hourCycle: 12 | 24;
|
|
29
30
|
clearable: boolean;
|
|
30
31
|
clearIcon: string;
|
|
31
|
-
rangeSeparatorIcon: string;
|
|
32
32
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
33
33
|
declare const _default: typeof __VLS_export;
|
|
34
34
|
export default _default;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Schema } from 'effect';
|
|
2
2
|
import { Environment } from '../vendor/cel-js/lib/index.js';
|
|
3
3
|
import { Locale } from './locale.js';
|
|
4
|
-
type ResultType = string | string[] | ((type: string) => boolean);
|
|
4
|
+
export type ResultType = string | string[] | ((type: string) => boolean);
|
|
5
5
|
export declare function Expression(options: {
|
|
6
6
|
configure: (env: Environment) => void;
|
|
7
7
|
resultType?: ResultType;
|
|
@@ -19,4 +19,3 @@ export declare function Markdown(options: {
|
|
|
19
19
|
export declare function LocaleMarkdown(options: {
|
|
20
20
|
configure: (env: Environment) => void;
|
|
21
21
|
}): Schema.filter<typeof Locale>;
|
|
22
|
-
export {};
|
|
@@ -35,14 +35,15 @@ watch(() => props.slotValue.layouts, (sets) => {
|
|
|
35
35
|
const gridStyle = computed(() => {
|
|
36
36
|
const l = activeLayout.value?.layout;
|
|
37
37
|
if (!l) return "";
|
|
38
|
-
const tracks = (n) => `repeat(${n}, minmax(
|
|
38
|
+
const tracks = (n, min) => `repeat(${n}, minmax(${min}, 1fr))`;
|
|
39
|
+
const gap = `calc(${l.gap ?? DEFAULT_GAP} * 0.25rem)`;
|
|
40
|
+
const colGap = l.columns > 1 ? `min(${gap}, calc(100% / ${l.columns - 1}))` : gap;
|
|
39
41
|
const parts = [
|
|
40
42
|
"display: grid",
|
|
41
|
-
`grid-template-columns: ${tracks(l.columns)}`,
|
|
42
|
-
l.rows ? `grid-template-rows: ${tracks(l.rows)}` : "",
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
`gap: calc(${l.gap ?? DEFAULT_GAP} * 0.25rem)`,
|
|
43
|
+
`grid-template-columns: ${tracks(l.columns, "0")}`,
|
|
44
|
+
l.rows ? `grid-template-rows: ${tracks(l.rows, "auto")}` : "",
|
|
45
|
+
`column-gap: ${colGap}`,
|
|
46
|
+
`row-gap: ${gap}`,
|
|
46
47
|
l.style ?? ""
|
|
47
48
|
].filter(Boolean);
|
|
48
49
|
return parts.join("; ");
|
|
@@ -20,7 +20,7 @@ The `homogeneousAggregateLiterals` and `enableOptionalTypes` environment options
|
|
|
20
20
|
|
|
21
21
|
The custom `Optional` class has been replaced with Effect's `Option` type (`import { Option } from 'effect'`). Internal helpers `optionalOf(value)` and `optionalValue(opt)` in `optional.js` handle the CEL-specific semantics (treating `undefined` as `None`, throwing `EvaluationError` on missing value access).
|
|
22
22
|
|
|
23
|
-
An `http` built-in has been added (`http-builtins.ts`, `http-builder.ts`) — not from upstream. It registers the `http` constant and the `http` / `HttpRequest` types on `globalRegistry`, so `http.get(url).header(...).body(...)` expressions type-check and evaluate in every `Environment`. A CEL expression
|
|
23
|
+
An `http` built-in has been added (`http-builtins.ts`, `http-builder.ts`) — not from upstream. It registers the `http` constant and the `http` / `HttpRequest` types on `globalRegistry`, so `http.get(url).header(...).body(...)` expressions type-check and evaluate in every `Environment`. A CEL expression builds an `HttpRequestBuilder`; the terminal `HttpRequest.file(): File` method issues the request and evaluates to the downloaded `File`, while `.json()` is dispatched by the host on the builder value (it is not a CEL method). Endpoints must be absolute URLs — there is no base-URL resolution. Depends on `fx-fetch`.
|
|
24
24
|
|
|
25
25
|
## Architecture
|
|
26
26
|
|
|
@@ -197,7 +197,7 @@ location.param("id") // first value when a param repeats
|
|
|
197
197
|
|
|
198
198
|
## HTTP
|
|
199
199
|
|
|
200
|
-
Build HTTP requests using the `http` builder. CEL
|
|
200
|
+
Build HTTP requests using the `http` builder. A CEL expression *describes* a request; calling `.file()` on it issues the request and evaluates to the downloaded `File`. Any other request is handed to the host to dispatch — there is no way to read a JSON or text response from CEL.
|
|
201
201
|
|
|
202
202
|
**URLs must be absolute** — pass a full `https://…` URL. There is no base URL, so relative paths like `/api/users` will not resolve.
|
|
203
203
|
|
|
@@ -229,12 +229,21 @@ http.get("https://api.example.com/users")
|
|
|
229
229
|
.query(form)
|
|
230
230
|
.query("page", string(pageIndex))
|
|
231
231
|
|
|
232
|
-
// Set request body
|
|
232
|
+
// Set request body. An object serializes to JSON; set the Content-Type
|
|
233
|
+
// header yourself. Optional values are unwrapped — a present `.?` field
|
|
234
|
+
// keeps its value, an absent one becomes `null` (the key is kept):
|
|
233
235
|
http.post("https://api.example.com/users")
|
|
234
|
-
.
|
|
236
|
+
.header("Content-Type", "application/json")
|
|
237
|
+
.body({"name": "Alice", "channel": query.?channel})
|
|
238
|
+
|
|
239
|
+
// Download the response as a File. Unlike the chainable methods above,
|
|
240
|
+
// .file() is terminal — it issues the request and the expression evaluates
|
|
241
|
+
// to a File (filename from the Content-Disposition header, else the URL path):
|
|
242
|
+
http.get("https://api.example.com/files/report.pdf").file()
|
|
235
243
|
|
|
236
244
|
// Full example — the expression returns an HttpRequest; the host sends it:
|
|
237
245
|
http.post("https://api.example.com/users")
|
|
246
|
+
.header("Content-Type", "application/json")
|
|
238
247
|
.header("Authorization", "Bearer " + token)
|
|
239
248
|
.body({"name": "Alice"})
|
|
240
249
|
```
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `HttpRequestBuilder` — the value an `http.*` CEL expression evaluates to.
|
|
3
3
|
*
|
|
4
|
-
* A local (non-upstream) extension. CEL
|
|
5
|
-
*
|
|
4
|
+
* A local (non-upstream) extension. A CEL expression builds and *describes* a
|
|
5
|
+
* request; `.file()` is exposed as a CEL method and evaluates to the downloaded
|
|
6
|
+
* `File`, while `.json()` is dispatched by the host on the returned builder.
|
|
6
7
|
*
|
|
7
8
|
* Endpoints are used verbatim — there is no base-URL resolution, so callers
|
|
8
9
|
* must pass absolute URLs.
|
|
@@ -15,7 +16,13 @@ export declare class HttpRequestBuilder {
|
|
|
15
16
|
header(name: string, value: string): this;
|
|
16
17
|
query(key: string, value: string | number): this;
|
|
17
18
|
query(record: Record<string, unknown>): this;
|
|
18
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Set the request body. A pre-built `FormData` / `Blob` / `ArrayBuffer` /
|
|
21
|
+
* string is used verbatim; anything else is normalized (see
|
|
22
|
+
* `normalizeBody`) and JSON-serialized. The `Content-Type` header is *not*
|
|
23
|
+
* set here — the caller adds `.header('Content-Type', …)` explicitly.
|
|
24
|
+
*/
|
|
25
|
+
body(data: unknown): this;
|
|
19
26
|
/**
|
|
20
27
|
* A structural snapshot of the request this builder will issue — an equal
|
|
21
28
|
* snapshot means an equal HTTP request. Handy for change-detection, e.g.
|
|
@@ -1,9 +1,28 @@
|
|
|
1
|
-
import { Effect } from "effect";
|
|
1
|
+
import { Effect, Option } from "effect";
|
|
2
2
|
import {
|
|
3
3
|
Fetch,
|
|
4
4
|
Request as FxRequest,
|
|
5
5
|
Response as FxResponse
|
|
6
6
|
} from "fx-fetch";
|
|
7
|
+
import { Decimal } from "./decimal.js";
|
|
8
|
+
function normalizeBody(value) {
|
|
9
|
+
if (value === null || value === void 0) return value;
|
|
10
|
+
if (value instanceof Decimal) return value.toNumber();
|
|
11
|
+
if (Option.isOption(value)) {
|
|
12
|
+
return Option.isSome(value) ? normalizeBody(value.value) : null;
|
|
13
|
+
}
|
|
14
|
+
if (Array.isArray(value)) return value.map(normalizeBody);
|
|
15
|
+
if (typeof value === "object") {
|
|
16
|
+
const proto = Object.getPrototypeOf(value);
|
|
17
|
+
if (proto !== Object.prototype && proto !== null) return value;
|
|
18
|
+
const out = {};
|
|
19
|
+
for (const key of Object.keys(value)) {
|
|
20
|
+
out[key] = normalizeBody(value[key]);
|
|
21
|
+
}
|
|
22
|
+
return out;
|
|
23
|
+
}
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
7
26
|
function extractFilename(response, url) {
|
|
8
27
|
const disposition = FxResponse.getHeader(response, "content-disposition");
|
|
9
28
|
if (disposition) {
|
|
@@ -53,11 +72,15 @@ export class HttpRequestBuilder {
|
|
|
53
72
|
}
|
|
54
73
|
throw new Error(`query: nested object values are not supported (key: "${key}")`);
|
|
55
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Set the request body. A pre-built `FormData` / `Blob` / `ArrayBuffer` /
|
|
77
|
+
* string is used verbatim; anything else is normalized (see
|
|
78
|
+
* `normalizeBody`) and JSON-serialized. The `Content-Type` header is *not*
|
|
79
|
+
* set here — the caller adds `.header('Content-Type', …)` explicitly.
|
|
80
|
+
*/
|
|
56
81
|
body(data) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
this.#headers.push(["Content-Type", "application/json"]);
|
|
60
|
-
}
|
|
82
|
+
const value = normalizeBody(data);
|
|
83
|
+
this.#body = value instanceof FormData || value instanceof Blob || value instanceof ArrayBuffer || typeof value === "string" ? value : JSON.stringify(value);
|
|
61
84
|
return this;
|
|
62
85
|
}
|
|
63
86
|
/**
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
* HTTP built-ins for CEL — a local (non-upstream) extension.
|
|
3
3
|
*
|
|
4
4
|
* Registers the `http` / `HttpRequest` types, the `http` constant, and the
|
|
5
|
-
* request-builder functions on the registry.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* request-builder functions on the registry. `http.get(url).header(...).body(...)`
|
|
6
|
+
* builds an `HttpRequestBuilder`; the terminal `.file()` method issues the
|
|
7
|
+
* request and evaluates to the downloaded `File`. `.json()` is *not* a CEL
|
|
8
|
+
* method — the host dispatches that on the returned builder value.
|
|
8
9
|
*
|
|
9
10
|
* Wired into `globalRegistry` at module load (see `evaluator.ts`), so every
|
|
10
11
|
* `Environment` gets HTTP for free — both type-checking and evaluation.
|