mapples 0.2.0-beta.9 → 0.2.0

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 (87) hide show
  1. package/README.md +1 -1
  2. package/dist/api/client.d.ts +16 -0
  3. package/dist/api/client.js +37 -0
  4. package/dist/api/client.js.map +1 -1
  5. package/dist/api/commit.js +19 -1
  6. package/dist/api/commit.js.map +1 -1
  7. package/dist/api/errors.d.ts +1 -1
  8. package/dist/api/errors.js +3 -0
  9. package/dist/api/errors.js.map +1 -1
  10. package/dist/api/objects.d.ts +3 -1
  11. package/dist/api/objects.js +31 -4
  12. package/dist/api/objects.js.map +1 -1
  13. package/dist/api/project.d.ts +11 -0
  14. package/dist/api/project.js +29 -0
  15. package/dist/api/project.js.map +1 -0
  16. package/dist/assets/assets.d.ts +12 -0
  17. package/dist/assets/assets.js +31 -2
  18. package/dist/assets/assets.js.map +1 -1
  19. package/dist/codegen/imports.d.ts +7 -0
  20. package/dist/codegen/imports.js +31 -0
  21. package/dist/codegen/imports.js.map +1 -1
  22. package/dist/commands/doctor.js +3 -1
  23. package/dist/commands/doctor.js.map +1 -1
  24. package/dist/commands/impl/createImpl.js +34 -4
  25. package/dist/commands/impl/createImpl.js.map +1 -1
  26. package/dist/commands/impl/doctorImpl.js +17 -7
  27. package/dist/commands/impl/doctorImpl.js.map +1 -1
  28. package/dist/commands/impl/initImpl.js +47 -1
  29. package/dist/commands/impl/initImpl.js.map +1 -1
  30. package/dist/commands/impl/syncImpl.js +16 -2
  31. package/dist/commands/impl/syncImpl.js.map +1 -1
  32. package/dist/commands/init.js +1 -0
  33. package/dist/commands/init.js.map +1 -1
  34. package/dist/nav/navigatorTree.d.ts +36 -2
  35. package/dist/nav/navigatorTree.js +191 -40
  36. package/dist/nav/navigatorTree.js.map +1 -1
  37. package/dist/nav/routeTree.d.ts +2 -1
  38. package/dist/nav/routeTree.js +9 -4
  39. package/dist/nav/routeTree.js.map +1 -1
  40. package/dist/nav/screenOptions.d.ts +24 -0
  41. package/dist/nav/screenOptions.js +41 -13
  42. package/dist/nav/screenOptions.js.map +1 -1
  43. package/dist/packages/catalog.d.ts +20 -0
  44. package/dist/packages/catalog.js +94 -0
  45. package/dist/packages/catalog.js.map +1 -0
  46. package/dist/packages/resolve.d.ts +61 -0
  47. package/dist/packages/resolve.js +149 -0
  48. package/dist/packages/resolve.js.map +1 -0
  49. package/dist/runtime/runtimeFiles.d.ts +17 -0
  50. package/dist/runtime/runtimeFiles.js +183 -0
  51. package/dist/runtime/runtimeFiles.js.map +1 -0
  52. package/dist/services/appDeps.d.ts +41 -0
  53. package/dist/services/appDeps.js +152 -0
  54. package/dist/services/appDeps.js.map +1 -0
  55. package/dist/services/appPackages.d.ts +46 -0
  56. package/dist/services/appPackages.js +266 -0
  57. package/dist/services/appPackages.js.map +1 -0
  58. package/dist/services/doctorService.d.ts +28 -1
  59. package/dist/services/doctorService.js +217 -3
  60. package/dist/services/doctorService.js.map +1 -1
  61. package/dist/services/scaffold.d.ts +13 -1
  62. package/dist/services/scaffold.js +57 -5
  63. package/dist/services/scaffold.js.map +1 -1
  64. package/dist/services/syncEngine.js +89 -25
  65. package/dist/services/syncEngine.js.map +1 -1
  66. package/dist/types.d.ts +4 -0
  67. package/dist/types.js.map +1 -1
  68. package/dist/ui/report.d.ts +8 -0
  69. package/dist/ui/report.js +22 -0
  70. package/dist/ui/report.js.map +1 -1
  71. package/dist/version.d.ts +21 -0
  72. package/dist/version.js +40 -3
  73. package/dist/version.js.map +1 -1
  74. package/package.json +4 -3
  75. package/templates/agent/mapples.md +9 -4
  76. package/templates/agent/skills/mapples-conventions/SKILL.md +5 -4
  77. package/templates/agent/skills/mapples-design/SKILL.md +4 -4
  78. package/templates/agent/skills/mapples-design/reference/component-library.md +3 -3
  79. package/templates/agent/skills/mapples-design/reference/layout-contract.md +2 -3
  80. package/templates/agent/skills/mapples-design/reference/playbooks/onboarding-flow.md +1 -1
  81. package/templates/agent/skills/mapples-design/reference/playbooks/screen-flow-wiring.md +2 -5
  82. package/templates/agent/skills/mapples-design/reference/style-guides.md +2 -0
  83. package/templates/agent/skills/mapples-sync/SKILL.md +3 -2
  84. package/templates/app/_layout.tsx +6 -1
  85. package/templates/gitignore +2 -0
  86. package/templates/metro.config.js +11 -0
  87. package/templates/package.json +27 -33
