I would like to add my own custom behavior (server-side) to the closing tab(s) operation, so I think I should extend this method closeFile() of the
DocumentManager https://github.com/jupyterlab/jupyterlab/blob/master/packages/docmanager/src/manager.ts#L177.
I have a custom file browser plugin (extension) that works well if I use it with JupyterLab's core IDocumentManager but not if I use it with the extended/overwritten IMyDocumentManager like here:
const browserPlugin: JupyterLabPlugin<void> = {
id: "my:fs",
requires: [IMyDocumentManager, ISettingRegistry, IMainMenu],
activate: activateMyBrowser,
autoStart: true
};
My IMyDocumentManager looks like this:
import { IDocumentManager, DocumentManager } from '#jupyterlab/docmanager';
import { Token } from '#phosphor/coreutils';
export interface IMyDocumentManager extends IDocumentManager {}
export const IMyDocumentManager = new Token<IMyDocumentManager ('#jupyterlab/docmanager:IDocumentManager');
export class MyDocumentManager extends DocumentManager implements IMyDocumentManager {
closeFile(path: string): Promise<void> {
console.log("Test override a method for closing: " + path);
return super.closeFile(path);
}
}
When I load JupyterLab in the browser I get the error:
It's probably because I have to define the Token differently. Instead of new Token<IMyDocumentManager ('#jupyterlab/docmanager:IDocumentManager') I should use some other string than '#jupyterlab/docmanager:IDocumentManager' but I don't really know what. It's hard to infer from the PhosphorJS code.
Related
I am new prisma / nextjs user and I am trying to understand how to unit test an API route that uses prisma. I have read the unit testing guide.
I like the dependency injection approach and have started trying to implement it. However I am struggling with the following development issue. Can anybody help?
With the dependency injection approach the unit testing guide explains how to setup the mock context and use this in the data access layer. Does anyone have any examples of how and where the real context could be initialised and used with an API route that uses a repository pattern? Is it possible to expand the next.js api handler with middleware to include the context to facilitate testing?
import type { NextApiRequest, NextApiResponse } from 'next'
import { PublishRepository } from '../../../repository'
// PUT /api/publish/:id
export default async function handle(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method == 'PUT') {
const postId = req.query.id;
let repo = new PublishRepository( // where does the live context come from and how is it initialised??? )
const post = repo.set_published(postId)
res.json(post);
}
}
Repository - Initialised using Context instance - How is this initialise for development and how is it mocked?
import { Post, PrismaClient } from "#prisma/client"
import { Context } from "../context"
import prisma from "lib/prisma"
export class PublishRepository {
private prisma: PrismaClient
constructor(context: Context) {
this.prisma = context.prisma
}
async set_published(post_id: string | string[]): Promise<Post> {
return await prisma.post.update({
where: { id: Number(post_id) },
data: { published: true },
});
}
}
I’m looking for some help about custom validator & custom decorator in Nest.
FIRST CASE : working one
A DTO, with class-validator anotations :
import { IsNotEmpty, IsString } from 'class-validator';
import { IsOwnerExisting } from '../decorators/is-owner-existing.decorator';
export class CreatePollDto {
#IsNotEmpty()
#IsString()
#IsOwnerExisting() // custom decorator, calling custom validator, using a service to check in db
ownerEmail: string;
#IsNotEmpty()
#IsString()
#NotContains(' ', { message: 'Slug should NOT contain any whitespace.' })
slug: string;
}
I use it in a controller :
#Controller()
#ApiTags('/polls')
export class PollsController {
constructor(private readonly pollsService: PollsService) {}
#Post()
public async create(#Body() createPollDto: CreatePollDto): Promise<Poll> {
return await this.pollsService.create(createPollDto);
}
}
When this endpoint is called, the dto is validating by class-validator, and my custom validator works. If the email doesn’t fit any user in database, a default message is displayed.
That is how I understand it.
SECOND CASE : how to make it work ?
Now, I want to do something similar but in a nested route, with an ApiParam. I’d like to check with a custom validator if the param matches some object in database.
In that case, I can’t use a decorator in the dto, because the dto doesn’t handle the "slug" property, it’s a ManyToOne, and the property is on the other side.
// ENTITIES
export class Choice {
#ManyToOne((type) => Poll)
poll: Poll;
}
export class Poll {
#Column({ unique: true })
slug: string;
#OneToMany((type) => Choice, (choice) => choice.poll, { cascade: true, eager: true })
#JoinColumn()
choices?: Choice[];
}
// DTOs
export class CreateChoiceDto {
#IsNotEmpty()
#IsString()
label: string;
#IsOptional()
#IsString()
imageUrl?: string;
}
export class CreatePollDto {
#IsNotEmpty()
#IsString()
#NotContains(' ', { message: 'Slug should NOT contain any whitespace.' })
slug: string;
#IsOptional()
#IsArray()
#ValidateNested({ each: true })
#Type(() => CreateChoiceDto)
choices: CreateChoiceDto[] = [];
}
So where should I hook my validation ?
I’d like to use some decorator directly in the controller. Maybe it’s not the good place, I don’t know. I could do it in the service too.
#Controller()
#ApiTags('/polls/{slug}/choices')
export class ChoicesController {
constructor(private readonly choicesService: ChoicesService) {}
#Post()
#ApiParam({ name: 'slug', type: String })
async create(#Param('slug') slug: string, #Body() createChoiceDto: CreateChoiceDto): Promise<Choice> {
return await this.choicesService.create(slug, createChoiceDto);
}
}
As in my first case, I’d like to use something like following, but in the create method of the controller.
#ValidatorConstraint({ async: true })
export class IsSlugMatchingAnyExistingPollConstraint implements ValidatorConstraintInterface {
constructor(#Inject(forwardRef(() => PollsService)) private readonly pollsService: PollsService) {}
public async validate(slug: string, args: ValidationArguments): Promise<boolean> {
return (await this.pollsService.findBySlug(slug)) ? true : false;
}
public defaultMessage(args: ValidationArguments): string {
return `No poll exists with this slug : $value. Use an existing slug, or register one.`;
}
}
Do you understand what I want to do ? Is it feasible ? What is the good way ?
Thanks a lot !
If you're needing to validate the slug with your custom rules you have one of two options
make a custom pipe that doesn't use class-validator and does the validation directly in it.
Use #Param() { slug }: CreatePollDto. This assumes that everything will be sent via URL parameters. You could always make the DTO a simple one such as
export class SlugDto {
#IsNotEmpty()
#IsString()
#NotContains(' ', { message: 'Slug should NOT contain any whitespace.' })
slug: string;
}
And then use #Param() { slug }: SlugDto, and now Nest will do the validation via the ValidationPipe for you.
If it didn't work with you with service try to use
getConnection().createQueryBuilder().select().from().where()
I used it in custom decorator to make a isUnique and it works well, but niot with injectable service.
public async validate(slug: string, args: ValidationArguments): Promise<boolean> { return (await getConnection().createQueryBuilder().select(PollsEntityAlias).from(PollsEntity).where('PollsEntity.slug =:slug',{slug}))) ? true : false; }
That’s so greeat! Thanks a lot, it’s working.
I’ve tried something like that, but can’t find the good way.
The deconstructed { slug }: SlugDto, so tricky & clever ! I’ve tried slug : SlugDto, but it couldn’t work, I was like «..hmmm… how to do that… »
Just something else : in the controller method, I was using (as in documentation) #Param('slug'), but with the slugDto, it can’t work. Instead, it must be just #Param().
Finally, my method :
#Post()
#ApiParam({ name: 'slug', type: String })
public async create(#Param() { slug }: SlugDto, #Body() createChoiceDto: CreateChoiceDto): Promise<Choice> {
return await this.choicesService.create(slug, createChoiceDto);
}
And the dto :
export class SlugDto {
#IsNotEmpty()
#IsString()
#NotContains(' ', { message: 'Slug should NOT contain any whitespace.' })
#IsSlugMatchingAnyExistingPoll()
slug: string;
}
Personally, I wouldn't register this as a class-validator decorator, because these are beyond the scopes of Nestjs's dependency injection. Getting a grasp of a service/database connection in order to check the existence of a poll would be troublesome and messy from a validator constraint. Instead, I would suggest implementing this as a pipe.
If you want to only check if the poll exists, you could do something like:
#Injectable()
export class VerifyPollBySlugPipe implements PipeTransform {
constructor(#InjectRepository(Poll) private repository: Repository<Poll>) {}
transform(slug: string, metadata: ArgumentsMetadata): Promise<string> {
let found: Poll = await repository.findOne({
where: { slug }
});
if (!found) throw new NotFoundException(`No poll with slug ${slug} was found`);
return slug;
}
}
But, since you're already fetching the poll entry from the database, maybe you can give it a use in the service, so the same pipe can work to retrieve the entity and throw if not found. I answered a similar question here, you'd just need to add the throwing of the 404 to match your case.
Hope it helps, good luck!
Why we cant use an decorator within a NestJS service? Here is a example on how I tried to do, but it does not work.
Decorator: #User()
// user.decorator.ts
import { createParamDecorator } from '#nestjs/common';
export const User = createParamDecorator((data, req): {userId, email} => {
return data ? req.user[data] : req.user;
});
When I call this decorator into a service, I got this message: Unable to resolve signature of property decorator when called as an expression
// connect.service.ts
import { Injectable, Inject } from '#nestjs/common';
import { User } from '../account/user/user.decorator';
#Injectable()
export class ConnectService {
#User()
userInfo;
}
It looks like you are trying to add a decorator on an Injectable() I don't think you can do that. It would need to be on a method so that when it is called some magic can happen behind the scenes. Consider using class-validator and the validationPipe
For example:
#Get('vitalsByEncounterID')
async getVitalsByEncounterID(#Query() params: VitalsByEncounterPathDTO, #Headers(DFDHeaders.xRequestId) requestId: string): Promise<VitalSignsDTO[]> {}
Then you'd decorate the class
export class VitalsByEncounterPathDTO {
#IsString()
#IsNotEmpty()
#ApiModelProperty({ required: true, description: 'iCentra id for the patient' })
patientId: string;
#IsString()
#IsNotEmpty()
#ApiModelProperty({ required: true, description: 'an encounter id for the patient' })
encounterId: string;
}
You're trying to decorate a property with a ParamDecorator, that's why you get this error message.
Can you give some more details on your usecase? That would maybe help someone to give some insights on what you're trying to achieve.
I have the following types:
DataService - Gets data from the server using signalr hub.
AppComponent - which is the entry point for my main application
The data service constructor is as follows.
constructor(private http: Http) {
var hub = $.connection.spwHub;
hub.client.loadEmployees = this.loadEmployees;
$.connection.hub.start().done(() => {
...
});
}
My AppComponent is as follows:
constructor(service: DataService) {
this.company = service.getCompany();
service.getEmployees().then(employees => this.employees = employees);
this.departments = service.getDepartments();
}
I get the following error of course because the hub async call has not returned before the hub connection is made.
EXCEPTION: Error in ./AppComponent class AppComponent_Host - inline template:0:0 caused by: SignalR: Connection has not been fully initialized. Use .start().done() or .start().fail() to run logic after the connection has started.
What is the best way to deal with this issue in AngularJs2?
You can use the APP_INITIALIZER hook to perform logic, get something prepped, whatever, that you need before the rest of the application runs.
In your app.module.ts (or whatever your main module is):
import { APP_INITIALIZER, NgModule } from "#angular/core";
export function init_app(employeeService: EmployeeService) {
return () => employeeService.getEmployees();
}
#NgModule({
<...>
providers: [EmployeeService, {
provide: APP_INITIALIZER,
useFactory: init_app,
deps: [ EmployeeService ],
multi: true
}]
})
export class AppModule { }
The service is returning a Promise which will be automatically handled:
getEmployees() {
return <...function stuff ...>
.toPromise();
}
And here's the github issue where this is documented (no doc on the angular.io site yet): https://github.com/angular/angular/issues/9047
After searching and finding nothing I gave the idea that components that don't need to be loaded should probably be deferred by default. This means that the answer is a no-brainer.
// start.component.ts
constructor() {
// Start the connection
var hub = $.connection.spwHub;
$.connection.hub.start().done(() => {
// This loads the next component and runs the constructor
this.initialized = true;
});
}
// start.component.html
<div *ngIf="initialized">
<main-component></main-component>
<div>
// This type is lazy loaded as soon as the initialized equals true.
// main.component.ts
constructor(employeeService: EmployeeService) {
// Finally, load the needed data.
this.employees = employeeService.getEmployees();
}
I am trying to implement alanning Meteor-roles with react-router in my Meteor application. Everything is working fine except the fact I can't manage properly to restrict a route using alanning roles or Meteor.user()
I tried with meteor-roles:
I am trying to use the onEnter={requireVerified} on my route. This is the code:
const requireVerified = (nextState, replace) => {
if (!Roles.userIsInRole(Meteor.userId(), ['verified'],'user_default')) {
replace({
pathname: '/account/verify',
state: { nextPathname: nextState.location.pathname },
});
}
};
I tried with Meteor.user():
const requireVerified = (nextState, replace) => {
if (!Meteor.user().isverified == true) {
replace({
pathname: '/account/verify',
state: { nextPathname: nextState.location.pathname },
});
}
};
So this is working when I am clicking on a route link, but when i manually refresh (F5), it does not work. After digging into it, i have found that Meteor.user() is not ready when i manually refresh the page.
I know Meteor.userid() or Meteor.logginIn() are working, but i wanted
to verify not just that they are logged but if they are "verified" or
have a role.
I also tried to check inside the component with react, with componentDidMount() or componentWillMount(), in both cases it's the same, the manual fresh does not load Meteor.user() before the compenent is mounted.
So what is the best way to restrict components/routes with meteor/alaning roles + react router ? (I am using react-komposer inside TheMeteorChef's base)
Thank you.
Note I have not tried it yet, it's only a suggestion
One thing you could try is to use componentWillReceiveProps alongside createContainer from 'react-meteor-data' like that:
import React, { Component, PropTypes } from 'react';
import { Meteor } from 'meteor/meteor';
import { createContainer } from 'meteor/react-meteor-data';
import { Roles } from 'meteor/alanning:roles';
class MyComponent extends Component {
componentWillReceiveProps(nextProps) {
const { user } = nextProps;
if (user && !Roles.userIsInRole(user._id, ['verified'], 'user_default')) {
browserHistory.push('/account/verify');
}
// If Meteor.user() is not ready, this will be skipped.
}
}
MyComponent.propTypes = {
user: PropTypes.object,
};
export default createContainer(() => {
const user = Meteor.user() || null;
return { user };
}, MyComponent);
To explain the flow, when the page is loaded, as you said Meteor.user() is not defined so you can't check the permissions. However, when Meteor.user() gets defined, this will trigger a refresh of the template, and the new props will be passed to componentWillReceiveProps. At this moment you can check if user has been defined and redirect if needed.
To be really sure not to miss anything, I would actually put the verification in the constructor() as well (defining a function that takes the props as arguments and calling it in both constructor() and componentWillReceiveProps()).