@idealyst/cli 1.0.25 → 1.0.26
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.
- package/dist/index.js +114 -6
- package/dist/types/generators/utils.d.ts +4 -0
- package/dist/types/types.d.ts +1 -0
- package/package.json +1 -1
- package/templates/api/package.json +2 -2
- package/templates/api/src/index.ts +11 -47
- package/templates/api/src/server.ts +50 -0
- package/templates/native/src/App-with-trpc.tsx +72 -0
- package/templates/native/src/utils/trpc.ts +127 -0
- package/templates/web/package.json +4 -0
- package/templates/web/src/App-with-trpc.tsx +80 -0
- package/templates/web/src/utils/trpc.ts +93 -0
package/dist/index.js
CHANGED
|
@@ -253,6 +253,10 @@ async function mergePackageJsonDependencies(templatePath, projectPath) {
|
|
|
253
253
|
'@react-navigation/drawer': '^7.5.3',
|
|
254
254
|
'@react-navigation/native': '^7.1.14',
|
|
255
255
|
'@react-navigation/native-stack': '^7.3.21',
|
|
256
|
+
'@tanstack/react-query': '^5.83.0',
|
|
257
|
+
'@trpc/client': '^11.4.3',
|
|
258
|
+
'@trpc/react-query': '^11.4.3',
|
|
259
|
+
'@trpc/server': '^11.4.3',
|
|
256
260
|
'react-native-edge-to-edge': '^1.6.2',
|
|
257
261
|
'react-native-gesture-handler': '^2.27.1',
|
|
258
262
|
'react-native-nitro-modules': '^0.26.3',
|
|
@@ -332,6 +336,71 @@ async function promptForAppName(projectName) {
|
|
|
332
336
|
]);
|
|
333
337
|
return appName;
|
|
334
338
|
}
|
|
339
|
+
async function promptForTrpcIntegration() {
|
|
340
|
+
const { withTrpc } = await inquirer.prompt([
|
|
341
|
+
{
|
|
342
|
+
type: 'confirm',
|
|
343
|
+
name: 'withTrpc',
|
|
344
|
+
message: 'Would you like to include tRPC client setup and boilerplate?',
|
|
345
|
+
default: false
|
|
346
|
+
}
|
|
347
|
+
]);
|
|
348
|
+
return withTrpc;
|
|
349
|
+
}
|
|
350
|
+
async function copyTrpcFiles(templatePath, projectPath, data) {
|
|
351
|
+
const spinner = ora('Adding tRPC client utilities...').start();
|
|
352
|
+
try {
|
|
353
|
+
const trpcUtilsSource = path.join(templatePath, 'src', 'utils', 'trpc.ts');
|
|
354
|
+
const trpcUtilsTarget = path.join(projectPath, 'src', 'utils', 'trpc.ts');
|
|
355
|
+
// Ensure utils directory exists
|
|
356
|
+
await fs.ensureDir(path.join(projectPath, 'src', 'utils'));
|
|
357
|
+
// Copy and process the tRPC utils file
|
|
358
|
+
await fs.copy(trpcUtilsSource, trpcUtilsTarget);
|
|
359
|
+
await processTemplateFile(trpcUtilsTarget, data);
|
|
360
|
+
spinner.succeed('tRPC client utilities added');
|
|
361
|
+
}
|
|
362
|
+
catch (error) {
|
|
363
|
+
spinner.fail('Failed to add tRPC client utilities');
|
|
364
|
+
console.warn(chalk.yellow('⚠️ tRPC utilities could not be copied, but the project was created successfully'));
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
async function copyTrpcAppComponent(templatePath, projectPath, data) {
|
|
368
|
+
const spinner = ora('Setting up tRPC App component...').start();
|
|
369
|
+
try {
|
|
370
|
+
const trpcAppSource = path.join(templatePath, 'src', 'App-with-trpc.tsx');
|
|
371
|
+
const appTarget = path.join(projectPath, 'src', 'App.tsx');
|
|
372
|
+
// Copy the tRPC-enabled App component over the default one
|
|
373
|
+
await fs.copy(trpcAppSource, appTarget, { overwrite: true });
|
|
374
|
+
await processTemplateFile(appTarget, data);
|
|
375
|
+
spinner.succeed('tRPC App component configured');
|
|
376
|
+
}
|
|
377
|
+
catch (error) {
|
|
378
|
+
spinner.fail('Failed to configure tRPC App component');
|
|
379
|
+
console.warn(chalk.yellow('⚠️ tRPC App component could not be configured, but the project was created successfully'));
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
async function removeTrpcDependencies(projectPath) {
|
|
383
|
+
try {
|
|
384
|
+
const packageJsonPath = path.join(projectPath, 'package.json');
|
|
385
|
+
const packageJson = await fs.readJSON(packageJsonPath);
|
|
386
|
+
// Remove tRPC-related dependencies
|
|
387
|
+
const trpcDeps = [
|
|
388
|
+
'@tanstack/react-query',
|
|
389
|
+
'@trpc/client',
|
|
390
|
+
'@trpc/react-query',
|
|
391
|
+
'@trpc/server'
|
|
392
|
+
];
|
|
393
|
+
trpcDeps.forEach(dep => {
|
|
394
|
+
if (packageJson.dependencies && packageJson.dependencies[dep]) {
|
|
395
|
+
delete packageJson.dependencies[dep];
|
|
396
|
+
}
|
|
397
|
+
});
|
|
398
|
+
await fs.writeJSON(packageJsonPath, packageJson, { spaces: 2 });
|
|
399
|
+
}
|
|
400
|
+
catch (error) {
|
|
401
|
+
console.warn(chalk.yellow('⚠️ Could not remove tRPC dependencies from package.json'));
|
|
402
|
+
}
|
|
403
|
+
}
|
|
335
404
|
async function configureAndroidVectorIcons(projectPath) {
|
|
336
405
|
const buildGradlePath = path.join(projectPath, 'android', 'app', 'build.gradle');
|
|
337
406
|
try {
|
|
@@ -371,6 +440,8 @@ var utils = /*#__PURE__*/Object.freeze({
|
|
|
371
440
|
__proto__: null,
|
|
372
441
|
configureAndroidVectorIcons: configureAndroidVectorIcons,
|
|
373
442
|
copyTemplate: copyTemplate,
|
|
443
|
+
copyTrpcAppComponent: copyTrpcAppComponent,
|
|
444
|
+
copyTrpcFiles: copyTrpcFiles,
|
|
374
445
|
createPackageName: createPackageName,
|
|
375
446
|
getTemplateData: getTemplateData,
|
|
376
447
|
initializeReactNativeProject: initializeReactNativeProject,
|
|
@@ -383,6 +454,8 @@ var utils = /*#__PURE__*/Object.freeze({
|
|
|
383
454
|
promptForAppName: promptForAppName,
|
|
384
455
|
promptForProjectName: promptForProjectName,
|
|
385
456
|
promptForProjectType: promptForProjectType,
|
|
457
|
+
promptForTrpcIntegration: promptForTrpcIntegration,
|
|
458
|
+
removeTrpcDependencies: removeTrpcDependencies,
|
|
386
459
|
resolveProjectPath: resolveProjectPath,
|
|
387
460
|
runCommand: runCommand,
|
|
388
461
|
updateWorkspacePackageJson: updateWorkspacePackageJson,
|
|
@@ -392,7 +465,7 @@ var utils = /*#__PURE__*/Object.freeze({
|
|
|
392
465
|
const __filename$4 = fileURLToPath(import.meta.url);
|
|
393
466
|
const __dirname$4 = path.dirname(__filename$4);
|
|
394
467
|
async function generateNativeProject(options) {
|
|
395
|
-
const { name, directory, skipInstall, appName } = options;
|
|
468
|
+
const { name, directory, skipInstall, appName, withTrpc } = options;
|
|
396
469
|
if (!validateProjectName(name)) {
|
|
397
470
|
throw new Error(`Invalid project name: ${name}`);
|
|
398
471
|
}
|
|
@@ -412,9 +485,18 @@ async function generateNativeProject(options) {
|
|
|
412
485
|
await initializeReactNativeProject(projectName, projectDir, displayName, true);
|
|
413
486
|
// Step 3: Overlay Idealyst-specific files
|
|
414
487
|
await overlayIdealystFiles(templatePath, projectPath, templateData);
|
|
415
|
-
// Step 4:
|
|
488
|
+
// Step 4: Handle tRPC setup
|
|
489
|
+
if (withTrpc) {
|
|
490
|
+
await copyTrpcFiles(templatePath, projectPath, templateData);
|
|
491
|
+
await copyTrpcAppComponent(templatePath, projectPath, templateData);
|
|
492
|
+
}
|
|
493
|
+
// Step 5: Configure Android vector icons
|
|
416
494
|
await configureAndroidVectorIcons(projectPath);
|
|
417
|
-
// Step
|
|
495
|
+
// Step 6: Remove tRPC dependencies if not requested (after merge but before install)
|
|
496
|
+
if (!withTrpc) {
|
|
497
|
+
await removeTrpcDependencies(projectPath);
|
|
498
|
+
}
|
|
499
|
+
// Step 7: Install dependencies (including Idealyst packages) after workspace config is updated
|
|
418
500
|
await installDependencies(projectPath, skipInstall);
|
|
419
501
|
console.log(chalk.green('✅ React Native project created successfully!'));
|
|
420
502
|
console.log(chalk.blue('📋 Project includes:'));
|
|
@@ -427,6 +509,11 @@ async function generateNativeProject(options) {
|
|
|
427
509
|
console.log(chalk.white(' • Metro configuration'));
|
|
428
510
|
console.log(chalk.white(' • Babel configuration'));
|
|
429
511
|
console.log(chalk.white(' • Native platform directories (android/, ios/)'));
|
|
512
|
+
if (withTrpc) {
|
|
513
|
+
console.log(chalk.white(' • tRPC client setup and utilities'));
|
|
514
|
+
console.log(chalk.white(' • React Query integration'));
|
|
515
|
+
console.log(chalk.white(' • Pre-configured tRPC provider'));
|
|
516
|
+
}
|
|
430
517
|
}
|
|
431
518
|
catch (error) {
|
|
432
519
|
console.error(chalk.red('❌ Error creating React Native project:'));
|
|
@@ -438,7 +525,7 @@ async function generateNativeProject(options) {
|
|
|
438
525
|
const __filename$3 = fileURLToPath(import.meta.url);
|
|
439
526
|
const __dirname$3 = path.dirname(__filename$3);
|
|
440
527
|
async function generateWebProject(options) {
|
|
441
|
-
const { name, directory, skipInstall } = options;
|
|
528
|
+
const { name, directory, skipInstall, withTrpc } = options;
|
|
442
529
|
if (!validateProjectName(name)) {
|
|
443
530
|
throw new Error(`Invalid project name: ${name}`);
|
|
444
531
|
}
|
|
@@ -447,6 +534,15 @@ async function generateWebProject(options) {
|
|
|
447
534
|
const templatePath = path.join(__dirname$3, '..', 'templates', 'web');
|
|
448
535
|
const templateData = getTemplateData(name, `React web app built with Idealyst Framework`);
|
|
449
536
|
await copyTemplate(templatePath, projectPath, templateData);
|
|
537
|
+
// Handle tRPC setup
|
|
538
|
+
if (withTrpc) {
|
|
539
|
+
await copyTrpcFiles(templatePath, projectPath, templateData);
|
|
540
|
+
await copyTrpcAppComponent(templatePath, projectPath, templateData);
|
|
541
|
+
}
|
|
542
|
+
else {
|
|
543
|
+
// Remove tRPC dependencies if not requested
|
|
544
|
+
await removeTrpcDependencies(projectPath);
|
|
545
|
+
}
|
|
450
546
|
await installDependencies(projectPath, skipInstall);
|
|
451
547
|
await updateWorkspacePackageJson(workspacePath, directory);
|
|
452
548
|
console.log(chalk.green('✅ React Web project created successfully!'));
|
|
@@ -458,6 +554,11 @@ async function generateWebProject(options) {
|
|
|
458
554
|
console.log(chalk.white(' • Idealyst Theme'));
|
|
459
555
|
console.log(chalk.white(' • TypeScript configuration'));
|
|
460
556
|
console.log(chalk.white(' • React Router'));
|
|
557
|
+
if (withTrpc) {
|
|
558
|
+
console.log(chalk.white(' • tRPC client setup and utilities'));
|
|
559
|
+
console.log(chalk.white(' • React Query integration'));
|
|
560
|
+
console.log(chalk.white(' • Pre-configured tRPC provider'));
|
|
561
|
+
}
|
|
461
562
|
}
|
|
462
563
|
|
|
463
564
|
const __filename$2 = fileURLToPath(import.meta.url);
|
|
@@ -562,9 +663,10 @@ program
|
|
|
562
663
|
program
|
|
563
664
|
.command('create [project-name]')
|
|
564
665
|
.description('Create a new Idealyst project')
|
|
565
|
-
.option('-t, --type <type>', 'Project type: native, web, or
|
|
666
|
+
.option('-t, --type <type>', 'Project type: native, web, shared, or api')
|
|
566
667
|
.option('-d, --directory <directory>', 'Output directory', '.')
|
|
567
668
|
.option('-a, --app-name <app-name>', 'Display name for native apps (e.g., "My Awesome App")')
|
|
669
|
+
.option('--with-trpc', 'Include tRPC boilerplate and setup (for web/native projects)')
|
|
568
670
|
.option('--skip-install', 'Skip installing dependencies')
|
|
569
671
|
.action(async (projectName, options) => {
|
|
570
672
|
try {
|
|
@@ -598,12 +700,18 @@ program
|
|
|
598
700
|
if (projectType === 'native' && !appName) {
|
|
599
701
|
appName = await promptForAppName(projectName);
|
|
600
702
|
}
|
|
703
|
+
// Prompt for tRPC integration if it's a web/native project and flag not provided
|
|
704
|
+
let withTrpc = options.withTrpc;
|
|
705
|
+
if ((projectType === 'web' || projectType === 'native') && withTrpc === undefined) {
|
|
706
|
+
withTrpc = await promptForTrpcIntegration();
|
|
707
|
+
}
|
|
601
708
|
await generateProject({
|
|
602
709
|
name: projectName,
|
|
603
710
|
type: projectType,
|
|
604
711
|
directory: options.directory,
|
|
605
712
|
skipInstall: options.skipInstall || false,
|
|
606
|
-
appName
|
|
713
|
+
appName,
|
|
714
|
+
withTrpc: withTrpc || false
|
|
607
715
|
});
|
|
608
716
|
console.log(chalk.green(`✨ Successfully created ${projectName}!`));
|
|
609
717
|
console.log(chalk.blue(`📁 Project created in: ${options.directory}/packages/${projectName}`));
|
|
@@ -29,4 +29,8 @@ export declare function mergePackageJsonDependencies(templatePath: string, proje
|
|
|
29
29
|
export declare function promptForProjectName(): Promise<string>;
|
|
30
30
|
export declare function promptForProjectType(): Promise<string>;
|
|
31
31
|
export declare function promptForAppName(projectName: string): Promise<string>;
|
|
32
|
+
export declare function promptForTrpcIntegration(): Promise<boolean>;
|
|
33
|
+
export declare function copyTrpcFiles(templatePath: string, projectPath: string, data: TemplateData): Promise<void>;
|
|
34
|
+
export declare function copyTrpcAppComponent(templatePath: string, projectPath: string, data: TemplateData): Promise<void>;
|
|
35
|
+
export declare function removeTrpcDependencies(projectPath: string): Promise<void>;
|
|
32
36
|
export declare function configureAndroidVectorIcons(projectPath: string): Promise<void>;
|
package/dist/types/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"build": "tsc",
|
|
9
|
-
"dev": "tsx watch src/
|
|
10
|
-
"start": "node dist/
|
|
9
|
+
"dev": "tsx watch src/server.ts",
|
|
10
|
+
"start": "node dist/server.js",
|
|
11
11
|
"db:generate": "prisma generate",
|
|
12
12
|
"db:push": "prisma db push",
|
|
13
13
|
"db:studio": "prisma studio",
|
|
@@ -1,50 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import { appRouter } from './router/index.js';
|
|
5
|
-
import { createContext } from './context.js';
|
|
6
|
-
import dotenv from 'dotenv';
|
|
1
|
+
// Main exports for the API
|
|
2
|
+
export { appRouter } from './router/index.js';
|
|
3
|
+
export type { AppRouter } from './router/index.js';
|
|
7
4
|
|
|
8
|
-
//
|
|
9
|
-
|
|
5
|
+
// Export context type for client usage
|
|
6
|
+
export type { Context } from './context.js';
|
|
10
7
|
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
// Export middleware for potential external usage
|
|
9
|
+
export * from './middleware/auth.js';
|
|
10
|
+
export * from './middleware/common.js';
|
|
13
11
|
|
|
14
|
-
//
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
});
|
|
12
|
+
// Export controller base classes for extensions
|
|
13
|
+
export { BaseController, controllerToRouter } from './lib/controller.js';
|
|
14
|
+
export type { MiddlewareFn } from './lib/controller.js';
|
|
@@ -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,72 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
3
|
+
import { httpBatchLink } from '@trpc/client';
|
|
4
|
+
import { UnistylesRegistry } from 'react-native-unistyles';
|
|
5
|
+
import { Screen, Text, View } from '@idealyst/components';
|
|
6
|
+
import { breakpoints, lightTheme, darkTheme } from '@idealyst/theme';
|
|
7
|
+
import { trpc } from './utils/trpc';
|
|
8
|
+
|
|
9
|
+
// Register the Unistyles themes and breakpoints
|
|
10
|
+
UnistylesRegistry
|
|
11
|
+
.addBreakpoints(breakpoints)
|
|
12
|
+
.addThemes({
|
|
13
|
+
light: lightTheme,
|
|
14
|
+
dark: darkTheme,
|
|
15
|
+
})
|
|
16
|
+
.addConfig({
|
|
17
|
+
adaptiveThemes: true,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// Create tRPC client
|
|
21
|
+
const queryClient = new QueryClient();
|
|
22
|
+
|
|
23
|
+
const trpcClient = trpc.createClient({
|
|
24
|
+
links: [
|
|
25
|
+
httpBatchLink({
|
|
26
|
+
url: 'http://localhost:3000/trpc', // Update this to your API URL
|
|
27
|
+
// For device testing, you might need: 'http://192.168.1.xxx:3000/trpc'
|
|
28
|
+
// Optional: Add headers for authentication
|
|
29
|
+
// headers() {
|
|
30
|
+
// return {
|
|
31
|
+
// authorization: getAuthToken(),
|
|
32
|
+
// };
|
|
33
|
+
// },
|
|
34
|
+
}),
|
|
35
|
+
],
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
function App() {
|
|
39
|
+
// Example tRPC usage
|
|
40
|
+
const { data, isLoading, error } = trpc.hello.useQuery({ name: 'React Native' });
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<trpc.Provider client={trpcClient} queryClient={queryClient}>
|
|
44
|
+
<QueryClientProvider client={queryClient}>
|
|
45
|
+
<Screen>
|
|
46
|
+
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', padding: 20 }}>
|
|
47
|
+
<Text variant="h1" style={{ textAlign: 'center', marginBottom: 20 }}>
|
|
48
|
+
Welcome to {{appName}}!
|
|
49
|
+
</Text>
|
|
50
|
+
<Text variant="body" style={{ textAlign: 'center', marginBottom: 20 }}>
|
|
51
|
+
This is a React Native app built with the Idealyst Framework
|
|
52
|
+
</Text>
|
|
53
|
+
|
|
54
|
+
{/* tRPC Example */}
|
|
55
|
+
<View style={{ marginTop: 20, alignItems: 'center' }}>
|
|
56
|
+
<Text variant="h3" style={{ marginBottom: 10 }}>tRPC Example:</Text>
|
|
57
|
+
{isLoading && <Text>Loading...</Text>}
|
|
58
|
+
{error && <Text>Error: {error.message}</Text>}
|
|
59
|
+
{data && <Text style={{ textAlign: 'center' }}>{data.greeting}</Text>}
|
|
60
|
+
</View>
|
|
61
|
+
|
|
62
|
+
<Text variant="caption" style={{ textAlign: 'center', marginTop: 30 }}>
|
|
63
|
+
Edit src/App.tsx to get started
|
|
64
|
+
</Text>
|
|
65
|
+
</View>
|
|
66
|
+
</Screen>
|
|
67
|
+
</QueryClientProvider>
|
|
68
|
+
</trpc.Provider>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export default App;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { createTRPCReact } from '@trpc/react-query';
|
|
2
|
+
import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
|
|
3
|
+
|
|
4
|
+
// Import your API types here when you have an API project
|
|
5
|
+
// Example: import type { AppRouter } from '@your-workspace/api';
|
|
6
|
+
|
|
7
|
+
// For now, we'll use a generic type that you can replace
|
|
8
|
+
type AppRouter = any;
|
|
9
|
+
|
|
10
|
+
// Create the tRPC React hooks
|
|
11
|
+
export const trpc = createTRPCReact<AppRouter>();
|
|
12
|
+
|
|
13
|
+
// Create a vanilla client (for use outside of React components)
|
|
14
|
+
export const trpcClient = createTRPCProxyClient<AppRouter>({
|
|
15
|
+
links: [
|
|
16
|
+
httpBatchLink({
|
|
17
|
+
url: 'http://localhost:3000/trpc', // Update this to match your API URL
|
|
18
|
+
// Optional: Add headers for authentication
|
|
19
|
+
// headers() {
|
|
20
|
+
// return {
|
|
21
|
+
// authorization: getAuthToken(),
|
|
22
|
+
// };
|
|
23
|
+
// },
|
|
24
|
+
}),
|
|
25
|
+
],
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
/*
|
|
29
|
+
Usage Examples for React Native:
|
|
30
|
+
|
|
31
|
+
1. First, install the required dependencies:
|
|
32
|
+
yarn add @trpc/client @trpc/react-query @tanstack/react-query
|
|
33
|
+
|
|
34
|
+
2. Replace the AppRouter type import above with your actual API router:
|
|
35
|
+
import type { AppRouter } from '@your-workspace/api';
|
|
36
|
+
|
|
37
|
+
3. Set up the tRPC provider in your App component:
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
import React from 'react';
|
|
41
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
42
|
+
import { httpBatchLink } from '@trpc/client';
|
|
43
|
+
import { trpc } from './src/utils/trpc';
|
|
44
|
+
|
|
45
|
+
const queryClient = new QueryClient();
|
|
46
|
+
|
|
47
|
+
const trpcClient = trpc.createClient({
|
|
48
|
+
links: [
|
|
49
|
+
httpBatchLink({
|
|
50
|
+
url: 'http://localhost:3000/trpc', // Use your computer's IP for device testing
|
|
51
|
+
// For device testing, you might need: 'http://192.168.1.xxx:3000/trpc'
|
|
52
|
+
}),
|
|
53
|
+
],
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
function App() {
|
|
57
|
+
return (
|
|
58
|
+
<trpc.Provider client={trpcClient} queryClient={queryClient}>
|
|
59
|
+
<QueryClientProvider client={queryClient}>
|
|
60
|
+
{/* Your app components */}
|
|
61
|
+
</QueryClientProvider>
|
|
62
|
+
</trpc.Provider>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export default App;
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
4. Use tRPC in your React Native components:
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
import React from 'react';
|
|
73
|
+
import { View, Text, ScrollView, TouchableOpacity } from 'react-native';
|
|
74
|
+
import { trpc } from '../utils/trpc';
|
|
75
|
+
|
|
76
|
+
function UsersList() {
|
|
77
|
+
const { data: users, isLoading, refetch } = trpc.users.getAll.useQuery();
|
|
78
|
+
const createUser = trpc.users.create.useMutation({
|
|
79
|
+
onSuccess: () => {
|
|
80
|
+
refetch(); // Refresh the list after creating
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
if (isLoading) {
|
|
85
|
+
return (
|
|
86
|
+
<View>
|
|
87
|
+
<Text>Loading...</Text>
|
|
88
|
+
</View>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<ScrollView>
|
|
94
|
+
{users?.map(user => (
|
|
95
|
+
<View key={user.id}>
|
|
96
|
+
<Text>{user.name}</Text>
|
|
97
|
+
<Text>{user.email}</Text>
|
|
98
|
+
</View>
|
|
99
|
+
))}
|
|
100
|
+
<TouchableOpacity
|
|
101
|
+
onPress={() => createUser.mutate({
|
|
102
|
+
email: 'test@example.com',
|
|
103
|
+
name: 'Test User'
|
|
104
|
+
})}
|
|
105
|
+
>
|
|
106
|
+
<Text>Create User</Text>
|
|
107
|
+
</TouchableOpacity>
|
|
108
|
+
</ScrollView>
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
5. For device testing, make sure to:
|
|
114
|
+
- Use your computer's IP address instead of localhost
|
|
115
|
+
- Ensure your API server is accessible from the device
|
|
116
|
+
- Consider using ngrok for external testing
|
|
117
|
+
|
|
118
|
+
6. Error handling example:
|
|
119
|
+
|
|
120
|
+
```tsx
|
|
121
|
+
const { data, error, isLoading } = trpc.users.getAll.useQuery();
|
|
122
|
+
|
|
123
|
+
if (error) {
|
|
124
|
+
return <Text>Error: {error.message}</Text>;
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
*/
|
|
@@ -16,6 +16,10 @@
|
|
|
16
16
|
"@mdi/js": "^7.4.47",
|
|
17
17
|
"@mdi/react": "^1.6.1",
|
|
18
18
|
"@react-native/normalize-colors": "^0.80.1",
|
|
19
|
+
"@tanstack/react-query": "^5.83.0",
|
|
20
|
+
"@trpc/client": "^11.4.3",
|
|
21
|
+
"@trpc/react-query": "^11.4.3",
|
|
22
|
+
"@trpc/server": "^11.4.3",
|
|
19
23
|
"@types/react-router-dom": "^5.3.3",
|
|
20
24
|
"compression": "^1.7.4",
|
|
21
25
|
"express": "^4.18.2",
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
3
|
+
import { httpBatchLink } from '@trpc/client';
|
|
4
|
+
import { UnistylesRegistry } from 'react-native-unistyles';
|
|
5
|
+
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
|
6
|
+
import { trpc } from './utils/trpc';
|
|
7
|
+
import { Screen, Text, View } from '@idealyst/components';
|
|
8
|
+
import { breakpoints, lightTheme, darkTheme } from '@idealyst/theme';
|
|
9
|
+
|
|
10
|
+
// Register the Unistyles themes and breakpoints
|
|
11
|
+
UnistylesRegistry
|
|
12
|
+
.addBreakpoints(breakpoints)
|
|
13
|
+
.addThemes({
|
|
14
|
+
light: lightTheme,
|
|
15
|
+
dark: darkTheme,
|
|
16
|
+
})
|
|
17
|
+
.addConfig({
|
|
18
|
+
adaptiveThemes: true,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// Create tRPC client
|
|
22
|
+
const queryClient = new QueryClient();
|
|
23
|
+
|
|
24
|
+
const trpcClient = trpc.createClient({
|
|
25
|
+
links: [
|
|
26
|
+
httpBatchLink({
|
|
27
|
+
url: 'http://localhost:3000/trpc', // Update this to match your API URL
|
|
28
|
+
// Optional: Add headers for authentication
|
|
29
|
+
// headers() {
|
|
30
|
+
// return {
|
|
31
|
+
// authorization: getAuthToken(),
|
|
32
|
+
// };
|
|
33
|
+
// },
|
|
34
|
+
}),
|
|
35
|
+
],
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
function HomePage() {
|
|
39
|
+
// Example tRPC usage
|
|
40
|
+
const { data, isLoading, error } = trpc.hello.useQuery({ name: 'World' });
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<Screen>
|
|
44
|
+
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
|
|
45
|
+
<Text variant="h1">Welcome to {{projectName}}!</Text>
|
|
46
|
+
<Text variant="body">
|
|
47
|
+
This is a React Web app built with the Idealyst Framework
|
|
48
|
+
</Text>
|
|
49
|
+
|
|
50
|
+
{/* tRPC Example */}
|
|
51
|
+
<View style={{ marginTop: 20 }}>
|
|
52
|
+
<Text variant="h3">tRPC Example:</Text>
|
|
53
|
+
{isLoading && <Text>Loading...</Text>}
|
|
54
|
+
{error && <Text>Error: {error.message}</Text>}
|
|
55
|
+
{data && <Text>{data.greeting}</Text>}
|
|
56
|
+
</View>
|
|
57
|
+
|
|
58
|
+
<Text variant="caption" style={{ marginTop: 20 }}>
|
|
59
|
+
Edit src/App.tsx to get started
|
|
60
|
+
</Text>
|
|
61
|
+
</View>
|
|
62
|
+
</Screen>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function App() {
|
|
67
|
+
return (
|
|
68
|
+
<trpc.Provider client={trpcClient} queryClient={queryClient}>
|
|
69
|
+
<QueryClientProvider client={queryClient}>
|
|
70
|
+
<BrowserRouter>
|
|
71
|
+
<Routes>
|
|
72
|
+
<Route path="/" element={<HomePage />} />
|
|
73
|
+
</Routes>
|
|
74
|
+
</BrowserRouter>
|
|
75
|
+
</QueryClientProvider>
|
|
76
|
+
</trpc.Provider>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export default App;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { createTRPCReact } from '@trpc/react-query';
|
|
2
|
+
import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
|
|
3
|
+
|
|
4
|
+
// Import your API types here when you have an API project
|
|
5
|
+
// Example: import type { AppRouter } from '@your-workspace/api';
|
|
6
|
+
|
|
7
|
+
// For now, we'll use a generic type that you can replace
|
|
8
|
+
type AppRouter = any;
|
|
9
|
+
|
|
10
|
+
// Create the tRPC React hooks
|
|
11
|
+
export const trpc = createTRPCReact<AppRouter>();
|
|
12
|
+
|
|
13
|
+
// Create a vanilla client (for use outside of React components)
|
|
14
|
+
export const trpcClient = createTRPCProxyClient<AppRouter>({
|
|
15
|
+
links: [
|
|
16
|
+
httpBatchLink({
|
|
17
|
+
url: 'http://localhost:3000/trpc', // Update this to match your API URL
|
|
18
|
+
// Optional: Add headers
|
|
19
|
+
// headers() {
|
|
20
|
+
// return {
|
|
21
|
+
// authorization: getAuthToken(),
|
|
22
|
+
// };
|
|
23
|
+
// },
|
|
24
|
+
}),
|
|
25
|
+
],
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
/*
|
|
29
|
+
Usage Examples:
|
|
30
|
+
|
|
31
|
+
1. First, install the required dependencies:
|
|
32
|
+
yarn add @trpc/client @trpc/react-query @tanstack/react-query
|
|
33
|
+
|
|
34
|
+
2. Replace the AppRouter type import above with your actual API router:
|
|
35
|
+
import type { AppRouter } from '@your-workspace/api';
|
|
36
|
+
|
|
37
|
+
3. Set up the tRPC provider in your App component:
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
41
|
+
import { httpBatchLink } from '@trpc/client';
|
|
42
|
+
import { trpc } from './utils/trpc';
|
|
43
|
+
|
|
44
|
+
const queryClient = new QueryClient();
|
|
45
|
+
|
|
46
|
+
const trpcClient = trpc.createClient({
|
|
47
|
+
links: [
|
|
48
|
+
httpBatchLink({
|
|
49
|
+
url: 'http://localhost:3000/trpc',
|
|
50
|
+
}),
|
|
51
|
+
],
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
function App() {
|
|
55
|
+
return (
|
|
56
|
+
<trpc.Provider client={trpcClient} queryClient={queryClient}>
|
|
57
|
+
<QueryClientProvider client={queryClient}>
|
|
58
|
+
{/* Your app components */}
|
|
59
|
+
</QueryClientProvider>
|
|
60
|
+
</trpc.Provider>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
4. Use tRPC in your components:
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
import { trpc } from '../utils/trpc';
|
|
69
|
+
|
|
70
|
+
function UsersList() {
|
|
71
|
+
const { data: users, isLoading } = trpc.users.getAll.useQuery();
|
|
72
|
+
const createUser = trpc.users.create.useMutation();
|
|
73
|
+
|
|
74
|
+
if (isLoading) return <div>Loading...</div>;
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<div>
|
|
78
|
+
{users?.map(user => (
|
|
79
|
+
<div key={user.id}>{user.name}</div>
|
|
80
|
+
))}
|
|
81
|
+
<button
|
|
82
|
+
onClick={() => createUser.mutate({
|
|
83
|
+
email: 'test@example.com',
|
|
84
|
+
name: 'Test User'
|
|
85
|
+
})}
|
|
86
|
+
>
|
|
87
|
+
Create User
|
|
88
|
+
</button>
|
|
89
|
+
</div>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
*/
|