注意!
この方法は2025年10月4日時点でのハックです。
責任は取れません…
が、一旦動いたので共有します。(そのうち動かなくなるだろうな…)
前提
- 現時点では
Remote functions
をラップしたものをexport
できない -
Remote functions
を呼び出す側からSchemaに引数を渡すことができない
例
例えば記事の本文の最大文字数を管理画面上で指定できるアプリケーションがあったとします。
このようなSchemaです。
const schema = v.object({
text: v.pipe(v.string(), v.minLength(min)), // minが変化する
})
min
は変更したいので、
const getSchema = (min: number) => v.object({
text: v.pipe(v.string(), v.minLength(min)),
})
const schema = getSchema(20)
こんな感じで使うことになるでしょう。
このときRemote functions
は
export const addPost = (min: number) => query(getSchema(min), async (({ text })) => {
const post = await db … // 記事をインサート
return {
success: true
}
});
こんな感じにしたいと思いますが、現状これができません。
all exports from this file must be remote functions
というエラーメッセージが表示され、エラーで落ちてしまいます。
色々試しましたが、そもそもqueryなどをラップした時点でダメっぽかったのでいろいろ試して動いたのが以下のコードです。
import { json } from '@sveltejs/kit';
export const GET = async () => {
// ここで管理画面で設定した値を返す
return json({ min: 20 });
};
export const addPost = query(
// 変わったのはここから
await fetch('http://localhost:5173/test').then(async (res) => {
const data = await res.json();
return v.object({
text: v.pipe(v.string(), v.minLength(data.min)),
});
}),
// ここまで
async (({ text })) => {
const post = await db … // 記事をインサート
return {
success: true
}
});
queryの一つ目の引数部分で+server.tsにfetchしてSchemaを返すようにしました。
型は終わっていますし多分こんなことはやらない方がいいと思いますが、
一旦これでエラーが出ない状態でバリデーションが機能します。
センシティブなデータを取り扱う場合はこれだと都合が悪いと思いますが、
クライアントサイドのバリデーションですでにユーザーに知られている情報の場合はこれでもまぁ良さそうです。
- サーバーサイドとクライアントサイドで別でバリデーションする
- サーバーサイドだけで追加のバリデーションを行うことでSchemaを静的にする
- FormDataとしてminを渡してしまう
- localsで受け取る
この辺も考えられますが、あまり面倒なことはせずSchemaでできる限りのバリデーションを行っておきたいので
export const addPost = (min: number) => query(getSchema(min)
こういうのが許されて欲しいな〜と思いました。
experimentalが取れていないので今後に期待ですね。
最後に…
この方法は2025年10月4日時点でのハックです。
責任は取れません…
読んでくださりありがとうございました。