Shopify Template webhookHandlers Error Before Doing Anything - javascript

I have been trying to learn the basics of building a app for shopify. However I am running in to the issue that right from creating the template in my index.js file. I am not sure what is causing this error as I literally just created the app and have not edited any of the code or added anything. Any help on this would be appreciated, since this is a completely new skill I'm working on learning.
The error I am getting is:
Type '{ CUSTOMERS_DATA_REQUEST: { deliveryMethod: DeliveryMethod; callbackUrl: string; callback: (topic: any, shop: any, body: any, webhookId: any) => Promise<void>; }; CUSTOMERS_REDACT: { ...; }; SHOP_REDACT: { ...; }; }' is not assignable to type 'WebhookHandlersParam'.
Property 'CUSTOMERS_DATA_REQUEST' is incompatible with index signature.
Type '{ deliveryMethod: DeliveryMethod; callbackUrl: string; callback: (topic: any, shop: any, body: any, webhookId: any) => Promise<void>; }' is not assignable to type 'WebhookHandler | WebhookHandler[]'.
Type '{ deliveryMethod: DeliveryMethod; callbackUrl: string; callback: (topic: any, shop: any, body: any, webhookId: any) => Promise<void>; }' is not assignable to type 'HttpWebhookHandler'.
Types of property 'deliveryMethod' are incompatible.
Type 'DeliveryMethod' is not assignable to type 'DeliveryMethod.Http'.
index.js
// #ts-check
import { join } from "path";
import { readFileSync } from "fs";
import express from "express";
import serveStatic from "serve-static";
import shopify from "./shopify.js";
import productCreator from "./product-creator.js";
import GDPRWebhookHandlers from "./gdpr.js";
const PORT = parseInt(process.env.BACKEND_PORT || process.env.PORT, 10);
const STATIC_PATH =
process.env.NODE_ENV === "production"
? `${process.cwd()}/frontend/dist`
: `${process.cwd()}/frontend/`;
const app = express();
// Set up Shopify authentication and webhook handling
app.get(shopify.config.auth.path, shopify.auth.begin());
app.get(
shopify.config.auth.callbackPath,
shopify.auth.callback(),
shopify.redirectToShopifyOrAppRoot()
);
app.post(
shopify.config.webhooks.path,
shopify.processWebhooks({ webhookHandlers: GDPRWebhookHandlers })
);
// All endpoints after this point will require an active session
app.use("/api/*", shopify.validateAuthenticatedSession());
app.use(express.json());
app.get("/api/products/count", async (_req, res) => {
const countData = await shopify.api.rest.Product.count({
session: res.locals.shopify.session,
});
res.status(200).send(countData);
});
app.get("/api/products/create", async (_req, res) => {
let status = 200;
let error = null;
try {
await productCreator(res.locals.shopify.session);
} catch (e) {
console.log(`Failed to process products/create: ${e.message}`);
status = 500;
error = e.message;
}
res.status(status).send({ success: status === 200, error });
});
app.use(serveStatic(STATIC_PATH, { index: false }));
app.use("/*", shopify.ensureInstalledOnShop(), async (_req, res, _next) => {
return res
.status(200)
.set("Content-Type", "text/html")
.send(readFileSync(join(STATIC_PATH, "index.html")));
});
app.listen(PORT);

Related

Accessing the TypeORM Entity (MYSQL Table) in TypeScript

index.ts
import express, { Express } from 'express';
import dotenv from 'dotenv';
import { DataSource } from 'typeorm';
import cors from 'cors';
import bodyParser from 'body-parser';
import { Task } from './src/tasks/tasks.entity';
import { tasksRouter } from './src/tasks/tasks.router';
// Instantiate express app
const app: Express = express();
dotenv.config();
//Parsing incoming request
app.use(bodyParser.json());
//Use CORS install types as well
app.use(cors());
// Create Databse Connection
export const AppDataSource = new DataSource({
type: 'mysql',
host: 'localhost',
port: 3306,
username: process.env.MYSQL_USER,
password: process.env.MYSQL_PASSWORD,
database: process.env.MYSQL_DB,
entities: [Task],
synchronize: true,
logging: true,
});
//Define Server Port
const port = process.env.PORT;
AppDataSource.initialize()
.then(() => {
// Start listening Request on defined port
app.listen(port);
console.log('Data Source has been initialized');
})
.catch((err) => console.log(err));
//create a Route
app.use('/', tasksRouter);
tasks.router.ts
import { Request, Response, Router } from 'express';
import { validationResult } from 'express-validator';
import { tasksController } from './tasks.controller';
import { createValidator } from './tasks.validator';
export const tasksRouter: Router = Router();
tasksRouter.get('/tasks', tasksController.getAll);
tasksRouter.post(
'/tasks',
createValidator,
// eslint-disable-next-line #typescript-eslint/ban-ts-comment
//#ts-ignore
async (req: Request, res: Response) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res
.json({
errors: errors.array(),
})
.status(400);
}
},
);
tasks.controller.ts
import { AppDataSource } from '../../index';
import { Task } from './tasks.entity';
import { instanceToPlain } from 'class-transformer';
import { Request, Response } from 'express';
class TasksController {
constructor(private taskRepository = AppDataSource.getRepository(Task)) {}
// eslint-disable-next-line #typescript-eslint/ban-ts-comment
//#ts-ignore
public async getAll(req: Request, res: Response): Promise<Response> {
let allTasks: Task[];
try {
allTasks = await this.taskRepository.find({
order: {
date: 'ASC',
},
});
allTasks = instanceToPlain(allTasks) as Task[];
res.json(allTasks).status(200);
} catch (_errors) {
return res.json({ error: 'Internal Server Error' }).status(500);
}
}
}
export const tasksController = new TasksController();
Hi everyone, I wish you all a very Happy New Year.
I have a question, While accessing the Task Entity, I have been getting error in the tasks.controller.ts file and
TypeError: Cannot read properties of undefined (reading
'getRepository')
What can be the actual Issue? What difference soes it make if I Instantiate the class in tasks.controller.ts file instead of the tasks.router.ts file? coz it is working if I Instantiate the TasksController class inside the route

