@thorprovider/types 2.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.
@@ -0,0 +1,174 @@
1
+ /**
2
+ * @thorprovider/types — Supported Providers
3
+ *
4
+ * Centralized list of all supported commerce providers.
5
+ * This is the single source of truth for provider types across the monorepo.
6
+ *
7
+ * @remarks
8
+ * - L1 (Foundation): Defines the contract
9
+ * - L2 (@thorprovider/adapters) imports from here to build the factory
10
+ * - L5 (Starters) uses the factory which is bound to this enum
11
+ *
12
+ * When adding a new provider (e.g., Shopify):
13
+ * 1. Add to SupportedProviderType enum below
14
+ * 2. Update @thorprovider/adapters factory/index.ts with discriminated union
15
+ * 3. Create packages/adapters/src/providers/shopify/
16
+ * 4. Implement CommerceProvider interface
17
+ * 5. Update StorefrontPlatformType in storefront.ts (automatically synced)
18
+ */
19
+
20
+ /**
21
+ * All supported commerce platform providers.
22
+ * Currently only 'medusa' is implemented; others are placeholders for future expansion.
23
+ *
24
+ * @remarks Implementation status:
25
+ * - ✅ medusa: Fully implemented
26
+ * - 🟡 shopify: Planned (Phase 2)
27
+ * - 🟡 bigcommerce: Planned (Phase 2)
28
+ * - 🟡 woocommerce: Planned (Phase 3)
29
+ * - 🟡 spree: Planned (Phase 3)
30
+ * - 🟡 magento: Planned (Phase 3)
31
+ */
32
+ export enum SupportedProviderType {
33
+ Medusa = 'medusa',
34
+ Shopify = 'shopify',
35
+ BigCommerce = 'bigcommerce',
36
+ WooCommerce = 'woocommerce',
37
+ Spree = 'spree',
38
+ Magento = 'magento',
39
+ }
40
+
41
+ /**
42
+ * Union type of all supported provider string values.
43
+ * Use this for type annotations when a provider type is expected.
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * function getProviderName(type: ProviderTypeString): string {
48
+ * // type is 'medusa'
49
+ * }
50
+ * ```
51
+ */
52
+ export type ProviderTypeString = 'medusa' | 'shopify' | 'bigcommerce' | 'woocommerce' | 'spree' | 'magento';
53
+
54
+ /**
55
+ * Metadata about each provider.
56
+ * Useful for UI, error messages, validation, and documentation.
57
+ *
58
+ * @internal
59
+ */
60
+ export const PROVIDER_METADATA: Record<
61
+ ProviderTypeString,
62
+ {
63
+ name: string;
64
+ description: string;
65
+ requiresStorefront: boolean;
66
+ requiredEnvVars: string[];
67
+ maxRetries: number;
68
+ }
69
+ > = {
70
+ medusa: {
71
+ name: 'Medusa JS',
72
+ description: 'Medusa v2 commerce engine',
73
+ requiresStorefront: true,
74
+ requiredEnvVars: [
75
+ 'NEXT_PUBLIC_COMMERCE_API_URL',
76
+ 'NEXT_PUBLIC_COMMERCE_API_KEY',
77
+ 'NEXT_PUBLIC_SALES_CHANNEL_ID',
78
+ ],
79
+ maxRetries: 3,
80
+ },
81
+ shopify: {
82
+ name: 'Shopify',
83
+ description: 'Shopify Storefront API (GraphQL)',
84
+ requiresStorefront: false,
85
+ requiredEnvVars: [
86
+ 'NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN',
87
+ 'NEXT_PUBLIC_SHOPIFY_STOREFRONT_TOKEN',
88
+ ],
89
+ maxRetries: 3,
90
+ },
91
+ bigcommerce: {
92
+ name: 'BigCommerce',
93
+ description: 'BigCommerce REST Storefront API',
94
+ requiresStorefront: false,
95
+ requiredEnvVars: [
96
+ 'BIGCOMMERCE_STORE_HASH',
97
+ 'BIGCOMMERCE_STOREFRONT_API_TOKEN',
98
+ 'BIGCOMMERCE_CHANNEL_ID',
99
+ ],
100
+ maxRetries: 3,
101
+ },
102
+ woocommerce: {
103
+ name: 'WooCommerce',
104
+ description: 'WooCommerce Store API + REST API v3',
105
+ requiresStorefront: false,
106
+ requiredEnvVars: [
107
+ 'WOOCOMMERCE_URL',
108
+ 'WOOCOMMERCE_CONSUMER_KEY',
109
+ 'WOOCOMMERCE_CONSUMER_SECRET',
110
+ ],
111
+ maxRetries: 3,
112
+ },
113
+ spree: {
114
+ name: 'Spree Commerce',
115
+ description: 'Spree API v2 Storefront (JSON:API)',
116
+ requiresStorefront: false,
117
+ requiredEnvVars: [
118
+ 'SPREE_API_URL',
119
+ ],
120
+ maxRetries: 3,
121
+ },
122
+ magento: {
123
+ name: 'Adobe Commerce (Magento)',
124
+ description: 'Adobe Commerce GraphQL + REST API',
125
+ requiresStorefront: true,
126
+ requiredEnvVars: [
127
+ 'MAGENTO_URL',
128
+ 'MAGENTO_STORE_CODE',
129
+ ],
130
+ maxRetries: 3,
131
+ },
132
+ };
133
+
134
+ /**
135
+ * Check if a string is a valid provider type.
136
+ *
137
+ * @example
138
+ * ```typescript
139
+ * if (isSupportedProviderType(process.env.COMMERCE_PROVIDER)) {
140
+ * // type is narrowed to ProviderTypeString
141
+ * }
142
+ * ```
143
+ */
144
+ export function isSupportedProviderType(
145
+ value: unknown
146
+ ): value is ProviderTypeString {
147
+ return (
148
+ typeof value === 'string' &&
149
+ Object.values(SupportedProviderType).includes(value as SupportedProviderType)
150
+ );
151
+ }
152
+
153
+ /**
154
+ * Get metadata for a provider type.
155
+ * Useful for validation, error messages, and logging.
156
+ *
157
+ * @example
158
+ * ```typescript
159
+ * const meta = getProviderMetadata('medusa');
160
+ * console.log(`Using ${meta.name} with max ${meta.maxRetries} retries`);
161
+ * ```
162
+ */
163
+ export function getProviderMetadata(
164
+ type: ProviderTypeString
165
+ ): (typeof PROVIDER_METADATA)[ProviderTypeString] {
166
+ if (!isSupportedProviderType(type)) {
167
+ throw new Error(
168
+ `Unsupported provider: ${type}. Supported: ${Object.values(
169
+ SupportedProviderType
170
+ ).join(', ')}`
171
+ );
172
+ }
173
+ return PROVIDER_METADATA[type];
174
+ }
package/src/region.ts ADDED
@@ -0,0 +1,43 @@
1
+ /**
2
+ * @thorprovider/types v3.0
3
+ * Region types - geographic region configuration
4
+ * Universal interfaces compatible with: Shopify Markets, Medusa Regions, WooCommerce Zones
5
+ */
6
+
7
+ /**
8
+ * Geographic region configuration
9
+ *
10
+ * Represents a regional market with specific currency, tax, and payment settings.
11
+ *
12
+ * Platform mapping:
13
+ * - Shopify: Market (primaryDomain, regions, currencySettings)
14
+ * - Medusa: Region (currency_code, countries, payment_providers, tax_rate)
15
+ * - WooCommerce: Shipping Zone + Tax Settings (combined concept)
16
+ *
17
+ * Adapters transform platform-specific region data to this universal format.
18
+ */
19
+ export interface Region {
20
+ /** Unique region identifier */
21
+ id: string;
22
+
23
+ /** Region name (e.g., "United States", "Europe", "North America") */
24
+ name: string;
25
+
26
+ /** ISO 3166-1 alpha-2 country codes included in this region (e.g., ["US", "CA"]) */
27
+ countryCodes: string[];
28
+
29
+ /** Default currency for this region (ISO 4217 code, e.g., "USD", "EUR") */
30
+ currency: string;
31
+
32
+ /** Available payment provider IDs in this region */
33
+ paymentProviders?: string[];
34
+
35
+ /** Tax rate for this region (as decimal, e.g., 0.08 for 8%) */
36
+ taxRate?: number;
37
+
38
+ /** Whether this region is enabled and available for customers */
39
+ isEnabled?: boolean;
40
+
41
+ /** Additional region metadata for platform-specific features */
42
+ metadata?: Record<string, unknown>;
43
+ }
@@ -0,0 +1,87 @@
1
+ /**
2
+ * SiteConfigLabels - All translatable strings from site-config
3
+ *
4
+ * Maps to messages/siteConfig.* namespace in next-intl.
5
+ * Used in L5 to provide i18n-aware labels to components that otherwise use siteConfig.
6
+ *
7
+ * IMPORTANT: This interface contains ONLY translatable text — no hrefs, images, or structural config.
8
+ * Structural config (hrefs, images, module presets) stays in site-config.ts.
9
+ *
10
+ * Footer/featuredCategories labels are simple string arrays mapped by index to
11
+ * the corresponding entries in siteConfig.footerLinks / siteConfig.featuredCategories.
12
+ *
13
+ * @see packages/core/messages/en.json (siteConfig namespace)
14
+ * @see packages/core/hooks/use-site-config-labels.ts
15
+ */
16
+ export interface SiteConfigLabels {
17
+ title: string;
18
+ description: string;
19
+ tagline: string;
20
+ header: {
21
+ products: {
22
+ label: string;
23
+ newArrivals: {
24
+ heading: string;
25
+ description: string;
26
+ };
27
+ summerSale: {
28
+ heading: string;
29
+ description: string;
30
+ };
31
+ links: {
32
+ allProducts: string;
33
+ allProductsDescription: string;
34
+ newArrivals: string;
35
+ newArrivalsDescription: string;
36
+ bestSellers: string;
37
+ bestSellersDescription: string;
38
+ sale: string;
39
+ saleDescription: string;
40
+ };
41
+ };
42
+ categories: {
43
+ label: string;
44
+ };
45
+ account: {
46
+ label: string;
47
+ items: {
48
+ profile: string;
49
+ orders: string;
50
+ logout: string;
51
+ };
52
+ };
53
+ cart: {
54
+ label: string;
55
+ };
56
+ search: {
57
+ placeholder: string;
58
+ };
59
+ };
60
+ footer: {
61
+ shopTitle: string;
62
+ supportTitle: string;
63
+ companyTitle: string;
64
+ shop: string[];
65
+ support: string[];
66
+ company: string[];
67
+ legal: string[];
68
+ };
69
+ hero: {
70
+ badge: string;
71
+ title: string;
72
+ description: string;
73
+ primaryCta: string;
74
+ secondaryCta: string;
75
+ };
76
+ promo: {
77
+ badge: string;
78
+ title: string;
79
+ description: string;
80
+ emailPlaceholder: string;
81
+ ctaText: string;
82
+ };
83
+ featuredCategories: string[];
84
+ copyright: {
85
+ text: string;
86
+ };
87
+ }
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Site Configuration Types
3
+ *
4
+ * Foundation for multi-tenant, framework-agnostic site configuration.
5
+ * Defines the structure for branding, metadata, navigation, and module presets.
6
+ *
7
+ * @module site-config
8
+ */
9
+
10
+ import type { HeaderNavigationConfig } from './header-config';
11
+
12
+ /**
13
+ * Brand Information
14
+ */
15
+ export interface BrandConfig {
16
+ name: string;
17
+ title: string;
18
+ description: string;
19
+ tagline?: string;
20
+ logo?: string;
21
+ logoDark?: string;
22
+ preset?: string;
23
+ }
24
+
25
+ /**
26
+ * Site Metadata & Authorship
27
+ */
28
+ export interface AuthorConfig {
29
+ /** Name of the author or organization */
30
+ name: string;
31
+
32
+ /** Primary contact email */
33
+ email: string;
34
+ }
35
+
36
+ /**
37
+ * Social Media Links
38
+ */
39
+ export type SocialConfig = Record<string, string>;
40
+
41
+ /**
42
+ * Navigation Item (Simple)
43
+ */
44
+ export interface NavigationItem {
45
+ /** Display name of the link or button */
46
+ name: string;
47
+
48
+ /** URL or anchor for the link */
49
+ href: string;
50
+ }
51
+
52
+ /**
53
+ * Footer link categorization
54
+ */
55
+ export interface FooterLinksConfig {
56
+ /** Customer shopping shortcuts */
57
+ shop: NavigationItem[];
58
+
59
+ /** Customer service and support links */
60
+ support: NavigationItem[];
61
+
62
+ /** Corporate and information links */
63
+ company: NavigationItem[];
64
+
65
+ /** Legal, privacy, and policy links */
66
+ legal: NavigationItem[];
67
+ }
68
+
69
+ /**
70
+ * Copyright information for the site
71
+ */
72
+ export interface CopyrightConfig {
73
+ /** Current year or range (e.g., "2024" or "2023-2024") */
74
+ year: string | number;
75
+
76
+ /** Legal text following the year */
77
+ text: string;
78
+ }
79
+
80
+ /**
81
+ * Module-specific configurations
82
+ */
83
+ export interface ModulesConfig {
84
+ cart: {
85
+ mini: {
86
+ variant: 'mini';
87
+ composition: 'compact' | 'full' | 'separate-pages';
88
+ };
89
+ page: {
90
+ variant: 'page';
91
+ composition: 'compact' | 'full';
92
+ };
93
+ };
94
+ checkout: {
95
+ default: {
96
+ variant: 'simple' | 'standard' | 'complete';
97
+ composition: 'accordion' | 'wizard' | 'single-page';
98
+ };
99
+ };
100
+ profile: {
101
+ default: {
102
+ variant: 'basic' | 'standard' | 'complete';
103
+ composition: 'tabs' | 'accordion' | 'separate-pages' | 'side';
104
+ };
105
+ };
106
+ }
107
+
108
+ /**
109
+ * Complete Site Configuration
110
+ *
111
+ * Centralized interface for site-wide settings.
112
+ * Supports merging with database-stored overrides via Developer Dashboard.
113
+ */
114
+ export interface SiteConfig {
115
+ /** Brand identity and basic info */
116
+ name: string;
117
+ title: string;
118
+ description: string;
119
+ tagline?: string;
120
+ logo?: string;
121
+ logoDark?: string;
122
+ preset?: string;
123
+
124
+ /** URLs and social */
125
+ url?: string;
126
+ author?: AuthorConfig;
127
+ social?: SocialConfig;
128
+
129
+ /** Navigation structures */
130
+ navigation?: NavigationItem[];
131
+ header?: HeaderNavigationConfig;
132
+
133
+ /** Footer content and links */
134
+ footerLinks: FooterLinksConfig;
135
+
136
+ /** Copyright statement */
137
+ copyright: CopyrightConfig;
138
+
139
+ /** Module behavior & UI variants */
140
+ modules: ModulesConfig;
141
+
142
+ /**
143
+ * Extension point for custom properties
144
+ * Necessary for experimental features before they are formally typed
145
+ */
146
+ [key: string]: any;
147
+ }
148
+
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Inventory & fulfillment types
3
+ *
4
+ * Foundation layer (L1) types used by adapters, UI, and starters.
5
+ */
6
+
7
+ import type { Money } from './common';
8
+
9
+ export interface StockLocation {
10
+ id: string;
11
+ name: string;
12
+ address?: {
13
+ address1: string;
14
+ address2?: string;
15
+ city: string;
16
+ countryCode: string;
17
+ postalCode: string;
18
+ province?: string;
19
+ };
20
+ metadata?: {
21
+ lat?: number;
22
+ lng?: number;
23
+ timezone?: string;
24
+ };
25
+ }
26
+
27
+ export interface InventoryLevel {
28
+ locationId: string;
29
+ locationName: string;
30
+ availableQuantity: number;
31
+ reservedQuantity: number;
32
+ incomingQuantity?: number;
33
+ stockedQuantity: number;
34
+ }
35
+
36
+ export interface FulfillmentSet {
37
+ id: string;
38
+ name: string;
39
+ type: 'shipping' | 'pickup' | 'return';
40
+ location: StockLocation;
41
+ }
42
+
43
+ export interface FulfillmentOption {
44
+ id: string;
45
+ providerId: string;
46
+ name: string;
47
+ description?: string;
48
+ price: Money;
49
+ estimatedDays?: string;
50
+ stockLocation: StockLocation;
51
+ fulfillmentSet?: FulfillmentSet;
52
+ distance?: number;
53
+ }
54
+
55
+ export type StockStatus = 'in_stock' | 'out_of_stock' | 'low_stock';
56
+
57
+ export interface StockValidation {
58
+ allAvailable: boolean;
59
+ unavailableItems: Array<{
60
+ variantId: string;
61
+ productName: string;
62
+ requestedQuantity: number;
63
+ availableQuantity: number;
64
+ }>;
65
+ }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * @thorprovider/types — Storefront Configuration
3
+ *
4
+ * Type definitions for per-channel storefront configuration
5
+ * returned by the Thor Commerce backend plugin.
6
+ *
7
+ * Consumed by `CommerceProvider.getStorefrontConfig()` in L2 adapters.
8
+ * Replaces legacy environment variables: NEXT_PUBLIC_ACCENT_COLOR,
9
+ * NEXT_PUBLIC_LOGO_URL, NEXT_PUBLIC_CURRENCY_CODE.
10
+ *
11
+ * @module storefront-config
12
+ */
13
+
14
+ /**
15
+ * SEO default values for a storefront channel.
16
+ */
17
+ export interface StorefrontSeoDefaults {
18
+ /** Default page title */
19
+ title: string;
20
+
21
+ /** Default meta description */
22
+ description: string;
23
+
24
+ /** Default Open Graph image URL */
25
+ ogImage?: string;
26
+ }
27
+
28
+ /**
29
+ * Per-channel storefront configuration.
30
+ *
31
+ * Returned by `GET /store/thor/config` (resolved via publishable API key).
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * const config = await commerce.getStorefrontConfig();
36
+ * if (config) {
37
+ * console.log(config.logoUrl, config.themeAccentColor);
38
+ * }
39
+ * ```
40
+ */
41
+ export interface StorefrontConfig {
42
+ /** Unique identifier for this storefront config entry */
43
+ id: string;
44
+
45
+ /** Sales channel this config belongs to */
46
+ salesChannelId: string;
47
+
48
+ /** Theme accent color name (e.g., "indigo", "blue", "red") */
49
+ themeAccentColor: string;
50
+
51
+ /** Logo image URL */
52
+ logoUrl: string;
53
+
54
+ /** Default currency code (e.g., "EUR", "USD") */
55
+ currencyCode: string;
56
+
57
+ /** SEO default values */
58
+ seoDefaults: StorefrontSeoDefaults;
59
+
60
+ /** ISO 8601 creation timestamp */
61
+ createdAt: string;
62
+
63
+ /** ISO 8601 last update timestamp */
64
+ updatedAt: string;
65
+ }
@@ -0,0 +1,126 @@
1
+ /**
2
+ * @thorprovider/types — Storefront Context
3
+ *
4
+ * Platform-agnostic representation of a "sales channel" or equivalent.
5
+ * Abstracts differences between Medusa sales_channel, Shopify publications,
6
+ * BigCommerce channels, WooCommerce sites, Spree stores, and Magento store views.
7
+ *
8
+ * @remarks
9
+ * - Required for all multi-tenant deployments
10
+ * - Returned by `CommerceProvider.getStorefrontContext()`
11
+ * - MUST be validated on startup; errors should NOT be silently ignored
12
+ */
13
+
14
+ /**
15
+ * Supported commerce platform types for storefront identification.
16
+ *
17
+ * @remarks
18
+ * This type is automatically synced with SupportedProviderType from provider.ts.
19
+ * When adding a new provider, update packages/types/src/provider.ts,
20
+ * and this type will automatically reflect the new provider.
21
+ *
22
+ * Currently supported:
23
+ * - ✅ 'medusa': Fully implemented
24
+ *
25
+ * Planned (not yet implemented):
26
+ * - 🟡 'shopify': Phase 2
27
+ * - 🟡 'bigcommerce': Phase 2
28
+ * - 🟡 'woocommerce': Phase 3
29
+ * - 🟡 'spree': Phase 3
30
+ * - 🟡 'magento': Phase 3
31
+ */
32
+ export type StorefrontPlatformType = 'medusa' | 'shopify' | 'bigcommerce' | 'woocommerce' | 'spree' | 'magento';
33
+
34
+ /**
35
+ * StorefrontContext
36
+ *
37
+ * Platform-agnostic representation of a "sales channel" or equivalent.
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * const ctx: StorefrontContext = {
42
+ * id: 'sc_01J...',
43
+ * name: 'B2C Storefront',
44
+ * platformType: 'medusa',
45
+ * requiresProductScoping: true,
46
+ * currencyCode: 'USD',
47
+ * };
48
+ * ```
49
+ */
50
+ export interface StorefrontContext {
51
+ /**
52
+ * Unique identifier for this storefront across the system.
53
+ * Examples: "sc_123" (Medusa), "gid://shopify/Channel/789" (Shopify), "1" (WooCommerce)
54
+ */
55
+ id: string;
56
+
57
+ /**
58
+ * Human-readable name for logging and debugging.
59
+ */
60
+ name: string;
61
+
62
+ /**
63
+ * Platform this storefront belongs to.
64
+ */
65
+ platformType: StorefrontPlatformType;
66
+
67
+ /**
68
+ * Whether products must be explicitly linked/published to this storefront.
69
+ *
70
+ * @remarks
71
+ * - Medusa: true (products must be linked to sales channel)
72
+ * - Shopify: false (products visible by default unless unlisted)
73
+ * - WooCommerce: false (no scoping concept)
74
+ * - BigCommerce: false (products visible by default unless delisted)
75
+ * - Spree: true (products must be assigned per store)
76
+ * - Magento: true (products must be assigned per website)
77
+ */
78
+ requiresProductScoping: boolean;
79
+
80
+ /**
81
+ * Primary currency code for this storefront.
82
+ * Examples: "USD", "EUR", "GBP"
83
+ */
84
+ currencyCode: string;
85
+
86
+ /**
87
+ * Optional region or locale code.
88
+ * Examples: "US", "EU", "en-US", "es-ES"
89
+ */
90
+ locale?: string;
91
+
92
+ /**
93
+ * Optional: Store/Channel metadata from platform.
94
+ * @internal
95
+ */
96
+ metadata?: Record<string, unknown>;
97
+ }
98
+
99
+ /**
100
+ * Storefront validation error.
101
+ * Thrown when storefront configuration is invalid or missing.
102
+ *
103
+ * @example
104
+ * ```typescript
105
+ * throw new StorefrontConfigError(
106
+ * 'Medusa requires NEXT_PUBLIC_SALES_CHANNEL_ID',
107
+ * 'medusa',
108
+ * 'NEXT_PUBLIC_SALES_CHANNEL_ID',
109
+ * );
110
+ * ```
111
+ */
112
+ export class StorefrontConfigError extends Error {
113
+ public readonly platformType: string;
114
+ public readonly requiredEnvVar?: string;
115
+
116
+ constructor(
117
+ message: string,
118
+ platformType: string,
119
+ requiredEnvVar?: string,
120
+ ) {
121
+ super(message);
122
+ this.name = 'StorefrontConfigError';
123
+ this.platformType = platformType;
124
+ this.requiredEnvVar = requiredEnvVar;
125
+ }
126
+ }