Skip to content

Commit

Permalink
Create restructuring prototype (#1584)
Browse files Browse the repository at this point in the history
  • Loading branch information
sodic authored Jan 29, 2024
1 parent b227daf commit 6f0714a
Show file tree
Hide file tree
Showing 107 changed files with 3,422 additions and 87 deletions.
2 changes: 1 addition & 1 deletion examples/streaming/src/client/vite-env.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
/// <reference types="../../.wasp/out/web-app/node_modules/vite/client" />
/// <reference types="vite/client" />

This file was deleted.

6 changes: 3 additions & 3 deletions waspc/cli/src/Wasp/Cli/Common.hs
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@ dotWaspInfoFileInGeneratedCodeDir :: Path' (Rel Wasp.Generator.Common.ProjectRoo
dotWaspInfoFileInGeneratedCodeDir = [relfile|.waspinfo|]

extServerCodeDirInWaspProjectDir :: Path' (Rel WaspProjectDir) (Dir SourceExternalCodeDir)
extServerCodeDirInWaspProjectDir = [reldir|src/server|]
extServerCodeDirInWaspProjectDir = [reldir|src|]

extClientCodeDirInWaspProjectDir :: Path' (Rel WaspProjectDir) (Dir SourceExternalCodeDir)
extClientCodeDirInWaspProjectDir = [reldir|src/client|]
extClientCodeDirInWaspProjectDir = [reldir|src|]

extSharedCodeDirInWaspProjectDir :: Path' (Rel WaspProjectDir) (Dir SourceExternalCodeDir)
extSharedCodeDirInWaspProjectDir = [reldir|src/shared|]
extSharedCodeDirInWaspProjectDir = [reldir|src|]

waspSays :: String -> IO ()
waspSays what = putStrLn $ Term.applyStyles [Term.Yellow] what
Expand Down
10 changes: 10 additions & 0 deletions waspc/data/Cli/templates/basic/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "prototype",
"dependencies": {
"wasp": "file:.wasp/out/sdk/wasp",
"react": "18.2.0"
},
"devDependencies": {
"@types/react": "^18.0.37"
}
}
2 changes: 1 addition & 1 deletion waspc/data/Generator/templates/react-app/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import router from './router'
import {
initializeQueryClient,
queryClientInitialized,
} from './queryClient'
} from 'wasp/rpc/queryClient'

