mapples 0.2.0-beta.1 → 0.2.0-beta.4
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 +24 -5
- package/dist/api/objects.js +174 -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 +4 -7
- package/dist/codegen/emit.js +10 -29
- package/dist/codegen/emit.js.map +1 -1
- package/dist/codegen/imports.d.ts +1 -15
- package/dist/codegen/imports.js +2 -78
- package/dist/codegen/imports.js.map +1 -1
- package/dist/codegen/instances.d.ts +5 -0
- package/dist/codegen/instances.js +30 -0
- package/dist/codegen/instances.js.map +1 -0
- package/dist/codegen/styles.d.ts +1 -0
- package/dist/codegen/styles.js +3 -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 +2 -2
- package/dist/merge/threeWay.js +38 -6
- package/dist/merge/threeWay.js.map +1 -1
- package/dist/merge/toEdits.d.ts +1 -3
- package/dist/merge/toEdits.js +3 -91
- 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 +19 -1
- package/dist/project/baseStore.js +28 -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 +657 -300
- package/dist/services/syncEngine.js.map +1 -1
- package/dist/types.d.ts +40 -2
- package/dist/types.js +25 -0
- package/dist/types.js.map +1 -1
- package/package.json +3 -2
- package/templates/app/_layout.tsx +3 -0
- package/templates/mapples/sid.d.ts +6 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toEdits.js","sourceRoot":"","sources":["../../src/merge/toEdits.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,
|
|
1
|
+
{"version":3,"file":"toEdits.js","sourceRoot":"","sources":["../../src/merge/toEdits.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,yBAAyB;AACzB,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { NavigationDocument, PageEntity } from '../api/objects.js';
|
|
2
|
+
import type { PagesMap } from '../project/pagesMap.js';
|
|
3
|
+
import type { JpatchOp } from '../types.js';
|
|
4
|
+
import type { SyncReport } from '../ui/report.js';
|
|
5
|
+
import { type RoutePlan } from './placement.js';
|
|
6
|
+
export interface NavRouteNode {
|
|
7
|
+
id: string;
|
|
8
|
+
name: string;
|
|
9
|
+
target: {
|
|
10
|
+
kind: 'page';
|
|
11
|
+
pageUuid: string;
|
|
12
|
+
} | {
|
|
13
|
+
kind: 'navigator';
|
|
14
|
+
navigatorId: string;
|
|
15
|
+
};
|
|
16
|
+
options?: Record<string, unknown>;
|
|
17
|
+
presentation?: string;
|
|
18
|
+
path?: string;
|
|
19
|
+
[k: string]: unknown;
|
|
20
|
+
}
|
|
21
|
+
export interface NavigatorNode {
|
|
22
|
+
id: string;
|
|
23
|
+
type: 'stack' | 'tabs' | 'drawer';
|
|
24
|
+
name: string;
|
|
25
|
+
initialRouteId?: string;
|
|
26
|
+
routes: NavRouteNode[];
|
|
27
|
+
options?: Record<string, unknown>;
|
|
28
|
+
[k: string]: unknown;
|
|
29
|
+
}
|
|
30
|
+
export interface NavigatorDoc {
|
|
31
|
+
version: number;
|
|
32
|
+
rootNavigatorId: string;
|
|
33
|
+
navigators: Record<string, NavigatorNode>;
|
|
34
|
+
}
|
|
35
|
+
/** Accepts the canonical doc, or the backend's {id: 'nav_default', data: doc} wrapper. */
|
|
36
|
+
export declare function extractNavigatorDoc(raw: unknown): NavigatorDoc | null;
|
|
37
|
+
export declare function slugSegment(name: string): string;
|
|
38
|
+
export declare function humanizeSegment(segment: string): string;
|
|
39
|
+
interface PlannedLayout {
|
|
40
|
+
file: string;
|
|
41
|
+
content: string;
|
|
42
|
+
}
|
|
43
|
+
export interface NavPlan extends RoutePlan {
|
|
44
|
+
layouts: PlannedLayout[];
|
|
45
|
+
/** Navigator id by directory (relative to routesDir, '' = root) — adoption places files by it. */
|
|
46
|
+
navigatorByDir: Map<string, string>;
|
|
47
|
+
/** Navigators no route reaches from the root, by the `(group)` dir they were generated into. */
|
|
48
|
+
detachedByDir: Map<string, string>;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Plan the route tree for `doc`: every page route's file, every layout, and
|
|
52
|
+
* which navigator owns which directory. `segmentOverrides` (routeId -> file
|
|
53
|
+
* segment) lets the layout pass after local renames honour the files as the
|
|
54
|
+
* user left them.
|
|
55
|
+
*/
|
|
56
|
+
export declare function buildNavPlan(doc: NavigatorDoc, pages: Map<string, PageEntity>, notes: string[], segmentOverrides?: Map<string, string>): NavPlan;
|
|
57
|
+
/** Every layout the CLI writes opens with this; it is how a CLI-owned file is told from a user's. */
|
|
58
|
+
export declare const GENERATED_LAYOUT_HEADER: RegExp;
|
|
59
|
+
/**
|
|
60
|
+
* Write a CLI-owned layout. A file already there that the CLI did not
|
|
61
|
+
* generate is the user's: it is deprecated (`_depr_<ts>_…`), never
|
|
62
|
+
* overwritten (P0); one the CLI generated is simply replaced.
|
|
63
|
+
*/
|
|
64
|
+
export declare function writeOwnedLayout(root: string, routesDir: string, file: string, content: string, report: SyncReport): void;
|
|
65
|
+
export interface NavigatorSyncResult {
|
|
66
|
+
pushOps: JpatchOp[];
|
|
67
|
+
mergedNavigation: NavigationDocument | null;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Place every page file for the navigation document (routed pages under
|
|
71
|
+
* routesDir, the rest under pagesDir), regenerate the CLI-owned layouts, and
|
|
72
|
+
* push local file renames back as route renames. Runs BEFORE the page merge
|
|
73
|
+
* so the merge reads and writes each page at its final location.
|
|
74
|
+
*/
|
|
75
|
+
export declare function syncNavigatorTree(root: string, routesDir: string, pagesDir: string, pages: Map<string, PageEntity>, pagesMap: PagesMap, baseRaw: NavigationDocument | null, remoteRaw: NavigationDocument | null, report: SyncReport): NavigatorSyncResult;
|
|
76
|
+
/** Put the merged doc back into whatever wrapper shape the server used. */
|
|
77
|
+
export declare function rewrapDoc(raw: NavigationDocument | null, doc: NavigatorDoc): NavigationDocument;
|
|
78
|
+
export {};
|
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
// Creator NavigationDocument (navigators) <-> expo-router route tree.
|
|
2
|
+
//
|
|
3
|
+
// Schema: @mapples/types navigation.ts — {version, rootNavigatorId, navigators:
|
|
4
|
+
// {id -> {type: stack|tabs|drawer, name, initialRouteId?, routes: [{id, name,
|
|
5
|
+
// target: page|navigator, options?, presentation?, path?}], options?}}}.
|
|
6
|
+
// The dev backend wraps it as {id: 'nav_default', data: <doc>, routes: []}.
|
|
7
|
+
//
|
|
8
|
+
// Codegen contract:
|
|
9
|
+
// _layout.tsx files are CLI-OWNED — regenerated every sync. A layout the
|
|
10
|
+
// user wrote at a position the CLI owns is deprecated (`_depr_<ts>_…`),
|
|
11
|
+
// never overwritten; a generated layout nothing plans any more is removed.
|
|
12
|
+
// Page files ARE the route files (`<segment>.tsx`, RFC-0002 §5): their
|
|
13
|
+
// content is merged by the page pipeline; their LOCATION follows the
|
|
14
|
+
// navigation document (nav/placement.ts). Renaming a page file locally
|
|
15
|
+
// renames the route in Creator (pushed as a NavigationDocument merge patch
|
|
16
|
+
// replacing that navigator's routes array — arrays replace wholesale,
|
|
17
|
+
// RFC 7386), and a Creator rename moves the file, content preserved.
|
|
18
|
+
// Option names are translated (nav/screenOptions.ts): the document carries
|
|
19
|
+
// Creator names (`tabLabel`, `header.visible`), the layouts need
|
|
20
|
+
// react-navigation ones (`tabBarLabel`, `headerShown`).
|
|
21
|
+
//
|
|
22
|
+
// Placement rule: the ROOT navigator materializes at routesDir itself —
|
|
23
|
+
// `app/_layout.tsx` for apps born from `mapples create` (routesDir "app"),
|
|
24
|
+
// `app/(mapples)/_layout.tsx` for linked existing apps (routesDir
|
|
25
|
+
// "app/(mapples)"). Initial routes become `index.tsx` (pages) or a `(group)`
|
|
26
|
+
// directory (nested navigators) so they answer at the parent's own path.
|
|
27
|
+
// A navigator no route reaches from the root (Creator: "Not connected") is
|
|
28
|
+
// still generated — as a hidden `(<slug>)` route group under routesDir, kept
|
|
29
|
+
// out of the tab bar / drawer — so its pages stay reachable by path (a segue
|
|
30
|
+
// may target them). Its pages never use `index`: each answers at its own
|
|
31
|
+
// slug, so pages.json records a real path for them.
|
|
32
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, unlinkSync, writeFileSync, } from 'node:fs';
|
|
33
|
+
import { dirname, join, relative } from 'node:path';
|
|
34
|
+
import { printValue } from '@mapples/sid-ast';
|
|
35
|
+
import { withRouteMarker } from '../codegen/emit.js';
|
|
36
|
+
import { deprecateFile } from '../merge/deprecate.js';
|
|
37
|
+
import { deepEqual } from '../merge/mergePatch.js';
|
|
38
|
+
import { makePlan, placePages, pruneEmptyDirs, publicPath, } from './placement.js';
|
|
39
|
+
import { hiddenScreenOptions, mapNavigatorOptions, mapScreenOptions } from './screenOptions.js';
|
|
40
|
+
/** Accepts the canonical doc, or the backend's {id: 'nav_default', data: doc} wrapper. */
|
|
41
|
+
export function extractNavigatorDoc(raw) {
|
|
42
|
+
if (typeof raw !== 'object' || raw === null)
|
|
43
|
+
return null;
|
|
44
|
+
const outer = raw;
|
|
45
|
+
const candidate = (typeof outer.data === 'object' && outer.data !== null ? outer.data : raw);
|
|
46
|
+
if (typeof candidate.rootNavigatorId !== 'string' || typeof candidate.navigators !== 'object') {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
return candidate;
|
|
50
|
+
}
|
|
51
|
+
// ---- planning ----
|
|
52
|
+
export function slugSegment(name) {
|
|
53
|
+
const slug = name
|
|
54
|
+
.trim()
|
|
55
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
56
|
+
.replace(/[^A-Za-z0-9]+/g, '-')
|
|
57
|
+
.replace(/^-+|-+$/g, '')
|
|
58
|
+
.toLowerCase();
|
|
59
|
+
return slug || 'route';
|
|
60
|
+
}
|
|
61
|
+
export function humanizeSegment(segment) {
|
|
62
|
+
const bare = segment.replace(/^\(|\)$/g, '');
|
|
63
|
+
return bare
|
|
64
|
+
.split('-')
|
|
65
|
+
.map((part, i) => (i === 0 ? part.charAt(0).toUpperCase() + part.slice(1) : part))
|
|
66
|
+
.join(' ');
|
|
67
|
+
}
|
|
68
|
+
/** Route targets name pages by Creator uuid; pages without one are matched by tree id. */
|
|
69
|
+
function pageKeyIndex(pages) {
|
|
70
|
+
const index = new Map();
|
|
71
|
+
for (const [pageId, page] of pages) {
|
|
72
|
+
index.set(page.uuid ?? pageId, pageId);
|
|
73
|
+
index.set(pageId, pageId);
|
|
74
|
+
}
|
|
75
|
+
return index;
|
|
76
|
+
}
|
|
77
|
+
function uniqueSegment(segment, used) {
|
|
78
|
+
let unique = segment;
|
|
79
|
+
let n = 2;
|
|
80
|
+
while (used.has(unique))
|
|
81
|
+
unique = `${segment}-${n++}`;
|
|
82
|
+
used.add(unique);
|
|
83
|
+
return unique;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Plan the route tree for `doc`: every page route's file, every layout, and
|
|
87
|
+
* which navigator owns which directory. `segmentOverrides` (routeId -> file
|
|
88
|
+
* segment) lets the layout pass after local renames honour the files as the
|
|
89
|
+
* user left them.
|
|
90
|
+
*/
|
|
91
|
+
export function buildNavPlan(doc, pages, notes, segmentOverrides = new Map()) {
|
|
92
|
+
const pageByKey = pageKeyIndex(pages);
|
|
93
|
+
const routes = [];
|
|
94
|
+
const layouts = [];
|
|
95
|
+
const navigatorByDir = new Map();
|
|
96
|
+
const detachedByDir = new Map();
|
|
97
|
+
const seen = new Set();
|
|
98
|
+
const segmentFor = (route, isInitial) => {
|
|
99
|
+
const override = segmentOverrides.get(route.id);
|
|
100
|
+
if (override)
|
|
101
|
+
return override;
|
|
102
|
+
if (route.path)
|
|
103
|
+
return route.path.replace(/^\/+/, '').replace(/\/+$/, '') || 'index';
|
|
104
|
+
if (route.target.kind === 'page')
|
|
105
|
+
return isInitial ? 'index' : slugSegment(route.name);
|
|
106
|
+
return isInitial ? `(${slugSegment(route.name)})` : slugSegment(route.name);
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* Plan one navigator at `dir`; child navigators emit their own layouts, the
|
|
110
|
+
* caller emits this one (the root's screen list grows with detached groups
|
|
111
|
+
* first). `detached` subtrees never use `index`/`(group)` positions.
|
|
112
|
+
*/
|
|
113
|
+
const walk = (navigatorId, dir, detached, used) => {
|
|
114
|
+
if (seen.has(navigatorId)) {
|
|
115
|
+
notes.push(`navigation: navigator ${navigatorId} is referenced twice — second reference skipped`);
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
seen.add(navigatorId);
|
|
119
|
+
const nav = doc.navigators[navigatorId];
|
|
120
|
+
if (!nav) {
|
|
121
|
+
notes.push(`navigation: navigator ${navigatorId} is referenced but not defined — skipped`);
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
navigatorByDir.set(dir, navigatorId);
|
|
125
|
+
const initialId = nav.initialRouteId ?? nav.routes[0]?.id;
|
|
126
|
+
const screens = [];
|
|
127
|
+
for (const route of nav.routes) {
|
|
128
|
+
const isInitial = !detached && route.id === initialId;
|
|
129
|
+
const segment = uniqueSegment(segmentFor(route, isInitial), used);
|
|
130
|
+
const where = `route “${route.name}” of navigator “${nav.name}”`;
|
|
131
|
+
const options = mapScreenOptions(route, nav.type, where, notes);
|
|
132
|
+
if (route.target.kind === 'page') {
|
|
133
|
+
const pageId = pageByKey.get(route.target.pageUuid);
|
|
134
|
+
if (!pageId) {
|
|
135
|
+
notes.push(`navigation: route “${route.name}” targets page ${route.target.pageUuid} which has no synced page — screen skipped`);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
routes.push({
|
|
139
|
+
routeId: route.id,
|
|
140
|
+
pageId,
|
|
141
|
+
navigatorId: nav.id,
|
|
142
|
+
dir,
|
|
143
|
+
segment,
|
|
144
|
+
file: dir ? join(dir, `${segment}.tsx`) : `${segment}.tsx`,
|
|
145
|
+
routeName: route.name,
|
|
146
|
+
routePath: publicPath(dir, segment),
|
|
147
|
+
});
|
|
148
|
+
screens.push({ segment, options });
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
screens.push({ segment, options });
|
|
152
|
+
const childDir = dir ? join(dir, segment) : segment;
|
|
153
|
+
const child = walk(route.target.navigatorId, childDir, detached, new Set());
|
|
154
|
+
if (child)
|
|
155
|
+
layouts.push(layoutFor(child.nav, childDir, child.screens, notes));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return { nav, screens };
|
|
159
|
+
};
|
|
160
|
+
const rootUsed = new Set();
|
|
161
|
+
const root = walk(doc.rootNavigatorId, '', false, rootUsed);
|
|
162
|
+
if (!root)
|
|
163
|
+
return { ...makePlan(routes), layouts, navigatorByDir, detachedByDir };
|
|
164
|
+
// ---- detached navigators: hidden (group)s under the root directory ----
|
|
165
|
+
const referenced = new Set([doc.rootNavigatorId]);
|
|
166
|
+
for (const nav of Object.values(doc.navigators)) {
|
|
167
|
+
for (const route of nav.routes) {
|
|
168
|
+
if (route.target.kind === 'navigator')
|
|
169
|
+
referenced.add(route.target.navigatorId);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
const attach = (navigatorId) => {
|
|
173
|
+
const nav = doc.navigators[navigatorId];
|
|
174
|
+
const segment = uniqueSegment(`(${slugSegment(nav.name)})`, rootUsed);
|
|
175
|
+
const group = walk(navigatorId, segment, true, new Set());
|
|
176
|
+
if (!group)
|
|
177
|
+
return;
|
|
178
|
+
detachedByDir.set(segment, navigatorId);
|
|
179
|
+
layouts.push(layoutFor(group.nav, segment, group.screens, notes));
|
|
180
|
+
root.screens.push({ segment, options: hiddenScreenOptions(root.nav.type) });
|
|
181
|
+
};
|
|
182
|
+
// Unreferenced navigators first (deterministic: document order), then whatever
|
|
183
|
+
// only a cycle among detached navigators reaches.
|
|
184
|
+
for (const id of Object.keys(doc.navigators)) {
|
|
185
|
+
if (!seen.has(id) && !referenced.has(id))
|
|
186
|
+
attach(id);
|
|
187
|
+
}
|
|
188
|
+
for (const id of Object.keys(doc.navigators)) {
|
|
189
|
+
if (!seen.has(id))
|
|
190
|
+
attach(id);
|
|
191
|
+
}
|
|
192
|
+
layouts.push(layoutFor(root.nav, '', root.screens, notes));
|
|
193
|
+
return { ...makePlan(routes), layouts, navigatorByDir, detachedByDir };
|
|
194
|
+
}
|
|
195
|
+
function layoutFor(nav, dir, screens, notes) {
|
|
196
|
+
return {
|
|
197
|
+
file: dir ? join(dir, '_layout.tsx') : '_layout.tsx',
|
|
198
|
+
content: layoutContent(nav, screens, notes),
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
// ---- emission ----
|
|
202
|
+
const NAVIGATOR_IMPORT = {
|
|
203
|
+
stack: { name: 'Stack', module: 'expo-router' },
|
|
204
|
+
tabs: { name: 'Tabs', module: 'expo-router' },
|
|
205
|
+
drawer: { name: 'Drawer', module: 'expo-router/drawer' },
|
|
206
|
+
};
|
|
207
|
+
/** Every layout the CLI writes opens with this; it is how a CLI-owned file is told from a user's. */
|
|
208
|
+
export const GENERATED_LAYOUT_HEADER = /^\/\/\s*GENERATED by Mapples/;
|
|
209
|
+
/** Options literal; a string `tabBarIcon`/`drawerIcon` becomes an Icon renderer. */
|
|
210
|
+
function optionsLiteral(options, usesIcon) {
|
|
211
|
+
const iconKeys = ['tabBarIcon', 'drawerIcon'];
|
|
212
|
+
const plain = {};
|
|
213
|
+
const iconParts = [];
|
|
214
|
+
for (const [key, value] of Object.entries(options)) {
|
|
215
|
+
if (iconKeys.includes(key) && typeof value === 'string') {
|
|
216
|
+
usesIcon.value = true;
|
|
217
|
+
iconParts.push(`${key}: ({ color }) => <Icon iconName=${JSON.stringify(value)} color={color} />`);
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
plain[key] = value;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
const base = printValue(plain);
|
|
224
|
+
if (iconParts.length === 0)
|
|
225
|
+
return base;
|
|
226
|
+
const inner = base === '{}' ? '' : base.slice(1, -1).trim().replace(/,\s*$/, '') + ', ';
|
|
227
|
+
return `{ ${inner}${iconParts.join(', ')} }`;
|
|
228
|
+
}
|
|
229
|
+
function layoutContent(nav, screens, notes) {
|
|
230
|
+
const kind = NAVIGATOR_IMPORT[nav.type] ?? NAVIGATOR_IMPORT.stack;
|
|
231
|
+
const usesIcon = { value: false };
|
|
232
|
+
const screenLines = screens.map(({ segment, options }) => {
|
|
233
|
+
if (Object.keys(options).length === 0) {
|
|
234
|
+
return ` <${kind.name}.Screen name=${JSON.stringify(segment)} />`;
|
|
235
|
+
}
|
|
236
|
+
return ` <${kind.name}.Screen name=${JSON.stringify(segment)} options={${optionsLiteral(options, usesIcon)}} />`;
|
|
237
|
+
});
|
|
238
|
+
const navOptions = mapNavigatorOptions(nav.options, nav.type, `navigator “${nav.name}”`, notes);
|
|
239
|
+
const screenOptions = Object.keys(navOptions).length > 0
|
|
240
|
+
? ` screenOptions={${optionsLiteral(navOptions, usesIcon)}}`
|
|
241
|
+
: '';
|
|
242
|
+
const componentName = `${nav.name.replace(/[^A-Za-z0-9]/g, '') || 'Mapples'}Layout`;
|
|
243
|
+
return [
|
|
244
|
+
'// GENERATED by Mapples — DO NOT EDIT. This layout is owned by the CLI and',
|
|
245
|
+
`// regenerated from the navigation document (navigator “${nav.name}”, ${nav.type})`,
|
|
246
|
+
'// on every `mapples sync`. Edit navigation in Creator instead.',
|
|
247
|
+
`import { ${kind.name} } from '${kind.module}';`,
|
|
248
|
+
...(usesIcon.value ? ["import { Icon } from '@mapples/ui';"] : []),
|
|
249
|
+
'',
|
|
250
|
+
`export default function ${componentName}() {`,
|
|
251
|
+
' return (',
|
|
252
|
+
` <${kind.name}${screenOptions}>`,
|
|
253
|
+
...screenLines,
|
|
254
|
+
` </${kind.name}>`,
|
|
255
|
+
' );',
|
|
256
|
+
'}',
|
|
257
|
+
'',
|
|
258
|
+
].join('\n');
|
|
259
|
+
}
|
|
260
|
+
// ---- layout files ----
|
|
261
|
+
/**
|
|
262
|
+
* Write a CLI-owned layout. A file already there that the CLI did not
|
|
263
|
+
* generate is the user's: it is deprecated (`_depr_<ts>_…`), never
|
|
264
|
+
* overwritten (P0); one the CLI generated is simply replaced.
|
|
265
|
+
*/
|
|
266
|
+
export function writeOwnedLayout(root, routesDir, file, content, report) {
|
|
267
|
+
const rel = join(routesDir, file);
|
|
268
|
+
const abs = join(root, rel);
|
|
269
|
+
if (existsSync(abs)) {
|
|
270
|
+
const current = readFileSync(abs, 'utf8');
|
|
271
|
+
if (current === content)
|
|
272
|
+
return;
|
|
273
|
+
if (!GENERATED_LAYOUT_HEADER.test(current)) {
|
|
274
|
+
const deprecated = relative(root, deprecateFile(abs));
|
|
275
|
+
report.files.push({
|
|
276
|
+
file: rel,
|
|
277
|
+
action: 'deprecated',
|
|
278
|
+
detail: `layouts under ${routesDir} are generated from the navigation — yours is kept at ${deprecated}`,
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
mkdirSync(dirname(abs), { recursive: true });
|
|
283
|
+
writeFileSync(abs, content);
|
|
284
|
+
report.files.push({ file: rel, action: 'updated', detail: 'CLI-owned layout' });
|
|
285
|
+
}
|
|
286
|
+
/** Remove generated layouts the plan no longer has (a navigator moved or went away). Never a user file. */
|
|
287
|
+
function pruneStaleLayouts(root, routesDir, planned, report) {
|
|
288
|
+
const routesAbs = join(root, routesDir);
|
|
289
|
+
// Nothing planned means the document has no usable root: leave the tree alone.
|
|
290
|
+
if (planned.size === 0 || !existsSync(routesAbs))
|
|
291
|
+
return;
|
|
292
|
+
const walk = (rel) => {
|
|
293
|
+
for (const entry of readdirSync(join(routesAbs, rel), { withFileTypes: true })) {
|
|
294
|
+
const relPath = rel ? join(rel, entry.name) : entry.name;
|
|
295
|
+
if (entry.isDirectory()) {
|
|
296
|
+
if (entry.name === 'node_modules' || entry.name.startsWith('.'))
|
|
297
|
+
continue;
|
|
298
|
+
walk(relPath);
|
|
299
|
+
}
|
|
300
|
+
else if (entry.name === '_layout.tsx' && !planned.has(relPath)) {
|
|
301
|
+
const abs = join(routesAbs, relPath);
|
|
302
|
+
if (!GENERATED_LAYOUT_HEADER.test(readFileSync(abs, 'utf8')))
|
|
303
|
+
continue;
|
|
304
|
+
unlinkSync(abs);
|
|
305
|
+
pruneEmptyDirs(root, dirname(join(routesDir, relPath)));
|
|
306
|
+
report.files.push({
|
|
307
|
+
file: join(routesDir, relPath),
|
|
308
|
+
action: 'deprecated',
|
|
309
|
+
detail: 'generated layout for a navigator that is no longer here — removed',
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
walk('');
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Place every page file for the navigation document (routed pages under
|
|
318
|
+
* routesDir, the rest under pagesDir), regenerate the CLI-owned layouts, and
|
|
319
|
+
* push local file renames back as route renames. Runs BEFORE the page merge
|
|
320
|
+
* so the merge reads and writes each page at its final location.
|
|
321
|
+
*/
|
|
322
|
+
export function syncNavigatorTree(root, routesDir, pagesDir, pages, pagesMap, baseRaw, remoteRaw, report) {
|
|
323
|
+
const remoteDoc = extractNavigatorDoc(remoteRaw);
|
|
324
|
+
const notes = [];
|
|
325
|
+
const plan = remoteDoc ? buildNavPlan(remoteDoc, pages, notes) : makePlan([]);
|
|
326
|
+
const baseDoc = extractNavigatorDoc(baseRaw);
|
|
327
|
+
const basePlan = baseDoc ? buildNavPlan(baseDoc, pages, []) : null;
|
|
328
|
+
for (const n of notes)
|
|
329
|
+
report.notes.push(n);
|
|
330
|
+
const { renames } = placePages({
|
|
331
|
+
root,
|
|
332
|
+
routesDir,
|
|
333
|
+
pagesDir,
|
|
334
|
+
pages,
|
|
335
|
+
pagesMap,
|
|
336
|
+
plan,
|
|
337
|
+
basePlan,
|
|
338
|
+
report,
|
|
339
|
+
});
|
|
340
|
+
if (!remoteDoc)
|
|
341
|
+
return { pushOps: [], mergedNavigation: remoteRaw ?? baseRaw };
|
|
342
|
+
const renameMap = new Map();
|
|
343
|
+
for (const rename of renames) {
|
|
344
|
+
renameMap.set(rename.route.routeId, {
|
|
345
|
+
navigatorId: rename.route.navigatorId,
|
|
346
|
+
routeId: rename.route.routeId,
|
|
347
|
+
newName: humanizeSegment(rename.newSegment),
|
|
348
|
+
newSegment: rename.newSegment,
|
|
349
|
+
});
|
|
350
|
+
// The marker's display name follows the pushed route name, in the same sync.
|
|
351
|
+
const abs = join(root, routesDir, rename.route.file);
|
|
352
|
+
const source = readFileSync(abs, 'utf8');
|
|
353
|
+
const next = withRouteMarker(source, rename.route.routeId, humanizeSegment(rename.newSegment));
|
|
354
|
+
if (next !== source)
|
|
355
|
+
writeFileSync(abs, next);
|
|
356
|
+
}
|
|
357
|
+
// ---- layouts: CLI-owned, regenerated (with local renames reflected) ----
|
|
358
|
+
const segmentOverrides = new Map(plan.routes.map((r) => [r.routeId, r.segment]));
|
|
359
|
+
const mergedDoc = applyRenames(remoteDoc, renameMap);
|
|
360
|
+
const finalLayouts = buildNavPlan(mergedDoc, pages, [], segmentOverrides).layouts;
|
|
361
|
+
for (const layout of finalLayouts) {
|
|
362
|
+
writeOwnedLayout(root, routesDir, layout.file, layout.content, report);
|
|
363
|
+
}
|
|
364
|
+
pruneStaleLayouts(root, routesDir, new Set(finalLayouts.map((l) => l.file)), report);
|
|
365
|
+
// ---- push: replace each renamed navigator's routes array wholesale ----
|
|
366
|
+
const pushOps = [];
|
|
367
|
+
// Only a rename that changes the document is worth a commit; a no-op patch
|
|
368
|
+
// still moves HEAD server-side, and every later sync would repeat it.
|
|
369
|
+
const changedNavigators = [...new Set([...renameMap.values()].map((r) => r.navigatorId))].filter((navId) => !deepEqual(mergedDoc.navigators[navId]?.routes, remoteDoc.navigators[navId]?.routes));
|
|
370
|
+
if (changedNavigators.length > 0) {
|
|
371
|
+
const navigatorsPatch = {};
|
|
372
|
+
for (const navId of changedNavigators) {
|
|
373
|
+
navigatorsPatch[navId] = { routes: mergedDoc.navigators[navId].routes };
|
|
374
|
+
}
|
|
375
|
+
pushOps.push({
|
|
376
|
+
op: 'update',
|
|
377
|
+
entity: 'NavigationDocument',
|
|
378
|
+
id: 'nav_default',
|
|
379
|
+
patch: { data: { navigators: navigatorsPatch } },
|
|
380
|
+
});
|
|
381
|
+
const pushed = [...renameMap.values()].filter((r) => changedNavigators.includes(r.navigatorId));
|
|
382
|
+
report.notes.push(`navigation: pushing ${pushed.length} route rename(s) to Creator (${pushed.map((r) => r.newName).join(', ')})`);
|
|
383
|
+
}
|
|
384
|
+
const mergedNavigation = rewrapDoc(remoteRaw, mergedDoc);
|
|
385
|
+
return { pushOps, mergedNavigation };
|
|
386
|
+
}
|
|
387
|
+
function applyRenames(doc, renames) {
|
|
388
|
+
if (renames.size === 0)
|
|
389
|
+
return doc;
|
|
390
|
+
const cloned = structuredClone(doc);
|
|
391
|
+
for (const rename of renames.values()) {
|
|
392
|
+
const nav = cloned.navigators[rename.navigatorId];
|
|
393
|
+
const route = nav?.routes.find((r) => r.id === rename.routeId);
|
|
394
|
+
if (!route)
|
|
395
|
+
continue;
|
|
396
|
+
route.name = rename.newName;
|
|
397
|
+
// A pinned path follows the file, or the next plan would undo the rename.
|
|
398
|
+
if (route.path !== undefined)
|
|
399
|
+
route.path = rename.newSegment;
|
|
400
|
+
}
|
|
401
|
+
return cloned;
|
|
402
|
+
}
|
|
403
|
+
/** Put the merged doc back into whatever wrapper shape the server used. */
|
|
404
|
+
export function rewrapDoc(raw, doc) {
|
|
405
|
+
if (raw && typeof raw === 'object' && 'data' in raw) {
|
|
406
|
+
return { ...raw, data: doc };
|
|
407
|
+
}
|
|
408
|
+
return doc;
|
|
409
|
+
}
|
|
410
|
+
//# sourceMappingURL=navigatorTree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigatorTree.js","sourceRoot":"","sources":["../../src/nav/navigatorTree.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { PageEntity } from '../api/objects.js';
|
|
2
|
+
import type { PagesMap } from '../project/pagesMap.js';
|
|
3
|
+
import type { SyncReport } from '../ui/report.js';
|
|
4
|
+
export interface PlannedRoute {
|
|
5
|
+
routeId: string;
|
|
6
|
+
pageId: string;
|
|
7
|
+
/** Owning navigator (navigator documents); null for the flat route list. */
|
|
8
|
+
navigatorId: string | null;
|
|
9
|
+
/** Directory relative to routesDir ('' at the root). */
|
|
10
|
+
dir: string;
|
|
11
|
+
/** File segment without `.tsx`. Local renames rewrite this. */
|
|
12
|
+
segment: string;
|
|
13
|
+
/** File relative to routesDir, with `.tsx`. Local renames rewrite this. */
|
|
14
|
+
file: string;
|
|
15
|
+
routeName: string;
|
|
16
|
+
/** Public path, e.g. `/settings` — recorded in pages.json. */
|
|
17
|
+
routePath: string;
|
|
18
|
+
}
|
|
19
|
+
export interface RoutePlan {
|
|
20
|
+
routes: PlannedRoute[];
|
|
21
|
+
byRouteId: Map<string, PlannedRoute>;
|
|
22
|
+
}
|
|
23
|
+
export declare function makePlan(routes: PlannedRoute[]): RoutePlan;
|
|
24
|
+
/** expo-router public path for a file position: `(group)` segments vanish, `index` is the dir itself. */
|
|
25
|
+
export declare function publicPath(dir: string, segment: string): string;
|
|
26
|
+
export interface LocalRename {
|
|
27
|
+
route: PlannedRoute;
|
|
28
|
+
oldSegment: string;
|
|
29
|
+
newSegment: string;
|
|
30
|
+
}
|
|
31
|
+
export interface PlacementInput {
|
|
32
|
+
root: string;
|
|
33
|
+
routesDir: string;
|
|
34
|
+
pagesDir: string;
|
|
35
|
+
/** Remote pages — the set whose files are being placed. */
|
|
36
|
+
pages: Map<string, PageEntity>;
|
|
37
|
+
pagesMap: PagesMap;
|
|
38
|
+
plan: RoutePlan;
|
|
39
|
+
basePlan: RoutePlan | null;
|
|
40
|
+
report: SyncReport;
|
|
41
|
+
}
|
|
42
|
+
export interface PlacementResult {
|
|
43
|
+
/** Routes whose file the user renamed locally (the plan already reflects the new segment). */
|
|
44
|
+
renames: LocalRename[];
|
|
45
|
+
}
|
|
46
|
+
/** routeId -> file relative to `dir`, for every `.tsx` under it carrying a route marker. */
|
|
47
|
+
export declare function scanRouteFiles(dir: string): Map<string, string>;
|
|
48
|
+
/** A pre-0.2 route wrapper: nothing but comments and one `export { default } from '…'`. */
|
|
49
|
+
export declare function isReexportWrapper(source: string): boolean;
|
|
50
|
+
export declare function pruneEmptyDirs(rootDir: string, rel: string): void;
|
|
51
|
+
/** `<dir>/<Name>.tsx`, suffixed until it is free of `used`. */
|
|
52
|
+
export declare function mintEntityFile(dir: string, name: string, used: Set<string>): string;
|
|
53
|
+
export declare function placePages(input: PlacementInput): PlacementResult;
|