@paakd/api 0.0.1 → 0.0.2

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 (201) hide show
  1. package/buf/validate/validate_pb.ts +5001 -0
  2. package/dist/gen/buf/validate/validate_pb.d.ts +4634 -0
  3. package/dist/gen/buf/validate/validate_pb.d.ts.map +1 -0
  4. package/dist/gen/buf/validate/validate_pb.js +414 -0
  5. package/dist/gen/src/proto/auth/v1/entities/auth_pb.d.ts +268 -0
  6. package/dist/gen/src/proto/auth/v1/entities/auth_pb.d.ts.map +1 -0
  7. package/dist/gen/src/proto/auth/v1/entities/auth_pb.js +120 -0
  8. package/dist/gen/src/proto/auth/v1/entities/policy_pb.d.ts +235 -0
  9. package/dist/gen/src/proto/auth/v1/entities/policy_pb.d.ts.map +1 -0
  10. package/dist/gen/src/proto/auth/v1/entities/policy_pb.js +98 -0
  11. package/dist/gen/src/proto/auth/v1/service_pb.d.ts +117 -0
  12. package/dist/gen/src/proto/auth/v1/service_pb.d.ts.map +1 -0
  13. package/dist/gen/src/proto/auth/v1/service_pb.js +22 -0
  14. package/dist/gen/src/proto/customers/v1/entities/address_pb.d.ts +371 -0
  15. package/dist/gen/src/proto/customers/v1/entities/address_pb.d.ts.map +1 -0
  16. package/dist/gen/src/proto/customers/v1/entities/address_pb.js +84 -0
  17. package/dist/gen/src/proto/customers/v1/entities/profile_pb.d.ts +189 -0
  18. package/dist/gen/src/proto/customers/v1/entities/profile_pb.d.ts.map +1 -0
  19. package/dist/gen/src/proto/customers/v1/entities/profile_pb.js +70 -0
  20. package/dist/gen/src/proto/customers/v1/service_pb.d.ts +85 -0
  21. package/dist/gen/src/proto/customers/v1/service_pb.d.ts.map +1 -0
  22. package/dist/gen/src/proto/customers/v1/service_pb.js +22 -0
  23. package/dist/gen/src/proto/products/v1/entities/category_pb.d.ts +234 -0
  24. package/dist/gen/src/proto/products/v1/entities/category_pb.d.ts.map +1 -0
  25. package/dist/gen/src/proto/products/v1/entities/category_pb.js +84 -0
  26. package/dist/gen/src/proto/products/v1/entities/collection_pb.d.ts +159 -0
  27. package/dist/gen/src/proto/products/v1/entities/collection_pb.d.ts.map +1 -0
  28. package/dist/gen/src/proto/products/v1/entities/collection_pb.js +70 -0
  29. package/dist/gen/src/proto/products/v1/entities/product/create_pb.d.ts +146 -0
  30. package/dist/gen/src/proto/products/v1/entities/product/create_pb.d.ts.map +1 -0
  31. package/dist/gen/src/proto/products/v1/entities/product/create_pb.js +32 -0
  32. package/dist/gen/src/proto/products/v1/entities/product/option_pb.d.ts +50 -0
  33. package/dist/gen/src/proto/products/v1/entities/product/option_pb.d.ts.map +1 -0
  34. package/dist/gen/src/proto/products/v1/entities/product/option_pb.js +32 -0
  35. package/dist/gen/src/proto/products/v1/entities/product/shared_pb.d.ts +1042 -0
  36. package/dist/gen/src/proto/products/v1/entities/product/shared_pb.d.ts.map +1 -0
  37. package/dist/gen/src/proto/products/v1/entities/product/shared_pb.js +258 -0
  38. package/dist/gen/src/proto/products/v1/entities/product/update_pb.d.ts +236 -0
  39. package/dist/gen/src/proto/products/v1/entities/product/update_pb.d.ts.map +1 -0
  40. package/dist/gen/src/proto/products/v1/entities/product/update_pb.js +88 -0
  41. package/dist/gen/src/proto/products/v1/entities/tag_pb.d.ts +175 -0
  42. package/dist/gen/src/proto/products/v1/entities/tag_pb.d.ts.map +1 -0
  43. package/dist/gen/src/proto/products/v1/entities/tag_pb.js +84 -0
  44. package/dist/gen/src/proto/products/v1/entities/taxonomy_pb.d.ts +477 -0
  45. package/dist/gen/src/proto/products/v1/entities/taxonomy_pb.d.ts.map +1 -0
  46. package/dist/gen/src/proto/products/v1/entities/taxonomy_pb.js +235 -0
  47. package/dist/gen/src/proto/products/v1/entities/type_pb.d.ts +158 -0
  48. package/dist/gen/src/proto/products/v1/entities/type_pb.d.ts.map +1 -0
  49. package/dist/gen/src/proto/products/v1/entities/type_pb.js +70 -0
  50. package/dist/gen/src/proto/products/v1/entities/variant_pb.d.ts +489 -0
  51. package/dist/gen/src/proto/products/v1/entities/variant_pb.d.ts.map +1 -0
  52. package/dist/gen/src/proto/products/v1/entities/variant_pb.js +147 -0
  53. package/dist/gen/src/proto/products/v1/service_pb.d.ts +316 -0
  54. package/dist/gen/src/proto/products/v1/service_pb.d.ts.map +1 -0
  55. package/dist/gen/src/proto/products/v1/service_pb.js +36 -0
  56. package/dist/src/address.d.ts +53 -0
  57. package/dist/src/address.d.ts.map +1 -0
  58. package/dist/src/address.js +233 -0
  59. package/dist/src/address.spec.d.ts +2 -0
  60. package/dist/src/address.spec.d.ts.map +1 -0
  61. package/dist/src/address.spec.js +488 -0
  62. package/dist/src/auth.d.ts +27 -0
  63. package/dist/src/auth.d.ts.map +1 -0
  64. package/dist/src/auth.js +155 -0
  65. package/dist/src/auth.spec.d.ts +2 -0
  66. package/dist/src/auth.spec.d.ts.map +1 -0
  67. package/dist/src/auth.spec.js +582 -0
  68. package/dist/src/compressor/brotli.d.ts +3 -0
  69. package/dist/src/compressor/brotli.d.ts.map +1 -0
  70. package/dist/src/compressor/brotli.js +30 -0
  71. package/dist/src/index.d.ts +6 -0
  72. package/dist/src/index.d.ts.map +1 -0
  73. package/dist/src/interceptors.d.ts +16 -0
  74. package/dist/src/interceptors.d.ts.map +1 -0
  75. package/dist/src/interceptors.js +156 -0
  76. package/dist/src/interceptors.spec.d.ts +2 -0
  77. package/dist/src/interceptors.spec.d.ts.map +1 -0
  78. package/dist/src/interceptors.spec.js +1063 -0
  79. package/dist/src/policies.d.ts +217 -0
  80. package/dist/src/policies.d.ts.map +1 -0
  81. package/dist/src/policies.js +322 -0
  82. package/dist/src/policies.spec.d.ts +2 -0
  83. package/dist/src/policies.spec.d.ts.map +1 -0
  84. package/dist/src/policies.spec.js +463 -0
  85. package/dist/src/products.d.ts +39 -0
  86. package/dist/src/products.d.ts.map +1 -0
  87. package/dist/src/products.js +95 -0
  88. package/dist/src/products.spec.d.ts +2 -0
  89. package/dist/src/products.spec.d.ts.map +1 -0
  90. package/dist/src/products.spec.js +519 -0
  91. package/dist/src/profile.d.ts +62 -0
  92. package/dist/src/profile.d.ts.map +1 -0
  93. package/dist/src/profile.js +151 -0
  94. package/dist/src/profile.spec.d.ts +2 -0
  95. package/dist/src/profile.spec.d.ts.map +1 -0
  96. package/dist/src/profile.spec.js +475 -0
  97. package/dist/src/registration.d.ts +60 -0
  98. package/dist/src/registration.d.ts.map +1 -0
  99. package/dist/src/registration.js +147 -0
  100. package/dist/src/test-utils.d.ts +87 -0
  101. package/dist/src/test-utils.d.ts.map +1 -0
  102. package/dist/src/test-utils.js +132 -0
  103. package/gen/buf/validate/validate_pb.ts +4799 -0
  104. package/gen/src/proto/auth/v1/authv1connect/service.connect.go +454 -0
  105. package/gen/src/proto/auth/v1/entities/auth.pb.go +818 -0
  106. package/gen/src/proto/auth/v1/entities/auth_pb.ts +348 -0
  107. package/gen/src/proto/auth/v1/entities/policy.pb.go +727 -0
  108. package/gen/src/proto/auth/v1/entities/policy_pb.ts +306 -0
  109. package/gen/src/proto/auth/v1/service-AuthService_connectquery.ts +70 -0
  110. package/gen/src/proto/auth/v1/service.pb.go +119 -0
  111. package/gen/src/proto/auth/v1/service_pb.ts +152 -0
  112. package/gen/src/proto/customers/v1/customersv1connect/service.connect.go +358 -0
  113. package/gen/src/proto/customers/v1/entities/address.pb.go +1073 -0
  114. package/gen/src/proto/customers/v1/entities/address_pb.ts +478 -0
  115. package/gen/src/proto/customers/v1/entities/profile.pb.go +633 -0
  116. package/gen/src/proto/customers/v1/entities/profile_pb.ts +252 -0
  117. package/gen/src/proto/customers/v1/service-CustomerService_connectquery.ts +50 -0
  118. package/gen/src/proto/customers/v1/service.pb.go +110 -0
  119. package/gen/src/proto/customers/v1/service_pb.ts +121 -0
  120. package/gen/src/proto/files/v1/entities/file.pb.go +669 -0
  121. package/gen/src/proto/files/v1/entities/file_pb.ts +265 -0
  122. package/gen/src/proto/files/v1/filesv1connect/service.connect.go +200 -0
  123. package/gen/src/proto/files/v1/service-FileService_connectquery.ts +25 -0
  124. package/gen/src/proto/files/v1/service.pb.go +85 -0
  125. package/gen/src/proto/files/v1/service_pb.ts +65 -0
  126. package/gen/src/proto/products/v1/entities/category.pb.go +744 -0
  127. package/gen/src/proto/products/v1/entities/category_pb.ts +318 -0
  128. package/gen/src/proto/products/v1/entities/collection.pb.go +528 -0
  129. package/gen/src/proto/products/v1/entities/collection_pb.ts +214 -0
  130. package/gen/src/proto/products/v1/entities/product/create.pb.go +453 -0
  131. package/gen/src/proto/products/v1/entities/product/create_pb.ts +199 -0
  132. package/gen/src/proto/products/v1/entities/product/option.pb.go +206 -0
  133. package/gen/src/proto/products/v1/entities/product/option_pb.ts +74 -0
  134. package/gen/src/proto/products/v1/entities/product/shared.pb.go +2890 -0
  135. package/gen/src/proto/products/v1/entities/product/shared_pb.ts +1317 -0
  136. package/gen/src/proto/products/v1/entities/product/update.pb.go +794 -0
  137. package/gen/src/proto/products/v1/entities/product/update_pb.ts +325 -0
  138. package/gen/src/proto/products/v1/entities/tag.pb.go +610 -0
  139. package/gen/src/proto/products/v1/entities/tag_pb.ts +233 -0
  140. package/gen/src/proto/products/v1/entities/taxonomy.pb.go +1352 -0
  141. package/gen/src/proto/products/v1/entities/taxonomy_pb.ts +606 -0
  142. package/gen/src/proto/products/v1/entities/type.pb.go +553 -0
  143. package/gen/src/proto/products/v1/entities/type_pb.ts +215 -0
  144. package/gen/src/proto/products/v1/entities/variant.pb.go +1474 -0
  145. package/gen/src/proto/products/v1/entities/variant_pb.ts +629 -0
  146. package/gen/src/proto/products/v1/productsv1connect/service.connect.go +1195 -0
  147. package/gen/src/proto/products/v1/service-ProductsService_connectquery.ts +199 -0
  148. package/gen/src/proto/products/v1/service.pb.go +250 -0
  149. package/gen/src/proto/products/v1/service_pb.ts +429 -0
  150. package/gen/src/proto/promotions/v1/entities/campaign.pb.go +1229 -0
  151. package/gen/src/proto/promotions/v1/entities/campaign_pb.ts +511 -0
  152. package/gen/src/proto/promotions/v1/promotionsv1connect/service.connect.go +289 -0
  153. package/gen/src/proto/promotions/v1/service-CampaignService_connectquery.ts +42 -0
  154. package/gen/src/proto/promotions/v1/service.pb.go +98 -0
  155. package/gen/src/proto/promotions/v1/service_pb.ts +95 -0
  156. package/gen/src/proto/stocknodes/v1/entities/stocknode.pb.go +1499 -0
  157. package/gen/src/proto/stocknodes/v1/entities/stocknode_pb.ts +655 -0
  158. package/gen/src/proto/stocknodes/v1/service-StockNodesService_connectquery.ts +41 -0
  159. package/gen/src/proto/stocknodes/v1/service.pb.go +98 -0
  160. package/gen/src/proto/stocknodes/v1/service_pb.ts +95 -0
  161. package/gen/src/proto/stocknodes/v1/stocknodesv1connect/service.connect.go +297 -0
  162. package/package.json +5 -2
  163. package/src/address.spec.ts +0 -662
  164. package/src/address.ts +0 -300
  165. package/src/auth.spec.ts +0 -771
  166. package/src/auth.ts +0 -168
  167. package/src/compressor/brotli.ts +0 -26
  168. package/src/index.ts +0 -5
  169. package/src/interceptors.spec.ts +0 -1343
  170. package/src/interceptors.ts +0 -224
  171. package/src/policies.spec.ts +0 -595
  172. package/src/policies.ts +0 -431
  173. package/src/products.spec.ts +0 -710
  174. package/src/products.ts +0 -112
  175. package/src/profile.spec.ts +0 -626
  176. package/src/profile.ts +0 -169
  177. package/src/proto/auth/v1/entities/auth.proto +0 -140
  178. package/src/proto/auth/v1/entities/policy.proto +0 -57
  179. package/src/proto/auth/v1/service.proto +0 -26
  180. package/src/proto/customers/v1/entities/address.proto +0 -101
  181. package/src/proto/customers/v1/entities/profile.proto +0 -118
  182. package/src/proto/customers/v1/service.proto +0 -36
  183. package/src/proto/files/v1/entities/file.proto +0 -62
  184. package/src/proto/files/v1/service.proto +0 -19
  185. package/src/proto/products/v1/entities/category.proto +0 -98
  186. package/src/proto/products/v1/entities/collection.proto +0 -72
  187. package/src/proto/products/v1/entities/product/create.proto +0 -41
  188. package/src/proto/products/v1/entities/product/option.proto +0 -17
  189. package/src/proto/products/v1/entities/product/shared.proto +0 -255
  190. package/src/proto/products/v1/entities/product/update.proto +0 -66
  191. package/src/proto/products/v1/entities/tag.proto +0 -73
  192. package/src/proto/products/v1/entities/taxonomy.proto +0 -146
  193. package/src/proto/products/v1/entities/type.proto +0 -98
  194. package/src/proto/products/v1/entities/variant.proto +0 -127
  195. package/src/proto/products/v1/service.proto +0 -78
  196. package/src/proto/promotions/v1/entities/campaign.proto +0 -145
  197. package/src/proto/promotions/v1/service.proto +0 -17
  198. package/src/proto/stocknodes/v1/entities/stocknode.proto +0 -167
  199. package/src/proto/stocknodes/v1/service.proto +0 -21
  200. package/src/registration.ts +0 -170
  201. package/src/test-utils.ts +0 -176