{=# setupFn.isDefined =}
{=& setupFn.importStatement =}
Expand Down
2 changes: 1 addition & 1 deletion waspc/data/Generator/templates/react-app/src/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import type {
{=/ rootComponent.isDefined =}

{=# isAuthEnabled =}
import createAuthRequiredPage from "./auth/pages/createAuthRequiredPage"
import createAuthRequiredPage from "wasp/auth/pages/createAuthRequiredPage"
{=/ isAuthEnabled =}
{=# pagesToImport =}
Expand Down
12 changes: 9 additions & 3 deletions waspc/data/Generator/templates/react-app/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
// Allow importing pages with the .tsx extension.
"allowImportingTsExtensions": true
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
}
"include": [
"src"
],
"references": [
{
"path": "./tsconfig.node.json"
}
]
}
3 changes: 3 additions & 0 deletions waspc/data/Generator/templates/react-app/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ const _waspUserProvidedConfig = {};
const defaultViteConfig = {
base: "{= baseDir =}",
plugins: [react()],
optimizeDeps: {
exclude: ['wasp']
},
server: {
port: {= defaultClientPort =},
host: "0.0.0.0",
Expand Down
127 changes: 127 additions & 0 deletions waspc/data/Generator/templates/sdk/dependencies.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
Dependencies:

("@prisma/client", show prismaVersion), // sdk
("@tanstack/react-query", "^4.29.0"), // sdk
("axios", "^1.4.0"), // sdk
("cookie-parser", "~1.4.6"), //
("cors", "^2.8.5"), //
("dotenv", "16.0.2"), //
("express", "~4.18.1"), // sdk (for types)
("helmet", "^6.0.0"), //
("jsonwebtoken", "^8.5.1"), // sdk
("lodash.merge", "^4.6.2"), //
("mitt", "3.0.0"), // sdk
("morgan", "~1.10.0"), //
("patch-package", "^6.4.7"), //
("rate-limiter-flexible", "^2.4.1"), //
("react", "^18.2.0"), // sdk
("react-dom", "^18.2.0"), //
("react-hook-form", "^7.45.4") //
("react-router-dom", "^5.3.3"), // sdk
("secure-password", "^4.0.0"), // sdk
("superjson", "^1.12.2"), // sdk
("uuid", "^9.0.0"), //

Dev dependencies:
("@tsconfig/node" ++ show (major NodeVersion.latestMajorNodeVersion), "^1.0.1"),
("@tsconfig/vite-react", "^2.0.0")
("@types/cors", "^2.8.5")
("@types/express", "^4.17.13"),
("@types/express-serve-static-core", "^4.17.13"),
("@types/node", "^18.11.9"),
("@types/react", "^18.0.37"),
("@types/react-dom", "^18.0.11"),
("@types/react-router-dom", "^5.3.3"),
("@types/uuid", "^9.0.0"),
("@vitejs/plugin-react-swc", "^3.0.0"),
("dotenv", "^16.0.3"), // duplicate
("nodemon", "^2.0.19"), //
("prisma", show prismaVersion), //
("standard", "^17.0.0"), //
("typescript", "^5.1.0"), //
("vite", "^4.3.9"), //

Their package.json:
("react", "^18.2.0"),
("typescript", "^5.1.0")


Server

("cookie-parser", "~1.4.6"),
- [Framework] Generator/templates/server/src/middleware/globalMiddleware.ts

("cors", "^2.8.5"),
- [Framework] Generator/templates/server/src/middleware/globalMiddleware.ts

("express", "~4.18.1"),
- Generator/templates/server/src/auth/providers/config/local.ts
- Generator/templates/server/src/auth/providers/config/email.ts
- Generator/templates/server/src/routes/crud/index.ts
- Generator/templates/server/src/routes/crud/_crud.ts
- Generator/templates/server/src/routes/operations/index.js
- Generator/templates/server/src/routes/index.js
- Generator/templates/server/src/auth/providers/index.ts
- Generator/templates/server/src/auth/providers/oauth/createRouter.ts
- Generator/templates/server/src/routes/apis/index.ts
- Generator/templates/server/src/auth/providers/types.ts
- Generator/templates/server/src/types/index.ts
- Generator/templates/server/src/middleware/globalMiddleware.ts
- Generator/templates/server/src/app.js
- Generator/templates/server/src/auth/providers/email/signup.ts
- Generator/templates/server/src/routes/auth/index.js
- Generator/templates/server/src/auth/providers/email/login.ts
- Generator/templates/server/src/auth/providers/email/resetPassword.ts
- Generator/templates/server/src/auth/providers/email/requestPasswordReset.ts
- Generator/templates/server/src/auth/providers/email/verifyEmail.ts
- Generator/templates/server/src/_types/index.ts
- Generator/templates/server/src/apis/types.ts

("morgan", "~1.10.0"),
- [Framework] Generator/templates/server/src/middleware/globalMiddleware.ts

("@prisma/client", show prismaVersion),
- [SDK] Generator/templates/react-app/src/entities/index.ts
- [SDK] Generator/templates/server/src/dbClient.ts
- [Framework] Generator/templates/server/src/utils.js
- Generator/templates/server/src/auth/utils.ts
- Generator/templates/server/src/entities/index.ts
- Generator/templates/server/src/auth/providers/oauth/types.ts
- Generator/templates/server/src/crud/_operations.ts
- Generator/templates/server/src/dbSeed/types.ts


("jsonwebtoken", "^8.5.1"),
-- NOTE: secure-password has a package.json override for sodium-native.
("secure-password", "^4.0.0"),
("dotenv", "16.0.2"),
("helmet", "^6.0.0"),
("patch-package", "^6.4.7"),
("uuid", "^9.0.0"),
("lodash.merge", "^4.6.2"),
("rate-limiter-flexible", "^2.4.1"),
("superjson", "^1.12.2")

depsRequiredByPassport spec

depsRequiredByJobs spec

depsRequiredByEmail spec

depsRequiredByWebSockets spec,
N.waspDevDependencies =
AS.Dependency.fromList
[ ("nodemon", "^2.0.19"),
("standard", "^17.0.0"),
("prisma", show prismaVersion),
-- TODO: Allow users to choose whether they want to use TypeScript
-- in their projects and install these dependencies accordingly.
("typescript", "^5.1.0"),
("@types/express", "^4.17.13"),
("@types/express-serve-static-core", "^4.17.13"),
("@types/node", "^18.11.9"),
("@tsconfig/node" ++ show (major NodeVersion.latestMajorNodeVersion), "^1.0.1"),
("@types/uuid", "^9.0.0"),
("@types/cors", "^2.8.5")
]
}
36 changes: 36 additions & 0 deletions waspc/data/Generator/templates/sdk/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{{={= =}=}}
{
"name": "wasp",
"version": "1.0.0",
"private": true,
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"types": "tsc --declaration --emitDeclarationOnly --stripInternal --declarationDir dist"
},
"exports": {
"./core/HttpError": "./core/HttpError.js",
"./core/AuthError": "./core/AuthError.js",
"./core/config": "./core/config.js",
"./core/stitches.config": "./core/stitches.config.js",
"./core/storage": "./core/storage.ts",
"./rpc": "./rpc/index.ts",
"./rpc/queries": "./rpc/queries/index.ts",
"./rpc/actions": "./rpc/actions/index.ts",
"./rpc/queryClient": "./rpc/queryClient.ts",
"./types": "./types/index.ts",
"./auth/*": "./auth/*",
"./api": "./api/index.ts",
"./api/*": "./api/*",
"./operations": "./operations/index.ts",
"./operations/*": "./operations/*",
"./universal/url": "./universal/url.ts",
"./universal/types": "./universal/url.ts"
},
"license": "ISC",
"include": [
"src/**/*"
],
{=& depsChunk =},
{=& devDepsChunk =}
}
11 changes: 11 additions & 0 deletions waspc/data/Generator/templates/sdk/wasp/api/events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import mitt, { Emitter } from 'mitt';

type ApiEvents = {
// key: Event name
// type: Event payload type
'sessionId.set': void;
'sessionId.clear': void;
};

// Used to allow API clients to register for auth session ID change events.
export const apiEventsEmitter: Emitter<ApiEvents> = mitt<ApiEvents>();
104 changes: 104 additions & 0 deletions waspc/data/Generator/templates/sdk/wasp/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import axios, { type AxiosError } from 'axios'

import config from 'wasp/core/config'
import { storage } from 'wasp/core/storage'
import { apiEventsEmitter } from 'wasp/api/events'

const api = axios.create({
baseURL: config.apiUrl,
})

const WASP_APP_AUTH_SESSION_ID_NAME = 'sessionId'

let waspAppAuthSessionId = storage.get(WASP_APP_AUTH_SESSION_ID_NAME) as string | undefined

export function setSessionId(sessionId: string): void {
waspAppAuthSessionId = sessionId
storage.set(WASP_APP_AUTH_SESSION_ID_NAME, sessionId)
apiEventsEmitter.emit('sessionId.set')
}

export function getSessionId(): string | undefined {
return waspAppAuthSessionId
}

export function clearSessionId(): void {
waspAppAuthSessionId = undefined
storage.remove(WASP_APP_AUTH_SESSION_ID_NAME)
apiEventsEmitter.emit('sessionId.clear')
}

export function removeLocalUserData(): void {
waspAppAuthSessionId = undefined
storage.clear()
apiEventsEmitter.emit('sessionId.clear')
}

api.interceptors.request.use((request) => {
const sessionId = getSessionId()
if (sessionId) {
request.headers['Authorization'] = `Bearer ${sessionId}`
}
return request
})

api.interceptors.response.use(undefined, (error) => {
if (error.response?.status === 401) {
clearSessionId()
}
return Promise.reject(error)
})

// This handler will run on other tabs (not the active one calling API functions),
// and will ensure they know about auth session ID changes.
// Ref: https://developer.mozilla.org/en-US/docs/Web/API/Window/storage_event
// "Note: This won't work on the same page that is making the changes — it is really a way
// for other pages on the domain using the storage to sync any changes that are made."
window.addEventListener('storage', (event) => {
if (event.key === storage.getPrefixedKey(WASP_APP_AUTH_SESSION_ID_NAME)) {
if (!!event.newValue) {
waspAppAuthSessionId = event.newValue
apiEventsEmitter.emit('sessionId.set')
} else {
waspAppAuthSessionId = undefined
apiEventsEmitter.emit('sessionId.clear')
}
}
})

/**
* Takes an error returned by the app's API (as returned by axios), and transforms into a more
* standard format to be further used by the client. It is also assumed that given API
* error has been formatted as implemented by HttpError on the server.
*/
export function handleApiError(error: AxiosError<{ message?: string, data?: unknown }>): void {
if (error?.response) {
// If error came from HTTP response, we capture most informative message
// and also add .statusCode information to it.
// If error had JSON response, we assume it is of format { message, data } and
// add that info to the error.
// TODO: We might want to use HttpError here instead of just Error, since
// HttpError is also used on server to throw errors like these.
// That would require copying HttpError code to web-app also and using it here.
const responseJson = error.response?.data
const responseStatusCode = error.response.status
throw new WaspHttpError(responseStatusCode, responseJson?.message ?? error.message, responseJson)
} else {
// If any other error, we just propagate it.
throw error
}
}

class WaspHttpError extends Error {
statusCode: number

data: unknown

constructor (statusCode: number, message: string, data: unknown) {
super(message)
this.statusCode = statusCode
this.data = data
}
}

export default api
Loading

0 comments on commit 6f0714a

Please sign in to comment.