How to identify different handlebar templates? - html

I have several html files in my project which are templates to email messages, like email verification, password reset, etc...
I need to precompile these files and use them in the right place, for example, the email verification template must be sent in the registration function. The problem is how do I identify the templates to use them, given that I don't know from which type they are? How can I create some kind of identifier for the templates?

You can save your compiled templates in some data structure, returning it somehow and using it afterward.
Here down a sample based on your processing function and using Map as the data store:
export function preCompileTemplates(globString: string) {
const paths = getPathsFromGlob(globString)
const preCompiledTemplatesPs = paths.map(path => {
const templateName = path.substring(path.lastIndexOf('/') + 1, path.length - 5);
return fs.promises.readFile(path).then(template => {
return {name: templateName, content: Handlebars.precompile(template)}
})
})
const templates = new Map()
return Promises.all(preCompiledTemplatesPs, (preCompiledTemplates) => {
preCompiledTemplates.forEach(template => {
templates.set(template.name, template.content)
})
return templates
})
}

Related

Using async data for seo head elements in nuxt3

I am trying to create a site using data fetched from a directus instance.
Currently I have a layout component app.vue filling all seo meta tags using static default values hardcoded in that file.
So in the setup I am using:
useSeoMeta({
title: () => "Static title"
})
which is not creating the desired output. No title is rendered.
Also for a post component I want to overwrite the values from layout using data fetched from a remote source:
const { data: post, pending } = await useAsyncData('post', () => {
return getItemById({
collection: "collection_id",
filter: {
status: "published"
},
id: route.params.id,
}).then((data) => {
let ast = Markdoc.parse(data.content);
let transform = Markdoc.transform(ast);
data.content = Markdoc.renderers.html(transform);
useSeoMeta({
title: data.seo_title,
});
return data;
});
});
This is also not working as expected and serves different result, depending weather ssr is applied or not.
How would one implement a solution like this?

Firestore data() method does not exist on JSON parsed document after JSON stringified

I am building a FlashCard website using NextJs and firebase. I have a homepage which I want to render server side and so I am using getServerSideProps. InsidegetServerSideProps function, I am fetching all the documents of the current user from firestore and is stored in an array and is returned as props as below:
export const getServerSideProps = async(ctx: GetServerSidePropsContext) {
let notes: DocumentData[];
// fetch documents here and populate notes array like so [doc,doc,doc,..]
// data() method works here and returns document fields
console.log(notes[0].data());
// NextJs throws error "`object` ("[object Object]") cannot be serialized as JSON. Please only return JSON serializable data types.", so I have to JSON.stringify() the notes
return {
props: {
notes: JSON.stringify(notes),
}
}
}
Below, I have my homepage where I parse the JSON string and have access to the notes, but now the data() method on the document does not exist/works and throws method does not exist errors. If I have to access the document fields, I have to use the dot operator on every property of the document till I reach the fields property which is nested deep down in the object as follows:
export default function Home({ notes }) {
let docs = JSON.parse(notes); // can access notes
// data() method throws function does not exist error
console.log(docs[0].data());
// I am only able to access document fields as below
console.log(docs[0]._document.data.value.mapValue.fields);
return (
<Layout>
<HomeContent notes={docs}/>
</Layout>
);
}
I have searched everywhere and found nothing that helped me why data() method won't work. If I directly fetch the documents inside the page component on client side, the data() method on the document returns its' fields. I don't know how using JSON serializations affect it. I would always prefer to use data() method to access fields than to go that deep plus I am planning to fetch data on server on other pages as well.
I would really appreciate if you can shed some light on it. It took all of my days time.
EDIT: The code that gets notes from firestore:
// inside getServerSideProps
let notes: DocumentData[] = null;
const getNotes = async(ref: DocumentReference < DocumentData > , uid: string) => {
let tempNotes = [];
const categoriesSnapshot = await getDoc < DocumentData > (ref);
const categoriesObject = categoriesSnapshot.data();
// return if user doesn't have any documents
if (!categoriesObject) {
return;
}
const promises: [] = categoriesObject.categories.map((category: string) => {
const userCategoriesRef = collection(database, 'CategoryCollection', uid, category);
return getDocs(userCategoriesRef); // returns a promise
});
const allQuerySnapshots = await Promise.all < DocumentData > (promises);
allQuerySnapshots.forEach((querySnapshot) => {
tempNotes.push(...querySnapshot.docs);
});
notes = tempNotes;
}
const categoryDocRef = doc(database, "CategoryCollection", uid);
await getNotes(categoryDocRef, uid);

