diff --git a/.changeset/wise-mangos-kick.md b/.changeset/wise-mangos-kick.md
new file mode 100644
index 0000000..6377d81
--- /dev/null
+++ b/.changeset/wise-mangos-kick.md
@@ -0,0 +1,5 @@
+---
+'@0no-co/graphqlsp': patch
+---
+
+Add fix for nonNullAssertion and using Array.at
diff --git a/packages/example-tada/src/index.tsx b/packages/example-tada/src/index.tsx
index 6ddd4fa..edcd7e9 100644
--- a/packages/example-tada/src/index.tsx
+++ b/packages/example-tada/src/index.tsx
@@ -21,6 +21,12 @@ const PokemonQuery = graphql(`
name
__typename
}
+ pokemons {
+ name
+ maxCP
+ maxHP
+ types
+ }
}
`, [PokemonFields]);
@@ -30,6 +36,14 @@ const Pokemons = () => {
variables: { id: '' }
});
+ const selected = result.data?.pokemons?.at(0)!
+ console.log(result.data?.pokemons?.at(0)?.maxCP)
+ console.log(selected.maxHP)
+ const names = result.data?.pokemons?.map(x => x?.name)
+ console.log(names)
+ const pos = result.data?.pokemons?.map(x => ({ ...x }))
+ console.log(pos && pos[0].types)
+
// Works
console.log(result.data?.pokemon?.attacks && result.data?.pokemon?.attacks.special && result.data?.pokemon?.attacks.special[0] && result.data?.pokemon?.attacks.special[0].name)
@@ -49,4 +63,3 @@ const Pokemons = () => {
return ;
}
-
diff --git a/packages/example-tada/tsconfig.json b/packages/example-tada/tsconfig.json
index c1971a3..dcfaf25 100644
--- a/packages/example-tada/tsconfig.json
+++ b/packages/example-tada/tsconfig.json
@@ -4,9 +4,6 @@
{
"name": "@0no-co/graphqlsp",
"schema": "./schema.graphql",
- "disableTypegen": true,
- "shouldCheckForColocatedFragments": true,
- "trackFieldUsage": true,
"tadaOutputLocation": "./introspection.ts"
}
],
diff --git a/packages/graphqlsp/package.json b/packages/graphqlsp/package.json
index 1c4a6e1..253287f 100644
--- a/packages/graphqlsp/package.json
+++ b/packages/graphqlsp/package.json
@@ -36,6 +36,7 @@
},
"homepage": "https://github.com/0no-co/GraphQLSP#readme",
"devDependencies": {
+ "@0no-co/graphql.web": "^1.0.4",
"@sindresorhus/fnv1a": "^2.0.0",
"@types/node": "^18.15.11",
"@types/node-fetch": "^2.6.3",
diff --git a/packages/graphqlsp/src/fieldUsage.ts b/packages/graphqlsp/src/fieldUsage.ts
index c7b0c3e..e53498a 100644
--- a/packages/graphqlsp/src/fieldUsage.ts
+++ b/packages/graphqlsp/src/fieldUsage.ts
@@ -69,6 +69,17 @@ const traverseDestructuring = (
return results;
};
+const arrayMethods = new Set([
+ 'map',
+ 'filter',
+ 'forEach',
+ 'reduce',
+ 'every',
+ 'some',
+ 'find',
+ 'flatMap',
+ 'sort',
+]);
const crawlScope = (
node: ts.Identifier | ts.BindingName,
originalWip: Array,
@@ -146,6 +157,52 @@ const crawlScope = (
!pathParts.includes(foundRef.text)
) {
pathParts.push(foundRef.text);
+ } else if (
+ ts.isPropertyAccessExpression(foundRef) &&
+ foundRef.name.text === 'at' &&
+ ts.isCallExpression(foundRef.parent)
+ ) {
+ foundRef = foundRef.parent;
+ } else if (
+ ts.isPropertyAccessExpression(foundRef) &&
+ arrayMethods.has(foundRef.name.text) &&
+ ts.isCallExpression(foundRef.parent)
+ ) {
+ const isReduce = foundRef.name.text === 'reduce';
+ const isSomeOrEvery =
+ foundRef.name.text === 'every' || foundRef.name.text === 'some';
+ const callExpression = foundRef.parent;
+ const func = callExpression.arguments[0];
+ if (ts.isFunctionExpression(func) || ts.isArrowFunction(func)) {
+ const param = func.parameters[isReduce ? 1 : 0];
+ const res = crawlScope(
+ param.name,
+ pathParts,
+ allFields,
+ source,
+ info
+ );
+
+ // TODO: do we need to support variable destructuring here like
+ // .map being used in const [x] = list.map()?
+ if (
+ ts.isVariableDeclaration(callExpression.parent) &&
+ !isSomeOrEvery
+ ) {
+ const varRes = crawlScope(
+ callExpression.parent.name,
+ pathParts,
+ allFields,
+ source,
+ info
+ );
+ res.push(...varRes);
+ }
+
+ return res;
+ } else if (ts.isIdentifier(func)) {
+ // TODO: get the function and do the same as the above
+ }
} else if (
ts.isPropertyAccessExpression(foundRef) &&
allFields.includes(foundRef.name.text) &&
@@ -161,7 +218,11 @@ const crawlScope = (
pathParts.push(foundRef.argumentExpression.text);
}
- foundRef = foundRef.parent;
+ if (ts.isNonNullExpression(foundRef.parent)) {
+ foundRef = foundRef.parent.parent;
+ } else {
+ foundRef = foundRef.parent;
+ }
}
return pathParts.join('.');
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 39c8a6f..809bafc 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -171,6 +171,9 @@ importers:
specifier: ^2.0.0
version: 2.6.7
devDependencies:
+ '@0no-co/graphql.web':
+ specifier: ^1.0.4
+ version: 1.0.4(graphql@16.8.1)
'@sindresorhus/fnv1a':
specifier: ^2.0.0
version: 2.0.1
@@ -264,7 +267,6 @@ packages:
optional: true
dependencies:
graphql: 16.8.1
- dev: false
/@ampproject/remapping@2.2.1:
resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==}
@@ -3422,7 +3424,7 @@ packages:
object-assign: 4.1.1
promise: 7.3.1
setimmediate: 1.0.5
- ua-parser-js: 1.0.37
+ ua-parser-js: 0.7.37
transitivePeerDependencies:
- encoding
dev: true
@@ -4587,7 +4589,7 @@ packages:
dependencies:
hosted-git-info: 2.8.9
resolve: 1.22.2
- semver: 7.5.4
+ semver: 5.7.2
validate-npm-package-license: 3.0.4
dev: true
@@ -5171,6 +5173,11 @@ packages:
resolution: {integrity: sha512-MuCAyrGZcTLfQoH2XoBlQ8C6bzwN88XT/0slOGz0pn8+gIP85BOAfYa44ZXQUTOwRwPU0QvgU+V+OSajl/59Xg==}
dev: true
+ /semver@5.7.2:
+ resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==}
+ hasBin: true
+ dev: true
+
/semver@6.3.1:
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
hasBin: true
@@ -5687,8 +5694,8 @@ packages:
hasBin: true
dev: true
- /ua-parser-js@1.0.37:
- resolution: {integrity: sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==}
+ /ua-parser-js@0.7.37:
+ resolution: {integrity: sha512-xV8kqRKM+jhMvcHWUKthV9fNebIzrNy//2O9ZwWcfiBFR5f25XVZPLlEajk/sf3Ra15V92isyQqnIEXRDaZWEA==}
dev: true
/ufo@1.3.1: