Using watch with Nunjucks on Hapi - hapi.js

So I've tried both the Nunjucks example in the Vision docs as well as the plugin nunjucks-hapi with the same result - watch does not work.
var viewPath = Path.join(__dirname, 'views')
var env = NunjucksHapi.configure(viewPath, { watch: true})
server.register(plugins, (err) => {
if (err) throw err;
server.views({
engines: {
html: NunjucksHapi
},
path: viewPath
});
server.route(...);
server.start((err) => {
});
});
Packages:
"hapi": "^13.0.0",
"nunjucks": "^2.3.0",
"nunjucks-hapi": "^2.0.1",
"vision": "^4.0.1"
Suggestions as to where to look for issue?

try it:
server.register(require('vision'), (err) => {
Hoek.assert(!err, err)
server.views({
engines: {
njk: require('nunjucks-hapi')
},
relativeTo: __dirname,
path: 'resources/views'
})
})

Related

Use API Routes on localhost on build in Next.js [duplicate]

I don't understand these errors when I export as production npm run build , but when I test npm run dev it works just fine. I use getStaticProps and getStaticPath fetch from an API route.
First when I npm run build
FetchError: invalid json response body at https://main-website-next.vercel.app/api/products reason: Unexpected token T in JSON at position
0
at D:\zummon\Main Website\main-website-next\node_modules\node-fetch\lib\index.js:272:32
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at async getStaticPaths (D:\zummon\Main Website\main-website-next\.next\server\pages\product\[slug].js:1324:18)
at async buildStaticPaths (D:\zummon\Main Website\main-website-next\node_modules\next\dist\build\utils.js:16:80)
at async D:\zummon\Main Website\main-website-next\node_modules\next\dist\build\utils.js:26:612
at async D:\zummon\Main Website\main-website-next\node_modules\next\dist\build\tracer.js:1:1441 {
type: 'invalid-json'
}
\pages\product\[slug]
import { assetPrefix } from '../../next.config'
export default function Page(){...}
export const getStaticProps = async ({ params: { slug }, locale }) => {
const res = await fetch(`${assetPrefix}/api/products/${slug}`)
const result = await res.json()
const data = result.filter(item => item.locale === locale)[0]
const { title, keywords, description } = data
return {
props: {
data,
description,
keywords,
title
}
}
}
export const getStaticPaths = async () => {
const res = await fetch(`${assetPrefix}/api/products`)
const result = await res.json()
const paths = result.map(({ slug, locale }) => ({ params: { slug: slug }, locale }))
return {
fallback: true,
paths,
}
}
next.config.js
const isProd = process.env.NODE_ENV === 'production'
module.exports = {
assetPrefix: isProd ? 'https://main-website-next.vercel.app' : 'http://localhost:3000',
i18n: {
localeDetection: false,
locales: ['en', 'th'],
defaultLocale: 'en',
}
}
API routes
// pages/api/products/index.js
import data from '../../../data/products'
export default (req, res) => {
res.status(200).json(data)
}
// pages/api/products/[slug].js
import db from '../../../data/products'
export default ({ query: { slug } }, res) => {
const data = db.filter(item => item.slug === slug)
if (data.length > 0) {
res.status(200).json(data)
} else {
res.status(404).json({ message: `${slug} not found` })
}
}
// ../../../data/products (data source)
module.exports = [
{ locale: "en", slug: "google-sheets-combine-your-cashflow",
title: "Combine your cashflow",
keywords: ["Google Sheets","accounting"],
description: "...",
},
...
]
Second when I remove the production domain, I run npm run build but still get the error like
TypeError: Only absolute URLs are supported
at getNodeRequestOptions (D:\zummon\Main Website\main-website-next\node_modules\node-fetch\lib\index.js:1305:9)
at D:\zummon\Main Website\main-website-next\node_modules\node-fetch\lib\index.js:1410:19
at new Promise (<anonymous>)
at fetch (D:\zummon\Main Website\main-website-next\node_modules\node-fetch\lib\index.js:1407:9)
at getStaticPaths (D:\zummon\Main Website\main-website-next\.next\server\pages\[slug].js:938:21)
at buildStaticPaths (D:\zummon\Main Website\main-website-next\node_modules\next\dist\build\utils.js:16:86)
at D:\zummon\Main Website\main-website-next\node_modules\next\dist\build\utils.js:26:618
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at async D:\zummon\Main Website\main-website-next\node_modules\next\dist\build\tracer.js:1:1441 {
type: 'TypeError'
}
My next.config.js after remove
const isProd = process.env.NODE_ENV === 'production'
module.exports = { //remove
assetPrefix: isProd ? '' : 'http://localhost:3000',
i18n: {
localeDetection: false,
locales: ['en', 'th'],
defaultLocale: 'en',
}
}
My package.json when I npm run build script
{
"name": "main-website-next",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build && next export",
"start": "next start"
},
"dependencies": {
"next": "10.0.6",
"react": "17.0.1",
"react-dom": "17.0.1"
}
}
You should not call an internal API route inside getStaticProps. Instead, you can safely use your API logic directly in getStaticProps/getStaticPaths. These only happen server-side so you can write server-side code directly.
As getStaticProps runs only on the server-side, it will never run on
the client-side. It won’t even be included in the JS bundle for the
browser, so you can write direct database queries without them being
sent to browsers.
This means that instead of fetching an API route from
getStaticProps (that itself fetches data from an external source),
you can write the server-side code directly in getStaticProps.
Furthermore, your API routes are not available during build-time, as the server has not been started at that point.
Here's a small refactor of your code to address the issue.
// /pages/product/[slug]
import db from '../../../data/products'
// Remaining code..
export const getStaticProps = async ({ params: { slug }, locale }) => {
const result = db.filter(item => item.slug === slug)
const data = result.filter(item => item.locale === locale)[0]
const { title, keywords, description } = data
return {
props: {
data,
description,
keywords,
title
}
}
}
export const getStaticPaths = async () => {
const paths = db.map(({ slug, locale }) => ({ params: { slug: slug }, locale }))
return {
fallback: true,
paths,
}
}

