@idealyst/cli 1.0.46 → 1.0.49

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 (111) hide show
  1. package/dist/generators/fullstack.js +61 -3
  2. package/dist/generators/fullstack.js.map +1 -1
  3. package/dist/generators/native.js +12 -0
  4. package/dist/generators/native.js.map +1 -1
  5. package/dist/generators/utils.js +64 -31
  6. package/dist/generators/utils.js.map +1 -1
  7. package/dist/templates/api/README.md +207 -130
  8. package/dist/templates/api/package.json +5 -5
  9. package/dist/templates/api/src/controllers/TestController.ts +0 -0
  10. package/dist/templates/api/src/index.ts +2 -7
  11. package/dist/templates/api/src/lib/crud.ts +150 -0
  12. package/dist/templates/api/src/lib/database.ts +23 -0
  13. package/dist/templates/api/src/router/index.ts +104 -71
  14. package/dist/templates/api/src/routers/test.ts +59 -0
  15. package/dist/templates/api/src/routers/user.example.ts +83 -0
  16. package/dist/templates/api/src/server.ts +1 -1
  17. package/dist/templates/api/tsconfig.json +0 -1
  18. package/dist/templates/database/README.md +115 -1
  19. package/dist/templates/database/package.json +2 -0
  20. package/dist/templates/database/prisma/seed.ts +37 -1
  21. package/dist/templates/database/schema.prisma +11 -1
  22. package/dist/templates/native/index.js +1 -1
  23. package/dist/templates/native/metro.config.js +1 -1
  24. package/dist/templates/native/package.json +4 -0
  25. package/dist/templates/native/src/App.tsx +16 -0
  26. package/dist/templates/native/src/utils/trpc.ts +7 -127
  27. package/dist/templates/native/tsconfig.json +0 -2
  28. package/dist/templates/shared/package.json +8 -3
  29. package/dist/templates/shared/src/components/App.tsx +57 -0
  30. package/dist/templates/shared/src/components/HelloWorld.tsx +276 -86
  31. package/dist/templates/shared/src/components/index.ts +1 -1
  32. package/dist/templates/shared/src/index.ts +6 -2
  33. package/dist/templates/shared/src/trpc/client.ts +39 -0
  34. package/dist/templates/shared/tsconfig.json +1 -1
  35. package/dist/templates/web/README.md +65 -8
  36. package/dist/templates/web/package.json +3 -3
  37. package/dist/templates/web/src/App-with-trpc-and-shared.tsx +10 -6
  38. package/dist/templates/web/src/components/TestDemo.tsx +164 -0
  39. package/dist/templates/web/src/utils/trpc.ts +7 -93
  40. package/dist/templates/web/tsconfig.json +0 -1
  41. package/dist/templates/workspace/.devcontainer/devcontainer.json +4 -9
  42. package/dist/templates/workspace/.devcontainer/docker-compose.yml +1 -2
  43. package/dist/templates/workspace/.devcontainer/setup.sh +1 -1
  44. package/dist/templates/workspace/.env.example +1 -1
  45. package/dist/templates/workspace/Dockerfile +4 -4
  46. package/dist/templates/workspace/docker/nginx/prod.conf +2 -2
  47. package/dist/templates/workspace/docker/nginx.conf +1 -1
  48. package/dist/templates/workspace/docker/prometheus/prometheus.yml +1 -1
  49. package/dist/templates/workspace/docker-compose.yml +4 -5
  50. package/dist/templates/workspace/tsconfig.json +0 -1
  51. package/package.json +1 -1
  52. package/templates/api/README.md +207 -130
  53. package/templates/api/package.json +5 -5
  54. package/templates/api/src/controllers/TestController.ts +0 -0
  55. package/templates/api/src/index.ts +2 -7
  56. package/templates/api/src/lib/crud.ts +150 -0
  57. package/templates/api/src/lib/database.ts +23 -0
  58. package/templates/api/src/router/index.ts +104 -71
  59. package/templates/api/src/routers/test.ts +59 -0
  60. package/templates/api/src/routers/user.example.ts +83 -0
  61. package/templates/api/src/server.ts +1 -1
  62. package/templates/api/tsconfig.json +0 -1
  63. package/templates/database/README.md +115 -1
  64. package/templates/database/package.json +2 -0
  65. package/templates/database/prisma/seed.ts +37 -1
  66. package/templates/database/schema.prisma +11 -1
  67. package/templates/native/index.js +1 -1
  68. package/templates/native/metro.config.js +1 -1
  69. package/templates/native/package.json +4 -0
  70. package/templates/native/src/App-with-trpc-and-shared.tsx +0 -12
  71. package/templates/native/src/App.tsx +16 -0
  72. package/templates/native/src/utils/trpc.ts +7 -127
  73. package/templates/native/tsconfig.json +0 -2
  74. package/templates/shared/package.json +8 -3
  75. package/templates/shared/src/components/App.tsx +57 -0
  76. package/templates/shared/src/components/HelloWorld.tsx +276 -86
  77. package/templates/shared/src/components/index.ts +1 -1
  78. package/templates/shared/src/index.ts +6 -2
  79. package/templates/shared/src/trpc/client.ts +39 -0
  80. package/templates/shared/tsconfig.json +1 -1
  81. package/templates/web/README.md +65 -8
  82. package/templates/web/package.json +3 -3
  83. package/templates/web/src/App-with-trpc-and-shared.tsx +10 -6
  84. package/templates/web/src/components/TestDemo.tsx +164 -0
  85. package/templates/web/src/utils/trpc.ts +7 -93
  86. package/templates/web/tsconfig.json +0 -1
  87. package/templates/workspace/.devcontainer/devcontainer.json +4 -9
  88. package/templates/workspace/.devcontainer/docker-compose.yml +1 -2
  89. package/templates/workspace/.devcontainer/setup.sh +1 -1
  90. package/templates/workspace/.env.example +1 -1
  91. package/templates/workspace/Dockerfile +4 -4
  92. package/templates/workspace/docker/nginx/prod.conf +2 -2
  93. package/templates/workspace/docker/nginx.conf +1 -1
  94. package/templates/workspace/docker/prometheus/prometheus.yml +1 -1
  95. package/templates/workspace/docker-compose.yml +4 -5
  96. package/templates/workspace/tsconfig.json +0 -1
  97. package/dist/templates/api/src/controllers/UserController.ts +0 -102
  98. package/dist/templates/api/src/lib/controller.ts +0 -90
  99. package/dist/templates/api/src/lib/middleware.ts +0 -170
  100. package/dist/templates/api/src/middleware/auth.ts +0 -75
  101. package/dist/templates/api/src/middleware/common.ts +0 -103
  102. package/dist/templates/database/.env.example +0 -1
  103. package/dist/templates/native/App.tsx +0 -23
  104. package/dist/templates/native/src/App-with-trpc-and-shared.tsx +0 -12
  105. package/templates/api/src/controllers/UserController.ts +0 -102
  106. package/templates/api/src/lib/controller.ts +0 -90
  107. package/templates/api/src/lib/middleware.ts +0 -170
  108. package/templates/api/src/middleware/auth.ts +0 -75
  109. package/templates/api/src/middleware/common.ts +0 -103
  110. package/templates/database/.env.example +0 -1
  111. package/templates/native/App.tsx +0 -23
