@idealyst/cli 1.0.91 → 1.0.93

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 (71) hide show
  1. package/dist/generators/init.js +8 -13
  2. package/dist/generators/init.js.map +1 -1
  3. package/dist/generators/utils.js +3 -7
  4. package/dist/generators/utils.js.map +1 -1
  5. package/dist/template/.devcontainer/gitignore.template +2 -0
  6. package/dist/template/gitignore.template +56 -0
  7. package/dist/template/mcp.json.template +8 -0
  8. package/dist/template/packages/api/README.md +400 -164
  9. package/dist/template/packages/api/gitignore.template +35 -0
  10. package/dist/template/packages/api/package.json +11 -1
  11. package/dist/template/packages/api/src/context.ts +35 -2
  12. package/dist/template/packages/api/src/graphql/builder.ts +75 -0
  13. package/dist/template/packages/api/src/graphql/generated.ts +64 -0
  14. package/dist/template/packages/api/src/graphql/index.ts +75 -0
  15. package/dist/template/packages/api/src/graphql/types/index.ts +44 -0
  16. package/dist/template/packages/api/src/graphql/types/test.ts +245 -0
  17. package/dist/template/packages/api/src/index.ts +20 -3
  18. package/dist/template/packages/api/src/lib/database.ts +1 -1
  19. package/dist/template/packages/api/src/routers/test.ts +140 -38
  20. package/dist/template/packages/api/src/server.ts +23 -5
  21. package/dist/template/packages/api/tsconfig.json +1 -0
  22. package/dist/template/packages/database/gitignore.template +41 -0
  23. package/dist/template/packages/mobile/babel.config.js +1 -2
  24. package/dist/template/packages/mobile/gitignore.template +73 -0
  25. package/dist/template/packages/mobile/package.json +10 -2
  26. package/dist/template/packages/shared/gitignore.template +35 -0
  27. package/dist/template/packages/shared/package.json +6 -0
  28. package/dist/template/packages/shared/src/components/App.tsx +13 -2
  29. package/dist/template/packages/shared/src/components/HelloWorld.tsx +333 -106
  30. package/dist/template/packages/shared/src/graphql/client.ts +34 -0
  31. package/dist/template/packages/shared/src/index.ts +8 -0
  32. package/dist/template/packages/web/gitignore.template +35 -0
  33. package/dist/template/packages/web/vite.config.ts +2 -2
  34. package/dist/template/yarnrc.yml.template +4 -0
  35. package/package.json +1 -1
  36. package/template/packages/api/README.md +400 -164
  37. package/template/packages/api/package.json +11 -1
  38. package/template/packages/api/src/context.ts +35 -2
  39. package/template/packages/api/src/graphql/builder.ts +75 -0
  40. package/template/packages/api/src/graphql/generated.ts +64 -0
  41. package/template/packages/api/src/graphql/index.ts +75 -0
  42. package/template/packages/api/src/graphql/types/index.ts +44 -0
  43. package/template/packages/api/src/graphql/types/test.ts +245 -0
  44. package/template/packages/api/src/index.ts +20 -3
  45. package/template/packages/api/src/lib/database.ts +1 -1
  46. package/template/packages/api/src/routers/test.ts +140 -38
  47. package/template/packages/api/src/server.ts +23 -5
  48. package/template/packages/api/tsconfig.json +1 -0
  49. package/template/packages/mobile/babel.config.js +1 -2
  50. package/template/packages/mobile/package.json +10 -2
  51. package/template/packages/shared/package.json +6 -0
  52. package/template/packages/shared/src/components/App.tsx +13 -2
  53. package/template/packages/shared/src/components/HelloWorld.tsx +333 -106
  54. package/template/packages/shared/src/graphql/client.ts +34 -0
  55. package/template/packages/shared/src/index.ts +8 -0
  56. package/template/packages/web/vite.config.ts +2 -2
  57. package/dist/template/packages/api/src/lib/crud.ts +0 -150
  58. package/dist/template/packages/api/src/routers/user.example.ts +0 -83
  59. package/dist/template/packages/mobile/src/App-with-trpc-and-shared.tsx +0 -8
  60. package/dist/template/packages/mobile/src/App-with-trpc.tsx +0 -30
  61. package/dist/template/packages/web/src/App-with-trpc-and-shared.tsx +0 -14
  62. package/dist/template/packages/web/src/App-with-trpc.tsx +0 -32
  63. package/template/packages/api/src/lib/crud.ts +0 -150
  64. package/template/packages/api/src/routers/user.example.ts +0 -83
  65. package/template/packages/mobile/src/App-with-trpc-and-shared.tsx +0 -8
  66. package/template/packages/mobile/src/App-with-trpc.tsx +0 -30
  67. package/template/packages/web/src/App-with-trpc-and-shared.tsx +0 -14
  68. package/template/packages/web/src/App-with-trpc.tsx +0 -32
  69. /package/dist/template/{.dockerignore → dockerignore.template} +0 -0
  70. /package/dist/template/{.env.example → env.example.template} +0 -0
  71. /package/dist/template/packages/api/{.env.example → env.example.template} +0 -0
