Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/silly-falcons-kneel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@aws-amplify/data-schema": minor
---

optimize custom selection set type
29 changes: 8 additions & 21 deletions examples/client-types-example/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,14 @@ import type { Schema } from './resource';

const client = generateClient<Schema>();

async function createPost() {
await client.models.Post.create({
title: 'Hello world',
location: {
lat: 123,
long: 123,
},
});
}
async function createPost() {}

async function test() {
const {
data: [post],
} = await client.models.Post.list();

const { data } = await client.models.Post.get({ id: 'MyId' });

const { data: data2 } = await client.mutations.myMutation();

type TM = typeof data2;

type TPost = typeof post;
// ^?
const res = await client.models.Network.list({
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In linked issue we would see a TS error here due to the selection set type union length

selectionSet: [
'name',
'articles.*',
'articles.articleOriginalWorks.person.name',
],
});
}
244 changes: 225 additions & 19 deletions examples/client-types-example/resource.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,230 @@
import { a, ClientSchema } from '@aws-amplify/data-schema';
import { __modelMeta__ } from '@aws-amplify/data-schema-types';
import { configure } from '@aws-amplify/data-schema/internals';
import { __modelMeta__, Prettify } from '@aws-amplify/data-schema-types';
import { GraphQLFormattedError } from '@aws-amplify/data-schema/runtime';

