camelToSnake and snakeCamelMapper() drop the underscore when a digit precedes a camelCase boundary

Đang mở Phù hợp với người mới
#4,855 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

Đánh giá

Độ khó
2/5
Thời gian dự kiến
1-3 giờ
Mức phù hợp với người mới
85/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
postgresql, typescript
Lĩnh vực
api

Hướng nghiên cứu

Lỗi nằm ở camelToSnake trong packages/typescript-client/src/column-mapper.ts, biểu thức chính quy xác định ranh giới /([a-z_])([A-Z])/g của nó bỏ sót các chuyển tiếp từ chữ số sang chữ hoa. Chạy repro trong issue để thấy sha256Hash thành sha256hash. Hoàn thành khi camelToSnake trả về sha256_hash, oauth2_token, address1_line và v2_payload, và các test của column-mapper bao phủ các ranh giới chữ số.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

Versions

  • Client: typescript, @electric-sql/client 1.5.28 (also on main 3f9809fb0b, Node v26.13.0)
  • Electric: any (happens client-side before the request reaches Electric)

Bug description

snakeToCamel converts a column like sha256_hash into sha256Hash, and its doc comment states that the transform is round-trippable via camelToSnake. However, camelToSnake in packages/typescript-client/src/column-mapper.ts only inserts _ before an uppercase letter that follows [a-z_], so camelToSnake("sha256Hash") returns "sha256hash".

When ShapeStream or compileExpression uses snakeCamelMapper(), incoming rows are decoded with key sha256Hash, while columns, where, and subset expressions encode sha256Hash as sha256hash, sending a column name that does not exist in Postgres.

// repro.mjs
// npm i @electric-sql/[email protected] && node repro.mjs
import {
  ShapeStream,
  snakeCamelMapper,
  snakeToCamel,
  camelToSnake,
  compileExpression,
} from "@electric-sql/client"

for (const col of ["sha256_hash", "oauth2_token", "address1_line", "v2_payload"]) {
  const camel = snakeToCamel(col)
  console.log(`${col} -> ${camel} -> ${camelToSnake(camel)}`)
}

console.log(
  "compileExpression:",
  compileExpression({ type: "ref", column: "sha256Hash" }, snakeCamelMapper().encode)
)

const fetchClient = async (url) => {
  const u = new URL(url)
  console.log("columns sent:", u.searchParams.get("columns"))
  console.log("where sent:", u.searchParams.get("where"))
  return new Response("[]", { status: 400 })
}

const stream = new ShapeStream({
  url: "http://localhost:3000/v1/shape",
  params: {
    table: "files",
    columns: ["id", "sha256Hash"],
    where: "sha256Hash = $1",
    params: ["abc"],
  },
  columnMapper: snakeCamelMapper(),
  subscribe: false,
  fetchClient,
  onError: () => stream.unsubscribeAll(),
})
stream.subscribe(() => {})

Actual output:

sha256_hash -> sha256Hash -> sha256hash
oauth2_token -> oauth2Token -> oauth2token
address1_line -> address1Line -> address1line
v2_payload -> v2Payload -> v2payload
compileExpression: "sha256hash"
columns sent: "id","sha256hash"
where sent: sha256hash = $1

Expected behavior

camelToSnake should return sha256_hash, oauth2_token, address1_line, and v2_payload, compileExpression should return "sha256_hash", columns should be "id","sha256_hash", and where should be sha256_hash = $1. Changing the first boundary regex in camelToSnake from /([a-z_])([A-Z])/g to /([a-z0-9_])([A-Z])/g preserves the underscore after digits.

Credit: https://ucsbplse.github.io/

Ngôn ngữ chính
TypeScript
Star
10.4k
Fork
399
Chỉ số merge pull request
Không có pull request nào được merge trong 30 ngày

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của electric-sql/electric

Tất cả issue của electric-sql/electric

Issue tương tự

Thêm issue về TypeScript

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.