Apollo-link-rest: Diskusi Fitur: Menambahkan inferensi nama ketik otomatis

Dibuat pada 26 Jan 2018  ·  22Komentar  ·  Sumber: apollographql/apollo-link-rest

Hai,

Setelah @fbartho 's PR (#55) menambahkan nama tipe ke objek bersarang, saya berharap dapat secara otomatis menyimpulkan nama tipe berdasarkan nama properti objek. Namun, ini tidak terjadi.

Setelah berbicara dengannya di Slack, dia menyarankan agar saya membuka masalah sehingga kita dapat mendiskusikan apakah ini layak karena properti jarang cocok dengan TypeName.

Dalam kasus penggunaan saya, ini akan memungkinkan untuk menghubungkan klien GraphQL dengan cepat ke server REST, sambil hanya menyediakan __typenames khusus yang diperlukan menggunakan implementasi @fbartho .

Saya melakukan implementasi fitur ini dan saya akan segera membuka PR.

enhancement💡 question❔

Komentar yang paling membantu

@mpgon & @Rsullivan00 Saya akan mendukung penambahan bagian #### Related Libraries dengan tautan & deskripsi 1 baris perpustakaan Anda ke README kami.

Semua 22 komentar

Terima kasih telah berkontribusi @sky-franciscogoncalves!! Saya rasa ini penting untuk dibahas.

Kekhawatiran pribadi saya adalah bahwa dalam GraphQL API yang saya lihat, hanya query paling sederhana yang memiliki nama bidang yang cocok yang dapat dengan aman dimasukkan pascal menjadi __typename . Banyak dari mereka memiliki konjugasi alternatif, sementara hampir semua mutation s tidak akan berfungsi.

Secara umum, ketika menerapkan typePatcher saya pikir orang khawatir tentang memiliki sihir "berbahaya" yang mungkin tidak Anda inginkan -- dan kemudian perlu menonaktifkan secara kondisional. => Kompleksitas!

Namun, saya masih pemula di GraphQL, jadi saya akan senang jika @peggyrayzis , @jbaxleyiii , atau @sabativi dapat memberikan masukan tentang ide fitur ini!

Melihat melalui API graphql saya sendiri, saya tidak melihat banyak kasus di mana kasus pascal bidang cocok dengan jenisnya karena biasanya saya lakukan

type Action {
  kind: ActionKind!
  name: String!
}

catatan agar pascal casing berfungsi dan tidak berbenturan dengan jenis lain yang mungkin, saya perlu memanggil kind -> actionKind yang terasa aneh karena Anda sudah tahu Anda berada di dalam suatu tindakan

type Action {
  actionKind: ActionKind!
  name: String!
}

Saya kira Anda bisa menggabungkan Skema induk (Tindakan) dengan bidang bersarang Pascal cased name (Jenis) memberi Anda ActionKind . Meskipun ini akan mencegah tipe berbagi yaitu

type Schedule {
  start: Float
  end: Float
}
type Task {
  schedule: Schedule!
  name: String!
}
type Job {
  schedule: Schedule!
  name: String!
}

Apa pendapat Anda tentang membebani anotasi yang ada sehingga dapat digunakan untuk bidang bersarang tanpa atribut path?

query MyQuery {
  action @rest(type: "Action", path: "action/") {
    id
    name
    kind @rest(type: "ActionKind") {
      name
    }
  }
}

Saya tahu ini berarti menambahkannya setiap kali Anda menggunakan bidang itu dalam kueri alih-alih satu kali selama inisialisasi tautan-sisa. Namun IMHO saya tidak keberatan sedikit verbositas ekstra untuk ketegasan. Anda juga sudah mendefinisikan jenis skema tingkat atas sehingga harus mendefinisikan jenis anak-anak tampaknya lebih konsisten.

Sedangkan sistem typePatcher terasa aneh bagi saya ketika Anda akhirnya mendefinisikan tipe di dua tempat yang sangat berbeda dan itu memindahkan masalah ini terlalu jauh dari kueri.

@cloudkite : jika Anda melihat tiket #48 ini, kami membahas opsi dari @-directive. Temuan umum saya adalah bahwa sebagian besar akan rawan kesalahan jika pengguna harus menambahkannya setiap kali mereka menambah & menghapus bidang dari set pilihan mereka.

