@shwfed/config 2.11.1 → 2.11.4

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 (127) hide show
  1. package/dist/mcp.mjs +1416 -1211
  2. package/dist/module.json +1 -1
  3. package/dist/preview/assets/{FieldGroup.vue_vue_type_script_setup_true_lang-CosmpPSu.js → FieldGroup.vue_vue_type_script_setup_true_lang-BE68tZWF.js} +1 -1
  4. package/dist/preview/assets/{badge-BkYCxTFK.js → badge-CGMjdhLX.js} +1 -1
  5. package/dist/preview/assets/config-B7TZ-128.js +1 -0
  6. package/dist/preview/assets/{config-B62b9dMF.js → config-BSym_jQg.js} +1 -1
  7. package/dist/preview/assets/{config-Cbp7aAAw.js → config-ByCFJbd-.js} +1 -1
  8. package/dist/preview/assets/{config-Bbbyd5lB.js → config-C4cv2S64.js} +1 -1
  9. package/dist/preview/assets/{config-Dt8k1gnT.js → config-ChrJHusi.js} +1 -1
  10. package/dist/preview/assets/config-CxbYENZ0.js +1 -0
  11. package/dist/preview/assets/{config-Bt6--diX.js → config-DFS2XL3-.js} +1 -1
  12. package/dist/preview/assets/{config-C_Ia1CDq.js → config-DWj1CTai.js} +1 -1
  13. package/dist/preview/assets/{config-BcZe-bR9.js → config-DZI21_UB.js} +1 -1
  14. package/dist/preview/assets/{config-CPsd0ppi.js → config-D_O4ACtH.js} +1 -1
  15. package/dist/preview/assets/{config-Dk9OegYx.js → config-DjA8bfLm.js} +1 -1
  16. package/dist/preview/assets/{config-74YmXQsH.js → config-DwPGLI3R.js} +1 -1
  17. package/dist/preview/assets/{config-sCP15_0f.js → config-dkVvsr4h.js} +1 -1
  18. package/dist/preview/assets/{config-CYVafGLc.js → config-hsH0bSZh.js} +1 -1
  19. package/dist/preview/assets/{config-COr2MFhN.js → config-xrfje67L.js} +1 -1
  20. package/dist/preview/assets/{definition.vue_vue_type_script_setup_true_lang-C3NiB99t.js → definition.vue_vue_type_script_setup_true_lang-BGk00yfB.js} +1 -1
  21. package/dist/preview/assets/index-B4oT9ZrQ.js +1 -0
  22. package/dist/preview/assets/{index-DjG-VVR4.js → index-BSQlKkJR.js} +214 -202
  23. package/dist/preview/assets/{index-BMOizF8g.js → index-CzQKNngS.js} +1 -1
  24. package/dist/preview/assets/index-DPFQgj9g.css +1 -0
  25. package/dist/preview/assets/{item-C1efxuFt.js → item-D4gmvDO-.js} +1 -1
  26. package/dist/preview/assets/{runtime-LgZuN2Tf.js → runtime--e0UxK6b.js} +1 -1
  27. package/dist/preview/assets/runtime-BWH8ForT.js +1 -0
  28. package/dist/preview/assets/runtime-BgO2briD.js +1 -0
  29. package/dist/preview/assets/{runtime-DoLpKFu-.js → runtime-BmEP7xID.js} +1 -1
  30. package/dist/preview/assets/runtime-C66GF-2d.js +1 -0
  31. package/dist/preview/assets/{runtime-7z9N9JGG.js → runtime-CJCOS6D_.js} +1 -1
  32. package/dist/preview/assets/{runtime-S9eZ2nJS.js → runtime-CREolKJd.js} +1 -1
  33. package/dist/preview/assets/runtime-CjU46djh.js +1 -0
  34. package/dist/preview/assets/{runtime-Du0ghzR2.js → runtime-e59FkBkL.js} +1 -1
  35. package/dist/preview/assets/runtime-pYLX1Bb-.js +1 -0
  36. package/dist/preview/assets/{runtime-Dz7SCudL.js → runtime-wvP7jhBK.js} +1 -1
  37. package/dist/preview/assets/{schema-meta-CYKPEnu9.js → schema-meta-C4Ttq3eE.js} +1 -1
  38. package/dist/preview/index.html +2 -2
  39. package/dist/runtime/components/actions/buttons/2026-06-25/com.shwfed.actions.button.state.write/config.d.vue.ts +39 -0
  40. package/dist/runtime/components/actions/buttons/2026-06-25/com.shwfed.actions.button.state.write/config.vue +127 -0
  41. package/dist/runtime/components/actions/buttons/2026-06-25/com.shwfed.actions.button.state.write/config.vue.d.ts +39 -0
  42. package/dist/runtime/components/actions/buttons/2026-06-25/com.shwfed.actions.button.state.write/runtime.d.vue.ts +8 -0
  43. package/dist/runtime/components/actions/buttons/2026-06-25/com.shwfed.actions.button.state.write/runtime.vue +62 -0
  44. package/dist/runtime/components/actions/buttons/2026-06-25/com.shwfed.actions.button.state.write/runtime.vue.d.ts +8 -0
  45. package/dist/runtime/components/actions/buttons/2026-06-25/com.shwfed.actions.button.state.write/schema.d.ts +25 -0
  46. package/dist/runtime/components/actions/buttons/2026-06-25/com.shwfed.actions.button.state.write/schema.js +41 -0
  47. package/dist/runtime/components/config/blocks/2026-06-17/com.shwfed.block.tree.single/runtime.vue +5 -22
  48. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/config.d.vue.ts +70 -0
  49. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/config.vue +349 -0
  50. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/config.vue.d.ts +70 -0
  51. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/loop-item.d.vue.ts +33 -0
  52. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/loop-item.vue +37 -0
  53. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/loop-item.vue.d.ts +33 -0
  54. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/loop-scope-provider.d.vue.ts +13 -0
  55. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/loop-scope-provider.vue +22 -0
  56. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/loop-scope-provider.vue.d.ts +13 -0
  57. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/runtime.d.vue.ts +70 -0
  58. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/runtime.vue +62 -0
  59. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/runtime.vue.d.ts +70 -0
  60. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/schema.d.ts +85 -0
  61. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/schema.js +60 -0
  62. package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.textarea/config.d.vue.ts +2 -2
  63. package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.textarea/config.vue.d.ts +2 -2
  64. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.d.vue.ts +4 -4
  65. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.vue.d.ts +4 -4
  66. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.d.vue.ts +6 -6
  67. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.vue.d.ts +6 -6
  68. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/config.d.vue.ts +2 -2
  69. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/config.vue.d.ts +2 -2
  70. package/dist/runtime/components/form/fields/2026-05-23/com.shwfed.form.field.tree.multi/config.d.vue.ts +22 -22
  71. package/dist/runtime/components/form/fields/2026-05-23/com.shwfed.form.field.tree.multi/config.vue.d.ts +22 -22
  72. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.monthrange/config.d.vue.ts +4 -4
  73. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.monthrange/config.vue.d.ts +4 -4
  74. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/config.d.vue.ts +22 -22
  75. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/config.vue.d.ts +22 -22
  76. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/config.d.vue.ts +22 -22
  77. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/config.vue.d.ts +22 -22
  78. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/config.d.vue.ts +22 -22
  79. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/config.vue.d.ts +22 -22
  80. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/config.d.vue.ts +22 -22
  81. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/config.vue.d.ts +22 -22
  82. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/config.d.vue.ts +22 -22
  83. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/config.vue.d.ts +22 -22
  84. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/runtime.vue +2 -19
  85. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/config.d.vue.ts +22 -22
  86. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/config.vue.d.ts +22 -22
  87. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/runtime.vue +5 -22
  88. package/dist/runtime/components/operations/2026-06-15/com.shwfed.operation.http.download/config.d.vue.ts +2 -0
  89. package/dist/runtime/components/operations/2026-06-15/com.shwfed.operation.http.download/config.vue +49 -22
  90. package/dist/runtime/components/operations/2026-06-15/com.shwfed.operation.http.download/config.vue.d.ts +2 -0
  91. package/dist/runtime/components/operations/2026-06-15/com.shwfed.operation.http.download/runtime.js +17 -10
  92. package/dist/runtime/components/operations/2026-06-15/com.shwfed.operation.http.download/schema.d.ts +1 -0
  93. package/dist/runtime/components/operations/2026-06-15/com.shwfed.operation.http.download/schema.js +25 -3
  94. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-remote/config.d.vue.ts +2 -2
  95. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-remote/config.vue.d.ts +2 -2
  96. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-static/config.d.vue.ts +2 -2
  97. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-static/config.vue.d.ts +2 -2
  98. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-remote/config.d.vue.ts +2 -2
  99. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-remote/config.vue.d.ts +2 -2
  100. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-static/config.d.vue.ts +2 -2
  101. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-static/config.vue.d.ts +2 -2
  102. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/config.d.vue.ts +2 -2
  103. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/config.vue.d.ts +2 -2
  104. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single.remote/config.d.vue.ts +2 -2
  105. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single.remote/config.vue.d.ts +2 -2
  106. package/dist/runtime/components/ui/date-picker/DatePickerInput.d.vue.ts +1 -1
  107. package/dist/runtime/components/ui/date-picker/DatePickerInput.vue.d.ts +1 -1
  108. package/dist/runtime/components/ui/date-picker/DatePickerTimeInput.d.vue.ts +1 -1
  109. package/dist/runtime/components/ui/date-picker/DatePickerTimeInput.vue.d.ts +1 -1
  110. package/dist/runtime/components/ui/date-range-picker/DateRangePickerInput.d.vue.ts +1 -1
  111. package/dist/runtime/components/ui/date-range-picker/DateRangePickerInput.vue.d.ts +1 -1
  112. package/dist/runtime/components/ui/date-range-picker/DateRangePickerTimeInput.d.vue.ts +2 -2
  113. package/dist/runtime/components/ui/date-range-picker/DateRangePickerTimeInput.vue.d.ts +2 -2
  114. package/dist/runtime/components/ui/expression-editor/ExpressionEditor.vue +1 -1
  115. package/dist/runtime/share/loop-item-var.d.ts +21 -0
  116. package/dist/runtime/share/loop-item-var.js +13 -0
  117. package/dist/runtime/vendor/cel-js/CLAUDE.md +1 -1
  118. package/dist/runtime/vendor/cel-js/lib/http-builder.d.ts +38 -3
  119. package/dist/runtime/vendor/cel-js/lib/http-builder.js +33 -0
  120. package/package.json +1 -1
  121. package/dist/preview/assets/config-BHYlKhDX.js +0 -1
  122. package/dist/preview/assets/index-C9G8y6qZ.js +0 -1
  123. package/dist/preview/assets/index-DqRQ67sX.css +0 -1
  124. package/dist/preview/assets/runtime-Bpa1zRxG.js +0 -1
  125. package/dist/preview/assets/runtime-Csv04MYG.js +0 -1
  126. package/dist/preview/assets/runtime-D0bjM4NL.js +0 -1
  127. package/dist/preview/assets/runtime-Dz3ZQYdq.js +0 -1
