~repos /edge-city

#react#js#ssr

git clone https://pyrossh.dev/repos/edge-city.git

edge-city is a next level meta-framework for react that runs only on edge runtimes


e6b4ebec pyrossh

2 years ago
Add eslint/prettier
example/.vscode/extensions.json CHANGED
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "recommendations": [
3
- "ms-playwright.playwright"
3
+ "ms-playwright.playwright",
4
+ "esbenp.prettier-vscode"
4
5
  ]
5
6
  }
example/.vscode/settings.json CHANGED
@@ -9,5 +9,10 @@
9
9
  "**/dist": true,
10
10
  "**/playwright-report": true,
11
11
  "test-results": true
12
- }
12
+ },
13
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
14
+ "[javascript]": {
15
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
16
+ "editor.formatOnSave": true
17
+ },
13
18
  }
example/package.json CHANGED
@@ -2,6 +2,8 @@
2
2
  "name": "edge-city-example",
3
3
  "type": "module",
4
4
  "scripts": {
5
+ "lint": "eslint ./src",
6
+ "fmt": "prettier ./src --write",
5
7
  "dev": "edge-city dev -p cloudflare",
6
8
  "dev:wrangler": "cd build && wrangler pages dev static",
7
9
  "deploy:wrangler": "cd build && wrangler pages deploy static",
@@ -30,13 +32,17 @@
30
32
  "eslint": "^8.35.0",
31
33
  "eslint-config-react-app": "^7.0.1",
32
34
  "postgres": "3.3.4",
35
+ "prettier": "^2.8.8",
33
36
  "wrangler": "3.0.1"
34
37
  },
35
38
  "prettier": {
36
- "printWidth": 120
39
+ "printWidth": 100,
40
+ "singleQuote": false,
41
+ "jsxSingleQuote": false,
42
+ "bracketSameLine": false,
43
+ "trailingComma": "all"
37
44
  },
38
45
  "eslintConfig": {
39
- "root": true,
40
46
  "parserOptions": {
41
47
  "ecmaVersion": "latest",
42
48
  "sourceType": "module"
@@ -45,13 +51,14 @@
45
51
  "eslint:recommended",
46
52
  "react-app"
47
53
  ],
48
- "ignorePatterns": [
49
- "build"
50
- ],
51
54
  "rules": {
52
55
  "react/prop-types": "warn",
53
56
  "react/react-in-jsx-scope": "off",
54
57
  "no-unused-vars": "warn"
58
+ },
59
+ "globals": {
60
+ "globalThis": false,
61
+ "db": false
55
62
  }
56
63
  }
57
64
  }
example/src/components/Counter/Counter.css CHANGED
@@ -6,4 +6,4 @@
6
6
  color: white;
7
7
  margin-left: 0.5rem;
8
8
  }
9
- }
9
+ }
example/src/components/Counter/Counter.jsx CHANGED
@@ -1,5 +1,5 @@
1
1
  import React, { useState } from "react";
2
- import { Button } from 'react-aria-components';
2
+ import { Button } from "react-aria-components";
3
3
  import "./Counter.css";
4
4
 
5
5
  const Counter = () => {
@@ -11,14 +11,12 @@ const Counter = () => {
11
11
  <Button className="button" onClick={increment}>
12
12
  -
13
13
  </Button>
14
- <span className="count">
14
+ <span className="count">{count}</span>
15
- {count}
16
- </span>
17
15
  <Button className="button" onClick={decrement}>
18
16
  +
19
17
  </Button>
20
18
  </div>
21
- )
19
+ );
22
- }
20
+ };
23
21
 
24
- export default Counter;
22
+ export default Counter;
example/src/components/Layout/Layout.css CHANGED
@@ -24,4 +24,4 @@
24
24
  border-left: 2px solid #eee;
25
25
  min-height: 100vh;
26
26
  }
27
- }
27
+ }
example/src/components/Layout/Layout.jsx CHANGED
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React from "react";
2
2
  import { Link } from "edge-city";
3
3
  import "./Layout.css";
