@milaboratories/pl-client 2.16.12 → 2.16.13

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.
Files changed (33) hide show
  1. package/dist/core/driver.cjs +1 -1
  2. package/dist/core/driver.cjs.map +1 -1
  3. package/dist/core/driver.js +1 -1
  4. package/dist/core/driver.js.map +1 -1
  5. package/dist/core/ll_client.cjs +17 -7
  6. package/dist/core/ll_client.cjs.map +1 -1
  7. package/dist/core/ll_client.d.ts.map +1 -1
  8. package/dist/core/ll_client.js +17 -7
  9. package/dist/core/ll_client.js.map +1 -1
  10. package/dist/core/websocket_stream.cjs +126 -129
  11. package/dist/core/websocket_stream.cjs.map +1 -1
  12. package/dist/core/websocket_stream.d.ts +29 -22
  13. package/dist/core/websocket_stream.d.ts.map +1 -1
  14. package/dist/core/websocket_stream.js +127 -130
  15. package/dist/core/websocket_stream.js.map +1 -1
  16. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.cjs +136 -0
  17. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.cjs.map +1 -1
  18. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.d.ts +75 -1
  19. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.d.ts.map +1 -1
  20. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.js +135 -1
  21. package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.js.map +1 -1
  22. package/dist/proto-rest/index.cjs +16 -2
  23. package/dist/proto-rest/index.cjs.map +1 -1
  24. package/dist/proto-rest/index.d.ts.map +1 -1
  25. package/dist/proto-rest/index.js +16 -2
  26. package/dist/proto-rest/index.js.map +1 -1
  27. package/package.json +6 -6
  28. package/src/core/driver.ts +1 -1
  29. package/src/core/ll_client.ts +25 -8
  30. package/src/core/websocket_stream.test.ts +19 -8
  31. package/src/core/websocket_stream.ts +154 -166
  32. package/src/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.ts +179 -1
  33. package/src/proto-rest/index.ts +17 -2
