@idealyst/cli 1.0.32 → 1.0.34

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 (94) hide show
  1. package/dist/generators/api.js +28 -25
  2. package/dist/generators/api.js.map +1 -1
  3. package/dist/generators/index.js +33 -16
  4. package/dist/generators/index.js.map +1 -1
  5. package/dist/generators/native.js +51 -48
  6. package/dist/generators/native.js.map +1 -1
  7. package/dist/generators/shared.js +25 -22
  8. package/dist/generators/shared.js.map +1 -1
  9. package/dist/generators/utils.js +146 -118
  10. package/dist/generators/utils.js.map +1 -1
  11. package/dist/generators/web.js +33 -30
  12. package/dist/generators/web.js.map +1 -1
  13. package/dist/generators/workspace.js +24 -21
  14. package/dist/generators/workspace.js.map +1 -1
  15. package/dist/index.js +82 -44
  16. package/dist/index.js.map +1 -1
  17. package/dist/templates/api/README.md +207 -0
  18. package/dist/templates/api/__tests__/api.test.ts +26 -0
  19. package/dist/templates/api/env.example +12 -0
  20. package/dist/templates/api/jest.config.js +23 -0
  21. package/dist/templates/api/jest.setup.js +9 -0
  22. package/dist/templates/api/package.json +62 -0
  23. package/dist/templates/api/prisma/schema.prisma +21 -0
  24. package/dist/templates/api/src/context.ts +23 -0
  25. package/dist/templates/api/src/controllers/UserController.ts +102 -0
  26. package/dist/templates/api/src/index.ts +14 -0
  27. package/dist/templates/api/src/lib/controller.ts +90 -0
  28. package/dist/templates/api/src/lib/middleware.ts +170 -0
  29. package/dist/templates/api/src/middleware/auth.ts +75 -0
  30. package/dist/templates/api/src/middleware/common.ts +103 -0
  31. package/dist/templates/api/src/router/index.ts +130 -0
  32. package/dist/templates/api/src/server.ts +50 -0
  33. package/dist/templates/api/src/trpc.ts +28 -0
  34. package/dist/templates/api/tsconfig.json +44 -0
  35. package/dist/templates/native/.yarnrc.yml +19 -0
  36. package/dist/templates/native/App.tsx +23 -0
  37. package/dist/templates/native/README.md +86 -0
  38. package/dist/templates/native/__tests__/App.test.tsx +156 -0
  39. package/dist/templates/native/__tests__/components.test.tsx +300 -0
  40. package/dist/templates/native/app.json +5 -0
  41. package/dist/templates/native/babel.config.js +10 -0
  42. package/dist/templates/native/index.js +6 -0
  43. package/dist/templates/native/jest.config.js +21 -0
  44. package/dist/templates/native/jest.setup.js +12 -0
  45. package/dist/templates/native/metro.config.js +27 -0
  46. package/dist/templates/native/package.json +44 -0
  47. package/dist/templates/native/src/App-with-trpc.tsx +59 -0
  48. package/dist/templates/native/src/utils/trpc.ts +127 -0
  49. package/dist/templates/native/tsconfig.json +30 -0
  50. package/dist/templates/shared/README.md +109 -0
  51. package/dist/templates/shared/__tests__/shared.test.ts +39 -0
  52. package/dist/templates/shared/jest.config.js +22 -0
  53. package/dist/templates/shared/package.json +50 -0
  54. package/dist/templates/shared/rollup.config.js +43 -0
  55. package/dist/templates/shared/src/index.ts +1 -0
  56. package/dist/templates/shared/tsconfig.json +25 -0
  57. package/dist/templates/web/README.md +90 -0
  58. package/dist/templates/web/__tests__/App.test.tsx +342 -0
  59. package/dist/templates/web/__tests__/components.test.tsx +564 -0
  60. package/dist/templates/web/index.html +13 -0
  61. package/dist/templates/web/jest.config.js +27 -0
  62. package/dist/templates/web/jest.setup.js +24 -0
  63. package/dist/templates/web/package.json +66 -0
  64. package/dist/templates/web/src/App-with-trpc.tsx +67 -0
  65. package/dist/templates/web/src/App.tsx +15 -0
  66. package/dist/templates/web/src/main.tsx +25 -0
  67. package/dist/templates/web/src/utils/trpc.ts +93 -0
  68. package/dist/templates/web/tsconfig.json +27 -0
  69. package/dist/templates/web/vite.config.ts +69 -0
  70. package/dist/templates/workspace/.devcontainer/devcontainer.json +140 -0
  71. package/dist/templates/workspace/.devcontainer/docker-compose.yml +74 -0
  72. package/dist/templates/workspace/.devcontainer/post-create.sh +89 -0
  73. package/dist/templates/workspace/.dockerignore +151 -0
  74. package/dist/templates/workspace/.env.example +36 -0
  75. package/dist/templates/workspace/.env.production +56 -0
  76. package/dist/templates/workspace/.yarnrc.yml +26 -0
  77. package/dist/templates/workspace/DOCKER.md +0 -0
  78. package/dist/templates/workspace/Dockerfile +93 -0
  79. package/dist/templates/workspace/README.md +179 -0
  80. package/dist/templates/workspace/docker/nginx/prod.conf +238 -0
  81. package/dist/templates/workspace/docker/nginx.conf +131 -0
  82. package/dist/templates/workspace/docker/postgres/init.sql +41 -0
  83. package/dist/templates/workspace/docker/prometheus/prometheus.yml +52 -0
  84. package/dist/templates/workspace/docker-compose.prod.yml +146 -0
  85. package/dist/templates/workspace/docker-compose.yml +144 -0
  86. package/dist/templates/workspace/jest.config.js +20 -0
  87. package/dist/templates/workspace/package.json +35 -0
  88. package/dist/templates/workspace/scripts/docker/db-backup.sh +230 -0
  89. package/dist/templates/workspace/scripts/docker/deploy.sh +212 -0
  90. package/dist/templates/workspace/scripts/docker-build.sh +151 -0
  91. package/dist/templates/workspace/scripts/test-runner.js +120 -0
  92. package/dist/templates/workspace/setup.sh +205 -0
  93. package/dist/types.js +2 -1
  94. package/package.json +3 -3
