Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
4 changes: 2 additions & 2 deletions packages/api-client-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@gadgetinc/api-client-core",
"version": "0.15.11",
"version": "0.15.12",
"files": [
"Readme.md",
"dist/**/*"
Expand Down Expand Up @@ -37,7 +37,7 @@
"graphql-ws": "^5.13.1",
"isomorphic-ws": "^5.0.0",
"klona": "^2.0.6",
"tiny-graphql-query-compiler": "^0.2.2",
"tiny-graphql-query-compiler": "^0.2.3",
"tslib": "^2.6.2",
"ws": "^8.13.0"
},
Expand Down
107 changes: 107 additions & 0 deletions packages/api-client-core/spec/Select-type.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { AssertTrue, IsExact } from "conditional-type-checks";
import { Call } from "../src/FieldSelection.js";
import type { DeepFilterNever, Select } from "../src/types.js";
import type { TestSchema } from "./TestSchema.js";

Expand Down Expand Up @@ -75,5 +76,111 @@ describe("Select<>", () => {
>
>;

const argsSelection = {
someConnection: Call({ first: 5 }, { pageInfo: { hasNextPage: true }, edges: { node: { id: true, state: true } } }),
} as const;

type _withArgsSelection = Select<TestSchema, typeof argsSelection>;

type _TestSelectingConnectionWithArgs = AssertTrue<
IsExact<
_withArgsSelection,
{
someConnection: {
pageInfo: { hasNextPage: boolean };
edges: ({ node: { id: string; state: string } | null } | null)[] | null;
};
}
>
>;

const emptyArgsSelection = {
someConnection: Call({}, { pageInfo: { hasNextPage: true }, edges: { node: { id: true, state: true } } }),
} as const;

type _withEmptyArgsSelection = Select<TestSchema, typeof emptyArgsSelection>;

type _TestSelectingConnectionWithEmptyArgs = AssertTrue<
IsExact<
_withEmptyArgsSelection,
{
someConnection: {
pageInfo: { hasNextPage: boolean };
edges: ({ node: { id: string; state: string } | null } | null)[] | null;
};
}
>
>;

const wrongArgsSelection = {
someConnection: Call({ first: "wrong type" }, { pageInfo: { hasNextPage: true }, edges: { node: { id: true, state: true } } }),
} as const;
type _withWrongArgsSelection = Select<TestSchema, typeof wrongArgsSelection>;
type _TestSelectingConnectionWithWrongArgs = AssertTrue<
IsExact<_withWrongArgsSelection, { someConnection: { $error: "incorrectly typed args passed when calling field" } }>
>;

const doesntAcceptArgsSelection = {
optionalObj: Call({ first: "wrong type" }, { test: true }),
} as const;
type _withDoesntAcceptArgsSelection = Select<TestSchema, typeof doesntAcceptArgsSelection>;
type _TestSelectingFieldWhichDoesntAcceptArgs = AssertTrue<
IsExact<_withDoesntAcceptArgsSelection, { optionalObj: { $error: "field does not accept args" } }>
>;

const doesntAcceptArgsScalarSelection = {
num: Call({ first: "wrong type" }, { test: true }),
} as const;
type _withDoesntAcceptArgsScalarSelection = Select<TestSchema, typeof doesntAcceptArgsScalarSelection>;
type _TestSelectingScalarFieldWhichDoesntAcceptArgs = AssertTrue<
IsExact<_withDoesntAcceptArgsScalarSelection, { num: { $error: "field does not accept args" } }>
>;

const nestedCallSelection = {
someConnection: Call(
{ first: 5 },
{
edges: {
node: {
id: true,
state: true,
children: Call(
{ first: 10 },
{
edges: {
node: {
id: true,
},
},
}
),
},
},
}
),
} as const;
const nestedCallNoSelection = {
someConnection: {
edges: {
node: {
id: true,
state: true,
children: {
edges: {
node: {
id: true,
},
},
},
},
},
},
} as const;

type _withNestedNoCallSelection = Select<TestSchema, typeof nestedCallNoSelection>;
type _withNestedCallSelection = Select<TestSchema, typeof nestedCallSelection>;

type _TestSelectingWithNestedCalls = AssertTrue<IsExact<_withNestedCallSelection, _withNestedNoCallSelection>>;

test("true", () => undefined);
});
26 changes: 26 additions & 0 deletions packages/api-client-core/spec/TestSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,37 @@ export type TestSchema = {
}[]
| null;
someConnection: {
["$args"]: {
first?: number;
last?: number;
before?: string;
after?: string;
};
edges:
| ({
node: {
id: string;
state: string;
children: {
["$args"]: {
first?: number;
last?: number;
before?: string;
after?: string;
};
pageInfo: {
hasNextPage: boolean;
hasPreviousPage: boolean;
};
edges:
| ({
node: {
id: string;
state: string;
};
} | null)[]
| null;
};
} | null;
} | null)[]
| null;
Expand Down
169 changes: 168 additions & 1 deletion packages/api-client-core/spec/operationBuilders.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { actionOperation, findManyOperation, findOneByFieldOperation, findOneOperation } from "../src/index.js";
import { Call, actionOperation, findManyOperation, findOneByFieldOperation, findOneOperation } from "../src/index.js";

describe("operation builders", () => {
describe("findOneOperation", () => {
Expand Down Expand Up @@ -63,6 +63,41 @@ describe("operation builders", () => {
}
`);
});

test("findOneOperation should build a query with a call in it", () => {
expect(
findOneOperation(
"widget",
"123",
{ __typename: true, id: true, state: true, gizmos: Call({ first: 10 }, { edges: { node: { id: true } } }) },
"widget",
{ live: true }
)
).toMatchInlineSnapshot(`
{
"query": "query widget($id: GadgetID!) @live {
widget(id: $id) {
__typename
id
state
gizmos(first: 10) {
edges {
node {
id
}
}
}
}
gadgetMeta {
hydrations(modelName: "widget")
}
}",
"variables": {
"id": "123",
},
}
`);
});
});

describe("findManyOperation", () => {
Expand Down Expand Up @@ -259,6 +294,92 @@ describe("operation builders", () => {
}
`);
});

test("findManyOperation should build a query with arguments in it", () => {
expect(
findManyOperation(
"widgets",
{ __typename: true, id: true, state: true, gizmos: Call({ first: 10, after: "foobar" }, { edges: { node: { id: true } } }) },
"widget",
{ live: true }
)
).toMatchInlineSnapshot(`
{
"query": "query widgets($after: String, $first: Int, $before: String, $last: Int) @live {
widgets(after: $after, first: $first, before: $before, last: $last) {
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
edges {
cursor
node {
__typename
id
state
gizmos(first: 10, after: "foobar") {
edges {
node {
id
}
}
}
}
}
}
gadgetMeta {
hydrations(modelName: "widget")
}
}",
"variables": {},
}
`);
});

test("findManyOperation should build a query with a call but no arguments", () => {
expect(
findManyOperation(
"widgets",
{ __typename: true, id: true, state: true, gizmos: Call({}, { edges: { node: { id: true } } }) },
"widget",
{ live: true }
)
).toMatchInlineSnapshot(`
{
"query": "query widgets($after: String, $first: Int, $before: String, $last: Int) @live {
widgets(after: $after, first: $first, before: $before, last: $last) {
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
edges {
cursor
node {
__typename
id
state
gizmos {
edges {
node {
id
}
}
}
}
}
}
gadgetMeta {
hydrations(modelName: "widget")
}
}",
"variables": {},
}
`);
});
});

describe("findOneByFieldOperation", () => {
Expand Down Expand Up @@ -577,5 +698,51 @@ describe("operation builders", () => {
}
`);
});

test("actionOperation should build a mutation query for a result that has a call in it", () => {
expect(
actionOperation(
"createWidget",
{ __typename: true, id: true, state: true, gizmos: Call({ first: 10 }, { edges: { node: { id: true } } }) },
"widget",
"widget",
{}
)
).toMatchInlineSnapshot(`
{
"query": "mutation createWidget {
createWidget {
success
errors {
message
code
... on InvalidRecordError {
validationErrors {
message
apiIdentifier
}
}
}
widget {
__typename
id
state
gizmos(first: 10) {
edges {
node {
id
}
}
}
}
}
gadgetMeta {
hydrations(modelName: "widget")
}
}",
"variables": {},
}
`);
});
});
});
Loading