How to flow type a React Component in apollo graphql - flowtype

I am trying to correctly type a react component with flow and apollo graphql. I keep getting a flow error message. I am using react-apollo 2.0.1 and flow 0.53.1
// #flow
/**
*
* CompanyName
*
*/
import React from 'react';
import { graphql } from 'react-apollo';
import gql from 'graphql-tag';
import type { OperationComponent, ChildProps } from 'react-apollo';
type Company = {
id: string,
name: string,
};
type Response = {
company: Company,
};
type Props = {
className: ?string,
};
class CompanyName extends React.Component<ChildProps<Props, Response>> {
render() {
return (
<span className={this.props.className}>
{!!this.props.data.company && this.props.data.company.name}
</span>
);
}
}
const query = gql`
query {
company {
id
name
}
}
`;
const withCompanyName: OperationComponent<Response, Props> = graphql(query);
export default withCompanyName(CompanyName); // this line gives a flow error
I get an error on the last line of code saying that the type is incompatible. Everything else validates correctly.
The error message is: CompanyName (class type: CompanyName) This type is incompatible with StatelessComponent (union: type application of polymorphic type: type StatelessComponent | class type: type application of identifier React$Component)
I am able to get it to work properly if I change it to a stateless functional component, but I need to get this working for class components.
Update:
Here is my .flowconfig
[ignore]
[include]
[libs]
[options]
module.name_mapper='.*\(.gql\)' -> 'empty/object'
I am using the empty package to prevent gql imports from causing a flow error.

Related

Create a custom resource with AWS Amplify and CDK

I'm trying to create a custom resource in AWS Amplify, using AWS CDK. And, I'm trying to use an existing lambda function as a provider event handler.
When I do amplify push the resource creation fails with no useful information. What am I doing wrong here? How can I troubleshoot this?
import * as cdk from '#aws-cdk/core';
import * as AmplifyHelpers from '#aws-amplify/cli-extensibility-helper';
import * as cr from "#aws-cdk/custom-resources";
import * as logs from "#aws-cdk/aws-logs";
import * as lambda from '#aws-cdk/aws-lambda';
import { AmplifyDependentResourcesAttributes } from "../../types/amplify-dependent-resources-ref"
export class cdkStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps, amplifyResourceProps?: AmplifyHelpers.AmplifyResourceProps) {
super(scope, id, props);
/* Do not remove - Amplify CLI automatically injects the current deployment environment in this input parameter */
new cdk.CfnParameter(this, 'env', {
type: 'String',
description: 'Current Amplify CLI env name',
});
const dependencies: AmplifyDependentResourcesAttributes = AmplifyHelpers.addResourceDependency(this,
amplifyResourceProps.category,
amplifyResourceProps.resourceName,
[{
category: "function",
resourceName: "myFunction"
}]
);
const myFunctionArn = cdk.Fn.ref(dependencies.function.myFunction.Arn);
const importedLambda = lambda.Function.fromFunctionArn(this, "importedLambda", myFunctionArn);
const provider = new cr.Provider(this, "MyCustomResourceProvider", {
onEventHandler: importedLambda,
logRetention: logs.RetentionDays.ONE_DAY,
})
new cdk.CustomResource(this, "MyCustomResource", {
serviceToken: provider.serviceToken
})
}
}
Here's the error I get:
CREATE_FAILED custommyCustomResourceXXXX AWS::CloudFormation::Stack Parameters: [AssetParametersXXXX, .....] must have values.
I got a response from AWS support team. It looks like the AssetParameters error is caused by the fact that Amplify CLI currently doesn't support a high level construct of Custom Resource Provider inside the custom resource category in Amplify CLI. The resource should be created this way:
import * as cdk from '#aws-cdk/core';
import * as AmplifyHelpers from '#aws-amplify/cli-extensibility-helper';
import * as lambda from '#aws-cdk/aws-lambda';
import { AmplifyDependentResourcesAttributes } from "../../types/amplify-dependent-resources-ref"
export class cdkStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps, amplifyResourceProps?: AmplifyHelpers.AmplifyResourceProps) {
super(scope, id, props);
/* Do not remove - Amplify CLI automatically injects the current deployment environment in this input parameter */
new cdk.CfnParameter(this, 'env', {
type: 'String',
description: 'Current Amplify CLI env name',
});
const dependencies: AmplifyDependentResourcesAttributes = AmplifyHelpers.addResourceDependency(this,
amplifyResourceProps.category,
amplifyResourceProps.resourceName,
[{
category: "function",
resourceName: "myFunction"
}]
);
const myFunctionArn = cdk.Fn.ref(dependencies.function.myFunction.Arn);
const importedLambda = lambda.Function.fromFunctionArn(this, "importedLambda", myFunctionArn);
new cdk.CustomResource(this, "MyCustomResource", {
serviceToken: importedLambda.functionArn
})
}
}