4
4
 
@@ -10,11 +10,9 @@ const Layout = ({ children }) => {
10
10
  <Link href="/about">About us</Link>
11
11
  <Link href="/todos">Todos</Link>
12
12
  </div>
13
- <div className="content">
13
+ <div className="content">{children}</div>
14
- {children}
15
- </div>
16
14
  </div>
17
- )
15
+ );
18
- }
16
+ };
19
17
 
20
- export default Layout;
18
+ export default Layout;
example/src/components/Timer/Timer.jsx CHANGED
@@ -1,4 +1,4 @@
1
- import { useState, useEffect } from 'react';
1
+ import { useState, useEffect } from "react";
2
2
 
3
3
  export default function Timer() {
4
4
  const [counter, setCounter] = useState(0);
@@ -8,11 +8,11 @@ export default function Timer() {
8
8
  }, 100);
9
9
  return () => {
10
10
  clearInterval(ref);
11
- }
11
+ };
12
12
  }, []);
13
13
  return (
14
14
  <div>
15
15
  <p>(This page is interactive while data is loading: {counter})</p>
16
16
  </div>
17
17
  );
18
- }
18
+ }
example/src/components/Todo/Todo.css CHANGED
@@ -11,7 +11,8 @@
11
11
  display: flex;
12
12
  flex: 1;
13
13
  flex-direction: column;
14
- font-family: ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;
14
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
15
+ "Courier New", monospace;
15
16
  margin-left: 0.5rem;
16
17
  }
17
18
 
@@ -29,4 +30,4 @@
29
30
  & .delete-button {
30
31
  padding: 0.5rem;
31
32
  }
32
- }
33
+ }
example/src/components/Todo/Todo.jsx CHANGED
@@ -19,10 +19,13 @@ const Todo = ({ item, updateMutation, deleteMutation }) => {
19
19
  setBusy(true);
20
20
  save(item, null, item.completed);
21
21
  }, [item]);
22
- const doSaveCompleted = useCallback((completed) => {
22
+ const doSaveCompleted = useCallback(
23
+ (completed) => {
23
- setBusy(true);
24
+ setBusy(true);
24
- save(item, item.text, completed);
25
+ save(item, item.text, completed);
26
+ },
25
- }, [item]);
27
+ [item],
28
+ );
26
29
  return (
27
30
  <li className="todo">
28
31
  {!editing && (
@@ -32,16 +35,17 @@ const Todo = ({ item, updateMutation, deleteMutation }) => {
32
35
  <p>{item.text}</p>
33
36
  <p className="timestamp">{item.createdAt}</p>
34
37
  </div>
35
- <button className="edit-button" title="Edit">✏️</button>
38
+ <button className="edit-button" title="Edit">
39
+ ✏️
40
+ </button>
36
- <button class="delete-button" title="Delete">🗑️</button>
41
+ <button class="delete-button" title="Delete">
42
+ 🗑️
43
+ </button>
37
44
  </>
38
45
  )}
39
46
  {editing && (
40
47
  <>
41
- <input
42
- class="border rounded w-full py-2 px-3 mr-4"
48
+ <input class="border rounded w-full py-2 px-3 mr-4" defaultValue={item.text} />
43
- defaultValue={item.text}
44
- />
45
49
  <button
46
50
  class="p-2 rounded mr-2 disabled:opacity-50"
47
51
  title="Save"
example/src/init.js CHANGED
@@ -1,18 +1,20 @@
1
- import { drizzle } from 'drizzle-orm/neon-serverless';
1
+ import { drizzle } from "drizzle-orm/neon-serverless";
2
- import { Pool } from '@neondatabase/serverless';
2
+ import { Pool } from "@neondatabase/serverless";
3
- import { highlight } from 'sql-highlight';
3
+ import { highlight } from "sql-highlight";
4
4
 
5
5
  const init = async () => {
6
+ const pool = new Pool({
6
- const pool = new Pool({ connectionString: process.env.EDGE_PG_CONN_URL });
7
+ connectionString: process.env.EDGE_PG_CONN_URL,
8
+ });
7
9
  const db = drizzle(pool, {
8
10
  logger: {
9
11
  logQuery: (query, params) => {
10
12
  const sqlString = params.reduce((acc, v, i) => acc.replaceAll("$" + (i + 1), v), query);
11
13
  console.log(highlight(sqlString));
12
- }
14
+ },
13
- }
15
+ },
14
16
  });
15
17
  globalThis.db = db;
16
- }
18
+ };
17
19
 
18
- export default init;
20
+ export default init;
example/src/pages/_404/page.css CHANGED
@@ -5,12 +5,13 @@
5
5
  justify-content: center;
6
6
  color: #000;
7
7
  background: #fff;
8
- font-family: -apple-system, BlinkMacSystemFont, Roboto, "Segoe UI", "Fira Sans", Avenir, "Helvetica Neue", "Lucida Grande", sans-serif;
8
+ font-family: -apple-system, BlinkMacSystemFont, Roboto, "Segoe UI", "Fira Sans", Avenir,
9
+ "Helvetica Neue", "Lucida Grande", sans-serif;
9
10
  text-align: center;
10
11
 
11
12
  & h1 {
12
13
  display: inline-block;
13
- border-right: 1px solid rgba(0, 0, 0, .3);
14
+ border-right: 1px solid rgba(0, 0, 0, 0.3);
14
15
  margin: 0;
15
16
  margin-right: 20px;
16
17
  padding: 10px 23px 10px 0;
@@ -34,4 +35,4 @@
34
35
  margin: 0;
35
36
  padding: 0;
36
37
  }
37
- }
38
+ }
example/src/pages/_404/page.jsx CHANGED
@@ -1,5 +1,5 @@
1
- import React from 'react';
1
+ import React from "react";
2
- import { Helmet } from 'react-helmet-async';
2
+ import { Helmet } from "react-helmet-async";
3
3
  import "./page.css";
