Closed
Description
Description
With amplify cli version 12.12.0 model parsing does not populate the value in any complex non-model types. The properties of any complex non-model type will be null.
Categories
- Analytics
- API (REST)
- API (GraphQL)
- Auth
- Authenticator
- DataStore
- Notifications (Push)
- Storage
Steps to Reproduce
Given a schema that contains a complex non-model type
type MyModel @model @auth(rules: [{allow: owner}]) {
id: ID!
owner: String
token: MyToken
}
type Token {
externalId: String!
value: String!
}
When calling AppSync and setting the model type:
const decodePath = 'getMyModel';
final graphQLDocument = '''
query GetMyModel(\$id: ID!) {
$decodePath(id: \$id) {
id
owner
token {
externalId
value
}
}
}
''';
final result = await Amplify.API.query(
request: GraphQLRequest<MyModel>(
modelType: const MyModel.classType,
document: graphQLDocument,
decodePath: decodePath,
).response;
Complex non model types (e.g. Token) will not have their properties populated, i.e result.data.token.value == null
would be true in the above example.
This break was introduces with CLI version 12.12.0 and worked prior to this version.
Screenshots
No response
Platforms
- iOS
- Android
- Web
- macOS
- Windows
- Linux
Flutter Version
3.19.6
Amplify Flutter Version
1.7.0
Deployment Method
Amplify CLI
Schema
type Wallet @model @auth(rules: [{ allow: owner }]) {
id: ID!
owner: String @auth(rules: [{ allow: owner, operations: [create, read, delete] }]) @index
profiles: [Profile]! @hasMany
activeProfile: Profile @hasOne
financialInstitutions: [FinancialInstitution] @hasMany
xpub: String!
baseDerivationPath: String! # should be constent across wallets but here for the sake of consistency
nextChildIndex: Int!
}
type UserData @model @auth(rules: [{ allow: owner }]) {
id: ID!
owner: String @auth(rules: [{ allow: owner, operations: [create, read, delete] }]) @index
plainTextData: PlainTextData
securedData: String!
securedDocuments: [SecuredDocument] @hasMany
xpub: String!
baseDerivationPath: String! # The base derivation path for user documents under this account
nextChildIndex: Int!
}
type FinancialInstitutionData @model @auth(rules: [{allow: private, provider: userPools}, {allow: private, provider: iam}]) {
id: ID!
logo: String
name: String! @index
externalId: String
searchId: String! @index
}
type FinancialInstitution @model @auth(rules: [{allow: owner}, {allow: private, provider: iam}]) {
id: ID!
owner: String @auth(rules: [{ allow: owner, operations: [create, read, delete] }]) @index(sortKeyFields: ["searchId"])
name: String!
accounts: [Account] @hasMany
accessTokens: [AccessToken] @hasMany
wallet: Wallet! @belongsTo
financialInstitutionData: FinancialInstitutionData! @hasOne
externalId: String
searchId: String!
products: [String]
xpub: String!
baseDerivationPath: String!
nextChildIndex: Int!
createdAt: AWSDateTime!
updatedAt: AWSDateTime!
}
type Account @model @auth(rules: [{ allow: owner }, {allow: private, provider: iam}]) {
id: ID!
owner: String @auth(rules: [{ allow: owner, operations: [create, read, delete] }])
nativeId: String
name: String!
mask: String
facts: [AccountFact] @hasMany
secretFacts: String
pendingFacts: String
type: String!
documents: [FinancialDocument] @hasMany
financialInstitution: FinancialInstitution! @belongsTo
xpub: String!
baseDerivationPath: String! # The base derivation path for documents under this account
nextChildIndex: Int!
updatedAt: AWSDateTime!
}
type SecuredDocument @model @auth(rules: [{ allow: owner }, {allow: private, provider: iam}]) {
id: ID!
owner: String @auth(rules: [{ allow: owner, operations: [create, read, delete] }]) @index(sortKeyFields: ["createdAt"])
derivationPath: String!
effectiveDate: AWSDate!
name: String
s3Key: String!
sha256: String!
size: Int!
type: DocumentType!
createdAt: AWSDateTime!
}
type FinancialDocument @model @auth(rules: [{ allow: owner }, {allow: private, provider: iam}]) {
id: ID!
owner: String @auth(rules: [{ allow: owner, operations: [create, read, delete] }])
externalId: String
name: String
sha256: String!
securedDocument: SecuredDocument! @hasOne
account: Account! @belongsTo
}
type AccessToken @model @auth(rules: [{ allow: owner }, {allow: private, provider: iam}]) {
id: ID!
owner: String @auth(rules: [{ allow: owner, operations: [create, read, delete] }]) @index
externalId: String! @index
type: TokenType!
flinksToken: FlinksToken
plaidToken: PlaidToken
financialInstitutionAccessTokensId: ID! @index(name: "accessTokenByDate", queryField: "accessTokenByDate", sortKeyFields: ["createdAt"])
financialInstitution: FinancialInstitution! @belongsTo
createdAt: AWSDateTime!
}
type Profile @model @auth(rules: [{ allow: owner }]) {
id: ID!
owner: String @auth(rules: [{ allow: owner, operations: [read, delete] }])
name: String!
wallet: Wallet! @belongsTo
sharePackageReports: [SharePackageReport] @hasMany
}
type ProfileLink @model @auth(rules: [{ allow: owner }, {allow: private, provider: iam}]) {
id: ID!
owner: String @auth(rules: [{ allow: owner, operations: [read, delete] }])
financialInstitution: FinancialInstitution! @hasOne
profile: Profile! @hasOne
profileLinkFinancialInstitutionId: ID!
profileLinkProfileId: ID! @index(name: "byProfileAndFI", sortKeyFields: ["profileLinkFinancialInstitutionId"], queryField: "profileLinksByProfileAndFI")
}
type AccountFact @model @auth(rules: [{ allow: owner }, { allow: private, provider: iam }]) {
id: ID!
owner: String @auth(rules: [{ allow: owner, operations: [read, delete] }])
key: String!
value: String!
account: Account! @belongsTo
}
type AssetReportJob @model @auth(rules: [{ allow: owner }, { allow: private, provider: iam }]) {
id: ID!
owner: String @auth(rules: [{ allow: owner, operations: [read, delete] }])
status: JobStatus!
externalId: String! @index
message: String
token: String
s3Bucket: String!
createdAt: AWSDateTime!
updatedAt: AWSDateTime!
lastReportId: String
financialInstitution: FinancialInstitution! @hasOne
assetReportJobFinancialInstitutionId: ID! @index(name: "assetReportJobByFI", queryField: "assetReportJobByFI", sortKeyFields: ["updatedAt"])
}
type SharePackageReport @model @auth(rules: [{ allow: owner }, { allow: private, provider: iam }]) {
id: ID!
owner: String @auth(rules: [{ allow: owner, operations: [read, delete] }])
profile: Profile! @belongsTo
generalInfo: SharePackageGeneralInfo!
identityData: SharePackageIdentityData
createdAt: AWSDateTime!
updatedAt: AWSDateTime!
profileSharePackageReportsId: ID! @index(name: "byProfile", sortKeyFields: ["createdAt"], queryField: "sharePackageReportsByProfile")
}
type ShareReportDocumentLink @model @auth(rules: [{ allow: owner }, {allow: private, provider: iam}]) {
id: ID!
owner: String @auth(rules: [{ allow: owner, operations: [read, delete] }])
financialDocument: FinancialDocument! @hasOne
report: SharePackageReport! @hasOne
shareReportDocumentLinkFinancialDocumentId: ID!
shareReportDocumentLinkReportId: ID! @index(name: "shareReportDocumentLinksByReportAndDocument", sortKeyFields: ["shareReportDocumentLinkFinancialDocumentId"], queryField: "shareReportDocumentLinksByReportAndDocument")
}
type SharePackageGeneralInfo {
packageName: String!
recipient: String! # API provider or recipient's email address domain
securedRecipientEmail: String # The secured recipient email if shared via email
selectedCategories: [SharePackageCategory]
}
type SharePackageIdentityData {
securedData: String!
securedDocumentsIds: [String]
}
enum SharePackageCategory {
identity
income
bank
investment
tax
creditAndLoan
}
enum JobStatus {
pending # not ready for processing
ready # ready for processing
processing # processing
completed # completed successfully
failed # failed
}
enum ItemStatus {
OK
ACCESS_NOT_GRANTED
INSTANT_MATCH_FAILED
INSUFFICIENT_CREDENTIALS
INVALID_CREDENTIALS
INVALID_MFA
INVALID_OTP
INVALID_PHONE_NUMBER
INVALID_SEND_METHOD
INVALID_UPDATED_USERNAME
ITEM_CONCURRENTLY_DELETED
ITEM_LOCKED
ITEM_LOGIN_REQUIRED
ITEM_NOT_FOUND
ITEM_NOT_SUPPORTED
MFA_NOT_SUPPORTED
NO_ACCOUNTS
NO_AUTH_ACCOUNTS
NO_INVESTMENT_ACCOUNTS
NO_INVESTMENT_AUTH_ACCOUNTS
NO_LIABILITY_ACCOUNTS
PRODUCT_NOT_ENABLED
PRODUCT_NOT_READY
PRODUCTS_NOT_SUPPORTED
USER_INPUT_TIMEOUT
USER_SETUP_REQUIRED
}
enum TokenType {
plaid
flinks
}
enum DocumentType {
financialStatement
payStub
identity
tax
form1099
w2
other
}
type PlaidToken {
accessToken: String!
itemId: String!
status: ItemStatus
institutionId: String
institutionName: String
}
type FlinksToken {
loginId: String!
institution: String!
}
type PlainTextData {
incomeUser: IncomeUser!
firstName: String
financialGoals: [FinancialGoal]
}
enum FinancialGoal {
realEstate
rentingAHome
wealthPlanning
}
type IncomeUser {
id: String!
token: String!
}
type UpdateStatementsResponse {
statusCode: Int!
updateResult: UpdateResult!
}
type ExchangeTokenResponse {
statusCode: Int!
accessTokenId: String!
fiExternalId: String!
fiId: String!
}
type GetExternalInstitutionIdResponse {
statusCode: Int!
institutionId: String!
}
type CreateIncomeUserResponse {
id: String!
token: String!
}
input UpdateStatementsInput {
accessTokenId: String!
s3Bucket: String!
fiId: String!
}
input ExchangeTokenInput {
institutionId: String
institutionName: String
nextFIIndex: Int!
nextFIXpub: String!
profileId: String!
publicToken: String!
walletId: String!
}
input NewLinkTokenInput {
products: [String]
optionalProducts: [String]
incomeUserToken: String
accessTokenId: String
packageName: String!
}
input CreateCustomFIInput {
accountSubtype: String!
accountType: String!
institutionName: String!
isTax: Boolean!
logo: String
nextFIIndex: Int!
nextFIXpub: String!
products: [String]!
profileId: String!
walletId: String!
}
type CreateCustomFIResponse {
statusCode: Int!
financialInstitution: FinancialInstitution!
}
input GetPayrollDataInput {
incomeUserToken: String!
s3Bucket: String!
}
input NewAssetReportJobsInput {
fiIds: [String]!
s3Bucket: String!
}
type NewAssetReportJobsResponse {
jobs: [AssetReportJob]!
updateResults: [UpdateResult]!
}
type GetPayrollDataResponse {
statusCode: Int!
accounts: Int!
documents: Int!
}
input RefreshDataInput {
profileId: String
fiId: String
}
type UpdateResult {
financialInstitutionId: String!
accountsUpdated: Int!
documentsUpdated: Int!
accessTokenId: String
accessTokenStatus: ItemStatus
}
type RefreshDataResponse {
statusCode: Int!
updateResults: [UpdateResult]!
}
input GenerateUserHmacInput {
userId: String!
}
type GenerateUserHmacResponse {
hmacWeb: String!
hmacAndroid: String!
hmacIos: String!
}
type Mutation {
newLinkToken(input: NewLinkTokenInput!): String! @function(name: "newLinkToken-${env}")
exchangeToken(input: ExchangeTokenInput!): ExchangeTokenResponse! @function(name: "exchangeToken-${env}")
updateStatements(input: UpdateStatementsInput!): UpdateStatementsResponse! @function(name: "updateStatements-${env}")
createIncomeUser: CreateIncomeUserResponse! @function(name: "createIncomeUser-${env}")
createCustomFI(input: CreateCustomFIInput!): CreateCustomFIResponse! @function(name: "createCustomFI-${env}")
getPayrollData(input: GetPayrollDataInput!): GetPayrollDataResponse! @function(name: "getPayrollData-${env}")
newAssetReportJobs(input: NewAssetReportJobsInput!): NewAssetReportJobsResponse! @function(name: "newAssetReportJobs-${env}")
refreshData(input: RefreshDataInput!): RefreshDataResponse! @function(name: "refreshData-${env}")
generateUserHmac(input: GenerateUserHmacInput!): GenerateUserHmacResponse! @function(name: "generateUserHmac-${env}")
}