@meeovi/layer-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.
Files changed (34) hide show
  1. package/README.md +66 -0
  2. package/dist/app/composables/cart/registry.d.ts +3 -0
  3. package/dist/app/composables/cart/registry.js +10 -0
  4. package/dist/app/composables/cart/types.d.ts +16 -0
  5. package/dist/app/composables/cart/types.js +1 -0
  6. package/dist/app/composables/cart/useCart.d.ts +6 -0
  7. package/dist/app/composables/cart/useCart.js +13 -0
  8. package/dist/app/composables/config.d.ts +7 -0
  9. package/dist/app/composables/config.js +11 -0
  10. package/dist/app/composables/products/registry.d.ts +3 -0
  11. package/dist/app/composables/products/registry.js +10 -0
  12. package/dist/app/composables/products/types.d.ts +12 -0
  13. package/dist/app/composables/products/types.js +1 -0
  14. package/dist/app/composables/products/useProducts.d.ts +4 -0
  15. package/dist/app/composables/products/useProducts.js +10 -0
  16. package/dist/app/utils/client.d.ts +6 -0
  17. package/dist/app/utils/client.js +23 -0
  18. package/dist/app/utils/normalizer.d.ts +12 -0
  19. package/dist/app/utils/normalizer.js +13 -0
  20. package/dist/app/utils/normalizers/magento.d.ts +3 -0
  21. package/dist/app/utils/normalizers/magento.js +23 -0
  22. package/dist/app/utils/normalizers/shopify.d.ts +3 -0
  23. package/dist/app/utils/normalizers/shopify.js +24 -0
  24. package/dist/client.d.ts +6 -0
  25. package/dist/client.js +23 -0
  26. package/dist/index.d.ts +6 -0
  27. package/dist/index.js +6 -0
  28. package/dist/normalizer.d.ts +12 -0
  29. package/dist/normalizer.js +13 -0
  30. package/dist/normalizers/magento.d.ts +3 -0
  31. package/dist/normalizers/magento.js +23 -0
  32. package/dist/normalizers/shopify.d.ts +3 -0
  33. package/dist/normalizers/shopify.js +24 -0
  34. package/package.json +63 -0