rtmp video does not play under electron: build command

I use electron-builder to package my vue projects. In my project I have a video page that uses rtmp video stream.
However, the video plays fine when I use electron:serve and browser, but the video does not play when I use electron:build.
My version is as follows.
os : windows10
"vue": "2.6.10",
"electron": "^13.6.9",
"electron-builder":"#22.14.13"
"vue-aliplayer-v2": "^1.3.0",
My configuration is as follows.
'use strict'
import { app, protocol, BrowserWindow } from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
const isDevelopment = process.env.NODE_ENV !== 'production'
protocol.registerSchemesAsPrivileged([
{ scheme: 'app', privileges: { secure: true, standard: true, stream: true } }
])
async function createWindow() {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
enableRemoteModule: !!process.env.IS_TEST,
webSecurity: false,
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION
}
})
if (process.env.WEBPACK_DEV_SERVER_URL) {
await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
if (!process.env.IS_TEST) win.webContents.openDevTools()
} else {
createProtocol('app')
win.loadURL('app://./index.html')
}
}
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
app.on('ready', async () => {
if (isDevelopment && !process.env.IS_TEST) {
// Install Vue Devtools
try {
await installExtension(VUEJS_DEVTOOLS)
} catch (e) {
console.error('Vue Devtools failed to install:', e.toString())
}
}
createWindow()
})
if (isDevelopment) {
if (process.platform === 'win32') {
process.on('message', (data) => {
if (data === 'graceful-exit') {
app.quit()
}
})
} else {
process.on('SIGTERM', () => {
app.quit()
})
}
}
video page:
components: {
VueAliplayerV2
},
data() {
return {
options: {
isLive: true, //切换为直播流的时候必填
format: 'm3u8' //切换为直播流的时候必填
},
source: '//localhost:9600/live/uav0.m3u8',
show: true,
isShowMultiple: false,
};
},
I want to know how I need to solve the problem of unplayable video in electron.

