How to autoload a relationship with Adonis with find or findOrFail? - adonis.js

Is there a way to autoload a relationship with findByOrFail (or any other method like find etc.)?
In the code below, the method with() is not defined.
async show({ params, response }) {
try {
return await Company.findByOrFail('domain', params.id).with('websites')
} catch (error) {
console.error(error)
switch (error.name) {
case 'ModelNotFoundException':
return response.notFound({ message: 'companies_show_not_found' })
default:
return response.badRequest({ message: 'something_went_wrong' })
}
}
}

Why not just do it with query like:
await Company.query().where('domain', params.id).with('websites').firstOrFail()

Adonis 5 has support for hooks which are run during a pre-defined life-cycle event.
So ideally you could do something like this.
class Company extends Model {
#hasMany()
public static websites: HasMany<typeof Website>
#beforeFetch()
#beforeFind()
public static fetchWebsites(query: ModelQueryBuilderContract<typeof Company>) {
query.preload('websites')
}
}
Then when you fetch the company, the results will include the relation.
Company.all()
{
'name': 'company_name',
'websites': [
{
'name': 'my site',
'url': 'my.site'
}
...
]
}

It looks like the cleanest solution is to use a globalScope.
class Company extends Model {
static boot() {
super.boot()
this.addGlobalScope(function (builder) {
builder.with('websites')
})
}
websites() {
return this.hasMany('App/Models/Website')
}
}

you can use relation like this
async show({ params, response }) {
try {
const relationdata= await Company.findByOrFail('domain', params.id)
return await relationdata.websites().fetch()
} catch (error) {
console.error(error)
switch (error.name) {
case 'ModelNotFoundException':
return response.notFound({ message: 'companies_show_not_found' })
default:
return response.badRequest({ message: 'something_went_wrong' })
}
}
}

Related

Svelte with Apollo GraphQl - Mutation is not getting triggered

I'm working with my own api and I can see it work if I use #urql/svelte but since we're using Apollo with React on most of our projects, I would like to see the differences between frameworks using the same dependency.
My lib/client.js looks like this:
import { ApolloClient, HttpLink, InMemoryCache } from '#apollo/client/core';
function createApolloClient() {
const httpLink = new HttpLink({
uri: 'MY_API'
});
const cache = new InMemoryCache();
const client = new ApolloClient({
httpLink,
cache
});
return client;
}
const client = new createApolloClient();
export default client;
My index.svelte is looking like this
<script>
import { setClient, mutation } from 'svelte-apollo';
import { gql } from '#apollo/client/core';
import { browser } from '$app/env';
import { onMount } from 'svelte';
import client from '../lib/client';
const email = 'AN_EMAIL';
const password = 'A_PASSWORD';
let userName;
let isLoggedIn = false;
setClient(client);
const SIGN_IN = gql`
mutation ($email: String!, $password: String!) {
userSignIn(email: $email, password: $password) {
email
id
isEnabled
name
surname
userType
}
}
`;
const signInMutation = mutation(SIGN_IN);
async function signInAction() {
await try {
signInMutation({ variables: { email, password } }).then((result) => console.log(result));
} catch (error) {
console.log(error);
}
}
const isUserLoggedIn = () => {
if (browser && localStorage.getItem('isLoggedIn') && localStorage.getItem('userName')) {
isLoggedIn = true;
userName = localStorage.getItem('userName');
}
};
onMount(() => {
isUserLoggedIn();
});
</script>
<button on:click={signInAction}>Trigger</button>
{#if isLoggedIn}
<h1>Welcome {userName}</h1>
{/if}
I honestly can't figure out what I'm missing with the Apollo setup.
I have no errors on my console and my network doesn't show anything when I click the button. The UI seems to work fine with the urql setup.
Could someone point me in the right direction? Thank you!
You have an issue in your client setup:
// ...
// const client = new createApolloClient(); // wrong use of 'new' keyword, createApolloClient() is a regular function, not a class constructor!
const client = createApolloClient();
// ...
As stated in my comment, you also have an issue in your signInAction function definition. You need to settle for one syntax:
// async/await
async function signInAction() {
try {
const result = await signInMutation({ variables: { email, password } });
console.log(result);
} catch (error) {
console.log(error);
}
}
// then/catch
function signInAction() {
signInMutation({ variables: { email, password } })
.then((result) => console.log(result))
.catch((error) => console.log(error));
}
Off-topic and opinionated: svelte-apollo radically differs from the react apollo client, is not an 'official' apollo client, and has not been updated for the past year+. You will be much better off going back to #urql/svelte.

How to return a callback's function return value

I'm using loopback-next along with the stripe api. In the stripe API, I call retrieve account as follows, in a payments.controller.ts file:
#post('/payments/retrieve-stripe/{id}', {
responses: {
'200': {
description: 'User model instance',
content: {'application/json': {schema: {'x-ts-type': User}}},
},
},
})
async retrieveStripe(#param.path.number('id') id: number,
#requestBody() req: any): Promise<any> {
console.log(req);
if (!req.stripeAccountId) {
throw new HttpErrors.NotFound('No Stripe Account');
}
else {
return await stripe.accounts.retrieve(
req.stripeAccountId,
function(err: any, account: any) {
return err ? err : account
})
}
}
However, when I try return account, nothing is returned in the JSON body. If i try, response.json on the front end, it said that the JSON unexpectedly finished, meaning there is nothing in the body. How would I be able to successfully return account in the above function inside of a controller function?
This was the same problem I had for trying to return a string as well. I'm not sure what to do.
EDIT: I learned that you cannot return variables in a callback and that is the issue.
You have to require type definitions (#types/stripe) to use its library in promise style. After that you can use in following way:-
#post('/payments/retrieve-stripe/{id}', {
responses: {
'200': {
description: 'User model instance',
content: { 'application/json': { schema: { type: 'object' } } },
},
},
})
async retrieveStripe(#param.path.number('id') id: number,
#requestBody() req: any): Promise<any> {
console.log(req);
if (!req.stripeAccountId) {
throw new HttpErrors.NotFound('No Stripe Account');
} else {
return await stripe.accounts.retrieve(req.stripeAccountId).then((res: any) => {
return res;
}).catch((err: any) => {
console.debug(err);
throw new HttpErrors.InternalServerError('Something went wrong!')
});
}
}
For more details https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/stripe/stripe-tests.ts

