Initial Commit
commit
48d1d02925
@ -0,0 +1,24 @@
|
||||
# Dependency directories
|
||||
node_modules
|
||||
|
||||
# Logs
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# Rollup generate output
|
||||
lib
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
playground/app/*
|
||||
|
||||
.DS_Store
|
||||
@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npx commitlint --edit
|
||||
@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npx lerna run precommit
|
||||
@ -0,0 +1,8 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"arrowParens": "always",
|
||||
"tabWidth": 2,
|
||||
"bracketSpacing": true
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
FROM node:16-alpine AS build
|
||||
|
||||
WORKDIR /var/www
|
||||
|
||||
RUN apk add --no-cache \
|
||||
yarn
|
||||
|
||||
COPY . .
|
||||
|
||||
# Run dependencies needed to build API Reference
|
||||
RUN yarn install
|
||||
|
||||
# Build docs
|
||||
RUN cd docs \
|
||||
&& yarn install \
|
||||
&& sed -i "s/base: '\/',/base: '\/integration-boilerplate\/',/g" ./.vuepress/config.js \
|
||||
&& cat ./.vuepress/config.js \
|
||||
&& yarn api-extract \
|
||||
&& yarn build
|
||||
|
||||
FROM nginx
|
||||
|
||||
COPY --from=build /var/www/docs/.vuepress/dist /usr/share/nginx/html/integration-boilerplate
|
||||
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Vue Storefront
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@ -0,0 +1,92 @@
|
||||
# SDK Based Integration Boilerplate for VSF 2
|
||||
|
||||
## Creating a new integration?
|
||||
The fastest way to get started is to use our CLI to generate a new integration boilerplate
|
||||
|
||||
```bash
|
||||
npx @vue-storefront/cli create integration
|
||||
```
|
||||
|
||||
The CLI will ask you a few questions and generate a new integration boilerplate based on your answers.
|
||||
|
||||
For more information about creating a custom integration using the VSF SDK, please visit the [SDK documentation](https://docs.vuestorefront.io/sdk/custom-integrations/quick-start.html).
|
||||
|
||||
From the project root, you can run the one of following commands, depending on your package manager:
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
or
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
This will do the following:
|
||||
- start the development server for the `playground/app` application.
|
||||
- start the middleware server for the `playground/middleware` application.
|
||||
|
||||
## Adding an endpoint
|
||||
|
||||
```bash
|
||||
npx @vue-storefront/cli add endpoint getSomething
|
||||
```
|
||||
|
||||
This will do the following:
|
||||
- add a new endpoint to the `api-client` package
|
||||
- add a new method to the `sdk` package
|
||||
- add a new route to the `playground/middleware` application
|
||||
- add a new route to the `playground/app` application
|
||||
|
||||
|
||||
### Using vs Contributing
|
||||
Using the CLI is the recommended way to create a new integration boilerplate.
|
||||
However, if you're planning to contribute, you can follow the steps below.
|
||||
___
|
||||
## Would you like to contribute?
|
||||
|
||||
This is an open-source project. Feel free to contribute by creating a new issue or submitting a pull request.
|
||||
We highly recommend opening an issue and getting feedback *before* submitting a pull request, to avoid unnecessary work.
|
||||
|
||||
If we feel your contribution would benefit the community, and it adheres to our standards,
|
||||
we would be delighted to accept your pull requests.
|
||||
|
||||
> **For internal use only.**
|
||||
> All changes are recorded in the [CHANGELOG.md](CHANGELOG.md) file.
|
||||
|
||||
This is a new integration boilerplate for VSF 2 integrations based on the SDK.
|
||||
|
||||
## Requirements:
|
||||
|
||||
- NodeJS v16 or later,
|
||||
- [Yarn](https://yarnpkg.com/).
|
||||
|
||||
## Repository structure
|
||||
|
||||
This repository contains a few necessary packages to help you get started building your new integration:
|
||||
|
||||
- `playground/app` - (created during CLI initialization) Demonstrates the usage of `api-client` by creating an express server app. You can use this directory to demonstrate the usage of the integration.
|
||||
- `playground/middleware` - An express app that uses the `api-client` to create a server-to-server connection with service providers (e.g. commerce backend).
|
||||
- `packages/api-client` - The service the middleware uses. It contains an `exampleEndpoint` that can be used as an example for the other API endpoints,
|
||||
- `packages/sdk`- Think of the SDK Connector as a communication layer between the storefront and the middleware. It contains an `exampleMethod` with example documentation, unit & integration tests, that can be used as an example for the rest SDK connector methods.
|
||||
- `docs` - VuePress documentation with configured API extractor, to create an API Reference based on the `api-client` and `sdk` methods & interfaces.
|
||||
|
||||
## Getting started
|
||||
|
||||
```bash
|
||||
yarn
|
||||
```
|
||||
|
||||
5. Build the packages,
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
6. Test the packages,
|
||||
|
||||
```bash
|
||||
yarn test
|
||||
```
|
||||
|
||||
7. That's it. Now you can start the developing your contribution,
|
||||
8. Enjoy.
|
||||
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Config file for API Extractor. For more info, please visit: https://api-extractor.com
|
||||
*/
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
|
||||
"projectFolder": ".",
|
||||
"compiler": {
|
||||
"tsconfigFilePath": "<projectFolder>/tsconfig.base.json"
|
||||
},
|
||||
"docModel": {
|
||||
"enabled": true
|
||||
},
|
||||
"dtsRollup": {
|
||||
"enabled": true
|
||||
},
|
||||
"tsdocMetadata": {
|
||||
"enabled": false
|
||||
},
|
||||
"apiReport": {
|
||||
"enabled": false
|
||||
},
|
||||
"messages": {
|
||||
"compilerMessageReporting": {
|
||||
"default": {
|
||||
"logLevel": "warning"
|
||||
}
|
||||
},
|
||||
"extractorMessageReporting": {
|
||||
"default": {
|
||||
"logLevel": "none",
|
||||
"addToApiReportFile": false
|
||||
},
|
||||
"ae-extra-release-tag": {
|
||||
"logLevel": "none",
|
||||
"addToApiReportFile": false
|
||||
},
|
||||
"ae-forgotten-export": {
|
||||
"logLevel": "none"
|
||||
}
|
||||
},
|
||||
"tsdocMessageReporting": {
|
||||
"default": {
|
||||
"logLevel": "none",
|
||||
"addToApiReportFile": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
.vuepress/dist
|
||||
.vuepress/public/commercetools
|
||||
api.json
|
||||
reference
|
||||
@ -0,0 +1,40 @@
|
||||
module.exports = {
|
||||
title: 'Integration Boilerplate',
|
||||
base: '/integration-boilerplate/',
|
||||
description: 'Documentation for the new Integration boilerplate',
|
||||
head: [['link', { rel: 'icon', href: '/favicon.png' }]],
|
||||
theme: 'vsf-docs',
|
||||
configureWebpack: (config) => {
|
||||
config.module.rules = config.module.rules.map((rule) => ({
|
||||
...rule,
|
||||
use:
|
||||
rule.use &&
|
||||
rule.use.map((useRule) => ({
|
||||
...useRule,
|
||||
options:
|
||||
useRule.loader === 'url-loader'
|
||||
? /**
|
||||
Hack for loading images properly.
|
||||
ref: https://github.com/vuejs/vue-loader/issues/1612#issuecomment-559366730
|
||||
*/
|
||||
{ ...useRule.options, esModule: false }
|
||||
: useRule.options
|
||||
}))
|
||||
}));
|
||||
},
|
||||
themeConfig: {
|
||||
nav: [
|
||||
{ text: 'Vue Storefront', link: 'https://vuestorefront.io/' },
|
||||
{ text: 'Core Documentation', link: 'https://docs.vuestorefront.io/v2/' }
|
||||
],
|
||||
sidebar: {
|
||||
'/': [
|
||||
{
|
||||
title: 'Reference',
|
||||
collapsable: false,
|
||||
children: [['/reference/api/', 'API Reference']]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,6 @@
|
||||
export default ({
|
||||
Vue, // the version of Vue being used in the VuePress app
|
||||
options, // the options for the root Vue instance
|
||||
router, // the router instance for the app
|
||||
siteData // site metadata
|
||||
}) => {}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 109 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
@ -0,0 +1,18 @@
|
||||
.badge {
|
||||
margin-top: 4px;
|
||||
background-color: #22c34b;
|
||||
}
|
||||
|
||||
.badge.info {
|
||||
background-color: #22c34b !important;
|
||||
}
|
||||
|
||||
.multiselect__tag {
|
||||
background: #22c34b !important;
|
||||
}
|
||||
|
||||
.custom-block.tip {
|
||||
border-color: #22c34b;
|
||||
background-color: #f0f7f2;
|
||||
}
|
||||
|
||||
@ -0,0 +1 @@
|
||||
$accentColor = #22c34b;
|
||||
@ -0,0 +1,10 @@
|
||||
---
|
||||
enterpriseTag: true
|
||||
hideToc: true
|
||||
---
|
||||
# Integrations boilerplate
|
||||
|
||||
This project is the new Integrations Boilerplate
|
||||
|
||||
<CoreDocsList />
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "@vue-storefront/integration-boilerplate-docs",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"description": "Documentation for the new Integration boilerplate",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"dev": "vuepress dev",
|
||||
"build": "NODE_OPTIONS=--max_old_space_size=8192 vuepress build",
|
||||
"api-extract": "cd ../ && yarn build && cd docs/ && yarn api-ref && yarn sdk-ref && yarn ref-md",
|
||||
"api-ref": "cd ../packages/api-client && api-extractor run --local",
|
||||
"sdk-ref": "cd ../packages/sdk && api-extractor run --local",
|
||||
"ref-md": "api-documenter markdown --i reference/api --o reference/api"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@microsoft/api-documenter": "^7.13.30",
|
||||
"@microsoft/api-extractor": "7.18.1",
|
||||
"concat-md": "^0.3.5",
|
||||
"handlebars": "^4.7.7",
|
||||
"typedoc": "^0.20.20",
|
||||
"typedoc-plugin-markdown": "^3.4.5",
|
||||
"typescript": "^3.6.4",
|
||||
"vuepress": "^1.8.2",
|
||||
"vuepress-plugin-mermaidjs": "^1.9.1"
|
||||
},
|
||||
"author": "VSF",
|
||||
"dependencies": {
|
||||
"sass-loader": "^8.0.2",
|
||||
"vue-multiselect": "^2.1.6",
|
||||
"vuepress-theme-vsf-docs": "^1.1.0-alpha.8"
|
||||
},
|
||||
"workspaces": {
|
||||
"nohoist": [
|
||||
"typedoc-plugin-markdown"
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
{
|
||||
"hideBreadcrumbs": true,
|
||||
"hideInPageTOC": true,
|
||||
"readme": "none",
|
||||
"plugin": ["typedoc-plugin-markdown"],
|
||||
"theme": "./typedoc-vsf-theme"
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,11 @@
|
||||
// For a detailed explanation regarding each configuration property, visit:
|
||||
// https://jestjs.io/docs/en/configuration.html
|
||||
|
||||
module.exports = {
|
||||
transform: {
|
||||
'^.+\\.(j|t)s$': 'ts-jest',
|
||||
},
|
||||
coverageDirectory: './coverage/',
|
||||
collectCoverageFrom: ['src/**/*.ts'],
|
||||
testMatch: ['<rootDir>/**/__tests__/**/*spec.[jt]s?(x)'],
|
||||
};
|
||||
@ -0,0 +1,15 @@
|
||||
{
|
||||
"useWorkspaces": true,
|
||||
"npmClient": "yarn",
|
||||
"command": {
|
||||
"publish": {
|
||||
"message": "chore(release): %s",
|
||||
"conventionalCommits": true
|
||||
}
|
||||
},
|
||||
"packages": [
|
||||
"packages/**/*",
|
||||
"playground/**/*"
|
||||
],
|
||||
"version": "1.0.0"
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
{
|
||||
"name": "@vue-storefront/integration-boilerplate",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "lerna run build",
|
||||
"dev": "concurrently --names \"Frontend,Middleware\" \"npm run dev:app\" \"npm run dev:middleware\"",
|
||||
"dev:app": "cd playground/app && npm run dev",
|
||||
"dev:middleware": "cd playground/middleware && npm run dev",
|
||||
"test": "lerna run test"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.10.5",
|
||||
"@loopmode/crosslink": "^0.4.0",
|
||||
"@rollup/plugin-babel": "^5.1.0",
|
||||
"@rollup/plugin-node-resolve": "^13.0.6",
|
||||
"@rollup/plugin-replace": "^2.3.3",
|
||||
"@types/jest": "^27.4.0",
|
||||
"@types/node": "^12.12.14",
|
||||
"@types/supertest": "~2.0.12",
|
||||
"concurrently": "^8.0.1",
|
||||
"cross-env": "^6.0.3",
|
||||
"jest": "^27.4.7",
|
||||
"lerna": "^6.5.1",
|
||||
"lint-staged": "^10.0.7",
|
||||
"msw": "^0.49.1",
|
||||
"nodemon": "^2.0.22",
|
||||
"rimraf": "^3.0.2",
|
||||
"rollup": "^2.59.0",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"rollup-plugin-typescript2": "^0.34.1",
|
||||
"supertest": "~6.2.4",
|
||||
"ts-jest": "^27.1.3",
|
||||
"ts-node": "^8.4.1",
|
||||
"tslib": "^2.1.0",
|
||||
"typescript": "^4.2.2",
|
||||
"webpack-bundle-analyzer": "^3.5.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.x"
|
||||
},
|
||||
"workspaces": [
|
||||
"packages/*",
|
||||
"playground/*"
|
||||
],
|
||||
"dependencies": {
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
},
|
||||
"overrides": {
|
||||
"react-json-view": {
|
||||
"react": "$react",
|
||||
"react-dom": "$react-dom"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
node_modules
|
||||
coverage
|
||||
lib
|
||||
server
|
||||
@ -0,0 +1 @@
|
||||
node_modules
|
||||
@ -0,0 +1,5 @@
|
||||
export const contextMock = {
|
||||
config: {} as any,
|
||||
client: jest.fn() as any,
|
||||
api: jest.fn() as any,
|
||||
};
|
||||
@ -0,0 +1,21 @@
|
||||
// import { exampleEndpoint } from '../../src/api';
|
||||
// import { contextMock } from '../../__mocks__/context.mock';
|
||||
// import consola from 'consola';
|
||||
|
||||
describe('[Integration Boilerplate API] exampleEndpoint', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('calls commerce endpoint with proper parameters', async () => {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
|
||||
it('validates paramerets', async () => {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
|
||||
it('throws an error when request fails', async () => {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "../../api-extractor.base.json",
|
||||
"mainEntryPointFilePath": "./lib/index.d.ts",
|
||||
"dtsRollup": {
|
||||
"untrimmedFilePath": "./lib/<unscopedPackageName>.d.ts"
|
||||
},
|
||||
"docModel": {
|
||||
"apiJsonFilePath": "<projectFolder>/docs/reference/api/<unscopedPackageName>.api.json"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
const baseConfig = require('./../../jest.base.config');
|
||||
|
||||
const apiClientJestConfig = { ...baseConfig };
|
||||
|
||||
apiClientJestConfig.collectCoverageFrom = [
|
||||
'src/**/*.ts',
|
||||
'!src/types/**',
|
||||
'!src/index.ts'
|
||||
];
|
||||
|
||||
module.exports = apiClientJestConfig;
|
||||
@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "@vue-storefront/integration-boilerplate-api",
|
||||
"version": "0.1.0",
|
||||
"sideEffects": false,
|
||||
"server": "server/index.js",
|
||||
"main": "lib/index.cjs.js",
|
||||
"module": "lib/index.es.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"license": "VSFEL",
|
||||
"engines": {
|
||||
"node": ">=16.x"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "rimraf lib server && rollup -c",
|
||||
"dev": "rollup -c -w",
|
||||
"test": "cross-env APP_ENV=test jest",
|
||||
"prepublish": "yarn build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vue-storefront/middleware": "3.0.0-rc.2",
|
||||
"axios": "^0.21.1",
|
||||
"consola": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jsdom": "^17.0.0"
|
||||
},
|
||||
"files": [
|
||||
"lib/**/*",
|
||||
"server/**/*"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
import nodeResolve from '@rollup/plugin-node-resolve';
|
||||
import typescript from 'rollup-plugin-typescript2';
|
||||
import pkg from './package.json';
|
||||
import { generateBaseConfig } from '../../rollup.base.config';
|
||||
|
||||
const extensions = ['.ts', '.js'];
|
||||
|
||||
const server = {
|
||||
input: 'src/index.server.ts',
|
||||
output: [
|
||||
{
|
||||
file: pkg.server,
|
||||
format: 'cjs',
|
||||
sourcemap: true
|
||||
}
|
||||
],
|
||||
external: [
|
||||
...Object.keys(pkg.dependencies || {}),
|
||||
...Object.keys(pkg.peerDependencies || {})
|
||||
],
|
||||
plugins: [
|
||||
nodeResolve({
|
||||
extensions
|
||||
}),
|
||||
typescript({
|
||||
// eslint-disable-next-line global-require
|
||||
typescript: require('typescript'),
|
||||
objectHashIgnoreUnknownHack: false
|
||||
})
|
||||
]
|
||||
};
|
||||
|
||||
export default [
|
||||
generateBaseConfig(pkg), // It's required for other packages using api-client's types
|
||||
server
|
||||
];
|
||||
@ -0,0 +1,12 @@
|
||||
import { Endpoints } from '../../types';
|
||||
|
||||
export const exampleEndpoint: Endpoints['exampleEndpoint'] = async (
|
||||
context,
|
||||
params
|
||||
) => {
|
||||
console.log('exampleEndpoint has been called');
|
||||
|
||||
// Example request could look like this:
|
||||
// return await context.client.get(`example-url?id=${params.id}`);
|
||||
return { data: 'Hello, Vue Storefront Integrator!' };
|
||||
};
|
||||
@ -0,0 +1,18 @@
|
||||
import { Endpoints } from '../../types';
|
||||
|
||||
export const getProducts: Endpoints['getProducts'] = async (
|
||||
context,
|
||||
params
|
||||
) => {
|
||||
console.log('getProducts has been called');
|
||||
|
||||
const { client } = context;
|
||||
try {
|
||||
const { data } = await client.get('/shop/products?page=1&itemsPerPage=10');
|
||||
return { data };
|
||||
}
|
||||
catch (error) {
|
||||
console.log('error', error);
|
||||
return { data: 'error' };
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,2 @@
|
||||
export { exampleEndpoint } from './exampleEndpoint';
|
||||
export { getProducts } from './getProducts';
|
||||
@ -0,0 +1,31 @@
|
||||
import axios from 'axios';
|
||||
import { apiClientFactory } from '@vue-storefront/middleware';
|
||||
import { MiddlewareConfig } from './index';
|
||||
import * as apiEndpoints from './api';
|
||||
|
||||
/**
|
||||
* In here you should create the client you'll use to communicate with the backend.
|
||||
* Axios is just an example.
|
||||
*/
|
||||
const buildClient = () => {
|
||||
const axiosInstance = axios.create({
|
||||
baseURL: 'http://localhost:8000/api/v2',
|
||||
});
|
||||
return axiosInstance
|
||||
}
|
||||
|
||||
const onCreate = (settings: MiddlewareConfig) => {
|
||||
const client = buildClient();
|
||||
|
||||
return {
|
||||
config: settings,
|
||||
client
|
||||
};
|
||||
};
|
||||
|
||||
const { createApiClient } = apiClientFactory<any, any>({
|
||||
onCreate,
|
||||
api: apiEndpoints,
|
||||
});
|
||||
|
||||
export { createApiClient };
|
||||
@ -0,0 +1,10 @@
|
||||
/**
|
||||
* `api-client` for Vue Storefront 2 integration bolierplate.
|
||||
*
|
||||
* @remarks
|
||||
* In here you can find all references to the integration API Client.
|
||||
*
|
||||
* @packageDocumentation
|
||||
*/
|
||||
|
||||
export * from './types';
|
||||
@ -0,0 +1,18 @@
|
||||
import { BoilerplateIntegrationContext, TODO } from '..'
|
||||
|
||||
/**
|
||||
* Definition of all API-client methods available in {@link https://docs.vuestorefront.io/v2/advanced/context.html#context-api | context}.
|
||||
*/
|
||||
export interface Endpoints {
|
||||
|
||||
/**
|
||||
* Here you can find an example endpoint definition. Based on this example, you should define how your endpoint will look like.
|
||||
* This description will appear in the API extractor, so try to document all endpoints added here.
|
||||
*/
|
||||
exampleEndpoint(
|
||||
context: BoilerplateIntegrationContext,
|
||||
params: TODO
|
||||
): Promise<TODO>;
|
||||
|
||||
getProducts(context: BoilerplateIntegrationContext, params: TODO): Promise<TODO>;
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
export * from './endpoints';
|
||||
@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Settings to be provided in the `middleware.config.js` file.
|
||||
*/
|
||||
export interface MiddlewareConfig {
|
||||
// Add the fields provided in the `middleware.config.js` file.
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
import { IntegrationContext } from '@vue-storefront/middleware';
|
||||
import { AxiosInstance } from 'axios';
|
||||
import { MiddlewareConfig, ContextualizedEndpoints } from '../index';
|
||||
|
||||
/**
|
||||
* Runtime integration context, which includes API client instance, settings, and endpoints that will be passed via middleware server.
|
||||
* This interface name is starting with `Boilerplate`, but you should use your integration name in here.
|
||||
**/
|
||||
export type BoilerplateIntegrationContext = IntegrationContext<
|
||||
AxiosInstance,
|
||||
MiddlewareConfig,
|
||||
ContextualizedEndpoints
|
||||
>;
|
||||
|
||||
/**
|
||||
* Global context of the application which includes runtime integration context.
|
||||
**/
|
||||
export interface Context {
|
||||
// This property is named `boilerplate`, but you should use your integration name in here.
|
||||
$boilerplate: BoilerplateIntegrationContext;
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
import { Endpoints } from './api';
|
||||
|
||||
/**
|
||||
* All available API Endpoints without first argument - `context`, because this prop is set automatically.
|
||||
*/
|
||||
export type ContextualizedEndpoints = {
|
||||
[T in keyof Endpoints]: Endpoints[T] extends (
|
||||
x: any,
|
||||
...args: infer P
|
||||
) => infer R
|
||||
? (...args: P) => R
|
||||
: never;
|
||||
};
|
||||
|
||||
export type TODO = any;
|
||||
|
||||
export * from './api';
|
||||
export * from './config';
|
||||
export * from './context';
|
||||
@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"include": ["src"],
|
||||
"exclude": ["__mocks__", "__tests__"]
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
integrations: {
|
||||
boilerplate: {
|
||||
location: '@vue-storefront/integration-boilerplate-api/server',
|
||||
configuration: {},
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -0,0 +1,26 @@
|
||||
const { createServer } = require("@vue-storefront/middleware");
|
||||
const { integrations } = require("./middleware.config");
|
||||
const cors = require("cors");
|
||||
|
||||
(async () => {
|
||||
const app = await createServer({ integrations });
|
||||
const host = process.argv[2] ?? "0.0.0.0";
|
||||
const port = process.argv[3] ?? 8181;
|
||||
const CORS_MIDDLEWARE_NAME = "corsMiddleware";
|
||||
|
||||
const corsMiddleware = app._router.stack.find(
|
||||
(middleware) => middleware.name === CORS_MIDDLEWARE_NAME
|
||||
);
|
||||
|
||||
corsMiddleware.handle = cors({
|
||||
origin: [
|
||||
"http://localhost:3000",
|
||||
...(process.env.MIDDLEWARE_ALLOWED_ORIGINS?.split(",") ?? []),
|
||||
],
|
||||
credentials: true,
|
||||
});
|
||||
|
||||
app.listen(port, host, () => {
|
||||
console.log(`Middleware started: ${host}:${port}`);
|
||||
});
|
||||
})();
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "@vue-storefront/integration-boilerplate-demo",
|
||||
"private": true,
|
||||
"version": "0.1.0",
|
||||
"engines": {
|
||||
"node": ">=16.x"
|
||||
},
|
||||
"scripts": {
|
||||
"middleware": "node middleware.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vue-storefront/middleware": "3.0.0-rc.2",
|
||||
"@vue-storefront/integration-boilerplate-api": "*",
|
||||
"cors": "^2.8.5"
|
||||
},
|
||||
"files": [
|
||||
"lib/**/*",
|
||||
"server/**/*"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
node_modules
|
||||
coverage
|
||||
lib
|
||||
server
|
||||
.env
|
||||
@ -0,0 +1 @@
|
||||
node_modules
|
||||
@ -0,0 +1,109 @@
|
||||
# Integration tests automated mocks setup
|
||||
|
||||
Integration tests in this repository leverage automated mocks created by [Nock](https://github.com/nock/nock). The data from SAP is requested once (during the first integration tests run) and saved in the __nock-fixtures__ directory. Subsequent test runs use these recorded responses and do not send any requests to SAP.
|
||||
|
||||
While setting up Nock, we had to solve a couple of issues to make it work seamlessly in our case.
|
||||
|
||||
## Running API Middleware with Storefront removed from the monorepo
|
||||
|
||||
When the Storefront was still in the integration's monorepo, we could simply import `middleware.js` and `middleware.config.js` files to run the API Middleware from within SDK's `jest.setup.global.js` file. After the Storefront had been removed, we had to re-adjust `jest.setup.global.js` so that it can spin up the API Middleware completely on its own.
|
||||
|
||||
As a result, it repeats the logic and config previously imported from `middleware.js` and `middleware.config.js` files. It also uses a dedicated `.env` file from the `./packages/sdk/__tests__/integration/__config__` directory. Bear in mind the file is not version-controlled and **has to be added manually to the repo before running the tests locally**. Otherwise, you're in for an error with the following message:
|
||||
|
||||
> Missing at least one environment variable. Make sure the .env file is present in `__tests__/integration/__config__`.
|
||||
|
||||
## Setting Nock up once before all tests instead of every test separately
|
||||
|
||||
The simplest way to set up Nock would be to do it in every single test case. However, this would add a lot of boilerplate to our integration test suites. Thus, we've taken some time to figure out how to set it up once, before all tests, and not worry about it anymore.
|
||||
|
||||
For that purpose, we've created the `jest.setup.js` file where we have:
|
||||
- set Nock [mode](https://www.npmjs.com/package/nock#modes) to `record`,
|
||||
- told Nock what directory it should save recorded responses (fixtures) in,
|
||||
- told Nock to create fixtures names from `expect.getState().currentTestName`.
|
||||
|
||||
## Giving test groups uniform names
|
||||
|
||||
To avoid boilerplate while describing a test group, we use the `describeGroup()` helper. Instead of describing it like this:
|
||||
|
||||
```ts
|
||||
describe('[SDK][Integration Tests] getProduct', () => {});
|
||||
```
|
||||
|
||||
we describe it like this:
|
||||
|
||||
```ts
|
||||
import { describeGroup } from './__config__/jest.setup';
|
||||
|
||||
describe(describeGroup('getProduct'), () => {});
|
||||
```
|
||||
|
||||
In both cases, the result is the same. However, using the helper makes our test suites cleaner, makes sure every test group has the same description and allows us to create **uniform Nock fixtures names**.
|
||||
|
||||
## Mocking only requests to SAP (and not to API Middleware)
|
||||
|
||||
Let's say we are running our integration tests for the first time. During every test, 2 **real** requests are sent:
|
||||
- From SDK to API Middleware,
|
||||
- From API Middleware to SAP OCC API.
|
||||
|
||||
As a result of that first test run, Nock records responses to both of these requests. In subsequent test runs - instead of sending a real request from SDK to API Middleware again, Nock simply returns the mocked response. It means that our API Middleware is not reached and does not make call #2 (to SAP OCC API).
|
||||
|
||||
We want to avoid this situation. We want our integration tests to always send the **real** request #1 and only use the mocked response to request #2. To achieve that, we had to do two things in the `nockSetup()` method:
|
||||
- Add `afterRecord` callback to `nock.back()` and manually remove the recorded response for request #1 there
|
||||
- Call `nock.enableNetConnect()` after `nock.back()`. Without it, request #1 was blocked by Nock in subsequent test runs with the NetConnectNotAllowedError.
|
||||
|
||||
## Solving errors while running tests in parallel
|
||||
|
||||
While recording, Nock does not handle very well tests running in parallel (in multiple child processes) instead of serially in a single process. Therefore, to record responses properly, we must run integration tests with the `--runInBand` flag.
|
||||
|
||||
This repository has a dedicated command for running integration tests to create (or re-create) Nock mocks:
|
||||
|
||||
`test:integration:init`
|
||||
|
||||
For subsequent test runs (where mocks are already present in the `__nock-fixtures__` directory), the basic command should be used:
|
||||
|
||||
`yarn test:integration`
|
||||
|
||||
## Simulating authenticated user requests
|
||||
|
||||
Our SDK methods can send requests on behalf of both anonymous and authenticated users. We can simulate an authenticated user session by calling the async `initUserSession()` helper (imported from the `jest.setup` file) at the beginning of a test case:
|
||||
|
||||
```ts
|
||||
import { initUserSession } from './__config__/jest.setup';
|
||||
|
||||
it('simulates authenticated user session', async () => {
|
||||
await initUserSession();
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
First, the helper requests a real user token from the SAP authorization server and the response is saved in a fixture. Second, it attaches the token as a cookie header to all remaining requests to API Middleware within the running test case.
|
||||
|
||||
After the test case execution is over, the cookie header is cleared automatically within the global `afterEach()` hook. Subsequent test cases must call `initUserSession()` again if they want to simulate an authenticated user session.
|
||||
|
||||
```ts
|
||||
import { initUserSession } from './__config__/jest.setup';
|
||||
|
||||
it('simulates authenticated user session', async () => {
|
||||
await initUserSession();
|
||||
// ...
|
||||
});
|
||||
|
||||
it('simulates authenticated user session, too', async () => {
|
||||
await initUserSession();
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
If - for some reason - you need to simulate both authenticated and anonymous sessions within a single test, you can use a complimentary `terminateUserSession()` helper:
|
||||
|
||||
```ts
|
||||
import { initUserSession, terminateUserSession } from './__config__/jest.setup';
|
||||
|
||||
it('simulates authenticated user session', async () => {
|
||||
await initUserSession();
|
||||
// send some requests as a logged-in user...
|
||||
|
||||
terminateUserSession();
|
||||
// send some requests as an anonymous user...
|
||||
});
|
||||
```
|
||||
@ -0,0 +1,4 @@
|
||||
/** Setup variables */
|
||||
export const NOCK_FIXTURES_CATALOG_NAME = '__nock-fixtures__';
|
||||
export const NOCK_MODE = 'record';
|
||||
export const NOCK_EXCLUDED_SCOPE = 'localhost';
|
||||
@ -0,0 +1,26 @@
|
||||
import { createServer } from '@vue-storefront/middleware';
|
||||
|
||||
const middlewareConfig = {
|
||||
integrations: {
|
||||
boilerplate: {
|
||||
location: '@vue-storefront/integration-boilerplate-api/server',
|
||||
configuration: {},
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
export default async () => {
|
||||
const app = await createServer(middlewareConfig);
|
||||
const server = await runMiddleware(app);
|
||||
|
||||
// eslint-disable-next-line
|
||||
(globalThis as any).__MIDDLEWARE__ = server;
|
||||
};
|
||||
|
||||
async function runMiddleware (app: any) {
|
||||
return new Promise(resolve => {
|
||||
const server = app.listen(8181, async () => {
|
||||
resolve(server);
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
import nock from 'nock';
|
||||
import path from 'path';
|
||||
import {
|
||||
NOCK_MODE,
|
||||
NOCK_FIXTURES_CATALOG_NAME,
|
||||
NOCK_EXCLUDED_SCOPE,
|
||||
} from './jest.const';
|
||||
|
||||
let nockDone;
|
||||
/**
|
||||
* Sets Nock mode, fixture name and directory. Removes recorded requests to API Middleware
|
||||
* so that integration tests send them every time.
|
||||
*/
|
||||
async function setupNock (customFixtureName?) {
|
||||
nock.back.setMode(NOCK_MODE);
|
||||
nock.back.fixtures = path.join(__dirname, '../', NOCK_FIXTURES_CATALOG_NAME);
|
||||
|
||||
const fixtureName = customFixtureName ?? expect.getState().currentTestName.split(' ').join('-');
|
||||
const afterRecord = (recordings) => recordings.filter(
|
||||
recording => !recording.scope.toString().includes(NOCK_EXCLUDED_SCOPE)
|
||||
);
|
||||
const { nockDone } = await nock.back(fixtureName, { afterRecord });
|
||||
|
||||
nock.enableNetConnect();
|
||||
|
||||
return nockDone;
|
||||
}
|
||||
|
||||
beforeEach(async () => {
|
||||
nockDone = await setupNock();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
nockDone();
|
||||
});
|
||||
|
||||
@ -0,0 +1,4 @@
|
||||
export default () => {
|
||||
// eslint-disable-next-line
|
||||
(globalThis as any).__MIDDLEWARE__.close();
|
||||
};
|
||||
@ -0,0 +1,10 @@
|
||||
import { initSDK, buildModule } from '@vue-storefront/sdk';
|
||||
import { boilerplateModule, BoilerplateModuleType } from '../../../src';
|
||||
|
||||
const sdkConfig = {
|
||||
boilerplate: buildModule<BoilerplateModuleType>(boilerplateModule, {
|
||||
apiUrl: 'http://localhost:8181/boilerplate',
|
||||
}),
|
||||
};
|
||||
|
||||
export const sdk = initSDK<typeof sdkConfig>(sdkConfig);
|
||||
@ -0,0 +1 @@
|
||||
[]
|
||||
@ -0,0 +1 @@
|
||||
[]
|
||||
@ -0,0 +1 @@
|
||||
[]
|
||||
@ -0,0 +1 @@
|
||||
[]
|
||||
@ -0,0 +1,13 @@
|
||||
import { sdk } from './__config__/sdk.config';
|
||||
|
||||
describe('[Integration Boilerplate SDK][integration] exampleMethod', () => {
|
||||
it('makes a request to the middleware', async () => {
|
||||
const EXPECTED_RESPONSE = {"data": "Hello, Vue Storefront Integrator!"};
|
||||
|
||||
const res = await sdk.boilerplate.exampleMethod({
|
||||
id: 1,
|
||||
});
|
||||
|
||||
expect(res).toEqual(EXPECTED_RESPONSE);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,46 @@
|
||||
import { exampleMethod } from '../../src/methods/exampleMethod';
|
||||
import { client } from '../../src/client';
|
||||
|
||||
/** SETUP */
|
||||
const API_METHOD_NAME = 'exampleEndpoint';
|
||||
const PARAMS_MOCK = { id: 1 };
|
||||
const RESPONSE_MOCK = { data: "Hello, Vue Storefront Integrator!" };
|
||||
const ERROR_MOCK = new Error('error');
|
||||
|
||||
jest.mock('../../src/client', () => ({
|
||||
client: {
|
||||
post: jest.fn(() => RESPONSE_MOCK)
|
||||
}
|
||||
}));
|
||||
|
||||
/** TESTS */
|
||||
describe('[Integration Boilerplate SDK][unit] exampleMethod', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
})
|
||||
|
||||
it('makes a single call to API Middleware', async () => {
|
||||
await exampleMethod(PARAMS_MOCK);
|
||||
|
||||
expect(client.post).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
it('makes a call to API Middleware with the right params', async () => {
|
||||
await exampleMethod(PARAMS_MOCK);
|
||||
|
||||
expect(client.post).toBeCalledWith(API_METHOD_NAME, PARAMS_MOCK);
|
||||
});
|
||||
|
||||
it('throws an exception in case of network error', async () => {
|
||||
expect.hasAssertions();
|
||||
(client.post as jest.Mock).mockRejectedValueOnce(ERROR_MOCK);
|
||||
|
||||
try {
|
||||
await exampleMethod(PARAMS_MOCK);
|
||||
} catch (err) {
|
||||
expect(err).toBe(ERROR_MOCK);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "../../api-extractor.base.json",
|
||||
"mainEntryPointFilePath": "./lib/api-extractor.data.d.ts",
|
||||
"dtsRollup": {
|
||||
"untrimmedFilePath": "./lib/<unscopedPackageName>.d.ts"
|
||||
},
|
||||
"docModel": {
|
||||
"apiJsonFilePath": "<projectFolder>/docs/reference/api/<unscopedPackageName>.api.json"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
const baseConfig = require('./../../jest.base.config');
|
||||
|
||||
module.exports = {
|
||||
...baseConfig,
|
||||
preset: 'ts-jest',
|
||||
transform: {
|
||||
'^.+\\.(j|t)s$': 'ts-jest',
|
||||
},
|
||||
globalSetup: './__tests__/integration/__config__/jest.setup.global.ts',
|
||||
globalTeardown: './__tests__/integration/__config__/jest.teardown.global.ts',
|
||||
setupFilesAfterEnv: ['./__tests__/integration/__config__/jest.setup.ts']
|
||||
};
|
||||
@ -0,0 +1,3 @@
|
||||
const baseConfig = require('./../../jest.base.config');
|
||||
|
||||
module.exports = { ...baseConfig };
|
||||
@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "@vue-storefront/integration-boilerplate-sdk",
|
||||
"version": "0.1.0",
|
||||
"main": "lib/index.cjs.js",
|
||||
"module": "lib/index.es.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "rimraf lib && rollup -c",
|
||||
"dev": "rimraf lib && rollup -c -w",
|
||||
"lint": "eslint . --ext .ts",
|
||||
"test": "yarn test:unit && yarn test:integration",
|
||||
"test:unit": "jest ./unit -c ./jest.config.unit.js",
|
||||
"test:integration": "jest ./integration -c ./jest.config.integration.js --runInBand",
|
||||
"test:integration:init": "rm -rf __tests__/integration/__nock-fixtures__ && jest ./integration -c ./jest.config.integration.js --runInBand",
|
||||
"test:watch": "jest --watch",
|
||||
"test:coverage": "jest --coverage --passWithNoTests",
|
||||
"prepublish": "yarn build"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.27.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue-storefront/integration-boilerplate-api": "0.1.0",
|
||||
"@vue-storefront/sdk": "1.0.1",
|
||||
"nock": "^13.2.9",
|
||||
"msw": "^0.47.3",
|
||||
"rollup-plugin-typescript2": "^0.34.1"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
import typescript from 'rollup-plugin-typescript2';
|
||||
import pkg from './package.json';
|
||||
|
||||
export default [
|
||||
{
|
||||
input: 'src/index.ts',
|
||||
output: [
|
||||
{
|
||||
file: pkg.main,
|
||||
format: 'cjs',
|
||||
sourcemap: true,
|
||||
},
|
||||
{
|
||||
file: pkg.module,
|
||||
format: 'es',
|
||||
sourcemap: true,
|
||||
},
|
||||
],
|
||||
external: [...Object.keys(pkg.dependencies || {})],
|
||||
plugins: [
|
||||
typescript({
|
||||
// eslint-disable-next-line global-require
|
||||
typescript: require('typescript'),
|
||||
}),
|
||||
],
|
||||
},
|
||||
];
|
||||
@ -0,0 +1,10 @@
|
||||
/**
|
||||
* `sdk-connector` for Vue Storefront 2 integration bolierplate.
|
||||
*
|
||||
* @remarks
|
||||
* In here you can find all references to the integration SDK connector.
|
||||
*
|
||||
* @packageDocumentation
|
||||
*/
|
||||
export * from './types';
|
||||
export * from './methods';
|
||||
@ -0,0 +1,3 @@
|
||||
import axios from 'axios';
|
||||
|
||||
export const client = axios.create();
|
||||
@ -0,0 +1,17 @@
|
||||
import { client } from './client';
|
||||
import { Options } from './types';
|
||||
import * as methods from './methods/index';
|
||||
|
||||
/**
|
||||
* Connector methods.
|
||||
*/
|
||||
type Methods = typeof methods;
|
||||
|
||||
/**
|
||||
* Initialize the Boilerplate connector.
|
||||
*/
|
||||
export const boilerplateConnector = (options: Options): Methods => {
|
||||
client.defaults.baseURL = options.apiUrl;
|
||||
|
||||
return methods;
|
||||
};
|
||||
@ -0,0 +1,28 @@
|
||||
import { boilerplateConnector } from './connector';
|
||||
import type { Options } from './types';
|
||||
import type { Module } from '@vue-storefront/sdk';
|
||||
|
||||
/**
|
||||
* Boulerplate module type.
|
||||
*/
|
||||
export interface BoilerplateModuleType extends Module {
|
||||
/**
|
||||
* The connector of the Boilerplate module.
|
||||
*/
|
||||
connector: ReturnType<typeof boilerplateConnector>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Boilerplate module.
|
||||
*/
|
||||
export const boilerplateModule = (options: Options): BoilerplateModuleType => ({
|
||||
connector: boilerplateConnector({
|
||||
apiUrl: options.apiUrl,
|
||||
}),
|
||||
utils: {},
|
||||
subscribers: {},
|
||||
});
|
||||
|
||||
export { client } from './client';
|
||||
|
||||
export * from './types';
|
||||
@ -0,0 +1,3 @@
|
||||
export { exampleMethod } from './exampleMethod';
|
||||
|
||||
export { getProducts } from './getProducts';
|
||||
@ -0,0 +1,18 @@
|
||||
import { AxiosRequestConfig } from 'axios';
|
||||
|
||||
/**
|
||||
* Definition of the MethodOptions parameter.
|
||||
*/
|
||||
export interface MethodOptions {
|
||||
|
||||
/**
|
||||
* {@link https://axios-http.com/docs/req_config | AxiosRequestConfig} object
|
||||
* You can use it to override Axios request configuration
|
||||
*/
|
||||
axiosRequestConfig?: Readonly<AxiosRequestConfig>;
|
||||
|
||||
/**
|
||||
* Additional optional fields. Its usage depends on the custom implementation.
|
||||
*/
|
||||
[key: string]: any;
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
export type TODO = any;
|
||||
|
||||
export type { MethodOptions } from './MethodOptions';
|
||||
export type { Options } from './options';
|
||||
@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Options for the SDK module.
|
||||
*/
|
||||
export interface Options {
|
||||
/**
|
||||
* The API URL of the client-side environment.
|
||||
*/
|
||||
apiUrl: string;
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"include": ["src"],
|
||||
"exclude": ["__mocks__", "__tests__"]
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
integrations: {
|
||||
boilerplate: {
|
||||
location: '@vue-storefront/integration-boilerplate-api/server',
|
||||
configuration: {},
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -0,0 +1,26 @@
|
||||
const { createServer } = require("@vue-storefront/middleware");
|
||||
const { integrations } = require("./middleware.config");
|
||||
const cors = require("cors");
|
||||
|
||||
(async () => {
|
||||
const app = await createServer({ integrations });
|
||||
const host = process.argv[2] ?? "0.0.0.0";
|
||||
const port = process.argv[3] ?? 8181;
|
||||
const CORS_MIDDLEWARE_NAME = "corsMiddleware";
|
||||
|
||||
const corsMiddleware = app._router.stack.find(
|
||||
(middleware) => middleware.name === CORS_MIDDLEWARE_NAME
|
||||
);
|
||||
|
||||
corsMiddleware.handle = cors({
|
||||
origin: [
|
||||
"http://localhost:3000",
|
||||
...(process.env.MIDDLEWARE_ALLOWED_ORIGINS?.split(",") ?? []),
|
||||
],
|
||||
credentials: true,
|
||||
});
|
||||
|
||||
app.listen(port, host, () => {
|
||||
console.log(`Middleware started: ${host}:${port}`);
|
||||
});
|
||||
})();
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "@vue-storefront/integration-boilerplate-playground",
|
||||
"private": true,
|
||||
"version": "0.1.0",
|
||||
"engines": {
|
||||
"node": ">=16.x"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "nodemon --watch node middleware.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vue-storefront/middleware": "3.0.1",
|
||||
"@vue-storefront/integration-boilerplate-api": "*",
|
||||
"cors": "^2.8.5"
|
||||
},
|
||||
"files": [
|
||||
"lib/**/*",
|
||||
"server/**/*"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
import nodeResolve from '@rollup/plugin-node-resolve';
|
||||
import typescript from 'rollup-plugin-typescript2';
|
||||
import { terser } from 'rollup-plugin-terser';
|
||||
|
||||
const extensions = ['.ts', '.js'];
|
||||
|
||||
export function generateBaseConfig(pkg) {
|
||||
return {
|
||||
input: 'src/index.ts',
|
||||
output: [
|
||||
{
|
||||
file: pkg.main,
|
||||
format: 'cjs',
|
||||
sourcemap: true
|
||||
},
|
||||
{
|
||||
file: pkg.module,
|
||||
format: 'es',
|
||||
sourcemap: true
|
||||
}
|
||||
],
|
||||
external: [
|
||||
...Object.keys(pkg.dependencies || {}),
|
||||
...Object.keys(pkg.peerDependencies || {})
|
||||
],
|
||||
plugins: [
|
||||
nodeResolve({
|
||||
extensions
|
||||
}),
|
||||
typescript({
|
||||
// eslint-disable-next-line global-require
|
||||
typescript: require('typescript'),
|
||||
objectHashIgnoreUnknownHack: false
|
||||
}),
|
||||
terser()
|
||||
]
|
||||
};
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"outDir": "./lib",
|
||||
"esModuleInterop": true,
|
||||
"target": "ES2020",
|
||||
"module": "ES2015",
|
||||
"moduleResolution": "node",
|
||||
"importHelpers": true,
|
||||
"noEmitHelpers": true,
|
||||
"sourceMap": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"baseUrl": "./",
|
||||
"lib": ["ES2020", "dom"],
|
||||
"strict": false,
|
||||
"preserveSymlinks": true,
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
"exclude": ["node_modules", "**/*.spec.ts", "**/*.mock.ts"]
|
||||
}
|
||||
Loading…
Reference in New Issue