@shwfed/nuxt 0.11.34 → 0.11.36

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shwfed/nuxt",
3
3
  "configKey": "shwfed",
4
- "version": "0.11.34",
4
+ "version": "0.11.36",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.1"
@@ -22,6 +22,9 @@ type __VLS_Props = {
22
22
  dsl?: DslEffect;
23
23
  sidebar?: SidebarType;
24
24
  commands?: Array<ProfileCommandInputItem | ProfileCommandInputGroup>;
25
+ hideSidebar?: boolean;
26
+ hideTabs?: boolean;
27
+ hideMenubar?: boolean;
25
28
  };
26
29
  declare var __VLS_10: string, __VLS_11: any;
27
30
  type __VLS_Slots = {} & {
@@ -6,7 +6,10 @@ defineOptions({
6
6
  const props = defineProps({
7
7
  dsl: { type: null, required: false },
8
8
  sidebar: { type: Array, required: false },
9
- commands: { type: Array, required: false }
9
+ commands: { type: Array, required: false },
10
+ hideSidebar: { type: Boolean, required: false },
11
+ hideTabs: { type: Boolean, required: false },
12
+ hideMenubar: { type: Boolean, required: false }
10
13
  });
11
14
  </script>
12
15
 
@@ -22,6 +22,9 @@ type __VLS_Props = {
22
22
  dsl?: DslEffect;
23
23
  sidebar?: SidebarType;
24
24
  commands?: Array<ProfileCommandInputItem | ProfileCommandInputGroup>;
25
+ hideSidebar?: boolean;
26
+ hideTabs?: boolean;
27
+ hideMenubar?: boolean;
25
28
  };
26
29
  declare var __VLS_10: string, __VLS_11: any;
27
30
  type __VLS_Slots = {} & {
@@ -171,6 +171,7 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
171
171
  message: string;
172
172
  }[] | undefined;
173
173
  maxCount?: string | undefined;
174
+ template?: string | undefined;
174
175
  style?: string | undefined;
175
176
  initialValue?: string | undefined;
176
177
  hidden?: string | undefined;
@@ -359,6 +360,7 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
359
360
  message: string;
360
361
  }[] | undefined;
361
362
  maxCount?: string | undefined;
363
+ template?: string | undefined;
362
364
  style?: string | undefined;
363
365
  initialValue?: string | undefined;
364
366
  hidden?: string | undefined;
@@ -171,6 +171,7 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
171
171
  message: string;
172
172
  }[] | undefined;
173
173
  maxCount?: string | undefined;
174
+ template?: string | undefined;
174
175
  style?: string | undefined;
175
176
  initialValue?: string | undefined;
176
177
  hidden?: string | undefined;
@@ -359,6 +360,7 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
359
360
  message: string;
360
361
  }[] | undefined;
361
362
  maxCount?: string | undefined;
363
+ template?: string | undefined;
362
364
  style?: string | undefined;
363
365
  initialValue?: string | undefined;
364
366
  hidden?: string | undefined;
@@ -68,6 +68,9 @@ type __VLS_Props = {
68
68
  * Structured command entries for profile menu and command palette.
69
69
  */
70
70
  commands?: Array<ProfileCommandInputItem | ProfileCommandInputGroup>;
71
+ hideSidebar?: boolean;
72
+ hideTabs?: boolean;
73
+ hideMenubar?: boolean;
71
74
  };
72
75
  declare var __VLS_113: {}, __VLS_129: {}, __VLS_352: {};