Yang mengatakan, arahan @type(…) sebagian besar dapat menjadi aditif, jadi saya tidak akan terlalu menentang implementasi strategi itu. - 2 sen saya.

Mencoba menyimpulkan sesuatu yang tipenya tidak akan pernah berfungsi untuk semua kasus karena REST tidak memiliki standar dan setiap orang memiliki cara mereka sendiri untuk menamai titik akhir, sumber daya ... Jadi saya tidak melihat masa depan yang cerah untuk ini.
Namun yang menurut saya menarik adalah opsi @-directive yang muncul lagi di atas meja yang tampaknya mudah diatur tetapi ada kemungkinan orang terkadang melupakannya sehingga kami memerlukan cara untuk setidaknya memperingatkan mereka tentang hal ini.

Sebagai solusi pribadi, saya bekerja dengan skema untuk pengaturan apollo-link-state / apollo-link-rest saya di perusahaan saya, dan saya menulis alat yang melihat/mem-parsing file-file itu, dan menghasilkan kode typePatcher saya apollo-codegen untuk membuat kode binding TypeScript. Saya akan membagikannya di sini, tetapi ini bukan skrip yang ramah jadi saya pikir itu bukan solusi yang berlaku secara umum, tetapi itu akan berfungsi untuk kebutuhan tim saya.

Terima kasih atas tanggapan Anda. Saya masih sangat baru di GraphQL, jadi saya minta maaf atas kurangnya pengetahuan saya.

Menurut pendapat saya, solusi saat ini dapat membingungkan bagi pendatang baru. Karena tidak begitu jelas bagaimana TypePatcher bekerja, atau bagaimana pengguna harus menggunakannya.

Saya sangat menyukai solusi @cloudkite , karena ini akan memungkinkan pemahaman yang lebih baik tentang kueri bagi siapa pun yang membacanya. Jika kami bergerak maju dengan solusi ini, saya setuju dengan @sabativi bahwa kami harus memberi tahu orang-orang jika mereka lupa memberi anotasi pada kueri.

Di sisi lain, haruskah kita melakukan hal yang sama jika kita tetap berpegang pada solusi saat ini?

Saya juga bertanya-tanya apakah kami dapat mengambil manfaat dari mengikat skema ke RestLink sehingga kami dapat menyimpulkan nama jenis dari itu.

Jika kita memiliki skema seperti ini:

type Schedule {
  start: Float
  end: Float
}
type Task {
  schedule: Schedule!
  name: String!
}

Kemudian saat melakukan kueri, kami dapat memverifikasi bahwa tipe Task sebenarnya didefinisikan dalam skema dan objek bersarang schedule akan memiliki nama tipe yang disimpulkan dari tipe yang ditentukan dalam skema.

query MyQuery {
  task @rest(type: "Task", path: "task/") {
    name
    schedule {
      start
      end
    }
  }
}

Bisakah sesuatu seperti ini bekerja?

Saya sangat menyukai pendekatan di mana semua yang harus Anda tulis ada di dalam kueri, misalnya

query MyQuery {
  action @rest(type: "Action", path: "action/") {
    id
    name
    kind @type(name: "ActionKind") {
      name
    }
  }
}

Jauh lebih jelas bagi pendatang baru.

Mendefinisikan tipe seperti yang Anda sarankan juga dapat membingungkan seseorang yang mempelajari graphQL karena ini lebih merupakan sesuatu yang harus Anda lakukan di sisi server.

Saya suka percakapan ini

@sabativi , terima kasih atas masukannya!

Saya telah bermain-main dengan perpustakaan ini dan saya masih merasa bahwa kita harus mencoba menulis semua yang kita bisa di dalam kueri. Namun, ada beberapa kasus di mana hal itu tidak mungkin dilakukan.

Misalnya, jika Anda memiliki objek bersarang polimorfik di mana tipenya diberikan dari properti, Anda harus memiliki cara untuk melakukan operasi kompleks. Oleh karena itu, kecuali kami menemukan solusi yang berbeda, TypePatcher sangat membantu.

