@idealyst/cli 1.0.90 → 1.0.91

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 (87) hide show
  1. package/package.json +2 -2
  2. package/template/.devcontainer/Dockerfile +26 -0
  3. package/template/.devcontainer/devcontainer.json +113 -0
  4. package/template/.devcontainer/docker-compose.yml +59 -0
  5. package/template/.devcontainer/figma-mcp.sh +32 -0
  6. package/template/.devcontainer/setup.sh +45 -0
  7. package/template/.dockerignore +151 -0
  8. package/template/.env.example +36 -0
  9. package/template/.env.production +56 -0
  10. package/template/DOCKER.md +0 -0
  11. package/template/Dockerfile +111 -0
  12. package/template/README.md +233 -0
  13. package/template/docker/nginx/prod.conf +238 -0
  14. package/template/docker/nginx.conf +131 -0
  15. package/template/docker/postgres/init.sql +41 -0
  16. package/template/docker/prometheus/prometheus.yml +52 -0
  17. package/template/docker-compose.prod.yml +146 -0
  18. package/template/docker-compose.yml +143 -0
  19. package/template/jest.config.js +20 -0
  20. package/template/package.json +45 -0
  21. package/template/packages/api/.env.example +6 -0
  22. package/template/packages/api/README.md +274 -0
  23. package/template/packages/api/__tests__/api.test.ts +26 -0
  24. package/template/packages/api/jest.config.js +23 -0
  25. package/template/packages/api/jest.setup.js +9 -0
  26. package/template/packages/api/package.json +56 -0
  27. package/template/packages/api/src/context.ts +19 -0
  28. package/template/packages/api/src/controllers/TestController.ts +0 -0
  29. package/template/packages/api/src/index.ts +9 -0
  30. package/template/packages/api/src/lib/crud.ts +150 -0
  31. package/template/packages/api/src/lib/database.ts +23 -0
  32. package/template/packages/api/src/router/index.ts +163 -0
  33. package/template/packages/api/src/routers/test.ts +59 -0
  34. package/template/packages/api/src/routers/user.example.ts +83 -0
  35. package/template/packages/api/src/server.ts +50 -0
  36. package/template/packages/api/src/trpc.ts +28 -0
  37. package/template/packages/api/tsconfig.json +43 -0
  38. package/template/packages/database/README.md +162 -0
  39. package/template/packages/database/package.json +49 -0
  40. package/template/packages/database/prisma/seed.ts +64 -0
  41. package/template/packages/database/schema.prisma +107 -0
  42. package/template/packages/database/src/index.ts +15 -0
  43. package/template/packages/database/src/validators.ts +10 -0
  44. package/template/packages/database/tsconfig.json +18 -0
  45. package/template/packages/mobile/README.md +86 -0
  46. package/template/packages/mobile/__tests__/App.test.tsx +156 -0
  47. package/template/packages/mobile/__tests__/components.test.tsx +300 -0
  48. package/template/packages/mobile/app.json +5 -0
  49. package/template/packages/mobile/babel.config.js +11 -0
  50. package/template/packages/mobile/index.js +6 -0
  51. package/template/packages/mobile/jest.config.js +21 -0
  52. package/template/packages/mobile/jest.setup.js +12 -0
  53. package/template/packages/mobile/metro.config.js +27 -0
  54. package/template/packages/mobile/package.json +52 -0
  55. package/template/packages/mobile/src/App-with-trpc-and-shared.tsx +8 -0
  56. package/template/packages/mobile/src/App-with-trpc.tsx +30 -0
  57. package/template/packages/mobile/src/App.tsx +8 -0
  58. package/template/packages/mobile/src/utils/trpc.ts +7 -0
  59. package/template/packages/mobile/tsconfig.json +28 -0
  60. package/template/packages/shared/README.md +135 -0
  61. package/template/packages/shared/__tests__/shared.test.ts +51 -0
  62. package/template/packages/shared/jest.config.js +22 -0
  63. package/template/packages/shared/package.json +62 -0
  64. package/template/packages/shared/src/components/App.tsx +46 -0
  65. package/template/packages/shared/src/components/HelloWorld.tsx +304 -0
  66. package/template/packages/shared/src/components/index.ts +1 -0
  67. package/template/packages/shared/src/index.ts +14 -0
  68. package/template/packages/shared/src/navigation/AppRouter.tsx +565 -0
  69. package/template/packages/shared/src/trpc/client.ts +44 -0
  70. package/template/packages/shared/tsconfig.json +22 -0
  71. package/template/packages/web/README.md +131 -0
  72. package/template/packages/web/__tests__/App.test.tsx +342 -0
  73. package/template/packages/web/__tests__/components.test.tsx +564 -0
  74. package/template/packages/web/index.html +13 -0
  75. package/template/packages/web/jest.config.js +27 -0
  76. package/template/packages/web/jest.setup.js +24 -0
  77. package/template/packages/web/package.json +69 -0
  78. package/template/packages/web/src/App-with-trpc-and-shared.tsx +14 -0
  79. package/template/packages/web/src/App-with-trpc.tsx +32 -0
  80. package/template/packages/web/src/App.tsx +14 -0
  81. package/template/packages/web/src/components/TestDemo.tsx +164 -0
  82. package/template/packages/web/src/main.tsx +25 -0
  83. package/template/packages/web/src/utils/trpc.ts +7 -0
  84. package/template/packages/web/tsconfig.json +26 -0
  85. package/template/packages/web/vite.config.ts +98 -0
  86. package/template/setup.sh +30 -0
  87. package/template/tsconfig.json +31 -0