@@ -0,0 +1,130 @@
1
+ import { z } from 'zod';
2
+ import { router, publicProcedure } from '../trpc.js';
3
+
4
+ export const appRouter = router({
5
+ // Simple hello world procedure
6
+ hello: publicProcedure
7
+ .input(z.object({ name: z.string().optional() }))
8
+ .query(({ input }) => {
9
+ return {
10
+ greeting: `Hello ${input.name || 'World'}!`,
11
+ timestamp: new Date().toISOString(),
12
+ };
13
+ }),
14
+
15
+ // Health check procedure
16
+ health: publicProcedure.query(() => {
17
+ return {
18
+ status: 'OK',
19
+ timestamp: new Date().toISOString(),
20
+ version: '1.0.0',
21
+ };
22
+ }),
23
+
24
+ // Add your procedures here
25
+ // Example:
26
+ // users: userRouter,
27
+ // posts: postRouter,
28
+
29
+ // Example controller integration:
30
+ // Uncomment the lines below and create the corresponding controllers
31
+
32
+ // 1. Import your controllers at the top:
33
+ // import { userRouter } from '../controllers/UserController.js';
34
+
35
+ // 2. Add them to the router:
36
+ // users: userRouter,
37
+ });
38
+
39
+ // Export type definition of API
40
+ export type AppRouter = typeof appRouter;
41
+
42
+ /*
43
+ CONTROLLER & MIDDLEWARE SYSTEM USAGE:
44
+
45
+ This API template includes a controller and middleware system that works seamlessly with tRPC.
46
+
47
+ ## Quick Start with Controllers:
48
+
49
+ 1. Create a controller (see src/controllers/UserController.ts for example):
50
+
51
+ ```typescript
52
+ import { z } from 'zod';
53
+ import { BaseController, controllerToRouter } from '../lib/controller.js';
54
+ import { requireAuth } from '../middleware/auth.js';
55
+
56
+ export class UserController extends BaseController {
57
+ getAll = this.createQueryWithMiddleware(
58
+ z.object({}),
59
+ [requireAuth],
60
+ async (input, ctx) => {
61
+ return await ctx.prisma.user.findMany();
62
+ }
63
+ );
64
+ }
65
+
66
+ export const userRouter = controllerToRouter({
67
+ getAll: new UserController({} as any).getAll,
68
+ });
69
+ ```
70
+
71
+ 2. Add to main router:
72
+
73
+ ```typescript
74
+ import { userRouter } from '../controllers/UserController.js';
75
+
76
+ export const appRouter = router({
77
+ users: userRouter,
78
+ // ... other routes
79
+ });
80
+ ```
81
+
82
+ ## Available Middleware:
83
+
84
+ ### Authentication:
85
+ - `requireAuth` - Requires Bearer token
86
+ - `requireRole(role)` - Requires specific role
87
+ - `requireAdmin` - Requires admin role
88
+
89
+ ### Utility:
90
+ - `logger` - Request/response logging
91
+ - `rateLimit(max, window)` - Rate limiting
92
+ - `responseTime` - Adds response time header
93
+ - `requestId` - Adds unique request ID
94
+ - `errorHandler` - Centralized error handling
95
+
96
+ ## Usage Examples:
97
+
98
+ ```typescript
99
+ // Public endpoint
100
+ getPublicData = this.createQuery(schema, handler);
101
+
102
+ // Protected endpoint
103
+ getPrivateData = this.createQueryWithMiddleware(
104
+ schema,
105
+ [requireAuth],
106
+ handler
107
+ );
108
+
109
+ // Admin-only endpoint
110
+ adminAction = this.createMutationWithMiddleware(
111
+ schema,
112
+ [requireAuth, requireAdmin],
113
+ handler
114
+ );
115
+
116
+ // Multiple middleware
117
+ complexEndpoint = this.createQueryWithMiddleware(
118
+ schema,
119
+ [logger, rateLimit(10, 60000), requireAuth],
120
+ handler
121
+ );
122
+ ```
123
+
124
+ This system provides:
125
+ ✅ Type safety with tRPC
126
+ ✅ Reusable middleware
127
+ ✅ Clean controller organization
128
+ ✅ Easy testing
129
+ ✅ Consistent error handling
130
+ */
@@ -0,0 +1,50 @@
1
+ import express from 'express';
2
+ import cors from 'cors';
3
+ import { createExpressMiddleware } from '@trpc/server/adapters/express';
4
+ import { appRouter } from './router/index.js';
5
+ import { createContext } from './context.js';
6
+ import dotenv from 'dotenv';
7
+
8
+ // Load environment variables
9
+ dotenv.config();
10
+
11
+ const app = express();
12
+ const PORT = process.env.PORT || 3000;
13
+
14
+ // CORS configuration
15
+ app.use(cors({
16
+ origin: process.env.CORS_ORIGIN || 'http://localhost:3000',
17
+ credentials: true,
18
+ }));
19
+
20
+ // Health check endpoint
21
+ app.get('/health', (req, res) => {
22
+ res.json({ status: 'OK', timestamp: new Date().toISOString() });
23
+ });
24
+
25
+ // tRPC middleware
26
+ app.use(
27
+ '/trpc',
28
+ createExpressMiddleware({
29
+ router: appRouter,
30
+ createContext,
31
+ })
32
+ );
33
+
34
+ // Default route
35
+ app.get('/', (req, res) => {
36
+ res.json({
37
+ message: 'Welcome to {{projectName}} API',
38
+ endpoints: {
39
+ health: '/health',
40
+ trpc: '/trpc',
41
+ playground: '/trpc-playground' // Available in development
42
+ }
43
+ });
44
+ });
45
+
46
+ app.listen(PORT, () => {
47
+ console.log(`🚀 Server running on http://localhost:${PORT}`);
48
+ console.log(`📡 tRPC API available at http://localhost:${PORT}/trpc`);
49
+ console.log(`🏥 Health check at http://localhost:${PORT}/health`);
50
+ });
@@ -0,0 +1,28 @@
1
+ import { initTRPC } from '@trpc/server';
2
+ import { type Context } from './context.js';
3
+ import { ZodError } from 'zod';
4
+
5
+ const t = initTRPC.context<Context>().create({
6
+ errorFormatter({ shape, error }) {
7
+ return {
8
+ ...shape,
9
+ data: {
10
+ ...shape.data,
11
+ zodError:
12
+ error.cause instanceof ZodError ? error.cause.flatten() : null,
13
+ },
14
+ };
15
+ },
16
+ });
17
+
18
+ // Export reusable router and procedure helpers
19
+ export const router = t.router;
20
+ export const publicProcedure = t.procedure;
21
+
22
+ // You can create additional procedures with middleware here
23
+ // For example, a protected procedure that requires authentication:
24
+ // export const protectedProcedure = t.procedure.use(async ({ ctx, next }) => {
25
+ // // Add your authentication logic here
26
+ // // Example: check for valid session/token
27
+ // return next({ ctx: { ...ctx, user: { id: 'user-id' } } });
28
+ // });
@@ -0,0 +1,44 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "ESNext",
5
+ "moduleResolution": "node",
6
+ "allowSyntheticDefaultImports": true,
7
+ "esModuleInterop": true,
8
+ "allowJs": true,
9
+ "checkJs": false,
10
+ "jsx": "preserve",
11
+ "declaration": true,
12
+ "declarationMap": true,
13
+ "sourceMap": true,
14
+ "outDir": "./dist",
15
+ "rootDir": "./src",
16
+ "removeComments": false,
17
+ "strict": true,
18
+ "noImplicitAny": true,
19
+ "strictNullChecks": true,
20
+ "strictFunctionTypes": true,
21
+ "noImplicitThis": true,
22
+ "useUnknownInCatchVariables": true,
23
+ "noImplicitReturns": true,
24
+ "noFallthroughCasesInSwitch": true,
25
+ "noUncheckedIndexedAccess": true,
26
+ "exactOptionalPropertyTypes": true,
27
+ "noPropertyAccessFromIndexSignature": false,
28
+ "resolveJsonModule": true,
29
+ "isolatedModules": true,
30
+ "forceConsistentCasingInFileNames": true,
31
+ "skipLibCheck": true
32
+ },
33
+ "include": [
34
+ "src/**/*"
35
+ ],
36
+ "exclude": [
37
+ "node_modules",
38
+ "dist",
39
+ "**/*.test.ts"
40
+ ],
41
+ "ts-node": {
42
+ "esm": true
43
+ }
44
+ }
@@ -0,0 +1,19 @@
1
+ nodeLinker: "node-modules"
2
+
3
+ # Enable network for package downloads
4
+ enableNetwork: true
5
+
6
+ # Timeout for HTTP requests (in milliseconds)
7
+ httpTimeout: 60000
8
+
9
+ # Number of retry attempts for HTTP requests
10
+ httpRetry: 3
11
+
12
+ # Registry configuration
13
+ npmRegistryServer: "https://registry.yarnpkg.com"
14
+
15
+ # Enable progress bars
16
+ enableProgressBars: true
17
+
18
+ # Enable colors in output
19
+ enableColors: true
@@ -0,0 +1,23 @@
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;
@@ -0,0 +1,86 @@
1
+ # {{projectName}}
2
+
3
+ {{description}}
4
+
5
+ ## Getting Started
6
+
7
+ This is a React Native application built with the Idealyst Framework.
8
+
9
+ ### Prerequisites
10
+
11
+ - Node.js 18+
12
+ - Yarn
13
+ - React Native development environment
14
+ - Android Studio (for Android development)
15
+ - Xcode (for iOS development)
16
+
17
+ ### Installation
18
+
19
+ Install dependencies:
20
+ ```bash
21
+ yarn install
22
+ ```
23
+
24
+ ### Running the App
25
+
26
+ Start the Metro bundler:
27
+ ```bash
28
+ yarn start
29
+ ```
30
+
31
+ Run on Android:
32
+ ```bash
33
+ yarn android
34
+ ```
35
+
36
+ Run on iOS:
37
+ ```bash
38
+ yarn ios
39
+ ```
40
+
41
+ ### Project Structure
42
+
43
+ ```
44
+ {{projectName}}/
45
+ ├── src/
46
+ │ └── App.tsx # Main app component
47
+ ├── android/ # Android-specific code
48
+ ├── ios/ # iOS-specific code
49
+ ├── babel.config.js # Babel configuration
50
+ ├── metro.config.js # Metro configuration
51
+ └── tsconfig.json # TypeScript configuration
52
+ ```
53
+
54
+ ### Features
55
+
56
+ - **Idealyst Components**: Pre-built UI components
57
+ - **Idealyst Navigation**: Cross-platform navigation
58
+ - **Idealyst Theme**: Consistent theming system
59
+ - **TypeScript**: Full type safety
60
+ - **React Native 0.80.1**: Latest stable version
61
+
62
+ ### Development
63
+
64
+ The app uses the Idealyst Framework for consistent UI and navigation across platforms.
65
+
66
+ Edit `src/App.tsx` to start building your application.
67
+
68
+ ### Building for Production
69
+
70
+ Build Android APK:
71
+ ```bash
72
+ yarn build:android
73
+ ```
74
+
75
+ ### Testing
76
+
77
+ Run tests:
78
+ ```bash
79
+ yarn test
80
+ ```
81
+
82
+ ### Learn More
83
+
84
+ - [Idealyst Framework Documentation](https://github.com/your-username/idealyst-framework)
85
+ - [React Native Documentation](https://reactnative.dev/)
86
+ - [TypeScript Documentation](https://www.typescriptlang.org/)
@@ -0,0 +1,156 @@
1
+ /**
2
+ * @format
3
+ */
4
+
5
+ import React from 'react';
6
+ import ReactTestRenderer from 'react-test-renderer';
7
+ import App from '../App';
8
+
9
+ // Mock the NavigatorProvider to avoid complex navigation setup
10
+ jest.mock('@idealyst/navigation', () => ({
11
+ NavigatorProvider: ({ children }: { children?: React.ReactNode }) => (
12
+ React.createElement('View', { testID: 'navigator-provider' }, children || 'Navigator Content')
13
+ ),
14
+ }));
15
+
16
+ jest.mock('@idealyst/navigation/examples', () => ({
17
+ ExampleStackRouter: {},
18
+ }));
19
+
20
+ describe('App Component', () => {
21
+ it('renders correctly', async () => {
22
+ let component: ReactTestRenderer.ReactTestRenderer;
23
+
24
+ await ReactTestRenderer.act(() => {
25
+ component = ReactTestRenderer.create(<App />);
26
+ });
27
+
28
+ expect(component!).toBeDefined();
29
+ expect(component!.toJSON()).toMatchSnapshot();
30
+ });
31
+
32
+ it('renders without crashing', () => {
33
+ const tree = ReactTestRenderer.create(<App />);
34
+ expect(tree).toBeDefined();
35
+ expect(tree.root).toBeDefined();
36
+ });
37
+
38
+ it('contains NavigatorProvider', () => {
39
+ const tree = ReactTestRenderer.create(<App />);
40
+ const navigatorProvider = tree.root.findByProps({ testID: 'navigator-provider' });
41
+ expect(navigatorProvider).toBeDefined();
42
+ });
43
+
44
+ it('has proper SafeAreaView structure', () => {
45
+ const tree = ReactTestRenderer.create(<App />);
46
+ const safeAreaView = tree.root.findByType('SafeAreaView');
47
+ expect(safeAreaView).toBeDefined();
48
+ expect(safeAreaView.props.style).toEqual({ flex: 1 });
49
+ });
50
+ });
51
+
52
+ describe('Sample Component Tests', () => {
53
+ // Example of testing a simple functional component
54
+ const SimpleButton = ({ title, onPress, disabled = false }: {
55
+ title: string;
56
+ onPress: () => void;
57
+ disabled?: boolean;
58
+ }) => {
59
+ return React.createElement(
60
+ 'TouchableOpacity',
61
+ {
62
+ testID: 'simple-button',
63
+ onPress: disabled ? undefined : onPress,
64
+ style: { opacity: disabled ? 0.5 : 1 }
65
+ },
66
+ React.createElement('Text', null, title)
67
+ );
68
+ };
69
+
70
+ it('renders button with correct title', () => {
71
+ const mockPress = jest.fn();
72
+ const tree = ReactTestRenderer.create(
73
+ <SimpleButton title="Test Button" onPress={mockPress} />
74
+ );
75
+
76
+ const textElement = tree.root.findByType('Text');
77
+ expect(textElement.children).toEqual(['Test Button']);
78
+ });
79
+
80
+ it('handles press events', () => {
81
+ const mockPress = jest.fn();
82
+ const tree = ReactTestRenderer.create(
83
+ <SimpleButton title="Test Button" onPress={mockPress} />
84
+ );
85
+
86
+ const button = tree.root.findByProps({ testID: 'simple-button' });
87
+ ReactTestRenderer.act(() => {
88
+ button.props.onPress();
89
+ });
90
+
91
+ expect(mockPress).toHaveBeenCalledTimes(1);
92
+ });
93
+
94
+ it('disables button when disabled prop is true', () => {
95
+ const mockPress = jest.fn();
96
+ const tree = ReactTestRenderer.create(
97
+ <SimpleButton title="Disabled Button" onPress={mockPress} disabled={true} />
98
+ );
99
+
100
+ const button = tree.root.findByProps({ testID: 'simple-button' });
101
+ expect(button.props.onPress).toBeUndefined();
102
+ expect(button.props.style.opacity).toBe(0.5);
103
+ });
104
+
105
+ it('handles component state changes', () => {
106
+ const StatefulComponent = () => {
107
+ const [count, setCount] = React.useState(0);
108
+
109
+ return React.createElement(
110
+ 'View',
111
+ { testID: 'stateful-component' },
112
+ React.createElement('Text', { testID: 'count' }, count.toString()),
113
+ React.createElement(
114
+ 'TouchableOpacity',
115
+ {
116
+ testID: 'increment-button',
117
+ onPress: () => setCount(c => c + 1)
118
+ },
119
+ React.createElement('Text', null, 'Increment')
120
+ )
121
+ );
122
+ };
123
+
124
+ const tree = ReactTestRenderer.create(<StatefulComponent />);
125
+
126
+ // Check initial state
127
+ const countText = tree.root.findByProps({ testID: 'count' });
128
+ expect(countText.children).toEqual(['0']);
129
+
130
+ // Simulate button press
131
+ const incrementButton = tree.root.findByProps({ testID: 'increment-button' });
132
+ ReactTestRenderer.act(() => {
133
+ incrementButton.props.onPress();
134
+ });
135
+
136
+ // Check updated state
137
+ expect(countText.children).toEqual(['1']);
138
+ });
139
+ });
140
+
141
+ describe('Sample Native Tests', () => {
142
+ it('should pass a basic test', () => {
143
+ expect(1 + 1).toBe(2);
144
+ });
145
+
146
+ it('should handle string operations', () => {
147
+ const greeting = 'Hello World';
148
+ expect(greeting).toContain('World');
149
+ });
150
+
151
+ it('should work with arrays', () => {
152
+ const items = [1, 2, 3];
153
+ expect(items).toHaveLength(3);
154
+ expect(items).toContain(2);
155
+ });
156
+ });