Contoh di mana kumpulan atribut dapat berubah tergantung pada properti tipe.:

{
  animals: [
    {
      type: 'cat',
      attributes: {
          ....
      },
    },
    {
      type: 'dog',
      attributes: {
          ....
      },
    },
  ],
}

Masalah menyematkan semua yang ada dalam kueri Anda adalah Anda harus mengulanginya sendiri di mana saja.

Contoh: Meskipun objek Pengguna mungkin disematkan di N API, Anda harus melampirkan anotasi Jenis untuk setiap subbagian pengguna di setiap kueri yang memiliki pengguna. Jika Anda memiliki currentUser, Budlist, RecommendList, NearUsers sebagai kueri dan pengguna memiliki alamat, linkedAccounts, appData, sebagai sub-model, maka Anda harus menulis 4 x 3 = 12 Ketik anotasi — dan dengan asumsi setiap kueri hanya dirender sekali! Dengan typePatcher yang saat ini diimplementasikan, Anda hanya perlu menambal satu kali per submodel.

Hal yang paling mengganggu dalam pikiran saya tentang anotasi @type adalah bahwa setiap pengguna harus menyalin tempel / menulis ulang anotasi saat mereka bereksperimen dengan kueri mereka dan menambahkan-menghapus pilihan properti yang diketik. Ini akan menjadi titik gesekan besar untuk menggunakannya.

Untuk lebih jelasnya, saya tidak keberatan jika kita menambahkan anotasi — ini akan bagus untuk injeksi api REST yang sangat ringan. — jika Anda hanya ingin membungkus satu atau dua titik akhir REST kecil. Saya akan kecewa jika ini adalah satu-satunya atau cara yang disarankan untuk membungkus API. Karena kami merekomendasikan link-rest sebagai langkah pertama bagi orang-orang yang memigrasikan API berukuran penuh ke GraphQL, mendorong pola ini mungkin akan menakut-nakuti sejumlah orang yang tidak sepele, sama sekali!

Saya sepenuhnya setuju dengan Anda. Kita harus menjaga kedua pendekatan dan, jika memungkinkan, biarkan mereka berinteraksi.

Saya sudah mulai bermain-main dengan kemungkinan implementasi untuk memungkinkan perilaku ini. Namun, saya tidak yakin apakah saya mengambil pendekatan terbaik.

Saat ini, ia dapat menambahkan nama tipe setiap objek bersarang dan larik (dari larik) objek yang menambahkan anotasi @type(name: "Type") .

Juga, jika TypePatcher menambahkan nama ketik ke objek beranotasi, itu akan diganti dengan anotasi. Kita dapat mengubah tindakan ini dengan melewatkannya jika nama jenis sudah disetel.

Sayangnya, saya tidak dapat memberikan implementasi yang memungkinkan untuk menambahkan tipe beranotasi yang selanjutnya ditangani oleh TypePatcher. Seperti, jika saya mengerti dengan benar, TypePatcher bertindak sebelum saya menganalisis apakah ada anotasi @type . Itulah sebabnya kami mendapatkan perilaku penggantian secara gratis.

Anda dapat memeriksanya di sini . Saya telah menambahkan kasus uji yang menunjukkan apa yang saya sebutkan sebelumnya.

@fbartho Memiliki beberapa kueri menggunakan tipe yang sama dapat diselesaikan menggunakan fragmen. Anda cukup menentukan satu fragmen yang menambahkan semua anotasi @type(name: "Type") dan pengguna cukup menarik fragmennya.

@pyros2097 menggunakan fragmen bersama untuk meningkatkan kueri dengan @type adalah ide cerdas yang tidak saya pertimbangkan.

  • Bagaimana tepatnya Anda akan membagikan fragmen itu sehingga semua kueri dapat menggunakannya?
  • Apa yang terjadi ketika dua arah bertabrakan?

Inilah yang ingin saya lakukan menggunakan apollo-link-rest. Tapi gagal adalah tipe yang sangat bersarang. mis: Ini menimbulkan kesalahan untuk gambar { url } yang mengatakan tidak dapat membaca __typename untuk 'url' yang akan dipecahkan oleh arahan