const schema = configure({
database: { engine: 'mysql', connectionUri: {} as any },
}).schema({
Post: a.model({
title: a.string().required(),
description: a.string(),
location: a.ref('Location').required(),
}),
const masterType = {
id: a.id().required(),
name: a.string().required(),
type: a.string().required(),
sort: a.integer().required(),
};

Location: a.customType({
lat: a.float(),
long: a.float(),
}),
});
const schema = a
.schema({
Network: a
.model({
...masterType,
articles: a.hasMany('Article', 'networkId'),
})
.secondaryIndexes((index) => [
index('type').sortKeys(['sort']).queryField('networkListByTypeAndId'),
]),
Category: a
.model({
...masterType,
articles: a.hasMany('Article', 'categoryId'),
})
.secondaryIndexes((index) => [
index('type').sortKeys(['sort']).queryField('categoryListByTypeAndId'),
]),
Season: a
.model({
...masterType,
articles: a.hasMany('Article', 'seasonId'),
})
.secondaryIndexes((index) => [
index('type').sortKeys(['sort']).queryField('seasonListByTypeAndId'),
]),
Person: a
.model({
...masterType,
articleCasts: a.hasMany('ArticleCast', 'personId'),
articleAuthors: a.hasMany('ArticleAuthor', 'personId'),
articleDirectors: a.hasMany('ArticleDirector', 'personId'),
articleProducers: a.hasMany('ArticleProducer', 'personId'),
articleScreenwriters: a.hasMany('ArticleScreenwriter', 'personId'),
articleOriginalWorks: a.hasMany('ArticleOriginalWork', 'personId'),
image: a.string(),
})
.secondaryIndexes((index) => [
index('type').sortKeys(['sort']).queryField('personListByTypeAndId'),
]),
ArticleVod: a
.model({
articleId: a.id().required(),
vodId: a.id().required(),
vod: a.belongsTo('Vod', 'vodId'),
article: a.belongsTo('Article', 'articleId'),
})
.identifier(['articleId', 'vodId']),
Vod: a
.model({
...masterType,
articles: a.hasMany('ArticleVod', 'vodId'),
microcopy: a.string(),
url: a.string(),
})
.secondaryIndexes((index) => [
index('type').sortKeys(['sort']).queryField('vodListByTypeAndId'),
]),
ArticleCast: a
.model({
articleId: a.id().required(),
personId: a.id().required(),
roleName: a.string().required(),
person: a.belongsTo('Person', 'personId'),
article: a.belongsTo('Article', 'articleId'),
})
.identifier(['articleId', 'personId']),
ArticleAuthor: a
.model({
articleId: a.id().required(),
personId: a.id().required(),
person: a.belongsTo('Person', 'personId'),
article: a.belongsTo('Article', 'articleId'),
})
.identifier(['articleId', 'personId']),
ArticleDirector: a
.model({
articleId: a.id().required(),
personId: a.id().required(),
person: a.belongsTo('Person', 'personId'),
article: a.belongsTo('Article', 'articleId'),
})
.identifier(['articleId', 'personId']),
ArticleProducer: a
.model({
articleId: a.id().required(),
personId: a.id().required(),
person: a.belongsTo('Person', 'personId'),
article: a.belongsTo('Article', 'articleId'),
})
.identifier(['articleId', 'personId']),
ArticleScreenwriter: a
.model({
articleId: a.id().required(),
personId: a.id().required(),
person: a.belongsTo('Person', 'personId'),
article: a.belongsTo('Article', 'articleId'),
})
.identifier(['articleId', 'personId']),
ArticleOriginalWork: a
.model({
articleId: a.id().required(),
personId: a.id().required(),
person: a.belongsTo('Person', 'personId'),
article: a.belongsTo('Article', 'articleId'),
})
.identifier(['articleId', 'personId']),
ArticleMusic: a
.model({
type: a.string().required(),
articleId: a.id().required(),
article: a.belongsTo('Article', 'articleId'),
course: a.integer().required(),
opArtist: a.string(),
opSong: a.string(),
edArtist: a.string(),
edSong: a.string(),
otherArtist: a.string(),
otherSon: a.string(),
sort: a.integer().required(), // articleId
})
.identifier(['articleId', 'course'])
.secondaryIndexes((index) => [
index('type')
.sortKeys(['sort', 'course'])
.queryField('musicListByTypeAndSortCourse'),
]),
PageSetting: a
.model({
articleId: a.id().required(),
type: a.string().required(), // eg: anime-CAROUSEL / anime-SPOTLIGHT
article: a.belongsTo('Article', 'articleId'),
sort: a.integer().required(),
})
.identifier(['articleId', 'type'])
.secondaryIndexes((index) => [
index('type').sortKeys(['sort']).queryField('settingListByTypeAndSort'),
]),
Article: a
.model({
id: a.id().required(),
genreType: a.enum(['movie', 'drama', 'variety', 'anime']),
tagType: a.enum(['root', 'series', 'episode']),
pathName: a.string().required(), // eg: spy_family | spy_family/season1 | spy_family/season1/episode1
parentId: a.id(),
childs: a.hasMany('Article', 'parentId'),
parent: a.belongsTo('Article', 'parentId'),
pageSetting: a.hasMany('PageSetting', 'articleId'),
title: a.string().required(),
titleMeta: a.string(),
descriptionMeta: a.string(),
networkId: a.id().required(),
network: a.belongsTo('Network', 'networkId'),
seasonId: a.id(),
season: a.belongsTo('Season', 'seasonId'),
thumbnail: a.string(),
vods: a.hasMany('ArticleVod', 'articleId'),
categoryId: a.id().required(),
category: a.belongsTo('Category', 'categoryId'),
summary: a.customType({
title: a.string(),
text: a.string(),
}),
authors: a.hasMany('ArticleAuthor', 'articleId'),
authorOrganiation: a.string(),
directors: a.hasMany('ArticleDirector', 'articleId'),
producers: a.hasMany('ArticleProducer', 'articleId'),
screenwriters: a.hasMany('ArticleScreenwriter', 'articleId'),
staff: a.string(),
production: a.string().array(),
casts: a.hasMany('ArticleCast', 'articleId'),
sns: a.url().array(),
durationTime: a.string(),
seriesNumber: a.string(),
publisher: a.string(),
otherPublisher: a.string(),
website: a.url(),
articleOriginalWorks: a.hasMany('ArticleOriginalWork', 'articleId'),
originalWorkOrganization: a.string(),
label: a.string(),
durationPeriod: a.string(),
volume: a.string(),
content: a.customType({
genre: a.string(),
subgenre: a.string(),
}),
distributor: a.string(),
distributorOverseas: a.string(),
copyright: a.string(),
productionYear: a.string(),
musics: a.hasMany('ArticleMusic', 'articleId'),
video: a.customType({
text: a.string(),
url: a.url(),
}),
sort: a.integer().required(),
})
.secondaryIndexes((index) => [
index('genreType')
.sortKeys(['sort'])
.queryField('listByGenreTypeAndSort'),
index('parentId')
.sortKeys(['sort'])
.queryField('listByParentIdAndSort'),
index('seasonId')
.sortKeys(['genreType', 'tagType', 'sort'])
.queryField('listBySeasonIdAndTypeSort'),
index('categoryId')
.sortKeys(['genreType', 'tagType', 'sort'])
.queryField('listByCategoryIdAndTypeSort'),
index('pathName').queryField('listByPathName'),
]),
})
.authorization((allow) => [allow.publicApiKey()]);

const s2 = schema.addMutations({
myMutation: a.mutation().returns(a.ref('Post')),
});
export type Schema = ClientSchema<typeof schema>;

export type Schema = ClientSchema<typeof s2>;
type TN = Prettify<Schema['Network']['type']>;
type TNF = Prettify<Schema['Network']['__meta']['flatModel']>;
37 changes: 20 additions & 17 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/benches/combine/combine-CRUDL.bench.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,4 @@ bench('combined SQL and DDB schema w client types', async () => {
title: 'updated',
});
const _deletedBlog = await client.models.Blog.delete({ id: 'abc' });
}).types([2128533, 'instantiations']);
}).types([2133852, 'instantiations']);
Loading