@@ -10,6 +10,7 @@ class HttpRequestHalted {
10
10
  }
11
11
  _tag = "HttpRequestHalted";
12
12
  }
13
+ const TOAST_STYLES = /* @__PURE__ */ new Set(["success", "error", "warning", "info"]);
13
14
  function saveFile(file) {
14
15
  const url = URL.createObjectURL(file);
15
16
  const a = document.createElement("a");
@@ -21,28 +22,34 @@ function saveFile(file) {
21
22
  URL.revokeObjectURL(url);
22
23
  }
23
24
  export const handler = (params, ctx) => {
24
- const { expression, titleExpression, description } = params ?? {};
25
+ const { expression, resultExpression, titleExpression, description } = params ?? {};
25
26
  if (!expression || expression.trim().length === 0) return Effect.void;
26
27
  const program = Effect.gen(function* () {
27
28
  const steps = ctx.step?.outputs() ?? {};
28
29
  const evaluated = yield* ctx.cel(expression, { steps });
29
30
  const request = asRequest(evaluated);
30
31
  if (Option.isNone(request)) return;
31
- const outcome = yield* Effect.either(request.value.file());
32
- const result = Either.isLeft(outcome) ? "error" : "success";
32
+ const outcome = yield* Effect.either(request.value.fileOrJson());
33
+ const json = Either.isRight(outcome) && outcome.right._tag === "json" ? outcome.right.json : null;
34
+ const result = Either.isLeft(outcome) ? "error" : outcome.right._tag === "file" ? "success" : resultExpression === void 0 ? "error" : yield* ctx.cel(resultExpression, { json, steps });
35
+ const kind = TOAST_STYLES.has(result) ? result : "success";
33
36
  if (titleExpression !== void 0) {
34
- const title = yield* ctx.cel(titleExpression, { result, steps });
37
+ const title = yield* ctx.cel(titleExpression, { json, result, steps });
35
38
  if (title.length > 0) {
36
39
  const raw = getLocalizedText(description, ctx.locale()) ?? "";
37
- const body = raw.length === 0 ? void 0 : interpolateMarkdown(raw, ctx.cel, { result, steps });
38
- toast[result === "error" ? "error" : "success"](title, body === void 0 ? void 0 : { description: body });
40
+ const body = raw.length === 0 ? void 0 : interpolateMarkdown(raw, ctx.cel, { json, result, steps });
41
+ toast[kind](title, body === void 0 ? void 0 : { description: body });
39
42
  }
40
43
  }
41
44
  if (Either.isLeft(outcome)) {
42
45
  if (import.meta.dev) console.warn("[shwfed-operations] http download failed", outcome.left);
43
46
  return yield* Effect.die(new HttpRequestHalted(outcome.left));
44
47
  }
45
- yield* Effect.sync(() => saveFile(outcome.right));
48
+ if (kind === "error") return yield* Effect.die(new HttpRequestHalted("error result"));
49
+ if (outcome.right._tag === "file") {
50
+ const { file } = outcome.right;
51
+ yield* Effect.sync(() => saveFile(file));
52
+ }
46
53
  });
47
54
  return program.pipe(
48
55
  // The bus's handler contract has no requirements channel, so the host can't
@@ -50,9 +57,9 @@ export const handler = (params, ctx) => {
50
57
  // button runner uses.
51
58
  Effect.provide(Fetch.layer),
52
59
  // What remains on the error channel is CEL evaluation failure (request /
53
- // title expression) — a config bug, not a runtime outcome. Mirror the
54
- // request op: silent in prod, console in dev; the chain still halts so later
55
- // operations don't fire off a broken step.
60
+ // result / title expression) — a config bug, not a runtime outcome. Mirror
61
+ // the request op: silent in prod, console in dev; the chain still halts so
62
+ // later operations don't fire off a broken step.
56
63
  Effect.catchAll((error) => Effect.zipRight(
57
64
  Effect.sync(() => {
58
65
  if (import.meta.dev) console.warn("[shwfed-operations] http download op failed", error);
@@ -8,6 +8,7 @@ export declare const metadata: {
8
8
  };
9
9
  export declare function schema(configure: (env: Environment) => void): Schema.Struct<{
10
10
  expression: Schema.Schema<string, string, never>;
11
+ resultExpression: Schema.optional<Schema.Schema<string, string, never>>;
11
12
  titleExpression: Schema.optional<Schema.Schema<string, string, never>>;
12
13
  description: Schema.optional<Schema.TupleType<readonly [Schema.Struct<{
13
14
  locale: Schema.Literal<["zh"]>;
@@ -18,10 +18,20 @@ export function schema(configure) {
18
18
  registerStepsVariableIfAbsent(env);
19
19
  };
20
20
  const CelHttpRequest = Expression({ configure: withSteps, resultType: "HttpRequest" });
21
+ const withJson = (env) => {
22
+ withSteps(env);
23
+ env.registerVariable("json", "dyn", {
24
+ description: "\u54CD\u5E94\u4F53\uFF08\u5DF2\u89E3\u6790 JSON\uFF1B\u4EC5\u5F53\u54CD\u5E94\u4E3A JSON \u65F6\u5B58\u5728\uFF09"
25
+ });
26
+ };
27
+ const CelResultString = Expression({ configure: withJson, resultType: "string" });
21
28
  const withOutcome = (env) => {
22
29
  withSteps(env);
30
+ env.registerVariable("json", "dyn", {
31
+ description: "\u54CD\u5E94\u4F53\uFF08\u5DF2\u89E3\u6790 JSON\uFF1B\u54CD\u5E94\u975E JSON \u6216\u8BF7\u6C42\u5931\u8D25\u65F6\u4E3A null\uFF09"
32
+ });
23
33
  env.registerVariable("result", "string", {
24
- description: "\u6267\u884C\u7ED3\u679C\uFF08success | error\uFF09"
34
+ description: "\u300C\u6267\u884C\u7ED3\u679C\u300D\u8868\u8FBE\u5F0F\u7684\u503C\uFF08\u8BF7\u6C42\u5931\u8D25\u65F6\u4E3A error\uFF09"
25
35
  });
26
36
  };
27
37
  const CelToastString = Expression({ configure: withOutcome, resultType: "string" });
@@ -34,6 +44,17 @@ export function schema(configure) {
34
44
  \`发送请求\` 行取得的凭据用于构造真正的下载请求。
35
45
  `
36
46
  }),
47
+ resultExpression: Schema.optional(CelResultString.annotations({
48
+ title: "\u6267\u884C\u7ED3\u679C",
49
+ description: md`
50
+ 仅当响应为 JSON(\`application/json\`)时求值——下载本应返回二进制文件,
51
+ 响应为 JSON 通常意味着后端返回了错误信封(常见为 HTTP 200 + \`{ "code": -1 }\`)。
52
+ 需返回 \`'success' | 'warning' | 'error' | 'info'\` 中的**一个**,如
53
+ \`json.code == 0 ? 'success' : 'error'\`。\`error\` 中止本次触发链。
54
+ 不配置时,JSON 响应一律按 \`error\` 处理(多数情况即如此,但你可经此表达式自行裁定)。
55
+ 网络错误 / 非 2xx 等情况下,恒按 \`error\` 处理。
56
+ `
57
+ })),
37
58
  titleExpression: Schema.optional(CelToastString.annotations({
38
59
  title: "\u63D0\u793A\u6807\u9898",
39
60
  description: md`
@@ -50,8 +71,9 @@ export function schema(configure) {
50
71
  }).annotations({
51
72
  title: "HttpDownloadOperation",
52
73
  description: md`
53
- 发起一次 HTTP 请求并把响应保存为本地文件。下载失败(网络错误 / 非 2xx)
54
- 会中止本次触发链——其后排队的操作不再执行。把本操作接在一个
74
+ 发起一次 HTTP 请求:若响应是二进制(非 JSON)则保存为本地文件;若响应是 JSON,
75
+ 则视为后端返回的状态信封,经「执行结果」裁定成败而**不**保存。下载失败(网络错误 / 非 2xx)
76
+ 或「执行结果」为 \`error\` 会中止本次触发链——其后排队的操作不再执行。把本操作接在一个
55
77
  \`发送请求\` 行之后、并经 \`steps["<步骤标识>"]\` 引用其响应,即可实现
56
78
  “先取凭据再下载”的两步式。toast 完全由「提示标题」「提示内容」决定(含失败场景);
57
79
  不配置标题、或标题求值为空字符串则静默。
@@ -53,9 +53,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
53
53
  readonly locale: "en" | "ja" | "ko";
54
54
  readonly message: string;
55
55
  }[]];
56
- readonly sortKey?: string | undefined;
57
56
  readonly successMessage?: string | undefined;
58
57
  readonly accessor?: string | undefined;
58
+ readonly sortKey?: string | undefined;
59
59
  }) => any;
60
60
  }, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
61
61
  "onUpdate:modelValue"?: ((value: {
@@ -108,9 +108,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
108
108
  readonly locale: "en" | "ja" | "ko";
109
109
  readonly message: string;
110
110
  }[]];
111
- readonly sortKey?: string | undefined;
112
111
  readonly successMessage?: string | undefined;
113
112
  readonly accessor?: string | undefined;
113
+ readonly sortKey?: string | undefined;
114
114
  }) => any) | undefined;
115
115
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
116
116
  declare const _default: typeof __VLS_export;
@@ -53,9 +53,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
53
53
  readonly locale: "en" | "ja" | "ko";
54
54
  readonly message: string;
55
55
  }[]];
56
- readonly sortKey?: string | undefined;
57
56
  readonly successMessage?: string | undefined;
58
57
  readonly accessor?: string | undefined;
58
+ readonly sortKey?: string | undefined;
59
59
  }) => any;
60
60
  }, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
61
61
  "onUpdate:modelValue"?: ((value: {
@@ -108,9 +108,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
108
108
  readonly locale: "en" | "ja" | "ko";
109
109
  readonly message: string;
110
110
  }[]];
111
- readonly sortKey?: string | undefined;
112
111
  readonly successMessage?: string | undefined;
113
112
  readonly accessor?: string | undefined;
113
+ readonly sortKey?: string | undefined;
114
114
  }) => any) | undefined;
115
115
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
116
116
  declare const _default: typeof __VLS_export;
@@ -67,9 +67,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
67
67
  }[]] | undefined;
68
68
  readonly readonly?: string | undefined;
69
69
  readonly enableSorting?: boolean | undefined;
70
- readonly sortKey?: string | undefined;
71
70
  readonly successMessage?: string | undefined;
72
71
  readonly accessor?: string | undefined;
72
+ readonly sortKey?: string | undefined;
73
73
  }) => any;
74
74
  }, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
75
75
  "onUpdate:modelValue"?: ((value: {
@@ -136,9 +136,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
136
136
  }[]] | undefined;
137
137
  readonly readonly?: string | undefined;
138
138
  readonly enableSorting?: boolean | undefined;
139
- readonly sortKey?: string | undefined;
140
139
  readonly successMessage?: string | undefined;
141
140
  readonly accessor?: string | undefined;
141
+ readonly sortKey?: string | undefined;
142
142
  }) => any) | undefined;
143
143
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
144
144
  declare const _default: typeof __VLS_export;
@@ -67,9 +67,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
67
67
  }[]] | undefined;
68
68
  readonly readonly?: string | undefined;
69
69
  readonly enableSorting?: boolean | undefined;
70
- readonly sortKey?: string | undefined;
71
70
  readonly successMessage?: string | undefined;
72
71
  readonly accessor?: string | undefined;
72
+ readonly sortKey?: string | undefined;
73
73
  }) => any;
74
74
  }, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
75
75
  "onUpdate:modelValue"?: ((value: {
@@ -136,9 +136,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
136
136
  }[]] | undefined;
137
137
  readonly readonly?: string | undefined;
138
138
  readonly enableSorting?: boolean | undefined;
139
- readonly sortKey?: string | undefined;
140
139
  readonly successMessage?: string | undefined;
141
140
  readonly accessor?: string | undefined;
141
+ readonly sortKey?: string | undefined;
142
142
  }) => any) | undefined;
143
143
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
144
144
  declare const _default: typeof __VLS_export;
@@ -53,9 +53,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
53
53
  readonly locale: "en" | "ja" | "ko";
54
54
  readonly message: string;
55
55
  }[]];
56
- readonly sortKey?: string | undefined;
57
56
  readonly successMessage?: string | undefined;
58
57
  readonly accessor?: string | undefined;
58
+ readonly sortKey?: string | undefined;
59
59
  }) => any;
60
60
  }, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
61
61
  "onUpdate:modelValue"?: ((value: {
@@ -108,9 +108,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
108
108
  readonly locale: "en" | "ja" | "ko";
109
109
  readonly message: string;
110
110
  }[]];
111
- readonly sortKey?: string | undefined;
112
111
  readonly successMessage?: string | undefined;
113
112
  readonly accessor?: string | undefined;
113
+ readonly sortKey?: string | undefined;
114
114
  }) => any) | undefined;
115
115
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
116
116
  declare const _default: typeof __VLS_export;
@@ -53,9 +53,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
53
53
  readonly locale: "en" | "ja" | "ko";
54
54
  readonly message: string;
55
55
  }[]];
56
- readonly sortKey?: string | undefined;
57
56
  readonly successMessage?: string | undefined;
58
57
  readonly accessor?: string | undefined;
58
+ readonly sortKey?: string | undefined;
59
59
  }) => any;
60
60
  }, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
61
61
  "onUpdate:modelValue"?: ((value: {
@@ -108,9 +108,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
108
108
  readonly locale: "en" | "ja" | "ko";
109
109
  readonly message: string;
110
110
  }[]];
111
- readonly sortKey?: string | undefined;
112
111
  readonly successMessage?: string | undefined;
113
112
  readonly accessor?: string | undefined;
113
+ readonly sortKey?: string | undefined;
114
114
  }) => any) | undefined;
115
115
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
116
116
  declare const _default: typeof __VLS_export;
@@ -67,9 +67,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
67
67
  }[]] | undefined;
68
68
  readonly readonly?: string | undefined;
69
69
  readonly enableSorting?: boolean | undefined;
70
- readonly sortKey?: string | undefined;
71
70
  readonly successMessage?: string | undefined;
72
71
  readonly accessor?: string | undefined;
72
+ readonly sortKey?: string | undefined;
73
73
  }) => any;
74
74
  }, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
75
75
  "onUpdate:modelValue"?: ((value: {
@@ -136,9 +136,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
136
136
  }[]] | undefined;
137
137
  readonly readonly?: string | undefined;
138
138
  readonly enableSorting?: boolean | undefined;
139
- readonly sortKey?: string | undefined;
140
139
  readonly successMessage?: string | undefined;
141
140
  readonly accessor?: string | undefined;
141
+ readonly sortKey?: string | undefined;
142
142
  }) => any) | undefined;
143
143
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
144
144
  declare const _default: typeof __VLS_export;
@@ -67,9 +67,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
67
67
  }[]] | undefined;
68
68
  readonly readonly?: string | undefined;
69
69
  readonly enableSorting?: boolean | undefined;
70
- readonly sortKey?: string | undefined;
71
70
  readonly successMessage?: string | undefined;
72
71
  readonly accessor?: string | undefined;
72
+ readonly sortKey?: string | undefined;
73
73
  }) => any;
74
74
  }, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
75
75
  "onUpdate:modelValue"?: ((value: {
@@ -136,9 +136,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
136
136
  }[]] | undefined;
137
137
  readonly readonly?: string | undefined;
138
138
  readonly enableSorting?: boolean | undefined;
139
- readonly sortKey?: string | undefined;
140
139
  readonly successMessage?: string | undefined;
141
140
  readonly accessor?: string | undefined;
141
+ readonly sortKey?: string | undefined;
142
142
  }) => any) | undefined;
143
143
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
144
144
  declare const _default: typeof __VLS_export;
@@ -82,9 +82,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
82
82
  };
83
83
  }[];
84
84
  };
85
- readonly sortKey?: string | undefined;
86
85
  readonly successMessage?: string | undefined;
87
86
  readonly accessor?: string | undefined;
87
+ readonly sortKey?: string | undefined;
88
88
  }) => any;
89
89
  }, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
90
90
  "onUpdate:modelValue"?: ((value: {
@@ -166,9 +166,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
166
166
  };
167
167
  }[];
168
168
  };
169
- readonly sortKey?: string | undefined;
170
169
  readonly successMessage?: string | undefined;
171
170
  readonly accessor?: string | undefined;
171
+ readonly sortKey?: string | undefined;
172
172
  }) => any) | undefined;
173
173
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
174
174
  declare const _default: typeof __VLS_export;
@@ -82,9 +82,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
82
82
  };
83
83
  }[];
84
84
  };
85
- readonly sortKey?: string | undefined;
86
85
  readonly successMessage?: string | undefined;
87
86
  readonly accessor?: string | undefined;
87
+ readonly sortKey?: string | undefined;
88
88
  }) => any;
89
89
  }, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
90
90
  "onUpdate:modelValue"?: ((value: {
@@ -166,9 +166,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
166
166
  };
167
167
  }[];
168
168
  };
169
- readonly sortKey?: string | undefined;
170
169
  readonly successMessage?: string | undefined;
171
170
  readonly accessor?: string | undefined;
171
+ readonly sortKey?: string | undefined;
172
172
  }) => any) | undefined;
173
173
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
174
174
  declare const _default: typeof __VLS_export;
@@ -82,9 +82,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
82
82
  };
83
83
  }[];
84
84
  };
85
- readonly sortKey?: string | undefined;
86
85
  readonly successMessage?: string | undefined;
87
86
  readonly accessor?: string | undefined;
87
+ readonly sortKey?: string | undefined;
88
88
  }) => any;
89
89
  }, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
90
90
  "onUpdate:modelValue"?: ((value: {
@@ -166,9 +166,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
166
166
  };
167
167
  }[];
168
168
  };
169
- readonly sortKey?: string | undefined;
170
169
  readonly successMessage?: string | undefined;
171
170
  readonly accessor?: string | undefined;
171
+ readonly sortKey?: string | undefined;
172
172
  }) => any) | undefined;
173
173
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
174
174
  declare const _default: typeof __VLS_export;
@@ -82,9 +82,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
82
82
  };
83
83
  }[];
84
84
  };
85
- readonly sortKey?: string | undefined;
86
85
  readonly successMessage?: string | undefined;
87
86
  readonly accessor?: string | undefined;
87
+ readonly sortKey?: string | undefined;
88
88
  }) => any;
89
89
  }, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
90
90
  "onUpdate:modelValue"?: ((value: {
@@ -166,9 +166,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
166
166
  };
167
167
  }[];
168
168
  };
169
- readonly sortKey?: string | undefined;
170
169
  readonly successMessage?: string | undefined;
171
170
  readonly accessor?: string | undefined;
171
+ readonly sortKey?: string | undefined;
172
172
  }) => any) | undefined;
173
173
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
174
174
  declare const _default: typeof __VLS_export;
@@ -24,8 +24,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
24
24
  "onUpdate:modelValue"?: ((args_0: Date | undefined) => any) | undefined;
25
25
  }>, {
26
26
  size: "sm" | "md" | "lg";
27
- clearIcon: string;
28
27
  clearable: boolean;
28
+ clearIcon: string;
29
29
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
30
30
  declare const _default: typeof __VLS_export;
31
31
  export default _default;
@@ -24,8 +24,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
24
24
  "onUpdate:modelValue"?: ((args_0: Date | undefined) => any) | undefined;
25
25
  }>, {
26
26
  size: "sm" | "md" | "lg";
27
- clearIcon: string;
28
27
  clearable: boolean;
28
+ clearIcon: string;
29
29
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
30
30
  declare const _default: typeof __VLS_export;
31
31
  export default _default;
@@ -22,8 +22,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
22
22
  size: "sm" | "md" | "lg";
23
23
  granularity: "hour" | "minute" | "second";
24
24
  hourCycle: 12 | 24;
25
- clearIcon: string;
26
25
  clearable: boolean;
26
+ clearIcon: string;
27
27
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
28
28
  declare const _default: typeof __VLS_export;
29
29
  export default _default;
@@ -22,8 +22,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
22
22
  size: "sm" | "md" | "lg";
23
23
  granularity: "hour" | "minute" | "second";
24
24
  hourCycle: 12 | 24;
25
- clearIcon: string;
26
25
  clearable: boolean;
26
+ clearIcon: string;
27
27
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
28
28
  declare const _default: typeof __VLS_export;
29
29
  export default _default;
@@ -29,8 +29,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
29
29
  "onUpdate:endValue"?: ((args_0: Date | undefined) => any) | undefined;
30
30
  }>, {
31
31
  size: "sm" | "md" | "lg";
32
- clearIcon: string;
33
32
  clearable: boolean;
33
+ clearIcon: string;
34
34
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
35
35
  declare const _default: typeof __VLS_export;
36
36
  export default _default;
@@ -29,8 +29,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
29
29
  "onUpdate:endValue"?: ((args_0: Date | undefined) => any) | undefined;
30
30
  }>, {
31
31
  size: "sm" | "md" | "lg";
32
- clearIcon: string;
33
32
  clearable: boolean;
33
+ clearIcon: string;
34
34
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
35
35
  declare const _default: typeof __VLS_export;
36
36
  export default _default;
@@ -26,9 +26,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
26
26
  size: "sm" | "md" | "lg";
27
27
  granularity: "hour" | "minute" | "second";
28
28
  hourCycle: 12 | 24;
29
- rangeSeparatorIcon: string;
30
- clearIcon: string;
31
29
  clearable: boolean;
30
+ 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;
@@ -26,9 +26,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
26
26
  size: "sm" | "md" | "lg";
27
27
  granularity: "hour" | "minute" | "second";
28
28
  hourCycle: 12 | 24;
29
- rangeSeparatorIcon: string;
30
- clearIcon: string;
31
29
  clearable: boolean;
30
+ 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;
@@ -86,7 +86,7 @@ const addonAlign = computed(
86
86
  </script>
87
87
 
88
88
  <template>
89
- <div class="flex flex-col gap-1.5">
89
+ <div class="flex w-full min-w-0 flex-col gap-1.5">
90
90
  <InputGroup>
91
91
  <InputGroupAddon
92
92
  v-if="$slots.leading"
@@ -0,0 +1,21 @@
1
+ import type { Environment } from '../vendor/cel-js/lib/index.js';
2
+ /**
3
+ * The per-iteration CEL variables a `loop` block exposes to the blocks inside
4
+ * its slot: `item` (the current list element) and `index` (its 0-based
5
+ * position). Mirrors the form list field's row scope and the table row's
6
+ * `row`/`index`. `item` is always `dyn` — the element shape is backend-defined
7
+ * and unknowable at design time.
8
+ */
9
+ export declare const ITEM_VAR_TYPE = "dyn";
10
+ export declare const ITEM_VAR_DESCRIPTION = "\u5F53\u524D\u5FAA\u73AF\u9879\uFF1B\u7531 `\u5217\u8868` \u8868\u8FBE\u5F0F\u8FD4\u56DE\u7684\u6BCF\u4E00\u9879";
11
+ export declare const INDEX_VAR_TYPE = "number";
12
+ export declare const INDEX_VAR_DESCRIPTION = "\u5F53\u524D\u5FAA\u73AF\u9879\u7D22\u5F15\uFF0C\u4ECE `0` \u5F00\u59CB";
13
+ /**
14
+ * Register the per-iteration `item` (dyn) and `index` (number) CEL variables,
15
+ * skipping each when an enclosing `configure` already declared it. Idempotent
16
+ * so a loop nested inside another loop (or any host that already exposes these
17
+ * names) doesn't re-register — the CEL registry throws `'item' is already
18
+ * registered` on a second declaration. Mirrors `registerNodeVariableIfAbsent`
19
+ * (share/tree-node-var.ts).
20
+ */
21
+ export declare function registerLoopVariablesIfAbsent(env: Environment): void;
@@ -0,0 +1,13 @@
1
+ export const ITEM_VAR_TYPE = "dyn";
2
+ export const ITEM_VAR_DESCRIPTION = "\u5F53\u524D\u5FAA\u73AF\u9879\uFF1B\u7531 `\u5217\u8868` \u8868\u8FBE\u5F0F\u8FD4\u56DE\u7684\u6BCF\u4E00\u9879";
3
+ export const INDEX_VAR_TYPE = "number";
4
+ export const INDEX_VAR_DESCRIPTION = "\u5F53\u524D\u5FAA\u73AF\u9879\u7D22\u5F15\uFF0C\u4ECE `0` \u5F00\u59CB";
5
+ export function registerLoopVariablesIfAbsent(env) {
6
+ const declared = new Set(env.getDefinitions().variables.map((v) => v.name));
7
+ if (!declared.has("item")) {
8
+ env.registerVariable("item", ITEM_VAR_TYPE, { description: ITEM_VAR_DESCRIPTION });
9
+ }
10
+ if (!declared.has("index")) {
11
+ env.registerVariable("index", INDEX_VAR_TYPE, { description: INDEX_VAR_DESCRIPTION });
12
+ }
13
+ }
@@ -24,7 +24,7 @@ The `homogeneousAggregateLiterals` and `enableOptionalTypes` environment options
24
24
 
25
25
  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). The optional surface is `optional.of(A): optional<A>` (the lift / `pure`), `optional.none()`, `optional.hasValue()`, `optional.value()`, `optional.or(optional)`, `optional.orValue(value)`, plus `optional<A>.flatMap(var, body): optional<B>` (monadic bind) and `optional<A>.map(var, body): optional<B>` (the Functor `fmap`) — all local additions (not from upstream). Both are variable-binding macros (registered with `(ast, ast)` arg types so the body stays unevaluated): on `Some` they bind the value and evaluate `body`; on `None` they short-circuit without touching `body`. `flatMap`'s body must itself yield an `optional`; `map`'s body is a plain value that gets re-wrapped in `Some`. `map` is the derived `o.flatMap(v, optional.of(body))` promoted to a first-class macro. NOTE: `map` is **registered in `macros.ts`**, not here — the parser resolves a macro by name before types are known, so the optional `map` and the list-comprehension `map` must share one expander that dispatches on the receiver type at type-check (an `optional` receiver → fmap; `list`/`map` → comprehension; a `dyn` receiver is deferred to a runtime `Option.isOption` check).
26
26
 
27
- 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 only builds an `HttpRequestBuilder` — a pure description of a request; it never issues one. Both terminal methods, `.json()` and `.file()`, are dispatched by the host on the returned builder (neither is a CEL method), so expression evaluation stays free of IO. Endpoints must be absolute URLs — there is no base-URL resolution. Depends on `fx-fetch`. The host can register process-wide default headers via `HttpRequestBuilder.setDefaultHeader(name, valueOrGetter)` / `clearDefaultHeader(name)`; they are merged in at `#buildRequest()` time, with case-insensitive precedence to an explicit `.header(...)` on the builder. A getter that returns `null` / `undefined` / `''` skips the header for that request, so the host can source values from live refs (e.g. the active i18n locale for `Accept-Language`) without baking in stale snapshots. `.query` accepts `(string, string)` / `(string, number)`, the optional-valued `(string, optional<string>)` / `(string, optional<number>)` (a `None`, e.g. an absent `.?` field, drops the param rather than emitting `key=`; `Some` appends it via the string/number coercion), and the record-splat `(dyn)`.
27
+ 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 only builds an `HttpRequestBuilder` — a pure description of a request; it never issues one. The terminal methods `.json()`, `.file()`, and `.fileOrJson()` are dispatched by the host on the returned builder (none is a CEL method), so expression evaluation stays free of IO. `.fileOrJson()` branches on the response `Content-Type`: a JSON media type (`application/json` or a `+json` suffix) is parsed and returned as `{ _tag: 'json', json }`; anything else is returned as `{ _tag: 'file', file }`. Note the `Fetch` service itself `ensureOk`s (both `FetchLive` and the mock layer), so a non-2xx fails at `Fetch.fetch` before the branch and this only ever distinguishes 2xx bodies — i.e. the HTTP-200-with-error-envelope case. The download operation uses it so a backend that answers a download with a JSON error envelope (commonly `{ code: -1 }` on a 200) is classified rather than saved as the file. Endpoints must be absolute URLs — there is no base-URL resolution. Depends on `fx-fetch`. The host can register process-wide default headers via `HttpRequestBuilder.setDefaultHeader(name, valueOrGetter)` / `clearDefaultHeader(name)`; they are merged in at `#buildRequest()` time, with case-insensitive precedence to an explicit `.header(...)` on the builder. A getter that returns `null` / `undefined` / `''` skips the header for that request, so the host can source values from live refs (e.g. the active i18n locale for `Accept-Language`) without baking in stale snapshots. `.query` accepts `(string, string)` / `(string, number)`, the optional-valued `(string, optional<string>)` / `(string, optional<number>)` (a `None`, e.g. an absent `.?` field, drops the param rather than emitting `key=`; `Some` appends it via the string/number coercion), and the record-splat `(dyn)`.
28
28
 
29
29
  A `form(dyn): FormData` built-in has been added (`form-builtins.ts`) — not from upstream. It registers the `FormData` type on `globalRegistry` and a global `form` function that turns a CEL map into a native `FormData`, so authors can write `http.post(url).body(form({"file": myFile, "name": "Alice"}))` (`.body()` passes `FormData` through verbatim; `#buildRequest()` serializes it). NOTE: `#buildRequest()` must serialize a `FormData` body itself rather than hand it to fx-fetch — fx-fetch clones bodies via `new Response(body).blob()`, and the File API ASCII-lowercases `Blob#type`, so in Chrome the multipart boundary in the derived `Content-Type` loses its case while the body bytes keep it (boundaries are case-sensitive → every parser sees zero parts). The builder lifts the case-preserved `Content-Type` off the `Response` *header* (header values are never case-normalized), adds it as an explicit header (unless the author set their own `Content-Type`), and passes the bytes as a `Promise<Blob>` (fx-fetch resolves promises verbatim). Value coercion mirrors `.query()`'s flat-record semantics: `null` / `undefined` / `Option.None` skip the key; `Option.Some(x)` recurses on `x`; `File` / `Blob` pass through (preserves the `File` filename); `Decimal` → `.toString()` (preserves precision past safe-integer); `Date` (`TZDate`) → `.toISOString()`; `bool` → `'true'` / `'false'`; arrays append one entry per element; nested objects throw (`multipart/form-data` is flat — same rule as `.query(dyn)`). Top-level input must be a map literal / record (Map or plain object); passing an array or scalar throws.
30
30
  The `__proto__` / `constructor` / `prototype` keys are skipped on the top-level record, mirroring `safeFromEntries`.
@@ -2,15 +2,26 @@
2
2
  * `HttpRequestBuilder` — the value an `http.*` CEL expression evaluates to.
3
3
  *
4
4
  * A local (non-upstream) extension. A CEL expression only *describes* a
5
- * request — it never issues one. Both terminal methods, `.json()` and
6
- * `.file()`, are dispatched by the host on the returned builder, keeping
7
- * expression evaluation free of IO.
5
+ * request — it never issues one. The terminal methods `.json()`, `.file()`,
6
+ * and `.fileOrJson()` are dispatched by the host on the returned builder,
7
+ * keeping expression evaluation free of IO.
8
8
  *
9
9
  * Endpoints are used verbatim — there is no base-URL resolution, so callers
10
10
  * must pass absolute URLs.
11
11
  */
12
12
  import { Effect } from 'effect';
13
13
  import { Fetch } from 'fx-fetch';
14
+ /**
15
+ * The outcome of `.fileOrJson()` — discriminated on what the server actually
16
+ * returned, so the host can save a binary body but classify a JSON envelope.
17
+ */
18
+ export type FileOrJson = {
19
+ readonly _tag: 'file';
20
+ readonly file: File;
21
+ } | {
22
+ readonly _tag: 'json';
23
+ readonly json: unknown;
24
+ };
14
25
  export declare class HttpRequestBuilder {
15
26
  #private;
16
27
  static setDefaultHeader(name: string, value: string | (() => string | null | undefined)): void;
@@ -42,4 +53,28 @@ export declare class HttpRequestBuilder {
42
53
  };
43
54
  json(): Effect.Effect<unknown, import("fx-fetch/Cause").MalformedJsonError | Fetch.Fetch.ErrorType, Fetch.Fetch>;
44
55
  file(): Effect.Effect<File, Fetch.Fetch.ErrorType | import("fx-fetch/Cause").MalformedBlobError, Fetch.Fetch>;
56
+ /**
57
+ * A download that branches on the response Content-Type:
58
+ * - JSON (`application/json` / a `+json` type) → parse the body and return
59
+ * `{ _tag: 'json', json }`. A download endpoint that answers with JSON has
60
+ * almost always returned an error envelope (e.g. `{ code: -1 }` on a 200)
61
+ * rather than the file — the host classifies it instead of saving the
62
+ * bytes. This branch deliberately does not `ensureOk`, but the `Fetch`
63
+ * service already does (both `FetchLive` and the mock layer), so under the
64
+ * standard layer a non-2xx has already failed at `Fetch.fetch` above and
65
+ * this branch sees only 2xx — the HTTP-200-with-error-envelope case.
66
+ * - anything else → the bytes are the file. `ensureOk` is kept for parity
67
+ * with `.file()` (redundant under the standard `Fetch` service, defensive
68
+ * against a layer that doesn't), then return `{ _tag: 'file', file }` with
69
+ * the filename from `Content-Disposition`.
70
+ */
71
+ fileOrJson(): Effect.Effect<{
72
+ _tag: "json";
73
+ json: unknown;
74
+ file?: undefined;
75
+ } | {
76
+ _tag: "file";
77
+ file: File;
78
+ json?: undefined;
79
+ }, import("fx-fetch/Cause").MalformedJsonError | Fetch.Fetch.ErrorType | import("fx-fetch/Cause").MalformedBlobError, Fetch.Fetch>;
45
80
  }