@vcp-dev/site-edit-engine 0.6.11 → 0.7.1
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 +5 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +11 -11
- package/dist/internal/protocol/capability.d.ts +2 -0
- package/dist/internal/protocol/event.d.ts +8 -4
- package/dist/internal/protocol/operation.d.ts +3 -1
- package/dist/internal/protocol/render.d.ts +4 -1
- package/dist/next-app-router.d.ts +2 -1
- package/dist/next-app-router.js +1 -1
- package/dist/page-template-managed-source.d.ts +59 -0
- package/dist/preview-runtime.d.ts +295 -22
- package/dist/runtime.d.ts +44 -15
- package/dist/types.d.ts +32 -22
- package/package.json +2 -2
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SiteEditCompositionContext } from "@vcp-dev/contracts";
|
|
1
2
|
/**
|
|
2
3
|
* 节点能力快照 —— 描述该节点支持的操作及约束。
|
|
3
4
|
*
|
|
@@ -7,6 +8,7 @@
|
|
|
7
8
|
* 不能被收窄为 "只能插入 button"。
|
|
8
9
|
*/
|
|
9
10
|
export interface NodeCapabilitySnapshot {
|
|
11
|
+
composition: SiteEditCompositionContext;
|
|
10
12
|
key: string;
|
|
11
13
|
canUpdateText: boolean;
|
|
12
14
|
canInsertChild: boolean;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { OperationResult } from "./operation.js";
|
|
2
2
|
import type { OperationError } from "./error.js";
|
|
3
|
+
import type { SiteEditCompositionContext } from "@vcp-dev/contracts";
|
|
3
4
|
/**
|
|
4
5
|
* 设计器事件联合类型 —— engine 向 client 推送的所有事件。
|
|
5
6
|
*
|
|
@@ -13,27 +14,30 @@ import type { OperationError } from "./error.js";
|
|
|
13
14
|
*/
|
|
14
15
|
export type DesignerEvent = {
|
|
15
16
|
type: "document-changed";
|
|
16
|
-
|
|
17
|
+
composition: SiteEditCompositionContext;
|
|
17
18
|
version: number;
|
|
18
19
|
} | {
|
|
19
20
|
type: "operation-completed";
|
|
21
|
+
composition: SiteEditCompositionContext;
|
|
20
22
|
result: OperationResult;
|
|
21
23
|
} | {
|
|
22
24
|
type: "operation-failed";
|
|
23
25
|
requestId: string;
|
|
26
|
+
composition: SiteEditCompositionContext;
|
|
24
27
|
error: OperationError;
|
|
25
28
|
} | {
|
|
26
29
|
type: "graph-invalidated";
|
|
27
|
-
|
|
30
|
+
composition: SiteEditCompositionContext;
|
|
28
31
|
} | {
|
|
29
32
|
type: "graph-ready";
|
|
30
|
-
|
|
33
|
+
composition: SiteEditCompositionContext;
|
|
31
34
|
version: number;
|
|
32
35
|
} | {
|
|
33
36
|
type: "graph-error";
|
|
34
|
-
|
|
37
|
+
composition: SiteEditCompositionContext;
|
|
35
38
|
message: string;
|
|
36
39
|
} | {
|
|
37
40
|
type: "capability-changed";
|
|
41
|
+
composition: SiteEditCompositionContext;
|
|
38
42
|
keys: string[];
|
|
39
43
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SiteEditInsertNodeSpec, SiteEditMoveTarget, SiteEditOperationParams, SiteEditOperationRequest, SiteEditOperationTarget, SiteEditOperationType, SiteEditOperationValue, SiteEditStyleBreakpoint, SiteEditStyleProperty, SiteEditStyleStateMode, SiteEditOperationOutput } from "@vcp-dev/contracts";
|
|
1
|
+
import type { SiteEditCompositionContext, SiteEditInsertNodeSpec, SiteEditMoveTarget, SiteEditOperationParams, SiteEditOperationRequest, SiteEditOperationTarget, SiteEditOperationType, SiteEditOperationValue, SiteEditStyleBreakpoint, SiteEditStyleProperty, SiteEditStyleStateMode, SiteEditOperationOutput } from "@vcp-dev/contracts";
|
|
2
2
|
import type { OperationError } from "./error.js";
|
|
3
3
|
/** caller-facing 操作类型 */
|
|
4
4
|
export type OperationType = SiteEditOperationType;
|
|
@@ -58,6 +58,8 @@ export interface OperationSelectionRef {
|
|
|
58
58
|
instanceCount?: number;
|
|
59
59
|
}
|
|
60
60
|
export interface OperationResult {
|
|
61
|
+
/** Normalized composition that owned this operation. */
|
|
62
|
+
composition: SiteEditCompositionContext;
|
|
61
63
|
/** 对应的请求 ID */
|
|
62
64
|
requestId: string;
|
|
63
65
|
/** 操作类型 */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SiteEditClassNameSourceStyleContext, SiteEditPageComposition } from "@vcp-dev/contracts";
|
|
1
|
+
import type { SiteEditClassNameSourceStyleContext, SiteEditCompositionContext, SiteEditPageComposition } from "@vcp-dev/contracts";
|
|
2
2
|
import type { NodeCapabilitySnapshot } from "./capability.js";
|
|
3
3
|
import type { BoundaryKind } from "./boundary.js";
|
|
4
4
|
import type { OperationType } from "./operation.js";
|
|
@@ -13,6 +13,7 @@ export interface ExternalSourceView {
|
|
|
13
13
|
* 由 engine 从 graph 投影而来,client 用于构建大纲 / 画布。
|
|
14
14
|
*/
|
|
15
15
|
export interface RenderDocument {
|
|
16
|
+
composition: SiteEditCompositionContext;
|
|
16
17
|
routeId: string;
|
|
17
18
|
version: number;
|
|
18
19
|
rootKeys: string[];
|
|
@@ -82,6 +83,7 @@ export interface DynamicDataSummaryView {
|
|
|
82
83
|
* 包含完整 capability、text segments、boundary 信息、邻接关系。
|
|
83
84
|
*/
|
|
84
85
|
export interface RenderObjectDetail {
|
|
86
|
+
composition: SiteEditCompositionContext;
|
|
85
87
|
key: string;
|
|
86
88
|
tag: string;
|
|
87
89
|
componentName: string;
|
|
@@ -111,6 +113,7 @@ export interface RenderObjectDetail {
|
|
|
111
113
|
* 以及完整 provenance chain、文本值等 detail-only 数据。
|
|
112
114
|
*/
|
|
113
115
|
export interface RenderObjectEditContext {
|
|
116
|
+
composition: SiteEditCompositionContext;
|
|
114
117
|
key: string;
|
|
115
118
|
tag: string;
|
|
116
119
|
componentName: string;
|
|
@@ -6,6 +6,7 @@ export { scanNextAppRouterRoutes } from "./next-app-router-fs.js";
|
|
|
6
6
|
export type SiteEditRouteSourceFile = {
|
|
7
7
|
path: string;
|
|
8
8
|
};
|
|
9
|
-
export declare function scanNextAppRouterRoutesFromFiles(files: SiteEditRouteSourceFile[]): SiteEditNextRouteConfig[];
|
|
9
|
+
export declare function scanNextAppRouterRoutesFromFiles(files: readonly SiteEditRouteSourceFile[]): SiteEditNextRouteConfig[];
|
|
10
10
|
export declare function resolveNextAppRouteId(pathname: string | null | undefined, routes: SiteEditNextRouteConfig[], basePath?: string): string | undefined;
|
|
11
|
+
export declare function isNextAppRouterDynamicRoute(routeId: string): boolean;
|
|
11
12
|
export declare function normalizeNextRoutePath(pathname: string | null | undefined, basePath?: string): string;
|
package/dist/next-app-router.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import c from"node:fs";import u from"node:path";var
|
|
1
|
+
import c from"node:fs";import u from"node:path";var P=/^page\.(?:tsx|ts|jsx|js|mjs|cjs)$/;function $(t){let r=W(t);return r?p(r).map(e=>({routeId:g(r,e),entryFile:d(u.relative(t,e))})).sort((e,n)=>e.routeId.localeCompare(n.routeId)):[]}function W(t){for(let r of["app","src/app"]){let e=u.join(t,r);if(c.existsSync(e)&&c.statSync(e).isDirectory()&&p(e).length>0)return e}return null}function p(t){let r=[];for(let e of c.readdirSync(t,{withFileTypes:!0})){let n=u.join(t,e.name);if(e.isDirectory()){if(e.name==="node_modules"||e.name.startsWith(".")||e.name.startsWith("_"))continue;r.push(...p(n));continue}e.isFile()&&P.test(e.name)&&r.push(n)}return r}function g(t,r){let e=d(u.relative(t,u.dirname(r))),n=e?e.split("/").map(S).filter(i=>!!i):[];return n.length===0?"/":`/${n.join("/")}`}function y(t){return t.startsWith("(")&&t.endsWith(")")}function S(t){return!t||t.startsWith("@")||t.startsWith("_")||y(t)?null:A(t)}function A(t){return t.replace(/^\((?:\.|\.\.|\.\.\.)\)/,"")}function d(t){return t.replace(/\\/g,"/")}var j=/^page\.(?:tsx|ts|jsx|js|mjs|cjs)$/,l=/^\[[^\]]+\]$/,h=/^\[\.\.\.[^\]]+\]$/,f=/^\[\[\.\.\.[^\]]+\]\]$/,m=new WeakMap;function k(t){let r=t.map(n=>T(n.path)),e=F(r);return e?r.filter(n=>B(e,n)).map(n=>({routeId:z(e,n),entryFile:n})).sort((n,i)=>n.routeId.localeCompare(i.routeId)):[]}function O(t,r,e=""){let n=x(t,e),i=v(r);return i.exactRouteIds.has(n)?n:i.dynamicMatchers.find(o=>o.matcher.test(n))?.routeId}function v(t){let r=t.map(o=>`${o.routeId}\0${o.entryFile}`).join("\0"),e=m.get(t);if(e?.signature===r)return e;let n=new Set(t.map(o=>o.routeId)),i=t.filter(o=>o.routeId!=="/"&&I(o.routeId)).sort((o,s)=>R(s.routeId)-R(o.routeId)||s.routeId.length-o.routeId.length||o.routeId.localeCompare(s.routeId)).map(o=>({routeId:o.routeId,matcher:D(o.routeId)})),a={signature:r,exactRouteIds:n,dynamicMatchers:i};return m.set(t,a),a}function I(t){return t.split("/").filter(Boolean).some(r=>l.test(r)||h.test(r)||f.test(r))}function Q(t){return I(x(t))}function x(t,r=""){let n=((t??"/").trim()||"/").split(/[?#]/,1)[0]||"/",i=n.startsWith("/")?n:`/${n}`,a=N(r),o=a&&(i===a||i.startsWith(`${a}/`))?i.slice(a.length)||"/":i,s=o.startsWith("/")?o:`/${o}`;return s==="/"?"/":s.replace(/\/+$/,"")}function F(t){return t.some(n=>n.startsWith("app/")&&!w(n))?"app":t.some(n=>n.startsWith("src/app/"))?"src/app":null}function w(t){return t.startsWith("app/_vcp/")||t.startsWith("src/app/_vcp/")}function B(t,r){if(!r.startsWith(`${t}/`))return!1;let e=r.slice(r.lastIndexOf("/")+1);return j.test(e)?r.slice(t.length+1,-e.length-1).split("/").filter(Boolean).every(n=>!n.startsWith("_")):!1}function z(t,r){let e=r.slice(t.length+1).split("/").slice(0,-1).map(_).filter(n=>!!n);return e.length===0?"/":`/${e.join("/")}`}function b(t){return t.startsWith("(")&&t.endsWith(")")}function _(t){return!t||t.startsWith("@")||t.startsWith("_")||b(t)?null:C(t)}function C(t){return t.replace(/^\((?:\.|\.\.|\.\.\.)\)/,"")}function D(t){if(t==="/")return/^\/$/;let r=t.split("/").filter(Boolean).map(e=>f.test(e)?"(?:/.*)?":h.test(e)?"/.+":l.test(e)?"/[^/]+":`/${M(e)}`).join("");return new RegExp(`^${r}$`)}function R(t){return t.split("/").filter(Boolean).reduce((r,e)=>f.test(e)?r+1:h.test(e)?r+2:l.test(e)?r+3:r+4,0)}function N(t){let r=t.trim();return!r||r==="/"?"":(r.startsWith("/")?r:`/${r}`).replace(/\/+$/,"")}function M(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function T(t){return t.replace(/\\/g,"/").replace(/^\.\//,"")}export{Q as isNextAppRouterDynamicRoute,x as normalizeNextRoutePath,O as resolveNextAppRouteId,$ as scanNextAppRouterRoutes,k as scanNextAppRouterRoutesFromFiles};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { type SiteEditCompositionContext, type SiteEditCompositionSelector, type ManagedPageTemplateRouteManifestV1 } from "@vcp-dev/contracts";
|
|
2
|
+
import type { SiteEditSnapshotFile } from "./types.js";
|
|
3
|
+
/** A synchronous source view used by the pure managed-source helpers. */
|
|
4
|
+
export type SiteEditFileSystem = ReadonlyMap<string, string>;
|
|
5
|
+
export type SiteEditManagedSourceFiles = SiteEditFileSystem | readonly SiteEditSnapshotFile[];
|
|
6
|
+
export interface ManagedPageTemplatePaths {
|
|
7
|
+
routeRoot: string;
|
|
8
|
+
manifestFile: string;
|
|
9
|
+
runtimeFile: string;
|
|
10
|
+
registryFile: string;
|
|
11
|
+
templateEntryFile: string;
|
|
12
|
+
}
|
|
13
|
+
export type SiteEditEngineComposition = {
|
|
14
|
+
context: SiteEditCompositionContext;
|
|
15
|
+
entryFile: string;
|
|
16
|
+
};
|
|
17
|
+
export type PageTemplateCompositionSelector = SiteEditCompositionSelector;
|
|
18
|
+
export type ManagedPageTemplateCompositionResolution = SiteEditEngineComposition & {
|
|
19
|
+
mode: "direct" | "delegated";
|
|
20
|
+
/** The server-only source file selected for this resolution. */
|
|
21
|
+
effectiveEntryFile: string;
|
|
22
|
+
};
|
|
23
|
+
export type PageTemplateManagedSourceErrorCode = "PAGE_TEMPLATE_MANAGED_SOURCE_INVALID" | "PAGE_TEMPLATE_ID_COLLISION" | "PAGE_TEMPLATE_ROUTE_AMBIGUOUS";
|
|
24
|
+
export interface PageTemplateManagedSourceErrorDetails {
|
|
25
|
+
reason: string;
|
|
26
|
+
routeId?: string;
|
|
27
|
+
path?: string;
|
|
28
|
+
templateId?: string;
|
|
29
|
+
safeName?: string;
|
|
30
|
+
candidates?: readonly string[];
|
|
31
|
+
issues?: readonly string[];
|
|
32
|
+
}
|
|
33
|
+
export declare class PageTemplateManagedSourceError extends Error {
|
|
34
|
+
readonly code: PageTemplateManagedSourceErrorCode;
|
|
35
|
+
readonly details: PageTemplateManagedSourceErrorDetails;
|
|
36
|
+
constructor(code: PageTemplateManagedSourceErrorCode, message: string, details: PageTemplateManagedSourceErrorDetails);
|
|
37
|
+
}
|
|
38
|
+
export declare function computePageTemplateRouteKey(routeId: string): string;
|
|
39
|
+
export declare function computePageTemplateSafeName(rawTemplateId: string): string;
|
|
40
|
+
export declare function computeManagedPageTemplatePaths(routeId: string, rawTemplateId: string): ManagedPageTemplatePaths;
|
|
41
|
+
export declare function assertNoPageTemplateSafeNameCollision(input: readonly string[] | readonly {
|
|
42
|
+
template_id: string;
|
|
43
|
+
}[] | {
|
|
44
|
+
rawTemplateIds: readonly string[];
|
|
45
|
+
} | {
|
|
46
|
+
templateIds: readonly string[];
|
|
47
|
+
}): void;
|
|
48
|
+
export declare function parseManagedPageTemplateManifest(input: {
|
|
49
|
+
routeId: string;
|
|
50
|
+
files: SiteEditManagedSourceFiles;
|
|
51
|
+
}): ManagedPageTemplateRouteManifestV1 | null;
|
|
52
|
+
export declare function resolveManagedPageTemplateComposition(input: {
|
|
53
|
+
selector: PageTemplateCompositionSelector;
|
|
54
|
+
files: SiteEditManagedSourceFiles;
|
|
55
|
+
canonicalEntryFile: string;
|
|
56
|
+
}): ManagedPageTemplateCompositionResolution;
|
|
57
|
+
export declare function scanSiteEditCompositionsFromFiles(input: {
|
|
58
|
+
files: SiteEditManagedSourceFiles;
|
|
59
|
+
}): SiteEditEngineComposition[];
|