How can I loop through Nuxt.js generate routes to allow all my pages to render while using Woocommerce API?

Hello and thanks for the help in advance.
I'm trying to get my Nuxt app to automatically loop through my Woocommerce API automatically so it can generate the pages without much work.
How do I get the loop to function. Right now, I'm having issues and get a Nuxt Fatal Error:
TypeError: Cannot read property 'forEach' of undefined
Screenshot of Error + Code
I'm using Woocommerce API and, as you can see in the screenshot above, the Woocommerce code is imported into this code I need help with using a standard import.
import WooCommerce from './woocommerce.js';
generate: {
routes() {
WooCommerce.get("products").then((response) => {
let totalPages = response.headers['x-wp-totalpages'];
let page = 1;
while(page <= totalPages) {
WooCommerce.get("products", page).then((response) => {
response.data.map(product => {
return '/product/' + product.slug
});
})
page++;
}
})
}
},
You are not returning any routes in your routes function. Because of that, nuxt fails as it tries to iterate over them in a later step.
Assuming your way of accessing your API is correct, you would only need to add an array to which you push your routes and then return it.
I'm usually using async/await, which is why my code looks slightly different. It is a bit easier in this case I think.
// Declare the routes function asynchronous
async routes() {
const productsResponse = await WooCommerce.get('products');
const totalPages = productsResponse.headers['x-wp-totalpages'];
// Add an array to collect your routes
const routes = [];
let page = 1;
while (page <= totalPages) {
const pagesResponse = await WooCommerce.get('products', page);
// The 'map' function returns the routes for this set of pages
const productRoutes = pagesResponse.data.map((product) => {
return '/product/' + product.slug;
});
// Push your routes to the created array-
routes.push(...productRoutes);
page++;
}
// Return your routes
return routes;
};

React constant with parameters using square brackets

I'm new to React.
I have the code below with a function, but when I run it, it returns an error:
TypeError: renderJson[item.node] is not a function.
How can I fix the renderJson function?
export const readItem = item => {
printlog(item);
return renderJson[item.node](item);
};
const renderJson = {
"heading": item => <h1>{item.map(item => readItem(item))}</h1>
};
If you're trying to create a single React functional component that takes a JSON, and outputs the items in the JSON as a header, it would be more like this:
// If you're getting this JSON from an external source using something like a GET request, put the request inside a "useEffect()" hook
const myJson = {
"heading": ["My First Header", "My Second Header"]
};
export const Header = () => {
console.log(myJson);
return <h1>{myJson.heading.map(header => header}</h1>
};
I apologize if this is a misinterpretation of your question. If it is, any additional details would be helpful.

Is it possible to perform an action with `context` on the init of the app?

I'm simply looking for something like this
app.on('init', async context => {
...
})
Basically I just need to make to calls to the github API, but I'm not sure there is a way to do it without using the API client inside the Context object.
I ended up using probot-scheduler
const createScheduler = require('probot-scheduler')
module.exports = app => {
createScheduler(app, {
delay: false
})
robot.on('schedule.repository', context => {
// this is called on startup and can access context
})
}
I tried probot-scheduler but it didn't exist - perhaps removed in an update?
In any case, I managed to do it after lots of digging by using the actual app object - it's .auth() method returns a promise containing the GitHubAPI interface:
https://probot.github.io/api/latest/classes/application.html#auth
module.exports = app => {
router.get('/hello-world', async (req, res) => {
const github = await app.auth();
const result = await github.repos.listForOrg({'org':'org name});
console.log(result);
})
}
.auth() takes the ID of the installation if you wish to access private data. If called empty, the client will can only retrieve public data.
You can get the installation ID by calling .auth() without paramaters, and then listInstallations():
const github = await app.auth();
const result = github.apps.listInstallations();
console.log(result);
You get an array including IDs that you can in .auth().