@@ -1,57 +1,159 @@
1
- import { z } from "zod";
2
- import { createCrudRouter } from "../lib/crud.js";
3
-
4
- // Define Zod schemas for the Test model based on the Prisma schema
5
- const createTestSchema = z.object({
6
- name: z.string().min(1, "Name is required"),
7
- message: z.string().min(1, "Message is required"),
8
- status: z.string().optional().default("active"),
9
- });
1
+ import { z } from 'zod';
2
+ import { prisma } from '../lib/database.js';
3
+ import { publicProcedure, router } from '../trpc.js';
10
4
 
11
- const updateTestSchema = z.object({
12
- name: z.string().min(1, "Name is required").optional(),
13
- message: z.string().min(1, "Message is required").optional(),
14
- status: z.string().optional(),
15
- });
5
+ /**
6
+ * Test Router - tRPC CRUD operations for the Test model
7
+ *
8
+ * This router provides standard CRUD operations via tRPC.
9
+ * For the GraphQL equivalent, see src/graphql/types/test.ts
10
+ *
11
+ * Endpoints:
12
+ * - test.getById({ id }) - Get test by ID
13
+ * - test.getAll({ skip, take }) - Get all tests with pagination
14
+ * - test.count({ status }) - Get count of tests
15
+ * - test.create({ name, message }) - Create new test
16
+ * - test.update({ id, data }) - Update existing test
17
+ * - test.delete({ id }) - Delete test
18
+ */
19
+ export const testRouter = router({
20
+ // Get a single test by ID
21
+ getById: publicProcedure
22
+ .input(z.object({ id: z.string() }))
23
+ .query(async ({ input }) => {
24
+ const test = await prisma.test.findUnique({
25
+ where: { id: input.id },
26
+ });
27
+
28
+ if (!test) {
29
+ throw new Error('Test not found');
30
+ }
31
+
32
+ return test;
33
+ }),
34
+
35
+ // Get all tests with pagination
36
+ getAll: publicProcedure
37
+ .input(z.object({
38
+ skip: z.number().min(0).optional(),
39
+ take: z.number().min(1).max(100).optional(),
40
+ orderBy: z.enum(['createdAt', 'updatedAt', 'name']).optional(),
41
+ orderDir: z.enum(['asc', 'desc']).optional(),
42
+ }))
43
+ .query(async ({ input }) => {
44
+ const take = input.take ?? 10;
45
+ const orderField = input.orderBy ?? 'createdAt';
46
+ const orderDir = input.orderDir ?? 'desc';
47
+
48
+ return prisma.test.findMany({
49
+ ...(input.skip != null ? { skip: input.skip } : {}),
50
+ take,
51
+ orderBy: { [orderField]: orderDir },
52
+ });
53
+ }),
54
+
55
+ // Get count of tests
56
+ count: publicProcedure
57
+ .input(z.object({
58
+ status: z.string().optional(),
59
+ }))
60
+ .query(async ({ input }) => {
61
+ return prisma.test.count({
62
+ ...(input.status != null ? { where: { status: input.status } } : {}),
63
+ });
64
+ }),
16
65
 
17
- // Create the CRUD router for the Test model
18
- export const testRouter = createCrudRouter(
19
- "Test",
20
- createTestSchema,
21
- updateTestSchema
22
- );
66
+ // Create a new test
67
+ create: publicProcedure
68
+ .input(z.object({
69
+ name: z.string().min(1, 'Name is required'),
70
+ message: z.string().min(1, 'Message is required'),
71
+ status: z.string().optional().default('active'),
72
+ }))
73
+ .mutation(async ({ input }) => {
74
+ return prisma.test.create({
75
+ data: {
76
+ name: input.name,
77
+ message: input.message,
78
+ status: input.status,
79
+ },
80
+ });
81
+ }),
82
+
83
+ // Update an existing test
84
+ update: publicProcedure
85
+ .input(z.object({
86
+ id: z.string(),
87
+ data: z.object({
88
+ name: z.string().min(1).optional(),
89
+ message: z.string().min(1).optional(),
90
+ status: z.string().optional(),
91
+ }),
92
+ }))
93
+ .mutation(async ({ input }) => {
94
+ const existing = await prisma.test.findUnique({
95
+ where: { id: input.id },
96
+ });
97
+
98
+ if (!existing) {
99
+ throw new Error('Test not found');
100
+ }
101
+
102
+ // Build update data only with defined values
103
+ const updateData: { name?: string; message?: string; status?: string } = {};
104
+ if (input.data.name != null) updateData.name = input.data.name;
105
+ if (input.data.message != null) updateData.message = input.data.message;
106
+ if (input.data.status != null) updateData.status = input.data.status;
107
+
108
+ return prisma.test.update({
109
+ where: { id: input.id },
110
+ data: updateData,
111
+ });
112
+ }),
113
+
114
+ // Delete a test
115
+ delete: publicProcedure
116
+ .input(z.object({ id: z.string() }))
117
+ .mutation(async ({ input }) => {
118
+ const existing = await prisma.test.findUnique({
119
+ where: { id: input.id },
120
+ });
121
+
122
+ if (!existing) {
123
+ throw new Error('Test not found');
124
+ }
125
+
126
+ return prisma.test.delete({
127
+ where: { id: input.id },
128
+ });
129
+ }),
130
+ });
23
131
 
