) => {
+ try {
+ await updateTask({
+ taskId: task.id,
+ isDone: event.currentTarget.checked,
+ });
+ } catch (err: any) {
+ window.alert('Error while updating task: ' + err?.message);
+ }
+ };
+
+ return (
+
+
+ {number + 1}
+ {''}
+
+
+ {task.description}{' '}
+
+ );
+};
+
+const TasksList = ({tasks}: { tasks: Task[] }) => {
+ if (tasks.length === 0) return No tasks yet.
;
+ return (
+
+ {tasks.map((tsk, idx) => (
+
+ ))}
+
+ );
+};
+
+const NewTaskForm = () => {
+ const handleSubmit = async (event: React.FormEvent) => {
+ event.preventDefault();
+
+ try {
+ const description = event.currentTarget.description.value;
+ console.log(description)
+ event.currentTarget.reset();
+ await createTask({ description });
+ } catch (err: any) {
+ window.alert('Error: ' + err?.message);
+ }
+ };
+
+ return (
+
+ );
+};
+
+export default MainPage;
diff --git a/examples/todo-typescript/src/client/SignupPage.tsx b/examples/todo-typescript/src/client/SignupPage.tsx
new file mode 100644
index 000000000..8a8e8e7fe
--- /dev/null
+++ b/examples/todo-typescript/src/client/SignupPage.tsx
@@ -0,0 +1,19 @@
+import React from 'react';
+import { Link } from 'react-router-dom';
+import SignupForm from '@wasp/auth/forms/Signup';
+
+const SignupPage = () => {
+ return (
+
+ Sign Up
+ {/** Wasp has built-in auth forms & flows, which you can also opt-out of, if you wish :) */}
+
+
+
+ I already have an account (go to login).
+
+
+ );
+};
+
+export default SignupPage;
diff --git a/examples/todo-typescript/src/client/react-app-env.d.ts b/examples/todo-typescript/src/client/react-app-env.d.ts
new file mode 100644
index 000000000..e80934ce3
--- /dev/null
+++ b/examples/todo-typescript/src/client/react-app-env.d.ts
@@ -0,0 +1,60 @@
+declare module '*.avif' {
+ const src: string;
+ export default src;
+}
+
+declare module '*.bmp' {
+ const src: string;
+ export default src;
+}
+
+declare module '*.gif' {
+ const src: string;
+ export default src;
+}
+
+declare module '*.jpg' {
+ const src: string;
+ export default src;
+}
+
+declare module '*.jpeg' {
+ const src: string;
+ export default src;
+}
+
+declare module '*.png' {
+ const src: string;
+ export default src;
+}
+
+declare module '*.webp' {
+ const src: string;
+ export default src;
+}
+
+declare module '*.svg' {
+ import * as React from 'react';
+
+ export const ReactComponent: React.FunctionComponent & { title?: string }>;
+
+ const src: string;
+ export default src;
+}
+
+declare module '*.module.css' {
+ const classes: { readonly [key: string]: string };
+ export default classes;
+}
+
+declare module '*.module.scss' {
+ const classes: { readonly [key: string]: string };
+ export default classes;
+}
+
+declare module '*.module.sass' {
+ const classes: { readonly [key: string]: string };
+ export default classes;
+}
diff --git a/examples/todo-typescript/src/client/tsconfig.json b/examples/todo-typescript/src/client/tsconfig.json
new file mode 100644
index 000000000..d501a4193
--- /dev/null
+++ b/examples/todo-typescript/src/client/tsconfig.json
@@ -0,0 +1,55 @@
+// =============================== IMPORTANT =================================
+//
+// This file is only used for Wasp IDE support. You can change it to configure
+// your IDE checks, but none of these options will affect the TypeScript
+// compiler. Proper TS compiler configuration in Wasp is coming soon :)
+{
+ "compilerOptions": {
+ // JSX support
+ "jsx": "preserve",
+ "strict": true,
+ // Allow default imports.
+ "esModuleInterop": true,
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
+ "allowJs": true,
+ // Wasp needs the following settings enable IDE support in your source
+ // files. Editing them might break features like import autocompletion and
+ // definition lookup. Don't change them unless you know what you're doing.
+ //
+ // The relative path to the generated web app's root directory. This must be
+ // set to define the "paths" option.
+ "baseUrl": "../../.wasp/out/web-app/",
+ "paths": {
+ // Resolve all "@wasp" imports to the generated source code.
+ "@wasp/*": [
+ "src/*"
+ ],
+ // Resolve all non-relative imports to the correct node module. Source:
+ // https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping
+ "*": [
+ // Start by looking for the definiton inside the node modules root
+ // directory...
+ "node_modules/*",
+ // ... If that fails, try to find it inside definitely-typed type
+ // definitions.
+ "node_modules/@types/*"
+ ]
+ },
+ // Correctly resolve types: https://www.typescriptlang.org/tsconfig#typeRoots
+ "typeRoots": [
+ "../../.wasp/out/web-app/node_modules/@types"
+ ],
+ // Since this TS config is used only for IDE support and not for
+ // compilation, the following directory doesn't exist. We need to specify
+ // it to prevent this error:
+ // https://stackoverflow.com/questions/42609768/typescript-error-cannot-write-file-because-it-would-overwrite-input-file
+ "outDir": "phantom"
+ },
+ "exclude": [
+ "phantom"
+ ],
+}
\ No newline at end of file
diff --git a/examples/todo-typescript/src/client/types.ts b/examples/todo-typescript/src/client/types.ts
new file mode 100644
index 000000000..7739835bb
--- /dev/null
+++ b/examples/todo-typescript/src/client/types.ts
@@ -0,0 +1,6 @@
+export type Task = {
+ id: number;
+ description: string;
+ isDone: boolean;
+ userId: number | null;
+};
diff --git a/examples/todo-typescript/src/client/waspLogo.png b/examples/todo-typescript/src/client/waspLogo.png
new file mode 100644
index 000000000..d39a9443a
Binary files /dev/null and b/examples/todo-typescript/src/client/waspLogo.png differ
diff --git a/examples/todo-typescript/src/server/actions.ts b/examples/todo-typescript/src/server/actions.ts
new file mode 100644
index 000000000..7d29e0078
--- /dev/null
+++ b/examples/todo-typescript/src/server/actions.ts
@@ -0,0 +1,33 @@
+import HttpError from '@wasp/core/HttpError.js';
+import { Context, Task } from './serverTypes'
+
+type createArgs = { description: Task['description'] };
+
+export const createTask = async ({ description }: createArgs, context: Context) => {
+ if (!context.user) {
+ throw new HttpError(401);
+ }
+
+ return context.entities.Task.create({
+ data: {
+ description,
+ user: { connect: { id: context.user.id } },
+ },
+ });
+};
+
+type updateArgs = { taskId: Task['id']; isDone: Task['isDone'] };
+
+export const updateTask = async ({ taskId, isDone }: updateArgs, context: Context) => {
+ if (!context.user) {
+ throw new HttpError(401);
+ }
+
+ return context.entities.Task.updateMany({
+ where: {
+ id: taskId,
+ user: { id: context.user.id },
+ },
+ data: { isDone },
+ });
+};
diff --git a/examples/todo-typescript/src/server/queries.ts b/examples/todo-typescript/src/server/queries.ts
new file mode 100644
index 000000000..dab9b76a9
--- /dev/null
+++ b/examples/todo-typescript/src/server/queries.ts
@@ -0,0 +1,9 @@
+import HttpError from '@wasp/core/HttpError.js';
+import { Context, Task } from './serverTypes'
+
+export const getTasks = async (args: null, context: Context): Promise => {
+ if (!context.user) {
+ throw new HttpError(401);
+ }
+ return context.entities.Task.findMany({ where: { user: { id: context.user.id } } });
+};
diff --git a/examples/todo-typescript/src/server/serverTypes.ts b/examples/todo-typescript/src/server/serverTypes.ts
new file mode 100644
index 000000000..870f56eca
--- /dev/null
+++ b/examples/todo-typescript/src/server/serverTypes.ts
@@ -0,0 +1,11 @@
+import { Task as TaskType, User, Prisma } from '@prisma/client';
+
+export type Task = TaskType;
+
+export type Context = {
+ user: User;
+ entities: {
+ Task: Prisma.TaskDelegate<{}>;
+ User: Prisma.UserDelegate<{}>;
+ };
+};
diff --git a/examples/todo-typescript/src/server/tsconfig.json b/examples/todo-typescript/src/server/tsconfig.json
new file mode 100644
index 000000000..70a79b44e
--- /dev/null
+++ b/examples/todo-typescript/src/server/tsconfig.json
@@ -0,0 +1,48 @@
+// =============================== IMPORTANT =================================
+//
+// This file is only used for Wasp IDE support. You can change it to configure
+// your IDE checks, but none of these options will affect the TypeScript
+// compiler. Proper TS compiler configuration in Wasp is coming soon :)
+{
+ "compilerOptions": {
+ // Allows default imports.
+ "esModuleInterop": true,
+ "allowJs": true,
+ "strict": true,
+ // Wasp needs the following settings enable IDE support in your source
+ // files. Editing them might break features like import autocompletion and
+ // definition lookup. Don't change them unless you know what you're doing.
+ //
+ // The relative path to the generated web app's root directory. This must be
+ // set to define the "paths" option.
+ "baseUrl": "../../.wasp/out/server/",
+ "paths": {
+ // Resolve all "@wasp" imports to the generated source code.
+ "@wasp/*": [
+ "src/*"
+ ],
+ // Resolve all non-relative imports to the correct node module. Source:
+ // https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping
+ "*": [
+ // Start by looking for the definiton inside the node modules root
+ // directory...
+ "node_modules/*",
+ // ... If that fails, try to find it inside definitely-typed type
+ // definitions.
+ "node_modules/@types/*"
+ ]
+ },
+ // Correctly resolve types: https://www.typescriptlang.org/tsconfig#typeRoots
+ "typeRoots": [
+ "../../.wasp/out/server/node_modules/@types"
+ ],
+ // Since this TS config is used only for IDE support and not for
+ // compilation, the following directory doesn't exist. We need to specify
+ // it to prevent this error:
+ // https://stackoverflow.com/questions/42609768/typescript-error-cannot-write-file-because-it-would-overwrite-input-file
+ "outDir": "phantom",
+ },
+ "exclude": [
+ "phantom"
+ ],
+}
\ No newline at end of file
diff --git a/examples/todo-typescript/src/shared/tsconfig.json b/examples/todo-typescript/src/shared/tsconfig.json
new file mode 100644
index 000000000..f78b58a77
--- /dev/null
+++ b/examples/todo-typescript/src/shared/tsconfig.json
@@ -0,0 +1,28 @@
+{
+ "compilerOptions": {
+ // Enable default imports in TypeScript.
+ "esModuleInterop": true,
+ "allowJs": true,
+ // The following settings enable IDE support in user-provided source files.
+ // Editing them might break features like import autocompletion and
+ // definition lookup. Don't change them unless you know what you're doing.
+ //
+ // The relative path to the generated web app's root directory. This must be
+ // set to define the "paths" option.
+ "baseUrl": "../../.wasp/out/server/",
+ "paths": {
+ // Resolve all non-relative imports to the correct node module. Source:
+ // https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping
+ "*": [
+ // Start by looking for the definiton inside the node modules root
+ // directory...
+ "node_modules/*",
+ // ... If that fails, try to find it inside definitely-typed type
+ // definitions.
+ "node_modules/@types/*"
+ ]
+ },
+ // Correctly resolve types: https://www.typescriptlang.org/tsconfig#typeRoots
+ "typeRoots": ["../../.wasp/out/server/node_modules/@types"],
+ }
+}