3dviewer-sdk 1.0.2 → 1.0.4

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.
@@ -0,0 +1,97 @@
1
+ import type { MarkupListItem, MarkupOperationResultPayload, PdfCurrentPagePayload, PdfModeEventPayload, PdfToolbarActionEventPayload } from "./messages";
2
+ export declare type ViewerEventMap = {
3
+ "camera:home": {
4
+ timestamp: number;
5
+ };
6
+ "node:select": {
7
+ nodeId: string;
8
+ timestamp: number;
9
+ };
10
+ "interaction:pan-change": {
11
+ enabled: boolean;
12
+ };
13
+ "toolbar:pdf-plan-mode": PdfModeEventPayload;
14
+ "toolbar:pdf-document-mode": PdfModeEventPayload;
15
+ "toolbar:pdf-first-page": PdfToolbarActionEventPayload;
16
+ "toolbar:pdf-previous-page": PdfToolbarActionEventPayload;
17
+ "toolbar:pdf-next-page": PdfToolbarActionEventPayload;
18
+ "toolbar:pdf-last-page": PdfToolbarActionEventPayload;
19
+ "toolbar:pdf-current-page": PdfCurrentPagePayload;
20
+ "modelTree:node-ids": {
21
+ requestId: string;
22
+ nodeIds: string[];
23
+ timestamp: number;
24
+ };
25
+ "sheets:list": {
26
+ requestId: string;
27
+ sheets: {
28
+ id: string | number;
29
+ name: string;
30
+ is3D?: boolean;
31
+ viewId?: string;
32
+ }[];
33
+ activeSheetId?: string | number | null;
34
+ timestamp: number;
35
+ };
36
+ "markup:list": {
37
+ requestId: string;
38
+ markups: MarkupListItem[];
39
+ timestamp: number;
40
+ };
41
+ "markup:save": MarkupOperationResultPayload;
42
+ "markup:cancel": MarkupOperationResultPayload;
43
+ };
44
+ export declare type LoadStage = "idle" | "uploading" | "converting" | "rendering" | "completed" | "error";
45
+ export declare type LoadStatePayload = {
46
+ isLoading: boolean;
47
+ stage: LoadStage;
48
+ message?: string;
49
+ elapsedMs?: number;
50
+ };
51
+ export declare type PreparedViewerData = {
52
+ baseFileId: string;
53
+ baseMajorRev: number;
54
+ baseMinorRev: number;
55
+ fileName: string;
56
+ query: string;
57
+ url: string;
58
+ };
59
+ export declare type FilesEventMap = {
60
+ "files:state": LoadStatePayload;
61
+ "files:upload:start": {
62
+ fileName: string;
63
+ };
64
+ "files:upload:success": {
65
+ fileName: string;
66
+ baseFileId: string;
67
+ };
68
+ "files:upload:error": {
69
+ fileName: string;
70
+ error: string;
71
+ };
72
+ "files:conversion:start": {
73
+ fileName: string;
74
+ };
75
+ "files:conversion:success": PreparedViewerData;
76
+ "files:conversion:error": {
77
+ fileName: string;
78
+ error: string;
79
+ };
80
+ "files:render:start": {
81
+ url: string;
82
+ };
83
+ "files:render:success": {
84
+ url: string;
85
+ };
86
+ "files:render:error": {
87
+ url?: string;
88
+ error: string;
89
+ };
90
+ "files:load:success": PreparedViewerData;
91
+ "files:load:error": {
92
+ error: string;
93
+ };
94
+ };
95
+ export declare type SdkEventMap = ViewerEventMap & FilesEventMap;
96
+ export declare type SdkEventKey = keyof SdkEventMap;
97
+ export declare type SdkEventPayload<K extends SdkEventKey> = SdkEventMap[K];
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,153 @@
1
+ export declare enum ViewerMessageType {
2
+ LANGUAGE_CHANGE = "viewer-language-change",
3
+ ZOOM = "viewer-zoom",
4
+ DRAW_MODE = "viewer-draw-mode",
5
+ EXPLODE = "viewer-explode",
6
+ MARKUP_ACTION = "viewer-markup-action",
7
+ MARKUP_SAVE = "viewer-markup-save",
8
+ MARKUP_CANCEL = "viewer-markup-cancel",
9
+ MARKUP_GET_LIST = "viewer-markup-get-list",
10
+ MARKUP_SAVE_RESULT = "viewer-markup-save-result",
11
+ MARKUP_CANCEL_RESULT = "viewer-markup-cancel-result",
12
+ MARKUP_LIST = "viewer-markup-list",
13
+ HOME = "viewer-home",
14
+ PAN_TOGGLE = "viewer-pan-toggle",
15
+ SELECT = "viewer-select",
16
+ AREA_SELECT = "viewer-area-select",
17
+ ORBIT = "viewer-orbit",
18
+ ROTATE_Z = "viewer-rotate-z",
19
+ WALK_THROUGH = "viewer-walk-through",
20
+ ZOOM_WINDOW = "viewer-zoom-window",
21
+ ZOOM_FIT = "viewer-zoom-fit",
22
+ TOOLBAR_CONFIG = "viewer-toolbar-config",
23
+ PANEL_OPEN = "viewer-panel-open",
24
+ PANEL_CLOSE = "viewer-panel-close",
25
+ CUTTING_PLANE_ACTION = "viewer-cutting-plane-action",
26
+ SHEETS_GET_LIST = "viewer-sheets-get-list",
27
+ SHEETS_LIST = "viewer-sheets-list",
28
+ SHEETS_APPLY = "viewer-sheets-apply",
29
+ TREE_SELECT_NODE = "viewer-tree-select-node",
30
+ TREE_GET_NODE_IDS = "viewer-tree-get-node-ids",
31
+ TREE_NODE_IDS = "viewer-tree-node-ids",
32
+ PDF_PLAN_MODE = "viewer-pdf-plan-mode",
33
+ PDF_DOCUMENT_MODE = "viewer-pdf-document-mode",
34
+ PDF_FIRST_PAGE = "viewer-pdf-first-page",
35
+ PDF_PREVIOUS_PAGE = "viewer-pdf-previous-page",
36
+ PDF_NEXT_PAGE = "viewer-pdf-next-page",
37
+ PDF_LAST_PAGE = "viewer-pdf-last-page",
38
+ PDF_CURRENT_PAGE = "viewer-pdf-current-page",
39
+ HOME_CLICK = "viewer-home-click",
40
+ NODE_SELECT = "viewer-node-select",
41
+ PAN_CHANGE = "viewer-pan-change"
42
+ }
43
+ export declare enum ViewerMessageSource {
44
+ SDK = "HC_SDK",
45
+ VIEWER = "HC_VIEWER"
46
+ }
47
+ export declare type OutgoingMessage<T = unknown> = {
48
+ source: ViewerMessageSource.SDK;
49
+ type: ViewerMessageType;
50
+ payload?: T;
51
+ };
52
+ export declare type IncomingMessage<T = any> = {
53
+ source?: ViewerMessageSource | string;
54
+ type: ViewerMessageType;
55
+ payload?: T;
56
+ };
57
+ export declare type LanguageCode = "en" | "vn";
58
+ export declare type LanguageChangePayload = {
59
+ language: LanguageCode;
60
+ timestamp?: number;
61
+ };
62
+ export declare type DrawModeValue = "shaded" | "wireframe" | "hidden-line" | "shaded-wire" | "xray" | "ghosting";
63
+ export declare type DrawModePayload = {
64
+ mode: DrawModeValue;
65
+ };
66
+ export declare type ExplodePayload = {
67
+ magnitude: number;
68
+ };
69
+ export declare type MarkupAction = "line" | "arrow" | "circle" | "ellipse" | "rectangle" | "polygon" | "polyline" | "textbox" | "note" | "callout" | "cloud" | "freehand";
70
+ export declare type MarkupActionPayload = {
71
+ action: MarkupAction;
72
+ };
73
+ export declare type MarkupRequestPayload = {
74
+ requestId: string;
75
+ };
76
+ export declare type MarkupOperationResultPayload = {
77
+ requestId: string;
78
+ success: boolean;
79
+ timestamp: number;
80
+ error?: string;
81
+ };
82
+ export declare type MarkupListItem = {
83
+ id: string;
84
+ viewId: string;
85
+ viewName?: string;
86
+ title: string;
87
+ type: string;
88
+ shapeName?: string;
89
+ createdDate?: string;
90
+ modifiedDate?: string;
91
+ createdBy?: string;
92
+ lastModifiedBy?: string;
93
+ };
94
+ export declare type MarkupListPayload = {
95
+ requestId: string;
96
+ markups: MarkupListItem[];
97
+ timestamp: number;
98
+ };
99
+ export declare type PanelTarget = "clipping-commands" | "setting" | "statesObjects" | "linkedObjects" | "model-tree" | "sheets" | "object-properties";
100
+ export declare type PanelOpenPayload = {
101
+ panel: PanelTarget;
102
+ format?: "3d" | "pdf";
103
+ };
104
+ export declare type PanelClosePayload = {
105
+ panel: PanelTarget;
106
+ format?: "3d" | "pdf";
107
+ };
108
+ export declare type CuttingPlaneAction = "close" | "multi" | "toggle-section" | "toggle-plane" | "plane-x" | "plane-y" | "plane-z" | "plane-box" | "rotate-box" | "reverse-plane-x" | "reverse-plane-y" | "reverse-plane-z";
109
+ export declare type CuttingPlaneActionPayload = {
110
+ action: CuttingPlaneAction;
111
+ };
112
+ export declare type SheetsGetListPayload = {
113
+ requestId: string;
114
+ };
115
+ export declare type SheetListItem = {
116
+ id: string | number;
117
+ name: string;
118
+ is3D?: boolean;
119
+ viewId?: string;
120
+ };
121
+ export declare type SheetsListPayload = {
122
+ requestId: string;
123
+ sheets: SheetListItem[];
124
+ activeSheetId?: string | number | null;
125
+ timestamp: number;
126
+ };
127
+ export declare type SheetsApplyPayload = {
128
+ sheetId: string | number;
129
+ };
130
+ export declare type TreeSelectNodePayload = {
131
+ nodeId: string;
132
+ };
133
+ export declare type TreeGetNodeIdsPayload = {
134
+ requestId: string;
135
+ onlyRealNodes?: boolean;
136
+ };
137
+ export declare type TreeNodeIdsPayload = {
138
+ requestId: string;
139
+ nodeIds: string[];
140
+ timestamp: number;
141
+ };
142
+ export declare type PdfModeEventPayload = {
143
+ mode: "plan" | "document";
144
+ timestamp: number;
145
+ };
146
+ export declare type PdfToolbarActionEventPayload = {
147
+ timestamp: number;
148
+ };
149
+ export declare type PdfCurrentPagePayload = {
150
+ pageIndex: number;
151
+ pageNumber: number;
152
+ timestamp: number;
153
+ };
@@ -0,0 +1,49 @@
1
+ // sdk/src/contracts/messages.ts
2
+ export var ViewerMessageType;
3
+ (function (ViewerMessageType) {
4
+ ViewerMessageType["LANGUAGE_CHANGE"] = "viewer-language-change";
5
+ ViewerMessageType["ZOOM"] = "viewer-zoom";
6
+ ViewerMessageType["DRAW_MODE"] = "viewer-draw-mode";
7
+ ViewerMessageType["EXPLODE"] = "viewer-explode";
8
+ ViewerMessageType["MARKUP_ACTION"] = "viewer-markup-action";
9
+ ViewerMessageType["MARKUP_SAVE"] = "viewer-markup-save";
10
+ ViewerMessageType["MARKUP_CANCEL"] = "viewer-markup-cancel";
11
+ ViewerMessageType["MARKUP_GET_LIST"] = "viewer-markup-get-list";
12
+ ViewerMessageType["MARKUP_SAVE_RESULT"] = "viewer-markup-save-result";
13
+ ViewerMessageType["MARKUP_CANCEL_RESULT"] = "viewer-markup-cancel-result";
14
+ ViewerMessageType["MARKUP_LIST"] = "viewer-markup-list";
15
+ ViewerMessageType["HOME"] = "viewer-home";
16
+ ViewerMessageType["PAN_TOGGLE"] = "viewer-pan-toggle";
17
+ ViewerMessageType["SELECT"] = "viewer-select";
18
+ ViewerMessageType["AREA_SELECT"] = "viewer-area-select";
19
+ ViewerMessageType["ORBIT"] = "viewer-orbit";
20
+ ViewerMessageType["ROTATE_Z"] = "viewer-rotate-z";
21
+ ViewerMessageType["WALK_THROUGH"] = "viewer-walk-through";
22
+ ViewerMessageType["ZOOM_WINDOW"] = "viewer-zoom-window";
23
+ ViewerMessageType["ZOOM_FIT"] = "viewer-zoom-fit";
24
+ ViewerMessageType["TOOLBAR_CONFIG"] = "viewer-toolbar-config";
25
+ ViewerMessageType["PANEL_OPEN"] = "viewer-panel-open";
26
+ ViewerMessageType["PANEL_CLOSE"] = "viewer-panel-close";
27
+ ViewerMessageType["CUTTING_PLANE_ACTION"] = "viewer-cutting-plane-action";
28
+ ViewerMessageType["SHEETS_GET_LIST"] = "viewer-sheets-get-list";
29
+ ViewerMessageType["SHEETS_LIST"] = "viewer-sheets-list";
30
+ ViewerMessageType["SHEETS_APPLY"] = "viewer-sheets-apply";
31
+ ViewerMessageType["TREE_SELECT_NODE"] = "viewer-tree-select-node";
32
+ ViewerMessageType["TREE_GET_NODE_IDS"] = "viewer-tree-get-node-ids";
33
+ ViewerMessageType["TREE_NODE_IDS"] = "viewer-tree-node-ids";
34
+ ViewerMessageType["PDF_PLAN_MODE"] = "viewer-pdf-plan-mode";
35
+ ViewerMessageType["PDF_DOCUMENT_MODE"] = "viewer-pdf-document-mode";
36
+ ViewerMessageType["PDF_FIRST_PAGE"] = "viewer-pdf-first-page";
37
+ ViewerMessageType["PDF_PREVIOUS_PAGE"] = "viewer-pdf-previous-page";
38
+ ViewerMessageType["PDF_NEXT_PAGE"] = "viewer-pdf-next-page";
39
+ ViewerMessageType["PDF_LAST_PAGE"] = "viewer-pdf-last-page";
40
+ ViewerMessageType["PDF_CURRENT_PAGE"] = "viewer-pdf-current-page";
41
+ ViewerMessageType["HOME_CLICK"] = "viewer-home-click";
42
+ ViewerMessageType["NODE_SELECT"] = "viewer-node-select";
43
+ ViewerMessageType["PAN_CHANGE"] = "viewer-pan-change";
44
+ })(ViewerMessageType || (ViewerMessageType = {}));
45
+ export var ViewerMessageSource;
46
+ (function (ViewerMessageSource) {
47
+ ViewerMessageSource["SDK"] = "HC_SDK";
48
+ ViewerMessageSource["VIEWER"] = "HC_VIEWER";
49
+ })(ViewerMessageSource || (ViewerMessageSource = {}));
@@ -0,0 +1,7 @@
1
+ export declare class Emitter<EventMap extends Record<string, any>> {
2
+ private listeners;
3
+ on<K extends keyof EventMap>(event: K, cb: (payload: EventMap[K]) => void): () => void;
4
+ off<K extends keyof EventMap>(event: K, cb: (payload: EventMap[K]) => void): void;
5
+ emit<K extends keyof EventMap>(event: K, payload: EventMap[K]): void;
6
+ clear(): void;
7
+ }
@@ -0,0 +1,31 @@
1
+ // sdk/src/core/emitter.ts
2
+ export class Emitter {
3
+ constructor() {
4
+ this.listeners = {};
5
+ }
6
+ on(event, cb) {
7
+ if (!this.listeners[event]) {
8
+ this.listeners[event] = [];
9
+ }
10
+ const arr = this.listeners[event];
11
+ arr.push(cb);
12
+ return () => this.off(event, cb);
13
+ }
14
+ off(event, cb) {
15
+ const arr = this.listeners[event];
16
+ if (!arr)
17
+ return;
18
+ const idx = arr.indexOf(cb);
19
+ if (idx >= 0)
20
+ arr.splice(idx, 1);
21
+ if (arr.length === 0)
22
+ delete this.listeners[event];
23
+ }
24
+ emit(event, payload) {
25
+ var _a;
26
+ (_a = this.listeners[event]) === null || _a === void 0 ? void 0 : _a.forEach((cb) => cb(payload));
27
+ }
28
+ clear() {
29
+ this.listeners = {};
30
+ }
31
+ }
package/dist/index.d.mts CHANGED
@@ -233,6 +233,26 @@ type FilesConfig = {
233
233
  viewerPath?: string;
234
234
  uploadPath?: string;
235
235
  };
