@pact-foundation/pact-core 13.5.1 → 13.6.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 (61) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/binding.gyp +141 -0
  3. package/build/Makefile +334 -0
  4. package/build/binding.Makefile +6 -0
  5. package/build/copy_release_artifacts.target.mk +47 -0
  6. package/build/pact.target.mk +174 -0
  7. package/build/set_osx_install_name.target.mk +18 -0
  8. package/ffi/{v0.0.3-libpact_ffi-osx-aarch64-apple-darwin.dylib → libpact_ffi.dylib} +0 -0
  9. package/ffi/{v0.0.3-libpact_ffi-linux-x86_64.so → libpact_ffi.so} +0 -0
  10. package/ffi/libpact_ffi.so.gz +0 -0
  11. package/ffi/{v0.0.3-libpact_ffi-osx-x86_64.dylib → osxaarch64/libpact_ffi.dylib} +0 -0
  12. package/ffi/pact-cpp.h +2344 -0
  13. package/ffi/{v0.0.3-pact.h → pact.h} +667 -119
  14. package/ffi/{v0.0.3-pact_ffi-windows-x86_64.dll → pact_ffi.dll} +0 -0
  15. package/ffi/pact_ffi.dll.lib +0 -0
  16. package/native/addon.cc +68 -0
  17. package/native/consumer.cc +1570 -0
  18. package/native/consumer.h +124 -0
  19. package/native/ffi.cc +148 -0
  20. package/native/ffi.h +18 -0
  21. package/native/plugin.cc +6 -0
  22. package/native/plugin.h +7 -0
  23. package/native/provider.cc +815 -0
  24. package/native/provider.h +38 -0
  25. package/package.json +12 -9
  26. package/src/consumer/checkErrors.d.ts +7 -0
  27. package/src/consumer/checkErrors.js +41 -0
  28. package/src/consumer/checkErrors.js.map +1 -0
  29. package/src/consumer/index.d.ts +5 -0
  30. package/src/consumer/index.js +222 -0
  31. package/src/consumer/index.js.map +1 -0
  32. package/src/consumer/types.d.ts +132 -0
  33. package/src/{ffi/internals → consumer}/types.js +0 -0
  34. package/src/{ffi/internals → consumer}/types.js.map +0 -0
  35. package/src/ffi/index.d.ts +4 -3
  36. package/src/ffi/index.js +6 -9
  37. package/src/ffi/index.js.map +1 -1
  38. package/src/ffi/internals/index.d.ts +0 -2
  39. package/src/ffi/internals/index.js +1 -11
  40. package/src/ffi/internals/index.js.map +1 -1
  41. package/src/ffi/types.d.ts +100 -0
  42. package/src/ffi/types.js +70 -0
  43. package/src/ffi/types.js.map +1 -0
  44. package/src/index.d.ts +2 -0
  45. package/src/index.js +2 -0
  46. package/src/index.js.map +1 -1
  47. package/src/logger/index.d.ts +5 -2
  48. package/src/logger/index.js +15 -2
  49. package/src/logger/index.js.map +1 -1
  50. package/src/verifier/argumentMapper/arguments.js +8 -0
  51. package/src/verifier/argumentMapper/arguments.js.map +1 -1
  52. package/src/verifier/index.js +1 -7
  53. package/src/verifier/index.js.map +1 -1
  54. package/src/verifier/nativeVerifier.js +74 -15
  55. package/src/verifier/nativeVerifier.js.map +1 -1
  56. package/src/verifier/types.d.ts +10 -2
  57. package/test.js +52 -0
  58. package/src/ffi/declarations.d.ts +0 -136
  59. package/src/ffi/declarations.js +0 -92
  60. package/src/ffi/declarations.js.map +0 -1
  61. package/src/ffi/internals/types.d.ts +0 -23