@@ -0,0 +1,300 @@
1
+ /**
2
+ * Example component tests for React Native
3
+ * @format
4
+ */
5
+
6
+ import React from 'react';
7
+ import ReactTestRenderer from 'react-test-renderer';
8
+
9
+ describe('React Native Component Testing Examples', () => {
10
+ // Example 1: Simple Text Component
11
+ const SimpleText = ({ text, color = 'black' }: { text: string; color?: string }) => {
12
+ return React.createElement('Text', { style: { color }, testID: 'simple-text' }, text);
13
+ };
14
+
15
+ describe('SimpleText Component', () => {
16
+ it('renders text correctly', () => {
17
+ const tree = ReactTestRenderer.create(<SimpleText text="Hello World" />);
18
+ const textComponent = tree.root.findByProps({ testID: 'simple-text' });
19
+ expect(textComponent.children).toEqual(['Hello World']);
20
+ });
21
+
22
+ it('applies custom color', () => {
23
+ const tree = ReactTestRenderer.create(<SimpleText text="Colored Text" color="red" />);
24
+ const textComponent = tree.root.findByProps({ testID: 'simple-text' });
25
+ expect(textComponent.props.style.color).toBe('red');
26
+ });
27
+
28
+ it('uses default color when not specified', () => {
29
+ const tree = ReactTestRenderer.create(<SimpleText text="Default Color" />);
30
+ const textComponent = tree.root.findByProps({ testID: 'simple-text' });
31
+ expect(textComponent.props.style.color).toBe('black');
32
+ });
33
+ });
34
+
35
+ // Example 2: Button with Press Handler
36
+ const PressableButton = ({
37
+ title,
38
+ onPress,
39
+ disabled = false
40
+ }: {
41
+ title: string;
42
+ onPress: () => void;
43
+ disabled?: boolean;
44
+ }) => {
45
+ return React.createElement(
46
+ 'TouchableOpacity',
47
+ {
48
+ testID: 'pressable-button',
49
+ onPress: disabled ? undefined : onPress,
50
+ style: { opacity: disabled ? 0.5 : 1 }
51
+ },
52
+ React.createElement('Text', { testID: 'button-text' }, title)
53
+ );
54
+ };
55
+
56
+ describe('PressableButton Component', () => {
57
+ it('renders button with title', () => {
58
+ const mockPress = jest.fn();
59
+ const tree = ReactTestRenderer.create(
60
+ <PressableButton title="Press Me" onPress={mockPress} />
61
+ );
62
+
63
+ const buttonText = tree.root.findByProps({ testID: 'button-text' });
64
+ expect(buttonText.children).toEqual(['Press Me']);
65
+ });
66
+
67
+ it('calls onPress when pressed', () => {
68
+ const mockPress = jest.fn();
69
+ const tree = ReactTestRenderer.create(
70
+ <PressableButton title="Press Me" onPress={mockPress} />
71
+ );
72
+
73
+ const button = tree.root.findByProps({ testID: 'pressable-button' });
74
+ ReactTestRenderer.act(() => {
75
+ button.props.onPress();
76
+ });
77
+
78
+ expect(mockPress).toHaveBeenCalledTimes(1);
79
+ });
80
+
81
+ it('does not call onPress when disabled', () => {
82
+ const mockPress = jest.fn();
83
+ const tree = ReactTestRenderer.create(
84
+ <PressableButton title="Disabled" onPress={mockPress} disabled />
85
+ );
86
+
87
+ const button = tree.root.findByProps({ testID: 'pressable-button' });
88
+ expect(button.props.onPress).toBeUndefined();
89
+ expect(button.props.style.opacity).toBe(0.5);
90
+ });
91
+ });
92
+
93
+ // Example 3: List Component
94
+ const ItemList = ({ items }: { items: string[] }) => {
95
+ return React.createElement(
96
+ 'FlatList',
97
+ {
98
+ testID: 'item-list',
99
+ data: items,
100
+ renderItem: ({ item, index }: { item: string; index: number }) =>
101
+ React.createElement(
102
+ 'View',
103
+ { key: index, testID: `item-${index}` },
104
+ React.createElement('Text', { testID: `item-text-${index}` }, item)
105
+ ),
106
+ keyExtractor: (item: string, index: number) => `${item}-${index}`
107
+ }
108
+ );
109
+ };
110
+
111
+ describe('ItemList Component', () => {
112
+ it('renders list with items', () => {
113
+ const items = ['Item 1', 'Item 2', 'Item 3'];
114
+ const tree = ReactTestRenderer.create(<ItemList items={items} />);
115
+
116
+ const flatList = tree.root.findByProps({ testID: 'item-list' });
117
+ expect(flatList.props.data).toEqual(items);
118
+ });
119
+
120
+ it('generates correct key extractor', () => {
121
+ const items = ['Apple', 'Banana'];
122
+ const tree = ReactTestRenderer.create(<ItemList items={items} />);
123
+
124
+ const flatList = tree.root.findByProps({ testID: 'item-list' });
125
+ const keyExtractor = flatList.props.keyExtractor;
126
+
127
+ expect(keyExtractor('Apple', 0)).toBe('Apple-0');
128
+ expect(keyExtractor('Banana', 1)).toBe('Banana-1');
129
+ });
130
+ });
131
+
132
+ // Example 4: Form Input Component
133
+ const TextInput = ({
134
+ value,
135
+ onChangeText,
136
+ placeholder,
137
+ secureTextEntry = false
138
+ }: {
139
+ value: string;
140
+ onChangeText: (text: string) => void;
141
+ placeholder?: string;
142
+ secureTextEntry?: boolean;
143
+ }) => {
144
+ return React.createElement('TextInput', {
145
+ testID: 'text-input',
146
+ value,
147
+ onChangeText,
148
+ placeholder,
149
+ secureTextEntry,
150
+ style: { borderWidth: 1, padding: 10 }
151
+ });
152
+ };
153
+
154
+ describe('TextInput Component', () => {
155
+ it('renders with initial value', () => {
156
+ const mockChange = jest.fn();
157
+ const tree = ReactTestRenderer.create(
158
+ <TextInput value="Initial Value" onChangeText={mockChange} />
159
+ );
160
+
161
+ const input = tree.root.findByProps({ testID: 'text-input' });
162
+ expect(input.props.value).toBe('Initial Value');
163
+ });
164
+
165
+ it('calls onChangeText when text changes', () => {
166
+ const mockChange = jest.fn();
167
+ const tree = ReactTestRenderer.create(
168
+ <TextInput value="" onChangeText={mockChange} />
169
+ );
170
+
171
+ const input = tree.root.findByProps({ testID: 'text-input' });
172
+ ReactTestRenderer.act(() => {
173
+ input.props.onChangeText('New Text');
174
+ });
175
+
176
+ expect(mockChange).toHaveBeenCalledWith('New Text');
177
+ });
178
+
179
+ it('shows placeholder when provided', () => {
180
+ const mockChange = jest.fn();
181
+ const tree = ReactTestRenderer.create(
182
+ <TextInput
183
+ value=""
184
+ onChangeText={mockChange}
185
+ placeholder="Enter text here"
186
+ />
187
+ );
188
+
189
+ const input = tree.root.findByProps({ testID: 'text-input' });
190
+ expect(input.props.placeholder).toBe('Enter text here');
191
+ });
192
+
193
+ it('enables secure text entry when specified', () => {
194
+ const mockChange = jest.fn();
195
+ const tree = ReactTestRenderer.create(
196
+ <TextInput
197
+ value=""
198
+ onChangeText={mockChange}
199
+ secureTextEntry
200
+ />
201
+ );
202
+
203
+ const input = tree.root.findByProps({ testID: 'text-input' });
204
+ expect(input.props.secureTextEntry).toBe(true);
205
+ });
206
+ });
207
+
208
+ // Example 5: Component with Hooks
209
+ const Counter = ({ initialValue = 0 }: { initialValue?: number }) => {
210
+ const [count, setCount] = React.useState(initialValue);
211
+
212
+ return React.createElement(
213
+ 'View',
214
+ { testID: 'counter-container' },
215
+ React.createElement('Text', { testID: 'counter-value' }, count.toString()),
216
+ React.createElement(
217
+ 'TouchableOpacity',
218
+ {
219
+ testID: 'increment-button',
220
+ onPress: () => setCount(prev => prev + 1)
221
+ },
222
+ React.createElement('Text', null, '+')
223
+ ),
224
+ React.createElement(
225
+ 'TouchableOpacity',
226
+ {
227
+ testID: 'decrement-button',
228
+ onPress: () => setCount(prev => prev - 1)
229
+ },
230
+ React.createElement('Text', null, '-')
231
+ ),
232
+ React.createElement(
233
+ 'TouchableOpacity',
234
+ {
235
+ testID: 'reset-button',
236
+ onPress: () => setCount(initialValue)
237
+ },
238
+ React.createElement('Text', null, 'Reset')
239
+ )
240
+ );
241
+ };
242
+
243
+ describe('Counter Component', () => {
244
+ it('renders with initial value', () => {
245
+ const tree = ReactTestRenderer.create(<Counter initialValue={5} />);
246
+ const counterValue = tree.root.findByProps({ testID: 'counter-value' });
247
+ expect(counterValue.children).toEqual(['5']);
248
+ });
249
+
250
+ it('increments counter when increment button is pressed', () => {
251
+ const tree = ReactTestRenderer.create(<Counter />);
252
+ const counterValue = tree.root.findByProps({ testID: 'counter-value' });
253
+ const incrementButton = tree.root.findByProps({ testID: 'increment-button' });
254
+
255
+ expect(counterValue.children).toEqual(['0']);
256
+
257
+ ReactTestRenderer.act(() => {
258
+ incrementButton.props.onPress();
259
+ });
260
+
261
+ expect(counterValue.children).toEqual(['1']);
262
+ });
263
+
264
+ it('decrements counter when decrement button is pressed', () => {
265
+ const tree = ReactTestRenderer.create(<Counter initialValue={10} />);
266
+ const counterValue = tree.root.findByProps({ testID: 'counter-value' });
267
+ const decrementButton = tree.root.findByProps({ testID: 'decrement-button' });
268
+
269
+ expect(counterValue.children).toEqual(['10']);
270
+
271
+ ReactTestRenderer.act(() => {
272
+ decrementButton.props.onPress();
273
+ });
274
+
275
+ expect(counterValue.children).toEqual(['9']);
276
+ });
277
+
278
+ it('resets counter to initial value when reset is pressed', () => {
279
+ const tree = ReactTestRenderer.create(<Counter initialValue={5} />);
280
+ const counterValue = tree.root.findByProps({ testID: 'counter-value' });
281
+ const incrementButton = tree.root.findByProps({ testID: 'increment-button' });
282
+ const resetButton = tree.root.findByProps({ testID: 'reset-button' });
283
+
284
+ // Increment a few times
285
+ ReactTestRenderer.act(() => {
286
+ incrementButton.props.onPress();
287
+ incrementButton.props.onPress();
288
+ });
289
+
290
+ expect(counterValue.children).toEqual(['7']);
291
+
292
+ // Reset
293
+ ReactTestRenderer.act(() => {
294
+ resetButton.props.onPress();
295
+ });
296
+
297
+ expect(counterValue.children).toEqual(['5']);
298
+ });
299
+ });
300
+ });
@@ -0,0 +1,5 @@
1
+ {
2
+ "name": "{{appName}}",
3
+ "displayName": "{{appName}}",
4
+ "react-native-version": "0.80.1"
5
+ }
@@ -0,0 +1,11 @@
1
+ module.exports = {
2
+ presets: ['module:@react-native/babel-preset'],
3
+ plugins: [
4
+ ['react-native-unistyles/plugin', {
5
+ root: 'src',
6
+ autoProcessPaths: ['@idealyst/components', '@idealyst/navigation', '@idealyst/theme'],
7
+ }],
8
+ 'react-native-reanimated/plugin',
9
+ 'react-native-worklets/plugin',
10
+ ],
11
+ };
@@ -0,0 +1,6 @@
1
+ import '@idealyst/theme/unistyles';
2
+
3
+ import { AppRegistry } from 'react-native';
4
+ import App from './src/App';
5
+
6
+ AppRegistry.registerComponent('{{projectName}}', () => App);
@@ -0,0 +1,21 @@
1
+ module.exports = {
2
+ preset: 'react-native',
3
+ setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
4
+ testMatch: [
5
+ '**/__tests__/**/*.{ts,tsx,js}',
6
+ '**/*.{test,spec}.{ts,tsx,js}'
7
+ ],
8
+ transform: {
9
+ '^.+\\.(js|jsx|ts|tsx)$': 'babel-jest',
10
+ },
11
+ transformIgnorePatterns: [
12
+ 'node_modules/(?!(react-native|@react-native|@idealyst)/)',
13
+ ],
14
+ collectCoverageFrom: [
15
+ 'src/**/*.{ts,tsx}',
16
+ '!src/**/*.d.ts',
17
+ '!src/**/index.ts',
18
+ ],
19
+ coverageDirectory: 'coverage',
20
+ testEnvironment: 'jsdom',
21
+ };
@@ -0,0 +1,12 @@
1
+ // Global test setup for React Native tests
2
+ import 'react-native-gesture-handler/jestSetup';
3
+
4
+ // Mock react-native modules that are not available in test environment
5
+ jest.mock('react-native-reanimated', () => {
6
+ const Reanimated = require('react-native-reanimated/mock');
7
+ Reanimated.default.call = () => {};
8
+ return Reanimated;
9
+ });
10
+
11
+ // Silence the warning: Animated: `useNativeDriver` is not supported
12
+ jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper');
@@ -0,0 +1,27 @@
1
+ const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
2
+ const path = require('path');
3
+
4
+ const { wrapWithReanimatedMetroConfig } = require('react-native-reanimated/metro-config');
5
+
6
+ const config = {
7
+ projectRoot: __dirname,
8
+ watchFolders: [
9
+ // Add the workspace root to watch folders so Metro can find hoisted node_modules
10
+ path.resolve(__dirname, '../..'),
11
+ ],
12
+ resolver: {
13
+ nodeModulesPaths: [
14
+ path.resolve(__dirname, 'node_modules'),
15
+ // Add the workspace root node_modules for hoisted packages
16
+ path.resolve(__dirname, '../..', 'node_modules'),
17
+ ],
18
+ // Important for Idealyst to use .native extensions for React Native (eg: @idealyst/components/src/Button/Button.native.tsx)
19
+ sourceExts: ['native.tsx', 'native.ts', 'tsx', 'ts', 'native.jsx', 'native.js', 'jsx', 'js', 'json', 'cjs'],
20
+ },
21
+ watcher: {
22
+ // When configuring custom components with .native extensions, make sure the watcher looks for them
23
+ additionalExts: ['native.tsx', 'native.ts', 'native.jsx', 'native.js'],
24
+ },
25
+ };
26
+
27
+ module.exports = wrapWithReanimatedMetroConfig(mergeConfig(getDefaultConfig(__dirname), config));
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@{{workspaceScope}}/mobile",
3
+ "version": "{{version}}",
4
+ "description": "{{description}}",
5
+ "private": true,
6
+ "scripts": {
7
+ "start": "react-native start",
8
+ "ios": "react-native run-ios",
9
+ "android": "react-native run-android",
10
+ "test": "jest",
11
+ "test:watch": "jest --watch",
12
+ "test:coverage": "jest --coverage",
13
+ "lint": "eslint . --ext .js,.jsx,.ts,.tsx"
14
+ },
15
+ "dependencies": {
16
+ "@idealyst/components": "^{{idealystVersion}}",
17
+ "@idealyst/navigation": "^{{idealystVersion}}",
18
+ "@idealyst/theme": "^{{idealystVersion}}",
19
+ "@{{workspaceScope}}/shared": "workspace:*",
20
+ "@{{workspaceScope}}/database": "workspace:*",
21
+ "@tanstack/react-query": "^5.83.0",
22
+ "@trpc/client": "^11.5.1",
23
+ "@trpc/react-query": "^11.5.1",
24
+ "@trpc/server": "^11.5.1",
25
+ "react": "^18.2.0",
26
+ "react-native": "^0.73.0",
27
+ "react-native-svg": "^15.8.0",
28
+ "react-native-worklets": "^0.6.1"
29
+ },
30
+ "devDependencies": {
31
+ "@babel/core": "^7.20.0",
32
+ "@babel/preset-env": "^7.20.0",
33
+ "@babel/runtime": "^7.20.0",
34
+ "@react-native/babel-preset": "^0.73.0",
35
+ "@react-native/eslint-config": "^0.73.0",
36
+ "@react-native/metro-config": "^0.73.0",
37
+ "@react-native/typescript-config": "^0.73.0",
38
+ "@types/jest": "^29.5.12",
39
+ "@types/react": "^18.2.6",
40
+ "@types/react-test-renderer": "^18.0.7",
41
+ "eslint": "^8.19.0",
42
+ "jest": "^29.6.3",
43
+ "metro-react-native-babel-preset": "^0.76.8",
44
+ "prettier": "^2.4.1",
45
+ "react-test-renderer": "^18.2.0",
46
+ "typescript": "^5.0.4"
47
+ },
48
+ "idealyst": {
49
+ "framework": "react-native",
50
+ "version": "1.0.3"
51
+ }
52
+ }
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { App } from '@{{workspaceScope}}/shared';
3
+
4
+ function NativeApp() {
5
+ return <App />;
6
+ }
7
+
8
+ export default NativeApp;
@@ -0,0 +1,30 @@
1
+ import React from 'react';
2
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
3
+ import { NavigatorProvider } from '@idealyst/navigation';
4
+ import { trpc, createTRPCClient, AppRouter } from '{{workspaceScope}}/shared';
5
+
6
+ // Create tRPC client using shared factory
7
+ const queryClient = new QueryClient();
8
+
9
+ const trpcClient = createTRPCClient({
10
+ apiUrl: 'http://localhost:3000/trpc', // Update this to your API URL
11
+ // For device testing, you might need: 'http://192.168.1.xxx:3000/trpc'
12
+ // Optional: Add headers for authentication
13
+ // headers() {
14
+ // return {
15
+ // authorization: getAuthToken(),
16
+ // };
17
+ // },
18
+ });
19
+
20
+ function App() {
21
+ return (
22
+ <trpc.Provider client={trpcClient} queryClient={queryClient}>
23
+ <QueryClientProvider client={queryClient}>
24
+ <NavigatorProvider route={AppRouter} />
25
+ </QueryClientProvider>
26
+ </trpc.Provider>
27
+ );
28
+ }
29
+
30
+ export default App;
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { App } from '@{{workspaceScope}}/shared';
3
+
4
+ function NativeApp() {
5
+ return <App />;
6
+ }
7
+
8
+ export default NativeApp;
@@ -0,0 +1,7 @@
1
+ // Import tRPC client utilities from shared package
2
+ export {
3
+ trpc,
4
+ createTRPCClient,
5
+ createVanillaTRPCClient
6
+ } from '@{{workspaceScope}}/shared';
7
+ export type { TRPCClientConfig, AppRouter } from '@{{workspaceScope}}/shared';
@@ -0,0 +1,28 @@
1
+ {
2
+ "extends": "@react-native/typescript-config/tsconfig.json",
3
+ "compilerOptions": {
4
+ "allowJs": true,
5
+ "allowSyntheticDefaultImports": true,
6
+ "esModuleInterop": true,
7
+ "isolatedModules": true,
8
+ "jsx": "react-native",
9
+ "lib": ["es2017"],
10
+ "noEmit": true,
11
+ "strict": true,
12
+ "target": "esnext",
13
+ "skipLibCheck": true,
14
+ "baseUrl": "./",
15
+ "paths": {
16
+ "@/*": ["./src/*"]
17
+ }
18
+ },
19
+ "include": [
20
+ "src/**/*",
21
+ "index.js"
22
+ ],
23
+ "exclude": [
24
+ "node_modules",
25
+ "android",
26
+ "ios"
27
+ ]
28
+ }
@@ -0,0 +1,135 @@
1
+ # {{projectName}}
2
+
3
+ {{description}}
4
+
5
+ ## Getting Started
6
+
7
+ This is a shared component library built with the Idealyst Framework that can be used across React Native and React web applications. It exports source TypeScript files directly for seamless integration in monorepo setups.
8
+
9
+ ### Prerequisites
10
+
11
+ - Node.js 18+
12
+ - Yarn
13
+
14
+ ### Installation
15
+
16
+ Install dependencies:
17
+ ```bash
18
+ yarn install
19
+ ```
20
+
21
+ ### Development
22
+
23
+ Run tests:
24
+ ```bash
25
+ yarn test
26
+ ```
27
+
28
+ Type checking:
29
+ ```bash
30
+ yarn type-check
31
+ ```
32
+
33
+ ## Usage
34
+
35
+ Import the HelloWorld component in your React or React Native app:
36
+
37
+ ```typescript
38
+ import { HelloWorld } from '@{{workspaceName}}/shared';
39
+
40
+ function App() {
41
+ return <HelloWorld name="Developer" />;
42
+ }
43
+ ```
44
+
45
+ ## Component
46
+
47
+ ### HelloWorld
48
+
49
+ A simple welcome component that works on both web and mobile platforms.
50
+
51
+ **Props:**
52
+ - `name?: string` - Name to display in the greeting (defaults to "World")
53
+
54
+ **Example:**
55
+ ```typescript
56
+ <HelloWorld name="Alice" />
57
+ ```
58
+
59
+ ### Project Structure
60
+
61
+ ```
62
+ {{projectName}}/
63
+ ├── src/
64
+ │ ├── components/ # Shared components
65
+ │ ├── utils/ # Utility functions
66
+ │ ├── types/ # TypeScript types
67
+ │ └── index.ts # Main export file
68
+ ├── dist/ # Built library (generated)
69
+ ├── rollup.config.js # Build configuration
70
+ └── tsconfig.json # TypeScript configuration
71
+ ```
72
+
73
+ ### Features
74
+
75
+ - **Cross-platform**: Works on both React Native and React web
76
+ - **TypeScript**: Full type safety
77
+ - **Tree-shakeable**: Optimized for bundle size
78
+ - **Peer Dependencies**: Lightweight by design
79
+ - **Idealyst Theme Integration**: Compatible with the Idealyst theming system
80
+
81
+ ### Usage
82
+
83
+ After building, you can import and use the library in your projects:
84
+
85
+ ```tsx
86
+ import { SharedComponent, toTitleCase, ComponentProps } from '{{packageName}}';
87
+
88
+ // Use the shared component
89
+ <SharedComponent
90
+ title="Hello World"
91
+ description="This works on both web and mobile!"
92
+ />
93
+
94
+ // Use utility functions
95
+ const formatted = toTitleCase('hello world'); // "Hello World"
96
+ ```
97
+
98
+ ### Building for Production
99
+
100
+ Build the library:
101
+ ```bash
102
+ yarn build
103
+ ```
104
+
105
+ This creates:
106
+ - `dist/index.js` - CommonJS build
107
+ - `dist/index.esm.js` - ES modules build
108
+ - `dist/index.d.ts` - TypeScript declarations
109
+
110
+ ### Publishing
111
+
112
+ Before publishing, make sure to:
113
+
114
+ 1. Update the version in `package.json`
115
+ 2. Build the library: `yarn build`
116
+ 3. Publish to npm: `npm publish`
117
+
118
+ ### Development in Monorepo
119
+
120
+ If you're using this in a monorepo, you can reference it directly:
121
+
122
+ ```json
123
+ {
124
+ "dependencies": {
125
+ "{{packageName}}": "workspace:*"
126
+ }
127
+ }
128
+ ```
129
+
130
+ ### Learn More
131
+
132
+ - [Idealyst Framework Documentation](https://github.com/your-username/idealyst-framework)
133
+ - [React Native Documentation](https://reactnative.dev/)
134
+ - [React Documentation](https://react.dev/)
135
+ - [Rollup Documentation](https://rollupjs.org/)