@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.
Files changed (95) hide show
  1. package/.turbo/turbo-build.log +18 -0
  2. package/.turbo/turbo-test.log +1 -0
  3. package/.turbo/turbo-type-check.log +0 -0
  4. package/AGENTS.md +1 -0
  5. package/CHANGELOG.md +271 -0
  6. package/README.md +634 -0
  7. package/dist/.tsbuildinfo +1 -0
  8. package/dist/index.d.mts +2524 -0
  9. package/dist/index.d.ts +2524 -0
  10. package/dist/index.js +8136 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/index.mjs +8045 -0
  13. package/dist/index.mjs.map +1 -0
  14. package/docs/RETRY_SOLUTION_SUMMARY.md +55 -0
  15. package/docs/authentication.md +165 -0
  16. package/docs/capabilities-system.md +143 -0
  17. package/docs/category-customization.md +309 -0
  18. package/docs/fetch-reliability-solution.md +399 -0
  19. package/docs/getting-started.md +154 -0
  20. package/docs/multi-tenant-channel-scoping.md +225 -0
  21. package/docs/profile-management.md +147 -0
  22. package/docs/providers-overview.md +85 -0
  23. package/docs/services-overview.md +135 -0
  24. package/docs/update-documentation.md +113 -0
  25. package/package.json +43 -0
  26. package/publish.log +93 -0
  27. package/quick-reference.md +169 -0
  28. package/src/admin/AdminAuthService.ts +88 -0
  29. package/src/admin/AdminSessionService.ts +91 -0
  30. package/src/admin/MetricsService.ts +145 -0
  31. package/src/admin/index.ts +13 -0
  32. package/src/backend/BackendMetadataAdapter.ts +88 -0
  33. package/src/backend/factory.ts +107 -0
  34. package/src/backend/index.ts +12 -0
  35. package/src/backend/medusa/MedusaMetadataAdapter.ts +139 -0
  36. package/src/core/errors.js +161 -0
  37. package/src/core/errors.ts +132 -0
  38. package/src/core/fetch-utils.js +240 -0
  39. package/src/core/fetch-utils.ts +227 -0
  40. package/src/core/index.ts +8 -0
  41. package/src/core/logger.js +63 -0
  42. package/src/core/logger.ts +37 -0
  43. package/src/factory/index.ts +102 -0
  44. package/src/index.ts +205 -0
  45. package/src/lib/money-transform.ts +80 -0
  46. package/src/metadata/channel-scope-validation.js +136 -0
  47. package/src/metadata/channel-scope-validation.ts +151 -0
  48. package/src/metadata/channel-scope.js +174 -0
  49. package/src/metadata/channel-scope.ts +215 -0
  50. package/src/metadata/index.js +31 -0
  51. package/src/metadata/index.ts +37 -0
  52. package/src/providers/bigcommerce/bigcommerce.ts +6 -0
  53. package/src/providers/bigcommerce/index.ts +315 -0
  54. package/src/providers/bigcommerce/transforms.ts +227 -0
  55. package/src/providers/index.ts +22 -0
  56. package/src/providers/magento/index.ts +387 -0
  57. package/src/providers/magento/magento.ts +5 -0
  58. package/src/providers/magento/queries.ts +267 -0
  59. package/src/providers/magento/transforms.ts +249 -0
  60. package/src/providers/medusa/auth.js +601 -0
  61. package/src/providers/medusa/auth.ts +496 -0
  62. package/src/providers/medusa/fulfillment-planner.ts +225 -0
  63. package/src/providers/medusa/index.js +2485 -0
  64. package/src/providers/medusa/index.ts +4239 -0
  65. package/src/providers/medusa/medusa.ts +8 -0
  66. package/src/providers/medusa/payment.js +265 -0
  67. package/src/providers/medusa/payment.ts +269 -0
  68. package/src/providers/medusa/transforms.js +505 -0
  69. package/src/providers/medusa/transforms.ts +625 -0
  70. package/src/providers/shopify/index.ts +444 -0
  71. package/src/providers/shopify/mutations.ts +102 -0
  72. package/src/providers/shopify/queries.ts +324 -0
  73. package/src/providers/shopify/shopify.ts +7 -0
  74. package/src/providers/shopify/transforms.ts +270 -0
  75. package/src/providers/spree/index.ts +344 -0
  76. package/src/providers/spree/spree.ts +5 -0
  77. package/src/providers/spree/transforms.ts +254 -0
  78. package/src/providers/woocommerce/index.ts +310 -0
  79. package/src/providers/woocommerce/transforms.ts +254 -0
  80. package/src/providers/woocommerce/woocommerce.ts +5 -0
  81. package/src/resilience/README.md +299 -0
  82. package/src/resilience/circuit-breaker.ts +222 -0
  83. package/src/resilience/index.ts +10 -0
  84. package/src/types/capabilities.types.js +141 -0
  85. package/src/types/capabilities.types.ts +366 -0
  86. package/src/types/index.ts +24 -0
  87. package/src/types/provider.js +9 -0
  88. package/src/types/provider.ts +9 -0
  89. package/src/types/ui-responses.ts +261 -0
  90. package/src/utils/city-coordinates.ts +40 -0
  91. package/src/utils/geolocation.ts +52 -0
  92. package/src/utils/payment-utils.js +152 -0
  93. package/src/utils/payment-utils.ts +203 -0
  94. package/tsconfig.json +15 -0
  95. 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
+ }