@shopware-ag/app-server-sdk 1.1.29 → 2.0.1

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 (85) hide show
  1. package/dist/commonjs/app.d.ts +8 -2
  2. package/dist/commonjs/app.d.ts.map +1 -1
  3. package/dist/commonjs/app.js +3 -0
  4. package/dist/commonjs/app.js.map +1 -1
  5. package/dist/commonjs/context-resolver.d.ts.map +1 -1
  6. package/dist/commonjs/context-resolver.js +2 -8
  7. package/dist/commonjs/context-resolver.js.map +1 -1
  8. package/dist/commonjs/dual-signature-verifier.d.ts +31 -0
  9. package/dist/commonjs/dual-signature-verifier.d.ts.map +1 -0
  10. package/dist/commonjs/dual-signature-verifier.js +136 -0
  11. package/dist/commonjs/dual-signature-verifier.js.map +1 -0
  12. package/dist/commonjs/integration/better-sqlite3.d.ts.map +1 -1
  13. package/dist/commonjs/integration/better-sqlite3.js +35 -11
  14. package/dist/commonjs/integration/better-sqlite3.js.map +1 -1
  15. package/dist/commonjs/integration/bun-sqlite.d.ts.map +1 -1
  16. package/dist/commonjs/integration/bun-sqlite.js +40 -10
  17. package/dist/commonjs/integration/bun-sqlite.js.map +1 -1
  18. package/dist/commonjs/integration/cloudflare-kv.d.ts.map +1 -1
  19. package/dist/commonjs/integration/cloudflare-kv.js +24 -1
  20. package/dist/commonjs/integration/cloudflare-kv.js.map +1 -1
  21. package/dist/commonjs/integration/deno-kv.d.ts.map +1 -1
  22. package/dist/commonjs/integration/deno-kv.js +18 -0
  23. package/dist/commonjs/integration/deno-kv.js.map +1 -1
  24. package/dist/commonjs/integration/dynamodb.d.ts.map +1 -1
  25. package/dist/commonjs/integration/dynamodb.js +31 -1
  26. package/dist/commonjs/integration/dynamodb.js.map +1 -1
  27. package/dist/commonjs/integration/hono.d.ts +6 -0
  28. package/dist/commonjs/integration/hono.d.ts.map +1 -1
  29. package/dist/commonjs/integration/hono.js +7 -1
  30. package/dist/commonjs/integration/hono.js.map +1 -1
  31. package/dist/commonjs/mod.d.ts +2 -0
  32. package/dist/commonjs/mod.d.ts.map +1 -1
  33. package/dist/commonjs/mod.js +3 -1
  34. package/dist/commonjs/mod.js.map +1 -1
  35. package/dist/commonjs/registration.d.ts +4 -0
  36. package/dist/commonjs/registration.d.ts.map +1 -1
  37. package/dist/commonjs/registration.js +55 -11
  38. package/dist/commonjs/registration.js.map +1 -1
  39. package/dist/commonjs/repository.d.ts +53 -1
  40. package/dist/commonjs/repository.d.ts.map +1 -1
  41. package/dist/commonjs/repository.js +64 -1
  42. package/dist/commonjs/repository.js.map +1 -1
  43. package/dist/esm/app.d.ts +8 -2
  44. package/dist/esm/app.d.ts.map +1 -1
  45. package/dist/esm/app.js +3 -0
  46. package/dist/esm/app.js.map +1 -1
  47. package/dist/esm/context-resolver.d.ts.map +1 -1
  48. package/dist/esm/context-resolver.js +2 -8
  49. package/dist/esm/context-resolver.js.map +1 -1
  50. package/dist/esm/dual-signature-verifier.d.ts +31 -0
  51. package/dist/esm/dual-signature-verifier.d.ts.map +1 -0
  52. package/dist/esm/dual-signature-verifier.js +132 -0
  53. package/dist/esm/dual-signature-verifier.js.map +1 -0
  54. package/dist/esm/integration/better-sqlite3.d.ts.map +1 -1
  55. package/dist/esm/integration/better-sqlite3.js +35 -11
  56. package/dist/esm/integration/better-sqlite3.js.map +1 -1
  57. package/dist/esm/integration/bun-sqlite.d.ts.map +1 -1
  58. package/dist/esm/integration/bun-sqlite.js +40 -10
  59. package/dist/esm/integration/bun-sqlite.js.map +1 -1
  60. package/dist/esm/integration/cloudflare-kv.d.ts.map +1 -1
  61. package/dist/esm/integration/cloudflare-kv.js +24 -1
  62. package/dist/esm/integration/cloudflare-kv.js.map +1 -1
  63. package/dist/esm/integration/deno-kv.d.ts.map +1 -1
  64. package/dist/esm/integration/deno-kv.js +18 -0
  65. package/dist/esm/integration/deno-kv.js.map +1 -1
  66. package/dist/esm/integration/dynamodb.d.ts.map +1 -1
  67. package/dist/esm/integration/dynamodb.js +31 -1
  68. package/dist/esm/integration/dynamodb.js.map +1 -1
  69. package/dist/esm/integration/hono.d.ts +6 -0
  70. package/dist/esm/integration/hono.d.ts.map +1 -1
  71. package/dist/esm/integration/hono.js +7 -1
  72. package/dist/esm/integration/hono.js.map +1 -1
  73. package/dist/esm/mod.d.ts +2 -0
  74. package/dist/esm/mod.d.ts.map +1 -1
  75. package/dist/esm/mod.js +1 -0
  76. package/dist/esm/mod.js.map +1 -1
  77. package/dist/esm/registration.d.ts +4 -0
  78. package/dist/esm/registration.d.ts.map +1 -1
  79. package/dist/esm/registration.js +55 -11
  80. package/dist/esm/registration.js.map +1 -1
  81. package/dist/esm/repository.d.ts +53 -1
  82. package/dist/esm/repository.d.ts.map +1 -1
  83. package/dist/esm/repository.js +64 -1
  84. package/dist/esm/repository.js.map +1 -1
  85. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dual-signature-verifier.js","sourceRoot":"","sources":["../../src/dual-signature-verifier.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ShopInterface } from \"./repository.js\";\nimport { WebCryptoHmacSigner } from \"./signer.js\";\n\nconst SHOPWARE_SHOP_SIGNATURE_HEADER = \"shopware-shop-signature\";\nconst SHOPWARE_SHOP_SIGNATURE_PREVIOUS_HEADER = \"shopware-shop-signature-previous\";\nconst SHOPWARE_APP_SIGNATURE_HEADER = \"shopware-app-signature\";\nconst INFLIGHT_ALLOWANCE_MS = 60_000;\n\nexport interface DualSignatureConfiguration {\n\tappSecret: string;\n\tenforceDoubleSignature: boolean;\n}\n\nexport class DualSignatureVerifier<Shop extends ShopInterface = ShopInterface> {\n\tconstructor(\n\t\tprivate readonly signer: WebCryptoHmacSigner,\n\t\tprivate readonly now: () => Date = () => new Date(),\n\t) {}\n\n\tpublic async authenticateRegistrationRequest(\n\t\treq: Request,\n\t\tcfg: DualSignatureConfiguration,\n\t\tshop: Shop | null,\n\t): Promise<void> {\n\t\ttry {\n\t\t\tawait this.verifyRegistrationAppSignature(req, cfg.appSecret);\n\t\t} catch (error) {\n\t\t\tthrow new Error(\"invalid-app-signature\", { cause: error });\n\t\t}\n\n\t\tif (shop?.isRegistrationConfirmed() && this.shouldEnforceDoubleSignatureForRegister(cfg, shop, req)) {\n\t\t\ttry {\n\t\t\t\tawait this.verifyRegistrationShopSignature(req, shop.getShopSecret());\n\t\t\t} catch (error) {\n\t\t\t\tthrow new Error(\"invalid-shop-registration-signature\", { cause: error });\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic async authenticateRegistrationConfirmation(\n\t\treq: Request,\n\t\tbody: string,\n\t\tshop: Shop,\n\t\tcfg: DualSignatureConfiguration,\n\t): Promise<void> {\n\t\tconst pendingSecret = shop.getPendingShopSecret();\n\n\t\tif (pendingSecret === null) {\n\t\t\tthrow new Error(\"Signature could not be verified\");\n\t\t}\n\n\t\tawait this.verifyPostSignature(req, body, pendingSecret, SHOPWARE_SHOP_SIGNATURE_HEADER);\n\n\t\tif (!shop.isRegistrationConfirmed()) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.shouldEnforceDoubleSignatureForRegisterConfirm(cfg, shop, req)) {\n\t\t\tawait this.verifyPostSignature(req, body, shop.getShopSecret(), SHOPWARE_SHOP_SIGNATURE_PREVIOUS_HEADER);\n\t\t}\n\t}\n\n\tpublic async authenticatePostRequest(\n\t\treq: Request,\n\t\tbody: string,\n\t\tshop: Shop,\n\t): Promise<void> {\n\t\ttry {\n\t\t\tawait this.verifyPostSignature(req, body, shop.getShopSecret(), SHOPWARE_SHOP_SIGNATURE_HEADER);\n\t\t} catch (error) {\n\t\t\tawait this.tryAuthenticateWithPreviousSecret(\n\t\t\t\tshop,\n\t\t\t\terror,\n\t\t\t\tasync (secret) => {\n\t\t\t\t\tawait this.verifyPostSignature(req, body, secret, SHOPWARE_SHOP_SIGNATURE_HEADER);\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t}\n\n\tpublic async authenticateGetRequest(req: Request, shop: Shop): Promise<void> {\n\t\ttry {\n\t\t\tawait this.signer.verifyGetRequest(req, shop.getShopSecret());\n\t\t} catch (error) {\n\t\t\tawait this.tryAuthenticateWithPreviousSecret(\n\t\t\t\tshop,\n\t\t\t\terror,\n\t\t\t\tasync (secret) => {\n\t\t\t\t\tawait this.signer.verifyGetRequest(req, secret);\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate async verifyRegistrationAppSignature(req: Request, secret: string): Promise<void> {\n\t\tconst signature = req.headers.get(SHOPWARE_APP_SIGNATURE_HEADER);\n\n\t\tif (signature === null) {\n\t\t\tthrow new Error(\"Missing shopware-app-signature header\");\n\t\t}\n\n\t\tconst message = this.getRegistrationSignatureMessage(req);\n\t\tconst valid = await this.signer.verify(signature, message, secret);\n\n\t\tif (!valid) {\n\t\t\tthrow new Error(\"Invalid app signature\");\n\t\t}\n\t}\n\n\tprivate async verifyRegistrationShopSignature(req: Request, secret: string): Promise<void> {\n\t\tconst signature = req.headers.get(SHOPWARE_SHOP_SIGNATURE_HEADER);\n\n\t\tif (signature === null) {\n\t\t\tthrow new Error(\"Missing shopware-shop-signature header\");\n\t\t}\n\n\t\tconst message = this.getRegistrationSignatureMessage(req);\n\t\tconst valid = await this.signer.verify(signature, message, secret);\n\n\t\tif (!valid) {\n\t\t\tthrow new Error(\"Invalid shop signature\");\n\t\t}\n\t}\n\n\tprivate async verifyPostSignature(\n\t\treq: Request,\n\t\tbody: string,\n\t\tsecret: string,\n\t\theaderName: string,\n\t): Promise<void> {\n\t\tconst signature = req.headers.get(headerName);\n\n\t\tif (signature === null) {\n\t\t\tthrow new Error(`Missing ${headerName} header`);\n\t\t}\n\n\t\tconst valid = await this.signer.verify(signature, body, secret);\n\n\t\tif (!valid) {\n\t\t\tthrow new Error(\"Invalid signature\");\n\t\t}\n\t}\n\n\tprivate getRegistrationSignatureMessage(req: Request): string {\n\t\tconst url = new URL(req.url);\n\t\tconst shopId = url.searchParams.get(\"shop-id\");\n\t\tconst shopUrl = url.searchParams.get(\"shop-url\");\n\t\tconst timestamp = url.searchParams.get(\"timestamp\");\n\n\t\tif (!shopId || !shopUrl || !timestamp) {\n\t\t\tthrow new Error(\"Missing required registration parameters\");\n\t\t}\n\n\t\treturn `shop-id=${shopId}&shop-url=${shopUrl}&timestamp=${timestamp}`;\n\t}\n\n\tprivate async tryAuthenticateWithPreviousSecret(\n\t\tshop: Shop,\n\t\terror: unknown,\n\t\tverify: (secret: string) => Promise<void>,\n\t): Promise<void> {\n\t\tconst previousSecret = shop.getPreviousShopSecret();\n\t\tconst rotatedAt = shop.getSecretsRotatedAt();\n\n\t\tif (previousSecret === null || rotatedAt === null) {\n\t\t\tthrow error instanceof Error ? error : new Error(\"Invalid signature\");\n\t\t}\n\n\t\tconst allowanceEnd = rotatedAt.getTime() + INFLIGHT_ALLOWANCE_MS;\n\n\t\tif (this.now().getTime() >= allowanceEnd) {\n\t\t\tthrow error instanceof Error ? error : new Error(\"Invalid signature\");\n\t\t}\n\n\t\tawait verify(previousSecret);\n\t}\n\n\t/**\n\t * @deprecated tag:v6.0.0 - Will be removed. Double signature verification will always be enforced.\n\t *\n\t * 1. If the shop has previously verified with a double signature, it must always do so\n\t * 2. If the shop is sending a double signature, then we should also verify it\n\t * 3. If the app is configured to enforce double signature, then we should force it\n\t */\n\tprivate shouldEnforceDoubleSignature(cfg: DualSignatureConfiguration, shop: Shop, req: Request, header: string): boolean\n\t{\n\t\treturn shop.hasVerifiedWithDoubleSignature() || req.headers.has(header) || cfg.enforceDoubleSignature;\n\t}\n\n\tprivate shouldEnforceDoubleSignatureForRegister(cfg: DualSignatureConfiguration, shop: Shop, req: Request): boolean\n\t{\n\t\treturn this.shouldEnforceDoubleSignature(cfg, shop, req, SHOPWARE_SHOP_SIGNATURE_HEADER);\n\t}\n\n\tprivate shouldEnforceDoubleSignatureForRegisterConfirm(cfg: DualSignatureConfiguration, shop: Shop, req: Request): boolean\n\t{\n\t\treturn this.shouldEnforceDoubleSignature(cfg, shop, req, SHOPWARE_SHOP_SIGNATURE_PREVIOUS_HEADER);\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"better-sqlite3.d.ts","sourceRoot":"","sources":["../../../src/integration/better-sqlite3.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,uBAAuB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE5E,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC,qBAAa,uBACZ,YAAW,uBAAuB,CAAC,UAAU,CAAC;IAE9C,EAAE,EAAE,QAAQ,CAAC,QAAQ,CAAC;gBACV,QAAQ,EAAE,MAAM;IAetB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYlE,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IA0BnD,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAc3C,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG3C"}
