Skip to content

Commit

Permalink
feat(nuxt3-module): deps improvements and documentation (#200)
Browse files Browse the repository at this point in the history
* feat(nuxt3-module): internal dependency resolving and README

* chore: changeset

* fix: allow to override frontends dependency in local project

* docs: deps customization
  • Loading branch information
mkucmus committed May 12, 2023
1 parent d5e5964 commit 329b0ae
Show file tree
Hide file tree
Showing 12 changed files with 266 additions and 102 deletions.
6 changes: 6 additions & 0 deletions .changeset/lovely-drinks-love.md
@@ -0,0 +1,6 @@
---
"vue-demo-store": patch
"vue-blank": patch
---

Remove unnecessary dependencies
5 changes: 5 additions & 0 deletions .changeset/shy-bobcats-drive.md
@@ -0,0 +1,5 @@
---
"@shopware-pwa/nuxt3-module": patch
---

Internal dependency resolving
89 changes: 89 additions & 0 deletions packages/nuxt3-module/README.md
@@ -0,0 +1,89 @@
# shopware/frontends - nuxt3-module

[![](https://img.shields.io/npm/v/@shopware-pwa/nuxt3-module?color=blue&logo=data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTIiIGhlaWdodD0iMTIiIHZpZXdCb3g9IjAgMCA0ODggNTUzIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBkPSJNNDM5LjA0MSAxMjkuNTkzTDI1OC43NjkgMzEuMzA3NkMyNDQuOTE1IDIzLjc1NDEgMjI4LjExNiAyNC4wMDkzIDIxNC40OTcgMzEuOTgwMkw0Ny4yNjkgMTI5Ljg1OEMzMy40NzYzIDEzNy45MzEgMjUgMTUyLjcxMyAyNSAxNjguNjk1VjM4OC40NjZDMjUgNDA0LjczMiAzMy43Nzg1IDQxOS43MzIgNDcuOTYwMiA0MjcuNjk5TDIxNS4xNzggNTIxLjYzNkMyMjguNDUxIDUyOS4wOTIgMjQ0LjU5MyA1MjkuMzMyIDI1OC4wODIgNTIyLjI3NEw0MzguMzY0IDQyNy45MzRDNDUzLjIwMSA0MjAuMTcgNDYyLjUgNDA0LjgwOSA0NjIuNSAzODguMDYzVjE2OS4xMDJDNDYyLjUgMTUyLjYzMiA0NTMuNTAyIDEzNy40NzcgNDM5LjA0MSAxMjkuNTkzWiIgc3Ryb2tlPSJ1cmwoI3BhaW50MF9saW5lYXJfMTUzXzY5MjY1KSIgc3Ryb2tlLXdpZHRoPSI1MCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgo8ZGVmcz4KPGxpbmVhckdyYWRpZW50IGlkPSJwYWludDBfbGluZWFyXzE1M182OTI2NSIgeDE9Ii0xNi4yOTg5IiB5MT0iMTY1LjM0OSIgeDI9IjI3Ni40MTIiIHkyPSItODkuMzIzNCIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPgo8c3RvcCBzdG9wLWNvbG9yPSIjMDA4NUZGIi8+CjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI0MwRTJGNSIvPgo8L2xpbmVhckdyYWRpZW50Pgo8L2RlZnM+Cjwvc3ZnPg==)](https://npmjs.com/package/@shopware-pwa/nuxt3-module)
[![](https://img.shields.io/github/package-json/v/shopware/frontends?color=blue&filename=packages%2Fnuxt3-module%2Fpackage.json&label=nuxt3-module%40monorepo&logo=github)](https://github.com/shopware/frontends/tree/main/packages/nuxt3-module)
![](https://img.shields.io/github/license/shopware/frontends?color=blue)
[![](https://img.shields.io/github/issues/shopware/frontends/nuxt3-module?label=nuxt3-module%20issues&logo=github)](https://github.com/shopware/frontends/issues?q=is%3Aopen+is%3Aissue+label%3Anuxt3-module)

Nuxt [module](https://nuxt.com/docs/guide/going-further/modules) that allows you to set up a Nuxt 3 project with Shopware Frontends. It provides the composables and api-client packages.

If you want to use these packages with a different Vue.js framework, see [the guide](https://frontends.shopware.com/getting-started/templates/custom-project.html) for using Shopware Frontends in a custom project or use the [vue3-plugin](https://frontends.shopware.com/framework/internal-structure.html#vue3-plugin).

## Features

- Business logic covered by [Composables](https://npmjs.com/package/@shopware-pwa/composables-next) package. Registering all composable functions globally. [See the reference](https://frontends.shopware.com/packages/composables.html).
- Shopware context shared in Nuxt application.
- Configured [API Client](https://npmjs.com/package/@shopware-pwa/api-client) package.

## Setup

Install npm package:

```bash
# Using pnpm
pnpm add -D @shopware-pwa/nuxt3-module

# Using yarn
yarn add --dev @shopware-pwa/nuxt3-module

# Using npm
npm i @shopware-pwa/nuxt3-module --save-dev
```

Then, register the module by editing `nuxt.config.js` or (`.ts`) file (by extending `modules` array):

```js
/* nuxt.config.ts */

export default defineNuxtConfig({
/* ... */
modules: [, /* ... */ "@shopware-pwa/nuxt3-module"],

runtimeConfig: {
public: {
shopware: {
// connect to your Shopware 6 API instance
shopwareEndpoint: "https://demo-frontends.shopware.store",
shopwareAccessToken: "SWSCBHFSNTVMAWNZDNFKSHLAYW",
},
},
},
});
```

Set up your own API instance by adding public `runtimeConfiguration` in the same file. The nuxt module (and vue plugin) will use this values.

## Basic usage

Now you can use any composable function you need without extra import:

```html
<script setup>
const { login } = useUser();
const { refreshSessionContext } = useSessionContext();
refreshSessionContext();
</script>
```

The information about the session is kept in a cookie (`sw-context-token`) and used in every request made by any composable or directly, invoked by `api instance`:

```html
<script>
const { apiInstance } = useShopwareContext();
const rawApiResponse = await apiInstance.invokePost(/** params omitted */);
</script>
```

## TypeScript support

All composable functions are fully typed with TypeScript and they are registed globally in Nuxt.js application, so the type hinting will help you to work with all of them.

## 📦 Advanced packaging

Internally, the module uses [API Client](https://npmjs.com/package/@shopware-pwa/api-client) and [Composables](https://npmjs.com/package/@shopware-pwa/composables-next) packages, configured together to make everything working well. If you need to check how it's working on a different version of one of them, install a package locally in your project (to be installed and available in project's `package.json` file), then the Nuxt module will use yours. Keep in mind that the different configuration may lead to unexpected behavior.

## Links

- [📘 Documentation](https://frontends.shopware.com)

- [👥 Community](https://shopwarecommunity.slack.com) (`#shopware-frontends` & `#shopware-pwa` channel)
7 changes: 6 additions & 1 deletion packages/nuxt3-module/build.config.ts
Expand Up @@ -7,5 +7,10 @@ export default defineBuildConfig({
cjsBridge: true,
},
declaration: true,
externals: ["@nuxt/schema", "@nuxt/kit", "@shopware-pwa/composables-next"],
externals: [
"@nuxt/schema",
"@nuxt/kit",
"@shopware-pwa/composables-next",
"package-json-parser",
],
});
1 change: 1 addition & 0 deletions packages/nuxt3-module/package.json
Expand Up @@ -48,6 +48,7 @@
"@nuxt/devtools": "^0.4.5",
"@nuxt/schema": "^3.4.3",
"eslint-config-shopware": "workspace:*",
"package-json-parser": "^2.2.0",
"tsconfig": "workspace:*",
"typescript": "^5.0.4",
"unbuild": "^1.2.1"
Expand Down
14 changes: 3 additions & 11 deletions packages/nuxt3-module/plugin.ts
Expand Up @@ -29,8 +29,8 @@ const ShopwarePlugin = {
const cookieLanguageId = Cookies.get("sw-language-id");

if (
!runtimeConfig.public.shopware.shopwareEndpoint ||
!runtimeConfig.public.shopware.shopwareAccessToken
!runtimeConfig.public?.shopware?.shopwareEndpoint ||
!runtimeConfig.public?.shopware?.shopwareAccessToken
) {
throw new Error(
"Make sure that shopwareEndpoint and shopwareAccessToken are settled in the configuration"
Expand Down Expand Up @@ -85,15 +85,7 @@ const ShopwarePlugin = {
};

export default defineNuxtPlugin(async (nuxtApp) => {
const newConfig = getDefaultApiParams();
// newConfig.add("useOrderDetails.associations",{
// "lineItems": {
// "associations": {
// "cover": {}
// }
// }
// });
nuxtApp.vueApp.use(ShopwarePlugin, {
apiDefaults: newConfig,
apiDefaults: getDefaultApiParams(),
});
});
67 changes: 47 additions & 20 deletions packages/nuxt3-module/src/index.ts
Expand Up @@ -3,30 +3,14 @@
*/
import { defineNuxtModule, addPluginTemplate } from "@nuxt/kit";
import { resolve } from "path";

export type ShopwareNuxtOptions = {
/**
* Endpoint for your shopware backend.
*
* Default demo store: "https://demo-frontends.swstage.store/"
*/
shopwareEndpoint?: string;
shopwareAccessToken?: string;
apiClientConfig?: {
timeout?: number | string;
// auth?: {
// username: string;
// password: string;
// };
};
};
import { isDependencyInstalledLocally, resolveOwnDependency } from "./utils";

export default defineNuxtModule<ShopwareNuxtOptions>({
meta: {
name: "@shopware/nuxt3",
configKey: "shopware",
},
setup(moduleConfig, nuxt) {
async setup(moduleConfig, nuxt) {
addPluginTemplate({
filename: "runtime/shopware.plugin.mjs",
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
Expand All @@ -43,9 +27,37 @@ export default defineNuxtModule<ShopwareNuxtOptions>({
},
},
});

// TODO: remove it once nitro server build contains all external packages of nuxt3-module (composables-next)
nuxt.options.build.transpile.push("@shopware-pwa/composables-next");

// use a module's dependency in order to not install it again within an end-project to keep compatibility
const apiClientDependencyPath = await resolveOwnDependency(
"@shopware-pwa/api-client",
nuxt
);
const isApiClientInstalledLocally = await isDependencyInstalledLocally(
nuxt.options.rootDir,
"@shopware-pwa/api-client"
);
if (!isApiClientInstalledLocally && apiClientDependencyPath) {
nuxt.options.alias["@shopware-pwa/api-client"] = apiClientDependencyPath;
}

const isComposablesNextInstalledLocally =
await isDependencyInstalledLocally(
nuxt.options.rootDir,
"@shopware-pwa/composables-next"
);
const composablesDependencyPath = await resolveOwnDependency(
"@shopware-pwa/composables-next",
nuxt
);
if (!isComposablesNextInstalledLocally && composablesDependencyPath) {
nuxt.options.alias["@shopware-pwa/composables-next"] =
composablesDependencyPath;
}

nuxt.hook("imports:sources", (dirs) => {
dirs.push({
from: "@shopware-pwa/composables-next",
Expand Down Expand Up @@ -105,16 +117,31 @@ export default defineNuxtModule<ShopwareNuxtOptions>({
},
});
});

// nuxt.hook('')
},
});

export type ShopwareNuxtOptions = {
/**
* Endpoint for your shopware backend.
*
* Default demo store: "https://demo-frontends.swstage.store/"
*/
shopwareEndpoint?: string;
shopwareAccessToken?: string;
apiClientConfig?: {
timeout?: number | string;
};
};

declare module "@nuxt/schema" {
interface NuxtConfig {
shopware?: ShopwareNuxtOptions;
}
interface NuxtOptions {
shopware?: ShopwareNuxtOptions;
}

interface PublicRuntimeConfig {
shopware: ShopwareNuxtOptions;
}
}
56 changes: 56 additions & 0 deletions packages/nuxt3-module/src/utils.ts
@@ -0,0 +1,56 @@
import { Nuxt } from "@nuxt/schema";
import { resolve, dirname } from "path";
import { fileURLToPath } from "node:url";
import { promises as fs, constants as FS_CONSTANTS } from "node:fs";
import packageJson from "package-json-parser";

type DEPENDENCY = "@shopware-pwa/api-client" | "@shopware-pwa/composables-next";

const distDir = dirname(fileURLToPath(import.meta.url));
const pkgDir = resolve(distDir, "..");
const pkgModulesDir = resolve(pkgDir, "./node_modules");

export async function isDependencyInstalledLocally(
rootDir: string,
dependency: DEPENDENCY
) {
try {
const projectPackageJsonPath = resolve(rootDir, "package.json");
const packageJsonDefinition = packageJson.json(projectPackageJsonPath);
if (
packageJsonDefinition?.dependencies?.[dependency] ||
packageJsonDefinition?.devDependencies?.[dependency]
) {
return true;
}
} catch (error) {
console.error("nuxt3-module: unable to check local dependencies");
}
return false;
}

export async function isExists(path: string) {
try {
await fs.access(path, FS_CONSTANTS.F_OK);
return true;
} catch (e) {
return false;
}
}

export async function resolveOwnDependency(dependency: DEPENDENCY, nuxt: Nuxt) {
const { rootDir, workspaceDir } = nuxt.options;
const modulePath = `${dependency}/dist/index.mjs`;

const targets = [
resolve(rootDir, "node_modules", modulePath),
resolve(pkgModulesDir, modulePath),
resolve(workspaceDir, "node_modules", modulePath),
];

for (const target of targets) {
if (await isExists(target)) {
return target;
}
}
}
8 changes: 7 additions & 1 deletion packages/nuxt3-module/tsconfig.json
@@ -1,5 +1,11 @@
{
"extends": "tsconfig/base.json",
"include": ["."],
"exclude": ["dist"]
"exclude": [
"dist"
],
"compilerOptions": {
"target": "esnext",
"module": "esnext"
}
}

2 comments on commit 329b0ae

@vercel
Copy link

@vercel vercel bot commented on 329b0ae May 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

frontends-demo – ./templates/vue-demo-store

frontends-demo-git-main-shopware-frontends.vercel.app
frontends-demo.vercel.app
frontends-demo-shopware-frontends.vercel.app

@vercel
Copy link

@vercel vercel bot commented on 329b0ae May 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.