@@ -0,0 +1,183 @@
1
+ // The documents the exported app's behaviour runtime executes (@mapples/app
2
+ // `MapplesApp` → `MapplesRuntime`), written next to theme.ts and resolved by
3
+ // `mapplesResolver` (`@mapples/app/expo`) as `mapples::navigation`,
4
+ // `mapples::api` and `mapples::variables`:
5
+ //
6
+ // mapples/navigation.ts — the navigation document (guards, on-enter actions,
7
+ // navigate targets) + each route's expo-router
8
+ // screen names, from the same plan as the layouts.
9
+ // mapples/api.ts — the API document (requests, environments), the
10
+ // secrets its requests name, read from
11
+ // EXPO_PUBLIC_MAPPLES_SECRET_<NAME>, and the
12
+ // environment override EXPO_PUBLIC_MAPPLES_API_ENVIRONMENT.
13
+ // mapples/variables.ts — the project variables (`vars.*`).
14
+ //
15
+ // All three are CLI-OWNED like `_layout.tsx`: regenerated every sync, never
16
+ // pushed back (Creator edits these documents), a user file in their place is
17
+ // deprecated, never overwritten.
18
+ //
19
+ // Secrets outside Creator: Creator runs requests through its backend proxy,
20
+ // which holds the project's secrets. An exported app has no such proxy, so
21
+ // the default transport calls the API directly and applies each request's
22
+ // auth from build-time `EXPO_PUBLIC_MAPPLES_SECRET_<NAME>` variables
23
+ // (`.env.local`). Those values are compiled into the app bundle — fine for
24
+ // publishable/anon keys (Supabase `apikey`, public API keys), wrong for
25
+ // anything that must stay secret: route such requests through your own
26
+ // backend by passing `transport` to `MapplesApp`.
27
+ import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
28
+ import { dirname, join, relative } from 'node:path';
29
+ import { ProjectDocumentError } from '../api/client.js';
30
+ import { deprecateFile } from '../merge/deprecate.js';
31
+ export const NAVIGATION_MODULE = join('mapples', 'navigation.ts');
32
+ export const API_MODULE = join('mapples', 'api.ts');
33
+ export const VARIABLES_MODULE = join('mapples', 'variables.ts');
34
+ const HEADER = /^\/\/\s*GENERATED by Mapples/;
35
+ function header(what) {
36
+ return [
37
+ `// GENERATED by Mapples — DO NOT EDIT. ${what}`,
38
+ '// Regenerated on every `mapples sync`; edit it in Creator instead.',
39
+ '// @mapples/app runs it (MapplesApp reads this file through `mapplesResolver`).',
40
+ ].join('\n');
41
+ }
42
+ const json = (value) => JSON.stringify(value, null, 2);
43
+ /**
44
+ * Write a CLI-owned module. A file there the CLI did not generate is the
45
+ * user's: deprecated (`_depr_<ts>_…`), never overwritten; `content: null`
46
+ * removes a generated one whose document is gone.
47
+ */
48
+ function writeOwnedModule(root, file, content, report) {
49
+ const abs = join(root, file);
50
+ const existed = existsSync(abs);
51
+ if (existed) {
52
+ const current = readFileSync(abs, 'utf8');
53
+ if (current === content)
54
+ return;
55
+ if (!HEADER.test(current)) {
56
+ const deprecated = relative(root, deprecateFile(abs));
57
+ report.files.push({
58
+ file,
59
+ action: 'deprecated',
60
+ detail: `${file} is generated from Creator — yours is kept at ${deprecated}`,
61
+ });
62
+ }
63
+ else if (content === null) {
64
+ unlinkSync(abs);
65
+ report.files.push({
66
+ file,
67
+ action: 'deprecated',
68
+ detail: 'generated for a Creator document that is gone — removed',
69
+ });
70
+ return;
71
+ }
72
+ }
73
+ if (content === null)
74
+ return;
75
+ mkdirSync(dirname(abs), { recursive: true });
76
+ writeFileSync(abs, content);
77
+ report.files.push({
78
+ file,
79
+ action: existed ? 'updated' : 'created',
80
+ detail: 'CLI-owned runtime document',
81
+ });
82
+ }
83
+ /** `mapples/navigation.ts`: the navigation document and each route's screen names. */
84
+ export function writeNavigationModule(root, navigation, screensByRoute, report) {
85
+ const routes = Object.fromEntries([...screensByRoute].sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)));
86
+ const content = [
87
+ header('The Creator navigation the app runtime executes.'),
88
+ "import type { NavigationDocument } from '@mapples/types';",
89
+ '',
90
+ '/** Guards, on-enter actions and navigate targets resolve against this document. */',
91
+ `export const navigation = ${json(navigation)} as NavigationDocument;`,
92
+ '',
93
+ '/** Route id → its expo-router screen names, from the root navigator down. */',
94
+ `export const routes: Record<string, string[]> = ${json(routes)};`,
95
+ '',
96
+ ].join('\n');
97
+ writeOwnedModule(root, NAVIGATION_MODULE, content, report);
98
+ }
99
+ /** The env variable a secret reads from: `API_KEY` → `EXPO_PUBLIC_MAPPLES_SECRET_API_KEY`. */
100
+ export function secretEnvName(secretRef) {
101
+ return `EXPO_PUBLIC_MAPPLES_SECRET_${secretRef.toUpperCase().replace(/[^A-Z0-9]+/g, '_')}`;
102
+ }
103
+ function apiModule(document) {
104
+ // Response samples are design-time data for Creator's pickers and preview;
105
+ // the app only ever shows real responses.
106
+ const requests = {};
107
+ const secretRefs = new Set();
108
+ for (const [id, request] of Object.entries(document.requests ?? {})) {
109
+ const rest = { ...request };
110
+ delete rest.responseSample;
111
+ requests[id] = rest;
112
+ if (request.auth?.secretRef)
113
+ secretRefs.add(request.auth.secretRef);
114
+ }
115
+ const refs = [...secretRefs].sort();
116
+ // Expo inlines `process.env.EXPO_PUBLIC_*` only as literal member reads.
117
+ const secretLines = refs.map((ref) => ` ${JSON.stringify(ref)}: process.env.${secretEnvName(ref)},`);
118
+ return [
119
+ header('The Creator API requests the app runtime executes.'),
120
+ "import type { ApiDocument } from '@mapples/types';",
121
+ '',
122
+ `export const api = ${json({ ...document, requests })} as ApiDocument;`,
123
+ '',
124
+ '/**',
125
+ ' * Secrets the requests name, from build-time env variables (put them in',
126
+ ' * `.env.local`). They are compiled into the app bundle: only use this for',
127
+ ' * keys that are safe to ship in a client (publishable / anon keys). For',
128
+ ' * real secrets pass your own `transport` to <MapplesApp> and keep them on',
129
+ ' * a server.',
130
+ ...(refs.length > 0
131
+ ? [' *', ...refs.map((ref) => ` * ${secretEnvName(ref)} (${ref})`)]
132
+ : []),
133
+ ' */',
134
+ `export const secrets: Record<string, string | undefined> = {${secretLines.length > 0 ? `\n${secretLines.join('\n')}\n` : ''}};`,
135
+ '',
136
+ '/** The environment to run against (its name or id); unset → the one active in Creator. */',
137
+ 'export const environment = process.env.EXPO_PUBLIC_MAPPLES_API_ENVIRONMENT;',
138
+ '',
139
+ ].join('\n');
140
+ }
141
+ function variablesModule(document) {
142
+ return [
143
+ header('The Creator variables (`vars.*`) the app runtime holds.'),
144
+ "import type { VariablesDocument } from '@mapples/types';",
145
+ '',
146
+ `export const variables = ${json(document)} as VariablesDocument;`,
147
+ '',
148
+ ].join('\n');
149
+ }
150
+ /**
151
+ * Pull the API and variables documents and write their runtime modules. A
152
+ * project without one gets no module (the runtime is inert for it). A
153
+ * document the backend refuses to hand to this project key is reported —
154
+ * the app then runs without it — and its last generated module is left as
155
+ * it was rather than guessed at.
156
+ */
157
+ export async function syncRuntimeDocuments(root, client, report) {
158
+ const documents = [
159
+ { kind: 'apidef', file: API_MODULE, render: apiModule, label: 'API requests' },
160
+ {
161
+ kind: 'variablesdef',
162
+ file: VARIABLES_MODULE,
163
+ render: variablesModule,
164
+ label: 'variables',
165
+ },
166
+ ];
167
+ for (const { kind, file, render, label } of documents) {
168
+ let document;
169
+ try {
170
+ document = await client.projectDocument(kind);
171
+ }
172
+ catch (err) {
173
+ if (!(err instanceof ProjectDocumentError) || (err.status !== 401 && err.status !== 403)) {
174
+ throw err;
175
+ }
176
+ report.notes.push(`runtime: the Creator ${label} were not pulled — the backend refuses this project key for ${kind} (${err.message}). ` +
177
+ `The app runs without them until it allows it; ${file} is left as it was.`);
178
+ continue;
179
+ }
180
+ writeOwnedModule(root, file, document === null ? null : render(document), report);
181
+ }
182
+ }
183
+ //# sourceMappingURL=runtimeFiles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtimeFiles.js","sourceRoot":"","sources":["../../src/runtime/runtimeFiles.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ export type PackageManager = 'yarn' | 'pnpm' | 'bun' | 'npm';
2
+ /**
3
+ * Refuse an app `init` cannot make runnable. Mapples writes screens as
4
+ * expo-router route files (`app/(mapples)/…`), so the app must be an Expo app
5
+ * that boots expo-router, with its dependencies installed (the Expo SDK's
6
+ * native-module versions are read from the installed `expo`).
7
+ */
8
+ export declare function assertLinkableApp(root: string): void;
9
+ /**
10
+ * The installed Expo SDK's native-module pins (`expo/bundledNativeModules.json`),
11
+ * or `null` when the app's dependencies are not installed yet (a fresh
12
+ * `mapples create`) — callers then use the versions they were given.
13
+ */
14
+ export declare function installedSdkPins(root: string): Record<string, string> | null;
15
+ export interface AddedDependency {
16
+ name: string;
17
+ spec: string;
18
+ dev: boolean;
19
+ }
20
+ /**
21
+ * Add every dependency of the `mapples create` app that this app lacks
22
+ * (never changes an existing entry). Versions: `@mapples/*` get the one
23
+ * runtime spec, Expo SDK modules the version the installed SDK bundles,
24
+ * everything else the template's. Returns what was added (empty = nothing to do)
25
+ * plus existing `@mapples/*` entries whose spec differs from the runtime spec.
26
+ */
27
+ export declare function addRuntimeDependencies(root: string): {
28
+ added: AddedDependency[];
29
+ mismatched: {
30
+ name: string;
31
+ spec: string;
32
+ expected: string;
33
+ }[];
34
+ };
35
+ /** The app's package manager, from its lockfile (npm when there is none). */
36
+ export declare function detectPackageManager(root: string): PackageManager;
37
+ /**
38
+ * Run `<pm> install` in the app, output streamed. Throws when it fails;
39
+ * `retry` is what the user runs once the install is fixed.
40
+ */
41
+ export declare function runInstall(root: string, pm: PackageManager, retry?: string): void;
@@ -0,0 +1,152 @@
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
+ * The installed Expo SDK's native-module pins (`expo/bundledNativeModules.json`),
67
+ * or `null` when the app's dependencies are not installed yet (a fresh
68
+ * `mapples create`) — callers then use the versions they were given.
69
+ */
70
+ export function installedSdkPins(root) {
71
+ let path;
72
+ try {
73
+ path = createRequire(join(root, 'package.json')).resolve('expo/bundledNativeModules.json');
74
+ }
75
+ catch (err) {
76
+ if (err.code === 'MODULE_NOT_FOUND')
77
+ return null;
78
+ throw err;
79
+ }
80
+ return JSON.parse(readFileSync(path, 'utf8'));
81
+ }
82
+ /**
83
+ * Add every dependency of the `mapples create` app that this app lacks
84
+ * (never changes an existing entry). Versions: `@mapples/*` get the one
85
+ * runtime spec, Expo SDK modules the version the installed SDK bundles,
86
+ * everything else the template's. Returns what was added (empty = nothing to do)
87
+ * plus existing `@mapples/*` entries whose spec differs from the runtime spec.
88
+ */
89
+ export function addRuntimeDependencies(root) {
90
+ const pkg = readPackageJson(root);
91
+ const template = JSON.parse(readFileSync(join(templatesDir(), 'package.json'), 'utf8'));
92
+ const bundled = bundledNativeModules(root);
93
+ const expoDeps = JSON.parse(readFileSync(createRequire(join(root, 'package.json')).resolve('expo/package.json'), 'utf8')).dependencies ?? {};
94
+ const runtime = mapplesRuntimeSpec();
95
+ const added = [];
96
+ const mismatched = [];
97
+ const specFor = (name, templateSpec) => {
98
+ if (name.startsWith('@mapples/'))
99
+ return runtime;
100
+ if (templateSpec === '__CLI_VERSION__')
101
+ return cliVersion();
102
+ // The installed SDK's own pins first (native modules, then expo's direct
103
+ // deps such as babel-preset-expo), the template's for everything else.
104
+ return bundled[name] ?? expoDeps[name] ?? templateSpec;
105
+ };
106
+ for (const [field, dev] of [
107
+ ['dependencies', false],
108
+ ['devDependencies', true],
109
+ ]) {
110
+ for (const [name, templateSpec] of Object.entries(template[field] ?? {})) {
111
+ const existing = pkg.dependencies?.[name] ?? pkg.devDependencies?.[name];
112
+ if (existing) {
113
+ if (name.startsWith('@mapples/') && existing !== runtime) {
114
+ mismatched.push({ name, spec: existing, expected: runtime });
115
+ }
116
+ continue;
117
+ }
118
+ const spec = specFor(name, templateSpec);
119
+ pkg[field] = { ...(pkg[field] ?? {}), [name]: spec };
120
+ added.push({ name, spec, dev });
121
+ }
122
+ const deps = pkg[field];
123
+ if (deps)
124
+ pkg[field] = Object.fromEntries(Object.entries(deps).sort(([a], [b]) => a.localeCompare(b)));
125
+ }
126
+ if (added.length > 0)
127
+ writeFileSync(join(root, 'package.json'), JSON.stringify(pkg, null, 2) + '\n');
128
+ return { added, mismatched };
129
+ }
130
+ /** The app's package manager, from its lockfile (npm when there is none). */
131
+ export function detectPackageManager(root) {
132
+ if (existsSync(join(root, 'yarn.lock')))
133
+ return 'yarn';
134
+ if (existsSync(join(root, 'pnpm-lock.yaml')))
135
+ return 'pnpm';
136
+ if (existsSync(join(root, 'bun.lock')) || existsSync(join(root, 'bun.lockb')))
137
+ return 'bun';
138
+ return 'npm';
139
+ }
140
+ /**
141
+ * Run `<pm> install` in the app, output streamed. Throws when it fails;
142
+ * `retry` is what the user runs once the install is fixed.
143
+ */
144
+ export function runInstall(root, pm, retry = '`mapples init`') {
145
+ const result = spawnSync(pm, ['install'], { cwd: root, stdio: 'inherit' });
146
+ if (result.error)
147
+ throw result.error;
148
+ if (result.status !== 0) {
149
+ throw new Error(`\`${pm} install\` failed (exit ${result.status}) — package.json already lists the Mapples dependencies; fix the install and re-run ${retry}`);
150
+ }
151
+ }
152
+ //# sourceMappingURL=appDeps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"appDeps.js","sourceRoot":"","sources":["../../src/services/appDeps.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import { type JpatchClient } from '../api/client.js';
2
+ import { type PackagesDocument } from '../packages/resolve.js';
3
+ import { type PackageManager } from './appDeps.js';
4
+ export declare const PACKAGES_STATE_FILE: string;
5
+ export interface PackagesOutcome {
6
+ /** `document`: read from the project's packages document; `canvas`: derived (no document yet). */
7
+ source: 'document' | 'canvas';
8
+ iconFamily: string;
9
+ added: {
10
+ name: string;
11
+ spec: string;
12
+ package: string;
13
+ }[];
14
+ removed: {
15
+ name: string;
16
+ spec: string;
17
+ }[];
18
+ /** Not needed by the project any more, left in place — remove by hand if unused. */
19
+ removable: {
20
+ name: string;
21
+ reason: string;
22
+ }[];
23
+ pluginsAdded: string[];
24
+ pluginsRemoved: string[];
25
+ /** Plugins to register by hand (the app config is code, not app.json). */
26
+ pluginsManual: string[];
27
+ /** package.json changed: the app needs `<pm> install`. */
28
+ installNeeded: boolean;
29
+ packageManager: PackageManager;
30
+ notes: string[];
31
+ }
32
+ /** The project's packages document, `null` when it has none yet (404). Any other refusal stops the command. */
33
+ export declare function fetchPackagesDocument(client: JpatchClient): Promise<PackagesDocument | null>;
34
+ /**
35
+ * Bring package.json (and app.json's plugins) in line with the project's
36
+ * packages. Reads the synced canvas from the base, so call it after a
37
+ * successful sync. A transport failure propagates (the caller reports
38
+ * offline); a refused or malformed document stops the command.
39
+ */
40
+ export declare function syncAppPackages(root: string, client: JpatchClient): Promise<PackagesOutcome | {
41
+ skipped: string;
42
+ }>;
43
+ /** Human lines for the command output (the JSON report carries the outcome itself). */
44
+ export declare function renderPackagesOutcome(outcome: PackagesOutcome | {
45
+ skipped: string;
46
+ }): string[];