1
+ {"version":3,"file":"better-sqlite3.d.ts","sourceRoot":"","sources":["../../../src/integration/better-sqlite3.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,uBAAuB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE5E,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC,qBAAa,uBACZ,YAAW,uBAAuB,CAAC,UAAU,CAAC;IAE9C,EAAE,EAAE,QAAQ,CAAC,QAAQ,CAAC;gBACV,QAAQ,EAAE,MAAM;IAqBtB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYlE,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAwDnD,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAoB3C,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG3C"}
@@ -6,15 +6,21 @@ export class BetterSqlite3Repository {
6
6
  this.db = new Database(fileName);
7
7
  this.db.pragma("journal_mode = WAL");
8
8
  this.db.exec(`
9
- CREATE TABLE IF NOT EXISTS shop (
10
- id TEXT PRIMARY KEY,
11
- active BOOLEAN DEFAULT 1,
12
- url TEXT NOT NULL,
13
- secret TEXT NOT NULL,
14
- client_id TEXT NULL,
15
- client_secret TEXT NULL
16
- );
17
- `);
9
+ CREATE TABLE IF NOT EXISTS shop (
10
+ id TEXT PRIMARY KEY,
11
+ active BOOLEAN DEFAULT 1,
12
+ url TEXT NOT NULL,
13
+ secret TEXT NOT NULL,
14
+ client_id TEXT NULL,
15
+ client_secret TEXT NULL,
16
+ pending_shop_url TEXT NULL,
17
+ pending_shop_secret TEXT NULL,
18
+ previous_shop_secret TEXT NULL,
19
+ secrets_rotated_at INTEGER NULL,
20
+ verified_with_double_signatures BOOLEAN DEFAULT 0,
21
+ registration_confirmed BOOLEAN DEFAULT 0
22
+ );
23
+ `);
18
24
  }
19
25
  async createShop(id, url, secret) {
20
26
  const shop = await this.getShopById(id);
@@ -37,12 +43,30 @@ export class BetterSqlite3Repository {
37
43
  shop.setShopCredentials(result.client_id, result.client_secret);
38
44
  }
39
45
  shop.setShopActive(result.active === 1);
46
+ if (result.pending_shop_url) {
47
+ shop.setPendingShopUrl(result.pending_shop_url);
48
+ }
49
+ if (result.pending_shop_secret) {
50
+ shop.setPendingShopSecret(result.pending_shop_secret);
51
+ }
52
+ if (result.previous_shop_secret) {
53
+ shop.setPreviousShopSecret(result.previous_shop_secret);
54
+ }
55
+ if (result.secrets_rotated_at) {
56
+ shop.setSecretsRotatedAt(new Date(Number(result.secrets_rotated_at)));
57
+ }
58
+ if (result.verified_with_double_signatures === 1) {
59
+ shop.setVerifiedWithDoubleSignature();
60
+ }
61
+ if (result.registration_confirmed === 1) {
62
+ shop.setRegistrationConfirmed();
63
+ }
40
64
  return shop;
41
65
  }
42
66
  async updateShop(shop) {
43
67
  this.db
44
- .prepare("UPDATE shop SET url = ?, secret = ?, client_id = ?, client_secret = ?, active = ? WHERE id = ?")
45
- .run(shop.getShopUrl(), shop.getShopSecret(), shop.getShopClientId(), shop.getShopClientSecret(), +shop.getShopActive(), shop.getShopId());
68
+ .prepare("UPDATE shop SET url = ?, secret = ?, client_id = ?, client_secret = ?, active = ?, pending_shop_url = ?, pending_shop_secret = ?, previous_shop_secret = ?, secrets_rotated_at = ?, verified_with_double_signatures = ?, registration_confirmed = ? WHERE id = ?")
69
+ .run(shop.getShopUrl(), shop.getShopSecret(), shop.getShopClientId(), shop.getShopClientSecret(), +shop.getShopActive(), shop.getPendingShopUrl(), shop.getPendingShopSecret(), shop.getPreviousShopSecret(), shop.getSecretsRotatedAt()?.getTime() ?? null, +shop.hasVerifiedWithDoubleSignature(), +shop.isRegistrationConfirmed(), shop.getShopId());
46
70
  }
47
71
  async deleteShop(id) {
48
72
  this.db.prepare("DELETE FROM shop where id = ?").run(id);
@@ -1 +1 @@
1
- {"version":3,"file":"better-sqlite3.js","sourceRoot":"","sources":["../../../src/integration/better-sqlite3.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE5E,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC,MAAM,OAAO,uBAAuB;IAGnC,EAAE,CAAoB;IACtB,YAAY,QAAgB;QAC3B,IAAI,CAAC,EAAE,GAAG,IAAI,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACjC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;QACrC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;;;;;;;;;OASR,CAAC,CAAC;IACR,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,EAAU,EAAE,GAAW,EAAE,MAAc;QACvD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAExC,IAAI,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QAC3B,CAAC;QAED,IAAI,CAAC,EAAE;aACL,OAAO,CAAC,qDAAqD,CAAC;aAC9D,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,EAAU;QAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE;aACpB,OAAO,CAAC,iCAAiC,CAAC;aAC1C,GAAG,CAAC,EAAE,CAOP,CAAC;QAEF,IAAI,CAAC,MAAM,EAAE,CAAC;YACb,OAAO,IAAI,CAAC;QACb,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAElE,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;YAC9C,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;QACjE,CAAC;QAED,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC;QAExC,OAAO,IAAI,CAAC;IACb,CAAC;IACD,KAAK,CAAC,UAAU,CAAC,IAAgB;QAChC,IAAI,CAAC,EAAE;aACL,OAAO,CACP,gGAAgG,CAChG;aACA,GAAG,CACH,IAAI,CAAC,UAAU,EAAE,EACjB,IAAI,CAAC,aAAa,EAAE,EACpB,IAAI,CAAC,eAAe,EAAE,EACtB,IAAI,CAAC,mBAAmB,EAAE,EAC1B,CAAC,IAAI,CAAC,aAAa,EAAE,EACrB,IAAI,CAAC,SAAS,EAAE,CAChB,CAAC;IACJ,CAAC;IACD,KAAK,CAAC,UAAU,CAAC,EAAU;QAC1B,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,+BAA+B,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC1D,CAAC;CACD","sourcesContent":["import { type ShopRepositoryInterface, SimpleShop } from \"../repository.js\";\n\nimport Database from \"better-sqlite3\";\n\nexport class BetterSqlite3Repository\n\timplements ShopRepositoryInterface<SimpleShop>\n{\n\tdb: Database.Database;\n\tconstructor(fileName: string) {\n\t\tthis.db = new Database(fileName);\n\t\tthis.db.pragma(\"journal_mode = WAL\");\n\t\tthis.db.exec(`\n CREATE TABLE IF NOT EXISTS shop (\n id TEXT PRIMARY KEY,\n active BOOLEAN DEFAULT 1,\n url TEXT NOT NULL,\n secret TEXT NOT NULL,\n client_id TEXT NULL,\n client_secret TEXT NULL\n );\n `);\n\t}\n\n\tasync createShop(id: string, url: string, secret: string): Promise<void> {\n\t\tconst shop = await this.getShopById(id);\n\n\t\tif (shop) {\n\t\t\tawait this.deleteShop(id);\n\t\t}\n\n\t\tthis.db\n\t\t\t.prepare(\"INSERT INTO shop (id, url, secret) VALUES (?, ?, ?)\")\n\t\t\t.run(id, url, secret);\n\t}\n\n\tasync getShopById(id: string): Promise<SimpleShop | null> {\n\t\tconst result = this.db\n\t\t\t.prepare(\"SELECT * FROM shop WHERE id = ?\")\n\t\t\t.get(id) as null | {\n\t\t\tid: string;\n\t\t\tactive: number;\n\t\t\turl: string;\n\t\t\tsecret: string;\n\t\t\tclient_id?: string;\n\t\t\tclient_secret?: string;\n\t\t};\n\n\t\tif (!result) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst shop = new SimpleShop(result.id, result.url, result.secret);\n\n\t\tif (result.client_id && result.client_secret) {\n\t\t\tshop.setShopCredentials(result.client_id, result.client_secret);\n\t\t}\n\n\t\tshop.setShopActive(result.active === 1);\n\n\t\treturn shop;\n\t}\n\tasync updateShop(shop: SimpleShop): Promise<void> {\n\t\tthis.db\n\t\t\t.prepare(\n\t\t\t\t\"UPDATE shop SET url = ?, secret = ?, client_id = ?, client_secret = ?, active = ? WHERE id = ?\",\n\t\t\t)\n\t\t\t.run(\n\t\t\t\tshop.getShopUrl(),\n\t\t\t\tshop.getShopSecret(),\n\t\t\t\tshop.getShopClientId(),\n\t\t\t\tshop.getShopClientSecret(),\n\t\t\t\t+shop.getShopActive(),\n\t\t\t\tshop.getShopId(),\n\t\t\t);\n\t}\n\tasync deleteShop(id: string): Promise<void> {\n\t\tthis.db.prepare(\"DELETE FROM shop where id = ?\").run(id);\n\t}\n}\n"]}
1
+ {"version":3,"file":"better-sqlite3.js","sourceRoot":"","sources":["../../../src/integration/better-sqlite3.ts"],"names":[],"mappings":"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","sourcesContent":["import { type ShopRepositoryInterface, SimpleShop } from \"../repository.js\";\n\nimport Database from \"better-sqlite3\";\n\nexport class BetterSqlite3Repository\n\timplements ShopRepositoryInterface<SimpleShop>\n{\n\tdb: Database.Database;\n\tconstructor(fileName: string) {\n\t\tthis.db = new Database(fileName);\n\t\tthis.db.pragma(\"journal_mode = WAL\");\n\t\tthis.db.exec(`\n\t\tCREATE TABLE IF NOT EXISTS shop (\n\t\t id TEXT PRIMARY KEY,\n\t\t active BOOLEAN DEFAULT 1,\n\t\t url TEXT NOT NULL,\n\t\t secret TEXT NOT NULL,\n\t\t client_id TEXT NULL,\n\t\t client_secret TEXT NULL,\n\t\t pending_shop_url TEXT NULL,\n\t\t pending_shop_secret TEXT NULL,\n\t\t previous_shop_secret TEXT NULL,\n\t\t secrets_rotated_at INTEGER NULL,\n\t\t verified_with_double_signatures BOOLEAN DEFAULT 0,\n\t\t registration_confirmed BOOLEAN DEFAULT 0\n\t\t);\n\t `);\n\t}\n\n\tasync createShop(id: string, url: string, secret: string): Promise<void> {\n\t\tconst shop = await this.getShopById(id);\n\n\t\tif (shop) {\n\t\t\tawait this.deleteShop(id);\n\t\t}\n\n\t\tthis.db\n\t\t\t.prepare(\"INSERT INTO shop (id, url, secret) VALUES (?, ?, ?)\")\n\t\t\t.run(id, url, secret);\n\t}\n\n\tasync getShopById(id: string): Promise<SimpleShop | null> {\n\t\tconst result = this.db\n\t\t\t.prepare(\"SELECT * FROM shop WHERE id = ?\")\n\t\t\t.get(id) as null | {\n\t\t\tid: string;\n\t\t\tactive: number;\n\t\t\turl: string;\n\t\t\tsecret: string;\n\t\t\tclient_id?: string;\n\t\t\tclient_secret?: string;\n\t\t\tpending_shop_url?: string;\n\t\t\tpending_shop_secret?: string;\n\t\t\tprevious_shop_secret?: string;\n\t\t\tsecrets_rotated_at?: Date;\n\t\t\tverified_with_double_signatures?: number;\n\t\t\tregistration_confirmed?: number;\n\t\t};\n\n\t\tif (!result) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst shop = new SimpleShop(result.id, result.url, result.secret);\n\n\t\tif (result.client_id && result.client_secret) {\n\t\t\tshop.setShopCredentials(result.client_id, result.client_secret);\n\t\t}\n\n\t\tshop.setShopActive(result.active === 1);\n\n\t\tif (result.pending_shop_url) {\n\t\t\tshop.setPendingShopUrl(result.pending_shop_url);\n\t\t}\n\n\t\tif (result.pending_shop_secret) {\n\t\t\tshop.setPendingShopSecret(result.pending_shop_secret);\n\t\t}\n\n\t\tif (result.previous_shop_secret) {\n\t\t\tshop.setPreviousShopSecret(result.previous_shop_secret);\n\t\t}\n\n\t\tif (result.secrets_rotated_at) {\n\t\t\tshop.setSecretsRotatedAt(new Date(Number(result.secrets_rotated_at)));\n\t\t}\n\n\t\tif (result.verified_with_double_signatures === 1) {\n\t\t\tshop.setVerifiedWithDoubleSignature();\n\t\t}\n\n\t\tif (result.registration_confirmed === 1) {\n\t\t\tshop.setRegistrationConfirmed();\n\t\t}\n\n\t\treturn shop;\n\t}\n\tasync updateShop(shop: SimpleShop): Promise<void> {\n\t\tthis.db\n\t\t\t.prepare(\n\t\t\t\t\"UPDATE shop SET url = ?, secret = ?, client_id = ?, client_secret = ?, active = ?, pending_shop_url = ?, pending_shop_secret = ?, previous_shop_secret = ?, secrets_rotated_at = ?, verified_with_double_signatures = ?, registration_confirmed = ? WHERE id = ?\",\n\t\t\t)\n\t\t\t.run(\n\t\t\t\tshop.getShopUrl(),\n\t\t\t\tshop.getShopSecret(),\n\t\t\t\tshop.getShopClientId(),\n\t\t\t\tshop.getShopClientSecret(),\n\t\t\t\t+shop.getShopActive(),\n\t\t\t\tshop.getPendingShopUrl(),\n\t\t\t\tshop.getPendingShopSecret(),\n\t\t\t\tshop.getPreviousShopSecret(),\n\t\t\t\tshop.getSecretsRotatedAt()?.getTime() ?? null,\n\t\t\t\t+shop.hasVerifiedWithDoubleSignature(),\n\t\t\t\t+shop.isRegistrationConfirmed(),\n\t\t\t\tshop.getShopId(),\n\t\t\t);\n\t}\n\tasync deleteShop(id: string): Promise<void> {\n\t\tthis.db.prepare(\"DELETE FROM shop where id = ?\").run(id);\n\t}\n}\n"]}
@@ -1 +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;IAetB,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"}
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;IAqBtB,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;IA0DnD,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB3C,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG3C"}
@@ -6,15 +6,21 @@ export class BunSqliteRepository {
6
6
  this.db = new Database(fileName);
7
7
  this.db.exec("PRAGMA journal_mode = WAL;");
8
8
  this.db.exec(`
9
- CREATE TABLE IF NOT EXISTS shop (
10
- id TEXT PRIMARY KEY,
11
- active BOOLEAN DEFAULT 1,
12
- url TEXT NOT NULL,
13
- secret TEXT NOT NULL,
14
- client_id TEXT NULL,
15
- client_secret TEXT NULL
16
- );
17
- `);
9
+ CREATE TABLE IF NOT EXISTS shop (
10
+ id TEXT PRIMARY KEY,
11
+ active BOOLEAN DEFAULT 1,
12
+ url TEXT NOT NULL,
13
+ secret TEXT NOT NULL,
14
+ client_id TEXT NULL,
15
+ client_secret TEXT NULL,
16
+ pending_shop_url TEXT NULL,
17
+ pending_shop_secret TEXT NULL,
18
+ previous_shop_secret TEXT NULL,
19
+ secrets_rotated_at INTEGER NULL,
20
+ verified_with_double_signatures BOOLEAN DEFAULT 0,
21
+ registration_confirmed BOOLEAN DEFAULT 0
22
+ );
23
+ `);
18
24
  }
19
25
  async createShop(id, url, secret) {
20
26
  const shop = await this.getShopById(id);
@@ -38,15 +44,39 @@ export class BunSqliteRepository {
38
44
  shop.setShopCredentials(result.client_id, result.client_secret);
39
45
  }
40
46
  shop.setShopActive(result.active);
47
+ if (result.pending_shop_url) {
48
+ shop.setPendingShopUrl(result.pending_shop_url);
49
+ }
50
+ if (result.pending_shop_secret) {
51
+ shop.setPendingShopSecret(result.pending_shop_secret);
52
+ }
53
+ if (result.previous_shop_secret) {
54
+ shop.setPreviousShopSecret(result.previous_shop_secret);
55
+ }
56
+ if (result.secrets_rotated_at) {
57
+ shop.setSecretsRotatedAt(new Date(Number(result.secrets_rotated_at)));
58
+ }
59
+ if (result.verified_with_double_signatures === 1) {
60
+ shop.setVerifiedWithDoubleSignature();
61
+ }
62
+ if (result.registration_confirmed === 1) {
63
+ shop.setRegistrationConfirmed();
64
+ }
41
65
  return shop;
42
66
  }
43
67
  async updateShop(shop) {
44
- this.db.exec("UPDATE shop SET url = ?, secret = ?, client_id = ?, client_secret = ?, active = ? WHERE id = ?", [
68
+ this.db.exec("UPDATE shop SET url = ?, secret = ?, client_id = ?, client_secret = ?, active = ?, pending_shop_url = ?, pending_shop_secret = ?, previous_shop_secret = ?, secrets_rotated_at = ?, verified_with_double_signatures = ?, registration_confirmed = ? WHERE id = ?", [
45
69
  shop.getShopUrl(),
46
70
  shop.getShopSecret(),
47
71
  shop.getShopClientId(),
48
72
  shop.getShopClientSecret(),
49
73
  shop.getShopActive(),
74
+ shop.getPendingShopUrl(),
75
+ shop.getPendingShopSecret(),
76
+ shop.getPreviousShopSecret(),
77
+ shop.getSecretsRotatedAt()?.getTime() ?? null,
78
+ shop.hasVerifiedWithDoubleSignature(),
79
+ shop.isRegistrationConfirmed(),
50
80
  shop.getShopId(),
51
81
  ]);
52
82
  }
@@ -1 +1 @@
1
- {"version":3,"file":"bun-sqlite.js","sourceRoot":"","sources":["../../../src/integration/bun-sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE5E,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,MAAM,OAAO,mBAAmB;IAG/B,EAAE,CAAW;IACb,YAAY,QAAgB;QAC3B,IAAI,CAAC,EAAE,GAAG,IAAI,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACjC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QAC3C,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;;;;;;;;;OASR,CAAC,CAAC;IACR,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,EAAU,EAAE,GAAW,EAAE,MAAc;QACvD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAExC,IAAI,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QAC3B,CAAC;QAED,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,qDAAqD,EAAE;YACnE,EAAE;YACF,GAAG;YACH,MAAM;SACN,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,EAAU;QAC3B,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE,CAAC,KAAK,CAUzB,iCAAiC,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAE7B,IAAI,CAAC,MAAM,EAAE,CAAC;YACb,OAAO,IAAI,CAAC;QACb,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAElE,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;YAC9C,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;QACjE,CAAC;QAED,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAElC,OAAO,IAAI,CAAC;IACb,CAAC;IACD,KAAK,CAAC,UAAU,CAAC,IAAgB;QAChC,IAAI,CAAC,EAAE,CAAC,IAAI,CACX,gGAAgG,EAChG;YACC,IAAI,CAAC,UAAU,EAAE;YACjB,IAAI,CAAC,aAAa,EAAE;YACpB,IAAI,CAAC,eAAe,EAAE;YACtB,IAAI,CAAC,mBAAmB,EAAE;YAC1B,IAAI,CAAC,aAAa,EAAE;YACpB,IAAI,CAAC,SAAS,EAAE;SAChB,CACD,CAAC;IACH,CAAC;IACD,KAAK,CAAC,UAAU,CAAC,EAAU;QAC1B,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,+BAA+B,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACrD,CAAC;CACD","sourcesContent":["import { type ShopRepositoryInterface, SimpleShop } from \"../repository.js\";\n\nimport { Database } from \"bun:sqlite\";\n\nexport class BunSqliteRepository\n\timplements ShopRepositoryInterface<SimpleShop>\n{\n\tdb: Database;\n\tconstructor(fileName: string) {\n\t\tthis.db = new Database(fileName);\n\t\tthis.db.exec(\"PRAGMA journal_mode = WAL;\");\n\t\tthis.db.exec(`\n CREATE TABLE IF NOT EXISTS shop (\n id TEXT PRIMARY KEY,\n active BOOLEAN DEFAULT 1,\n url TEXT NOT NULL,\n secret TEXT NOT NULL,\n client_id TEXT NULL,\n client_secret TEXT NULL\n );\n `);\n\t}\n\n\tasync createShop(id: string, url: string, secret: string): Promise<void> {\n\t\tconst shop = await this.getShopById(id);\n\n\t\tif (shop) {\n\t\t\tawait this.deleteShop(id);\n\t\t}\n\n\t\tthis.db.exec(\"INSERT INTO shop (id, url, secret) VALUES (?, ?, ?)\", [\n\t\t\tid,\n\t\t\turl,\n\t\t\tsecret,\n\t\t]);\n\t}\n\n\tasync getShopById(id: string): Promise<SimpleShop | null> {\n\t\tconst query = this.db.query<\n\t\t\t{\n\t\t\t\tid: string;\n\t\t\t\tactive: boolean;\n\t\t\t\turl: string;\n\t\t\t\tsecret: string;\n\t\t\t\tclient_id?: string;\n\t\t\t\tclient_secret?: string;\n\t\t\t},\n\t\t\tstring\n\t\t>(\"SELECT * FROM shop WHERE id = ?\");\n\t\tconst result = query.get(id);\n\n\t\tif (!result) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst shop = new SimpleShop(result.id, result.url, result.secret);\n\n\t\tif (result.client_id && result.client_secret) {\n\t\t\tshop.setShopCredentials(result.client_id, result.client_secret);\n\t\t}\n\n\t\tshop.setShopActive(result.active);\n\n\t\treturn shop;\n\t}\n\tasync updateShop(shop: SimpleShop): Promise<void> {\n\t\tthis.db.exec(\n\t\t\t\"UPDATE shop SET url = ?, secret = ?, client_id = ?, client_secret = ?, active = ? WHERE id = ?\",\n\t\t\t[\n\t\t\t\tshop.getShopUrl(),\n\t\t\t\tshop.getShopSecret(),\n\t\t\t\tshop.getShopClientId(),\n\t\t\t\tshop.getShopClientSecret(),\n\t\t\t\tshop.getShopActive(),\n\t\t\t\tshop.getShopId(),\n\t\t\t],\n\t\t);\n\t}\n\tasync deleteShop(id: string): Promise<void> {\n\t\tthis.db.exec(\"DELETE FROM shop where id = ?\", [id]);\n\t}\n}\n"]}
1
+ {"version":3,"file":"bun-sqlite.js","sourceRoot":"","sources":["../../../src/integration/bun-sqlite.ts"],"names":[],"mappings":"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","sourcesContent":["import { type ShopRepositoryInterface, SimpleShop } from \"../repository.js\";\n\nimport { Database } from \"bun:sqlite\";\n\nexport class BunSqliteRepository\n\timplements ShopRepositoryInterface<SimpleShop>\n{\n\tdb: Database;\n\tconstructor(fileName: string) {\n\t\tthis.db = new Database(fileName);\n\t\tthis.db.exec(\"PRAGMA journal_mode = WAL;\");\n\t\tthis.db.exec(`\n\t\tCREATE TABLE IF NOT EXISTS shop (\n\t\t id TEXT PRIMARY KEY,\n\t\t active BOOLEAN DEFAULT 1,\n\t\t url TEXT NOT NULL,\n\t\t secret TEXT NOT NULL,\n\t\t client_id TEXT NULL,\n\t\t client_secret TEXT NULL,\n\t\t pending_shop_url TEXT NULL,\n\t\t pending_shop_secret TEXT NULL,\n\t\t previous_shop_secret TEXT NULL,\n\t\t secrets_rotated_at INTEGER NULL,\n\t\t verified_with_double_signatures BOOLEAN DEFAULT 0,\n\t\t registration_confirmed BOOLEAN DEFAULT 0\n\t\t);\n\t `);\n\t}\n\n\tasync createShop(id: string, url: string, secret: string): Promise<void> {\n\t\tconst shop = await this.getShopById(id);\n\n\t\tif (shop) {\n\t\t\tawait this.deleteShop(id);\n\t\t}\n\n\t\tthis.db.exec(\"INSERT INTO shop (id, url, secret) VALUES (?, ?, ?)\", [\n\t\t\tid,\n\t\t\turl,\n\t\t\tsecret,\n\t\t]);\n\t}\n\n\tasync getShopById(id: string): Promise<SimpleShop | null> {\n\t\tconst query = this.db.query<\n\t\t\t{\n\t\t\t\tid: string;\n\t\t\t\tactive: boolean;\n\t\t\t\turl: string;\n\t\t\t\tsecret: string;\n\t\t\t\tclient_id?: string;\n\t\t\t\tclient_secret?: string;\n\t\t\t\tpending_shop_url?: string;\n\t\t\t\tpending_shop_secret?: string;\n\t\t\t\tprevious_shop_secret?: string;\n\t\t\t\tsecrets_rotated_at?: Date;\n\t\t\t\tverified_with_double_signatures?: number;\n\t\t\t\tregistration_confirmed?: number;\n\t\t\t},\n\t\t\tstring\n\t\t>(\"SELECT * FROM shop WHERE id = ?\");\n\t\tconst result = query.get(id);\n\n\t\tif (!result) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst shop = new SimpleShop(result.id, result.url, result.secret);\n\n\t\tif (result.client_id && result.client_secret) {\n\t\t\tshop.setShopCredentials(result.client_id, result.client_secret);\n\t\t}\n\n\t\tshop.setShopActive(result.active);\n\n\t\tif (result.pending_shop_url) {\n\t\t\tshop.setPendingShopUrl(result.pending_shop_url);\n\t\t}\n\n\t\tif (result.pending_shop_secret) {\n\t\t\tshop.setPendingShopSecret(result.pending_shop_secret);\n\t\t}\n\n\t\tif (result.previous_shop_secret) {\n\t\t\tshop.setPreviousShopSecret(result.previous_shop_secret);\n\t\t}\n\n\t\tif (result.secrets_rotated_at) {\n\t\t\tshop.setSecretsRotatedAt(new Date(Number(result.secrets_rotated_at)));\n\t\t}\n\n\t\tif (result.verified_with_double_signatures === 1) {\n\t\t\tshop.setVerifiedWithDoubleSignature();\n\t\t}\n\n\t\tif (result.registration_confirmed === 1) {\n\t\t\tshop.setRegistrationConfirmed();\n\t\t}\n\n\t\treturn shop;\n\t}\n\tasync updateShop(shop: SimpleShop): Promise<void> {\n\t\tthis.db.exec(\n\t\t\t\"UPDATE shop SET url = ?, secret = ?, client_id = ?, client_secret = ?, active = ?, pending_shop_url = ?, pending_shop_secret = ?, previous_shop_secret = ?, secrets_rotated_at = ?, verified_with_double_signatures = ?, registration_confirmed = ? WHERE id = ?\",\n\t\t\t[\n\t\t\t\tshop.getShopUrl(),\n\t\t\t\tshop.getShopSecret(),\n\t\t\t\tshop.getShopClientId(),\n\t\t\t\tshop.getShopClientSecret(),\n\t\t\t\tshop.getShopActive(),\n\t\t\t\tshop.getPendingShopUrl(),\n\t\t\t\tshop.getPendingShopSecret(),\n\t\t\t\tshop.getPreviousShopSecret(),\n\t\t\t\tshop.getSecretsRotatedAt()?.getTime() ?? null,\n\t\t\t\tshop.hasVerifiedWithDoubleSignature(),\n\t\t\t\tshop.isRegistrationConfirmed(),\n\t\t\t\tshop.getShopId(),\n\t\t\t],\n\t\t);\n\t}\n\tasync deleteShop(id: string): Promise<void> {\n\t\tthis.db.exec(\"DELETE FROM shop where id = ?\", [id]);\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"cloudflare-kv.d.ts","sourceRoot":"","sources":["../../../src/integration/cloudflare-kv.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,KAAK,EAAE,6BAA6B,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAEjG;;;GAGG;AACH,qBAAa,wBACZ,YAAW,uBAAuB,CAAC,UAAU,CAAC;IAElC,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,WAAW;IAIlC,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOlE,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQrC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAcnD,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAQjD,SAAS,CAAC,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM;IAIjD,SAAS,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,GAAG,UAAU;CA4B9D;AAED;;;GAGG;AACH,qBAAa,8BAA+B,YAAW,6BAA6B;IACvE,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,WAAW;IAIxC;;OAEG;IACG,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,GAAG,IAAI,CAAC;IAmBxE;;OAEG;IACG,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC;IAU9E;;OAEG;IACG,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG/C"}
1
+ {"version":3,"file":"cloudflare-kv.d.ts","sourceRoot":"","sources":["../../../src/integration/cloudflare-kv.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,KAAK,EAAE,6BAA6B,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAEjG;;;GAGG;AACH,qBAAa,wBACZ,YAAW,uBAAuB,CAAC,UAAU,CAAC;IAElC,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,WAAW;IAIlC,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOlE,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQrC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAcnD,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAQjD,SAAS,CAAC,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM;IASjD,SAAS,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,GAAG,UAAU;CAoD9D;AAED;;;GAGG;AACH,qBAAa,8BAA+B,YAAW,6BAA6B;IACvE,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,WAAW;IAIxC;;OAEG;IACG,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,GAAG,IAAI,CAAC;IAmBxE;;OAEG;IACG,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC;IAU9E;;OAEG;IACG,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG/C"}
@@ -42,7 +42,12 @@ export class CloudflareShopRepository {
42
42
  ]);
43
43
  }
44
44
  serializeShop(shop) {
45
- return JSON.stringify(shop);
45
+ return JSON.stringify({
46
+ ...shop,
47
+ secretsRotatedAt: shop.getSecretsRotatedAt()
48
+ ? shop.getSecretsRotatedAt().getTime()
49
+ : null,
50
+ });
46
51
  }
47
52
  deserializeShop(data) {
48
53
  const obj = JSON.parse(data[0]);
@@ -52,6 +57,18 @@ export class CloudflareShopRepository {
52
57
  obj.shopActive = true;
53
58
  }
54
59
  shop.setShopActive(obj.shopActive);
60
+ if (obj.pendingShopUrl) {
61
+ shop.setPendingShopUrl(obj.pendingShopUrl);
62
+ }
63
+ if (obj.pendingShopSecret) {
64
+ shop.setPendingShopSecret(obj.pendingShopSecret);
65
+ }
66
+ if (obj.previousShopSecret) {
67
+ shop.setPreviousShopSecret(obj.previousShopSecret);
68
+ }
69
+ if (obj.secretsRotatedAt) {
70
+ shop.setSecretsRotatedAt(new Date(Number(obj.secretsRotatedAt)));
71
+ }
55
72
  if (data[1] !== null) {
56
73
  shop.setShopActive(JSON.parse(data[1]));
57
74
  }
@@ -59,6 +76,12 @@ export class CloudflareShopRepository {
59
76
  const credentials = JSON.parse(data[2]);
60
77
  shop.setShopCredentials(credentials.clientId || "", credentials.clientSecret || "");
61
78
  }
79
+ if (obj.verified_with_double_signatures === 1) {
80
+ shop.setVerifiedWithDoubleSignature();
81
+ }
82
+ if (obj.registrationConfirmed === 1) {
83
+ shop.setRegistrationConfirmed();
84
+ }
62
85
  return shop;
63
86
  }
64
87
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cloudflare-kv.js","sourceRoot":"","sources":["../../../src/integration/cloudflare-kv.ts"],"names":[],"mappings":"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","sourcesContent":["/// <reference types=\"@cloudflare/workers-types\" />\nimport { SimpleShop } from \"../repository.js\";\nimport type { ShopRepositoryInterface } from \"../repository.js\";\nimport type { HttpClientTokenCacheInterface, HttpClientTokenCacheItem } from \"../http-client.js\";\n\n/**\n * Cloudflare KV integration\n * @module\n */\nexport class CloudflareShopRepository\n\timplements ShopRepositoryInterface<SimpleShop>\n{\n\tconstructor(private storage: KVNamespace) {\n\t\tthis.storage = storage;\n\t}\n\n\tasync createShop(id: string, url: string, secret: string): Promise<void> {\n\t\tawait Promise.all([\n this.storage.put(id, this.serializeShop(new SimpleShop(id, url, secret))),\n this.storage.put(`${id}_active`, JSON.stringify(false)),\n ])\n\t}\n\n\tasync deleteShop(id: string): Promise<void> {\n\t\tawait Promise.all([\n this.storage.delete(id),\n this.storage.delete(`${id}_active`),\n this.storage.delete(`${id}_credentials`)\n ])\n\t}\n\n\tasync getShopById(id: string): Promise<SimpleShop | null> {\n\t\tconst kvValues = await Promise.all([\n this.storage.get(id),\n this.storage.get(`${id}_active`),\n this.storage.get(`${id}_credentials`)\n ]);\n\n\t\tif (kvValues[0] === null) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn this.deserializeShop(kvValues);\n\t}\n\n\tasync updateShop(shop: SimpleShop): Promise<void> {\n\t\tawait Promise.all([\n this.storage.put(shop.getShopId(), this.serializeShop(shop)),\n this.storage.put(`${shop.getShopId()}_active`, JSON.stringify(shop.getShopActive())),\n this.storage.put(`${shop.getShopId()}_credentials`, JSON.stringify({ clientId: shop.getShopClientId(), clientSecret: shop.getShopClientSecret() }))\n ])\n\t}\n\n\tprotected serializeShop(shop: SimpleShop): string {\n\t\treturn JSON.stringify(shop);\n\t}\n\n\tprotected deserializeShop(data: (string | null)[]): SimpleShop {\n\t\tconst obj = JSON.parse(data[0]!);\n\n\t\tconst shop = new SimpleShop(\n\t\t\tobj.shopId || \"\",\n\t\t\tobj.shopUrl || \"\",\n\t\t\tobj.shopSecret || \"\",\n\t\t);\n\n\t\tshop.setShopCredentials(obj.shopClientId || \"\", obj.shopClientSecret || \"\");\n\n\t\tif (obj.shopActive === undefined) {\n\t\t\tobj.shopActive = true;\n\t\t}\n\n\t\tshop.setShopActive(obj.shopActive);\n\n\t\tif (data[1] !== null) {\n\t\t\tshop.setShopActive(JSON.parse(data[1]!));\n\t\t}\n\n\t\tif (data[2] !== null) {\n\t\t\tconst credentials = JSON.parse(data[2]!);\n\t\t\tshop.setShopCredentials(credentials.clientId || \"\", credentials.clientSecret || \"\");\n\t\t}\n\n\t\treturn shop;\n\t}\n}\n\n/**\n * Cloudflare KV implementation for HttpClientTokenCacheInterface\n * @module\n */\nexport class CloudflareHttpClientTokenCache implements HttpClientTokenCacheInterface {\n\tconstructor(private storage: KVNamespace) {\n\t\tthis.storage = storage;\n\t}\n\n\t/**\n\t * Get a token from KV storage for the given shop ID\n\t */\n\tasync getToken(shopId: string): Promise<HttpClientTokenCacheItem | null> {\n\t\tconst tokenData = await this.storage.get(`token_${shopId}`);\n\t\t\n\t\tif (tokenData === null) {\n\t\t\treturn null;\n\t\t}\n\n\t\ttry {\n\t\t\tconst parsedToken = JSON.parse(tokenData);\n\t\t\t// Convert the ISO string back to a Date object\n\t\t\treturn {\n\t\t\t\ttoken: parsedToken.token,\n\t\t\t\texpiresIn: new Date(parsedToken.expiresIn)\n\t\t\t};\n\t\t} catch (error) {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Store a token in KV storage for the given shop ID\n\t */\n\tasync setToken(shopId: string, token: HttpClientTokenCacheItem): Promise<void> {\n\t\t// Convert the Date object to an ISO string for storage\n\t\tconst tokenData = {\n\t\t\ttoken: token.token,\n\t\t\texpiresIn: token.expiresIn.toISOString()\n\t\t};\n\t\t\n\t\tawait this.storage.put(`token_${shopId}`, JSON.stringify(tokenData));\n\t}\n\n\t/**\n\t * Remove a token from KV storage for the given shop ID\n\t */\n\tasync clearToken(shopId: string): Promise<void> {\n\t\tawait this.storage.delete(`token_${shopId}`);\n\t}\n}\n"]}
1
+ {"version":3,"file":"cloudflare-kv.js","sourceRoot":"","sources":["../../../src/integration/cloudflare-kv.ts"],"names":[],"mappings":"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","sourcesContent":["/// <reference types=\"@cloudflare/workers-types\" />\nimport { SimpleShop } from \"../repository.js\";\nimport type { ShopRepositoryInterface } from \"../repository.js\";\nimport type { HttpClientTokenCacheInterface, HttpClientTokenCacheItem } from \"../http-client.js\";\n\n/**\n * Cloudflare KV integration\n * @module\n */\nexport class CloudflareShopRepository\n\timplements ShopRepositoryInterface<SimpleShop>\n{\n\tconstructor(private storage: KVNamespace) {\n\t\tthis.storage = storage;\n\t}\n\n\tasync createShop(id: string, url: string, secret: string): Promise<void> {\n\t\tawait Promise.all([\n\t\t\tthis.storage.put(id, this.serializeShop(new SimpleShop(id, url, secret))),\n\t\t\tthis.storage.put(`${id}_active`, JSON.stringify(false)),\n\t\t])\n\t}\n\n\tasync deleteShop(id: string): Promise<void> {\n\t\tawait Promise.all([\n\t\t\tthis.storage.delete(id),\n\t\t\tthis.storage.delete(`${id}_active`),\n\t\t\tthis.storage.delete(`${id}_credentials`)\n\t\t])\n\t}\n\n\tasync getShopById(id: string): Promise<SimpleShop | null> {\n\t\tconst kvValues = await Promise.all([\n\t\t\tthis.storage.get(id),\n\t\t\tthis.storage.get(`${id}_active`),\n\t\t\tthis.storage.get(`${id}_credentials`)\n\t\t]);\n\n\t\tif (kvValues[0] === null) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn this.deserializeShop(kvValues);\n\t}\n\n\tasync updateShop(shop: SimpleShop): Promise<void> {\n\t\tawait Promise.all([\n\t\t\tthis.storage.put(shop.getShopId(), this.serializeShop(shop)),\n\t\t\tthis.storage.put(`${shop.getShopId()}_active`, JSON.stringify(shop.getShopActive())),\n\t\t\tthis.storage.put(`${shop.getShopId()}_credentials`, JSON.stringify({ clientId: shop.getShopClientId(), clientSecret: shop.getShopClientSecret() }))\n\t\t])\n\t}\n\n\tprotected serializeShop(shop: SimpleShop): string {\n\t\treturn JSON.stringify({\n\t\t\t...shop,\n\t\t\tsecretsRotatedAt: shop.getSecretsRotatedAt()\n\t\t\t\t? shop.getSecretsRotatedAt()!.getTime()\n\t\t\t\t: null,\n\t\t});\n\t}\n\n\tprotected deserializeShop(data: (string | null)[]): SimpleShop {\n\t\tconst obj = JSON.parse(data[0]!);\n\n\t\tconst shop = new SimpleShop(\n\t\t\tobj.shopId || \"\",\n\t\t\tobj.shopUrl || \"\",\n\t\t\tobj.shopSecret || \"\",\n\t\t);\n\n\t\tshop.setShopCredentials(obj.shopClientId || \"\", obj.shopClientSecret || \"\");\n\n\t\tif (obj.shopActive === undefined) {\n\t\t\tobj.shopActive = true;\n\t\t}\n\n\t\tshop.setShopActive(obj.shopActive);\n\n\t\tif (obj.pendingShopUrl) {\n\t\t\tshop.setPendingShopUrl(obj.pendingShopUrl);\n\t\t}\n\n\t\tif (obj.pendingShopSecret) {\n\t\t\tshop.setPendingShopSecret(obj.pendingShopSecret);\n\t\t}\n\n\t\tif (obj.previousShopSecret) {\n\t\t\tshop.setPreviousShopSecret(obj.previousShopSecret);\n\t\t}\n\n\t\tif (obj.secretsRotatedAt) {\n\t\t\tshop.setSecretsRotatedAt(new Date(Number(obj.secretsRotatedAt)));\n\t\t}\n\n\t\tif (data[1] !== null) {\n\t\t\tshop.setShopActive(JSON.parse(data[1]!));\n\t\t}\n\n\t\tif (data[2] !== null) {\n\t\t\tconst credentials = JSON.parse(data[2]!);\n\t\t\tshop.setShopCredentials(credentials.clientId || \"\", credentials.clientSecret || \"\");\n\t\t}\n\n\t\tif (obj.verified_with_double_signatures === 1) {\n\t\t\tshop.setVerifiedWithDoubleSignature();\n\t\t}\n\n\t\tif (obj.registrationConfirmed === 1) {\n\t\t\tshop.setRegistrationConfirmed();\n\t\t}\n\n\t\treturn shop;\n\t}\n}\n\n/**\n * Cloudflare KV implementation for HttpClientTokenCacheInterface\n * @module\n */\nexport class CloudflareHttpClientTokenCache implements HttpClientTokenCacheInterface {\n\tconstructor(private storage: KVNamespace) {\n\t\tthis.storage = storage;\n\t}\n\n\t/**\n\t * Get a token from KV storage for the given shop ID\n\t */\n\tasync getToken(shopId: string): Promise<HttpClientTokenCacheItem | null> {\n\t\tconst tokenData = await this.storage.get(`token_${shopId}`);\n\t\t\n\t\tif (tokenData === null) {\n\t\t\treturn null;\n\t\t}\n\n\t\ttry {\n\t\t\tconst parsedToken = JSON.parse(tokenData);\n\t\t\t// Convert the ISO string back to a Date object\n\t\t\treturn {\n\t\t\t\ttoken: parsedToken.token,\n\t\t\t\texpiresIn: new Date(parsedToken.expiresIn)\n\t\t\t};\n\t\t} catch (error) {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Store a token in KV storage for the given shop ID\n\t */\n\tasync setToken(shopId: string, token: HttpClientTokenCacheItem): Promise<void> {\n\t\t// Convert the Date object to an ISO string for storage\n\t\tconst tokenData = {\n\t\t\ttoken: token.token,\n\t\t\texpiresIn: token.expiresIn.toISOString()\n\t\t};\n\t\t\n\t\tawait this.storage.put(`token_${shopId}`, JSON.stringify(tokenData));\n\t}\n\n\t/**\n\t * Remove a token from KV storage for the given shop ID\n\t */\n\tasync clearToken(shopId: string): Promise<void> {\n\t\tawait this.storage.delete(`token_${shopId}`);\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"deno-kv.d.ts","sourceRoot":"","sources":["../../../src/integration/deno-kv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAEhE;;;GAGG;AAEH;;GAEG;AACH,qBAAa,gBAAiB,YAAW,uBAAuB,CAAC,UAAU,CAAC;IAC/D,OAAO,CAAC,SAAS;gBAAT,SAAS,SAAU;IAEjC,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOlE,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAiCnD,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAO3C,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAM3C"}
1
+ {"version":3,"file":"deno-kv.d.ts","sourceRoot":"","sources":["../../../src/integration/deno-kv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAEhE;;;GAGG;AAEH;;GAEG;AACH,qBAAa,gBAAiB,YAAW,uBAAuB,CAAC,UAAU,CAAC;IAC/D,OAAO,CAAC,SAAS;gBAAT,SAAS,SAAU;IAEjC,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOlE,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IA+DnD,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAO3C,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAM3C"}
@@ -32,6 +32,24 @@ export class DenoKVRepository {
32
32
  if (data.shopClientId && data.shopClientSecret) {
33
33
  shop.setShopCredentials(data.shopClientId, data.shopClientSecret);
34
34
  }
35
+ if (data.pendingShopUrl) {
36
+ shop.setPendingShopUrl(data.pendingShopUrl);
37
+ }
38
+ if (data.pendingShopSecret) {
39
+ shop.setPendingShopSecret(data.pendingShopSecret);
40
+ }
41
+ if (data.previousShopSecret) {
42
+ shop.setPreviousShopSecret(data.previousShopSecret);
43
+ }
44
+ if (data.secretsRotatedAt) {
45
+ shop.setSecretsRotatedAt(new Date(Number(data.secretsRotatedAt)));
46
+ }
47
+ if (data.verifiedWithDoubleSignature) {
48
+ shop.setVerifiedWithDoubleSignature();
49
+ }
50
+ if (data.registrationConfirmed) {
51
+ shop.setRegistrationConfirmed();
52
+ }
35
53
  return shop;
36
54
  }
37
55
  async updateShop(shop) {
@@ -1 +1 @@
1
- {"version":3,"file":"deno-kv.js","sourceRoot":"","sources":["../../../src/integration/deno-kv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C;;;GAGG;AAEH;;GAEG;AACH,MAAM,OAAO,gBAAgB;IACR;IAApB,YAAoB,YAAY,OAAO;QAAnB,cAAS,GAAT,SAAS,CAAU;IAAG,CAAC;IAE3C,KAAK,CAAC,UAAU,CAAC,EAAU,EAAE,GAAW,EAAE,MAAc;QACvD,aAAa;QACb,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QAE/B,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC,EAAE,IAAI,UAAU,CAAC,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;IACrE,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,EAAU;QAC3B,aAAa;QACb,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QAE/B,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC;QAElD,IAAI,MAAM,CAAC,GAAG,KAAK,IAAI,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC;QACb,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,KAOnB,CAAC;QAEF,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YACnC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACxB,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QACxE,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAEpC,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAChD,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;QACnE,CAAC;QAED,OAAO,IAAI,CAAC;IACb,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,IAAgB;QAChC,aAAa;QACb,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QAE/B,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,EAAU;QAC1B,aAAa;QACb,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QAE/B,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC;IACvC,CAAC;CACD","sourcesContent":["import { SimpleShop } from \"../repository.js\";\nimport type { ShopRepositoryInterface } from \"../repository.js\";\n\n/**\n * Deno KV integration\n * @module\n */\n\n/**\n * DenoKVRepository is a ShopRepositoryInterface implementation that uses the Deno KV storage to save the shop data\n */\nexport class DenoKVRepository implements ShopRepositoryInterface<SimpleShop> {\n\tconstructor(private namespace = \"shops\") {}\n\n\tasync createShop(id: string, url: string, secret: string): Promise<void> {\n\t\t// @ts-ignore\n\t\tconst kv = await Deno.openKv();\n\n\t\tawait kv.set([this.namespace, id], new SimpleShop(id, url, secret));\n\t}\n\n\tasync getShopById(id: string): Promise<SimpleShop | null> {\n\t\t// @ts-ignore\n\t\tconst kv = await Deno.openKv();\n\n\t\tconst result = await kv.get([this.namespace, id]);\n\n\t\tif (result.key === null) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst data = result.value as {\n\t\t\tshopId: string;\n\t\t\tshopActive: boolean | undefined;\n\t\t\tshopUrl: string;\n\t\t\tshopSecret: string;\n\t\t\tshopClientId: string | null;\n\t\t\tshopClientSecret: string | null;\n\t\t};\n\n\t\tif (data.shopActive === undefined) {\n\t\t\tdata.shopActive = true;\n\t\t}\n\n\t\tconst shop = new SimpleShop(data.shopId, data.shopUrl, data.shopSecret);\n\t\tshop.setShopActive(data.shopActive);\n\n\t\tif (data.shopClientId && data.shopClientSecret) {\n\t\t\tshop.setShopCredentials(data.shopClientId, data.shopClientSecret);\n\t\t}\n\n\t\treturn shop;\n\t}\n\n\tasync updateShop(shop: SimpleShop): Promise<void> {\n\t\t// @ts-ignore\n\t\tconst kv = await Deno.openKv();\n\n\t\tawait kv.set([this.namespace, shop.getShopId()], shop);\n\t}\n\n\tasync deleteShop(id: string): Promise<void> {\n\t\t// @ts-ignore\n\t\tconst kv = await Deno.openKv();\n\n\t\tawait kv.delete([this.namespace, id]);\n\t}\n}\n"]}
1
+ {"version":3,"file":"deno-kv.js","sourceRoot":"","sources":["../../../src/integration/deno-kv.ts"],"names":[],"mappings":"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","sourcesContent":["import { SimpleShop } from \"../repository.js\";\nimport type { ShopRepositoryInterface } from \"../repository.js\";\n\n/**\n * Deno KV integration\n * @module\n */\n\n/**\n * DenoKVRepository is a ShopRepositoryInterface implementation that uses the Deno KV storage to save the shop data\n */\nexport class DenoKVRepository implements ShopRepositoryInterface<SimpleShop> {\n\tconstructor(private namespace = \"shops\") {}\n\n\tasync createShop(id: string, url: string, secret: string): Promise<void> {\n\t\t// @ts-ignore\n\t\tconst kv = await Deno.openKv();\n\n\t\tawait kv.set([this.namespace, id], new SimpleShop(id, url, secret));\n\t}\n\n\tasync getShopById(id: string): Promise<SimpleShop | null> {\n\t\t// @ts-ignore\n\t\tconst kv = await Deno.openKv();\n\n\t\tconst result = await kv.get([this.namespace, id]);\n\n\t\tif (result.key === null) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst data = result.value as {\n\t\t\tshopId: string;\n\t\t\tshopActive: boolean | undefined;\n\t\t\tshopUrl: string;\n\t\t\tshopSecret: string;\n\t\t\tshopClientId: string | null;\n\t\t\tshopClientSecret: string | null;\n\t\t\tpendingShopUrl: string | null;\n\t\t\tpendingShopSecret: string | null;\n\t\t\tpreviousShopSecret: string | null;\n\t\t\tsecretsRotatedAt: number | null;\n\t\t\tverifiedWithDoubleSignature: boolean | undefined;\n\t\t\tregistrationConfirmed: boolean | undefined;\n\t\t};\n\n\t\tif (data.shopActive === undefined) {\n\t\t\tdata.shopActive = true;\n\t\t}\n\n\t\tconst shop = new SimpleShop(data.shopId, data.shopUrl, data.shopSecret);\n\t\tshop.setShopActive(data.shopActive);\n\n\t\tif (data.shopClientId && data.shopClientSecret) {\n\t\t\tshop.setShopCredentials(data.shopClientId, data.shopClientSecret);\n\t\t}\n\n\t\tif (data.pendingShopUrl) {\n\t\t\tshop.setPendingShopUrl(data.pendingShopUrl);\n\t\t}\n\n\t\tif (data.pendingShopSecret) {\n\t\t\tshop.setPendingShopSecret(data.pendingShopSecret);\n\t\t}\n\n\t\tif (data.previousShopSecret) {\n\t\t\tshop.setPreviousShopSecret(data.previousShopSecret);\n\t\t}\n\n\t\tif (data.secretsRotatedAt) {\n\t\t\tshop.setSecretsRotatedAt(new Date(Number(data.secretsRotatedAt)));\n\t\t}\n\n\t\tif (data.verifiedWithDoubleSignature) {\n\t\t\tshop.setVerifiedWithDoubleSignature();\n\t\t}\n\n\t\tif (data.registrationConfirmed) {\n\t\t\tshop.setRegistrationConfirmed();\n\t\t}\n\n\t\treturn shop;\n\t}\n\n\tasync updateShop(shop: SimpleShop): Promise<void> {\n\t\t// @ts-ignore\n\t\tconst kv = await Deno.openKv();\n\n\t\tawait kv.set([this.namespace, shop.getShopId()], shop);\n\t}\n\n\tasync deleteShop(id: string): Promise<void> {\n\t\t// @ts-ignore\n\t\tconst kv = await Deno.openKv();\n\n\t\tawait kv.delete([this.namespace, id]);\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"dynamodb.d.ts","sourceRoot":"","sources":["../../../src/integration/dynamodb.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAEN,sBAAsB,EAItB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,KAAK,uBAAuB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE5E,qBAAa,kBAAmB,YAAW,uBAAuB,CAAC,UAAU,CAAC;IAC7E,SAAS,EAAE,sBAAsB,CAAC;IAClC,SAAS,EAAE,MAAM,CAAC;gBAEN,MAAM,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM;IAK/C,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBlE,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAoCnD,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAqB3C,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAU3C"}
1
+ {"version":3,"file":"dynamodb.d.ts","sourceRoot":"","sources":["../../../src/integration/dynamodb.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAEN,sBAAsB,EAItB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,KAAK,uBAAuB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE5E,qBAAa,kBAAmB,YAAW,uBAAuB,CAAC,UAAU,CAAC;IAC7E,SAAS,EAAE,sBAAsB,CAAC;IAClC,SAAS,EAAE,MAAM,CAAC;gBAEN,MAAM,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM;IAK/C,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBlE,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IA4DnD,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IA2B3C,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAU3C"}
@@ -17,6 +17,12 @@ export class DynamoDBRepository {
17
17
  secret: secret,
18
18
  clientId: null,
19
19
  clientSecret: null,
20
+ pendingShopUrl: null,
21
+ pendingShopSecret: null,
22
+ previousShopSecret: null,
23
+ secretsRotatedAt: null,
24
+ verifiedWithDoubleSignature: null,
25
+ registrationConfirmed: false,
20
26
  },
21
27
  });
22
28
  await this.docClient.send(cmd);
@@ -40,13 +46,31 @@ export class DynamoDBRepository {
40
46
  if (response.Item.clientId) {
41
47
  shop.setShopCredentials(response.Item.clientId, response.Item.clientSecret);
42
48
  }
49
+ if (response.Item.pendingShopUrl) {
50
+ shop.setPendingShopUrl(response.Item.pendingShopUrl);
51
+ }
52
+ if (response.Item.pendingShopSecret) {
53
+ shop.setPendingShopSecret(response.Item.pendingShopSecret);
54
+ }
55
+ if (response.Item.previousShopSecret) {
56
+ shop.setPreviousShopSecret(response.Item.previousShopSecret);
57
+ }
58
+ if (response.Item.secretsRotatedAt) {
59
+ shop.setSecretsRotatedAt(new Date(Number(response.Item.secretsRotatedAt)));
60
+ }
61
+ if (response.Item.verifiedWithDoubleSignature) {
62
+ shop.setVerifiedWithDoubleSignature();
63
+ }
64
+ if (response.Item.registrationConfirmed) {
65
+ shop.setRegistrationConfirmed();
66
+ }
43
67
  return shop;
44
68
  }
45
69
  async updateShop(shop) {
46
70
  const cmd = new UpdateCommand({
47
71
  TableName: this.tableName,
48
72
  Key: { id: shop.getShopId() },
49
- UpdateExpression: "SET active = :active, #u = :url, secret = :secret, clientId = :clientId, clientSecret = :clientSecret",
73
+ UpdateExpression: "SET active = :active, #u = :url, secret = :secret, clientId = :clientId, clientSecret = :clientSecret, pendingShopUrl = :pendingShopUrl, pendingShopSecret = :pendingShopSecret, previousShopSecret = :previousShopSecret, secretsRotatedAt = :secretsRotatedAt, verifiedWithDoubleSignature = :verifiedWithDoubleSignature, registrationConfirmed = :registrationConfirmed",
50
74
  ExpressionAttributeNames: {
51
75
  "#u": "url",
52
76
  },
@@ -56,6 +80,12 @@ export class DynamoDBRepository {
56
80
  ":secret": shop.getShopSecret(),
57
81
  ":clientId": shop.getShopClientId(),
58
82
  ":clientSecret": shop.getShopClientSecret(),
83
+ ":pendingShopUrl": shop.getPendingShopUrl(),
84
+ ":pendingShopSecret": shop.getPendingShopSecret(),
85
+ ":previousShopSecret": shop.getPreviousShopSecret(),
86
+ ":secretsRotatedAt": shop.getSecretsRotatedAt()?.getTime() ?? null,
87
+ ":verifiedWithDoubleSignature": shop.hasVerifiedWithDoubleSignature(),
88
+ ":registrationConfirmed": shop.isRegistrationConfirmed(),
59
89
  },
60
90
  });
61
91
  await this.docClient.send(cmd);
@@ -1 +1 @@
1
- {"version":3,"file":"dynamodb.js","sourceRoot":"","sources":["../../../src/integration/dynamodb.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DynamoDBClient } from \"@aws-sdk/client-dynamodb\";\nimport {\n\tDeleteCommand,\n\tDynamoDBDocumentClient,\n\tGetCommand,\n\tPutCommand,\n\tUpdateCommand,\n} from \"@aws-sdk/lib-dynamodb\";\nimport { type ShopRepositoryInterface, SimpleShop } from \"../repository.js\";\n\nexport class DynamoDBRepository implements ShopRepositoryInterface<SimpleShop> {\n\tdocClient: DynamoDBDocumentClient;\n\ttableName: string;\n\n\tconstructor(client: DynamoDBClient, tableName: string) {\n\t\tthis.tableName = tableName;\n\t\tthis.docClient = DynamoDBDocumentClient.from(client);\n\t}\n\n\tasync createShop(id: string, url: string, secret: string): Promise<void> {\n\t\tconst cmd = new PutCommand({\n\t\t\tTableName: this.tableName,\n\t\t\tItem: {\n\t\t\t\tid: id,\n\t\t\t\tactive: false,\n\t\t\t\turl: url,\n\t\t\t\tsecret: secret,\n\t\t\t\tclientId: null,\n\t\t\t\tclientSecret: null,\n\t\t\t},\n\t\t});\n\n\t\tawait this.docClient.send(cmd);\n\t}\n\n\tasync getShopById(id: string): Promise<SimpleShop | null> {\n\t\tconst cmd = new GetCommand({\n\t\t\tTableName: this.tableName,\n\t\t\tKey: {\n\t\t\t\tid: id,\n\t\t\t},\n\t\t});\n\n\t\tconst response = await this.docClient.send(cmd);\n\n\t\tif (!response.Item) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst shop = new SimpleShop(\n\t\t\tresponse.Item.id,\n\t\t\tresponse.Item.url,\n\t\t\tresponse.Item.secret,\n\t\t);\n\n\t\tif (response.Item.active === undefined) {\n\t\t\tresponse.Item.active = true;\n\t\t}\n\n\t\tshop.setShopActive(response.Item.active);\n\n\t\tif (response.Item.clientId) {\n\t\t\tshop.setShopCredentials(\n\t\t\t\tresponse.Item.clientId,\n\t\t\t\tresponse.Item.clientSecret,\n\t\t\t);\n\t\t}\n\n\t\treturn shop;\n\t}\n\n\tasync updateShop(shop: SimpleShop): Promise<void> {\n\t\tconst cmd = new UpdateCommand({\n\t\t\tTableName: this.tableName,\n\t\t\tKey: { id: shop.getShopId() },\n\t\t\tUpdateExpression:\n\t\t\t\t\"SET active = :active, #u = :url, secret = :secret, clientId = :clientId, clientSecret = :clientSecret\",\n\t\t\tExpressionAttributeNames: {\n\t\t\t\t\"#u\": \"url\",\n\t\t\t},\n\t\t\tExpressionAttributeValues: {\n\t\t\t\t\":active\": shop.getShopActive(),\n\t\t\t\t\":url\": shop.getShopUrl(),\n\t\t\t\t\":secret\": shop.getShopSecret(),\n\t\t\t\t\":clientId\": shop.getShopClientId(),\n\t\t\t\t\":clientSecret\": shop.getShopClientSecret(),\n\t\t\t},\n\t\t});\n\n\t\tawait this.docClient.send(cmd);\n\t}\n\n\tasync deleteShop(id: string): Promise<void> {\n\t\tconst cmd = new DeleteCommand({\n\t\t\tTableName: this.tableName,\n\t\t\tKey: {\n\t\t\t\tid: id,\n\t\t\t},\n\t\t});\n\n\t\tawait this.docClient.send(cmd);\n\t}\n}\n"]}
1
+ {"version":3,"file":"dynamodb.js","sourceRoot":"","sources":["../../../src/integration/dynamodb.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DynamoDBClient } from \"@aws-sdk/client-dynamodb\";\nimport {\n\tDeleteCommand,\n\tDynamoDBDocumentClient,\n\tGetCommand,\n\tPutCommand,\n\tUpdateCommand,\n} from \"@aws-sdk/lib-dynamodb\";\nimport { type ShopRepositoryInterface, SimpleShop } from \"../repository.js\";\n\nexport class DynamoDBRepository implements ShopRepositoryInterface<SimpleShop> {\n\tdocClient: DynamoDBDocumentClient;\n\ttableName: string;\n\n\tconstructor(client: DynamoDBClient, tableName: string) {\n\t\tthis.tableName = tableName;\n\t\tthis.docClient = DynamoDBDocumentClient.from(client);\n\t}\n\n\tasync createShop(id: string, url: string, secret: string): Promise<void> {\n\t\tconst cmd = new PutCommand({\n\t\t\tTableName: this.tableName,\n\t\t\tItem: {\n\t\t\t\tid: id,\n\t\t\t\tactive: false,\n\t\t\t\turl: url,\n\t\t\t\tsecret: secret,\n\t\t\t\tclientId: null,\n\t\t\t\tclientSecret: null,\n\t\t\t\tpendingShopUrl: null,\n\t\t\t\tpendingShopSecret: null,\n\t\t\t\tpreviousShopSecret: null,\n\t\t\t\tsecretsRotatedAt: null,\n\t\t\t\tverifiedWithDoubleSignature: null,\n\t\t\t\tregistrationConfirmed: false,\n\t\t\t},\n\t\t});\n\n\t\tawait this.docClient.send(cmd);\n\t}\n\n\tasync getShopById(id: string): Promise<SimpleShop | null> {\n\t\tconst cmd = new GetCommand({\n\t\t\tTableName: this.tableName,\n\t\t\tKey: {\n\t\t\t\tid: id,\n\t\t\t},\n\t\t});\n\n\t\tconst response = await this.docClient.send(cmd);\n\n\t\tif (!response.Item) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst shop = new SimpleShop(\n\t\t\tresponse.Item.id,\n\t\t\tresponse.Item.url,\n\t\t\tresponse.Item.secret,\n\t\t);\n\n\t\tif (response.Item.active === undefined) {\n\t\t\tresponse.Item.active = true;\n\t\t}\n\n\t\tshop.setShopActive(response.Item.active);\n\n\t\tif (response.Item.clientId) {\n\t\t\tshop.setShopCredentials(\n\t\t\t\tresponse.Item.clientId,\n\t\t\t\tresponse.Item.clientSecret,\n\t\t\t);\n\t\t}\n\n\t\tif (response.Item.pendingShopUrl) {\n\t\t\tshop.setPendingShopUrl(response.Item.pendingShopUrl);\n\t\t}\n\n\t\tif (response.Item.pendingShopSecret) {\n\t\t\tshop.setPendingShopSecret(response.Item.pendingShopSecret);\n\t\t}\n\n\t\tif (response.Item.previousShopSecret) {\n\t\t\tshop.setPreviousShopSecret(response.Item.previousShopSecret);\n\t\t}\n\n\t\tif (response.Item.secretsRotatedAt) {\n\t\t\tshop.setSecretsRotatedAt(new Date(Number(response.Item.secretsRotatedAt)));\n\t\t}\n\n\t\tif (response.Item.verifiedWithDoubleSignature) {\n\t\t\tshop.setVerifiedWithDoubleSignature();\n\t\t}\n\n\t\tif (response.Item.registrationConfirmed) {\n\t\t\tshop.setRegistrationConfirmed();\n\t\t}\n\n\t\treturn shop;\n\t}\n\n\tasync updateShop(shop: SimpleShop): Promise<void> {\n\t\tconst cmd = new UpdateCommand({\n\t\t\tTableName: this.tableName,\n\t\t\tKey: { id: shop.getShopId() },\n\t\t\tUpdateExpression:\n\t\t\t\t\"SET active = :active, #u = :url, secret = :secret, clientId = :clientId, clientSecret = :clientSecret, pendingShopUrl = :pendingShopUrl, pendingShopSecret = :pendingShopSecret, previousShopSecret = :previousShopSecret, secretsRotatedAt = :secretsRotatedAt, verifiedWithDoubleSignature = :verifiedWithDoubleSignature, registrationConfirmed = :registrationConfirmed\",\n\t\t\tExpressionAttributeNames: {\n\t\t\t\t\"#u\": \"url\",\n\t\t\t},\n\t\t\tExpressionAttributeValues: {\n\t\t\t\t\":active\": shop.getShopActive(),\n\t\t\t\t\":url\": shop.getShopUrl(),\n\t\t\t\t\":secret\": shop.getShopSecret(),\n\t\t\t\t\":clientId\": shop.getShopClientId(),\n\t\t\t\t\":clientSecret\": shop.getShopClientSecret(),\n\t\t\t\t\":pendingShopUrl\": shop.getPendingShopUrl(),\n\t\t\t\t\":pendingShopSecret\": shop.getPendingShopSecret(),\n\t\t\t\t\":previousShopSecret\": shop.getPreviousShopSecret(),\n\t\t\t\t\":secretsRotatedAt\": shop.getSecretsRotatedAt()?.getTime() ?? null,\n\t\t\t\t\":verifiedWithDoubleSignature\": shop.hasVerifiedWithDoubleSignature(),\n\t\t\t\t\":registrationConfirmed\": shop.isRegistrationConfirmed(),\n\t\t\t},\n\t\t});\n\n\t\tawait this.docClient.send(cmd);\n\t}\n\n\tasync deleteShop(id: string): Promise<void> {\n\t\tconst cmd = new DeleteCommand({\n\t\t\tTableName: this.tableName,\n\t\t\tKey: {\n\t\t\t\tid: id,\n\t\t\t},\n\t\t});\n\n\t\tawait this.docClient.send(cmd);\n\t}\n}\n"]}
@@ -27,6 +27,12 @@ interface MiddlewareConfigBase {
27
27
  * @default "/app/register/confirm"
28
28
  */
29
29
  registerConfirmationUrl?: string | null;
30
+ /**
31
+ * When true, registration requires both app and shop signatures during re-registration and confirmation.
32
+ *
33
+ * @default true
34
+ */
35
+ enforceDoubleSignature?: boolean;
30
36
  /**
31
37
  * The relative url of the app installation lifecycle endpoint
32
38
  *
@@ -1 +1 @@
1
- {"version":3,"file":"hono.d.ts","sourceRoot":"","sources":["../../../src/integration/hono.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAE/E,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,MAAM,CAAC;AACzD,OAAO,EAAc,KAAK,6BAA6B,EAAE,MAAM,mBAAmB,CAAC;AAEnF,OAAO,QAAQ,MAAM,CAAC;IACrB,UAAU,kBAAkB;QAE3B,GAAG,EAAE,SAAS,CAAC,aAAa,CAAC,CAAC;QAC9B,IAAI,EAAE,aAAa,CAAC;QAEpB,OAAO,EAAE,OAAO,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;KACzC;CACD;AAGD,UAAU,oBAAoB;IAC7B;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEvB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEhC;;;;OAIG;IACH,uBAAuB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAExC;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE9B;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE/B;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE7B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEjC;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE7B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAExB;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE9B;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC5C;AAGD,UAAU,eAAe;IACxB;;OAEG;IACH,SAAS,EAAE,SAAS,CAAC;CACrB;AAED,UAAU,gBAAgB;IACzB;;OAEG;IACH,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,WAAW,KAAK,MAAM,CAAC,CAAC;IAC/C;;OAEG;IACH,SAAS,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,WAAW,KAAK,MAAM,CAAC,CAAC;IACjD;;OAEG;IACH,cAAc,EACX,uBAAuB,GACvB,CAAC,CAAC,CAAC,EAAE,WAAW,KAAK,uBAAuB,CAAC,CAAC;IAEjD;;OAEG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IAEtB;;OAEG;IACH,oBAAoB,CAAC,EAAE,6BAA6B,GAAG,CAAC,CAAC,CAAC,EAAE,WAAW,KAAK,6BAA6B,CAAC,CAAC;IAE3G;;OAEG;IACH,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,IAAI,CAAC;CACjC;AAGD,KAAK,gBAAgB,GAClB,CAAC,oBAAoB,GAAG,eAAe,CAAC,GACxC,CAAC,oBAAoB,GAAG,gBAAgB,CAAC,CAAC;AAE7C;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,gBAAgB,QAwMnE"}
1
+ {"version":3,"file":"hono.d.ts","sourceRoot":"","sources":["../../../src/integration/hono.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAE/E,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,MAAM,CAAC;AACzD,OAAO,EAAc,KAAK,6BAA6B,EAAE,MAAM,mBAAmB,CAAC;AAEnF,OAAO,QAAQ,MAAM,CAAC;IACrB,UAAU,kBAAkB;QAE3B,GAAG,EAAE,SAAS,CAAC,aAAa,CAAC,CAAC;QAC9B,IAAI,EAAE,aAAa,CAAC;QAEpB,OAAO,EAAE,OAAO,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;KACzC;CACD;AAGD,UAAU,oBAAoB;IAC7B;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEvB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEhC;;;;OAIG;IACH,uBAAuB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAExC;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE9B;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE/B;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE7B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEjC;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE7B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAExB;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE9B;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC5C;AAGD,UAAU,eAAe;IACxB;;OAEG;IACH,SAAS,EAAE,SAAS,CAAC;CACrB;AAED,UAAU,gBAAgB;IACzB;;OAEG;IACH,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,WAAW,KAAK,MAAM,CAAC,CAAC;IAC/C;;OAEG;IACH,SAAS,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,WAAW,KAAK,MAAM,CAAC,CAAC;IACjD;;OAEG;IACH,cAAc,EACX,uBAAuB,GACvB,CAAC,CAAC,CAAC,EAAE,WAAW,KAAK,uBAAuB,CAAC,CAAC;IAEjD;;OAEG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IAEtB;;OAEG;IACH,oBAAoB,CAAC,EAAE,6BAA6B,GAAG,CAAC,CAAC,CAAC,EAAE,WAAW,KAAK,6BAA6B,CAAC,CAAC;IAE3G;;OAEG;IACH,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,IAAI,CAAC;CACjC;AAGD,KAAK,gBAAgB,GAClB,CAAC,oBAAoB,GAAG,eAAe,CAAC,GACxC,CAAC,oBAAoB,GAAG,gBAAgB,CAAC,CAAC;AAE7C;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,gBAAgB,QA+MnE"}
@@ -40,6 +40,7 @@ export function configureAppServer(hono, cfg) {
40
40
  appName: cfg.appName,
41
41
  appSecret: cfg.appSecret,
42
42
  authorizeCallbackUrl: appUrl + cfg.registerConfirmationUrl,
43
+ enforceDoubleSignature: cfg.enforceDoubleSignature ?? false,
43
44
  }, cfg.shopRepository, cfg.httpClientTokenCache);
44
45
  if (cfg.setup) {
45
46
  cfg.setup(app);
@@ -140,7 +141,12 @@ export function configureAppServer(hono, cfg) {
140
141
  }
141
142
  redirect = newUrl.toString();
142
143
  }
143
- await setSignedCookie(ctx, "shop", ctx.get("shop").getShopId(), ctx.get("app").cfg.appSecret);
144
+ await setSignedCookie(ctx, "shop", ctx.get("shop").getShopId(), ctx.get("app").cfg.appSecret, {
145
+ path: "/",
146
+ secure: true,
147
+ sameSite: "None",
148
+ partitioned: true,
149
+ });
144
150
  return ctx.redirect(redirect);
145
151
  });
146
152
  }