Open5

Svellte/SvelteKit tips集

ryoppippiryoppippi

問題

import { PrismaClient } from "@prisma/client"
export const prisma = new PrismaClient()

こんな感じにフツーにPrismaClientを定義して、
Prisma & SvelteKitをadapter-nodeでbuildして動かそうとすると

 ReferenceError: __dirname is not defined in ES module scope 

エラーが出る。

解決策

https://github.com/prisma/prisma/issues/15614

requireを用いてimportする。
ただし、普通にrequireするだけでは型補完が効かなくなるので、少々Hackyな方法で定義する。
Github Issue Comment参照

$lib/server/prisma.ts
import type { PrismaClient as ImportedPrismaClient } from '@prisma/client';
import { createRequire } from 'module';

const require = createRequire(import.meta.url ?? __filename);

const { PrismaClient: RequiredPrismaClient } = require('@prisma/client');

const _PrismaClient: typeof ImportedPrismaClient = RequiredPrismaClient;

export class PrismaClient extends _PrismaClient {}
$lib/server/db.ts
import { PrismaClient } from './prisma';
export const db = new PrismaClient();

なぜ起きるか

__dirname や __filename は、CommonJSで定義されているが、ESMでは定義されていない。
SvelteKitでは基本的にESMなため、Conflictする。
(ちなみにSolidStartとかでもこの問題は起きるっぽい)

Issueに興味深いコメントあり

As you are likely aware, the root cause seems to be that we're using ES2022 but the Prisma client is using an old __dirname() function that isn't support/available in ES2022, which I believe is the default used in SvelteKit. The reason for the continued use of this __dirname() function for the detection of the environment specifically for Vercel hosted websites.

ご存知のように、根本的な原因は、ES2022を使っているのに、PrismaクライアントがES2022ではサポート/利用できない古い__dirname()関数を使っていることにあるようです(これはSvelteKitで使われているデフォルトだと思います)。この__dirname()関数を使い続けている理由は、VercelがホストするWebサイトに特化した環境の検出のためです。

だからかー。Vercelに上げてる人が多いからみんなハマってないのか。ぐぬぬぬぬ

ryoppippiryoppippi

問題

NeovimのSvelte LSPがjs/tsの変更を検知してくれない

解決策

https://github.com/neovim/nvim-lspconfig/issues/725#issuecomment-1539789005
nvim-lspconfigを使っているなら以下の設定を入れよう

lspconfig.svelte.setup{
      on_attach = function(client, bufnr)
  vim.api.nvim_create_autocmd("BufWritePost", {
    pattern = { "*.js", "*.ts" },
    callback = function(ctx)
      -- Here use ctx.match instead of ctx.file
      client.notify("$/onDidChangeTsOrJsFile", { uri = ctx.match })
    end,
  })
end,
}

原因

https://github.com/neovim/nvim-lspconfig/issues/725#issuecomment-1538535131
Svelte LSPが、 他のLSPではよく使われているdidChangeWatchedFilesではなく、$/onDidChangeTsOrJsFileなる名前でnotificationを受けているらしい
なので、autocmdを使ってプロジェクト内のjstsファイルの変更を監視して、変更のたびにLSPの$/onDidChangeTsOrJsFileへ通知を送る実装をマニュアルで書かないといけない
流石に解決されるのは時間の問題かもしれないが。。。

あと新しいファイルも検知できてない
現在直してもらってる

ryoppippiryoppippi

Inlay hintsをNeovimで有効にする

Neovim 0.10.0でInlay hintsに対応
Svelte language serverも対応しているので

lspconfig.svelte.setup{
  on_attach = function(client, _)
    local root_dir = client.config.root_dir
    vim.api.nvim_create_autocmd("BufWritePost", {
      pattern = {
        root_dir .. "/*.js",
        root_dir .. "/*.ts",
      },
      callback = function(ctx)
        client.notify("$/onDidChangeTsOrJsFile", { uri = ctx.file })
      end,
    })
  end,
  settings = {
    typescript = {
      inlayHints = {
        parameterTypes = { enabled = true },
        enumMemberValues = { enabled = true },
        parameterNames = {
          suppressWhenArgumentMatchesName = true,
          enabled = "literals", -- 'none' | 'literals' | 'all';
        },
        functionLikeReturnTypes = { enabled = true },
        variableTypes = { enabled = true },
      },
    },

  }

これでうごきます。
ここら辺に色々書いてあります
https://github.com/sveltejs/language-tools/blob/48ae8ce082de4a570461926a10598c3b0c27ecd7/packages/language-server/src/ls-config.ts#L239-L251