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

TypeScript strict mode support + docs #5491

Merged
merged 83 commits into from
Jul 25, 2022
Merged
Show file tree
Hide file tree
Changes from 76 commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
eb2d15b
Add function retrieve tsconfig from proejct to structure
dac09 May 9, 2022
df5844a
Move tsconfig detection to internal
dac09 May 10, 2022
448ad56
Merge branch 'main' of github.com:redwoodjs/redwood into feat/ts-stri…
dac09 May 10, 2022
6784575
Change resolver when strict mode is on
dac09 May 10, 2022
9bdb866
Additional info on how to configure codegen
dac09 May 10, 2022
217b4e5
Keep obj optional
dac09 May 11, 2022
1da9eb2
Strict typing dbAuth handler | Export types
dac09 May 15, 2022
79dd5f7
Update resolverFn return types to handle when promises are passed in …
dac09 May 16, 2022
e8a1e09
Expose Scenario data type
dac09 May 16, 2022
4ceb0b8
Update scenario, test and service templates
dac09 May 16, 2022
b1968fd
Update dbAuth templates for function and src/lib/auth
dac09 May 17, 2022
8f43558
Scenario types: Use camel name for prisma model name
dac09 May 17, 2022
2e58a4c
Give DbAuthSession number generic by default in generator
dac09 May 17, 2022
fc6a383
Optional chaining to all errors in cell templates
dac09 May 17, 2022
ba6ed98
CellSuccessGuarantee + Name, Names, EditName, NewName templates in sc…
dac09 May 18, 2022
a0d8ba4
Form scaffold type changes | Expose required types from rwjs/forms
dac09 May 19, 2022
9238015
Avoid Cell types in scaffolded components
dac09 May 19, 2022
80640db
Update snapshots
dac09 May 19, 2022
4756041
Dont use partials in ResoverFn ReturnType
dac09 May 19, 2022
64b1c01
Merge branch 'main' into feat/ts-strictmode-gen
dac09 May 20, 2022
f951881
Optional id in scaffolded forms
dac09 May 20, 2022
959c960
Merge branch 'main' of github.com:redwoodjs/redwood into feat/ts-stri…
dac09 Jun 7, 2022
c336e97
Merge branch 'main' of github.com:redwoodjs/redwood into feat/ts-stri…
dac09 Jun 14, 2022
6319380
Initial docs setup for TS
dac09 Jun 15, 2022
85ed9fa
Update snapshot for service test
dac09 Jun 16, 2022
626264e
Update lib/auth templates
dac09 Jun 16, 2022
980e40d
WIP: strict mode docs
dac09 Jun 16, 2022
e3702e6
Update dbAuth types
dac09 Jun 20, 2022
57a5527
Merge branch 'main' of github.com:redwoodjs/redwood into feat/ts-stri…
dac09 Jun 20, 2022
58062a6
wip
dac09 Jun 21, 2022
f3ffff6
Add content about typing currentUser
dac09 Jun 21, 2022
735bfd9
Update gql resolver docs
dac09 Jun 22, 2022
f528fe8
Use inferred current user in mockCurrentUser types
dac09 Jun 23, 2022
9e04a3b
WIP: utility types
dac09 Jun 23, 2022
1c89c0a
Merge branch 'main' of github.com:redwoodjs/redwood into feat/ts-stri…
dac09 Jun 23, 2022
091858d
Write up utility types
dac09 Jun 23, 2022
75c8390
Add backlinks from Cells and Scenarios
dac09 Jun 23, 2022
4b1d3df
Fix broken links
dac09 Jun 23, 2022
8be7cb9
Another broken link
dac09 Jun 23, 2022
46872d4
Undo accidental change to authClients
dac09 Jun 24, 2022
962dfd4
Final ts issue fixes
dac09 Jun 24, 2022
9cd0870
Update dbAuth web templates
dac09 Jun 24, 2022
e463b12
Rebuild fixture
dac09 Jun 24, 2022
3ef64d3
Update scaffold snapshots
dac09 Jun 24, 2022
4d840fc
Merge branch 'main' into feat/ts-strictmode-gen
dac09 Jun 27, 2022
d596958
Add blurb about currentUser types
dac09 Jun 28, 2022
d6d609b
Merge branch 'main' into feat/ts-strictmode-gen
dac09 Jun 30, 2022
4512182
Merge branch 'main' into feat/ts-strictmode-gen
dac09 Jul 1, 2022
991a314
chore: update docs
jtoar Jul 2, 2022
1d46fd5
Rename generic name for Scenarios
dac09 Jul 2, 2022
5d54dc2
Finish sentences in strict-mode doc
dac09 Jul 2, 2022
9121751
Update docs/docs/typescript/generated-types.md
dac09 Jul 2, 2022
a8db898
Include scripts config in strictmode
dac09 Jul 2, 2022
128a05e
Merge branch 'main' into feat/ts-strictmode-gen
dac09 Jul 6, 2022
327fa21
Restore partials in resolver types
dac09 Jul 6, 2022
f91d10c
Fix truncate in scaffold tempalte
dac09 Jul 6, 2022
9dc43df
Rebuild fixture again
dac09 Jul 6, 2022
2ee52b6
Make Promise check in ResolverFn less specific
dac09 Jul 6, 2022
ae06e80
Update snapshots again
dac09 Jul 6, 2022
3076531
Update docs/docs/typescript/utility-types.md
dac09 Jul 7, 2022
ac1e53e
Update packages/api/src/functions/dbAuth/DbAuthHandler.ts
dac09 Jul 7, 2022
9ae0d48
Simplify truncate function in scaffold template
dac09 Jul 7, 2022
346f0b1
Merge branch 'main' of github.com:redwoodjs/redwood into feat/ts-stri…
dac09 Jul 12, 2022
957f9dd
Update resolverFn yet again
dac09 Jul 12, 2022
aecf6f6
Use const instead of let
dac09 Jul 21, 2022
50e91f3
Update docs/docs/typescript/generated-types.md
dac09 Jul 21, 2022
e037c5d
Update docs/docs/typescript/generated-types.md
dac09 Jul 21, 2022
b410e0b
Update docs/docs/typescript/generated-types.md
dac09 Jul 21, 2022
d3ee172
Update statement about generated resolver types
dac09 Jul 21, 2022
26305df
Merge branch 'feat/ts-strictmode-gen' of github.com:dac09/redwood int…
dac09 Jul 21, 2022
0791d43
Merge branch 'main' into feat/ts-strictmode-gen
cannikin Jul 21, 2022
c8c4c4f
Merge branch 'feat/ts-strictmode-gen' of github.com:dac09/redwood int…
dac09 Jul 22, 2022
d667d13
Merge branch 'main' of github.com:redwoodjs/redwood into feat/ts-stri…
dac09 Jul 22, 2022
fc0e34e
Fix merge of dbAuthHandler
dac09 Jul 22, 2022
722ec1e
Rebuild fixture
dac09 Jul 22, 2022
68c864d
Merge branch 'main' into feat/ts-strictmode-gen
dac09 Jul 22, 2022
582543e
Merge branch 'main' into feat/ts-strictmode-gen
dac09 Jul 24, 2022
a39536e
Add missing args in storybook replace
dac09 Jul 25, 2022
4f07de0
Merge branch 'main' into feat/ts-strictmode-gen
dac09 Jul 25, 2022
e5e8d9a
Update type import and rebuild fixture
dac09 Jul 25, 2022
3cd9a72
Merge branch 'main' of github.com:redwoodjs/redwood into feat/ts-stri…
dac09 Jul 25, 2022
d6d9cfb
Rebuild fixture again
dac09 Jul 25, 2022
049ee24
Fix casing on RWGqlError
dac09 Jul 25, 2022
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
1 change: 1 addition & 0 deletions __fixtures__/test-project/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ yarn-error.log
web/public/mockServiceWorker.js
web/types/graphql.d.ts
api/types/graphql.d.ts
api/src/lib/generateGraphiQLHeader.*
.pnp.*
.yarn/*
!.yarn/patches
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ describe('requireAuth directive', () => {
// If you want to set values in context, pass it through e.g.
// mockRedwoodDirective(requireAuth, { context: { currentUser: { id: 1, name: 'Lebron McGretzky' } }})
const mockExecution = mockRedwoodDirective(requireAuth, {
context: { currentUser: { id: 1, roles: 'ADMIN', email: '[email protected]' } },
})
context: { currentUser: { id: 1, roles: 'ADMIN', email: '[email protected]' } },
})

expect(mockExecution).not.toThrowError()
})
Expand Down
20 changes: 13 additions & 7 deletions __fixtures__/test-project/api/src/functions/auth.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import { db } from 'src/lib/db'
import type { APIGatewayProxyEvent, Context } from 'aws-lambda'

import { DbAuthHandler } from '@redwoodjs/api'
import type { DbAuthHandlerOptions } from '@redwoodjs/api'

export const handler = async (event, context) => {
import { db } from 'src/lib/db'

const forgotPasswordOptions = {
export const handler = async (
event: APIGatewayProxyEvent,
context: Context
) => {
const forgotPasswordOptions: DbAuthHandlerOptions['forgotPassword'] = {
// handler() is invoked after verifying that a user was found with the given
// username. This is where you can send the user an email with a link to
// reset their password. With the default dbAuth routes and field names, the
Expand Down Expand Up @@ -33,7 +39,7 @@ export const handler = async (event, context) => {
},
}

const loginOptions = {
const loginOptions: DbAuthHandlerOptions['login'] = {
// handler() is called after finding the user that matches the
// username/password provided at login, but before actually considering them
// logged in. The `user` argument will be the user in the database that
Expand Down Expand Up @@ -62,13 +68,13 @@ export const handler = async (event, context) => {
expires: 60 * 60 * 24 * 365 * 10,
}

const resetPasswordOptions = {
const resetPasswordOptions: DbAuthHandlerOptions['resetPassword'] = {
// handler() is invoked after the password has been successfully updated in
// the database. Returning anything truthy will automatically log the user
// in. Return `false` otherwise, and in the Reset Password page redirect the
// user to the login page.
handler: (user) => {
return user
return !!user
},

// If `false` then the new password MUST be different from the current one
Expand All @@ -86,7 +92,7 @@ export const handler = async (event, context) => {
},
}

const signupOptions = {
const signupOptions: DbAuthHandlerOptions['signup'] = {
// Whatever you want to happen to your data on new user signup. Redwood will
// check for duplicate usernames before calling this handler. At a minimum
// you need to save the `username`, `hashedPassword` and `salt` to your
Expand Down
3 changes: 1 addition & 2 deletions __fixtures__/test-project/api/src/functions/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ import { createGraphQLHandler } from '@redwoodjs/graphql-server'

import directives from 'src/directives/**/*.{js,ts}'
import sdls from 'src/graphql/**/*.sdl.{js,ts}'
import { getCurrentUser } from 'src/lib/auth'
import { db } from 'src/lib/db'
import { logger } from 'src/lib/logger'
import services from 'src/services/**/*.{js,ts}'

import { getCurrentUser } from 'src/lib/auth'

export const handler = createGraphQLHandler({
getCurrentUser,
loggerConfig: { logger, options: {} },
Expand Down
2 changes: 1 addition & 1 deletion __fixtures__/test-project/api/src/graphql/contacts.sdl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ export const schema = gql`
type Mutation {
createContact(input: CreateContactInput!): Contact @skipAuth
updateContact(id: Int!, input: UpdateContactInput!): Contact! @requireAuth
deleteContact(id: Int!): Contact! @requireAuth(roles:["ADMIN"])
deleteContact(id: Int!): Contact! @requireAuth(roles: ["ADMIN"])
}
`
2 changes: 1 addition & 1 deletion __fixtures__/test-project/api/src/graphql/posts.sdl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const schema = gql`

type Query {
posts: [Post!]! @skipAuth
post(id: Int!): Post @skipAuth
post(id: Int!): Post @skipAuth
}

input CreatePostInput {
Expand Down
8 changes: 5 additions & 3 deletions __fixtures__/test-project/api/src/lib/auth.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import type { DbAuthSession } from '@redwoodjs/api'
import { AuthenticationError, ForbiddenError } from '@redwoodjs/graphql-server'

import { db } from './db'

/**
Expand All @@ -18,10 +20,10 @@ import { db } from './db'
* fields to the `select` object below once you've decided they are safe to be
* seen if someone were to open the Web Inspector in their browser.
*/
export const getCurrentUser = async (session) => {
export const getCurrentUser = async (session: DbAuthSession<number>) => {
return await db.user.findUnique({
where: { id: session.id },
select: { id: true, roles: true, email: true},
select: { id: true, roles: true, email: true },
})
}

Expand Down Expand Up @@ -71,7 +73,7 @@ export const hasRole = (roles: AllowedRoles): boolean => {
return currentUserRoles?.some((allowedRole) =>
roles.includes(allowedRole)
)
} else if (typeof context.currentUser.roles === 'string') {
} else if (typeof context?.currentUser?.roles === 'string') {
// roles to check is an array, currentUser.roles is a string
return roles.some(
(allowedRole) => context.currentUser?.roles === allowedRole
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import type { Prisma } from '@prisma/client'
import type { Prisma, Contact } from '@prisma/client'

import type { ScenarioData } from '@redwoodjs/testing/api'

export const standard = defineScenario<Prisma.ContactCreateArgs>({
contact: {
Expand All @@ -7,4 +9,4 @@ export const standard = defineScenario<Prisma.ContactCreateArgs>({
},
})

export type StandardScenario = typeof standard
export type StandardScenario = ScenarioData<Contact, 'contact'>
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { Contact } from '@prisma/client'

import {
contacts,
contact,
Expand Down Expand Up @@ -37,7 +39,7 @@ describe('contacts', () => {
})

scenario('updates a contact', async (scenario: StandardScenario) => {
const original = await contact({ id: scenario.contact.one.id })
const original = (await contact({ id: scenario.contact.one.id })) as Contact
const result = await updateContact({
id: original.id,
input: { name: 'String2' },
Expand All @@ -47,7 +49,9 @@ describe('contacts', () => {
})

scenario('deletes a contact', async (scenario: StandardScenario) => {
const original = await deleteContact({ id: scenario.contact.one.id })
const original = (await deleteContact({
id: scenario.contact.one.id,
})) as Contact
const result = await contact({ id: original.id })

expect(result).toEqual(null)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import type { Prisma } from '@prisma/client'
import type { Prisma, Post } from '@prisma/client'

import type { ScenarioData } from '@redwoodjs/testing/api'

export const standard = defineScenario<Prisma.PostCreateArgs>({
post: {
Expand All @@ -7,4 +9,4 @@ export const standard = defineScenario<Prisma.PostCreateArgs>({
},
})

export type StandardScenario = typeof standard
export type StandardScenario = ScenarioData<Post, 'post'>
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { Post } from '@prisma/client'

import { posts, post, createPost, updatePost, deletePost } from './posts'
import type { StandardScenario } from './posts.scenarios'

Expand Down Expand Up @@ -30,7 +32,7 @@ describe('posts', () => {
})

scenario('updates a post', async (scenario: StandardScenario) => {
const original = await post({ id: scenario.post.one.id })
const original = (await post({ id: scenario.post.one.id })) as Post
const result = await updatePost({
id: original.id,
input: { title: 'String2' },
Expand All @@ -40,7 +42,7 @@ describe('posts', () => {
})

scenario('deletes a post', async (scenario: StandardScenario) => {
const original = await deletePost({ id: scenario.post.one.id })
const original = (await deletePost({ id: scenario.post.one.id })) as Post
const result = await post({ id: original.id })

expect(result).toEqual(null)
Expand Down
4 changes: 2 additions & 2 deletions __fixtures__/test-project/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"devDependencies": {
"autoprefixer": "^10.4.7",
"postcss": "^8.4.14",
"postcss-loader": "^7.0.0",
"tailwindcss": "^3.1.4"
"postcss-loader": "^7.0.1",
"tailwindcss": "^3.1.6"
}
}
1 change: 0 additions & 1 deletion __fixtures__/test-project/web/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { AuthProvider } from '@redwoodjs/auth'

import { FatalErrorBoundary, RedwoodProvider } from '@redwoodjs/web'
import { RedwoodApolloProvider } from '@redwoodjs/web/apollo'

Expand Down
35 changes: 18 additions & 17 deletions __fixtures__/test-project/web/src/Routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,42 @@

import { Router, Route, Private, Set } from '@redwoodjs/router'

import BlogLayout from 'src/layouts/BlogLayout'
import ContactsLayout from 'src/layouts/ContactsLayout'

import PostsLayout from 'src/layouts/PostsLayout';

import HomePage from "src/pages/HomePage";
import BlogLayout from "src/layouts/BlogLayout";
import PostsLayout from 'src/layouts/PostsLayout'
import HomePage from 'src/pages/HomePage'

const Routes = () => {
return (
(<Router>
<Router>
<Route path="/login" page={LoginPage} name="login" />
<Route path="/signup" page={SignupPage} name="signup" />
<Route path="/forgot-password" page={ForgotPasswordPage} name="forgotPassword" />
<Route path="/reset-password" page={ResetPasswordPage} name="resetPassword" />
<Set wrap={ContactsLayout}>
<Route path="/contacts/new" page={ContactNewContactPage} name="newContact" />
<Route path="/contacts/{id:Int}/edit" page={ContactEditContactPage} name="editContact" />
<Route path="/contacts/{id:Int}" page={ContactContactPage} name="contact" />
<Route path="/contacts" page={ContactContactsPage} name="contacts" />
<Route path="/contacts/new" page={ContactNewContactPage} name="newContact" />
<Route path="/contacts/{id:Int}/edit" page={ContactEditContactPage} name="editContact" />
<Route path="/contacts/{id:Int}" page={ContactContactPage} name="contact" />
<Route path="/contacts" page={ContactContactsPage} name="contacts" />
</Set>
<Set wrap={PostsLayout}>
<Route path="/posts/new" page={PostNewPostPage} name="newPost" />
<Route path="/posts/{id:Int}/edit" page={PostEditPostPage} name="editPost" />
<Route path="/posts/{id:Int}" page={PostPostPage} name="post" />
<Route path="/posts" page={PostPostsPage} name="posts" />
<Route path="/posts/new" page={PostNewPostPage} name="newPost" />
<Route path="/posts/{id:Int}/edit" page={PostEditPostPage} name="editPost" />
<Route path="/posts/{id:Int}" page={PostPostPage} name="post" />
<Route path="/posts" page={PostPostsPage} name="posts" />
</Set>
<Set wrap={BlogLayout}>
<Private unauthenticated="login"><Route path="/profile" page={ProfilePage} name="profile" /></Private>
<Private unauthenticated="login">
<Route path="/profile" page={ProfilePage} name="profile" />
</Private>
<Route path="/blog-post/{id:Int}" page={BlogPostPage} name="blogPost" />
<Route path="/contact" page={ContactPage} name="contact" />
<Route path="/about" page={AboutPage} name="about" prerender />
<Route path="/" page={HomePage} name="home" prerender />
<Route notfound page={NotFoundPage} prerender />
</Set></Router>)
);
</Set>
</Router>
)
}

export default Routes
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import BlogPost from './BlogPost'

export const generated = () => {
return <BlogPost />
export const generated = (args) => {
return <BlogPost {...args} />
}

export default { title: 'Components/BlogPost' }
55 changes: 26 additions & 29 deletions __fixtures__/test-project/web/src/components/BlogPost/BlogPost.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,38 @@
import { Link, routes } from "@redwoodjs/router";
import { FindBlogPostQuery } from 'types/graphql'

import { Link, routes } from '@redwoodjs/router'

interface Props extends FindBlogPostQuery {}


const BlogPost = ({ blogPost }: Props) => {
return (

<article>
{blogPost && (
<>
<header className="mt-4">
<p className="text-sm">
{new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric',
}).format(new Date(blogPost.createdAt))}
</p>
<h2 className="text-xl mt-2 font-semibold">
<Link
className="hover:text-blue-600"
to={routes.blogPost({ id: blogPost.id })}
>
{blogPost.title}
</Link>
</h2>
</header>
<div className="mt-2 mb-4 text-gray-900 font-light">
{blogPost.body}
</div>
</>
)}
{blogPost && (
<>
<header className="mt-4">
<p className="text-sm">
{new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric',
}).format(new Date(blogPost.createdAt))}
</p>
<h2 className="text-xl mt-2 font-semibold">
<Link
className="hover:text-blue-600"
to={routes.blogPost({ id: blogPost.id })}
>
{blogPost.title}
</Link>
</h2>
</header>
<div className="mt-2 mb-4 text-gray-900 font-light">
{blogPost.body}
</div>
</>
)}
</article>

);
)
}

export default BlogPost
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
export const standard = (/* vars, { ctx, req } */) => ({
blogPost: {
id: 42,
title: "Mocked title",
body: "Mocked body",
createdAt: "2022-01-17T13:57:51.607Z"
title: 'Mocked title',
body: 'Mocked body',
createdAt: '2022-01-17T13:57:51.607Z',
},
})
Loading