@shopware-ag/app-server-sdk 1.0.1 → 1.1.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 (130) hide show
  1. package/README.md +52 -41
  2. package/dist/commonjs/context-resolver.test.d.ts +2 -0
  3. package/dist/commonjs/context-resolver.test.d.ts.map +1 -0
  4. package/dist/commonjs/context-resolver.test.js +81 -0
  5. package/dist/commonjs/context-resolver.test.js.map +1 -0
  6. package/dist/commonjs/helper/app-actions.test.d.ts +2 -0
  7. package/dist/commonjs/helper/app-actions.test.d.ts.map +1 -0
  8. package/dist/commonjs/helper/app-actions.test.js +31 -0
  9. package/dist/commonjs/helper/app-actions.test.js.map +1 -0
  10. package/dist/commonjs/http-client.test.d.ts +2 -0
  11. package/dist/commonjs/http-client.test.d.ts.map +1 -0
  12. package/dist/commonjs/http-client.test.js +71 -0
  13. package/dist/commonjs/http-client.test.js.map +1 -0
  14. package/dist/commonjs/integration/bun-sqlite.d.ts +11 -0
  15. package/dist/commonjs/integration/bun-sqlite.d.ts.map +1 -0
  16. package/dist/commonjs/integration/bun-sqlite.js +60 -0
  17. package/dist/commonjs/integration/bun-sqlite.js.map +1 -0
  18. package/dist/commonjs/integration/bun-sqlite.test.d.ts +2 -0
  19. package/dist/commonjs/integration/bun-sqlite.test.d.ts.map +1 -0
  20. package/dist/commonjs/integration/bun-sqlite.test.js +24 -0
  21. package/dist/commonjs/integration/bun-sqlite.test.js.map +1 -0
  22. package/dist/commonjs/integration/cloudflare-kv.d.ts +20 -0
  23. package/dist/commonjs/integration/cloudflare-kv.d.ts.map +1 -0
  24. package/dist/commonjs/integration/cloudflare-kv.js +49 -0
  25. package/dist/commonjs/integration/cloudflare-kv.js.map +1 -0
  26. package/dist/commonjs/integration/cloudflare.test.d.ts +2 -0
  27. package/dist/commonjs/integration/cloudflare.test.d.ts.map +1 -0
  28. package/dist/commonjs/integration/cloudflare.test.js +39 -0
  29. package/dist/commonjs/integration/cloudflare.test.js.map +1 -0
  30. package/dist/commonjs/integration/deno-kv.d.ts +18 -0
  31. package/dist/commonjs/integration/deno-kv.d.ts.map +1 -0
  32. package/dist/commonjs/integration/deno-kv.js +52 -0
  33. package/dist/commonjs/integration/deno-kv.js.map +1 -0
  34. package/dist/commonjs/integration/deno.test.d.ts +2 -0
  35. package/dist/commonjs/integration/deno.test.d.ts.map +1 -0
  36. package/dist/commonjs/integration/deno.test.js +48 -0
  37. package/dist/commonjs/integration/deno.test.js.map +1 -0
  38. package/dist/commonjs/integration/dynamodb.d.ts +13 -0
  39. package/dist/commonjs/integration/dynamodb.d.ts.map +1 -0
  40. package/dist/commonjs/integration/dynamodb.js +73 -0
  41. package/dist/commonjs/integration/dynamodb.js.map +1 -0
  42. package/dist/commonjs/integration/dynamodb.test.d.ts +2 -0
  43. package/dist/commonjs/integration/dynamodb.test.d.ts.map +1 -0
  44. package/dist/commonjs/integration/dynamodb.test.js +132 -0
  45. package/dist/commonjs/integration/dynamodb.test.js.map +1 -0
  46. package/dist/commonjs/integration/hono.d.ts +29 -0
  47. package/dist/commonjs/integration/hono.d.ts.map +1 -0
  48. package/dist/commonjs/integration/hono.js +105 -0
  49. package/dist/commonjs/integration/hono.js.map +1 -0
  50. package/dist/commonjs/integration/hono.test.d.ts +2 -0
  51. package/dist/commonjs/integration/hono.test.d.ts.map +1 -0
  52. package/dist/commonjs/integration/hono.test.js +86 -0
  53. package/dist/commonjs/integration/hono.test.js.map +1 -0
  54. package/dist/commonjs/registration.test.d.ts +2 -0
  55. package/dist/commonjs/registration.test.d.ts.map +1 -0
  56. package/dist/commonjs/registration.test.js +59 -0
  57. package/dist/commonjs/registration.test.js.map +1 -0
  58. package/dist/commonjs/repository.test.d.ts +2 -0
  59. package/dist/commonjs/repository.test.d.ts.map +1 -0
  60. package/dist/commonjs/repository.test.js +32 -0
  61. package/dist/commonjs/repository.test.js.map +1 -0
  62. package/dist/commonjs/signer.test.d.ts +2 -0
  63. package/dist/commonjs/signer.test.d.ts.map +1 -0
  64. package/dist/commonjs/signer.test.js +25 -0
  65. package/dist/commonjs/signer.test.js.map +1 -0
  66. package/dist/esm/context-resolver.test.d.ts +2 -0
  67. package/dist/esm/context-resolver.test.d.ts.map +1 -0
  68. package/dist/esm/context-resolver.test.js +79 -0
  69. package/dist/esm/context-resolver.test.js.map +1 -0
  70. package/dist/esm/helper/app-actions.test.d.ts +2 -0
  71. package/dist/esm/helper/app-actions.test.d.ts.map +1 -0
  72. package/dist/esm/helper/app-actions.test.js +29 -0
  73. package/dist/esm/helper/app-actions.test.js.map +1 -0
  74. package/dist/esm/http-client.test.d.ts +2 -0
  75. package/dist/esm/http-client.test.d.ts.map +1 -0
  76. package/dist/esm/http-client.test.js +69 -0
  77. package/dist/esm/http-client.test.js.map +1 -0
  78. package/dist/esm/integration/bun-sqlite.d.ts +11 -0
  79. package/dist/esm/integration/bun-sqlite.d.ts.map +1 -0
  80. package/dist/esm/integration/bun-sqlite.js +56 -0
  81. package/dist/esm/integration/bun-sqlite.js.map +1 -0
  82. package/dist/esm/integration/bun-sqlite.test.d.ts +2 -0
  83. package/dist/esm/integration/bun-sqlite.test.d.ts.map +1 -0
  84. package/dist/esm/integration/bun-sqlite.test.js +22 -0
  85. package/dist/esm/integration/bun-sqlite.test.js.map +1 -0
  86. package/dist/esm/integration/cloudflare-kv.d.ts +20 -0
  87. package/dist/esm/integration/cloudflare-kv.d.ts.map +1 -0
  88. package/dist/esm/integration/cloudflare-kv.js +45 -0
  89. package/dist/esm/integration/cloudflare-kv.js.map +1 -0
  90. package/dist/esm/integration/cloudflare.test.d.ts +2 -0
  91. package/dist/esm/integration/cloudflare.test.d.ts.map +1 -0
  92. package/dist/esm/integration/cloudflare.test.js +37 -0
  93. package/dist/esm/integration/cloudflare.test.js.map +1 -0
  94. package/dist/esm/integration/deno-kv.d.ts +18 -0
  95. package/dist/esm/integration/deno-kv.d.ts.map +1 -0
  96. package/dist/esm/integration/deno-kv.js +48 -0
  97. package/dist/esm/integration/deno-kv.js.map +1 -0
  98. package/dist/esm/integration/deno.test.d.ts +2 -0
  99. package/dist/esm/integration/deno.test.d.ts.map +1 -0
  100. package/dist/esm/integration/deno.test.js +46 -0
  101. package/dist/esm/integration/deno.test.js.map +1 -0
  102. package/dist/esm/integration/dynamodb.d.ts +13 -0
  103. package/dist/esm/integration/dynamodb.d.ts.map +1 -0
  104. package/dist/esm/integration/dynamodb.js +69 -0
  105. package/dist/esm/integration/dynamodb.js.map +1 -0
  106. package/dist/esm/integration/dynamodb.test.d.ts +2 -0
  107. package/dist/esm/integration/dynamodb.test.d.ts.map +1 -0
  108. package/dist/esm/integration/dynamodb.test.js +130 -0
  109. package/dist/esm/integration/dynamodb.test.js.map +1 -0
  110. package/dist/esm/integration/hono.d.ts +29 -0
  111. package/dist/esm/integration/hono.d.ts.map +1 -0
  112. package/dist/esm/integration/hono.js +102 -0
  113. package/dist/esm/integration/hono.js.map +1 -0
  114. package/dist/esm/integration/hono.test.d.ts +2 -0
  115. package/dist/esm/integration/hono.test.d.ts.map +1 -0
  116. package/dist/esm/integration/hono.test.js +84 -0
  117. package/dist/esm/integration/hono.test.js.map +1 -0
  118. package/dist/esm/registration.test.d.ts +2 -0
  119. package/dist/esm/registration.test.d.ts.map +1 -0
  120. package/dist/esm/registration.test.js +57 -0
  121. package/dist/esm/registration.test.js.map +1 -0
  122. package/dist/esm/repository.test.d.ts +2 -0
  123. package/dist/esm/repository.test.d.ts.map +1 -0
  124. package/dist/esm/repository.test.js +30 -0
  125. package/dist/esm/repository.test.js.map +1 -0
  126. package/dist/esm/signer.test.d.ts +2 -0
  127. package/dist/esm/signer.test.d.ts.map +1 -0
  128. package/dist/esm/signer.test.js +23 -0
  129. package/dist/esm/signer.test.js.map +1 -0
  130. package/package.json +142 -63
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const bun_test_1 = require("bun:test");
4
+ const hono_1 = require("hono");
5
+ const repository_js_1 = require("../repository.js");
6
+ const hono_js_1 = require("./hono.js");
7
+ (0, bun_test_1.describe)("Hono", async () => {
8
+ const repo = new repository_js_1.InMemoryShopRepository();
9
+ await repo.createShop("a", "a", "a");
10
+ (0, bun_test_1.test)("configre by functions", async () => {
11
+ const hono = new hono_1.Hono();
12
+ (0, hono_js_1.configureAppServer)(hono, {
13
+ appName: () => "test",
14
+ appSecret: () => "test",
15
+ shopRepository: () => repo,
16
+ });
17
+ const resp = await hono.fetch(new Request("http://localhost/app/register"));
18
+ (0, bun_test_1.expect)(resp.status).toBe(400);
19
+ });
20
+ (0, bun_test_1.test)("register", async () => {
21
+ const hono = new hono_1.Hono();
22
+ (0, hono_js_1.configureAppServer)(hono, {
23
+ appName: "test",
24
+ appSecret: "test",
25
+ shopRepository: repo,
26
+ });
27
+ const resp = await hono.fetch(new Request("http://localhost/app/register"));
28
+ (0, bun_test_1.expect)(resp.status).toBe(400);
29
+ });
30
+ (0, bun_test_1.test)("register: success", async () => {
31
+ const hono = new hono_1.Hono();
32
+ (0, hono_js_1.configureAppServer)(hono, {
33
+ appName: "My App",
34
+ appSecret: "my-secret",
35
+ shopRepository: repo,
36
+ });
37
+ const resp = await hono.fetch(new Request("http://localhost/app/register?shop-id=123&shop-url=https://my-shop.com&timestamp=1234567890", {
38
+ headers: new Headers({
39
+ "shopware-app-signature": "96c91f86c822e11444b7a57b54ef125ed86b1a639c5360d45c5397daa8c3f70b",
40
+ }),
41
+ }));
42
+ (0, bun_test_1.expect)(resp.status).toBe(200);
43
+ const body = (await resp.json());
44
+ (0, bun_test_1.expect)(body).toBeObject();
45
+ (0, bun_test_1.expect)(body.proof).not.toBeNull();
46
+ });
47
+ (0, bun_test_1.test)("registerConfirm", async () => {
48
+ const hono = new hono_1.Hono();
49
+ (0, hono_js_1.configureAppServer)(hono, {
50
+ appName: "test",
51
+ appSecret: "test",
52
+ shopRepository: repo,
53
+ });
54
+ const resp = await hono.fetch(new Request("http://localhost/app/register/confirm", {
55
+ method: "POST",
56
+ body: "{}",
57
+ }));
58
+ (0, bun_test_1.expect)(resp.status).toBe(400);
59
+ });
60
+ (0, bun_test_1.test)("signature failure", async () => {
61
+ const hono = new hono_1.Hono();
62
+ (0, hono_js_1.configureAppServer)(hono, {
63
+ appName: "test",
64
+ appSecret: "test",
65
+ shopRepository: repo,
66
+ });
67
+ hono.get("/app/test", (c) => c.text("ok"));
68
+ const resp = await hono.fetch(new Request("http://localhost/app/test?shopware-shop-signature=invalid&shop-id=a"));
69
+ (0, bun_test_1.expect)(resp.status).toBe(400);
70
+ (0, bun_test_1.expect)(await resp.text()).toBe('{"message":"Invalid request"}');
71
+ });
72
+ (0, bun_test_1.test)("signature success", async () => {
73
+ const hono = new hono_1.Hono();
74
+ (0, hono_js_1.configureAppServer)(hono, {
75
+ appName: "test",
76
+ appSecret: "test",
77
+ shopRepository: repo,
78
+ });
79
+ hono.get("/app/test", (c) => c.text("ok"));
80
+ const resp = await hono.fetch(new Request("http://localhost/app/test?shopware-shop-signature=8b523d99aeef5b456288fcec48236c3367a914c6b2c9fded63d81257ac019b25&shop-id=a"));
81
+ (0, bun_test_1.expect)(resp.status).toBe(200);
82
+ (0, bun_test_1.expect)(await resp.text()).toBe("ok");
83
+ (0, bun_test_1.expect)(resp.headers.get("shopware-app-signature")).toBe("4a43a105ccce57e8e38d4a1f7b3565d743b1e15fb1fec36f41fdf20164fa1c8b");
84
+ });
85
+ });
86
+ //# sourceMappingURL=hono.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hono.test.js","sourceRoot":"","sources":["../../../src/integration/hono.test.ts"],"names":[],"mappings":";;AAAA,uCAAkD;AAClD,+BAA4B;AAC5B,oDAA0D;AAC1D,uCAA+C;AAE/C,IAAA,mBAAQ,EAAC,MAAM,EAAE,KAAK,IAAI,EAAE;IAC3B,MAAM,IAAI,GAAG,IAAI,sCAAsB,EAAE,CAAC;IAE1C,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAErC,IAAA,eAAI,EAAC,uBAAuB,EAAE,KAAK,IAAI,EAAE;QACxC,MAAM,IAAI,GAAG,IAAI,WAAI,EAAE,CAAC;QAExB,IAAA,4BAAkB,EAAC,IAAI,EAAE;YACxB,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM;YACrB,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM;YACvB,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI;SAC1B,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,+BAA+B,CAAC,CAAC,CAAC;QAE5E,IAAA,iBAAM,EAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,IAAA,eAAI,EAAC,UAAU,EAAE,KAAK,IAAI,EAAE;QAC3B,MAAM,IAAI,GAAG,IAAI,WAAI,EAAE,CAAC;QAExB,IAAA,4BAAkB,EAAC,IAAI,EAAE;YACxB,OAAO,EAAE,MAAM;YACf,SAAS,EAAE,MAAM;YACjB,cAAc,EAAE,IAAI;SACpB,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,+BAA+B,CAAC,CAAC,CAAC;QAE5E,IAAA,iBAAM,EAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,IAAA,eAAI,EAAC,mBAAmB,EAAE,KAAK,IAAI,EAAE;QACpC,MAAM,IAAI,GAAG,IAAI,WAAI,EAAE,CAAC;QAExB,IAAA,4BAAkB,EAAC,IAAI,EAAE;YACxB,OAAO,EAAE,QAAQ;YACjB,SAAS,EAAE,WAAW;YACtB,cAAc,EAAE,IAAI;SACpB,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAC5B,IAAI,OAAO,CACV,6FAA6F,EAC7F;YACC,OAAO,EAAE,IAAI,OAAO,CAAC;gBACpB,wBAAwB,EACvB,kEAAkE;aACnE,CAAC;SACF,CACD,CACD,CAAC;QAEF,IAAA,iBAAM,EAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAE9B,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAsB,CAAC;QAEtD,IAAA,iBAAM,EAAC,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;QAE1B,IAAA,iBAAM,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,IAAA,eAAI,EAAC,iBAAiB,EAAE,KAAK,IAAI,EAAE;QAClC,MAAM,IAAI,GAAG,IAAI,WAAI,EAAE,CAAC;QAExB,IAAA,4BAAkB,EAAC,IAAI,EAAE;YACxB,OAAO,EAAE,MAAM;YACf,SAAS,EAAE,MAAM;YACjB,cAAc,EAAE,IAAI;SACpB,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAC5B,IAAI,OAAO,CAAC,uCAAuC,EAAE;YACpD,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI;SACV,CAAC,CACF,CAAC;QAEF,IAAA,iBAAM,EAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,IAAA,eAAI,EAAC,mBAAmB,EAAE,KAAK,IAAI,EAAE;QACpC,MAAM,IAAI,GAAG,IAAI,WAAI,EAAE,CAAC;QAExB,IAAA,4BAAkB,EAAC,IAAI,EAAE;YACxB,OAAO,EAAE,MAAM;YACf,SAAS,EAAE,MAAM;YACjB,cAAc,EAAE,IAAI;SACpB,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAE3C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAC5B,IAAI,OAAO,CACV,qEAAqE,CACrE,CACD,CAAC;QAEF,IAAA,iBAAM,EAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAA,iBAAM,EAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,IAAA,eAAI,EAAC,mBAAmB,EAAE,KAAK,IAAI,EAAE;QACpC,MAAM,IAAI,GAAG,IAAI,WAAI,EAAE,CAAC;QAExB,IAAA,4BAAkB,EAAC,IAAI,EAAE;YACxB,OAAO,EAAE,MAAM;YACf,SAAS,EAAE,MAAM;YACjB,cAAc,EAAE,IAAI;SACpB,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAE3C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAC5B,IAAI,OAAO,CACV,8HAA8H,CAC9H,CACD,CAAC;QAEF,IAAA,iBAAM,EAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAA,iBAAM,EAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,IAAA,iBAAM,EAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC,CAAC,IAAI,CACtD,kEAAkE,CAClE,CAAC;IACH,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, test } from \"bun:test\";\nimport { Hono } from \"hono\";\nimport { InMemoryShopRepository } from \"../repository.js\";\nimport { configureAppServer } from \"./hono.js\";\n\ndescribe(\"Hono\", async () => {\n\tconst repo = new InMemoryShopRepository();\n\n\tawait repo.createShop(\"a\", \"a\", \"a\");\n\n\ttest(\"configre by functions\", async () => {\n\t\tconst hono = new Hono();\n\n\t\tconfigureAppServer(hono, {\n\t\t\tappName: () => \"test\",\n\t\t\tappSecret: () => \"test\",\n\t\t\tshopRepository: () => repo,\n\t\t});\n\n\t\tconst resp = await hono.fetch(new Request(\"http://localhost/app/register\"));\n\n\t\texpect(resp.status).toBe(400);\n\t});\n\n\ttest(\"register\", async () => {\n\t\tconst hono = new Hono();\n\n\t\tconfigureAppServer(hono, {\n\t\t\tappName: \"test\",\n\t\t\tappSecret: \"test\",\n\t\t\tshopRepository: repo,\n\t\t});\n\n\t\tconst resp = await hono.fetch(new Request(\"http://localhost/app/register\"));\n\n\t\texpect(resp.status).toBe(400);\n\t});\n\n\ttest(\"register: success\", async () => {\n\t\tconst hono = new Hono();\n\n\t\tconfigureAppServer(hono, {\n\t\t\tappName: \"My App\",\n\t\t\tappSecret: \"my-secret\",\n\t\t\tshopRepository: repo,\n\t\t});\n\n\t\tconst resp = await hono.fetch(\n\t\t\tnew Request(\n\t\t\t\t\"http://localhost/app/register?shop-id=123&shop-url=https://my-shop.com&timestamp=1234567890\",\n\t\t\t\t{\n\t\t\t\t\theaders: new Headers({\n\t\t\t\t\t\t\"shopware-app-signature\":\n\t\t\t\t\t\t\t\"96c91f86c822e11444b7a57b54ef125ed86b1a639c5360d45c5397daa8c3f70b\",\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t),\n\t\t);\n\n\t\texpect(resp.status).toBe(200);\n\n\t\tconst body = (await resp.json()) as { proof: string };\n\n\t\texpect(body).toBeObject();\n\n\t\texpect(body.proof).not.toBeNull();\n\t});\n\n\ttest(\"registerConfirm\", async () => {\n\t\tconst hono = new Hono();\n\n\t\tconfigureAppServer(hono, {\n\t\t\tappName: \"test\",\n\t\t\tappSecret: \"test\",\n\t\t\tshopRepository: repo,\n\t\t});\n\n\t\tconst resp = await hono.fetch(\n\t\t\tnew Request(\"http://localhost/app/register/confirm\", {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: \"{}\",\n\t\t\t}),\n\t\t);\n\n\t\texpect(resp.status).toBe(400);\n\t});\n\n\ttest(\"signature failure\", async () => {\n\t\tconst hono = new Hono();\n\n\t\tconfigureAppServer(hono, {\n\t\t\tappName: \"test\",\n\t\t\tappSecret: \"test\",\n\t\t\tshopRepository: repo,\n\t\t});\n\n\t\thono.get(\"/app/test\", (c) => c.text(\"ok\"));\n\n\t\tconst resp = await hono.fetch(\n\t\t\tnew Request(\n\t\t\t\t\"http://localhost/app/test?shopware-shop-signature=invalid&shop-id=a\",\n\t\t\t),\n\t\t);\n\n\t\texpect(resp.status).toBe(400);\n\t\texpect(await resp.text()).toBe('{\"message\":\"Invalid request\"}');\n\t});\n\n\ttest(\"signature success\", async () => {\n\t\tconst hono = new Hono();\n\n\t\tconfigureAppServer(hono, {\n\t\t\tappName: \"test\",\n\t\t\tappSecret: \"test\",\n\t\t\tshopRepository: repo,\n\t\t});\n\n\t\thono.get(\"/app/test\", (c) => c.text(\"ok\"));\n\n\t\tconst resp = await hono.fetch(\n\t\t\tnew Request(\n\t\t\t\t\"http://localhost/app/test?shopware-shop-signature=8b523d99aeef5b456288fcec48236c3367a914c6b2c9fded63d81257ac019b25&shop-id=a\",\n\t\t\t),\n\t\t);\n\n\t\texpect(resp.status).toBe(200);\n\t\texpect(await resp.text()).toBe(\"ok\");\n\t\texpect(resp.headers.get(\"shopware-app-signature\")).toBe(\n\t\t\t\"4a43a105ccce57e8e38d4a1f7b3565d743b1e15fb1fec36f41fdf20164fa1c8b\",\n\t\t);\n\t});\n});\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=registration.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registration.test.d.ts","sourceRoot":"","sources":["../../src/registration.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const bun_test_1 = require("bun:test");
4
+ const app_js_1 = require("../src/app.js");
5
+ const repository_js_1 = require("../src/repository.js");
6
+ (0, bun_test_1.describe)("Registration", async () => {
7
+ const app = new app_js_1.AppServer({ appName: "test", appSecret: "test", authorizeCallbackUrl: "test" }, new repository_js_1.InMemoryShopRepository());
8
+ (0, bun_test_1.test)("authorize: invalid request", async () => {
9
+ const resp = await app.registration.authorize(new Request("http://localhost"));
10
+ (0, bun_test_1.expect)(resp.status).toBe(400);
11
+ });
12
+ (0, bun_test_1.test)("authorize: invalid signature", async () => {
13
+ const resp = await app.registration.authorize(new Request("http://localhost?shop-url=test&shop-id=test&timestamp=test", { headers: new Headers({ "shopware-app-signature": "test" }) }));
14
+ (0, bun_test_1.expect)(resp.status).toBe(401);
15
+ });
16
+ (0, bun_test_1.test)("authorize: valid request", async () => {
17
+ app.signer.verify = bun_test_1.jest.fn().mockResolvedValue(true);
18
+ const resp = await app.registration.authorize(new Request("http://localhost?shop-url=test&shop-id=test&timestamp=test", { headers: new Headers({ "shopware-app-signature": "test" }) }));
19
+ (0, bun_test_1.expect)(resp.status).toBe(200);
20
+ });
21
+ (0, bun_test_1.test)("authorizeCallback: invalid request", async () => {
22
+ const resp = await app.registration.authorizeCallback(new Request("http://localhost", { body: "{}" }));
23
+ (0, bun_test_1.expect)(resp.status).toBe(400);
24
+ });
25
+ (0, bun_test_1.test)("authorizeCallback: shop does not exist", async () => {
26
+ const resp = await app.registration.authorizeCallback(new Request("http://localhost", {
27
+ body: '{"shopId": "test", "apiKey": "test", "secretKey": "test"}',
28
+ }));
29
+ (0, bun_test_1.expect)(resp.status).toBe(400);
30
+ });
31
+ (0, bun_test_1.test)("activateShop", async () => {
32
+ await app.repository.createShop("1", "http://localhost", "test");
33
+ const shop = await app.repository.getShopById("1");
34
+ shop?.setShopActive(false);
35
+ app.contextResolver.fromAPI = bun_test_1.jest.fn().mockResolvedValue({ shop });
36
+ const resp = await app.registration.activate(new Request("http://localhost", { body: '{"source": {"shopId": "1"}}' }));
37
+ (0, bun_test_1.expect)(resp.status).toBe(204);
38
+ (0, bun_test_1.expect)(shop?.getShopActive()).toBe(true);
39
+ });
40
+ (0, bun_test_1.test)("deactivateShop", async () => {
41
+ await app.repository.createShop("1", "http://localhost", "test");
42
+ const shop = await app.repository.getShopById("1");
43
+ shop?.setShopActive(true);
44
+ app.contextResolver.fromAPI = bun_test_1.jest.fn().mockResolvedValue({ shop });
45
+ const resp = await app.registration.deactivate(new Request("http://localhost", { body: '{"source": {"shopId": "1"}}' }));
46
+ (0, bun_test_1.expect)(resp.status).toBe(204);
47
+ (0, bun_test_1.expect)(shop?.getShopActive()).toBe(false);
48
+ });
49
+ (0, bun_test_1.test)("deletedShop", async () => {
50
+ await app.repository.createShop("1", "http://localhost", "test");
51
+ const shop = await app.repository.getShopById("1");
52
+ (0, bun_test_1.expect)(shop).not.toBeNull();
53
+ app.contextResolver.fromAPI = bun_test_1.jest.fn().mockResolvedValue({ shop });
54
+ const resp = await app.registration.delete(new Request("http://localhost", { body: '{"source": {"shopId": "1"}}' }));
55
+ (0, bun_test_1.expect)(resp.status).toBe(204);
56
+ (0, bun_test_1.expect)(app.repository.getShopById("1")).resolves.toBeNull();
57
+ });
58
+ });
59
+ //# sourceMappingURL=registration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registration.test.js","sourceRoot":"","sources":["../../src/registration.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, jest, test } from \"bun:test\";\nimport { AppServer } from \"../src/app.js\";\nimport { InMemoryShopRepository, SimpleShop } from \"../src/repository.js\";\n\ndescribe(\"Registration\", async () => {\n\tconst app = new AppServer(\n\t\t{ appName: \"test\", appSecret: \"test\", authorizeCallbackUrl: \"test\" },\n\t\tnew InMemoryShopRepository(),\n\t);\n\n\ttest(\"authorize: invalid request\", async () => {\n\t\tconst resp = await app.registration.authorize(\n\t\t\tnew Request(\"http://localhost\"),\n\t\t);\n\n\t\texpect(resp.status).toBe(400);\n\t});\n\n\ttest(\"authorize: invalid signature\", async () => {\n\t\tconst resp = await app.registration.authorize(\n\t\t\tnew Request(\n\t\t\t\t\"http://localhost?shop-url=test&shop-id=test&timestamp=test\",\n\t\t\t\t{ headers: new Headers({ \"shopware-app-signature\": \"test\" }) },\n\t\t\t),\n\t\t);\n\n\t\texpect(resp.status).toBe(401);\n\t});\n\n\ttest(\"authorize: valid request\", async () => {\n\t\tapp.signer.verify = jest.fn().mockResolvedValue(true);\n\n\t\tconst resp = await app.registration.authorize(\n\t\t\tnew Request(\n\t\t\t\t\"http://localhost?shop-url=test&shop-id=test&timestamp=test\",\n\t\t\t\t{ headers: new Headers({ \"shopware-app-signature\": \"test\" }) },\n\t\t\t),\n\t\t);\n\n\t\texpect(resp.status).toBe(200);\n\t});\n\n\ttest(\"authorizeCallback: invalid request\", async () => {\n\t\tconst resp = await app.registration.authorizeCallback(\n\t\t\tnew Request(\"http://localhost\", { body: \"{}\" }),\n\t\t);\n\n\t\texpect(resp.status).toBe(400);\n\t});\n\n\ttest(\"authorizeCallback: shop does not exist\", async () => {\n\t\tconst resp = await app.registration.authorizeCallback(\n\t\t\tnew Request(\"http://localhost\", {\n\t\t\t\tbody: '{\"shopId\": \"test\", \"apiKey\": \"test\", \"secretKey\": \"test\"}',\n\t\t\t}),\n\t\t);\n\n\t\texpect(resp.status).toBe(400);\n\t});\n\n\ttest(\"activateShop\", async () => {\n\t\tawait app.repository.createShop(\"1\", \"http://localhost\", \"test\");\n\n\t\tconst shop = await app.repository.getShopById(\"1\");\n\n\t\tshop?.setShopActive(false);\n\n\t\tapp.contextResolver.fromAPI = jest.fn().mockResolvedValue({ shop });\n\n\t\tconst resp = await app.registration.activate(\n\t\t\tnew Request(\"http://localhost\", { body: '{\"source\": {\"shopId\": \"1\"}}' }),\n\t\t);\n\n\t\texpect(resp.status).toBe(204);\n\n\t\texpect(shop?.getShopActive()).toBe(true);\n\t});\n\n\ttest(\"deactivateShop\", async () => {\n\t\tawait app.repository.createShop(\"1\", \"http://localhost\", \"test\");\n\n\t\tconst shop = await app.repository.getShopById(\"1\");\n\n\t\tshop?.setShopActive(true);\n\n\t\tapp.contextResolver.fromAPI = jest.fn().mockResolvedValue({ shop });\n\n\t\tconst resp = await app.registration.deactivate(\n\t\t\tnew Request(\"http://localhost\", { body: '{\"source\": {\"shopId\": \"1\"}}' }),\n\t\t);\n\n\t\texpect(resp.status).toBe(204);\n\n\t\texpect(shop?.getShopActive()).toBe(false);\n\t});\n\n\ttest(\"deletedShop\", async () => {\n\t\tawait app.repository.createShop(\"1\", \"http://localhost\", \"test\");\n\n\t\tconst shop = await app.repository.getShopById(\"1\");\n\n\t\texpect(shop).not.toBeNull();\n\n\t\tapp.contextResolver.fromAPI = jest.fn().mockResolvedValue({ shop });\n\n\t\tconst resp = await app.registration.delete(\n\t\t\tnew Request(\"http://localhost\", { body: '{\"source\": {\"shopId\": \"1\"}}' }),\n\t\t);\n\n\t\texpect(resp.status).toBe(204);\n\n\t\texpect(app.repository.getShopById(\"1\")).resolves.toBeNull();\n\t});\n});\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=repository.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository.test.d.ts","sourceRoot":"","sources":["../../src/repository.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const bun_test_1 = require("bun:test");
4
+ const repository_js_1 = require("../src/repository.js");
5
+ (0, bun_test_1.describe)("Repository", async () => {
6
+ (0, bun_test_1.test)("SimpleShop", async () => {
7
+ const shop = new repository_js_1.SimpleShop("test", "test", "test");
8
+ (0, bun_test_1.expect)(shop.getShopId()).toBe("test");
9
+ (0, bun_test_1.expect)(shop.getShopUrl()).toBe("test");
10
+ (0, bun_test_1.expect)(shop.getShopSecret()).toBe("test");
11
+ (0, bun_test_1.expect)(shop.getShopClientId()).toBeNull();
12
+ (0, bun_test_1.expect)(shop.getShopClientSecret()).toBeNull();
13
+ (0, bun_test_1.expect)(shop.getShopActive()).toBe(true);
14
+ shop.setShopActive(false);
15
+ (0, bun_test_1.expect)(shop.getShopActive()).toBe(false);
16
+ shop.setShopCredentials("test", "test");
17
+ (0, bun_test_1.expect)(shop.getShopClientId()).toBe("test");
18
+ (0, bun_test_1.expect)(shop.getShopClientSecret()).toBe("test");
19
+ });
20
+ (0, bun_test_1.test)("InMemoryShopRepository", async () => {
21
+ const shop = new repository_js_1.SimpleShop("test", "test", "test");
22
+ const repository = new repository_js_1.InMemoryShopRepository();
23
+ (0, bun_test_1.expect)(repository.getShopById("test")).resolves.toBeNull();
24
+ await repository.createShop("test", "test", "test");
25
+ (0, bun_test_1.expect)(repository.getShopById("test")).resolves.toBeInstanceOf(repository_js_1.SimpleShop);
26
+ await repository.deleteShop("test");
27
+ (0, bun_test_1.expect)(repository.getShopById("test")).resolves.toBeNull();
28
+ await repository.updateShop(shop);
29
+ (0, bun_test_1.expect)(repository.getShopById("test")).resolves.toBe(shop);
30
+ });
31
+ });
32
+ //# sourceMappingURL=repository.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository.test.js","sourceRoot":"","sources":["../../src/repository.test.ts"],"names":[],"mappings":";;AAAA,uCAAkD;AAClD,wDAA0E;AAE1E,IAAA,mBAAQ,EAAC,YAAY,EAAE,KAAK,IAAI,EAAE;IACjC,IAAA,eAAI,EAAC,YAAY,EAAE,KAAK,IAAI,EAAE;QAC7B,MAAM,IAAI,GAAG,IAAI,0BAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QAEpD,IAAA,iBAAM,EAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtC,IAAA,iBAAM,EAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvC,IAAA,iBAAM,EAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAA,iBAAM,EAAC,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC1C,IAAA,iBAAM,EAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC9C,IAAA,iBAAM,EAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAExC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAE1B,IAAA,iBAAM,EAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEzC,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAExC,IAAA,iBAAM,EAAC,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5C,IAAA,iBAAM,EAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,IAAA,eAAI,EAAC,wBAAwB,EAAE,KAAK,IAAI,EAAE;QACzC,MAAM,IAAI,GAAG,IAAI,0BAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QAEpD,MAAM,UAAU,GAAG,IAAI,sCAAsB,EAAE,CAAC;QAEhD,IAAA,iBAAM,EAAC,UAAU,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;QAE3D,MAAM,UAAU,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QAEpD,IAAA,iBAAM,EAAC,UAAU,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,0BAAU,CAAC,CAAC;QAE3E,MAAM,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAEpC,IAAA,iBAAM,EAAC,UAAU,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;QAE3D,MAAM,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAElC,IAAA,iBAAM,EAAC,UAAU,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, test } from \"bun:test\";\nimport { InMemoryShopRepository, SimpleShop } from \"../src/repository.js\";\n\ndescribe(\"Repository\", async () => {\n\ttest(\"SimpleShop\", async () => {\n\t\tconst shop = new SimpleShop(\"test\", \"test\", \"test\");\n\n\t\texpect(shop.getShopId()).toBe(\"test\");\n\t\texpect(shop.getShopUrl()).toBe(\"test\");\n\t\texpect(shop.getShopSecret()).toBe(\"test\");\n\t\texpect(shop.getShopClientId()).toBeNull();\n\t\texpect(shop.getShopClientSecret()).toBeNull();\n\t\texpect(shop.getShopActive()).toBe(true);\n\n\t\tshop.setShopActive(false);\n\n\t\texpect(shop.getShopActive()).toBe(false);\n\n\t\tshop.setShopCredentials(\"test\", \"test\");\n\n\t\texpect(shop.getShopClientId()).toBe(\"test\");\n\t\texpect(shop.getShopClientSecret()).toBe(\"test\");\n\t});\n\n\ttest(\"InMemoryShopRepository\", async () => {\n\t\tconst shop = new SimpleShop(\"test\", \"test\", \"test\");\n\n\t\tconst repository = new InMemoryShopRepository();\n\n\t\texpect(repository.getShopById(\"test\")).resolves.toBeNull();\n\n\t\tawait repository.createShop(\"test\", \"test\", \"test\");\n\n\t\texpect(repository.getShopById(\"test\")).resolves.toBeInstanceOf(SimpleShop);\n\n\t\tawait repository.deleteShop(\"test\");\n\n\t\texpect(repository.getShopById(\"test\")).resolves.toBeNull();\n\n\t\tawait repository.updateShop(shop);\n\n\t\texpect(repository.getShopById(\"test\")).resolves.toBe(shop);\n\t});\n});\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=signer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signer.test.d.ts","sourceRoot":"","sources":["../../src/signer.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const bun_test_1 = require("bun:test");
4
+ const signer_js_1 = require("../src/signer.js");
5
+ (0, bun_test_1.describe)("Signer", () => {
6
+ (0, bun_test_1.test)("signResponse", async () => {
7
+ const signer = new signer_js_1.WebCryptoHmacSigner();
8
+ const response = new Response("Hello, World!");
9
+ await signer.signResponse(response, "test");
10
+ (0, bun_test_1.expect)(response.headers.get("shopware-app-signature")).toBe("52589bd80ccfa4acbb3f9512dfaf4f700fa5195008aae0b77a9e47dcca75beac");
11
+ await signer.signResponse(response, "test");
12
+ (0, bun_test_1.expect)(response.headers.get("shopware-app-signature")).toBe("52589bd80ccfa4acbb3f9512dfaf4f700fa5195008aae0b77a9e47dcca75beac");
13
+ });
14
+ (0, bun_test_1.test)("sign", async () => {
15
+ const signer = new signer_js_1.WebCryptoHmacSigner();
16
+ (0, bun_test_1.expect)(await signer.sign("shop-id=blaa", "test")).toBe("f2cb1044ac5a2cb807e1942b06433d23d66bcf7dfad1095b286203e5c1f39cb6");
17
+ });
18
+ (0, bun_test_1.test)("verifyGetRequest", async () => {
19
+ const signer = new signer_js_1.WebCryptoHmacSigner();
20
+ (0, bun_test_1.expect)(signer.verifyGetRequest(new Request("https://example.com/?shopware-shop-signature=52589bd80ccfa4acbb3f9512dfaf4f700fa5195008aae0b77a9e47dcca75beac"), "test")).rejects.toThrowError("Missing query parameters to verify the GET request");
21
+ (0, bun_test_1.expect)(signer.verifyGetRequest(new Request("https://example.com/?shopware-shop-signature=52589bd80ccfa4acbb3f9512dfaf4f700fa5195008aae0b77a9e47dcca75beac&a=1"), "test")).rejects.toThrowError("Invalid signature");
22
+ (0, bun_test_1.expect)(signer.verifyGetRequest(new Request("https://example.com/?shopware-shop-signature=f2cb1044ac5a2cb807e1942b06433d23d66bcf7dfad1095b286203e5c1f39cb6&shop-id=blaa"), "test")).resolves.pass();
23
+ });
24
+ });
25
+ //# sourceMappingURL=signer.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signer.test.js","sourceRoot":"","sources":["../../src/signer.test.ts"],"names":[],"mappings":";;AAAA,uCAAkD;AAClD,gDAAuD;AAEvD,IAAA,mBAAQ,EAAC,QAAQ,EAAE,GAAG,EAAE;IACvB,IAAA,eAAI,EAAC,cAAc,EAAE,KAAK,IAAI,EAAE;QAC/B,MAAM,MAAM,GAAG,IAAI,+BAAmB,EAAE,CAAC;QAEzC,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,eAAe,CAAC,CAAC;QAE/C,MAAM,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAE5C,IAAA,iBAAM,EAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC,CAAC,IAAI,CAC1D,kEAAkE,CAClE,CAAC;QAEF,MAAM,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAE5C,IAAA,iBAAM,EAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC,CAAC,IAAI,CAC1D,kEAAkE,CAClE,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAA,eAAI,EAAC,MAAM,EAAE,KAAK,IAAI,EAAE;QACvB,MAAM,MAAM,GAAG,IAAI,+BAAmB,EAAE,CAAC;QAEzC,IAAA,iBAAM,EAAC,MAAM,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CACrD,kEAAkE,CAClE,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAA,eAAI,EAAC,kBAAkB,EAAE,KAAK,IAAI,EAAE;QACnC,MAAM,MAAM,GAAG,IAAI,+BAAmB,EAAE,CAAC;QAEzC,IAAA,iBAAM,EACL,MAAM,CAAC,gBAAgB,CACtB,IAAI,OAAO,CACV,+GAA+G,CAC/G,EACD,MAAM,CACN,CACD,CAAC,OAAO,CAAC,YAAY,CACrB,oDAAoD,CACpD,CAAC;QACF,IAAA,iBAAM,EACL,MAAM,CAAC,gBAAgB,CACtB,IAAI,OAAO,CACV,mHAAmH,CACnH,EACD,MAAM,CACN,CACD,CAAC,OAAO,CAAC,YAAY,CAAC,mBAAmB,CAAC,CAAC;QAE5C,IAAA,iBAAM,EACL,MAAM,CAAC,gBAAgB,CACtB,IAAI,OAAO,CACV,4HAA4H,CAC5H,EACD,MAAM,CACN,CACD,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IACnB,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, test } from \"bun:test\";\nimport { WebCryptoHmacSigner } from \"../src/signer.js\";\n\ndescribe(\"Signer\", () => {\n\ttest(\"signResponse\", async () => {\n\t\tconst signer = new WebCryptoHmacSigner();\n\n\t\tconst response = new Response(\"Hello, World!\");\n\n\t\tawait signer.signResponse(response, \"test\");\n\n\t\texpect(response.headers.get(\"shopware-app-signature\")).toBe(\n\t\t\t\"52589bd80ccfa4acbb3f9512dfaf4f700fa5195008aae0b77a9e47dcca75beac\",\n\t\t);\n\n\t\tawait signer.signResponse(response, \"test\");\n\n\t\texpect(response.headers.get(\"shopware-app-signature\")).toBe(\n\t\t\t\"52589bd80ccfa4acbb3f9512dfaf4f700fa5195008aae0b77a9e47dcca75beac\",\n\t\t);\n\t});\n\n\ttest(\"sign\", async () => {\n\t\tconst signer = new WebCryptoHmacSigner();\n\n\t\texpect(await signer.sign(\"shop-id=blaa\", \"test\")).toBe(\n\t\t\t\"f2cb1044ac5a2cb807e1942b06433d23d66bcf7dfad1095b286203e5c1f39cb6\",\n\t\t);\n\t});\n\n\ttest(\"verifyGetRequest\", async () => {\n\t\tconst signer = new WebCryptoHmacSigner();\n\n\t\texpect(\n\t\t\tsigner.verifyGetRequest(\n\t\t\t\tnew Request(\n\t\t\t\t\t\"https://example.com/?shopware-shop-signature=52589bd80ccfa4acbb3f9512dfaf4f700fa5195008aae0b77a9e47dcca75beac\",\n\t\t\t\t),\n\t\t\t\t\"test\",\n\t\t\t),\n\t\t).rejects.toThrowError(\n\t\t\t\"Missing query parameters to verify the GET request\",\n\t\t);\n\t\texpect(\n\t\t\tsigner.verifyGetRequest(\n\t\t\t\tnew Request(\n\t\t\t\t\t\"https://example.com/?shopware-shop-signature=52589bd80ccfa4acbb3f9512dfaf4f700fa5195008aae0b77a9e47dcca75beac&a=1\",\n\t\t\t\t),\n\t\t\t\t\"test\",\n\t\t\t),\n\t\t).rejects.toThrowError(\"Invalid signature\");\n\n\t\texpect(\n\t\t\tsigner.verifyGetRequest(\n\t\t\t\tnew Request(\n\t\t\t\t\t\"https://example.com/?shopware-shop-signature=f2cb1044ac5a2cb807e1942b06433d23d66bcf7dfad1095b286203e5c1f39cb6&shop-id=blaa\",\n\t\t\t\t),\n\t\t\t\t\"test\",\n\t\t\t),\n\t\t).resolves.pass();\n\t});\n});\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=context-resolver.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-resolver.test.d.ts","sourceRoot":"","sources":["../../src/context-resolver.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,79 @@
1
+ import { describe, expect, jest, test } from "bun:test";
2
+ import { AppServer } from "../src/app.js";
3
+ import { ContextResolver } from "../src/context-resolver.js";
4
+ import { InMemoryShopRepository } from "../src/repository.js";
5
+ describe("Context Resolver", async () => {
6
+ const app = new AppServer({
7
+ appName: "test",
8
+ appSecret: "test",
9
+ authorizeCallbackUrl: "test",
10
+ }, new InMemoryShopRepository());
11
+ await app.repository.createShop("blaa", "test", "test");
12
+ const contextResolver = new ContextResolver(app);
13
+ test("fromBrowser: shop does not exist", async () => {
14
+ expect(contextResolver.fromBrowser(new Request("https://example.com/?shop-id=test&shopware-shop-signature=aaa"))).rejects.toThrowError("Cannot find shop by id test");
15
+ });
16
+ test("fromBrowser: missing header", async () => {
17
+ expect(contextResolver.fromBrowser(new Request("https://example.com/?shop-id=blaa"))).rejects.toThrowError("Missing shopware-shop-signature query parameter");
18
+ });
19
+ test("fromBrowser: shop exists", async () => {
20
+ app.signer.verifyGetRequest = jest.fn().mockResolvedValue(true);
21
+ const context = await contextResolver.fromBrowser(new Request("https://example.com/?shop-id=blaa&shopware-shop-signature=aaa"));
22
+ expect(context.payload).toEqual({
23
+ "shop-id": "blaa",
24
+ "shopware-shop-signature": "aaa",
25
+ });
26
+ });
27
+ test("fromSource: missing signature header", async () => {
28
+ expect(contextResolver.fromAPI(new Request("https://example.com/", {
29
+ body: JSON.stringify({
30
+ source: {
31
+ shopId: "blaa",
32
+ },
33
+ }),
34
+ }))).rejects.toThrowError("Missing shopware-shop-signature header");
35
+ });
36
+ test("fromSource: shop does not exists", async () => {
37
+ expect(contextResolver.fromAPI(new Request("https://example.com/", {
38
+ headers: {
39
+ "shopware-shop-signature": "aaa",
40
+ },
41
+ body: JSON.stringify({
42
+ source: {
43
+ shopId: "test",
44
+ },
45
+ }),
46
+ }))).rejects.toThrowError("Cannot find shop by id test");
47
+ });
48
+ test("fromSource: invalid signature", async () => {
49
+ expect(contextResolver.fromAPI(new Request("https://example.com/", {
50
+ headers: {
51
+ "shopware-shop-signature": "aaa",
52
+ },
53
+ body: JSON.stringify({
54
+ source: {
55
+ shopId: "blaa",
56
+ },
57
+ }),
58
+ }))).rejects.toThrowError("Invalid signature");
59
+ });
60
+ test("fromSource: resolved", async () => {
61
+ app.signer.verify = jest.fn().mockResolvedValue(true);
62
+ const ctx = await contextResolver.fromAPI(new Request("https://example.com/", {
63
+ headers: {
64
+ "shopware-shop-signature": "aaa",
65
+ },
66
+ body: JSON.stringify({
67
+ source: {
68
+ shopId: "blaa",
69
+ },
70
+ }),
71
+ }));
72
+ expect(ctx.payload).toEqual({
73
+ source: {
74
+ shopId: "blaa",
75
+ },
76
+ });
77
+ });
78
+ });
79
+ //# sourceMappingURL=context-resolver.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-resolver.test.js","sourceRoot":"","sources":["../../src/context-resolver.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, jest, test } from \"bun:test\";\nimport { AppServer } from \"../src/app.js\";\nimport { ContextResolver } from \"../src/context-resolver.js\";\nimport { InMemoryShopRepository, SimpleShop } from \"../src/repository.js\";\n\ndescribe(\"Context Resolver\", async () => {\n\tconst app = new AppServer(\n\t\t{\n\t\t\tappName: \"test\",\n\t\t\tappSecret: \"test\",\n\t\t\tauthorizeCallbackUrl: \"test\",\n\t\t},\n\t\tnew InMemoryShopRepository(),\n\t);\n\n\tawait app.repository.createShop(\"blaa\", \"test\", \"test\");\n\n\tconst contextResolver = new ContextResolver(app);\n\n\ttest(\"fromBrowser: shop does not exist\", async () => {\n\t\texpect(\n\t\t\tcontextResolver.fromBrowser(\n\t\t\t\tnew Request(\n\t\t\t\t\t\"https://example.com/?shop-id=test&shopware-shop-signature=aaa\",\n\t\t\t\t),\n\t\t\t),\n\t\t).rejects.toThrowError(\"Cannot find shop by id test\");\n\t});\n\n\ttest(\"fromBrowser: missing header\", async () => {\n\t\texpect(\n\t\t\tcontextResolver.fromBrowser(\n\t\t\t\tnew Request(\"https://example.com/?shop-id=blaa\"),\n\t\t\t),\n\t\t).rejects.toThrowError(\"Missing shopware-shop-signature query parameter\");\n\t});\n\n\ttest(\"fromBrowser: shop exists\", async () => {\n\t\tapp.signer.verifyGetRequest = jest.fn().mockResolvedValue(true);\n\n\t\tconst context = await contextResolver.fromBrowser(\n\t\t\tnew Request(\n\t\t\t\t\"https://example.com/?shop-id=blaa&shopware-shop-signature=aaa\",\n\t\t\t),\n\t\t);\n\n\t\texpect(context.payload).toEqual({\n\t\t\t\"shop-id\": \"blaa\",\n\t\t\t\"shopware-shop-signature\": \"aaa\",\n\t\t});\n\t});\n\n\ttest(\"fromSource: missing signature header\", async () => {\n\t\texpect(\n\t\t\tcontextResolver.fromAPI(\n\t\t\t\tnew Request(\"https://example.com/\", {\n\t\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\t\tsource: {\n\t\t\t\t\t\t\tshopId: \"blaa\",\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t}),\n\t\t\t),\n\t\t).rejects.toThrowError(\"Missing shopware-shop-signature header\");\n\t});\n\n\ttest(\"fromSource: shop does not exists\", async () => {\n\t\texpect(\n\t\t\tcontextResolver.fromAPI(\n\t\t\t\tnew Request(\"https://example.com/\", {\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"shopware-shop-signature\": \"aaa\",\n\t\t\t\t\t},\n\t\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\t\tsource: {\n\t\t\t\t\t\t\tshopId: \"test\",\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t}),\n\t\t\t),\n\t\t).rejects.toThrowError(\"Cannot find shop by id test\");\n\t});\n\n\ttest(\"fromSource: invalid signature\", async () => {\n\t\texpect(\n\t\t\tcontextResolver.fromAPI(\n\t\t\t\tnew Request(\"https://example.com/\", {\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"shopware-shop-signature\": \"aaa\",\n\t\t\t\t\t},\n\t\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\t\tsource: {\n\t\t\t\t\t\t\tshopId: \"blaa\",\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t}),\n\t\t\t),\n\t\t).rejects.toThrowError(\"Invalid signature\");\n\t});\n\n\ttest(\"fromSource: resolved\", async () => {\n\t\tapp.signer.verify = jest.fn().mockResolvedValue(true);\n\n\t\tconst ctx = await contextResolver.fromAPI(\n\t\t\tnew Request(\"https://example.com/\", {\n\t\t\t\theaders: {\n\t\t\t\t\t\"shopware-shop-signature\": \"aaa\",\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tsource: {\n\t\t\t\t\t\tshopId: \"blaa\",\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t}),\n\t\t);\n\n\t\texpect(ctx.payload).toEqual({\n\t\t\tsource: {\n\t\t\t\tshopId: \"blaa\",\n\t\t\t},\n\t\t});\n\t});\n});\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=app-actions.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-actions.test.d.ts","sourceRoot":"","sources":["../../../src/helper/app-actions.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,29 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { createModalResponse, createNewTabResponse, createNotificationResponse, } from "../../src/helper/app-actions.js";
3
+ describe("AppActions", async () => {
4
+ test("createNewTabResponse", async () => {
5
+ const resp = createNewTabResponse("test");
6
+ expect(resp.headers.get("content-type")).toBe("application/json");
7
+ expect(await resp.text()).toBe(JSON.stringify({
8
+ actionType: "openNewTab",
9
+ payload: { redirectUrl: "test" },
10
+ }));
11
+ });
12
+ test("createNotificationResponse", async () => {
13
+ const resp = createNotificationResponse("success", "test");
14
+ expect(resp.headers.get("content-type")).toBe("application/json");
15
+ expect(await resp.text()).toBe(JSON.stringify({
16
+ actionType: "notification",
17
+ payload: { status: "success", message: "test" },
18
+ }));
19
+ });
20
+ test("createModalResponse", async () => {
21
+ const resp = createModalResponse("test", "small", true);
22
+ expect(resp.headers.get("content-type")).toBe("application/json");
23
+ expect(await resp.text()).toBe(JSON.stringify({
24
+ actionType: "openModal",
25
+ payload: { iframeUrl: "test", size: "small", expand: true },
26
+ }));
27
+ });
28
+ });
29
+ //# sourceMappingURL=app-actions.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-actions.test.js","sourceRoot":"","sources":["../../../src/helper/app-actions.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EACN,mBAAmB,EACnB,oBAAoB,EACpB,0BAA0B,GAC1B,MAAM,iCAAiC,CAAC;AAEzC,QAAQ,CAAC,YAAY,EAAE,KAAK,IAAI,EAAE;IACjC,IAAI,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE;QACvC,MAAM,IAAI,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;QAE1C,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAClE,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAC7B,IAAI,CAAC,SAAS,CAAC;YACd,UAAU,EAAE,YAAY;YACxB,OAAO,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE;SAChC,CAAC,CACF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;QAC7C,MAAM,IAAI,GAAG,0BAA0B,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAE3D,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAClE,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAC7B,IAAI,CAAC,SAAS,CAAC;YACd,UAAU,EAAE,cAAc;YAC1B,OAAO,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE;SAC/C,CAAC,CACF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,qBAAqB,EAAE,KAAK,IAAI,EAAE;QACtC,MAAM,IAAI,GAAG,mBAAmB,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAExD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAClE,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAC7B,IAAI,CAAC,SAAS,CAAC;YACd,UAAU,EAAE,WAAW;YACvB,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE;SAC3D,CAAC,CACF,CAAC;IACH,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, test } from \"bun:test\";\nimport {\n\tcreateModalResponse,\n\tcreateNewTabResponse,\n\tcreateNotificationResponse,\n} from \"../../src/helper/app-actions.js\";\n\ndescribe(\"AppActions\", async () => {\n\ttest(\"createNewTabResponse\", async () => {\n\t\tconst resp = createNewTabResponse(\"test\");\n\n\t\texpect(resp.headers.get(\"content-type\")).toBe(\"application/json\");\n\t\texpect(await resp.text()).toBe(\n\t\t\tJSON.stringify({\n\t\t\t\tactionType: \"openNewTab\",\n\t\t\t\tpayload: { redirectUrl: \"test\" },\n\t\t\t}),\n\t\t);\n\t});\n\n\ttest(\"createNotificationResponse\", async () => {\n\t\tconst resp = createNotificationResponse(\"success\", \"test\");\n\n\t\texpect(resp.headers.get(\"content-type\")).toBe(\"application/json\");\n\t\texpect(await resp.text()).toBe(\n\t\t\tJSON.stringify({\n\t\t\t\tactionType: \"notification\",\n\t\t\t\tpayload: { status: \"success\", message: \"test\" },\n\t\t\t}),\n\t\t);\n\t});\n\n\ttest(\"createModalResponse\", async () => {\n\t\tconst resp = createModalResponse(\"test\", \"small\", true);\n\n\t\texpect(resp.headers.get(\"content-type\")).toBe(\"application/json\");\n\t\texpect(await resp.text()).toBe(\n\t\t\tJSON.stringify({\n\t\t\t\tactionType: \"openModal\",\n\t\t\t\tpayload: { iframeUrl: \"test\", size: \"small\", expand: true },\n\t\t\t}),\n\t\t);\n\t});\n});\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=http-client.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-client.test.d.ts","sourceRoot":"","sources":["../../src/http-client.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,69 @@
1
+ import { describe, expect, spyOn, test } from "bun:test";
2
+ import { HttpClient } from "../src/http-client.js";
3
+ import { SimpleShop } from "../src/repository.js";
4
+ describe("HTTP Client", async () => {
5
+ test("getToken", async () => {
6
+ const mockFetch = spyOn(global, "fetch").mockImplementation(() => Promise.resolve(new Response('{"access_token": "test", "expires_in": 3600}')));
7
+ const client = new HttpClient(new SimpleShop("blaa", "test", "test"));
8
+ expect(client.getToken()).resolves.toBe("test");
9
+ // We fetched already once the token, so the second time we should get it from the storage
10
+ await client.getToken();
11
+ expect(mockFetch.mock.calls).toBeArrayOfSize(1);
12
+ mockFetch.mockRestore();
13
+ });
14
+ test("getToken: failed request", async () => {
15
+ const mockFetch = spyOn(global, "fetch").mockImplementation(() => Promise.resolve(new Response('{"error": "invalid_grant"}', { status: 400 })));
16
+ const client = new HttpClient(new SimpleShop("blaa", "test", "test"));
17
+ expect(client.getToken()).rejects.toThrowError("The api client authentication to shop with id: blaa");
18
+ mockFetch.mockRestore();
19
+ });
20
+ test("getToken: expired refetch", async () => {
21
+ const mockFetch = spyOn(global, "fetch").mockImplementation(() => Promise.resolve(new Response('{"access_token": "test", "expires_in": -500}')));
22
+ const client = new HttpClient(new SimpleShop("blaa", "test", "test"));
23
+ expect(client.getToken()).resolves.toBe("test");
24
+ expect(mockFetch.mock.calls).toBeArrayOfSize(1);
25
+ expect(client.getToken()).resolves.toBe("test");
26
+ expect(mockFetch.mock.calls).toBeArrayOfSize(2);
27
+ mockFetch.mockRestore();
28
+ });
29
+ test("get, post, put, patch, delete", async () => {
30
+ const mockFetch = spyOn(global, "fetch").mockImplementationOnce(() => Promise.resolve(new Response('{"access_token": "test", "expires_in": 5000}')));
31
+ const client = new HttpClient(new SimpleShop("blaa", "test", "test"));
32
+ mockFetch.mockImplementation(() => Promise.resolve(new Response('{"data": "test"}')));
33
+ expect(client.get("/test")).resolves.toEqual({
34
+ body: { data: "test" },
35
+ headers: new Headers(),
36
+ statusCode: 200,
37
+ });
38
+ expect(client.post("/test", { data: "test" })).resolves.toEqual({
39
+ body: { data: "test" },
40
+ headers: new Headers(),
41
+ statusCode: 200,
42
+ });
43
+ expect(client.put("/test", { data: "test" })).resolves.toEqual({
44
+ body: { data: "test" },
45
+ headers: new Headers(),
46
+ statusCode: 200,
47
+ });
48
+ expect(client.patch("/test", { data: "test" })).resolves.toEqual({
49
+ body: { data: "test" },
50
+ headers: new Headers(),
51
+ statusCode: 200,
52
+ });
53
+ expect(client.delete("/test")).resolves.toEqual({
54
+ body: { data: "test" },
55
+ headers: new Headers(),
56
+ statusCode: 200,
57
+ });
58
+ expect(mockFetch.mock.calls).toBeArrayOfSize(6);
59
+ mockFetch.mockRestore();
60
+ });
61
+ test("get: request failed", async () => {
62
+ const mockFetch = spyOn(global, "fetch").mockImplementationOnce(() => Promise.resolve(new Response('{"access_token": "test", "expires_in": 5000}')));
63
+ const client = new HttpClient(new SimpleShop("blaa", "test", "test"));
64
+ mockFetch.mockImplementation(() => Promise.resolve(new Response('{"data": "test"}', { status: 400 })));
65
+ expect(client.get("/test")).rejects.toThrowError("The api request failed with status code: 400 for shop with id: blaa");
66
+ mockFetch.mockRestore();
67
+ });
68
+ });
69
+ //# sourceMappingURL=http-client.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-client.test.js","sourceRoot":"","sources":["../../src/http-client.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, spyOn, test } from \"bun:test\";\nimport { HttpClient } from \"../src/http-client.js\";\nimport { SimpleShop } from \"../src/repository.js\";\n\ndescribe(\"HTTP Client\", async () => {\n\ttest(\"getToken\", async () => {\n\t\tconst mockFetch = spyOn(global, \"fetch\").mockImplementation(() =>\n\t\t\tPromise.resolve(\n\t\t\t\tnew Response('{\"access_token\": \"test\", \"expires_in\": 3600}'),\n\t\t\t),\n\t\t);\n\n\t\tconst client = new HttpClient(new SimpleShop(\"blaa\", \"test\", \"test\"));\n\t\texpect(client.getToken()).resolves.toBe(\"test\");\n\n\t\t// We fetched already once the token, so the second time we should get it from the storage\n\t\tawait client.getToken();\n\n\t\texpect(mockFetch.mock.calls).toBeArrayOfSize(1);\n\n\t\tmockFetch.mockRestore();\n\t});\n\n\ttest(\"getToken: failed request\", async () => {\n\t\tconst mockFetch = spyOn(global, \"fetch\").mockImplementation(() =>\n\t\t\tPromise.resolve(\n\t\t\t\tnew Response('{\"error\": \"invalid_grant\"}', { status: 400 }),\n\t\t\t),\n\t\t);\n\n\t\tconst client = new HttpClient(new SimpleShop(\"blaa\", \"test\", \"test\"));\n\t\texpect(client.getToken()).rejects.toThrowError(\n\t\t\t\"The api client authentication to shop with id: blaa\",\n\t\t);\n\n\t\tmockFetch.mockRestore();\n\t});\n\n\ttest(\"getToken: expired refetch\", async () => {\n\t\tconst mockFetch = spyOn(global, \"fetch\").mockImplementation(() =>\n\t\t\tPromise.resolve(\n\t\t\t\tnew Response('{\"access_token\": \"test\", \"expires_in\": -500}'),\n\t\t\t),\n\t\t);\n\n\t\tconst client = new HttpClient(new SimpleShop(\"blaa\", \"test\", \"test\"));\n\t\texpect(client.getToken()).resolves.toBe(\"test\");\n\n\t\texpect(mockFetch.mock.calls).toBeArrayOfSize(1);\n\n\t\texpect(client.getToken()).resolves.toBe(\"test\");\n\n\t\texpect(mockFetch.mock.calls).toBeArrayOfSize(2);\n\n\t\tmockFetch.mockRestore();\n\t});\n\n\ttest(\"get, post, put, patch, delete\", async () => {\n\t\tconst mockFetch = spyOn(global, \"fetch\").mockImplementationOnce(() =>\n\t\t\tPromise.resolve(\n\t\t\t\tnew Response('{\"access_token\": \"test\", \"expires_in\": 5000}'),\n\t\t\t),\n\t\t);\n\n\t\tconst client = new HttpClient(new SimpleShop(\"blaa\", \"test\", \"test\"));\n\n\t\tmockFetch.mockImplementation(() =>\n\t\t\tPromise.resolve(new Response('{\"data\": \"test\"}')),\n\t\t);\n\n\t\texpect(client.get(\"/test\")).resolves.toEqual({\n\t\t\tbody: { data: \"test\" },\n\t\t\theaders: new Headers(),\n\t\t\tstatusCode: 200,\n\t\t});\n\t\texpect(client.post(\"/test\", { data: \"test\" })).resolves.toEqual({\n\t\t\tbody: { data: \"test\" },\n\t\t\theaders: new Headers(),\n\t\t\tstatusCode: 200,\n\t\t});\n\t\texpect(client.put(\"/test\", { data: \"test\" })).resolves.toEqual({\n\t\t\tbody: { data: \"test\" },\n\t\t\theaders: new Headers(),\n\t\t\tstatusCode: 200,\n\t\t});\n\t\texpect(client.patch(\"/test\", { data: \"test\" })).resolves.toEqual({\n\t\t\tbody: { data: \"test\" },\n\t\t\theaders: new Headers(),\n\t\t\tstatusCode: 200,\n\t\t});\n\t\texpect(client.delete(\"/test\")).resolves.toEqual({\n\t\t\tbody: { data: \"test\" },\n\t\t\theaders: new Headers(),\n\t\t\tstatusCode: 200,\n\t\t});\n\n\t\texpect(mockFetch.mock.calls).toBeArrayOfSize(6);\n\n\t\tmockFetch.mockRestore();\n\t});\n\n\ttest(\"get: request failed\", async () => {\n\t\tconst mockFetch = spyOn(global, \"fetch\").mockImplementationOnce(() =>\n\t\t\tPromise.resolve(\n\t\t\t\tnew Response('{\"access_token\": \"test\", \"expires_in\": 5000}'),\n\t\t\t),\n\t\t);\n\n\t\tconst client = new HttpClient(new SimpleShop(\"blaa\", \"test\", \"test\"));\n\n\t\tmockFetch.mockImplementation(() =>\n\t\t\tPromise.resolve(new Response('{\"data\": \"test\"}', { status: 400 })),\n\t\t);\n\n\t\texpect(client.get(\"/test\")).rejects.toThrowError(\n\t\t\t\"The api request failed with status code: 400 for shop with id: blaa\",\n\t\t);\n\n\t\tmockFetch.mockRestore();\n\t});\n});\n"]}
@@ -0,0 +1,11 @@
1
+ import { type ShopRepositoryInterface, SimpleShop } from "../repository.js";
2
+ import { Database } from "bun:sqlite";
3
+ export declare class BunSqliteRepository implements ShopRepositoryInterface<SimpleShop> {
4
+ db: Database;
5
+ constructor(fileName: string);
6
+ createShop(id: string, url: string, secret: string): Promise<void>;
7
+ getShopById(id: string): Promise<SimpleShop | null>;
8
+ updateShop(shop: SimpleShop): Promise<void>;
9
+ deleteShop(id: string): Promise<void>;
10
+ }
11
+ //# sourceMappingURL=bun-sqlite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bun-sqlite.d.ts","sourceRoot":"","sources":["../../../src/integration/bun-sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,uBAAuB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE5E,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,qBAAa,mBACZ,YAAW,uBAAuB,CAAC,UAAU,CAAC;IAE9C,EAAE,EAAE,QAAQ,CAAC;gBACD,QAAQ,EAAE,MAAM;IActB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAclE,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IA4BnD,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAa3C,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG3C"}
@@ -0,0 +1,56 @@
1
+ import { SimpleShop } from "../repository.js";
2
+ import { Database } from "bun:sqlite";
3
+ export class BunSqliteRepository {
4
+ db;
5
+ constructor(fileName) {
6
+ this.db = new Database(fileName);
7
+ this.db.exec(`
8
+ CREATE TABLE IF NOT EXISTS shop (
9
+ id TEXT PRIMARY KEY,
10
+ active BOOLEAN DEFAULT 1,
11
+ url TEXT NOT NULL,
12
+ secret TEXT NOT NULL,
13
+ client_id TEXT NULL,
14
+ client_secret TEXT NULL
15
+ );
16
+ `);
17
+ }
18
+ async createShop(id, url, secret) {
19
+ const shop = await this.getShopById(id);
20
+ if (shop) {
21
+ return await this.updateShop(shop);
22
+ }
23
+ this.db.exec("INSERT INTO shop (id, url, secret) VALUES (?, ?, ?)", [
24
+ id,
25
+ url,
26
+ secret,
27
+ ]);
28
+ }
29
+ async getShopById(id) {
30
+ const query = this.db.query("SELECT * FROM shop WHERE id = ?");
31
+ const result = query.get(id);
32
+ if (!result) {
33
+ return null;
34
+ }
35
+ const shop = new SimpleShop(result.id, result.url, result.secret);
36
+ if (result.client_id && result.client_secret) {
37
+ shop.setShopCredentials(result.client_id, result.client_secret);
38
+ }
39
+ shop.setShopActive(result.active);
40
+ return shop;
41
+ }
42
+ async updateShop(shop) {
43
+ this.db.exec("UPDATE shop SET url = ?, secret = ?, client_id = ?, client_secret = ?, active = ? WHERE id = ?", [
44
+ shop.getShopUrl(),
45
+ shop.getShopSecret(),
46
+ shop.getShopClientId(),
47
+ shop.getShopClientSecret(),
48
+ shop.getShopActive(),
49
+ shop.getShopId(),
50
+ ]);
51
+ }
52
+ async deleteShop(id) {
53
+ this.db.exec("DELETE FROM shop where id = ?", [id]);
54
+ }
55
+ }
56
+ //# sourceMappingURL=bun-sqlite.js.map