24
132
  /**
25
- * This generates the following endpoints:
26
- *
27
- * - test.getAll({ skip?, take?, orderBy? }) - Get all test records with pagination
28
- * - test.getById({ id }) - Get test record by ID
29
- * - test.create({ name, message, status? }) - Create new test record
30
- * - test.update({ id, data: { name?, message?, status? } }) - Update test record
31
- * - test.delete({ id }) - Delete test record
32
- * - test.count({ where? }) - Get test record count
33
- *
34
133
  * Example usage in frontend:
35
- *
134
+ *
36
135
  * ```typescript
37
136
  * // Get all tests
38
137
  * const { data: tests } = trpc.test.getAll.useQuery({ take: 10 });
39
- *
138
+ *
139
+ * // Get test by ID
140
+ * const { data: test } = trpc.test.getById.useQuery({ id: 'test-id' });
141
+ *
40
142
  * // Create a new test
41
143
  * const createTest = trpc.test.create.useMutation();
42
- * await createTest.mutateAsync({
43
- * name: 'My Test',
144
+ * await createTest.mutateAsync({
145
+ * name: 'My Test',
44
146
  * message: 'This is a test message',
45
147
  * status: 'active'
46
148
  * });
47
- *
149
+ *
48
150
  * // Update a test
49
151
  * const updateTest = trpc.test.update.useMutation();
50
- * await updateTest.mutateAsync({
51
- * id: 'test-id',
52
- * data: { name: 'Updated Test' }
152
+ * await updateTest.mutateAsync({
153
+ * id: 'test-id',
154
+ * data: { name: 'Updated Test' }
53
155
  * });
54
- *
156
+ *
55
157
  * // Delete a test
56
158
  * const deleteTest = trpc.test.delete.useMutation();
57
159
  * await deleteTest.mutateAsync({ id: 'test-id' });
@@ -3,6 +3,7 @@ import cors from 'cors';
3
3
  import { createExpressMiddleware } from '@trpc/server/adapters/express';
4
4
  import { appRouter } from './router/index.js';
5
5
  import { createContext } from './context.js';
6
+ import { yoga } from './graphql/index.js';
6
7
  import dotenv from 'dotenv';
7
8
 
8
9
  // Load environment variables
@@ -17,12 +18,15 @@ app.use(cors({
17
18
  credentials: true,
18
19
  }));
19
20
 
21
+ // Parse JSON bodies (needed for some GraphQL clients)
22
+ app.use(express.json());
23
+
20
24
  // Health check endpoint
21
- app.get('/health', (req, res) => {
25
+ app.get('/health', (_req, res) => {
22
26
  res.json({ status: 'OK', timestamp: new Date().toISOString() });
23
27
  });
24
28
 
25
- // tRPC middleware
29
+ // tRPC middleware - for internal TypeScript clients
26
30
  app.use(
27
31
  '/trpc',
28
32
  createExpressMiddleware({
@@ -31,20 +35,34 @@ app.use(
31
35
  })
32
36
  );
33
37
 
38
+ // GraphQL middleware - for public API, mobile clients, etc.
39
+ // GraphQL Yoga handles the /graphql endpoint
40
+ // Using all() to handle both GET (GraphiQL) and POST (queries)
41
+ app.all('/graphql', yoga as unknown as express.RequestHandler);
42
+
34
43
  // Default route
35
- app.get('/', (req, res) => {
44
+ app.get('/', (_req, res) => {
36
45
  res.json({
37
46
  message: 'Welcome to {{projectName}} API',
38
47
  endpoints: {
39
48
  health: '/health',
40
49
  trpc: '/trpc',
41
- playground: '/trpc-playground' // Available in development
42
- }
50
+ graphql: '/graphql',
51
+ graphiql: process.env.NODE_ENV !== 'production' ? '/graphql' : undefined,
52
+ },
53
+ documentation: {
54
+ trpc: 'Use tRPC for internal TypeScript clients with full type safety',
55
+ graphql: 'Use GraphQL for public APIs, mobile apps, and third-party integrations',
56
+ },
43
57
  });
44
58
  });
45
59
 
46
60
  app.listen(PORT, () => {
47
61
  console.log(`🚀 Server running on http://localhost:${PORT}`);
48
62
  console.log(`📡 tRPC API available at http://localhost:${PORT}/trpc`);
63
+ console.log(`📊 GraphQL API available at http://localhost:${PORT}/graphql`);
64
+ if (process.env.NODE_ENV !== 'production') {
65
+ console.log(`🎮 GraphiQL Playground at http://localhost:${PORT}/graphql`);
66
+ }
49
67
  console.log(`🏥 Health check at http://localhost:${PORT}/health`);
50
68
  });
@@ -2,6 +2,7 @@
2
2
  "compilerOptions": {
3
3
  "target": "ES2020",
4
4
  "module": "ESNext",
5
+ "moduleResolution": "bundler",
5
6
  "allowSyntheticDefaultImports": true,
6
7
  "esModuleInterop": true,
7
8
  "allowJs": true,
@@ -5,7 +5,6 @@ module.exports = {
5
5
  root: 'src',
6
6
  autoProcessPaths: ['@idealyst/components', '@idealyst/navigation', '@idealyst/theme'],
7
7
  }],
8
- 'react-native-reanimated/plugin',
9
- 'react-native-worklets/plugin',
8
+ 'react-native-reanimated/plugin'
10
9
  ],
11
10
  };
@@ -22,9 +22,17 @@
22
22
  "@trpc/client": "^11.5.1",
23
23
  "@trpc/react-query": "^11.5.1",
24
24
  "@trpc/server": "^11.5.1",
25
- "react": "^18.2.0",
26
- "react-native": "^0.73.0",
25
+ "react": "19.1.1",
26
+ "react-native": "0.82.1",
27
+ "react-native-edge-to-edge": "^1.6.2",
28
+ "react-native-gesture-handler": "^2.27.1",
29
+ "react-native-nitro-modules": "^0.30.0",
30
+ "react-native-reanimated": "^4.1.3",
31
+ "react-native-safe-area-context": "^5.5.1",
32
+ "react-native-screens": "^4.11.1",
27
33
  "react-native-svg": "^15.8.0",
34
+ "react-native-unistyles": "^3.0.4",
35
+ "react-native-vector-icons": "^10.2.0",
28
36
  "react-native-worklets": "^0.6.1"
29
37
  },
30
38
  "devDependencies": {
@@ -35,6 +35,12 @@
35
35
  "optional": true
36
36
  }
37
37
  },
38
+ "dependencies": {
39
+ "@mdi/js": "^7.4.47",
40
+ "@mdi/react": "^1.6.1",
41
+ "graphql": "^16.9.0",
42
+ "graphql-request": "^7.1.2"
43
+ },
38
44
  "devDependencies": {
39
45
  "@idealyst/components": "^{{idealystVersion}}",
40
46
  "@idealyst/navigation": "^{{idealystVersion}}",
@@ -1,11 +1,13 @@
1
1
  import { NavigatorProvider } from "@idealyst/navigation";
2
2
  import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
3
- import React from "react";
3
+ import React, { useEffect } from "react";
4
+ import { createGraphQLClient } from "../graphql/client";
4
5
  import AppRouter from "../navigation/AppRouter";
5
6
  import { createTRPCClient, trpc } from "../trpc/client";
6
7
 
7
8
  interface AppProps {
8
9
  apiUrl?: string;
10
+ graphqlUrl?: string;
9
11
  queryClient?: QueryClient;
10
12
  headers?: () => Record<string, string>;
11
13
  }
@@ -20,11 +22,12 @@ const defaultQueryClient = new QueryClient({
20
22
  });
21
23
 
22
24
  /**
23
- * Unified App component that sets up tRPC, React Query providers, and Navigation
25
+ * Unified App component that sets up tRPC, GraphQL, React Query providers, and Navigation
24
26
  * This component can be used by both web and mobile platforms
25
27
  */
26
28
  export const App: React.FC<AppProps> = ({
27
29
  apiUrl = "http://localhost:3000/trpc",
30
+ graphqlUrl = "http://localhost:3000/graphql",
28
31
  queryClient = defaultQueryClient,
29
32
  headers,
30
33
  }) => {
@@ -34,6 +37,14 @@ export const App: React.FC<AppProps> = ({
34
37
  headers,
35
38
  });
36
39
 
40
+ // Initialize GraphQL client
41
+ useEffect(() => {
42
+ createGraphQLClient({
43
+ apiUrl: graphqlUrl,
44
+ headers,
45
+ });
46
+ }, [graphqlUrl, headers]);
47
+
37
48
  return (
38
49
  <trpc.Provider client={trpcClient} queryClient={queryClient}>
39
50
  <QueryClientProvider client={queryClient}>