@flowgram.ai/history-storage 0.1.0-alpha.6 → 0.1.0-alpha.8

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/esm/index.js CHANGED
@@ -147,8 +147,8 @@ var HistoryStorageManager = class {
147
147
  * @param ctx
148
148
  */
149
149
  onInit(_ctx, opts) {
150
- this.db = new HistoryDatabase(opts?.databaseName);
151
- if (opts?.resourceStorageLimit) {
150
+ this.db = new HistoryDatabase(opts == null ? void 0 : opts.databaseName);
151
+ if (opts == null ? void 0 : opts.resourceStorageLimit) {
152
152
  this.db.resourceStorageLimit = opts.resourceStorageLimit;
153
153
  }
154
154
  this._toDispose.push(
@@ -191,6 +191,7 @@ var HistoryStorageManager = class {
191
191
  * @returns
192
192
  */
193
193
  historyItemToRecord(historyService, historyItem) {
194
+ var _a;
194
195
  const operations = historyItem.operations.map(
195
196
  (op) => this.historyOperationToRecord(historyItem, op)
196
197
  );
@@ -199,7 +200,7 @@ var HistoryStorageManager = class {
199
200
  uuid: historyItem.id,
200
201
  timestamp: historyItem.timestamp,
201
202
  type: historyItem.type,
202
- resourceURI: historyItem.uri?.toString() || "",
203
+ resourceURI: ((_a = historyItem.uri) == null ? void 0 : _a.toString()) || "",
203
204
  resourceJSON: historyService.getSnapshot() || ""
204
205
  },
205
206
  operations
@@ -212,13 +213,14 @@ var HistoryStorageManager = class {
212
213
  * @returns
213
214
  */
214
215
  historyOperationToRecord(historyItem, op) {
216
+ var _a, _b;
215
217
  return {
216
218
  uuid: op.id,
217
219
  type: op.type,
218
220
  timestamp: op.timestamp,
219
221
  label: op.label || "",
220
- uri: op?.uri?.toString() || "",
221
- resourceURI: historyItem.uri?.toString() || "",
222
+ uri: ((_a = op == null ? void 0 : op.uri) == null ? void 0 : _a.toString()) || "",
223
+ resourceURI: ((_b = historyItem.uri) == null ? void 0 : _b.toString()) || "",
222
224
  description: op.description || "",
223
225
  value: JSON.stringify(op.value),
224
226
  historyId: historyItem.id
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/create-history-storage-plugin.ts","../../src/history-storage-manager.ts","../../src/history-database.ts","../../src/history-storage-container-module.ts","../../src/use-storage-hisotry-items.tsx"],"sourcesContent":["import { definePluginCreator } from '@flowgram.ai/core';\n\nimport { HistoryStoragePluginOptions } from './types';\nimport { HistoryStorageManager } from './history-storage-manager';\nimport { HistoryStorageContainerModule } from './history-storage-container-module';\n\nexport const createHistoryStoragePlugin = definePluginCreator<HistoryStoragePluginOptions>({\n onBind: ({ bind, rebind }) => {},\n onInit(ctx, opts): void {\n const historyStorageManager = ctx.get<HistoryStorageManager>(HistoryStorageManager);\n historyStorageManager.onInit(ctx, opts);\n },\n onDispose(ctx) {\n const historyStorageManager = ctx.get<HistoryStorageManager>(HistoryStorageManager);\n historyStorageManager.dispose();\n },\n containerModules: [HistoryStorageContainerModule],\n});\n","import { inject, injectable } from 'inversify';\nimport { DisposableCollection } from '@flowgram.ai/utils';\nimport {\n HistoryItem,\n HistoryManager,\n HistoryOperation,\n HistoryStackChangeType,\n HistoryService,\n HistoryStackAddOperationEvent,\n HistoryStackUpdateOperationEvent,\n} from '@flowgram.ai/history';\nimport { PluginContext } from '@flowgram.ai/core';\n\nimport { HistoryOperationRecord, HistoryRecord, HistoryStoragePluginOptions } from './types';\nimport { HistoryDatabase } from './history-database';\n\n/**\n * 历史存储管理\n */\n@injectable()\nexport class HistoryStorageManager {\n private _toDispose = new DisposableCollection();\n\n db: HistoryDatabase;\n\n @inject(HistoryManager)\n protected historyManager: HistoryManager;\n\n /**\n * 初始化\n * @param ctx\n */\n onInit(_ctx: PluginContext, opts: HistoryStoragePluginOptions) {\n this.db = new HistoryDatabase(opts?.databaseName);\n\n if (opts?.resourceStorageLimit) {\n this.db.resourceStorageLimit = opts.resourceStorageLimit;\n }\n\n this._toDispose.push(\n this.historyManager.historyStack.onChange(event => {\n if (event.type === HistoryStackChangeType.ADD) {\n const [history, operations] = this.historyItemToRecord(event.service, event.value);\n this.db.addHistoryRecord(history, operations).catch(console.error);\n }\n\n // operation merge的时候需要更新snapshot\n if (\n [HistoryStackChangeType.ADD_OPERATION, HistoryStackChangeType.UPDATE_OPERATION].includes(\n event.type,\n )\n ) {\n const {\n service,\n value: { historyItem },\n } = event as HistoryStackAddOperationEvent | HistoryStackUpdateOperationEvent;\n // 更新快照\n this.db\n .updateHistoryByUUID(historyItem.id, {\n resourceJSON: service.getSnapshot() || '',\n })\n .catch(console.error);\n }\n\n if (event.type === HistoryStackChangeType.ADD_OPERATION) {\n const operationRecord: HistoryOperationRecord = this.historyOperationToRecord(\n event.value.historyItem,\n event.value.operation,\n );\n this.db.addOperationRecord(operationRecord).catch(console.error);\n }\n if (event.type === HistoryStackChangeType.UPDATE_OPERATION) {\n const operationRecord: HistoryOperationRecord = this.historyOperationToRecord(\n event.value.historyItem,\n event.value.operation,\n );\n this.db.updateOperationRecord(operationRecord).catch(console.error);\n }\n }),\n );\n }\n\n /**\n * 内存历史转数据表记录\n * @param historyItem\n * @returns\n */\n historyItemToRecord(\n historyService: HistoryService,\n historyItem: HistoryItem,\n ): [HistoryRecord, HistoryOperationRecord[]] {\n const operations = historyItem.operations.map(op =>\n this.historyOperationToRecord(historyItem, op),\n );\n\n return [\n {\n uuid: historyItem.id,\n timestamp: historyItem.timestamp,\n type: historyItem.type,\n resourceURI: historyItem.uri?.toString() || '',\n resourceJSON: historyService.getSnapshot() || '',\n },\n operations,\n ];\n }\n\n /**\n * 内存操作转数据表操作\n * @param historyItem\n * @param op\n * @returns\n */\n historyOperationToRecord(historyItem: HistoryItem, op: HistoryOperation): HistoryOperationRecord {\n return {\n uuid: op.id,\n type: op.type,\n timestamp: op.timestamp,\n label: op.label || '',\n uri: op?.uri?.toString() || '',\n resourceURI: historyItem.uri?.toString() || '',\n description: op.description || '',\n value: JSON.stringify(op.value),\n historyId: historyItem.id,\n };\n }\n\n /**\n * 销毁\n */\n dispose() {\n this._toDispose.dispose();\n }\n}\n","import Dexie, { type Table } from 'dexie';\n\nimport { HistoryOperationRecord, HistoryRecord } from './types';\n\n/**\n * 历史数据库\n */\nexport class HistoryDatabase extends Dexie {\n readonly history: Table<HistoryRecord>;\n\n readonly operation: Table<HistoryOperationRecord>;\n\n resourceStorageLimit: number = 100;\n\n constructor(databaseName: string = 'ide-history-storage') {\n super(databaseName);\n this.version(1).stores({\n history: '++id, &uuid, resourceURI',\n operation: '++id, &uuid, historyId, uri, resourceURI',\n });\n }\n\n /**\n * 某个uri下所有的history记录\n * @param resourceURI 资源uri\n * @returns\n */\n allHistoryByResourceURI(resourceURI: string) {\n return this.history.where({ resourceURI }).toArray();\n }\n\n /**\n * 根据uuid获取历史\n * @param uuid\n * @returns\n */\n getHistoryByUUID(uuid: string) {\n return this.history.get({ uuid });\n }\n\n /**\n * 某个uri下所有的operation记录\n * @param resourceURI 资源uri\n * @returns\n */\n allOperationByResourceURI(resourceURI: string) {\n return this.operation.where({ resourceURI }).toArray();\n }\n\n /**\n * 添加历史记录\n * @param history 历史记录\n * @param operations 操作记录\n * @returns\n */\n addHistoryRecord(history: HistoryRecord, operations: HistoryOperationRecord[]) {\n return this.transaction('rw', this.history, this.operation, async () => {\n const count = await this.history.where({ resourceURI: history.resourceURI }).count();\n if (count >= this.resourceStorageLimit) {\n const limit = count - this.resourceStorageLimit;\n const items = await this.history\n .where({ resourceURI: history.resourceURI })\n .limit(limit)\n .toArray();\n const ids = items.map(i => i.id);\n const uuid = items.map(i => i.uuid);\n await Promise.all([\n this.history.bulkDelete(ids),\n ...uuid.map(async uuid => {\n await this.operation.where({ historyId: uuid }).delete();\n }),\n ]);\n }\n\n return Promise.all([this.history.add(history), this.operation.bulkAdd(operations)]);\n });\n }\n\n /**\n * 更新历史记录\n * @param historyRecord\n * @returns\n */\n async updateHistoryByUUID(uuid: string, historyRecord: Partial<HistoryRecord>) {\n const history = await this.getHistoryByUUID(uuid);\n if (!history) {\n console.warn('no history record found');\n return;\n }\n return this.history.update(history.id, historyRecord);\n }\n\n /**\n * 添加操作记录\n * @param record 操作记录\n * @returns\n */\n addOperationRecord(record: HistoryOperationRecord) {\n return this.operation.add(record);\n }\n\n /**\n * 更新操作记录\n * @param record 操作记录\n * @returns\n */\n async updateOperationRecord(record: HistoryOperationRecord) {\n const op = await this.operation.where({ uuid: record.uuid }).first();\n if (!op) {\n console.warn('no operation record found');\n return;\n }\n return this.operation.put({\n id: op.id,\n ...record,\n });\n }\n\n /**\n * 重置数据库\n * @returns\n */\n reset() {\n return this.transaction('rw', this.history, this.operation, async () => {\n await Promise.all(this.tables.map(table => table.clear()));\n });\n }\n\n /**\n * 清空某个资源下所有的数据\n * @param resourceURI\n * @returns\n */\n resetByResourceURI(resourceURI: string) {\n return this.transaction('rw', this.history, this.operation, async () => {\n await Promise.all(this.tables.map(table => table.where({ resourceURI }).delete()));\n });\n }\n}\n","import { ContainerModule } from 'inversify';\n\nimport { HistoryStorageManager } from './history-storage-manager';\n\nexport const HistoryStorageContainerModule = new ContainerModule(bind => {\n bind(HistoryStorageManager).toSelf().inSingletonScope();\n});\n","import { groupBy } from 'lodash';\nimport { useLiveQuery } from 'dexie-react-hooks';\nimport { HistoryItem, HistoryOperation, HistoryStack } from '@flowgram.ai/history';\n\nimport { HistoryStorageManager } from './history-storage-manager';\nexport function useStorageHistoryItems(\n historyStorageManager: HistoryStorageManager,\n resourceURI: string\n): {\n items: HistoryItem[];\n} {\n const items: HistoryItem[] =\n useLiveQuery(async () => {\n const [historyItems, operations] = await Promise.all([\n historyStorageManager.db.allHistoryByResourceURI(resourceURI),\n historyStorageManager.db.allOperationByResourceURI(resourceURI),\n ]);\n\n const grouped = groupBy<HistoryOperation>(\n operations.map((o) => ({\n id: o.uuid,\n timestamp: o.timestamp,\n type: o.type,\n label: o.label,\n description: o.description,\n value: o.value ? JSON.parse(o.value) : undefined,\n uri: o.uri,\n historyId: o.historyId,\n })),\n 'historyId'\n );\n return historyItems\n .sort((a, b) => (b.id as number) - (a.id as number))\n .map(\n (historyItem) =>\n ({\n id: historyItem.uuid,\n type: historyItem.type,\n timestamp: historyItem.timestamp,\n operations: grouped[historyItem.uuid] || [],\n time: HistoryStack.dateFormat(historyItem.timestamp),\n uri: historyItem.resourceURI,\n } as HistoryItem)\n );\n }, [resourceURI]) || [];\n\n return {\n items,\n };\n}\n"],"mappings":"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","names":["uuid"]}
1
+ {"version":3,"sources":["../../src/create-history-storage-plugin.ts","../../src/history-storage-manager.ts","../../src/history-database.ts","../../src/history-storage-container-module.ts","../../src/use-storage-hisotry-items.tsx"],"sourcesContent":["import { definePluginCreator } from '@flowgram.ai/core';\n\nimport { HistoryStoragePluginOptions } from './types';\nimport { HistoryStorageManager } from './history-storage-manager';\nimport { HistoryStorageContainerModule } from './history-storage-container-module';\n\nexport const createHistoryStoragePlugin = definePluginCreator<HistoryStoragePluginOptions>({\n onBind: ({ bind, rebind }) => {},\n onInit(ctx, opts): void {\n const historyStorageManager = ctx.get<HistoryStorageManager>(HistoryStorageManager);\n historyStorageManager.onInit(ctx, opts);\n },\n onDispose(ctx) {\n const historyStorageManager = ctx.get<HistoryStorageManager>(HistoryStorageManager);\n historyStorageManager.dispose();\n },\n containerModules: [HistoryStorageContainerModule],\n});\n","import { inject, injectable } from 'inversify';\nimport { DisposableCollection } from '@flowgram.ai/utils';\nimport {\n HistoryItem,\n HistoryManager,\n HistoryOperation,\n HistoryStackChangeType,\n HistoryService,\n HistoryStackAddOperationEvent,\n HistoryStackUpdateOperationEvent,\n} from '@flowgram.ai/history';\nimport { PluginContext } from '@flowgram.ai/core';\n\nimport { HistoryOperationRecord, HistoryRecord, HistoryStoragePluginOptions } from './types';\nimport { HistoryDatabase } from './history-database';\n\n/**\n * 历史存储管理\n */\n@injectable()\nexport class HistoryStorageManager {\n private _toDispose = new DisposableCollection();\n\n db: HistoryDatabase;\n\n @inject(HistoryManager)\n protected historyManager: HistoryManager;\n\n /**\n * 初始化\n * @param ctx\n */\n onInit(_ctx: PluginContext, opts: HistoryStoragePluginOptions) {\n this.db = new HistoryDatabase(opts?.databaseName);\n\n if (opts?.resourceStorageLimit) {\n this.db.resourceStorageLimit = opts.resourceStorageLimit;\n }\n\n this._toDispose.push(\n this.historyManager.historyStack.onChange(event => {\n if (event.type === HistoryStackChangeType.ADD) {\n const [history, operations] = this.historyItemToRecord(event.service, event.value);\n this.db.addHistoryRecord(history, operations).catch(console.error);\n }\n\n // operation merge的时候需要更新snapshot\n if (\n [HistoryStackChangeType.ADD_OPERATION, HistoryStackChangeType.UPDATE_OPERATION].includes(\n event.type,\n )\n ) {\n const {\n service,\n value: { historyItem },\n } = event as HistoryStackAddOperationEvent | HistoryStackUpdateOperationEvent;\n // 更新快照\n this.db\n .updateHistoryByUUID(historyItem.id, {\n resourceJSON: service.getSnapshot() || '',\n })\n .catch(console.error);\n }\n\n if (event.type === HistoryStackChangeType.ADD_OPERATION) {\n const operationRecord: HistoryOperationRecord = this.historyOperationToRecord(\n event.value.historyItem,\n event.value.operation,\n );\n this.db.addOperationRecord(operationRecord).catch(console.error);\n }\n if (event.type === HistoryStackChangeType.UPDATE_OPERATION) {\n const operationRecord: HistoryOperationRecord = this.historyOperationToRecord(\n event.value.historyItem,\n event.value.operation,\n );\n this.db.updateOperationRecord(operationRecord).catch(console.error);\n }\n }),\n );\n }\n\n /**\n * 内存历史转数据表记录\n * @param historyItem\n * @returns\n */\n historyItemToRecord(\n historyService: HistoryService,\n historyItem: HistoryItem,\n ): [HistoryRecord, HistoryOperationRecord[]] {\n const operations = historyItem.operations.map(op =>\n this.historyOperationToRecord(historyItem, op),\n );\n\n return [\n {\n uuid: historyItem.id,\n timestamp: historyItem.timestamp,\n type: historyItem.type,\n resourceURI: historyItem.uri?.toString() || '',\n resourceJSON: historyService.getSnapshot() || '',\n },\n operations,\n ];\n }\n\n /**\n * 内存操作转数据表操作\n * @param historyItem\n * @param op\n * @returns\n */\n historyOperationToRecord(historyItem: HistoryItem, op: HistoryOperation): HistoryOperationRecord {\n return {\n uuid: op.id,\n type: op.type,\n timestamp: op.timestamp,\n label: op.label || '',\n uri: op?.uri?.toString() || '',\n resourceURI: historyItem.uri?.toString() || '',\n description: op.description || '',\n value: JSON.stringify(op.value),\n historyId: historyItem.id,\n };\n }\n\n /**\n * 销毁\n */\n dispose() {\n this._toDispose.dispose();\n }\n}\n","import Dexie, { type Table } from 'dexie';\n\nimport { HistoryOperationRecord, HistoryRecord } from './types';\n\n/**\n * 历史数据库\n */\nexport class HistoryDatabase extends Dexie {\n readonly history: Table<HistoryRecord>;\n\n readonly operation: Table<HistoryOperationRecord>;\n\n resourceStorageLimit: number = 100;\n\n constructor(databaseName: string = 'ide-history-storage') {\n super(databaseName);\n this.version(1).stores({\n history: '++id, &uuid, resourceURI',\n operation: '++id, &uuid, historyId, uri, resourceURI',\n });\n }\n\n /**\n * 某个uri下所有的history记录\n * @param resourceURI 资源uri\n * @returns\n */\n allHistoryByResourceURI(resourceURI: string) {\n return this.history.where({ resourceURI }).toArray();\n }\n\n /**\n * 根据uuid获取历史\n * @param uuid\n * @returns\n */\n getHistoryByUUID(uuid: string) {\n return this.history.get({ uuid });\n }\n\n /**\n * 某个uri下所有的operation记录\n * @param resourceURI 资源uri\n * @returns\n */\n allOperationByResourceURI(resourceURI: string) {\n return this.operation.where({ resourceURI }).toArray();\n }\n\n /**\n * 添加历史记录\n * @param history 历史记录\n * @param operations 操作记录\n * @returns\n */\n addHistoryRecord(history: HistoryRecord, operations: HistoryOperationRecord[]) {\n return this.transaction('rw', this.history, this.operation, async () => {\n const count = await this.history.where({ resourceURI: history.resourceURI }).count();\n if (count >= this.resourceStorageLimit) {\n const limit = count - this.resourceStorageLimit;\n const items = await this.history\n .where({ resourceURI: history.resourceURI })\n .limit(limit)\n .toArray();\n const ids = items.map(i => i.id);\n const uuid = items.map(i => i.uuid);\n await Promise.all([\n this.history.bulkDelete(ids),\n ...uuid.map(async uuid => {\n await this.operation.where({ historyId: uuid }).delete();\n }),\n ]);\n }\n\n return Promise.all([this.history.add(history), this.operation.bulkAdd(operations)]);\n });\n }\n\n /**\n * 更新历史记录\n * @param historyRecord\n * @returns\n */\n async updateHistoryByUUID(uuid: string, historyRecord: Partial<HistoryRecord>) {\n const history = await this.getHistoryByUUID(uuid);\n if (!history) {\n console.warn('no history record found');\n return;\n }\n return this.history.update(history.id, historyRecord);\n }\n\n /**\n * 添加操作记录\n * @param record 操作记录\n * @returns\n */\n addOperationRecord(record: HistoryOperationRecord) {\n return this.operation.add(record);\n }\n\n /**\n * 更新操作记录\n * @param record 操作记录\n * @returns\n */\n async updateOperationRecord(record: HistoryOperationRecord) {\n const op = await this.operation.where({ uuid: record.uuid }).first();\n if (!op) {\n console.warn('no operation record found');\n return;\n }\n return this.operation.put({\n id: op.id,\n ...record,\n });\n }\n\n /**\n * 重置数据库\n * @returns\n */\n reset() {\n return this.transaction('rw', this.history, this.operation, async () => {\n await Promise.all(this.tables.map(table => table.clear()));\n });\n }\n\n /**\n * 清空某个资源下所有的数据\n * @param resourceURI\n * @returns\n */\n resetByResourceURI(resourceURI: string) {\n return this.transaction('rw', this.history, this.operation, async () => {\n await Promise.all(this.tables.map(table => table.where({ resourceURI }).delete()));\n });\n }\n}\n","import { ContainerModule } from 'inversify';\n\nimport { HistoryStorageManager } from './history-storage-manager';\n\nexport const HistoryStorageContainerModule = new ContainerModule(bind => {\n bind(HistoryStorageManager).toSelf().inSingletonScope();\n});\n","import { groupBy } from 'lodash';\nimport { useLiveQuery } from 'dexie-react-hooks';\nimport { HistoryItem, HistoryOperation, HistoryStack } from '@flowgram.ai/history';\n\nimport { HistoryStorageManager } from './history-storage-manager';\nexport function useStorageHistoryItems(\n historyStorageManager: HistoryStorageManager,\n resourceURI: string\n): {\n items: HistoryItem[];\n} {\n const items: HistoryItem[] =\n useLiveQuery(async () => {\n const [historyItems, operations] = await Promise.all([\n historyStorageManager.db.allHistoryByResourceURI(resourceURI),\n historyStorageManager.db.allOperationByResourceURI(resourceURI),\n ]);\n\n const grouped = groupBy<HistoryOperation>(\n operations.map((o) => ({\n id: o.uuid,\n timestamp: o.timestamp,\n type: o.type,\n label: o.label,\n description: o.description,\n value: o.value ? JSON.parse(o.value) : undefined,\n uri: o.uri,\n historyId: o.historyId,\n })),\n 'historyId'\n );\n return historyItems\n .sort((a, b) => (b.id as number) - (a.id as number))\n .map(\n (historyItem) =>\n ({\n id: historyItem.uuid,\n type: historyItem.type,\n timestamp: historyItem.timestamp,\n operations: grouped[historyItem.uuid] || [],\n time: HistoryStack.dateFormat(historyItem.timestamp),\n uri: historyItem.resourceURI,\n } as HistoryItem)\n );\n }, [resourceURI]) || [];\n\n return {\n items,\n };\n}\n"],"mappings":"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","names":["uuid"]}
package/dist/index.js CHANGED
@@ -181,8 +181,8 @@ var HistoryStorageManager = class {
181
181
  * @param ctx
182
182
  */
183
183
  onInit(_ctx, opts) {
184
- this.db = new HistoryDatabase(opts?.databaseName);
185
- if (opts?.resourceStorageLimit) {
184
+ this.db = new HistoryDatabase(opts == null ? void 0 : opts.databaseName);
185
+ if (opts == null ? void 0 : opts.resourceStorageLimit) {
186
186
  this.db.resourceStorageLimit = opts.resourceStorageLimit;
187
187
  }
188
188
  this._toDispose.push(
@@ -225,6 +225,7 @@ var HistoryStorageManager = class {
225
225
  * @returns
226
226
  */
227
227
  historyItemToRecord(historyService, historyItem) {
228
+ var _a;
228
229
  const operations = historyItem.operations.map(
229
230
  (op) => this.historyOperationToRecord(historyItem, op)
230
231
  );
@@ -233,7 +234,7 @@ var HistoryStorageManager = class {
233
234
  uuid: historyItem.id,
234
235
  timestamp: historyItem.timestamp,
235
236
  type: historyItem.type,
236
- resourceURI: historyItem.uri?.toString() || "",
237
+ resourceURI: ((_a = historyItem.uri) == null ? void 0 : _a.toString()) || "",
237
238
  resourceJSON: historyService.getSnapshot() || ""
238
239
  },
239
240
  operations
@@ -246,13 +247,14 @@ var HistoryStorageManager = class {
246
247
  * @returns
247
248
  */
248
249
  historyOperationToRecord(historyItem, op) {
250
+ var _a, _b;
249
251
  return {
250
252
  uuid: op.id,
251
253
  type: op.type,
252
254
  timestamp: op.timestamp,
253
255
  label: op.label || "",
254
- uri: op?.uri?.toString() || "",
255
- resourceURI: historyItem.uri?.toString() || "",
256
+ uri: ((_a = op == null ? void 0 : op.uri) == null ? void 0 : _a.toString()) || "",
257
+ resourceURI: ((_b = historyItem.uri) == null ? void 0 : _b.toString()) || "",
256
258
  description: op.description || "",
257
259
  value: JSON.stringify(op.value),
258
260
  historyId: historyItem.id
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/create-history-storage-plugin.ts","../src/history-storage-manager.ts","../src/history-database.ts","../src/history-storage-container-module.ts","../src/use-storage-hisotry-items.tsx"],"sourcesContent":["export * from './create-history-storage-plugin';\nexport * from './use-storage-hisotry-items';\nexport * from './types';\nexport * from './history-database';\nexport * from './history-storage-container-module';\nexport * from './history-storage-manager';\n","import { definePluginCreator } from '@flowgram.ai/core';\n\nimport { HistoryStoragePluginOptions } from './types';\nimport { HistoryStorageManager } from './history-storage-manager';\nimport { HistoryStorageContainerModule } from './history-storage-container-module';\n\nexport const createHistoryStoragePlugin = definePluginCreator<HistoryStoragePluginOptions>({\n onBind: ({ bind, rebind }) => {},\n onInit(ctx, opts): void {\n const historyStorageManager = ctx.get<HistoryStorageManager>(HistoryStorageManager);\n historyStorageManager.onInit(ctx, opts);\n },\n onDispose(ctx) {\n const historyStorageManager = ctx.get<HistoryStorageManager>(HistoryStorageManager);\n historyStorageManager.dispose();\n },\n containerModules: [HistoryStorageContainerModule],\n});\n","import { inject, injectable } from 'inversify';\nimport { DisposableCollection } from '@flowgram.ai/utils';\nimport {\n HistoryItem,\n HistoryManager,\n HistoryOperation,\n HistoryStackChangeType,\n HistoryService,\n HistoryStackAddOperationEvent,\n HistoryStackUpdateOperationEvent,\n} from '@flowgram.ai/history';\nimport { PluginContext } from '@flowgram.ai/core';\n\nimport { HistoryOperationRecord, HistoryRecord, HistoryStoragePluginOptions } from './types';\nimport { HistoryDatabase } from './history-database';\n\n/**\n * 历史存储管理\n */\n@injectable()\nexport class HistoryStorageManager {\n private _toDispose = new DisposableCollection();\n\n db: HistoryDatabase;\n\n @inject(HistoryManager)\n protected historyManager: HistoryManager;\n\n /**\n * 初始化\n * @param ctx\n */\n onInit(_ctx: PluginContext, opts: HistoryStoragePluginOptions) {\n this.db = new HistoryDatabase(opts?.databaseName);\n\n if (opts?.resourceStorageLimit) {\n this.db.resourceStorageLimit = opts.resourceStorageLimit;\n }\n\n this._toDispose.push(\n this.historyManager.historyStack.onChange(event => {\n if (event.type === HistoryStackChangeType.ADD) {\n const [history, operations] = this.historyItemToRecord(event.service, event.value);\n this.db.addHistoryRecord(history, operations).catch(console.error);\n }\n\n // operation merge的时候需要更新snapshot\n if (\n [HistoryStackChangeType.ADD_OPERATION, HistoryStackChangeType.UPDATE_OPERATION].includes(\n event.type,\n )\n ) {\n const {\n service,\n value: { historyItem },\n } = event as HistoryStackAddOperationEvent | HistoryStackUpdateOperationEvent;\n // 更新快照\n this.db\n .updateHistoryByUUID(historyItem.id, {\n resourceJSON: service.getSnapshot() || '',\n })\n .catch(console.error);\n }\n\n if (event.type === HistoryStackChangeType.ADD_OPERATION) {\n const operationRecord: HistoryOperationRecord = this.historyOperationToRecord(\n event.value.historyItem,\n event.value.operation,\n );\n this.db.addOperationRecord(operationRecord).catch(console.error);\n }\n if (event.type === HistoryStackChangeType.UPDATE_OPERATION) {\n const operationRecord: HistoryOperationRecord = this.historyOperationToRecord(\n event.value.historyItem,\n event.value.operation,\n );\n this.db.updateOperationRecord(operationRecord).catch(console.error);\n }\n }),\n );\n }\n\n /**\n * 内存历史转数据表记录\n * @param historyItem\n * @returns\n */\n historyItemToRecord(\n historyService: HistoryService,\n historyItem: HistoryItem,\n ): [HistoryRecord, HistoryOperationRecord[]] {\n const operations = historyItem.operations.map(op =>\n this.historyOperationToRecord(historyItem, op),\n );\n\n return [\n {\n uuid: historyItem.id,\n timestamp: historyItem.timestamp,\n type: historyItem.type,\n resourceURI: historyItem.uri?.toString() || '',\n resourceJSON: historyService.getSnapshot() || '',\n },\n operations,\n ];\n }\n\n /**\n * 内存操作转数据表操作\n * @param historyItem\n * @param op\n * @returns\n */\n historyOperationToRecord(historyItem: HistoryItem, op: HistoryOperation): HistoryOperationRecord {\n return {\n uuid: op.id,\n type: op.type,\n timestamp: op.timestamp,\n label: op.label || '',\n uri: op?.uri?.toString() || '',\n resourceURI: historyItem.uri?.toString() || '',\n description: op.description || '',\n value: JSON.stringify(op.value),\n historyId: historyItem.id,\n };\n }\n\n /**\n * 销毁\n */\n dispose() {\n this._toDispose.dispose();\n }\n}\n","import Dexie, { type Table } from 'dexie';\n\nimport { HistoryOperationRecord, HistoryRecord } from './types';\n\n/**\n * 历史数据库\n */\nexport class HistoryDatabase extends Dexie {\n readonly history: Table<HistoryRecord>;\n\n readonly operation: Table<HistoryOperationRecord>;\n\n resourceStorageLimit: number = 100;\n\n constructor(databaseName: string = 'ide-history-storage') {\n super(databaseName);\n this.version(1).stores({\n history: '++id, &uuid, resourceURI',\n operation: '++id, &uuid, historyId, uri, resourceURI',\n });\n }\n\n /**\n * 某个uri下所有的history记录\n * @param resourceURI 资源uri\n * @returns\n */\n allHistoryByResourceURI(resourceURI: string) {\n return this.history.where({ resourceURI }).toArray();\n }\n\n /**\n * 根据uuid获取历史\n * @param uuid\n * @returns\n */\n getHistoryByUUID(uuid: string) {\n return this.history.get({ uuid });\n }\n\n /**\n * 某个uri下所有的operation记录\n * @param resourceURI 资源uri\n * @returns\n */\n allOperationByResourceURI(resourceURI: string) {\n return this.operation.where({ resourceURI }).toArray();\n }\n\n /**\n * 添加历史记录\n * @param history 历史记录\n * @param operations 操作记录\n * @returns\n */\n addHistoryRecord(history: HistoryRecord, operations: HistoryOperationRecord[]) {\n return this.transaction('rw', this.history, this.operation, async () => {\n const count = await this.history.where({ resourceURI: history.resourceURI }).count();\n if (count >= this.resourceStorageLimit) {\n const limit = count - this.resourceStorageLimit;\n const items = await this.history\n .where({ resourceURI: history.resourceURI })\n .limit(limit)\n .toArray();\n const ids = items.map(i => i.id);\n const uuid = items.map(i => i.uuid);\n await Promise.all([\n this.history.bulkDelete(ids),\n ...uuid.map(async uuid => {\n await this.operation.where({ historyId: uuid }).delete();\n }),\n ]);\n }\n\n return Promise.all([this.history.add(history), this.operation.bulkAdd(operations)]);\n });\n }\n\n /**\n * 更新历史记录\n * @param historyRecord\n * @returns\n */\n async updateHistoryByUUID(uuid: string, historyRecord: Partial<HistoryRecord>) {\n const history = await this.getHistoryByUUID(uuid);\n if (!history) {\n console.warn('no history record found');\n return;\n }\n return this.history.update(history.id, historyRecord);\n }\n\n /**\n * 添加操作记录\n * @param record 操作记录\n * @returns\n */\n addOperationRecord(record: HistoryOperationRecord) {\n return this.operation.add(record);\n }\n\n /**\n * 更新操作记录\n * @param record 操作记录\n * @returns\n */\n async updateOperationRecord(record: HistoryOperationRecord) {\n const op = await this.operation.where({ uuid: record.uuid }).first();\n if (!op) {\n console.warn('no operation record found');\n return;\n }\n return this.operation.put({\n id: op.id,\n ...record,\n });\n }\n\n /**\n * 重置数据库\n * @returns\n */\n reset() {\n return this.transaction('rw', this.history, this.operation, async () => {\n await Promise.all(this.tables.map(table => table.clear()));\n });\n }\n\n /**\n * 清空某个资源下所有的数据\n * @param resourceURI\n * @returns\n */\n resetByResourceURI(resourceURI: string) {\n return this.transaction('rw', this.history, this.operation, async () => {\n await Promise.all(this.tables.map(table => table.where({ resourceURI }).delete()));\n });\n }\n}\n","import { ContainerModule } from 'inversify';\n\nimport { HistoryStorageManager } from './history-storage-manager';\n\nexport const HistoryStorageContainerModule = new ContainerModule(bind => {\n bind(HistoryStorageManager).toSelf().inSingletonScope();\n});\n","import { groupBy } from 'lodash';\nimport { useLiveQuery } from 'dexie-react-hooks';\nimport { HistoryItem, HistoryOperation, HistoryStack } from '@flowgram.ai/history';\n\nimport { HistoryStorageManager } from './history-storage-manager';\nexport function useStorageHistoryItems(\n historyStorageManager: HistoryStorageManager,\n resourceURI: string\n): {\n items: HistoryItem[];\n} {\n const items: HistoryItem[] =\n useLiveQuery(async () => {\n const [historyItems, operations] = await Promise.all([\n historyStorageManager.db.allHistoryByResourceURI(resourceURI),\n historyStorageManager.db.allOperationByResourceURI(resourceURI),\n ]);\n\n const grouped = groupBy<HistoryOperation>(\n operations.map((o) => ({\n id: o.uuid,\n timestamp: o.timestamp,\n type: o.type,\n label: o.label,\n description: o.description,\n value: o.value ? JSON.parse(o.value) : undefined,\n uri: o.uri,\n historyId: o.historyId,\n })),\n 'historyId'\n );\n return historyItems\n .sort((a, b) => (b.id as number) - (a.id as number))\n .map(\n (historyItem) =>\n ({\n id: historyItem.uuid,\n type: historyItem.type,\n timestamp: historyItem.timestamp,\n operations: grouped[historyItem.uuid] || [],\n time: HistoryStack.dateFormat(historyItem.timestamp),\n uri: historyItem.resourceURI,\n } as HistoryItem)\n );\n }, [resourceURI]) || [];\n\n return {\n items,\n };\n}\n"],"mappings":"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","names":["Dexie","uuid","import_inversify","import_history"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/create-history-storage-plugin.ts","../src/history-storage-manager.ts","../src/history-database.ts","../src/history-storage-container-module.ts","../src/use-storage-hisotry-items.tsx"],"sourcesContent":["export * from './create-history-storage-plugin';\nexport * from './use-storage-hisotry-items';\nexport * from './types';\nexport * from './history-database';\nexport * from './history-storage-container-module';\nexport * from './history-storage-manager';\n","import { definePluginCreator } from '@flowgram.ai/core';\n\nimport { HistoryStoragePluginOptions } from './types';\nimport { HistoryStorageManager } from './history-storage-manager';\nimport { HistoryStorageContainerModule } from './history-storage-container-module';\n\nexport const createHistoryStoragePlugin = definePluginCreator<HistoryStoragePluginOptions>({\n onBind: ({ bind, rebind }) => {},\n onInit(ctx, opts): void {\n const historyStorageManager = ctx.get<HistoryStorageManager>(HistoryStorageManager);\n historyStorageManager.onInit(ctx, opts);\n },\n onDispose(ctx) {\n const historyStorageManager = ctx.get<HistoryStorageManager>(HistoryStorageManager);\n historyStorageManager.dispose();\n },\n containerModules: [HistoryStorageContainerModule],\n});\n","import { inject, injectable } from 'inversify';\nimport { DisposableCollection } from '@flowgram.ai/utils';\nimport {\n HistoryItem,\n HistoryManager,\n HistoryOperation,\n HistoryStackChangeType,\n HistoryService,\n HistoryStackAddOperationEvent,\n HistoryStackUpdateOperationEvent,\n} from '@flowgram.ai/history';\nimport { PluginContext } from '@flowgram.ai/core';\n\nimport { HistoryOperationRecord, HistoryRecord, HistoryStoragePluginOptions } from './types';\nimport { HistoryDatabase } from './history-database';\n\n/**\n * 历史存储管理\n */\n@injectable()\nexport class HistoryStorageManager {\n private _toDispose = new DisposableCollection();\n\n db: HistoryDatabase;\n\n @inject(HistoryManager)\n protected historyManager: HistoryManager;\n\n /**\n * 初始化\n * @param ctx\n */\n onInit(_ctx: PluginContext, opts: HistoryStoragePluginOptions) {\n this.db = new HistoryDatabase(opts?.databaseName);\n\n if (opts?.resourceStorageLimit) {\n this.db.resourceStorageLimit = opts.resourceStorageLimit;\n }\n\n this._toDispose.push(\n this.historyManager.historyStack.onChange(event => {\n if (event.type === HistoryStackChangeType.ADD) {\n const [history, operations] = this.historyItemToRecord(event.service, event.value);\n this.db.addHistoryRecord(history, operations).catch(console.error);\n }\n\n // operation merge的时候需要更新snapshot\n if (\n [HistoryStackChangeType.ADD_OPERATION, HistoryStackChangeType.UPDATE_OPERATION].includes(\n event.type,\n )\n ) {\n const {\n service,\n value: { historyItem },\n } = event as HistoryStackAddOperationEvent | HistoryStackUpdateOperationEvent;\n // 更新快照\n this.db\n .updateHistoryByUUID(historyItem.id, {\n resourceJSON: service.getSnapshot() || '',\n })\n .catch(console.error);\n }\n\n if (event.type === HistoryStackChangeType.ADD_OPERATION) {\n const operationRecord: HistoryOperationRecord = this.historyOperationToRecord(\n event.value.historyItem,\n event.value.operation,\n );\n this.db.addOperationRecord(operationRecord).catch(console.error);\n }\n if (event.type === HistoryStackChangeType.UPDATE_OPERATION) {\n const operationRecord: HistoryOperationRecord = this.historyOperationToRecord(\n event.value.historyItem,\n event.value.operation,\n );\n this.db.updateOperationRecord(operationRecord).catch(console.error);\n }\n }),\n );\n }\n\n /**\n * 内存历史转数据表记录\n * @param historyItem\n * @returns\n */\n historyItemToRecord(\n historyService: HistoryService,\n historyItem: HistoryItem,\n ): [HistoryRecord, HistoryOperationRecord[]] {\n const operations = historyItem.operations.map(op =>\n this.historyOperationToRecord(historyItem, op),\n );\n\n return [\n {\n uuid: historyItem.id,\n timestamp: historyItem.timestamp,\n type: historyItem.type,\n resourceURI: historyItem.uri?.toString() || '',\n resourceJSON: historyService.getSnapshot() || '',\n },\n operations,\n ];\n }\n\n /**\n * 内存操作转数据表操作\n * @param historyItem\n * @param op\n * @returns\n */\n historyOperationToRecord(historyItem: HistoryItem, op: HistoryOperation): HistoryOperationRecord {\n return {\n uuid: op.id,\n type: op.type,\n timestamp: op.timestamp,\n label: op.label || '',\n uri: op?.uri?.toString() || '',\n resourceURI: historyItem.uri?.toString() || '',\n description: op.description || '',\n value: JSON.stringify(op.value),\n historyId: historyItem.id,\n };\n }\n\n /**\n * 销毁\n */\n dispose() {\n this._toDispose.dispose();\n }\n}\n","import Dexie, { type Table } from 'dexie';\n\nimport { HistoryOperationRecord, HistoryRecord } from './types';\n\n/**\n * 历史数据库\n */\nexport class HistoryDatabase extends Dexie {\n readonly history: Table<HistoryRecord>;\n\n readonly operation: Table<HistoryOperationRecord>;\n\n resourceStorageLimit: number = 100;\n\n constructor(databaseName: string = 'ide-history-storage') {\n super(databaseName);\n this.version(1).stores({\n history: '++id, &uuid, resourceURI',\n operation: '++id, &uuid, historyId, uri, resourceURI',\n });\n }\n\n /**\n * 某个uri下所有的history记录\n * @param resourceURI 资源uri\n * @returns\n */\n allHistoryByResourceURI(resourceURI: string) {\n return this.history.where({ resourceURI }).toArray();\n }\n\n /**\n * 根据uuid获取历史\n * @param uuid\n * @returns\n */\n getHistoryByUUID(uuid: string) {\n return this.history.get({ uuid });\n }\n\n /**\n * 某个uri下所有的operation记录\n * @param resourceURI 资源uri\n * @returns\n */\n allOperationByResourceURI(resourceURI: string) {\n return this.operation.where({ resourceURI }).toArray();\n }\n\n /**\n * 添加历史记录\n * @param history 历史记录\n * @param operations 操作记录\n * @returns\n */\n addHistoryRecord(history: HistoryRecord, operations: HistoryOperationRecord[]) {\n return this.transaction('rw', this.history, this.operation, async () => {\n const count = await this.history.where({ resourceURI: history.resourceURI }).count();\n if (count >= this.resourceStorageLimit) {\n const limit = count - this.resourceStorageLimit;\n const items = await this.history\n .where({ resourceURI: history.resourceURI })\n .limit(limit)\n .toArray();\n const ids = items.map(i => i.id);\n const uuid = items.map(i => i.uuid);\n await Promise.all([\n this.history.bulkDelete(ids),\n ...uuid.map(async uuid => {\n await this.operation.where({ historyId: uuid }).delete();\n }),\n ]);\n }\n\n return Promise.all([this.history.add(history), this.operation.bulkAdd(operations)]);\n });\n }\n\n /**\n * 更新历史记录\n * @param historyRecord\n * @returns\n */\n async updateHistoryByUUID(uuid: string, historyRecord: Partial<HistoryRecord>) {\n const history = await this.getHistoryByUUID(uuid);\n if (!history) {\n console.warn('no history record found');\n return;\n }\n return this.history.update(history.id, historyRecord);\n }\n\n /**\n * 添加操作记录\n * @param record 操作记录\n * @returns\n */\n addOperationRecord(record: HistoryOperationRecord) {\n return this.operation.add(record);\n }\n\n /**\n * 更新操作记录\n * @param record 操作记录\n * @returns\n */\n async updateOperationRecord(record: HistoryOperationRecord) {\n const op = await this.operation.where({ uuid: record.uuid }).first();\n if (!op) {\n console.warn('no operation record found');\n return;\n }\n return this.operation.put({\n id: op.id,\n ...record,\n });\n }\n\n /**\n * 重置数据库\n * @returns\n */\n reset() {\n return this.transaction('rw', this.history, this.operation, async () => {\n await Promise.all(this.tables.map(table => table.clear()));\n });\n }\n\n /**\n * 清空某个资源下所有的数据\n * @param resourceURI\n * @returns\n */\n resetByResourceURI(resourceURI: string) {\n return this.transaction('rw', this.history, this.operation, async () => {\n await Promise.all(this.tables.map(table => table.where({ resourceURI }).delete()));\n });\n }\n}\n","import { ContainerModule } from 'inversify';\n\nimport { HistoryStorageManager } from './history-storage-manager';\n\nexport const HistoryStorageContainerModule = new ContainerModule(bind => {\n bind(HistoryStorageManager).toSelf().inSingletonScope();\n});\n","import { groupBy } from 'lodash';\nimport { useLiveQuery } from 'dexie-react-hooks';\nimport { HistoryItem, HistoryOperation, HistoryStack } from '@flowgram.ai/history';\n\nimport { HistoryStorageManager } from './history-storage-manager';\nexport function useStorageHistoryItems(\n historyStorageManager: HistoryStorageManager,\n resourceURI: string\n): {\n items: HistoryItem[];\n} {\n const items: HistoryItem[] =\n useLiveQuery(async () => {\n const [historyItems, operations] = await Promise.all([\n historyStorageManager.db.allHistoryByResourceURI(resourceURI),\n historyStorageManager.db.allOperationByResourceURI(resourceURI),\n ]);\n\n const grouped = groupBy<HistoryOperation>(\n operations.map((o) => ({\n id: o.uuid,\n timestamp: o.timestamp,\n type: o.type,\n label: o.label,\n description: o.description,\n value: o.value ? JSON.parse(o.value) : undefined,\n uri: o.uri,\n historyId: o.historyId,\n })),\n 'historyId'\n );\n return historyItems\n .sort((a, b) => (b.id as number) - (a.id as number))\n .map(\n (historyItem) =>\n ({\n id: historyItem.uuid,\n type: historyItem.type,\n timestamp: historyItem.timestamp,\n operations: grouped[historyItem.uuid] || [],\n time: HistoryStack.dateFormat(historyItem.timestamp),\n uri: historyItem.resourceURI,\n } as HistoryItem)\n );\n }, [resourceURI]) || [];\n\n return {\n items,\n };\n}\n"],"mappings":"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","names":["Dexie","uuid","import_inversify","import_history"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowgram.ai/history-storage",
3
- "version": "0.1.0-alpha.6",
3
+ "version": "0.1.0-alpha.8",
4
4
  "homepage": "https://flowgram.ai/",
5
5
  "repository": "https://github.com/bytedance/flowgram.ai",
6
6
  "license": "MIT",
@@ -22,9 +22,9 @@
22
22
  "reflect-metadata": "~0.2.2",
23
23
  "lodash": "^4.17.21",
24
24
  "nanoid": "^4.0.2",
25
- "@flowgram.ai/core": "0.1.0-alpha.6",
26
- "@flowgram.ai/history": "0.1.0-alpha.6",
27
- "@flowgram.ai/utils": "0.1.0-alpha.6"
25
+ "@flowgram.ai/core": "0.1.0-alpha.8",
26
+ "@flowgram.ai/history": "0.1.0-alpha.8",
27
+ "@flowgram.ai/utils": "0.1.0-alpha.8"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@types/lodash": "^4.14.137",
@@ -35,8 +35,8 @@
35
35
  "tsup": "^8.0.1",
36
36
  "typescript": "^5.0.4",
37
37
  "vitest": "^0.34.6",
38
- "@flowgram.ai/ts-config": "0.1.0-alpha.6",
39
- "@flowgram.ai/eslint-config": "0.1.0-alpha.6"
38
+ "@flowgram.ai/eslint-config": "0.1.0-alpha.8",
39
+ "@flowgram.ai/ts-config": "0.1.0-alpha.8"
40
40
  },
41
41
  "publishConfig": {
42
42
  "access": "public",