How do I set a filename for a json schema in serverless.ts - serverless-framework

So the typescript template now builds with a serverless.ts instead of YAML, which is cool - but there is a dearth of examples of how the format of the file works - specifically I'm struggling with the equivalent of yaml's:
request:
schema:
application/json: ${file(src/schema/login_request.json)}
what would x be below?
request: {
schema: {
'application/json': x
}
}

You just use Typescript's import.
import login_request from './src/schema/login_request.json'
// example how to use the value
const request: {
schema: {
'application/json': login_request
}
}

Related

Fastify equivalent of express-mongo-sanitize

Hello Fastify Experts,
In MongoDB queries I can pass various operators, which may risks the security aspect by having various attack surfaces.
So before sending the payload, I would like to sanitize the query/filters/sort etc. However I don't think I need to sanitize the request payload as such because Mongo will anyway store it as BSON, hence safer.
Now in Express world, we used to have the express-mongo-sanitize sort of plugin.
What open source plugin you propose for Fastify world to achieve the similar functionality?
Thanks,
Pradip
You have two options:
use the schema eviction: adding additionalProperties as flag into the input schema, will remove all the keys you did not expect from input
With this code, you can submit a payload with:
{
foo: 'hello',
$where: 'cut'
}
and the $where key will be removed.
const fastify = require('fastify')({ logger: true })
fastify.post('/', {
schema: {
body: {
type: 'object',
additionalProperties: false,
properties: {
foo: { type: 'string' }
}
}
}
},
async (request, reply) => {
console.log(request.body)
return request.body
})
fastify.listen(8080)
The framework you linked has a module feature and you can integrate it with an hook:
const mongoSanitize = require('express-mongo-sanitize');
fastify.addHook('preHandler', function hook (request, reply, done) {
mongoSanitize.sanitize(request.body);
done(null)
})

How do I upload files to a graphql backend implemented using graphql-upload using axios?

I have a GraphQL backend implemented using express, express-graphql, graphql and graphql-upload. My GraphQL schema declaration is as follows:
type OProject {
_id: ID!
title: String!
theme: String!
budget: Float!
documentation: String!
date: Date
}
input IProject {
title: String!
theme: String!
budget: Float!
file: Upload!
}
type Mutations {
create(data: IProject): OProject
}
type Mutation {
Project: Mutations
}
I want to make a create request to my GraphQL API at /graphql using axios. How go I go about it?
Following the GraphQL multipart request specification detailed here you would go about doing so by:
creating a FormData instance and populating it with the following:
The operations field,
the map field and,
the files to upload
Creating the FormData Instance
var formData = new FormData();
The operations field:
The value of this field will be a JSON string containing the GraphQL query and variables. You must set all file field in the variables object to null e.g:
const query = `
mutation($project: IProject!) {
Project { create(data: $project) { _id } }
}
`;
const project = {
title: document.getElementById("project-title").value,
theme: document.getElementById("project-theme").value,
budget: Number(document.getElementById("project-budget").value),
file: null
};
const operations = JSON.stringify({ query, variables: { project } });
formData.append("operations", operations);
The map field:
As its name implies, the value of this field will be a JSON string of an object whose keys are the names of the field in the FormData instance containing the files. The value of each field will be an array containing a string indicating to which field in the variables object the file, corresponding to value's key, will be bound to e.g:
const map = {
"0": ["variables.project.file"]
};
formData.append("map", JSON.stringify(map));
The files to upload
You then should add the files to the FormData instance as per the map. In this case;
const file = document.getElementById("file").files[0];
formData.append("0", file);
And that is it. You are now ready to make the request to your backend using axios and the FormData instance:
axios({
url: "/graphql",
method: "post",
data: formData
})
.then(response => { ... })
.catch(error => { ... });
To complete the answer of #Archy
If you are using definition of what you expect in GraphQl like Inputs don't forget to set your graphql mutation definition after the mutation keyword
You have to put the definition of your payload like this
const query = `
mutation MutationName($payload: Input!) {
DocumentUpload(payload: $payload) {
someDataToGet
}
}`
And your operations like this the operationName and the order doesn't matter
const operations = JSON.stringify({ operationName: "MutationName", variables: { payload: { file: null } }, query })

Apollo query that depends on another query's result