Error: Invalid AST Node: Undefined on Vue apollo query

I'm getting the error below when providing a constant with my graphql query to useQuery inside of my component.
Uncaught (in promise) Error: Invalid AST Node: undefined.
at devAssert (app.js:60958:11)
at visit (app.js:65283:130)
at Object.assign.added (app.js:59225:58)
at InMemoryCache.transformDocument (app.js:53379:101)
at QueryManager.transform (app.js:56649:42)
at QueryManager.getVariables (app.js:56681:121)
at QueryManager.watchQuery (app.js:56684:147)
at ApolloClient.watchQuery (app.js:55091:34)
at start (app.js:5304:26)
at immediate (app.js:5522:7)
My component script section looks like:
<script>
import { MY_QUERY } from "./constants/qraphql";
import {useQuery} from "#vue/apollo-composable";
export default {
setup() {
const {result, loading, error} = useQuery(MY_QUERY);
return {
result,
loading,
error
}
}
}
</script>
And my ./constants/graphql.js file looks like:
import gql from 'graphql-tag';
const MY_QUERY = gql`
query exampleQuery {
tasks {
id
name
title
text
}
}`;
Why is this happening?
Turns out I forgot to prefix export to my constant MY_QUERY. This caused the component to attempt to use a undefined constant because it failed to import.
In my ./constants/graphql.js file I have to change
const MY_QUERY
to
export const MY_QUERY
Now the error is fixed

Unable to use a decorator into a NestJS service

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.

Accessing a reducer state from within another reducer in NGRX

