### Check Node.js Installation Source: https://github.com/netoecommerce/app-tutorial/blob/master/README.md Verifies if Node.js is installed and displays its version. Requires Node.js to be installed on the system. ```Bash node -v ``` -------------------------------- ### Set up Express Server Entry Point Source: https://github.com/netoecommerce/app-tutorial/blob/master/README.md Initializes an Express.js server, sets up middleware for CORS and body parsing, and starts the server listening on port 3000. This serves as the main entry point for the application. ```javascript const express = require('express'); const app = express(); app.use(require('cors')()); app.use(require('body-parser').urlencoded({ extended: true })); app.listen(3000, (err) => { if (err) throw err; console.log(`Listening on http://localhost:3000`); }); ``` -------------------------------- ### Check Docker Installation Source: https://github.com/netoecommerce/app-tutorial/blob/master/README.md Verifies if Docker is installed and displays its version. Requires Docker to be installed on the system. ```Bash docker -v ``` -------------------------------- ### Install React App Rewired Source: https://github.com/netoecommerce/app-tutorial/blob/master/README.md Installs `react-app-rewired` as a development dependency. This package allows customization of the `create-react-app` build configuration without ejecting. ```bash npm install -D react-app-rewired ``` -------------------------------- ### Install Node.js Dependencies Source: https://github.com/netoecommerce/app-tutorial/blob/master/README.md Installs the necessary Node.js packages for the project, including body-parser, cors, dotenv, express, passport, passport-oauth2, and redis. This command is run using npm within a Node.js project. ```Bash npm install --save body-parser cors dotenv express passport passport-oauth2 redis ``` -------------------------------- ### Interact with Redis using Node.js Redis Client Source: https://github.com/netoecommerce/app-tutorial/blob/master/README.md Provides a Node.js module to interact with Redis. It includes functions to set and get key-value pairs, establishes a connection to the Redis client, and handles potential client errors. ```javascript const { createClient } = require('redis'); const client = createClient(); const setClient = async (key, value) => { await client.set(key, value); } const getClient = async (key) => { const value = await client.get(key); return value; } (async () => { await client.connect(); })(); client.on('error', err => console.log('Redis Client Error', err)); module.exports = { setClient, getClient }; ``` -------------------------------- ### Inject Server-Side Variables into Custom Script Source: https://github.com/netoecommerce/app-tutorial/blob/master/README.md This example shows how to pass server-side variables, such as email address and page ID, from Neto's B@SE template language into your custom JavaScript. These variables are made available globally via the window object. ```html
``` -------------------------------- ### Add History Route with Redis Caching (JavaScript Diff) Source: https://github.com/netoecommerce/app-tutorial/blob/master/README.md This code snippet, presented as a diff, adds a new GET route '/history' to an Express.js application. It retrieves store domain and authentication tokens from Redis, fetches orders from the Neto API if the cache has expired, maps the orders, and serves them. If the cache is valid, it serves the cached orders. This enhances performance by reducing direct API calls. ```diff const express = require('express'); const passport = require('passport'); + const client = require('./redis'); + const { getOrders, mapOrders } = require('./neto'); const router = express.Router(); router.get( '/auth/callback', passport.authenticate('neto', { session: false, }), (_req, res) => { res.redirect('/auth/success'); } ); router.get('/auth/success', (req, res) => { res.send('Successfully authenticated!'); }); +router.get('/history', async (req, res) => { + const store_domain = req.get('Origin').replace('https://', ''); + const expiryDate = await client.getClient(`${store_domain}#expiry`); + + // serve new orders + if (new Date() > new Date(expiryDate || 0)) { + const secret = await client.getClient(`${store_domain}#token`); + const json = await getOrders(store_domain, secret); + const orders = mapOrders(json.Order); + res.json(orders); + await client.setClient(`${store_domain}#expiry`, new Date(Date.now() + 5184000000).toISOString()); + await client.setClient(`${store_domain}#orders`, JSON.stringify(orders)); + } + // serve cached orders + else { + const json = await client.getClient(`${store_domain}#orders`); + const orders = JSON.parse(json); + res.json(orders); + } +}); module.exports = router; ``` -------------------------------- ### Initialize Node.js Project Source: https://github.com/netoecommerce/app-tutorial/blob/master/README.md Initializes a new Node.js project by creating a package.json file. This command is run within a Node.js project directory. ```Bash npm init ``` -------------------------------- ### Create React App for Neto Addon Source: https://github.com/netoecommerce/app-tutorial/blob/master/README.md Initializes a new React project named 'addon-front-end' using `create-react-app`. This command sets up the basic structure for the front-end widget. ```bash npx create-react-app addon-front-end ``` -------------------------------- ### Create Project Folder Source: https://github.com/netoecommerce/app-tutorial/blob/master/README.md Creates a new directory for the add-on's backend code. This is a standard command-line operation. ```Bash mkdir addon-back-end ``` -------------------------------- ### Navigate to Project Folder Source: https://github.com/netoecommerce/app-tutorial/blob/master/README.md Changes the current directory to the newly created project folder. This is a standard command-line operation. ```Bash cd addon-back-end ``` -------------------------------- ### Build Custom Script with npm Source: https://github.com/netoecommerce/app-tutorial/blob/master/README.md This command initiates the build process for your custom widget, generating a bundled JavaScript file. The output is typically found in a 'build/static/' directory. ```bash npm run build ``` -------------------------------- ### Configure Build Optimization Source: https://github.com/netoecommerce/app-tutorial/blob/master/README.md Provides a `config-overrides.js` file to modify the Webpack configuration used by `create-react-app`. It disables runtime chunk and splits chunks to ensure a single output file for the widget. ```javascript module.exports = function override(config) { config.optimization.runtimeChunk = false; config.optimization.splitChunks = { cacheGroups: { default: false, }, }; return config; }; ``` -------------------------------- ### Fetch Neto Orders and Map Data (JavaScript) Source: https://github.com/netoecommerce/app-tutorial/blob/master/README.md This snippet defines two asynchronous JavaScript functions: `getOrders` to retrieve order data from the Neto API using POST requests with specific headers and filters, and `mapOrders` to transform the fetched order data into a simpler format. It requires a configuration file for client ID and uses the `fetch` API. Error handling is included for the fetch operation. ```javascript const config = require('./config'); const getOrders = async (store_domain, secret) => { try { const res = await fetch(`https://${store_domain}/do/WS/NetoAPI`, { method: 'POST', headers: { X_ACCESS_KEY: config.CLIENT_ID, X_SECRET_KEY: secret, NETOAPI_ACTION: 'GetOrder', Accept: 'application/json', }, body: `{ "Filter": { "DatePlacedFrom": "${new Date(Date.now() - 86400000).toISOString()}", "OutputSelector": [ "OrderLine", "OrderLine.ProductName", "BillAddress", "DatePlaced" ] } }`, }); orders = await res.json(); return orders; } catch (e) { return `Fetch Error. ${e}`; } }; const mapOrders = (orders) => { return orders.map((order) => ({ date_placed: order.DatePlaced, sku: order.OrderLine[0].SKU, name: order.OrderLine[0].ProductName, city: order.BillCity, })); }; module.exports = { mapOrders, getOrders }; ``` -------------------------------- ### Define Express Routes for Neto OAuth Callback Source: https://github.com/netoecommerce/app-tutorial/blob/master/README.md Creates Express routes to handle the OAuth callback from Neto and a success route. The callback route uses Passport.js to authenticate the user and redirects to a success page upon successful authentication. ```javascript const express = require('express'); const passport = require('passport'); const router = express.Router(); router.get( '/auth/callback', passport.authenticate('neto', { session: false, }), (_req, res) => { res.redirect('/auth/success'); } ); router.get('/auth/success', (req, res) => { res.send('Successfully authenticated!'); }); module.exports = router; ``` -------------------------------- ### Load Environment Variables for Application Configuration Source: https://github.com/netoecommerce/app-tutorial/blob/master/README.md Loads environment variables, specifically 'CLIENT_ID' and 'CLIENT_SECRET', using the 'dotenv' package. These variables are intended to store sensitive credentials securely. ```javascript require("dotenv").config(); module.exports = { CLIENT_ID: process.env.CLIENT_ID, CLIENT_SECRET: process.env.CLIENT_SECRET }; ``` -------------------------------- ### Configure Passport OAuth2 Strategy for Neto Source: https://github.com/netoecommerce/app-tutorial/blob/master/README.md Sets up a Passport.js OAuth2 strategy for integrating with Neto's authentication system. It defines authorization and token URLs, client credentials, callback URL, and handles the access token by storing it in Redis. ```javascript const passport = require('passport'); const OAuth2Strategy = require('passport-oauth2'); const client = require('./redis'); const config = require('./config'); passport.use( 'neto', new OAuth2Strategy( { authorizationURL: 'https://apps.getneto.com/oauth/v2/auth', tokenURL: 'https://apps.getneto.com/oauth/v2/token', clientID: config.CLIENT_ID, clientSecret: config.CLIENT_SECRET, callbackURL: 'http://localhost:3000/auth/callback', passReqToCallback: true, }, async ( req, accessToken, _refreshToken, { store_domain }, info, callback ) => { client.setClient(`${store_domain}#token`, accessToken); callback(null, {}); } ) ); module.exports = passport; ``` -------------------------------- ### Add Styling and Elapsed Time to React Widget Source: https://github.com/netoecommerce/app-tutorial/blob/master/README.md This code extends the previous React widget by adding inline styles for presentation and a helper function `getElapsedTime` to display how long ago an order was placed. The widget now shows the elapsed time below the purchase details. ```javascript import React, { useEffect, useState } from "react"; const styles = { position: "fixed", bottom: 100, right: 50, width: 400, height: 80, zIndex: 2000, boxShadow: "4px 4px 4px grey", border: "1px solid #fafafa", fontSize: 12, background: "white", padding: 8, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', textAlign: 'center' }; const getElapsedTime = (time) => { const since = Number(time); const elapsed = Date.now() - since; const second = 1000; const minute = second * 60; const hour = minute * 60; const day = hour * 24; if (elapsed >= second && elapsed < minute) { const seconds = Math.floor(elapsed / second); return `${seconds} second${seconds > 1 ? "s" : ""} ago`; } if (elapsed >= minute && elapsed < hour) { const minutes = Math.floor(elapsed / minute); return `${minutes} minute${minutes > 1 ? "s" : ""} ago`; } if (elapsed >= hour && elapsed < day) { const hours = Math.floor(elapsed / hour); return `${hours} hour${hours > 1 ? "s" : ""} ago`; } const days = Math.floor(elapsed / day); return `${days} day${days > 1 ? "s" : ""} ago`; }; const App = () => { // ... existing code ... const { city, name, date_placed } = activeOrder; return Object.keys(activeOrder).length ? (

Someone in {city} bought {name}!

{getElapsedTime(new Date(date_placed))}
) : null; }; export default App; ``` -------------------------------- ### Configure Redis with Docker Compose Source: https://github.com/netoecommerce/app-tutorial/blob/master/README.md Defines a Docker Compose configuration to run a Redis container locally. It specifies the Redis image, names the container 'cache', and exposes the default Redis port (6379) to the host machine. ```yml version: '3' services: redis: image: redis:latest container_name: cache ports: - 6379:6379 ``` -------------------------------- ### Update Build Script in package.json Source: https://github.com/netoecommerce/app-tutorial/blob/master/README.md Modifies the 'build' script in `package.json` to use `react-app-rewired build` instead of `react-scripts build`. This ensures the custom build configuration is applied. ```json { ... "scripts": { "start": "react-scripts start", "build": "react-app-rewired build", "test": "react-scripts test", "eject": "react-scripts eject" }, ... } ``` -------------------------------- ### Add Custom Script to Neto Page Footer Source: https://github.com/netoecommerce/app-tutorial/blob/master/README.md This HTML snippet demonstrates how to include your custom JavaScript file in the page footer of your Neto store. It uses Neto's theme asset tag to correctly reference the script path. ```html
``` -------------------------------- ### Integrate Passport and Routes into Express App Source: https://github.com/netoecommerce/app-tutorial/blob/master/README.md Modifies the main Express application file (`index.js`) to include the Passport middleware and the custom routes for OAuth handling. This enables the application to process authentication requests. ```javascript const express = require('express'); const routes = require('./routes'); const passport = require('./passport'); const app = express(); app.use(require('cors')()); app.use(require('body-parser').urlencoded({ extended: true })); app.use(passport.initialize()); app.use(routes); app.listen(3000, (err) => { if (err) throw err; console.log(`Listening on http://localhost:3000`); }); ``` -------------------------------- ### Display Recent Orders Widget in React Source: https://github.com/netoecommerce/app-tutorial/blob/master/README.md This snippet shows a React component that fetches order history from a server, displays the most recent order, and cycles through orders at a set interval. It includes state management for orders and the active order, and uses `useEffect` for data fetching and interval management. ```javascript import React, { useEffect, useState } from "react"; const App = () => { const [orders, setOrders] = useState([]); const [activeOrder, setActiveOrder] = useState({}); useEffect(() => { fetch("http://localhost:3000/history") .then((res) => res.json()) .then((json) => { setOrders(json); }); }, []); useEffect(() => { if (orders.length) { let i = 0; setActiveOrder(orders[i]); const interval = setInterval(() => { if (i === orders.length - 1) { i = 0; } else { i += 1; } setActiveOrder(orders[i]); }, [1000 * 10]); return () => { clearInterval(interval); }; } }, [orders]); const { city, name, date_placed } = activeOrder; return Object.keys(activeOrder).length ? (

Someone in {city} bought {name}!

) : null; }; export default App; ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.