Express, Ejs and i18next how to switch between languages?

I have been trying to figure out how to make the switcher or language selector work from the frontend part of the website. Also my first time working with SSR, so I am not sure about the communication in between. So far what I handled and works well, the inclusion for the translation rendering is working, also when i manually change the language for testing purpose.
I have been reading the documentation, but there is not specific tutorial about how to handle this, more than the function "changeLanguage" and some solutions I found are older as 5 years and involves, deprecated version and some kind of extra library to handled some template views, and I don't know if if this actually is still feasible. However inside the repository from i18next-http-middleware, there is an example that basically does kind what I want. So can be found under the "basic-pug" folder. The difference is that it is used "Pug" as a template engine, which I don't think it should affect or make any difference. so I used exactly the same configuration as the example, which i downloaded and tested and it was working, so it supposed enabled a cookie, and then on the url can pass the cookie as a param, with the locale, and it supposed to work, however not working with in my project, and I also wondering if it possible to have "/de/" instead "/?lang=de", example www.myweb.com/de/about and not www.myweb.com/about/?lang=de, because that's not exactly what I was imagining, and also no clear how to handled when u have nested or several routes.
In general, I was wondering how to use the "changelanguage" function in the frontend side, so I have, for example, something like:
<div>
<div onclick="Changelanguage("de")"> Deutsch</div>
<div onclick="Changelanguage("en")"> English</div>
</div>
Because by declaring the function just like in the views, on a script tag, I the changelanguage is not a function, because there is no communication between both.
Please find below my configuration:
Json file:
{
"name": "project",
"version": "0.0.0",
"private": true,
"author": "project",
"main": "dist/index.js",
"scripts": {
"start": "node dist/index.js",
"dev": "nodemon src/index.js --exec \"node -r dotenv/config -r #babel/register\"",
"clean": "rimraf dist",
"build": "npm run clean && mkdir -p dist && babel src -s -D -d dist",
"postinstall": "npm run build"
},
"dependencies": {
"#babel/cli": "^7.18.9",
"#babel/core": "^7.18.9",
"#babel/plugin-proposal-class-properties": "^7.18.6",
"#babel/plugin-proposal-object-rest-spread": "^7.18.9",
"#babel/preset-env": "^7.18.9",
"body-parser": "^1.19.0",
"ejs": "^3.1.8",
"express": "^4.18.1",
"graphql": "^16.5.0",
"graphql-request": "^4.3.0",
"i18next": "^21.9.1",
"i18next-fs-backend": "^1.1.5",
"i18next-http-middleware": "^3.2.1",
"locomotive-scroll": "^4.1.4",
"morgan": "^1.10.0",
"node-sass-middleware": "^1.0.1",
"rimraf": "^3.0.0"
},
"devDependencies": {
"#babel/register": "^7.18.9",
"dotenv": "^16.0.1",
"nodemon": "^2.0.19"
},
"babel": {
"presets": [
[
"#babel/preset-env",
{
"targets": {
"node": "current"
}
}
]
],
"plugins": [
"#babel/plugin-proposal-class-properties",
"#babel/plugin-proposal-object-rest-spread"
]
}
}
My routes file js
import { GraphQLClient
} from "graphql-request";
import { Router
} from "express";
import * as queries from "./queries";
import i18next from "i18next";
const routes = Router();
export function request({ query, variables, preview, includeDrafts
}) {
// ...some headers and client configs
};
return client.request(query, variables);
}
let generalInfo = null;
const getData = async (options) => {
options.page = options.page ? options.page : "";
if (!generalInfo) {
generalInfo = await request({
query: queries.getGeneralInfo,
variables: {
locale: options.lang
}
});
}
let q = queries.getPage(options.page);
let data = await request({
query: q,
variables: {
locale: options.lang
}
});
data = Object.assign(data, generalInfo);
return data;
};
const getCase = async (slug, lang) => {
if (!generalInfo) {
generalInfo = await request({
query: queries.getGeneralInfo,
variables: {
locale: lang
}
});
}
slug = slug ? slug : "";
let q = queries.getCase;
let data = await request({
query: q,
variables: {
locale: lang
}
});
data = Object.assign(data, generalInfo);
const filter = data.allCases.filter((n) => n.slug == slug)
return filter;
};
const getInnerPage = async (slug, lang) => {
if (!generalInfo) {
generalInfo = await request({
query: queries.getGeneralInfo,
variables: {
locale: lang
}
});
}
slug = slug ? slug : "";
let q = queries.getInner;
let data = await request({
query: q,
variables: {
locale: lang
}
});
data = Object.assign(data, generalInfo);
const filter = data.allPages.filter((n) => n.slug == slug);
return filter;
};
routes.get("/cases/:slug", (req, res) => {
let slug = req.params.slug;
getCase(slug, req.locale).then(filter => {
if (filter.length) {
res.render("case",
{ title: filter.project_title, filter, t: i18next.t
});
} else {
res.render("404");
}
}).catch(e => {
console.error(e);
});
});
routes.get("/page/:slug", (req, res) => {
let slug = req.params.slug;
getInnerPage(slug, req.locale).then(filter => {
if (filter.length) {
res.render("page",
{ title: filter[
0
].titlePage, filter, t: i18next.t
});
} else {
res.render("404");
}
}).catch(e => {
console.error(e);
});
});
routes.get("/", (req, res) => {
let options = { 'lang': req.locale, 'page': ""
}
//console.log(req.locale + " locale selected");
getData(options).then(data => {
res.render("home",
{ title: "Home", data, t: i18next.t
});
}).catch(e => {
console.error(e);
});
});
export default routes;
My index js
import express from "express";
import path from "path";
import logger from "morgan";
import bodyParser from "body-parser";
import routes from "./routes";
import sassMiddleware from "node-sass-middleware";
import i18next from "i18next";
import i18nextBackend from "i18next-fs-backend";
import i18nextMiddleware from "i18next-http-middleware";
const { PORT = 5050 } = process.env;
const app = express();
i18next.use(i18nextBackend)
.use(i18nextMiddleware.LanguageDetector)
.init({
//lng: 'de',
debug: true,
fallbackLng: 'en',
preload: ['de', 'en'],
backend: {
loadPath: './locales/{{lng}}/translation.json'
},
detection: {
order: ['querystring', 'cookie'],
caches: ['cookie'],
lookupQuerystring: 'lang',
lookupCookie: 'lang',
ignoreCase: true,
cookieSecure: false
},
})
app.use(i18nextMiddleware.handle(i18next));
//i18next.changeLanguage('de');
app.set("views", path.join(__dirname, "../views"));
app.set("view engine", "ejs");
app.use(logger("dev"));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.locals = { config: { whatever: 'this is' } };
app.use(
sassMiddleware({
src: path.join(__dirname, "../public/scss"),
dest: path.join(__dirname, "../public"),
indentedSyntax: false,
sourceMap: false
})
);
app.use(express.static(path.join(__dirname, "../public")));
app.use("/", routes);
app.use(function (req, res) {
res.status(404).render('404.ejs');
});
app.use(function (req, res) {
res.status(500).render('500.ejs');
});
app.listen(PORT, () => {
console.log(`Listening on port ${PORT}`);
});
export default app;
Thank you in advance for any help, I think I am mainly struggling because I use to work on client side, but still learning about SSR.
You should be able to define the language also in the route, like described here: https://github.com/i18next/i18next-http-middleware#language-detection
Define the 'path' in the detection options: order: ['path', /*'session', */ 'querystring', 'cookie', 'header'],
Regarding the language change. You probably just need to navigate to the route with the appropriate language.

