@operato/board 1.22.2 → 1.23.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/CHANGELOG.md CHANGED
@@ -3,6 +3,15 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [1.23.0](https://github.com/hatiolab/operato/compare/v1.22.2...v1.23.0) (2026-03-30)
7
+
8
+
9
+ ### :rocket: New Features
10
+
11
+ * **board:** add board model cache ([1d97505](https://github.com/hatiolab/operato/commit/1d97505461f0a901e0e2102164d4ff8359abc842))
12
+
13
+
14
+
6
15
  ## [1.22.2](https://github.com/hatiolab/operato/compare/v1.22.1...v1.22.2) (2025-03-04)
7
16
 
8
17
  **Note:** Version bump only for package @operato/board
@@ -0,0 +1,30 @@
1
+ export interface CachedBoard {
2
+ id: string;
3
+ name: string;
4
+ model: any;
5
+ updatedAt: string;
6
+ }
7
+ export declare class BoardModelCache {
8
+ /**
9
+ * 캐시에서 보드 모델 조회
10
+ * @returns 캐시된 보드 또는 null
11
+ */
12
+ static get(boardId: string): Promise<CachedBoard | null>;
13
+ /**
14
+ * 보드 모델을 캐시에 저장
15
+ */
16
+ static put(boardId: string, name: string, model: string, updatedAt: string): Promise<void>;
17
+ /**
18
+ * 캐시가 최신인지 확인
19
+ * @returns true면 캐시 유효, false면 갱신 필요
20
+ */
21
+ static isValid(boardId: string, serverUpdatedAt: string): Promise<boolean>;
22
+ /**
23
+ * 특정 보드 캐시 삭제
24
+ */
25
+ static remove(boardId: string): Promise<void>;
26
+ /**
27
+ * 전체 캐시 클리어
28
+ */
29
+ static clear(): Promise<void>;
30
+ }
@@ -0,0 +1,93 @@
1
+ /*
2
+ * Copyright © HatioLab Inc. All rights reserved.
3
+ *
4
+ * BoardModelCache — 보드 모델 JSON을 IndexedDB에 캐싱.
5
+ *
6
+ * 캐시 히트 시 네트워크 대기 없이 즉시 scene 생성 가능.
7
+ * updatedAt 비교로 캐시 무효화.
8
+ */
9
+ import Dexie from 'dexie';
10
+ class BoardModelDatabase extends Dexie {
11
+ constructor() {
12
+ super('board-model-cache');
13
+ this.version(1).stores({
14
+ board_models: 'id'
15
+ });
16
+ }
17
+ }
18
+ const db = new BoardModelDatabase();
19
+ export class BoardModelCache {
20
+ /**
21
+ * 캐시에서 보드 모델 조회
22
+ * @returns 캐시된 보드 또는 null
23
+ */
24
+ static async get(boardId) {
25
+ try {
26
+ const record = await db.board_models.get(boardId);
27
+ if (!record)
28
+ return null;
29
+ return {
30
+ id: record.id,
31
+ name: record.name,
32
+ model: JSON.parse(record.model),
33
+ updatedAt: record.updatedAt
34
+ };
35
+ }
36
+ catch (_a) {
37
+ return null;
38
+ }
39
+ }
40
+ /**
41
+ * 보드 모델을 캐시에 저장
42
+ */
43
+ static async put(boardId, name, model, updatedAt) {
44
+ try {
45
+ await db.board_models.put({
46
+ id: boardId,
47
+ name,
48
+ model,
49
+ updatedAt,
50
+ cachedAt: Date.now()
51
+ });
52
+ }
53
+ catch (_a) {
54
+ // 캐시 저장 실패는 무시 — 기능에 영향 없음
55
+ }
56
+ }
57
+ /**
58
+ * 캐시가 최신인지 확인
59
+ * @returns true면 캐시 유효, false면 갱신 필요
60
+ */
61
+ static async isValid(boardId, serverUpdatedAt) {
62
+ try {
63
+ const record = await db.board_models.get(boardId);
64
+ return (record === null || record === void 0 ? void 0 : record.updatedAt) === serverUpdatedAt;
65
+ }
66
+ catch (_a) {
67
+ return false;
68
+ }
69
+ }
70
+ /**
71
+ * 특정 보드 캐시 삭제
72
+ */
73
+ static async remove(boardId) {
74
+ try {
75
+ await db.board_models.delete(boardId);
76
+ }
77
+ catch (_a) {
78
+ // ignore
79
+ }
80
+ }
81
+ /**
82
+ * 전체 캐시 클리어
83
+ */
84
+ static async clear() {
85
+ try {
86
+ await db.board_models.clear();
87
+ }
88
+ catch (_a) {
89
+ // ignore
90
+ }
91
+ }
92
+ }
93
+ //# sourceMappingURL=board-model-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"board-model-cache.js","sourceRoot":"","sources":["../../../src/data-storage/board-model-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAA;AAUzB,MAAM,kBAAmB,SAAQ,KAAK;IAGpC;QACE,KAAK,CAAC,mBAAmB,CAAC,CAAA;QAC1B,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;YACrB,YAAY,EAAE,IAAI;SACnB,CAAC,CAAA;IACJ,CAAC;CACF;AAED,MAAM,EAAE,GAAG,IAAI,kBAAkB,EAAE,CAAA;AASnC,MAAM,OAAO,eAAe;IAC1B;;;OAGG;IACH,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,OAAe;QAC9B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YACjD,IAAI,CAAC,MAAM;gBAAE,OAAO,IAAI,CAAA;YAExB,OAAO;gBACL,EAAE,EAAE,MAAM,CAAC,EAAE;gBACb,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC;gBAC/B,SAAS,EAAE,MAAM,CAAC,SAAS;aAC5B,CAAA;QACH,CAAC;QAAC,WAAM,CAAC;YACP,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,OAAe,EAAE,IAAY,EAAE,KAAa,EAAE,SAAiB;QAC9E,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC;gBACxB,EAAE,EAAE,OAAO;gBACX,IAAI;gBACJ,KAAK;gBACL,SAAS;gBACT,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE;aACrB,CAAC,CAAA;QACJ,CAAC;QAAC,WAAM,CAAC;YACP,2BAA2B;QAC7B,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,OAAe,EAAE,eAAuB;QAC3D,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YACjD,OAAO,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,SAAS,MAAK,eAAe,CAAA;QAC9C,CAAC;QAAC,WAAM,CAAC;YACP,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAe;QACjC,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QACvC,CAAC;QAAC,WAAM,CAAC;YACP,SAAS;QACX,CAAC;IACH,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,KAAK;QAChB,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,CAAA;QAC/B,CAAC;QAAC,WAAM,CAAC;YACP,SAAS;QACX,CAAC;IACH,CAAC;CACF","sourcesContent":["/*\n * Copyright © HatioLab Inc. All rights reserved.\n *\n * BoardModelCache — 보드 모델 JSON을 IndexedDB에 캐싱.\n *\n * 캐시 히트 시 네트워크 대기 없이 즉시 scene 생성 가능.\n * updatedAt 비교로 캐시 무효화.\n */\n\nimport Dexie from 'dexie'\n\ninterface IBoardModelRecord {\n id: string // board ID (primary key)\n name: string\n model: string // JSON string (파싱 전)\n updatedAt: string // 서버의 updatedAt\n cachedAt: number // 로컬 캐시 시점\n}\n\nclass BoardModelDatabase extends Dexie {\n board_models!: Dexie.Table<IBoardModelRecord, string>\n\n constructor() {\n super('board-model-cache')\n this.version(1).stores({\n board_models: 'id'\n })\n }\n}\n\nconst db = new BoardModelDatabase()\n\nexport interface CachedBoard {\n id: string\n name: string\n model: any // 파싱된 모델 객체\n updatedAt: string\n}\n\nexport class BoardModelCache {\n /**\n * 캐시에서 보드 모델 조회\n * @returns 캐시된 보드 또는 null\n */\n static async get(boardId: string): Promise<CachedBoard | null> {\n try {\n const record = await db.board_models.get(boardId)\n if (!record) return null\n\n return {\n id: record.id,\n name: record.name,\n model: JSON.parse(record.model),\n updatedAt: record.updatedAt\n }\n } catch {\n return null\n }\n }\n\n /**\n * 보드 모델을 캐시에 저장\n */\n static async put(boardId: string, name: string, model: string, updatedAt: string): Promise<void> {\n try {\n await db.board_models.put({\n id: boardId,\n name,\n model,\n updatedAt,\n cachedAt: Date.now()\n })\n } catch {\n // 캐시 저장 실패는 무시 — 기능에 영향 없음\n }\n }\n\n /**\n * 캐시가 최신인지 확인\n * @returns true면 캐시 유효, false면 갱신 필요\n */\n static async isValid(boardId: string, serverUpdatedAt: string): Promise<boolean> {\n try {\n const record = await db.board_models.get(boardId)\n return record?.updatedAt === serverUpdatedAt\n } catch {\n return false\n }\n }\n\n /**\n * 특정 보드 캐시 삭제\n */\n static async remove(boardId: string): Promise<void> {\n try {\n await db.board_models.delete(boardId)\n } catch {\n // ignore\n }\n }\n\n /**\n * 전체 캐시 클리어\n */\n static async clear(): Promise<void> {\n try {\n await db.board_models.clear()\n } catch {\n // ignore\n }\n }\n}\n"]}
@@ -1,6 +1,8 @@
1
1
  export * from './types.js';
2
2
  export { registerDefaultGroups } from './component/register-default-groups.js';
3
3
  export { BoardDataStorage, PlaylistStorage } from './data-storage/data-storage.js';
4
+ export { BoardModelCache } from './data-storage/board-model-cache.js';
5
+ export type { CachedBoard } from './data-storage/board-model-cache.js';
4
6
  export * from './ox-board-viewer.js';
5
7
  export * from './ox-board-player.js';
6
8
  export * from './ox-board-modeller.js';
package/dist/src/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from './types.js';
2
2
  export { registerDefaultGroups } from './component/register-default-groups.js';
3
3
  export { BoardDataStorage, PlaylistStorage } from './data-storage/data-storage.js';
4
+ export { BoardModelCache } from './data-storage/board-model-cache.js';
4
5
  export * from './ox-board-viewer.js';
5
6
  export * from './ox-board-player.js';
6
7
  export * from './ox-board-modeller.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAE1B,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAA;AAC9E,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAA;AAElF,cAAc,sBAAsB,CAAA;AACpC,cAAc,sBAAsB,CAAA;AACpC,cAAc,wBAAwB,CAAA;AACtC,cAAc,oBAAoB,CAAA","sourcesContent":["export * from './types.js'\n\nexport { registerDefaultGroups } from './component/register-default-groups.js'\nexport { BoardDataStorage, PlaylistStorage } from './data-storage/data-storage.js'\n\nexport * from './ox-board-viewer.js'\nexport * from './ox-board-player.js'\nexport * from './ox-board-modeller.js'\nexport * from './ox-board-list.js'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAE1B,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAA;AAC9E,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAA;AAClF,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAA;AAGrE,cAAc,sBAAsB,CAAA;AACpC,cAAc,sBAAsB,CAAA;AACpC,cAAc,wBAAwB,CAAA;AACtC,cAAc,oBAAoB,CAAA","sourcesContent":["export * from './types.js'\n\nexport { registerDefaultGroups } from './component/register-default-groups.js'\nexport { BoardDataStorage, PlaylistStorage } from './data-storage/data-storage.js'\nexport { BoardModelCache } from './data-storage/board-model-cache.js'\nexport type { CachedBoard } from './data-storage/board-model-cache.js'\n\nexport * from './ox-board-viewer.js'\nexport * from './ox-board-player.js'\nexport * from './ox-board-modeller.js'\nexport * from './ox-board-list.js'\n"]}
@@ -66,7 +66,7 @@ export declare class BoardViewer extends LitElement {
66
66
  getSceneImageData(base64?: boolean): Promise<{
67
67
  width: any;
68
68
  height: any;
69
- data: string | Uint8ClampedArray<ArrayBufferLike>;
69
+ data: string | ImageDataArray;
70
70
  } | undefined>;
71
71
  printTrick(image: string): Promise<void>;
72
72
  }