4
4
 
5
5
  export default function Page() {
@@ -13,5 +13,5 @@ export default function Page() {
13
13
  <h2>This page could not be found</h2>
14
14
  </div>
15
15
  </div>
16
- )
16
+ );
17
- }
17
+ }
example/src/pages/_500/page.css CHANGED
@@ -5,13 +5,14 @@
5
5
  justify-content: center;
6
6
  color: #000;
7
7
  background: #fff;
8
- font-family: -apple-system, BlinkMacSystemFont, Roboto, "Segoe UI", "Fira Sans", Avenir, "Helvetica Neue", "Lucida Grande", sans-serif;
8
+ font-family: -apple-system, BlinkMacSystemFont, Roboto, "Segoe UI", "Fira Sans", Avenir,
9
+ "Helvetica Neue", "Lucida Grande", sans-serif;
9
10
  height: 100vh;
10
11
  text-align: center;
11
12
 
12
13
  & h1 {
13
14
  display: inline-block;
14
- border-right: 1px solid rgba(0, 0, 0, .3);
15
+ border-right: 1px solid rgba(0, 0, 0, 0.3);
15
16
  margin: 0;
16
17
  margin-right: 20px;
17
18
  padding: 10px 23px 10px 0;
@@ -35,4 +36,4 @@
35
36
  margin: 0;
36
37
  padding: 0;
37
38
  }
38
- }
39
+ }
example/src/pages/_500/page.jsx CHANGED
@@ -1,5 +1,5 @@
1
- import React from 'react';
1
+ import React from "react";
2
- import { Helmet } from 'react-helmet-async';
2
+ import { Helmet } from "react-helmet-async";
3
3
  import "./page.css";
4
4
 
5
5
  export default function Page() {
@@ -13,5 +13,5 @@ export default function Page() {
13
13
  <h2>Internal Server Error</h2>
14
14
  </div>
15
15
  </div>
16
- )
16
+ );
17
- }
17
+ }
example/src/pages/about/page.css CHANGED
@@ -6,4 +6,4 @@
6
6
  & footer {
7
7
  margin-top: 100px;
8
8
  }
