@teardown/cli 2.0.73 → 2.0.75
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/package.json +2 -2
- package/src/cli/commands/dev.ts +48 -26
- package/src/cli/commands/run.ts +36 -1
- package/src/config/loader.ts +5 -0
- package/src/config/schema.ts +18 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/metro-config.ts +155 -0
- package/templates/.teardown/linking.generated.ts +11 -0
- package/templates/.teardown/manifest.json +18 -0
- package/templates/.teardown/register.d.ts +9 -0
- package/templates/.teardown/routeTree.generated.ts +42 -0
- package/templates/.teardown/routes.generated.ts +19 -0
- package/templates/metro.config.js +3 -7
- package/templates/src/_routes/home.tsx +1 -1
- package/templates/src/components/ui/text.tsx +2 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teardown/cli",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.75",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
},
|
|
77
77
|
"devDependencies": {
|
|
78
78
|
"@biomejs/biome": "2.3.11",
|
|
79
|
-
"@teardown/tsconfig": "2.0.
|
|
79
|
+
"@teardown/tsconfig": "2.0.75",
|
|
80
80
|
"@types/bun": "1.3.5",
|
|
81
81
|
"@types/ejs": "^3.1.5",
|
|
82
82
|
"typescript": "5.9.3"
|
package/src/cli/commands/dev.ts
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
* Dev command - starts the Metro bundler
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import { spawn } from "node:child_process";
|
|
6
5
|
import { existsSync } from "node:fs";
|
|
7
|
-
import { join } from "node:path";
|
|
6
|
+
import { join, resolve } from "node:path";
|
|
8
7
|
import chalk from "chalk";
|
|
9
8
|
import { Command } from "commander";
|
|
9
|
+
import { attachBundlerToForeground, startBundlerBackground } from "../../utils/bundler";
|
|
10
|
+
import { getNavigationConfig } from "../../utils/metro-config";
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Check if a metro.config.js file exists in the project
|
|
@@ -48,39 +49,60 @@ export function createDevCommand(): Command {
|
|
|
48
49
|
console.log(chalk.gray("Tip: Add @teardown/metro-config for 36x faster builds\n"));
|
|
49
50
|
}
|
|
50
51
|
|
|
51
|
-
|
|
52
|
+
// Pre-generate routes if navigation-metro is installed
|
|
53
|
+
const navigationMetroPath = join(projectRoot, "node_modules/@teardown/navigation-metro");
|
|
54
|
+
const navConfig = getNavigationConfig(projectRoot);
|
|
52
55
|
|
|
53
|
-
|
|
56
|
+
if (existsSync(navigationMetroPath) && navConfig) {
|
|
57
|
+
const routesDir = resolve(projectRoot, navConfig.routesDir);
|
|
58
|
+
const generatedDir = resolve(projectRoot, navConfig.generatedDir);
|
|
54
59
|
|
|
55
|
-
|
|
56
|
-
|
|
60
|
+
if (existsSync(routesDir)) {
|
|
61
|
+
try {
|
|
62
|
+
// Dynamic require from user's node_modules
|
|
63
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
64
|
+
const { generateAllRouteFiles } = require(navigationMetroPath) as {
|
|
65
|
+
generateAllRouteFiles: (opts: {
|
|
66
|
+
routesDir: string;
|
|
67
|
+
generatedDir: string;
|
|
68
|
+
prefixes: string[];
|
|
69
|
+
verbose: boolean;
|
|
70
|
+
}) => void;
|
|
71
|
+
};
|
|
72
|
+
generateAllRouteFiles({
|
|
73
|
+
routesDir,
|
|
74
|
+
generatedDir,
|
|
75
|
+
prefixes: [],
|
|
76
|
+
verbose: options.verbose,
|
|
77
|
+
});
|
|
78
|
+
if (options.verbose) {
|
|
79
|
+
console.log(chalk.gray("Generated route types\n"));
|
|
80
|
+
}
|
|
81
|
+
} catch {
|
|
82
|
+
// Ignore - Metro will regenerate
|
|
83
|
+
}
|
|
84
|
+
}
|
|
57
85
|
}
|
|
58
86
|
|
|
59
|
-
|
|
60
|
-
args.push("--verbose");
|
|
61
|
-
}
|
|
87
|
+
console.log(chalk.blue("Starting Metro bundler...\n"));
|
|
62
88
|
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
89
|
+
const metroProcess = startBundlerBackground({
|
|
90
|
+
port: options.port,
|
|
91
|
+
resetCache: options.resetCache,
|
|
92
|
+
verbose: options.verbose,
|
|
66
93
|
cwd: projectRoot,
|
|
67
|
-
env: {
|
|
68
|
-
...process.env,
|
|
69
|
-
// Ensure proper encoding for CocoaPods compatibility
|
|
70
|
-
LANG: "en_US.UTF-8",
|
|
71
|
-
},
|
|
72
94
|
});
|
|
73
95
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
96
|
+
// Handle cleanup on SIGINT/SIGTERM
|
|
97
|
+
const cleanup = () => {
|
|
98
|
+
metroProcess.kill("SIGTERM");
|
|
99
|
+
process.exit(0);
|
|
100
|
+
};
|
|
101
|
+
process.on("SIGINT", cleanup);
|
|
102
|
+
process.on("SIGTERM", cleanup);
|
|
78
103
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
process.exit(code);
|
|
82
|
-
}
|
|
83
|
-
});
|
|
104
|
+
// Attach to foreground with interactive input (r, j, d, etc.)
|
|
105
|
+
attachBundlerToForeground(metroProcess);
|
|
84
106
|
});
|
|
85
107
|
|
|
86
108
|
return dev;
|
package/src/cli/commands/run.ts
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
import { type ChildProcess, exec, spawn } from "node:child_process";
|
|
14
14
|
import { existsSync } from "node:fs";
|
|
15
|
-
import { join } from "node:path";
|
|
15
|
+
import { join, resolve } from "node:path";
|
|
16
16
|
import { createInterface } from "node:readline";
|
|
17
17
|
import { promisify } from "node:util";
|
|
18
18
|
import chalk from "chalk";
|
|
@@ -20,6 +20,7 @@ import { Command } from "commander";
|
|
|
20
20
|
import ora from "ora";
|
|
21
21
|
import { attachBundlerToForeground, startBundlerBackground, waitForBundlerReady } from "../../utils/bundler";
|
|
22
22
|
import { getAppScheme, launchAppWithBundler } from "../../utils/deep-link";
|
|
23
|
+
import { getNavigationConfig } from "../../utils/metro-config";
|
|
23
24
|
|
|
24
25
|
const execAsync = promisify(exec);
|
|
25
26
|
|
|
@@ -336,6 +337,40 @@ export function createRunCommand(): Command {
|
|
|
336
337
|
|
|
337
338
|
// Start Metro bundler FIRST (unless --no-bundler or --release)
|
|
338
339
|
if (options.bundler && !options.release) {
|
|
340
|
+
// Pre-generate routes if navigation-metro is installed
|
|
341
|
+
const projectRoot = process.cwd();
|
|
342
|
+
const navigationMetroPath = join(projectRoot, "node_modules/@teardown/navigation-metro");
|
|
343
|
+
const navConfig = getNavigationConfig(projectRoot);
|
|
344
|
+
|
|
345
|
+
if (existsSync(navigationMetroPath) && navConfig) {
|
|
346
|
+
const routesDir = resolve(projectRoot, navConfig.routesDir);
|
|
347
|
+
const generatedDir = resolve(projectRoot, navConfig.generatedDir);
|
|
348
|
+
|
|
349
|
+
if (existsSync(routesDir)) {
|
|
350
|
+
try {
|
|
351
|
+
// Dynamic require from user's node_modules
|
|
352
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
353
|
+
const { generateAllRouteFiles } = require(navigationMetroPath) as {
|
|
354
|
+
generateAllRouteFiles: (opts: {
|
|
355
|
+
routesDir: string;
|
|
356
|
+
generatedDir: string;
|
|
357
|
+
prefixes: string[];
|
|
358
|
+
verbose: boolean;
|
|
359
|
+
}) => void;
|
|
360
|
+
};
|
|
361
|
+
const slug = getAppScheme(projectRoot) || "app";
|
|
362
|
+
generateAllRouteFiles({
|
|
363
|
+
routesDir,
|
|
364
|
+
generatedDir,
|
|
365
|
+
prefixes: [`${slug}://`],
|
|
366
|
+
verbose: false,
|
|
367
|
+
});
|
|
368
|
+
} catch {
|
|
369
|
+
// Ignore - Metro will regenerate
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
339
374
|
metroProcess = await startMetroAndWait(options.port, platform);
|
|
340
375
|
}
|
|
341
376
|
|
package/src/config/loader.ts
CHANGED
package/src/config/schema.ts
CHANGED
|
@@ -108,6 +108,20 @@ export const PluginEntrySchema = z.union([
|
|
|
108
108
|
z.tuple([z.any()]),
|
|
109
109
|
]);
|
|
110
110
|
|
|
111
|
+
/**
|
|
112
|
+
* Navigation configuration schema
|
|
113
|
+
*/
|
|
114
|
+
export const NavigationConfigSchema = z.object({
|
|
115
|
+
/** Path to routes directory relative to project root */
|
|
116
|
+
routesDir: z.string().optional().default("./src/_routes"),
|
|
117
|
+
|
|
118
|
+
/** Path for generated type files */
|
|
119
|
+
generatedDir: z.string().optional().default("./.teardown"),
|
|
120
|
+
|
|
121
|
+
/** Auto-populate new route files with template content */
|
|
122
|
+
autoTemplate: z.boolean().optional().default(true),
|
|
123
|
+
});
|
|
124
|
+
|
|
111
125
|
/**
|
|
112
126
|
* Main Teardown configuration schema
|
|
113
127
|
*/
|
|
@@ -150,6 +164,9 @@ export const TeardownConfigSchema = z.object({
|
|
|
150
164
|
|
|
151
165
|
/** Environment variables to inject */
|
|
152
166
|
env: z.record(z.string(), z.string()).optional(),
|
|
167
|
+
|
|
168
|
+
/** Navigation configuration */
|
|
169
|
+
navigation: NavigationConfigSchema.optional(),
|
|
153
170
|
});
|
|
154
171
|
|
|
155
172
|
/**
|
|
@@ -241,3 +258,4 @@ export type TeardownConfig = z.infer<typeof TeardownConfigSchema>;
|
|
|
241
258
|
export type iOSConfig = z.infer<typeof iOSConfigSchema>;
|
|
242
259
|
export type AndroidConfig = z.infer<typeof AndroidConfigSchema>;
|
|
243
260
|
export type SplashConfig = z.infer<typeof SplashConfigSchema>;
|
|
261
|
+
export type NavigationConfig = z.infer<typeof NavigationConfigSchema>;
|
package/src/utils/index.ts
CHANGED
|
@@ -41,5 +41,7 @@ export {
|
|
|
41
41
|
formatKeyValue,
|
|
42
42
|
formatList,
|
|
43
43
|
} from "./logger";
|
|
44
|
+
export type { NavigationConfig } from "./metro-config";
|
|
45
|
+
export { getNavigationConfig, parseNavigationConfig } from "./metro-config";
|
|
44
46
|
export type { ReporterStep, StepStatus, TerminalReporterConfig } from "./terminal-reporter";
|
|
45
47
|
export { createReporter, TerminalReporter } from "./terminal-reporter";
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metro Config Parser
|
|
3
|
+
*
|
|
4
|
+
* Extracts navigation configuration from teardown.config.ts or metro.config.js
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Navigation options extracted from config files
|
|
12
|
+
*/
|
|
13
|
+
export interface NavigationConfig {
|
|
14
|
+
routesDir: string;
|
|
15
|
+
generatedDir: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Default navigation configuration
|
|
20
|
+
*/
|
|
21
|
+
const DEFAULT_CONFIG: NavigationConfig = {
|
|
22
|
+
routesDir: "./src/_routes",
|
|
23
|
+
generatedDir: "./.teardown",
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Config file names to search for teardown config (in order of priority)
|
|
28
|
+
*/
|
|
29
|
+
const TEARDOWN_CONFIG_FILES = [
|
|
30
|
+
"teardown.config.ts",
|
|
31
|
+
"teardown.config.js",
|
|
32
|
+
"teardown.config.mjs",
|
|
33
|
+
"launchpad.config.ts",
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Finds metro.config.js in the project
|
|
38
|
+
*/
|
|
39
|
+
function findMetroConfig(projectRoot: string): string | null {
|
|
40
|
+
const configNames = ["metro.config.js", "metro.config.cjs", "metro.config.mjs"];
|
|
41
|
+
|
|
42
|
+
for (const name of configNames) {
|
|
43
|
+
const configPath = join(projectRoot, name);
|
|
44
|
+
if (existsSync(configPath)) {
|
|
45
|
+
return configPath;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Parses metro.config.js to extract withTeardownNavigation options
|
|
54
|
+
*
|
|
55
|
+
* This uses simple regex parsing since we can't safely evaluate the JS file.
|
|
56
|
+
* It looks for patterns like:
|
|
57
|
+
* withTeardownNavigation(config, { routesDir: "./src/_routes", generatedDir: "./.teardown" })
|
|
58
|
+
*/
|
|
59
|
+
export function parseNavigationConfig(projectRoot: string): NavigationConfig | null {
|
|
60
|
+
const configPath = findMetroConfig(projectRoot);
|
|
61
|
+
if (!configPath) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
const content = readFileSync(configPath, "utf-8");
|
|
67
|
+
|
|
68
|
+
// Check if withTeardownNavigation is used
|
|
69
|
+
if (!content.includes("withTeardownNavigation")) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Extract routesDir using regex
|
|
74
|
+
// Matches: routesDir: "./src/_routes" or routesDir: './src/_routes'
|
|
75
|
+
const routesDirMatch = content.match(/routesDir:\s*['"]([^'"]+)['"]/);
|
|
76
|
+
const routesDir = routesDirMatch ? routesDirMatch[1] : DEFAULT_CONFIG.routesDir;
|
|
77
|
+
|
|
78
|
+
// Extract generatedDir using regex
|
|
79
|
+
const generatedDirMatch = content.match(/generatedDir:\s*['"]([^'"]+)['"]/);
|
|
80
|
+
const generatedDir = generatedDirMatch ? generatedDirMatch[1] : DEFAULT_CONFIG.generatedDir;
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
routesDir,
|
|
84
|
+
generatedDir,
|
|
85
|
+
};
|
|
86
|
+
} catch {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Parses teardown.config.ts to extract navigation options
|
|
93
|
+
*
|
|
94
|
+
* This uses simple regex parsing since we can't safely evaluate the TS file at runtime.
|
|
95
|
+
*/
|
|
96
|
+
function parseTeardownConfig(projectRoot: string): NavigationConfig | null {
|
|
97
|
+
for (const fileName of TEARDOWN_CONFIG_FILES) {
|
|
98
|
+
const configPath = join(projectRoot, fileName);
|
|
99
|
+
if (existsSync(configPath)) {
|
|
100
|
+
try {
|
|
101
|
+
const content = readFileSync(configPath, "utf-8");
|
|
102
|
+
|
|
103
|
+
// Check if navigation config exists
|
|
104
|
+
if (!content.includes("navigation:") && !content.includes("navigation :")) {
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Extract routesDir using regex
|
|
109
|
+
const routesDirMatch = content.match(/routesDir:\s*['"]([^'"]+)['"]/);
|
|
110
|
+
const generatedDirMatch = content.match(/generatedDir:\s*['"]([^'"]+)['"]/);
|
|
111
|
+
|
|
112
|
+
// Only return if we found at least one navigation property
|
|
113
|
+
if (routesDirMatch || generatedDirMatch) {
|
|
114
|
+
return {
|
|
115
|
+
routesDir: routesDirMatch?.[1] ?? DEFAULT_CONFIG.routesDir,
|
|
116
|
+
generatedDir: generatedDirMatch?.[1] ?? DEFAULT_CONFIG.generatedDir,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
} catch {
|
|
120
|
+
// Ignore read errors and try next config file
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Gets navigation config for a project, with fallbacks
|
|
129
|
+
*
|
|
130
|
+
* Priority:
|
|
131
|
+
* 1. teardown.config.ts navigation section
|
|
132
|
+
* 2. metro.config.js withTeardownNavigation options
|
|
133
|
+
* 3. Default config if routes directory exists
|
|
134
|
+
*/
|
|
135
|
+
export function getNavigationConfig(projectRoot: string): NavigationConfig | null {
|
|
136
|
+
// Try to parse from teardown.config.ts first (single source of truth)
|
|
137
|
+
const teardownConfig = parseTeardownConfig(projectRoot);
|
|
138
|
+
if (teardownConfig) {
|
|
139
|
+
return teardownConfig;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Fallback: parse from metro.config.js (backwards compatibility)
|
|
143
|
+
const metroConfig = parseNavigationConfig(projectRoot);
|
|
144
|
+
if (metroConfig) {
|
|
145
|
+
return metroConfig;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Fallback: check if default routes dir exists
|
|
149
|
+
const defaultRoutesPath = join(projectRoot, DEFAULT_CONFIG.routesDir);
|
|
150
|
+
if (existsSync(defaultRoutesPath)) {
|
|
151
|
+
return DEFAULT_CONFIG;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Auto-generated by @teardown/navigation
|
|
2
|
+
import type { LinkingOptions } from "@react-navigation/native";
|
|
3
|
+
import type { RouteParams } from "./routes.generated";
|
|
4
|
+
|
|
5
|
+
export const generatedLinkingConfig: LinkingOptions<RouteParams>["config"] = {
|
|
6
|
+
screens: {
|
|
7
|
+
"/home": "home",
|
|
8
|
+
},
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const defaultPrefixes: string[] = ["app://"];
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"generatedAt": "2026-01-31T19:48:52.201Z",
|
|
3
|
+
"routeCount": 1,
|
|
4
|
+
"routes": [
|
|
5
|
+
{
|
|
6
|
+
"path": "",
|
|
7
|
+
"file": "_layout.tsx",
|
|
8
|
+
"params": [],
|
|
9
|
+
"layoutType": "stack"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"path": "/home",
|
|
13
|
+
"file": "home.tsx",
|
|
14
|
+
"params": [],
|
|
15
|
+
"layoutType": "none"
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
|
|
4
|
+
// Auto-generated by @teardown/navigation
|
|
5
|
+
// Do not edit this file directly
|
|
6
|
+
// Generated at: 2026-01-31T19:48:52.202Z
|
|
7
|
+
|
|
8
|
+
import type { NavigatorNode } from "@teardown/navigation";
|
|
9
|
+
|
|
10
|
+
import layout from "../src/_routes/_layout";
|
|
11
|
+
import home from "../src/_routes/home";
|
|
12
|
+
|
|
13
|
+
export const routeTree: NavigatorNode =
|
|
14
|
+
{
|
|
15
|
+
type: "stack",
|
|
16
|
+
layout: layout,
|
|
17
|
+
screens: {
|
|
18
|
+
"home": {
|
|
19
|
+
screen: home,
|
|
20
|
+
path: "/home",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// Flat screens export for backwards compatibility
|
|
26
|
+
export const screens = {
|
|
27
|
+
"/home": home,
|
|
28
|
+
} as const;
|
|
29
|
+
|
|
30
|
+
export const layouts = {
|
|
31
|
+
"src__routes": layout,
|
|
32
|
+
} as const;
|
|
33
|
+
|
|
34
|
+
export type Screens = typeof screens;
|
|
35
|
+
export type Layouts = typeof layouts;
|
|
36
|
+
export type RouteTreeType = typeof routeTree;
|
|
37
|
+
|
|
38
|
+
export const routePaths = [
|
|
39
|
+
"/home",
|
|
40
|
+
] as const;
|
|
41
|
+
|
|
42
|
+
export type RoutePath = (typeof routePaths)[number];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Auto-generated by @teardown/navigation
|
|
2
|
+
// Do not edit this file directly
|
|
3
|
+
// Generated at: 2026-01-31T19:48:52.201Z
|
|
4
|
+
|
|
5
|
+
export interface RouteParams {
|
|
6
|
+
"/home": undefined;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type RoutePath = keyof RouteParams;
|
|
10
|
+
|
|
11
|
+
export type ParamsFor<T extends RoutePath> = RouteParams[T];
|
|
12
|
+
|
|
13
|
+
export type RouteWithParams = {
|
|
14
|
+
[K in RoutePath]: RouteParams[K] extends undefined
|
|
15
|
+
? { path: K }
|
|
16
|
+
: { path: K; params: RouteParams[K] };
|
|
17
|
+
}[RoutePath];
|
|
18
|
+
|
|
19
|
+
export type NavigatorType = "stack" | "tabs" | "drawer";
|
|
@@ -11,12 +11,11 @@ const { getDefaultConfig, mergeConfig } = require("@react-native/metro-config");
|
|
|
11
11
|
* - Monorepo/workspace detection and watch folder configuration
|
|
12
12
|
* - Bun-specific handling (.bun directory blocking)
|
|
13
13
|
*
|
|
14
|
-
*
|
|
15
14
|
* withTeardownNavigation() automatically handles:
|
|
16
15
|
* - Type-safe route generation from file-based routes
|
|
17
16
|
* - Deep linking configuration generation
|
|
18
17
|
* - Hot-reload support via file watching in development
|
|
19
|
-
*
|
|
18
|
+
* - Reads routesDir/generatedDir from teardown.config.ts navigation section
|
|
20
19
|
*
|
|
21
20
|
* withUniwindConfig() enables:
|
|
22
21
|
* - Tailwind CSS 4 support for React Native
|
|
@@ -29,11 +28,8 @@ const config = {};
|
|
|
29
28
|
|
|
30
29
|
const teardownConfig = withTeardown(mergeConfig(getDefaultConfig(__dirname), config));
|
|
31
30
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
generatedDir: "./.teardown",
|
|
35
|
-
verbose: false,
|
|
36
|
-
});
|
|
31
|
+
// Navigation config is read from teardown.config.ts navigation section
|
|
32
|
+
const navigationConfig = withTeardownNavigation(teardownConfig);
|
|
37
33
|
|
|
38
34
|
module.exports = withUniwindConfig(navigationConfig, {
|
|
39
35
|
cssEntryFile: "./src/global.css",
|
|
@@ -51,7 +51,7 @@ function HomeScreen() {
|
|
|
51
51
|
<Card.Title>Getting Started</Card.Title>
|
|
52
52
|
<Card.Description>
|
|
53
53
|
1. Explore the components in src/components/ui/{"\n"}
|
|
54
|
-
2. Add new routes in src/
|
|
54
|
+
2. Add new routes in src/_routes/{"\n"}
|
|
55
55
|
3. Customize the theme in global.css{"\n"}
|
|
56
56
|
4. Build your app!
|
|
57
57
|
</Card.Description>
|
|
@@ -97,17 +97,13 @@ const Text = (props: TextProps) => {
|
|
|
97
97
|
invert: invert,
|
|
98
98
|
}),
|
|
99
99
|
textClassName,
|
|
100
|
-
className
|
|
100
|
+
className
|
|
101
101
|
);
|
|
102
102
|
}, [variant, color, invert, textClassName, className]);
|
|
103
103
|
|
|
104
104
|
return (
|
|
105
105
|
<TextClassContext.Provider value={classNames}>
|
|
106
|
-
<Animated.Text
|
|
107
|
-
{...otherProps}
|
|
108
|
-
className={classNames}
|
|
109
|
-
allowFontScaling={false}
|
|
110
|
-
/>
|
|
106
|
+
<Animated.Text {...otherProps} className={classNames} allowFontScaling={false} />
|
|
111
107
|
</TextClassContext.Provider>
|
|
112
108
|
);
|
|
113
109
|
};
|