Nuxt 3 server router does not response

I have followed the documentation of "Advanced usage" https://v3.nuxtjs.org/guide/features/server-routes#advanced-usage-examples
Now i tried it out:
My folder is structured like this:
server\api\global.ts
Here is my file global.ts
import { createRouter } from "h3";
const router = createRouter();
router.get("/", () => "Hello World");
export default router;
Now i try to fetch some data:
export const Bloggy = {
login({ password, username }: LoginParameterI) {
return $fetch("/api/global", {
method: "GET",
});
},
};
interface LoginParameterI {
password: string;
username: string;
}
Now when i try to fetch some data, i receive an error:
[nuxt] [request error] Invalid lazy handler result. It should be a function
I wanted to use it with router, because i want to use certain middlewares for certain routes. In the nuxt documentation the middlewares will get triggered on every route
What am i doing wrong?

How can i upload an image with graphql-upload

I tried uploading a file to a graphql server that has graphql-tool. I have set up the request multipart specification and I use Altair graphql client to make a request to the graphql endpoint.
I get the error SyntaxError: Unexpected token - in JSON at position 0
I do not know what I am doing incorrectly. Please help me out.
Below is my code
const graphqlHTTP = require('express-graphql');
const { graphqlUploadExpress } = require('graphql-upload');
const { makeExecutableSchema } = require('#graphql-tools/schema');
const schema = makeExecutableSchema({
typeDefs,
resolvers
});
app.use("/graphql",
graphqlUploadExpress({ maxFileSize: 10000000, maxFiles: 10 }),
graphqlHTTP((req, res) => ({
schema,
graphiql: true,
context: {
accessToken: req.header("accessToken"),
authFunction: jwtAuthentication
},
tracing: true
})))
in my resolver, I included GraphQLUpload
module.exports = {
Upload: GraphQLUpload,
Query: {
},
Mutation: {
ChangeBusinesslogo: async (parent, { file }, context, info)=> {
//
},
}
}
In my type definition, I have
scalar Upload
type File {
id: ID!
path: String!
filename: String!
mimetype: String!
encoding: String!
}
type Mutation {
ChangeBusinesslogo(file: Upload!): File
}
I use altair graphql-client but I get this error
SyntaxError: Unexpected token - in JSON at position 0
I do not know what I am not doing correctly. Please help me out

Custom error handler in express.js is not called

