@meeovi/commerce 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.ts +11 -0
- package/package.json +17 -0
- package/src/cart/registry.ts +13 -0
- package/src/cart/types.ts +18 -0
- package/src/cart/useCart.ts +15 -0
- package/src/categories/registry.ts +13 -0
- package/src/categories/types.ts +13 -0
- package/src/categories/useCategories.ts +12 -0
- package/src/config.ts +19 -0
- package/src/products/registry.ts +13 -0
- package/src/products/types.ts +13 -0
- package/src/products/useProducts.ts +12 -0
- package/src/utils/countryList.ts +14 -0
- package/src/utils/currency.js +56 -0
- package/src/utils/index.js +0 -0
- package/src/utils/stripe.ts +16 -0
package/index.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from './src/products/types'
|
|
2
|
+
export * from './src/products/registry'
|
|
3
|
+
export * from './src/products/useProducts'
|
|
4
|
+
|
|
5
|
+
export * from './src/cart/types'
|
|
6
|
+
export * from './src/cart/registry'
|
|
7
|
+
export * from './src/cart/useCart'
|
|
8
|
+
|
|
9
|
+
export * from './src/categories/types'
|
|
10
|
+
export * from './src/categories/registry'
|
|
11
|
+
export * from './src/categories/useCategories'
|
package/package.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@meeovi/commerce",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Commerce module for the M Framework.",
|
|
5
|
+
"license": "ISC",
|
|
6
|
+
"author": "Meeovi",
|
|
7
|
+
"type": "commonjs",
|
|
8
|
+
"main": "index.js",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@better-auth/stripe": "^1.4.15",
|
|
14
|
+
"@polar-sh/better-auth": "^1.6.4",
|
|
15
|
+
"@polar-sh/sdk": "^0.42.2"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { CartProvider } from "./types"
|
|
2
|
+
|
|
3
|
+
const providers: Record<string, CartProvider> = {}
|
|
4
|
+
|
|
5
|
+
export function registerCartProvider(name: string, provider: CartProvider) {
|
|
6
|
+
providers[name] = provider
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function getCartProvider(name: string) {
|
|
10
|
+
const provider = providers[name]
|
|
11
|
+
if (!provider) throw new Error(`Cart provider "${name}" not found`)
|
|
12
|
+
return provider
|
|
13
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface CartItem {
|
|
2
|
+
id: string
|
|
3
|
+
quantity: number
|
|
4
|
+
product: any
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface Cart {
|
|
8
|
+
id: string
|
|
9
|
+
items: CartItem[]
|
|
10
|
+
total: number
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface CartProvider {
|
|
14
|
+
getCart(): Promise<Cart>
|
|
15
|
+
addItem(productId: string, quantity?: number): Promise<Cart>
|
|
16
|
+
removeItem(productId: string): Promise<Cart>
|
|
17
|
+
clearCart(): Promise<Cart>
|
|
18
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { getCartProvider } from './registry'
|
|
2
|
+
import { useRuntimeConfig } from '#imports'
|
|
3
|
+
|
|
4
|
+
export function useCart() {
|
|
5
|
+
const config = useRuntimeConfig()
|
|
6
|
+
const providerName = config.public.cartProvider || 'directus'
|
|
7
|
+
const provider = getCartProvider(providerName)
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
getCart: provider.getCart,
|
|
11
|
+
addItem: provider.addItem,
|
|
12
|
+
removeItem: provider.removeItem,
|
|
13
|
+
clearCart: provider.clearCart
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { CategoryProvider } from "./types"
|
|
2
|
+
|
|
3
|
+
const providers: Record<string, CategoryProvider> = {}
|
|
4
|
+
|
|
5
|
+
export function registerCategoryProvider(name: string, provider: CategoryProvider) {
|
|
6
|
+
providers[name] = provider
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function getCategoryProvider(name: string) {
|
|
10
|
+
const provider = providers[name]
|
|
11
|
+
if (!provider) throw new Error(`Category provider "${name}" not found`)
|
|
12
|
+
return provider
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface Category {
|
|
2
|
+
id: string
|
|
3
|
+
name: string
|
|
4
|
+
slug: string
|
|
5
|
+
parentId?: string
|
|
6
|
+
children?: Category[]
|
|
7
|
+
[key: string]: any
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface CategoryProvider {
|
|
11
|
+
getCategory(id: string): Promise<Category>
|
|
12
|
+
listCategories(params?: Record<string, any>): Promise<Category[]>
|
|
13
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { getCommerceConfig } from '../config'
|
|
2
|
+
import { getCategoryProvider } from './registry'
|
|
3
|
+
|
|
4
|
+
export function useCategories() {
|
|
5
|
+
const { categoryProvider } = getCommerceConfig()
|
|
6
|
+
const provider = getCategoryProvider(categoryProvider)
|
|
7
|
+
|
|
8
|
+
return {
|
|
9
|
+
getCategory: provider.getCategory,
|
|
10
|
+
listCategories: provider.listCategories
|
|
11
|
+
}
|
|
12
|
+
}
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface CommerceConfig {
|
|
2
|
+
productProvider: string
|
|
3
|
+
cartProvider: string
|
|
4
|
+
categoryProvider: string
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
let config: CommerceConfig = {
|
|
8
|
+
productProvider: 'directus',
|
|
9
|
+
cartProvider: 'directus',
|
|
10
|
+
categoryProvider: 'directus'
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function setCommerceConfig(newConfig: Partial<CommerceConfig>) {
|
|
14
|
+
config = { ...config, ...newConfig }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function getCommerceConfig() {
|
|
18
|
+
return config
|
|
19
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ProductProvider } from "./types"
|
|
2
|
+
|
|
3
|
+
const providers: Record<string, ProductProvider> = {}
|
|
4
|
+
|
|
5
|
+
export function registerProductProvider(name: string, provider: ProductProvider) {
|
|
6
|
+
providers[name] = provider
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function getProductProvider(name: string) {
|
|
10
|
+
const provider = providers[name]
|
|
11
|
+
if (!provider) throw new Error(`Product provider "${name}" not found`)
|
|
12
|
+
return provider
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface Product {
|
|
2
|
+
id: string
|
|
3
|
+
title: string
|
|
4
|
+
description?: string
|
|
5
|
+
price: number
|
|
6
|
+
images: string[]
|
|
7
|
+
[key: string]: any
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface ProductProvider {
|
|
11
|
+
getProduct(id: string): Promise<Product>
|
|
12
|
+
listProducts(params?: Record<string, any>): Promise<Product[]>
|
|
13
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { getCommerceConfig } from '../config'
|
|
2
|
+
import { getProductProvider } from './registry'
|
|
3
|
+
|
|
4
|
+
export function useProducts() {
|
|
5
|
+
const { productProvider } = getCommerceConfig()
|
|
6
|
+
const provider = getProductProvider(productProvider)
|
|
7
|
+
|
|
8
|
+
return {
|
|
9
|
+
getProduct: provider.getProduct,
|
|
10
|
+
listProducts: provider.listProducts
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// ISO 3166-1 country codes and names (short sample, extend as needed)
|
|
2
|
+
export default [
|
|
3
|
+
{ code: 'US', name: 'United States' },
|
|
4
|
+
{ code: 'CA', name: 'Canada' },
|
|
5
|
+
{ code: 'GB', name: 'United Kingdom' },
|
|
6
|
+
{ code: 'DE', name: 'Germany' },
|
|
7
|
+
{ code: 'FR', name: 'France' },
|
|
8
|
+
{ code: 'IT', name: 'Italy' },
|
|
9
|
+
{ code: 'ES', name: 'Spain' },
|
|
10
|
+
{ code: 'AU', name: 'Australia' },
|
|
11
|
+
{ code: 'JP', name: 'Japan' },
|
|
12
|
+
{ code: 'CN', name: 'China' },
|
|
13
|
+
// ...add more as needed
|
|
14
|
+
];
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format a price amount according to the given currency
|
|
3
|
+
* @param {number} amount - The price amount to format
|
|
4
|
+
* @param {string} currency - The currency code (e.g., 'USD', 'EUR')
|
|
5
|
+
* @param {Object} exchangeRates - Object containing exchange rates
|
|
6
|
+
* @returns {string} Formatted price string
|
|
7
|
+
*/
|
|
8
|
+
export const formatPrice = (amount, currency, exchangeRates) => {
|
|
9
|
+
if (!amount || !currency) return ''
|
|
10
|
+
|
|
11
|
+
const rate = exchangeRates[currency] || 1
|
|
12
|
+
const convertedAmount = amount * rate
|
|
13
|
+
|
|
14
|
+
return new Intl.NumberFormat(undefined, {
|
|
15
|
+
style: 'currency',
|
|
16
|
+
currency: currency
|
|
17
|
+
}).format(convertedAmount)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Convert price from one currency to another
|
|
22
|
+
* @param {number} amount - The price amount to convert
|
|
23
|
+
* @param {string} fromCurrency - Source currency code
|
|
24
|
+
* @param {string} toCurrency - Target currency code
|
|
25
|
+
* @param {Object} exchangeRates - Object containing exchange rates
|
|
26
|
+
* @returns {number} Converted price amount
|
|
27
|
+
*/
|
|
28
|
+
export const convertPrice = (amount, fromCurrency, toCurrency, exchangeRates) => {
|
|
29
|
+
if (!amount || !fromCurrency || !toCurrency || !exchangeRates) return amount
|
|
30
|
+
|
|
31
|
+
const fromRate = exchangeRates[fromCurrency] || 1
|
|
32
|
+
const toRate = exchangeRates[toCurrency] || 1
|
|
33
|
+
|
|
34
|
+
return (amount * toRate) / fromRate
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Get currency symbol for a currency code
|
|
39
|
+
* @param {string} code - Currency code
|
|
40
|
+
* @returns {string} Currency symbol
|
|
41
|
+
*/
|
|
42
|
+
export const getCurrencySymbol = (code) => {
|
|
43
|
+
const symbols = {
|
|
44
|
+
USD: '$',
|
|
45
|
+
EUR: '€',
|
|
46
|
+
GBP: '£',
|
|
47
|
+
JPY: '¥',
|
|
48
|
+
AUD: 'A$',
|
|
49
|
+
CAD: 'C$',
|
|
50
|
+
CHF: 'CHF',
|
|
51
|
+
CNY: '¥',
|
|
52
|
+
INR: '₹',
|
|
53
|
+
// Add more currency symbols as needed
|
|
54
|
+
}
|
|
55
|
+
return symbols[code] || code
|
|
56
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// utils/stripe.ts
|
|
2
|
+
import { loadStripe, type Stripe } from '@stripe/stripe-js';
|
|
3
|
+
|
|
4
|
+
let stripePromise: Promise<Stripe | null> | null = null;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Returns a Stripe instance (singleton per publishable key)
|
|
8
|
+
* @param {string} publishableKey - Your Stripe publishable key
|
|
9
|
+
* @returns {Promise<Stripe | null>}
|
|
10
|
+
*/
|
|
11
|
+
export function getStripe(publishableKey: string): Promise<Stripe | null> {
|
|
12
|
+
if (!stripePromise) {
|
|
13
|
+
stripePromise = loadStripe(publishableKey);
|
|
14
|
+
}
|
|
15
|
+
return stripePromise;
|
|
16
|
+
}
|