@hodeinavarro/odoo-rpc-ts 0.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.
Files changed (184) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +401 -0
  3. package/dist/client.d.ts +184 -0
  4. package/dist/client.d.ts.map +1 -0
  5. package/dist/client.js +277 -0
  6. package/dist/client.js.map +1 -0
  7. package/dist/combinators/retryOnSessionExpired.d.ts +13 -0
  8. package/dist/combinators/retryOnSessionExpired.d.ts.map +1 -0
  9. package/dist/combinators/retryOnSessionExpired.js +15 -0
  10. package/dist/combinators/retryOnSessionExpired.js.map +1 -0
  11. package/dist/commands.d.ts +91 -0
  12. package/dist/commands.d.ts.map +1 -0
  13. package/dist/commands.js +69 -0
  14. package/dist/commands.js.map +1 -0
  15. package/dist/config.d.ts +32 -0
  16. package/dist/config.d.ts.map +1 -0
  17. package/dist/config.js +60 -0
  18. package/dist/config.js.map +1 -0
  19. package/dist/domain.d.ts +30 -0
  20. package/dist/domain.d.ts.map +1 -0
  21. package/dist/domain.js +70 -0
  22. package/dist/domain.js.map +1 -0
  23. package/dist/errors/auth.d.ts +27 -0
  24. package/dist/errors/auth.d.ts.map +1 -0
  25. package/dist/errors/auth.js +8 -0
  26. package/dist/errors/auth.js.map +1 -0
  27. package/dist/errors/index.d.ts +30 -0
  28. package/dist/errors/index.d.ts.map +1 -0
  29. package/dist/errors/index.js +13 -0
  30. package/dist/errors/index.js.map +1 -0
  31. package/dist/errors/mapFault.d.ts +31 -0
  32. package/dist/errors/mapFault.d.ts.map +1 -0
  33. package/dist/errors/mapFault.js +48 -0
  34. package/dist/errors/mapFault.js.map +1 -0
  35. package/dist/errors/protocol.d.ts +22 -0
  36. package/dist/errors/protocol.d.ts.map +1 -0
  37. package/dist/errors/protocol.js +9 -0
  38. package/dist/errors/protocol.js.map +1 -0
  39. package/dist/errors/schema.d.ts +22 -0
  40. package/dist/errors/schema.d.ts.map +1 -0
  41. package/dist/errors/schema.js +14 -0
  42. package/dist/errors/schema.js.map +1 -0
  43. package/dist/errors/server.d.ts +109 -0
  44. package/dist/errors/server.d.ts.map +1 -0
  45. package/dist/errors/server.js +49 -0
  46. package/dist/errors/server.js.map +1 -0
  47. package/dist/errors/session.d.ts +16 -0
  48. package/dist/errors/session.d.ts.map +1 -0
  49. package/dist/errors/session.js +11 -0
  50. package/dist/errors/session.js.map +1 -0
  51. package/dist/errors/transport.d.ts +42 -0
  52. package/dist/errors/transport.d.ts.map +1 -0
  53. package/dist/errors/transport.js +49 -0
  54. package/dist/errors/transport.js.map +1 -0
  55. package/dist/index.d.ts +33 -0
  56. package/dist/index.d.ts.map +1 -0
  57. package/dist/index.js +57 -0
  58. package/dist/index.js.map +1 -0
  59. package/dist/internal/platform.d.ts +12 -0
  60. package/dist/internal/platform.d.ts.map +1 -0
  61. package/dist/internal/platform.js +11 -0
  62. package/dist/internal/platform.js.map +1 -0
  63. package/dist/internal/singleFlight.d.ts +29 -0
  64. package/dist/internal/singleFlight.d.ts.map +1 -0
  65. package/dist/internal/singleFlight.js +41 -0
  66. package/dist/internal/singleFlight.js.map +1 -0
  67. package/dist/profiles.d.ts +179 -0
  68. package/dist/profiles.d.ts.map +1 -0
  69. package/dist/profiles.js +191 -0
  70. package/dist/profiles.js.map +1 -0
  71. package/dist/protocol/jsonrpc.d.ts +127 -0
  72. package/dist/protocol/jsonrpc.d.ts.map +1 -0
  73. package/dist/protocol/jsonrpc.js +117 -0
  74. package/dist/protocol/jsonrpc.js.map +1 -0
  75. package/dist/records/index.d.ts +14 -0
  76. package/dist/records/index.d.ts.map +1 -0
  77. package/dist/records/index.js +14 -0
  78. package/dist/records/index.js.map +1 -0
  79. package/dist/records/recordModel.d.ts +131 -0
  80. package/dist/records/recordModel.d.ts.map +1 -0
  81. package/dist/records/recordModel.js +101 -0
  82. package/dist/records/recordModel.js.map +1 -0
  83. package/dist/records/related.d.ts +42 -0
  84. package/dist/records/related.d.ts.map +1 -0
  85. package/dist/records/related.js +51 -0
  86. package/dist/records/related.js.map +1 -0
  87. package/dist/records/relations.d.ts +66 -0
  88. package/dist/records/relations.d.ts.map +1 -0
  89. package/dist/records/relations.js +119 -0
  90. package/dist/records/relations.js.map +1 -0
  91. package/dist/records/spec.d.ts +44 -0
  92. package/dist/records/spec.d.ts.map +1 -0
  93. package/dist/records/spec.js +63 -0
  94. package/dist/records/spec.js.map +1 -0
  95. package/dist/records/typed.d.ts +71 -0
  96. package/dist/records/typed.d.ts.map +1 -0
  97. package/dist/records/typed.js +65 -0
  98. package/dist/records/typed.js.map +1 -0
  99. package/dist/rpc.d.ts +90 -0
  100. package/dist/rpc.d.ts.map +1 -0
  101. package/dist/rpc.js +113 -0
  102. package/dist/rpc.js.map +1 -0
  103. package/dist/services/db.d.ts +128 -0
  104. package/dist/services/db.d.ts.map +1 -0
  105. package/dist/services/db.js +132 -0
  106. package/dist/services/db.js.map +1 -0
  107. package/dist/services/report.d.ts +48 -0
  108. package/dist/services/report.d.ts.map +1 -0
  109. package/dist/services/report.js +103 -0
  110. package/dist/services/report.js.map +1 -0
  111. package/dist/session/cookie.d.ts +114 -0
  112. package/dist/session/cookie.d.ts.map +1 -0
  113. package/dist/session/cookie.js +231 -0
  114. package/dist/session/cookie.js.map +1 -0
  115. package/dist/testing/fakeTransport.d.ts +40 -0
  116. package/dist/testing/fakeTransport.d.ts.map +1 -0
  117. package/dist/testing/fakeTransport.js +36 -0
  118. package/dist/testing/fakeTransport.js.map +1 -0
  119. package/dist/testing/index.d.ts +9 -0
  120. package/dist/testing/index.d.ts.map +1 -0
  121. package/dist/testing/index.js +9 -0
  122. package/dist/testing/index.js.map +1 -0
  123. package/dist/transport.d.ts +62 -0
  124. package/dist/transport.d.ts.map +1 -0
  125. package/dist/transport.js +9 -0
  126. package/dist/transport.js.map +1 -0
  127. package/dist/transports/json2.d.ts +41 -0
  128. package/dist/transports/json2.d.ts.map +1 -0
  129. package/dist/transports/json2.js +196 -0
  130. package/dist/transports/json2.js.map +1 -0
  131. package/dist/transports/jsonrpc.d.ts +41 -0
  132. package/dist/transports/jsonrpc.d.ts.map +1 -0
  133. package/dist/transports/jsonrpc.js +119 -0
  134. package/dist/transports/jsonrpc.js.map +1 -0
  135. package/dist/transports/web.d.ts +15 -0
  136. package/dist/transports/web.d.ts.map +1 -0
  137. package/dist/transports/web.js +62 -0
  138. package/dist/transports/web.js.map +1 -0
  139. package/dist/version-live.d.ts +41 -0
  140. package/dist/version-live.d.ts.map +1 -0
  141. package/dist/version-live.js +26 -0
  142. package/dist/version-live.js.map +1 -0
  143. package/dist/version.d.ts +78 -0
  144. package/dist/version.d.ts.map +1 -0
  145. package/dist/version.js +46 -0
  146. package/dist/version.js.map +1 -0
  147. package/docs/protocol-verification.md +43 -0
  148. package/package.json +71 -0
  149. package/src/client.ts +731 -0
  150. package/src/combinators/retryOnSessionExpired.ts +25 -0
  151. package/src/commands.ts +112 -0
  152. package/src/config.ts +110 -0
  153. package/src/domain.ts +91 -0
  154. package/src/errors/auth.ts +28 -0
  155. package/src/errors/index.ts +50 -0
  156. package/src/errors/mapFault.ts +92 -0
  157. package/src/errors/protocol.ts +19 -0
  158. package/src/errors/schema.ts +18 -0
  159. package/src/errors/server.ts +79 -0
  160. package/src/errors/session.ts +12 -0
  161. package/src/errors/transport.ts +74 -0
  162. package/src/index.ts +152 -0
  163. package/src/internal/platform.ts +22 -0
  164. package/src/internal/singleFlight.ts +80 -0
  165. package/src/profiles.ts +386 -0
  166. package/src/protocol/jsonrpc.ts +162 -0
  167. package/src/records/index.ts +49 -0
  168. package/src/records/recordModel.ts +211 -0
  169. package/src/records/related.ts +80 -0
  170. package/src/records/relations.ts +192 -0
  171. package/src/records/spec.ts +96 -0
  172. package/src/records/typed.ts +180 -0
  173. package/src/rpc.ts +219 -0
  174. package/src/services/db.ts +282 -0
  175. package/src/services/report.ts +165 -0
  176. package/src/session/cookie.ts +461 -0
  177. package/src/testing/fakeTransport.ts +84 -0
  178. package/src/testing/index.ts +9 -0
  179. package/src/transport.ts +72 -0
  180. package/src/transports/json2.ts +303 -0
  181. package/src/transports/jsonrpc.ts +218 -0
  182. package/src/transports/web.ts +96 -0
  183. package/src/version-live.ts +67 -0
  184. package/src/version.ts +102 -0
