Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into new-client-schema-dx-d
Browse files Browse the repository at this point in the history
  • Loading branch information
svidgen committed Apr 25, 2024
2 parents 45eafa1 + 7145e6d commit 2d66909
Show file tree
Hide file tree
Showing 12 changed files with 236 additions and 270 deletions.
3 changes: 2 additions & 1 deletion examples/tsc-compliance/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
},
"dependencies": {
"@aws-amplify/data-schema": "*",
"aws-amplify": "*"
"aws-amplify": "*",
"aws-cdk-lib": "^2.127.0"
},
"keywords": [],
"author": "",
Expand Down
376 changes: 155 additions & 221 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"@types/prettier": "^3.0.0",
"@typescript-eslint/eslint-plugin": "^6.7.4",
"@typescript-eslint/parser": "^6.7.4",
"aws-amplify": "^6.0.29",
"aws-amplify": "unstable",
"glob": "^10.3.10",
"eslint": "^8.50.0",
"eslint-config-prettier": "^9.0.0",
Expand Down
6 changes: 6 additions & 0 deletions packages/data-schema/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# @aws-amplify/data-schema

## 0.17.1

### Patch Changes

- abfbd9d: fix: naming collision on default secondary index queryField

## 0.17.0

### Minor Changes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ describe('ModelSecondaryIndexes', () => {
Post: {
secondaryIndexes: [
{
queryField: 'listByTitle';
defaultQueryFieldSuffix: 'Title';
queryField: never;
pk: {
title: string;
};
Expand Down Expand Up @@ -121,6 +122,7 @@ describe('ModelSecondaryIndexes', () => {
Post: {
secondaryIndexes: [
{
defaultQueryFieldSuffix: 'TitleAndViewCount';
queryField: 'myFavIdx';
pk: {
title: string;
Expand All @@ -130,7 +132,8 @@ describe('ModelSecondaryIndexes', () => {
};
},
{
queryField: 'listByDescription';
defaultQueryFieldSuffix: 'Description';
queryField: never;
pk: {
description: string;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ exports[`secondary indexes generates a primary key AND secondary index annotatio
exports[`secondary indexes generates a secondary index annotation 1`] = `
"type widget @model @auth(rules: [{allow: public, provider: apiKey}])
{
title: String! @index(queryField: "listByTitle")
title: String! @index(queryField: "listWidgetByTitle")
}"
`;

Expand All @@ -530,7 +530,7 @@ exports[`secondary indexes generates a secondary index annotation with attribute
exports[`secondary indexes generates multiple secondary index annotations on the same field 1`] = `
"type widget @model @auth(rules: [{allow: public, provider: apiKey}])
{
title: String! @index(queryField: "listByTitle") @index(sortKeyFields: ["timestamp"], queryField: "listByTitleAndTimestamp") @index(name: "myGSI", sortKeyFields: ["description", "timestamp"], queryField: "byTitleDescTs")
title: String! @index(queryField: "listWidgetByTitle") @index(sortKeyFields: ["timestamp"], queryField: "listWidgetByTitleAndTimestamp") @index(name: "myGSI", sortKeyFields: ["description", "timestamp"], queryField: "byTitleDescTs")
description: String!
timestamp: Int!
}"
Expand All @@ -539,8 +539,8 @@ exports[`secondary indexes generates multiple secondary index annotations on the
exports[`secondary indexes generates secondary index annotations on different fields 1`] = `
"type widget @model @auth(rules: [{allow: public, provider: apiKey}])
{
title: String! @index(queryField: "listByTitle")
description: String! @index(sortKeyFields: ["timestamp"], queryField: "listByDescriptionAndTimestamp")
title: String! @index(queryField: "listWidgetByTitle")
description: String! @index(sortKeyFields: ["timestamp"], queryField: "listWidgetByDescriptionAndTimestamp")
timestamp: Int! @index(sortKeyFields: ["description"], queryField: "byTimeStampDesc")
}"
`;
2 changes: 1 addition & 1 deletion packages/data-schema/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@aws-amplify/data-schema",
"version": "0.17.0",
"version": "0.17.1",
"license": "Apache-2.0",
"repository": {
"type": "git",
Expand Down
48 changes: 22 additions & 26 deletions packages/data-schema/src/MappedTypes/MapSecondaryIndexes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { IsEmptyStringOrNever } from '@aws-amplify/data-schema-types';
import { ModelIndexType } from '../ModelIndex';

type ModelIndexTypeShape = ModelIndexType<any, any, any, any, any>;
Expand Down Expand Up @@ -34,31 +33,28 @@ export type SecondaryIndexToIR<
*
* @remarks - the IR type alias is defined as SecondaryIndexIrShape in data-schema-types
*/
type SingleIndexIrFromType<
Idx extends ModelIndexTypeShape,
ResolvedFields,
> = Idx extends ModelIndexType<
any,
infer PK extends string,
infer SK,
infer QueryField extends string | never,
any
>
? {
queryField: IsEmptyStringOrNever<QueryField> extends true
? `listBy${QueryFieldLabelFromTuple<SK, Capitalize<PK>>}`
: QueryField;
pk: PK extends keyof ResolvedFields
? {
[Key in PK]: Exclude<ResolvedFields[PK], null>;
}
: never;
// distribute ResolvedFields over SK
sk: unknown extends SK
? never
: ResolvedSortKeyFields<SK, ResolvedFields>;
}
: never;
type SingleIndexIrFromType<Idx extends ModelIndexTypeShape, ResolvedFields> =
Idx extends ModelIndexType<
any,
infer PK extends string,
infer SK,
infer QueryField extends string | never,
any
>
? {
defaultQueryFieldSuffix: `${QueryFieldLabelFromTuple<SK, Capitalize<PK>>}`;
queryField: QueryField;
pk: PK extends keyof ResolvedFields
? {
[Key in PK]: Exclude<ResolvedFields[PK], null>;
}
: never;
// distribute ResolvedFields over SK
sk: unknown extends SK
? never
: ResolvedSortKeyFields<SK, ResolvedFields>;
}
: never;

/**
* @typeParam SK - tuple of SortKey field names, e.g. ['viewCount', 'createdAt']
Expand Down
7 changes: 6 additions & 1 deletion packages/data-schema/src/SchemaProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -810,12 +810,13 @@ type TransformedSecondaryIndexes = {
* @returns default query field name
*/
const secondaryIndexDefaultQueryField = (
modelName: string,
pk: string,
sk?: readonly string[],
): string => {
const skName = sk?.length ? 'And' + sk?.map(capitalize).join('And') : '';

const queryField = `listBy${capitalize(pk)}${skName}`;
const queryField = `list${capitalize(modelName)}By${capitalize(pk)}${skName}`;

return queryField;
};
Expand All @@ -825,6 +826,7 @@ const secondaryIndexDefaultQueryField = (
* and the value is an array of transformed Amplify @index directives with all supplied attributes
*/
const transformedSecondaryIndexesForModel = (
modelName: string,
secondaryIndexes: readonly InternalModelIndexType[],
): TransformedSecondaryIndexes => {
const indexDirectiveWithAttributes = (
Expand All @@ -835,6 +837,7 @@ const transformedSecondaryIndexesForModel = (
): string => {
if (!sortKeys.length && !indexName && !queryField) {
return `@index(queryField: "${secondaryIndexDefaultQueryField(
modelName,
partitionKey,
)}")`;
}
Expand All @@ -856,6 +859,7 @@ const transformedSecondaryIndexesForModel = (
} else {
attributes.push(
`queryField: "${secondaryIndexDefaultQueryField(
modelName,
partitionKey,
sortKeys,
)}"`,
Expand Down Expand Up @@ -1164,6 +1168,7 @@ const schemaPreprocessor = (
const [partitionKey] = identifier;

const transformedSecondaryIndexes = transformedSecondaryIndexesForModel(
typeName,
typeDef.data.secondaryIndexes,
);

Expand Down
39 changes: 30 additions & 9 deletions packages/data-schema/src/runtime/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
Equal,
__modelMeta__,
ExtractModelMeta,
IsEmptyStringOrNever,
} from '@aws-amplify/data-schema-types';
import type { Observable } from 'rxjs';

Expand Down Expand Up @@ -494,10 +495,11 @@ type ModelMetaShape = {

// TODO: remove export. added for debugging.
export type ModelTypesClient<
ModelName extends string,
Model extends Record<string, unknown>,
ModelMeta extends ModelMetaShape,
FlatModel extends Record<string, unknown> = ResolvedModel<Model>,
> = IndexQueryMethodsFromIR<ModelMeta['secondaryIndexes'], Model> & {
> = IndexQueryMethodsFromIR<ModelMeta['secondaryIndexes'], ModelName, Model> & {
create: (
model: Prettify<CreateModelInput<Model, ModelMeta>>,
options?: {
Expand Down Expand Up @@ -589,10 +591,11 @@ export type ModelTypesClient<
};

type ModelTypesSSRCookies<
ModelName extends string,
Model extends Record<string, unknown>,
ModelMeta extends ModelMetaShape,
FlatModel extends Record<string, unknown> = ResolvedModel<Model>,
> = IndexQueryMethodsFromIR<ModelMeta['secondaryIndexes'], Model> & {
> = IndexQueryMethodsFromIR<ModelMeta['secondaryIndexes'], ModelName, Model> & {
create: (
model: Prettify<CreateModelInput<Model, ModelMeta>>,
options?: {
Expand Down Expand Up @@ -641,10 +644,11 @@ type ModelTypesSSRCookies<
};

type ModelTypesSSRRequest<
ModelName extends string,
Model extends Record<string, unknown>,
ModelMeta extends ModelMetaShape,
FlatModel extends Record<string, unknown> = ResolvedModel<Model>,
> = IndexQueryMethodsFromIR<ModelMeta['secondaryIndexes'], Model> & {
> = IndexQueryMethodsFromIR<ModelMeta['secondaryIndexes'], ModelName, Model> & {
create: (
// TODO: actual type
contextSpec: any,
Expand Down Expand Up @@ -716,14 +720,20 @@ export type ModelTypes<
>]: ModelName extends string
? Schema[ModelName] extends Record<string, unknown>
? Context extends 'CLIENT'
? ModelTypesClient<Schema[ModelName]['type'], ModelMeta[ModelName]>
? ModelTypesClient<
ModelName,
Schema[ModelName]['type'],
ModelMeta[ModelName]
>
: Context extends 'COOKIES'
? ModelTypesSSRCookies<
ModelName,
Schema[ModelName]['type'],
ModelMeta[ModelName]
>
: Context extends 'REQUEST'
? ModelTypesSSRRequest<
ModelName,
Schema[ModelName]['type'],
ModelMeta[ModelName]
>
Expand Down Expand Up @@ -853,27 +863,38 @@ export type CustomHeaders =
* SecondaryIndex index types and query methods
*/
export type SecondaryIndexIrShape = {
defaultQueryFieldSuffix: string;
queryField: string;
pk: { [key: string]: string | number };
sk: { [key: string]: string | number };
};

type IndexQueryMethodsFromIR<
SecondaryIdxTuple extends SecondaryIndexIrShape[],
ModelName extends string,
Model extends Record<string, unknown>,
Res = unknown, // defaulting `unknown` because it gets absorbed in an intersection, e.g. `{a: 1} & unknown` => `{a: 1}`
> = SecondaryIdxTuple extends [
infer A extends SecondaryIndexIrShape,
...infer B extends SecondaryIndexIrShape[],
]
? IndexQueryMethodsFromIR<B, Model, IndexQueryMethodSignature<A, Model> & Res>
? IndexQueryMethodsFromIR<
B,
ModelName,
Model,
IndexQueryMethodSignature<A, ModelName, Model> & Res
>
: Res;

type IndexQueryMethodSignature<
Idx extends SecondaryIndexIrShape,
ModelName extends string,
Model extends Record<string, unknown>,
> = {
[K in Idx['queryField'] & string]: <
> = Record<
IsEmptyStringOrNever<Idx['queryField']> extends false
? Idx['queryField']
: `list${ModelName}By${Idx['defaultQueryFieldSuffix']}`,
<
FlatModel extends Record<string, unknown> = ResolvedModel<Model>,
SelectionSet extends ReadonlyArray<ModelPath<FlatModel>> = never[],
>(
Expand All @@ -892,8 +913,8 @@ type IndexQueryMethodSignature<
authToken?: string;
headers?: CustomHeaders;
},
) => ListReturnValue<Prettify<ReturnValue<Model, FlatModel, SelectionSet>>>;
};
) => ListReturnValue<Prettify<ReturnValue<Model, FlatModel, SelectionSet>>>
>;

type FilteredKeys<T> = {
[P in keyof T]: T[P] extends never ? never : P;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ describe('secondary indexes / index queries', () => {
// Doing the following input type validation as an alternative:

// Valid key input
client.models.Post.listByTitle(
client.models.Post.listPostByTitle(
{
title: 'abc',
},
Expand All @@ -58,7 +58,7 @@ describe('secondary indexes / index queries', () => {
});

test('Return type', async () => {
const { data: posts } = await client.models.Post.listByTitle(
const { data: posts } = await client.models.Post.listPostByTitle(
{
title: 'abc',
},
Expand All @@ -81,7 +81,7 @@ describe('secondary indexes / index queries', () => {
});

test('Custom selection set return type', async () => {
const { data: posts } = await client.models.Post.listByTitle(
const { data: posts } = await client.models.Post.listPostByTitle(
{
title: 'abc',
},
Expand Down
2 changes: 1 addition & 1 deletion packages/integration-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"@aws-amplify/data-schema-types": "*",
"@tsd/typescript": "^5.1.6",
"@types/jest": "29.5.4",
"aws-amplify": "*",
"aws-amplify": "unstable",
"jest": "^29.7.0",
"jest-tsd": "^0.2.2",
"ts-jest": "^29.1.1"
Expand Down

0 comments on commit 2d66909

Please sign in to comment.