export const UserFragment = gql`
  fragment UserFragment on User {
    id
    first_name
    last_name
    image @type(name: "Image") {
      ...ImageFragment
    }
  }
`;

export const ImageFragment = gql`
  fragment ImageFragment on Image {
    url
    width
    height
  }
`;

export const AdventureFragment = gql`
  fragment AdventureFragment on Adventure {
    id
    name
    user @type(name: "User") {
      ...UserFragment
    }
    cover_photo @type(name: "Image") {
      ...ImageFragment
    }
    created_at
    updated_at
  }
`;

export const GetUserQuery = gql`
  query UserAdventures($page: Int!) {
    user @rest(method: "GET", path: "/api/current", type: "User") {
      id @export(as: "id")
      ...UserFragment
      adventures(page: $page) @rest(method: "GET",  path: "/api/adventures", params: { id: $id }, type: "Adventure") {
        ...AdventureFragment
      }
    }
  }
  ${ImageFragment}
  ${UserFragment}
  ${AdventureFragment}
`;
  • Sangat mudah untuk membagikan fragmen, Anda hanya perlu mendeklarasikannya secara terpisah dan memasukkannya ke dalam kueri tempat Anda ingin menggunakannya.
  • Jika 2 arahan bertabrakan, saya kira arahan/fragmen terakhir dengan arahan itu akan didahulukan. Perlu memverifikasi ini.

@pyros2097 -- data JSON apa yang Anda berikan untuk tanggapan Anda? Contoh Anda terlihat baik-baik saja, tetapi seharusnya tidak mencoba menggunakan ___typename dari url jika url hanyalah sebuah string?

url hanyalah sebuah string tetapi memberi saya peringatan untuk semua kunci dalam fragmen gambar. Juga memberitahu saya untuk menggunakan IntrospectionFragmentMatcher dari apollo-inmemory-cache. Ini bisa menjadi cache memori apollo yang tidak dapat mengidentifikasi jenis untuk cache dan tidak terkait dengan apollo-link-rest.

fragmentMatcher: By default, the InMemoryCache uses a heuristic fragment matcher.
If you are using
fragments on unions and interfaces, you will need to use an IntrospectionFragmentMatcher.
For more
information, please read [our guide to setting up fragment matching for unions & interfaces].

@sky-franciscogoncalves Silakan kirimkan anotasi @type() sebagai PR ke repo ini sehingga kami dapat mendiskusikannya secara langsung tanpa memperumitnya lebih lanjut dalam diskusi tentang inferensi nama jenis "otomatis".

Tidak ada tindakan pada utas ini sejak Februari, dan kami secara terpisah membuka #72 untuk menerapkan petunjuk manual @type(name: …) , jadi saya merasa nyaman menutup tiket ini seperti yang dilakukan untuk saat ini. Silakan buka kembali jika Anda ingin terus mendiskusikan teknik untuk inferensi nama ketik yang benar-benar "otomatis" -- terutama jika kita dapat memikirkan cara standar yang aman untuk melakukannya. -- Saya pikir diskusi kita tidak menemukan teknik itu.

Hai @fbartho! Saya tahu utas ini ditutup cukup lama, tetapi sebelumnya dikatakan, sejauh yang saya bisa temukan, belum ada cara untuk dengan mudah menyimpulkan nama jenis. Meskipun anotasi @type sangat bagus untuk membuat eksperimen, itu tidak berskala. Dan meskipun typepatcher fungsional yang dikembangkan di #55 adalah alternatif yang sangat bagus, saya merasa masih terlalu bertele-tele untuk mengetik API besar.
Dengan begitu, saya akan sangat tertarik dengan pendapat tentang lib yang saya buat untuk mengetik dengan mudah menambal API besar. Ini disebut apollo-type-patcher dan inilah demo kode dan

Bagi siapa pun yang menemukan utas ini dan bekerja dengan layanan yang sesuai dengan JSON API , saya telah memotong Tautan API JSON untuk secara otomatis menyimpulkan jenis sumber daya. Ini juga memberikan beberapa perataan hubungan yang nyaman.

@mpgon & @Rsullivan00 Saya akan mendukung penambahan bagian #### Related Libraries dengan tautan & deskripsi 1 baris perpustakaan Anda ke README kami.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat