@thorprovider/adapters 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +18 -0
- package/.turbo/turbo-test.log +1 -0
- package/.turbo/turbo-type-check.log +0 -0
- package/AGENTS.md +1 -0
- package/CHANGELOG.md +271 -0
- package/README.md +634 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/index.d.mts +2524 -0
- package/dist/index.d.ts +2524 -0
- package/dist/index.js +8136 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +8045 -0
- package/dist/index.mjs.map +1 -0
- package/docs/RETRY_SOLUTION_SUMMARY.md +55 -0
- package/docs/authentication.md +165 -0
- package/docs/capabilities-system.md +143 -0
- package/docs/category-customization.md +309 -0
- package/docs/fetch-reliability-solution.md +399 -0
- package/docs/getting-started.md +154 -0
- package/docs/multi-tenant-channel-scoping.md +225 -0
- package/docs/profile-management.md +147 -0
- package/docs/providers-overview.md +85 -0
- package/docs/services-overview.md +135 -0
- package/docs/update-documentation.md +113 -0
- package/package.json +43 -0
- package/publish.log +93 -0
- package/quick-reference.md +169 -0
- package/src/admin/AdminAuthService.ts +88 -0
- package/src/admin/AdminSessionService.ts +91 -0
- package/src/admin/MetricsService.ts +145 -0
- package/src/admin/index.ts +13 -0
- package/src/backend/BackendMetadataAdapter.ts +88 -0
- package/src/backend/factory.ts +107 -0
- package/src/backend/index.ts +12 -0
- package/src/backend/medusa/MedusaMetadataAdapter.ts +139 -0
- package/src/core/errors.js +161 -0
- package/src/core/errors.ts +132 -0
- package/src/core/fetch-utils.js +240 -0
- package/src/core/fetch-utils.ts +227 -0
- package/src/core/index.ts +8 -0
- package/src/core/logger.js +63 -0
- package/src/core/logger.ts +37 -0
- package/src/factory/index.ts +102 -0
- package/src/index.ts +205 -0
- package/src/lib/money-transform.ts +80 -0
- package/src/metadata/channel-scope-validation.js +136 -0
- package/src/metadata/channel-scope-validation.ts +151 -0
- package/src/metadata/channel-scope.js +174 -0
- package/src/metadata/channel-scope.ts +215 -0
- package/src/metadata/index.js +31 -0
- package/src/metadata/index.ts +37 -0
- package/src/providers/bigcommerce/bigcommerce.ts +6 -0
- package/src/providers/bigcommerce/index.ts +315 -0
- package/src/providers/bigcommerce/transforms.ts +227 -0
- package/src/providers/index.ts +22 -0
- package/src/providers/magento/index.ts +387 -0
- package/src/providers/magento/magento.ts +5 -0
- package/src/providers/magento/queries.ts +267 -0
- package/src/providers/magento/transforms.ts +249 -0
- package/src/providers/medusa/auth.js +601 -0
- package/src/providers/medusa/auth.ts +496 -0
- package/src/providers/medusa/fulfillment-planner.ts +225 -0
- package/src/providers/medusa/index.js +2485 -0
- package/src/providers/medusa/index.ts +4239 -0
- package/src/providers/medusa/medusa.ts +8 -0
- package/src/providers/medusa/payment.js +265 -0
- package/src/providers/medusa/payment.ts +269 -0
- package/src/providers/medusa/transforms.js +505 -0
- package/src/providers/medusa/transforms.ts +625 -0
- package/src/providers/shopify/index.ts +444 -0
- package/src/providers/shopify/mutations.ts +102 -0
- package/src/providers/shopify/queries.ts +324 -0
- package/src/providers/shopify/shopify.ts +7 -0
- package/src/providers/shopify/transforms.ts +270 -0
- package/src/providers/spree/index.ts +344 -0
- package/src/providers/spree/spree.ts +5 -0
- package/src/providers/spree/transforms.ts +254 -0
- package/src/providers/woocommerce/index.ts +310 -0
- package/src/providers/woocommerce/transforms.ts +254 -0
- package/src/providers/woocommerce/woocommerce.ts +5 -0
- package/src/resilience/README.md +299 -0
- package/src/resilience/circuit-breaker.ts +222 -0
- package/src/resilience/index.ts +10 -0
- package/src/types/capabilities.types.js +141 -0
- package/src/types/capabilities.types.ts +366 -0
- package/src/types/index.ts +24 -0
- package/src/types/provider.js +9 -0
- package/src/types/provider.ts +9 -0
- package/src/types/ui-responses.ts +261 -0
- package/src/utils/city-coordinates.ts +40 -0
- package/src/utils/geolocation.ts +52 -0
- package/src/utils/payment-utils.js +152 -0
- package/src/utils/payment-utils.ts +203 -0
- package/tsconfig.json +15 -0
- package/tsup.config.ts +14 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Update Documentation
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
type: how-to
|
|
5
|
+
tags: [documentation, maintenance, adapters, standards, copilot]
|
|
6
|
+
related:
|
|
7
|
+
- ../../../docs/templates/README.md
|
|
8
|
+
- ../../../docs/update-documentation.md
|
|
9
|
+
updated: 2026-02-28
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
**Specific guidelines for updating @thorprovider/adapters documentation.**
|
|
13
|
+
|
|
14
|
+
Global guidelines: [docs/update-documentation.md](../../../docs/update-documentation.md)
|
|
15
|
+
|
|
16
|
+
## Prerequisites
|
|
17
|
+
|
|
18
|
+
- Read [global guidelines](../../../docs/update-documentation.md) for doc types and templates
|
|
19
|
+
- Understand the [Providers System](providers-overview.md) and [Capabilities System](capabilities-system.md)
|
|
20
|
+
- Ensure understanding of the [Adapter Strategy](../../ARCHITECTURE.md) (Strategy Pattern)
|
|
21
|
+
|
|
22
|
+
## Step-by-Step Process for Adapters
|
|
23
|
+
|
|
24
|
+
### Step 1: Identify Document Type
|
|
25
|
+
|
|
26
|
+
- **how-to**: Focuses on implementation tasks (e.g., `authentication.md`).
|
|
27
|
+
- **reference**: Focuses on technical specifications (e.g., `capabilities-system.md`).
|
|
28
|
+
- **guide**: Focuses on conceptual understanding (e.g., `services-overview.md`).
|
|
29
|
+
|
|
30
|
+
### Step 2: Framework-Agnostic Examples
|
|
31
|
+
|
|
32
|
+
**CRITICAL:** Adapters docs must prioritize framework-agnostic examples (Vanille TypeScript).
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
// ✅ DO: Framework-agnostic example
|
|
36
|
+
import { createProvider } from '@thorprovider/adapters';
|
|
37
|
+
const commerce = createProvider({ ... });
|
|
38
|
+
|
|
39
|
+
// ❌ DONT: Next.js or React specific code in core service docs
|
|
40
|
+
import { useAuth } from '@/hooks/useAuth';
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Step 3: Handle Capabilities
|
|
44
|
+
|
|
45
|
+
If the documentation involves a feature that differs across backends, always mention the corresponding capability.
|
|
46
|
+
|
|
47
|
+
```markdown
|
|
48
|
+
### Capability Check
|
|
49
|
+
Before performing this operation, check:
|
|
50
|
+
`if (commerce.capabilities.deleteAccount) { ... }`
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Step 4: Validate Changes
|
|
54
|
+
|
|
55
|
+
1. **Frontmatter:** Ensure `updated:` is current, `type:` is correct.
|
|
56
|
+
2. **Line Count:** Ensure file is `< 400` lines.
|
|
57
|
+
3. **PnP:** Run `yarn install` if imports are failing in examples.
|
|
58
|
+
4. **Links:** Verify relative links to other docs in the same folder.
|
|
59
|
+
|
|
60
|
+
## ✅ DO's
|
|
61
|
+
|
|
62
|
+
1. **Use TypeScript for all examples:** Ensure types are clear.
|
|
63
|
+
2. **Mention Backend Disparity:** Explicitly state if Medusa, Shopify, or others differ.
|
|
64
|
+
3. **Include Error Handling:** Show `CommerceError` or `AuthError` usage.
|
|
65
|
+
4. **Follow Singleton Pattern in setup examples:** Discourage multiple instance creation.
|
|
66
|
+
5. **Keep adapters clean of UI logic:** No React, No Next/Link, No DOM manipulation.
|
|
67
|
+
|
|
68
|
+
## ❌ DONT's
|
|
69
|
+
|
|
70
|
+
1. **Don't hardcode backend URLs:** Always use environment variable placeholders.
|
|
71
|
+
2. **Don't add UI dependencies:** Adapters are core business logic; docs shouldn't import `@thorprovider/components`.
|
|
72
|
+
3. **Don't skip capability checks:** Teaching AIs or users to ignore capabilities leads to runtime errors.
|
|
73
|
+
4. **Don't exceed 400 lines:** If a service (e.g., Products) gets too complex, split into `products.md` and `products-api.md`.
|
|
74
|
+
5. **Don't use old patterns:** Ensure examples follow Medusa v2 patterns.
|
|
75
|
+
|
|
76
|
+
## Common Patterns
|
|
77
|
+
|
|
78
|
+
### Capability Warning Pattern
|
|
79
|
+
Used for features not universally supported.
|
|
80
|
+
|
|
81
|
+
```markdown
|
|
82
|
+
> ⚠️ **Backend Disparity:** email updates are not supported natively in Medusa v2.
|
|
83
|
+
> Use the admin API or metadata fallbacks.
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Service Usage Pattern
|
|
87
|
+
```typescript
|
|
88
|
+
import { commerce } from '@/lib/commerce';
|
|
89
|
+
|
|
90
|
+
async function performTask() {
|
|
91
|
+
try {
|
|
92
|
+
const result = await commerce.service.method();
|
|
93
|
+
return result;
|
|
94
|
+
} catch (err) {
|
|
95
|
+
// Handle CommerceError
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Common Errors & Solutions
|
|
101
|
+
|
|
102
|
+
### Error: "Example uses Next.js imports"
|
|
103
|
+
**Cause:** Copy-pasting from Starter docs.
|
|
104
|
+
**Solution:** Refactor to pure TypeScript; move framework-specific notes to a "Framework Integration" sub-section if necessary.
|
|
105
|
+
|
|
106
|
+
### Error: "Complexity is too high for one doc"
|
|
107
|
+
**Cause:** Mixing conceptual guide with deep API reference.
|
|
108
|
+
**Solution:** Split into focus areas (e.g., `cart-management.md` and `cart-api.md`).
|
|
109
|
+
|
|
110
|
+
## Next Steps
|
|
111
|
+
|
|
112
|
+
- [global update-documentation.md](../../../docs/update-documentation.md)
|
|
113
|
+
- [How-to: Getting Started](getting-started.md)
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@thorprovider/adapters",
|
|
3
|
+
"version": "3.0.2",
|
|
4
|
+
"description": "Framework-agnostic commerce adapters for Thor Commerce ecosystem - Multi-platform support with unified API",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"registry": "https://registry.npmjs.org",
|
|
7
|
+
"access": "restricted"
|
|
8
|
+
},
|
|
9
|
+
"main": "dist/index.js",
|
|
10
|
+
"types": "dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"development": "./src/index.ts",
|
|
15
|
+
"import": "./dist/index.js",
|
|
16
|
+
"require": "./dist/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsup",
|
|
21
|
+
"dev": "tsup --watch",
|
|
22
|
+
"type-check": "tsc --noEmit",
|
|
23
|
+
"test": "echo \"No tests yet\" && exit 0",
|
|
24
|
+
"generate:agent-index": "node ../../scripts/generate-package-agents-index.cjs packages/adapters @thorprovider/adapters"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@medusajs/js-sdk": "2.11.3",
|
|
28
|
+
"@medusajs/types": "2.11.3",
|
|
29
|
+
"@thorprovider/types": "workspace:*",
|
|
30
|
+
"bcryptjs": "^3.0.3",
|
|
31
|
+
"jose": "^6.2.2"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"tsup": "^8.0.0",
|
|
35
|
+
"typescript": "^5.0.0"
|
|
36
|
+
},
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "https://github.com/thorprovider/thor-commerce",
|
|
40
|
+
"directory": "packages/adapters"
|
|
41
|
+
},
|
|
42
|
+
"license": "MIT"
|
|
43
|
+
}
|
package/publish.log
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
npm warn Unknown project config "network-concurrency". This will stop working in the next major version of npm.
|
|
2
|
+
npm warn publish npm auto-corrected some errors in your package.json when publishing. Please run "npm pkg fix" to address these errors.
|
|
3
|
+
npm warn publish errors corrected:
|
|
4
|
+
npm warn publish "repository.url" was normalized to "git+https://github.com/thorprovider/thor-commerce.git"
|
|
5
|
+
npm notice
|
|
6
|
+
npm notice 📦 @thor/adapters@3.0.1
|
|
7
|
+
npm notice Tarball Contents
|
|
8
|
+
npm notice 629B AGENTS.md
|
|
9
|
+
npm notice 9.1kB CHANGELOG.md
|
|
10
|
+
npm notice 19.2kB README.md
|
|
11
|
+
npm notice 73.6kB dist/index.d.mts
|
|
12
|
+
npm notice 73.6kB dist/index.d.ts
|
|
13
|
+
npm notice 191.6kB dist/index.js
|
|
14
|
+
npm notice 377.7kB dist/index.js.map
|
|
15
|
+
npm notice 187.4kB dist/index.mjs
|
|
16
|
+
npm notice 377.4kB dist/index.mjs.map
|
|
17
|
+
npm notice 4.7kB docs/authentication.md
|
|
18
|
+
npm notice 4.3kB docs/capabilities-system.md
|
|
19
|
+
npm notice 9.9kB docs/category-customization.md
|
|
20
|
+
npm notice 11.0kB docs/fetch-reliability-solution.md
|
|
21
|
+
npm notice 4.4kB docs/getting-started.md
|
|
22
|
+
npm notice 7.8kB docs/multi-tenant-channel-scoping.md
|
|
23
|
+
npm notice 4.5kB docs/profile-management.md
|
|
24
|
+
npm notice 3.7kB docs/providers-overview.md
|
|
25
|
+
npm notice 2.1kB docs/RETRY_SOLUTION_SUMMARY.md
|
|
26
|
+
npm notice 5.2kB docs/services-overview.md
|
|
27
|
+
npm notice 4.0kB docs/update-documentation.md
|
|
28
|
+
npm notice 1.2kB package.json
|
|
29
|
+
npm notice 6.3kB quick-reference.md
|
|
30
|
+
npm notice 2.5kB src/admin/AdminAuthService.ts
|
|
31
|
+
npm notice 2.4kB src/admin/AdminSessionService.ts
|
|
32
|
+
npm notice 414B src/admin/index.ts
|
|
33
|
+
npm notice 4.2kB src/admin/MetricsService.ts
|
|
34
|
+
npm notice 2.5kB src/backend/BackendMetadataAdapter.ts
|
|
35
|
+
npm notice 3.5kB src/backend/factory.ts
|
|
36
|
+
npm notice 312B src/backend/index.ts
|
|
37
|
+
npm notice 3.9kB src/backend/medusa/MedusaMetadataAdapter.ts
|
|
38
|
+
npm notice 6.3kB src/core/errors.js
|
|
39
|
+
npm notice 3.5kB src/core/errors.ts
|
|
40
|
+
npm notice 11.3kB src/core/fetch-utils.js
|
|
41
|
+
npm notice 6.0kB src/core/fetch-utils.ts
|
|
42
|
+
npm notice 141B src/core/index.ts
|
|
43
|
+
npm notice 2.3kB src/core/logger.js
|
|
44
|
+
npm notice 1.1kB src/core/logger.ts
|
|
45
|
+
npm notice 2.0kB src/factory/index.ts
|
|
46
|
+
npm notice 4.5kB src/index.ts
|
|
47
|
+
npm notice 2.7kB src/lib/money-transform.ts
|
|
48
|
+
npm notice 6.2kB src/metadata/channel-scope-validation.js
|
|
49
|
+
npm notice 5.1kB src/metadata/channel-scope-validation.ts
|
|
50
|
+
npm notice 7.6kB src/metadata/channel-scope.js
|
|
51
|
+
npm notice 8.2kB src/metadata/channel-scope.ts
|
|
52
|
+
npm notice 3.3kB src/metadata/index.js
|
|
53
|
+
npm notice 810B src/metadata/index.ts
|
|
54
|
+
npm notice 148B src/providers/index.ts
|
|
55
|
+
npm notice 30.0kB src/providers/medusa/auth.js
|
|
56
|
+
npm notice 15.1kB src/providers/medusa/auth.ts
|
|
57
|
+
npm notice 6.2kB src/providers/medusa/fulfillment-planner.ts
|
|
58
|
+
npm notice 151.8kB src/providers/medusa/index.js
|
|
59
|
+
npm notice 147.6kB src/providers/medusa/index.ts
|
|
60
|
+
npm notice 184B src/providers/medusa/medusa.ts
|
|
61
|
+
npm notice 11.0kB src/providers/medusa/payment.js
|
|
62
|
+
npm notice 7.2kB src/providers/medusa/payment.ts
|
|
63
|
+
npm notice 25.8kB src/providers/medusa/transforms.js
|
|
64
|
+
npm notice 19.8kB src/providers/medusa/transforms.ts
|
|
65
|
+
npm notice 5.5kB src/resilience/circuit-breaker.ts
|
|
66
|
+
npm notice 238B src/resilience/index.ts
|
|
67
|
+
npm notice 7.6kB src/resilience/README.md
|
|
68
|
+
npm notice 4.8kB src/types/capabilities.types.js
|
|
69
|
+
npm notice 4.7kB src/types/capabilities.types.ts
|
|
70
|
+
npm notice 513B src/types/index.ts
|
|
71
|
+
npm notice 350B src/types/provider.js
|
|
72
|
+
npm notice 365B src/types/provider.ts
|
|
73
|
+
npm notice 6.5kB src/types/ui-responses.ts
|
|
74
|
+
npm notice 1.1kB src/utils/city-coordinates.ts
|
|
75
|
+
npm notice 1.3kB src/utils/geolocation.ts
|
|
76
|
+
npm notice 5.6kB src/utils/payment-utils.js
|
|
77
|
+
npm notice 6.5kB src/utils/payment-utils.ts
|
|
78
|
+
npm notice 357B tsconfig.json
|
|
79
|
+
npm notice 370B tsup.config.ts
|
|
80
|
+
npm notice Tarball Details
|
|
81
|
+
npm notice name: @thor/adapters
|
|
82
|
+
npm notice version: 3.0.1
|
|
83
|
+
npm notice filename: thor-adapters-3.0.1.tgz
|
|
84
|
+
npm notice package size: 413.9 kB
|
|
85
|
+
npm notice unpacked size: 1.9 MB
|
|
86
|
+
npm notice shasum: 696c58c4b5629ad1ec09336238ea157aad015e3d
|
|
87
|
+
npm notice integrity: sha512-tIweHlz73prg8[...]3KYkFTyNlUX4w==
|
|
88
|
+
npm notice total files: 72
|
|
89
|
+
npm notice
|
|
90
|
+
npm notice Publishing to https://npm.pkg.github.com with tag latest and restricted access
|
|
91
|
+
npm error code E401
|
|
92
|
+
npm error 401 Unauthorized - PUT https://npm.pkg.github.com/@thor%2fadapters - unauthenticated: User cannot be authenticated with the token provided.
|
|
93
|
+
npm error A complete log of this run can be found in: /home/nelson/.npm/_logs/2026-04-16T15_45_37_415Z-debug-0.log
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# @thorprovider/adapters AI Quick Reference
|
|
2
|
+
|
|
3
|
+
## 🎯 Package Purpose
|
|
4
|
+
Framework-agnostic business logic SDK for e-commerce operations. Provides unified API for Medusa.js, Shopify, BigCommerce, and custom providers.
|
|
5
|
+
|
|
6
|
+
**WHY IT EXISTS**: Eliminate vendor lock-in. Switch backends with 1 line change instead of rewriting 500 files. Provides a **full bidirectional compatibility layer**: backend responses are normalized to `@thorprovider/types` (inbound reads), and `@thorprovider/types` objects are transformed into vendor-specific API payloads for mutations (outbound writes: cart creation, address updates, order placement, customer management, etc.).
|
|
7
|
+
|
|
8
|
+
**ROI**: Backend migration cost reduction 97% ($90,000 → $3,000 for 10 apps). Development speed 66x faster with pre-built commerce operations.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 🤖 AI Decision Framework (CRITICAL)
|
|
13
|
+
|
|
14
|
+
### When to Use @thorprovider/adapters
|
|
15
|
+
✅ Integrating with e-commerce backends (Medusa, Shopify, custom)
|
|
16
|
+
✅ Multi-tenant platforms (different backends per client)
|
|
17
|
+
✅ Need to switch backends in future (reduce vendor lock-in)
|
|
18
|
+
✅ Framework-agnostic apps (Next.js, Remix, Astro)
|
|
19
|
+
|
|
20
|
+
### When NOT to Use
|
|
21
|
+
❌ Single backend forever + never migrating
|
|
22
|
+
❌ Need 100% platform-specific features
|
|
23
|
+
❌ Non-commerce application
|
|
24
|
+
|
|
25
|
+
### Mission-Critical Rules
|
|
26
|
+
1. **NEVER import React/Next.js** (framework-agnostic layer)
|
|
27
|
+
2. **ALWAYS transform to @thorprovider/types** (don't expose backend types)
|
|
28
|
+
3. **ALWAYS use try/catch** with CommerceError
|
|
29
|
+
4. **DOCUMENT capabilities** when adding providers
|
|
30
|
+
5. **WRITE transform functions** for each data type
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 🏗️ Core Architecture
|
|
35
|
+
- **Type**: Framework-agnostic SDK (NO React/Next.js imports)
|
|
36
|
+
- **Pattern**: Provider abstraction with unified interface
|
|
37
|
+
- **Tech Stack**: TypeScript (strict mode), Zod validation, native fetch
|
|
38
|
+
- **Export Strategy**: Dual ESM + CJS via tsup
|
|
39
|
+
|
|
40
|
+
## ⚠️ Critical Constraints
|
|
41
|
+
- **NEVER import React** (`react`, `react-dom`)
|
|
42
|
+
- **NEVER import Next.js** (`next/link`, `next/navigation`)
|
|
43
|
+
- **NEVER import UI libraries** (maintain separation of concerns)
|
|
44
|
+
- **ALWAYS use dependency injection** for external services
|
|
45
|
+
- **ALWAYS validate inputs** with Zod schemas
|
|
46
|
+
|
|
47
|
+
## 📦 Module Structure
|
|
48
|
+
|
|
49
|
+
### Core API (Unified Interface)
|
|
50
|
+
- **Products**: `getProducts()`, `getProduct()`, search, pagination
|
|
51
|
+
- **Cart**: `createCart()`, `addToCart()`, `updateCart()`, `removeFromCart()`
|
|
52
|
+
- **Collections**: Product collections/categories
|
|
53
|
+
- **Customer**: Authentication, profile management
|
|
54
|
+
- **Orders**: Order history, details, tracking
|
|
55
|
+
|
|
56
|
+
### Provider Architecture
|
|
57
|
+
```
|
|
58
|
+
createProvider() → Provider instance
|
|
59
|
+
├── MedusaProvider (complete implementation)
|
|
60
|
+
├── ShopifyProvider (planned)
|
|
61
|
+
└── Custom providers (extensible)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Capability Detection (v2.0)
|
|
65
|
+
Backend capabilities exposed via `commerce.capabilities`:
|
|
66
|
+
- `updateProfile`, `updateEmail`, `changePasswordDirect`, etc.
|
|
67
|
+
- 21 total capability flags for adaptive UI
|
|
68
|
+
|
|
69
|
+
### Error Handling
|
|
70
|
+
- **Network errors**: Retry logic with exponential backoff
|
|
71
|
+
- **Validation errors**: Zod schema validation with detailed messages
|
|
72
|
+
- **Business errors**: Typed error objects with actionable codes
|
|
73
|
+
- **Type-safe**: All errors typed for proper handling
|
|
74
|
+
|
|
75
|
+
## 🛠️ Development Standards
|
|
76
|
+
|
|
77
|
+
### Adding New Service
|
|
78
|
+
1. Define types in `src/types/`
|
|
79
|
+
2. Implement in provider: `src/providers/medusa/`
|
|
80
|
+
3. Update factory: `src/factory/create-provider.ts`
|
|
81
|
+
4. Export from `src/index.ts`
|
|
82
|
+
5. Document in README.md
|
|
83
|
+
6. Add tests
|
|
84
|
+
|
|
85
|
+
### Type Safety
|
|
86
|
+
- **Interfaces first**: Define public API before implementation
|
|
87
|
+
- **Zod schemas**: All external data validated
|
|
88
|
+
- **Generic types**: Reusable across providers
|
|
89
|
+
- **Strict null checks**: No implicit any or undefined
|
|
90
|
+
|
|
91
|
+
### Testing Strategy
|
|
92
|
+
- **Unit tests**: Individual service methods
|
|
93
|
+
- **Integration tests**: Provider implementations
|
|
94
|
+
- **Mock providers**: For testing without backend
|
|
95
|
+
- **Coverage target**: >80% for critical paths
|
|
96
|
+
|
|
97
|
+
## 📚 Key Documentation
|
|
98
|
+
- [README.md](./README.md) - Package overview, installation, usage (435 lines)
|
|
99
|
+
- [CHANGELOG.md](./CHANGELOG.md) - Version history
|
|
100
|
+
- [examples/](./examples/) - Example implementations
|
|
101
|
+
- [src/](./src/) - Source code with inline documentation
|
|
102
|
+
|
|
103
|
+
## 🔗 Integration Points
|
|
104
|
+
|
|
105
|
+
### Usage in Applications
|
|
106
|
+
```typescript
|
|
107
|
+
// Create provider instance
|
|
108
|
+
import { createProvider } from '@thorprovider/adapters';
|
|
109
|
+
|
|
110
|
+
const commerce = createProvider({
|
|
111
|
+
provider: 'medusa',
|
|
112
|
+
config: {
|
|
113
|
+
baseUrl: process.env.NEXT_PUBLIC_COMMERCE_API_URL!,
|
|
114
|
+
publishableKey: process.env.NEXT_PUBLIC_COMMERCE_API_KEY!,
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// Use in React Server Components (Next.js App)
|
|
119
|
+
const products = await commerce.getProducts({ first: 10 });
|
|
120
|
+
|
|
121
|
+
// Access backend capabilities (v2.0)
|
|
122
|
+
console.log(commerce.capabilities.updateProfile); // true/false
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Usage in UI Components (via Context)
|
|
126
|
+
```typescript
|
|
127
|
+
// @thorprovider/components components receive data as props (no direct adapter calls)
|
|
128
|
+
// Applications manage adapter calls and pass data down
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## 🚀 Performance Considerations
|
|
132
|
+
- **Request deduplication**: Prevent parallel duplicate requests
|
|
133
|
+
- **Caching strategy**: Delegate to application layer (TanStack Query)
|
|
134
|
+
- **Batch operations**: Where provider supports it
|
|
135
|
+
- **Lazy loading**: Dynamic imports for large providers
|
|
136
|
+
|
|
137
|
+
## 🔍 Common Tasks
|
|
138
|
+
|
|
139
|
+
### Add New Service/Module
|
|
140
|
+
Consult [README.md](./README.md) for extension patterns and API documentation
|
|
141
|
+
|
|
142
|
+
### Add Provider Support
|
|
143
|
+
1. Implement provider class extending base
|
|
144
|
+
2. Map provider-specific types to unified interface
|
|
145
|
+
3. Handle provider-specific errors
|
|
146
|
+
4. Add provider tests
|
|
147
|
+
5. Document provider limitations
|
|
148
|
+
|
|
149
|
+
### Update Types
|
|
150
|
+
1. Modify interface in `src/types/`
|
|
151
|
+
2. Update base class in `src/base/`
|
|
152
|
+
3. Update all provider implementations
|
|
153
|
+
4. Update tests and documentation
|
|
154
|
+
5. Bump version following semver
|
|
155
|
+
|
|
156
|
+
## 🧪 Testing & Debugging
|
|
157
|
+
- **Run tests**: `yarn workspace @thorprovider/adapters test`
|
|
158
|
+
- **Type check**: `yarn workspace @thorprovider/adapters type-check`
|
|
159
|
+
- **Build**: `yarn workspace @thorprovider/adapters build`
|
|
160
|
+
- **Watch mode**: `yarn workspace @thorprovider/adapters dev`
|
|
161
|
+
|
|
162
|
+
## 📝 Anti-Patterns
|
|
163
|
+
- ❌ Importing framework-specific code
|
|
164
|
+
- ❌ Direct API calls without provider abstraction
|
|
165
|
+
- ❌ Unvalidated external data
|
|
166
|
+
- ❌ Mixing UI concerns with business logic
|
|
167
|
+
- ❌ Provider-specific logic leaking into base classes
|
|
168
|
+
- ❌ Synchronous operations that should be async
|
|
169
|
+
- ❌ Missing error handling for network operations
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin Authentication Service
|
|
3
|
+
*
|
|
4
|
+
* Framework-agnostic authentication logic for admin dashboard.
|
|
5
|
+
* Uses bcryptjs for password hashing and jose for JWT operations.
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* - L2: No Next.js imports, no env var access
|
|
9
|
+
* - Edge-compatible JWT via jose library
|
|
10
|
+
* - Password verification via bcryptjs
|
|
11
|
+
*
|
|
12
|
+
* @module admin/AdminAuthService
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import bcrypt from 'bcryptjs';
|
|
16
|
+
import { SignJWT, jwtVerify, type JWTPayload } from 'jose';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Admin Auth Service
|
|
20
|
+
*
|
|
21
|
+
* Provides password verification and JWT management for admin authentication.
|
|
22
|
+
* All methods are framework-agnostic and can be used in any runtime.
|
|
23
|
+
*/
|
|
24
|
+
export class AdminAuthService {
|
|
25
|
+
/**
|
|
26
|
+
* Verify password against bcrypt hash
|
|
27
|
+
*
|
|
28
|
+
* @param password - Plain text password from login form
|
|
29
|
+
* @param hash - Bcrypt hash stored in environment
|
|
30
|
+
* @returns true if password matches hash
|
|
31
|
+
*/
|
|
32
|
+
async verifyPassword(password: string, hash: string): Promise<boolean> {
|
|
33
|
+
return bcrypt.compare(password, hash);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Generate a bcrypt hash for a password
|
|
38
|
+
*
|
|
39
|
+
* @param password - Plain text password
|
|
40
|
+
* @param rounds - Bcrypt cost factor (default: 10)
|
|
41
|
+
* @returns Bcrypt hash string
|
|
42
|
+
*/
|
|
43
|
+
async hashPassword(password: string, rounds: number = 10): Promise<string> {
|
|
44
|
+
return bcrypt.hash(password, rounds);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Generate JWT token (Edge-compatible via jose)
|
|
49
|
+
*
|
|
50
|
+
* @param payload - Token payload data
|
|
51
|
+
* @param secret - JWT secret string (min 32 chars recommended)
|
|
52
|
+
* @param expiresIn - Token expiration (default: '8h')
|
|
53
|
+
* @returns Signed JWT token string
|
|
54
|
+
*/
|
|
55
|
+
async generateJWT(
|
|
56
|
+
payload: Record<string, unknown>,
|
|
57
|
+
secret: string,
|
|
58
|
+
expiresIn: string = '8h',
|
|
59
|
+
): Promise<string> {
|
|
60
|
+
const secretKey = new TextEncoder().encode(secret);
|
|
61
|
+
|
|
62
|
+
return new SignJWT(payload as JWTPayload)
|
|
63
|
+
.setProtectedHeader({ alg: 'HS256' })
|
|
64
|
+
.setIssuedAt()
|
|
65
|
+
.setExpirationTime(expiresIn)
|
|
66
|
+
.sign(secretKey);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Verify JWT token (Edge-compatible via jose)
|
|
71
|
+
*
|
|
72
|
+
* @param token - JWT token string
|
|
73
|
+
* @param secret - JWT secret string
|
|
74
|
+
* @returns Decoded payload or null if invalid/expired
|
|
75
|
+
*/
|
|
76
|
+
async verifyJWT(
|
|
77
|
+
token: string,
|
|
78
|
+
secret: string,
|
|
79
|
+
): Promise<Record<string, unknown> | null> {
|
|
80
|
+
try {
|
|
81
|
+
const secretKey = new TextEncoder().encode(secret);
|
|
82
|
+
const { payload } = await jwtVerify(token, secretKey);
|
|
83
|
+
return payload as Record<string, unknown>;
|
|
84
|
+
} catch {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin Session Service
|
|
3
|
+
*
|
|
4
|
+
* Framework-agnostic session verification for admin routes.
|
|
5
|
+
* Extracts and verifies JWT tokens from HTTP requests.
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* - L2: No Next.js imports, no env var access
|
|
9
|
+
* - Uses standard Request API (works in Edge, Node.js, etc.)
|
|
10
|
+
* - JWT secret injected via constructor (no env var reading)
|
|
11
|
+
*
|
|
12
|
+
* @module admin/AdminSessionService
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { AdminAuthService } from './AdminAuthService';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Admin Session payload decoded from JWT
|
|
19
|
+
*/
|
|
20
|
+
export interface AdminSession {
|
|
21
|
+
/** Admin user identifier */
|
|
22
|
+
adminId: string;
|
|
23
|
+
/** Token type (always 'admin') */
|
|
24
|
+
type: 'admin';
|
|
25
|
+
/** Issued at timestamp */
|
|
26
|
+
iat: number;
|
|
27
|
+
/** Expiration timestamp */
|
|
28
|
+
exp: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Admin Session Service
|
|
33
|
+
*
|
|
34
|
+
* Verifies admin sessions by extracting and validating JWT tokens
|
|
35
|
+
* from HTTP request cookies or Authorization headers.
|
|
36
|
+
*/
|
|
37
|
+
export class AdminSessionService {
|
|
38
|
+
private authService: AdminAuthService;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @param jwtSecret - JWT secret for token verification
|
|
42
|
+
*/
|
|
43
|
+
constructor(private jwtSecret: string) {
|
|
44
|
+
this.authService = new AdminAuthService();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Verify admin session from HTTP request
|
|
49
|
+
*
|
|
50
|
+
* Checks for JWT token in:
|
|
51
|
+
* 1. `admin_token` cookie
|
|
52
|
+
* 2. `Authorization: Bearer <token>` header
|
|
53
|
+
*
|
|
54
|
+
* @param request - Standard HTTP Request object
|
|
55
|
+
* @returns AdminSession if valid, null otherwise
|
|
56
|
+
*/
|
|
57
|
+
async verifySession(request: Request): Promise<AdminSession | null> {
|
|
58
|
+
const token = this.extractToken(request);
|
|
59
|
+
if (!token) return null;
|
|
60
|
+
|
|
61
|
+
const payload = await this.authService.verifyJWT(token, this.jwtSecret);
|
|
62
|
+
if (!payload || payload.type !== 'admin') return null;
|
|
63
|
+
|
|
64
|
+
return payload as unknown as AdminSession;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Extract JWT token from request (cookie or Authorization header)
|
|
69
|
+
*/
|
|
70
|
+
private extractToken(request: Request): string | null {
|
|
71
|
+
// Try cookie first
|
|
72
|
+
const cookieHeader = request.headers.get('cookie');
|
|
73
|
+
if (cookieHeader) {
|
|
74
|
+
const cookies = Object.fromEntries(
|
|
75
|
+
cookieHeader.split(';').map((c) => {
|
|
76
|
+
const [key, ...v] = c.trim().split('=');
|
|
77
|
+
return [key, v.join('=')];
|
|
78
|
+
}),
|
|
79
|
+
);
|
|
80
|
+
if (cookies.admin_token) return cookies.admin_token;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Try Authorization header
|
|
84
|
+
const authHeader = request.headers.get('authorization');
|
|
85
|
+
if (authHeader?.startsWith('Bearer ')) {
|
|
86
|
+
return authHeader.substring(7);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}
|