@dimina-kit/devtools 0.3.1 → 0.3.2-dev.20260522085907

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 (190) hide show
  1. package/README.md +297 -133
  2. package/dist/main/api.d.ts +6 -2
  3. package/dist/main/api.js +5 -2
  4. package/dist/main/app/app.d.ts +1 -1
  5. package/dist/main/app/app.js +84 -36
  6. package/dist/main/app/bootstrap.js +2 -1
  7. package/dist/main/app/launch.d.ts +2 -2
  8. package/dist/main/app/launch.js +10 -8
  9. package/dist/main/index.bundle.js +1567 -477
  10. package/dist/main/ipc/app.d.ts +2 -1
  11. package/dist/main/ipc/app.js +5 -4
  12. package/dist/main/ipc/index.d.ts +5 -4
  13. package/dist/main/ipc/index.js +5 -4
  14. package/dist/main/ipc/panels.d.ts +2 -1
  15. package/dist/main/ipc/panels.js +16 -13
  16. package/dist/main/ipc/popover.d.ts +4 -1
  17. package/dist/main/ipc/popover.js +15 -5
  18. package/dist/main/ipc/projects.d.ts +6 -1
  19. package/dist/main/ipc/projects.js +127 -6
  20. package/dist/main/ipc/session.d.ts +4 -1
  21. package/dist/main/ipc/session.js +34 -6
  22. package/dist/main/ipc/settings.d.ts +4 -1
  23. package/dist/main/ipc/settings.js +51 -23
  24. package/dist/main/ipc/simulator-module.d.ts +8 -0
  25. package/dist/main/ipc/simulator-module.js +19 -0
  26. package/dist/main/ipc/simulator.d.ts +2 -1
  27. package/dist/main/ipc/simulator.js +23 -18
  28. package/dist/main/ipc/toolbar.d.ts +2 -1
  29. package/dist/main/ipc/toolbar.js +3 -2
  30. package/dist/main/menu/index.js +11 -0
  31. package/dist/main/services/automation/exec.d.ts +2 -0
  32. package/dist/main/services/automation/exec.js +7 -9
  33. package/dist/main/services/automation/handlers/app.js +37 -51
  34. package/dist/main/services/automation/handlers/element.js +27 -41
  35. package/dist/main/services/automation/index.js +88 -13
  36. package/dist/main/services/default-adapter.js +3 -3
  37. package/dist/main/services/mcp/index.d.ts +1 -0
  38. package/dist/main/services/mcp/index.js +1 -0
  39. package/dist/main/services/mcp/server.d.ts +2 -1
  40. package/dist/main/services/mcp/server.js +10 -0
  41. package/dist/main/services/mcp/status.d.ts +10 -0
  42. package/dist/main/services/mcp/status.js +14 -0
  43. package/dist/main/services/mcp/target-manager.js +2 -1
  44. package/dist/main/services/module.d.ts +18 -0
  45. package/dist/main/services/module.js +2 -0
  46. package/dist/main/services/notifications/renderer-notifier.d.ts +5 -3
  47. package/dist/main/services/notifications/renderer-notifier.js +3 -6
  48. package/dist/main/services/projects/builtin-templates.d.ts +3 -0
  49. package/dist/main/services/projects/builtin-templates.js +24 -0
  50. package/dist/main/services/projects/create-project-service.d.ts +7 -0
  51. package/dist/main/services/projects/create-project-service.js +84 -0
  52. package/dist/main/services/projects/index.d.ts +7 -0
  53. package/dist/main/services/projects/index.js +9 -0
  54. package/dist/main/services/projects/local-provider.d.ts +3 -0
  55. package/dist/main/services/projects/local-provider.js +25 -0
  56. package/dist/main/services/projects/project-repository.d.ts +1 -1
  57. package/dist/main/services/projects/project-repository.js +3 -0
  58. package/dist/main/services/projects/templates.d.ts +21 -0
  59. package/dist/main/services/projects/templates.js +39 -0
  60. package/dist/main/services/projects/thumbnail.d.ts +8 -0
  61. package/dist/main/services/projects/thumbnail.js +37 -0
  62. package/dist/main/services/projects/types.d.ts +118 -0
  63. package/dist/main/services/projects/types.js +19 -0
  64. package/dist/main/services/settings/index.d.ts +11 -0
  65. package/dist/main/services/settings/index.js +18 -2
  66. package/dist/main/services/simulator/custom-apis.d.ts +10 -0
  67. package/dist/main/services/simulator/custom-apis.js +26 -0
  68. package/dist/main/services/simulator-storage/index.d.ts +22 -1
  69. package/dist/main/services/simulator-storage/index.js +334 -97
  70. package/dist/main/services/update/update-manager.d.ts +16 -1
  71. package/dist/main/services/update/update-manager.js +18 -15
  72. package/dist/main/services/views/view-manager.d.ts +7 -7
  73. package/dist/main/services/views/view-manager.js +53 -29
  74. package/dist/main/services/window-service.d.ts +24 -0
  75. package/dist/main/services/window-service.js +26 -0
  76. package/dist/main/services/workbench-context.d.ts +49 -2
  77. package/dist/main/services/workbench-context.js +15 -2
  78. package/dist/main/services/workspace/workspace-service.d.ts +9 -6
  79. package/dist/main/services/workspace/workspace-service.js +71 -11
  80. package/dist/main/simulator-apis.d.ts +23 -0
  81. package/dist/main/simulator-apis.js +24 -0
  82. package/dist/main/utils/disposable.d.ts +13 -0
  83. package/dist/main/utils/disposable.js +60 -0
  84. package/dist/main/utils/ipc-registry.d.ts +39 -0
  85. package/dist/main/utils/ipc-registry.js +109 -0
  86. package/dist/main/utils/ipc-schema.d.ts +28 -0
  87. package/dist/main/utils/ipc-schema.js +38 -0
  88. package/dist/main/utils/paths.d.ts +6 -0
  89. package/dist/main/utils/paths.js +6 -0
  90. package/dist/main/utils/sender-policy.d.ts +25 -0
  91. package/dist/main/utils/sender-policy.js +44 -0
  92. package/dist/main/utils/theme.d.ts +24 -0
  93. package/dist/main/utils/theme.js +38 -1
  94. package/dist/main/windows/main-window/create.d.ts +6 -0
  95. package/dist/main/windows/main-window/create.js +66 -10
  96. package/dist/main/windows/main-window/events.d.ts +2 -1
  97. package/dist/main/windows/main-window/events.js +25 -2
  98. package/dist/main/windows/navigation-hardening.d.ts +24 -0
  99. package/dist/main/windows/navigation-hardening.js +55 -0
  100. package/dist/main/windows/settings-window/create.js +11 -1
  101. package/dist/preload/index.d.ts +22 -0
  102. package/dist/preload/index.js +19 -0
  103. package/dist/preload/instrumentation/app-data.d.ts +32 -2
  104. package/dist/preload/instrumentation/app-data.js +253 -79
  105. package/dist/preload/instrumentation/index.d.ts +2 -2
  106. package/dist/preload/instrumentation/index.js +2 -2
  107. package/dist/preload/instrumentation/wxml.d.ts +16 -4
  108. package/dist/preload/instrumentation/wxml.js +188 -178
  109. package/dist/preload/miniapp-snapshot/host.d.ts +12 -0
  110. package/dist/preload/miniapp-snapshot/host.js +117 -0
  111. package/dist/preload/miniapp-snapshot/types.d.ts +62 -0
  112. package/dist/preload/miniapp-snapshot/types.js +15 -0
  113. package/dist/preload/runtime/bridge.js +5 -24
  114. package/dist/preload/runtime/custom-apis.d.ts +6 -0
  115. package/dist/preload/runtime/custom-apis.js +43 -0
  116. package/dist/preload/runtime/host.d.ts +1 -0
  117. package/dist/preload/runtime/host.js +13 -0
  118. package/dist/preload/shared/expose.d.ts +15 -0
  119. package/dist/preload/shared/expose.js +33 -0
  120. package/dist/preload/shared/page-iframe.d.ts +3 -0
  121. package/dist/preload/shared/page-iframe.js +6 -0
  122. package/dist/preload/shared/types.d.ts +2 -0
  123. package/dist/preload/windows/main.cjs +47 -0
  124. package/dist/preload/windows/main.cjs.map +7 -0
  125. package/dist/preload/windows/simulator.js +501 -272
  126. package/dist/renderer/assets/constants-DI382mTP.js +2 -0
  127. package/dist/renderer/assets/index-D8VFYBh-.js +46 -0
  128. package/dist/renderer/assets/{input-DxfYnzX_.js → input-CoWcfa8u.js} +2 -2
  129. package/dist/renderer/assets/ipc-transport-Cd2xPrsa.js +9 -0
  130. package/dist/renderer/assets/ipc-transport-DqbRdZNO.css +1 -0
  131. package/dist/renderer/assets/popover-Nq5gT9DO.js +2 -0
  132. package/dist/renderer/assets/select-By5KH-UG.js +2 -0
  133. package/dist/renderer/assets/{settings-DteGraEU.js → settings-Dj_N70qR.js} +2 -2
  134. package/dist/renderer/assets/settings-api-Do0_Smq1.js +2 -0
  135. package/dist/renderer/assets/workbenchSettings-CazSLGYt.js +8 -0
  136. package/dist/renderer/entries/main/index.html +13 -5
  137. package/dist/renderer/entries/popover/index.html +8 -5
  138. package/dist/renderer/entries/settings/index.html +7 -5
  139. package/dist/renderer/entries/workbench-settings/index.html +7 -4
  140. package/dist/shared/ipc-channels.d.ts +46 -13
  141. package/dist/shared/ipc-channels.js +60 -14
  142. package/dist/shared/ipc-schemas.d.ts +118 -0
  143. package/dist/shared/ipc-schemas.js +133 -0
  144. package/dist/shared/simulator-route.d.ts +72 -0
  145. package/dist/shared/simulator-route.js +169 -0
  146. package/dist/shared/types.d.ts +82 -8
  147. package/dist/simulator/assets/simulator-DJCozrU5.js +9 -0
  148. package/dist/simulator/simulator.html +6 -43
  149. package/package.json +18 -29
  150. package/templates/blank/app.js +6 -0
  151. package/templates/blank/app.json +11 -0
  152. package/templates/blank/app.wxss +5 -0
  153. package/templates/blank/pages/index/index.js +6 -0
  154. package/templates/blank/pages/index/index.json +3 -0
  155. package/templates/blank/pages/index/index.wxml +3 -0
  156. package/templates/blank/pages/index/index.wxss +11 -0
  157. package/templates/blank/project.config.json +13 -0
  158. package/templates/blank/sitemap.json +9 -0
  159. package/templates/taro-todo/app.js +1 -0
  160. package/templates/taro-todo/app.json +1 -0
  161. package/templates/taro-todo/app.wxss +1 -0
  162. package/templates/taro-todo/base.wxml +851 -0
  163. package/templates/taro-todo/common.js +1 -0
  164. package/templates/taro-todo/comp.js +1 -0
  165. package/templates/taro-todo/comp.json +1 -0
  166. package/templates/taro-todo/comp.wxml +2 -0
  167. package/templates/taro-todo/custom-wrapper.js +1 -0
  168. package/templates/taro-todo/custom-wrapper.json +1 -0
  169. package/templates/taro-todo/custom-wrapper.wxml +4 -0
  170. package/templates/taro-todo/pages/index/index.js +2 -0
  171. package/templates/taro-todo/pages/index/index.json +1 -0
  172. package/templates/taro-todo/pages/index/index.wxml +2 -0
  173. package/templates/taro-todo/pages/index/index.wxss +1 -0
  174. package/templates/taro-todo/project.config.json +44 -0
  175. package/templates/taro-todo/runtime.js +1 -0
  176. package/templates/taro-todo/taro.js +2 -0
  177. package/templates/taro-todo/utils.wxs +39 -0
  178. package/templates/taro-todo/vendors.js +2 -0
  179. package/dist/preload/instrumentation/disposable.d.ts +0 -11
  180. package/dist/preload/instrumentation/disposable.js +0 -15
  181. package/dist/preload/windows/main.d.ts +0 -6
  182. package/dist/preload/windows/main.js +0 -6
  183. package/dist/renderer/assets/index-D1p6crtf.js +0 -46
  184. package/dist/renderer/assets/ipc-transport-ClIvDcYY.js +0 -9
  185. package/dist/renderer/assets/ipc-transport-EiWxu_hG.css +0 -1
  186. package/dist/renderer/assets/popover-CtXcBJtM.js +0 -2
  187. package/dist/renderer/assets/select-DMfp49f1.js +0 -2
  188. package/dist/renderer/assets/settings-api-CY84UMpN.js +0 -2
  189. package/dist/renderer/assets/workbenchSettings-DjELLnSJ.js +0 -8
  190. package/dist/simulator/assets/simulator-C1eHXnuq.js +0 -9