How can i access (read) the state of a reducer state within a another reducer in NGRX?
It is a very similar question to this.
Does NGRX offers any other solution to this?
I just stumbled upon this question when thinking about doing something similar. I needed a copy of some state information from a different reducer as a temporary "editing" data set that could be canceled and reverted back to the "recorded" data set.
I ended up extending my UI reducer (the reducer that held the state/edits for the current user's session) to include a property to hold a copy of data from my Data reducer (the reducer that represents what is stored in the database). That data gets passed in via a "Start" action.
Here is an abbreviated copy of my UI action:
import { Action } from "#ngrx/store";
import {
ICableFeature
} from "../../shared/models";
export enum UIActionTypes {
...
UI_EDIT_CUSTOM_TAGS_START = "[UI] Edit Custom Tags Start",
UI_EDIT_CUSTOM_TAGS_UPDATE = "[UI] Edit Custom Tags Update",
UI_EDIT_CUSTOM_TAGS_SAVE = "[UI] Edit Custom Tags Save",
UI_EDIT_CUSTOM_TAGS_SUCCESSFUL = "[UI] Edit Custom Tags Successful",
UI_EDIT_CUSTOM_TAGS_FAILED = "[UI] Edit Custom Tags Failed",
UI_EDIT_CUSTOM_TAGS_CANCELED = "[UI] Edit Custom Tags Canceled"
}
...
export class EditCustomTagsStart implements Action {
readonly type = UIActionTypes.UI_EDIT_CUSTOM_TAGS_START;
constructor(public payload: ICableFeature) {}
}
export class EditCustomTagsUpdate implements Action {
readonly type = UIActionTypes.UI_EDIT_CUSTOM_TAGS_UPDATE;
constructor(public payload: ICableFeature) {} // This payload has a copy of the data I needed from the other reducer. Make sure it is a copy and not the same object!
}
export class EditCustomTagsSave implements Action {
readonly type = UIActionTypes.UI_EDIT_CUSTOM_TAGS_SAVE;
constructor() {}
}
export class EditCustomTagsSuccessful implements Action {
readonly type = UIActionTypes.UI_EDIT_CUSTOM_TAGS_SUCCESSFUL;
constructor() {}
}
export class EditCustomTagsFailed implements Action {
readonly type = UIActionTypes.UI_EDIT_CUSTOM_TAGS_FAILED;
constructor(public payload: string) {}
}
export class EditCustomTagsCanceled implements Action {
readonly type = UIActionTypes.UI_EDIT_CUSTOM_TAGS_CANCELED;
constructor() {}
}
export type UIActions =
...
| EditCustomTagsStart
| EditCustomTagsUpdate
| EditCustomTagsSuccessful
| EditCustomTagsFailed
| EditCustomTagsCanceled;
And here is an abbreviated copy of my UI reducer:
import * as fromUI from "../actions/ui.actions";
import {
IOrchestratorState,
IOrchestratorStatusState,
ICableFeature
} from "../../shared/models";
export const uiFeatureKey = "ui";
export interface State {
showScroll: boolean;
fillingGaps: boolean;
fillGapStatus: IOrchestratorStatusState;
currentFillGapState: IOrchestratorState;
editingCustomTags: boolean;
customTagEdits: ICableFeature;
}
export const initialState: State = {
showScroll: true,
fillingGaps: false,
fillGapStatus: null,
currentFillGapState: null,
editingCustomTags: false,
customTagEdits: null
};
export function reducer(state = initialState, action: fromUI.UIActions) {
switch (action.type) {
...
case fromUI.UIActionTypes.UI_EDIT_CUSTOM_TAGS_START:
return {
...state,
editingCustomTags: true,
customTagEdits: action.payload // This is a copy of the data I needed from the other reducer
};
case fromUI.UIActionTypes.UI_EDIT_CUSTOM_TAGS_UPDATE:
return {
...state,
customTagEdits: action.payload // This is the updated information from user edits, not saved.
// I can also create a router guard that checks to makes sure the data in this
// property and the data in my Data store are the same before the page is deactivated
};
case fromUI.UIActionTypes.UI_EDIT_CUSTOM_TAGS_SUCCESSFUL:
case fromUI.UIActionTypes.UI_EDIT_CUSTOM_TAGS_FAILED:
case fromUI.UIActionTypes.UI_EDIT_CUSTOM_TAGS_CANCELED:
return {
...state,
editingCustomTags: false,
customTagEdits: null
};
default:
return state;
}
}
As you can see, by passing the data from one reducer to the other as payloads in actions, I am able to maintain pure functions in my reducers.
I hope this helps!

Angular 5 Firebase 2 -- Property 'includes' is missing in type

I am following a tutorial which is clearly outdated. But I tried my best to follow up with the migration guide but I am still stuck with this one little error.
import { Injectable } from '#angular/core';
import { AngularFireList, AngularFireObject, AngularFireDatabase } from 'angularfire2/database';
import { ExpenseModel } from './expense-model';
#Injectable()
export class ExplistService {
private basePath = '/UD';
explist: AngularFireList<ExpenseModel[]> = null; // list of objects
exp: AngularFireObject<ExpenseModel> = null;
createExpenseModel(exp: ExpenseModel): void {
this.explist.push(exp)
.catch(error => this.handleError(error));
}
I am getting the error at the line
this.explist.push(exp)
Argument of type 'ExpenseModel' is not assignable to parameter of type
'ExpenseModel[]'. Property 'includes' is missing in type
'ExpenseModel'.

Resources