mapples 0.2.0-beta.0 → 0.2.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/README.md +133 -22
  2. package/dist/adopt/scan.d.ts +8 -2
  3. package/dist/adopt/scan.js +31 -13
  4. package/dist/adopt/scan.js.map +1 -1
  5. package/dist/api/agent.d.ts +85 -0
  6. package/dist/api/agent.js +92 -0
  7. package/dist/api/agent.js.map +1 -0
  8. package/dist/api/auth.d.ts +2 -0
  9. package/dist/api/auth.js +28 -6
  10. package/dist/api/auth.js.map +1 -1
  11. package/dist/api/client.d.ts +13 -1
  12. package/dist/api/client.js +26 -4
  13. package/dist/api/client.js.map +1 -1
  14. package/dist/api/commit.d.ts +9 -0
  15. package/dist/api/commit.js +36 -0
  16. package/dist/api/commit.js.map +1 -1
  17. package/dist/api/errors.js +12 -2
  18. package/dist/api/errors.js.map +1 -1
  19. package/dist/api/objects.d.ts +36 -5
  20. package/dist/api/objects.js +176 -10
  21. package/dist/api/objects.js.map +1 -1
  22. package/dist/api/poll.d.ts +5 -3
  23. package/dist/api/poll.js +17 -6
  24. package/dist/api/poll.js.map +1 -1
  25. package/dist/api/txPlan.d.ts +15 -0
  26. package/dist/api/txPlan.js +196 -0
  27. package/dist/api/txPlan.js.map +1 -0
  28. package/dist/assets/assets.d.ts +9 -0
  29. package/dist/assets/assets.js +33 -4
  30. package/dist/assets/assets.js.map +1 -1
  31. package/dist/codegen/emit.d.ts +4 -7
  32. package/dist/codegen/emit.js +10 -29
  33. package/dist/codegen/emit.js.map +1 -1
  34. package/dist/codegen/imports.d.ts +8 -15
  35. package/dist/codegen/imports.js +27 -72
  36. package/dist/codegen/imports.js.map +1 -1
  37. package/dist/codegen/instances.d.ts +5 -0
  38. package/dist/codegen/instances.js +30 -0
  39. package/dist/codegen/instances.js.map +1 -0
  40. package/dist/codegen/styles.d.ts +1 -0
  41. package/dist/codegen/styles.js +3 -0
  42. package/dist/codegen/styles.js.map +1 -0
  43. package/dist/commands/agent.d.ts +2 -0
  44. package/dist/commands/agent.js +87 -0
  45. package/dist/commands/agent.js.map +1 -0
  46. package/dist/commands/create.js +1 -0
  47. package/dist/commands/create.js.map +1 -1
  48. package/dist/commands/impl/adoptImpl.js +3 -0
  49. package/dist/commands/impl/adoptImpl.js.map +1 -1
  50. package/dist/commands/impl/agentImpl.d.ts +23 -0
  51. package/dist/commands/impl/agentImpl.js +426 -0
  52. package/dist/commands/impl/agentImpl.js.map +1 -0
  53. package/dist/commands/impl/createImpl.js +31 -4
  54. package/dist/commands/impl/createImpl.js.map +1 -1
  55. package/dist/commands/impl/initImpl.js +28 -4
  56. package/dist/commands/impl/initImpl.js.map +1 -1
  57. package/dist/commands/impl/syncImpl.js +30 -5
  58. package/dist/commands/impl/syncImpl.js.map +1 -1
  59. package/dist/commands/init.js +1 -0
  60. package/dist/commands/init.js.map +1 -1
  61. package/dist/index.js +12 -1
  62. package/dist/index.js.map +1 -1
  63. package/dist/merge/applyOps.d.ts +5 -2
  64. package/dist/merge/applyOps.js +75 -32
  65. package/dist/merge/applyOps.js.map +1 -1
  66. package/dist/merge/childrenOrder.d.ts +13 -0
  67. package/dist/merge/childrenOrder.js +51 -0
  68. package/dist/merge/childrenOrder.js.map +1 -0
  69. package/dist/merge/diff.d.ts +20 -1
  70. package/dist/merge/diff.js +77 -17
  71. package/dist/merge/diff.js.map +1 -1
  72. package/dist/merge/threeWay.d.ts +2 -2
  73. package/dist/merge/threeWay.js +74 -10
  74. package/dist/merge/threeWay.js.map +1 -1
  75. package/dist/merge/toEdits.d.ts +1 -3
  76. package/dist/merge/toEdits.js +3 -91
  77. package/dist/merge/toEdits.js.map +1 -1
  78. package/dist/nav/navigatorTree.d.ts +78 -0
  79. package/dist/nav/navigatorTree.js +410 -0
  80. package/dist/nav/navigatorTree.js.map +1 -0
  81. package/dist/nav/placement.d.ts +53 -0
  82. package/dist/nav/placement.js +260 -0
  83. package/dist/nav/placement.js.map +1 -0
  84. package/dist/nav/routeTree.d.ts +8 -2
  85. package/dist/nav/routeTree.js +79 -151
  86. package/dist/nav/routeTree.js.map +1 -1
  87. package/dist/nav/screenOptions.d.ts +15 -0
  88. package/dist/nav/screenOptions.js +213 -0
  89. package/dist/nav/screenOptions.js.map +1 -0
  90. package/dist/project/agentState.d.ts +30 -0
  91. package/dist/project/agentState.js +42 -0
  92. package/dist/project/agentState.js.map +1 -0
  93. package/dist/project/baseStore.d.ts +19 -1
  94. package/dist/project/baseStore.js +28 -0
  95. package/dist/project/baseStore.js.map +1 -1
  96. package/dist/project/componentsMap.d.ts +7 -0
  97. package/dist/project/componentsMap.js +21 -0
  98. package/dist/project/componentsMap.js.map +1 -0
  99. package/dist/project/config.d.ts +12 -3
  100. package/dist/project/config.js +11 -2
  101. package/dist/project/config.js.map +1 -1
  102. package/dist/project/env.d.ts +10 -3
  103. package/dist/project/env.js +23 -5
  104. package/dist/project/env.js.map +1 -1
  105. package/dist/project/pagesMap.d.ts +2 -0
  106. package/dist/project/pagesMap.js.map +1 -1
  107. package/dist/project/secret.d.ts +6 -2
  108. package/dist/project/secret.js +11 -5
  109. package/dist/project/secret.js.map +1 -1
  110. package/dist/services/adoptService.d.ts +3 -0
  111. package/dist/services/adoptService.js +357 -38
  112. package/dist/services/adoptService.js.map +1 -1
  113. package/dist/services/agentInstall.d.ts +80 -0
  114. package/dist/services/agentInstall.js +309 -0
  115. package/dist/services/agentInstall.js.map +1 -0
  116. package/dist/services/agentLease.d.ts +2 -0
  117. package/dist/services/agentLease.js +32 -0
  118. package/dist/services/agentLease.js.map +1 -0
  119. package/dist/services/clientFactory.d.ts +2 -0
  120. package/dist/services/clientFactory.js +20 -3
  121. package/dist/services/clientFactory.js.map +1 -1
  122. package/dist/services/doctorService.js +77 -66
  123. package/dist/services/doctorService.js.map +1 -1
  124. package/dist/services/scaffold.js +4 -0
  125. package/dist/services/scaffold.js.map +1 -1
  126. package/dist/services/syncEngine.d.ts +7 -0
  127. package/dist/services/syncEngine.js +719 -306
  128. package/dist/services/syncEngine.js.map +1 -1
  129. package/dist/style/theme.js +17 -1
  130. package/dist/style/theme.js.map +1 -1
  131. package/dist/types.d.ts +51 -2
  132. package/dist/types.js +25 -0
  133. package/dist/types.js.map +1 -1
  134. package/dist/ui/report.d.ts +15 -0
  135. package/dist/ui/report.js +30 -0
  136. package/dist/ui/report.js.map +1 -1
  137. package/package.json +3 -2
  138. package/templates/agent/agents-md/AGENTS.md +8 -0
  139. package/templates/agent/claude/CLAUDE.md +7 -0
  140. package/templates/agent/claude/mcp.json +11 -0
  141. package/templates/agent/claude/settings.json +26 -0
  142. package/templates/agent/codex/config.toml +6 -0
  143. package/templates/agent/codex/hooks.json +26 -0
  144. package/templates/agent/cursor/hooks.json +9 -0
  145. package/templates/agent/cursor/mcp.json +10 -0
  146. package/templates/agent/mapples.md +124 -0
  147. package/templates/agent/skills/mapples-conventions/SKILL.md +137 -0
  148. package/templates/agent/skills/mapples-design/SKILL.md +235 -0
  149. package/templates/agent/skills/mapples-design/reference/component-library.md +128 -0
  150. package/templates/agent/skills/mapples-design/reference/design-tokens.md +132 -0
  151. package/templates/agent/skills/mapples-design/reference/layout-contract.md +227 -0
  152. package/templates/agent/skills/mapples-design/reference/lint-checklist.md +51 -0
  153. package/templates/agent/skills/mapples-design/reference/plan.md +95 -0
  154. package/templates/agent/skills/mapples-design/reference/playbooks/empty-states.md +14 -0
  155. package/templates/agent/skills/mapples-design/reference/playbooks/forms-and-auth.md +22 -0
  156. package/templates/agent/skills/mapples-design/reference/playbooks/home-dashboard.md +14 -0
  157. package/templates/agent/skills/mapples-design/reference/playbooks/list-and-detail.md +18 -0
  158. package/templates/agent/skills/mapples-design/reference/playbooks/microcopy.md +20 -0
  159. package/templates/agent/skills/mapples-design/reference/playbooks/navigation-chrome.md +21 -0
  160. package/templates/agent/skills/mapples-design/reference/playbooks/onboarding-flow.md +15 -0
  161. package/templates/agent/skills/mapples-design/reference/playbooks/screen-flow-wiring.md +37 -0
  162. package/templates/agent/skills/mapples-design/reference/playbooks/settings-profile.md +16 -0
  163. package/templates/agent/skills/mapples-design/reference/playbooks/stats-and-progress.md +17 -0
  164. package/templates/agent/skills/mapples-design/reference/playbooks/visual-hierarchy.md +18 -0
  165. package/templates/agent/skills/mapples-design/reference/style-guides.md +92 -0
  166. package/templates/agent/skills/mapples-sync/SKILL.md +93 -0
  167. package/templates/app/_layout.tsx +3 -0
  168. package/templates/app.json +0 -1
  169. package/templates/gitignore +2 -0
  170. package/templates/mapples/sid.d.ts +6 -0
  171. package/templates/package.json +12 -10
@@ -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;