236
+ type ConvertOptions = {
237
+ downloadUrl?: string;
238
+ };
239
+ type ConvertV2Options = {
240
+ filename: string;
241
+ originalFilePath: string;
242
+ downloadUrl: string;
243
+ baseFileId: string;
244
+ baseMajorRev?: number;
245
+ baseMinorRev?: number;
246
+ overwrite?: boolean;
247
+ project?: string;
248
+ convertOptions?: Partial<StreamConvertOptions>;
249
+ };
250
+ type StreamConvertOptions = {
251
+ convert3DModel: number;
252
+ convert2DSheet: number;
253
+ extractProperties: number;
254
+ childModels: number;
255
+ };
236
256
  declare class FilesModule {
237
257
  private viewer;
238
258
  on: {
@@ -282,12 +302,13 @@ declare class FilesModule {
282
302
  fileName: string;
283
303
  baseFileId: string;
284
304
  }>;
285
- convert(file?: File): Promise<PreparedViewerData>;
286
- prepare(file?: File): Promise<PreparedViewerData>;
305
+ convert(file?: File, options?: ConvertOptions): Promise<PreparedViewerData>;
306
+ prepare(file?: File, options?: ConvertOptions): Promise<PreparedViewerData>;
307
+ convertV2(options: ConvertV2Options): Promise<PreparedViewerData>;
287
308
  open(input: PreparedViewerData | {
288
309
  url: string;
289
310
  }): void;
290
- render(file?: File): Promise<PreparedViewerData>;
311
+ render(file?: File, options?: ConvertOptions): Promise<PreparedViewerData>;
291
312
  private resolveFile;
292
313
  private normalizeBaseUrl;
293
314
  private resolveBaseUrl;
@@ -301,8 +322,11 @@ declare class FilesModule {
301
322
  private getUploadSessionForFile;
302
323
  private uploadInternal;
303
324
  private buildCachePayload;
325
+ private buildConvertV2Payload;
304
326
  private cacheFile;
327
+ private cacheFileV2;
305
328
  private convertInternal;
329
+ private convertV2Internal;
306
330
  private updateState;
307
331
  private withOperation;
308
332
  private toErrorMessage;
@@ -475,4 +499,4 @@ declare class Viewer3D {
475
499
  private handleMessage;
476
500
  }
477
501
 
478
- export { type FilesConfig, type LanguageCode, type LoadStage, type LoadStatePayload, type MarkupAction, type MarkupListItem, type MarkupOperationResultPayload, type PreparedViewerData, Viewer3D };
502
+ export { type ConvertOptions, type ConvertV2Options, type FilesConfig, type LanguageCode, type LoadStage, type LoadStatePayload, type MarkupAction, type MarkupListItem, type MarkupOperationResultPayload, type PreparedViewerData, Viewer3D };
package/dist/index.d.ts CHANGED
@@ -233,6 +233,26 @@ type FilesConfig = {
233
233
  viewerPath?: string;
234
234
  uploadPath?: string;
235
235
  };
236
+ type ConvertOptions = {
237
+ downloadUrl?: string;
238
+ };
239
+ type ConvertV2Options = {
240
+ filename: string;
241
+ originalFilePath: string;
242
+ downloadUrl: string;
243
+ baseFileId: string;
244
+ baseMajorRev?: number;
245
+ baseMinorRev?: number;
246
+ overwrite?: boolean;
247
+ project?: string;
248
+ convertOptions?: Partial<StreamConvertOptions>;
249
+ };
250
+ type StreamConvertOptions = {
251
+ convert3DModel: number;
252
+ convert2DSheet: number;
253
+ extractProperties: number;
254
+ childModels: number;
255
+ };
236
256
  declare class FilesModule {
237
257
  private viewer;
238
258
  on: {
@@ -282,12 +302,13 @@ declare class FilesModule {
282
302
  fileName: string;
283
303
  baseFileId: string;
284
304
  }>;
285
- convert(file?: File): Promise<PreparedViewerData>;
286
- prepare(file?: File): Promise<PreparedViewerData>;
305
+ convert(file?: File, options?: ConvertOptions): Promise<PreparedViewerData>;
306
+ prepare(file?: File, options?: ConvertOptions): Promise<PreparedViewerData>;
307
+ convertV2(options: ConvertV2Options): Promise<PreparedViewerData>;
287
308
  open(input: PreparedViewerData | {
288
309
  url: string;
289
310
  }): void;
290
- render(file?: File): Promise<PreparedViewerData>;
311
+ render(file?: File, options?: ConvertOptions): Promise<PreparedViewerData>;
291
312
  private resolveFile;
292
313
  private normalizeBaseUrl;
293
314
  private resolveBaseUrl;
@@ -301,8 +322,11 @@ declare class FilesModule {
301
322
  private getUploadSessionForFile;
302
323
  private uploadInternal;
303
324
  private buildCachePayload;
325
+ private buildConvertV2Payload;
304
326
  private cacheFile;
327
+ private cacheFileV2;
305
328
  private convertInternal;
329
+ private convertV2Internal;
306
330
  private updateState;
307
331
  private withOperation;
308
332
  private toErrorMessage;
@@ -475,4 +499,4 @@ declare class Viewer3D {
475
499
  private handleMessage;
476
500
  }
477
501
 
478
- export { type FilesConfig, type LanguageCode, type LoadStage, type LoadStatePayload, type MarkupAction, type MarkupListItem, type MarkupOperationResultPayload, type PreparedViewerData, Viewer3D };
502
+ export { type ConvertOptions, type ConvertV2Options, type FilesConfig, type LanguageCode, type LoadStage, type LoadStatePayload, type MarkupAction, type MarkupListItem, type MarkupOperationResultPayload, type PreparedViewerData, Viewer3D };
package/dist/index.js CHANGED
@@ -146,7 +146,7 @@ var NodeModule = class {
146
146
 
147
147
  // src/modules/files.module.ts
148
148
  var DEFAULT_API_BASE_URL = "https://dev.3dviewer.anybim.vn";
149
- var DEFAULT_VIEWER_ORIGIN = "https://dev.3dviewer.anybim.vn";
149
+ var DEFAULT_VIEWER_ORIGIN = "http://localhost:3000";
150
150
  var FilesModule = class {
151
151
  constructor(viewer) {
152
152
  this.viewer = viewer;
@@ -194,12 +194,12 @@ var FilesModule = class {
194
194
  });
195
195
  }
196
196
  // Trigger conversion flow and resolve final viewer metadata.
197
- async convert(file) {
197
+ async convert(file, options = {}) {
198
198
  const target = this.resolveFile(file);
199
199
  return this.withOperation({ stage: "converting", message: "Converting file..." }, async () => {
200
200
  this.viewer._emit("files:conversion:start", { fileName: target.name });
201
201
  try {
202
- const prepared = await this.convertInternal(target);
202
+ const prepared = await this.convertInternal(target, options);
203
203
  this.viewer._emit("files:conversion:success", prepared);
204
204
  return prepared;
205
205
  } catch (e) {
@@ -209,14 +209,28 @@ var FilesModule = class {
209
209
  });
210
210
  }
211
211
  // Convenience API: upload first, then convert in one call.
212
- async prepare(file) {
212
+ async prepare(file, options = {}) {
213
213
  const target = this.resolveFile(file);
214
214
  return this.withOperation({ stage: "uploading", message: "Preparing file..." }, async () => {
215
215
  await this.uploadInternal(target);
216
- const prepared = await this.convertInternal(target);
216
+ const prepared = await this.convertInternal(target, options);
217
217
  return prepared;
218
218
  });
219
219
  }
220
+ // Trigger the newer downloadUrl-based conversion flow.
221
+ async convertV2(options) {
222
+ return this.withOperation({ stage: "converting", message: "Converting file..." }, async () => {
223
+ this.viewer._emit("files:conversion:start", { fileName: options.filename });
224
+ try {
225
+ const prepared = await this.convertV2Internal(options);
226
+ this.viewer._emit("files:conversion:success", prepared);
227
+ return prepared;
228
+ } catch (e) {
229
+ this.viewer._emit("files:conversion:error", { fileName: options.filename, error: this.toErrorMessage(e) });
230
+ throw e;
231
+ }
232
+ });
233
+ }
220
234
  // Open iframe with an already prepared viewer URL.
221
235
  open(input) {
222
236
  const url = input.url;
@@ -230,11 +244,11 @@ var FilesModule = class {
230
244
  }
231
245
  }
232
246
  // Full pipeline: upload + convert + open iframe.
233
- async render(file) {
247
+ async render(file, options = {}) {
234
248
  const target = this.resolveFile(file);
235
249
  return this.withOperation({ stage: "uploading", message: "Uploading + converting + opening..." }, async () => {
236
250
  await this.upload(target);
237
- const prepared = await this.convert(target);
251
+ const prepared = await this.convert(target, options);
238
252
  this.updateState({ stage: "rendering", message: "Opening viewer..." });
239
253
  this.open(prepared);
240
254
  this.viewer._emit("files:load:success", prepared);
@@ -327,10 +341,11 @@ var FilesModule = class {
327
341
  }
328
342
  }
329
343
  // Build StreamFile payload compatible with conversion service.
330
- buildCachePayload(file, baseFileId) {
344
+ buildCachePayload(file, baseFileId, options = {}) {
331
345
  const createdDate = (/* @__PURE__ */ new Date()).toISOString();
332
346
  return {
333
347
  filename: file.name,
348
+ ...options.downloadUrl ? { downloadUrl: options.downloadUrl } : {},
334
349
  baseFileId,
335
350
  baseMajorRev: 0,
336
351
  baseMinorRev: 0,
@@ -373,11 +388,31 @@ var FilesModule = class {
373
388
  attemptedConvertTimes: 0
374
389
  };
375
390
  }
391
+ // Build payload for POST /api/StreamFile/convert.
392
+ buildConvertV2Payload(options) {
393
+ var _a, _b;
394
+ const convertOptions = {
395
+ convert3DModel: 1,
396
+ convert2DSheet: 1,
397
+ extractProperties: 1,
398
+ childModels: 0,
399
+ ...options.convertOptions
400
+ };
401
+ return {
402
+ filename: options.filename,
403
+ originalFilePath: options.originalFilePath,
404
+ convertOptions,
405
+ downloadUrl: options.downloadUrl,
406
+ baseFileId: options.baseFileId,
407
+ baseMajorRev: (_a = options.baseMajorRev) != null ? _a : 0,
408
+ baseMinorRev: (_b = options.baseMinorRev) != null ? _b : 0
409
+ };
410
+ }
376
411
  // Submit conversion/caching request and return service response.
377
- async cacheFile(file, baseFileId) {
412
+ async cacheFile(file, baseFileId, options = {}) {
378
413
  const hostConversion = await this.resolveHostConversion();
379
414
  const url = `${hostConversion}/api/StreamFile?overwrite=true&ignore_line_weight=1`;
380
- const payload = this.buildCachePayload(file, baseFileId);
415
+ const payload = this.buildCachePayload(file, baseFileId, options);
381
416
  const response = await fetch(url, {
382
417
  method: "POST",
383
418
  headers: {
@@ -393,17 +428,45 @@ var FilesModule = class {
393
428
  }
394
429
  return await response.json();
395
430
  }
431
+ // Submit conversion request to the newer downloadUrl-based endpoint.
432
+ async cacheFileV2(options) {
433
+ const hostConversion = await this.resolveHostConversion();
434
+ const params = new URLSearchParams();
435
+ if (typeof options.overwrite === "boolean") {
436
+ params.set("overwrite", String(options.overwrite));
437
+ }
438
+ if (options.project) {
439
+ params.set("project", options.project);
440
+ }
441
+ const query = params.toString();
442
+ const url = `${hostConversion}/api/StreamFile/convert${query ? `?${query}` : ""}`;
443
+ const payload = this.buildConvertV2Payload(options);
444
+ const response = await fetch(url, {
445
+ method: "POST",
446
+ headers: {
447
+ "Content-Type": "application/json",
448
+ Accept: "application/json"
449
+ },
450
+ body: JSON.stringify(payload)
451
+ });
452
+ if (!response.ok) {
453
+ throw new Error(
454
+ `Cache/convert v2 failed (${response.status} ${response.statusText})`
455
+ );
456
+ }
457
+ return await response.json();
458
+ }
396
459
  // Convert file and generate final iframe URL with query string.
397
- async convertInternal(file) {
460
+ async convertInternal(file, options = {}) {
398
461
  var _a, _b, _c, _d;
399
462
  this.updateState({ stage: "converting", message: "Converting file..." });
400
463
  const uploadSession = this.getUploadSessionForFile(file) || this.createUploadSession(file);
401
464
  const seedBaseFileId = uploadSession.baseFileId;
402
- const cacheResult = await this.cacheFile(file, seedBaseFileId);
465
+ const cacheResult = await this.cacheFile(file, seedBaseFileId, options);
403
466
  const baseFileId = (_a = cacheResult.baseFileId) != null ? _a : seedBaseFileId;
404
467
  const baseMajorRev = (_b = cacheResult.baseMajorRev) != null ? _b : 0;
405
468
  const baseMinorRev = (_c = cacheResult.baseMinorRev) != null ? _c : 0;
406
- const fileName = cacheResult.filename || file.name;
469
+ const fileName = cacheResult.filename || cacheResult.fileName || file.name;
407
470
  const cacheListItem = { baseFileId, baseMajorRev, baseMinorRev, fileName };
408
471
  if (cacheResult.cacheStatus !== 2) {
409
472
  throw new Error(`Conversion not ready after first request (cacheStatus=${(_d = cacheResult.cacheStatus) != null ? _d : "unknown"})`);
@@ -414,6 +477,24 @@ var FilesModule = class {
414
477
  const url = `${viewerBase}${viewerPath}?${query}`;
415
478
  return { baseFileId, baseMajorRev, baseMinorRev, fileName, query, url };
416
479
  }
480
+ async convertV2Internal(options) {
481
+ var _a, _b, _c, _d, _e;
482
+ this.updateState({ stage: "converting", message: "Converting file..." });
483
+ const cacheResult = await this.cacheFileV2(options);
484
+ const baseFileId = (_a = cacheResult.baseFileId) != null ? _a : options.baseFileId;
485
+ const baseMajorRev = (_c = (_b = cacheResult.baseMajorRev) != null ? _b : options.baseMajorRev) != null ? _c : 0;
486
+ const baseMinorRev = (_e = (_d = cacheResult.baseMinorRev) != null ? _d : options.baseMinorRev) != null ? _e : 0;
487
+ const fileName = cacheResult.filename || cacheResult.fileName || options.filename;
488
+ if (cacheResult.cacheStatus !== void 0 && cacheResult.cacheStatus !== 2) {
489
+ throw new Error(`Conversion not ready after v2 request (cacheStatus=${cacheResult.cacheStatus})`);
490
+ }
491
+ const cacheListItem = { baseFileId, baseMajorRev, baseMinorRev, fileName };
492
+ const query = new URLSearchParams({ fileList: JSON.stringify([cacheListItem]) }).toString();
493
+ const viewerBase = this.resolveViewerOrigin();
494
+ const viewerPath = this.resolveViewerPath();
495
+ const url = `${viewerBase}${viewerPath}?${query}`;
496
+ return { baseFileId, baseMajorRev, baseMinorRev, fileName, query, url };
497
+ }
417
498
  // Update internal loading state and emit state event.
418
499
  updateState(next) {
419
500
  const elapsedMs = this.operationStartTime > 0 ? Date.now() - this.operationStartTime : 0;