Skip to content

Commit

Permalink
Switch create-redwood-app template to TypeScript (#1810)
Browse files Browse the repository at this point in the history
* Convert tempate js files to ts files.

* Add code to transpile and format TS in JS.

* Add helper to convert project.

* Rename tsconfig to jsconfig.

* Add a `ts-to-js` test helper to redwood-tools.

* Add jsconfig to create-redwood-app.

* Add --typescript flag to create-redwood-app.

* App.js to App.tsx.

* Make ts2js take a cwd.

* Switch this to JS == true.

* Rework test-tutorial script into run-cypress.

* Make cypress command composable.

* Remove uncaught exception if tsconfig does not exist.

* Fix reference to 'run-e2e' script.

* Fix references in tests.

* Apply suggestions from code review.

Co-authored-by: Daniel Choudhury <dannychoudhury@gmail.com>
  • Loading branch information
peterp and dac09 committed Mar 7, 2021
1 parent 4792d73 commit 91cef20
Show file tree
Hide file tree
Showing 37 changed files with 564 additions and 188 deletions.
5 changes: 1 addition & 4 deletions .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,7 @@ jobs:
echo "::set-output name=project_path::$project_path"
- name: Create a RedwoodJS app
run: ./tasks/test-tutorial ${{ steps.createpath.outputs.project_path }}
env:
CREATE_RWJS_PROJECT: 1
CI: 1
run: ./tasks/run-e2e ${{ steps.createpath.outputs.project_path }} --no-start

- name: Start server in background
run: yarn rw dev &
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/src/commands/generate/scaffold/scaffold.js
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ export const routes = async ({ model: name, path: scaffoldPath = '' }) => {
}

const addScaffoldImport = () => {
const appJsPath = path.join(getPaths().web.src, 'App.js')
const appJsPath = getPaths().web.app
let appJsContents = readFile(appJsPath).toString()

if (appJsContents.match(SCAFFOLD_STYLE_PATH)) {
Expand All @@ -395,7 +395,7 @@ const addScaffoldImport = () => {
)
writeFile(appJsPath, appJsContents, { overwriteExisting: true })

return 'Added scaffold import to App.js'
return 'Added scaffold import to App.{js,tsx}'
}

export const command = 'scaffold <model>'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Should add config lines to App.js Matches Auth0 Snapshot 1`] = `
exports[`Should add config lines to App.{js,tsx} Matches Auth0 Snapshot 1`] = `
"import { AuthProvider } from '@redwoodjs/auth'
import { Auth0Client } from '@auth0/auth0-spa-js'
import { FatalErrorBoundary } from '@redwoodjs/web'
Expand Down Expand Up @@ -37,7 +37,7 @@ export default App
"
`;

exports[`Should add config lines to App.js Matches Firebase Snapshot 1`] = `
exports[`Should add config lines to App.{js,tsx} Matches Firebase Snapshot 1`] = `
"import { AuthProvider } from '@redwoodjs/auth'
import * as firebase from 'firebase/app'
import 'firebase/auth'
Expand Down Expand Up @@ -78,7 +78,7 @@ export default App
"
`;

exports[`Should add config lines to App.js Matches azureActiveDirectory Snapshot 1`] = `
exports[`Should add config lines to App.{js,tsx} Matches azureActiveDirectory Snapshot 1`] = `
"import { AuthProvider } from '@redwoodjs/auth'
import { UserAgentApplication } from 'msal'
import { FatalErrorBoundary } from '@redwoodjs/web'
Expand Down Expand Up @@ -112,7 +112,7 @@ export default App
"
`;

exports[`Should add config lines to App.js Matches ethereum Snapshot 1`] = `
exports[`Should add config lines to App.{js,tsx} Matches ethereum Snapshot 1`] = `
"import { AuthProvider } from '@redwoodjs/auth'
import EthereumAuthClient from '@oneclickdapp/ethereum-auth'
import { ApolloClient, InMemoryCache } from '@apollo/client'
Expand Down Expand Up @@ -178,7 +178,7 @@ export default App
"
`;

exports[`Should add config lines to App.js Matches goTrue Snapshot 1`] = `
exports[`Should add config lines to App.{js,tsx} Matches goTrue Snapshot 1`] = `
"import { AuthProvider } from '@redwoodjs/auth'
import GoTrue from 'gotrue-js'
import { FatalErrorBoundary } from '@redwoodjs/web'
Expand Down Expand Up @@ -208,7 +208,7 @@ export default App
"
`;

exports[`Should add config lines to App.js Matches magicLink Snapshot 1`] = `
exports[`Should add config lines to App.{js,tsx} Matches magicLink Snapshot 1`] = `
"import { AuthProvider } from '@redwoodjs/auth'
import { Magic } from 'magic-sdk'
import { FatalErrorBoundary } from '@redwoodjs/web'
Expand All @@ -235,7 +235,7 @@ export default App
"
`;

exports[`Should add config lines to App.js Matches netlify Snapshot 1`] = `
exports[`Should add config lines to App.{js,tsx} Matches netlify Snapshot 1`] = `
"import { AuthProvider } from '@redwoodjs/auth'
import netlifyIdentity from 'netlify-identity-widget'
import { isBrowser } from '@redwoodjs/prerender/browserUtils'
Expand Down Expand Up @@ -263,7 +263,7 @@ export default App
"
`;

exports[`Should add config lines to App.js Matches nhost Snapshot 1`] = `
exports[`Should add config lines to App.{js,tsx} Matches nhost Snapshot 1`] = `
"import { AuthProvider } from '@redwoodjs/auth'
import { createClient } from 'nhost-js-sdk'
import { FatalErrorBoundary } from '@redwoodjs/web'
Expand Down Expand Up @@ -294,7 +294,7 @@ export default App
"
`;

exports[`Should add config lines to App.js Matches supabase Snapshot 1`] = `
exports[`Should add config lines to App.{js,tsx} Matches supabase Snapshot 1`] = `
"import { AuthProvider } from '@redwoodjs/auth'
import { createClient } from '@supabase/supabase-js'
import { FatalErrorBoundary } from '@redwoodjs/web'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ jest.mock('src/lib', () => {
api: { functions: '', src: '', lib: '' },
web: {
src: path.join(__dirname, '../create-redwood-app/template/web/src'),
app: path.join(
__dirname,
'../create-redwood-app/template/web/src/App.tsx'
),
},
}),
}
Expand All @@ -26,7 +30,7 @@ beforeEach(() => {
jest.spyOn(fs, 'writeFileSync').mockImplementation(writeFileSyncSpy)
})

describe('Should add config lines to App.js', () => {
describe('Should add config lines to App.{js,tsx}', () => {
it('Matches Auth0 Snapshot', async () => {
const auth0Data = await import(`../providers/auth0`)
await addConfigToApp(auth0Data.config, false)
Expand Down
18 changes: 9 additions & 9 deletions packages/cli/src/commands/setup/auth/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,27 +32,27 @@ const TEMPLATES = fs
}, {})

const OUTPUT_PATH = path.join(getPaths().api.lib, 'auth.js')
const WEB_SRC_APP_PATH = path.join(getPaths().web.src, 'App.js')
const WEB_SRC_APP_PATH = getPaths().web.app

const SUPPORTED_PROVIDERS = fs
.readdirSync(path.resolve(__dirname, 'providers'))
.map((file) => path.basename(file, '.js'))
.filter((file) => file !== 'README.md')

// returns the content of App.js with import statements added
// returns the content of App.{js,tsx} with import statements added
const addWebImports = (content, imports) => {
return `${AUTH_PROVIDER_IMPORT}\n` + imports.join('\n') + '\n' + content
}

// returns the content of App.js with init lines added
// returns the content of App.{js,tsx} with init lines added
const addWebInit = (content, init) => {
return content.replace(
'const App = () => (',
`${init}\n\nconst App = () => (`
)
}

// returns the content of App.js with <AuthProvider> added
// returns the content of App.{js,tsx} with <AuthProvider> added
const addWebRender = (content, authProvider) => {
const [_, indent, redwoodApolloProvider] = content.match(
/(\s+)(<RedwoodApolloProvider>.*<\/RedwoodApolloProvider>)/s
Expand Down Expand Up @@ -90,18 +90,18 @@ const addWebRender = (content, authProvider) => {
)
}

// returns the content of App.js with <AuthProvider> updated
// returns the content of App.{js,tsx} with <AuthProvider> updated
const updateWebRender = (content, authProvider) => {
const renderContent = `<AuthProvider client={${authProvider.client}} type="${authProvider.type}">`
return content.replace(/<AuthProvider client={.*} type=".*">/s, renderContent)
}

// returns the content of App.js without the old auth import
// returns the content of App.{js,tsx} without the old auth import
const removeOldWebImports = (content, imports) => {
return content.replace(`${AUTH_PROVIDER_IMPORT}\n` + imports.join('\n'), '')
}

// returns the content of App.js without the old auth init
// returns the content of App.{js,tsx} without the old auth init
const removeOldWebInit = (content, init) => {
return content.replace(init, '')
}
Expand Down Expand Up @@ -145,7 +145,7 @@ export const files = (provider) => {
}
}

// actually inserts the required config lines into App.js
// actually inserts the required config lines into App.{js,tsx}
export const addConfigToApp = async (config, force) => {
let content = fs.readFileSync(WEB_SRC_APP_PATH).toString()

Expand Down Expand Up @@ -245,7 +245,7 @@ export const handler = async ({ provider, force }) => {
if (webIndexDoesExist()) {
addConfigToApp(providerData.config, force)
} else {
task.skip('web/src/App.js not found, skipping')
task.skip('web/src/App.{js,tsx} not found, skipping')
}
},
},
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/src/commands/setup/auth/providers/auth0.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// the lines that need to be added to App.js
// the lines that need to be added to App.{js,tsx}
export const config = {
imports: [`import { Auth0Client } from '@auth0/auth0-spa-js'`],
init: `const auth0 = new Auth0Client({
Expand All @@ -25,7 +25,7 @@ export const apiPackages = []
// any notes to print out when the job is done
export const notes = [
'You will need to create several environment variables with your Auth0 config options.',
'Check out web/src/App.js for the variables you need to add.',
'Check out web/src/App.{js,tsx} for the variables you need to add.',
'See: https://auth0.com/docs/quickstart/spa/react#get-your-application-keys',
'\n',
"You must also create an API and set the audience parameter, or you'll",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// the lines that need to be added to App.js
// the lines that need to be added to App.{js,tsx}
export const config = {
imports: [`import { UserAgentApplication } from 'msal'`],
init: `const azureActiveDirectoryClient = new UserAgentApplication({
Expand All @@ -21,7 +21,7 @@ export const apiPackages = []

// any notes to print out when the job is done
export const notes = [
'You will need to create several environment variables with your Azure AD config options. Check out web/src/App.js for the variables you need to add.',
'You will need to create several environment variables with your Azure AD config options. Check out web/src/App.{js,tsx} for the variables you need to add.',
'\n',
'RedwoodJS specific Documentation:',
'https://redwoodjs.com/docs/authentication#azure-ad',
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/commands/setup/auth/providers/ethereum.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// the lines that need to be added to App.js
// the lines that need to be added to App.{js,tsx}
export const config = {
imports: [
`import EthereumAuthClient from '@oneclickdapp/ethereum-auth'`,
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/src/commands/setup/auth/providers/firebase.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// the lines that need to be added to App.js
// the lines that need to be added to App.{js,tsx}
export const config = {
imports: [
`import * as firebase from 'firebase/app'`,
Expand Down Expand Up @@ -28,6 +28,6 @@ export const apiPackages = ['firebase-admin']
// any notes to print out when the job is done
export const notes = [
'You will need to create several environment variables with your Firebase config options.',
'Check out web/src/App.js for the variables you need to add.',
'Check out web/src/App.{js,tsx} for the variables you need to add.',
'See: https://firebase.google.com/docs/web/setup#config-object',
]
2 changes: 1 addition & 1 deletion packages/cli/src/commands/setup/auth/providers/goTrue.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// the lines that need to be added to App.js
// the lines that need to be added to App.{js,tsx}
export const config = {
imports: [`import GoTrue from 'gotrue-js'`],
init: `const goTrueClient = new GoTrue({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// the lines that need to be added to App.js
// the lines that need to be added to App.{js,tsx}
export const config = {
imports: [`import { Magic } from 'magic-sdk'`],
init: 'const m = new Magic(process.env.MAGICLINK_PUBLIC)',
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/commands/setup/auth/providers/netlify.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// the lines that need to be added to App.js
// the lines that need to be added to App.{js,tsx}
export const config = {
imports: [
`import netlifyIdentity from 'netlify-identity-widget'`,
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/commands/setup/auth/providers/nhost.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// the lines that need to be added to App.js
// the lines that need to be added to App.{js,tsx}
export const config = {
imports: [`import { createClient } from 'nhost-js-sdk'`],
init: `const nhostClient = createClient({
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/commands/setup/auth/providers/supabase.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// the lines that need to be added to App.js
// the lines that need to be added to App.{js,tsx}
export const config = {
imports: [`import { createClient } from '@supabase/supabase-js'`],
init: `const supabaseClient = createClient(
Expand Down
6 changes: 3 additions & 3 deletions packages/cli/src/commands/setup/i18n/i18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const builder = (yargs) => {
}

export const handler = async ({ force }) => {
const INDEX_JS_PATH = path.join(getPaths().web.src, 'App.js')
const INDEX_JS_PATH = getPaths().web.app
const tasks = new Listr([
{
title: 'Installing packages...',
Expand Down Expand Up @@ -61,10 +61,10 @@ export const handler = async ({ force }) => {
},
},
{
title: 'Adding import to App.js...',
title: 'Adding import to App.{js,tsx}...',
task: () => {
/**
* Add i18n import to the top of App.js
* Add i18n import to the top of App.{js,tsx}
*/
let indexJS = fs.readFileSync(INDEX_JS_PATH)
indexJS = [`import './i18n'`, indexJS].join(`\n`)
Expand Down
1 change: 0 additions & 1 deletion packages/cli/src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,3 @@ declare namespace NodeJS {

// TODO: Remove the following declarations when these files get types.
declare module 'src/lib/test'
declare module 'src/lib'
9 changes: 8 additions & 1 deletion packages/cli/src/redwood-tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ import prompts from 'prompts'
import rimraf from 'rimraf'
import yargs from 'yargs'

import { getPaths, ensurePosixPath } from '@redwoodjs/internal'
import {
getPaths,
ensurePosixPath,
convertTsProjectToJs,
} from '@redwoodjs/internal'

import c from './lib/colors'

Expand Down Expand Up @@ -368,5 +372,8 @@ yargs
fixProjectBinaries(getPaths().base)
}
)
.command(['ts-to-js'], 'Convert TS files in a project to JS', {}, () => {
convertTsProjectToJs(process.cwd())
})
.demandCommand()
.strict().argv
2 changes: 1 addition & 1 deletion packages/create-redwood-app/__tests__/web-template.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ test('Web/src/App should contain App', () => {
// packages/cli/src/commands/setup/auth/auth.js should also be changed

const indexContent = fs
.readFileSync(path.join(__dirname, '../template/web/src/App.js'))
.readFileSync(path.join(__dirname, '../template/web/src/App.tsx'))
.toString()

expect(indexContent).toContain('const App = () => (')
Expand Down
15 changes: 15 additions & 0 deletions packages/create-redwood-app/jsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"extends": "../../tsconfig.compilerOption.json",
"compilerOptions": {
"baseUrl": ".",
"rootDir": "src",
"outDir": "dist",
"paths": {
"src/*": ["./src/*"]
}
},
"include": ["src"],
"references": [
{ "path": "../internal" },
]
}
Loading

0 comments on commit 91cef20

Please sign in to comment.