zenstack 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (300) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +194 -1
  3. package/bin/cli +3 -0
  4. package/bin/post-install.js +24 -0
  5. package/cli/actions/generate.d.ts +13 -0
  6. package/cli/actions/generate.js +71 -0
  7. package/cli/actions/generate.js.map +1 -0
  8. package/cli/actions/index.d.ts +3 -0
  9. package/cli/actions/index.js +20 -0
  10. package/cli/actions/index.js.map +1 -0
  11. package/cli/actions/info.d.ts +4 -0
  12. package/cli/actions/info.js +63 -0
  13. package/cli/actions/info.js.map +1 -0
  14. package/cli/actions/init.d.ts +12 -0
  15. package/cli/actions/init.js +83 -0
  16. package/cli/actions/init.js.map +1 -0
  17. package/cli/cli-error.d.ts +5 -0
  18. package/cli/cli-error.js +10 -0
  19. package/cli/cli-error.js.map +1 -0
  20. package/cli/cli-util.d.ts +21 -0
  21. package/cli/cli-util.js +211 -0
  22. package/cli/cli-util.js.map +1 -0
  23. package/cli/config.d.ts +10 -0
  24. package/cli/config.js +62 -0
  25. package/cli/config.js.map +1 -0
  26. package/cli/index.d.ts +7 -0
  27. package/cli/index.js +128 -0
  28. package/cli/index.js.map +1 -0
  29. package/cli/plugin-runner.d.ts +24 -0
  30. package/cli/plugin-runner.js +229 -0
  31. package/cli/plugin-runner.js.map +1 -0
  32. package/constants.d.ts +1 -0
  33. package/constants.js +6 -0
  34. package/constants.js.map +1 -0
  35. package/language-server/constants.d.ts +22 -0
  36. package/language-server/constants.js +27 -0
  37. package/language-server/constants.js.map +1 -0
  38. package/language-server/main.d.ts +1 -0
  39. package/language-server/main.js +13 -0
  40. package/language-server/main.js.map +1 -0
  41. package/language-server/types.d.ts +10 -0
  42. package/language-server/types.js +3 -0
  43. package/language-server/types.js.map +1 -0
  44. package/language-server/utils.d.ts +5 -0
  45. package/language-server/utils.js +22 -0
  46. package/language-server/utils.js.map +1 -0
  47. package/language-server/validator/attribute-application-validator.d.ts +15 -0
  48. package/language-server/validator/attribute-application-validator.js +246 -0
  49. package/language-server/validator/attribute-application-validator.js.map +1 -0
  50. package/language-server/validator/attribute-validator.d.ts +9 -0
  51. package/language-server/validator/attribute-validator.js +14 -0
  52. package/language-server/validator/attribute-validator.js.map +1 -0
  53. package/language-server/validator/datamodel-validator.d.ts +22 -0
  54. package/language-server/validator/datamodel-validator.js +329 -0
  55. package/language-server/validator/datamodel-validator.js.map +1 -0
  56. package/language-server/validator/datasource-validator.d.ts +12 -0
  57. package/language-server/validator/datasource-validator.js +66 -0
  58. package/language-server/validator/datasource-validator.js.map +1 -0
  59. package/language-server/validator/enum-validator.d.ts +11 -0
  60. package/language-server/validator/enum-validator.js +25 -0
  61. package/language-server/validator/enum-validator.js.map +1 -0
  62. package/language-server/validator/expression-validator.d.ts +10 -0
  63. package/language-server/validator/expression-validator.js +135 -0
  64. package/language-server/validator/expression-validator.js.map +1 -0
  65. package/language-server/validator/function-decl-validator.d.ts +9 -0
  66. package/language-server/validator/function-decl-validator.js +13 -0
  67. package/language-server/validator/function-decl-validator.js.map +1 -0
  68. package/language-server/validator/function-invocation-validator.d.ts +11 -0
  69. package/language-server/validator/function-invocation-validator.js +135 -0
  70. package/language-server/validator/function-invocation-validator.js.map +1 -0
  71. package/language-server/validator/schema-validator.d.ts +13 -0
  72. package/language-server/validator/schema-validator.js +49 -0
  73. package/language-server/validator/schema-validator.js.map +1 -0
  74. package/language-server/validator/utils.d.ts +24 -0
  75. package/language-server/validator/utils.js +154 -0
  76. package/language-server/validator/utils.js.map +1 -0
  77. package/language-server/validator/zmodel-validator.d.ts +25 -0
  78. package/language-server/validator/zmodel-validator.js +83 -0
  79. package/language-server/validator/zmodel-validator.js.map +1 -0
  80. package/language-server/zmodel-code-action.d.ts +15 -0
  81. package/language-server/zmodel-code-action.js +118 -0
  82. package/language-server/zmodel-code-action.js.map +1 -0
  83. package/language-server/zmodel-definition.d.ts +7 -0
  84. package/language-server/zmodel-definition.js +31 -0
  85. package/language-server/zmodel-definition.js.map +1 -0
  86. package/language-server/zmodel-formatter.d.ts +9 -0
  87. package/language-server/zmodel-formatter.js +76 -0
  88. package/language-server/zmodel-formatter.js.map +1 -0
  89. package/language-server/zmodel-linker.d.ts +32 -0
  90. package/language-server/zmodel-linker.js +447 -0
  91. package/language-server/zmodel-linker.js.map +1 -0
  92. package/language-server/zmodel-module.d.ts +41 -0
  93. package/language-server/zmodel-module.js +83 -0
  94. package/language-server/zmodel-module.js.map +1 -0
  95. package/language-server/zmodel-scope.d.ts +16 -0
  96. package/language-server/zmodel-scope.js +100 -0
  97. package/language-server/zmodel-scope.js.map +1 -0
  98. package/language-server/zmodel-workspace-manager.d.ts +12 -0
  99. package/language-server/zmodel-workspace-manager.js +138 -0
  100. package/language-server/zmodel-workspace-manager.js.map +1 -0
  101. package/package.json +140 -8
  102. package/plugins/access-policy/expression-writer.d.ts +46 -0
  103. package/plugins/access-policy/expression-writer.js +580 -0
  104. package/plugins/access-policy/expression-writer.js.map +1 -0
  105. package/plugins/access-policy/index.d.ts +4 -0
  106. package/plugins/access-policy/index.js +22 -0
  107. package/plugins/access-policy/index.js.map +1 -0
  108. package/plugins/access-policy/policy-guard-generator.d.ts +22 -0
  109. package/plugins/access-policy/policy-guard-generator.js +634 -0
  110. package/plugins/access-policy/policy-guard-generator.js.map +1 -0
  111. package/plugins/model-meta/index.d.ts +4 -0
  112. package/plugins/model-meta/index.js +232 -0
  113. package/plugins/model-meta/index.js.map +1 -0
  114. package/plugins/plugin-utils.d.ts +17 -0
  115. package/plugins/plugin-utils.js +80 -0
  116. package/plugins/plugin-utils.js.map +1 -0
  117. package/plugins/prisma/indent-string.d.ts +4 -0
  118. package/plugins/prisma/indent-string.js +12 -0
  119. package/plugins/prisma/indent-string.js.map +1 -0
  120. package/plugins/prisma/index.d.ts +4 -0
  121. package/plugins/prisma/index.js +22 -0
  122. package/plugins/prisma/index.js.map +1 -0
  123. package/plugins/prisma/prisma-builder.d.ts +145 -0
  124. package/plugins/prisma/prisma-builder.js +358 -0
  125. package/plugins/prisma/prisma-builder.js.map +1 -0
  126. package/plugins/prisma/schema-generator.d.ts +29 -0
  127. package/plugins/prisma/schema-generator.js +336 -0
  128. package/plugins/prisma/schema-generator.js.map +1 -0
  129. package/plugins/prisma/zmodel-code-generator.d.ts +30 -0
  130. package/plugins/prisma/zmodel-code-generator.js +124 -0
  131. package/plugins/prisma/zmodel-code-generator.js.map +1 -0
  132. package/plugins/zod/generator.d.ts +4 -0
  133. package/plugins/zod/generator.js +254 -0
  134. package/plugins/zod/generator.js.map +1 -0
  135. package/plugins/zod/index.d.ts +4 -0
  136. package/plugins/zod/index.js +24 -0
  137. package/plugins/zod/index.js.map +1 -0
  138. package/plugins/zod/transformer.d.ts +68 -0
  139. package/plugins/zod/transformer.js +554 -0
  140. package/plugins/zod/transformer.js.map +1 -0
  141. package/plugins/zod/types.d.ts +25 -0
  142. package/plugins/zod/types.js +3 -0
  143. package/plugins/zod/types.js.map +1 -0
  144. package/plugins/zod/utils/removeDir.d.ts +1 -0
  145. package/plugins/zod/utils/removeDir.js +30 -0
  146. package/plugins/zod/utils/removeDir.js.map +1 -0
  147. package/plugins/zod/utils/schema-gen.d.ts +3 -0
  148. package/plugins/zod/utils/schema-gen.js +188 -0
  149. package/plugins/zod/utils/schema-gen.js.map +1 -0
  150. package/res/prism-zmodel.js +20 -0
  151. package/res/starter.zmodel +51 -0
  152. package/res/stdlib.zmodel +506 -0
  153. package/telemetry.d.ts +21 -0
  154. package/telemetry.js +129 -0
  155. package/telemetry.js.map +1 -0
  156. package/utils/ast-utils.d.ts +13 -0
  157. package/utils/ast-utils.js +136 -0
  158. package/utils/ast-utils.js.map +1 -0
  159. package/utils/exec-utils.d.ts +6 -0
  160. package/utils/exec-utils.js +13 -0
  161. package/utils/exec-utils.js.map +1 -0
  162. package/utils/pkg-utils.d.ts +3 -0
  163. package/utils/pkg-utils.js +64 -0
  164. package/utils/pkg-utils.js.map +1 -0
  165. package/utils/typescript-expression-transformer.d.ts +54 -0
  166. package/utils/typescript-expression-transformer.js +326 -0
  167. package/utils/typescript-expression-transformer.js.map +1 -0
  168. package/utils/version-utils.d.ts +1 -0
  169. package/utils/version-utils.js +20 -0
  170. package/utils/version-utils.js.map +1 -0
  171. package/.vscode/extensions.json +0 -7
  172. package/.vscode/launch.json +0 -49
  173. package/.vscode/settings.json +0 -4
  174. package/packages/internal/jest.config.ts +0 -32
  175. package/packages/internal/package.json +0 -42
  176. package/packages/internal/src/constants.ts +0 -1
  177. package/packages/internal/src/handler/data/guard-utils.ts +0 -7
  178. package/packages/internal/src/handler/data/handler.ts +0 -415
  179. package/packages/internal/src/handler/data/query-processor.ts +0 -504
  180. package/packages/internal/src/handler/index.ts +0 -1
  181. package/packages/internal/src/handler/types.ts +0 -20
  182. package/packages/internal/src/index.ts +0 -3
  183. package/packages/internal/src/request-handler.ts +0 -27
  184. package/packages/internal/src/request.ts +0 -101
  185. package/packages/internal/src/types.ts +0 -40
  186. package/packages/internal/tests/query-processor.test.ts +0 -172
  187. package/packages/internal/tsconfig.json +0 -21
  188. package/packages/runtime/auth.d.ts +0 -1
  189. package/packages/runtime/auth.js +0 -3
  190. package/packages/runtime/hooks.d.ts +0 -10
  191. package/packages/runtime/hooks.js +0 -3
  192. package/packages/runtime/index.d.ts +0 -3
  193. package/packages/runtime/index.js +0 -1
  194. package/packages/runtime/package-lock.json +0 -512
  195. package/packages/runtime/package.json +0 -16
  196. package/packages/runtime/server.d.ts +0 -1
  197. package/packages/runtime/server.js +0 -3
  198. package/packages/runtime/types.d.ts +0 -1
  199. package/packages/runtime/types.js +0 -3
  200. package/packages/schema/.eslintrc.json +0 -13
  201. package/packages/schema/.vscodeignore +0 -4
  202. package/packages/schema/asset/logo-dark.png +0 -0
  203. package/packages/schema/asset/logo-light.png +0 -0
  204. package/packages/schema/bin/cli +0 -3
  205. package/packages/schema/jest.config.ts +0 -32
  206. package/packages/schema/langium-config.json +0 -14
  207. package/packages/schema/langium-quickstart.md +0 -41
  208. package/packages/schema/language-configuration.json +0 -30
  209. package/packages/schema/package.json +0 -96
  210. package/packages/schema/src/cli/cli-util.ts +0 -80
  211. package/packages/schema/src/cli/index.ts +0 -64
  212. package/packages/schema/src/extension.ts +0 -76
  213. package/packages/schema/src/generator/constants.ts +0 -5
  214. package/packages/schema/src/generator/index.ts +0 -92
  215. package/packages/schema/src/generator/next-auth/index.ts +0 -197
  216. package/packages/schema/src/generator/package.template.json +0 -9
  217. package/packages/schema/src/generator/prisma/expression-writer.ts +0 -352
  218. package/packages/schema/src/generator/prisma/index.ts +0 -32
  219. package/packages/schema/src/generator/prisma/plain-expression-builder.ts +0 -91
  220. package/packages/schema/src/generator/prisma/prisma-builder.ts +0 -366
  221. package/packages/schema/src/generator/prisma/query-gard-generator.ts +0 -208
  222. package/packages/schema/src/generator/prisma/schema-generator.ts +0 -300
  223. package/packages/schema/src/generator/react-hooks/index.ts +0 -181
  224. package/packages/schema/src/generator/service/index.ts +0 -107
  225. package/packages/schema/src/generator/tsconfig.template.json +0 -17
  226. package/packages/schema/src/generator/types.ts +0 -17
  227. package/packages/schema/src/generator/utils.ts +0 -9
  228. package/packages/schema/src/language-server/generated/ast.ts +0 -603
  229. package/packages/schema/src/language-server/generated/grammar.ts +0 -2190
  230. package/packages/schema/src/language-server/generated/module.ts +0 -24
  231. package/packages/schema/src/language-server/main.ts +0 -12
  232. package/packages/schema/src/language-server/stdlib.zmodel +0 -22
  233. package/packages/schema/src/language-server/types.ts +0 -9
  234. package/packages/schema/src/language-server/zmodel-index.ts +0 -33
  235. package/packages/schema/src/language-server/zmodel-linker.ts +0 -409
  236. package/packages/schema/src/language-server/zmodel-module.ts +0 -90
  237. package/packages/schema/src/language-server/zmodel-scope.ts +0 -21
  238. package/packages/schema/src/language-server/zmodel-validator.ts +0 -35
  239. package/packages/schema/src/language-server/zmodel.langium +0 -186
  240. package/packages/schema/src/utils/exec-utils.ts +0 -5
  241. package/packages/schema/src/utils/indent-string.ts +0 -6
  242. package/packages/schema/syntaxes/zmodel.json +0 -57
  243. package/packages/schema/syntaxes/zmodel.tmLanguage.json +0 -57
  244. package/packages/schema/tests/generator/expression-writer.test.ts +0 -676
  245. package/packages/schema/tests/generator/prisma-builder.test.ts +0 -138
  246. package/packages/schema/tests/schema/parser.test.ts +0 -423
  247. package/packages/schema/tests/schema/sample-todo.test.ts +0 -14
  248. package/packages/schema/tests/utils.ts +0 -38
  249. package/packages/schema/tsconfig.json +0 -23
  250. package/pnpm-workspace.yaml +0 -3
  251. package/samples/todo/.env +0 -2
  252. package/samples/todo/.eslintrc.json +0 -3
  253. package/samples/todo/.vscode/launch.json +0 -11
  254. package/samples/todo/README.md +0 -34
  255. package/samples/todo/components/AuthGuard.tsx +0 -17
  256. package/samples/todo/components/Avatar.tsx +0 -22
  257. package/samples/todo/components/BreadCrumb.tsx +0 -44
  258. package/samples/todo/components/ManageMembers.tsx +0 -134
  259. package/samples/todo/components/NavBar.tsx +0 -57
  260. package/samples/todo/components/SpaceMembers.tsx +0 -76
  261. package/samples/todo/components/Spaces.tsx +0 -28
  262. package/samples/todo/components/TimeInfo.tsx +0 -17
  263. package/samples/todo/components/Todo.tsx +0 -72
  264. package/samples/todo/components/TodoList.tsx +0 -77
  265. package/samples/todo/lib/context.ts +0 -31
  266. package/samples/todo/next.config.js +0 -10
  267. package/samples/todo/package-lock.json +0 -7527
  268. package/samples/todo/package.json +0 -45
  269. package/samples/todo/pages/_app.tsx +0 -50
  270. package/samples/todo/pages/api/auth/[...nextauth].ts +0 -83
  271. package/samples/todo/pages/api/zenstack/[...path].ts +0 -16
  272. package/samples/todo/pages/create-space.tsx +0 -114
  273. package/samples/todo/pages/index.tsx +0 -32
  274. package/samples/todo/pages/space/[slug]/[listId]/index.tsx +0 -88
  275. package/samples/todo/pages/space/[slug]/index.tsx +0 -169
  276. package/samples/todo/postcss.config.js +0 -6
  277. package/samples/todo/public/avatar.jpg +0 -0
  278. package/samples/todo/public/favicon.ico +0 -0
  279. package/samples/todo/public/logo.png +0 -0
  280. package/samples/todo/public/vercel.svg +0 -4
  281. package/samples/todo/styles/globals.css +0 -7
  282. package/samples/todo/tailwind.config.js +0 -11
  283. package/samples/todo/tsconfig.json +0 -28
  284. package/samples/todo/types/next-auth.d.ts +0 -14
  285. package/samples/todo/types/next.d.ts +0 -16
  286. package/samples/todo/zenstack/migrations/20221014084317_init/migration.sql +0 -153
  287. package/samples/todo/zenstack/migrations/20221020094651_upate_cli/migration.sql +0 -23
  288. package/samples/todo/zenstack/migrations/migration_lock.toml +0 -3
  289. package/samples/todo/zenstack/schema.prisma +0 -126
  290. package/samples/todo/zenstack/schema.zmodel +0 -161
  291. package/tests/integration/jest.config.ts +0 -16
  292. package/tests/integration/package-lock.json +0 -1081
  293. package/tests/integration/package.json +0 -27
  294. package/tests/integration/tests/operation-coverate.test.ts +0 -563
  295. package/tests/integration/tests/operations.zmodel +0 -69
  296. package/tests/integration/tests/todo-e2e.test.ts +0 -577
  297. package/tests/integration/tests/todo.zmodel +0 -123
  298. package/tests/integration/tests/tsconfig.template.json +0 -10
  299. package/tests/integration/tests/utils.ts +0 -133
  300. package/tests/integration/tsconfig.json +0 -10