@@ -0,0 +1,169 @@
1
+ /**
2
+ * Single source of truth for the simulator URL format.
3
+ *
4
+ * Upstream dimina (didi/dimina, since commit 68310fe) encodes the page route
5
+ * as query params: `?appId={id}&entry={spec}&page={spec}` where each spec is
6
+ * `pagePath?key=val&…`. HashRouter.syncStack rewrites the URL after every
7
+ * navigation; before mount, parent code consumes whatever URL it received.
8
+ *
9
+ * Every URL-building or URL-parsing site in devtools should go through this
10
+ * module — if upstream changes the contract again it's a single-file diff.
11
+ */
12
+ const ROUTE_KEYS = ['appId', 'entry', 'page'];
13
+ // ── Low-level encode / decode ────────────────────────────────────────────────
14
+ /**
15
+ * Encode a search-param value but leave `/` and `,` un-escaped for
16
+ * readability. Upstream `HashRouter._encodeSearchValue` only spares `/`;
17
+ * we also spare `,` so CSV-style extras (e.g. `apiNamespaces=qd,mt`) stay
18
+ * legible in the URL. Both characters are safe in a query string.
19
+ */
20
+ export function encodeRouteValue(value) {
21
+ return encodeURIComponent(value).replace(/%2F/g, '/').replace(/%2C/g, ',');
22
+ }
23
+ /** Encode `{ pagePath, query }` as `pagePath?k1=v1&k2=v2` (no trailing `?` when empty). */
24
+ export function encodePageSpec(spec) {
25
+ const keys = Object.keys(spec.query);
26
+ if (keys.length === 0)
27
+ return spec.pagePath;
28
+ const qs = keys
29
+ .map((k) => `${encodeURIComponent(k)}=${encodeURIComponent(spec.query[k] ?? '')}`)
30
+ .join('&');
31
+ return `${spec.pagePath}?${qs}`;
32
+ }
33
+ /** Decode `pagePath?k=v` into `{ pagePath, query }`. Tolerates missing query. */
34
+ export function decodePageSpec(value) {
35
+ const qIdx = value.indexOf('?');
36
+ if (qIdx < 0)
37
+ return { pagePath: value, query: {} };
38
+ const pagePath = value.slice(0, qIdx);
39
+ const query = {};
40
+ for (const pair of value.slice(qIdx + 1).split('&')) {
41
+ if (!pair)
42
+ continue;
43
+ const eqIdx = pair.indexOf('=');
44
+ const k = eqIdx >= 0 ? pair.slice(0, eqIdx) : pair;
45
+ const v = eqIdx >= 0 ? pair.slice(eqIdx + 1) : '';
46
+ if (k)
47
+ query[decodeURIComponent(k)] = decodeURIComponent(v);
48
+ }
49
+ return { pagePath, query };
50
+ }
51
+ // ── Build ────────────────────────────────────────────────────────────────────
52
+ /**
53
+ * Build the search-params string (without a leading `?`) for a route where
54
+ * `entry === current`. `extras` is appended verbatim (e.g. `apiNamespaces`).
55
+ */
56
+ export function buildRouteSearch(appId, page, extras = {}) {
57
+ const spec = encodePageSpec(page);
58
+ const params = [
59
+ `appId=${encodeRouteValue(appId)}`,
60
+ `entry=${encodeRouteValue(spec)}`,
61
+ `page=${encodeRouteValue(spec)}`,
62
+ ];
63
+ for (const [k, v] of Object.entries(extras)) {
64
+ if (ROUTE_KEYS.includes(k))
65
+ continue;
66
+ params.push(`${encodeURIComponent(k)}=${encodeRouteValue(v)}`);
67
+ }
68
+ return params.join('&');
69
+ }
70
+ /**
71
+ * Build a full simulator URL. The default `host`/`pathname` match what the
72
+ * devkit dev server serves; both are overridable for tests.
73
+ */
74
+ export function buildSimulatorUrlFromSpec(opts) {
75
+ const host = opts.host ?? 'localhost';
76
+ const pathname = opts.pathname ?? '/simulator.html';
77
+ const search = buildRouteSearch(opts.appId, opts.page, opts.extras ?? {});
78
+ return `http://${host}:${opts.port}${pathname}?${search}`;
79
+ }
80
+ /**
81
+ * Renderer-facing convenience: build a simulator URL from devtools'
82
+ * `CompileConfig` shape (startPage / scene / queryParams).
83
+ */
84
+ export function buildSimulatorUrl(appId, compileConfig, port, apiNamespaces) {
85
+ const pagePath = compileConfig.startPage || 'pages/index/index';
86
+ const query = {};
87
+ for (const p of compileConfig.queryParams ?? []) {
88
+ if (p.key)
89
+ query[p.key] = p.value;
90
+ }
91
+ query.scene = String(compileConfig.scene ?? 1001);
92
+ const extras = {};
93
+ if (apiNamespaces?.length)
94
+ extras.apiNamespaces = apiNamespaces.join(',');
95
+ return buildSimulatorUrlFromSpec({
96
+ appId,
97
+ page: { pagePath, query },
98
+ port,
99
+ extras,
100
+ });
101
+ }
102
+ // ── Parse ────────────────────────────────────────────────────────────────────
103
+ /**
104
+ * Parse `location.search` (the query route `?appId=&entry=&page=`) into a
105
+ * `SimulatorRoute`. Returns `null` when no recognisable route is present.
106
+ */
107
+ export function parseLocationRoute(search) {
108
+ const params = new URLSearchParams(search.startsWith('?') ? search.slice(1) : search);
109
+ const appId = params.get('appId');
110
+ const entryRaw = params.get('entry');
111
+ if (!appId || !entryRaw)
112
+ return null;
113
+ const entry = decodePageSpec(entryRaw);
114
+ const pageRaw = params.get('page');
115
+ const current = pageRaw && pageRaw !== entryRaw ? decodePageSpec(pageRaw) : entry;
116
+ return { appId, entry, current };
117
+ }
118
+ /** Parse a full URL string into a `SimulatorRoute`, or `null`. */
119
+ export function parseRoute(url) {
120
+ if (!url)
121
+ return null;
122
+ try {
123
+ const u = new URL(url);
124
+ return parseLocationRoute(u.search);
125
+ }
126
+ catch {
127
+ return null;
128
+ }
129
+ }
130
+ // ── Convenience helpers ──────────────────────────────────────────────────────
131
+ /** Return the current page path (no query) from a URL, or `''` if unparseable. */
132
+ export function getCurrentPagePath(url) {
133
+ const route = parseRoute(url);
134
+ return route?.current.pagePath ?? '';
135
+ }
136
+ /**
137
+ * Rewrite the URL so `entry === current`. Used before a hot-reload so the
138
+ * container boots at just the top page — avoids merged-bundle requests for a
139
+ * multi-page stack that the incremental compiler never emits.
140
+ */
141
+ export function collapseRouteToTopPage(url) {
142
+ if (!url)
143
+ return url;
144
+ let u;
145
+ try {
146
+ u = new URL(url);
147
+ }
148
+ catch {
149
+ return url;
150
+ }
151
+ const route = parseLocationRoute(u.search);
152
+ if (!route)
153
+ return url;
154
+ if (route.entry.pagePath === route.current.pagePath
155
+ && encodePageSpec(route.entry) === encodePageSpec(route.current)) {
156
+ return url;
157
+ }
158
+ // Preserve non-route extras (apiNamespaces etc.) from the query portion;
159
+ // a non-route fragment in `u.hash`, if any, is carried through verbatim.
160
+ const searchParams = new URLSearchParams(u.search.startsWith('?') ? u.search.slice(1) : u.search);
161
+ const extras = {};
162
+ for (const [k, v] of searchParams) {
163
+ if (!ROUTE_KEYS.includes(k))
164
+ extras[k] = v;
165
+ }
166
+ const search = buildRouteSearch(route.appId, route.current, extras);
167
+ return `${u.origin}${u.pathname}?${search}${u.hash}`;
168
+ }
169
+ //# sourceMappingURL=simulator-route.js.map
@@ -1,3 +1,4 @@
1
+ import type { OpenProjectOptions } from '@dimina-kit/devkit';
1
2
  export interface AppInfo {
2
3
  appName?: string;
3
4
  [key: string]: unknown;
@@ -8,14 +9,7 @@ export interface ProjectSession {
8
9
  appInfo: AppInfo | unknown;
9
10
  }
10
11
  export interface CompilationAdapter {
11
- openProject(opts: {
12
- projectPath: string;
13
- port?: number;
14
- sourcemap?: boolean;
15
- simulatorDir?: string;
16
- onRebuild?: () => void;
17
- onBuildError?: (err: unknown) => void;
18
- }): Promise<ProjectSession>;
12
+ openProject(opts: Omit<OpenProjectOptions, 'containerDir' | 'outputDir'>): Promise<ProjectSession>;
19
13
  }
20
14
  export type BuiltinPanelId = 'wxml' | 'console' | 'appdata' | 'storage';
21
15
  export type BuiltinModuleId = 'projects' | 'session' | 'simulator' | 'popover' | 'settings';
@@ -86,6 +80,43 @@ export interface WorkbenchHostInstance {
86
80
  mainWindow: import('electron').BrowserWindow;
87
81
  context: import('../main/services/workbench-context.js').WorkbenchContext;
88
82
  }
83
+ /**
84
+ * Pluggable backend for the project-list panel. Hosts may supply this to
85
+ * take over project storage from the default `<userData>/dimina-projects.json`.
86
+ *
87
+ * Detailed contract lives in
88
+ * `@dimina-kit/devtools/projects-provider` (the runtime exports it).
89
+ * Repeated here as a structural type so `WorkbenchAppConfig` can reference
90
+ * it without a circular import from the main-process tree.
91
+ */
92
+ export interface ProjectsProvider {
93
+ listProjects(): unknown[] | Promise<unknown[]>;
94
+ validateProjectDir?(dirPath: string): string | null;
95
+ addProject(dirPath: string): unknown;
96
+ removeProject(dirPath: string): void | Promise<void>;
97
+ updateLastOpened?(dirPath: string): void | Promise<void>;
98
+ getCompileConfig?(dirPath: string): unknown;
99
+ saveCompileConfig?(dirPath: string, cfg: unknown): void | Promise<void>;
100
+ }
101
+ export interface ProjectTemplate {
102
+ id: string;
103
+ name: string;
104
+ description?: string;
105
+ icon?: string;
106
+ source?: {
107
+ type: 'directory';
108
+ path: string;
109
+ };
110
+ generate?: (target: string, opts: {
111
+ name: string;
112
+ }) => Promise<void>;
113
+ }
114
+ export interface CreateProjectInput {
115
+ name: string;
116
+ path: string;
117
+ templateId?: string;
118
+ extra?: Record<string, unknown>;
119
+ }
89
120
  export interface WorkbenchAppConfig extends WorkbenchConfig {
90
121
  /** Absolute path to the renderer dist directory. Defaults to dimina-devtools' built-in renderer. */
91
122
  rendererDir?: string;
@@ -112,5 +143,48 @@ export interface WorkbenchAppConfig extends WorkbenchConfig {
112
143
  /** Override the version string passed to the checker. Default: app.getVersion() */
113
144
  getCurrentVersion?: () => string;
114
145
  };
146
+ /** Override the default `<userData>/dimina-projects.json` backend. */
147
+ projectsProvider?: ProjectsProvider;
148
+ /** Templates injected at the head of the list; same-id overrides a built-in. */
149
+ projectTemplates?: ProjectTemplate[];
150
+ /** Built-in policy: 'all' (default), 'none', or an allowlist of ids. */
151
+ builtinTemplates?: 'all' | 'none' | string[];
152
+ /**
153
+ * Host-supplied "新建项目" dialog. When provided, the renderer routes the
154
+ * "+" card click through IPC into this main-process hook instead of
155
+ * showing the built-in dialog. Receives the parent window for native
156
+ * dialog parenting and the merged + sanitized template list (no
157
+ * `generate` functions cross the IPC boundary).
158
+ *
159
+ * Return either:
160
+ * - `null` — user cancelled.
161
+ * - a `CreateProjectInput` — devtools runs its built-in scaffold
162
+ * (copy template → write project.config.json → provider.addProject)
163
+ * on the host's behalf.
164
+ * - `{ ready: Project }` — the host has ALREADY created the project
165
+ * (typically via its own backend). devtools skips the scaffold and
166
+ * just refreshes the list. Use this when materialization is remote
167
+ * or already done.
168
+ */
169
+ customCreateProjectDialog?: (ctx: {
170
+ parentWindow: import('electron').BrowserWindow;
171
+ templates: ProjectTemplate[];
172
+ }) => Promise<CustomCreateProjectDialogResult>;
115
173
  }
174
+ /**
175
+ * Discriminated return of `customCreateProjectDialog`. `null` = cancelled.
176
+ * `{ ready }` = host created the project itself; devtools just refreshes.
177
+ * Otherwise treated as `CreateProjectInput` and devtools materializes the
178
+ * template locally.
179
+ *
180
+ * The `ready.Project` shape is the structural minimum devtools needs to
181
+ * render the card (mirrors `Project` in `./projects-provider`).
182
+ */
183
+ export type CustomCreateProjectDialogResult = null | {
184
+ ready: {
185
+ name: string;
186
+ path: string;
187
+ lastOpened?: string | null;
188
+ };
189
+ } | CreateProjectInput;
116
190
  //# sourceMappingURL=types.d.ts.map