@squadbase/vantage-template 0.1.1-dev1.7c71823 → 0.1.1-dev1.80c51bb

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.
@@ -112,6 +112,11 @@ if (q.isError) return <ErrorState message={q.error.message} /> // HttpError の
112
112
  const rows = useApiQuery<Row[]>("/api/customers", { search: { segment } })
113
113
  ```
114
114
 
115
+ 絞り込み(期間・セグメント)を持つページでは、この `ErrorState` の早期 return をデータを描く
116
+ 子コンポーネントの中に置く。ページの先頭に置くと、失敗したときに絞り込みの欄ごと消えて条件を
117
+ 直せなくなる。期間は `DateRangePicker` で選ばせる(→ `agents/page.md` の「絞り込みの欄は、
118
+ 読み込み中も失敗したときも出し続ける」)。
119
+
115
120
  書き込みは `useApiMutation(path, { method: "POST" })` — 変数がそのまま JSON ボディになる。
116
121
 
117
122
  ## UI コンポーネント / ブロックを追加する
@@ -32,6 +32,9 @@ export async function GET({ params, env }: ApiContext) {
32
32
  (`!` で黙らせない)。
33
33
  - **クライアントに見せたいエラーは `HttpError(status, msg)` を throw する。** それ以外の throw は
34
34
  ログに記録され汎用の 500 に丸められる。
35
+ - **入力の誤りは 400 で返し、`msg` には何がどう誤りかを書く。** `msg` はそのまま `ErrorState` に
36
+ 出る。「開始日(10/20)が終了日(10/01)より後です」のように、利用者が条件を直せる文にする。
37
+ 許す範囲だけを並べた文(「最大366日で指定」)では、どこを直せばよいか伝わらない。
35
38
  - **シークレットは `ApiContext.env` にだけ届く**(クライアントには決して届かない)。
36
39
 
37
40
  クライアント側からは `useApiQuery` で `/api/*` を叩く。ベース URL の解決・JSON パース・
@@ -74,5 +77,9 @@ return <Chart sessions={sessions.data} metrics={metrics.data} />
74
77
  カードごとに別々に読み込み中・エラーを出すなら、`data` を渡す側で `q.data ?? []` にするか、
75
78
  カードのコンポーネントの中で上と同じ判定をする。
76
79
 
80
+ 期間などの絞り込みを持つページでは、上の早期 return をページの先頭に置かない。失敗したときに
81
+ 絞り込みの欄まで消え、条件を直せなくなる。判定はデータを描く子コンポーネントの中で行う
82
+ (→ `agents/page.md` の「絞り込みの欄は、読み込み中も失敗したときも出し続ける」)。
83
+
77
84
  `ApiError` は `message`・`status`・`body`・`requestId` を持つ。hook が使えない場所では
78
85
  `apiJson(path, init)`、生の `Response` が要るときは `apiFetch`。
@@ -147,6 +147,42 @@ const [segments, setSegments] = useSearchState<string[]>("segments", []) // JSON
147
147
  デフォルト値(または `null`)を書くとキーは URL から消える。履歴は既定で `replace`
148
148
  (`{ replace: false }` で push)。
149
149
 
150
+ ### 絞り込みの欄は、読み込み中も失敗したときも出し続ける
151
+
152
+ ページの先頭で `if (q.isError) return <ErrorState …/>` と書くと、取得に失敗したときに
153
+ 期間などの絞り込みの欄まで消える。利用者は条件を直せず、初期値に戻すしかなくなる。
154
+ 絞り込みの欄はページに置いたままにし、取得と `Loading` / `ErrorState` はデータを描く
155
+ 子コンポーネントに入れる:
156
+
157
+ ```tsx
158
+ export default function Traffic() {
159
+ const [from, setFrom] = useSearchParam("from", DEFAULT_FROM)
160
+ const [to, setTo] = useSearchParam("to", DEFAULT_TO)
161
+ return (
162
+ <>
163
+ {/* 失敗しても消えない。ここから条件を直せる */}
164
+ <PeriodFilter from={from} to={to} onChange={…} />
165
+ <TrafficBody from={from} to={to} />
166
+ </>
167
+ )
168
+ }
169
+
170
+ function TrafficBody({ from, to }: { from: string; to: string }) {
171
+ const q = useApiQuery<Row[]>("/api/traffic", { search: { from, to } })
172
+ if (q.isPending) return <Loading />
173
+ if (q.isError) return <ErrorState message={q.error.message} />
174
+ return <BarChart data={q.data} index="channel" categories={["sessions"]} />
175
+ }
176
+ ```
177
+
178
+ - **期間は `DateRangePicker`(`@squadbase/vantage/components`)で選ばせる。** カレンダーで
179
+ 範囲を選ぶので開始と終了が逆にならず、選べる日を `minDate` / `maxDate` で絞れる。
180
+ `<input type="date">` を 2 つ並べて自前で組まない。
181
+ - 値をそのまま打ち込める欄を置くなら、開始が終了より後・選べる範囲の外といった誤りは、
182
+ API へ送る前に欄のそばで理由を出す。誤りがあるあいだはデータの子コンポーネントを描かない
183
+ (送れば失敗するだけで、`ErrorState` には直し方が出ない)。
184
+ - サーバー側の検証で弾くときも、`HttpError(400, …)` の文で何がどう誤りかを言う(→ `agents/api.md`)。
185
+
150
186
  ### 動的パラメータの「3 つの綴り」を同期させる
151
187
 
152
188
  崩すと静かにマッチしなくなる不変条件:
@@ -6,7 +6,7 @@
6
6
  "name": "vibe-app",
7
7
  "dependencies": {
8
8
  "@squadbase/react": "^0.1.0",
9
- "@squadbase/vantage": "0.6.2-dev1.bcb51d1",
9
+ "@squadbase/vantage": "0.6.2-dev1.a881d95",
10
10
  "@squadbase/vantage-sdk": "0.1.1-dev1.54d3684",
11
11
  "date-fns": "^4.1.0",
12
12
  "lucide-react": "^0.468.0",
@@ -196,7 +196,7 @@
196
196
 
197
197
  "@squadbase/react": ["@squadbase/react@0.1.0", "", { "dependencies": { "zod": "^4.3.6" }, "peerDependencies": { "@types/react": "17.x || 18.x || 19.x", "react": "17.x || 18.x || 19.x" }, "optionalPeers": ["@types/react"] }, "sha512-k+Dpyj7eH+Yjydw54iEluCjYDae086d12hWgBjNMpw4wLbQGz3CrJ6Yipodg8n1cKUt7zvwddlcTHd79bgKsXg=="],
198
198
 
199
- "@squadbase/vantage": ["@squadbase/vantage@0.6.2-dev1.bcb51d1", "", { "dependencies": { "@base-ui/react": "^1.6.0", "@hono/node-server": "^2.1.5", "@streamdown/code": "^1.1.1", "@tailwindcss/vite": "^4.3.3", "@tanstack/react-query": "^5.101.2", "@tanstack/react-router": "^1.170.17", "@tanstack/react-table": "^8.21.3", "@vitejs/plugin-react": "^6.1.2", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.1.1", "date-fns": "^4.1.0", "echarts": "^6.0.0", "esbuild": "0.28.1", "fflate": "^0.8.3", "hono": "^4.13.13", "html-to-image": "^1.11.13", "lucide-react": "^0.468.0", "papaparse": "^5.7.0", "picocolors": "^1.1.1", "react-day-picker": "^10.0.1", "read-excel-file": "^9.3.10", "shiki": "3.23.0", "streamdown": "^2.5.0", "tailwind-merge": "3.6.0", "tailwindcss": "^4.3.3", "tw-animate-css": "^1.0.0", "vite": "^8.3.4" }, "peerDependencies": { "react": ">=18.2.0", "react-dom": ">=18.2.0", "typescript": ">=5.0.0" }, "optionalPeers": ["typescript"], "bin": { "vantage": "dist/cli.js" } }, "sha512-r12gMlgfkR6kGRuKmQ5AYhq56imbznE4Z4tsUvGtpkDsNtIRz8QFQQrWVeiDXSmpAlJr3IUh21SzsO/rDA8SjQ=="],
199
+ "@squadbase/vantage": ["@squadbase/vantage@0.6.2-dev1.a881d95", "", { "dependencies": { "@base-ui/react": "^1.6.0", "@hono/node-server": "^2.1.5", "@streamdown/code": "^1.1.1", "@tailwindcss/vite": "^4.3.3", "@tanstack/react-query": "^5.101.2", "@tanstack/react-router": "^1.170.17", "@tanstack/react-table": "^8.21.3", "@vitejs/plugin-react": "^6.1.2", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.1.1", "date-fns": "^4.1.0", "echarts": "^6.0.0", "esbuild": "0.28.1", "fflate": "^0.8.3", "hono": "^4.13.13", "html-to-image": "^1.11.13", "lucide-react": "^0.468.0", "papaparse": "^5.7.0", "picocolors": "^1.1.1", "react-day-picker": "^10.0.1", "read-excel-file": "^9.3.10", "shiki": "3.23.0", "streamdown": "^2.5.0", "tailwind-merge": "3.6.0", "tailwindcss": "^4.3.3", "tw-animate-css": "^1.0.0", "vite": "^8.3.4" }, "peerDependencies": { "react": ">=18.2.0", "react-dom": ">=18.2.0", "typescript": ">=5.0.0" }, "optionalPeers": ["typescript"], "bin": { "vantage": "dist/cli.js" } }, "sha512-6rZQrw/EyYAFhczGLRsQMjYrAxwDIbPyb2b8QZRh7TDIa5OzBFqcpdPCCnAh00BkX5cPwsa32ZuQNI8Ta71e/g=="],
200
200
 
201
201
  "@squadbase/vantage-sdk": ["@squadbase/vantage-sdk@0.1.1-dev1.54d3684", "", {}, "sha512-dKwVlkeeyKn92zeF1GWwswLHmARsT5Nx2Pvi6Z+XfCzu3N02XmlxISr/YCAzAaXrdWEoAp3/ghlRZtLoPl30AQ=="],
202
202
 
@@ -512,7 +512,7 @@
512
512
 
513
513
  "hastscript": ["hastscript@9.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^4.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w=="],
514
514
 
515
- "hono": ["hono@4.13.13", "", {}, "sha512-CQ46U0ZkAGmbT/4UxdzzGJpacP2IeKgY4a5/tOI9AABbpOMfK739wfDXmv1usCk+3RkKj1hQy4/fjhiwa2xlrA=="],
515
+ "hono": ["hono@4.13.14", "", {}, "sha512-yhRLQ21U6qa9Hsu2N7Qcbh8tE+WKEcoErjIo56LeSGiGXGp9sA7UpE86Ui9uexb61KakiGwuHMn2QdV7w6i6kQ=="],
516
516
 
517
517
  "html-to-image": ["html-to-image@1.11.13", "", {}, "sha512-cuOPoI7WApyhBElTTb9oqsawRvZ0rHhaHwghRLlTuffoD1B2aDemlCruLeZrUIIdvG7gs9xeELEPm6PhuASqrg=="],
518
518
 
@@ -700,7 +700,7 @@
700
700
 
701
701
  "points-on-path": ["points-on-path@0.2.1", "", { "dependencies": { "path-data-parser": "0.1.0", "points-on-curve": "0.2.0" } }, "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g=="],
702
702
 
703
- "postcss": ["postcss@8.5.31", "", { "dependencies": { "nanoid": "^3.3.20", "picocolors": "^1.1.1", "source-map-js": "^1.2.2" } }, "sha512-YUbWYCgErwnMAVkjUnYa+KlMBzGpHwiIt/DE7f0G33AuX2LH9UcTk6KgWxd3zRU+pN3u/C+Xl3EnMLM4Hea7Sg=="],
703
+ "postcss": ["postcss@8.5.32", "", { "dependencies": { "nanoid": "^3.3.20", "picocolors": "^1.1.1", "source-map-js": "^1.2.2" } }, "sha512-LJlKCCAUFKOuZxipUdYw1NzIITEsPcgyOG9LkvRJvuKj/bRzbuRY0ARXvL0pWGpsZvn8jku+LMep2eU0seHp8g=="],
704
704
 
705
705
  "property-information": ["property-information@7.2.0", "", {}, "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg=="],
706
706
 
@@ -716,7 +716,7 @@
716
716
 
717
717
  "react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="],
718
718
 
719
- "read-excel-file": ["read-excel-file@9.3.12", "", { "dependencies": { "fflate": "^0.8.3", "saxen": "^11.1.0", "unzipper-esm": "^0.13.3", "worker-f": "^0.1.12" } }, "sha512-benNAoQbe5HqoTi3qrQkR8wMeHq0gVWLt2Br73hVvmBPGdzMf9OLGsps/812AfZ+bvzVYsUyhF77Y3o4B51yCA=="],
719
+ "read-excel-file": ["read-excel-file@9.3.13", "", { "dependencies": { "fflate": "^0.8.3", "saxen": "^11.1.0", "unzipper-esm": "^0.13.3", "worker-f": "^0.1.12" } }, "sha512-dzSGFNBVOk4QkFXE37cREK7DOEVAMNYyXO1QIOoquJ24HhA2hZAZ9WYwf4KddjiV6ZMtsY3OM2JSVLpCg++9jA=="],
720
720
 
721
721
  "regex": ["regex@6.1.0", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg=="],
722
722
 
@@ -834,7 +834,7 @@
834
834
 
835
835
  "web-namespaces": ["web-namespaces@2.0.1", "", {}, "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="],
836
836
 
837
- "worker-f": ["worker-f@0.1.20", "", {}, "sha512-7z5K5z4x++FykhpDTfriT/dOu7CmSap9BBv38DVFU3CD38obopq+DoFH75yBV3butpGm+OeqR9BKdSvYJSnUfQ=="],
837
+ "worker-f": ["worker-f@0.1.21", "", {}, "sha512-pMi7wCz3uZVxRvRSphyaIYoN7rm9bV0usifTib7u01kKU+hOo+/hFwhajYnpOCHyr0Xp3/2ulc4F+Jm2a3YIfg=="],
838
838
 
839
839
  "zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="],
840
840
 
@@ -12,7 +12,7 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@squadbase/react": "^0.1.0",
15
- "@squadbase/vantage": "0.6.2-dev1.bcb51d1",
15
+ "@squadbase/vantage": "0.6.2-dev1.a881d95",
16
16
  "@squadbase/vantage-sdk": "0.1.1-dev1.54d3684",
17
17
  "date-fns": "^4.1.0",
18
18
  "lucide-react": "^0.468.0",
package/dist/index.js CHANGED
@@ -1146,8 +1146,8 @@ var buildThemeCss = (cssVars) => [
1146
1146
  var THEME_PRESETS_DATA = [
1147
1147
  {
1148
1148
  "id": "neutral",
1149
- "title": "\u30CB\u30E5\u30FC\u30C8\u30E9\u30EB",
1150
- "description": "\u65E2\u5B9A\u306E\u30CB\u30E5\u30FC\u30C8\u30E9\u30EB\u306B\u623B\u3059\u30D7\u30EA\u30BB\u30C3\u30C8\u3002\u57FA\u5E95\u306E theme \u3068\u540C\u3058\u5024\u3067\u3001\u30D7\u30EA\u30BB\u30C3\u30C8\u3092\u5207\u308A\u66FF\u3048\u308B\u3068\u304D\u306E\u8D77\u70B9\u306B\u3059\u308B\u3002",
1149
+ "title": "Neutral",
1150
+ "description": "A preset that restores the default neutral theme. It has the same values as the base theme and is the starting point when switching presets.",
1151
1151
  "cssVars": {
1152
1152
  "light": {
1153
1153
  "radius": "0.5rem",
@@ -1253,8 +1253,8 @@ var THEME_PRESETS_DATA = [
1253
1253
  },
1254
1254
  {
1255
1255
  "id": "ocean",
1256
- "title": "\u30AA\u30FC\u30B7\u30E3\u30F3",
1257
- "description": "\u9752\u3092\u57FA\u8ABF\u306B\u3057\u305F\u30D7\u30EA\u30BB\u30C3\u30C8\u3002\u843D\u3061\u7740\u3044\u305F\u4FE1\u983C\u611F\u306E\u3042\u308B\u914D\u8272\u3067\u3001\u89D2\u4E38\u306F\u6A19\u6E96\u3088\u308A\u5C0F\u3055\u3081\u306E\u3084\u3084\u89D2\u3070\u3063\u305F\u5370\u8C61\u3002",
1256
+ "title": "Ocean",
1257
+ "description": "A blue preset with a calm, trustworthy palette and slightly smaller, squarer corners than the default.",
1258
1258
  "cssVars": {
1259
1259
  "light": {
1260
1260
  "radius": "0.375rem",
@@ -1360,8 +1360,8 @@ var THEME_PRESETS_DATA = [
1360
1360
  },
1361
1361
  {
1362
1362
  "id": "forest",
1363
- "title": "\u30D5\u30A9\u30EC\u30B9\u30C8",
1364
- "description": "\u7DD1\u3092\u57FA\u8ABF\u306B\u3057\u305F\u30D7\u30EA\u30BB\u30C3\u30C8\u3002\u89D2\u4E38\u306F\u3084\u3084\u5C0F\u3055\u3081\u3002\u66F8\u4F53\u306F\u4E38\u30B4\u30B7\u30C3\u30AF\u7CFB\uFF08Safari \u306E ui-rounded\u3001macOS / iOS \u306E\u30D2\u30E9\u30AE\u30CE\u4E38\u30B4\u3002\u307B\u304B\u306E\u74B0\u5883\u306F\u6A19\u6E96\u306E\u66F8\u4F53\uFF09\u3002",
1363
+ "title": "Forest",
1364
+ "description": "A green preset with slightly smaller corners. The font is a rounded sans-serif (ui-rounded in Safari, Hiragino Maru Gothic on macOS and iOS, the default font elsewhere).",
1365
1365
  "cssVars": {
1366
1366
  "light": {
1367
1367
  "radius": "0.5rem",
@@ -1467,8 +1467,8 @@ var THEME_PRESETS_DATA = [
1467
1467
  },
1468
1468
  {
1469
1469
  "id": "sunset",
1470
- "title": "\u30B5\u30F3\u30BB\u30C3\u30C8",
1471
- "description": "\u6A59\u3092\u57FA\u8ABF\u306B\u3057\u305F\u30D7\u30EA\u30BB\u30C3\u30C8\u3002\u6E29\u304B\u307F\u306E\u3042\u308B\u914D\u8272\u3067\u3001\u89D2\u4E38\u306F\u3084\u3084\u5927\u304D\u3081\u3002",
1470
+ "title": "Sunset",
1471
+ "description": "An orange preset with a warm palette and slightly larger corners.",
1472
1472
  "cssVars": {
1473
1473
  "light": {
1474
1474
  "radius": "0.75rem",
@@ -1574,8 +1574,8 @@ var THEME_PRESETS_DATA = [
1574
1574
  },
1575
1575
  {
1576
1576
  "id": "violet",
1577
- "title": "\u30D0\u30A4\u30AA\u30EC\u30C3\u30C8",
1578
- "description": "\u7D2B\u3092\u57FA\u8ABF\u306B\u3057\u305F\u30D7\u30EA\u30BB\u30C3\u30C8\u3002\u89D2\u4E38\u306F\u5927\u304D\u3081\u3067\u3084\u308F\u3089\u304B\u3044\u5370\u8C61\u3002",
1577
+ "title": "Violet",
1578
+ "description": "A purple preset with large, soft corners.",
1579
1579
  "cssVars": {
1580
1580
  "light": {
1581
1581
  "radius": "0.875rem",
@@ -1681,8 +1681,8 @@ var THEME_PRESETS_DATA = [
1681
1681
  },
1682
1682
  {
1683
1683
  "id": "rose",
1684
- "title": "\u30ED\u30FC\u30BA",
1685
- "description": "\u8D64\u7D2B\u304B\u3089\u30D4\u30F3\u30AF\u3092\u57FA\u8ABF\u306B\u3057\u305F\u30D7\u30EA\u30BB\u30C3\u30C8\u3002destructive \u306E\u8D64\u3068\u6DF7\u540C\u3057\u306A\u3044\u843D\u3061\u7740\u3044\u305F\u8272\u3067\u3001\u89D2\u4E38\u306F\u5927\u304D\u3081\u3002",
1684
+ "title": "Rose",
1685
+ "description": "A magenta-to-pink preset in muted tones that don't read as the destructive red, with large corners.",
1686
1686
  "cssVars": {
1687
1687
  "light": {
1688
1688
  "radius": "1rem",
@@ -1788,8 +1788,8 @@ var THEME_PRESETS_DATA = [
1788
1788
  },
1789
1789
  {
1790
1790
  "id": "mono",
1791
- "title": "\u30E2\u30CE",
1792
- "description": "\u7121\u5F69\u8272\u5BC4\u308A\u306E\u30D7\u30EA\u30BB\u30C3\u30C8\u3002\u30C1\u30E3\u30FC\u30C8\u3082\u5F69\u5EA6\u3092\u6291\u3048\u3001\u89D2\u4E38\u306F\u6700\u5C0F\u3002\u66F8\u4F53\u306F\u7B49\u5E45\uFF08\u30B7\u30B9\u30C6\u30E0\u306E\u7B49\u5E45\u30D5\u30A9\u30F3\u30C8\uFF09\u3002",
1791
+ "title": "Mono",
1792
+ "description": "A near-grayscale preset with muted chart colors, the smallest corners and a monospace font (the system monospace font).",
1793
1793
  "cssVars": {
1794
1794
  "light": {
1795
1795
  "radius": "0.25rem",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@squadbase/vantage-template",
3
- "version": "0.1.1-dev1.7c71823",
3
+ "version": "0.1.1-dev1.80c51bb",
4
4
  "description": "CLI tool for initializing and customizing Squadbase Vantage projects.",
5
5
  "keywords": [
6
6
  "squadbase",
@@ -50,7 +50,7 @@
50
50
  "@ai-sdk/openai": "2.0.122",
51
51
  "ai": "^5.0.52"
52
52
  },
53
- "gitHead": "7c71823f425ae7ea55b59bb2d459f8f15bf2be49",
53
+ "gitHead": "80c51bb5594930f164d4ac511b08a347c9844bc2",
54
54
  "scripts": {
55
55
  "sync-base": "rsync -a --delete --exclude='node_modules' --exclude='dist' --exclude='.vantage' --exclude='*.tsbuildinfo' --exclude='*.log' template/ base-template/ && mv base-template/.gitignore base-template/_gitignore",
56
56
  "build": "pnpm run sync-base && tsup",