mapples 0.2.0-beta.10 → 0.2.0-beta.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/client.d.ts +15 -0
- package/dist/api/client.js +36 -0
- package/dist/api/client.js.map +1 -1
- package/dist/api/commit.js +19 -1
- package/dist/api/commit.js.map +1 -1
- package/dist/api/errors.d.ts +1 -1
- package/dist/api/errors.js +3 -0
- package/dist/api/errors.js.map +1 -1
- package/dist/api/objects.d.ts +3 -1
- package/dist/api/objects.js +31 -4
- package/dist/api/objects.js.map +1 -1
- package/dist/api/project.d.ts +11 -0
- package/dist/api/project.js +29 -0
- package/dist/api/project.js.map +1 -0
- package/dist/assets/assets.d.ts +12 -0
- package/dist/assets/assets.js +31 -2
- package/dist/assets/assets.js.map +1 -1
- package/dist/commands/doctor.js +2 -1
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/impl/createImpl.js +26 -4
- package/dist/commands/impl/createImpl.js.map +1 -1
- package/dist/commands/impl/doctorImpl.js +14 -7
- package/dist/commands/impl/doctorImpl.js.map +1 -1
- package/dist/commands/impl/initImpl.js +34 -1
- package/dist/commands/impl/initImpl.js.map +1 -1
- package/dist/commands/init.js +1 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/nav/navigatorTree.d.ts +36 -2
- package/dist/nav/navigatorTree.js +191 -40
- package/dist/nav/navigatorTree.js.map +1 -1
- package/dist/nav/routeTree.d.ts +2 -1
- package/dist/nav/routeTree.js +9 -4
- package/dist/nav/routeTree.js.map +1 -1
- package/dist/nav/screenOptions.d.ts +24 -0
- package/dist/nav/screenOptions.js +41 -13
- package/dist/nav/screenOptions.js.map +1 -1
- package/dist/runtime/runtimeFiles.d.ts +17 -0
- package/dist/runtime/runtimeFiles.js +183 -0
- package/dist/runtime/runtimeFiles.js.map +1 -0
- package/dist/services/appDeps.d.ts +32 -0
- package/dist/services/appDeps.js +132 -0
- package/dist/services/appDeps.js.map +1 -0
- package/dist/services/doctorService.d.ts +19 -1
- package/dist/services/doctorService.js +117 -3
- package/dist/services/doctorService.js.map +1 -1
- package/dist/services/scaffold.d.ts +13 -1
- package/dist/services/scaffold.js +57 -5
- package/dist/services/scaffold.js.map +1 -1
- package/dist/services/syncEngine.js +85 -22
- package/dist/services/syncEngine.js.map +1 -1
- package/dist/types.d.ts +4 -0
- package/dist/types.js.map +1 -1
- package/dist/version.d.ts +21 -0
- package/dist/version.js +40 -3
- package/dist/version.js.map +1 -1
- package/package.json +4 -3
- package/templates/agent/mapples.md +9 -4
- package/templates/agent/skills/mapples-conventions/SKILL.md +2 -2
- package/templates/agent/skills/mapples-design/SKILL.md +4 -4
- package/templates/agent/skills/mapples-design/reference/component-library.md +1 -1
- package/templates/agent/skills/mapples-design/reference/layout-contract.md +2 -3
- package/templates/agent/skills/mapples-design/reference/playbooks/onboarding-flow.md +1 -1
- package/templates/agent/skills/mapples-design/reference/playbooks/screen-flow-wiring.md +2 -5
- package/templates/app/_layout.tsx +6 -1
- package/templates/gitignore +2 -0
- package/templates/metro.config.js +11 -0
- package/templates/package.json +19 -10
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// `mapples init` on an existing app: check the app can host Mapples routes
|
|
2
|
+
// (an Expo app on expo-router) BEFORE anything is written, then add the
|
|
3
|
+
// runtime dependencies the synced files import and install them with the
|
|
4
|
+
// app's own package manager. The template package.json is the source of the
|
|
5
|
+
// dependency list, so `create` and `init` apps depend on the same things.
|
|
6
|
+
import { spawnSync } from 'node:child_process';
|
|
7
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
8
|
+
import { createRequire } from 'node:module';
|
|
9
|
+
import { join, resolve } from 'node:path';
|
|
10
|
+
import { cliVersion, mapplesRuntimeSpec } from '../version.js';
|
|
11
|
+
import { templatesDir } from './scaffold.js';
|
|
12
|
+
function readPackageJson(root) {
|
|
13
|
+
return JSON.parse(readFileSync(join(root, 'package.json'), 'utf8'));
|
|
14
|
+
}
|
|
15
|
+
function hasDep(pkg, name) {
|
|
16
|
+
return Boolean(pkg.dependencies?.[name] ?? pkg.devDependencies?.[name]);
|
|
17
|
+
}
|
|
18
|
+
/** True when the app boots through expo-router (`main` is its entry, or a local entry file that imports it). */
|
|
19
|
+
function bootsExpoRouter(root, pkg) {
|
|
20
|
+
if (pkg.main === 'expo-router/entry')
|
|
21
|
+
return true;
|
|
22
|
+
if (!pkg.main)
|
|
23
|
+
return false; // Expo's default entry renders App.tsx
|
|
24
|
+
const entry = resolve(root, pkg.main);
|
|
25
|
+
const candidates = [entry, `${entry}.js`, `${entry}.ts`, `${entry}.tsx`];
|
|
26
|
+
const file = candidates.find((c) => existsSync(c));
|
|
27
|
+
return file ? /['"]expo-router\/entry['"]/.test(readFileSync(file, 'utf8')) : false;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Refuse an app `init` cannot make runnable. Mapples writes screens as
|
|
31
|
+
* expo-router route files (`app/(mapples)/…`), so the app must be an Expo app
|
|
32
|
+
* that boots expo-router, with its dependencies installed (the Expo SDK's
|
|
33
|
+
* native-module versions are read from the installed `expo`).
|
|
34
|
+
*/
|
|
35
|
+
export function assertLinkableApp(root) {
|
|
36
|
+
const pkg = readPackageJson(root);
|
|
37
|
+
if (!hasDep(pkg, 'expo')) {
|
|
38
|
+
throw new Error('`mapples init` links an Expo app, and this package.json has no `expo` dependency.\n' +
|
|
39
|
+
' Start a new app with `npx mapples create <name>` instead.');
|
|
40
|
+
}
|
|
41
|
+
if (!hasDep(pkg, 'expo-router') || !bootsExpoRouter(root, pkg)) {
|
|
42
|
+
throw new Error([
|
|
43
|
+
`this app does not use expo-router (package.json "main" is ${JSON.stringify(pkg.main ?? 'expo/AppEntry')}),`,
|
|
44
|
+
' but Mapples syncs screens as expo-router routes — nothing would render them. Nothing was changed.',
|
|
45
|
+
' Either start from `npx mapples create <name>` (a ready expo-router app), or move this app to',
|
|
46
|
+
' expo-router first (https://docs.expo.dev/router/installation/#modify-project-configuration):',
|
|
47
|
+
' npx expo install expo-router expo-linking expo-constants react-native-screens react-native-safe-area-context',
|
|
48
|
+
' set "main": "expo-router/entry" in package.json and a "scheme" in app.json (expo install adds the plugin),',
|
|
49
|
+
' move App.tsx into app/index.tsx — then re-run `mapples init`.',
|
|
50
|
+
].join('\n'));
|
|
51
|
+
}
|
|
52
|
+
bundledNativeModules(root); // throws when dependencies are not installed yet
|
|
53
|
+
}
|
|
54
|
+
function bundledNativeModules(root) {
|
|
55
|
+
const require = createRequire(join(root, 'package.json'));
|
|
56
|
+
let path;
|
|
57
|
+
try {
|
|
58
|
+
path = require.resolve('expo/bundledNativeModules.json');
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
throw new Error(`cannot find the installed \`expo\` package in ${root} — install the app's dependencies first, then re-run \`mapples init\``, { cause: err });
|
|
62
|
+
}
|
|
63
|
+
return JSON.parse(readFileSync(path, 'utf8'));
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Add every dependency of the `mapples create` app that this app lacks
|
|
67
|
+
* (never changes an existing entry). Versions: `@mapples/*` get the one
|
|
68
|
+
* runtime spec, Expo SDK modules the version the installed SDK bundles,
|
|
69
|
+
* everything else the template's. Returns what was added (empty = nothing to do)
|
|
70
|
+
* plus existing `@mapples/*` entries whose spec differs from the runtime spec.
|
|
71
|
+
*/
|
|
72
|
+
export function addRuntimeDependencies(root) {
|
|
73
|
+
const pkg = readPackageJson(root);
|
|
74
|
+
const template = JSON.parse(readFileSync(join(templatesDir(), 'package.json'), 'utf8'));
|
|
75
|
+
const bundled = bundledNativeModules(root);
|
|
76
|
+
const expoDeps = JSON.parse(readFileSync(createRequire(join(root, 'package.json')).resolve('expo/package.json'), 'utf8')).dependencies ?? {};
|
|
77
|
+
const runtime = mapplesRuntimeSpec();
|
|
78
|
+
const added = [];
|
|
79
|
+
const mismatched = [];
|
|
80
|
+
const specFor = (name, templateSpec) => {
|
|
81
|
+
if (name.startsWith('@mapples/'))
|
|
82
|
+
return runtime;
|
|
83
|
+
if (templateSpec === '__CLI_VERSION__')
|
|
84
|
+
return cliVersion();
|
|
85
|
+
// The installed SDK's own pins first (native modules, then expo's direct
|
|
86
|
+
// deps such as babel-preset-expo), the template's for everything else.
|
|
87
|
+
return bundled[name] ?? expoDeps[name] ?? templateSpec;
|
|
88
|
+
};
|
|
89
|
+
for (const [field, dev] of [
|
|
90
|
+
['dependencies', false],
|
|
91
|
+
['devDependencies', true],
|
|
92
|
+
]) {
|
|
93
|
+
for (const [name, templateSpec] of Object.entries(template[field] ?? {})) {
|
|
94
|
+
const existing = pkg.dependencies?.[name] ?? pkg.devDependencies?.[name];
|
|
95
|
+
if (existing) {
|
|
96
|
+
if (name.startsWith('@mapples/') && existing !== runtime) {
|
|
97
|
+
mismatched.push({ name, spec: existing, expected: runtime });
|
|
98
|
+
}
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
const spec = specFor(name, templateSpec);
|
|
102
|
+
pkg[field] = { ...(pkg[field] ?? {}), [name]: spec };
|
|
103
|
+
added.push({ name, spec, dev });
|
|
104
|
+
}
|
|
105
|
+
const deps = pkg[field];
|
|
106
|
+
if (deps)
|
|
107
|
+
pkg[field] = Object.fromEntries(Object.entries(deps).sort(([a], [b]) => a.localeCompare(b)));
|
|
108
|
+
}
|
|
109
|
+
if (added.length > 0)
|
|
110
|
+
writeFileSync(join(root, 'package.json'), JSON.stringify(pkg, null, 2) + '\n');
|
|
111
|
+
return { added, mismatched };
|
|
112
|
+
}
|
|
113
|
+
/** The app's package manager, from its lockfile (npm when there is none). */
|
|
114
|
+
export function detectPackageManager(root) {
|
|
115
|
+
if (existsSync(join(root, 'yarn.lock')))
|
|
116
|
+
return 'yarn';
|
|
117
|
+
if (existsSync(join(root, 'pnpm-lock.yaml')))
|
|
118
|
+
return 'pnpm';
|
|
119
|
+
if (existsSync(join(root, 'bun.lock')) || existsSync(join(root, 'bun.lockb')))
|
|
120
|
+
return 'bun';
|
|
121
|
+
return 'npm';
|
|
122
|
+
}
|
|
123
|
+
/** Run `<pm> install` in the app, output streamed. Throws when it fails. */
|
|
124
|
+
export function runInstall(root, pm) {
|
|
125
|
+
const result = spawnSync(pm, ['install'], { cwd: root, stdio: 'inherit' });
|
|
126
|
+
if (result.error)
|
|
127
|
+
throw result.error;
|
|
128
|
+
if (result.status !== 0) {
|
|
129
|
+
throw new Error(`\`${pm} install\` failed (exit ${result.status}) — package.json already lists the Mapples dependencies; fix the install and re-run \`mapples init\``);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=appDeps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"appDeps.js","sourceRoot":"","sources":["../../src/services/appDeps.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,wEAAwE;AACxE,yEAAyE;AACzE,4EAA4E;AAC5E,0EAA0E;AAE1E,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAW7C,SAAS,eAAe,CAAC,IAAY;IACnC,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAgB,CAAC;AACrF,CAAC;AAED,SAAS,MAAM,CAAC,GAAgB,EAAE,IAAY;IAC5C,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,eAAe,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;AAC1E,CAAC;AAED,gHAAgH;AAChH,SAAS,eAAe,CAAC,IAAY,EAAE,GAAgB;IACrD,IAAI,GAAG,CAAC,IAAI,KAAK,mBAAmB;QAAE,OAAO,IAAI,CAAC;IAClD,IAAI,CAAC,GAAG,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC,CAAC,uCAAuC;IACpE,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,KAAK,EAAE,GAAG,KAAK,KAAK,EAAE,GAAG,KAAK,MAAM,CAAC,CAAC;IACzE,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IACnD,OAAO,IAAI,CAAC,CAAC,CAAC,4BAA4B,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AACtF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,MAAM,GAAG,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CACb,qFAAqF;YACnF,6DAA6D,CAChE,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;QAC/D,MAAM,IAAI,KAAK,CACb;YACE,6DAA6D,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,IAAI,eAAe,CAAC,IAAI;YAC5G,qGAAqG;YACrG,gGAAgG;YAChG,gGAAgG;YAChG,kHAAkH;YAClH,gHAAgH;YAChH,mEAAmE;SACpE,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IACJ,CAAC;IACD,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,iDAAiD;AAC/E,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAY;IACxC,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC;IAC1D,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,gCAAgC,CAAC,CAAC;IAC3D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,iDAAiD,IAAI,uEAAuE,EAC5H,EAAE,KAAK,EAAE,GAAG,EAAE,CACf,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAA2B,CAAC;AAC1E,CAAC;AAQD;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAY;IAIjD,MAAM,GAAG,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CACzB,YAAY,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAC5C,CAAC;IACjB,MAAM,OAAO,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAEV,IAAI,CAAC,KAAK,CACR,YAAY,CACV,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,mBAAmB,CAAC,EACtE,MAAM,CACP,CAEJ,CAAC,YAAY,IAAI,EAAE,CAAC;IACvB,MAAM,OAAO,GAAG,kBAAkB,EAAE,CAAC;IACrC,MAAM,KAAK,GAAsB,EAAE,CAAC;IACpC,MAAM,UAAU,GAAuD,EAAE,CAAC;IAE1E,MAAM,OAAO,GAAG,CAAC,IAAY,EAAE,YAAoB,EAAU,EAAE;QAC7D,IAAI,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;YAAE,OAAO,OAAO,CAAC;QACjD,IAAI,YAAY,KAAK,iBAAiB;YAAE,OAAO,UAAU,EAAE,CAAC;QAC5D,yEAAyE;QACzE,uEAAuE;QACvE,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC;IACzD,CAAC,CAAC;IACF,KAAK,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI;QACzB,CAAC,cAAc,EAAE,KAAK,CAAC;QACvB,CAAC,iBAAiB,EAAE,IAAI,CAAC;KACjB,EAAE,CAAC;QACX,KAAK,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YACzE,MAAM,QAAQ,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,eAAe,EAAE,CAAC,IAAI,CAAC,CAAC;YACzE,IAAI,QAAQ,EAAE,CAAC;gBACb,IAAI,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;oBACzD,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;gBAC/D,CAAC;gBACD,SAAS;YACX,CAAC;YACD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;YACzC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC;YACrD,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;QAClC,CAAC;QACD,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;QACxB,IAAI,IAAI;YACN,GAAG,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACjG,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAClB,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACjF,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;AAC/B,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IACvD,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IAC5D,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5F,OAAO,KAAK,CAAC;AACf,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,EAAkB;IACzD,MAAM,MAAM,GAAG,SAAS,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IAC3E,IAAI,MAAM,CAAC,KAAK;QAAE,MAAM,MAAM,CAAC,KAAK,CAAC;IACrC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CACb,KAAK,EAAE,2BAA2B,MAAM,CAAC,MAAM,sGAAsG,CACtJ,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
export type DoctorIssueKind = 'missing-file' | 'duplicate-sid' | 'unknown-sid' | 'missing-sid' | 'orphaned-base' | 'drift' | 'no-head';
|
|
1
|
+
export type DoctorIssueKind = 'missing-file' | 'duplicate-sid' | 'unknown-sid' | 'missing-sid' | 'orphaned-base' | 'drift' | 'no-head' | 'foreign-layout' | 'stale-layout' | 'type-error' | 'no-typecheck';
|
|
2
|
+
/** Informational kinds: reported, but doctor still exits 0. */
|
|
3
|
+
export declare const INFO_KINDS: ReadonlySet<DoctorIssueKind>;
|
|
4
|
+
export interface DoctorCounts {
|
|
5
|
+
pages: number;
|
|
6
|
+
components: number;
|
|
7
|
+
layouts: number;
|
|
8
|
+
}
|
|
2
9
|
export interface DoctorIssue {
|
|
3
10
|
kind: DoctorIssueKind;
|
|
4
11
|
file?: string;
|
|
@@ -8,4 +15,15 @@ export interface DoctorIssue {
|
|
|
8
15
|
export declare function runDoctorChecks(root: string): {
|
|
9
16
|
issues: DoctorIssue[];
|
|
10
17
|
checkedFiles: number;
|
|
18
|
+
counts: DoctorCounts;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Typecheck the app with its own TypeScript (`tsc --noEmit -p .`): synced
|
|
22
|
+
* files that compile against the wrong @mapples/* types fail here, not on a
|
|
23
|
+
* device. Errors in any file are reported — an app that does not compile is
|
|
24
|
+
* not healthy whichever file is at fault.
|
|
25
|
+
*/
|
|
26
|
+
export declare function runTypecheck(root: string): {
|
|
27
|
+
issues: DoctorIssue[];
|
|
28
|
+
ran: boolean;
|
|
11
29
|
};
|
|
@@ -1,13 +1,23 @@
|
|
|
1
1
|
// `mapples doctor` — $sid lint (RFC-0002 Phase 8): duplicate/edited/missing
|
|
2
2
|
// $sids, orphaned base entries, drift (re-extract vs base at HEAD).
|
|
3
|
+
import { spawnSync } from 'node:child_process';
|
|
3
4
|
import { existsSync, readFileSync } from 'node:fs';
|
|
4
|
-
import {
|
|
5
|
+
import { createRequire } from 'node:module';
|
|
6
|
+
import { basename, join, relative, resolve } from 'node:path';
|
|
5
7
|
import { extract } from '@mapples/sid-ast';
|
|
8
|
+
import { buildNavPlan, chromeFilesFor, extractNavigatorDoc, GENERATED_LAYOUT_HEADER, } from '../nav/navigatorTree.js';
|
|
6
9
|
import { BaseStore } from '../project/baseStore.js';
|
|
10
|
+
import { readConfig } from '../project/config.js';
|
|
7
11
|
import { readHead } from '../project/head.js';
|
|
8
12
|
import { readComponentsMap } from '../project/componentsMap.js';
|
|
9
13
|
import { readPagesMap } from '../project/pagesMap.js';
|
|
10
14
|
import { deepEqual } from '../merge/mergePatch.js';
|
|
15
|
+
/** Informational kinds: reported, but doctor still exits 0. */
|
|
16
|
+
export const INFO_KINDS = new Set([
|
|
17
|
+
'drift',
|
|
18
|
+
'stale-layout',
|
|
19
|
+
'no-typecheck',
|
|
20
|
+
]);
|
|
11
21
|
function collectSids(root) {
|
|
12
22
|
const sids = new Set();
|
|
13
23
|
const walk = (n) => {
|
|
@@ -20,10 +30,11 @@ function collectSids(root) {
|
|
|
20
30
|
}
|
|
21
31
|
export function runDoctorChecks(root) {
|
|
22
32
|
const issues = [];
|
|
33
|
+
const counts = { pages: 0, components: 0, layouts: 0 };
|
|
23
34
|
const head = readHead(root);
|
|
24
35
|
if (!head) {
|
|
25
36
|
issues.push({ kind: 'no-head', detail: 'no .mapples/head — run `mapples sync` first' });
|
|
26
|
-
return { issues, checkedFiles: 0 };
|
|
37
|
+
return { issues, checkedFiles: 0, counts };
|
|
27
38
|
}
|
|
28
39
|
const base = new BaseStore(root).readAll();
|
|
29
40
|
let checkedFiles = 0;
|
|
@@ -68,6 +79,7 @@ export function runDoctorChecks(root) {
|
|
|
68
79
|
continue;
|
|
69
80
|
}
|
|
70
81
|
checkedFiles += 1;
|
|
82
|
+
counts[kind.label === 'page' ? 'pages' : 'components'] += 1;
|
|
71
83
|
const source = readFileSync(filePath, 'utf8');
|
|
72
84
|
const extracted = extract(source);
|
|
73
85
|
for (const w of extracted.warnings) {
|
|
@@ -120,7 +132,109 @@ export function runDoctorChecks(root) {
|
|
|
120
132
|
}
|
|
121
133
|
}
|
|
122
134
|
}
|
|
123
|
-
|
|
135
|
+
// CLI-owned layouts: every layout the navigation at HEAD plans must be
|
|
136
|
+
// there, generated, and current.
|
|
137
|
+
const { routesDir = 'app' } = readConfig(root);
|
|
138
|
+
const navDoc = extractNavigatorDoc(base.navigation);
|
|
139
|
+
if (navDoc) {
|
|
140
|
+
const pagesMap = readPagesMap(root);
|
|
141
|
+
const overrides = new Map();
|
|
142
|
+
for (const entry of Object.values(pagesMap)) {
|
|
143
|
+
if (entry.routeId)
|
|
144
|
+
overrides.set(entry.routeId, basename(entry.file, '.tsx'));
|
|
145
|
+
}
|
|
146
|
+
const chromeFiles = chromeFilesFor(base.components, readComponentsMap(root));
|
|
147
|
+
for (const layout of buildNavPlan(navDoc, base.pages, [], overrides, {
|
|
148
|
+
routesDir,
|
|
149
|
+
chromeFiles,
|
|
150
|
+
}).layouts) {
|
|
151
|
+
const rel = join(routesDir, layout.file);
|
|
152
|
+
const abs = join(root, rel);
|
|
153
|
+
if (!existsSync(abs)) {
|
|
154
|
+
issues.push({
|
|
155
|
+
kind: 'missing-file',
|
|
156
|
+
file: rel,
|
|
157
|
+
detail: 'navigator layout is missing — the next sync will regenerate it',
|
|
158
|
+
});
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
checkedFiles += 1;
|
|
162
|
+
counts.layouts += 1;
|
|
163
|
+
const current = readFileSync(abs, 'utf8');
|
|
164
|
+
if (!GENERATED_LAYOUT_HEADER.test(current)) {
|
|
165
|
+
issues.push({
|
|
166
|
+
kind: 'foreign-layout',
|
|
167
|
+
file: rel,
|
|
168
|
+
detail: 'this layout position is owned by the navigation, but the file lacks the GENERATED header — the next sync deprecates it (_depr_…)',
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
else if (current !== layout.content) {
|
|
172
|
+
issues.push({
|
|
173
|
+
kind: 'stale-layout',
|
|
174
|
+
file: rel,
|
|
175
|
+
detail: 'layout differs from what the navigation at HEAD generates — run `mapples sync`',
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return { issues, checkedFiles, counts };
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Typecheck the app with its own TypeScript (`tsc --noEmit -p .`): synced
|
|
184
|
+
* files that compile against the wrong @mapples/* types fail here, not on a
|
|
185
|
+
* device. Errors in any file are reported — an app that does not compile is
|
|
186
|
+
* not healthy whichever file is at fault.
|
|
187
|
+
*/
|
|
188
|
+
export function runTypecheck(root) {
|
|
189
|
+
if (!existsSync(join(root, 'tsconfig.json'))) {
|
|
190
|
+
return {
|
|
191
|
+
issues: [{ kind: 'no-typecheck', detail: 'no tsconfig.json — typecheck skipped' }],
|
|
192
|
+
ran: false,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
let tscPath;
|
|
196
|
+
try {
|
|
197
|
+
tscPath = createRequire(join(root, 'package.json')).resolve('typescript/bin/tsc');
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
// Not an error to hide: reported as its own (informational) issue.
|
|
201
|
+
return {
|
|
202
|
+
issues: [
|
|
203
|
+
{
|
|
204
|
+
kind: 'no-typecheck',
|
|
205
|
+
detail: 'typescript is not installed in this app — install dependencies to typecheck',
|
|
206
|
+
},
|
|
207
|
+
],
|
|
208
|
+
ran: false,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
const result = spawnSync(process.execPath, [tscPath, '--noEmit', '-p', root, '--pretty', 'false'], {
|
|
212
|
+
cwd: root,
|
|
213
|
+
encoding: 'utf8',
|
|
214
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
215
|
+
});
|
|
216
|
+
if (result.error)
|
|
217
|
+
throw result.error;
|
|
218
|
+
const issues = [];
|
|
219
|
+
const output = `${result.stdout}${result.stderr}`;
|
|
220
|
+
for (const line of output.split('\n')) {
|
|
221
|
+
const m = /^(.+?)\((\d+),(\d+)\): error (TS\d+): (.*)$/.exec(line);
|
|
222
|
+
if (m) {
|
|
223
|
+
const file = relative(root, resolve(root, m[1]));
|
|
224
|
+
issues.push({
|
|
225
|
+
kind: 'type-error',
|
|
226
|
+
file: `${file}:${m[2]}:${m[3]}`,
|
|
227
|
+
detail: `${m[4]} ${m[5]}`,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
else if (line.startsWith(' ') && issues.length > 0) {
|
|
231
|
+
issues[issues.length - 1].detail += `\n ${line.trim()}`;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
if (result.status !== 0 && issues.length === 0) {
|
|
235
|
+
issues.push({ kind: 'type-error', detail: `tsc exited ${result.status}:\n${output.trim()}` });
|
|
236
|
+
}
|
|
237
|
+
return { issues, ran: true };
|
|
124
238
|
}
|
|
125
239
|
/** Fill NON_LITERAL holes from base so expression props don't read as drift. */
|
|
126
240
|
function stripNonLiteralHoles(local, baseRoot) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctorService.js","sourceRoot":"","sources":["../../src/services/doctorService.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,oEAAoE;AAEpE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"doctorService.js","sourceRoot":"","sources":["../../src/services/doctorService.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
export declare function templatesDir(): string;
|
|
2
|
+
export interface ScaffoldOptions {
|
|
3
|
+
/** The Creator project's identifier → app.json ios.bundleIdentifier / android.package. */
|
|
4
|
+
identifier?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface ScaffoldResult {
|
|
7
|
+
written: string[];
|
|
8
|
+
/** Lossy steps the caller must surface (e.g. an identifier a platform rejects). */
|
|
9
|
+
warnings: string[];
|
|
10
|
+
}
|
|
2
11
|
/** Copy the app-shell templates into `target`, substituting __APP_NAME__. Never overwrites. */
|
|
3
|
-
export declare function scaffoldApp(target: string, appName: string):
|
|
12
|
+
export declare function scaffoldApp(target: string, appName: string, options?: ScaffoldOptions): ScaffoldResult;
|
|
4
13
|
/** Write mapples/sid.d.ts into an existing app (init). Never overwrites. */
|
|
5
14
|
export declare function writeSidTypes(root: string): boolean;
|
|
15
|
+
/** Ensure @mapples/app's Metro resolver is wired (mapples/theme.ts, mapples/assetMap.ts).
|
|
16
|
+
* Creates metro.config.js when absent; never edits an existing one. */
|
|
17
|
+
export declare function ensureMetroConfig(root: string): 'created' | 'present' | 'manual';
|
|
6
18
|
/** Ensure babel-plugin-mapples-sid is wired. Creates babel.config.js when absent; never edits an existing one. */
|
|
7
19
|
export declare function ensureBabelPlugin(root: string): 'created' | 'present' | 'manual';
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { dirname, join } from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
|
-
import {
|
|
5
|
+
import { isValidAndroidPackage, isValidBundleIdentifier } from '../api/project.js';
|
|
6
|
+
import { cliVersion, mapplesRuntimeSpec } from '../version.js';
|
|
6
7
|
export function templatesDir() {
|
|
7
8
|
// dist/services/scaffold.js -> ../../templates
|
|
8
9
|
return fileURLToPath(new URL('../../templates/', import.meta.url));
|
|
@@ -11,8 +12,10 @@ const RENAMES = { gitignore: '.gitignore' };
|
|
|
11
12
|
/** Template subtrees that are not part of the app shell (installed by their own service). */
|
|
12
13
|
const NOT_APP_SHELL = new Set(['agent']);
|
|
13
14
|
/** Copy the app-shell templates into `target`, substituting __APP_NAME__. Never overwrites. */
|
|
14
|
-
export function scaffoldApp(target, appName) {
|
|
15
|
+
export function scaffoldApp(target, appName, options = {}) {
|
|
15
16
|
const written = [];
|
|
17
|
+
const warnings = [];
|
|
18
|
+
const runtime = mapplesRuntimeSpec();
|
|
16
19
|
const src = templatesDir();
|
|
17
20
|
const walk = (rel) => {
|
|
18
21
|
for (const entry of readdirSync(join(src, rel), { withFileTypes: true })) {
|
|
@@ -28,15 +31,52 @@ export function scaffoldApp(target, appName) {
|
|
|
28
31
|
if (existsSync(outPath))
|
|
29
32
|
continue; // never overwrite
|
|
30
33
|
mkdirSync(dirname(outPath), { recursive: true });
|
|
31
|
-
|
|
34
|
+
let content = readFileSync(join(src, relPath), 'utf8')
|
|
32
35
|
.replaceAll('__APP_NAME__', appName)
|
|
33
|
-
.replaceAll('__CLI_VERSION__', cliVersion())
|
|
36
|
+
.replaceAll('__CLI_VERSION__', cliVersion())
|
|
37
|
+
.replaceAll('__MAPPLES_RUNTIME__', runtime);
|
|
38
|
+
if (relPath === 'package.json')
|
|
39
|
+
content = pinMapplesRuntime(content, runtime);
|
|
40
|
+
if (relPath === 'app.json' && options.identifier) {
|
|
41
|
+
content = withStoreIdentity(content, options.identifier, warnings);
|
|
42
|
+
}
|
|
34
43
|
writeFileSync(outPath, content);
|
|
35
44
|
written.push(outRel);
|
|
36
45
|
}
|
|
37
46
|
};
|
|
38
47
|
walk('');
|
|
39
|
-
return written;
|
|
48
|
+
return { written, warnings };
|
|
49
|
+
}
|
|
50
|
+
/** Every @mapples/* dependency gets the one runtime spec (fixed Changesets group) — whatever version a template edit wrote. */
|
|
51
|
+
function pinMapplesRuntime(content, runtime) {
|
|
52
|
+
const pkg = JSON.parse(content);
|
|
53
|
+
for (const field of ['dependencies', 'devDependencies']) {
|
|
54
|
+
const deps = pkg[field];
|
|
55
|
+
if (!deps)
|
|
56
|
+
continue;
|
|
57
|
+
for (const name of Object.keys(deps)) {
|
|
58
|
+
if (name.startsWith('@mapples/'))
|
|
59
|
+
deps[name] = runtime;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return JSON.stringify(pkg, null, 2) + '\n';
|
|
63
|
+
}
|
|
64
|
+
/** Write the Creator project's identifier as the native store identity, so `expo prebuild` does not invent one. */
|
|
65
|
+
function withStoreIdentity(content, identifier, warnings) {
|
|
66
|
+
const appJson = JSON.parse(content);
|
|
67
|
+
if (isValidBundleIdentifier(identifier)) {
|
|
68
|
+
appJson.expo.ios = { ...appJson.expo.ios, bundleIdentifier: identifier };
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
warnings.push(`project identifier “${identifier}” is not a valid iOS bundle identifier — set expo.ios.bundleIdentifier in app.json yourself`);
|
|
72
|
+
}
|
|
73
|
+
if (isValidAndroidPackage(identifier)) {
|
|
74
|
+
appJson.expo.android = { ...appJson.expo.android, package: identifier };
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
warnings.push(`project identifier “${identifier}” is not a valid Android package name — set expo.android.package in app.json yourself`);
|
|
78
|
+
}
|
|
79
|
+
return JSON.stringify(appJson, null, 2) + '\n';
|
|
40
80
|
}
|
|
41
81
|
/** Write mapples/sid.d.ts into an existing app (init). Never overwrites. */
|
|
42
82
|
export function writeSidTypes(root) {
|
|
@@ -47,6 +87,18 @@ export function writeSidTypes(root) {
|
|
|
47
87
|
cpSync(join(templatesDir(), 'mapples', 'sid.d.ts'), target);
|
|
48
88
|
return true;
|
|
49
89
|
}
|
|
90
|
+
/** Ensure @mapples/app's Metro resolver is wired (mapples/theme.ts, mapples/assetMap.ts).
|
|
91
|
+
* Creates metro.config.js when absent; never edits an existing one. */
|
|
92
|
+
export function ensureMetroConfig(root) {
|
|
93
|
+
const configPath = join(root, 'metro.config.js');
|
|
94
|
+
if (!existsSync(configPath)) {
|
|
95
|
+
cpSync(join(templatesDir(), 'metro.config.js'), configPath);
|
|
96
|
+
return 'created';
|
|
97
|
+
}
|
|
98
|
+
if (readFileSync(configPath, 'utf8').includes('mapplesResolver'))
|
|
99
|
+
return 'present';
|
|
100
|
+
return 'manual';
|
|
101
|
+
}
|
|
50
102
|
/** Ensure babel-plugin-mapples-sid is wired. Creates babel.config.js when absent; never edits an existing one. */
|
|
51
103
|
export function ensureBabelPlugin(root) {
|
|
52
104
|
const configPath = join(root, 'babel.config.js');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../src/services/scaffold.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAE7D,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClG,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../src/services/scaffold.ts"],"names":[],"mappings":"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"}
|