@wishknish/knishio-client-ts 1.1.0 → 1.2.0

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wishknish/knishio-client-ts",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "productName": "Knish.IO TypeScript SDK Client",
5
5
  "description": "TypeScript implementation of the Knish.IO SDK to consume Knish.IO GraphQL APIs with enhanced type safety.",
6
6
  "license": "GPL-3.0-or-later",
package/src/index.ts CHANGED
@@ -403,7 +403,7 @@ export {
403
403
  // MUST equal package.json's "version". The CI `version consistency` job enforces this via
404
404
  // .github/scripts/check-version.sh, which parses this exact line — keep the literal form
405
405
  // `export const SDK_VERSION = '<semver>'` intact so the gate can read it.
406
- export const SDK_VERSION = '1.1.0'
406
+ export const SDK_VERSION = '1.2.0'
407
407
  export const SDK_NAME = 'KnishIO-Client-TS'
408
408
  export const COMPATIBLE_SERVER_VERSIONS = [4, 5]
409
409
 
@@ -55,6 +55,7 @@ import {
55
55
  } from '@urql/core'
56
56
  import { createClient as createWSClient } from 'graphql-ws'
57
57
  import { pipe, subscribe } from 'wonka'
58
+ import { CodeException } from '@/exception'
58
59
  import type {
59
60
  GraphQLClient as IGraphQLClient,
60
61
  GraphQLRequest,
@@ -200,17 +201,29 @@ export default class GraphQLClient implements IGraphQLClient {
200
201
  private async cipherFetch(input: any, init: any): Promise<Response> {
201
202
  const wallet = this.$__wallet
202
203
  const serverPubkey = this.$__pubkey
203
- let encryptedRequest = false
204
+ // Non-null only on the encrypted path, so the response decrypt needs no assertion.
205
+ let cipherWallet: Wallet | null = null
204
206
  let requestInit = init
205
207
 
206
- if (wallet && serverPubkey && init && typeof init.body === 'string' && this.shouldEncrypt(init.body)) {
208
+ // Decide the bypass FIRST, then demand the keys: a bypassed operation (`__schema`,
209
+ // `ContinuId`, `AccessToken`, U-isotope `ProposeMolecule`) must still go out in plaintext or
210
+ // the auth bootstrap would deadlock encrypting to a server pubkey it has not learned yet.
211
+ // Anything else on an encryption-enabled client fails closed rather than silently
212
+ // downgrading to plaintext (matches PHP Cipher.php / Kotlin HttpClient).
213
+ if (init && typeof init.body === 'string' && this.shouldEncrypt(init.body)) {
214
+ if (!wallet) {
215
+ throw new CodeException('Authorized wallet missing.')
216
+ }
217
+ if (!serverPubkey) {
218
+ throw new CodeException('Server public key missing.')
219
+ }
207
220
  const hashVar = await wallet.encryptStringML(init.body, serverPubkey)
208
221
  requestInit = { ...init, body: JSON.stringify({ query: CIPHER_HASH_QUERY, variables: { Hash: hashVar } }) }
209
- encryptedRequest = true
222
+ cipherWallet = wallet
210
223
  }
211
224
 
212
225
  const response = await fetch(input, requestInit)
213
- if (!encryptedRequest) {
226
+ if (!cipherWallet) {
214
227
  return response
215
228
  }
216
229
 
@@ -228,7 +241,7 @@ export default class GraphQLClient implements IGraphQLClient {
228
241
  // Plaintext (e.g. a validator-side error response) — pass through unchanged.
229
242
  return new Response(text, init2)
230
243
  }
231
- const decrypted = await wallet!.decryptMyMessageML(JSON.parse(hash))
244
+ const decrypted = await cipherWallet.decryptMyMessageML(JSON.parse(hash))
232
245
  return new Response(decrypted != null ? decrypted : text, init2)
233
246
  }
234
247