Metro config not accepting blockList

I am building a react-native app with expo, I am using the modules of react-native-svg-transformer and also amplify (where I have created functions). The problem is that the functions in the amplify directory have package.json files and do not work. This is why I'm trying to put the amplify directory in the blocList of the metro configuration, but I keep getting the error:
Failed to construct transformer: TypeError: Transformer is not a constructor
This is my metro config:
const { getDefaultConfig } = require("expo/metro-config")
// extra config is needed to enable `react-native-svg-transformer`
module.exports = (async () => {
const {
resolver: { sourceExts, assetExts },
} = await getDefaultConfig(__dirname)
return {
transformer: {
babelTransformerPath: require.resolve("react-native-svg-transformer"),
assetPlugins: ["expo-asset/tools/hashAssetFiles"],
},
resolver: {
assetExts: assetExts.filter((ext) => ext !== "svg"),
sourceExts: [...sourceExts, "svg"],
blockList: [/amplify.*/]
},
}
})()
I also tried this but it didn't work either:
const { getDefaultConfig } = require("expo/metro-config")
// extra config is needed to enable `react-native-svg-transformer`
module.exports = (async () => {
const {
resolver: { sourceExts, assetExts },
} = await getDefaultConfig(__dirname)
return {
transformer: {
babelTransformerPath: require.resolve("react-native-svg-transformer"),
experimentalImportSupport: false,
inlineRequires: true,
},
resolver: {
assetExts: assetExts.filter((ext) => ext !== "svg"),
sourceExts: [...sourceExts, "svg"],
blockList: [/amplify.*/]
},
}
})()
It was that some packages used metro-config#0.59 and I npm-installed metro-config#0.61 so they were incompatible.

