11import { expectTypeTestsToPassAsync } from 'jest-tsd' ;
2- import { ClientSchema , a } from '../src/index' ;
3- import { ExtractModelMeta , Prettify } from '@aws-amplify/data-schema-types' ;
2+ import { a } from '../src/index' ;
43
54// evaluates type defs in corresponding test-d.ts file
65it ( 'should not produce static type errors' , async ( ) => {
@@ -75,6 +74,132 @@ describe('secondary index schema generation', () => {
7574 } ) ;
7675} ) ;
7776
77+ describe ( 'GSI projection functionality' , ( ) => {
78+ it ( 'generates correct schema for KEYS_ONLY projection' , ( ) => {
79+ const schema = a
80+ . schema ( {
81+ Product : a
82+ . model ( {
83+ id : a . id ( ) . required ( ) ,
84+ name : a . string ( ) . required ( ) ,
85+ category : a . string ( ) . required ( ) ,
86+ price : a . float ( ) . required ( ) ,
87+ inStock : a . boolean ( ) . required ( ) ,
88+ } )
89+ . secondaryIndexes ( ( index ) => [
90+ index ( 'category' ) . projection ( 'KEYS_ONLY' ) ,
91+ ] ) ,
92+ } )
93+ . authorization ( ( allow ) => allow . publicApiKey ( ) ) ;
94+
95+ const transformed = schema . transform ( ) . schema ;
96+
97+ expect ( transformed ) . toContain ( 'projection: { type: KEYS_ONLY }' ) ;
98+ expect ( transformed ) . not . toContain ( 'nonKeyAttributes' ) ;
99+ expect ( transformed ) . toMatchSnapshot ( ) ;
100+ } ) ;
101+
102+ it ( 'generates correct schema for INCLUDE projection with nonKeyAttributes' , ( ) => {
103+ const schema = a
104+ . schema ( {
105+ Product : a
106+ . model ( {
107+ id : a . id ( ) . required ( ) ,
108+ name : a . string ( ) . required ( ) ,
109+ category : a . string ( ) . required ( ) ,
110+ price : a . float ( ) . required ( ) ,
111+ inStock : a . boolean ( ) . required ( ) ,
112+ } )
113+ . secondaryIndexes ( ( index ) => [
114+ index ( 'category' ) . projection ( 'INCLUDE' , [ 'name' , 'price' ] ) ,
115+ ] ) ,
116+ } )
117+ . authorization ( ( allow ) => allow . publicApiKey ( ) ) ;
118+
119+ const transformed = schema . transform ( ) . schema ;
120+
121+ expect ( transformed ) . toContain (
122+ 'projection: { type: INCLUDE, nonKeyAttributes: ["name", "price"] }' ,
123+ ) ;
124+ expect ( transformed ) . toMatchSnapshot ( ) ;
125+ } ) ;
126+
127+ it ( 'generates correct schema for ALL projection' , ( ) => {
128+ const schema = a
129+ . schema ( {
130+ Product : a
131+ . model ( {
132+ id : a . id ( ) . required ( ) ,
133+ name : a . string ( ) . required ( ) ,
134+ category : a . string ( ) . required ( ) ,
135+ price : a . float ( ) . required ( ) ,
136+ inStock : a . boolean ( ) . required ( ) ,
137+ } )
138+ . secondaryIndexes ( ( index ) => [ index ( 'category' ) . projection ( 'ALL' ) ] ) ,
139+ } )
140+ . authorization ( ( allow ) => allow . publicApiKey ( ) ) ;
141+
142+ const transformed = schema . transform ( ) . schema ;
143+
144+ // When projection is ALL and no explicit projection is set, it may be omitted from output
145+ expect ( transformed ) . toContain ( '@index' ) ;
146+ expect ( transformed ) . not . toContain ( 'nonKeyAttributes' ) ;
147+ expect ( transformed ) . toMatchSnapshot ( ) ;
148+ } ) ;
149+
150+ it ( 'generates correct schema for multiple indexes with different projection types' , ( ) => {
151+ const schema = a
152+ . schema ( {
153+ Order : a
154+ . model ( {
155+ id : a . id ( ) . required ( ) ,
156+ customerId : a . string ( ) . required ( ) ,
157+ status : a . string ( ) . required ( ) ,
158+ total : a . float ( ) . required ( ) ,
159+ createdAt : a . datetime ( ) . required ( ) ,
160+ } )
161+ . secondaryIndexes ( ( index ) => [
162+ index ( 'customerId' ) . projection ( 'ALL' ) ,
163+ index ( 'status' ) . projection ( 'INCLUDE' , [ 'customerId' , 'total' ] ) ,
164+ index ( 'createdAt' ) . projection ( 'KEYS_ONLY' ) ,
165+ ] ) ,
166+ } )
167+ . authorization ( ( allow ) => allow . publicApiKey ( ) ) ;
168+
169+ const transformed = schema . transform ( ) . schema ;
170+
171+ expect ( transformed ) . toContain (
172+ 'projection: { type: INCLUDE, nonKeyAttributes: ["customerId", "total"] }' ,
173+ ) ;
174+ expect ( transformed ) . toContain ( 'projection: { type: KEYS_ONLY }' ) ;
175+ expect ( transformed ) . toMatchSnapshot ( ) ;
176+ } ) ;
177+
178+ it ( 'generates correct schema without projection (defaults to ALL)' , ( ) => {
179+ const schema = a
180+ . schema ( {
181+ Product : a
182+ . model ( {
183+ id : a . id ( ) . required ( ) ,
184+ name : a . string ( ) . required ( ) ,
185+ category : a . string ( ) . required ( ) ,
186+ price : a . float ( ) . required ( ) ,
187+ } )
188+ . secondaryIndexes ( ( index ) => [
189+ index ( 'category' ) , // No projection specified, should default to ALL
190+ ] ) ,
191+ } )
192+ . authorization ( ( allow ) => allow . publicApiKey ( ) ) ;
193+
194+ const transformed = schema . transform ( ) . schema ;
195+
196+ // When no projection is specified, it defaults to ALL and may be omitted from output
197+ expect ( transformed ) . toContain ( '@index' ) ;
198+ expect ( transformed ) . not . toContain ( 'nonKeyAttributes' ) ;
199+ expect ( transformed ) . toMatchSnapshot ( ) ;
200+ } ) ;
201+ } ) ;
202+
78203describe ( 'SchemaProcessor validation against secondary indexes' , ( ) => {
79204 it ( 'throws error when a.ref() used as the index partition key points to a non-existing type' , ( ) => {
80205 const schema = a . schema ( {
@@ -138,9 +263,7 @@ describe('SchemaProcessor validation against secondary indexes', () => {
138263 content : a . string ( ) ,
139264 status : a . enum ( [ 'open' , 'in_progress' , 'completed' ] ) ,
140265 } )
141- . secondaryIndexes ( ( index ) => [
142- index ( 'status' ) . sortKeys ( [ 'title' ] )
143- ] ) ,
266+ . secondaryIndexes ( ( index ) => [ index ( 'status' ) . sortKeys ( [ 'title' ] ) ] ) ,
144267 } )
145268 . authorization ( ( allow ) => allow . publicApiKey ( ) ) ;
146269
@@ -157,7 +280,9 @@ describe('SchemaProcessor validation against secondary indexes', () => {
157280 status : a . enum ( [ 'open' , 'in_progress' , 'completed' ] ) ,
158281 } )
159282 . secondaryIndexes ( ( index ) => [
160- index ( 'status' ) . sortKeys ( [ 'title' ] ) . queryField ( 'userDefinedQueryField' )
283+ index ( 'status' )
284+ . sortKeys ( [ 'title' ] )
285+ . queryField ( 'userDefinedQueryField' ) ,
161286 ] ) ,
162287 } )
163288 . authorization ( ( allow ) => allow . publicApiKey ( ) ) ;
@@ -175,7 +300,7 @@ describe('SchemaProcessor validation against secondary indexes', () => {
175300 status : a . enum ( [ 'open' , 'in_progress' , 'completed' ] ) ,
176301 } )
177302 . secondaryIndexes ( ( index ) => [
178- index ( 'status' ) . sortKeys ( [ 'title' ] ) . queryField ( null )
303+ index ( 'status' ) . sortKeys ( [ 'title' ] ) . queryField ( null ) ,
179304 ] ) ,
180305 } )
181306 . authorization ( ( allow ) => allow . publicApiKey ( ) ) ;
0 commit comments