@dimina-kit/devtools 0.3.1 → 0.3.2-dev.20260522110734
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +298 -133
- package/dist/main/api.d.ts +6 -2
- package/dist/main/api.js +5 -2
- package/dist/main/app/app.d.ts +1 -1
- package/dist/main/app/app.js +84 -36
- package/dist/main/app/bootstrap.js +2 -1
- package/dist/main/app/launch.d.ts +2 -2
- package/dist/main/app/launch.js +10 -8
- package/dist/main/index.bundle.js +1567 -477
- package/dist/main/ipc/app.d.ts +2 -1
- package/dist/main/ipc/app.js +5 -4
- package/dist/main/ipc/index.d.ts +5 -4
- package/dist/main/ipc/index.js +5 -4
- package/dist/main/ipc/panels.d.ts +2 -1
- package/dist/main/ipc/panels.js +16 -13
- package/dist/main/ipc/popover.d.ts +4 -1
- package/dist/main/ipc/popover.js +15 -5
- package/dist/main/ipc/projects.d.ts +6 -1
- package/dist/main/ipc/projects.js +127 -6
- package/dist/main/ipc/session.d.ts +4 -1
- package/dist/main/ipc/session.js +34 -6
- package/dist/main/ipc/settings.d.ts +4 -1
- package/dist/main/ipc/settings.js +51 -23
- package/dist/main/ipc/simulator-module.d.ts +8 -0
- package/dist/main/ipc/simulator-module.js +19 -0
- package/dist/main/ipc/simulator.d.ts +2 -1
- package/dist/main/ipc/simulator.js +23 -18
- package/dist/main/ipc/toolbar.d.ts +2 -1
- package/dist/main/ipc/toolbar.js +3 -2
- package/dist/main/menu/index.js +11 -0
- package/dist/main/services/automation/exec.d.ts +2 -0
- package/dist/main/services/automation/exec.js +7 -9
- package/dist/main/services/automation/handlers/app.js +37 -51
- package/dist/main/services/automation/handlers/element.js +27 -41
- package/dist/main/services/automation/index.js +88 -13
- package/dist/main/services/default-adapter.js +3 -3
- package/dist/main/services/mcp/index.d.ts +1 -0
- package/dist/main/services/mcp/index.js +1 -0
- package/dist/main/services/mcp/server.d.ts +2 -1
- package/dist/main/services/mcp/server.js +10 -0
- package/dist/main/services/mcp/status.d.ts +10 -0
- package/dist/main/services/mcp/status.js +14 -0
- package/dist/main/services/mcp/target-manager.js +2 -1
- package/dist/main/services/module.d.ts +18 -0
- package/dist/main/services/module.js +2 -0
- package/dist/main/services/notifications/renderer-notifier.d.ts +5 -3
- package/dist/main/services/notifications/renderer-notifier.js +3 -6
- package/dist/main/services/projects/builtin-templates.d.ts +3 -0
- package/dist/main/services/projects/builtin-templates.js +24 -0
- package/dist/main/services/projects/create-project-service.d.ts +7 -0
- package/dist/main/services/projects/create-project-service.js +84 -0
- package/dist/main/services/projects/index.d.ts +7 -0
- package/dist/main/services/projects/index.js +9 -0
- package/dist/main/services/projects/local-provider.d.ts +3 -0
- package/dist/main/services/projects/local-provider.js +25 -0
- package/dist/main/services/projects/project-repository.d.ts +1 -1
- package/dist/main/services/projects/project-repository.js +3 -0
- package/dist/main/services/projects/templates.d.ts +21 -0
- package/dist/main/services/projects/templates.js +39 -0
- package/dist/main/services/projects/thumbnail.d.ts +8 -0
- package/dist/main/services/projects/thumbnail.js +37 -0
- package/dist/main/services/projects/types.d.ts +118 -0
- package/dist/main/services/projects/types.js +19 -0
- package/dist/main/services/settings/index.d.ts +11 -0
- package/dist/main/services/settings/index.js +18 -2
- package/dist/main/services/simulator/custom-apis.d.ts +10 -0
- package/dist/main/services/simulator/custom-apis.js +26 -0
- package/dist/main/services/simulator-storage/index.d.ts +22 -1
- package/dist/main/services/simulator-storage/index.js +334 -97
- package/dist/main/services/update/update-manager.d.ts +16 -1
- package/dist/main/services/update/update-manager.js +18 -15
- package/dist/main/services/views/view-manager.d.ts +7 -7
- package/dist/main/services/views/view-manager.js +53 -29
- package/dist/main/services/window-service.d.ts +24 -0
- package/dist/main/services/window-service.js +26 -0
- package/dist/main/services/workbench-context.d.ts +49 -2
- package/dist/main/services/workbench-context.js +15 -2
- package/dist/main/services/workspace/workspace-service.d.ts +9 -6
- package/dist/main/services/workspace/workspace-service.js +71 -11
- package/dist/main/simulator-apis.d.ts +23 -0
- package/dist/main/simulator-apis.js +24 -0
- package/dist/main/utils/disposable.d.ts +13 -0
- package/dist/main/utils/disposable.js +60 -0
- package/dist/main/utils/ipc-registry.d.ts +39 -0
- package/dist/main/utils/ipc-registry.js +109 -0
- package/dist/main/utils/ipc-schema.d.ts +28 -0
- package/dist/main/utils/ipc-schema.js +38 -0
- package/dist/main/utils/paths.d.ts +6 -0
- package/dist/main/utils/paths.js +6 -0
- package/dist/main/utils/sender-policy.d.ts +25 -0
- package/dist/main/utils/sender-policy.js +44 -0
- package/dist/main/utils/theme.d.ts +24 -0
- package/dist/main/utils/theme.js +38 -1
- package/dist/main/windows/main-window/create.d.ts +6 -0
- package/dist/main/windows/main-window/create.js +66 -10
- package/dist/main/windows/main-window/events.d.ts +2 -1
- package/dist/main/windows/main-window/events.js +25 -2
- package/dist/main/windows/navigation-hardening.d.ts +24 -0
- package/dist/main/windows/navigation-hardening.js +55 -0
- package/dist/main/windows/settings-window/create.js +11 -1
- package/dist/preload/index.d.ts +22 -0
- package/dist/preload/index.js +19 -0
- package/dist/preload/instrumentation/app-data.d.ts +32 -2
- package/dist/preload/instrumentation/app-data.js +253 -79
- package/dist/preload/instrumentation/index.d.ts +2 -2
- package/dist/preload/instrumentation/index.js +2 -2
- package/dist/preload/instrumentation/wxml.d.ts +16 -4
- package/dist/preload/instrumentation/wxml.js +188 -178
- package/dist/preload/miniapp-snapshot/host.d.ts +12 -0
- package/dist/preload/miniapp-snapshot/host.js +117 -0
- package/dist/preload/miniapp-snapshot/types.d.ts +62 -0
- package/dist/preload/miniapp-snapshot/types.js +15 -0
- package/dist/preload/runtime/bridge.js +5 -24
- package/dist/preload/runtime/custom-apis.d.ts +6 -0
- package/dist/preload/runtime/custom-apis.js +43 -0
- package/dist/preload/runtime/host.d.ts +1 -0
- package/dist/preload/runtime/host.js +13 -0
- package/dist/preload/shared/expose.d.ts +15 -0
- package/dist/preload/shared/expose.js +33 -0
- package/dist/preload/shared/page-iframe.d.ts +3 -0
- package/dist/preload/shared/page-iframe.js +6 -0
- package/dist/preload/shared/types.d.ts +2 -0
- package/dist/preload/windows/main.cjs +47 -0
- package/dist/preload/windows/main.cjs.map +7 -0
- package/dist/preload/windows/simulator.js +501 -272
- package/dist/renderer/assets/constants-DI382mTP.js +2 -0
- package/dist/renderer/assets/index-D8VFYBh-.js +46 -0
- package/dist/renderer/assets/{input-DxfYnzX_.js → input-CoWcfa8u.js} +2 -2
- package/dist/renderer/assets/ipc-transport-Cd2xPrsa.js +9 -0
- package/dist/renderer/assets/ipc-transport-DqbRdZNO.css +1 -0
- package/dist/renderer/assets/popover-Nq5gT9DO.js +2 -0
- package/dist/renderer/assets/select-By5KH-UG.js +2 -0
- package/dist/renderer/assets/{settings-DteGraEU.js → settings-Dj_N70qR.js} +2 -2
- package/dist/renderer/assets/settings-api-Do0_Smq1.js +2 -0
- package/dist/renderer/assets/workbenchSettings-CazSLGYt.js +8 -0
- package/dist/renderer/entries/main/index.html +13 -5
- package/dist/renderer/entries/popover/index.html +8 -5
- package/dist/renderer/entries/settings/index.html +7 -5
- package/dist/renderer/entries/workbench-settings/index.html +7 -4
- package/dist/shared/ipc-channels.d.ts +46 -13
- package/dist/shared/ipc-channels.js +60 -14
- package/dist/shared/ipc-schemas.d.ts +118 -0
- package/dist/shared/ipc-schemas.js +133 -0
- package/dist/shared/simulator-route.d.ts +72 -0
- package/dist/shared/simulator-route.js +169 -0
- package/dist/shared/types.d.ts +82 -8
- package/dist/simulator/assets/simulator-CZc88Jeh.js +9 -0
- package/dist/simulator/simulator.html +6 -43
- package/package.json +16 -27
- package/templates/blank/app.js +6 -0
- package/templates/blank/app.json +11 -0
- package/templates/blank/app.wxss +5 -0
- package/templates/blank/pages/index/index.js +6 -0
- package/templates/blank/pages/index/index.json +3 -0
- package/templates/blank/pages/index/index.wxml +3 -0
- package/templates/blank/pages/index/index.wxss +11 -0
- package/templates/blank/project.config.json +13 -0
- package/templates/blank/sitemap.json +9 -0
- package/templates/taro-todo/app.js +1 -0
- package/templates/taro-todo/app.json +1 -0
- package/templates/taro-todo/app.wxss +1 -0
- package/templates/taro-todo/base.wxml +851 -0
- package/templates/taro-todo/common.js +1 -0
- package/templates/taro-todo/comp.js +1 -0
- package/templates/taro-todo/comp.json +1 -0
- package/templates/taro-todo/comp.wxml +2 -0
- package/templates/taro-todo/custom-wrapper.js +1 -0
- package/templates/taro-todo/custom-wrapper.json +1 -0
- package/templates/taro-todo/custom-wrapper.wxml +4 -0
- package/templates/taro-todo/pages/index/index.js +2 -0
- package/templates/taro-todo/pages/index/index.json +1 -0
- package/templates/taro-todo/pages/index/index.wxml +2 -0
- package/templates/taro-todo/pages/index/index.wxss +1 -0
- package/templates/taro-todo/project.config.json +44 -0
- package/templates/taro-todo/runtime.js +1 -0
- package/templates/taro-todo/taro.js +2 -0
- package/templates/taro-todo/utils.wxs +39 -0
- package/templates/taro-todo/vendors.js +2 -0
- package/dist/preload/instrumentation/disposable.d.ts +0 -11
- package/dist/preload/instrumentation/disposable.js +0 -15
- package/dist/preload/windows/main.d.ts +0 -6
- package/dist/preload/windows/main.js +0 -6
- package/dist/renderer/assets/index-D1p6crtf.js +0 -46
- package/dist/renderer/assets/ipc-transport-ClIvDcYY.js +0 -9
- package/dist/renderer/assets/ipc-transport-EiWxu_hG.css +0 -1
- package/dist/renderer/assets/popover-CtXcBJtM.js +0 -2
- package/dist/renderer/assets/select-DMfp49f1.js +0 -2
- package/dist/renderer/assets/settings-api-CY84UMpN.js +0 -2
- package/dist/renderer/assets/workbenchSettings-DjELLnSJ.js +0 -8
- package/dist/simulator/assets/simulator-C1eHXnuq.js +0 -9
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in template catalog. Each entry's `source.path` points at a
|
|
3
|
+
* directory inside `<devtools-package-root>/templates/`, which is
|
|
4
|
+
* committed to the repo and (via the `files` field of package.json's
|
|
5
|
+
* publish manifest) included in the published tarball.
|
|
6
|
+
*/
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import { devtoolsPackageRoot } from '../../utils/paths.js';
|
|
9
|
+
const TEMPLATES_DIR = path.join(devtoolsPackageRoot, 'templates');
|
|
10
|
+
export const BUILTIN_TEMPLATES = [
|
|
11
|
+
{
|
|
12
|
+
id: 'blank',
|
|
13
|
+
name: 'Blank',
|
|
14
|
+
description: '最小骨架:app.* + 一个 index 页面',
|
|
15
|
+
source: { type: 'directory', path: path.join(TEMPLATES_DIR, 'blank') },
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: 'taro-todo',
|
|
19
|
+
name: 'Taro Todo',
|
|
20
|
+
description: 'Taro 编译产物的 Todo 示例',
|
|
21
|
+
source: { type: 'directory', path: path.join(TEMPLATES_DIR, 'taro-todo') },
|
|
22
|
+
},
|
|
23
|
+
];
|
|
24
|
+
//# sourceMappingURL=builtin-templates.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CreateProjectInput, Project, ProjectTemplate, ProjectsProvider } from './types.js';
|
|
2
|
+
export interface CreateProjectCtx {
|
|
3
|
+
templates: ProjectTemplate[];
|
|
4
|
+
projectsProvider: ProjectsProvider;
|
|
5
|
+
}
|
|
6
|
+
export declare function createProject(input: CreateProjectInput, ctx: CreateProjectCtx): Promise<Project>;
|
|
7
|
+
//# sourceMappingURL=create-project-service.d.ts.map
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical server-side path for the "新建项目" flow.
|
|
3
|
+
*
|
|
4
|
+
* `createProject(input, ctx)`:
|
|
5
|
+
* 1. validates `input.name` (non-empty after trim) and `input.path` (does
|
|
6
|
+
* not exist OR exists but is an empty directory).
|
|
7
|
+
* 2. resolves `input.templateId` (default 'blank') against `ctx.templates`.
|
|
8
|
+
* 3. copies the template `source` directory into `input.path`, or invokes
|
|
9
|
+
* `template.generate(input.path, { name })` for programmatic templates.
|
|
10
|
+
* 4. rewrites `<input.path>/project.config.json`'s `projectname` to
|
|
11
|
+
* `input.name`.
|
|
12
|
+
* 5. registers the project with `ctx.projectsProvider.addProject(input.path)`
|
|
13
|
+
* and returns the resulting Project.
|
|
14
|
+
*/
|
|
15
|
+
import fs from 'node:fs';
|
|
16
|
+
import path from 'node:path';
|
|
17
|
+
const DEFAULT_TEMPLATE_ID = 'blank';
|
|
18
|
+
export async function createProject(input, ctx) {
|
|
19
|
+
// 1. name validation
|
|
20
|
+
const name = (input.name ?? '').trim();
|
|
21
|
+
if (name.length === 0) {
|
|
22
|
+
throw new Error('Project name cannot be empty');
|
|
23
|
+
}
|
|
24
|
+
// 2. path validation: does-not-exist OR exists+empty.
|
|
25
|
+
const target = input.path;
|
|
26
|
+
if (!target || typeof target !== 'string') {
|
|
27
|
+
throw new Error('Project path is required');
|
|
28
|
+
}
|
|
29
|
+
if (fs.existsSync(target)) {
|
|
30
|
+
const stat = fs.statSync(target);
|
|
31
|
+
if (!stat.isDirectory()) {
|
|
32
|
+
throw new Error(`Project path exists and is not a directory: ${target}`);
|
|
33
|
+
}
|
|
34
|
+
const entries = fs.readdirSync(target);
|
|
35
|
+
if (entries.length > 0) {
|
|
36
|
+
throw new Error(`Project path is not empty (refusing to overwrite): ${target}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// 3. template lookup (default 'blank')
|
|
40
|
+
const templateId = input.templateId ?? DEFAULT_TEMPLATE_ID;
|
|
41
|
+
const template = ctx.templates.find((t) => t.id === templateId);
|
|
42
|
+
if (!template) {
|
|
43
|
+
throw new Error(`Template not found: ${templateId}`);
|
|
44
|
+
}
|
|
45
|
+
if (!template.source && !template.generate) {
|
|
46
|
+
throw new Error(`Template '${templateId}' has neither a source directory nor a generate function`);
|
|
47
|
+
}
|
|
48
|
+
// 4. materialise: ensure target exists, then copy or generate.
|
|
49
|
+
fs.mkdirSync(target, { recursive: true });
|
|
50
|
+
if (template.generate) {
|
|
51
|
+
await template.generate(target, { name });
|
|
52
|
+
}
|
|
53
|
+
else if (template.source) {
|
|
54
|
+
if (!fs.existsSync(template.source.path)) {
|
|
55
|
+
throw new Error(`Template source missing on disk: ${template.source.path}`);
|
|
56
|
+
}
|
|
57
|
+
// `recursive: true` makes cpSync mirror the entire tree (files,
|
|
58
|
+
// subdirs, symlinks). `force: true` mirrors over an empty target.
|
|
59
|
+
fs.cpSync(template.source.path, target, {
|
|
60
|
+
recursive: true,
|
|
61
|
+
force: true,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
// 5. rewrite project.config.json projectname (best-effort: create the file
|
|
65
|
+
// if the template didn't ship one — gives the user a working starting
|
|
66
|
+
// point even for tiny generators).
|
|
67
|
+
const cfgPath = path.join(target, 'project.config.json');
|
|
68
|
+
let cfg = {};
|
|
69
|
+
if (fs.existsSync(cfgPath)) {
|
|
70
|
+
try {
|
|
71
|
+
cfg = JSON.parse(fs.readFileSync(cfgPath, 'utf-8'));
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
cfg = {};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
cfg.projectname = name;
|
|
78
|
+
fs.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2));
|
|
79
|
+
// 6. register with provider — this is what makes the new project appear
|
|
80
|
+
// in the list immediately after the dialog closes.
|
|
81
|
+
const created = await ctx.projectsProvider.addProject(target);
|
|
82
|
+
return created;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=create-project-service.js.map
|
|
@@ -1,2 +1,9 @@
|
|
|
1
1
|
export * from './project-repository.js';
|
|
2
|
+
export { createLocalProjectsProvider } from './local-provider.js';
|
|
3
|
+
export type { ProjectsProvider, ProjectTemplate, CreateProjectInput, BuiltinTemplatesMode, } from './types.js';
|
|
4
|
+
export { DEFAULT_COMPILE_CONFIG } from './types.js';
|
|
5
|
+
export { resolveTemplates, sanitizeTemplates } from './templates.js';
|
|
6
|
+
export { BUILTIN_TEMPLATES } from './builtin-templates.js';
|
|
7
|
+
export { createProject } from './create-project-service.js';
|
|
8
|
+
export type { CreateProjectCtx } from './create-project-service.js';
|
|
2
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -2,5 +2,14 @@
|
|
|
2
2
|
// keeps working. The filesystem-level helpers live in project-repository.ts;
|
|
3
3
|
// higher-level coordination (session + renderer notifications) lives in
|
|
4
4
|
// ../workspace/workspace-service.ts.
|
|
5
|
+
//
|
|
6
|
+
// Phase 1 adds the extensibility surface: `types.ts` (ProjectsProvider,
|
|
7
|
+
// ProjectTemplate, CreateProjectInput) and `local-provider.ts` (the default
|
|
8
|
+
// implementation injected when the host omits `projectsProvider`).
|
|
5
9
|
export * from './project-repository.js';
|
|
10
|
+
export { createLocalProjectsProvider } from './local-provider.js';
|
|
11
|
+
export { DEFAULT_COMPILE_CONFIG } from './types.js';
|
|
12
|
+
export { resolveTemplates, sanitizeTemplates } from './templates.js';
|
|
13
|
+
export { BUILTIN_TEMPLATES } from './builtin-templates.js';
|
|
14
|
+
export { createProject } from './create-project-service.js';
|
|
6
15
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default ProjectsProvider — persists the project list to
|
|
3
|
+
* `<userData>/dimina-projects.json` and exposes the validation / compile-
|
|
4
|
+
* config helpers historically provided by `project-repository.ts`.
|
|
5
|
+
*
|
|
6
|
+
* The repository module is kept for thumbnail/paths/page helpers; the
|
|
7
|
+
* canonical list & validation surface for the workspace service is this
|
|
8
|
+
* provider.
|
|
9
|
+
*/
|
|
10
|
+
import * as repo from './project-repository.js';
|
|
11
|
+
import { loadThumbnail, saveThumbnailFromDataUrl } from './thumbnail.js';
|
|
12
|
+
export function createLocalProjectsProvider() {
|
|
13
|
+
return {
|
|
14
|
+
listProjects: () => repo.listProjects(),
|
|
15
|
+
addProject: (dirPath) => repo.addProject(dirPath),
|
|
16
|
+
removeProject: (dirPath) => repo.removeProject(dirPath),
|
|
17
|
+
validateProjectDir: (dirPath) => repo.validateProjectDir(dirPath),
|
|
18
|
+
updateLastOpened: (dirPath) => repo.updateLastOpened(dirPath),
|
|
19
|
+
getCompileConfig: (dirPath) => repo.getCompileConfig(dirPath),
|
|
20
|
+
saveCompileConfig: (dirPath, cfg) => repo.saveCompileConfig(dirPath, cfg),
|
|
21
|
+
saveThumbnail: (dirPath, dataUrl) => saveThumbnailFromDataUrl(dirPath, dataUrl),
|
|
22
|
+
getThumbnail: (dirPath) => loadThumbnail(dirPath),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=local-provider.js.map
|
|
@@ -12,9 +12,9 @@ export interface ProjectPages {
|
|
|
12
12
|
export interface ProjectSettings {
|
|
13
13
|
uploadWithSourceMap: boolean;
|
|
14
14
|
}
|
|
15
|
-
export type { CompileConfig } from '../../../shared/types.js';
|
|
16
15
|
export declare function listProjects(): Project[];
|
|
17
16
|
export declare function validateProjectDir(dirPath: string): string | null;
|
|
17
|
+
export declare function hasProject(dirPath: string): boolean;
|
|
18
18
|
export declare function addProject(dirPath: string): Project;
|
|
19
19
|
export declare function removeProject(dirPath: string): void;
|
|
20
20
|
export declare function updateLastOpened(dirPath: string): void;
|
|
@@ -46,6 +46,9 @@ export function validateProjectDir(dirPath) {
|
|
|
46
46
|
}
|
|
47
47
|
return null;
|
|
48
48
|
}
|
|
49
|
+
export function hasProject(dirPath) {
|
|
50
|
+
return load().some((p) => p.path === dirPath);
|
|
51
|
+
}
|
|
49
52
|
export function addProject(dirPath) {
|
|
50
53
|
const projects = load();
|
|
51
54
|
let name = path.basename(dirPath);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in template policy merge logic.
|
|
3
|
+
*
|
|
4
|
+
* `resolveTemplates(builtin, injected, mode)`:
|
|
5
|
+
* - mode='all' → keep every built-in
|
|
6
|
+
* - mode='none' → drop every built-in
|
|
7
|
+
* - mode=string[] → keep only built-ins whose id is in the whitelist
|
|
8
|
+
*
|
|
9
|
+
* Injected templates always win over a same-id built-in. Order is:
|
|
10
|
+
* injected (input order) ++ remaining built-ins (in their input order
|
|
11
|
+
* for 'all'; in the whitelist's order for an array mode).
|
|
12
|
+
*/
|
|
13
|
+
import type { BuiltinTemplatesMode, ProjectTemplate } from './types.js';
|
|
14
|
+
export declare function resolveTemplates(builtin: ProjectTemplate[], injected: ProjectTemplate[], mode: BuiltinTemplatesMode): ProjectTemplate[];
|
|
15
|
+
/**
|
|
16
|
+
* Strip non-serialisable fields (e.g. `generate` functions) so the merged
|
|
17
|
+
* catalog can be sent across the renderer IPC boundary. Anything left is
|
|
18
|
+
* structured-clonable.
|
|
19
|
+
*/
|
|
20
|
+
export declare function sanitizeTemplates(templates: ProjectTemplate[]): ProjectTemplate[];
|
|
21
|
+
//# sourceMappingURL=templates.d.ts.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export function resolveTemplates(builtin, injected, mode) {
|
|
2
|
+
let kept;
|
|
3
|
+
if (mode === 'none') {
|
|
4
|
+
kept = [];
|
|
5
|
+
}
|
|
6
|
+
else if (mode === 'all') {
|
|
7
|
+
kept = [...builtin];
|
|
8
|
+
}
|
|
9
|
+
else {
|
|
10
|
+
// Whitelist: keep only listed ids, in the whitelist's order. Unknown
|
|
11
|
+
// ids are dropped silently — the user opted in to a curated subset and
|
|
12
|
+
// we don't want a typo to crash the new-project dialog.
|
|
13
|
+
const byId = new Map(builtin.map((t) => [t.id, t]));
|
|
14
|
+
kept = [];
|
|
15
|
+
for (const id of mode) {
|
|
16
|
+
const t = byId.get(id);
|
|
17
|
+
if (t)
|
|
18
|
+
kept.push(t);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
// Strip any built-ins whose id is overridden by an injected template, then
|
|
22
|
+
// prepend the injected list so host-supplied versions win on rendering.
|
|
23
|
+
const injectedIds = new Set(injected.map((t) => t.id));
|
|
24
|
+
const remaining = kept.filter((t) => !injectedIds.has(t.id));
|
|
25
|
+
return [...injected, ...remaining];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Strip non-serialisable fields (e.g. `generate` functions) so the merged
|
|
29
|
+
* catalog can be sent across the renderer IPC boundary. Anything left is
|
|
30
|
+
* structured-clonable.
|
|
31
|
+
*/
|
|
32
|
+
export function sanitizeTemplates(templates) {
|
|
33
|
+
return templates.map((t) => {
|
|
34
|
+
// `generate` is a function and would throw on structuredClone / IPC.
|
|
35
|
+
const { generate: _generate, ...rest } = t;
|
|
36
|
+
return rest;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=templates.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persist a data-URL screenshot for the local default provider. Silently
|
|
3
|
+
* drops the call when the URL isn't the expected PNG base64 form — the
|
|
4
|
+
* provider contract documents this as best-effort.
|
|
5
|
+
*/
|
|
6
|
+
export declare function saveThumbnailFromDataUrl(projectPath: string, imageDataUrl: string): void;
|
|
7
|
+
export declare function loadThumbnail(projectPath: string): string | null;
|
|
8
|
+
//# sourceMappingURL=thumbnail.d.ts.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { createHash } from 'crypto';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { app } from 'electron';
|
|
5
|
+
function getThumbnailDir() {
|
|
6
|
+
return path.join(app.getPath('userData'), 'thumbnails');
|
|
7
|
+
}
|
|
8
|
+
function hashProjectPath(projectPath) {
|
|
9
|
+
return createHash('sha256').update(projectPath).digest('hex').slice(0, 16);
|
|
10
|
+
}
|
|
11
|
+
function getThumbnailPath(projectPath) {
|
|
12
|
+
return path.join(getThumbnailDir(), `${hashProjectPath(projectPath)}.png`);
|
|
13
|
+
}
|
|
14
|
+
const DATA_URL_PNG_PREFIX = 'data:image/png;base64,';
|
|
15
|
+
/**
|
|
16
|
+
* Persist a data-URL screenshot for the local default provider. Silently
|
|
17
|
+
* drops the call when the URL isn't the expected PNG base64 form — the
|
|
18
|
+
* provider contract documents this as best-effort.
|
|
19
|
+
*/
|
|
20
|
+
export function saveThumbnailFromDataUrl(projectPath, imageDataUrl) {
|
|
21
|
+
if (!imageDataUrl.startsWith(DATA_URL_PNG_PREFIX))
|
|
22
|
+
return;
|
|
23
|
+
const png = Buffer.from(imageDataUrl.slice(DATA_URL_PNG_PREFIX.length), 'base64');
|
|
24
|
+
fs.mkdirSync(getThumbnailDir(), { recursive: true });
|
|
25
|
+
fs.writeFileSync(getThumbnailPath(projectPath), png);
|
|
26
|
+
}
|
|
27
|
+
export function loadThumbnail(projectPath) {
|
|
28
|
+
const filePath = getThumbnailPath(projectPath);
|
|
29
|
+
try {
|
|
30
|
+
const buf = fs.readFileSync(filePath);
|
|
31
|
+
return `${DATA_URL_PNG_PREFIX}${buf.toString('base64')}`;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=thumbnail.js.map
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public extensibility surface for the project list panel. Hosts that embed
|
|
3
|
+
* dimina-devtools (e.g. qdmp) can inject implementations of these types via
|
|
4
|
+
* `WorkbenchAppConfig` to fully take over the project source-of-truth, the
|
|
5
|
+
* template catalog, and the "新建项目" dialog.
|
|
6
|
+
*/
|
|
7
|
+
import type { CompileConfig } from '../../../shared/types.js';
|
|
8
|
+
import type { Project } from './project-repository.js';
|
|
9
|
+
export type { Project };
|
|
10
|
+
/**
|
|
11
|
+
* Default compile config returned by WorkspaceService when the injected
|
|
12
|
+
* provider omits `getCompileConfig`, or when no record exists for a path.
|
|
13
|
+
* Exported so host providers can mirror the canonical shape instead of
|
|
14
|
+
* re-deriving the magic values.
|
|
15
|
+
*/
|
|
16
|
+
export declare const DEFAULT_COMPILE_CONFIG: CompileConfig;
|
|
17
|
+
/**
|
|
18
|
+
* Pluggable project-list backend. The default implementation
|
|
19
|
+
* (LocalProjectsProvider) persists to `<userData>/dimina-projects.json`.
|
|
20
|
+
*
|
|
21
|
+
* All methods may return synchronously OR as a Promise.
|
|
22
|
+
*
|
|
23
|
+
* Optional methods documented per field below; when the host omits an
|
|
24
|
+
* optional method, WorkspaceService applies a documented default
|
|
25
|
+
* (typically a safe no-op) — it does NOT silently fall back to the local
|
|
26
|
+
* file-system helpers, since for a remote provider the project path may
|
|
27
|
+
* not exist on this machine at all.
|
|
28
|
+
*/
|
|
29
|
+
export interface ProjectsProvider {
|
|
30
|
+
listProjects(): Project[] | Promise<Project[]>;
|
|
31
|
+
/**
|
|
32
|
+
* Validate that `dirPath` points at a mini-app source tree.
|
|
33
|
+
* Return `null` if valid, or a user-facing error message string.
|
|
34
|
+
*
|
|
35
|
+
* Default when omitted: returns `null` (no validation). Remote
|
|
36
|
+
* providers SHOULD implement this if the host UI exposes "import an
|
|
37
|
+
* existing directory"; otherwise the user can add unreachable paths.
|
|
38
|
+
*/
|
|
39
|
+
validateProjectDir?(dirPath: string): string | null | Promise<string | null>;
|
|
40
|
+
addProject(dirPath: string): Project | Promise<Project>;
|
|
41
|
+
removeProject(dirPath: string): void | Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Record that the user just opened a project (drives "recent" ordering).
|
|
44
|
+
*
|
|
45
|
+
* Default when omitted: silently no-ops. The renderer's "recent" sort
|
|
46
|
+
* order will then reflect whatever the provider's `listProjects` returns.
|
|
47
|
+
*/
|
|
48
|
+
updateLastOpened?(dirPath: string): void | Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* Read the per-project compile config.
|
|
51
|
+
*
|
|
52
|
+
* Default when omitted: returns `DEFAULT_COMPILE_CONFIG`
|
|
53
|
+
* (`{ startPage: '', scene: 1001, queryParams: [] }`).
|
|
54
|
+
*/
|
|
55
|
+
getCompileConfig?(dirPath: string): CompileConfig | Promise<CompileConfig>;
|
|
56
|
+
/**
|
|
57
|
+
* Persist the per-project compile config.
|
|
58
|
+
*
|
|
59
|
+
* Default when omitted: silently no-ops — the renderer's edits will
|
|
60
|
+
* not survive a reload. Implement this if your UI exposes the compile
|
|
61
|
+
* config panel.
|
|
62
|
+
*/
|
|
63
|
+
saveCompileConfig?(dirPath: string, cfg: CompileConfig): void | Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* Persist a captured screenshot for the given project. `imageDataUrl`
|
|
66
|
+
* is a `data:image/png;base64,...` string so a remote provider can ship
|
|
67
|
+
* it straight to its backend without re-encoding.
|
|
68
|
+
*
|
|
69
|
+
* Default when omitted: silently no-ops (the screenshot is dropped).
|
|
70
|
+
* Implement this for hosts whose projects don't live on the local
|
|
71
|
+
* filesystem and that want thumbnails to round-trip through their own
|
|
72
|
+
* storage.
|
|
73
|
+
*/
|
|
74
|
+
saveThumbnail?(dirPath: string, imageDataUrl: string): void | Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* Load the most recently saved thumbnail for the given project.
|
|
77
|
+
* Returns a `data:image/png;base64,...` string or `null` when there
|
|
78
|
+
* is none.
|
|
79
|
+
*
|
|
80
|
+
* Default when omitted: returns `null`.
|
|
81
|
+
*/
|
|
82
|
+
getThumbnail?(dirPath: string): string | null | Promise<string | null>;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* A template the user can pick from in the "新建项目" dialog. Exactly one of
|
|
86
|
+
* `source` or `generate` should be supplied; if both are omitted, the
|
|
87
|
+
* service refuses to materialise the template.
|
|
88
|
+
*/
|
|
89
|
+
export interface ProjectTemplate {
|
|
90
|
+
/** Stable identifier. Used by host whitelists and the `templateId` field of CreateProjectInput. */
|
|
91
|
+
id: string;
|
|
92
|
+
/** Human-readable label shown in the dialog. */
|
|
93
|
+
name: string;
|
|
94
|
+
description?: string;
|
|
95
|
+
icon?: string;
|
|
96
|
+
/** Copy-tree source. `path` must be absolute. */
|
|
97
|
+
source?: {
|
|
98
|
+
type: 'directory';
|
|
99
|
+
path: string;
|
|
100
|
+
};
|
|
101
|
+
/** Programmatic generator. `target` is the absolute destination directory. */
|
|
102
|
+
generate?: (target: string, opts: {
|
|
103
|
+
name: string;
|
|
104
|
+
}) => Promise<void>;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Payload returned from the create-project dialog. The service uses this to
|
|
108
|
+
* scaffold disk content and to register the project with the provider.
|
|
109
|
+
*/
|
|
110
|
+
export interface CreateProjectInput {
|
|
111
|
+
name: string;
|
|
112
|
+
path: string;
|
|
113
|
+
templateId?: string;
|
|
114
|
+
extra?: Record<string, unknown>;
|
|
115
|
+
}
|
|
116
|
+
/** Built-in template policy. */
|
|
117
|
+
export type BuiltinTemplatesMode = 'all' | 'none' | readonly string[];
|
|
118
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public extensibility surface for the project list panel. Hosts that embed
|
|
3
|
+
* dimina-devtools (e.g. qdmp) can inject implementations of these types via
|
|
4
|
+
* `WorkbenchAppConfig` to fully take over the project source-of-truth, the
|
|
5
|
+
* template catalog, and the "新建项目" dialog.
|
|
6
|
+
*/
|
|
7
|
+
import { DEFAULT_SCENE } from '../../../shared/constants.js';
|
|
8
|
+
/**
|
|
9
|
+
* Default compile config returned by WorkspaceService when the injected
|
|
10
|
+
* provider omits `getCompileConfig`, or when no record exists for a path.
|
|
11
|
+
* Exported so host providers can mirror the canonical shape instead of
|
|
12
|
+
* re-deriving the magic values.
|
|
13
|
+
*/
|
|
14
|
+
export const DEFAULT_COMPILE_CONFIG = {
|
|
15
|
+
startPage: '',
|
|
16
|
+
scene: DEFAULT_SCENE,
|
|
17
|
+
queryParams: [],
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -8,7 +8,18 @@ export interface WorkbenchSettings {
|
|
|
8
8
|
enabled: boolean;
|
|
9
9
|
port: number;
|
|
10
10
|
};
|
|
11
|
+
compile: {
|
|
12
|
+
/** Watch project files and auto-recompile on change. */
|
|
13
|
+
watch: boolean;
|
|
14
|
+
};
|
|
11
15
|
theme: ThemeSource;
|
|
16
|
+
/**
|
|
17
|
+
* Parent directory used to pre-fill the "新建项目" dialog's target path.
|
|
18
|
+
* Updated whenever a project is successfully created. `null` until the
|
|
19
|
+
* first create; the dialog then falls back to a platform default
|
|
20
|
+
* (Documents).
|
|
21
|
+
*/
|
|
22
|
+
lastCreateBaseDir: string | null;
|
|
12
23
|
}
|
|
13
24
|
export declare function loadWorkbenchSettings(): WorkbenchSettings;
|
|
14
25
|
export declare function saveWorkbenchSettings(settings: WorkbenchSettings): void;
|
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
import { app, nativeTheme } from 'electron';
|
|
2
2
|
import fs from 'fs';
|
|
3
3
|
import path from 'path';
|
|
4
|
+
import { DEFAULT_CDP_PORT } from '../../../shared/constants.js';
|
|
4
5
|
const DEFAULTS = {
|
|
5
6
|
cdp: {
|
|
6
7
|
enabled: false,
|
|
7
|
-
port:
|
|
8
|
+
port: DEFAULT_CDP_PORT,
|
|
8
9
|
},
|
|
9
10
|
mcp: {
|
|
10
11
|
enabled: false,
|
|
11
12
|
port: 7789,
|
|
12
13
|
},
|
|
14
|
+
compile: {
|
|
15
|
+
watch: true,
|
|
16
|
+
},
|
|
13
17
|
theme: 'system',
|
|
18
|
+
lastCreateBaseDir: null,
|
|
14
19
|
};
|
|
15
20
|
function getSettingsFile() {
|
|
16
21
|
return path.join(app.getPath('userData'), 'dimina-workbench-settings.json');
|
|
@@ -30,11 +35,22 @@ export function loadWorkbenchSettings() {
|
|
|
30
35
|
enabled: data.mcp?.enabled ?? DEFAULTS.mcp.enabled,
|
|
31
36
|
port: data.mcp?.port ?? DEFAULTS.mcp.port,
|
|
32
37
|
},
|
|
38
|
+
compile: {
|
|
39
|
+
watch: data.compile?.watch ?? DEFAULTS.compile.watch,
|
|
40
|
+
},
|
|
33
41
|
theme,
|
|
42
|
+
lastCreateBaseDir: typeof data.lastCreateBaseDir === 'string'
|
|
43
|
+
? data.lastCreateBaseDir
|
|
44
|
+
: DEFAULTS.lastCreateBaseDir,
|
|
34
45
|
};
|
|
35
46
|
}
|
|
36
47
|
catch {
|
|
37
|
-
return {
|
|
48
|
+
return {
|
|
49
|
+
...DEFAULTS,
|
|
50
|
+
cdp: { ...DEFAULTS.cdp },
|
|
51
|
+
mcp: { ...DEFAULTS.mcp },
|
|
52
|
+
compile: { ...DEFAULTS.compile },
|
|
53
|
+
};
|
|
38
54
|
}
|
|
39
55
|
}
|
|
40
56
|
export function saveWorkbenchSettings(settings) {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type SimulatorApiHandler = (params: unknown) => unknown | Promise<unknown>;
|
|
2
|
+
export interface SimulatorApiRegistry {
|
|
3
|
+
register(name: string, handler: SimulatorApiHandler): () => void;
|
|
4
|
+
list(): string[];
|
|
5
|
+
invoke(name: string, params: unknown): Promise<unknown>;
|
|
6
|
+
clear(): void;
|
|
7
|
+
}
|
|
8
|
+
export declare function createSimulatorApiRegistry(): SimulatorApiRegistry;
|
|
9
|
+
export declare const simulatorApiRegistry: SimulatorApiRegistry;
|
|
10
|
+
//# sourceMappingURL=custom-apis.d.ts.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export function createSimulatorApiRegistry() {
|
|
2
|
+
const handlers = new Map();
|
|
3
|
+
return {
|
|
4
|
+
register(name, handler) {
|
|
5
|
+
handlers.set(name, handler);
|
|
6
|
+
return () => {
|
|
7
|
+
if (handlers.get(name) === handler)
|
|
8
|
+
handlers.delete(name);
|
|
9
|
+
};
|
|
10
|
+
},
|
|
11
|
+
list() {
|
|
12
|
+
return Array.from(handlers.keys());
|
|
13
|
+
},
|
|
14
|
+
async invoke(name, params) {
|
|
15
|
+
const handler = handlers.get(name);
|
|
16
|
+
if (!handler)
|
|
17
|
+
throw new Error(`Simulator API "${name}" is not registered`);
|
|
18
|
+
return await handler(params);
|
|
19
|
+
},
|
|
20
|
+
clear() {
|
|
21
|
+
handlers.clear();
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export const simulatorApiRegistry = createSimulatorApiRegistry();
|
|
26
|
+
//# sourceMappingURL=custom-apis.js.map
|
|
@@ -16,5 +16,26 @@
|
|
|
16
16
|
* events stop flowing until they close it.
|
|
17
17
|
*/
|
|
18
18
|
import { type WebContents } from 'electron';
|
|
19
|
-
|
|
19
|
+
import { type Disposable } from '../../utils/disposable.js';
|
|
20
|
+
import { type SenderPolicy } from '../../utils/ipc-registry.js';
|
|
21
|
+
export interface SimulatorStorageOptions {
|
|
22
|
+
/**
|
|
23
|
+
* Sender gate applied to `SimulatorStorageChannel.GetSnapshot`.
|
|
24
|
+
* When provided, the IpcRegistry rejects invocations whose `event.sender`
|
|
25
|
+
* is not whitelisted (typically the workbench-wide policy that allows
|
|
26
|
+
* the main window renderer and overlay views only).
|
|
27
|
+
* Omitted in unit tests that mock the electron module.
|
|
28
|
+
*/
|
|
29
|
+
senderPolicy?: SenderPolicy;
|
|
30
|
+
/**
|
|
31
|
+
* Returns the appId of the currently-active project session, or null when
|
|
32
|
+
* no session is active. The simulator uses a fixed `persist:simulator`
|
|
33
|
+
* partition + simulator.html origin, so localStorage is shared across
|
|
34
|
+
* every project that has ever opened. The dimina runtime isolates writes
|
|
35
|
+
* with `${appId}_` prefixes; this callback lets the panel filter the
|
|
36
|
+
* CDP snapshot/event stream to the active appId.
|
|
37
|
+
*/
|
|
38
|
+
getActiveAppId: () => string | null;
|
|
39
|
+
}
|
|
40
|
+
export declare function setupSimulatorStorage(host: WebContents, options: SimulatorStorageOptions): Disposable;
|
|
20
41
|
//# sourceMappingURL=index.d.ts.map
|