Good day everyone!
I'm trying to deploy the first smart contracts according to the helloWorld manuals, but I'm getting an error please see the snippet. Tell me, please, what can be done about this? Tried lot of way to fix it but failed.
Thanks in advance!
import { Command } from ""commander"";
import prompts, { PromptObject } from ""prompts"";
import { isNumeric, Migration } from ""./utils"";
const program = new Command();
const migration = new Migration();
async function main() {
const promptsData: PromptObject[] = [];
program
.allowUnknownOption()
.option(""-kn, --key_number <key_number>"", ""Public key number"")
.option(
""-b, --balance <balance>"",
""Initial balance in EVERs (will send from Giver)"",
);
program.parse(process.argv);
const options = program.opts();
if (!options.key_number) {
promptsData.push({
type: ""text"",
name: ""keyNumber"",
message: ""Public key number"",
validate: value => (isNumeric(value) ? true : ""Invalid number""),
});
}
if (!options.balance) {
promptsData.push({
type: ""text"",
name: ""balance"",
message: ""Initial balance (will send from Giver)"",
validate: value => (isNumeric(value) ? true : ""Invalid number""),
});
}
const response = await prompts(promptsData);
const keyNumber = +(options.key_number || response.keyNumber);
const balance = +(options.balance || response.balance);
const signer = (await locklift.keystore.getSigner(keyNumber.toString()))!;
let accountsFactory = locklift.factory.getAccountsFactory(""Account"");
const { account: Account } = await accountsFactory.deployNewAccount({
publicKey: signer.publicKey,
initParams: {
_randomNonce: locklift.utils.getRandomNonce(),
},
constructorParams: {},
value: locklift.utils.toNano(balance),
});
migration.store(Account, ""account"");
console.log(`Account deployed at: ${Account.address}`);
}
main()
.then(() => process.exit(0))
.catch(e => {
console.log(e);
process.exit(1);
});"
Crashes on an attempt to collect Account contract assembly artefacts
There is no such thing in the build folder!
I want to create a simple Nuxt 3 file upload implementation that stores the file in the locally in a folder in the Nuxt project. In PHP the server side code is very easy and straight forward but I am finding it difficult doing the same thing in Nuxt 3 server side.
First:
npm install formidable
second:
define formidable in Nuxt config file inside modules list.
export default defineNuxtConfig({
modules: ["formidable"],
});
then in your handler for example upload.post.js :
import formidable from "formidable";
import fs from "fs";
import path from "path";
export default defineEventHandler(async (event) => {
let imageUrl = "";
let oldPath = "";
let newPath = "";
const form = formidable({ multiples: true });
const data = await new Promise((resolve, reject) => {
form.parse(event.req, (err, fields, files) => {
if (err) {
reject(err);
}
if (!files.photo) {
resolve({
status: "error",
message: "Please upload a photo with name photo in the form",
});
}
if (files.photo.mimetype.startsWith("image/")) {
let imageName =
Date.now() +
Math.round(Math.random() * 100000) +
files.photo.originalFilename;
oldPath = files.photo.filepath;
newPath = `${path.join("public", "uploads", imageName)}`;
imageUrl = "./public/upload/" + imageName;
fs.copyFileSync(oldPath, newPath);
resolve({
status: "ok",
url: imageUrl,
});
} else {
resolve({
status: "error",
message: "Please upload nothing but images.",
});
}
});
});
return data;
});
don't forget to name the input field "photo" in the client side or change it here in every "files.photo".
ALso the path of uploaded photos will be in public/uploads directory you can change it too if you like in "path.join" method.
Good luck
I am trying to upload multiple files with nestjs using the fastify adapter. I can do so following the tutorial in this link -article on upload
Now this does the job of file upload using fastify-multipart, but I couldnt make use of the request validations before uploading,
for example, here is my rule-file-models (which later I wanted to save to postgre)
import {IsUUID, Length, IsEnum, IsString, Matches, IsOptional} from "class-validator";
import { FileExtEnum } from "./enums/file-ext.enum";
import { Updatable } from "./updatable.model";
import {Expose, Type} from "class-transformer";
export class RuleFile {
#Expose()
#IsUUID("4", { always: true })
id: string;
#Expose()
#Length(2, 50, {
always: true,
each: true,
context: {
errorCode: "REQ-000",
message: `Filename shouldbe within 2 and can reach a max of 50 characters`,
},
})
fileNames: string[];
#Expose()
#IsEnum(FileExtEnum, { always: true, each: true })
fileExts: string[];
#IsOptional({each: true, message: 'File is corrupated'})
#Type(() => Buffer)
file: Buffer;
}
export class RuleFileDetail extends RuleFile implements Updatable {
#IsString()
#Matches(/[aA]{1}[\w]{6}/)
recUpdUser: string;
}
And I wanted to validate the multipart request and see if these are set properly.
I cannot make it to work with event subscription based approach. Here are a few things I tried - adding the interceptor, to check for the request
#Injectable()
export class FileUploadValidationInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const req: FastifyRequest = context.switchToHttp().getRequest();
console.log('inside interceptor', req.body);
// content type cmes with multipart/form-data;boundary----. we dont need to valdidate the boundary
// TODO: handle split errors based on semicolon
const contentType = req.headers['content-type'].split(APP_CONSTANTS.CHAR.SEMI_COLON)[0];
console.log(APP_CONSTANTS.REGEX.MULTIPART_CONTENT_TYPE.test(contentType));
const isHeaderMultipart = contentType != null?
this.headerValidation(contentType): this.throwError(contentType);
**// CANNOT check fir req.file() inside this, as it throws undefined**
return next.handle();
}
headerValidation(contentType) {
return APP_CONSTANTS.REGEX.MULTIPART_CONTENT_TYPE.test(contentType) ? true : this.throwError(contentType);
}
throwError(contentType: string) {
throw AppConfigService.getCustomError('FID-HEADERS', `Request header does not contain multipart type:
Provided incorrect type - ${contentType}`);
}
}
I wasnt able to check req.file() in the above interceptor. It throws as undefined. I tried to follow the fastify-multipart
But I wasnt able to get the request data in a prehandler as provided in the documentation for fastify-multipart
fastify.post('/', async function (req, reply) {
// process a single file
// also, consider that if you allow to upload multiple files
// you must consume all files othwise the promise will never fulfill
const data = await req.file()
data.file // stream
data.fields // other parsed parts
data.fieldname
data.filename
data.encoding
data.mimetype
// to accumulate the file in memory! Be careful!
//
// await data.toBuffer() // Buffer
//
// or
await pump(data.file, fs.createWriteStream(data.filename))
I tried getting via by registering a prehandler hook of my own like this (executed as iife)
(async function bootstrap() {
const appConfig = AppConfigService.getAppCommonConfig();
const fastifyInstance = SERVERADAPTERINSTANCE.configureFastifyServer();
// #ts-ignore
const fastifyAdapter = new FastifyAdapter(fastifyInstance);
app = await NestFactory.create<NestFastifyApplication>(
AppModule,
fastifyAdapter
).catch((err) => {
console.log("err in creating adapter", err);
process.exit(1);
});
.....
app.useGlobalPipes(
new ValidationPipe({
errorHttpStatusCode: 500,
transform: true,
validationError: {
target: true,
value: true,
},
exceptionFactory: (errors: ValidationError[]) => {
// send it to the global exception filter\
AppConfigService.validationExceptionFactory(errors);
},
}),
);
app.register(require('fastify-multipart'), {
limits: {
fieldNameSize: 100, // Max field name size in bytes
fieldSize: 1000000, // Max field value size in bytes
fields: 10, // Max number of non-file fields
fileSize: 100000000000, // For multipart forms, the max file size
files: 3, // Max number of file fields
headerPairs: 2000, // Max number of header key=>value pairs
},
});
(app.getHttpAdapter().getInstance() as FastifyInstance).addHook('onRoute', (routeOptions) => {
console.log('all urls:', routeOptions.url);
if(routeOptions.url.includes('upload')) {
// The registration actually works, but I cant use the req.file() in the prehandler
console.log('###########################');
app.getHttpAdapter().getInstance().addHook('preHandler', FilePrehandlerService.fileHandler);
}
});
SERVERADAPTERINSTANCE.configureSecurity(app);
//Connect to database
await SERVERADAPTERINSTANCE.configureDbConn(app);
app.useStaticAssets({
root: join(__dirname, "..", "public"),
prefix: "/public/",
});
app.setViewEngine({
engine: {
handlebars: require("handlebars"),
},
templates: join(__dirname, "..", "views"),
});
await app.listen(appConfig.port, appConfig.host, () => {
console.log(`Server listening on port - ${appConfig.port}`);
});
})();
Here is the prehandler,
export class FilePrehandlerService {
constructor() {}
static fileHandler = async (req, reply) => {
console.log('coming inside prehandler');
console.log('req is a multipart req',await req.file);
const data = await req.file();
console.log('data received -filename:', data.filename);
console.log('data received- fieldname:', data.fieldname);
console.log('data received- fields:', data.fields);
return;
};
}
This pattern of registring and gettin the file using preHandler works in bare fastify application. I tried it
Bare fastify server:
export class FileController {
constructor() {}
async testHandler(req: FastifyRequest, reply: FastifyReply) {
reply.send('test reading dne');
}
async fileReadHandler(req, reply: FastifyReply) {
const data = await req.file();
console.log('field val:', data.fields);
console.log('field filename:', data.filename);
console.log('field fieldname:', data.fieldname);
reply.send('done');
}
}
export const FILE_CONTROLLER_INSTANCE = new FileController();
This is my route file
const testRoute: RouteOptions<Server, IncomingMessage, ServerResponse, RouteGenericInterface, unknown> = {
method: 'GET',
url: '/test',
handler: TESTCONTROLLER_INSTANCE.testMethodRouteHandler,
};
const fileRoute: RouteOptions = {
method: 'GET',
url: '/fileTest',
preHandler: fileInterceptor,
handler: FILE_CONTROLLER_INSTANCE.testHandler,
};
const fileUploadRoute: RouteOptions = {
method: 'POST',
url: '/fileUpload',
preHandler: fileInterceptor,
handler: FILE_CONTROLLER_INSTANCE.fileReadHandler,
};
const apiRoutes = [testRoute, fileRoute, fileUploadRoute];
export default apiRoutes;
Could someone let me know the right the way to get the fieldnames , validate them befr the service being called in Nestjs
Well, I have done something like this and It works great for me. Maybe it can work for you too.
// main.ts
import multipart from "fastify-multipart";
const app = await NestFactory.create<NestFastifyApplication>(
AppModule,
new FastifyAdapter(),
);
app.register(multipart);
// upload.guard.ts
import {
Injectable,
CanActivate,
ExecutionContext,
BadRequestException,
} from "#nestjs/common";
import { FastifyRequest } from "fastify";
#Injectable()
export class UploadGuard implements CanActivate {
public async canActivate(ctx: ExecutionContext): Promise<boolean> {
const req = ctx.switchToHttp().getRequest() as FastifyRequest;
const isMultipart = req.isMultipart();
if (!isMultipart)
throw new BadRequestException("multipart/form-data expected.");
const file = await req.file();
if (!file) throw new BadRequestException("file expected");
req.incomingFile = file;
return true;
}
}
// file.decorator.ts
import { createParamDecorator, ExecutionContext } from "#nestjs/common";
import { FastifyRequest } from "fastify";
export const File = createParamDecorator(
(_data: unknown, ctx: ExecutionContext) => {
const req = ctx.switchToHttp().getRequest() as FastifyRequest;
const file = req.incomingFile;
return file
},
);
// post controller
#Post("upload")
#UseGuards(UploadGuard)
uploadFile(#File() file: Storage.MultipartFile) {
console.log(file); // logs MultipartFile from "fastify-multipart"
return "File uploaded"
}
and finally my typing file
declare global {
namespace Storage {
interface MultipartFile {
toBuffer: () => Promise<Buffer>;
file: NodeJS.ReadableStream;
filepath: string;
fieldname: string;
filename: string;
encoding: string;
mimetype: string;
fields: import("fastify-multipart").MultipartFields;
}
}
}
declare module "fastify" {
interface FastifyRequest {
incomingFile: Storage.MultipartFile;
}
}
So I found a simpler alternative. I started using fastify-multer. I used it along with this awesome lib - which made me use the multer for fastify - #webundsoehne/nest-fastify-file-upload
These are the changes I made. I registered the multer content process.
app.register(multer( {dest:path.join(process.cwd()+'/upload'),
limits:{
fields: 5, //Number of non-file fields allowed
files: 1,
fileSize: 2097152,// 2 MB,
}}).contentParser);
Then in the controller - I use it as the nestjs doc says . This actually makes fasitfy work with multer
#UseInterceptors(FileUploadValidationInterceptor, FileInterceptor('file'))
#Post('/multerSample')
async multerUploadFiles(#UploadedFile() file, #Body() ruleFileCreate: RuleFileCreate) {
console.log('data sent', ruleFileCreate);
console.log(file);
// getting the original name of the file - no matter what
ruleFileCreate.originalName = file.originalname;
return await this.fileService.fileUpload(file.buffer, ruleFileCreate);
}
BONUS - storing the file in local and storing it in DB - Please refer
github link
I am trying to learn react native and how to download files to the device. I know you can do this with react native file system but that does not support authentication which I need. React native fetch blob does support this.
For education purposes, I want to have the code from the first answer to this question recreated in react native fetch blob instead of react native file system.
I someone could write sutch an examlple form me I would be super tankfull.
Question: Downloading data files with React Native for offline use
Try this, it's work fine on Android:
export const download = (url, name) => {
const { config, fs } = RNFetchBlob;
let PictureDir = fs.dirs.PictureDir;
let options = {
fileCache: true,
addAndroidDownloads: {
useDownloadManager: true,
notification: true,
path: PictureDir + name,
description: t('downloading_file')
}
};
config(options)
.fetch('GET', url)
.then(res => {
if (res.data) {
alert(t('download_success'));
} else {
alert(t('download_failed'));
}
});
};
downloadImage(){
var date = new Date();
var url = "http://debasish.com/image.jpg";
var ext = this.getExtention(url);
ext = "."+ext[0];
const { config, fs } = RNFetchBlob ;
let PictureDir = fs.dirs.PictureDir
let options = {
fileCache: true,
addAndroidDownloads : {
useDownloadManager : true,
notification : true,
path: PictureDir + "/image_"+Math.floor(date.getTime()
+ date.getSeconds() / 2)+ext,
description : 'Image'
}
}
config(options).fetch('GET', url).then((res) => {
Alert.alert("Download Success !");
});
}
getExtention(filename){
return (/[.]/.exec(filename)) ? /[^.]+$/.exec(filename) :
undefined;
}
I working on backend written in flask that returns REST API for various task, one of which is to request deployment,
Then log gets filled in the database. So I have created another REST API endpoint to return log message for the specific request id. Now what I want is to once the showStatus is true the log_url used by axios.get should be constantly hitting and retrieving data from the backend endpoint retrieving data after 30 seconds. and show it in the show below as statusMessage.
<script>
import Vue from 'vue';
import axios from "axios";
import Multiselect from "vue-multiselect";
Vue.component("multiselect", Multiselect);
export default {
name: 'SelectServices',
data: function() {
return {
selectedService: "",
services: [],
updateExisting: "",
showStatus: false,
statusMessage : ""
}
},
mounted() {
console.log("running script");
},
methods : {
selectServiceToDeploy: function(){
// alert("micro services");
},
deploySelected: function(){
this.showStatus = true ;
// animate open the status window.
$("#status_update").animate({height: '500'})
var url = "http://localwebsite.com:5060/services/request_deploy";
axios.post(url)
.then(response => {
if (typeof response.data.reason != "undefined"){
alert("Recieved Status: " + response.data.status + ",\nReason: " + response.data.reason);
}
var req_id = response.data.result.request_id;
this.statusMessage = "Initiating deployment of Services for Request ID: " + req_id ;
var log_url = "http://localwebsite.com:5060/services/get_logs/" + req_id;
axios.get(log_url)
.then(response => {
if (response.data.status == "success"){
this.statusMessage = this.statusMessage + response.data.logs;
}
})
})
.catch((err) => {
console.log("Error happened: " + err.request.message);
alert(err);
return Promise.reject(err);
})
console.log(url);
console.log(log_url);
}
}
}
based on the above logic I have written in vue it successfully request for deployment but the logs don't get printed in the UI! how can I constantly retrieve data from http://localwebsite.com:5060/services/get_logs/" + req_id after every 30 seconds.
You can do something in the mounted hook:
mounted(){
this.interval = setInterval(() => {
axios.get(this.my_url).then(res => { /* do something */});
}, 30000 );
},
data(){
return {
interval: undefined,
my_url: undefined
}
}
setInterval is a javascript function that allow you to run a function every predefined milliseconds. You can cancel it later with the following command: clearInterval(this.interval). You can also change my_url when you want :)