9
- }
9
+ }
example/src/pages/about/page.jsx CHANGED
@@ -1,6 +1,6 @@
1
- import React from 'react';
1
+ import React from "react";
2
2
  import { Link, useRouter } from "edge-city";
3
- import { Helmet } from 'react-helmet-async';
3
+ import { Helmet } from "react-helmet-async";
4
4
  import "./page.css";
5
5
 
6
6
  export default function Page() {
@@ -13,14 +13,12 @@ export default function Page() {
13
13
  </Helmet>
14
14
  <div>
15
15
  <h1>About Page</h1>
16
- <p>
17
- Path: {router.pathname}
16
+ <p>Path: {router.pathname}</p>
18
- </p>
19
17
  <p>Showcase of using edge-city meta-framework.</p>
20
18
  </div>
21
19
  <footer>
22
20
  <Link href="/">Back</Link>
23
21
  </footer>
24
22
  </div>
25
- )
23
+ );
26
24
  }
example/src/pages/app.css CHANGED
@@ -9,12 +9,12 @@
9
9
  box-sizing: border-box; /* 1 */
10
10
  border-width: 0; /* 2 */
11
11
  border-style: solid; /* 2 */
12
- border-color: theme('borderColor.DEFAULT', currentColor); /* 2 */
12
+ border-color: theme("borderColor.DEFAULT", currentColor); /* 2 */
13
13
  }
14
14
 
15
15
  ::before,
16
16
  ::after {
17
- --tw-content: '';
17
+ --tw-content: "";
18
18
  }
19
19
 
20
20
  /*
@@ -31,9 +31,25 @@ html {
31
31
  -webkit-text-size-adjust: 100%; /* 2 */
32
32
  -moz-tab-size: 4; /* 3 */
33
33
  tab-size: 4; /* 3 */
34
- font-family: theme('fontFamily.sans', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"); /* 4 */
35
- font-feature-settings: theme('fontFamily.sans[1].fontFeatureSettings', normal); /* 5 */
36
- font-variation-settings: theme('fontFamily.sans[1].fontVariationSettings', normal); /* 6 */
34
+ font-family: theme(
35
+ "fontFamily.sans",
36
+ ui-sans-serif,
37
+ system-ui,
38
+ -apple-system,
39
+ BlinkMacSystemFont,
40
+ "Segoe UI",
41
+ Roboto,
42
+ "Helvetica Neue",
43
+ Arial,
44
+ "Noto Sans",
45
+ sans-serif,
46
+ "Apple Color Emoji",
47
+ "Segoe UI Emoji",
48
+ "Segoe UI Symbol",
49
+ "Noto Color Emoji"
50
+ ); /* 4 */
51
+ font-feature-settings: theme("fontFamily.sans[1].fontFeatureSettings", normal); /* 5 */
52
+ font-variation-settings: theme("fontFamily.sans[1].fontVariationSettings", normal); /* 6 */
37
53
  }
38
54
 
39
55
  /*
@@ -107,7 +123,17 @@ code,
107
123
  kbd,
108
124
  samp,
109
125
  pre {
126
+ font-family: theme(
127
+ "fontFamily.mono",
128
+ ui-monospace,
129
+ SFMono-Regular,
130
+ Menlo,
131
+ Monaco,
132
+ Consolas,
110
- font-family: theme('fontFamily.mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace); /* 1 */
133
+ "Liberation Mono",
134
+ "Courier New",
135
+ monospace
136
+ ); /* 1 */
111
137
  font-size: 1em; /* 2 */
112
138
  }
113
139
 