@@ -1,90 +0,0 @@
1
- import { z } from 'zod';
2
- import type { Context } from '../context.js';
3
- import { publicProcedure } from '../trpc.js';
4
-
5
- // Base controller class
6
- export abstract class BaseController {
7
- protected ctx: Context;
8
-
9
- constructor(ctx: Context) {
10
- this.ctx = ctx;
11
- }
12
-
13
- // Helper method to create a query procedure
14
- protected createQuery<TInput, TOutput>(
15
- inputSchema: z.ZodSchema<TInput>,
16
- handler: (input: TInput, ctx: Context) => Promise<TOutput> | TOutput
17
- ) {
18
- return publicProcedure
19
- .input(inputSchema)
20
- .query(async ({ input, ctx }) => {
21
- return handler(input, ctx);
22
- });
23
- }
24
-
25
- // Helper method to create a mutation procedure
26
- protected createMutation<TInput, TOutput>(
27
- inputSchema: z.ZodSchema<TInput>,
28
- handler: (input: TInput, ctx: Context) => Promise<TOutput> | TOutput
29
- ) {
30
- return publicProcedure
31
- .input(inputSchema)
32
- .mutation(async ({ input, ctx }) => {
33
- return handler(input, ctx);
34
- });
35
- }
36
-
37
- // Helper method to create a query with middleware
38
- protected createQueryWithMiddleware<TInput, TOutput>(
39
- inputSchema: z.ZodSchema<TInput>,
40
- middleware: MiddlewareFn[],
41
- handler: (input: TInput, ctx: Context) => Promise<TOutput> | TOutput
42
- ) {
43
- let procedure = publicProcedure.input(inputSchema);
44
-
45
- // Apply middleware
46
- for (const mw of middleware) {
47
- procedure = procedure.use(mw);
48
- }
49
-
50
- return procedure.query(async ({ input, ctx }) => {
51
- return handler(input, ctx);
52
- });
53
- }
54
-
55
- // Helper method to create a mutation with middleware
56
- protected createMutationWithMiddleware<TInput, TOutput>(
57
- inputSchema: z.ZodSchema<TInput>,
58
- middleware: MiddlewareFn[],
59
- handler: (input: TInput, ctx: Context) => Promise<TOutput> | TOutput
60
- ) {
61
- let procedure = publicProcedure.input(inputSchema);
62
-
63
- // Apply middleware
64
- for (const mw of middleware) {
65
- procedure = procedure.use(mw);
66
- }
67
-
68
- return procedure.mutation(async ({ input, ctx }) => {
69
- return handler(input, ctx);
70
- });
71
- }
72
- }
73
-
74
- // Middleware function type compatible with tRPC
75
- export type MiddlewareFn = (opts: {
76
- ctx: Context;
77
- next: () => Promise<{ ctx: Context }>;
78
- }) => Promise<{ ctx: Context }>;
79
-
80
- // Controller method decorator type
81
- export interface ControllerMethod {
82
- [key: string]: ReturnType<typeof publicProcedure.query> | ReturnType<typeof publicProcedure.mutation>;
83
- }
84
-
85
- // Helper function to convert controller to tRPC router object
86
- export function controllerToRouter<T extends Record<string, any>>(
87
- controllerMethods: T
88
- ): T {
89
- return controllerMethods;
90
- }
@@ -1,170 +0,0 @@
1
- import { TRPCError } from '@trpc/server';
2
- import type { Context } from '../context.js';
3
-
4
- // Middleware function type that works with tRPC
5
- export type MiddlewareFunction = (opts: {
6
- ctx: Context;
7
- next: () => Promise<{ ctx: Context }>;
8
- }) => Promise<{ ctx: Context }>;
9
-
10
- // Authentication middleware
11
- export const requireAuth: MiddlewareFunction = async ({ ctx, next }) => {
12
- // Example: Check for authorization header
13
- const authHeader = ctx.req.headers.authorization;
14
-
15
- if (!authHeader || !authHeader.startsWith('Bearer ')) {
16
- throw new TRPCError({
17
- code: 'UNAUTHORIZED',
18
- message: 'Missing or invalid authorization header',
19
- });
20
- }
21
-
22
- const token = authHeader.substring(7);
23
-
24
- // Here you would validate the token (JWT, session, etc.)
25
- // For this example, we'll just check if it's not empty
26
- if (!token) {
27
- throw new TRPCError({
28
- code: 'UNAUTHORIZED',
29
- message: 'Invalid token',
30
- });
31
- }
32
-
33
- // Add user info to context (replace with your actual user lookup)
34
- const user = {
35
- id: 'user-id-from-token',
36
- email: 'user@example.com',
37
- // ... other user properties
38
- };
39
-
40
- return next({
41
- ctx: {
42
- ...ctx,
43
- user, // Add user to context
44
- },
45
- });
46
- };
47
-
48
- // Role-based authorization middleware
49
- export const requireRole = (role: string): MiddlewareFunction => {
50
- return async ({ ctx, next }) => {
51
- const user = (ctx as any).user;
52
-
53
- if (!user) {
54
- throw new TRPCError({
55
- code: 'UNAUTHORIZED',
56
- message: 'Authentication required',
57
- });
58
- }
59
-
60
- // Check if user has required role
61
- if (!user.roles?.includes(role)) {
62
- throw new TRPCError({
63
- code: 'FORBIDDEN',
64
- message: `Role '${role}' required`,
65
- });
66
- }
67
-
68
- return next();
69
- };
70
- };
71
-
72
- // Logging middleware
73
- export const logger: MiddlewareFunction = async ({ ctx, next }) => {
74
- const start = Date.now();
75
-
76
- console.log(`📝 ${ctx.req.method} ${ctx.req.url} - ${new Date().toISOString()}`);
77
-
78
- try {
79
- const result = await next();
80
- const duration = Date.now() - start;
81
- console.log(`✅ Request completed in ${duration}ms`);
82
- return result;
83
- } catch (error) {
84
- const duration = Date.now() - start;
85
- console.log(`❌ Request failed in ${duration}ms:`, error);
86
- throw error;
87
- }
88
- };
89
-
90
- // Rate limiting middleware (simple in-memory implementation)
91
- const requestCounts = new Map<string, { count: number; resetTime: number }>();
92
-
93
- export const rateLimit = (maxRequests: number, windowMs: number): MiddlewareFunction => {
94
- return async ({ ctx, next }) => {
95
- const clientId = ctx.req.ip || 'unknown';
96
- const now = Date.now();
97
-
98
- const clientData = requestCounts.get(clientId);
99
-
100
- if (!clientData || now > clientData.resetTime) {
101
- // Reset or initialize
102
- requestCounts.set(clientId, {
103
- count: 1,
104
- resetTime: now + windowMs,
105
- });
106
- } else {
107
- clientData.count++;
108
-
109
- if (clientData.count > maxRequests) {
110
- throw new TRPCError({
111
- code: 'TOO_MANY_REQUESTS',
112
- message: 'Rate limit exceeded',
113
- });
114
- }
115
- }
116
-
117
- return next();
118
- };
119
- };
120
-
121
- // Validation middleware factory
122
- export const validateInput = <T>(schema: import('zod').ZodSchema<T>) => {
123
- const middleware: MiddlewareFunction = async ({ ctx, next }) => {
124
- return next();
125
- };
126
- return middleware;
127
- };
128
-
129
- // Error handling middleware
130
- export const errorHandler: MiddlewareFunction = async ({ ctx, next }) => {
131
- try {
132
- return await next();
133
- } catch (error) {
134
- // Log the error
135
- console.error('❌ API Error:', error);
136
-
137
- // Re-throw tRPC errors as-is
138
- if (error instanceof TRPCError) {
139
- throw error;
140
- }
141
-
142
- // Convert unknown errors to internal server error
143
- throw new TRPCError({
144
- code: 'INTERNAL_SERVER_ERROR',
145
- message: 'An unexpected error occurred',
146
- cause: error,
147
- });
148
- }
149
- };
150
-
151
- // Middleware composer utility
152
- export const composeMiddleware = (...middlewares: MiddlewareFunction[]): MiddlewareFunction => {
153
- return async ({ ctx, next }) => {
154
- let index = 0;
155
-
156
- const runMiddleware = async (currentCtx: Context): Promise<{ ctx: Context }> => {
157
- if (index >= middlewares.length) {
158
- return next();
159
- }
160
-
161
- const middleware = middlewares[index++];
162
- return middleware({
163
- ctx: currentCtx,
164
- next: () => runMiddleware(currentCtx),
165
- });
166
- };
167
-
168
- return runMiddleware(ctx);
169
- };
170
- };
@@ -1,75 +0,0 @@
1
- import { TRPCError } from '@trpc/server';
2
- import type { Context } from '../context.js';
3
- import type { MiddlewareFn } from '../lib/controller.js';
4
-
5
- // Extended context with user
6
- export interface AuthContext extends Context {
7
- user: {
8
- id: string;
9
- email: string;
10
- roles?: string[];
11
- };
12
- }
13
-
14
- // Authentication middleware
15
- export const requireAuth: MiddlewareFn = async ({ ctx, next }) => {
16
- const authHeader = ctx.req.headers.authorization;
17
-
18
- if (!authHeader || !authHeader.startsWith('Bearer ')) {
19
- throw new TRPCError({
20
- code: 'UNAUTHORIZED',
21
- message: 'Missing or invalid authorization header',
22
- });
23
- }
24
-
25
- const token = authHeader.substring(7);
26
-
27
- // Here you would validate the token (JWT, session, etc.)
28
- // For example purposes, we'll simulate token validation
29
- if (!token || token === 'invalid') {
30
- throw new TRPCError({
31
- code: 'UNAUTHORIZED',
32
- message: 'Invalid token',
33
- });
34
- }
35
-
36
- // Mock user lookup - replace with your actual implementation
37
- const user = {
38
- id: 'user-123',
39
- email: 'user@example.com',
40
- roles: ['user'],
41
- };
42
-
43
- return next({
44
- ctx: {
45
- ...ctx,
46
- user,
47
- } as AuthContext,
48
- });
49
- };
50
-
51
- // Role-based authorization middleware factory
52
- export const requireRole = (requiredRole: string): MiddlewareFn => {
53
- return async ({ ctx, next }) => {
54
- const authCtx = ctx as AuthContext;
55
-
56
- if (!authCtx.user) {
57
- throw new TRPCError({
58
- code: 'UNAUTHORIZED',
59
- message: 'Authentication required',
60
- });
61
- }
62
-
63
- if (!authCtx.user.roles?.includes(requiredRole)) {
64
- throw new TRPCError({
65
- code: 'FORBIDDEN',
66
- message: `Role '${requiredRole}' required`,
67
- });
68
- }
69
-
70
- return next();
71
- };
72
- };
73
-
74
- // Admin role middleware
75
- export const requireAdmin = requireRole('admin');
@@ -1,103 +0,0 @@
1
- import type { Context } from '../context.js';
2
- import type { MiddlewareFn } from '../lib/controller.js';
3
-
4
- // Logging middleware
5
- export const logger: MiddlewareFn = async ({ ctx, next }) => {
6
- const start = Date.now();
7
- const { method, url } = ctx.req;
8
-
9
- console.log(`📝 ${method} ${url} - ${new Date().toISOString()}`);
10
-
11
- try {
12
- const result = await next();
13
- const duration = Date.now() - start;
14
- console.log(`✅ Request completed in ${duration}ms`);
15
- return result;
16
- } catch (error) {
17
- const duration = Date.now() - start;
18
- console.log(`❌ Request failed in ${duration}ms:`, error);
19
- throw error;
20
- }
21
- };
22
-
23
- // Simple rate limiting middleware (in-memory)
24
- const requestCounts = new Map<string, { count: number; resetTime: number }>();
25
-
26
- export const rateLimit = (maxRequests: number = 100, windowMs: number = 15 * 60 * 1000): MiddlewareFn => {
27
- return async ({ ctx, next }) => {
28
- const clientId = ctx.req.ip || ctx.req.socket.remoteAddress || 'unknown';
29
- const now = Date.now();
30
-
31
- const clientData = requestCounts.get(clientId);
32
-
33
- if (!clientData || now > clientData.resetTime) {
34
- // Reset or initialize
35
- requestCounts.set(clientId, {
36
- count: 1,
37
- resetTime: now + windowMs,
38
- });
39
- } else {
40
- clientData.count++;
41
-
42
- if (clientData.count > maxRequests) {
43
- throw new Error('Rate limit exceeded');
44
- }
45
- }
46
-
47
- return next();
48
- };
49
- };
50
-
51
- // CORS middleware (though this should typically be handled at Express level)
52
- export const cors: MiddlewareFn = async ({ ctx, next }) => {
53
- // Set CORS headers (note: this is just for demonstration)
54
- // In practice, use the cors Express middleware
55
- ctx.res.setHeader('Access-Control-Allow-Origin', '*');
56
- ctx.res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
57
- ctx.res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
58
-
59
- return next();
60
- };
61
-
62
- // Error handling middleware
63
- export const errorHandler: MiddlewareFn = async ({ ctx, next }) => {
64
- try {
65
- return await next();
66
- } catch (error) {
67
- // Log the error
68
- console.error('❌ API Error:', error);
69
-
70
- // Re-throw the error (tRPC will handle it properly)
71
- throw error;
72
- }
73
- };
74
-
75
- // Response time header middleware
76
- export const responseTime: MiddlewareFn = async ({ ctx, next }) => {
77
- const start = Date.now();
78
-
79
- const result = await next();
80
-
81
- const duration = Date.now() - start;
82
- ctx.res.setHeader('X-Response-Time', `${duration}ms`);
83
-
84
- return result;
85
- };
86
-
87
- // Request ID middleware
88
- export const requestId: MiddlewareFn = async ({ ctx, next }) => {
89
- const id = Math.random().toString(36).substring(2, 15);
90
-
91
- // Add request ID to context
92
- const newCtx = {
93
- ...ctx,
94
- requestId: id,
95
- };
96
-
97
- // Set response header
98
- ctx.res.setHeader('X-Request-ID', id);
99
-
100
- return next({
101
- ctx: newCtx,
102
- });
103
- };
@@ -1 +0,0 @@
1
- DATABASE_URL="sqlite:./dev.db"
@@ -1,23 +0,0 @@
1
- import React from 'react';
2
- import {
3
- SafeAreaView,
4
- } from 'react-native';
5
-
6
- import { ExampleStackRouter } from '@idealyst/navigation/examples';
7
- import { NavigatorProvider } from '@idealyst/navigation';
8
-
9
-
10
- function App() {
11
-
12
- const backgroundStyle = {
13
- flex: 1,
14
- };
15
-
16
- return (
17
- <SafeAreaView style={backgroundStyle}>
18
- <NavigatorProvider route={ExampleStackRouter} />
19
- </SafeAreaView>
20
- );
21
- }
22
-
23
- export default App;