@@ -0,0 +1,1063 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
12
+ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
13
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
14
+ var g = generator.apply(thisArg, _arguments || []), i, q = [];
15
+ return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
16
+ function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
17
+ function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
18
+ function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
19
+ function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
20
+ function fulfill(value) { resume("next", value); }
21
+ function reject(value) { resume("throw", value); }
22
+ function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
23
+ };
24
+ var __asyncValues = (this && this.__asyncValues) || function (o) {
25
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
26
+ var m = o[Symbol.asyncIterator], i;
27
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
28
+ function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
29
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
30
+ };
31
+ Object.defineProperty(exports, "__esModule", { value: true });
32
+ const connect_1 = require("@connectrpc/connect");
33
+ const interceptors_1 = require("./interceptors");
34
+ // Mock the checkout config
35
+ vi.mock('@paakd/config', () => ({
36
+ Checkout: {},
37
+ }));
38
+ vi.mock('./compressor/brotli', () => ({
39
+ brotliCompression: {
40
+ name: 'brotli',
41
+ compress: vi.fn(),
42
+ decompress: vi.fn(),
43
+ },
44
+ }));
45
+ describe('interceptors', () => {
46
+ describe('createLoggingInterceptor', () => {
47
+ let mockLogger;
48
+ let mockNext;
49
+ let mockRequest;
50
+ let mockResponse;
51
+ beforeEach(() => {
52
+ mockLogger = {
53
+ onRequestHeader: vi.fn(),
54
+ onRequestMessage: vi.fn(),
55
+ onResponseHeader: vi.fn(),
56
+ onResponseMessage: vi.fn(),
57
+ onResponseTrailer: vi.fn(),
58
+ onError: vi.fn(),
59
+ };
60
+ mockNext = vi.fn();
61
+ mockRequest = {
62
+ stream: false,
63
+ method: {
64
+ methodKind: 'unary',
65
+ toString: () => 'TestService/TestMethod',
66
+ },
67
+ header: new Headers(),
68
+ message: { $typeName: 'test.Message' },
69
+ };
70
+ mockResponse = {
71
+ stream: false,
72
+ header: new Headers(),
73
+ message: { $typeName: 'test.Message' },
74
+ trailer: new Headers(),
75
+ };
76
+ });
77
+ it('should create a logging interceptor with default logger', () => {
78
+ const interceptor = (0, interceptors_1.createLoggingInterceptor)();
79
+ expect(typeof interceptor).toBe('function');
80
+ });
81
+ it('should create a logging interceptor with custom logger', () => {
82
+ const customLogger = vi.fn().mockReturnValue(mockLogger);
83
+ const interceptor = (0, interceptors_1.createLoggingInterceptor)(customLogger);
84
+ expect(typeof interceptor).toBe('function');
85
+ });
86
+ it('should log unary request and response', () => __awaiter(void 0, void 0, void 0, function* () {
87
+ const customLogger = vi.fn().mockReturnValue(mockLogger);
88
+ const interceptor = (0, interceptors_1.createLoggingInterceptor)(customLogger);
89
+ const interceptorFn = interceptor(mockNext);
90
+ mockNext.mockResolvedValue(mockResponse);
91
+ const result = yield interceptorFn(mockRequest);
92
+ expect(customLogger).toHaveBeenCalledWith(mockRequest);
93
+ expect(mockLogger.onRequestHeader).toHaveBeenCalledWith(mockRequest.header);
94
+ expect(mockLogger.onRequestMessage).toHaveBeenCalledWith(mockRequest.message);
95
+ expect(mockLogger.onResponseHeader).toHaveBeenCalledWith(mockResponse.header);
96
+ expect(mockLogger.onResponseMessage).toHaveBeenCalledWith(mockResponse.message);
97
+ expect(mockLogger.onResponseTrailer).toHaveBeenCalledWith(mockResponse.trailer);
98
+ expect(result).toBe(mockResponse);
99
+ }));
100
+ it('should handle stream requests with multiple messages', () => __awaiter(void 0, void 0, void 0, function* () {
101
+ var _a, e_1, _b, _c;
102
+ const customLogger = vi.fn().mockReturnValue(mockLogger);
103
+ const interceptor = (0, interceptors_1.createLoggingInterceptor)(customLogger);
104
+ const interceptorFn = interceptor(mockNext);
105
+ const messages = [
106
+ { $typeName: 'test.Message', id: 1 },
107
+ { $typeName: 'test.Message', id: 2 },
108
+ { $typeName: 'test.Message', id: 3 },
109
+ ];
110
+ const streamRequest = Object.assign(Object.assign({}, mockRequest), { stream: true, message: (function () {
111
+ return __asyncGenerator(this, arguments, function* () {
112
+ for (const msg of messages) {
113
+ yield yield __await(msg);
114
+ }
115
+ });
116
+ })() });
117
+ const streamResponse = Object.assign(Object.assign({}, mockResponse), { stream: true, message: (function () {
118
+ return __asyncGenerator(this, arguments, function* () {
119
+ for (const msg of messages) {
120
+ yield yield __await(msg);
121
+ }
122
+ });
123
+ })() });
124
+ mockNext.mockResolvedValue(streamResponse);
125
+ const result = yield interceptorFn(streamRequest);
126
+ expect(customLogger).toHaveBeenCalledWith(streamRequest);
127
+ expect(mockLogger.onRequestHeader).toHaveBeenCalledWith(streamRequest.header);
128
+ expect(result).toBeDefined();
129
+ expect(result.stream).toBe(true);
130
+ // Consume the stream to trigger message logging
131
+ const responseMessages = [];
132
+ try {
133
+ for (var _d = true, _e = __asyncValues(result.message), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
134
+ _c = _f.value;
135
+ _d = false;
136
+ const msg = _c;
137
+ responseMessages.push(msg);
138
+ }
139
+ }
140
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
141
+ finally {
142
+ try {
143
+ if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
144
+ }
145
+ finally { if (e_1) throw e_1.error; }
146
+ }
147
+ expect(responseMessages).toHaveLength(3);
148
+ expect(mockLogger.onResponseMessage).toHaveBeenCalledTimes(3);
149
+ expect(mockLogger.onResponseTrailer).toHaveBeenCalledWith(mockResponse.trailer);
150
+ }));
151
+ it('should log errors in stream and rethrow', () => __awaiter(void 0, void 0, void 0, function* () {
152
+ const customLogger = vi.fn().mockReturnValue(mockLogger);
153
+ const interceptor = (0, interceptors_1.createLoggingInterceptor)(customLogger);
154
+ const interceptorFn = interceptor(mockNext);
155
+ const streamError = new Error('Stream processing error');
156
+ const streamRequest = Object.assign(Object.assign({}, mockRequest), { stream: true, message: (function () {
157
+ return __asyncGenerator(this, arguments, function* () {
158
+ yield yield __await({ $typeName: 'test.Message' });
159
+ throw streamError;
160
+ });
161
+ })() });
162
+ const streamResponse = Object.assign(Object.assign({}, mockResponse), { stream: true, message: (function () {
163
+ return __asyncGenerator(this, arguments, function* () {
164
+ throw streamError;
165
+ });
166
+ })() });
167
+ mockNext.mockResolvedValue(streamResponse);
168
+ const result = yield interceptorFn(streamRequest);
169
+ // Consume the response stream to trigger error
170
+ yield expect(() => __awaiter(void 0, void 0, void 0, function* () {
171
+ var _a, e_2, _b, _c;
172
+ try {
173
+ for (var _d = true, _e = __asyncValues(result.message), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
174
+ _c = _f.value;
175
+ _d = false;
176
+ const msg = _c;
177
+ }
178
+ }
179
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
180
+ finally {
181
+ try {
182
+ if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
183
+ }
184
+ finally { if (e_2) throw e_2.error; }
185
+ }
186
+ })).rejects.toThrow('Stream processing error');
187
+ expect(mockLogger.onError).toHaveBeenCalledWith(streamError);
188
+ }));
189
+ it('should log errors and rethrow them in unary calls', () => __awaiter(void 0, void 0, void 0, function* () {
190
+ const customLogger = vi.fn().mockReturnValue(mockLogger);
191
+ const interceptor = (0, interceptors_1.createLoggingInterceptor)(customLogger);
192
+ const interceptorFn = interceptor(mockNext);
193
+ const error = new Error('Test error');
194
+ mockNext.mockRejectedValue(error);
195
+ yield expect(interceptorFn(mockRequest)).rejects.toThrow('Test error');
196
+ expect(mockLogger.onError).toHaveBeenCalledWith(error);
197
+ }));
198
+ it('should log ConnectError during request processing', () => __awaiter(void 0, void 0, void 0, function* () {
199
+ const customLogger = vi.fn().mockReturnValue(mockLogger);
200
+ const interceptor = (0, interceptors_1.createLoggingInterceptor)(customLogger);
201
+ const interceptorFn = interceptor(mockNext);
202
+ const connectError = new connect_1.ConnectError('Service unavailable', connect_1.Code.Unavailable);
203
+ mockNext.mockRejectedValue(connectError);
204
+ yield expect(interceptorFn(mockRequest)).rejects.toThrow();
205
+ expect(mockLogger.onError).toHaveBeenCalledWith(connectError);
206
+ }));
207
+ it('should use default logger when none provided', () => __awaiter(void 0, void 0, void 0, function* () {
208
+ const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
209
+ const interceptor = (0, interceptors_1.createLoggingInterceptor)();
210
+ const interceptorFn = interceptor(mockNext);
211
+ mockNext.mockResolvedValue(mockResponse);
212
+ yield interceptorFn(mockRequest);
213
+ expect(consoleSpy).toHaveBeenCalled();
214
+ const calls = consoleSpy.mock.calls.filter(call => { var _a; return (_a = call[0]) === null || _a === void 0 ? void 0 : _a.includes('TestService'); });
215
+ expect(calls.length).toBeGreaterThan(0);
216
+ consoleSpy.mockRestore();
217
+ }));
218
+ it('should handle partial logger implementation', () => __awaiter(void 0, void 0, void 0, function* () {
219
+ const partialLogger = {
220
+ onRequestHeader: vi.fn(),
221
+ // Missing other callbacks
222
+ };
223
+ const customLogger = vi.fn().mockReturnValue(partialLogger);
224
+ const interceptor = (0, interceptors_1.createLoggingInterceptor)(customLogger);
225
+ const interceptorFn = interceptor(mockNext);
226
+ mockNext.mockResolvedValue(mockResponse);
227
+ // Should not throw even with missing callbacks
228
+ yield expect(interceptorFn(mockRequest)).resolves.toBeDefined();
229
+ expect(partialLogger.onRequestHeader).toHaveBeenCalled();
230
+ }));
231
+ it('should pass correct method info to logger function', () => __awaiter(void 0, void 0, void 0, function* () {
232
+ const customLogger = vi.fn().mockReturnValue(mockLogger);
233
+ const interceptor = (0, interceptors_1.createLoggingInterceptor)(customLogger);
234
+ const interceptorFn = interceptor(mockNext);
235
+ mockNext.mockResolvedValue(mockResponse);
236
+ const testRequest = Object.assign(Object.assign({}, mockRequest), { method: {
237
+ methodKind: 'unary',
238
+ toString: () => 'CustomService/CustomMethod',
239
+ } });
240
+ yield interceptorFn(testRequest);
241
+ expect(customLogger).toHaveBeenCalledWith(testRequest);
242
+ const loggerResult = customLogger.mock.results[0].value;
243
+ expect(loggerResult).toBeDefined();
244
+ }));
245
+ it('should handle stream response completion without error', () => __awaiter(void 0, void 0, void 0, function* () {
246
+ var _a, e_3, _b, _c;
247
+ const customLogger = vi.fn().mockReturnValue(mockLogger);
248
+ const interceptor = (0, interceptors_1.createLoggingInterceptor)(customLogger);
249
+ const interceptorFn = interceptor(mockNext);
250
+ const streamResponse = Object.assign(Object.assign({}, mockResponse), { stream: true, message: (function () {
251
+ return __asyncGenerator(this, arguments, function* () {
252
+ yield yield __await({ $typeName: 'test.Message', id: 1 }
253
+ // Stream ends normally
254
+ );
255
+ // Stream ends normally
256
+ });
257
+ })() });
258
+ mockNext.mockResolvedValue(streamResponse);
259
+ const result = yield interceptorFn(mockRequest);
260
+ // Consume the stream
261
+ const messages = [];
262
+ try {
263
+ for (var _d = true, _e = __asyncValues(result.message), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
264
+ _c = _f.value;
265
+ _d = false;
266
+ const msg = _c;
267
+ messages.push(msg);
268
+ }
269
+ }
270
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
271
+ finally {
272
+ try {
273
+ if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
274
+ }
275
+ finally { if (e_3) throw e_3.error; }
276
+ }
277
+ expect(messages).toHaveLength(1);
278
+ expect(mockLogger.onResponseTrailer).toHaveBeenCalled();
279
+ }));
280
+ it('should handle stream iterator with throw method', () => __awaiter(void 0, void 0, void 0, function* () {
281
+ const customLogger = vi.fn().mockReturnValue(mockLogger);
282
+ const interceptor = (0, interceptors_1.createLoggingInterceptor)(customLogger);
283
+ const interceptorFn = interceptor(mockNext);
284
+ const mockIterator = {
285
+ next: vi.fn().mockResolvedValue({
286
+ done: false,
287
+ value: { $typeName: 'test.Message' },
288
+ }),
289
+ throw: vi.fn().mockRejectedValue(new Error('Thrown error')),
290
+ return: vi.fn().mockResolvedValue({ done: true }),
291
+ };
292
+ const streamResponse = Object.assign(Object.assign({}, mockResponse), { stream: true, message: {
293
+ [Symbol.asyncIterator]: () => mockIterator,
294
+ } });
295
+ mockNext.mockResolvedValue(streamResponse);
296
+ const result = yield interceptorFn(mockRequest);
297
+ // Get the intercepted iterator
298
+ const interceptedIterator = result.message[Symbol.asyncIterator]();
299
+ // The intercepted iterator should have throw and return methods
300
+ expect(typeof interceptedIterator.throw).toBe('function');
301
+ expect(typeof interceptedIterator.return).toBe('function');
302
+ }));
303
+ it('should handle stream iterator without throw method', () => __awaiter(void 0, void 0, void 0, function* () {
304
+ const customLogger = vi.fn().mockReturnValue(mockLogger);
305
+ const interceptor = (0, interceptors_1.createLoggingInterceptor)(customLogger);
306
+ const interceptorFn = interceptor(mockNext);
307
+ const mockIterator = {
308
+ next: vi.fn().mockResolvedValue({
309
+ done: false,
310
+ value: { $typeName: 'test.Message' },
311
+ }),
312
+ // No throw or return methods
313
+ };
314
+ const streamResponse = Object.assign(Object.assign({}, mockResponse), { stream: true, message: {
315
+ [Symbol.asyncIterator]: () => mockIterator,
316
+ } });
317
+ mockNext.mockResolvedValue(streamResponse);
318
+ const result = yield interceptorFn(mockRequest);
319
+ const interceptedIterator = result.message[Symbol.asyncIterator]();
320
+ // Should work without throw/return methods
321
+ const msg = yield interceptedIterator.next();
322
+ expect(msg.value).toBeDefined();
323
+ }));
324
+ });
325
+ describe('createAuthenticationInterceptor', () => {
326
+ let mockNext;
327
+ let mockRequest;
328
+ let mockResponse;
329
+ let mockCheckoutConfig;
330
+ beforeEach(() => {
331
+ mockNext = vi.fn();
332
+ mockRequest = {
333
+ header: new Headers(),
334
+ };
335
+ mockResponse = {
336
+ header: new Headers(),
337
+ message: { $typeName: 'test.Message' },
338
+ trailer: new Headers(),
339
+ };
340
+ mockCheckoutConfig = {
341
+ hostname: 'example.com',
342
+ cmsRemoteURL: 'https://cms.example.com',
343
+ enterpriseRemoteURL: 'https://enterprise.example.com',
344
+ cmsURL: 'https://cms-local.example.com',
345
+ enterpriseURL: 'https://enterprise.example.com',
346
+ secureCookiePassword: 'secure-cookie-password',
347
+ forestAPIKey: 'forest-api-key',
348
+ saleChannelAccessKey: 'test-sales-channel-access',
349
+ salesChannelAPISecret: 'test-sales-channel-secret',
350
+ storeAccessKey: 'test-store-access',
351
+ storeAPISecret: 'test-store-secret',
352
+ isProduction: false,
353
+ posthogKey: 'posthog-key',
354
+ posthogDomain: 'posthog.example.com',
355
+ posthogHost: 'posthog.example.com',
356
+ assetsPath: '/assets',
357
+ assetsDomain: 'assets.example.com',
358
+ turnstileKey: 'turnstile-key',
359
+ turnstileSecret: 'turnstile-secret',
360
+ redis: {
361
+ user: 'redis-user',
362
+ host: 'localhost',
363
+ password: 'redis-password',
364
+ port: 6379,
365
+ },
366
+ };
367
+ });
368
+ it('should create an authentication interceptor', () => {
369
+ const interceptor = (0, interceptors_1.createAuthenticationInterceptor)(mockCheckoutConfig);
370
+ expect(typeof interceptor).toBe('function');
371
+ });
372
+ it('should set all authentication headers', () => __awaiter(void 0, void 0, void 0, function* () {
373
+ const interceptor = (0, interceptors_1.createAuthenticationInterceptor)(mockCheckoutConfig);
374
+ const interceptorFn = interceptor(mockNext);
375
+ mockNext.mockResolvedValue(mockResponse);
376
+ const result = yield interceptorFn(mockRequest);
377
+ expect(mockRequest.header.get('X-Store-Key')).toBe('test-store-secret');
378
+ expect(mockRequest.header.get('X-SA-Key')).toBe('test-store-access');
379
+ expect(mockRequest.header.get('X-CH-Key')).toBe('test-sales-channel-secret');
380
+ expect(mockRequest.header.get('X-CHA-Key')).toBe('test-sales-channel-access');
381
+ expect(mockNext).toHaveBeenCalledWith(mockRequest);
382
+ expect(result).toBe(mockResponse);
383
+ }));
384
+ it('should set headers exactly once per call', () => __awaiter(void 0, void 0, void 0, function* () {
385
+ var _a;
386
+ const interceptor = (0, interceptors_1.createAuthenticationInterceptor)(mockCheckoutConfig);
387
+ const interceptorFn = interceptor(mockNext);
388
+ mockNext.mockResolvedValue(mockResponse);
389
+ yield interceptorFn(mockRequest);
390
+ // Verify headers are set exactly once
391
+ const headerSetCalls = ((_a = mockRequest.header.set.mock) === null || _a === void 0 ? void 0 : _a.calls) || [];
392
+ // Headers.set might not be mockable, so we verify via get
393
+ expect(mockRequest.header.get('X-Store-Key')).toBe('test-store-secret');
394
+ expect(mockRequest.header.get('X-SA-Key')).toBe('test-store-access');
395
+ expect(mockRequest.header.get('X-CH-Key')).toBe('test-sales-channel-secret');
396
+ expect(mockRequest.header.get('X-CHA-Key')).toBe('test-sales-channel-access');
397
+ }));
398
+ it('should work with stream requests', () => __awaiter(void 0, void 0, void 0, function* () {
399
+ const interceptor = (0, interceptors_1.createAuthenticationInterceptor)(mockCheckoutConfig);
400
+ const interceptorFn = interceptor(mockNext);
401
+ const streamRequest = Object.assign(Object.assign({}, mockRequest), { stream: true });
402
+ mockNext.mockResolvedValue(mockResponse);
403
+ const result = yield interceptorFn(streamRequest);
404
+ expect(streamRequest.header.get('X-Store-Key')).toBe('test-store-secret');
405
+ expect(streamRequest.header.get('X-SA-Key')).toBe('test-store-access');
406
+ expect(streamRequest.header.get('X-CH-Key')).toBe('test-sales-channel-secret');
407
+ expect(streamRequest.header.get('X-CHA-Key')).toBe('test-sales-channel-access');
408
+ expect(result).toBe(mockResponse);
409
+ }));
410
+ it('should pass request unchanged to next interceptor', () => __awaiter(void 0, void 0, void 0, function* () {
411
+ const interceptor = (0, interceptors_1.createAuthenticationInterceptor)(mockCheckoutConfig);
412
+ const interceptorFn = interceptor(mockNext);
413
+ mockNext.mockResolvedValue(mockResponse);
414
+ const originalRequest = mockRequest;
415
+ yield interceptorFn(originalRequest);
416
+ expect(mockNext).toHaveBeenCalledWith(originalRequest);
417
+ }));
418
+ it('should handle empty config values', () => __awaiter(void 0, void 0, void 0, function* () {
419
+ const emptyConfig = {
420
+ hostname: 'example.com',
421
+ cmsRemoteURL: 'https://cms.example.com',
422
+ enterpriseRemoteURL: 'https://enterprise.example.com',
423
+ cmsURL: 'https://cms-local.example.com',
424
+ enterpriseURL: 'https://enterprise.example.com',
425
+ secureCookiePassword: 'secure-cookie-password',
426
+ forestAPIKey: 'forest-api-key',
427
+ saleChannelAccessKey: '',
428
+ salesChannelAPISecret: '',
429
+ storeAccessKey: '',
430
+ storeAPISecret: '',
431
+ isProduction: false,
432
+ posthogKey: 'posthog-key',
433
+ posthogDomain: 'posthog.example.com',
434
+ posthogHost: 'posthog.example.com',
435
+ assetsPath: '/assets',
436
+ assetsDomain: 'assets.example.com',
437
+ turnstileKey: 'turnstile-key',
438
+ turnstileSecret: 'turnstile-secret',
439
+ redis: {
440
+ user: 'redis-user',
441
+ host: 'localhost',
442
+ password: 'redis-password',
443
+ port: 6379,
444
+ },
445
+ };
446
+ const interceptor = (0, interceptors_1.createAuthenticationInterceptor)(emptyConfig);
447
+ const interceptorFn = interceptor(mockNext);
448
+ mockNext.mockResolvedValue(mockResponse);
449
+ const result = yield interceptorFn(mockRequest);
450
+ expect(mockRequest.header.get('X-Store-Key')).toBe('');
451
+ expect(mockRequest.header.get('X-SA-Key')).toBe('');
452
+ expect(result).toBe(mockResponse);
453
+ }));
454
+ it('should propagate response from next interceptor', () => __awaiter(void 0, void 0, void 0, function* () {
455
+ const interceptor = (0, interceptors_1.createAuthenticationInterceptor)(mockCheckoutConfig);
456
+ const interceptorFn = interceptor(mockNext);
457
+ const customResponse = Object.assign(Object.assign({}, mockResponse), { message: { $typeName: 'custom.Message', data: 'custom' } });
458
+ mockNext.mockResolvedValue(customResponse);
459
+ const result = yield interceptor(mockNext)(mockRequest);
460
+ expect(result).toBe(customResponse);
461
+ expect(result.message.data).toBe('custom');
462
+ }));
463
+ });
464
+ describe('createCustomerAuthenticationInterceptor', () => {
465
+ let mockNext;
466
+ let mockRequest;
467
+ let mockResponse;
468
+ beforeEach(() => {
469
+ mockNext = vi.fn();
470
+ mockRequest = {
471
+ header: new Headers(),
472
+ };
473
+ mockResponse = {
474
+ header: new Headers(),
475
+ message: { $typeName: 'test.Message' },
476
+ trailer: new Headers(),
477
+ };
478
+ });
479
+ it('should create a customer authentication interceptor', () => {
480
+ const interceptor = (0, interceptors_1.createCustomerAuthenticationInterceptor)('test-jwt-token');
481
+ expect(typeof interceptor).toBe('function');
482
+ });
483
+ it('should set Authorization header with Bearer token', () => __awaiter(void 0, void 0, void 0, function* () {
484
+ const jwtToken = 'test-jwt-token';
485
+ const interceptor = (0, interceptors_1.createCustomerAuthenticationInterceptor)(jwtToken);
486
+ const interceptorFn = interceptor(mockNext);
487
+ mockNext.mockResolvedValue(mockResponse);
488
+ const result = yield interceptorFn(mockRequest);
489
+ expect(mockRequest.header.get('Authorization')).toBe(`Bearer ${jwtToken}`);
490
+ expect(mockNext).toHaveBeenCalledWith(mockRequest);
491
+ expect(result).toBe(mockResponse);
492
+ }));
493
+ it('should work with various JWT token formats', () => __awaiter(void 0, void 0, void 0, function* () {
494
+ const tokens = [
495
+ 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c',
496
+ 'simple-token',
497
+ 'token-with-many-dashes-123-456-789',
498
+ ];
499
+ for (const token of tokens) {
500
+ const interceptor = (0, interceptors_1.createCustomerAuthenticationInterceptor)(token);
501
+ const interceptorFn = interceptor(mockNext);
502
+ mockNext.mockResolvedValue(mockResponse);
503
+ const request = { header: new Headers() };
504
+ yield interceptorFn(request);
505
+ expect(request.header.get('Authorization')).toBe(`Bearer ${token}`);
506
+ }
507
+ }));
508
+ it('should work with stream requests', () => __awaiter(void 0, void 0, void 0, function* () {
509
+ const jwtToken = 'test-jwt-token';
510
+ const interceptor = (0, interceptors_1.createCustomerAuthenticationInterceptor)(jwtToken);
511
+ const interceptorFn = interceptor(mockNext);
512
+ const streamRequest = Object.assign(Object.assign({}, mockRequest), { stream: true });
513
+ mockNext.mockResolvedValue(mockResponse);
514
+ const result = yield interceptorFn(streamRequest);
515
+ expect(streamRequest.header.get('Authorization')).toBe(`Bearer ${jwtToken}`);
516
+ expect(result).toBe(mockResponse);
517
+ }));
518
+ it('should throw error for empty JWT token', () => __awaiter(void 0, void 0, void 0, function* () {
519
+ const interceptor = (0, interceptors_1.createCustomerAuthenticationInterceptor)('');
520
+ const interceptorFn = interceptor(mockNext);
521
+ try {
522
+ yield interceptorFn(mockRequest);
523
+ expect.fail('Should have thrown error');
524
+ }
525
+ catch (error) {
526
+ expect(error).toBeInstanceOf(connect_1.ConnectError);
527
+ }
528
+ }));
529
+ it('should throw Unauthenticated error code for empty JWT', () => __awaiter(void 0, void 0, void 0, function* () {
530
+ const interceptor = (0, interceptors_1.createCustomerAuthenticationInterceptor)('');
531
+ const interceptorFn = interceptor(mockNext);
532
+ try {
533
+ yield interceptorFn(mockRequest);
534
+ expect.fail('Should have thrown error');
535
+ }
536
+ catch (error) {
537
+ expect(error).toBeInstanceOf(connect_1.ConnectError);
538
+ expect(error.code).toBe(connect_1.Code.Unauthenticated);
539
+ }
540
+ }));
541
+ it('should throw error for null JWT token', () => __awaiter(void 0, void 0, void 0, function* () {
542
+ const interceptor = (0, interceptors_1.createCustomerAuthenticationInterceptor)(null);
543
+ const interceptorFn = interceptor(mockNext);
544
+ yield expect(interceptorFn(mockRequest)).rejects.toThrow();
545
+ }));
546
+ it('should throw error for undefined JWT token', () => __awaiter(void 0, void 0, void 0, function* () {
547
+ const interceptor = (0, interceptors_1.createCustomerAuthenticationInterceptor)(undefined);
548
+ const interceptorFn = interceptor(mockNext);
549
+ yield expect(interceptorFn(mockRequest)).rejects.toThrow();
550
+ }));
551
+ it('should not call next when JWT validation fails', () => __awaiter(void 0, void 0, void 0, function* () {
552
+ const interceptor = (0, interceptors_1.createCustomerAuthenticationInterceptor)('');
553
+ const interceptorFn = interceptor(mockNext);
554
+ yield expect(interceptorFn(mockRequest)).rejects.toThrow();
555
+ // next should never be called if validation fails
556
+ expect(mockNext).not.toHaveBeenCalled();
557
+ }));
558
+ it('should propagate response from next interceptor', () => __awaiter(void 0, void 0, void 0, function* () {
559
+ const jwtToken = 'test-jwt-token';
560
+ const interceptor = (0, interceptors_1.createCustomerAuthenticationInterceptor)(jwtToken);
561
+ const interceptorFn = interceptor(mockNext);
562
+ const customResponse = Object.assign(Object.assign({}, mockResponse), { message: { $typeName: 'custom.Message', userId: 'user123' } });
563
+ mockNext.mockResolvedValue(customResponse);
564
+ const result = yield interceptorFn(mockRequest);
565
+ expect(result).toBe(customResponse);
566
+ expect(result.message.userId).toBe('user123');
567
+ }));
568
+ });
569
+ describe('createHeadersInterceptor', () => {
570
+ let mockNext;
571
+ let mockRequest;
572
+ let mockResponse;
573
+ beforeEach(() => {
574
+ mockNext = vi.fn();
575
+ mockRequest = {
576
+ header: new Headers(),
577
+ };
578
+ mockResponse = {
579
+ header: new Headers(),
580
+ message: { $typeName: 'test.Message' },
581
+ trailer: new Headers(),
582
+ };
583
+ });
584
+ it('should set expected headers from header mapping', () => __awaiter(void 0, void 0, void 0, function* () {
585
+ const customHeaders = {
586
+ 'x-original-host': 'example.com',
587
+ 'x-shop-id': 'shop123',
588
+ 'x-sitepath': '/path',
589
+ 'x-locale': 'en',
590
+ 'x-region': 'US',
591
+ };
592
+ const interceptor = (0, interceptors_1.createHeadersInterceptor)(customHeaders);
593
+ const interceptorFn = interceptor(mockNext);
594
+ mockNext.mockResolvedValue(mockResponse);
595
+ const result = yield interceptorFn(mockRequest);
596
+ expect(mockRequest.header.get('X-Original-Host')).toBe('example.com');
597
+ expect(mockRequest.header.get('X-shop-id')).toBe('shop123');
598
+ expect(mockRequest.header.get('X-Sitepath')).toBe('/path');
599
+ expect(mockRequest.header.get('X-locale')).toBe('en');
600
+ expect(mockRequest.header.get('X-region')).toBe('US');
601
+ expect(mockNext).toHaveBeenCalledWith(mockRequest);
602
+ expect(result).toBe(mockResponse);
603
+ }));
604
+ it('should throw error when x-original-host is missing', () => __awaiter(void 0, void 0, void 0, function* () {
605
+ const customHeaders = {
606
+ 'x-shop-id': 'shop123',
607
+ 'x-sitepath': '/path',
608
+ 'x-locale': 'en',
609
+ 'x-region': 'US',
610
+ };
611
+ const interceptor = (0, interceptors_1.createHeadersInterceptor)(customHeaders);
612
+ const interceptorFn = interceptor(mockNext);
613
+ try {
614
+ yield interceptorFn(mockRequest);
615
+ expect.fail('Should have thrown error');
616
+ }
617
+ catch (error) {
618
+ expect(error).toBeInstanceOf(connect_1.ConnectError);
619
+ expect(error.code).toBe(connect_1.Code.InvalidArgument);
620
+ expect(error.message).toContain('Original host');
621
+ }
622
+ }));
623
+ it('should throw error when x-shop-id is missing', () => __awaiter(void 0, void 0, void 0, function* () {
624
+ const customHeaders = {
625
+ 'x-original-host': 'example.com',
626
+ 'x-sitepath': '/path',
627
+ 'x-locale': 'en',
628
+ 'x-region': 'US',
629
+ };
630
+ const interceptor = (0, interceptors_1.createHeadersInterceptor)(customHeaders);
631
+ const interceptorFn = interceptor(mockNext);
632
+ try {
633
+ yield interceptorFn(mockRequest);
634
+ expect.fail('Should have thrown error');
635
+ }
636
+ catch (error) {
637
+ expect(error).toBeInstanceOf(connect_1.ConnectError);
638
+ expect(error.message).toContain('Shop id');
639
+ }
640
+ }));
641
+ it('should throw error when x-sitepath is missing', () => __awaiter(void 0, void 0, void 0, function* () {
642
+ const customHeaders = {
643
+ 'x-original-host': 'example.com',
644
+ 'x-shop-id': 'shop123',
645
+ 'x-locale': 'en',
646
+ 'x-region': 'US',
647
+ };
648
+ const interceptor = (0, interceptors_1.createHeadersInterceptor)(customHeaders);
649
+ const interceptorFn = interceptor(mockNext);
650
+ try {
651
+ yield interceptorFn(mockRequest);
652
+ expect.fail('Should have thrown error');
653
+ }
654
+ catch (error) {
655
+ expect(error).toBeInstanceOf(connect_1.ConnectError);
656
+ expect(error.message).toContain('Sitepath');
657
+ }
658
+ }));
659
+ it('should throw error when x-locale is missing', () => __awaiter(void 0, void 0, void 0, function* () {
660
+ const customHeaders = {
661
+ 'x-original-host': 'example.com',
662
+ 'x-shop-id': 'shop123',
663
+ 'x-sitepath': '/path',
664
+ 'x-region': 'US',
665
+ };
666
+ const interceptor = (0, interceptors_1.createHeadersInterceptor)(customHeaders);
667
+ const interceptorFn = interceptor(mockNext);
668
+ try {
669
+ yield interceptorFn(mockRequest);
670
+ expect.fail('Should have thrown error');
671
+ }
672
+ catch (error) {
673
+ expect(error).toBeInstanceOf(connect_1.ConnectError);
674
+ expect(error.message).toContain('Locale');
675
+ }
676
+ }));
677
+ it('should throw error when x-region is missing', () => __awaiter(void 0, void 0, void 0, function* () {
678
+ const customHeaders = {
679
+ 'x-original-host': 'example.com',
680
+ 'x-shop-id': 'shop123',
681
+ 'x-sitepath': '/path',
682
+ 'x-locale': 'en',
683
+ };
684
+ const interceptor = (0, interceptors_1.createHeadersInterceptor)(customHeaders);
685
+ const interceptorFn = interceptor(mockNext);
686
+ try {
687
+ yield interceptorFn(mockRequest);
688
+ expect.fail('Should have thrown error');
689
+ }
690
+ catch (error) {
691
+ expect(error).toBeInstanceOf(connect_1.ConnectError);
692
+ expect(error.message).toContain('Region');
693
+ }
694
+ }));
695
+ it('should throw error when x-original-host is null', () => __awaiter(void 0, void 0, void 0, function* () {
696
+ const customHeaders = {
697
+ 'x-original-host': null,
698
+ 'x-shop-id': 'shop123',
699
+ 'x-sitepath': '/path',
700
+ 'x-locale': 'en',
701
+ 'x-region': 'US',
702
+ };
703
+ const interceptor = (0, interceptors_1.createHeadersInterceptor)(customHeaders);
704
+ const interceptorFn = interceptor(mockNext);
705
+ yield expect(interceptorFn(mockRequest)).rejects.toThrow();
706
+ }));
707
+ it('should throw error when x-shop-id is null', () => __awaiter(void 0, void 0, void 0, function* () {
708
+ const customHeaders = {
709
+ 'x-original-host': 'example.com',
710
+ 'x-shop-id': null,
711
+ 'x-sitepath': '/path',
712
+ 'x-locale': 'en',
713
+ 'x-region': 'US',
714
+ };
715
+ const interceptor = (0, interceptors_1.createHeadersInterceptor)(customHeaders);
716
+ const interceptorFn = interceptor(mockNext);
717
+ yield expect(interceptorFn(mockRequest)).rejects.toThrow();
718
+ }));
719
+ it('should throw error when x-sitepath is null', () => __awaiter(void 0, void 0, void 0, function* () {
720
+ const customHeaders = {
721
+ 'x-original-host': 'example.com',
722
+ 'x-shop-id': 'shop123',
723
+ 'x-sitepath': null,
724
+ 'x-locale': 'en',
725
+ 'x-region': 'US',
726
+ };
727
+ const interceptor = (0, interceptors_1.createHeadersInterceptor)(customHeaders);
728
+ const interceptorFn = interceptor(mockNext);
729
+ yield expect(interceptorFn(mockRequest)).rejects.toThrow();
730
+ }));
731
+ it('should throw error when x-locale is null', () => __awaiter(void 0, void 0, void 0, function* () {
732
+ const customHeaders = {
733
+ 'x-original-host': 'example.com',
734
+ 'x-shop-id': 'shop123',
735
+ 'x-sitepath': '/path',
736
+ 'x-locale': null,
737
+ 'x-region': 'US',
738
+ };
739
+ const interceptor = (0, interceptors_1.createHeadersInterceptor)(customHeaders);
740
+ const interceptorFn = interceptor(mockNext);
741
+ yield expect(interceptorFn(mockRequest)).rejects.toThrow();
742
+ }));
743
+ it('should throw error when x-region is null', () => __awaiter(void 0, void 0, void 0, function* () {
744
+ const customHeaders = {
745
+ 'x-original-host': 'example.com',
746
+ 'x-shop-id': 'shop123',
747
+ 'x-sitepath': '/path',
748
+ 'x-locale': 'en',
749
+ 'x-region': null,
750
+ };
751
+ const interceptor = (0, interceptors_1.createHeadersInterceptor)(customHeaders);
752
+ const interceptorFn = interceptor(mockNext);
753
+ yield expect(interceptorFn(mockRequest)).rejects.toThrow();
754
+ }));
755
+ it('should work with stream requests', () => __awaiter(void 0, void 0, void 0, function* () {
756
+ const customHeaders = {
757
+ 'x-original-host': 'example.com',
758
+ 'x-shop-id': 'shop123',
759
+ 'x-sitepath': '/path',
760
+ 'x-locale': 'en',
761
+ 'x-region': 'US',
762
+ };
763
+ const interceptor = (0, interceptors_1.createHeadersInterceptor)(customHeaders);
764
+ const interceptorFn = interceptor(mockNext);
765
+ const streamRequest = {
766
+ header: new Headers(),
767
+ stream: true,
768
+ };
769
+ mockNext.mockResolvedValue(mockResponse);
770
+ const result = yield interceptorFn(streamRequest);
771
+ expect(streamRequest.header.get('X-Original-Host')).toBe('example.com');
772
+ expect(streamRequest.header.get('X-shop-id')).toBe('shop123');
773
+ expect(result).toBe(mockResponse);
774
+ }));
775
+ it('should not call next when header validation fails', () => __awaiter(void 0, void 0, void 0, function* () {
776
+ const customHeaders = {
777
+ 'x-original-host': 'example.com',
778
+ // Missing x-shop-id
779
+ 'x-sitepath': '/path',
780
+ 'x-locale': 'en',
781
+ 'x-region': 'US',
782
+ };
783
+ const interceptor = (0, interceptors_1.createHeadersInterceptor)(customHeaders);
784
+ const interceptorFn = interceptor(mockNext);
785
+ yield expect(interceptorFn(mockRequest)).rejects.toThrow();
786
+ // next should never be called if validation fails
787
+ expect(mockNext).not.toHaveBeenCalled();
788
+ }));
789
+ it('should propagate response from next interceptor', () => __awaiter(void 0, void 0, void 0, function* () {
790
+ const customHeaders = {
791
+ 'x-original-host': 'example.com',
792
+ 'x-shop-id': 'shop123',
793
+ 'x-sitepath': '/path',
794
+ 'x-locale': 'en',
795
+ 'x-region': 'US',
796
+ };
797
+ const interceptor = (0, interceptors_1.createHeadersInterceptor)(customHeaders);
798
+ const interceptorFn = interceptor(mockNext);
799
+ const customResponse = Object.assign(Object.assign({}, mockResponse), { message: { $typeName: 'custom.Message', requestId: 'req123' } });
800
+ mockNext.mockResolvedValue(customResponse);
801
+ const result = yield interceptor(mockNext)(mockRequest);
802
+ expect(result).toBe(customResponse);
803
+ expect(result.message.requestId).toBe('req123');
804
+ }));
805
+ it('should handle headers with special characters', () => __awaiter(void 0, void 0, void 0, function* () {
806
+ const customHeaders = {
807
+ 'x-original-host': 'example.com:8080',
808
+ 'x-shop-id': 'shop-123-456',
809
+ 'x-sitepath': '/en-GB/products',
810
+ 'x-locale': 'en_GB',
811
+ 'x-region': 'EU-West-1',
812
+ };
813
+ const interceptor = (0, interceptors_1.createHeadersInterceptor)(customHeaders);
814
+ const interceptorFn = interceptor(mockNext);
815
+ mockNext.mockResolvedValue(mockResponse);
816
+ const result = yield interceptorFn(mockRequest);
817
+ expect(mockRequest.header.get('X-Original-Host')).toBe('example.com:8080');
818
+ expect(mockRequest.header.get('X-shop-id')).toBe('shop-123-456');
819
+ expect(mockRequest.header.get('X-Sitepath')).toBe('/en-GB/products');
820
+ expect(result).toBe(mockResponse);
821
+ }));
822
+ it('should handle empty string headers (should fail validation)', () => __awaiter(void 0, void 0, void 0, function* () {
823
+ const customHeaders = {
824
+ 'x-original-host': '',
825
+ 'x-shop-id': 'shop123',
826
+ 'x-sitepath': '/path',
827
+ 'x-locale': 'en',
828
+ 'x-region': 'US',
829
+ };
830
+ const interceptor = (0, interceptors_1.createHeadersInterceptor)(customHeaders);
831
+ const interceptorFn = interceptor(mockNext);
832
+ // Empty string is falsy, so validation should fail
833
+ yield expect(interceptorFn(mockRequest)).rejects.toThrow();
834
+ }));
835
+ });
836
+ describe('interceptor integration', () => {
837
+ it('should chain multiple interceptors in order', () => __awaiter(void 0, void 0, void 0, function* () {
838
+ const jwtToken = 'test-jwt';
839
+ const mockNext = vi.fn();
840
+ mockNext.mockResolvedValue({
841
+ header: new Headers(),
842
+ message: { $typeName: 'test.Message' },
843
+ trailer: new Headers(),
844
+ });
845
+ const mockCheckoutConfig = {
846
+ hostname: 'example.com',
847
+ cmsRemoteURL: 'https://cms.example.com',
848
+ enterpriseRemoteURL: 'https://enterprise.example.com',
849
+ cmsURL: 'https://cms-local.example.com',
850
+ enterpriseURL: 'https://enterprise.example.com',
851
+ secureCookiePassword: 'secure-cookie-password',
852
+ forestAPIKey: 'forest-api-key',
853
+ saleChannelAccessKey: 'test-sales-channel-access',
854
+ salesChannelAPISecret: 'test-sales-channel-secret',
855
+ storeAccessKey: 'test-store-access',
856
+ storeAPISecret: 'test-store-secret',
857
+ isProduction: false,
858
+ posthogKey: 'posthog-key',
859
+ posthogDomain: 'posthog.example.com',
860
+ posthogHost: 'posthog.example.com',
861
+ assetsPath: '/assets',
862
+ assetsDomain: 'assets.example.com',
863
+ turnstileKey: 'turnstile-key',
864
+ turnstileSecret: 'turnstile-secret',
865
+ redis: {
866
+ user: 'redis-user',
867
+ host: 'localhost',
868
+ password: 'redis-password',
869
+ port: 6379,
870
+ },
871
+ };
872
+ // Create interceptors
873
+ const authInterceptor = (0, interceptors_1.createAuthenticationInterceptor)(mockCheckoutConfig);
874
+ const customerAuthInterceptor = (0, interceptors_1.createCustomerAuthenticationInterceptor)(jwtToken);
875
+ const loggingInterceptor = (0, interceptors_1.createLoggingInterceptor)();
876
+ // Chain them together
877
+ const chainedInterceptor = authInterceptor(customerAuthInterceptor(loggingInterceptor(mockNext)));
878
+ const mockRequest = {
879
+ header: new Headers(),
880
+ method: {
881
+ toString: () => 'TestService/TestMethod',
882
+ },
883
+ message: { $typeName: 'test.Message' },
884
+ };
885
+ yield chainedInterceptor(mockRequest);
886
+ // Verify all headers are set
887
+ expect(mockRequest.header.get('X-Store-Key')).toBe('test-store-secret');
888
+ expect(mockRequest.header.get('X-SA-Key')).toBe('test-store-access');
889
+ expect(mockRequest.header.get('Authorization')).toBe(`Bearer ${jwtToken}`);
890
+ expect(mockNext).toHaveBeenCalled();
891
+ }));
892
+ it('should handle errors in chained interceptors', () => __awaiter(void 0, void 0, void 0, function* () {
893
+ const jwtToken = '';
894
+ const mockNext = vi.fn();
895
+ mockNext.mockResolvedValue({
896
+ header: new Headers(),
897
+ message: { $typeName: 'test.Message' },
898
+ trailer: new Headers(),
899
+ });
900
+ const mockCheckoutConfig = {
901
+ hostname: 'example.com',
902
+ cmsRemoteURL: 'https://cms.example.com',
903
+ enterpriseRemoteURL: 'https://enterprise.example.com',
904
+ cmsURL: 'https://cms-local.example.com',
905
+ enterpriseURL: 'https://enterprise.example.com',
906
+ secureCookiePassword: 'secure-cookie-password',
907
+ forestAPIKey: 'forest-api-key',
908
+ saleChannelAccessKey: 'test-sales-channel-access',
909
+ salesChannelAPISecret: 'test-sales-channel-secret',
910
+ storeAccessKey: 'test-store-access',
911
+ storeAPISecret: 'test-store-secret',
912
+ isProduction: false,
913
+ posthogKey: 'posthog-key',
914
+ posthogDomain: 'posthog.example.com',
915
+ posthogHost: 'posthog.example.com',
916
+ assetsPath: '/assets',
917
+ assetsDomain: 'assets.example.com',
918
+ turnstileKey: 'turnstile-key',
919
+ turnstileSecret: 'turnstile-secret',
920
+ redis: {
921
+ user: 'redis-user',
922
+ host: 'localhost',
923
+ password: 'redis-password',
924
+ port: 6379,
925
+ },
926
+ };
927
+ // Chain: auth -> customer auth (will fail) -> logging
928
+ const authInterceptor = (0, interceptors_1.createAuthenticationInterceptor)(mockCheckoutConfig);
929
+ const customerAuthInterceptor = (0, interceptors_1.createCustomerAuthenticationInterceptor)(jwtToken);
930
+ const loggingInterceptor = (0, interceptors_1.createLoggingInterceptor)();
931
+ const chainedInterceptor = authInterceptor(customerAuthInterceptor(loggingInterceptor(mockNext)));
932
+ const mockRequest = {
933
+ header: new Headers(),
934
+ method: {
935
+ toString: () => 'TestService/TestMethod',
936
+ },
937
+ message: { $typeName: 'test.Message' },
938
+ };
939
+ // Should fail at customer auth interceptor
940
+ yield expect(chainedInterceptor(mockRequest)).rejects.toThrow();
941
+ // Auth headers should still be set before error
942
+ expect(mockRequest.header.get('X-Store-Key')).toBe('test-store-secret');
943
+ // But next should not be called
944
+ expect(mockNext).not.toHaveBeenCalled();
945
+ }));
946
+ it('should work with all interceptors including headers', () => __awaiter(void 0, void 0, void 0, function* () {
947
+ const jwtToken = 'test-jwt';
948
+ const mockNext = vi.fn();
949
+ mockNext.mockResolvedValue({
950
+ header: new Headers(),
951
+ message: { $typeName: 'test.Message' },
952
+ trailer: new Headers(),
953
+ });
954
+ const mockCheckoutConfig = {
955
+ hostname: 'example.com',
956
+ cmsRemoteURL: 'https://cms.example.com',
957
+ enterpriseRemoteURL: 'https://enterprise.example.com',
958
+ cmsURL: 'https://cms-local.example.com',
959
+ enterpriseURL: 'https://enterprise.example.com',
960
+ secureCookiePassword: 'secure-cookie-password',
961
+ forestAPIKey: 'forest-api-key',
962
+ saleChannelAccessKey: 'test-sales-channel-access',
963
+ salesChannelAPISecret: 'test-sales-channel-secret',
964
+ storeAccessKey: 'test-store-access',
965
+ storeAPISecret: 'test-store-secret',
966
+ isProduction: false,
967
+ posthogKey: 'posthog-key',
968
+ posthogDomain: 'posthog.example.com',
969
+ posthogHost: 'posthog.example.com',
970
+ assetsPath: '/assets',
971
+ assetsDomain: 'assets.example.com',
972
+ turnstileKey: 'turnstile-key',
973
+ turnstileSecret: 'turnstile-secret',
974
+ redis: {
975
+ user: 'redis-user',
976
+ host: 'localhost',
977
+ password: 'redis-password',
978
+ port: 6379,
979
+ },
980
+ };
981
+ const customHeaders = {
982
+ 'x-original-host': 'example.com',
983
+ 'x-shop-id': 'shop123',
984
+ 'x-sitepath': '/path',
985
+ 'x-locale': 'en',
986
+ 'x-region': 'US',
987
+ };
988
+ // Chain all interceptors
989
+ const headersInterceptor = (0, interceptors_1.createHeadersInterceptor)(customHeaders);
990
+ const authInterceptor = (0, interceptors_1.createAuthenticationInterceptor)(mockCheckoutConfig);
991
+ const customerAuthInterceptor = (0, interceptors_1.createCustomerAuthenticationInterceptor)(jwtToken);
992
+ const loggingInterceptor = (0, interceptors_1.createLoggingInterceptor)();
993
+ const chainedInterceptor = headersInterceptor(authInterceptor(customerAuthInterceptor(loggingInterceptor(mockNext))));
994
+ const mockRequest = {
995
+ header: new Headers(),
996
+ method: {
997
+ toString: () => 'TestService/TestMethod',
998
+ },
999
+ message: { $typeName: 'test.Message' },
1000
+ };
1001
+ yield chainedInterceptor(mockRequest);
1002
+ // Verify all headers from all interceptors are set
1003
+ expect(mockRequest.header.get('X-Original-Host')).toBe('example.com');
1004
+ expect(mockRequest.header.get('X-shop-id')).toBe('shop123');
1005
+ expect(mockRequest.header.get('X-Store-Key')).toBe('test-store-secret');
1006
+ expect(mockRequest.header.get('Authorization')).toBe(`Bearer ${jwtToken}`);
1007
+ expect(mockNext).toHaveBeenCalled();
1008
+ }));
1009
+ it('should validate headers before auth in chain', () => __awaiter(void 0, void 0, void 0, function* () {
1010
+ const mockNext = vi.fn();
1011
+ mockNext.mockResolvedValue({
1012
+ header: new Headers(),
1013
+ message: { $typeName: 'test.Message' },
1014
+ trailer: new Headers(),
1015
+ });
1016
+ const mockCheckoutConfig = {
1017
+ hostname: 'example.com',
1018
+ cmsRemoteURL: 'https://cms.example.com',
1019
+ enterpriseRemoteURL: 'https://enterprise.example.com',
1020
+ cmsURL: 'https://cms-local.example.com',
1021
+ enterpriseURL: 'https://enterprise.example.com',
1022
+ secureCookiePassword: 'secure-cookie-password',
1023
+ forestAPIKey: 'forest-api-key',
1024
+ saleChannelAccessKey: 'test-sales-channel-access',
1025
+ salesChannelAPISecret: 'test-sales-channel-secret',
1026
+ storeAccessKey: 'test-store-access',
1027
+ storeAPISecret: 'test-store-secret',
1028
+ isProduction: false,
1029
+ posthogKey: 'posthog-key',
1030
+ posthogDomain: 'posthog.example.com',
1031
+ posthogHost: 'posthog.example.com',
1032
+ assetsPath: '/assets',
1033
+ assetsDomain: 'assets.example.com',
1034
+ turnstileKey: 'turnstile-key',
1035
+ turnstileSecret: 'turnstile-secret',
1036
+ redis: {
1037
+ user: 'redis-user',
1038
+ host: 'localhost',
1039
+ password: 'redis-password',
1040
+ port: 6379,
1041
+ },
1042
+ };
1043
+ const invalidHeaders = {
1044
+ // Missing x-shop-id
1045
+ 'x-original-host': 'example.com',
1046
+ 'x-sitepath': '/path',
1047
+ 'x-locale': 'en',
1048
+ 'x-region': 'US',
1049
+ };
1050
+ const headersInterceptor = (0, interceptors_1.createHeadersInterceptor)(invalidHeaders);
1051
+ const authInterceptor = (0, interceptors_1.createAuthenticationInterceptor)(mockCheckoutConfig);
1052
+ const chainedInterceptor = headersInterceptor(authInterceptor(mockNext));
1053
+ const mockRequest = {
1054
+ header: new Headers(),
1055
+ message: { $typeName: 'test.Message' },
1056
+ };
1057
+ // Should fail at headers validation
1058
+ yield expect(chainedInterceptor(mockRequest)).rejects.toThrow();
1059
+ // Auth headers should not be set because headers validation failed
1060
+ expect(mockRequest.header.get('X-Store-Key')).toBeNull();
1061
+ }));
1062
+ });
1063
+ });