mapples 0.2.0-beta.1 → 0.2.0-beta.3
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/README.md +70 -22
- package/dist/adopt/scan.d.ts +8 -2
- package/dist/adopt/scan.js +31 -13
- package/dist/adopt/scan.js.map +1 -1
- package/dist/api/client.d.ts +9 -1
- package/dist/api/client.js +21 -2
- package/dist/api/client.js.map +1 -1
- package/dist/api/commit.d.ts +9 -0
- package/dist/api/commit.js +32 -2
- package/dist/api/commit.js.map +1 -1
- package/dist/api/errors.js +8 -0
- package/dist/api/errors.js.map +1 -1
- package/dist/api/objects.d.ts +22 -5
- package/dist/api/objects.js +151 -10
- package/dist/api/objects.js.map +1 -1
- package/dist/api/poll.d.ts +5 -3
- package/dist/api/poll.js +17 -6
- package/dist/api/poll.js.map +1 -1
- package/dist/assets/assets.d.ts +9 -0
- package/dist/assets/assets.js +33 -4
- package/dist/assets/assets.js.map +1 -1
- package/dist/codegen/emit.d.ts +27 -1
- package/dist/codegen/emit.js +130 -9
- package/dist/codegen/emit.js.map +1 -1
- package/dist/codegen/imports.d.ts +2 -0
- package/dist/codegen/imports.js +38 -0
- package/dist/codegen/imports.js.map +1 -1
- package/dist/codegen/instances.d.ts +16 -0
- package/dist/codegen/instances.js +141 -0
- package/dist/codegen/instances.js.map +1 -0
- package/dist/codegen/styles.d.ts +11 -0
- package/dist/codegen/styles.js +131 -0
- package/dist/codegen/styles.js.map +1 -0
- package/dist/commands/impl/createImpl.js +8 -4
- package/dist/commands/impl/createImpl.js.map +1 -1
- package/dist/commands/impl/initImpl.js +5 -4
- package/dist/commands/impl/initImpl.js.map +1 -1
- package/dist/commands/impl/syncImpl.js +20 -2
- package/dist/commands/impl/syncImpl.js.map +1 -1
- package/dist/merge/applyOps.d.ts +1 -1
- package/dist/merge/applyOps.js +33 -2
- package/dist/merge/applyOps.js.map +1 -1
- package/dist/merge/diff.d.ts +1 -1
- package/dist/merge/diff.js +30 -17
- package/dist/merge/diff.js.map +1 -1
- package/dist/merge/threeWay.d.ts +1 -1
- package/dist/merge/threeWay.js +38 -6
- package/dist/merge/threeWay.js.map +1 -1
- package/dist/merge/toEdits.d.ts +1 -1
- package/dist/merge/toEdits.js +4 -1
- package/dist/merge/toEdits.js.map +1 -1
- package/dist/nav/navigatorTree.d.ts +78 -0
- package/dist/nav/navigatorTree.js +410 -0
- package/dist/nav/navigatorTree.js.map +1 -0
- package/dist/nav/placement.d.ts +53 -0
- package/dist/nav/placement.js +260 -0
- package/dist/nav/placement.js.map +1 -0
- package/dist/nav/routeTree.d.ts +8 -2
- package/dist/nav/routeTree.js +79 -151
- package/dist/nav/routeTree.js.map +1 -1
- package/dist/nav/screenOptions.d.ts +15 -0
- package/dist/nav/screenOptions.js +213 -0
- package/dist/nav/screenOptions.js.map +1 -0
- package/dist/project/baseStore.d.ts +8 -0
- package/dist/project/baseStore.js +15 -0
- package/dist/project/baseStore.js.map +1 -1
- package/dist/project/componentsMap.d.ts +7 -0
- package/dist/project/componentsMap.js +21 -0
- package/dist/project/componentsMap.js.map +1 -0
- package/dist/project/config.d.ts +12 -3
- package/dist/project/config.js +11 -2
- package/dist/project/config.js.map +1 -1
- package/dist/project/env.d.ts +10 -3
- package/dist/project/env.js +23 -5
- package/dist/project/env.js.map +1 -1
- package/dist/project/pagesMap.d.ts +2 -0
- package/dist/project/pagesMap.js.map +1 -1
- package/dist/services/adoptService.d.ts +3 -0
- package/dist/services/adoptService.js +346 -38
- package/dist/services/adoptService.js.map +1 -1
- package/dist/services/clientFactory.js +4 -2
- package/dist/services/clientFactory.js.map +1 -1
- package/dist/services/doctorService.js +77 -66
- package/dist/services/doctorService.js.map +1 -1
- package/dist/services/syncEngine.d.ts +7 -0
- package/dist/services/syncEngine.js +428 -292
- package/dist/services/syncEngine.js.map +1 -1
- package/dist/types.d.ts +21 -1
- package/dist/types.js +22 -0
- package/dist/types.js.map +1 -1
- package/package.json +2 -2
- package/templates/app/_layout.tsx +3 -0
- package/templates/mapples/sid.d.ts +6 -0
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
// Page file placement: a page's code lives at the route file expo-router
|
|
2
|
+
// expects (`<routesDir>/<segment>.tsx`) while it is in the navigation, and
|
|
3
|
+
// under `<pagesDir>/<Name>.tsx` while it is not. This module decides where
|
|
4
|
+
// every page file belongs for the current navigation plan and MOVES files to
|
|
5
|
+
// match — content is never regenerated here, only relocated (P0: no user
|
|
6
|
+
// file is overwritten or deleted; a stale generated re-export wrapper from the
|
|
7
|
+
// pre-0.2 split layout is the one file removed, and only when it is pristine).
|
|
8
|
+
//
|
|
9
|
+
// Route identity for a file is its marker line (`// mapples-route: <id>`):
|
|
10
|
+
// renaming a routed file locally keeps the marker, so the rename is detected
|
|
11
|
+
// and pushed to Creator as a route rename; a Creator rename moves the file.
|
|
12
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmdirSync, unlinkSync, writeFileSync, } from 'node:fs';
|
|
13
|
+
import { basename, dirname, join, relative, sep } from 'node:path';
|
|
14
|
+
import { pageComponentName, readRouteMarker, withRouteMarker, withoutRouteMarker, } from '../codegen/emit.js';
|
|
15
|
+
import { deprecateFile } from '../merge/deprecate.js';
|
|
16
|
+
export function makePlan(routes) {
|
|
17
|
+
return { routes, byRouteId: new Map(routes.map((r) => [r.routeId, r])) };
|
|
18
|
+
}
|
|
19
|
+
/** expo-router public path for a file position: `(group)` segments vanish, `index` is the dir itself. */
|
|
20
|
+
export function publicPath(dir, segment) {
|
|
21
|
+
const parts = dir.split(sep).filter((p) => p !== '' && !/^\(.*\)$/.test(p));
|
|
22
|
+
if (segment !== 'index')
|
|
23
|
+
parts.push(segment);
|
|
24
|
+
return `/${parts.join('/')}`;
|
|
25
|
+
}
|
|
26
|
+
/** routeId -> file relative to `dir`, for every `.tsx` under it carrying a route marker. */
|
|
27
|
+
export function scanRouteFiles(dir) {
|
|
28
|
+
const found = new Map();
|
|
29
|
+
if (!existsSync(dir))
|
|
30
|
+
return found;
|
|
31
|
+
const walk = (rel) => {
|
|
32
|
+
for (const entry of readdirSync(join(dir, rel), { withFileTypes: true })) {
|
|
33
|
+
const relPath = rel ? join(rel, entry.name) : entry.name;
|
|
34
|
+
if (entry.isDirectory()) {
|
|
35
|
+
if (entry.name === 'node_modules' || entry.name.startsWith('.'))
|
|
36
|
+
continue;
|
|
37
|
+
walk(relPath);
|
|
38
|
+
}
|
|
39
|
+
else if (entry.name.endsWith('.tsx') &&
|
|
40
|
+
entry.name !== '_layout.tsx' &&
|
|
41
|
+
!entry.name.startsWith('_depr_')) {
|
|
42
|
+
const id = readRouteMarker(readFileSync(join(dir, relPath), 'utf8'));
|
|
43
|
+
if (id)
|
|
44
|
+
found.set(id, relPath);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
walk('');
|
|
49
|
+
return found;
|
|
50
|
+
}
|
|
51
|
+
/** A pre-0.2 route wrapper: nothing but comments and one `export { default } from '…'`. */
|
|
52
|
+
export function isReexportWrapper(source) {
|
|
53
|
+
let exports = 0;
|
|
54
|
+
for (const raw of source.split('\n')) {
|
|
55
|
+
const line = raw.trim();
|
|
56
|
+
if (line === '' || line.startsWith('//'))
|
|
57
|
+
continue;
|
|
58
|
+
if (/^export\s*\{\s*default\s*\}\s*from\s*['"][^'"]+['"];?$/.test(line)) {
|
|
59
|
+
exports += 1;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
return exports === 1;
|
|
65
|
+
}
|
|
66
|
+
const MAPPLET_EXPORT = /export default function ([A-Za-z0-9_]+)Mapplet\(/;
|
|
67
|
+
function isUnder(file, dir) {
|
|
68
|
+
const rel = relative(dir, file);
|
|
69
|
+
return rel !== '' && !rel.startsWith('..') && !rel.startsWith(sep);
|
|
70
|
+
}
|
|
71
|
+
export function pruneEmptyDirs(rootDir, rel) {
|
|
72
|
+
let cursor = rel;
|
|
73
|
+
while (cursor && cursor !== '.') {
|
|
74
|
+
const abs = join(rootDir, cursor);
|
|
75
|
+
if (!existsSync(abs) || readdirSync(abs).length > 0)
|
|
76
|
+
return;
|
|
77
|
+
rmdirSync(abs);
|
|
78
|
+
cursor = dirname(cursor);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/** `<dir>/<Name>.tsx`, suffixed until it is free of `used`. */
|
|
82
|
+
export function mintEntityFile(dir, name, used) {
|
|
83
|
+
const baseName = pageComponentName(name);
|
|
84
|
+
let file = join(dir, `${baseName}.tsx`);
|
|
85
|
+
let counter = 2;
|
|
86
|
+
while (used.has(file)) {
|
|
87
|
+
file = join(dir, `${baseName}${counter}.tsx`);
|
|
88
|
+
counter += 1;
|
|
89
|
+
}
|
|
90
|
+
return file;
|
|
91
|
+
}
|
|
92
|
+
export function placePages(input) {
|
|
93
|
+
const { root, routesDir, pagesDir, pages, pagesMap, plan, basePlan, report } = input;
|
|
94
|
+
const routesAbs = join(root, routesDir);
|
|
95
|
+
const localFiles = scanRouteFiles(routesAbs);
|
|
96
|
+
const renames = [];
|
|
97
|
+
// ---- local renames: 3-way on the file segment, per route id ----
|
|
98
|
+
for (const route of plan.routes) {
|
|
99
|
+
const baseFile = basePlan?.byRouteId.get(route.routeId)?.file ?? null;
|
|
100
|
+
const localFile = localFiles.get(route.routeId) ?? null;
|
|
101
|
+
if (!localFile || !baseFile || localFile === baseFile)
|
|
102
|
+
continue;
|
|
103
|
+
const localSegment = basename(localFile, '.tsx');
|
|
104
|
+
const remoteChanged = route.file !== baseFile;
|
|
105
|
+
if (remoteChanged && route.file !== localFile) {
|
|
106
|
+
// Renamed on both sides: Creator wins for the name; the file (and every
|
|
107
|
+
// edit in it) moves to the Creator position below — nothing is lost.
|
|
108
|
+
report.conflicts.push({
|
|
109
|
+
file: join(routesDir, localFile),
|
|
110
|
+
sid: route.routeId,
|
|
111
|
+
reason: 'same-prop',
|
|
112
|
+
props: ['name'],
|
|
113
|
+
localValue: localSegment,
|
|
114
|
+
remoteValue: route.segment,
|
|
115
|
+
detail: `route renamed on both sides (${localSegment} vs ${route.segment}) — Creator's name kept, your edits kept`,
|
|
116
|
+
});
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (!remoteChanged) {
|
|
120
|
+
if (localSegment === route.segment) {
|
|
121
|
+
// Same segment, different directory: the file sits where its route is
|
|
122
|
+
// not (a route parked in another navigator). That is a placement
|
|
123
|
+
// mismatch, not a rename — pushing the unchanged name moved HEAD on
|
|
124
|
+
// every sync without changing anything.
|
|
125
|
+
report.notes.push(`${join(routesDir, localFile)} keeps its route “${route.segment}” in navigator ${route.navigatorId ?? '(root)'} — move the route in Creator to relocate it`);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
// Local-only rename: the file stays where the user put it; push the name.
|
|
129
|
+
renames.push({ route, oldSegment: route.segment, newSegment: localSegment });
|
|
130
|
+
route.segment = localSegment;
|
|
131
|
+
route.file = localFile;
|
|
132
|
+
route.dir = dirname(localFile) === '.' ? '' : dirname(localFile);
|
|
133
|
+
route.routePath = publicPath(route.dir, route.segment);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// ---- routed pages: the page file IS the route file ----
|
|
137
|
+
const used = new Set(Object.values(pagesMap).map((m) => m.file));
|
|
138
|
+
for (const route of plan.routes)
|
|
139
|
+
used.add(join(routesDir, route.file));
|
|
140
|
+
const routedPages = new Set();
|
|
141
|
+
for (const route of plan.routes) {
|
|
142
|
+
const page = pages.get(route.pageId);
|
|
143
|
+
if (!page)
|
|
144
|
+
continue;
|
|
145
|
+
routedPages.add(route.pageId);
|
|
146
|
+
const target = join(routesDir, route.file);
|
|
147
|
+
const mapping = pagesMap[route.pageId];
|
|
148
|
+
let current = mapping && existsSync(join(root, mapping.file)) && mapping.file !== target
|
|
149
|
+
? mapping.file
|
|
150
|
+
: existsSync(join(root, target))
|
|
151
|
+
? target
|
|
152
|
+
: null;
|
|
153
|
+
const markerRel = localFiles.get(route.routeId);
|
|
154
|
+
const markerFile = markerRel ? join(routesDir, markerRel) : null;
|
|
155
|
+
let migrated = false;
|
|
156
|
+
if (markerFile && markerFile !== current) {
|
|
157
|
+
const markerSource = readFileSync(join(root, markerFile), 'utf8');
|
|
158
|
+
if (current && isReexportWrapper(markerSource)) {
|
|
159
|
+
// Pre-0.2 split layout: a generated wrapper re-exported the page
|
|
160
|
+
// module. The page file takes the wrapper's place; a pristine
|
|
161
|
+
// wrapper holds nothing of the user's and is removed.
|
|
162
|
+
unlinkSync(join(root, markerFile));
|
|
163
|
+
migrated = true;
|
|
164
|
+
}
|
|
165
|
+
else if (!current) {
|
|
166
|
+
current = markerFile; // the user's file carries the marker: it is the page file
|
|
167
|
+
}
|
|
168
|
+
else if (markerFile === target) {
|
|
169
|
+
const deprecated = relative(root, deprecateFile(join(root, markerFile)));
|
|
170
|
+
report.files.push({
|
|
171
|
+
file: markerFile,
|
|
172
|
+
action: 'deprecated',
|
|
173
|
+
detail: `a second file claimed route ${route.routeId}; kept at ${deprecated}`,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
report.notes.push(`${markerFile} carries the marker of route ${route.routeId}, which ${mapping.file} already renders — left untouched`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (current && current !== target) {
|
|
181
|
+
const targetAbs = join(root, target);
|
|
182
|
+
if (existsSync(targetAbs)) {
|
|
183
|
+
const deprecated = relative(root, deprecateFile(targetAbs));
|
|
184
|
+
report.files.push({
|
|
185
|
+
file: target,
|
|
186
|
+
action: 'deprecated',
|
|
187
|
+
detail: `in the way of page “${page.name}”; kept at ${deprecated}`,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
mkdirSync(dirname(targetAbs), { recursive: true });
|
|
191
|
+
renameSync(join(root, current), targetAbs);
|
|
192
|
+
pruneEmptyDirs(root, dirname(current));
|
|
193
|
+
report.files.push({
|
|
194
|
+
file: target,
|
|
195
|
+
action: 'updated',
|
|
196
|
+
detail: migrated
|
|
197
|
+
? `page code moved in from ${current} (route wrapper folded into this file)`
|
|
198
|
+
: `moved from ${current}`,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
const targetAbs = join(root, target);
|
|
202
|
+
if (existsSync(targetAbs)) {
|
|
203
|
+
const source = readFileSync(targetAbs, 'utf8');
|
|
204
|
+
let next = withRouteMarker(source, route.routeId, route.routeName);
|
|
205
|
+
if (migrated)
|
|
206
|
+
next = next.replace(MAPPLET_EXPORT, 'export default function $1(');
|
|
207
|
+
if (next !== source)
|
|
208
|
+
writeFileSync(targetAbs, next);
|
|
209
|
+
}
|
|
210
|
+
pagesMap[route.pageId] = {
|
|
211
|
+
file: target,
|
|
212
|
+
name: page.name,
|
|
213
|
+
route: route.routePath,
|
|
214
|
+
routeId: route.routeId,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
// ---- pages outside the navigation: <pagesDir>/<Name>.tsx ----
|
|
218
|
+
for (const [pageId, page] of pages) {
|
|
219
|
+
if (routedPages.has(pageId))
|
|
220
|
+
continue;
|
|
221
|
+
const mapping = pagesMap[pageId];
|
|
222
|
+
const current = mapping && existsSync(join(root, mapping.file)) ? mapping.file : null;
|
|
223
|
+
let target;
|
|
224
|
+
if (current) {
|
|
225
|
+
const source = readFileSync(join(root, current), 'utf8');
|
|
226
|
+
if (isUnder(current, routesDir) && readRouteMarker(source) !== null) {
|
|
227
|
+
// Its route is gone: the file leaves the router tree (content kept).
|
|
228
|
+
target = mintEntityFile(pagesDir, page.name, used);
|
|
229
|
+
used.add(target);
|
|
230
|
+
mkdirSync(join(root, dirname(target)), { recursive: true });
|
|
231
|
+
renameSync(join(root, current), join(root, target));
|
|
232
|
+
pruneEmptyDirs(root, dirname(current));
|
|
233
|
+
writeFileSync(join(root, target), withoutRouteMarker(source));
|
|
234
|
+
report.files.push({
|
|
235
|
+
file: target,
|
|
236
|
+
action: 'updated',
|
|
237
|
+
detail: `no longer in the navigation — moved out of ${routesDir} (was ${current})`,
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
target = current;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
target = mapping?.file ?? mintEntityFile(pagesDir, page.name, used);
|
|
246
|
+
used.add(target);
|
|
247
|
+
}
|
|
248
|
+
pagesMap[pageId] = { file: target, name: page.name, route: page.route };
|
|
249
|
+
}
|
|
250
|
+
// ---- marker files nobody renders any more ----
|
|
251
|
+
const claimed = new Set(Object.values(pagesMap).map((m) => m.file));
|
|
252
|
+
for (const [routeId, rel] of localFiles) {
|
|
253
|
+
const file = join(routesDir, rel);
|
|
254
|
+
if (plan.byRouteId.has(routeId) || claimed.has(file) || !existsSync(join(root, file)))
|
|
255
|
+
continue;
|
|
256
|
+
report.notes.push(`${file} carries the marker of route ${routeId}, which no page renders any more — left untouched`);
|
|
257
|
+
}
|
|
258
|
+
return { renames };
|
|
259
|
+
}
|
|
260
|
+
//# sourceMappingURL=placement.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"placement.js","sourceRoot":"","sources":["../../src/nav/placement.ts"],"names":[],"mappings":"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"}
|
package/dist/nav/routeTree.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { NavigationDocument } from '../api/objects.js';
|
|
1
|
+
import type { NavigationDocument, PageEntity } from '../api/objects.js';
|
|
2
2
|
import type { PagesMap } from '../project/pagesMap.js';
|
|
3
3
|
import type { JpatchOp } from '../types.js';
|
|
4
4
|
import type { SyncReport } from '../ui/report.js';
|
|
@@ -8,4 +8,10 @@ export interface NavSyncResult {
|
|
|
8
8
|
pushOps: JpatchOp[];
|
|
9
9
|
mergedNavigation: NavigationDocument | null;
|
|
10
10
|
}
|
|
11
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Place every page file for the navigation (routed pages under routesDir,
|
|
13
|
+
* the rest under pagesDir), regenerate the CLI-owned layout, and push local
|
|
14
|
+
* file renames back as route path changes. Runs BEFORE the page merge so the
|
|
15
|
+
* merge reads and writes each page at its final location.
|
|
16
|
+
*/
|
|
17
|
+
export declare function syncNavigation(root: string, routesDir: string, pagesDir: string, pages: Map<string, PageEntity>, pagesMap: PagesMap, base: NavigationDocument | null, remote: NavigationDocument | null, report: SyncReport): NavSyncResult;
|
package/dist/nav/routeTree.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
// NavigationDocument
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
|
|
1
|
+
// Flat NavigationDocument ({routes: [{id, name, path, pageId}]}) <-> route
|
|
2
|
+
// files — the mock-server / pre-navigator contract; Creator navigator
|
|
3
|
+
// documents go through navigatorTree.ts. Same discipline: the layout is
|
|
4
|
+
// CLI-OWNED (regenerated every sync); page files ARE the route files and
|
|
5
|
+
// follow route paths (nav/placement.ts) — renaming one locally pushes the new
|
|
6
|
+
// path, a Creator rename moves it, content preserved either way.
|
|
7
|
+
import { basename, dirname, sep } from 'node:path';
|
|
8
|
+
import { extractNavigatorDoc, syncNavigatorTree, writeOwnedLayout } from './navigatorTree.js';
|
|
9
|
+
import { makePlan, placePages } from './placement.js';
|
|
9
10
|
export function routePathToFile(routePath) {
|
|
10
11
|
const clean = routePath.replace(/^\/+/, '').replace(/\/+$/, '');
|
|
11
12
|
return clean === '' ? 'index.tsx' : `${clean}.tsx`;
|
|
@@ -17,14 +18,6 @@ export function fileToRoutePath(relFile) {
|
|
|
17
18
|
.join('/');
|
|
18
19
|
return noExt === 'index' ? '/' : `/${noExt}`;
|
|
19
20
|
}
|
|
20
|
-
function wrapperContent(routeId, routeName, importTarget) {
|
|
21
|
-
return [
|
|
22
|
-
`// mapples-route: ${routeId} — "${routeName}". Created once by Mapples; edit freely.`,
|
|
23
|
-
'// Renaming this file renames the route in Creator on the next `mapples sync`.',
|
|
24
|
-
`export { default } from '${importTarget}';`,
|
|
25
|
-
'',
|
|
26
|
-
].join('\n');
|
|
27
|
-
}
|
|
28
21
|
function layoutContent() {
|
|
29
22
|
return [
|
|
30
23
|
'// GENERATED by Mapples — DO NOT EDIT. This layout is owned by the CLI;',
|
|
@@ -37,146 +30,81 @@ function layoutContent() {
|
|
|
37
30
|
'',
|
|
38
31
|
].join('\n');
|
|
39
32
|
}
|
|
40
|
-
function
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const walk = (rel) => {
|
|
47
|
-
for (const entry of readdirSync(join(dir, rel), { withFileTypes: true })) {
|
|
48
|
-
const relPath = rel ? join(rel, entry.name) : entry.name;
|
|
49
|
-
if (entry.isDirectory())
|
|
50
|
-
walk(relPath);
|
|
51
|
-
else if (entry.name.endsWith('.tsx') &&
|
|
52
|
-
entry.name !== '_layout.tsx' &&
|
|
53
|
-
!entry.name.startsWith('_depr_')) {
|
|
54
|
-
const match = ROUTE_MARKER.exec(readFileSync(join(dir, relPath), 'utf8'));
|
|
55
|
-
if (match?.[1])
|
|
56
|
-
found.set(match[1], relPath);
|
|
57
|
-
}
|
|
33
|
+
function planFlat(routes, pages, notes) {
|
|
34
|
+
const planned = [];
|
|
35
|
+
for (const route of routes) {
|
|
36
|
+
if (!route.pageId || !pages.has(route.pageId)) {
|
|
37
|
+
notes.push(`route ${route.id} (${route.path}) has no synced page — skipped`);
|
|
38
|
+
continue;
|
|
58
39
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const anyRoutes = baseRoutes.size > 0 || remoteRoutes.size > 0 || localFiles.size > 0;
|
|
71
|
-
if (!anyRoutes)
|
|
72
|
-
return { pushOps: [], mergedNavigation: remote ?? base };
|
|
73
|
-
// Layout: CLI-owned, always regenerated.
|
|
74
|
-
mkdirSync(dir, { recursive: true });
|
|
75
|
-
const layoutPath = join(dir, '_layout.tsx');
|
|
76
|
-
const layout = layoutContent();
|
|
77
|
-
if (!existsSync(layoutPath) || readFileSync(layoutPath, 'utf8') !== layout) {
|
|
78
|
-
writeFileSync(layoutPath, layout);
|
|
79
|
-
report.files.push({
|
|
80
|
-
file: join(routesDir, '_layout.tsx'),
|
|
81
|
-
action: 'updated',
|
|
82
|
-
detail: 'CLI-owned layout',
|
|
40
|
+
const file = routePathToFile(route.path);
|
|
41
|
+
const dir = dirname(file);
|
|
42
|
+
planned.push({
|
|
43
|
+
routeId: route.id,
|
|
44
|
+
pageId: route.pageId,
|
|
45
|
+
navigatorId: null,
|
|
46
|
+
dir: dir === '.' ? '' : dir,
|
|
47
|
+
segment: basename(file, '.tsx'),
|
|
48
|
+
file,
|
|
49
|
+
routeName: route.name,
|
|
50
|
+
routePath: route.path,
|
|
83
51
|
});
|
|
84
52
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
sid: id,
|
|
99
|
-
reason: 'same-prop',
|
|
100
|
-
props: ['path'],
|
|
101
|
-
localValue: localPath,
|
|
102
|
-
remoteValue: remotePath,
|
|
103
|
-
detail: `route renamed on both sides (${localPath} vs ${remotePath})`,
|
|
104
|
-
});
|
|
105
|
-
const deprecated = relative(root, deprecateFile(join(dir, localFile)));
|
|
106
|
-
report.files.push({
|
|
107
|
-
file: join(routesDir, localFile),
|
|
108
|
-
action: 'deprecated',
|
|
109
|
-
detail: `kept at ${deprecated}`,
|
|
110
|
-
});
|
|
111
|
-
localFiles.delete(id);
|
|
112
|
-
}
|
|
113
|
-
else if (localChanged && (!remoteChanged || localPath === remotePath)) {
|
|
114
|
-
finalPath = localPath;
|
|
115
|
-
if (localPath !== remotePath) {
|
|
116
|
-
pushOps.push({ op: 'update', entity: 'NavigationRoute', id, patch: { path: localPath } });
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
const targetFile = routePathToFile(finalPath);
|
|
120
|
-
const targetAbs = join(dir, targetFile);
|
|
121
|
-
const pageMapping = remoteRoute.pageId ? pagesMap[remoteRoute.pageId] : undefined;
|
|
122
|
-
const importTarget = pageMapping
|
|
123
|
-
? posix.join(...relative(dirname(targetAbs), join(root, pageMapping.file.replace(/\.tsx$/, ''))).split(sep))
|
|
124
|
-
: null;
|
|
125
|
-
const currentFile = localFiles.get(id);
|
|
126
|
-
if (currentFile && currentFile !== targetFile) {
|
|
127
|
-
// Wrapper exists elsewhere: RENAME it (create-once — content is the user's).
|
|
128
|
-
mkdirSync(dirname(targetAbs), { recursive: true });
|
|
129
|
-
renameSync(join(dir, currentFile), targetAbs);
|
|
130
|
-
report.files.push({
|
|
131
|
-
file: join(routesDir, targetFile),
|
|
132
|
-
action: 'updated',
|
|
133
|
-
detail: `route moved from ${fileToRoutePath(currentFile)} to ${finalPath}`,
|
|
134
|
-
});
|
|
135
|
-
pruneEmptyDirs(dir, dirname(currentFile));
|
|
136
|
-
}
|
|
137
|
-
else if (!currentFile && !existsSync(targetAbs)) {
|
|
138
|
-
if (!importTarget) {
|
|
139
|
-
report.notes.push(`route ${id} (${finalPath}) has no page mapping — wrapper not created`);
|
|
140
|
-
}
|
|
141
|
-
else {
|
|
142
|
-
mkdirSync(dirname(targetAbs), { recursive: true });
|
|
143
|
-
writeFileSync(targetAbs, wrapperContent(id, remoteRoute.name, importTarget.startsWith('.') ? importTarget : `./${importTarget}`));
|
|
144
|
-
report.files.push({ file: join(routesDir, targetFile), action: 'created' });
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
mergedRoutes.push({ ...remoteRoute, path: finalPath });
|
|
53
|
+
return makePlan(planned);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Place every page file for the navigation (routed pages under routesDir,
|
|
57
|
+
* the rest under pagesDir), regenerate the CLI-owned layout, and push local
|
|
58
|
+
* file renames back as route path changes. Runs BEFORE the page merge so the
|
|
59
|
+
* merge reads and writes each page at its final location.
|
|
60
|
+
*/
|
|
61
|
+
export function syncNavigation(root, routesDir, pagesDir, pages, pagesMap, base, remote, report) {
|
|
62
|
+
// Creator navigator documents get the expo-router tree codegen; the flat
|
|
63
|
+
// {routes: [...]} shape below is the legacy/mock contract.
|
|
64
|
+
if (extractNavigatorDoc(remote ?? base)) {
|
|
65
|
+
return syncNavigatorTree(root, routesDir, pagesDir, pages, pagesMap, base, remote, report);
|
|
148
66
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
67
|
+
const remoteRoutes = remote?.routes ?? [];
|
|
68
|
+
const baseRoutes = base?.routes ?? [];
|
|
69
|
+
const notes = [];
|
|
70
|
+
const plan = planFlat(remoteRoutes, pages, notes);
|
|
71
|
+
const basePlan = baseRoutes.length > 0 ? planFlat(baseRoutes, pages, []) : null;
|
|
72
|
+
const { renames } = placePages({
|
|
73
|
+
root,
|
|
74
|
+
routesDir,
|
|
75
|
+
pagesDir,
|
|
76
|
+
pages,
|
|
77
|
+
pagesMap,
|
|
78
|
+
plan,
|
|
79
|
+
basePlan,
|
|
80
|
+
report,
|
|
81
|
+
});
|
|
82
|
+
for (const n of notes)
|
|
83
|
+
report.notes.push(n);
|
|
84
|
+
if (remoteRoutes.length === 0 && baseRoutes.length === 0) {
|
|
85
|
+
return { pushOps: [], mergedNavigation: remote ?? base };
|
|
165
86
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
cursor = dirname(cursor);
|
|
87
|
+
// Layout: CLI-owned, always regenerated (a user's layout there is deprecated, never overwritten).
|
|
88
|
+
writeOwnedLayout(root, routesDir, '_layout.tsx', layoutContent(), report);
|
|
89
|
+
const pushOps = [];
|
|
90
|
+
const newPaths = new Map();
|
|
91
|
+
for (const rename of renames) {
|
|
92
|
+
const path = fileToRoutePath(rename.route.file);
|
|
93
|
+
newPaths.set(rename.route.routeId, path);
|
|
94
|
+
pushOps.push({
|
|
95
|
+
op: 'update',
|
|
96
|
+
entity: 'NavigationRoute',
|
|
97
|
+
id: rename.route.routeId,
|
|
98
|
+
patch: { path },
|
|
99
|
+
});
|
|
180
100
|
}
|
|
101
|
+
const mergedRoutes = remoteRoutes.map((route) => {
|
|
102
|
+
const path = newPaths.get(route.id);
|
|
103
|
+
return path === undefined ? route : { ...route, path };
|
|
104
|
+
});
|
|
105
|
+
return {
|
|
106
|
+
pushOps,
|
|
107
|
+
mergedNavigation: { routes: mergedRoutes, layouts: remote?.layouts ?? base?.layouts ?? {} },
|
|
108
|
+
};
|
|
181
109
|
}
|
|
182
110
|
//# sourceMappingURL=routeTree.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routeTree.js","sourceRoot":"","sources":["../../src/nav/routeTree.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"routeTree.js","sourceRoot":"","sources":["../../src/nav/routeTree.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { NavigatorNode } from './navigatorTree.js';
|
|
2
|
+
export type NavigatorKind = NavigatorNode['type'];
|
|
3
|
+
type Options = Record<string, unknown>;
|
|
4
|
+
/** `ref(theme:…)` / `ref(icon:…)` — resolvable only by the Creator runtime. */
|
|
5
|
+
export declare function isRef(value: unknown): value is string;
|
|
6
|
+
/** Navigator-level options -> `screenOptions` of the generated navigator. */
|
|
7
|
+
export declare function mapNavigatorOptions(options: Options | undefined, kind: NavigatorKind, where: string, notes: string[]): Options;
|
|
8
|
+
/** Per-route options (+ stack presentation) -> `<X.Screen options>` of the parent navigator. */
|
|
9
|
+
export declare function mapScreenOptions(route: {
|
|
10
|
+
options?: Options;
|
|
11
|
+
presentation?: string;
|
|
12
|
+
}, kind: NavigatorKind, where: string, notes: string[]): Options;
|
|
13
|
+
/** Options hiding a route group from a tab bar / drawer (detached navigators). */
|
|
14
|
+
export declare function hiddenScreenOptions(kind: NavigatorKind): Options;
|
|
15
|
+
export {};
|