73
76
  type __VLS_Slots = {} & {
@@ -28,7 +28,10 @@ const overlay = useOverlay();
28
28
  const props = defineProps({
29
29
  dsl: { type: null, required: false },
30
30
  sidebar: { type: Array, required: false },
31
- commands: { type: Array, required: false }
31
+ commands: { type: Array, required: false },
32
+ hideSidebar: { type: Boolean, required: false },
33
+ hideTabs: { type: Boolean, required: false },
34
+ hideMenubar: { type: Boolean, required: false }
32
35
  });
33
36
  const { active, tabs, nameOf, close } = useNavigationTabs(() => props.sidebar ?? []);
34
37
  const ui = reactive({
@@ -167,7 +170,7 @@ function runPaletteEffect(effect) {
167
170
  </ClientOnly>
168
171
 
169
172
  <main class="h-screen w-screen flex flex-col overflow-hidden">
170
- <header class="bg-(--primary) h-12 w-full flex items-center justify-between px-4 gap-4">
173
+ <header :class="['bg-(--primary) h-12 w-full flex items-center justify-between px-4 gap-4', { hidden: hideMenubar }]">
171
174
  <Logo />
172
175
  <slot name="menu" />
173
176
  <span class="flex-1" />
@@ -257,7 +260,7 @@ function runPaletteEffect(effect) {
257
260
  <main class="flex-1 flex w-full overflow-hidden">
258
261
  <SidebarProvider
259
262
  default-open
260
- class="w-fit"
263
+ :class="['w-fit', { hidden: hideSidebar }]"
261
264
  :style="{
262
265
  '--sidebar-width': '13rem'
263
266
  }"
@@ -361,7 +364,7 @@ function runPaletteEffect(effect) {
361
364
  </Sidebar>
362
365
  </SidebarProvider>
363
366
  <main class="flex-1 flex flex-col bg-zinc-100 overflow-hidden">
364
- <nav class="bg-white p-1 border-b border-zinc-100 h-10 flex items-center justify-start gap-1 overflow-x-auto min-w-0">
367
+ <nav :class="['bg-white p-1 border-b border-zinc-100 h-10 flex items-center justify-start gap-1 overflow-x-auto min-w-0', { hidden: hideTabs }]">
365
368
  <div
366
369
  v-for="tab in tabs"
367
370
  :key="tab"
@@ -68,6 +68,9 @@ type __VLS_Props = {
68
68
  * Structured command entries for profile menu and command palette.
69
69
  */
70
70
  commands?: Array<ProfileCommandInputItem | ProfileCommandInputGroup>;
71
+ hideSidebar?: boolean;
72
+ hideTabs?: boolean;
73
+ hideMenubar?: boolean;
71
74
  };
72
75
  declare var __VLS_113: {}, __VLS_129: {}, __VLS_352: {};
73
76
  type __VLS_Slots = {} & {
@@ -165,6 +165,7 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
165
165
  message: string;
166
166
  }[] | undefined;
167
167
  maxCount?: string | undefined;
168
+ template?: string | undefined;
168
169
  style?: string | undefined;
169
170
  initialValue?: string | undefined;
170
171
  hidden?: string | undefined;
@@ -352,6 +353,7 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
352
353
  message: string;
353
354
  }[] | undefined;
354
355
  maxCount?: string | undefined;
356
+ template?: string | undefined;
355
357
  style?: string | undefined;
356
358
  initialValue?: string | undefined;
357
359
  hidden?: string | undefined;
@@ -535,6 +537,7 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
535
537
  message: string;
536
538
  }[] | undefined;
537
539
  maxCount?: string | undefined;
540
+ template?: string | undefined;
538
541
  style?: string | undefined;
539
542
  initialValue?: string | undefined;
540
543
  hidden?: string | undefined;
@@ -720,6 +723,7 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
720
723
  message: string;
721
724
  }[] | undefined;
722
725
  maxCount?: string | undefined;
726
+ template?: string | undefined;
723
727
  style?: string | undefined;
724
728
  initialValue?: string | undefined;
725
729
  hidden?: string | undefined;
@@ -298,6 +298,24 @@ function handleUploadDrop(field, event) {
298
298
  function handleUploadDragOver(event) {
299
299
  event.preventDefault();
300
300
  }
301
+ const templateDownloading = ref({});
302
+ async function handleTemplateDownload(field) {
303
+ if (!field.template || templateDownloading.value[field.id]) return;
304
+ templateDownloading.value[field.id] = true;
305
+ try {
306
+ const file = await $dsl.evaluate`${field.template}`();
307
+ const url = URL.createObjectURL(file);
308
+ const a = document.createElement("a");
309
+ a.href = url;
310
+ a.download = file.name;
311
+ a.click();
312
+ URL.revokeObjectURL(url);
313
+ } catch (e) {
314
+ console.error("[Fields] template download failed:", e);
315
+ } finally {
316
+ templateDownloading.value[field.id] = false;
317
+ }
318
+ }
301
319
  function stringifySelectValue(value) {
302
320
  try {
303
321
  return JSON.stringify(value);
@@ -660,6 +678,19 @@ export {
660
678
  >*</sup>
661
679
  </span>
662
680
  </p>
681
+ <button
682
+ v-if="field.template"
683
+ type="button"
684
+ class="inline-flex items-center gap-1 self-start text-sm text-[--el-color-primary] hover:underline disabled:opacity-50"
685
+ :disabled="templateDownloading[field.id]"
686
+ @click="handleTemplateDownload(field)"
687
+ >
688
+ <Icon
689
+ :icon="templateDownloading[field.id] ? 'svg-spinners:ring-resize' : 'fluent:arrow-download-20-regular'"
690
+ class="text-base"
691
+ />
692
+ {{ t("upload-download-template") }}
693
+ </button>
663
694
  <label
664
695
  v-if="getUploadFiles(field).length < getUploadMaxCount(field)"
665
696
  :class="[
@@ -1105,7 +1136,8 @@ export {
1105
1136
  "upload-click-or-drag": "点击或拖拽文件到此处上传",
1106
1137
  "upload-accept-description": "仅接受 {formats} 格式文件",
1107
1138
  "upload-accept-or": "或",
1108
- "upload-accept-all": "接受所有格式文件"
1139
+ "upload-accept-all": "接受所有格式文件",
1140
+ "upload-download-template": "下载模板"
1109
1141
  },
1110
1142
  "ja": {
1111
1143
  "clear": "クリア",
@@ -1115,7 +1147,8 @@ export {
1115
1147
  "upload-click-or-drag": "クリックまたはファイルをここにドラッグしてアップロード",
1116
1148
  "upload-accept-description": "{formats} 形式のファイルのみ受け付けます",
1117
1149
  "upload-accept-or": "または",
1118
- "upload-accept-all": "すべての形式を受け付けます"
1150
+ "upload-accept-all": "すべての形式を受け付けます",
1151
+ "upload-download-template": "テンプレートをダウンロード"
1119
1152
  },
1120
1153
  "en": {
1121
1154
  "clear": "Clear",
@@ -1125,7 +1158,8 @@ export {
1125
1158
  "upload-click-or-drag": "Click or drag files here to upload",
1126
1159
  "upload-accept-description": "Only {formats} format files accepted",
1127
1160
  "upload-accept-or": "or",
1128
- "upload-accept-all": "All formats accepted"
1161
+ "upload-accept-all": "All formats accepted",
1162
+ "upload-download-template": "Download Template"
1129
1163
  }
1130
1164
  }
1131
1165
  </i18n>
@@ -165,6 +165,7 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
165
165
  message: string;
166
166
  }[] | undefined;
167
167
  maxCount?: string | undefined;
168
+ template?: string | undefined;
168
169
  style?: string | undefined;
169
170
  initialValue?: string | undefined;
170
171
  hidden?: string | undefined;
@@ -352,6 +353,7 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
352
353
  message: string;
353
354
  }[] | undefined;
354
355
  maxCount?: string | undefined;
356
+ template?: string | undefined;
355
357
  style?: string | undefined;
356
358
  initialValue?: string | undefined;
357
359
  hidden?: string | undefined;
@@ -535,6 +537,7 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
535
537
  message: string;
536
538
  }[] | undefined;
537
539
  maxCount?: string | undefined;
540
+ template?: string | undefined;
538
541
  style?: string | undefined;
539
542
  initialValue?: string | undefined;
540
543
  hidden?: string | undefined;
@@ -720,6 +723,7 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
720
723
  message: string;
721
724
  }[] | undefined;
722
725
  maxCount?: string | undefined;
726
+ template?: string | undefined;
723
727
  style?: string | undefined;
724
728
  initialValue?: string | undefined;
725
729
  hidden?: string | undefined;
@@ -217,6 +217,7 @@ export declare const UploadFieldC: z.ZodObject<{
217
217
  message: z.ZodString;
218
218
  }, z.core.$strip>>>>;
219
219
  maxCount: z.ZodOptional<z.ZodString>;
220
+ template: z.ZodOptional<z.ZodString>;
220
221
  style: z.ZodOptional<z.ZodString>;
221
222
  initialValue: z.ZodOptional<z.ZodString>;
222
223
  hidden: z.ZodOptional<z.ZodString>;
@@ -437,6 +438,7 @@ export declare const FieldC: z.ZodDiscriminatedUnion<[z.ZodObject<{
437
438
  message: z.ZodString;
438
439
  }, z.core.$strip>>>>;
439
440
  maxCount: z.ZodOptional<z.ZodString>;
441
+ template: z.ZodOptional<z.ZodString>;
440
442
  style: z.ZodOptional<z.ZodString>;
441
443
  initialValue: z.ZodOptional<z.ZodString>;
442
444
  hidden: z.ZodOptional<z.ZodString>;
@@ -671,6 +673,7 @@ export declare const FieldsBodyC: z.ZodReadonly<z.ZodObject<{
671
673
  message: z.ZodString;
672
674
  }, z.core.$strip>>>>;
673
675
  maxCount: z.ZodOptional<z.ZodString>;
676
+ template: z.ZodOptional<z.ZodString>;
674
677
  style: z.ZodOptional<z.ZodString>;
675
678
  initialValue: z.ZodOptional<z.ZodString>;
676
679
  hidden: z.ZodOptional<z.ZodString>;
@@ -899,6 +902,7 @@ export declare const FieldsBodyInputC: z.ZodReadonly<z.ZodObject<{
899
902
  message: z.ZodString;
900
903
  }, z.core.$strip>>>>;
901
904
  maxCount: z.ZodOptional<z.ZodString>;
905
+ template: z.ZodOptional<z.ZodString>;
902
906
  style: z.ZodOptional<z.ZodString>;
903
907
  initialValue: z.ZodOptional<z.ZodString>;
904
908
  hidden: z.ZodOptional<z.ZodString>;
@@ -1127,6 +1131,7 @@ export declare const FieldsConfigC: z.ZodReadonly<z.ZodObject<{
1127
1131
  message: z.ZodString;
1128
1132
  }, z.core.$strip>>>>;
1129
1133
  maxCount: z.ZodOptional<z.ZodString>;
1134
+ template: z.ZodOptional<z.ZodString>;
1130
1135
  style: z.ZodOptional<z.ZodString>;
1131
1136
  initialValue: z.ZodOptional<z.ZodString>;
1132
1137
  hidden: z.ZodOptional<z.ZodString>;
@@ -1357,6 +1362,7 @@ export declare const FieldsConfigInputC: z.ZodReadonly<z.ZodObject<{
1357
1362
  message: z.ZodString;
1358
1363
  }, z.core.$strip>>>>;
1359
1364
  maxCount: z.ZodOptional<z.ZodString>;
1365
+ template: z.ZodOptional<z.ZodString>;
1360
1366
  style: z.ZodOptional<z.ZodString>;
1361
1367
  initialValue: z.ZodOptional<z.ZodString>;
1362
1368
  hidden: z.ZodOptional<z.ZodString>;
@@ -133,6 +133,7 @@ export const UploadFieldC = z.object({
133
133
  accept: z.array(z.string()).readonly().optional().describe("\u5141\u8BB8\u4E0A\u4F20\u7684 MIME \u7C7B\u578B\u6570\u7EC4\uFF0C\u540C\u65F6\u63A7\u5236\u6587\u4EF6\u9009\u62E9\u8FC7\u6EE4\u548C\u533A\u57DF\u63CF\u8FF0\u6587\u5B57"),
134
134
  description: localeC.optional().describe("\u4E0A\u4F20\u533A\u57DF\u7684\u63D0\u793A\u6587\u672C\u7684\u672C\u5730\u5316\u663E\u793A\u6587\u672C\uFF0C\u66FF\u6362\u9ED8\u8BA4\u7684\u300C\u70B9\u51FB\u6216\u62D6\u62FD\u5230\u6B64\u5904\u4E0A\u4F20\u300D"),
135
135
  maxCount: expressionC(["int", "dyn"], inheritedFieldContext).optional().describe("\u8FD4\u56DE\u6574\u6570\u7684 CEL \u8868\u8FBE\u5F0F\uFF0C\u9650\u5236\u6700\u5927\u53EF\u4E0A\u4F20\u6587\u4EF6\u6570\u91CF\uFF0C\u53EF\u4F7F\u7528 form\u3001row\u3001index \u548C id \u53D8\u91CF"),
136
+ template: expressionC(["File", "dyn"]).optional().describe('\u8FD4\u56DE File \u7684 CEL \u8868\u8FBE\u5F0F\uFF08\u5982 http.post("/url").file()\uFF09\uFF0C\u914D\u7F6E\u540E\u5728\u4E0A\u4F20\u533A\u57DF\u663E\u793A\u300C\u4E0B\u8F7D\u6A21\u677F\u300D\u6309\u94AE'),
136
137
  style: z.string().optional().describe("CSS \u6837\u5F0F\u5BF9\u8C61\u8868\u8FBE\u5F0F\uFF0C\u63A7\u5236\u5B57\u6BB5\u7684\u5E03\u5C40\u4E0E\u5916\u89C2"),
137
138
  initialValue: expressionC(["list(dyn)", "dyn"], inheritedFieldContext).optional().describe("\u8FD4\u56DE\u6570\u7EC4\u7684 CEL \u8868\u8FBE\u5F0F\uFF0C\u5728\u5B57\u6BB5\u9996\u6B21\u521D\u59CB\u5316\u4E14 path \u4E0D\u5B58\u5728\u65F6\u5199\u5165\u521D\u59CB\u503C\uFF0C\u53EF\u4F7F\u7528 form\u3001row\u3001index \u548C id \u53D8\u91CF"),
138
139
  hidden: expressionC(["bool", "dyn"], inheritedFieldContext).optional().describe("\u4E3A true \u65F6\uFF0C\u9690\u85CF\u8FD9\u4E2A\u5B57\u6BB5\uFF0C\u53EF\u4F7F\u7528 form\u3001row\u3001index \u548C id \u53D8\u91CF"),
@@ -166,6 +166,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
166
166
  message: string;
167
167
  }[] | undefined;
168
168
  maxCount?: string | undefined;
169
+ template?: string | undefined;
169
170
  style?: string | undefined;
170
171
  initialValue?: string | undefined;
171
172
  hidden?: string | undefined;
@@ -349,6 +350,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
349
350
  message: string;
350
351
  }[] | undefined;
351
352
  maxCount?: string | undefined;
353
+ template?: string | undefined;
352
354
  style?: string | undefined;
353
355
  initialValue?: string | undefined;
354
356
  hidden?: string | undefined;
@@ -301,6 +301,7 @@ function normalizeField(field) {
301
301
  contentStyle: normalizeOptionalString(field.contentStyle ?? ""),
302
302
  accept: normalizedAccept.length > 0 ? normalizedAccept : void 0,
303
303
  maxCount: normalizeOptionalString(field.maxCount ?? ""),
304
+ template: normalizeOptionalString(field.template ?? ""),
304
305
  initialValue: normalizeOptionalString(field.initialValue ?? ""),
305
306
  hidden: normalizeOptionalString(field.hidden ?? ""),
306
307
  disabled: normalizeOptionalString(field.disabled ?? ""),
@@ -923,6 +924,22 @@ function updateSelectedUploadMaxCount(value) {
923
924
  };
924
925
  });
925
926
  }
927
+ function updateSelectedUploadTemplate(value) {
928
+ const selected = selectedField.value;
929
+ if (!selected || selected.field.type !== "upload") {
930
+ return;
931
+ }
932
+ clearFieldError(selected.draftId, "template");
933
+ updateDraftField(selected.draftId, (field) => {
934
+ if (field.type !== "upload") {
935
+ return field;
936
+ }
937
+ return {
938
+ ...field,
939
+ template: normalizeOptionalString(String(value))
940
+ };
941
+ });
942
+ }
926
943
  function addValidationRule() {
927
944
  const selected = selectedField.value;
928
945
  if (!selected || isPassiveField(selected.field)) {
@@ -2298,6 +2315,26 @@ function confirmChanges() {
2298
2315
  {{ validationErrors[getFieldErrorKey(selectedField.draftId, "maxCount")] }}
2299
2316
  </p>
2300
2317
  </label>
2318
+
2319
+ <label class="flex flex-col gap-2 md:col-span-2">
2320
+ <span class="text-xs font-medium text-zinc-500">
2321
+ {{ t("field-upload-template") }}
2322
+ </span>
2323
+ <Textarea
2324
+ data-slot="fields-configurator-field-upload-template-input"
2325
+ :model-value="selectedField.field.template ?? ''"
2326
+ :aria-invalid="validationErrors[getFieldErrorKey(selectedField.draftId, 'template')] ? 'true' : void 0"
2327
+ :placeholder="t('field-upload-template-placeholder')"
2328
+ class="min-h-20 font-mono text-sm"
2329
+ @update:model-value="updateSelectedUploadTemplate"
2330
+ />
2331
+ <p
2332
+ v-if="validationErrors[getFieldErrorKey(selectedField.draftId, 'template')]"
2333
+ class="text-xs text-red-500"
2334
+ >
2335
+ {{ validationErrors[getFieldErrorKey(selectedField.draftId, "template")] }}
2336
+ </p>
2337
+ </label>
2301
2338
  </section>
2302
2339
 
2303
2340
  <section
@@ -2582,6 +2619,8 @@ function confirmChanges() {
2582
2619
  "field-upload-description": "上传提示文本",
2583
2620
  "field-upload-max-count": "最大文件数量",
2584
2621
  "field-upload-max-count-placeholder": "例如 5",
2622
+ "field-upload-template": "下载模板表达式",
2623
+ "field-upload-template-placeholder": "例如 http.post(\"/api/v1/example/download_template\").file()",
2585
2624
  "field-validation": "校验规则",
2586
2625
  "field-validation-description": "字段失焦时按顺序执行,命中第一个失败规则后停止。",
2587
2626
  "add-validation-rule": "新增规则",
@@ -2699,6 +2738,8 @@ function confirmChanges() {
2699
2738
  "field-upload-description": "アップロード説明文",
2700
2739
  "field-upload-max-count": "最大ファイル数",
2701
2740
  "field-upload-max-count-placeholder": "例: 5",
2741
+ "field-upload-template": "テンプレートダウンロード式",
2742
+ "field-upload-template-placeholder": "例: http.post(\"/api/v1/example/download_template\").file()",
2702
2743
  "field-validation": "検証ルール",
2703
2744
  "field-validation-description": "フォーカスを外したときに順番に評価し、最初の失敗で停止します。",
2704
2745
  "add-validation-rule": "ルールを追加",
@@ -2816,6 +2857,8 @@ function confirmChanges() {
2816
2857
  "field-upload-description": "Upload description",
2817
2858
  "field-upload-max-count": "Max file count",
2818
2859
  "field-upload-max-count-placeholder": "For example 5",
2860
+ "field-upload-template": "Template download expression",
2861
+ "field-upload-template-placeholder": "e.g. http.post(\"/api/v1/example/download_template\").file()",
2819
2862
  "field-validation": "Validation rules",
2820
2863
  "field-validation-description": "Rules run on blur in order and stop at the first failure.",
2821
2864
  "add-validation-rule": "Add rule",
@@ -166,6 +166,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
166
166
  message: string;
167
167
  }[] | undefined;
168
168
  maxCount?: string | undefined;
169
+ template?: string | undefined;
169
170
  style?: string | undefined;
170
171
  initialValue?: string | undefined;
171
172
  hidden?: string | undefined;
@@ -349,6 +350,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
349
350
  message: string;
350
351
  }[] | undefined;
351
352
  maxCount?: string | undefined;
353
+ template?: string | undefined;
352
354
  style?: string | undefined;
353
355
  initialValue?: string | undefined;
354
356
  hidden?: string | undefined;
@@ -2,6 +2,7 @@ import { defineNuxtPlugin, useNuxtApp, useRuntimeConfig } from "#app";
2
2
  import { useNavigatorLanguage } from "@vueuse/core";
3
3
  import { Effect } from "effect";
4
4
  import z from "zod";
5
+ import { setFileHandler } from "../cel/http-request.js";
5
6
  let isRedirectingAfterTokenExpiry = false;
6
7
  const processedResponses = /* @__PURE__ */ new WeakSet();
7
8
  export default defineNuxtPlugin({
@@ -121,6 +122,21 @@ export default defineNuxtPlugin({
121
122
  data
122
123
  });
123
124
  }
125
+ setFileHandler(async (request) => {
126
+ const headers = new Headers(request.headers);
127
+ applyRequestHeaders(headers);
128
+ const response = await fetch(createRequestUrl(request.url, request.query), {
129
+ method: request.method,
130
+ headers,
131
+ body: createRequestBody(request.body, headers)
132
+ });
133
+ await handleExpiredFetchResponse(response);
134
+ if (!response.ok) throw new Error(`Download failed: ${response.status}`);
135
+ const blob = await response.blob();
136
+ const disposition = response.headers.get("Content-Disposition");
137
+ const filename = disposition?.split(/filename=/i)[1]?.replaceAll(/"|'/g, "") ?? "download";
138
+ return new File([blob], decodeURIComponent(filename), { type: blob.type });
139
+ });
124
140
  const api = $fetch.create({
125
141
  baseURL: config.api.host,
126
142
  onRequest: ({
@@ -1,4 +1,5 @@
1
1
  import { Environment, EvaluationError, Optional } from "../../vendor/cel/index.js";
2
+ import { Http, HttpRequest, getFileHandler } from "./http-request.js";
2
3
  import { startOfDay, startOfWeek, startOfYear, startOfMonth, endOfDay, endOfWeek, endOfYear, endOfMonth, addYears, addMonths, addDays, addWeeks, setDate, setMonth, setYear, formatDate, isBefore, isAfter, isEqual } from "date-fns";
3
4
  import { TZDate } from "@date-fns/tz";
4
5
  import { BigNumber } from "bignumber.js";
@@ -184,5 +185,10 @@ export function createEnvironment(f = identity) {
184
185
  return Optional.none();
185
186
  }
186
187
  });
188
+ env.registerType("Http", Http).registerType("HttpRequest", HttpRequest).registerType("File", File).registerConstant("http", "Http", new Http()).registerFunction("Http.get(string): HttpRequest", (_, url) => new HttpRequest(url, "GET")).registerFunction("Http.post(string): HttpRequest", (_, url) => new HttpRequest(url, "POST")).registerFunction("Http.put(string): HttpRequest", (_, url) => new HttpRequest(url, "PUT")).registerFunction("Http.delete(string): HttpRequest", (_, url) => new HttpRequest(url, "DELETE")).registerFunction("HttpRequest.header(string, string): HttpRequest", (r, k, v) => r.withHeader(k, v)).registerFunction("HttpRequest.query(string, string): HttpRequest", (r, k, v) => r.withQuery(k, v)).registerFunction("HttpRequest.body(dyn): HttpRequest", (r, body) => r.withBody(body)).registerFunction("HttpRequest.file(): File", async (request) => {
189
+ const handler = getFileHandler();
190
+ if (!handler) throw new EvaluationError("HttpRequest.file() handler not initialized");
191
+ return handler(request);
192
+ });
187
193
  return f(env);
188
194
  }
@@ -0,0 +1,16 @@
1
+ export declare class Http {
2
+ readonly kind: "Http";
3
+ }
4
+ export declare class HttpRequest {
5
+ readonly url: string;
6
+ readonly method: string;
7
+ readonly headers: Record<string, string>;
8
+ readonly query: Record<string, string>;
9
+ readonly body: unknown;
10
+ constructor(url: string, method?: string, headers?: Record<string, string>, query?: Record<string, string>, body?: unknown);
11
+ withHeader(key: string, value: string): HttpRequest;
12
+ withQuery(key: string, value: string): HttpRequest;
13
+ withBody(body: unknown): HttpRequest;
14
+ }
15
+ export declare function getFileHandler(): ((request: HttpRequest) => Promise<File>) | null;
16
+ export declare function setFileHandler(fn: (request: HttpRequest) => Promise<File>): void;
@@ -0,0 +1,36 @@
1
+ export class Http {
2
+ kind = "Http";
3
+ }
4
+ export class HttpRequest {
5
+ url;
6
+ method;
7
+ headers;
8
+ query;
9
+ body;
10
+ constructor(url, method = "GET", headers = {}, query = {}, body = void 0) {
11
+ this.url = url;
12
+ this.method = method;
13
+ this.headers = headers;
14
+ this.query = query;
15
+ this.body = body;
16
+ Object.freeze(this);
17
+ }
18
+ withHeader(key, value) {
19
+ return new HttpRequest(this.url, this.method, { ...this.headers, [key]: value }, this.query, this.body);
20
+ }
21
+ withQuery(key, value) {
22
+ return new HttpRequest(this.url, this.method, this.headers, { ...this.query, [key]: value }, this.body);
23
+ }
24
+ withBody(body) {
25
+ return new HttpRequest(this.url, this.method, this.headers, this.query, body);
26
+ }
27
+ }
28
+ const httpState = {
29
+ fileHandler: null
30
+ };
31
+ export function getFileHandler() {
32
+ return httpState.fileHandler;
33
+ }
34
+ export function setFileHandler(fn) {
35
+ httpState.fileHandler = fn;
36
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shwfed/nuxt",
3
- "version": "0.11.34",
3
+ "version": "0.11.36",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "type": "module",