@@ -0,0 +1,41 @@
1
+ import { Effect, Layer } from "effect";
2
+ import type { SchemaDriftError } from "./errors/schema.js";
3
+ import type { ProtocolUnsupportedError } from "./errors/protocol.js";
4
+ import type { OdooTransportError } from "./errors/transport.js";
5
+ import { type CommonVersionResponse, type ServerVersionInfo, VersionResolver } from "./version.js";
6
+ /**
7
+ * The two version-probe shapes we accept, already boundary-decoded by whichever
8
+ * transport family issued the probe:
9
+ *
10
+ * - {@link CommonVersionResponse} — the `/jsonrpc` `common.version` response.
11
+ * - `{ version, version_info }` — the web `/web/webclient/version_info` shape.
12
+ *
13
+ * Both carry the `server_version_info` tuple under different keys; that tuple is
14
+ * all this resolver needs.
15
+ */
16
+ export type VersionProbeResponse = CommonVersionResponse | {
17
+ readonly version: string;
18
+ readonly version_info: ServerVersionInfo;
19
+ };
20
+ /**
21
+ * The typed failures a transport-provided VERSION probe may surface. The
22
+ * `VersionProbe` prefix is deliberate: the bare word "probe" belongs to the
23
+ * application layer's product-capability probing (`fields_get` reachability);
24
+ * this package only ever probes the server version.
25
+ */
26
+ export type VersionProbeError = OdooTransportError | SchemaDriftError | ProtocolUnsupportedError;
27
+ /**
28
+ * Build a {@link VersionResolver} service from a transport-agnostic `probe`.
29
+ *
30
+ * The `Transport` seam only exposes `call_kw`, so version discovery lives with
31
+ * each transport family (which owns the right endpoint and decode). This
32
+ * resolver stays generic: hand it the decoded probe effect and it success-only
33
+ * single-flight caches the mapped {@link ResolvedVersion}.
34
+ */
35
+ export declare const make: (probe: Effect.Effect<VersionProbeResponse, VersionProbeError>) => Effect.Effect<typeof VersionResolver.Service, never>;
36
+ /**
37
+ * The {@link VersionResolver} layer over a transport-provided `probe`. Transport
38
+ * packages construct the probe (endpoint + decode) and pass it here.
39
+ */
40
+ export declare const layer: (probe: Effect.Effect<VersionProbeResponse, VersionProbeError>) => Layer.Layer<VersionResolver>;
41
+ //# sourceMappingURL=version-live.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-live.d.ts","sourceRoot":"","sources":["../src/version-live.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEhE,OAAO,EACL,KAAK,qBAAqB,EAI1B,KAAK,iBAAiB,EACtB,eAAe,EAChB,MAAM,cAAc,CAAC;AAEtB;;;;;;;;;GASG;AACH,MAAM,MAAM,oBAAoB,GAC5B,qBAAqB,GACrB;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,YAAY,EAAE,iBAAiB,CAAA;CAAE,CAAC;AAE3E;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG,kBAAkB,GAAG,gBAAgB,GAAG,wBAAwB,CAAC;AAUjG;;;;;;;GAOG;AACH,eAAO,MAAM,IAAI,UACR,MAAM,CAAC,MAAM,CAAC,oBAAoB,EAAE,iBAAiB,CAAC,KAC5D,MAAM,CAAC,MAAM,CAAC,OAAO,eAAe,CAAC,OAAO,EAAE,KAAK,CAIlD,CAAC;AAEL;;;GAGG;AACH,eAAO,MAAM,KAAK,UACT,MAAM,CAAC,MAAM,CAAC,oBAAoB,EAAE,iBAAiB,CAAC,KAC5D,KAAK,CAAC,KAAK,CAAC,eAAe,CAA+C,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { Effect, Layer } from "effect";
2
+ import * as SingleFlight from "./internal/singleFlight.js";
3
+ import { deriveWireCapabilities, parseVersionInfo, VersionResolver, } from "./version.js";
4
+ const extractInfo = (response) => "server_version_info" in response ? response.server_version_info : response.version_info;
5
+ const resolveVersion = (response) => {
6
+ const version = parseVersionInfo(extractInfo(response));
7
+ return { version, capabilities: deriveWireCapabilities(version) };
8
+ };
9
+ /**
10
+ * Build a {@link VersionResolver} service from a transport-agnostic `probe`.
11
+ *
12
+ * The `Transport` seam only exposes `call_kw`, so version discovery lives with
13
+ * each transport family (which owns the right endpoint and decode). This
14
+ * resolver stays generic: hand it the decoded probe effect and it success-only
15
+ * single-flight caches the mapped {@link ResolvedVersion}.
16
+ */
17
+ export const make = (probe) => Effect.gen(function* () {
18
+ const cache = yield* SingleFlight.make(Effect.map(probe, resolveVersion));
19
+ return { resolve: cache.get };
20
+ });
21
+ /**
22
+ * The {@link VersionResolver} layer over a transport-provided `probe`. Transport
23
+ * packages construct the probe (endpoint + decode) and pass it here.
24
+ */
25
+ export const layer = (probe) => Layer.effect(VersionResolver, make(probe));
26
+ //# sourceMappingURL=version-live.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-live.js","sourceRoot":"","sources":["../src/version-live.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAIvC,OAAO,KAAK,YAAY,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAEL,sBAAsB,EACtB,gBAAgB,EAGhB,eAAe,GAChB,MAAM,cAAc,CAAC;AAwBtB,MAAM,WAAW,GAAG,CAAC,QAA8B,EAAqB,EAAE,CACxE,qBAAqB,IAAI,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC;AAE3F,MAAM,cAAc,GAAG,CAAC,QAA8B,EAAmB,EAAE;IACzE,MAAM,OAAO,GAAG,gBAAgB,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC;IACxD,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,sBAAsB,CAAC,OAAO,CAAC,EAAE,CAAC;AACpE,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAClB,KAA6D,EACP,EAAE,CACxD,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC;IAC1E,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC;AAChC,CAAC,CAAC,CAAC;AAEL;;;GAGG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CACnB,KAA6D,EAC/B,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,eAAe,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC"}
@@ -0,0 +1,78 @@
1
+ import { Context, type Effect, Schema } from "effect";
2
+ import type { ProtocolUnsupportedError } from "./errors/protocol.js";
3
+ import type { SchemaDriftError } from "./errors/schema.js";
4
+ import type { OdooTransportError } from "./errors/transport.js";
5
+ /**
6
+ * Odoo's `server_version_info`: `[major, minor, micro, releaselevel, serial]`,
7
+ * a heterogeneous tuple (numbers plus a string release level). Modeled
8
+ * leniently as a mixed array so a shape change on a future version surfaces as
9
+ * a decode drift rather than a silent truncation.
10
+ */
11
+ export declare const ServerVersionInfo: Schema.$Array<Schema.Union<readonly [Schema.Number, Schema.String]>>;
12
+ export type ServerVersionInfo = typeof ServerVersionInfo.Type;
13
+ /**
14
+ * The response of the `common.version` call (`/jsonrpc` service `common`,
15
+ * method `version`). Decoded at the boundary; drift raises `SchemaDriftError`.
16
+ */
17
+ export declare const CommonVersionResponse: Schema.Struct<{
18
+ readonly server_version: Schema.String;
19
+ readonly server_version_info: Schema.$Array<Schema.Union<readonly [Schema.Number, Schema.String]>>;
20
+ readonly server_serie: Schema.String;
21
+ readonly protocol_version: Schema.Number;
22
+ }>;
23
+ export type CommonVersionResponse = typeof CommonVersionResponse.Type;
24
+ /** A parsed, structured server version. */
25
+ export interface OdooVersion {
26
+ readonly major: number;
27
+ readonly minor: number;
28
+ readonly micro: number;
29
+ readonly releaseLevel: string;
30
+ readonly serial: number;
31
+ readonly raw: ServerVersionInfo;
32
+ }
33
+ /**
34
+ * What a given server version can and cannot do, ON THE WIRE. This package
35
+ * owns WIRE capabilities derived from the server version; the application
36
+ * layer owns PRODUCT capabilities (derived from `fields_get` reachability,
37
+ * installed modules, …) — the bare words "capabilities"/"probe" belong to the
38
+ * app layer, hence the `Wire`/`VersionProbe` prefixes here.
39
+ */
40
+ export interface WireCapabilities {
41
+ /** The JSON-2 `/json/2` bearer API exists (Odoo 19+). */
42
+ readonly supportsJson2: boolean;
43
+ /** `/jsonrpc` and `/xmlrpc` are deprecated upstream (Odoo 19+). */
44
+ readonly jsonRpcDeprecated: boolean;
45
+ /**
46
+ * `web_read`/`web_search_read`/`web_save` accept a nested `specification`
47
+ * kwarg (Odoo 17+). This gates the declared-prefetch typed record path
48
+ * (`searchTyped`/`readTyped`/`saveTyped`); on 16 the kwarg is rejected, so a
49
+ * relation-free declared model degrades to `search_read`/`read` and a declared
50
+ * relation fails with `ProtocolUnsupportedError` before any round trip.
51
+ */
52
+ readonly supportsWebReadSpec: boolean;
53
+ }
54
+ /** A resolved version together with its derived wire capabilities. */
55
+ export interface ResolvedVersion {
56
+ readonly version: OdooVersion;
57
+ readonly capabilities: WireCapabilities;
58
+ }
59
+ /**
60
+ * Turn a raw `server_version_info` tuple into a structured {@link OdooVersion}.
61
+ * Missing trailing elements default to `0` / empty; the raw tuple is retained.
62
+ */
63
+ export declare const parseVersionInfo: (raw: ServerVersionInfo) => OdooVersion;
64
+ /** Derive wire capabilities from a version. JSON-2 lands, and the legacy RPC
65
+ * routes are deprecated, at major 19. */
66
+ export declare const deriveWireCapabilities: (version: OdooVersion) => WireCapabilities;
67
+ declare const VersionResolver_base: Context.ServiceClass<VersionResolver, "odoo-rpc-ts/VersionResolver", {
68
+ readonly resolve: Effect.Effect<ResolvedVersion, OdooTransportError | SchemaDriftError | ProtocolUnsupportedError>;
69
+ }>;
70
+ /**
71
+ * Resolves (and success-only caches) the server version behind whichever
72
+ * transport is provided. Implementation ships later; this is the seam so the
73
+ * client can gate protocol choices on capabilities.
74
+ */
75
+ export declare class VersionResolver extends VersionResolver_base {
76
+ }
77
+ export {};
78
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACtD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEhE;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,sEAA6D,CAAC;AAC5F,MAAM,MAAM,iBAAiB,GAAG,OAAO,iBAAiB,CAAC,IAAI,CAAC;AAE9D;;;GAGG;AACH,eAAO,MAAM,qBAAqB;;;;;EAKhC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,OAAO,qBAAqB,CAAC,IAAI,CAAC;AAEtE,2CAA2C;AAC3C,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,iBAAiB,CAAC;CACjC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,yDAAyD;IACzD,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,mEAAmE;IACnE,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC;;;;;;OAMG;IACH,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;CACvC;AAED,sEAAsE;AACtE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,gBAAgB,CAAC;CACzC;AAKD;;;GAGG;AACH,eAAO,MAAM,gBAAgB,QAAS,iBAAiB,KAAG,WAOxD,CAAC;AAEH;yCACyC;AACzC,eAAO,MAAM,sBAAsB,YAAa,WAAW,KAAG,gBAI5D,CAAC;;sBAUmB,MAAM,CAAC,MAAM,CAC7B,eAAe,EACf,kBAAkB,GAAG,gBAAgB,GAAG,wBAAwB,CACjE;;AAXL;;;;GAIG;AACH,qBAAa,eAAgB,SAAQ,oBAQH;CAAG"}
@@ -0,0 +1,46 @@
1
+ import { Context, Schema } from "effect";
2
+ /**
3
+ * Odoo's `server_version_info`: `[major, minor, micro, releaselevel, serial]`,
4
+ * a heterogeneous tuple (numbers plus a string release level). Modeled
5
+ * leniently as a mixed array so a shape change on a future version surfaces as
6
+ * a decode drift rather than a silent truncation.
7
+ */
8
+ export const ServerVersionInfo = Schema.Array(Schema.Union([Schema.Number, Schema.String]));
9
+ /**
10
+ * The response of the `common.version` call (`/jsonrpc` service `common`,
11
+ * method `version`). Decoded at the boundary; drift raises `SchemaDriftError`.
12
+ */
13
+ export const CommonVersionResponse = Schema.Struct({
14
+ server_version: Schema.String,
15
+ server_version_info: ServerVersionInfo,
16
+ server_serie: Schema.String,
17
+ protocol_version: Schema.Number,
18
+ });
19
+ const asNumber = (value) => typeof value === "number" ? value : 0;
20
+ /**
21
+ * Turn a raw `server_version_info` tuple into a structured {@link OdooVersion}.
22
+ * Missing trailing elements default to `0` / empty; the raw tuple is retained.
23
+ */
24
+ export const parseVersionInfo = (raw) => ({
25
+ major: asNumber(raw[0]),
26
+ minor: asNumber(raw[1]),
27
+ micro: asNumber(raw[2]),
28
+ releaseLevel: typeof raw[3] === "string" ? raw[3] : "",
29
+ serial: asNumber(raw[4]),
30
+ raw,
31
+ });
32
+ /** Derive wire capabilities from a version. JSON-2 lands, and the legacy RPC
33
+ * routes are deprecated, at major 19. */
34
+ export const deriveWireCapabilities = (version) => ({
35
+ supportsJson2: version.major >= 19,
36
+ jsonRpcDeprecated: version.major >= 19,
37
+ supportsWebReadSpec: version.major >= 17,
38
+ });
39
+ /**
40
+ * Resolves (and success-only caches) the server version behind whichever
41
+ * transport is provided. Implementation ships later; this is the seam so the
42
+ * client can gate protocol choices on capabilities.
43
+ */
44
+ export class VersionResolver extends Context.Service()("odoo-rpc-ts/VersionResolver") {
45
+ }
46
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAe,MAAM,EAAE,MAAM,QAAQ,CAAC;AAKtD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAG5F;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAM,CAAC,MAAM,CAAC;IACjD,cAAc,EAAE,MAAM,CAAC,MAAM;IAC7B,mBAAmB,EAAE,iBAAiB;IACtC,YAAY,EAAE,MAAM,CAAC,MAAM;IAC3B,gBAAgB,EAAE,MAAM,CAAC,MAAM;CAChC,CAAC,CAAC;AAyCH,MAAM,QAAQ,GAAG,CAAC,KAAkC,EAAU,EAAE,CAC9D,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAExC;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,GAAsB,EAAe,EAAE,CAAC,CAAC;IACxE,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACvB,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACvB,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACvB,YAAY,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;IACtD,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACxB,GAAG;CACJ,CAAC,CAAC;AAEH;yCACyC;AACzC,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,OAAoB,EAAoB,EAAE,CAAC,CAAC;IACjF,aAAa,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE;IAClC,iBAAiB,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE;IACtC,mBAAmB,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE;CACzC,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,OAAO,eAAgB,SAAQ,OAAO,CAAC,OAAO,EAQjD,CAAC,6BAA6B,CAAC;CAAG"}
@@ -0,0 +1,43 @@
1
+ # Protocol verification record
2
+
3
+ The protocol contract is derived from Odoo source, not third-party summaries.
4
+ The current Odoo 16–19 claims were reviewed at these immutable public upstream
5
+ snapshots:
6
+
7
+ | Odoo | Source snapshot |
8
+ | ---- | ------------------------------------------------------------------------------------------------------------------------ |
9
+ | 16.0 | [`6aca71c9522b3be5b221847e8b005f233d3ea872`](https://github.com/odoo/odoo/tree/6aca71c9522b3be5b221847e8b005f233d3ea872) |
10
+ | 17.0 | [`c7953a5283e7a07e77b809c521fc372d476c2c67`](https://github.com/odoo/odoo/tree/c7953a5283e7a07e77b809c521fc372d476c2c67) |
11
+ | 18.0 | [`e37f0420450ed2c8f465305b19cbbcfa78162666`](https://github.com/odoo/odoo/tree/e37f0420450ed2c8f465305b19cbbcfa78162666) |
12
+ | 19.0 | [`c5f1a963e6c65cf67b56b7ca2d4b77de66140e78`](https://github.com/odoo/odoo/tree/c5f1a963e6c65cf67b56b7ca2d4b77de66140e78) |
13
+
14
+ ## Source map
15
+
16
+ At each snapshot, the shared protocol review covered these paths:
17
+
18
+ - `odoo/http.py`: request dispatch, sessions, JSON-RPC envelopes, and
19
+ serialized failures; Odoo 19 also contains `Json2Dispatcher`.
20
+ - `odoo/service/model.py`: `execute_kw` and model-call dispatch.
21
+ - `odoo/service/db.py`: database-service dispatch, including `exp_restore`.
22
+ - `addons/web/controllers/session.py`: web-session authentication.
23
+ - `addons/web/controllers/dataset.py`: the web `call_kw` route.
24
+ - `addons/web/controllers/report.py`: authenticated report downloads.
25
+ - `addons/web/models/ir_http.py`: session information returned to clients.
26
+ - `odoo/addons/base/models/res_users.py`: authentication and API-key behavior.
27
+
28
+ Odoo 16–18 additionally expose `/jsonrpc` through
29
+ `odoo/addons/base/controllers/rpc.py`. The Odoo 19 protocol entry points and
30
+ JSON-2 fixtures are available at these immutable paths:
31
+
32
+ - [`addons/rpc/controllers/jsonrpc.py`](https://github.com/odoo/odoo/blob/c5f1a963e6c65cf67b56b7ca2d4b77de66140e78/addons/rpc/controllers/jsonrpc.py)
33
+ - [`addons/rpc/controllers/json2.py`](https://github.com/odoo/odoo/blob/c5f1a963e6c65cf67b56b7ca2d4b77de66140e78/addons/rpc/controllers/json2.py)
34
+ - [`odoo/http.py`](https://github.com/odoo/odoo/blob/c5f1a963e6c65cf67b56b7ca2d4b77de66140e78/odoo/http.py)
35
+ - [`odoo/addons/test_http/tests/test_webjson2.py`](https://github.com/odoo/odoo/blob/c5f1a963e6c65cf67b56b7ca2d4b77de66140e78/odoo/addons/test_http/tests/test_webjson2.py)
36
+
37
+ ## Reproduce the source review
38
+
39
+ Fetch `https://github.com/odoo/odoo.git`, detach one worktree at each commit
40
+ above, and inspect the listed paths. A protocol change must update this record
41
+ to the exact new commits, identify the affected paths, and add focused fixture
42
+ or integration coverage. Live observations are useful corroboration, but source
43
+ snapshots and checked-in tests are the reproducible basis for repository claims.
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "@hodeinavarro/odoo-rpc-ts",
3
+ "version": "0.2.0",
4
+ "description": "Effect-native, strongly-typed Odoo RPC client for TypeScript \u2014 JSON-RPC, JSON-2, and cookie-session transports for Odoo 16\u201319 with a tagged-error taxonomy.",
5
+ "keywords": [
6
+ "api-client",
7
+ "effect",
8
+ "effect-ts",
9
+ "erp",
10
+ "json-rpc",
11
+ "odoo",
12
+ "rpc",
13
+ "typescript"
14
+ ],
15
+ "license": "MIT",
16
+ "author": "Hodei Navarro",
17
+ "packageManager": "pnpm@11.12.0",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/hodeinavarro/odoo-rpc-ts.git"
21
+ },
22
+ "homepage": "https://github.com/hodeinavarro/odoo-rpc-ts#readme",
23
+ "bugs": {
24
+ "url": "https://github.com/hodeinavarro/odoo-rpc-ts/issues"
25
+ },
26
+ "files": [
27
+ "dist",
28
+ "src",
29
+ "docs/protocol-verification.md"
30
+ ],
31
+ "type": "module",
32
+ "sideEffects": false,
33
+ "exports": {
34
+ ".": {
35
+ "types": "./dist/index.d.ts",
36
+ "default": "./dist/index.js"
37
+ },
38
+ "./testing": {
39
+ "types": "./dist/testing/index.d.ts",
40
+ "default": "./dist/testing/index.js"
41
+ },
42
+ "./package.json": "./package.json"
43
+ },
44
+ "publishConfig": {
45
+ "access": "public",
46
+ "registry": "https://registry.npmjs.org/"
47
+ },
48
+ "scripts": {
49
+ "build": "rm -rf dist && tsc -p tsconfig.build.json && node scripts/fix-dts-extensions.mjs",
50
+ "prepack": "pnpm build",
51
+ "check": "tsc --noEmit",
52
+ "harness": "node harness/cli.mjs",
53
+ "test": "vitest run",
54
+ "test:integration": "vitest run --config vitest.integration.config.ts",
55
+ "lint": "oxlint",
56
+ "fmt": "oxfmt"
57
+ },
58
+ "devDependencies": {
59
+ "@effect/platform-node": "4.0.0-beta.93",
60
+ "@effect/vitest": "4.0.0-beta.93",
61
+ "@types/node": "^26.1.1",
62
+ "effect": "4.0.0-beta.93",
63
+ "oxfmt": "^0.58.0",
64
+ "oxlint": "^1.73.0",
65
+ "typescript": "^7.0.2",
66
+ "vitest": "^4.1.10"
67
+ },
68
+ "peerDependencies": {
69
+ "effect": "4.0.0-beta.93"
70
+ }
71
+ }