@@ -14,9 +14,23 @@ function createClient(opts) {
14
14
  const client = createOpenApiClient({
15
15
  baseUrl: `${scheme}${opts.hostAndPort}`,
16
16
  fetch: (input) => {
17
- return undici.fetch(input.url, {
18
- ...input,
17
+ // If body has already been consumed, clone the request
18
+ const request = input.bodyUsed ? input.clone() : input;
19
+ return undici.fetch(request.url, {
20
+ body: request.body,
21
+ cache: request.cache,
22
+ credentials: request.credentials,
19
23
  dispatcher: opts.dispatcher,
24
+ duplex: request.duplex,
25
+ headers: request.headers,
26
+ integrity: request.integrity,
27
+ keepalive: request.keepalive,
28
+ method: request.method,
29
+ mode: request.mode,
30
+ redirect: request.redirect,
31
+ referrer: request.referrer,
32
+ referrerPolicy: request.referrerPolicy,
33
+ signal: request.signal,
20
34
  });
21
35
  },
22
36
  });
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../src/proto-rest/index.ts"],"sourcesContent":["//\n// This file is NOT autogenerated!\n//\n// After generating new clients from openapi specifications, add client types here.\n//\n\nimport type { paths as PlApiPaths } from './plapi';\nimport { default as createOpenApiClient, type Middleware, type Client } from 'openapi-fetch';\nimport { Dispatcher, fetch as undiciFetch } from 'undici';\nimport { rethrowMeaningfulError } from '../core/errors';\nimport { Code } from '../proto-grpc/google/rpc/code';\n\nexport { PlApiPaths };\nexport type PlRestClientType = Client<PlApiPaths>;\n\nexport type RestClientConfig = {\n hostAndPort: string;\n ssl: boolean;\n dispatcher: Dispatcher;\n middlewares: Middleware[];\n}\n\nexport function createClient<Paths extends {}>(opts: RestClientConfig): Client<Paths> {\n const scheme = opts.ssl ? 'https://' : 'http://';\n const client = createOpenApiClient<Paths>({\n baseUrl: `${scheme}${opts.hostAndPort}`,\n fetch: (input: Request): Promise<Response> => {\n return undiciFetch(input.url, {\n ...input,\n dispatcher: opts.dispatcher,\n });\n },\n });\n client.use(errorHandlerMiddleware(), ...opts.middlewares);\n return client;\n}\n\nexport type ErrorResponse = {\n code: Code,\n message: string,\n details: any[],\n}\nexport async function parseResponseError(response: Response): Promise<{\n error?: ErrorResponse | string,\n origBody?: string,\n}>{\n if (response.status < 400) {\n return {};\n }\n\n let error: any = await response.clone().text();\n const origBody = error;\n try {\n error = JSON.parse(error) as ErrorResponse;\n } catch {\n }\n return {\n error: error,\n origBody\n };\n}\n\n/**\n * Parses all API responses and thrown error in case of error response.\n * Allows all callers to not bother about .error response field checking.\n */\nfunction errorHandlerMiddleware(): Middleware {\n return {\n onResponse: async ({ request: _request, response, options: _options }) => {\n const respErr = await parseResponseError(response);\n if (!respErr.error) {\n const { body, ...resOptions } = response;\n return new Response(body, { ...resOptions, status: response.status });\n }\n\n if (typeof respErr.error === 'string') {\n throw new Error(respErr.error);\n }\n\n rethrowMeaningfulError(respErr.error);\n },\n };\n}\n"],"names":["undiciFetch","rethrowMeaningfulError"],"mappings":";;;;;;AAAA;AACA;AACA;AACA;AACA;AAkBM,SAAU,YAAY,CAAmB,IAAsB,EAAA;AACnE,IAAA,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,GAAG,UAAU,GAAG,SAAS;IAChD,MAAM,MAAM,GAAG,mBAAmB,CAAQ;AACxC,QAAA,OAAO,EAAE,CAAA,EAAG,MAAM,GAAG,IAAI,CAAC,WAAW,CAAA,CAAE;AACvC,QAAA,KAAK,EAAE,CAAC,KAAc,KAAuB;AAC3C,YAAA,OAAOA,YAAW,CAAC,KAAK,CAAC,GAAG,EAAE;AAC5B,gBAAA,GAAG,KAAK;gBACR,UAAU,EAAE,IAAI,CAAC,UAAU;AAC5B,aAAA,CAAC;QACJ,CAAC;AACF,KAAA,CAAC;IACF,MAAM,CAAC,GAAG,CAAC,sBAAsB,EAAE,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC;AACzD,IAAA,OAAO,MAAM;AACf;AAOO,eAAe,kBAAkB,CAAC,QAAkB,EAAA;AAIzD,IAAA,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE;AACzB,QAAA,OAAO,EAAE;IACX;IAEA,IAAI,KAAK,GAAQ,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE;IAC9C,MAAM,QAAQ,GAAG,KAAK;AACtB,IAAA,IAAI;AACF,QAAA,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAkB;IAC5C;AAAE,IAAA,MAAM;IACR;IACA,OAAO;AACL,QAAA,KAAK,EAAE,KAAK;QACZ;KACD;AACH;AAEA;;;AAGG;AACH,SAAS,sBAAsB,GAAA;IAC7B,OAAO;AACL,QAAA,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAI;AACvE,YAAA,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,QAAQ,CAAC;AAClD,YAAA,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;gBAClB,MAAM,EAAE,IAAI,EAAE,GAAG,UAAU,EAAE,GAAG,QAAQ;AACxC,gBAAA,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,GAAG,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;YACvE;AAEA,YAAA,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,EAAE;AACrC,gBAAA,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAChC;AAEA,YAAAC,6BAAsB,CAAC,OAAO,CAAC,KAAK,CAAC;QACvC,CAAC;KACF;AACH;;;;;"}
1
+ {"version":3,"file":"index.cjs","sources":["../../src/proto-rest/index.ts"],"sourcesContent":["//\n// This file is NOT autogenerated!\n//\n// After generating new clients from openapi specifications, add client types here.\n//\n\nimport type { paths as PlApiPaths } from './plapi';\nimport { default as createOpenApiClient, type Middleware, type Client } from 'openapi-fetch';\nimport { Dispatcher, fetch as undiciFetch } from 'undici';\nimport { rethrowMeaningfulError } from '../core/errors';\nimport { Code } from '../proto-grpc/google/rpc/code';\n\nexport { PlApiPaths };\nexport type PlRestClientType = Client<PlApiPaths>;\n\nexport type RestClientConfig = {\n hostAndPort: string;\n ssl: boolean;\n dispatcher: Dispatcher;\n middlewares: Middleware[];\n}\n\nexport function createClient<Paths extends {}>(opts: RestClientConfig): Client<Paths> {\n const scheme = opts.ssl ? 'https://' : 'http://';\n const client = createOpenApiClient<Paths>({\n baseUrl: `${scheme}${opts.hostAndPort}`,\n fetch: (input: Request): Promise<Response> => {\n // If body has already been consumed, clone the request\n const request = input.bodyUsed ? input.clone() : input;\n\n return undiciFetch(request.url, {\n body: request.body,\n cache: request.cache,\n credentials: request.credentials,\n dispatcher: opts.dispatcher,\n duplex: request.duplex,\n headers: request.headers,\n integrity: request.integrity,\n keepalive: request.keepalive,\n method: request.method,\n mode: request.mode,\n redirect: request.redirect,\n referrer: request.referrer,\n referrerPolicy: request.referrerPolicy,\n signal: request.signal,\n });\n },\n });\n client.use(errorHandlerMiddleware(), ...opts.middlewares);\n return client;\n}\n\nexport type ErrorResponse = {\n code: Code,\n message: string,\n details: any[],\n}\nexport async function parseResponseError(response: Response): Promise<{\n error?: ErrorResponse | string,\n origBody?: string,\n}>{\n if (response.status < 400) {\n return {};\n }\n\n let error: any = await response.clone().text();\n const origBody = error;\n try {\n error = JSON.parse(error) as ErrorResponse;\n } catch {\n }\n return {\n error: error,\n origBody\n };\n}\n\n/**\n * Parses all API responses and thrown error in case of error response.\n * Allows all callers to not bother about .error response field checking.\n */\nfunction errorHandlerMiddleware(): Middleware {\n return {\n onResponse: async ({ request: _request, response, options: _options }) => {\n const respErr = await parseResponseError(response);\n if (!respErr.error) {\n const { body, ...resOptions } = response;\n return new Response(body, { ...resOptions, status: response.status });\n }\n\n if (typeof respErr.error === 'string') {\n throw new Error(respErr.error);\n }\n\n rethrowMeaningfulError(respErr.error);\n },\n };\n}\n"],"names":["undiciFetch","rethrowMeaningfulError"],"mappings":";;;;;;AAAA;AACA;AACA;AACA;AACA;AAkBM,SAAU,YAAY,CAAmB,IAAsB,EAAA;AACnE,IAAA,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,GAAG,UAAU,GAAG,SAAS;IAChD,MAAM,MAAM,GAAG,mBAAmB,CAAQ;AACxC,QAAA,OAAO,EAAE,CAAA,EAAG,MAAM,GAAG,IAAI,CAAC,WAAW,CAAA,CAAE;AACvC,QAAA,KAAK,EAAE,CAAC,KAAc,KAAuB;;AAE3C,YAAA,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC,KAAK,EAAE,GAAG,KAAK;AAEtD,YAAA,OAAOA,YAAW,CAAC,OAAO,CAAC,GAAG,EAAE;gBAC9B,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,cAAc,EAAE,OAAO,CAAC,cAAc;gBACtC,MAAM,EAAE,OAAO,CAAC,MAAM;AACvB,aAAA,CAAC;QACJ,CAAC;AACF,KAAA,CAAC;IACF,MAAM,CAAC,GAAG,CAAC,sBAAsB,EAAE,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC;AACzD,IAAA,OAAO,MAAM;AACf;AAOO,eAAe,kBAAkB,CAAC,QAAkB,EAAA;AAIzD,IAAA,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE;AACzB,QAAA,OAAO,EAAE;IACX;IAEA,IAAI,KAAK,GAAQ,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE;IAC9C,MAAM,QAAQ,GAAG,KAAK;AACtB,IAAA,IAAI;AACF,QAAA,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAkB;IAC5C;AAAE,IAAA,MAAM;IACR;IACA,OAAO;AACL,QAAA,KAAK,EAAE,KAAK;QACZ;KACD;AACH;AAEA;;;AAGG;AACH,SAAS,sBAAsB,GAAA;IAC7B,OAAO;AACL,QAAA,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAI;AACvE,YAAA,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,QAAQ,CAAC;AAClD,YAAA,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;gBAClB,MAAM,EAAE,IAAI,EAAE,GAAG,UAAU,EAAE,GAAG,QAAQ;AACxC,gBAAA,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,GAAG,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;YACvE;AAEA,YAAA,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,EAAE;AACrC,gBAAA,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAChC;AAEA,YAAAC,6BAAsB,CAAC,OAAO,CAAC,KAAK,CAAC;QACvC,CAAC;KACF;AACH;;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/proto-rest/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,KAAK,IAAI,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAkC,KAAK,UAAU,EAAE,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AAC7F,OAAO,EAAE,UAAU,EAAwB,MAAM,QAAQ,CAAC;AAE1D,OAAO,EAAE,IAAI,EAAE,MAAM,+BAA+B,CAAC;AAErD,OAAO,EAAE,UAAU,EAAE,CAAC;AACtB,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;AAElD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,OAAO,CAAC;IACb,UAAU,EAAE,UAAU,CAAC;IACvB,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B,CAAA;AAED,wBAAgB,YAAY,CAAC,KAAK,SAAS,EAAE,EAAE,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAAC,KAAK,CAAC,CAapF;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,GAAG,EAAE,CAAC;CAChB,CAAA;AACD,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC;IACpE,KAAK,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC,CAeD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/proto-rest/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,KAAK,IAAI,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAkC,KAAK,UAAU,EAAE,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AAC7F,OAAO,EAAE,UAAU,EAAwB,MAAM,QAAQ,CAAC;AAE1D,OAAO,EAAE,IAAI,EAAE,MAAM,+BAA+B,CAAC;AAErD,OAAO,EAAE,UAAU,EAAE,CAAC;AACtB,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;AAElD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,OAAO,CAAC;IACb,UAAU,EAAE,UAAU,CAAC;IACvB,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B,CAAA;AAED,wBAAgB,YAAY,CAAC,KAAK,SAAS,EAAE,EAAE,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAAC,KAAK,CAAC,CA4BpF;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,GAAG,EAAE,CAAC;CAChB,CAAA;AACD,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC;IACpE,KAAK,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC,CAeD"}
@@ -12,9 +12,23 @@ function createClient(opts) {
12
12
  const client = createOpenApiClient({
13
13
  baseUrl: `${scheme}${opts.hostAndPort}`,
14
14
  fetch: (input) => {
15
- return fetch(input.url, {
16
- ...input,
15
+ // If body has already been consumed, clone the request
16
+ const request = input.bodyUsed ? input.clone() : input;
17
+ return fetch(request.url, {
18
+ body: request.body,
19
+ cache: request.cache,
20
+ credentials: request.credentials,
17
21
  dispatcher: opts.dispatcher,
22
+ duplex: request.duplex,
23
+ headers: request.headers,
24
+ integrity: request.integrity,
25
+ keepalive: request.keepalive,
26
+ method: request.method,
27
+ mode: request.mode,
28
+ redirect: request.redirect,
29
+ referrer: request.referrer,
30
+ referrerPolicy: request.referrerPolicy,
31
+ signal: request.signal,
18
32
  });
19
33
  },
20
34
  });
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/proto-rest/index.ts"],"sourcesContent":["//\n// This file is NOT autogenerated!\n//\n// After generating new clients from openapi specifications, add client types here.\n//\n\nimport type { paths as PlApiPaths } from './plapi';\nimport { default as createOpenApiClient, type Middleware, type Client } from 'openapi-fetch';\nimport { Dispatcher, fetch as undiciFetch } from 'undici';\nimport { rethrowMeaningfulError } from '../core/errors';\nimport { Code } from '../proto-grpc/google/rpc/code';\n\nexport { PlApiPaths };\nexport type PlRestClientType = Client<PlApiPaths>;\n\nexport type RestClientConfig = {\n hostAndPort: string;\n ssl: boolean;\n dispatcher: Dispatcher;\n middlewares: Middleware[];\n}\n\nexport function createClient<Paths extends {}>(opts: RestClientConfig): Client<Paths> {\n const scheme = opts.ssl ? 'https://' : 'http://';\n const client = createOpenApiClient<Paths>({\n baseUrl: `${scheme}${opts.hostAndPort}`,\n fetch: (input: Request): Promise<Response> => {\n return undiciFetch(input.url, {\n ...input,\n dispatcher: opts.dispatcher,\n });\n },\n });\n client.use(errorHandlerMiddleware(), ...opts.middlewares);\n return client;\n}\n\nexport type ErrorResponse = {\n code: Code,\n message: string,\n details: any[],\n}\nexport async function parseResponseError(response: Response): Promise<{\n error?: ErrorResponse | string,\n origBody?: string,\n}>{\n if (response.status < 400) {\n return {};\n }\n\n let error: any = await response.clone().text();\n const origBody = error;\n try {\n error = JSON.parse(error) as ErrorResponse;\n } catch {\n }\n return {\n error: error,\n origBody\n };\n}\n\n/**\n * Parses all API responses and thrown error in case of error response.\n * Allows all callers to not bother about .error response field checking.\n */\nfunction errorHandlerMiddleware(): Middleware {\n return {\n onResponse: async ({ request: _request, response, options: _options }) => {\n const respErr = await parseResponseError(response);\n if (!respErr.error) {\n const { body, ...resOptions } = response;\n return new Response(body, { ...resOptions, status: response.status });\n }\n\n if (typeof respErr.error === 'string') {\n throw new Error(respErr.error);\n }\n\n rethrowMeaningfulError(respErr.error);\n },\n };\n}\n"],"names":["undiciFetch"],"mappings":";;;;AAAA;AACA;AACA;AACA;AACA;AAkBM,SAAU,YAAY,CAAmB,IAAsB,EAAA;AACnE,IAAA,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,GAAG,UAAU,GAAG,SAAS;IAChD,MAAM,MAAM,GAAG,mBAAmB,CAAQ;AACxC,QAAA,OAAO,EAAE,CAAA,EAAG,MAAM,GAAG,IAAI,CAAC,WAAW,CAAA,CAAE;AACvC,QAAA,KAAK,EAAE,CAAC,KAAc,KAAuB;AAC3C,YAAA,OAAOA,KAAW,CAAC,KAAK,CAAC,GAAG,EAAE;AAC5B,gBAAA,GAAG,KAAK;gBACR,UAAU,EAAE,IAAI,CAAC,UAAU;AAC5B,aAAA,CAAC;QACJ,CAAC;AACF,KAAA,CAAC;IACF,MAAM,CAAC,GAAG,CAAC,sBAAsB,EAAE,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC;AACzD,IAAA,OAAO,MAAM;AACf;AAOO,eAAe,kBAAkB,CAAC,QAAkB,EAAA;AAIzD,IAAA,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE;AACzB,QAAA,OAAO,EAAE;IACX;IAEA,IAAI,KAAK,GAAQ,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE;IAC9C,MAAM,QAAQ,GAAG,KAAK;AACtB,IAAA,IAAI;AACF,QAAA,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAkB;IAC5C;AAAE,IAAA,MAAM;IACR;IACA,OAAO;AACL,QAAA,KAAK,EAAE,KAAK;QACZ;KACD;AACH;AAEA;;;AAGG;AACH,SAAS,sBAAsB,GAAA;IAC7B,OAAO;AACL,QAAA,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAI;AACvE,YAAA,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,QAAQ,CAAC;AAClD,YAAA,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;gBAClB,MAAM,EAAE,IAAI,EAAE,GAAG,UAAU,EAAE,GAAG,QAAQ;AACxC,gBAAA,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,GAAG,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;YACvE;AAEA,YAAA,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,EAAE;AACrC,gBAAA,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAChC;AAEA,YAAA,sBAAsB,CAAC,OAAO,CAAC,KAAK,CAAC;QACvC,CAAC;KACF;AACH;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../../src/proto-rest/index.ts"],"sourcesContent":["//\n// This file is NOT autogenerated!\n//\n// After generating new clients from openapi specifications, add client types here.\n//\n\nimport type { paths as PlApiPaths } from './plapi';\nimport { default as createOpenApiClient, type Middleware, type Client } from 'openapi-fetch';\nimport { Dispatcher, fetch as undiciFetch } from 'undici';\nimport { rethrowMeaningfulError } from '../core/errors';\nimport { Code } from '../proto-grpc/google/rpc/code';\n\nexport { PlApiPaths };\nexport type PlRestClientType = Client<PlApiPaths>;\n\nexport type RestClientConfig = {\n hostAndPort: string;\n ssl: boolean;\n dispatcher: Dispatcher;\n middlewares: Middleware[];\n}\n\nexport function createClient<Paths extends {}>(opts: RestClientConfig): Client<Paths> {\n const scheme = opts.ssl ? 'https://' : 'http://';\n const client = createOpenApiClient<Paths>({\n baseUrl: `${scheme}${opts.hostAndPort}`,\n fetch: (input: Request): Promise<Response> => {\n // If body has already been consumed, clone the request\n const request = input.bodyUsed ? input.clone() : input;\n\n return undiciFetch(request.url, {\n body: request.body,\n cache: request.cache,\n credentials: request.credentials,\n dispatcher: opts.dispatcher,\n duplex: request.duplex,\n headers: request.headers,\n integrity: request.integrity,\n keepalive: request.keepalive,\n method: request.method,\n mode: request.mode,\n redirect: request.redirect,\n referrer: request.referrer,\n referrerPolicy: request.referrerPolicy,\n signal: request.signal,\n });\n },\n });\n client.use(errorHandlerMiddleware(), ...opts.middlewares);\n return client;\n}\n\nexport type ErrorResponse = {\n code: Code,\n message: string,\n details: any[],\n}\nexport async function parseResponseError(response: Response): Promise<{\n error?: ErrorResponse | string,\n origBody?: string,\n}>{\n if (response.status < 400) {\n return {};\n }\n\n let error: any = await response.clone().text();\n const origBody = error;\n try {\n error = JSON.parse(error) as ErrorResponse;\n } catch {\n }\n return {\n error: error,\n origBody\n };\n}\n\n/**\n * Parses all API responses and thrown error in case of error response.\n * Allows all callers to not bother about .error response field checking.\n */\nfunction errorHandlerMiddleware(): Middleware {\n return {\n onResponse: async ({ request: _request, response, options: _options }) => {\n const respErr = await parseResponseError(response);\n if (!respErr.error) {\n const { body, ...resOptions } = response;\n return new Response(body, { ...resOptions, status: response.status });\n }\n\n if (typeof respErr.error === 'string') {\n throw new Error(respErr.error);\n }\n\n rethrowMeaningfulError(respErr.error);\n },\n };\n}\n"],"names":["undiciFetch"],"mappings":";;;;AAAA;AACA;AACA;AACA;AACA;AAkBM,SAAU,YAAY,CAAmB,IAAsB,EAAA;AACnE,IAAA,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,GAAG,UAAU,GAAG,SAAS;IAChD,MAAM,MAAM,GAAG,mBAAmB,CAAQ;AACxC,QAAA,OAAO,EAAE,CAAA,EAAG,MAAM,GAAG,IAAI,CAAC,WAAW,CAAA,CAAE;AACvC,QAAA,KAAK,EAAE,CAAC,KAAc,KAAuB;;AAE3C,YAAA,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC,KAAK,EAAE,GAAG,KAAK;AAEtD,YAAA,OAAOA,KAAW,CAAC,OAAO,CAAC,GAAG,EAAE;gBAC9B,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,cAAc,EAAE,OAAO,CAAC,cAAc;gBACtC,MAAM,EAAE,OAAO,CAAC,MAAM;AACvB,aAAA,CAAC;QACJ,CAAC;AACF,KAAA,CAAC;IACF,MAAM,CAAC,GAAG,CAAC,sBAAsB,EAAE,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC;AACzD,IAAA,OAAO,MAAM;AACf;AAOO,eAAe,kBAAkB,CAAC,QAAkB,EAAA;AAIzD,IAAA,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE;AACzB,QAAA,OAAO,EAAE;IACX;IAEA,IAAI,KAAK,GAAQ,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE;IAC9C,MAAM,QAAQ,GAAG,KAAK;AACtB,IAAA,IAAI;AACF,QAAA,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAkB;IAC5C;AAAE,IAAA,MAAM;IACR;IACA,OAAO;AACL,QAAA,KAAK,EAAE,KAAK;QACZ;KACD;AACH;AAEA;;;AAGG;AACH,SAAS,sBAAsB,GAAA;IAC7B,OAAO;AACL,QAAA,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAI;AACvE,YAAA,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,QAAQ,CAAC;AAClD,YAAA,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;gBAClB,MAAM,EAAE,IAAI,EAAE,GAAG,UAAU,EAAE,GAAG,QAAQ;AACxC,gBAAA,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,GAAG,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;YACvE;AAEA,YAAA,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,EAAE;AACrC,gBAAA,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAChC;AAEA,YAAA,sBAAsB,CAAC,OAAO,CAAC,KAAK,CAAC;QACvC,CAAC;KACF;AACH;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@milaboratories/pl-client",
3
- "version": "2.16.12",
3
+ "version": "2.16.13",
4
4
  "engines": {
5
5
  "node": ">=22.19.0"
6
6
  },
@@ -36,8 +36,8 @@
36
36
  "utility-types": "^3.11.0",
37
37
  "yaml": "^2.8.0",
38
38
  "@milaboratories/pl-http": "1.2.0",
39
- "@milaboratories/pl-model-common": "1.21.9",
40
- "@milaboratories/ts-helpers": "1.5.4"
39
+ "@milaboratories/ts-helpers": "1.5.4",
40
+ "@milaboratories/pl-model-common": "1.21.10"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@protobuf-ts/plugin": "2.11.1",
@@ -47,9 +47,9 @@
47
47
  "@vitest/coverage-v8": "^4.0.7",
48
48
  "vitest": "^4.0.7",
49
49
  "typescript": "~5.6.3",
50
- "@milaboratories/ts-builder": "1.0.5",
51
- "@milaboratories/ts-configs": "1.0.6",
52
- "@milaboratories/build-configs": "1.0.8"
50
+ "@milaboratories/ts-builder": "1.0.6",
51
+ "@milaboratories/build-configs": "1.0.9",
52
+ "@milaboratories/ts-configs": "1.0.6"
53
53
  },
54
54
  "scripts": {
55
55
  "type-check": "ts-builder types --target node",
@@ -36,6 +36,6 @@ export function addRTypeToMetadata(rType: ResourceType, options?: RpcOptions) {
36
36
  */
37
37
  export function createRTypeRoutingHeader(rType: ResourceType): Record<string, string> {
38
38
  return {
39
- resourcetype: `${rType.name}:${rType.version}`,
39
+ resourceType: `${rType.name}:${rType.version}`,
40
40
  };
41
41
  }
@@ -29,6 +29,7 @@ import { type PlApiPaths, type PlRestClientType, createClient, parseResponseErro
29
29
  import { notEmpty } from '@milaboratories/ts-helpers';
30
30
  import { Code } from '../proto-grpc/google/rpc/code';
31
31
  import { WebSocketBiDiStream } from './websocket_stream';
32
+ import { TxAPI_ClientMessage, TxAPI_ServerMessage } from '../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api';
32
33
 
33
34
  export interface PlCallOps {
34
35
  timeout?: number;
@@ -162,7 +163,7 @@ export class LLPlClient implements WireClientProviderFactory {
162
163
  }
163
164
 
164
165
  private initRestConnection(): void {
165
- const dispatcher = defaultHttpDispatcher(this.conf.httpProxy, this._restInterceptors);
166
+ const dispatcher = defaultHttpDispatcher(this.conf.grpcProxy, this._restInterceptors);
166
167
  this._replaceWireConnection({ type: 'rest', Config: this.conf, Dispatcher: dispatcher, Middlewares: this._restMiddlewares });
167
168
  }
168
169
 
@@ -490,22 +491,38 @@ export class LLPlClient implements WireClientProviderFactory {
490
491
  });
491
492
  }
492
493
 
493
- if (this._wireProto === 'rest') {
494
+ const wireConn = this.wireConnection;
495
+ if (wireConn.type === 'rest') {
494
496
  // For REST/WebSocket protocol, timeout needs to be converted to AbortSignal
495
497
  if (timeout !== undefined) {
496
498
  totalAbortSignal = AbortSignal.any([totalAbortSignal, AbortSignal.timeout(timeout)]);
497
499
  }
500
+
501
+ // The gRPC transport has the auth interceptor that already handles it, but here we need to refresh the auth information to be safe.
502
+ this.refreshAuthInformationIfNeeded();
503
+
498
504
  const wsUrl = this.conf.ssl
499
505
  ? `wss://${this.conf.hostAndPort}/v1/ws/tx`
500
506
  : `ws://${this.conf.hostAndPort}/v1/ws/tx`;
501
507
 
502
- // The gRPC transport has the auth interceptor that already handles it, so we need to refresh the auth information here.
503
- this.refreshAuthInformationIfNeeded();
504
- const jwtToken = this.authInformation?.jwtToken;
505
-
506
- return new WebSocketBiDiStream(wsUrl, totalAbortSignal, jwtToken);
508
+ return new WebSocketBiDiStream(wsUrl,
509
+ (msg) => TxAPI_ClientMessage.toBinary(msg),
510
+ (data) => TxAPI_ServerMessage.fromBinary(new Uint8Array(data)),
511
+ {
512
+ abortSignal: totalAbortSignal,
513
+ jwtToken: this.authInformation?.jwtToken,
514
+ dispatcher: wireConn.Dispatcher,
515
+
516
+ onComplete: async (stream) => stream.requests.send({
517
+ // Ask server to gracefully close the stream on its side, if not done yet.
518
+ requestId: 0,
519
+ request: { oneofKind: 'streamClose', streamClose: {} },
520
+ }),
521
+ },
522
+ );
507
523
  }
508
- throw new Error('tx is not supported for this wire protocol');
524
+
525
+ throw new Error(`transactions are not supported for wire protocol ${this._wireProto}`);
509
526
  });
510
527
  }
511
528
 
@@ -82,7 +82,7 @@ import type { RetryConfig } from '../helpers/retry_strategy';
82
82
  type MockWS = InstanceType<typeof MockWebSocket>;
83
83
 
84
84
  interface StreamContext {
85
- stream: WebSocketBiDiStream;
85
+ stream: WebSocketBiDiStream<ClientMessageType, ServerMessageType>;
86
86
  ws: MockWS;
87
87
  controller: AbortController;
88
88
  }
@@ -91,9 +91,13 @@ function createStream(token?: string, retryConfig?: Partial<RetryConfig>): Strea
91
91
  const controller = new AbortController();
92
92
  const stream = new WebSocketBiDiStream(
93
93
  'ws://localhost:8080',
94
- controller.signal,
95
- token,
96
- retryConfig,
94
+ (message: ClientMessageType) => ClientMessageType.toBinary(message),
95
+ (data) => ServerMessageType.fromBinary(data),
96
+ {
97
+ abortSignal: controller.signal,
98
+ jwtToken: token,
99
+ retryConfig: retryConfig,
100
+ },
97
101
  );
98
102
  const ws = MockWebSocket.instances[MockWebSocket.instances.length - 1];
99
103
  return { stream, ws, controller };
@@ -115,7 +119,7 @@ function createClientMessage(): ClientMessageType {
115
119
  }
116
120
 
117
121
  async function collectMessages(
118
- stream: WebSocketBiDiStream,
122
+ stream: WebSocketBiDiStream<ClientMessageType, ServerMessageType>,
119
123
  count: number,
120
124
  ): Promise<ServerMessageType[]> {
121
125
  const messages: ServerMessageType[] = [];
@@ -149,7 +153,14 @@ describe('WebSocketBiDiStream', () => {
149
153
  const controller = new AbortController();
150
154
  controller.abort();
151
155
 
152
- new WebSocketBiDiStream('ws://localhost:8080', controller.signal);
156
+ new WebSocketBiDiStream(
157
+ 'ws://localhost:8080',
158
+ (message: ClientMessageType) => ClientMessageType.toBinary(message),
159
+ (data) => ServerMessageType.fromBinary(data),
160
+ {
161
+ abortSignal: controller.signal,
162
+ },
163
+ );
153
164
 
154
165
  expect(MockWebSocket.instances).toHaveLength(0);
155
166
  });
@@ -332,7 +343,7 @@ describe('WebSocketBiDiStream', () => {
332
343
  maxAttempts: 5,
333
344
  };
334
345
 
335
- test('should attempt reconnection on unexpected close', async () => {
346
+ test('should not attempt reconnection on unexpected close', async () => {
336
347
  const { ws } = createStream(undefined, retryConfig);
337
348
 
338
349
  await openConnection(ws);
@@ -341,7 +352,7 @@ describe('WebSocketBiDiStream', () => {
341
352
  ws.emit('close');
342
353
  await vi.advanceTimersByTimeAsync(150);
343
354
 
344
- expect(MockWebSocket.instances.length).toBeGreaterThan(1);
355
+ expect(MockWebSocket.instances.length).toBe(1);
345
356
  });
346
357
 
347
358
  test('should stop reconnecting after max attempts', async () => {