Upload React-Native imagePicker with axios on Cloudinary

I try to upload some image from the camera gallery on localhost and prod environnement. My code works with a valid url like : https://res.cloudinary.com/dtdiwoz7o/image/upload/v1586706052/cn-2016-sashaonyshchenko-1920x1920-1510074905_dyfldk.jpg
But when I pass the image file path, it's return an 400 error.
Here is my code with some log :
_avatarClicked = () => {
const options = {
title: 'Select Photo',
storageOptions: {
skipBackup: true,
path: 'images',
},
};
ImagePicker.showImagePicker(options, (response) => {
if (response.didCancel) {
return
}
else if (response.error) {
return
}
else {
let data = {
file: response.uri,
upload_preset: "my_preset_name",
}
axios.post("https://api.cloudinary.com/v1_1/my_cloud_name/image/upload", data)
.then(res => console.log(res))
.catch(err => console.log(err))
}
})
}
log of my repsponse.uri :
(file:///Users/clement/Library/Developer/CoreSimulator/Devices/62E85527-A2AC-46CD-B517-E6039F99E056/data/Containers/Data/Application/E218E950-3A1C-40EB-8289-3837EC89FBBB/Documents/images/46674162-E32B-4302-B28A-5EF9150206D0.jpg)
I tried to replace in data file this by this 'const source' but it doesn't work :
const source = {
uri: response.uri,
type: response.type,
name: response.fileName,
}
I saw and test this on the react-native)image-picker documentation but I've got the same 400 error...
// const source = { uri: 'data:image/jpeg;base64,' + response.data };
I also try to Base64.encode(response.url) or Base64.encodeURI(response.url)
Please, can you help me ?
And sorry for my bad english
"react-native": "~0.61.4",
"react-native-image-picker": "^2.3.1",
///////////////////////////
I found the solution :
let data = {
file: 'data:image/jpg;base64,' + response.data,
upload_preset: "my_preset_name",
}
axios.post("https://api.cloudinary.com/v1_1/my_cloud_name/image/upload/", data)
.then(res => console.log(res))
.catch(err => console.log(err))
Ok I find the solution :
let data = {
file: 'data:image/jpg;base64,' + response.data,
upload_preset: "my_preset_name",
}
axios.post("https://api.cloudinary.com/v1_1/my_cloud_name/image/upload/", data)
.then(res => console.log(res))
.catch(err => console.log(err))