英文:
TypeError: ImgurClient is not a constructor
问题
I have a project in svelte kit, vite and typescript. Part of the project is uploading images to imgur. For that task I use an unofficial library to connect to imgur. Here is the link:
https://github.com/KenEucker/imgur/tree/main
When I run npm run build
I get the following output:
.svelte-kit/output/server/chunks/Offcanvas.svelte_svelte_type_style_lang.js 5.40 kB
.svelte-kit/output/server/chunks/Register.js 6.19 kB
.svelte-kit/output/server/entries/pages/_page.svelte.js 8.41 kB
.svelte-kit/output/server/chunks/index.js 11.33 kB
.svelte-kit/output/server/chunks/Login.js 14.05 kB
.svelte-kit/output/server/entries/pages/_layout.svelte.js 18.48 kB
.svelte-kit/output/server/chunks/Portal.js 22.35 kB
.svelte-kit/output/server/index.js 76.62 kB
.svelte-kit/output/server/entries/pages/atlas/_page.svelte.js 615.65 kB
file:///C:/Users/marti/Documents/school/project/Olimpiada2023/svdemo/.svelte-kit/output/server/entries/pages/uploadPhoto/_page.server.ts.js:35
const client = new ImgurClient({
^
TypeError: ImgurClient is not a constructor
at file:///C:/Users/marti/Documents/school/project/Olimpiada2023/svdemo/.svelte-kit/output/server/entries/pages/uploadPhoto/_page.server.ts.js:35:16
at ModuleJob.run (node:internal/modules/esm/module_job:193:25)
at async Promise.all (index 0)
at async ESMLoader.import (node:internal/modules/esm/loader:530:24)
at async Promise.all (index 1)
at async prerender (file:///C:/Users/marti/Documents/school/project/Olimpiada2023/svdemo/node_modules/@sveltejs/kit/src/core/prerender/prerender.js:370:18)
[vite-plugin-sveltekit-compile] Prerendering failed with code 1
error during build:
Error: Prerendering failed with code 1
at ChildProcess.<anonymous> (file:///C:/Users/marti/Documents/school/project/Olimpiada2023/svdemo/node_modules/@sveltejs/kit/src/exports/vite/index.js:551:15)
at ChildProcess.emit (node:events:513:28)
at Process.ChildProcess._handle.onexit (node:internal/child_process:293:12)
Here is my uploadPhoto/+page.server.ts for reference:
import ImgurClient from 'imgur';
import type { PageServerLoad, Action, Actions } from './$types';
import { mssqlConnection } from '../../db/mssqldb';
import ppkg from 'mssql';
const { Request } = ppkg;
import { v4 as uuidv4 } from 'uuid';
import { fail, redirect } from '@sveltejs/kit';
let username: string;
export const load: PageServerLoad = async ({ locals }) => {
if (!locals.user) {
throw redirect(302, 'login');
} else {
username = locals.user.username;
if (process.env.NOVA_KEY) {
const sessionKey = await fetchAstrometrySessionKey(process.env.NOVA_KEY);
const data = await submitURL(sessionKey, 'http://apod.nasa.gov/apod/image/1206/ldn673s_block1123.jpg');
console.log(data);
const jobResult = await getJobResults(data)
if (jobResult.status === "success") {
console.log(jobResult.tags)
if (jobResult.tags.length) {
//post to 3d map
console.log("found stars");
const dataFor3dMap = await fetchData(jobResult.tags);
const maybeJson=JSON.stringify( dataFor3dMap)
console.log(maybeJson);
await fetch(`http://localhost:5173/atlas/api/findStars?dataMap={${maybeJson}},{method:'POST'}`);
} else {
//no stars found
fail(500, { error: false, noStars: true })
}
} else {
//display error
//ask the user to send the image again
fail(500, { error: true, noStars: true })
}
}
}
};
const client = new ImgurClient({
accessToken: process.env.TOKEN,
clientId: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
refreshToken: process.env.REFRESH_TOKEN
});
async function fetchData(starNames: object) {
let formData="";
let validStarNames = starNames.filter(starName => {
return starName.match(/^\w+\s+\d+.*$/g) || starName.startsWith("The star");
});
for(let starName in validStarNames){
formData+=await setStarNameAndCoordinates(validStarNames[starName],formData)
}
return formData;
}
async function setStarNameAndCoordinates(starName:string,formData:string) {
if (starName.startsWith("The star")) {
starName = starName.slice("The star".length).trim();
}
starName = starName.replace(/ /g, "+");
const res = await fetch("https://cds.unistra.fr/cgi-bin/nph-sesame?" + starName);
starName = starName.replace("+", " ");
const text = await res.text();
const row=getDataRow(text)
return `${starName}:${row}`
}
function getDataRow(text: string): string {
const lines = text.split("\n");
for (let line of lines) {
if (line.startsWith("%J")) {
let index = line.indexOf("=");
return line.slice(3, index).trim();
}
}
return "";
}
async function saveURL(url: string) {
const connection = await mssqlConnection();
const selectRequest = new Request(connection);
const selectResult = await selectRequest
.input('Username', username)
.query('SELECT Id FROM Users WHERE Username = @Username');
const id = selectResult.recordset[0].Id;
console.log(id);
const insertRequest = new Request(connection);
const insertResult = await insertRequest
.input('Id', uuidv4())
.input('UserId', id)
.input('ImageURL', url)
.query('INSERT INTO UsersImages(Id, UserId, ImageURL) VALUES(@Id, @UserId, @ImageURL)');
return insertResult === undefined;
}
async function uploadToUmgur(file: File) {
const buffer = Buffer.from(await file.arrayBuffer());
const base64 = buffer.toString('base64');
const response = await client.upload({
image: base64,
type: 'base64'
});
console.log(response.data);
return response.data;
}
<details>
<summary>英文:</summary>
I have a project in svelte kit, vite and typescript. Part of the project is uploading images to imgur. For that task I use an unofficial library to connect to imgur. Here is the link:
https://github.com/KenEucker/imgur/tree/main
When I run `npm run build` I get the following output:
.svelte-kit/output/server/chunks/Offcanvas.svelte_svelte_type_style_lang.js 5.40 kB
.svelte-kit/output/server/chunks/Register.js 6.19 kB
.svelte-kit/output/server/entries/pages/_page.svelte.js 8.41 kB
.svelte-kit/output/server/chunks/index.js 11.33 kB
.svelte-kit/output/server/chunks/Login.js 14.05 kB
.svelte-kit/output/server/entries/pages/_layout.svelte.js 18.48 kB
.svelte-kit/output/server/chunks/Portal.js 22.35 kB
.svelte-kit/output/server/index.js 76.62 kB
.svelte-kit/output/server/entries/pages/atlas/_page.svelte.js 615.65 kB
file:///C:/Users/marti/Documents/school/project/Olimpiada2023/svdemo/.svelte-kit/output/server/entries/pages/uploadPhoto/_page.server.ts.js:35
const client = new ImgurClient({
^
TypeError: ImgurClient is not a constructor
at file:///C:/Users/marti/Documents/school/project/Olimpiada2023/svdemo/.svelte-kit/output/server/entries/pages/uploadPhoto/_page.server.ts.js:35:16
at ModuleJob.run (node:internal/modules/esm/module_job:193:25)
at async Promise.all (index 0)
at async ESMLoader.import (node:internal/modules/esm/loader:530:24)
at async Promise.all (index 1)
at async prerender (file:///C:/Users/marti/Documents/school/project/Olimpiada2023/svdemo/node_modules/@sveltejs/kit/src/core/prerender/prerender.js:370:18)
[vite-plugin-sveltekit-compile] Prerendering failed with code 1
error during build:
Error: Prerendering failed with code 1
at ChildProcess.<anonymous> (file:///C:/Users/marti/Documents/school/project/Olimpiada2023/svdemo/node_modules/@sveltejs/kit/src/exports/vite/index.js:551:15)
at ChildProcess.emit (node:events:513:28)
at Process.ChildProcess._handle.onexit (node:internal/child_process:293:12)
here is my uploadPhoto/+page.server.ts for reference:
import ImgurClient from 'imgur';
import type { PageServerLoad, Action, Actions } from './$types';
import { mssqlConnection } from '../../db/mssqldb';
import ppkg from 'mssql';
const { Request } = ppkg;
import { v4 as uuidv4 } from 'uuid';
import { fail, redirect } from '@sveltejs/kit';
let username: string;
export const load: PageServerLoad = async ({ locals }) => {
if (!locals.user) {
throw redirect(302, 'login');
} else {
username = locals.user.username;
if (process.env.NOVA_KEY) {
const sessionKey = await fetchAstrometrySessionKey(process.env.NOVA_KEY);
const data = await submitURL(sessionKey, 'http://apod.nasa.gov/apod/image/1206/ldn673s_block1123.jpg');
console.log(data);
const jobResult = await getJobResults(data)
if (jobResult.status === "success") {
console.log(jobResult.tags)
if (jobResult.tags.length) {
//post to 3d map
console.log("found stars");
const dataFor3dMap = await fetchData(jobResult.tags);
const maybeJson=JSON.stringify( dataFor3dMap)
console.log(maybeJson);
await fetch(`http://localhost:5173/atlas/api/findStars?dataMap={${maybeJson}},{method:'POST'}`);
} else {
//no stars found
fail(500, { error: false, noStars: true })
}
} else {
//display error
//ask the user to send the image again
fail(500, { error: true, noStars: true })
}
}
}
};
const client = new ImgurClient({
accessToken: process.env.TOKEN,
clientId: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
refreshToken: process.env.REFRESH_TOKEN
});
async function fetchData(starNames: object) {
let formData="";
let validStarNames = starNames.filter(starName => {
return starName.match(/^\w+\s+\d+.*$/g) || starName.startsWith("The star");
});
for(let starName in validStarNames){
formData+=await setStarNameAndCoordinates(validStarNames[starName],formData)
}
return formData;
}
async function setStarNameAndCoordinates(starName:string,formData:string) {
if (starName.startsWith("The star")) {
starName = starName.slice("The star".length).trim();
}
starName = starName.replace(/ /g, "+");
const res = await fetch("https://cds.unistra.fr/cgi-bin/nph-sesame?" + starName);
starName = starName.replace("+", " ");
const text = await res.text();
const row=getDataRow(text)
return `${starName}:${row}`
}
function getDataRow(text: string): string {
const lines = text.split("\n");
for (let line of lines) {
if (line.startsWith("%J")) {
let index = line.indexOf("=");
return line.slice(3, index).trim();
}
}
return "";
}
async function saveURL(url: string) {
const connection = await mssqlConnection();
const selectRequest = new Request(connection);
const selectResult = await selectRequest
.input('Username', username)
.query('SELECT Id FROM Users WHERE Username = @Username');
const id = selectResult.recordset[0].Id;
console.log(id);
const insertRequest = new Request(connection);
const insertResult = await insertRequest
.input('Id', uuidv4())
.input('UserId', id)
.input('ImageURL', url)
.query('INSERT INTO UsersImages(Id, UserId, ImageURL) VALUES(@Id, @UserId, @ImageURL)');
return insertResult === undefined;
}
async function uploadToUmgur(file: File) {
const buffer = Buffer.from(await file.arrayBuffer());
const base64 = buffer.toString('base64');
const response = await client.upload({
image: base64,
type: 'base64'
});
console.log(response.data);
return response.data;
}
async function fetchAstrometrySessionKey(apikey: string) {
const response = await fetch('http://nova.astrometry.net/api/login', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: `request-json=${encodeURIComponent(JSON.stringify({ apikey }))}`
});
const data = await response.json();
if (data.status !== 'success') {
console.log('Could not obtain session key: ' + data.message);
}
return data.session;
}
async function submitURL(sessionId: string, url: string) {
const options = {
method: 'POST',
body: new URLSearchParams({
"request-json": JSON.stringify({
session: sessionId,
url: url,
scale_units: 'degwidth',
scale_lower: 0.5,
scale_upper: 1.0,
center_ra: 290,
center_dec: 11,
radius: 2.0
})
})
};
const response = await fetch('http://nova.astrometry.net/api/url_upload', options);
const result = await response.json();
if (result.status === 'success') {
console.log(`Successful submission: ${result.subid} with hash ${result.hash}`);
return result.subid;
} else {
console.error(result);
return null;
}
}
async function getJobResults(jobid: string) {
const response = await fetch(`https://nova.astrometry.net/api/jobs/${jobid}/info/`);
return await response.json();
}
const upload: Action = async ({ request }) => {
try {
if (request.method === 'POST') {
const form = await request.formData();
const image = form.get('img') as File;
console.log(form.get('img'));
if (image) {
console.log(`Received file with name: ${image.name}`);
const link = (await uploadToUmgur(image)).link;
console.log(link);
if (await saveURL(link)) {
return link;
} else {
fail(500, { error: true, noStars: false });
}
}
}
} catch (e) {
console.log(e);
}
};
export const actions: Actions = { upload };
In fewer words, I get error when I initialize the client variable:
const client = new ImgurClient({
accessToken: process.env.TOKEN,
clientId: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
refreshToken: process.env.REFRESH_TOKEN
});
The error I get is that ImgurClient is not a constructor. The code works when I run `npm run dev` and I get no errors.
--------EDIT-------
so my initial goal was to follow the https://vitejs.dev/guide/build.html#building-for-production
vite's tutorial, but as you already know, I get a lot of errors. After these errors I am starting to search for a solution where I host the site using npm run dev or something similar. Forgot to mention that this is my first time deploying and don't know anything about it.
------------NEW EDIT------------
After a research, I come up with a conclusion that this is just a bug with the library. I have changed the implementation to:
async function uploadToUmgur(file: File) {
const buffer = Buffer.from(await file.arrayBuffer());
const base64 = buffer.toString('base64');
let apiUrl = 'https://api.imgur.com/3/image';
const formData= new FormData();
formData.append("image",base64);
let link="";
await fetch(apiUrl,{
method:"post",
headers:{
Authorization: "Client-ID "+process.env.CLIENT_ID
},
body:formData
}).then(data => data.json()).then(data=>{
link =data.data.link;
})
return link;
}
so yeah, the lesson is:
not to follow unofficial libraries with little documentation
</details>
# 答案1
**得分**: 1
import { ImgurClient } from 'imgur';
您可以尝试这样写。
<details>
<summary>英文:</summary>
import ImgurClient from 'imgur';
You are importing the entire module here as one object
import { ImgurClient } from 'imgur';
Try this instead.
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论