@commercejs/nuxt 0.2.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/README.md +99 -0
- package/dist/module.cjs +5 -0
- package/dist/module.d.mts +23 -0
- package/dist/module.d.ts +23 -0
- package/dist/module.json +12 -0
- package/dist/module.mjs +101 -0
- package/dist/runtime/composables/index.d.ts +0 -0
- package/dist/runtime/composables/index.js +15 -0
- package/dist/runtime/composables/useAdapter.d.ts +0 -0
- package/dist/runtime/composables/useAdapter.js +11 -0
- package/dist/runtime/composables/useBrands.d.ts +0 -0
- package/dist/runtime/composables/useBrands.js +32 -0
- package/dist/runtime/composables/useCart.d.ts +0 -0
- package/dist/runtime/composables/useCart.js +144 -0
- package/dist/runtime/composables/useCategories.d.ts +0 -0
- package/dist/runtime/composables/useCategories.js +9 -0
- package/dist/runtime/composables/useCheckout.d.ts +0 -0
- package/dist/runtime/composables/useCheckout.js +142 -0
- package/dist/runtime/composables/useCountries.d.ts +0 -0
- package/dist/runtime/composables/useCountries.js +32 -0
- package/dist/runtime/composables/useCustomer.d.ts +0 -0
- package/dist/runtime/composables/useCustomer.js +179 -0
- package/dist/runtime/composables/useLocations.d.ts +0 -0
- package/dist/runtime/composables/useLocations.js +32 -0
- package/dist/runtime/composables/useProduct.d.ts +0 -0
- package/dist/runtime/composables/useProduct.js +16 -0
- package/dist/runtime/composables/useProducts.d.ts +0 -0
- package/dist/runtime/composables/useProducts.js +26 -0
- package/dist/runtime/composables/usePromotions.d.ts +0 -0
- package/dist/runtime/composables/usePromotions.js +48 -0
- package/dist/runtime/composables/useReturns.d.ts +0 -0
- package/dist/runtime/composables/useReturns.js +89 -0
- package/dist/runtime/composables/useReviews.d.ts +0 -0
- package/dist/runtime/composables/useReviews.js +77 -0
- package/dist/runtime/composables/useStoreInfo.d.ts +0 -0
- package/dist/runtime/composables/useStoreInfo.js +15 -0
- package/dist/runtime/composables/useWishlist.d.ts +0 -0
- package/dist/runtime/composables/useWishlist.js +82 -0
- package/dist/runtime/plugin.d.ts +0 -0
- package/dist/runtime/plugin.js +24 -0
- package/dist/runtime/server/api/auth.forgot-password.post.d.ts +0 -0
- package/dist/runtime/server/api/auth.forgot-password.post.js +8 -0
- package/dist/runtime/server/api/auth.login.post.d.ts +0 -0
- package/dist/runtime/server/api/auth.login.post.js +7 -0
- package/dist/runtime/server/api/auth.logout.post.d.ts +0 -0
- package/dist/runtime/server/api/auth.logout.post.js +7 -0
- package/dist/runtime/server/api/auth.register.post.d.ts +0 -0
- package/dist/runtime/server/api/auth.register.post.js +7 -0
- package/dist/runtime/server/api/auth.reset-password.post.d.ts +0 -0
- package/dist/runtime/server/api/auth.reset-password.post.js +8 -0
- package/dist/runtime/server/api/brands.get.d.ts +0 -0
- package/dist/runtime/server/api/brands.get.js +6 -0
- package/dist/runtime/server/api/cart.[id].get.d.ts +0 -0
- package/dist/runtime/server/api/cart.[id].get.js +7 -0
- package/dist/runtime/server/api/cart.[id].items.[itemId].delete.d.ts +0 -0
- package/dist/runtime/server/api/cart.[id].items.[itemId].delete.js +8 -0
- package/dist/runtime/server/api/cart.[id].items.[itemId].put.d.ts +0 -0
- package/dist/runtime/server/api/cart.[id].items.[itemId].put.js +9 -0
- package/dist/runtime/server/api/cart.[id].items.post.d.ts +0 -0
- package/dist/runtime/server/api/cart.[id].items.post.js +8 -0
- package/dist/runtime/server/api/cart.post.d.ts +0 -0
- package/dist/runtime/server/api/cart.post.js +6 -0
- package/dist/runtime/server/api/categories.get.d.ts +0 -0
- package/dist/runtime/server/api/categories.get.js +10 -0
- package/dist/runtime/server/api/checkout.payment-methods.[cartId].get.d.ts +0 -0
- package/dist/runtime/server/api/checkout.payment-methods.[cartId].get.js +7 -0
- package/dist/runtime/server/api/checkout.place-order.post.d.ts +0 -0
- package/dist/runtime/server/api/checkout.place-order.post.js +7 -0
- package/dist/runtime/server/api/checkout.shipping-methods.[cartId].get.d.ts +0 -0
- package/dist/runtime/server/api/checkout.shipping-methods.[cartId].get.js +7 -0
- package/dist/runtime/server/api/countries.get.d.ts +0 -0
- package/dist/runtime/server/api/countries.get.js +6 -0
- package/dist/runtime/server/api/customer.addresses.[addressId].delete.d.ts +0 -0
- package/dist/runtime/server/api/customer.addresses.[addressId].delete.js +8 -0
- package/dist/runtime/server/api/customer.addresses.[addressId].put.d.ts +0 -0
- package/dist/runtime/server/api/customer.addresses.[addressId].put.js +8 -0
- package/dist/runtime/server/api/customer.addresses.get.d.ts +0 -0
- package/dist/runtime/server/api/customer.addresses.get.js +6 -0
- package/dist/runtime/server/api/customer.addresses.post.d.ts +0 -0
- package/dist/runtime/server/api/customer.addresses.post.js +7 -0
- package/dist/runtime/server/api/customer.get.d.ts +0 -0
- package/dist/runtime/server/api/customer.get.js +6 -0
- package/dist/runtime/server/api/customer.orders.get.d.ts +0 -0
- package/dist/runtime/server/api/customer.orders.get.js +10 -0
- package/dist/runtime/server/api/locations.get.d.ts +0 -0
- package/dist/runtime/server/api/locations.get.js +6 -0
- package/dist/runtime/server/api/products.[id].get.d.ts +0 -0
- package/dist/runtime/server/api/products.[id].get.js +7 -0
- package/dist/runtime/server/api/products.get.d.ts +0 -0
- package/dist/runtime/server/api/products.get.js +13 -0
- package/dist/runtime/server/api/promotions.get.d.ts +0 -0
- package/dist/runtime/server/api/promotions.get.js +6 -0
- package/dist/runtime/server/api/promotions.validate.post.d.ts +0 -0
- package/dist/runtime/server/api/promotions.validate.post.js +7 -0
- package/dist/runtime/server/api/returns.[returnId].cancel.post.d.ts +0 -0
- package/dist/runtime/server/api/returns.[returnId].cancel.post.js +7 -0
- package/dist/runtime/server/api/returns.[returnId].get.d.ts +0 -0
- package/dist/runtime/server/api/returns.[returnId].get.js +7 -0
- package/dist/runtime/server/api/returns.get.d.ts +0 -0
- package/dist/runtime/server/api/returns.get.js +10 -0
- package/dist/runtime/server/api/returns.post.d.ts +0 -0
- package/dist/runtime/server/api/returns.post.js +7 -0
- package/dist/runtime/server/api/reviews.[productId].get.d.ts +0 -0
- package/dist/runtime/server/api/reviews.[productId].get.js +11 -0
- package/dist/runtime/server/api/reviews.[productId].summary.get.d.ts +0 -0
- package/dist/runtime/server/api/reviews.[productId].summary.get.js +7 -0
- package/dist/runtime/server/api/reviews.post.d.ts +0 -0
- package/dist/runtime/server/api/reviews.post.js +7 -0
- package/dist/runtime/server/api/store.get.d.ts +0 -0
- package/dist/runtime/server/api/store.get.js +6 -0
- package/dist/runtime/server/api/wishlist.get.d.ts +0 -0
- package/dist/runtime/server/api/wishlist.get.js +6 -0
- package/dist/runtime/server/api/wishlist.items.[itemId].delete.d.ts +0 -0
- package/dist/runtime/server/api/wishlist.items.[itemId].delete.js +7 -0
- package/dist/runtime/server/api/wishlist.items.post.d.ts +0 -0
- package/dist/runtime/server/api/wishlist.items.post.js +7 -0
- package/dist/runtime/server/plugins/commerce-adapter.d.ts +0 -0
- package/dist/runtime/server/plugins/commerce-adapter.js +25 -0
- package/dist/runtime/server/utils/adapter.d.ts +0 -0
- package/dist/runtime/server/utils/adapter.js +11 -0
- package/dist/types.d.mts +7 -0
- package/dist/types.d.ts +7 -0
- package/package.json +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# @commercejs/nuxt
|
|
2
|
+
|
|
3
|
+
CommerceJS Nuxt module — composables, plugin, and auto-generated REST API.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@commercejs/nuxt)
|
|
6
|
+
[](https://nuxt.com/)
|
|
7
|
+
[](https://www.typescriptlang.org/)
|
|
8
|
+
[](https://opensource.org/licenses/MIT)
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
`@commercejs/nuxt` is a Nuxt module that integrates CommerceJS into your Nuxt application. It provides auto-imported composables, injects the adapter into your app context, and optionally generates a full REST API from your adapter — zero boilerplate.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @commercejs/nuxt @commercejs/types @commercejs/adapter-salla
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Setup
|
|
21
|
+
|
|
22
|
+
Add the module to your `nuxt.config.ts`:
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
export default defineNuxtConfig({
|
|
26
|
+
modules: ['@commercejs/nuxt'],
|
|
27
|
+
|
|
28
|
+
commerce: {
|
|
29
|
+
adapter: 'salla', // adapter package to use
|
|
30
|
+
apiBase: '/api/_commerce', // REST API base path (default)
|
|
31
|
+
apiRoutes: true, // auto-generate REST routes (default)
|
|
32
|
+
},
|
|
33
|
+
})
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
### Composables
|
|
39
|
+
|
|
40
|
+
The module auto-imports composables for your Vue components:
|
|
41
|
+
|
|
42
|
+
```vue
|
|
43
|
+
<script setup>
|
|
44
|
+
const { data: products } = await useCommerce().getProducts({ limit: 12 })
|
|
45
|
+
const { data: cart } = await useCommerce().getCart(cartId)
|
|
46
|
+
</script>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Plugin
|
|
50
|
+
|
|
51
|
+
The adapter is available on `$commerce` in your Nuxt app:
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
const { $commerce } = useNuxtApp()
|
|
55
|
+
const store = await $commerce.getStore()
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Auto-Generated REST API
|
|
59
|
+
|
|
60
|
+
When `apiRoutes` is enabled, the module registers 40+ REST endpoints:
|
|
61
|
+
|
|
62
|
+
| Endpoint | Method | Description |
|
|
63
|
+
|----------|--------|-------------|
|
|
64
|
+
| `/api/_commerce/products` | GET | List products |
|
|
65
|
+
| `/api/_commerce/products/:id` | GET | Get product by ID |
|
|
66
|
+
| `/api/_commerce/categories` | GET | List categories |
|
|
67
|
+
| `/api/_commerce/cart` | POST | Create cart |
|
|
68
|
+
| `/api/_commerce/cart/:id` | GET | Get cart |
|
|
69
|
+
| `/api/_commerce/cart/:id/items` | POST | Add to cart |
|
|
70
|
+
| `/api/_commerce/checkout/place-order` | POST | Place order |
|
|
71
|
+
| `/api/_commerce/auth/login` | POST | Login |
|
|
72
|
+
| `/api/_commerce/customer` | GET | Get customer profile |
|
|
73
|
+
| `/api/_commerce/customer/orders` | GET | List orders |
|
|
74
|
+
| `/api/_commerce/wishlist` | GET | Get wishlist |
|
|
75
|
+
| `/api/_commerce/reviews/:productId` | GET | Get product reviews |
|
|
76
|
+
| ... | ... | 30+ more routes |
|
|
77
|
+
|
|
78
|
+
## Configuration
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
interface CommerceModuleOptions {
|
|
82
|
+
/** Adapter name: 'salla', 'shopify', 'medusa', etc. */
|
|
83
|
+
adapter?: string
|
|
84
|
+
|
|
85
|
+
/** REST API base path (default: '/api/_commerce') */
|
|
86
|
+
apiBase?: string
|
|
87
|
+
|
|
88
|
+
/** Auto-generate REST API routes (default: true) */
|
|
89
|
+
apiRoutes?: boolean
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Documentation
|
|
94
|
+
|
|
95
|
+
Full docs at [commerce.js.org](https://commerce.js.org)
|
|
96
|
+
|
|
97
|
+
## License
|
|
98
|
+
|
|
99
|
+
[MIT](../../LICENSE)
|
package/dist/module.cjs
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { NuxtModule } from '@nuxt/schema';
|
|
2
|
+
|
|
3
|
+
interface CommerceModuleOptions {
|
|
4
|
+
/**
|
|
5
|
+
* The adapter to use (e.g., 'salla', 'zid', 'shopify', 'medusa').
|
|
6
|
+
* The adapter package must be installed separately.
|
|
7
|
+
*/
|
|
8
|
+
adapter?: string;
|
|
9
|
+
/**
|
|
10
|
+
* Base path for auto-generated REST API routes.
|
|
11
|
+
* @default '/api/_commerce'
|
|
12
|
+
*/
|
|
13
|
+
apiBase?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Whether to register auto-generated REST API routes.
|
|
16
|
+
* @default true
|
|
17
|
+
*/
|
|
18
|
+
apiRoutes?: boolean;
|
|
19
|
+
}
|
|
20
|
+
declare const commerceModule: NuxtModule<CommerceModuleOptions>;
|
|
21
|
+
|
|
22
|
+
export { commerceModule as default };
|
|
23
|
+
export type { CommerceModuleOptions };
|
package/dist/module.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { NuxtModule } from '@nuxt/schema';
|
|
2
|
+
|
|
3
|
+
interface CommerceModuleOptions {
|
|
4
|
+
/**
|
|
5
|
+
* The adapter to use (e.g., 'salla', 'zid', 'shopify', 'medusa').
|
|
6
|
+
* The adapter package must be installed separately.
|
|
7
|
+
*/
|
|
8
|
+
adapter?: string;
|
|
9
|
+
/**
|
|
10
|
+
* Base path for auto-generated REST API routes.
|
|
11
|
+
* @default '/api/_commerce'
|
|
12
|
+
*/
|
|
13
|
+
apiBase?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Whether to register auto-generated REST API routes.
|
|
16
|
+
* @default true
|
|
17
|
+
*/
|
|
18
|
+
apiRoutes?: boolean;
|
|
19
|
+
}
|
|
20
|
+
declare const commerceModule: NuxtModule<CommerceModuleOptions>;
|
|
21
|
+
|
|
22
|
+
export { commerceModule as default };
|
|
23
|
+
export type { CommerceModuleOptions };
|
package/dist/module.json
ADDED
package/dist/module.mjs
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { defineNuxtModule, createResolver, addTypeTemplate, addPlugin, addServerPlugin, addImportsDir, addServerHandler } from '@nuxt/kit';
|
|
2
|
+
import { consola } from 'consola';
|
|
3
|
+
|
|
4
|
+
const logger = consola.withTag("@commercejs/nuxt");
|
|
5
|
+
const commerceModule = defineNuxtModule({
|
|
6
|
+
meta: {
|
|
7
|
+
name: "@commercejs/nuxt",
|
|
8
|
+
configKey: "commerce",
|
|
9
|
+
compatibility: {
|
|
10
|
+
nuxt: ">=3.0.0"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
defaults: {
|
|
14
|
+
apiBase: "/api/_commerce",
|
|
15
|
+
apiRoutes: true
|
|
16
|
+
},
|
|
17
|
+
setup(options, nuxt) {
|
|
18
|
+
const { resolve } = createResolver(import.meta.url);
|
|
19
|
+
logger.info("Initializing CommerceJS module...");
|
|
20
|
+
nuxt.options.runtimeConfig.public.commerce = {
|
|
21
|
+
adapter: options.adapter || "",
|
|
22
|
+
apiBase: options.apiBase || "/api/_commerce"
|
|
23
|
+
};
|
|
24
|
+
addTypeTemplate({
|
|
25
|
+
filename: "types/commercejs.d.ts",
|
|
26
|
+
getContents: () => `
|
|
27
|
+
import type { CommerceAdapter } from '@commercejs/types'
|
|
28
|
+
|
|
29
|
+
declare module '#app' {
|
|
30
|
+
interface NuxtApp {
|
|
31
|
+
$commerce: CommerceAdapter
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
declare module 'vue' {
|
|
36
|
+
interface ComponentCustomProperties {
|
|
37
|
+
$commerce: CommerceAdapter
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export {}
|
|
42
|
+
`
|
|
43
|
+
});
|
|
44
|
+
addPlugin(resolve("./runtime/plugin"));
|
|
45
|
+
addServerPlugin(resolve("./runtime/server/plugins/commerce-adapter"));
|
|
46
|
+
addImportsDir(resolve("./runtime/composables"));
|
|
47
|
+
if (options.apiRoutes) {
|
|
48
|
+
const apiBase = options.apiBase || "/api/_commerce";
|
|
49
|
+
let routeCount = 0;
|
|
50
|
+
const route = (path, handler, method) => {
|
|
51
|
+
addServerHandler({
|
|
52
|
+
route: `${apiBase}${path}`,
|
|
53
|
+
handler: resolve(`./runtime/server/api/${handler}`),
|
|
54
|
+
...method ? { method } : {}
|
|
55
|
+
});
|
|
56
|
+
routeCount++;
|
|
57
|
+
};
|
|
58
|
+
route("/store", "store.get");
|
|
59
|
+
route("/products", "products.get");
|
|
60
|
+
route("/products/:id", "products.[id].get");
|
|
61
|
+
route("/categories", "categories.get");
|
|
62
|
+
route("/brands", "brands.get");
|
|
63
|
+
route("/cart", "cart.post", "post");
|
|
64
|
+
route("/cart/:id", "cart.[id].get");
|
|
65
|
+
route("/cart/:id/items", "cart.[id].items.post", "post");
|
|
66
|
+
route("/cart/:id/items/:itemId", "cart.[id].items.[itemId].put", "put");
|
|
67
|
+
route("/cart/:id/items/:itemId", "cart.[id].items.[itemId].delete", "delete");
|
|
68
|
+
route("/checkout/shipping-methods/:cartId", "checkout.shipping-methods.[cartId].get");
|
|
69
|
+
route("/checkout/payment-methods/:cartId", "checkout.payment-methods.[cartId].get");
|
|
70
|
+
route("/checkout/place-order", "checkout.place-order.post", "post");
|
|
71
|
+
route("/auth/login", "auth.login.post", "post");
|
|
72
|
+
route("/auth/register", "auth.register.post", "post");
|
|
73
|
+
route("/auth/logout", "auth.logout.post", "post");
|
|
74
|
+
route("/auth/forgot-password", "auth.forgot-password.post", "post");
|
|
75
|
+
route("/auth/reset-password", "auth.reset-password.post", "post");
|
|
76
|
+
route("/customer", "customer.get");
|
|
77
|
+
route("/customer/orders", "customer.orders.get");
|
|
78
|
+
route("/customer/addresses", "customer.addresses.get");
|
|
79
|
+
route("/customer/addresses", "customer.addresses.post", "post");
|
|
80
|
+
route("/customer/addresses/:addressId", "customer.addresses.[addressId].put", "put");
|
|
81
|
+
route("/customer/addresses/:addressId", "customer.addresses.[addressId].delete", "delete");
|
|
82
|
+
route("/reviews/:productId", "reviews.[productId].get");
|
|
83
|
+
route("/reviews/:productId/summary", "reviews.[productId].summary.get");
|
|
84
|
+
route("/reviews", "reviews.post", "post");
|
|
85
|
+
route("/wishlist", "wishlist.get");
|
|
86
|
+
route("/wishlist/items", "wishlist.items.post", "post");
|
|
87
|
+
route("/wishlist/items/:itemId", "wishlist.items.[itemId].delete", "delete");
|
|
88
|
+
route("/promotions", "promotions.get");
|
|
89
|
+
route("/promotions/validate", "promotions.validate.post", "post");
|
|
90
|
+
route("/returns", "returns.get");
|
|
91
|
+
route("/returns", "returns.post", "post");
|
|
92
|
+
route("/returns/:returnId", "returns.[returnId].get");
|
|
93
|
+
route("/returns/:returnId/cancel", "returns.[returnId].cancel.post", "post");
|
|
94
|
+
route("/countries", "countries.get");
|
|
95
|
+
route("/locations", "locations.get");
|
|
96
|
+
logger.info(`Registered ${routeCount} REST API routes under ${apiBase}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
export { commerceModule as default };
|
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { useAdapter } from "./useAdapter.js";
|
|
2
|
+
export { useProduct } from "./useProduct.js";
|
|
3
|
+
export { useProducts } from "./useProducts.js";
|
|
4
|
+
export { useCategories } from "./useCategories.js";
|
|
5
|
+
export { useCart } from "./useCart.js";
|
|
6
|
+
export { useCustomer } from "./useCustomer.js";
|
|
7
|
+
export { useCheckout } from "./useCheckout.js";
|
|
8
|
+
export { useWishlist } from "./useWishlist.js";
|
|
9
|
+
export { useReviews } from "./useReviews.js";
|
|
10
|
+
export { useStoreInfo } from "./useStoreInfo.js";
|
|
11
|
+
export { usePromotions } from "./usePromotions.js";
|
|
12
|
+
export { useReturns } from "./useReturns.js";
|
|
13
|
+
export { useBrands } from "./useBrands.js";
|
|
14
|
+
export { useCountries } from "./useCountries.js";
|
|
15
|
+
export { useLocations } from "./useLocations.js";
|
|
File without changes
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { useNuxtApp } from "#imports";
|
|
2
|
+
export function useAdapter() {
|
|
3
|
+
const nuxtApp = useNuxtApp();
|
|
4
|
+
const adapter = nuxtApp.$commerce;
|
|
5
|
+
if (!adapter && import.meta.server) {
|
|
6
|
+
throw new Error(
|
|
7
|
+
"[@commercejs/nuxt] No commerce adapter available. Make sure you have installed and configured an adapter package (e.g., @commercejs/adapter-salla, @commercejs/adapter-zid)."
|
|
8
|
+
);
|
|
9
|
+
}
|
|
10
|
+
return adapter || null;
|
|
11
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { useState, readonly } from "#imports";
|
|
2
|
+
import { CommerceError, isCommerceError } from "@commercejs/types";
|
|
3
|
+
import { useAdapter } from "./useAdapter.js";
|
|
4
|
+
export function useBrands() {
|
|
5
|
+
const adapter = useAdapter();
|
|
6
|
+
const brands = useState("commerce:brands", () => []);
|
|
7
|
+
const loading = useState("commerce:brands:loading", () => false);
|
|
8
|
+
const error = useState("commerce:brands:error", () => null);
|
|
9
|
+
async function refresh() {
|
|
10
|
+
loading.value = true;
|
|
11
|
+
error.value = null;
|
|
12
|
+
try {
|
|
13
|
+
brands.value = await adapter.getBrands();
|
|
14
|
+
} catch (err) {
|
|
15
|
+
const e = isCommerceError(err) ? err : new CommerceError(
|
|
16
|
+
err instanceof Error ? err.message : String(err),
|
|
17
|
+
"UNKNOWN",
|
|
18
|
+
void 0,
|
|
19
|
+
err
|
|
20
|
+
);
|
|
21
|
+
error.value = e;
|
|
22
|
+
} finally {
|
|
23
|
+
loading.value = false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
brands: readonly(brands),
|
|
28
|
+
loading: readonly(loading),
|
|
29
|
+
error: readonly(error),
|
|
30
|
+
refresh
|
|
31
|
+
};
|
|
32
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { useState, useCookie, computed, readonly, useRuntimeConfig } from "#imports";
|
|
2
|
+
import { CommerceError, isCommerceError } from "@commercejs/types";
|
|
3
|
+
import { createEventHook } from "@vueuse/core";
|
|
4
|
+
export function useCart() {
|
|
5
|
+
const config = useRuntimeConfig();
|
|
6
|
+
const apiBase = config.public.commerce?.apiBase || "/api/_commerce";
|
|
7
|
+
const cartId = useCookie("commerce_cart_id", { maxAge: 60 * 60 * 24 * 30 });
|
|
8
|
+
const cart = useState("commerce_cart", () => null);
|
|
9
|
+
const loading = useState("commerce_cart_loading", () => false);
|
|
10
|
+
const error = useState("commerce_cart_error", () => null);
|
|
11
|
+
const itemAddedHook = createEventHook();
|
|
12
|
+
const itemUpdatedHook = createEventHook();
|
|
13
|
+
const itemRemovedHook = createEventHook();
|
|
14
|
+
const errorHook = createEventHook();
|
|
15
|
+
function handleError(err) {
|
|
16
|
+
const e = isCommerceError(err) ? err : new CommerceError(
|
|
17
|
+
err instanceof Error ? err.message : String(err),
|
|
18
|
+
"UNKNOWN",
|
|
19
|
+
void 0,
|
|
20
|
+
err
|
|
21
|
+
);
|
|
22
|
+
error.value = e;
|
|
23
|
+
errorHook.trigger(e);
|
|
24
|
+
return e;
|
|
25
|
+
}
|
|
26
|
+
async function createCart() {
|
|
27
|
+
loading.value = true;
|
|
28
|
+
error.value = null;
|
|
29
|
+
try {
|
|
30
|
+
const newCart = await $fetch(`${apiBase}/cart`, { method: "POST" });
|
|
31
|
+
cart.value = newCart;
|
|
32
|
+
cartId.value = newCart.id;
|
|
33
|
+
return newCart;
|
|
34
|
+
} catch (err) {
|
|
35
|
+
throw handleError(err);
|
|
36
|
+
} finally {
|
|
37
|
+
loading.value = false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async function refresh() {
|
|
41
|
+
if (!cartId.value) return;
|
|
42
|
+
loading.value = true;
|
|
43
|
+
error.value = null;
|
|
44
|
+
try {
|
|
45
|
+
cart.value = await $fetch(`${apiBase}/cart/${cartId.value}`);
|
|
46
|
+
} catch (err) {
|
|
47
|
+
handleError(err);
|
|
48
|
+
} finally {
|
|
49
|
+
loading.value = false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async function addItem(item) {
|
|
53
|
+
if (!cartId.value) {
|
|
54
|
+
throw new Error("[@commercejs/nuxt] No cart ID. Ensure the cart is initialized.");
|
|
55
|
+
}
|
|
56
|
+
loading.value = true;
|
|
57
|
+
error.value = null;
|
|
58
|
+
try {
|
|
59
|
+
cart.value = await $fetch(`${apiBase}/cart/${cartId.value}/items`, {
|
|
60
|
+
method: "POST",
|
|
61
|
+
body: item
|
|
62
|
+
});
|
|
63
|
+
itemAddedHook.trigger(cart.value);
|
|
64
|
+
} catch (err) {
|
|
65
|
+
throw handleError(err);
|
|
66
|
+
} finally {
|
|
67
|
+
loading.value = false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
async function updateItem(itemId, quantity) {
|
|
71
|
+
if (!cartId.value) return;
|
|
72
|
+
loading.value = true;
|
|
73
|
+
error.value = null;
|
|
74
|
+
try {
|
|
75
|
+
cart.value = await $fetch(`${apiBase}/cart/${cartId.value}/items/${itemId}`, {
|
|
76
|
+
method: "PUT",
|
|
77
|
+
body: { quantity }
|
|
78
|
+
});
|
|
79
|
+
itemUpdatedHook.trigger(cart.value);
|
|
80
|
+
} catch (err) {
|
|
81
|
+
throw handleError(err);
|
|
82
|
+
} finally {
|
|
83
|
+
loading.value = false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async function removeItem(itemId) {
|
|
87
|
+
if (!cartId.value) return;
|
|
88
|
+
loading.value = true;
|
|
89
|
+
error.value = null;
|
|
90
|
+
try {
|
|
91
|
+
cart.value = await $fetch(`${apiBase}/cart/${cartId.value}/items/${itemId}`, {
|
|
92
|
+
method: "DELETE"
|
|
93
|
+
});
|
|
94
|
+
itemRemovedHook.trigger(cart.value);
|
|
95
|
+
} catch (err) {
|
|
96
|
+
throw handleError(err);
|
|
97
|
+
} finally {
|
|
98
|
+
loading.value = false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
async function applyCoupon(code) {
|
|
102
|
+
if (!cartId.value) return;
|
|
103
|
+
loading.value = true;
|
|
104
|
+
error.value = null;
|
|
105
|
+
try {
|
|
106
|
+
cart.value = await $fetch(`${apiBase}/promotions/validate`, {
|
|
107
|
+
method: "POST",
|
|
108
|
+
body: { cartId: cartId.value, code }
|
|
109
|
+
});
|
|
110
|
+
} catch (err) {
|
|
111
|
+
throw handleError(err);
|
|
112
|
+
} finally {
|
|
113
|
+
loading.value = false;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
async function removeCoupon() {
|
|
117
|
+
await refresh();
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
/** Reactive cart state (readonly to enforce mutations through methods) */
|
|
121
|
+
cart: readonly(cart),
|
|
122
|
+
/** Cart ID stored in cookie */
|
|
123
|
+
cartId,
|
|
124
|
+
/** Whether a cart operation is in progress */
|
|
125
|
+
loading: readonly(loading),
|
|
126
|
+
/** Last error from a cart operation */
|
|
127
|
+
error: readonly(error),
|
|
128
|
+
/** Number of items in the cart */
|
|
129
|
+
itemCount: computed(() => cart.value?.itemCount ?? 0),
|
|
130
|
+
// Event hooks — subscribe: onItemAdded((cart) => { ... })
|
|
131
|
+
onItemAdded: itemAddedHook.on,
|
|
132
|
+
onItemUpdated: itemUpdatedHook.on,
|
|
133
|
+
onItemRemoved: itemRemovedHook.on,
|
|
134
|
+
onError: errorHook.on,
|
|
135
|
+
// Methods
|
|
136
|
+
createCart,
|
|
137
|
+
refresh,
|
|
138
|
+
addItem,
|
|
139
|
+
updateItem,
|
|
140
|
+
removeItem,
|
|
141
|
+
applyCoupon,
|
|
142
|
+
removeCoupon
|
|
143
|
+
};
|
|
144
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { useFetch, useRuntimeConfig } from "#imports";
|
|
2
|
+
export function useCategories() {
|
|
3
|
+
const config = useRuntimeConfig();
|
|
4
|
+
const apiBase = config.public.commerce?.apiBase || "/api/_commerce";
|
|
5
|
+
return useFetch(
|
|
6
|
+
`${apiBase}/categories`,
|
|
7
|
+
{ key: "categories" }
|
|
8
|
+
);
|
|
9
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { useState, readonly } from "#imports";
|
|
2
|
+
import { CommerceError, isCommerceError } from "@commercejs/types";
|
|
3
|
+
import { createEventHook } from "@vueuse/core";
|
|
4
|
+
import { useAdapter } from "./useAdapter.js";
|
|
5
|
+
import { useCart } from "./useCart.js";
|
|
6
|
+
export function useCheckout() {
|
|
7
|
+
const adapter = useAdapter();
|
|
8
|
+
const { cart, cartId } = useCart();
|
|
9
|
+
const shippingMethods = useState("commerce_shipping_methods", () => []);
|
|
10
|
+
const paymentMethods = useState("commerce_payment_methods", () => []);
|
|
11
|
+
const loading = useState("commerce_checkout_loading", () => false);
|
|
12
|
+
const error = useState("commerce_checkout_error", () => null);
|
|
13
|
+
const orderPlacedHook = createEventHook();
|
|
14
|
+
const errorHook = createEventHook();
|
|
15
|
+
function handleError(err) {
|
|
16
|
+
const e = isCommerceError(err) ? err : new CommerceError(
|
|
17
|
+
err instanceof Error ? err.message : String(err),
|
|
18
|
+
"UNKNOWN",
|
|
19
|
+
void 0,
|
|
20
|
+
err
|
|
21
|
+
);
|
|
22
|
+
error.value = e;
|
|
23
|
+
errorHook.trigger(e);
|
|
24
|
+
return e;
|
|
25
|
+
}
|
|
26
|
+
function requireCartId() {
|
|
27
|
+
if (!cartId.value) {
|
|
28
|
+
throw new Error("[@commercejs/nuxt] No cart ID found. Add items to cart first.");
|
|
29
|
+
}
|
|
30
|
+
return cartId.value;
|
|
31
|
+
}
|
|
32
|
+
async function loadShippingMethods() {
|
|
33
|
+
const id = requireCartId();
|
|
34
|
+
loading.value = true;
|
|
35
|
+
error.value = null;
|
|
36
|
+
try {
|
|
37
|
+
shippingMethods.value = await adapter.getShippingMethods(id);
|
|
38
|
+
} catch (err) {
|
|
39
|
+
throw handleError(err);
|
|
40
|
+
} finally {
|
|
41
|
+
loading.value = false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async function loadPaymentMethods() {
|
|
45
|
+
const id = requireCartId();
|
|
46
|
+
loading.value = true;
|
|
47
|
+
error.value = null;
|
|
48
|
+
try {
|
|
49
|
+
paymentMethods.value = await adapter.getPaymentMethods(id);
|
|
50
|
+
} catch (err) {
|
|
51
|
+
throw handleError(err);
|
|
52
|
+
} finally {
|
|
53
|
+
loading.value = false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async function setShippingAddress(address) {
|
|
57
|
+
const id = requireCartId();
|
|
58
|
+
loading.value = true;
|
|
59
|
+
error.value = null;
|
|
60
|
+
try {
|
|
61
|
+
const updatedCart = await adapter.setShippingAddress(id, address);
|
|
62
|
+
useState("commerce_cart").value = updatedCart;
|
|
63
|
+
} catch (err) {
|
|
64
|
+
throw handleError(err);
|
|
65
|
+
} finally {
|
|
66
|
+
loading.value = false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async function setBillingAddress(address) {
|
|
70
|
+
const id = requireCartId();
|
|
71
|
+
loading.value = true;
|
|
72
|
+
error.value = null;
|
|
73
|
+
try {
|
|
74
|
+
const updatedCart = await adapter.setBillingAddress(id, address);
|
|
75
|
+
useState("commerce_cart").value = updatedCart;
|
|
76
|
+
} catch (err) {
|
|
77
|
+
throw handleError(err);
|
|
78
|
+
} finally {
|
|
79
|
+
loading.value = false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
async function setShippingMethod(methodId) {
|
|
83
|
+
const id = requireCartId();
|
|
84
|
+
loading.value = true;
|
|
85
|
+
error.value = null;
|
|
86
|
+
try {
|
|
87
|
+
const updatedCart = await adapter.setShippingMethod(id, methodId);
|
|
88
|
+
useState("commerce_cart").value = updatedCart;
|
|
89
|
+
} catch (err) {
|
|
90
|
+
throw handleError(err);
|
|
91
|
+
} finally {
|
|
92
|
+
loading.value = false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async function setPaymentMethod(methodId) {
|
|
96
|
+
const id = requireCartId();
|
|
97
|
+
loading.value = true;
|
|
98
|
+
error.value = null;
|
|
99
|
+
try {
|
|
100
|
+
const updatedCart = await adapter.setPaymentMethod(id, methodId);
|
|
101
|
+
useState("commerce_cart").value = updatedCart;
|
|
102
|
+
} catch (err) {
|
|
103
|
+
throw handleError(err);
|
|
104
|
+
} finally {
|
|
105
|
+
loading.value = false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
async function placeOrder() {
|
|
109
|
+
const id = requireCartId();
|
|
110
|
+
loading.value = true;
|
|
111
|
+
error.value = null;
|
|
112
|
+
try {
|
|
113
|
+
const order = await adapter.placeOrder(id);
|
|
114
|
+
useState("commerce_cart").value = null;
|
|
115
|
+
cartId.value = "";
|
|
116
|
+
orderPlacedHook.trigger(order);
|
|
117
|
+
return order;
|
|
118
|
+
} catch (err) {
|
|
119
|
+
throw handleError(err);
|
|
120
|
+
} finally {
|
|
121
|
+
loading.value = false;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
cart,
|
|
126
|
+
shippingMethods: readonly(shippingMethods),
|
|
127
|
+
paymentMethods: readonly(paymentMethods),
|
|
128
|
+
loading: readonly(loading),
|
|
129
|
+
error: readonly(error),
|
|
130
|
+
// Event hooks
|
|
131
|
+
onOrderPlaced: orderPlacedHook.on,
|
|
132
|
+
onError: errorHook.on,
|
|
133
|
+
// Methods
|
|
134
|
+
loadShippingMethods,
|
|
135
|
+
loadPaymentMethods,
|
|
136
|
+
setShippingAddress,
|
|
137
|
+
setBillingAddress,
|
|
138
|
+
setShippingMethod,
|
|
139
|
+
setPaymentMethod,
|
|
140
|
+
placeOrder
|
|
141
|
+
};
|
|
142
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { useState, readonly } from "#imports";
|
|
2
|
+
import { CommerceError, isCommerceError } from "@commercejs/types";
|
|
3
|
+
import { useAdapter } from "./useAdapter.js";
|
|
4
|
+
export function useCountries() {
|
|
5
|
+
const adapter = useAdapter();
|
|
6
|
+
const countries = useState("commerce:countries", () => []);
|
|
7
|
+
const loading = useState("commerce:countries:loading", () => false);
|
|
8
|
+
const error = useState("commerce:countries:error", () => null);
|
|
9
|
+
async function refresh() {
|
|
10
|
+
loading.value = true;
|
|
11
|
+
error.value = null;
|
|
12
|
+
try {
|
|
13
|
+
countries.value = await adapter.getCountries();
|
|
14
|
+
} catch (err) {
|
|
15
|
+
const e = isCommerceError(err) ? err : new CommerceError(
|
|
16
|
+
err instanceof Error ? err.message : String(err),
|
|
17
|
+
"UNKNOWN",
|
|
18
|
+
void 0,
|
|
19
|
+
err
|
|
20
|
+
);
|
|
21
|
+
error.value = e;
|
|
22
|
+
} finally {
|
|
23
|
+
loading.value = false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
countries: readonly(countries),
|
|
28
|
+
loading: readonly(loading),
|
|
29
|
+
error: readonly(error),
|
|
30
|
+
refresh
|
|
31
|
+
};
|
|
32
|
+
}
|
|
File without changes
|