@@ -1,17 +0,0 @@
1
- import { signIn, useSession } from 'next-auth/react';
2
-
3
- type Props = {
4
- children: JSX.Element | JSX.Element[];
5
- };
6
-
7
- export default function AuthGuard({ children }: Props) {
8
- const { status } = useSession();
9
- if (status === 'loading') {
10
- return <p>Loading...</p>;
11
- } else if (status === 'unauthenticated') {
12
- signIn();
13
- return <></>;
14
- } else {
15
- return <>{children}</>;
16
- }
17
- }
@@ -1,22 +0,0 @@
1
- import { UserIcon } from '@heroicons/react/24/outline';
2
- import { User } from 'next-auth';
3
- import Image from 'next/image';
4
-
5
- type Props = {
6
- user: User;
7
- size?: number;
8
- };
9
-
10
- export default function Avatar({ user, size }: Props) {
11
- return (
12
- <div className="tooltip" data-tip={user.name || user.email}>
13
- <Image
14
- src={user.image || '/avatar.jpg'}
15
- alt="avatar"
16
- width={size || 32}
17
- height={size || 32}
18
- className="rounded-full"
19
- />
20
- </div>
21
- );
22
- }
@@ -1,44 +0,0 @@
1
- import { useList } from '@zenstackhq/runtime/hooks';
2
- import Link from 'next/link';
3
- import { useRouter } from 'next/router';
4
- import { useCurrentSpace } from '@lib/context';
5
-
6
- export default function BreadCrumb() {
7
- const router = useRouter();
8
- const space = useCurrentSpace();
9
- const { get: getList } = useList();
10
-
11
- const parts = router.asPath.split('/').filter((p) => p);
12
-
13
- const [base, slug, listId] = parts;
14
- if (base !== 'space') {
15
- return <></>;
16
- }
17
-
18
- const items: Array<{ text: string; link: string }> = [];
19
-
20
- items.push({ text: 'Home', link: '/' });
21
- items.push({ text: space?.name || '', link: `/space/${slug}` });
22
-
23
- if (listId) {
24
- const { data } = getList(listId);
25
- items.push({
26
- text: data?.title || '',
27
- link: `/space/${slug}/${listId}`,
28
- });
29
- }
30
-
31
- return (
32
- <div className="text-sm text-gray-600 breadcrumbs">
33
- <ul>
34
- {items.map((item, i) => (
35
- <li key={i}>
36
- <Link href={item.link}>
37
- <a>{item.text}</a>
38
- </Link>
39
- </li>
40
- ))}
41
- </ul>
42
- </div>
43
- );
44
- }
@@ -1,134 +0,0 @@
1
- import { PlusIcon, TrashIcon } from '@heroicons/react/24/outline';
2
- import { useCurrentUser } from '@lib/context';
3
- import { ServerErrorCode } from '@zenstackhq/internal';
4
- import { HooksError, useSpaceUser } from '@zenstackhq/runtime/hooks';
5
- import { Space, SpaceUserRole } from '@zenstackhq/runtime/types';
6
- import { ChangeEvent, KeyboardEvent, useState } from 'react';
7
- import { toast } from 'react-toastify';
8
- import Avatar from './Avatar';
9
-
10
- type Props = {
11
- space: Space;
12
- };
13
-
14
- export default function ManageMembers({ space }: Props) {
15
- const [email, setEmail] = useState('');
16
- const [role, setRole] = useState<SpaceUserRole>(SpaceUserRole.USER);
17
- const user = useCurrentUser();
18
-
19
- const { find, create: addMember, del: delMember } = useSpaceUser();
20
- const { data: members } = find({
21
- where: {
22
- spaceId: space.id,
23
- },
24
- include: {
25
- user: true,
26
- },
27
- });
28
-
29
- const inviteUser = async () => {
30
- try {
31
- const r = await addMember({
32
- data: {
33
- user: {
34
- connect: {
35
- email,
36
- },
37
- },
38
- space: {
39
- connect: {
40
- id: space.id,
41
- },
42
- },
43
- role,
44
- },
45
- });
46
- console.log('SpaceUser created:', r);
47
- } catch (err: any) {
48
- console.error(JSON.stringify(err));
49
- if (err.info?.code) {
50
- const { info } = err as HooksError;
51
- if (info.code === ServerErrorCode.UNIQUE_CONSTRAINT_VIOLATION) {
52
- toast.error('User is already a member of the space');
53
- } else if (
54
- info.code === ServerErrorCode.REFERENCE_CONSTRAINT_VIOLATION
55
- ) {
56
- toast.error('User is not found for this email');
57
- }
58
- } else {
59
- toast.error(`Error occurred: ${err}`);
60
- }
61
- }
62
- };
63
-
64
- const removeMember = async (id: string) => {
65
- if (confirm(`Are you sure to remove this member from space?`)) {
66
- await delMember(id);
67
- }
68
- };
69
-
70
- return (
71
- <div>
72
- <div className="flex flex-wrap gap-2 items-center mb-8 w-full">
73
- <input
74
- type="text"
75
- placeholder="Type user email and enter to invite"
76
- className="input input-sm input-bordered flex-grow mr-2"
77
- value={email}
78
- onChange={(e: ChangeEvent<HTMLInputElement>) => {
79
- setEmail(e.currentTarget.value);
80
- }}
81
- onKeyUp={(e: KeyboardEvent<HTMLInputElement>) => {
82
- if (e.key === 'Enter') {
83
- inviteUser();
84
- }
85
- }}
86
- />
87
-
88
- <select
89
- className="select select-sm mr-2"
90
- value={role}
91
- onChange={(e: ChangeEvent<HTMLSelectElement>) => {
92
- setRole(e.currentTarget.value as SpaceUserRole);
93
- }}
94
- >
95
- <option value={SpaceUserRole.USER}>USER</option>
96
- <option value={SpaceUserRole.ADMIN}>ADMIN</option>
97
- </select>
98
-
99
- <button>
100
- <PlusIcon className="w-6 h-6 text-gray-500" />
101
- </button>
102
- </div>
103
-
104
- <ul className="space-y-2">
105
- {members?.map((member) => (
106
- <li
107
- key={member.id}
108
- className="flex flex-wrap w-full justify-between"
109
- >
110
- <div className="flex items-center">
111
- <div className="hidden md:block mr-2">
112
- <Avatar user={member.user} size={32} />
113
- </div>
114
- <p className="w-36 md:w-48 line-clamp-1 mr-2">
115
- {member.user.name || member.user.email}
116
- </p>
117
- <p>{member.role}</p>
118
- </div>
119
- <div className="flex items-center">
120
- {user?.id !== member.user.id && (
121
- <TrashIcon
122
- className="w-4 h-4 text-gray-500"
123
- onClick={() => {
124
- removeMember(member.id);
125
- }}
126
- />
127
- )}
128
- </div>
129
- </li>
130
- ))}
131
- </ul>
132
- </div>
133
- );
134
- }
@@ -1,57 +0,0 @@
1
- import Image from 'next/image';
2
- import Avatar from './Avatar';
3
- import { signOut } from 'next-auth/react';
4
- import Link from 'next/link';
5
- import { Space } from '@zenstackhq/runtime/types';
6
- import { User } from 'next-auth';
7
-
8
- type Props = {
9
- space: Space | undefined;
10
- user: User | undefined;
11
- };
12
-
13
- export default function NavBar({ user, space }: Props) {
14
- return (
15
- <div className="navbar bg-base-100 px-8 py-2 border-b">
16
- <div className="flex-1">
17
- <Link href="/">
18
- <a className="flex items-center">
19
- <Image
20
- src="/logo.png"
21
- alt="Logo"
22
- width={32}
23
- height={32}
24
- />
25
- <div className="text-xl font-semibold ml-2 text-slate-700 hidden md:inline-block">
26
- {space?.name || 'Welcome Todo App'}
27
- </div>
28
- <p className="text-xs ml-2 text-gray-500 self-end">
29
- Powered by ZenStack
30
- </p>
31
- </a>
32
- </Link>
33
- </div>
34
- <div className="flex-none">
35
- <div className="dropdown dropdown-end">
36
- <label
37
- tabIndex={0}
38
- className="btn btn-ghost btn-circle avatar"
39
- >
40
- {user && <Avatar user={user!} />}
41
- </label>
42
- <ul
43
- tabIndex={0}
44
- className="menu menu-compact dropdown-content mt-3 p-2 shadow bg-base-100 rounded-box w-52"
45
- >
46
- <li className="border-b border-gray-200">
47
- {user && <div>{user.name || user.email}</div>}
48
- </li>
49
- <li>
50
- <a onClick={() => signOut()}>Logout</a>
51
- </li>
52
- </ul>
53
- </div>
54
- </div>
55
- </div>
56
- );
57
- }
@@ -1,76 +0,0 @@
1
- import { useSpaceUser } from '@zenstackhq/runtime/hooks';
2
- import { useCurrentSpace } from '@lib/context';
3
- import { PlusIcon } from '@heroicons/react/24/outline';
4
- import Avatar from './Avatar';
5
- import ManageMembers from './ManageMembers';
6
- import { Space } from '@zenstackhq/runtime/types';
7
-
8
- function ManagementDialog(space?: Space) {
9
- if (!space) return undefined;
10
- return (
11
- <>
12
- <label htmlFor="management-modal" className="modal-button">
13
- <PlusIcon className="w-6 h-6 text-gray-500 cursor-pointer mr-1" />
14
- </label>
15
-
16
- <input
17
- type="checkbox"
18
- id="management-modal"
19
- className="modal-toggle"
20
- />
21
- <div className="modal">
22
- <div className="modal-box">
23
- <h3 className="font-bold text-base md:text-lg">
24
- Manage Members of {space.name}
25
- </h3>
26
-
27
- <div className="p-4 mt-4">
28
- <ManageMembers space={space} />
29
- </div>
30
-
31
- <div className="modal-action">
32
- <label
33
- htmlFor="management-modal"
34
- className="btn btn-outline"
35
- >
36
- Close
37
- </label>
38
- </div>
39
- </div>
40
- </div>
41
- </>
42
- );
43
- }
44
-
45
- export default function SpaceMembers() {
46
- const space = useCurrentSpace();
47
-
48
- const { find: findMembers } = useSpaceUser();
49
- const { data: members } = findMembers({
50
- where: {
51
- spaceId: space?.id,
52
- },
53
- include: {
54
- user: true,
55
- },
56
- orderBy: {
57
- role: 'desc',
58
- },
59
- });
60
-
61
- return (
62
- <div className="flex items-center">
63
- {ManagementDialog(space)}
64
- {members && (
65
- <label
66
- className="mr-1 modal-button cursor-pointer"
67
- htmlFor="management-modal"
68
- >
69
- {members?.map((member) => (
70
- <Avatar key={member.id} user={member.user} size={24} />
71
- ))}
72
- </label>
73
- )}
74
- </div>
75
- );
76
- }
@@ -1,28 +0,0 @@
1
- import { useSpace } from '@zenstackhq/runtime/hooks';
2
- import Link from 'next/link';
3
-
4
- export default function Spaces() {
5
- const { find } = useSpace();
6
- const spaces = find();
7
-
8
- return (
9
- <ul className="flex flex-wrap gap-4">
10
- {spaces.data?.map((space) => (
11
- <li
12
- className="card w-80 h-32 shadow-xl text-gray-600 cursor-pointer hover:bg-gray-50 border"
13
- key={space.id}
14
- >
15
- <Link href={`/space/${space.slug}`}>
16
- <a>
17
- <div className="card-body" title={space.name}>
18
- <h2 className="card-title line-clamp-1">
19
- {space.name}
20
- </h2>
21
- </div>
22
- </a>
23
- </Link>
24
- </li>
25
- ))}
26
- </ul>
27
- );
28
- }
@@ -1,17 +0,0 @@
1
- import moment from 'moment';
2
-
3
- type Props = {
4
- value: { createdAt: Date; updatedAt: Date; completedAt?: Date | null };
5
- };
6
-
7
- export default function TimeInfo({ value }: Props) {
8
- return (
9
- <p className="text-sm text-gray-500">
10
- {value.completedAt
11
- ? `Completed ${moment(value.completedAt).fromNow()}`
12
- : value.createdAt === value.updatedAt
13
- ? `Created ${moment(value.createdAt).fromNow()}`
14
- : `Updated ${moment(value.updatedAt).fromNow()}`}
15
- </p>
16
- );
17
- }
@@ -1,72 +0,0 @@
1
- import { TrashIcon } from '@heroicons/react/24/outline';
2
- import { useTodo } from '@zenstackhq/runtime/hooks';
3
- import { Todo, User } from '@zenstackhq/runtime/types';
4
- import { ChangeEvent, useEffect, useState } from 'react';
5
- import Avatar from './Avatar';
6
- import TimeInfo from './TimeInfo';
7
-
8
- type Props = {
9
- value: Todo & { owner: User };
10
- updated?: (value: Todo) => any;
11
- deleted?: (value: Todo) => any;
12
- };
13
-
14
- export default function Component({ value, updated, deleted }: Props) {
15
- const [completed, setCompleted] = useState(!!value.completedAt);
16
- const { update, del } = useTodo();
17
-
18
- useEffect(() => {
19
- if (!!value.completedAt !== completed) {
20
- update(value.id, {
21
- data: { completedAt: completed ? new Date() : null },
22
- }).then((newValue) => {
23
- if (updated) {
24
- updated(newValue);
25
- }
26
- });
27
- }
28
- });
29
-
30
- const deleteTodo = async () => {
31
- await del(value.id);
32
- if (deleted) {
33
- deleted(value);
34
- }
35
- };
36
-
37
- return (
38
- <div className="border rounded-lg px-8 py-4 shadow-lg flex flex-col items-center w-full lg:w-[480px]">
39
- <div className="flex justify-between w-full mb-4">
40
- <h3
41
- className={`text-xl line-clamp-1 ${
42
- value.completedAt
43
- ? 'line-through text-gray-400 italic'
44
- : 'text-gray-700'
45
- }`}
46
- >
47
- {value.title}
48
- </h3>
49
- <div className="flex">
50
- <input
51
- type="checkbox"
52
- className="checkbox mr-2"
53
- checked={completed}
54
- onChange={(e: ChangeEvent<HTMLInputElement>) =>
55
- setCompleted(e.currentTarget.checked)
56
- }
57
- />
58
- <TrashIcon
59
- className="w-6 h-6 text-gray-500 cursor-pointer"
60
- onClick={() => {
61
- deleteTodo();
62
- }}
63
- />
64
- </div>
65
- </div>
66
- <div className="flex justify-end w-full space-x-2">
67
- <TimeInfo value={value} />
68
- <Avatar user={value.owner} size={18} />
69
- </div>
70
- </div>
71
- );
72
- }
@@ -1,77 +0,0 @@
1
- import Image from 'next/image';
2
- import { List } from '@zenstackhq/runtime/types';
3
- import { customAlphabet } from 'nanoid';
4
- import { LockClosedIcon, TrashIcon } from '@heroicons/react/24/outline';
5
- import { User } from 'next-auth';
6
- import Avatar from './Avatar';
7
- import Link from 'next/link';
8
- import { useRouter } from 'next/router';
9
- import { useList } from '@zenstackhq/runtime/hooks';
10
- import TimeInfo from './TimeInfo';
11
-
12
- type Props = {
13
- value: List & { owner: User };
14
- deleted?: (value: List) => void;
15
- };
16
-
17
- export default function TodoList({ value, deleted }: Props) {
18
- const router = useRouter();
19
-
20
- const { del } = useList();
21
-
22
- const deleteList = async () => {
23
- if (confirm('Are you sure to delete this list?')) {
24
- await del(value.id);
25
- if (deleted) {
26
- deleted(value);
27
- }
28
- }
29
- };
30
-
31
- return (
32
- <div className="card w-80 bg-base-100 shadow-xl cursor-pointer hover:bg-gray-50">
33
- <Link href={`${router.asPath}/${value.id}`}>
34
- <a>
35
- <figure>
36
- <Image
37
- src={`https://picsum.photos/300/200?r=${customAlphabet(
38
- '0123456789'
39
- )(4)}`}
40
- width={320}
41
- height={200}
42
- alt="Cover"
43
- />
44
- </figure>
45
- </a>
46
- </Link>
47
- <div className="card-body">
48
- <Link href={`${router.asPath}/${value.id}`}>
49
- <a>
50
- <h2 className="card-title line-clamp-1">
51
- {value.title || 'Missing Title'}
52
- </h2>
53
- </a>
54
- </Link>
55
- <div className="card-actions flex w-full justify-between">
56
- <div>
57
- <TimeInfo value={value} />
58
- </div>
59
- <div className="flex space-x-2">
60
- <Avatar user={value.owner} size={18} />
61
- {value.private && (
62
- <div className="tooltip" data-tip="Private">
63
- <LockClosedIcon className="w-4 h-4 text-gray-500" />
64
- </div>
65
- )}
66
- <TrashIcon
67
- className="w-4 h-4 text-gray-500 cursor-pointer"
68
- onClick={() => {
69
- deleteList();
70
- }}
71
- />
72
- </div>
73
- </div>
74
- </div>
75
- </div>
76
- );
77
- }
@@ -1,31 +0,0 @@
1
- import { useSpace } from '@zenstackhq/runtime/hooks';
2
- import { Space } from '@zenstackhq/runtime/types';
3
- import { User } from 'next-auth';
4
- import { useSession } from 'next-auth/react';
5
- import { useRouter } from 'next/router';
6
- import { createContext } from 'react';
7
-
8
- export const UserContext = createContext<User | undefined>(undefined);
9
-
10
- export function useCurrentUser() {
11
- const { data: session } = useSession();
12
- return session?.user;
13
- }
14
-
15
- export const SpaceContext = createContext<Space | undefined>(undefined);
16
-
17
- export function useCurrentSpace() {
18
- const router = useRouter();
19
- const { find } = useSpace();
20
- const spaces = find({
21
- where: {
22
- slug: router.query.slug as string,
23
- },
24
- });
25
-
26
- if (!router.query.slug) {
27
- return undefined;
28
- }
29
-
30
- return spaces.data?.[0];
31
- }
@@ -1,10 +0,0 @@
1
- /** @type {import('next').NextConfig} */
2
- const nextConfig = {
3
- reactStrictMode: true,
4
- swcMinify: true,
5
- images: {
6
- domains: ['lh3.googleusercontent.com', 'picsum.photos'],
7
- },
8
- };
9
-
10
- module.exports = nextConfig;