@@ -186,9 +212,9 @@ select {
186
212
  */
187
213
 
188
214
  button,
189
- [type='button'],
215
+ [type="button"],
190
- [type='reset'],
216
+ [type="reset"],
191
- [type='submit'] {
217
+ [type="submit"] {
192
218
  -webkit-appearance: button; /* 1 */
193
219
  background-color: transparent; /* 2 */
194
220
  background-image: none; /* 2 */
@@ -232,7 +258,7 @@ Correct the cursor style of increment and decrement buttons in Safari.
232
258
  2. Correct the outline style in Safari.
233
259
  */
234
260
 
235
- [type='search'] {
261
+ [type="search"] {
236
262
  -webkit-appearance: textfield; /* 1 */
237
263
  outline-offset: -2px; /* 2 */
238
264
  }
@@ -316,7 +342,7 @@ textarea {
316
342
  input::placeholder,
317
343
  textarea::placeholder {
318
344
  opacity: 1; /* 1 */
319
- color: theme('colors.gray.400', #9ca3af); /* 2 */
345
+ color: theme("colors.gray.400", #9ca3af); /* 2 */
320
346
  }
321
347
 
322
348
  /*
@@ -372,7 +398,9 @@ html {
372
398
  line-height: 1.5;
373
399
  font-size: 16px;
374
400
  -webkit-text-size-adjust: 100%;
375
- font-family: ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";
401
+ font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
402
+ "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
403
+ "Segoe UI Symbol", "Noto Color Emoji";
376
404
  }
377
405
 
378
406
  body {
@@ -384,4 +412,4 @@ h1 {
384
412
  font-size: 1.25rem;
385
413
  line-height: 1.75rem;
386
414
  font-weight: 700;
387
- }
415
+ }
example/src/pages/app.jsx CHANGED
@@ -1,13 +1,11 @@
1
- import { SSRProvider } from 'react-aria';
1
+ import { SSRProvider } from "react-aria";
2
- import Layout from '@/components/Layout/Layout';
2
+ import Layout from "@/components/Layout/Layout";
3
3
  import "./app.css";
4
4
 
5
5
  export default function App({ children }) {
6
6
  return (
7
7
  <SSRProvider>
8
- <Layout>
9
- {children}
10
- </Layout>
8
+ <Layout>{children}</Layout>
11
9
  </SSRProvider>
12
- )
10
+ );
13
- }
11
+ }
example/src/pages/page.css CHANGED
@@ -5,4 +5,4 @@
5
5
  font-size: 30px;
6
6
  font-weight: 600;
7
7
  }
8
- }
8
+ }
example/src/pages/page.jsx CHANGED
@@ -1,7 +1,7 @@
1
- import React from 'react';
1
+ import React from "react";
2
2
  import { useRouter } from "edge-city";
3
3
  import Counter from "@/components/Counter/Counter";
4
- import { Helmet } from 'react-helmet-async';
4
+ import { Helmet } from "react-helmet-async";
5
5
  import "./page.css";
6
6
 
7
7
  export default function Page() {
@@ -13,11 +13,9 @@ export default function Page() {
13
13
  </Helmet>
14
14
  <div className="home-page">
15
15
  <h1>Home Page</h1>
16
- <p>
17
- Path: {router.pathname}
16
+ <p>Path: {router.pathname}</p>
18
- </p>
19
17
  <Counter />
20
18
  </div>
21
19
  </div>
22
- )
23
- };
20
+ );
21
+ }
example/src/pages/page.spec.js CHANGED
@@ -16,4 +16,4 @@
16
16
  // test('has counter', async ({ page }) => {
17
17
  // const counter = page.getByText("Counter");
18
18
  // expect(counter.innerText).toEqual("123");
19
- // });
19
+ // });
example/src/pages/todos/page.css CHANGED
@@ -71,7 +71,7 @@
71
71
  margin-right: 1rem;
72
72
  border-width: 1px;
73
73
  width: 100%;
74
- padding-left: 0.75rem;
74
+ padding-left: 0.75rem;
75
75
  padding-right: 0.75rem;
76
76
  padding-bottom: 0.5rem;
77
77
  padding-top: 0.5rem;
@@ -92,11 +92,11 @@
92
92
  }
93
93
  }
94
94
 
95
- [slot=description] {
95
+ [slot="description"] {
96
96
  font-size: 12px;
97
97
  }
98
98
 
99
- [slot=errorMessage] {
99
+ [slot="errorMessage"] {
100
100
  font-size: 12px;
101
101
  color: var(--invalid-color);
102
102
  }
@@ -112,4 +112,4 @@
112
112
  --focus-ring-color: Highlight;
113
113
  --invalid-color: LinkText;
114
114
  }
115
- }
115
+ }
example/src/pages/todos/page.jsx CHANGED
@@ -1,8 +1,8 @@
1
- import React from 'react';
1
+ import React from "react";
2
- import { Helmet } from 'react-helmet-async';
2
+ import { Helmet } from "react-helmet-async";
3
3
  import { useQuery, useMutation } from "edge-city";
4
- import { useForm } from 'react-hook-form';
4
+ import { useForm } from "react-hook-form";
5
- import { Button, TextField, Input } from 'react-aria-components';
5
+ import { Button, TextField, Input } from "react-aria-components";
6
6
  import Todo from "@/components/Todo/Todo";
7
7
  import { getTodos, createTodo, updateTodo, deleteTodo } from "@/services/todos.service";
8
8
  import "./page.css";
@@ -13,7 +13,7 @@ export default function Page() {
13
13
  await createTodo({
14
14
  text,
15
15
  completed: false,
16
- })
16
+ });
17
17
  await refetch();
18
18
  });
19
19
  const updateMutation = useMutation(async ({ text, completed }) => {
@@ -23,8 +23,12 @@ export default function Page() {
23
23
  const deleteMutation = useMutation(async (id) => {
24
24
  await deleteTodo(id);
25
25
  await refetch();
26
- })
26
+ });
27
+ const {
28
+ register,
29
+ handleSubmit,
27
- const { register, handleSubmit, formState: { errors } } = useForm();
30
+ formState: { errors },
31
+ } = useForm();
28
32
  return (
29
33
  <div className="todos-page">
30
34
  <h1 className="title">Todo List</h1>
@@ -35,10 +39,12 @@ export default function Page() {
35
39
  <p className="subtitle">Share this page to collaborate with others.</p>
36
40
  <form onSubmit={handleSubmit(mutate)}>
37
41
  <TextField isRequired isReadOnly={isMutating}>
38
- <Input {...register('text')} placeholder="Add a todo item" />
42
+ <Input {...register("text")} placeholder="Add a todo item" />
39
43
  {err?.text && <p>{err.text._errors[0]}</p>}
40
44
  </TextField>
41
- <Button className="add-button" type="submit" isDisabled={isMutating}>Add</Button>
45
+ <Button className="add-button" type="submit" isDisabled={isMutating}>
46
+ Add
47
+ </Button>
42
48
  </form>
43
49
  <ul>
44
50
  {data.map((item) => (
@@ -52,5 +58,5 @@ export default function Page() {
52
58
  </ul>
53
59
  </div>
54
60
  </div>
55
- )
61
+ );
56
- }
62
+ }
example/src/services/todos.service.js CHANGED
@@ -1,13 +1,13 @@
1
- import { eq, asc } from 'drizzle-orm';
1
+ import { eq, asc } from "drizzle-orm";
2
- import { boolean, date, pgTable, serial, text } from 'drizzle-orm/pg-core';
2
+ import { boolean, date, pgTable, serial, text } from "drizzle-orm/pg-core";
3
- import { z } from 'zod';
3
+ import { z } from "zod";
4
-
4
+
5
- export const todos = pgTable('todos', {
5
+ export const todos = pgTable("todos", {
6
- id: serial('id').primaryKey(),
6
+ id: serial("id").primaryKey(),
7
- text: text('text').notNull(),
7
+ text: text("text").notNull(),
8
- completed: boolean('completed').notNull(),
8
+ completed: boolean("completed").notNull(),
9
- createdAt: date('createdAt').notNull(),
9
+ createdAt: date("createdAt").notNull(),
10
- updatedAt: date('updatedAt'),
10
+ updatedAt: date("updatedAt"),
11
11
  });
12
12
 
13
13
  export const createSchema = z.object({
@@ -22,27 +22,27 @@ const updateSchema = z.object({
22
22
 
23
23
  export const getTodos = async () => {
24
24
  return await db.select().from(todos).orderBy(asc(todos.id));
25
- }
25
+ };
26
26
 
27
27
  /** @param {z.infer<typeof createSchema>} params */
28
28
  export const createTodo = async (params) => {
29
29
  const item = createSchema.parse(params);
30
30
  item.createdAt = new Date();
31
31
  return await db.insert(todos).values(item).returning();
32
- }
32
+ };
33
33
 
34
34
  export const getTodo = async (id) => {
35
35
  const results = await db.select().from(todos).where(eq(todos.id, id));
36
- return results[0]
36
+ return results[0];
37
- }
37
+ };
38
38
 
39
39
  /** @param {z.infer<typeof updateSchema>} params */
40
40
  export const updateTodo = async (params) => {
41
41
  const item = updateSchema.parse(params);
42
42
  item.updatedAt = new Date();
43
43
  return await db.update(todos).set(item).where(eq(todos.id, item.id)).returning();
44
- }
44
+ };
45
45
 
46
46
  export const deleteTodo = async (id) => {
47
47
  return await db.delete(todos).where(eq(todos.id, id)).returning();
48
- }
48
+ };
example/src/services/todos.service.test.js CHANGED
@@ -3,38 +3,34 @@ import { createSchema } from "./todos.service";
3
3
  test("validate createSchema", () => {
4
4
  expect(createSchema.safeParse({}).error.issues).toEqual([
5
5
  {
6
- "code": "invalid_type",
6
+ code: "invalid_type",
7
- "expected": "string",
7
+ expected: "string",
8
- "message": "Required",
8
+ message: "Required",
9
- "path": [
10
- "text"
9
+ path: ["text"],
11
- ],
12
- "received": "undefined"
10
+ received: "undefined",
13
11
  },
14
12
  {
15
- "code": "invalid_type",
13
+ code: "invalid_type",
16
- "expected": "boolean",
14
+ expected: "boolean",
17
- "message": "Required",
15
+ message: "Required",
18
- "path": [
19
- "completed"
16
+ path: ["completed"],
20
- ],
21
- "received": "undefined"
17
+ received: "undefined",
22
- }
18
+ },
23
- ])
19
+ ]);
20
+ expect(
24
- expect(createSchema.safeParse({
21
+ createSchema.safeParse({
25
- text: '',
22
+ text: "",
26
- completed: true,
23
+ completed: true,
27
- }).error.issues).toEqual([
24
+ }).error.issues,
25
+ ).toEqual([
28
26
  {
29
- "code": "too_small",
27
+ code: "too_small",
30
- "exact": false,
28
+ exact: false,
31
- "inclusive": true,
29
+ inclusive: true,
32
- "message": "please enter some text",
30
+ message: "please enter some text",
33
- "minimum": 1,
31
+ minimum: 1,
34
- "path": [
35
- "text"
32
+ path: ["text"],
36
- ],
37
- "type": "string"
33
+ type: "string",
38
34
  },
39
- ])
35
+ ]);
40
- })
36
+ });
pnpm-lock.yaml CHANGED
@@ -135,6 +135,9 @@ importers:
135
135
  postgres:
136
136
  specifier: 3.3.4
137
137
  version: 3.3.4
138
+ prettier:
139
+ specifier: ^2.8.8
140
+ version: 2.8.8
138
141
  wrangler:
139
142
  specifier: 3.0.1
140
143
  version: 3.0.1
@@ -7420,6 +7423,12 @@ packages:
7420
7423
  engines: {node: '>= 0.8.0'}
7421
7424
  dev: true
7422
7425
 
7426
+ /prettier@2.8.8:
7427
+ resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==}
7428
+ engines: {node: '>=10.13.0'}
7429
+ hasBin: true
7430
+ dev: true
7431
+
7423
7432
  /pretty-format@29.5.0:
7424
7433
  resolution: {integrity: sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==}
7425
7434
  engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}