I am setting up a simple express.js node server, and I can't seem to get my custom error handler to work. It seems like it isn't being called at all and instead some default express.js error handler is being called.
Note that this is in typescript, and uses mongodb, if that matters (don't think it should). Here is the relevant code:
index.ts:
import routes from './routes/index.ts';
import express, { Request, Response, NextFunction } from 'express';
// other imports...
type ServerErrror = {
status: number;
message: string;
}
const app = express();
// set up logging...
app.use(bodyParser.json());
app.use('/', routes);
app.use((err: ServerError, req: Request, res: Response, next: NextFunction) => { // eslint-disable-line no-unused-vars
console.error('in error handler');
res.status(err.status).send(`got error: ${err.message}`);
});
mongoose.connect(MONGODB_URI)
.then(() => {
console.log('Successfully connected to database.');
app.listen(SERVER_PORT, () => {
console.log(`Server is up and running on port ${SERVER_PORT}`);
}).on('error', error => {
console.log('Error starting server:', error);
});
}, error => {
console.log('Error connecting to database:', error);
});
routes/index.ts:
import { Router } from 'express';
import dataRoutes from './data.ts';
const router = Router();
router.use('/data', dataRoutes);
export default router;
routes/data.ts:
import { Router } from 'express';
import Data from './models/Data';
const router = Router();
router.get('/', (_, res, next) => {
Data.find((error, data) => {
if (error) {
console.log('found an error')
next({ status: 500, message: 'got an error' });
return;
}
res.send(`Got data: ${JSON.stringify(data.map(datum => datum.toJSON()))}`);
});
});
export default router;
When I start the server and then send a GET request to the /data endpoint using postman, this is the output on the server:
Successfully connected to database.
Server is up and running on port 1234
found an error
GET /data 500 35.289 ms - 142 // this is from morgan logging
[object Object] // no idea where this is coming from, i assume express default error handler
And this is the return value i see in postman:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>[object Object]</pre>
</body>
</html>
Again, not sure where this is coming from. I assume it must be the express default error handler.
There are some problems with your code:
import routes from './routes/index.ts' should not have the *.ts extension.
import dataRoutes from './data.ts'; should not have the *.ts extension.
ServerErrror has one too many letters.
Here is short example that works on my machine. I removed the Mongoose-related code and changed the sample so that it is easy to reproduce in a single file. A call to http://localhost:5000/data returns customErrorHandler > dataRoutes.get > Error, which is I think what you require.
import { Request, Response, NextFunction } from 'express';
import bodyParser = require('body-parser');
import express = require('express');
type ServerError = {
status: number;
message: string;
}
const dataRoutes = express.Router().get('/', (_, res, next) => {
setTimeout(() => { // mimic an asynchronous operation
const error = true;
if (error) {
next({ status: 500, message: 'dataRoutes.get > Error' });
return;
}
res.send('dataRoutes.get > Success');
}, 1000);
});
const routes = express.Router().use('/data', dataRoutes);
const app = express();
app.use(bodyParser.json());
app.use('/', routes);
app.use((err: ServerError, req: Request, res: Response, next: NextFunction) => {
res
.status(err.status)
.send(`customErrorHandler > ${err.message}`);
});
app.listen(5000);
console.log('Now listening on port 5000');
This is my tsconfig.json file:
{
"compilerOptions": {
"moduleResolution": "node",
"module": "commonjs",
"allowSyntheticDefaultImports": true
}
}
These are my package.json dependencies:
"devDependencies": {
"#types/express": "^4.16.1",
"typescript": "^3.4.1"
},
"dependencies": {
"express": "^4.16.4"
}
It turns out the problem was my use of babel-preset-minify which apparently did not transform the code correctly. Getting rid of this preset made the code work with no other modifications.
In my case, I disable babel-preset-minify option deadcode and work well.
{
"presets": [
[
"minify",
{
"deadcode": false
}
]
]
}

"fake path" issue using multer+angular 6

I spend the last 3 days to fix the problem , but i didnt figure out yet the issue.
Angular CLI: 6.0.8
Node: 8.11.2
OS: win32 x64
Angular: 6.0.6
multer. 1.3.1
my code at "childApi" using multer staff :
var store = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads');
},
filename: function (req, file, cb) {
cb(null, Date.now() + '.' + file.originalname);
}
});
var upload = multer({ storage: store , }).single('file');
router.post('/upload', function (req, res, next) {
upload(req, res, function (err) {
if (err) {
return console.log ('not working well')
}
//do all database record saving activity
return res.json({ originalname: req.file.originalname, uploadname: req.file.filename });
});
});
my code at "add-child" component using simple code :
import { Component, OnInit, Inject } from '#angular/core';
import { ActivatedRoute, Router } from '#angular/router';
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '#angular/material';
import { Child } from '../../models/child';
import { ChildService } from '../../services/child.service';
import {FileUploader } from 'ng2-file-upload';
const uri = 'http://localhost:3000/childApi/upload';
#Component({
selector: 'app-add-child',
templateUrl: './add-child.component.html',
styleUrls: ['./add-child.component.css']
})
export class AddChildComponent implements OnInit {
newChild = new Child;
uploader: FileUploader = new FileUploader({ url: uri });
attachmentList: any = [];
constructor(private childService: ChildService,
private route: ActivatedRoute,
private router: Router,
public dialogRef: MatDialogRef<AddChildComponent>,
#Inject(MAT_DIALOG_DATA) public data: any) {
this.uploader.onCompleteItem = (item: any, response: any, status: any, headers: any) => {
this.attachmentList.push(JSON.parse(response));
};
}
The problem is that after I upload the file to the folder "uploads"
,I want to display my new photo on the screen.
The console give me this error :
GET unsafe:C:\fakepath\child+thinking.jpg 0 ()
If someone help its will be amazing.
Thanks...
I figure out what to do , I just put this sentences inside my code at "add-child" component using :
this.uploader.onCompleteItem = (item: any, response: any, status: any, headers: any) => {
this.newChild.user_img = JSON.parse(response).uploadname;
this.attachmentList.push(JSON.parse(response));
};
}
As I understand from your post that you have doing a model named child inside your project so if you have can I take a look on it I will be grateful because I'm doing the same task except still getting the error:
Access to XMLHttpRequest at 'http://localhost:4000/file/upload' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
core.js:1449 ERROR SyntaxError: Unexpected end of JSON input
at JSON.parse (<anonymous>)
at FileUploader.UploadFileComponent.uploader.onCompleteItem (upload-file.component.ts:27)
at FileUploader.push../node_modules/ng2-file-upload/file-upload/file-uploader.class.js.FileUploader._onCompleteItem (file-uploader.class.js:199)
at XMLHttpRequest.xhr.onerror [as __zone_symbol__ON_PROPERTYerror] (file-uploader.class.js:268)`
javascript html typescript angular6 multer

Categories