@jay-framework/editor-protocol 0.12.0 → 0.14.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.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,20 @@
1
- import { PluginManifest as PluginManifest$1, DynamicContractConfig } from '@jay-framework/compiler-shared';
2
-
1
+ interface ContractTag {
2
+ tag: string;
3
+ type: string | string[];
4
+ dataType?: string;
5
+ elementType?: string;
6
+ required?: boolean;
7
+ repeated?: boolean;
8
+ tags?: ContractTag[];
9
+ link?: string;
10
+ trackBy?: string;
11
+ async?: boolean;
12
+ phase?: string;
13
+ }
14
+ interface Contract {
15
+ name: string;
16
+ tags: ContractTag[];
17
+ }
3
18
  interface BaseMessage<TResponse extends BaseResponse = BaseResponse> {
4
19
  type: string;
5
20
  }
@@ -36,6 +51,17 @@ interface HasImageMessage extends BaseMessage<HasImageResponse> {
36
51
  interface GetProjectInfoMessage extends BaseMessage<GetProjectInfoResponse> {
37
52
  type: 'getProjectInfo';
38
53
  }
54
+ interface ExportMessage<TVendorDoc> extends BaseMessage<ExportResponse> {
55
+ type: 'export';
56
+ vendorId: string;
57
+ pageUrl: string;
58
+ vendorDoc: TVendorDoc;
59
+ }
60
+ interface ImportMessage<TVendorDoc> extends BaseMessage<ImportResponse<TVendorDoc>> {
61
+ type: 'import';
62
+ vendorId: string;
63
+ pageUrl: string;
64
+ }
39
65
  interface PublishResponse extends BaseResponse {
40
66
  type: 'publish';
41
67
  status: {
@@ -61,7 +87,7 @@ interface ProjectPage {
61
87
  name: string;
62
88
  url: string;
63
89
  filePath: string;
64
- contractSchema?: ContractSchema;
90
+ contract?: Contract;
65
91
  usedComponents: {
66
92
  appName: string;
67
93
  componentName: string;
@@ -73,49 +99,9 @@ interface ProjectComponent {
73
99
  filePath: string;
74
100
  contractPath?: string;
75
101
  }
76
-
77
- interface PluginManifest extends PluginManifest$1 {
78
- }
79
- interface DynamicContractDef extends DynamicContractConfig {
80
- }
81
- interface StaticContractDef {
82
- name: string;
83
- contract: string;
84
- component: string;
85
- description?: string;
86
- }
87
102
  interface Plugin {
88
- manifest: PluginManifest;
89
- location: {
90
- type: 'local' | 'npm';
91
- path?: string;
92
- module?: string;
93
- };
94
- }
95
- interface InstalledApp {
96
103
  name: string;
97
- module: string;
98
- pages: {
99
- name: string;
100
- headless_components: {
101
- name: string;
102
- key: string;
103
- contract: string;
104
- slugs?: string[];
105
- }[];
106
- }[];
107
- components: {
108
- name: string;
109
- headless_components: {
110
- name: string;
111
- key: string;
112
- contract: string;
113
- }[];
114
- }[];
115
- config_map?: {
116
- display_name: string;
117
- key: string;
118
- }[];
104
+ contracts: Contract[];
119
105
  }
120
106
  interface ProjectInfo {
121
107
  name: string;
@@ -123,64 +109,49 @@ interface ProjectInfo {
123
109
  pages: ProjectPage[];
124
110
  components: ProjectComponent[];
125
111
  plugins: Plugin[];
126
- installedApps: InstalledApp[];
127
- installedAppContracts: {
128
- [appName: string]: InstalledAppContracts;
129
- };
130
112
  }
131
113
  interface GetProjectInfoResponse extends BaseResponse {
132
114
  type: 'getProjectInfo';
133
115
  info: ProjectInfo;
134
116
  }
135
- interface ContractTag {
136
- tag: string;
137
- type: string | string[];
138
- dataType?: string;
139
- elementType?: string;
140
- required?: boolean;
141
- repeated?: boolean;
142
- tags?: ContractTag[];
143
- link?: string;
117
+ interface ExportResponse extends BaseResponse {
118
+ type: 'export';
119
+ vendorSourcePath?: string;
120
+ jayHtmlPath?: string;
121
+ contractPath?: string;
122
+ warnings?: string[];
144
123
  }
145
- interface ContractSchema {
146
- name: string;
147
- tags: ContractTag[];
124
+ interface ImportResponse<TVendorDoc> extends BaseResponse {
125
+ type: 'import';
126
+ vendorDoc?: TVendorDoc;
148
127
  }
149
- interface InstalledAppContracts {
150
- appName: string;
151
- module: string;
152
- pages: Array<{
153
- pageName: string;
154
- contractSchema: ContractSchema;
155
- }>;
156
- components: Array<{
157
- componentName: string;
158
- contractSchema: ContractSchema;
159
- }>;
160
- }
161
- type EditorProtocolMessageTypes = PublishMessage | SaveImageMessage | HasImageMessage | GetProjectInfoMessage;
162
- type EditorProtocolResponseTypes = PublishResponse | SaveImageResponse | HasImageResponse | GetProjectInfoResponse;
163
- interface ProtocolMessage {
128
+ type EditorProtocolMessageTypes<TVendorDoc> = PublishMessage | SaveImageMessage | HasImageMessage | GetProjectInfoMessage | ExportMessage<TVendorDoc> | ImportMessage<TVendorDoc>;
129
+ type EditorProtocolResponseTypes<TVendorDoc> = PublishResponse | SaveImageResponse | HasImageResponse | GetProjectInfoResponse | ExportResponse | ImportResponse<TVendorDoc>;
130
+ interface ProtocolMessage<TVendorDoc> {
164
131
  id: string;
165
132
  timestamp: number;
166
- payload: EditorProtocolMessageTypes;
133
+ payload: EditorProtocolMessageTypes<TVendorDoc>;
167
134
  }
168
- interface ProtocolResponse {
135
+ interface ProtocolResponse<TVendorDoc> {
169
136
  id: string;
170
137
  timestamp: number;
171
- payload: EditorProtocolResponseTypes;
138
+ payload: EditorProtocolResponseTypes<TVendorDoc>;
172
139
  }
173
140
  interface EditorProtocol {
174
141
  publish(params: PublishMessage): Promise<PublishResponse>;
175
142
  saveImage(params: SaveImageMessage): Promise<SaveImageResponse>;
176
143
  hasImage(params: HasImageMessage): Promise<HasImageResponse>;
177
144
  getProjectInfo(params: GetProjectInfoMessage): Promise<GetProjectInfoResponse>;
145
+ export<TVendorDoc>(params: ExportMessage<TVendorDoc>): Promise<ExportResponse>;
146
+ import<TVendorDoc>(params: ImportMessage<TVendorDoc>): Promise<ImportResponse<TVendorDoc>>;
178
147
  }
179
148
  interface DevServerProtocol {
180
149
  onPublish(callback: EditorProtocol['publish']): void;
181
150
  onSaveImage(callback: EditorProtocol['saveImage']): void;
182
151
  onHasImage(callback: EditorProtocol['hasImage']): void;
183
152
  onGetProjectInfo(callback: EditorProtocol['getProjectInfo']): void;
153
+ onExport(callback: EditorProtocol['export']): void;
154
+ onImport(callback: EditorProtocol['import']): void;
184
155
  }
185
156
 
186
157
  interface EditorConfig {
@@ -202,11 +173,150 @@ declare function createPublishMessage(pages?: PublishMessage['pages'], component
202
173
  declare function createSaveImageMessage(imageId: string, imageData: string): SaveImageMessage;
203
174
  declare function createHasImageMessage(imageId: string): HasImageMessage;
204
175
  declare function createGetProjectInfoMessage(): GetProjectInfoMessage;
176
+ declare function createExportMessage<TVendorDoc>(vendorId: string, pageUrl: string, vendorDoc: TVendorDoc): ExportMessage<TVendorDoc>;
177
+ declare function createImportMessage<TVendorDoc>(vendorId: string, pageUrl: string): ImportMessage<TVendorDoc>;
205
178
  declare function createPublishResponse(status: PublishResponse['status']): PublishResponse;
206
179
  declare function createSaveImageResponse(success: boolean, imageUrl?: string, error?: string): SaveImageResponse;
207
180
  declare function createHasImageResponse(exists: boolean, imageUrl?: string): HasImageResponse;
208
181
  declare function createGetProjectInfoResponse(info: ProjectInfo, success?: boolean, error?: string): GetProjectInfoResponse;
209
- declare function createProtocolMessage(payload: EditorProtocolMessageTypes): ProtocolMessage;
210
- declare function createProtocolResponse(id: string, payload: EditorProtocolResponseTypes): ProtocolResponse;
182
+ declare function createExportResponse(success: boolean, vendorSourcePath?: string, jayHtmlPath?: string, contractPath?: string, warnings?: string[], error?: string): ExportResponse;
183
+ declare function createImportResponse<TVendorDoc>(success: boolean, vendorDoc?: TVendorDoc, error?: string): ImportResponse<TVendorDoc>;
184
+ declare function createProtocolMessage<TVendorDoc>(payload: EditorProtocolMessageTypes<TVendorDoc>): ProtocolMessage<TVendorDoc>;
185
+ declare function createProtocolResponse<TVendorDoc>(id: string, payload: EditorProtocolResponseTypes<TVendorDoc>): ProtocolResponse<TVendorDoc>;
186
+
187
+ /**
188
+ * Figma Vendor Document Type
189
+ *
190
+ * A JSON-compatible representation of Figma nodes that can be safely
191
+ * transmitted over the protocol.
192
+ *
193
+ * @example
194
+ * ```typescript
195
+ * import { FigmaVendorDocument } from '@jay-framework/editor-protocol';
196
+ *
197
+ * const sectionNode = figma.currentPage.selection[0];
198
+ * const vendorDoc: FigmaVendorDocument = serializeNode(sectionNode);
199
+ *
200
+ * await editorProtocol.export({
201
+ * vendorId: 'figma',
202
+ * pageUrl: '/home',
203
+ * vendorDoc
204
+ * });
205
+ * ```
206
+ */
207
+ type FigmaVendorDocument = {
208
+ id: string;
209
+ name: string;
210
+ type: string;
211
+ visible?: boolean;
212
+ locked?: boolean;
213
+ parentId?: string;
214
+ children?: FigmaVendorDocument[];
215
+ x?: number;
216
+ y?: number;
217
+ width?: number;
218
+ height?: number;
219
+ pluginData?: {
220
+ [key: string]: string;
221
+ };
222
+ componentPropertyDefinitions?: {
223
+ [propertyName: string]: {
224
+ type: 'VARIANT' | 'BOOLEAN' | 'TEXT' | 'INSTANCE_SWAP';
225
+ variantOptions?: string[];
226
+ defaultValue?: string | boolean;
227
+ };
228
+ };
229
+ componentSetId?: string;
230
+ componentSetName?: string;
231
+ mainComponentId?: string;
232
+ mainComponentName?: string;
233
+ componentProperties?: any;
234
+ variantProperties?: {
235
+ [propertyName: string]: string;
236
+ };
237
+ variants?: FigmaVendorDocument[];
238
+ characters?: string;
239
+ fontName?: {
240
+ family: string;
241
+ style: string;
242
+ } | 'MIXED';
243
+ fontSize?: number | 'MIXED';
244
+ fontWeight?: number | 'MIXED';
245
+ textAlignHorizontal?: 'LEFT' | 'CENTER' | 'RIGHT' | 'JUSTIFIED';
246
+ textAlignVertical?: 'TOP' | 'CENTER' | 'BOTTOM';
247
+ letterSpacing?: {
248
+ value: number;
249
+ unit: 'PIXELS' | 'PERCENT';
250
+ };
251
+ lineHeight?: {
252
+ value: number;
253
+ unit: 'PIXELS' | 'PERCENT' | 'AUTO';
254
+ } | {
255
+ unit: 'AUTO';
256
+ };
257
+ textDecoration?: 'NONE' | 'UNDERLINE' | 'STRIKETHROUGH';
258
+ textCase?: 'ORIGINAL' | 'UPPER' | 'LOWER' | 'TITLE';
259
+ textTruncation?: 'DISABLED' | 'ENDING';
260
+ maxLines?: number;
261
+ maxWidth?: number;
262
+ textAutoResize?: 'NONE' | 'WIDTH_AND_HEIGHT' | 'HEIGHT' | 'TRUNCATE';
263
+ hasMissingFont?: boolean;
264
+ hyperlinks?: Array<{
265
+ start: number;
266
+ end: number;
267
+ url: string;
268
+ }>;
269
+ fills?: any[];
270
+ strokes?: any[];
271
+ effects?: any[];
272
+ cornerRadius?: number | 'MIXED';
273
+ topLeftRadius?: number;
274
+ topRightRadius?: number;
275
+ bottomLeftRadius?: number;
276
+ bottomRightRadius?: number;
277
+ strokeWeight?: number;
278
+ strokeTopWeight?: number;
279
+ strokeBottomWeight?: number;
280
+ strokeLeftWeight?: number;
281
+ strokeRightWeight?: number;
282
+ dashPattern?: number[];
283
+ layoutMode?: 'NONE' | 'HORIZONTAL' | 'VERTICAL';
284
+ primaryAxisAlignItems?: 'MIN' | 'CENTER' | 'MAX' | 'SPACE_BETWEEN';
285
+ counterAxisAlignItems?: 'MIN' | 'CENTER' | 'MAX';
286
+ itemSpacing?: number;
287
+ paddingLeft?: number;
288
+ paddingRight?: number;
289
+ paddingTop?: number;
290
+ paddingBottom?: number;
291
+ layoutPositioning?: 'AUTO' | 'ABSOLUTE';
292
+ layoutSizingHorizontal?: 'FIXED' | 'HUG' | 'FILL';
293
+ layoutSizingVertical?: 'FIXED' | 'HUG' | 'FILL';
294
+ layoutGrow?: number;
295
+ layoutAlign?: 'MIN' | 'CENTER' | 'MAX' | 'STRETCH';
296
+ layoutWrap?: 'NO_WRAP' | 'WRAP';
297
+ clipsContent?: boolean;
298
+ overflowDirection?: 'NONE' | 'HORIZONTAL' | 'VERTICAL' | 'BOTH';
299
+ scrollBehavior?: 'SCROLLS' | 'FIXED';
300
+ parentLayoutMode?: 'NONE' | 'HORIZONTAL' | 'VERTICAL';
301
+ parentType?: string;
302
+ parentOverflowDirection?: 'NONE' | 'HORIZONTAL' | 'VERTICAL' | 'BOTH';
303
+ parentNumberOfFixedChildren?: number;
304
+ parentChildIndex?: number;
305
+ opacity?: number;
306
+ rotation?: number;
307
+ vectorPaths?: Array<{
308
+ windingRule: 'NONZERO' | 'EVENODD';
309
+ data: string;
310
+ }>;
311
+ fillGeometry?: Array<{
312
+ windingRule: 'NONZERO' | 'EVENODD';
313
+ data: string;
314
+ }>;
315
+ strokeGeometry?: Array<{
316
+ windingRule: 'NONZERO' | 'EVENODD';
317
+ data: string;
318
+ }>;
319
+ [key: string]: any;
320
+ };
211
321
 
212
- export { type BaseMessage, type BaseResponse, type ConnectionState, type ContractSchema, type ContractTag, type DevServerProtocol, type DynamicContractDef, type EditorConfig, type EditorProtocol, type EditorProtocolMessageTypes, type EditorProtocolResponseTypes, type GetProjectInfoMessage, type GetProjectInfoResponse, type HasImageMessage, type HasImageResponse, type InstalledApp, type InstalledAppContracts, type Plugin, type PluginManifest, type PortDiscoveryResponse, type ProjectComponent, type ProjectInfo, type ProjectPage, type ProtocolMessage, type ProtocolResponse, type PublishComponent, type PublishMessage, type PublishPage, type PublishResponse, type PublishStatus, type SaveImageMessage, type SaveImageResponse, type StaticContractDef, createGetProjectInfoMessage, createGetProjectInfoResponse, createHasImageMessage, createHasImageResponse, createProtocolMessage, createProtocolResponse, createPublishMessage, createPublishResponse, createSaveImageMessage, createSaveImageResponse };
322
+ export { type BaseMessage, type BaseResponse, type ConnectionState, type Contract, type ContractTag, type DevServerProtocol, type EditorConfig, type EditorProtocol, type EditorProtocolMessageTypes, type EditorProtocolResponseTypes, type ExportMessage, type ExportResponse, type FigmaVendorDocument, type GetProjectInfoMessage, type GetProjectInfoResponse, type HasImageMessage, type HasImageResponse, type ImportMessage, type ImportResponse, type Plugin, type PortDiscoveryResponse, type ProjectComponent, type ProjectInfo, type ProjectPage, type ProtocolMessage, type ProtocolResponse, type PublishComponent, type PublishMessage, type PublishPage, type PublishResponse, type PublishStatus, type SaveImageMessage, type SaveImageResponse, createExportMessage, createExportResponse, createGetProjectInfoMessage, createGetProjectInfoResponse, createHasImageMessage, createHasImageResponse, createImportMessage, createImportResponse, createProtocolMessage, createProtocolResponse, createPublishMessage, createPublishResponse, createSaveImageMessage, createSaveImageResponse };
package/dist/index.js CHANGED
@@ -23,6 +23,21 @@ function createGetProjectInfoMessage() {
23
23
  type: "getProjectInfo"
24
24
  };
25
25
  }
26
+ function createExportMessage(vendorId, pageUrl, vendorDoc) {
27
+ return {
28
+ type: "export",
29
+ vendorId,
30
+ pageUrl,
31
+ vendorDoc
32
+ };
33
+ }
34
+ function createImportMessage(vendorId, pageUrl) {
35
+ return {
36
+ type: "import",
37
+ vendorId,
38
+ pageUrl
39
+ };
40
+ }
26
41
  function createPublishResponse(status) {
27
42
  return {
28
43
  type: "publish",
@@ -54,6 +69,25 @@ function createGetProjectInfoResponse(info, success = true, error) {
54
69
  error
55
70
  };
56
71
  }
72
+ function createExportResponse(success, vendorSourcePath, jayHtmlPath, contractPath, warnings, error) {
73
+ return {
74
+ type: "export",
75
+ success,
76
+ vendorSourcePath,
77
+ jayHtmlPath,
78
+ contractPath,
79
+ warnings,
80
+ error
81
+ };
82
+ }
83
+ function createImportResponse(success, vendorDoc, error) {
84
+ return {
85
+ type: "import",
86
+ success,
87
+ vendorDoc,
88
+ error
89
+ };
90
+ }
57
91
  let messageIdCounter = 0;
58
92
  function generateMessageId() {
59
93
  const timestamp = Date.now();
@@ -75,10 +109,14 @@ function createProtocolResponse(id, payload) {
75
109
  };
76
110
  }
77
111
  export {
112
+ createExportMessage,
113
+ createExportResponse,
78
114
  createGetProjectInfoMessage,
79
115
  createGetProjectInfoResponse,
80
116
  createHasImageMessage,
81
117
  createHasImageResponse,
118
+ createImportMessage,
119
+ createImportResponse,
82
120
  createProtocolMessage,
83
121
  createProtocolResponse,
84
122
  createPublishMessage,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jay-framework/editor-protocol",
3
- "version": "0.12.0",
3
+ "version": "0.14.0",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/index.js",
@@ -24,11 +24,11 @@
24
24
  "test:watch": ":"
25
25
  },
26
26
  "dependencies": {
27
- "@jay-framework/compiler-shared": "^0.12.0"
27
+ "@jay-framework/compiler-shared": "^0.14.0"
28
28
  },
29
29
  "devDependencies": {
30
- "@jay-framework/dev-environment": "^0.12.0",
31
- "@jay-framework/jay-cli": "^0.12.0",
30
+ "@jay-framework/dev-environment": "^0.14.0",
31
+ "@jay-framework/jay-cli": "^0.14.0",
32
32
  "@types/node": "^22.15.21",
33
33
  "rimraf": "^5.0.5",
34
34
  "tsup": "^8.0.1",
package/readme.md CHANGED
@@ -25,12 +25,16 @@ import {
25
25
  createPublishMessage,
26
26
  createSaveImageMessage,
27
27
  createHasImageMessage,
28
+ createExportMessage,
29
+ createImportMessage,
28
30
  createProtocolMessage,
29
31
  } from '@jay-framework/editor-protocol';
30
32
 
31
33
  // Use in editor applications
32
34
  const editor: EditorProtocol = {
33
35
  publish: async (params) => ({
36
+ type: 'publish',
37
+ success: true,
34
38
  status: [
35
39
  {
36
40
  success: true,
@@ -39,8 +43,40 @@ const editor: EditorProtocol = {
39
43
  },
40
44
  ],
41
45
  }),
42
- saveImage: async (params) => ({ success: true, imageUrl: '/assets/image.png' }),
43
- hasImage: async (params) => ({ exists: true, imageUrl: '/assets/image.png' }),
46
+ saveImage: async (params) => ({
47
+ type: 'saveImage',
48
+ success: true,
49
+ imageUrl: '/assets/image.png',
50
+ }),
51
+ hasImage: async (params) => ({
52
+ type: 'hasImage',
53
+ success: true,
54
+ exists: true,
55
+ imageUrl: '/assets/image.png',
56
+ }),
57
+ getProjectInfo: async (params) => ({
58
+ type: 'getProjectInfo',
59
+ success: true,
60
+ info: {
61
+ name: 'My Project',
62
+ localPath: '/path/to/project',
63
+ pages: [],
64
+ components: [],
65
+ plugins: [],
66
+ },
67
+ }),
68
+ export: async (params) => ({
69
+ type: 'export',
70
+ success: true,
71
+ vendorSourcePath: '/pages/home/page.figma.json',
72
+ }),
73
+ import: async (params) => ({
74
+ type: 'import',
75
+ success: true,
76
+ vendorDoc: {
77
+ /* vendor document */
78
+ },
79
+ }),
44
80
  };
45
81
 
46
82
  // Use in dev servers
@@ -48,6 +84,9 @@ const server: DevServerProtocol = {
48
84
  onPublish: (callback) => {},
49
85
  onSaveImage: (callback) => {},
50
86
  onHasImage: (callback) => {},
87
+ onGetProjectInfo: (callback) => {},
88
+ onExport: (callback) => {},
89
+ onImport: (callback) => {},
51
90
  };
52
91
 
53
92
  // Create messages using constructors
@@ -91,6 +130,9 @@ const protocolMessage = createProtocolMessage(publishMessage);
91
130
  - `createPublishMessage(pages?, components?)` - Creates a publish message with optional pages and components
92
131
  - `createSaveImageMessage(imageId, imageData)` - Creates a save image message
93
132
  - `createHasImageMessage(imageId)` - Creates a has image message
133
+ - `createGetProjectInfoMessage()` - Creates a get project info message
134
+ - `createExportMessage<TVendorDoc>(vendorId, pageUrl, vendorDoc)` - Creates an export message with vendor document
135
+ - `createImportMessage<TVendorDoc>(vendorId, pageUrl)` - Creates an import message to retrieve vendor document
94
136
  - `createProtocolMessage(payload)` - Creates a protocol message wrapper with auto-generated timestamp-based ID
95
137
 
96
138
  ### Response Constructors
@@ -98,6 +140,9 @@ const protocolMessage = createProtocolMessage(publishMessage);
98
140
  - `createPublishResponse(status)` - Creates a publish response
99
141
  - `createSaveImageResponse(success, imageUrl?, error?)` - Creates a save image response
100
142
  - `createHasImageResponse(exists, imageUrl?)` - Creates a has image response
143
+ - `createGetProjectInfoResponse(info, success?, error?)` - Creates a get project info response
144
+ - `createExportResponse(success, vendorSourcePath?, jayHtmlPath?, contractPath?, warnings?, error?)` - Creates an export response
145
+ - `createImportResponse<TVendorDoc>(success, vendorDoc?, error?)` - Creates an import response with vendor document
101
146
  - `createProtocolResponse(id, payload)` - Creates a protocol response wrapper with timestamp
102
147
 
103
148
  ## Protocol Operations
@@ -121,6 +166,81 @@ Saves base64 image data to the dev server's public assets.
121
166
 
122
167
  Checks if an image with the given ID already exists on the server.
123
168
 
169
+ ### Get Project Info
170
+
171
+ Retrieves comprehensive project information including pages, components, and installed plugins with their contracts.
172
+
173
+ ### Export
174
+
175
+ Exports a vendor-specific document (e.g., Figma, Wix) to the dev server at a specific page route. The document is saved as `page.<vendorId>.json` alongside the page's jay-html file.
176
+
177
+ **Use case**: When a designer exports a Figma design to Jay, the original Figma document can be saved so it can be re-imported later.
178
+
179
+ **Example:**
180
+
181
+ ```typescript
182
+ import { createExportMessage } from '@jay-framework/editor-protocol';
183
+
184
+ interface FigmaDocument {
185
+ nodeId: string;
186
+ name: string;
187
+ layers: any[];
188
+ }
189
+
190
+ const figmaDoc: FigmaDocument = {
191
+ nodeId: 'abc123',
192
+ name: 'Homepage',
193
+ layers: [
194
+ /* ... */
195
+ ],
196
+ };
197
+
198
+ const exportMessage = createExportMessage<FigmaDocument>(
199
+ 'figma', // vendorId
200
+ '/home', // pageUrl
201
+ figmaDoc, // vendor document
202
+ );
203
+
204
+ const response = await editorClient.export(exportMessage);
205
+ // File saved at: src/pages/home/page.figma.json
206
+ ```
207
+
208
+ ### Import
209
+
210
+ Imports a previously exported vendor document from the dev server for a specific page route.
211
+
212
+ **Use case**: When reopening a page in Figma, retrieve the original Figma document to maintain design history and node references.
213
+
214
+ **Example:**
215
+
216
+ ```typescript
217
+ import { createImportMessage } from '@jay-framework/editor-protocol';
218
+
219
+ interface FigmaDocument {
220
+ nodeId: string;
221
+ name: string;
222
+ layers: any[];
223
+ }
224
+
225
+ const importMessage = createImportMessage<FigmaDocument>(
226
+ 'figma', // vendorId
227
+ '/home', // pageUrl
228
+ );
229
+
230
+ const response = await editorClient.import(importMessage);
231
+ if (response.success && response.vendorDoc) {
232
+ const figmaDoc = response.vendorDoc;
233
+ // Restore Figma design from saved document
234
+ console.log('Restored Figma node:', figmaDoc.nodeId);
235
+ }
236
+ ```
237
+
238
+ **File naming convention**: Vendor documents are saved as `page.<vendorId>.json` in the same directory as the page's jay-html file. For example:
239
+
240
+ - `/src/pages/home/page.jay-html`
241
+ - `/src/pages/home/page.figma.json`
242
+ - `/src/pages/home/page.wix.json`
243
+
124
244
  ## Contract Publishing
125
245
 
126
246
  Contract files enable headless component support by defining the component's data interface and refs structure. When publishing components or pages, you can optionally include contract content: