Use typescript.

pull/1/head
Joshua Potter 2023-12-01 18:48:47 -07:00
parent 01ffd518f2
commit d11d591fa9
9 changed files with 206 additions and 57 deletions

View File

@ -1,13 +1,24 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e set -e
filesToFormat=$( mixFiles=$(
git --no-pager diff --name-status --no-color --cached | \ git --no-pager diff --name-status --no-color --cached | \
awk '$1 != "D" && $2 ~ /\.exs?$/ {print $NF}' awk '$1 != "D" && $2 ~ /\.exs?$/ {print $NF}'
) )
for path in $filesToFormat for path in $mixFiles
do do
mix format "$path" mix format "$path"
git add "$path" git add "$path"
done done
webFiles=$(
git --no-pager diff --name-status --no-color --cached | \
awk '$1 != "D" && $2 ~ /\.jsx?$|\.tsx?$/ {print $NF}'
)
for path in $webFiles
do
prettier --write "$path"
git add "$path"
done

View File

@ -3,5 +3,4 @@ import * as React from 'react'
import ReactDOM from 'react-dom/client' import ReactDOM from 'react-dom/client'
import App from './App' import App from './App'
ReactDOM.createRoot(document.getElementById('mount')).render(<App />) ReactDOM.createRoot(document.getElementById('mount')!).render(<App />)

139
assets/package-lock.json generated Normal file
View File

@ -0,0 +1,139 @@
{
"name": "assets",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.2.40",
"@types/react-dom": "^18.2.17",
"typescript": "^5.3.2"
}
},
"node_modules/.pnpm/js-tokens@4.0.0/node_modules/js-tokens": {
"version": "4.0.0",
"extraneous": true,
"license": "MIT",
"devDependencies": {
"coffeescript": "2.1.1",
"esprima": "4.0.0",
"everything.js": "1.0.3",
"mocha": "5.0.0"
}
},
"node_modules/.pnpm/loose-envify@1.4.0": {
"extraneous": true
},
"node_modules/.pnpm/react-dom@18.2.0_react@18.2.0": {
"extraneous": true
},
"node_modules/.pnpm/react@18.2.0": {
"extraneous": true
},
"node_modules/.pnpm/scheduler@0.23.0": {
"extraneous": true
},
"node_modules/@types/prop-types": {
"version": "15.7.11",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz",
"integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==",
"dev": true
},
"node_modules/@types/react": {
"version": "18.2.40",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.40.tgz",
"integrity": "sha512-H+BUhb9C1zBtogDLAk+KCNRKiHDrqSwQT/0z0PVTwMFBxqg3011ByLomADtgkgMkfwj4AMOiXBReyLTUBg681g==",
"dev": true,
"dependencies": {
"@types/prop-types": "*",
"@types/scheduler": "*",
"csstype": "^3.0.2"
}
},
"node_modules/@types/react-dom": {
"version": "18.2.17",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.17.tgz",
"integrity": "sha512-rvrT/M7Df5eykWFxn6MYt5Pem/Dbyc1N8Y0S9Mrkw2WFCRiqUgw9P7ul2NpwsXCSM1DVdENzdG9J5SreqfAIWg==",
"dev": true,
"dependencies": {
"@types/react": "*"
}
},
"node_modules/@types/scheduler": {
"version": "0.16.8",
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz",
"integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==",
"dev": true
},
"node_modules/csstype": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==",
"dev": true
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
},
"node_modules/loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
},
"bin": {
"loose-envify": "cli.js"
}
},
"node_modules/react": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
"integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
"dependencies": {
"loose-envify": "^1.1.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/react-dom": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
"integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.0"
},
"peerDependencies": {
"react": "^18.2.0"
}
},
"node_modules/scheduler": {
"version": "0.23.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
"integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
"dependencies": {
"loose-envify": "^1.1.0"
}
},
"node_modules/typescript": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz",
"integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
}
}
}

View File

@ -2,5 +2,10 @@
"dependencies": { "dependencies": {
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0" "react-dom": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.2.40",
"@types/react-dom": "^18.2.17",
"typescript": "^5.3.2"
} }
} }

View File

@ -1,49 +0,0 @@
lockfileVersion: '6.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
dependencies:
react:
specifier: ^18.2.0
version: 18.2.0
react-dom:
specifier: ^18.2.0
version: 18.2.0(react@18.2.0)
packages:
/js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
dev: false
/loose-envify@1.4.0:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true
dependencies:
js-tokens: 4.0.0
dev: false
/react-dom@18.2.0(react@18.2.0):
resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==}
peerDependencies:
react: ^18.2.0
dependencies:
loose-envify: 1.4.0
react: 18.2.0
scheduler: 0.23.0
dev: false
/react@18.2.0:
resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==}
engines: {node: '>=0.10.0'}
dependencies:
loose-envify: 1.4.0
dev: false
/scheduler@0.23.0:
resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==}
dependencies:
loose-envify: 1.4.0
dev: false

30
assets/tsconfig.json Normal file
View File

@ -0,0 +1,30 @@
{
// https://esbuild.github.io/content-types/#tsconfig-json
"compilerOptions": {
// Keep in mind that ES6+ syntax to ES5 is not supported in esbuild yet.
"target": "es2016",
// Even when transpiling a single module, the TypeScript compiler actually
// parses imported files so it can tell whether an imported name is a type
// or a value. However, tools like esbuild compile each file in isolation so
// they can't tell if an imported name is a type or a value.
// https://esbuild.github.io/content-types/#isolated-modules
"isolatedModules": true,
// Disables legacy behavior around imports and makes TypeScript's type
// system compatible with ESM.
"esModuleInterop": true,
// Enables define semantics. In this mode, TypeScript class fields behave
// like normal JavaScript class fields. Field initializers do not trigger
// setters on the base class.
"useDefineForClassFields": true,
// If either of these options are enabled, esbuild will consider all code
// in all TypeScript files to be in strict mode and will prefix generated
// code with "use strict" unless the output format is set to esm (since all
// ESM files are automatically in strict mode).
"strict": true,
// Emit .js files with JSX changed to the equivalent React.createElement
// calls. It seems like the "react" value mirrors esbuild's native
// "transform" option, but it isn't obvious how these two relate from the
// documentation: https://esbuild.github.io/api/#jsx.
"jsx": "react"
}
}

View File

@ -32,12 +32,23 @@ config :boardwise, BoardWiseWeb.Endpoint,
# at the `config/runtime.exs`. # at the `config/runtime.exs`.
config :boardwise, BoardWise.Mailer, adapter: Swoosh.Adapters.Local config :boardwise, BoardWise.Mailer, adapter: Swoosh.Adapters.Local
# Configure esbuild (the version is required) # Configure esbuild (the version is required). Aim to use the same target as
# specified in tsconfig.json for ease of understanding. There are cases where
# esbuild will interpret the tsconfig.json target independently of that
# specified in this command (e.g. `useDefineForClassFields` as explained in
# https://esbuild.github.io/content-types/#tsconfig-json).
config :esbuild, config :esbuild,
version: "0.17.11", version: "0.17.11",
default: [ default: [
args: args: ~w(
~w(js/app.js js/react/main.jsx --bundle --target=es2017 --outdir=../priv/static/assets --external:/fonts/* --external:/images/*), js/app.js
js/react/main.jsx
--bundle
--target=es2016
--outdir=../priv/static/assets
--external:/fonts/*
--external:/images/*
),
cd: Path.expand("../assets", __DIR__), cd: Path.expand("../assets", __DIR__),
env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)} env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
] ]

View File

@ -44,8 +44,11 @@
] ++ (with pkgs; [ ] ++ (with pkgs; [
inotify-tools # For file watching in development. inotify-tools # For file watching in development.
mix2nix mix2nix
nodePackages.pnpm nodePackages.prettier
nodePackages.typescript-language-server
nodejs
postgresql_15 postgresql_15
typescript
]); ]);
shellHook = '' shellHook = ''
# The server will try to use the data directory named by this # The server will try to use the data directory named by this