Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow customtypes ref in arguments/main #497

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
e7f97fa
feat(custom-operations): allow CustomType and RefType in arguments
vaisshnavi7 Nov 8, 2024
0e0561e
Refactor type tests for CustomType and RefType
vaisshnavi7 Nov 8, 2024
1a54cde
Merge branch 'main' into feat/allow-customtype-ref-in-arguments
vaisshnavi7 Nov 13, 2024
ecf2ec2
Merge branch 'main' into feat/allow-customtype-ref-in-arguments
vaisshnavi7 Nov 21, 2024
a0872b9
feat: add support for custom, nested, and ref type arguments (#402)
vaisshnavi7 Nov 26, 2024
2f7e948
Merge branch 'main' into feat/allow-customtype-ref-in-arguments
vaisshnavi7 Nov 26, 2024
45074a3
Merge branch 'main' into feat/allow-customtype-ref-in-arguments
vaisshnavi7 Dec 11, 2024
3517643
feat: Custom type and ref arg handling in SchemaProcessor with tests …
vaisshnavi7 Jan 9, 2025
2e81a9d
Merge remote-tracking branch 'origin/main' into feat/allow-customtype…
vaisshnavi7 Jan 9, 2025
c54ed9b
Fix: Generate nested CustomTypes in schema output
vaisshnavi7 Jan 15, 2025
a7dd990
Merge branch 'main' into feat/allow-customtypes-ref-in-arguments/main
vaisshnavi7 Jan 15, 2025
cc50e20
refactor: Add tests for nested custom types and mixed refs
vaisshnavi7 Jan 15, 2025
fff0b5d
Add test for RefType with nested CustomType in complex structures
vaisshnavi7 Jan 16, 2025
f4b9171
Merge branch 'main' into feat/allow-customtypes-ref-in-arguments/main
stocaaro Jan 16, 2025
949e6ee
fix: Adjust schema component ordering to minimize enum reordering
vaisshnavi7 Jan 17, 2025
cdb02d1
Revert unnecessary changes for custom types and refs
vaisshnavi7 Jan 17, 2025
2f8c281
Merge branch 'main' into feat/allow-customtypes-ref-in-arguments/main
vaisshnavi7 Jan 21, 2025
6b82830
Add unit tests for custom operations with custom types and refs in Cu…
vaisshnavi7 Jan 22, 2025
f1b8e0e
Refactor schemaPreprocessor Consolidate schema components into single…
vaisshnavi7 Jan 23, 2025
acaa7d4
Improve tests for CustomType and RefType arguments in custom operations
vaisshnavi7 Jan 23, 2025
0f19e89
Fix: Support enums in custom types and references
vaisshnavi7 Jan 27, 2025
832a436
Remove empty block for enum ref handling in generateInputTypes
vaisshnavi7 Jan 27, 2025
3b32405
remove unused variable
vaisshnavi7 Jan 27, 2025
8ddcf13
Add unit tests for enum refs and improve ResolveFields type export
vaisshnavi7 Jan 28, 2025
a4c040e
Fix enum handling and duplication in nested custom types
vaisshnavi7 Jan 29, 2025
59c34ba
fix: lint errors for unused variables
vaisshnavi7 Jan 29, 2025
1310383
Merge branch 'main' into feat/allow-customtypes-ref-in-arguments/main
stocaaro Jan 30, 2025
bb7b4f2
test: add test cases for enum handling in arguments
vaisshnavi7 Jan 30, 2025
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/polite-crabs-rush.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@aws-amplify/data-schema": minor
---

Allow CustomType and RefType in arguments for custom operations
151 changes: 151 additions & 0 deletions packages/data-schema/__tests__/CustomOperations.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type {
import { configure } from '../src/ModelSchema';
import { Nullable } from '../src/ModelField';
import { defineFunctionStub } from './utils';
import type { CustomOperation } from '../src/CustomOperation';

describe('custom operations return types', () => {
describe('when .ref() a basic custom type', () => {
Expand Down Expand Up @@ -855,3 +856,153 @@ describe('.for() modifier', () => {
a.subscription().for(a.ref('Model'));
});
});

describe('.arguments() modifier', () => {
// Test to verify that CustomType can be used as an argument in custom operations
it('accepts CustomType in arguments', () => {
type ExpectedType = CustomOperation<
any,
'arguments' | 'for',
'queryCustomOperation'
>;

const operation = a.query().arguments({
customArg: a.customType({
field1: a.string(),
field2: a.integer(),
}),
});

type test = Expect<Equal<ExpectedType, typeof operation>>;
});

// Test to verify that RefType can be used as an argument in custom operations
it('accepts RefType in arguments', () => {
type ExpectedType = CustomOperation<
any,
'arguments' | 'for',
'queryCustomOperation'
>;

const operation = a.query().arguments({
refArg: a.ref('SomeType'),
});

type test = Expect<Equal<ExpectedType, typeof operation>>;
});

it('handles deeply nested custom types', () => {
const schema = a.schema({
DeepNested: a.customType({
level1: a.customType({
level2: a.customType({
level3: a.string(),
}),
}),
}),
deepQuery: a
.query()
.arguments({
input: a.ref('DeepNested'),
})
.returns(a.string()),
});

type Schema = ClientSchema<typeof schema>;

type ExpectedArgs = {
input?: {
level1?: {
level2?: {
level3?: string | null;
} | null;
} | null;
} | null;
};

type ActualArgs = Schema['deepQuery']['args'];

type Test = Expect<Equal<ActualArgs, ExpectedArgs>>;
});

it('handles mixed custom types and refs', () => {
const schema = a.schema({
RefType: a.customType({
field: a.string(),
}),
stocaaro marked this conversation as resolved.
Show resolved Hide resolved
MixedType: a.customType({
nested: a.customType({
refField: a.ref('RefType'),
customField: a.customType({
deepField: a.integer(),
}),
}),
}),
mixedQuery: a
.query()
.arguments({
input: a.ref('MixedType'),
})
.returns(a.string()),
});

type Schema = ClientSchema<typeof schema>;

type ExpectedArgs = {
input?: {
nested?: {
refField?: {
field?: string | null;
} | null;
customField?: {
deepField?: number | null;
} | null;
} | null;
} | null;
};

type ActualArgs = Schema['mixedQuery']['args'];

type Test = Expect<Equal<ActualArgs, ExpectedArgs>>;
});

it('handles RefType with multi-layered custom types in nested structures', () => {
const schema = a.schema({
NestedCustomType: a.customType({
nestedField: a.string(),
}),
RefType: a.customType({
field: a.string(),
nestedCustom: a.ref('NestedCustomType'),
}),
OuterType: a.customType({
refField: a.ref('RefType'),
otherField: a.integer(),
}),
complexQuery: a
.query()
.arguments({
input: a.ref('OuterType'),
})
.returns(a.string()),
});

type Schema = ClientSchema<typeof schema>;

type ExpectedArgs = {
input?: {
refField?: {
field?: string | null;
nestedCustom?: {
nestedField?: string | null;
} | null;
} | null;
otherField?: number | null;
} | null;
};

type ActualArgs = Schema['complexQuery']['args'];

type Test = Expect<Equal<ActualArgs, ExpectedArgs>>;
});
});
189 changes: 189 additions & 0 deletions packages/data-schema/__tests__/CustomOperations.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1089,6 +1089,195 @@ describe('CustomOperation transform', () => {
});
});

describe('custom operations with custom types and refs', () => {
test('Schema with custom query using custom type argument', () => {
const s = a
.schema({
CustomArgType: a.customType({
field: a.string(),
}),
queryWithCustomTypeArg: a
.query()
.arguments({ customArg: a.ref('CustomArgType') })
.returns(a.string())
.handler(a.handler.function('myFunc')),
})
.authorization((allow) => allow.publicApiKey());

const result = s.transform().schema;

expect(result).toMatchSnapshot();
});

test('Schema with custom query using ref argument', () => {
const s = a
.schema({
RefArgType: a.customType({
field: a.string(),
}),
queryWithRefArg: a
.query()
.arguments({ refArg: a.ref('RefArgType') })
.returns(a.string())
.handler(a.handler.function('myFunc')),
})
.authorization((allow) => allow.publicApiKey());

const result = s.transform().schema;

expect(result).toMatchSnapshot();
});

test('Schema with custom mutation using custom type argument', () => {
const s = a
.schema({
CustomArgType: a.customType({
field: a.string(),
}),
mutateWithCustomTypeArg: a
.mutation()
.arguments({ customArg: a.ref('CustomArgType') })
.returns(a.string())
.handler(a.handler.function('myFunc')),
})
.authorization((allow) => allow.publicApiKey());

const result = s.transform().schema;

expect(result).toMatchSnapshot();
});

test('Schema with custom mutation using ref argument', () => {
const s = a
.schema({
RefArgType: a.customType({
field: a.string(),
}),
mutationWithRefArg: a
.mutation()
.arguments({ refArg: a.ref('RefArgType') })
.returns(a.string())
.handler(a.handler.function('myFunc')),
})
.authorization((allow) => allow.publicApiKey());

const result = s.transform().schema;

expect(result).toMatchSnapshot();
});

test('Schema with custom mutation using enum ref in nested custom type', () => {
const s = a
.schema({
NestedCustomType: a.customType({
field: a.string(),
enumField: a.ref('SomeEnum'),
}),
SomeEnum: a.enum(['VALUE1', 'VALUE2']),
mutateWithNestedEnumRef: a
.mutation()
.arguments({ nestedArg: a.ref('NestedCustomType') })
.returns(a.string())
.handler(a.handler.function('myFunc')),
})
.authorization((allow) => allow.publicApiKey());

const result = s.transform().schema;

expect(result).toMatchSnapshot();
});

test('Schema with custom query using enum ref as argument', () => {
const s = a
.schema({
SomeEnum: a.enum(['OPTION1', 'OPTION2']),
queryWithEnumRefArg: a
.query()
.arguments({ enumArg: a.ref('SomeEnum') })
.returns(a.string())
.handler(a.handler.function('myFunc')),
})
.authorization((allow) => allow.publicApiKey());

const result = s.transform().schema;

expect(result).toMatchSnapshot();
});

test('Schema with custom operation using enum directly in arguments', () => {
const s = a
.schema({
directEnumQuery: a
.query()
.arguments({
status: a.enum(['PENDING', 'APPROVED', 'REJECTED']),
})
.returns(a.string())
.handler(a.handler.function('myFunc')),
})
.authorization((allow) => allow.publicApiKey());

const result = s.transform().schema;

expect(result).toMatchSnapshot();
expect(result).toContain('enum DirectEnumQueryStatus {');
expect(result).toContain(
'directEnumQuery(status: DirectEnumQueryStatus): String',
);
});

test('Schema with custom operation using enum in inline custom type arguments', () => {
const s = a
.schema({
inlineEnumQuery: a
.query()
.arguments({
input: a.customType({
name: a.string(),
status: a.enum(['ACTIVE', 'INACTIVE']),
}),
})
.returns(a.string())
.handler(a.handler.function('myFunc')),
})
.authorization((allow) => allow.publicApiKey());

const result = s.transform().schema;

expect(result).toMatchSnapshot();
expect(result).toContain('enum InlineEnumQueryInputStatus {');
expect(result).toContain('input InlineEnumQueryInput {');
expect(result).toContain(
'inlineEnumQuery(input: InlineEnumQueryInput): String',
);
});

test('Schema with custom operation using enum in referenced custom type arguments', () => {
const s = a
.schema({
StatusInput: a.customType({
name: a.string(),
status: a.enum(['NEW', 'IN_PROGRESS', 'COMPLETED']),
}),
refEnumQuery: a
.query()
.arguments({
input: a.ref('StatusInput'),
})
.returns(a.string())
.handler(a.handler.function('myFunc')),
})
.authorization((allow) => allow.publicApiKey());

const result = s.transform().schema;
Comment on lines +1256 to +1272
Copy link
Member

Choose a reason for hiding this comment

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

The snapshot for this test is odd


expect(result).toMatchSnapshot();
expect(result).toContain('enum StatusInputStatus {');
expect(result).toContain('input StatusInput {');
expect(result).toContain('refEnumQuery(input: StatusInput): String');
});
});

const fakeSecret = () => ({}) as any;

const datasourceConfigMySQL = {
Expand Down
Loading
Loading