I’m trying to create an Apollo query (in Vue/Nuxt) that depends on the result of another query.
sessions needs person in order to use this.person.id. How can I ensure that person exists before getting data for sessions?
My script and queries are below. Both queries work fine in GraphiQL. Thank you!
JS
import gql from 'graphql-tag'
import Photo from '~/components/Photo.vue'
import Session from '~/components/Session.vue'
import {Route} from 'vue-router'
import { currentPerson, currentPersonSessions } from '~/apollo/queries.js'
export default {
name: 'Speaker',
props: ['slug', 'id', 'person'],
data() {
return {
title: 'Speaker',
routeParam: this.$route.params.slug
}
},
apollo: {
person: {
query: currentPerson,
loadingKey: 'loading',
variables() {
return {
slug: this.routeParam
}
}
},
sessions: {
query: currentPersonSessions,
loadingKey: 'loading',
variables() {
return {
itemId: this.person.id
}
}
}
},
components: {
Photo,
Session
}
}
Queries
export const currentPerson = gql `query ($slug: String!) {
person(filter: { slug: { eq: $slug }}) {
name
bio
affiliation
id
photo {
url
}
}
}`
export const currentPersonSessions = gql `query($itemId: ItemId!) {
allSessions (filter: { speakers: { anyIn: [$itemId] }}) {
title
slug
start
end
}
}`
I managed to solve this by breaking out the part the sessions into a separate component.
Is that the appropriate way to handle a case like this, or is there a better way by chaining the requests here? If there's a way to do this, I still wouldn't mind hearing other answers.
I think the best way is to have a proper graph of your data model like :
type Person {
name: String!
bio: String
affiliation: String
id: ID!
photo: Photo
sessions(filter: SessionFilter): SessionList!
}
With GraphQL, you model your business domain as a graph
Graphs are powerful tools for modeling many real-world phenomena because they resemble our natural mental models and verbal descriptions of the underlying process. With GraphQL, you model your business domain as a graph by defining a schema; within your schema, you define different types of nodes and how they connect/relate to one another. On the client, this creates a pattern similar to Object-Oriented Programming: types that reference other types
You can read more in the official docucmentation

What is the correct path for a prefilled Realm file?

I have a realm file that is prefilled with the correct data. That file has the following schemas defined:
import Realm from 'realm';
let WordSchema = {
name: 'Word',
properties: {
word: 'string',
definition: 'string'
}
}
let BookmarkSchema = {
name: 'Bookmark',
properties: {
words: {type: 'list', object: 'Word'}
}
}
export default new Realm({
path: 'dictionary.realm',
schema: [WordSchema, BookmarkSchema]
}
I am having huge trouble trying bundle a prefilled Realm database.
Do I have the correct path name? The realm file is located in the same folder as the script.
Thank you for reading my question.

Ember, Ember Data - Updating hasMany relation

I'm trying to update a hasMany relation in Ember but I'm having a bit of trouble getting the data to send correctly.
I have the following Ember models:
// models/post.js
export default DS.Model.extend({
title: DS.attr('string'),
tags: DS.hasMany('tag', { async: true })
});
// models/tag.js
export default DS.Model.extend({
title: DS.attr('string'),
post: DS.belongsTo('post', { async: true })
});
And then I have the following action in my route to create a new tag and update the post:
addTag: function() {
var post = this.get('currentModel');
var newTag = this.store.createRecord('tag', {
title: 'Lorem Ipsum',
post: post
});
newTag.save().then(function() {
post.get('tags').pushObject(newTag);
post.save();
});
}
The new tag is created successfully and saved by my Express api but the post doesn't get saved correctly. It's received by the api but the request payload made by Ember never contains the tag IDs (it does send the tag title though). What am I doing wrong? Would really appreciate any help!
Edit
It turns out the RESTSerializer by default doesn't serialize and include the related IDs for a hasMany relationship. It only includes them for the belongsTo side as it expects the API to take care of saving it where needed. I will probably change my API to fit this behaviour as it's more efficient but in case any one else comes across this, it is possible to make the serializer include the IDs by extending the serializer and using the DS.EmbeddedRecordsMixin mixin - http://emberjs.com/api/data/classes/DS.EmbeddedRecordsMixin.html - Which would look something like this:
export default DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
tags: { serialize: 'ids' }
}
});
You don't need to call .save() on post. When you call createRecord to create a tag, your backend receives id of post and should persist dependencies accordingly.
addTag: function() {
var post = this.get('currentModel');
this.store.createRecord('tag', {
title: 'Lorem Ipsum',
post: post})
.save()
.then(function(tag) {
post.get('tags').pushObject(tag);
});
Meet the same problem.
Currently I solve it by serializeHasMany hook.
// app/serializers/application
import {ActiveModelSerializer} from 'active-model-adapter';
export default ActiveModelSerializer.extend({
serializeHasMany: function(snapshot, json, relationship){
this._super.apply this, arguments
if (!json[relationship.type + '_ids']){
var ids = []
snapshot.record.get(relationship.key).forEach(function(item){
ids.push item.get 'id'
});
json[relationship.type + '_ids'] = ids
}
}
})