@@ -0,0 +1,1570 @@
1
+ #include <napi.h>
2
+ #include "pact-cpp.h"
3
+
4
+ using namespace Napi;
5
+
6
+ PactSpecification integerToSpecification(Napi::Env &env, uint32_t number) {
7
+ PactSpecification specification = PactSpecification::PactSpecification_V2;
8
+
9
+ switch(number) {
10
+ case 0:
11
+ specification = PactSpecification::PactSpecification_Unknown;
12
+ break;
13
+ case 1:
14
+ specification = PactSpecification::PactSpecification_V1;
15
+ break;
16
+ case 2:
17
+ specification = PactSpecification::PactSpecification_V1_1;
18
+ break;
19
+ case 3:
20
+ specification = PactSpecification::PactSpecification_V2;
21
+ break;
22
+ case 4:
23
+ specification = PactSpecification::PactSpecification_V3;
24
+ break;
25
+ case 5:
26
+ specification = PactSpecification::PactSpecification_V4;
27
+ break;
28
+ default:
29
+ std::string err = "Unable to parse pact specification: ";
30
+ err += number;
31
+
32
+ throw Napi::Error::New(env, err);
33
+ }
34
+
35
+ return specification;
36
+ }
37
+
38
+ InteractionPart integerToInteractionPart(Napi::Env &env, uint32_t number) {
39
+ InteractionPart part = InteractionPart::InteractionPart_Request;
40
+
41
+ switch(number) {
42
+ case 0:
43
+ part = InteractionPart::InteractionPart_Request;
44
+ break;
45
+ case 1:
46
+ part = InteractionPart::InteractionPart_Response;
47
+ break;
48
+ default:
49
+ std::string err = "Unable to parse pact interaction part: ";
50
+ err += number;
51
+
52
+ throw Napi::Error::New(env, err);
53
+ }
54
+
55
+ return part;
56
+ }
57
+
58
+ /**
59
+ * Fetch the in-memory logger buffer contents. This will only have any contents if the `buffer`
60
+ * sink has been configured to log to. The contents will be allocated on the heap and will need
61
+ * to be freed with `string_delete`.
62
+ *
63
+ * Fetches the logs associated with the provided identifier, or uses the "global" one if the
64
+ * identifier is not specified (i.e. NULL).
65
+ *
66
+ * Returns a NULL pointer if the buffer can't be fetched. This can occur is there is not
67
+ * sufficient memory to make a copy of the contents or the buffer contains non-UTF-8 characters.
68
+ *
69
+ * # Safety
70
+ *
71
+ * This function will fail if the log_id pointer is invalid or does not point to a NULL
72
+ * terminated string.
73
+ *
74
+ * C interface:
75
+ *
76
+ * const char *pactffi_fetch_log_buffer(const char *log_id);
77
+ */
78
+ Napi::Value PactffiFetchLogBuffer(const Napi::CallbackInfo& info) {
79
+ Napi::Env env = info.Env();
80
+
81
+ if (info.Length() < 1) {
82
+ throw Napi::Error::New(env, "PactffiFetchLogBuffer received < 1 arguments");
83
+ }
84
+
85
+ if (!info[0].IsString()) {
86
+ throw Napi::Error::New(env, "PactffiFetchLogBuffer(log_id) expected a string");
87
+ }
88
+
89
+ std::string log_id = info[0].As<Napi::String>().Utf8Value();
90
+
91
+ const char* buffer = pactffi_fetch_log_buffer(log_id.c_str());
92
+
93
+ return Napi::String::New(env, buffer);
94
+ }
95
+
96
+ /**
97
+ * Delete a string previously returned by this FFI.
98
+ *
99
+ * It is explicitly allowed to pass a null pointer to this function;
100
+ * in that case the function will do nothing.
101
+ *
102
+ * C interface:
103
+ *
104
+ * void pactffi_string_delete(char *string);
105
+ */
106
+ Napi::Value PactffiStringDelete(const Napi::CallbackInfo& info) {
107
+ Napi::Env env = info.Env();
108
+
109
+ if (info.Length() < 1) {
110
+ throw Napi::Error::New(env, "PactffiStringDelete received < 1 arguments");
111
+ }
112
+
113
+ if (!info[0].IsString()) {
114
+ throw Napi::Error::New(env, "PactffiStringDelete(str) expected a string");
115
+ }
116
+
117
+ throw Napi::Error::New(env, "PactffiStringDelete(str) is unimplemented");
118
+
119
+ return info.Env().Undefined();
120
+ }
121
+
122
+ /**
123
+ * External interface to check if a mock server has matched all its requests. The port number is
124
+ * passed in, and if all requests have been matched, true is returned. False is returned if there
125
+ * is no mock server on the given port, or if any request has not been successfully matched, or
126
+ * the method panics.
127
+ *
128
+ * C interface:
129
+ *
130
+ * bool pactffi_mock_server_matched(int32_t mock_server_port);
131
+ */
132
+ Napi::Value PactffiMockServerMatched(const Napi::CallbackInfo& info) {
133
+ Napi::Env env = info.Env();
134
+
135
+ if (info.Length() < 1) {
136
+ throw Napi::Error::New(env, "PactffiMockServerMatched received < 1 arguments");
137
+ }
138
+
139
+ if (!info[0].IsNumber()) {
140
+ throw Napi::Error::New(env, "PactffiMockServerMatched(port) expected a number");
141
+ }
142
+
143
+ int32_t port = info[0].As<Napi::Number>().Int32Value();
144
+
145
+ bool res = pactffi_mock_server_matched(port);
146
+
147
+ return Napi::Boolean::New(env, res);
148
+ }
149
+
150
+ /**
151
+ * External interface to get all the mismatches from a mock server. The port number of the mock
152
+ * server is passed in, and a pointer to a C string with the mismatches in JSON format is
153
+ * returned.
154
+ *
155
+ * **NOTE:** The JSON string for the result is allocated on the heap, and will have to be freed
156
+ * once the code using the mock server is complete. The [`cleanup_mock_server`](fn.cleanup_mock_server.html) function is
157
+ * provided for this purpose.
158
+ *
159
+ * # Errors
160
+ *
161
+ * If there is no mock server with the provided port number, or the function panics, a NULL
162
+ * pointer will be returned. Don't try to dereference it, it will not end well for you.
163
+ *
164
+ * C interface:
165
+ *
166
+ * char *pactffi_mock_server_mismatches(int32_t mock_server_port);
167
+ */
168
+ Napi::Value PactffiMockServerMismatches(const Napi::CallbackInfo& info) {
169
+ Napi::Env env = info.Env();
170
+
171
+ if (info.Length() < 1) {
172
+ throw Napi::Error::New(env, "PactffiMockServerMismatches received < 1 arguments");
173
+ }
174
+
175
+ if (!info[0].IsNumber()) {
176
+ throw Napi::Error::New(env, "PactffiMockServerMismatches(port) expected a number");
177
+ }
178
+
179
+ int32_t port = info[0].As<Napi::Number>().Int32Value();
180
+ char* res = pactffi_mock_server_mismatches(port);
181
+
182
+ return Napi::String::New(env, res);
183
+ }
184
+
185
+ /**
186
+ * External interface to create a mock server. A Pact handle is passed in,
187
+ * as well as the port for the mock server to run on. A value of 0 for the port will result in a
188
+ * port being allocated by the operating system. The port of the mock server is returned.
189
+ *
190
+ * * `pact` - Handle to a Pact model
191
+ * * `addr_str` - Address to bind to in the form name:port (i.e. 127.0.0.1:0)
192
+ * * `tls` - boolean flag to indicate of the mock server should use TLS (using a self-signed certificate)
193
+ *
194
+ * # Errors
195
+ *
196
+ * Errors are returned as negative values.
197
+ *
198
+ * | Error | Description |
199
+ * |-------|-------------|
200
+ * | -1 | An invalid handle was received |
201
+ * | -3 | The mock server could not be started |
202
+ * | -4 | The method panicked |
203
+ * | -5 | The address is not valid |
204
+ * | -6 | Could not create the TLS configuration with the self-signed certificate |
205
+ *
206
+ * C interface:
207
+ *
208
+ * int32_t pactffi_create_mock_server_for_pact(PactHandle pact, const char *addr_str, bool tls);
209
+ */
210
+ Napi::Value PactffiCreateMockServerForPact(const Napi::CallbackInfo& info) {
211
+ Napi::Env env = info.Env();
212
+
213
+ if (info.Length() < 3) {
214
+ throw Napi::Error::New(env, "PactffiCreateMockServerForPact received < 3 arguments");
215
+ }
216
+
217
+ if (!info[0].IsNumber()) {
218
+ throw Napi::Error::New(env, "PactffiCreateMockServerForPact(arg 0) expected a PactHandle (uint16_t)");
219
+ }
220
+
221
+ if (!info[1].IsString()) {
222
+ throw Napi::Error::New(env, "PactffiCreateMockServerForPact(arg 1) expected a string");
223
+ }
224
+
225
+ if (!info[2].IsBoolean()) {
226
+ throw Napi::Error::New(env, "PactffiCreateMockServerForPact(arg 2) expected a boolean");
227
+ }
228
+
229
+ PactHandle pact = info[0].As<Napi::Number>().Int32Value();
230
+ std::string addr = info[1].As<Napi::String>().Utf8Value();
231
+ bool tls = info[2].As<Napi::Boolean>().Value();
232
+
233
+ // int32_t pactffi_create_mock_server_for_pact(PactHandle pact, const char *addr_str, bool tls);
234
+
235
+ uint16_t result = pactffi_create_mock_server_for_pact(pact, addr.c_str(), tls);
236
+
237
+ return Number::New(env, result);
238
+ }
239
+
240
+ /**
241
+ * External interface to cleanup a mock server. This function will try terminate the mock server
242
+ * with the given port number and cleanup any memory allocated for it. Returns true, unless a
243
+ * mock server with the given port number does not exist, or the function panics.
244
+ *
245
+ * C interface:
246
+ *
247
+ * bool pactffi_cleanup_mock_server(int32_t mock_server_port);
248
+ */
249
+ Napi::Value PactffiCleanupMockServer(const Napi::CallbackInfo& info) {
250
+ Napi::Env env = info.Env();
251
+
252
+ if (info.Length() < 1) {
253
+ throw Napi::Error::New(env, "PactffiCleanupMockServer received < 1 arguments");
254
+ }
255
+
256
+ if (!info[0].IsNumber()) {
257
+ throw Napi::Error::New(env, "PactffiCleanupMockServer(arg 0) expected a number");
258
+ }
259
+
260
+ uint32_t port = info[0].As<Napi::Number>().Int32Value();
261
+
262
+ bool res = pactffi_cleanup_mock_server(port);
263
+
264
+ return Napi::Boolean::New(env, res);
265
+ }
266
+
267
+ /**
268
+ * External interface to write out the pact file. This function should
269
+ * be called if all the consumer tests have passed. The directory to write the file to is passed
270
+ * as the second parameter. If a NULL pointer is passed, the current working directory is used.
271
+ *
272
+ * If overwrite is true, the file will be overwritten with the contents of the current pact.
273
+ * Otherwise, it will be merged with any existing pact file.
274
+ *
275
+ * Returns 0 if the pact file was successfully written. Returns a positive code if the file can
276
+ * not be written or the function panics.
277
+ *
278
+ * # Safety
279
+ *
280
+ * The directory parameter must either be NULL or point to a valid NULL terminated string.
281
+ *
282
+ * # Errors
283
+ *
284
+ * Errors are returned as positive values.
285
+ *
286
+ * | Error | Description |
287
+ * |-------|-------------|
288
+ * | 1 | The function panicked. |
289
+ * | 2 | The pact file was not able to be written. |
290
+ * | 3 | The pact for the given handle was not found. |
291
+ *
292
+ * C Interface:
293
+ *
294
+ * int32_t pactffi_pact_handle_write_file(PactHandle pact, const char *directory, bool overwrite);
295
+ */
296
+ Napi::Value PactffiWritePactFile(const Napi::CallbackInfo& info) {
297
+ Napi::Env env = info.Env();
298
+
299
+ if (info.Length() < 3) {
300
+ throw Napi::Error::New(env, "PactffiWritePactFile received < 3 arguments");
301
+ }
302
+
303
+ if (!info[0].IsNumber()) {
304
+ throw Napi::Error::New(env, "PactffiWritePactFile(arg 0) expected a PactHandle (uint16_t");
305
+ }
306
+
307
+ if (!info[1].IsString()) {
308
+ throw Napi::Error::New(env, "PactffiWritePactFile(arg 1) expected a string");
309
+ }
310
+
311
+ if (!info[2].IsBoolean()) {
312
+ throw Napi::Error::New(env, "PactffiWritePactFile(arg 2) expected a boolean");
313
+ }
314
+
315
+ PactHandle pact = info[0].As<Napi::Number>().Int32Value();
316
+ std::string dir = info[1].As<Napi::String>().Utf8Value();
317
+ bool overwrite = info[2].As<Napi::Boolean>().Value();
318
+
319
+ int32_t res = pactffi_pact_handle_write_file(pact, dir.c_str(), overwrite);
320
+
321
+ return Number::New(env, res);
322
+ }
323
+
324
+ /**
325
+ * Creates a new Pact model and returns a handle to it.
326
+ *
327
+ * * `consumer_name` - The name of the consumer for the pact.
328
+ * * `provider_name` - The name of the provider for the pact.
329
+ *
330
+ * Returns a new `PactHandle`. The handle will need to be freed with the `pactffi_free_pact_handle`
331
+ * method to release its resources.
332
+ *
333
+ * C interface:
334
+ *
335
+ * PactHandle pactffi_new_pact(const char *consumer_name, const char *provider_name);
336
+ */
337
+ Napi::Value PactffiNewPact(const Napi::CallbackInfo& info) {
338
+ Napi::Env env = info.Env();
339
+
340
+ if (info.Length() < 2) {
341
+ throw Napi::Error::New(env, "PactffiNewPact received < 2 arguments");
342
+ }
343
+
344
+ if (!info[0].IsString()) {
345
+ throw Napi::Error::New(env, "PactffiNewPact(arg 0) expected a string");
346
+ }
347
+
348
+ if (!info[1].IsString()) {
349
+ throw Napi::Error::New(env, "PactffiNewPact(arg 1) expected a string");
350
+ }
351
+
352
+ std::string consumer = info[0].As<Napi::String>().Utf8Value();
353
+ std::string provider = info[1].As<Napi::String>().Utf8Value();
354
+
355
+ PactHandle pact = pactffi_new_pact(consumer.c_str(), provider.c_str());
356
+
357
+ return Number::New(env, pact);
358
+ }
359
+
360
+ /**
361
+ * Creates a new HTTP Interaction and returns a handle to it.
362
+ *
363
+ * * `description` - The interaction description. It needs to be unique for each interaction.
364
+ *
365
+ * Returns a new `InteractionHandle`.
366
+ *
367
+ * C interface:
368
+ *
369
+ * InteractionHandle pactffi_new_interaction(PactHandle pact, const char *description);
370
+ */
371
+ Napi::Value PactffiNewInteraction(const Napi::CallbackInfo& info) {
372
+ Napi::Env env = info.Env();
373
+
374
+ if (info.Length() < 2) {
375
+ throw Napi::Error::New(env, "PactffiNewInteraction received < 2 arguments");
376
+ }
377
+
378
+ if (!info[0].IsNumber()) {
379
+ throw Napi::Error::New(env, "PactffiNewInteraction(arg 0) expected a PactHandle (uint16_t)");
380
+ }
381
+
382
+ if (!info[1].IsString()) {
383
+ throw Napi::Error::New(env, "PactffiNewInteraction(arg 1) expected a string");
384
+ }
385
+
386
+ PactHandle pact = info[0].As<Napi::Number>().Uint32Value();
387
+ std::string description = info[1].As<Napi::String>().Utf8Value();
388
+
389
+ InteractionHandle handle = pactffi_new_interaction(pact, description.c_str());
390
+
391
+ return Number::New(env, handle);
392
+ }
393
+
394
+ /**
395
+ * Sets the description for the Interaction. Returns false if the interaction or Pact can't be
396
+ * modified (i.e. the mock server for it has already started)
397
+ *
398
+ * * `description` - The interaction description. It needs to be unique for each interaction.
399
+ *
400
+ * C interface:
401
+ *
402
+ * bool pactffi_upon_receiving(InteractionHandle interaction, const char *description);
403
+ */
404
+ Napi::Value PactffiUponReceiving(const Napi::CallbackInfo& info) {
405
+ Napi::Env env = info.Env();
406
+
407
+ if (info.Length() < 2) {
408
+ throw Napi::Error::New(env, "PactffiUponReceiving received < 2 arguments");
409
+ }
410
+
411
+ if (!info[0].IsNumber()) {
412
+ throw Napi::Error::New(env, "PactffiUponReceiving(arg 0) expected a InteractionHandle (uint32_t)");
413
+ }
414
+
415
+ if (!info[1].IsString()) {
416
+ throw Napi::Error::New(env, "PactffiUponReceiving(arg 1) expected a string");
417
+ }
418
+
419
+ InteractionHandle interaction = info[0].As<Napi::Number>().Uint32Value();
420
+ std::string description = info[1].As<Napi::String>().Utf8Value();
421
+
422
+ bool res = pactffi_upon_receiving(interaction, description.c_str());
423
+
424
+ return Napi::Boolean::New(env, res);
425
+ }
426
+
427
+ /**
428
+ * Adds a provider state to the Interaction. Returns false if the interaction or Pact can't be
429
+ * modified (i.e. the mock server for it has already started)
430
+ *
431
+ * * `description` - The provider state description. It needs to be unique.
432
+ *
433
+ * C interface:
434
+ *
435
+ * bool pactffi_given(InteractionHandle interaction, const char *description);
436
+ */
437
+ Napi::Value PactffiGiven(const Napi::CallbackInfo& info) {
438
+ Napi::Env env = info.Env();
439
+
440
+ if (info.Length() < 2) {
441
+ throw Napi::Error::New(env, "PactffiGiven received < 2 arguments");
442
+ }
443
+
444
+ if (!info[0].IsNumber()) {
445
+ throw Napi::Error::New(env, "PactffiGiven(arg 0) expected a InteractionHandle (uint32_t)");
446
+ }
447
+
448
+ if (!info[1].IsString()) {
449
+ throw Napi::Error::New(env, "PactffiGiven(arg 1) expected a string");
450
+ }
451
+
452
+ InteractionHandle interaction = info[0].As<Napi::Number>().Uint32Value();
453
+ std::string description = info[1].As<Napi::String>().Utf8Value();
454
+
455
+ bool res = pactffi_given(interaction, description.c_str());
456
+
457
+ return Napi::Boolean::New(env, res);
458
+ }
459
+
460
+ /**
461
+ * Adds a provider state to the Interaction with a parameter key and value. Returns false if the interaction or Pact can't be
462
+ * modified (i.e. the mock server for it has already started)
463
+ *
464
+ * * `description` - The provider state description. It needs to be unique.
465
+ * * `name` - Parameter name.
466
+ * * `value` - Parameter value.
467
+ *
468
+ * C interface:
469
+ *
470
+ * bool pactffi_given_with_param(InteractionHandle interaction,
471
+ * const char *description,
472
+ * const char *name,
473
+ * const char *value);
474
+ */
475
+ Napi::Value PactffiGivenWithParam(const Napi::CallbackInfo& info) {
476
+ Napi::Env env = info.Env();
477
+
478
+ if (info.Length() < 4) {
479
+ throw Napi::Error::New(env, "PactffiGivenWithParam received < 4 arguments");
480
+ }
481
+
482
+ if (!info[0].IsNumber()) {
483
+ throw Napi::Error::New(env, "PactffiGivenWithParam(arg 0) expected a InteractionHandle (uint32_t)");
484
+ }
485
+
486
+ if (!info[1].IsString()) {
487
+ throw Napi::Error::New(env, "PactffiGivenWithParam(arg 1) expected a string");
488
+ }
489
+
490
+ if (!info[2].IsString()) {
491
+ throw Napi::Error::New(env, "PactffiGivenWithParam(arg 2) expected a string");
492
+ }
493
+
494
+ if (!info[3].IsString()) {
495
+ throw Napi::Error::New(env, "PactffiGivenWithParam(arg 3) expected a string");
496
+ }
497
+
498
+ InteractionHandle interaction = info[0].As<Napi::Number>().Uint32Value();
499
+ std::string description = info[1].As<Napi::String>().Utf8Value();
500
+ std::string name = info[2].As<Napi::String>().Utf8Value();
501
+ std::string value = info[3].As<Napi::String>().Utf8Value();
502
+
503
+ bool res = pactffi_given_with_param(interaction, description.c_str(), name.c_str(), value.c_str());
504
+
505
+ return Napi::Boolean::New(env, res);
506
+ }
507
+
508
+ /**
509
+ * Configures the request for the Interaction. Returns false if the interaction or Pact can't be
510
+ * modified (i.e. the mock server for it has already started)
511
+ *
512
+ * * `method` - The request method. Defaults to GET.
513
+ * * `path` - The request path. Defaults to `/`.
514
+ *
515
+ * C interface:
516
+ *
517
+ * bool pactffi_with_request(InteractionHandle interaction, const char *method, const char *path);
518
+ */
519
+ Napi::Value PactffiWithRequest(const Napi::CallbackInfo& info) {
520
+ Napi::Env env = info.Env();
521
+
522
+ if (info.Length() < 3) {
523
+ throw Napi::Error::New(env, "PactffiWithRequest received < 3 arguments");
524
+ }
525
+
526
+ if (!info[0].IsNumber()) {
527
+ throw Napi::Error::New(env, "PactffiWithRequest(arg 0) expected a InteractionHandle (uint32_t)");
528
+ }
529
+
530
+ if (!info[1].IsString()) {
531
+ throw Napi::Error::New(env, "PactffiWithRequest(arg 1) expected a string");
532
+ }
533
+
534
+ if (!info[2].IsString()) {
535
+ throw Napi::Error::New(env, "PactffiWithRequest(arg 2) expected a string");
536
+ }
537
+
538
+ InteractionHandle interaction = info[0].As<Napi::Number>().Uint32Value();
539
+ std::string method = info[1].As<Napi::String>().Utf8Value();
540
+ std::string path = info[2].As<Napi::String>().Utf8Value();
541
+
542
+ bool res = pactffi_with_request(interaction, method.c_str(), path.c_str());
543
+
544
+ return Napi::Boolean::New(env, res);
545
+ }
546
+
547
+ /**
548
+ * Configures a query parameter for the Interaction. Returns false if the interaction or Pact can't be
549
+ * modified (i.e. the mock server for it has already started)
550
+ *
551
+ * * `name` - the query parameter name.
552
+ * * `value` - the query parameter value.
553
+ * * `index` - the index of the value (starts at 0). You can use this to create a query parameter with multiple values
554
+ *
555
+ * C interface:
556
+ *
557
+ * bool pactffi_with_query_parameter(InteractionHandle interaction, const char *name, size_t index, const char *value);
558
+ */
559
+ Napi::Value PactffiWithQueryParameter(const Napi::CallbackInfo& info) {
560
+ Napi::Env env = info.Env();
561
+
562
+ if (info.Length() < 4) {
563
+ throw Napi::Error::New(env, "PactffiWithQueryParameter received < 4 arguments");
564
+ }
565
+
566
+ if (!info[0].IsNumber()) {
567
+ throw Napi::Error::New(env, "PactffiWithQueryParameter(arg 0) expected a InteractionHandle (uint32_t)");
568
+ }
569
+
570
+ if (!info[1].IsString()) {
571
+ throw Napi::Error::New(env, "PactffiWithQueryParameter(arg 1) expected a string");
572
+ }
573
+
574
+ if (!info[2].IsNumber()) {
575
+ throw Napi::Error::New(env, "PactffiWithQueryParameter(arg 2) expected a number");
576
+ }
577
+
578
+ if (!info[3].IsString()) {
579
+ throw Napi::Error::New(env, "PactffiWithQueryParameter(arg 3) expected a string");
580
+ }
581
+
582
+ InteractionHandle interaction = info[0].As<Napi::Number>().Uint32Value();
583
+ std::string name = info[1].As<Napi::String>().Utf8Value();
584
+ size_t index = info[2].As<Napi::Number>().Uint32Value();
585
+ std::string value = info[3].As<Napi::String>().Utf8Value();
586
+
587
+ bool res = pactffi_with_query_parameter(interaction, name.c_str(), index, value.c_str());
588
+
589
+ return Napi::Boolean::New(env, res);
590
+ }
591
+
592
+ /**
593
+ * Sets the specification version for a given Pact model. Returns false if the interaction or Pact can't be
594
+ * modified (i.e. the mock server for it has already started) or the version is invalid
595
+ *
596
+ * * `pact` - Handle to a Pact model
597
+ * * `version` - the spec version to use
598
+ *
599
+ * C interface:
600
+ *
601
+ * bool pactffi_with_specification(PactHandle pact, PactSpecification version);
602
+ */
603
+ Napi::Value PactffiWithSpecification(const Napi::CallbackInfo& info) {
604
+ Napi::Env env = info.Env();
605
+
606
+ if (info.Length() < 2) {
607
+ throw Napi::Error::New(env, "PactffiWithSpecification received < 2 arguments");
608
+ }
609
+
610
+ if (!info[0].IsNumber()) {
611
+ throw Napi::Error::New(env, "PactffiWithSpecification(arg 0) expected a PactHandle (uint16_t)");
612
+ }
613
+
614
+ if (!info[1].IsNumber()) {
615
+ throw Napi::Error::New(env, "PactffiWithSpecification(arg 1) expected a number");
616
+ }
617
+
618
+ PactHandle pact = info[0].As<Napi::Number>().Uint32Value();
619
+ uint32_t specificationNumber = info[1].As<Napi::Number>().Uint32Value();
620
+ PactSpecification specification = integerToSpecification(env, specificationNumber);
621
+
622
+ bool res = pactffi_with_specification(pact, specification);
623
+
624
+ return Napi::Boolean::New(env, res);
625
+ }
626
+
627
+ /**
628
+ * Sets the additional metadata on the Pact file. Common uses are to add the client library details such as the name and version
629
+ * Returns false if the interaction or Pact can't be modified (i.e. the mock server for it has already started)
630
+ *
631
+ * * `pact` - Handle to a Pact model
632
+ * * `namespace` - the top level metadat key to set any key values on
633
+ * * `name` - the key to set
634
+ * * `value` - the value to set
635
+ *
636
+ * C interface:
637
+ *
638
+ * bool pactffi_with_pact_metadata(PactHandle pact, const char *namespace_, const char *name, const char *value);
639
+ */
640
+ Napi::Value PactffiWithPactMetadata(const Napi::CallbackInfo& info) {
641
+ Napi::Env env = info.Env();
642
+
643
+ if (info.Length() < 4) {
644
+ throw Napi::Error::New(env, "PactffiWithPactMetadata received < 4 arguments");
645
+ }
646
+
647
+ if (!info[0].IsNumber()) {
648
+ throw Napi::Error::New(env, "PactffiWithPactMetadata(arg 0) expected a PactHandle (uint16_t)");
649
+ }
650
+
651
+ if (!info[1].IsString()) {
652
+ throw Napi::Error::New(env, "PactffiWithPactMetadata(arg 1) expected a string");
653
+ }
654
+
655
+ if (!info[2].IsString()) {
656
+ throw Napi::Error::New(env, "PactffiWithPactMetadata(arg 2) expected a string");
657
+ }
658
+
659
+ if (!info[3].IsString()) {
660
+ throw Napi::Error::New(env, "PactffiWithPactMetadata(arg 3) expected a string");
661
+ }
662
+
663
+ PactHandle pact = info[0].As<Napi::Number>().Uint32Value();
664
+ std::string ns = info[1].As<Napi::String>().Utf8Value();
665
+ std::string name = info[2].As<Napi::String>().Utf8Value();
666
+ std::string value = info[3].As<Napi::String>().Utf8Value();
667
+
668
+ bool res = pactffi_with_pact_metadata(pact, ns.c_str(), name.c_str(), value.c_str());
669
+
670
+ return Napi::Boolean::New(env, res);
671
+ }
672
+
673
+ /**
674
+ * Configures a header for the Interaction. Returns false if the interaction or Pact can't be
675
+ * modified (i.e. the mock server for it has already started)
676
+ *
677
+ * * `part` - The part of the interaction to add the header to (Request or Response).
678
+ * * `name` - the header name.
679
+ * * `value` - the header value.
680
+ * * `index` - the index of the value (starts at 0). You can use this to create a header with multiple values
681
+ *
682
+ * C interface:
683
+ *
684
+ * bool pactffi_with_header(InteractionHandle interaction,
685
+ * InteractionPart part,
686
+ * const char *name,
687
+ * size_t index,
688
+ * const char *value);
689
+ */
690
+ Napi::Value PactffiWithHeader(const Napi::CallbackInfo& info) {
691
+ Napi::Env env = info.Env();
692
+
693
+ if (info.Length() < 5) {
694
+ throw Napi::Error::New(env, "PactffiWithHeader received < 5 arguments");
695
+ }
696
+
697
+ if (!info[0].IsNumber()) {
698
+ throw Napi::Error::New(env, "PactffiWithHeader(arg 0) expected a PactHandle (uint16_t)");
699
+ }
700
+
701
+ if (!info[1].IsNumber()) {
702
+ throw Napi::Error::New(env, "PactffiWithHeader(arg 1) expected an InteractionPart (uint32_t)");
703
+ }
704
+
705
+ if (!info[2].IsString()) {
706
+ throw Napi::Error::New(env, "PactffiWithHeader(arg 2) expected a string");
707
+ }
708
+
709
+ if (!info[3].IsNumber()) {
710
+ throw Napi::Error::New(env, "PactffiWithHeader(arg 3) expected a number");
711
+ }
712
+
713
+ if (!info[4].IsString()) {
714
+ throw Napi::Error::New(env, "PactffiWithHeader(arg 4) expected a string");
715
+ }
716
+
717
+ InteractionHandle interaction = info[0].As<Napi::Number>().Uint32Value();
718
+ uint32_t partNumber = info[1].As<Napi::Number>().Uint32Value();
719
+ InteractionPart part = integerToInteractionPart(env, partNumber);
720
+ std::string name = info[2].As<Napi::String>().Utf8Value();
721
+ size_t index = info[3].As<Napi::Number>().Uint32Value();
722
+ std::string value = info[4].As<Napi::String>().Utf8Value();
723
+
724
+ bool res = pactffi_with_header(interaction, part, name.c_str(), index, value.c_str());
725
+
726
+ return Napi::Boolean::New(env, res);
727
+ }
728
+
729
+ /**
730
+ * Adds the body for the interaction. Returns false if the interaction or Pact can't be
731
+ * modified (i.e. the mock server for it has already started)
732
+ *
733
+ * * `part` - The part of the interaction to add the body to (Request or Response).
734
+ * * `content_type` - The content type of the body. Defaults to `text/plain`. Will be ignored if a content type
735
+ * header is already set.
736
+ * * `body` - The body contents. For JSON payloads, matching rules can be embedded in the body.
737
+ *
738
+ * C interface:
739
+ *
740
+ * bool pactffi_with_body(InteractionHandle interaction,
741
+ * InteractionPart part,
742
+ * const char *content_type,
743
+ * const char *body);
744
+ */
745
+ Napi::Value PactffiWithBody(const Napi::CallbackInfo& info) {
746
+ Napi::Env env = info.Env();
747
+
748
+ if (info.Length() < 4) {
749
+ throw Napi::Error::New(env, "PactffiWithBody received < 4 arguments");
750
+ }
751
+
752
+ if (!info[0].IsNumber()) {
753
+ throw Napi::Error::New(env, "PactffiWithBody(arg 0) expected a PactHandle (uint16_t)");
754
+ }
755
+
756
+ if (!info[1].IsNumber()) {
757
+ throw Napi::Error::New(env, "PactffiWithBody(arg 1) expected an InteractionPart (uint32_t)");
758
+ }
759
+
760
+ if (!info[2].IsString()) {
761
+ throw Napi::Error::New(env, "PactffiWithBody(arg 2) expected a string");
762
+ }
763
+
764
+ if (!info[3].IsString()) {
765
+ throw Napi::Error::New(env, "PactffiWithBody(arg 3) expected a string");
766
+ }
767
+
768
+ InteractionHandle interaction = info[0].As<Napi::Number>().Uint32Value();
769
+ uint32_t partNumber = info[1].As<Napi::Number>().Uint32Value();
770
+ InteractionPart part = integerToInteractionPart(env, partNumber);
771
+ std::string contentType = info[2].As<Napi::String>().Utf8Value();
772
+ std::string body = info[3].As<Napi::String>().Utf8Value();
773
+
774
+ bool res = pactffi_with_body(interaction, part, contentType.c_str(), body.c_str());
775
+
776
+ return Napi::Boolean::New(env, res);
777
+ }
778
+
779
+ /**
780
+ * Adds a binary file as the body with the expected content type and example contents. Will use
781
+ * a mime type matcher to match the body. Returns false if the interaction or Pact can't be
782
+ * modified (i.e. the mock server for it has already started)
783
+ *
784
+ * * `interaction` - Interaction handle to set the body for.
785
+ * * `part` - Request or response part.
786
+ * * `content_type` - Expected content type.
787
+ * * `body` - example body contents in bytes
788
+ * * `size` - number of bytes in the body
789
+ *
790
+ * C interface:
791
+ *
792
+ * bool pactffi_with_binary_file(InteractionHandle interaction,
793
+ * InteractionPart part,
794
+ * const char *content_type,
795
+ * const uint8_t *body,
796
+ * size_t size);
797
+ */
798
+ Napi::Value PactffiWithBinaryFile(const Napi::CallbackInfo& info) {
799
+ Napi::Env env = info.Env();
800
+
801
+ if (info.Length() < 5) {
802
+ throw Napi::Error::New(env, "PactffiWithBinaryFile received < 5 arguments");
803
+ }
804
+
805
+ if (!info[0].IsNumber()) {
806
+ throw Napi::Error::New(env, "PactffiWithBinaryFile(arg 0) expected a PactHandle (uint16_t)");
807
+ }
808
+
809
+ if (!info[1].IsNumber()) {
810
+ throw Napi::Error::New(env, "PactffiWithBinaryFile(arg 1) expected an InteractionPart (uint32_t)");
811
+ }
812
+
813
+ if (!info[2].IsString()) {
814
+ throw Napi::Error::New(env, "PactffiWithBinaryFile(arg 2) expected a string");
815
+ }
816
+
817
+ if (!info[3].IsBuffer()) {
818
+ throw Napi::Error::New(env, "PactffiWithBinaryFile(arg 3) expected a Buffer");
819
+ }
820
+
821
+ if (!info[4].IsNumber()) {
822
+ throw Napi::Error::New(env, "PactffiWithBinaryFile(arg 4) expected a number");
823
+ }
824
+
825
+ InteractionHandle interaction = info[0].As<Napi::Number>().Uint32Value();
826
+ uint32_t partNumber = info[1].As<Napi::Number>().Uint32Value();
827
+ InteractionPart part = integerToInteractionPart(env, partNumber);
828
+
829
+ // uint32_t part = info[1].As<Napi::Number>().Uint32Value();
830
+ std::string contentType = info[2].As<Napi::String>().Utf8Value();
831
+ Napi::Buffer<uint8_t> buffer = info[3].As<Napi::Buffer<uint8_t>>();
832
+ size_t size = info[4].As<Napi::Number>().Uint32Value();
833
+
834
+ bool res = pactffi_with_binary_file(interaction, part, contentType.c_str(), buffer.Data(), size);
835
+
836
+ return Napi::Boolean::New(env, res);
837
+ }
838
+
839
+ /**
840
+ * Adds a binary file as the body as a MIME multipart with the expected content type and example contents. Will use
841
+ * a mime type matcher to match the body. Returns an error if the interaction or Pact can't be
842
+ * modified (i.e. the mock server for it has already started)
843
+ *
844
+ * * `interaction` - Interaction handle to set the body for.
845
+ * * `part` - Request or response part.
846
+ * * `content_type` - Expected content type of the file.
847
+ * * `file` - path to the example file
848
+ * * `part_name` - name for the mime part
849
+ *
850
+ * C interface:
851
+ *
852
+ * StringResult pactffi_with_multipart_file(InteractionHandle interaction,
853
+ * InteractionPart part,
854
+ * const char *content_type,
855
+ * const char *file,
856
+ * const char part_name);
857
+ */
858
+ Napi::Value PactffiWithMultipartFile(const Napi::CallbackInfo& info) {
859
+ Napi::Env env = info.Env();
860
+
861
+ if (info.Length() < 5) {
862
+ throw Napi::Error::New(env, "PactffiWithMultipartFile received < 5 arguments");
863
+ }
864
+
865
+ if (!info[0].IsNumber()) {
866
+ throw Napi::Error::New(env, "PactffiWithMultipartFile(arg 0) expected a PactHandle (uint16_t)");
867
+ }
868
+
869
+ if (!info[1].IsNumber()) {
870
+ throw Napi::Error::New(env, "PactffiWithMultipartFile(arg 1) expected an InteractionPart (uint32_t)");
871
+ }
872
+
873
+ if (!info[2].IsString()) {
874
+ throw Napi::Error::New(env, "PactffiWithMultipartFile(arg 2) expected a string");
875
+ }
876
+
877
+ if (!info[3].IsString()) {
878
+ throw Napi::Error::New(env, "PactffiWithMultipartFile(arg 3) expected a string");
879
+ }
880
+
881
+ if (!info[4].IsString()) {
882
+ throw Napi::Error::New(env, "PactffiWithMultipartFile(arg 4) expected a string");
883
+ }
884
+
885
+ InteractionHandle interaction = info[0].As<Napi::Number>().Uint32Value();
886
+ uint32_t partNumber = info[1].As<Napi::Number>().Uint32Value();
887
+ InteractionPart part = integerToInteractionPart(env, partNumber);
888
+
889
+ std::string contentType = info[2].As<Napi::String>().Utf8Value();
890
+ std::string file = info[3].As<Napi::String>().Utf8Value();
891
+ std::string partName = info[4].As<Napi::String>().Utf8Value();
892
+
893
+ StringResult res = pactffi_with_multipart_file(interaction, part, contentType.c_str(), file.c_str(), partName.c_str());
894
+
895
+ // TODO: this will also break the https://github.com/pact-foundation/pact-js-core/tree/feat/ffi-consumer/src/consumer branch
896
+ // which expects a struct
897
+ if (res.tag == StringResult::Tag::StringResult_Ok) {
898
+ return env.Undefined();
899
+ }
900
+
901
+ std::string err = "PactffiWithMultipartFile: invalid multipart body specified:";
902
+ err += res.failed._0;
903
+
904
+ throw Napi::Error::New(env, err);
905
+ }
906
+
907
+ /**
908
+ * Configures the response for the Interaction. Returns false if the interaction or Pact can't be
909
+ * modified (i.e. the mock server for it has already started)
910
+ *
911
+ * * `status` - the response status. Defaults to 200.
912
+ *
913
+ * C interface:
914
+ *
915
+ * bool pactffi_response_status(InteractionHandle interaction, unsigned short status);
916
+ */
917
+ Napi::Value PactffiResponseStatus(const Napi::CallbackInfo& info) {
918
+ Napi::Env env = info.Env();
919
+
920
+ if (info.Length() < 2) {
921
+ throw Napi::Error::New(env, "PactffiResponseStatus received < 2 arguments");
922
+ }
923
+
924
+ if (!info[0].IsNumber()) {
925
+ throw Napi::Error::New(env, "PactffiResponseStatus(arg 0) expected a number");
926
+ }
927
+
928
+ if (!info[1].IsNumber()) {
929
+ throw Napi::Error::New(env, "PactffiResponseStatus(arg 1) expected a number");
930
+ }
931
+
932
+ InteractionHandle interaction = info[0].As<Napi::Number>().Uint32Value();
933
+ unsigned short status = info[1].As<Napi::Number>().Uint32Value();
934
+
935
+ bool res = pactffi_response_status(interaction, status);
936
+
937
+ return Napi::Boolean::New(env, res);
938
+ }
939
+
940
+ /**
941
+ * External interface to write out the message pact file. This function should
942
+ * be called if all the consumer tests have passed. The directory to write the file to is passed
943
+ * as the second parameter. If a NULL pointer is passed, the current working directory is used.
944
+ *
945
+ * If overwrite is true, the file will be overwritten with the contents of the current pact.
946
+ * Otherwise, it will be merged with any existing pact file.
947
+ *
948
+ * Returns 0 if the pact file was successfully written. Returns a positive code if the file can
949
+ * not be written, or there is no mock server running on that port or the function panics.
950
+ *
951
+ * # Errors
952
+ *
953
+ * Errors are returned as positive values.
954
+ *
955
+ * | Error | Description |
956
+ * |-------|-------------|
957
+ * | 1 | The pact file was not able to be written |
958
+ * | 2 | The message pact for the given handle was not found |
959
+ *
960
+ * C interface:
961
+ *
962
+ * int32_t pactffi_write_message_pact_file(MessagePactHandle pact,
963
+ * const char *directory,
964
+ * bool overwrite);
965
+ */
966
+
967
+ // Napi::Value PactffiWriteMessagePactFile(const Napi::CallbackInfo& info) {
968
+ // Napi::Env env = info.Env();
969
+
970
+ // if (info.Length() < 3) {
971
+ // throw Napi::Error::New(env, "PactffiWriteMessagePactFile received < 3 arguments");
972
+ // }
973
+
974
+ // if (!info[0].IsNumber()) {
975
+ // throw Napi::Error::New(env, "PactffiWriteMessagePactFile(arg 0) expected a MessagePactHandle (uint32_t)");
976
+ // }
977
+
978
+ // if (!info[1].IsString()) {
979
+ // throw Napi::Error::New(env, "PactffiWriteMessagePactFile(arg 1) expected a string");
980
+ // }
981
+
982
+ // if (!info[2].IsBoolean()) {
983
+ // throw Napi::Error::New(env, "PactffiWriteMessagePactFile(arg 2) expected a boolean");
984
+ // }
985
+
986
+ // MessagePactHandle handle = info[0].As<Napi::Number>().Uint32Value();
987
+ // std::string dir = info[1].As<Napi::String>().Utf8Value();
988
+ // bool overwrite = info[2].As<Napi::Boolean>().Value();
989
+
990
+ // bool res = pactffi_write_message_pact_file(handle, dir.c_str(), overwrite);
991
+
992
+ // return Napi::Number::New(env, res);
993
+ // }
994
+
995
+ /**
996
+ * Sets the additional metadata on the Pact file. Common uses are to add the client library details such as the name and version
997
+ *
998
+ * * `pact` - Handle to a Pact model
999
+ * * `namespace` - the top level metadat key to set any key values on
1000
+ * * `name` - the key to set
1001
+ * * `value` - the value to set
1002
+ *
1003
+ * C interface:
1004
+ *
1005
+ * void pactffi_with_message_pact_metadata(MessagePactHandle pact,
1006
+ * const char *namespace_,
1007
+ * const char *name,
1008
+ * const char *value);
1009
+ */
1010
+ // Napi::Value PactffiWithMessagePactMetadata(const Napi::CallbackInfo& info) {
1011
+ // Napi::Env env = info.Env();
1012
+
1013
+ // if (info.Length() < 4) {
1014
+ // throw Napi::Error::New(env, "PactffiWithMessagePactMetadata received < 4 arguments");
1015
+ // }
1016
+
1017
+ // if (!info[0].IsNumber()) {
1018
+ // throw Napi::Error::New(env, "PactffiWithMessagePactMetadata(arg 0) expected a MessagePactHandle (uint32_t)");
1019
+ // }
1020
+
1021
+ // if (!info[1].IsString()) {
1022
+ // throw Napi::Error::New(env, "PactffiWithMessagePactMetadata(arg 1) expected a string");
1023
+ // }
1024
+
1025
+ // if (!info[2].IsString()) {
1026
+ // throw Napi::Error::New(env, "PactffiWithMessagePactMetadata(arg 2) expected a string");
1027
+ // }
1028
+
1029
+ // if (!info[3].IsString()) {
1030
+ // throw Napi::Error::New(env, "PactffiWithMessagePactMetadata(arg 3) expected a string");
1031
+ // }
1032
+
1033
+ // MessagePactHandle handle = info[0].As<Napi::Number>().Uint32Value();
1034
+ // std::string ns = info[1].As<Napi::String>().Utf8Value();
1035
+ // std::string name = info[2].As<Napi::String>().Utf8Value();
1036
+ // std::string value = info[3].As<Napi::String>().Utf8Value();
1037
+
1038
+ // pactffi_with_message_pact_metadata(handle, ns.c_str(), name.c_str(), value.c_str());
1039
+
1040
+ // return env.Undefined();
1041
+ // }
1042
+
1043
+ /**
1044
+ * Creates a new Pact Message model and returns a handle to it.
1045
+ *
1046
+ * * `consumer_name` - The name of the consumer for the pact.
1047
+ * * `provider_name` - The name of the provider for the pact.
1048
+ *
1049
+ * Returns a new `MessagePactHandle`. The handle will need to be freed with the `pactffi_free_message_pact_handle`
1050
+ * function to release its resources.
1051
+ *
1052
+ * C interface:
1053
+ *
1054
+ * MessagePactHandle pactffi_new_message_pact(const char *consumer_name,
1055
+ * const char *provider_name);
1056
+ *
1057
+ */
1058
+ // Napi::Value PactffiNewMessagePact(const Napi::CallbackInfo& info) {
1059
+ // Napi::Env env = info.Env();
1060
+
1061
+ // if (info.Length() < 2) {
1062
+ // throw Napi::Error::New(env, "PactffiNewMessagePact received < 2 arguments");
1063
+ // }
1064
+
1065
+ // if (!info[0].IsString()) {
1066
+ // throw Napi::Error::New(env, "PactffiNewMessagePact(arg 0) expected a string");
1067
+ // }
1068
+
1069
+ // if (!info[1].IsString()) {
1070
+ // throw Napi::Error::New(env, "PactffiNewMessagePact(arg 1) expected a string");
1071
+ // }
1072
+
1073
+ // std::string consumer = info[0].As<Napi::String>().Utf8Value();
1074
+ // std::string provider = info[1].As<Napi::String>().Utf8Value();
1075
+
1076
+ // MessagePactHandle handle = pactffi_new_message_pact(consumer.c_str(), provider.c_str());
1077
+
1078
+ // return Napi::Number::New(env, handle);
1079
+ // }
1080
+
1081
+ /**
1082
+ * Creates a new V4 asynchronous message and returns a handle to it.
1083
+ *
1084
+ * * `description` - The message description. It needs to be unique for each Message.
1085
+ *
1086
+ * Returns a new `MessageHandle`.
1087
+ *
1088
+ * C interface:
1089
+ *
1090
+ * MessageHandle pactffi_new_async_message(PactHandle pact, const char *description);
1091
+ *
1092
+ */
1093
+ Napi::Value PactffiNewAsyncMessage(const Napi::CallbackInfo& info) {
1094
+ Napi::Env env = info.Env();
1095
+
1096
+ if (info.Length() < 1) {
1097
+ throw Napi::Error::New(env, "PactffiNewAsyncMessage received < 2 arguments");
1098
+ }
1099
+
1100
+ if (!info[0].IsNumber()) {
1101
+ throw Napi::Error::New(env, "PactffiNewAsyncMessage(arg 0) expected a PactHandle (uint16_t)");
1102
+ }
1103
+
1104
+ if (!info[1].IsString()) {
1105
+ throw Napi::Error::New(env, "PactffiNewAsyncMessage(arg 1) expected a string");
1106
+ }
1107
+
1108
+ PactHandle pact = info[0].As<Napi::Number>().Int32Value();
1109
+ std::string description = info[1].As<Napi::String>().Utf8Value();
1110
+
1111
+ MessageHandle handle = pactffi_new_async_message(pact, description.c_str());
1112
+
1113
+ return Napi::Number::New(env, handle);
1114
+ }
1115
+
1116
+ /**
1117
+ * Creates a new synchronous message interaction (request/response) and return a handle to it
1118
+ * * `description` - The interaction description. It needs to be unique for each interaction.
1119
+ *
1120
+ * Returns a new `InteractionHandle`.
1121
+ *
1122
+ * C interface:
1123
+ *
1124
+ * InteractionHandle pactffi_new_sync_message_interaction(PactHandle pact, const char *description);
1125
+ *
1126
+ */
1127
+ Napi::Value PactffiNewSyncMessage(const Napi::CallbackInfo& info) {
1128
+ Napi::Env env = info.Env();
1129
+
1130
+ if (info.Length() < 1) {
1131
+ throw Napi::Error::New(env, "PactffiNewSyncMessage received < 2 arguments");
1132
+ }
1133
+
1134
+ if (!info[0].IsNumber()) {
1135
+ throw Napi::Error::New(env, "PactffiNewSyncMessage(arg 0) expected a PactHandle (uint16_t)");
1136
+ }
1137
+
1138
+ if (!info[1].IsString()) {
1139
+ throw Napi::Error::New(env, "PactffiNewSyncMessage(arg 1) expected a string");
1140
+ }
1141
+
1142
+ PactHandle pact = info[0].As<Napi::Number>().Int32Value();
1143
+ std::string description = info[1].As<Napi::String>().Utf8Value();
1144
+
1145
+ InteractionHandle handle = pactffi_new_sync_message_interaction(pact, description.c_str());
1146
+
1147
+ return Napi::Number::New(env, handle);
1148
+ }
1149
+
1150
+ /**
1151
+ * Creates a new Message and returns a handle to it.
1152
+ *
1153
+ * * `description` - The message description. It needs to be unique for each Message.
1154
+ *
1155
+ * Returns a new `MessageHandle`.
1156
+ *
1157
+ * C interface:
1158
+ *
1159
+ * MessageHandle pactffi_new_message(MessagePactHandle pact, const char *description);
1160
+ *
1161
+ */
1162
+ // Napi::Value PactffiNewMessage(const Napi::CallbackInfo& info) {
1163
+ // Napi::Env env = info.Env();
1164
+
1165
+ // if (info.Length() < 2) {
1166
+ // throw Napi::Error::New(env, "PactffiNewMessage received < 2 arguments");
1167
+ // }
1168
+
1169
+ // if (!info[0].IsNumber()) {
1170
+ // throw Napi::Error::New(env, "PactffiNewMessage(arg 0) expected a MessagePactHandle (uint32_t)");
1171
+ // }
1172
+
1173
+ // if (!info[1].IsString()) {
1174
+ // throw Napi::Error::New(env, "PactffiNewMessage(arg 1) expected a string");
1175
+ // }
1176
+
1177
+ // MessagePactHandle handle = info[0].As<Napi::Number>().Uint32Value();
1178
+ // std::string desc = info[1].As<Napi::String>().Utf8Value();
1179
+
1180
+ // MessageHandle res = pactffi_new_message(handle, desc.c_str());
1181
+
1182
+ // return Napi::Number::New(env, res);
1183
+ // }
1184
+
1185
+ /**
1186
+ * Sets the description for the Message.
1187
+ *
1188
+ * * `description` - The message description. It needs to be unique for each message.
1189
+ *
1190
+ * C interface:
1191
+ *
1192
+ * void pactffi_message_expects_to_receive(MessageHandle message, const char *description);
1193
+ */
1194
+ Napi::Value PactffiMessageExpectsToReceive(const Napi::CallbackInfo& info) {
1195
+ Napi::Env env = info.Env();
1196
+
1197
+ if (info.Length() < 2) {
1198
+ throw Napi::Error::New(env, "PactffiMessageExpectsToReceive received < 2 arguments");
1199
+ }
1200
+
1201
+ if (!info[0].IsNumber()) {
1202
+ throw Napi::Error::New(env, "PactffiMessageExpectsToReceive(arg 0) expected a MessageHandle (uint32_t)");
1203
+ }
1204
+
1205
+ if (!info[1].IsString()) {
1206
+ throw Napi::Error::New(env, "PactffiMessageExpectsToReceive(arg 1) expected a string");
1207
+ }
1208
+
1209
+ MessageHandle handle = info[0].As<Napi::Number>().Uint32Value();
1210
+ std::string desc = info[1].As<Napi::String>().Utf8Value();
1211
+
1212
+ pactffi_message_expects_to_receive(handle, desc.c_str());
1213
+
1214
+ return env.Undefined();
1215
+ }
1216
+
1217
+ /**
1218
+ * Adds a provider state to the Interaction.
1219
+ *
1220
+ * C interface:
1221
+ *
1222
+ * * `description` - The provider state description. It needs to be unique for each message
1223
+ *
1224
+ * C interface:
1225
+ *
1226
+ * void pactffi_message_given(MessageHandle message, const char *description);
1227
+ */
1228
+ Napi::Value PactffiMessageGiven(const Napi::CallbackInfo& info) {
1229
+ Napi::Env env = info.Env();
1230
+
1231
+ if (info.Length() < 2) {
1232
+ throw Napi::Error::New(env, "PactffiMessageGiven received < 2 arguments");
1233
+ }
1234
+
1235
+ if (!info[0].IsNumber()) {
1236
+ throw Napi::Error::New(env, "PactffiMessageGiven(arg 0) expected a MessageHandle (uint32_t)");
1237
+ }
1238
+
1239
+ if (!info[1].IsString()) {
1240
+ throw Napi::Error::New(env, "PactffiMessageGiven(arg 1) expected a string");
1241
+ }
1242
+ MessageHandle handle = info[0].As<Napi::Number>().Uint32Value();
1243
+ std::string desc = info[1].As<Napi::String>().Utf8Value();
1244
+
1245
+ pactffi_message_given(handle, desc.c_str());
1246
+
1247
+ return env.Undefined();
1248
+ }
1249
+
1250
+ /**
1251
+ * Adds a provider state to the Message with a parameter key and value.
1252
+ *
1253
+ * * `description` - The provider state description. It needs to be unique.
1254
+ * * `name` - Parameter name.
1255
+ * * `value` - Parameter value.
1256
+ *
1257
+ * C interface:
1258
+ *
1259
+ * void pactffi_message_given_with_param(MessageHandle message,
1260
+ * const char *description,
1261
+ * const char *name,
1262
+ * const char *value);
1263
+ */
1264
+ Napi::Value PactffiMessageGivenWithParam(const Napi::CallbackInfo& info) {
1265
+ Napi::Env env = info.Env();
1266
+
1267
+ if (info.Length() < 4) {
1268
+ throw Napi::Error::New(env, "PactffiMessageGivenWithParam received < 4 arguments");
1269
+ }
1270
+
1271
+ if (!info[0].IsNumber()) {
1272
+ throw Napi::Error::New(env, "PactffiMessageGivenWithParam(arg 0) expected a MessageHandle (uint32_t)");
1273
+ }
1274
+
1275
+ if (!info[1].IsString()) {
1276
+ throw Napi::Error::New(env, "PactffiMessageGivenWithParam(arg 1) expected a string");
1277
+ }
1278
+
1279
+ if (!info[2].IsString()) {
1280
+ throw Napi::Error::New(env, "PactffiMessageGivenWithParam(arg 2) expected a string");
1281
+ }
1282
+
1283
+ if (!info[3].IsString()) {
1284
+ throw Napi::Error::New(env, "PactffiMessageGivenWithParam(arg 3) expected a string");
1285
+ }
1286
+
1287
+ MessageHandle handle = info[0].As<Napi::Number>().Uint32Value();
1288
+ std::string desc = info[1].As<Napi::String>().Utf8Value();
1289
+ std::string name = info[2].As<Napi::String>().Utf8Value();
1290
+ std::string value = info[3].As<Napi::String>().Utf8Value();
1291
+
1292
+ pactffi_message_given_with_param(handle, desc.c_str(), name.c_str(), value.c_str());
1293
+
1294
+ return env.Undefined();
1295
+ }
1296
+
1297
+ /**
1298
+ * Adds the contents of the Message.
1299
+ *
1300
+ * Accepts JSON, binary and other payload types. Binary data will be base64 encoded when serialised.
1301
+ *
1302
+ * Note: For text bodies (plain text, JSON or XML), you can pass in a C string (NULL terminated)
1303
+ * and the size of the body is not required (it will be ignored). For binary bodies, you need to
1304
+ * specify the number of bytes in the body.
1305
+ *
1306
+ * * `content_type` - The content type of the body. Defaults to `text/plain`, supports JSON structures with matchers and binary data.
1307
+ * * `body` - The body contents as bytes. For text payloads (JSON, XML, etc.), a C string can be used and matching rules can be embedded in the body.
1308
+ * * `content_type` - Expected content type (e.g. application/json, application/octet-stream)
1309
+ * * `size` - number of bytes in the message body to read. This is not required for text bodies (JSON, XML, etc.).
1310
+ *
1311
+ * C interface:
1312
+ *
1313
+ * void pactffi_message_with_contents(MessageHandle message_handle,
1314
+ * const char *content_type,
1315
+ * const uint8_t *body,
1316
+ * size_t size);
1317
+ */
1318
+ Napi::Value PactffiMessageWithContents(const Napi::CallbackInfo& info) {
1319
+ Napi::Env env = info.Env();
1320
+
1321
+ if (info.Length() < 4) {
1322
+ throw Napi::Error::New(env, "PactffiMessageWithContents received < 4 arguments");
1323
+ }
1324
+
1325
+ if (!info[0].IsNumber()) {
1326
+ throw Napi::Error::New(env, "PactffiMessageWithContents(arg 0) expected a MessageHandle (uint32_t)");
1327
+ }
1328
+
1329
+ if (!info[1].IsString()) {
1330
+ throw Napi::Error::New(env, "PactffiMessageWithContents(arg 1) expected a string");
1331
+ }
1332
+
1333
+ if (!info[2].IsBuffer()) {
1334
+ throw Napi::Error::New(env, "PactffiMessageWithContents(arg 2) expected a Buffer");
1335
+ }
1336
+
1337
+ if (!info[3].IsNumber()) {
1338
+ throw Napi::Error::New(env, "PactffiMessageWithContents(arg 3) expected a number");
1339
+ }
1340
+
1341
+ MessageHandle handle = info[0].As<Napi::Number>().Uint32Value();
1342
+ std::string contentType = info[1].As<Napi::String>().Utf8Value();
1343
+ Napi::Buffer<uint8_t> buffer = info[2].As<Napi::Buffer<uint8_t>>();
1344
+ size_t size = info[3].As<Napi::Number>().Uint32Value();
1345
+
1346
+ pactffi_message_with_contents(handle, contentType.c_str(), buffer.Data(), size);
1347
+
1348
+ return env.Undefined();
1349
+ }
1350
+
1351
+ /**
1352
+ * Adds expected metadata to the Message
1353
+ *
1354
+ * * `key` - metadata key
1355
+ * * `value` - metadata value.
1356
+ *
1357
+ * C interface:
1358
+ *
1359
+ * void pactffi_message_with_metadata(MessageHandle message_handle,
1360
+ * const char *key,
1361
+ * const char *value);
1362
+ */
1363
+ Napi::Value PactffiMessageWithMetadata(const Napi::CallbackInfo& info) {
1364
+ Napi::Env env = info.Env();
1365
+
1366
+ if (info.Length() < 3) {
1367
+ throw Napi::Error::New(env, "PactffiMessageWithMetadata received < 3 arguments");
1368
+ }
1369
+
1370
+ if (!info[0].IsNumber()) {
1371
+ throw Napi::Error::New(env, "PactffiMessageWithMetadata(arg 0) expected a MessageHandle (uint32_t)");
1372
+ }
1373
+
1374
+ if (!info[1].IsString()) {
1375
+ throw Napi::Error::New(env, "PactffiMessageWithMetadata(arg 1) expected a string");
1376
+ }
1377
+
1378
+ if (!info[2].IsString()) {
1379
+ throw Napi::Error::New(env, "PactffiMessageWithMetadata(arg 2) expected a string");
1380
+ }
1381
+
1382
+ MessageHandle handle = info[0].As<Napi::Number>().Uint32Value();
1383
+ std::string key = info[1].As<Napi::String>().Utf8Value();
1384
+ std::string value = info[2].As<Napi::String>().Utf8Value();
1385
+
1386
+ pactffi_message_with_metadata(handle, key.c_str(), value.c_str());
1387
+
1388
+ return env.Undefined();
1389
+ }
1390
+
1391
+ /**
1392
+ * Reifies the given message
1393
+ *
1394
+ * Reification is the process of stripping away any matchers, and returning the original contents.
1395
+ * NOTE: the returned string needs to be deallocated with the `free_string` function
1396
+ *
1397
+ * C interface:
1398
+ *
1399
+ * const char *pactffi_message_reify(MessageHandle message_handle);
1400
+ */
1401
+ Napi::Value PactffiMessageReify(const Napi::CallbackInfo& info) {
1402
+ Napi::Env env = info.Env();
1403
+
1404
+ if (info.Length() < 1) {
1405
+ throw Napi::Error::New(env, "PactffiMessageReify received < 1 arguments");
1406
+ }
1407
+
1408
+ if (!info[0].IsNumber()) {
1409
+ throw Napi::Error::New(env, "PactffiMessageReify(arg 0) expected a MessageHandle (uint32_t)");
1410
+ }
1411
+
1412
+ MessageHandle handle = info[0].As<Napi::Number>().Uint32Value();
1413
+
1414
+ auto res = pactffi_message_reify(handle);
1415
+
1416
+ return Napi::String::New(env, res);
1417
+ }
1418
+
1419
+ /**
1420
+ * Add a plugin to be used by the test. The plugin needs to be installed correctly for this
1421
+ * function to work.
1422
+ *
1423
+ * * `plugin_name` is the name of the plugin to load.
1424
+ * * `plugin_version` is the version of the plugin to load. It is optional, and can be NULL.
1425
+ *
1426
+ * Returns zero on success, and a positive integer value on failure.
1427
+ *
1428
+ * Note that plugins run as separate processes, so will need to be cleaned up afterwards by
1429
+ * calling `pactffi_cleanup_plugins` otherwise you have plugin processes left running.
1430
+ *
1431
+ * # Safety
1432
+ *
1433
+ * `plugin_name` must be a valid pointer to a NULL terminated string. `plugin_version` may be null,
1434
+ * and if not NULL must also be a valid pointer to a NULL terminated string.
1435
+ *
1436
+ * # Errors
1437
+ *
1438
+ * * `1` - A general panic was caught.
1439
+ * * `2` - Failed to load the plugin.
1440
+ * * `3` - Pact Handle is not valid.
1441
+ *
1442
+ * When an error errors, LAST_ERROR will contain the error message.
1443
+ *
1444
+ * C interface:
1445
+ *
1446
+ * unsigned int pactffi_using_plugin(PactHandle pact,
1447
+ * const char *plugin_name,
1448
+ * const char *plugin_version);
1449
+ */
1450
+ Napi::Value PactffiUsingPlugin(const Napi::CallbackInfo& info) {
1451
+ Napi::Env env = info.Env();
1452
+
1453
+ if (info.Length() < 3) {
1454
+ throw Napi::Error::New(env, "PactffiUsingPlugin received < 3 arguments");
1455
+ }
1456
+
1457
+ if (!info[0].IsNumber()) {
1458
+ throw Napi::Error::New(env, "PactffiUsingPlugin(arg 0) expected a PactHandle (uint16_t)");
1459
+ }
1460
+
1461
+ if (!info[1].IsString()) {
1462
+ throw Napi::Error::New(env, "PactffiUsingPlugin(arg 1) expected a string");
1463
+ }
1464
+
1465
+ if (!info[2].IsString()) {
1466
+ throw Napi::Error::New(env, "PactffiUsingPlugin(arg 2) expected a string");
1467
+ }
1468
+
1469
+ PactHandle pact = info[0].As<Napi::Number>().Int32Value();
1470
+ std::string name = info[1].As<Napi::String>().Utf8Value();
1471
+ std::string version = info[2].As<Napi::String>().Utf8Value();
1472
+
1473
+ uint16_t result = pactffi_using_plugin(pact, name.c_str(), version.c_str());
1474
+
1475
+ return Number::New(env, result);
1476
+ }
1477
+
1478
+ /**
1479
+ * Decrement the access count on any plugins that are loaded for the Pact. This will shutdown
1480
+ * any plugins that are no longer required (access count is zero).
1481
+ *
1482
+ * C interface:
1483
+ *
1484
+ * void pactffi_cleanup_plugins(PactHandle pact);
1485
+ */
1486
+ Napi::Value PactffiCleanupPlugins(const Napi::CallbackInfo& info) {
1487
+ Napi::Env env = info.Env();
1488
+
1489
+ if (info.Length() < 1) {
1490
+ throw Napi::Error::New(env, "PactffiUsingPlugin received < 1 arguments");
1491
+ }
1492
+
1493
+ if (!info[0].IsNumber()) {
1494
+ throw Napi::Error::New(env, "PactffiUsingPlugin(arg 0) expected a PactHandle (uint16_t)");
1495
+ }
1496
+
1497
+ PactHandle pact = info[0].As<Napi::Number>().Int32Value();
1498
+
1499
+ pactffi_cleanup_plugins(pact);
1500
+
1501
+ return env.Undefined();
1502
+ }
1503
+
1504
+ /**
1505
+ * Setup the interaction part using a plugin. The contents is a JSON string that will be passed on to
1506
+ * the plugin to configure the interaction part. Refer to the plugin documentation on the format
1507
+ * of the JSON contents.
1508
+ *
1509
+ * Returns zero on success, and a positive integer value on failure.
1510
+ *
1511
+ * * `interaction` - Handle to the interaction to configure.
1512
+ * * `part` - The part of the interaction to configure (request or response). It is ignored for messages.
1513
+ * * `content_type` - NULL terminated C string of the content type of the part.
1514
+ * * `contents` - NULL terminated C string of the JSON contents that gets passed to the plugin.
1515
+ *
1516
+ * # Safety
1517
+ *
1518
+ * `content_type` and `contents` must be a valid pointers to NULL terminated strings.
1519
+ *
1520
+ * # Errors
1521
+ *
1522
+ * * `1` - A general panic was caught.
1523
+ * * `2` - The mock server has already been started.
1524
+ * * `3` - The interaction handle is invalid.
1525
+ * * `4` - The content type is not valid.
1526
+ * * `5` - The contents JSON is not valid JSON.
1527
+ * * `6` - The plugin returned an error.
1528
+ *
1529
+ * When an error errors, LAST_ERROR will contain the error message.
1530
+ *
1531
+ * C interface:
1532
+ *
1533
+ * unsigned int pactffi_interaction_contents(InteractionHandle interaction,
1534
+ * InteractionPart part,
1535
+ * const char *content_type,
1536
+ * const char *contents);
1537
+ */
1538
+ Napi::Value PactffiPluginInteractionContents(const Napi::CallbackInfo& info) {
1539
+ Napi::Env env = info.Env();
1540
+
1541
+ if (info.Length() < 4) {
1542
+ throw Napi::Error::New(env, "PactffiPluginInteractionContents received < 4 arguments");
1543
+ }
1544
+
1545
+ if (!info[0].IsNumber()) {
1546
+ throw Napi::Error::New(env, "PactffiPluginInteractionContents(arg 0) expected a InteractionHandle (uint32_t)");
1547
+ }
1548
+
1549
+ if (!info[1].IsNumber()) {
1550
+ throw Napi::Error::New(env, "PactffiPluginInteractionContents(arg 1) expected an InteractionPart (uint32_t)");
1551
+ }
1552
+
1553
+ if (!info[2].IsString()) {
1554
+ throw Napi::Error::New(env, "PactffiPluginInteractionContents(arg 2) expected a string");
1555
+ }
1556
+
1557
+ if (!info[3].IsString()) {
1558
+ throw Napi::Error::New(env, "PactffiPluginInteractionContents(arg 3) expected a string");
1559
+ }
1560
+
1561
+ InteractionHandle interaction = info[0].As<Napi::Number>().Uint32Value();
1562
+ uint32_t partNumber = info[1].As<Napi::Number>().Uint32Value();
1563
+ InteractionPart part = integerToInteractionPart(env, partNumber);
1564
+ std::string contentType = info[2].As<Napi::String>().Utf8Value();
1565
+ std::string contents = info[3].As<Napi::String>().Utf8Value();
1566
+
1567
+ bool res = pactffi_interaction_contents(interaction, part, contentType.c_str(), contents.c_str());
1568
+
1569
+ return Napi::Boolean::New(env, res);
1570
+ }