How to enter transaction callback in typeorm?

I'm kind of new in unit testing and trying to make some test with typeorm.
The code I've is this:
public executeTransaction(querys: IQueryTransaction[]) {
return getManager().transaction(async transactionalManager => {
for (const query of querys) {
await transactionalManager.query(query[0], query[1]);
}
});
}
I need to enter the transaction callBack but can't figured out how to do it. I tried to mock getManager and transaction playing with it, but with no results.
I'm using jest, typeorm and nest.
Someone knows how to do this?.
EDIT: Connecting to the database is not an option
I think you should try something like this...
return await getManager().transaction(async transactionalManager => {
for (const query of querys) {
await transactionalManager.query(query[0], query[1]);
}
});
OR
import {getManager} from "typeorm";
await getManager().transaction(async transactionalManager => {
await transactionalManager.save(users);
await transactionalManager.save(photos);
});
OR
#Controller("/user")
export class UserController {
constructor(
private userService: UserService,
) {}
#Post("/")
#Transaction()
async createNewUser(#Body() body: UserDTO) {
return await this.userService.createNewUser(body);
}
}
you can use Istambul to simplify your life.
/* istanbul ignore next */

How can i work with GraphQL Mutation?

how can i work with resolvers for mutations after i create type Mutations in graphql-yoga?
i've tried to create resolvers for mutations, but when i run in graph playground, i the code return error.
and here's my code:
const { GraphQLServer } = require('graphql-yoga')
// 1
const typeDefs = `
type Query {
users: [User!]!
user(id: ID!): User
}
type Mutation {
createUser(name: String!): User!
}
type User {
id: ID!
name: String!
}
`
// 2
const resolvers = {
Query: {
users: () => User,
},
Mutation: {
// WHAT SHOULD I WRITE IN HERE?
}
}
// 3
const server = new GraphQLServer({
typeDefs,
resolvers,
})
server.start(() => console.log(`Server is running on http://localhost:4000`))
if someone know how can i do for resolvers mutation, can shared with me?
thanks
Resolver for createUser can be defined as follows:
const resolvers = {
Query: {
// Query resolvers
},
Mutation: {
createUser: (parent, args) => {
// Business logic. Maybe save record in database
// Return created user. I am returning dummy data for now, so that you can test it in playground
return {id: 1, name: "John}
}
}
}
Finally it works for me.
i used this:
const resolvers = {
Query: {
users: () => User
},
Mutation: {
createUser: (source, {input}) => {
let newUser = [];
newUser.id = id;
newUser.name = input.name;
User.push(newUser);
return newUser;
}
}
}

EmberJS fulfill multiple nested promises

I want to return an array of objects. My code looks like this:
var apps = [];
this.get('groups').then(function(groups)
{
groups.forEach(function(group)
{
self.store.find('module', group.get('module').get('id')).then(function(module)
{
self.store.find('app', module.get('app').get('id')).then(function(app)
{
if(!apps.contains(app))
apps.pushObject(app);
});
});
});
});
I want to return all apps after foreach-loop is fulfilled, but I have no idea.
You must always return a promise to keep building the chain.
var self = this;
return this.get('groups')
// Return an app for each group
.then(function (groups) {
return Ember.RSVP.Promise.all(groups.map(function (group) {
return self.store.find('module', group.get('module.id'))
.then(function (module) {
return self.store.find('app', module.get('app.id'));
});
}));
})
// Filter out duplicates
.then(function (apps) {
return apps.uniq();
});