package/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # @meeovi/commerce
2
+
3
+ A backend‑agnostic commerce domain module for the Meeovi ecosystem.
4
+ This package provides a unified interface for products, categories, carts, and other commerce operations — regardless of the underlying backend (Directus, Medusa, Shopify, custom APIs, etc.).
5
+
6
+ ## ✨ Features
7
+
8
+ - Pluggable provider architecture
9
+ - Unified composables (`useProducts`, `useCart`, `useCategories`)
10
+ - Backend‑agnostic types
11
+ - Runtime configuration
12
+ - Zero Nuxt dependency
13
+ - Works in any JS/TS environment
14
+
15
+ ## 📦 Installation
16
+
17
+ ```sh
18
+ npm install @meeovi/commerce
19
+
20
+ ⚙️ Configuration
21
+ Configure the active providers at runtime:
22
+
23
+
24
+ import { setCommerceConfig } from '@meeovi/commerce'
25
+
26
+ setCommerceConfig({
27
+ productProvider: 'directus',
28
+ cartProvider: 'directus',
29
+ categoryProvider: 'directus'
30
+ })
31
+
32
+ 🧩 Usage
33
+
34
+ import { useProducts } from '@meeovi/commerce'
35
+
36
+ const { listProducts, getProduct } = useProducts()
37
+
38
+ const products = await listProducts()
39
+ const product = await getProduct('123')
40
+ 🔌 Providers
41
+ A provider implements one or more domain interfaces:
42
+
43
+
44
+ export interface ProductProvider {
45
+ getProduct(id: string): Promise<Product>
46
+ listProducts(params?: any): Promise<Product[]>
47
+ }
48
+ Register a provider:
49
+
50
+
51
+ import { registerProductProvider } from '@meeovi/commerce'
52
+
53
+ registerProductProvider('directus', {
54
+ getProduct: async (id) => { ... },
55
+ listProducts: async () => { ... }
56
+ })
57
+
58
+ 🧱 Folder Structure
59
+ Code
60
+ src/
61
+ products/
62
+ cart/
63
+ categories/
64
+ config.
65
+ registry.
66
+ useCommerce.
@@ -0,0 +1,3 @@
1
+ import { CartProvider } from "./types";
2
+ export declare function registerCartProvider(name: string, provider: CartProvider): void;
3
+ export declare function getCartProvider(name: string): CartProvider;
@@ -0,0 +1,10 @@
1
+ const providers = {};
2
+ export function registerCartProvider(name, provider) {
3
+ providers[name] = provider;
4
+ }
5
+ export function getCartProvider(name) {
6
+ const provider = providers[name];
7
+ if (!provider)
8
+ throw new Error(`Cart provider "${name}" not found`);
9
+ return provider;
10
+ }
@@ -0,0 +1,16 @@
1
+ export interface CartItem {
2
+ id: string;
3
+ quantity: number;
4
+ product: any;
5
+ }
6
+ export interface Cart {
7
+ id: string;
8
+ items: CartItem[];
9
+ total: number;
10
+ }
11
+ export interface CartProvider {
12
+ getCart(): Promise<Cart>;
13
+ addItem(productId: string, quantity?: number): Promise<Cart>;
14
+ removeItem(productId: string): Promise<Cart>;
15
+ clearCart(): Promise<Cart>;
16
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ export declare function useCart(): {
2
+ getCart: () => Promise<import("./types").Cart>;
3
+ addItem: (productId: string, quantity?: number) => Promise<import("./types").Cart>;
4
+ removeItem: (productId: string) => Promise<import("./types").Cart>;
5
+ clearCart: () => Promise<import("./types").Cart>;
6
+ };
@@ -0,0 +1,13 @@
1
+ import { getCartProvider } from './registry';
2
+ import { useRuntimeConfig } from '#imports';
3
+ export function useCart() {
4
+ const config = useRuntimeConfig();
5
+ const providerName = config.public.cartProvider || 'directus';
6
+ const provider = getCartProvider(providerName);
7
+ return {
8
+ getCart: provider.getCart,
9
+ addItem: provider.addItem,
10
+ removeItem: provider.removeItem,
11
+ clearCart: provider.clearCart
12
+ };
13
+ }
@@ -0,0 +1,7 @@
1
+ export interface CommerceConfig {
2
+ productProvider: string;
3
+ cartProvider: string;
4
+ categoryProvider: string;
5
+ }
6
+ export declare function setCommerceConfig(newConfig: Partial<CommerceConfig>): void;
7
+ export declare function getCommerceConfig(): CommerceConfig;
@@ -0,0 +1,11 @@
1
+ let config = {
2
+ productProvider: 'directus',
3
+ cartProvider: 'directus',
4
+ categoryProvider: 'directus'
5
+ };
6
+ export function setCommerceConfig(newConfig) {
7
+ config = { ...config, ...newConfig };
8
+ }
9
+ export function getCommerceConfig() {
10
+ return config;
11
+ }
@@ -0,0 +1,3 @@
1
+ import { ProductProvider } from "./types";
2
+ export declare function registerProductProvider(name: string, provider: ProductProvider): void;
3
+ export declare function getProductProvider(name: string): ProductProvider;
@@ -0,0 +1,10 @@
1
+ const providers = {};
2
+ export function registerProductProvider(name, provider) {
3
+ providers[name] = provider;
4
+ }
5
+ export function getProductProvider(name) {
6
+ const provider = providers[name];
7
+ if (!provider)
8
+ throw new Error(`Product provider "${name}" not found`);
9
+ return provider;
10
+ }
@@ -0,0 +1,12 @@
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
+ export interface ProductProvider {
10
+ getProduct(id: string): Promise<Product>;
11
+ listProducts(params?: Record<string, any>): Promise<Product[]>;
12
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ export declare function useProducts(): {
2
+ getProduct: (id: string) => Promise<import("./types").Product>;
3
+ listProducts: (params?: Record<string, any>) => Promise<import("./types").Product[]>;
4
+ };
@@ -0,0 +1,10 @@
1
+ import { getCommerceConfig } from '../config';
2
+ import { getProductProvider } from './registry';
3
+ export function useProducts() {
4
+ const { productProvider } = getCommerceConfig();
5
+ const provider = getProductProvider(productProvider);
6
+ return {
7
+ getProduct: provider.getProduct,
8
+ listProducts: provider.listProducts
9
+ };
10
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Returns a commerce client. Prefer `@meeovi/commerce` client creation APIs
3
+ * when available, otherwise fall back to `sdk.commerce`.
4
+ */
5
+ export declare function getCommerceClient(provider?: string, providerConfig?: any): any;
6
+ export default getCommerceClient;
@@ -0,0 +1,23 @@
1
+ import * as CommercePkg from '#imports';
2
+ import { sdk } from '@meeovi/sdk';
3
+ const CommerceAny = CommercePkg;
4
+ /**
5
+ * Returns a commerce client. Prefer `@meeovi/commerce` client creation APIs
6
+ * when available, otherwise fall back to `sdk.commerce`.
7
+ */
8
+ export function getCommerceClient(provider, providerConfig) {
9
+ try {
10
+ if (typeof CommerceAny.createClient === 'function') {
11
+ return CommerceAny.createClient(provider, providerConfig);
12
+ }
13
+ if (typeof CommerceAny.init === 'function') {
14
+ return CommerceAny.init(providerConfig);
15
+ }
16
+ }
17
+ catch (e) {
18
+ // swallow and fallback to sdk
19
+ }
20
+ // fallback: return the SDK's commerce helper (already used in many composables)
21
+ return sdk.commerce;
22
+ }
23
+ export default getCommerceClient;
@@ -0,0 +1,12 @@
1
+ export interface CommerceNormalizer {
2
+ normalizeProduct(data: any): any;
3
+ normalizeCategory?(data: any): any;
4
+ normalizeCart?(data: any): any;
5
+ }
6
+ export declare class NormalizerRegistry {
7
+ private registry;
8
+ register(name: string, normalizer: CommerceNormalizer): void;
9
+ get(name: string): CommerceNormalizer | undefined;
10
+ list(): string[];
11
+ }
12
+ export default NormalizerRegistry;
@@ -0,0 +1,13 @@
1
+ export class NormalizerRegistry {
2
+ registry = new Map();
3
+ register(name, normalizer) {
4
+ this.registry.set(name, normalizer);
5
+ }
6
+ get(name) {
7
+ return this.registry.get(name);
8
+ }
9
+ list() {
10
+ return Array.from(this.registry.keys());
11
+ }
12
+ }
13
+ export default NormalizerRegistry;
@@ -0,0 +1,3 @@
1
+ import { CommerceNormalizer } from "../normalizer";
2
+ export declare const magentoNormalizer: CommerceNormalizer;
3
+ export default magentoNormalizer;
@@ -0,0 +1,23 @@
1
+ export const magentoNormalizer = {
2
+ normalizeProduct(data) {
3
+ return {
4
+ id: data?.id ?? data?.sku ?? data?.item_id,
5
+ title: data?.name ?? data?.title,
6
+ price: data?.price ?? data?.price_range?.minimum_price?.final_price?.value,
7
+ description: data?.description ?? data?.short_description,
8
+ images: (data?.media_gallery_entries ?? []).map((m) => m.file || m.url),
9
+ raw: data,
10
+ };
11
+ },
12
+ normalizeCategory(data) {
13
+ return {
14
+ id: data?.id,
15
+ name: data?.name,
16
+ raw: data,
17
+ };
18
+ },
19
+ normalizeCart(data) {
20
+ return { raw: data };
21
+ },
22
+ };
23
+ export default magentoNormalizer;
@@ -0,0 +1,3 @@
1
+ import { CommerceNormalizer } from "../normalizer";
2
+ export declare const shopifyNormalizer: CommerceNormalizer;
3
+ export default shopifyNormalizer;
@@ -0,0 +1,24 @@
1
+ export const shopifyNormalizer = {
2
+ normalizeProduct(data) {
3
+ // Shopify payloads vary depending on SDK; this maps common fields
4
+ return {
5
+ id: data?.id ?? data?.variants?.[0]?.id,
6
+ title: data?.title ?? data?.name,
7
+ price: data?.variants?.[0]?.price ?? data?.price,
8
+ description: data?.body_html ?? data?.description,
9
+ images: (data?.images ?? []).map((i) => i?.src || i?.url),
10
+ raw: data,
11
+ };
12
+ },
13
+ normalizeCategory(data) {
14
+ return {
15
+ id: data?.id,
16
+ name: data?.title ?? data?.name,
17
+ raw: data,
18
+ };
19
+ },
20
+ normalizeCart(data) {
21
+ return { raw: data };
22
+ },
23
+ };
24
+ export default shopifyNormalizer;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Returns a commerce client. Prefer `@meeovi/commerce` client creation APIs
3
+ * when available, otherwise fall back to `sdk.commerce`.
4
+ */
5
+ export declare function getCommerceClient(provider?: string, providerConfig?: any): any;
6
+ export default getCommerceClient;
package/dist/client.js ADDED
@@ -0,0 +1,23 @@
1
+ import * as CommercePkg from '@meeovi/commerce';
2
+ import { sdk } from '@meeovi/sdk';
3
+ const CommerceAny = CommercePkg;
4
+ /**
5
+ * Returns a commerce client. Prefer `@meeovi/commerce` client creation APIs
6
+ * when available, otherwise fall back to `sdk.commerce`.
7
+ */
8
+ export function getCommerceClient(provider, providerConfig) {
9
+ try {
10
+ if (typeof CommerceAny.createClient === 'function') {
11
+ return CommerceAny.createClient(provider, providerConfig);
12
+ }
13
+ if (typeof CommerceAny.init === 'function') {
14
+ return CommerceAny.init(providerConfig);
15
+ }
16
+ }
17
+ catch (e) {
18
+ // swallow and fallback to sdk
19
+ }
20
+ // fallback: return the SDK's commerce helper (already used in many composables)
21
+ return sdk.commerce;
22
+ }
23
+ export default getCommerceClient;
@@ -0,0 +1,6 @@
1
+ export * from './app/composables/products/types';
2
+ export * from './app/composables/products/registry';
3
+ export * from './app/composables/products/useProducts';
4
+ export * from './app/composables/cart/types';
5
+ export * from './app/composables/cart/registry';
6
+ export * from './app/composables/cart/useCart';
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export * from './app/composables/products/types';
2
+ export * from './app/composables/products/registry';
3
+ export * from './app/composables/products/useProducts';
4
+ export * from './app/composables/cart/types';
5
+ export * from './app/composables/cart/registry';
6
+ export * from './app/composables/cart/useCart';
@@ -0,0 +1,12 @@
1
+ export interface CommerceNormalizer {
2
+ normalizeProduct(data: any): any;
3
+ normalizeCategory?(data: any): any;
4
+ normalizeCart?(data: any): any;
5
+ }
6
+ export declare class NormalizerRegistry {
7
+ private registry;
8
+ register(name: string, normalizer: CommerceNormalizer): void;
9
+ get(name: string): CommerceNormalizer | undefined;
10
+ list(): string[];
11
+ }
12
+ export default NormalizerRegistry;
@@ -0,0 +1,13 @@
1
+ export class NormalizerRegistry {
2
+ registry = new Map();
3
+ register(name, normalizer) {
4
+ this.registry.set(name, normalizer);
5
+ }
6
+ get(name) {
7
+ return this.registry.get(name);
8
+ }
9
+ list() {
10
+ return Array.from(this.registry.keys());
11
+ }
12
+ }
13
+ export default NormalizerRegistry;
@@ -0,0 +1,3 @@
1
+ import { CommerceNormalizer } from "../normalizer";
2
+ export declare const magentoNormalizer: CommerceNormalizer;
3
+ export default magentoNormalizer;
@@ -0,0 +1,23 @@
1
+ export const magentoNormalizer = {
2
+ normalizeProduct(data) {
3
+ return {
4
+ id: data?.id ?? data?.sku ?? data?.item_id,
5
+ title: data?.name ?? data?.title,
6
+ price: data?.price ?? data?.price_range?.minimum_price?.final_price?.value,
7
+ description: data?.description ?? data?.short_description,
8
+ images: (data?.media_gallery_entries ?? []).map((m) => m.file || m.url),
9
+ raw: data,
10
+ };
11
+ },
12
+ normalizeCategory(data) {
13
+ return {
14
+ id: data?.id,
15
+ name: data?.name,
16
+ raw: data,
17
+ };
18
+ },
19
+ normalizeCart(data) {
20
+ return { raw: data };
21
+ },
22
+ };
23
+ export default magentoNormalizer;
@@ -0,0 +1,3 @@
1
+ import { CommerceNormalizer } from "../normalizer";
2
+ export declare const shopifyNormalizer: CommerceNormalizer;
3
+ export default shopifyNormalizer;
@@ -0,0 +1,24 @@
1
+ export const shopifyNormalizer = {
2
+ normalizeProduct(data) {
3
+ // Shopify payloads vary depending on SDK; this maps common fields
4
+ return {
5
+ id: data?.id ?? data?.variants?.[0]?.id,
6
+ title: data?.title ?? data?.name,
7
+ price: data?.variants?.[0]?.price ?? data?.price,
8
+ description: data?.body_html ?? data?.description,
9
+ images: (data?.images ?? []).map((i) => i?.src || i?.url),
10
+ raw: data,
11
+ };
12
+ },
13
+ normalizeCategory(data) {
14
+ return {
15
+ id: data?.id,
16
+ name: data?.title ?? data?.name,
17
+ raw: data,
18
+ };
19
+ },
20
+ normalizeCart(data) {
21
+ return { raw: data };
22
+ },
23
+ };
24
+ export default shopifyNormalizer;
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@meeovi/layer-commerce",
3
+ "version": "1.0.0",
4
+ "description": "Commerce Layer for the Alternate Framework",
5
+ "keywords": [
6
+ "commerce",
7
+ "alternate-framework",
8
+ "nuxt",
9
+ "layer"
10
+ ],
11
+ "license": "MIT",
12
+ "author": "Meeovi",
13
+ "main": "dist/index.js",
14
+ "module": "dist/index.js",
15
+ "types": "dist/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "import": "./dist/index.js",
19
+ "types": "./dist/index.d.ts"
20
+ }
21
+ },
22
+ "scripts": {
23
+ "test": "vitest",
24
+ "build": "tsc -p tsconfig.json",
25
+ "typecheck": "tsc -p tsconfig.json --noEmit",
26
+ "lint": "eslint 'src/**/*.{ts,tsx}' || true",
27
+ "clean": "rimraf dist",
28
+ "prepare": "npm run build",
29
+ "prepublishOnly": "npm run typecheck && npm run build",
30
+ "codegen": "npx graphql-codegen --config ./node_modules/@meeovi/adapter-magento/codegen.ts"
31
+ },
32
+ "files": [
33
+ "dist"
34
+ ],
35
+ "peerDependencies": {
36
+ "@meeovi/types": "^1.0.0"
37
+ },
38
+ "dependencies": {
39
+ "@meeovi/adapter-magento": "^1.0.2",
40
+ "@meeovi/api": "^1.0.1",
41
+ "@meeovi/sdk": "^1.0.2",
42
+ "@meeovi/types": "^1.0.0",
43
+ "@better-auth/stripe": "^1.4.15",
44
+ "@meeovi/core": "^1.0.1",
45
+ "@polar-sh/better-auth": "^1.6.4",
46
+ "@polar-sh/sdk": "^0.42.2",
47
+ "@storefront-ui/nuxt": "^3.1.1",
48
+ "ramda": "^0.32.0",
49
+ "type-fest": "^5.4.1"
50
+ },
51
+ "devDependencies": {
52
+ "@biomejs/biome": "^2.3.11",
53
+ "@types/ramda": "^0.31.1",
54
+ "@vitest/coverage-v8": "^4.0.17",
55
+ "jest-cucumber": "^4.5.0",
56
+ "vitest": "^4.0.17",
57
+ "@types/node": "^20.0.0",
58
+ "eslint": "^8.0.0",
59
+ "nuxt": "^4.2.2",
60
+ "rimraf": "^5.0.0",
61
+ "typescript": "^5.8.2"
62
+ }
63
+ }