Adding a new model to an existing aws api gateway using CDK and Typescript - aws-api-gateway

I have an API gateway defined in a cdk project and I have exported the RestApi. In a different project, I'm trying to add a few Models to this API gateway but I get an error.
Here is how the import line:
const restApi = apiGateway.RestApi.fromRestApiId(this,"MyGatewayApi",props.restApiId);
and when I try to add a model I get this error:
Property 'addModel' does not exist on type 'IRestApi'.
Here is the code that uses the restApi:
const errorModel = restApi.addModel('errorModel', {
contentType: 'application/json',
modelName: 'Error',
schema: {
schema: apiGateway.JsonSchemaVersion.DRAFT4,
title: 'Error',
type: apiGateway.JsonSchemaType.OBJECT,
properties: {
errorId: {type: apiGateway.JsonSchemaType.STRING} ,
}
}
});
Then I changed my import line to this :
const restApi = apiGateway.RestApi.fromRestApiId(this,"MyGatewayApi",props.restApiId) as apiGateway.RestApi;
and the IDE doesn't show any errors. But the problem is when I run cdk synth it returns another error:
const errorModel = restApi.addModel('errorModel', {
^ TypeError: restApi.addModel is not a function
Does anybody know what's wrong? and how can I fix it?

Add a model with the Model constructor. The restApi prop accepts the IRestApi type:
const errorModel = new apigw.Model(this, "errorModal", {
restApi,
schema: {},
});
The addModel method isn't exposed on the IRestApi interface type returned by the fromRestApiId method. This is an implemenation choice, not an underlying constraint. Under the hood, addModel just calls the Model constructor as we do above.

Related

Cannot read property 'type' of undefined ember and firebase

I am trying to retrieve data from my firestore using ember.js and emberfire.
i have a simple movie database. All that is in it right now is 1 document but for some reason when i try and retrieve the data, i keep getting "Cannot read property 'type' of undefined"! i understand that this is a JSONAPI issue but nothing seems to fix it.
My Route:
import Route from '#ember/routing/route';
export default class MovieRoute extends Route {
async model() {
this.store.findAll('movies').then(function(movie) {
console.log(movie);
});
}
}
My Model:
import Model, { attr } from '#ember-data/model';
export default class MoviesModel extends Model {
#attr('string') title;
}
Now it was my understanding that the default JSONAPISerializer is the default one but i tried adding a serializer anyway and my error changes to: Assertion Failed: normalizeResponse must return a valid JSON API document.
My adapter:
import FirestoreAdapter from 'emberfire/adapters/firestore';
export default FirestoreAdapter.extend({
// Uncomment the following lines to enable offline persistence and multi-tab support
// enablePersistence: true,
// persistenceSettings: { synchronizeTabs: true },
});
My Serializer:
import JSONAPISerializer from '#ember-data/serializer/json-api';
export default class ApplicationSerializer extends JSONAPISerializer {}
it is also my understanding that the way the JSON is to be accepted is:
{
data {
type: 'movies',
id: 1,
attributes {
title: 'ghostbusters'
}
}
}
so i also created a new document in the firestore, following this same format. Still no luck.
Can anyone point me in the right direction as to how to get the correct data returning from the firestore?
**edited --
error message:

Why does this not raise a compilation error? (Mongoose, Typescript, MongoDB)

I'm currently setting up a MERN project in Typescript, and I'm wondering why the following doesn't create a compilation error in TS.
Here's my model:
import { Document, Schema, model } from "mongoose";
export interface Hello extends Document {
name: string;
}
const helloSchema = new Schema({
name: {
required: true,
type: String,
},
});
const helloModel = model<Hello>("Hello", helloSchema);
export default helloModel;
then used like this:
import express from "express";
import helloModel from "./model";
const app = express();
app.get("/", (req, res) => {
res.send("hi");
});
const x = new helloModel({ age: 1 }); <===== no errors here
app.listen(7000);
I would expect there to be compilation errors saying that x doesn't conform to the interface. Am I using the model incorrectly? I'm fairly new to MongoDB and Typescript if that's not immediately clear (I hope not).
Many thanks to anyone who can explain.
EDIT FOLLOW-UP
I've found this in the #types files:
/**
* Model constructor
* Provides the interface to MongoDB collections as well as creates document instances.
* #param doc values with which to create the document
* #event error If listening to this event, it is emitted when a document
* was saved without passing a callback and an error occurred. If not
* listening, the event bubbles to the connection used to create this Model.
* #event index Emitted after Model#ensureIndexes completes. If an error
* occurred it is passed with the event.
* #event index-single-start Emitted when an individual index starts within
* Model#ensureIndexes. The fields and options being used to build the index
* are also passed with the event.
* #event index-single-done Emitted when an individual index finishes within
* Model#ensureIndexes. If an error occurred it is passed with the event.
* The fields, options, and index name are also passed.
*/
new (doc?: any): T;
So that doc?: any is why there's no compile error. Does this mean that generally when we're joining our Mongo schemas with our TS interfaces we can only have type checking on Read, Update and Delete rather than on Create?
You're right with doc?: any, we can't have typechecking on create method. It will throw an error when you will try to save it to the database and only because schema check.

Vuex ORM model constructor issue on insert

I have the following model:
import { Model } from '#vuex-orm/core'
export class User extends Model {
static entity = 'users'
static fields () {
return {
id: this.attr(null),
name: this.attr('')
}
}
}
and when I try to do this:
User.insert({
data: { id: 1, name: 'John' }
})
I get the following error:
Uncaught (in promise) TypeError: Class constructor User cannot be invoked without 'new'
Any idea what is the problem? This code is from the documentation, so I'm confused a little bit.
as I can see you are missing the registration of the model in the database at the beginning of the application.
You have to implement your vuex store with the corresponding plugin
EXAMPLE:
import Vue from 'vue'
import Vuex from 'vuex'
import VuexORM from '#vuex-orm/core'
import User from '#/models/User'
import Post from '#/models/Post'
Vue.use(Vuex)
// Create a new instance of Database.
const database = new VuexORM.Database()
// Register Models to Database.
database.register(User)
database.register(Post)
// Create Vuex Store and register database through Vuex ORM.
const store = new Vuex.Store({
plugins: [VuexORM.install(database)]
})
export default store
You now have good documentation in this regard
I hope I have helped you, greetings

Swagger-generated Spring controller recievs NULLs in the body parameter of POST

My API-first swagger client/server transfers POST request body parameter object incorrectly. Spring (4.3.14.RELEASE) server receives nulls in the #RequestBody parameter of the POST request.
The key difference between requests passed over SwaggerUI and over generated
typescript client is that SwaggerUI passes object fields as query parameters (Spring handles well), but the generated typescript client over json body (Spring handles nulls).
It seems like autogenerated client sends parameter over body, but the autogenerated server expects parameters in the query.
The swagger fragment:
/project:
post:
security:
- Bearer: []
tags:
- Project
summary: Create new project
operationId: createProject
consumes:
- "application/json"
- "text/json"
parameters:
- name: project
in: body
description: project value
schema:
$ref: '#/definitions/ProjectRequestDTO'
responses:
'200':
description: Successful response
schema:
$ref: '#/definitions/ProjectDTO'
default:
description: Bad requst
The resulting Spring MVC method:
ApiOperation(value = "Create new project", nickname = "createHachathon", notes = "", response = ProjectDTO.class, authorizations = {
#Authorization(value = "Bearer")
}, tags={ "Project", })
#ApiResponses(value = {
#ApiResponse(code = 200, message = "Successful response", response = ProjectDTO.class),
#ApiResponse(code = 200, message = "Bad requst") })
#RequestMapping(value = "/project",
consumes = { "application/json", "text/json" },
method = RequestMethod.POST)
default ResponseEntity<ProjectDTO> createHachathon(#ApiParam(value = "project value" ) #Valid #RequestBody ProjectRequestDTO project) {
I'm sending request from typescript over manually hacked client (title parameter added as demonstration that this parameter will be unmarshalled well):
return this.httpClient.post<ProjectDTO>(`${this.basePath}/project?title=hello`,
The resulting request in the Chrome console:
Unfortunatelly Spring receives only the value which were passed over query parameter but not over request body:
Plese help me to make my swagger-codegen-maven-plugin 2.3.1 produce client/server swagger API which will transfer data transparently.
The root cause is that Spring ignores method parameter annotations of the implemented Interface, so the #RequestBody was ignored in my Controller implementation.
The <delegatePattern>true</delegatePattern> parameter inside <configOptions> section of swagger-codegen-maven-plugin resolved this problem.
This parameter makes Swagger generate invocation of delegate method inside default implementation of API Interface methods. My Controller implements this method and overrides this delegate mathods, so the source method annotations are in safe.
Sorry, may be late answer. maybe helps someone.
I was hitting same issue while using spring boot+Swagger2.
My REST API with POST method :
public void getAllNames(#ApiParam(name = "Get All names Request",
value = "Request to get all names",
required = true) #RequestBody BasicCredentialsJsonObject requestJson)
I had to introduce Json annotations(JsonPropertyOrder, JsonProperty) on below class to get going. I was hitting issue till I made this changes.
BasicCredentialsJsonObject :
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"password",
"username"
})
public class BasicCredentialsJsonObject {
#JsonProperty("username")
private String username;
#JsonProperty("password")
private String password;
}
Sometimes, it seems stupid but I had issue with my request body, it was null into the controller. What I changed, the import, I was using the swagger.requestBody package instead of the springframeWork.request import.

How to use type check Loopback / Fireloop PersistedModel

I'm using Fireloop with Loopback 3 and wanting to know how best to create typesafe hooks and remote methods using type checked PersistedModel and Validatable methods. I'd like to change the type of the constructor from ...
constructor(public model: any) { }
to ...
constructor(public model: SomeType) { }
I'd like to make PersistedModel calls like
this.model.count().then((n) => ...);
OR Validatable calls like:
model.validatesLengthOf('code', {
min: 6, max: 12, message: { min: 'too short', max: 'too long'}
});
The Fireloop examples like the one below only use any as type of this.model.
The firestarter model samples and Fireloop documentation were also of no use here.
I know that there is a type called ModelConstructor declared in the fireloop source tree under core/index.d.ts. This interface looks correct because it implements all the PersistedModel and Validatable methods but where is it published in npmjs? Is it already part of the Fireloop server SDK or do I need to npm install it? No idea.
import { Model } from '#mean-expert/model';
/**
* #module Account
* #description
* Write a useful Account Model description.
* Register hooks and remote methods within the
* Model Decorator
**/
#Model({
hooks: {
beforeSave: { name: 'before save', type: 'operation' }
},
remotes: {
myRemote: {
returns: { arg: 'result', type: 'array' },
http: { path: '/my-remote', verb: 'get' }
}
}
})
class Account {
// LoopBack model instance is injected in constructor
constructor(public model: any) { }
// Example Operation Hook
beforeSave(ctx: any, next: Function): void {
console.log('Account: Before Save', ctx.instance);
next();
}
// Example Remote Method
myRemote(next: Function): void {
this.model.find(next);
}
}
module.exports = Account;
Finially, I've also attempted to use the Loopback 3 Typescript definitions but hit more problems as the PersistedModel methods here are all declared as static so fail type checks and return Promise<T> | void. The later means you’re forced to type cast the result back to just Promise<T> so it seems like the type def authors have never actually used them. Is this a bug or am I missing something? Can't find any working examples to prove otherwise.
This is the server side API pain. Client side REST API for Fireloop is also undocumented (lots of example for Real-time API) but none for the REST api it's also supposed to include (just mentioned once in one issue). Would be nice to find it can all be type checked by Typescript.
I found that ModelConstructor validation methods were missing arguments like { message: 'my error message' } and methods like exists() returned Promise<any> instead of Promise<boolean>.
The type definitions in Loopback 3 Type definitions were more complete but were unusable unless fixed as described above.
In the end I used ..
# Used modified type defs from https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/loopback/index.d.ts
import { Validatable } from '../types/validatable';
# Fixed static methods and return types.
import { PersistedModel } from '../types/loopback';
constructor(public MyModel: Validatable | PersistedModel) {
let Model = MyModel as Validatable;
Model.validatesLengthOf('code', {
min: 6,
max: 80,
message: { min: 'too short', max: 'too long' } });
Model.validatesFormatOf('email',
{ with: this.reEmail,
message: 'invalid email address',
allowNull: false });
Model.validatesInclusionOf('role', {
in: RoleNames,
message: 'is not valid'
});
}
And in later methods ..
let Model = this.MyModel as PersistedModel;
// knows that isFound is boolean
Model.exists(code).then(isFound => { ... });