@platforma-sdk/model 1.54.13 → 1.55.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/bconfig/normalization.cjs +8 -1
- package/dist/bconfig/normalization.cjs.map +1 -1
- package/dist/bconfig/normalization.d.ts.map +1 -1
- package/dist/bconfig/normalization.js +8 -1
- package/dist/bconfig/normalization.js.map +1 -1
- package/dist/block_api_v3.d.ts +2 -2
- package/dist/block_api_v3.d.ts.map +1 -1
- package/dist/block_migrations.cjs +246 -214
- package/dist/block_migrations.cjs.map +1 -1
- package/dist/block_migrations.d.ts +180 -158
- package/dist/block_migrations.d.ts.map +1 -1
- package/dist/block_migrations.js +247 -214
- package/dist/block_migrations.js.map +1 -1
- package/dist/block_model.cjs +85 -35
- package/dist/block_model.cjs.map +1 -1
- package/dist/block_model.d.ts +66 -38
- package/dist/block_model.d.ts.map +1 -1
- package/dist/block_model.js +86 -36
- package/dist/block_model.js.map +1 -1
- package/dist/{builder.cjs → block_model_legacy.cjs} +2 -2
- package/dist/block_model_legacy.cjs.map +1 -0
- package/dist/{builder.d.ts → block_model_legacy.d.ts} +1 -1
- package/dist/block_model_legacy.d.ts.map +1 -0
- package/dist/{builder.js → block_model_legacy.js} +2 -2
- package/dist/block_model_legacy.js.map +1 -0
- package/dist/block_state_patch.d.ts +11 -1
- package/dist/block_state_patch.d.ts.map +1 -1
- package/dist/block_storage.cjs +126 -109
- package/dist/block_storage.cjs.map +1 -1
- package/dist/block_storage.d.ts +109 -112
- package/dist/block_storage.d.ts.map +1 -1
- package/dist/block_storage.js +126 -101
- package/dist/block_storage.js.map +1 -1
- package/dist/block_storage_callbacks.cjs +227 -0
- package/dist/block_storage_callbacks.cjs.map +1 -0
- package/dist/block_storage_callbacks.d.ts +113 -0
- package/dist/block_storage_callbacks.d.ts.map +1 -0
- package/dist/block_storage_callbacks.js +218 -0
- package/dist/block_storage_callbacks.js.map +1 -0
- package/dist/block_storage_facade.cjs +104 -0
- package/dist/block_storage_facade.cjs.map +1 -0
- package/dist/block_storage_facade.d.ts +168 -0
- package/dist/block_storage_facade.d.ts.map +1 -0
- package/dist/block_storage_facade.js +99 -0
- package/dist/block_storage_facade.js.map +1 -0
- package/dist/index.cjs +13 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +8 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/package.json.cjs +1 -1
- package/dist/package.json.js +1 -1
- package/dist/platforma.d.ts +11 -4
- package/dist/platforma.d.ts.map +1 -1
- package/dist/plugin_model.cjs +171 -0
- package/dist/plugin_model.cjs.map +1 -0
- package/dist/plugin_model.d.ts +162 -0
- package/dist/plugin_model.d.ts.map +1 -0
- package/dist/plugin_model.js +169 -0
- package/dist/plugin_model.js.map +1 -0
- package/dist/render/api.cjs +20 -21
- package/dist/render/api.cjs.map +1 -1
- package/dist/render/api.d.ts +8 -8
- package/dist/render/api.d.ts.map +1 -1
- package/dist/render/api.js +20 -21
- package/dist/render/api.js.map +1 -1
- package/dist/render/internal.cjs.map +1 -1
- package/dist/render/internal.d.ts +1 -1
- package/dist/render/internal.d.ts.map +1 -1
- package/dist/render/internal.js.map +1 -1
- package/dist/version.cjs +4 -0
- package/dist/version.cjs.map +1 -1
- package/dist/version.d.ts +4 -0
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +4 -1
- package/dist/version.js.map +1 -1
- package/package.json +5 -5
- package/src/bconfig/normalization.ts +8 -1
- package/src/block_api_v3.ts +2 -2
- package/src/block_migrations.test.ts +141 -171
- package/src/block_migrations.ts +300 -285
- package/src/block_model.ts +205 -95
- package/src/{builder.ts → block_model_legacy.ts} +1 -1
- package/src/block_state_patch.ts +13 -1
- package/src/block_storage.test.ts +283 -95
- package/src/block_storage.ts +199 -188
- package/src/block_storage_callbacks.ts +326 -0
- package/src/block_storage_facade.ts +199 -0
- package/src/index.ts +7 -3
- package/src/platforma.ts +26 -7
- package/src/plugin_model.test.ts +168 -0
- package/src/plugin_model.ts +242 -0
- package/src/render/api.ts +26 -24
- package/src/render/internal.ts +1 -1
- package/src/typing.test.ts +1 -1
- package/src/version.ts +8 -0
- package/dist/block_storage_vm.cjs +0 -262
- package/dist/block_storage_vm.cjs.map +0 -1
- package/dist/block_storage_vm.d.ts +0 -59
- package/dist/block_storage_vm.d.ts.map +0 -1
- package/dist/block_storage_vm.js +0 -258
- package/dist/block_storage_vm.js.map +0 -1
- package/dist/branding.d.ts +0 -7
- package/dist/branding.d.ts.map +0 -1
- package/dist/builder.cjs.map +0 -1
- package/dist/builder.d.ts.map +0 -1
- package/dist/builder.js.map +0 -1
- package/dist/sdk_info.cjs +0 -10
- package/dist/sdk_info.cjs.map +0 -1
- package/dist/sdk_info.d.ts +0 -5
- package/dist/sdk_info.d.ts.map +0 -1
- package/dist/sdk_info.js +0 -8
- package/dist/sdk_info.js.map +0 -1
- package/dist/unionize.d.ts +0 -12
- package/dist/unionize.d.ts.map +0 -1
- package/src/block_storage_vm.ts +0 -346
- package/src/branding.ts +0 -4
- package/src/sdk_info.ts +0 -9
- package/src/unionize.ts +0 -12
|
@@ -4,20 +4,15 @@ import {
|
|
|
4
4
|
BLOCK_STORAGE_SCHEMA_VERSION,
|
|
5
5
|
DATA_MODEL_DEFAULT_VERSION,
|
|
6
6
|
createBlockStorage,
|
|
7
|
-
defaultBlockStorageHandlers,
|
|
8
|
-
getFromStorage,
|
|
9
7
|
getPluginData,
|
|
10
|
-
getPluginNames,
|
|
11
8
|
getStorageData,
|
|
12
|
-
getStorageDataVersion,
|
|
13
9
|
isBlockStorage,
|
|
14
|
-
|
|
10
|
+
migrateBlockStorage,
|
|
15
11
|
normalizeBlockStorage,
|
|
16
|
-
removePluginData,
|
|
17
|
-
setPluginData,
|
|
18
12
|
updateStorageData,
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
type MutateStoragePayload,
|
|
14
|
+
type PluginName,
|
|
15
|
+
type PluginRegistry,
|
|
21
16
|
} from "./block_storage";
|
|
22
17
|
|
|
23
18
|
describe("BlockStorage", () => {
|
|
@@ -39,7 +34,11 @@ describe("BlockStorage", () => {
|
|
|
39
34
|
});
|
|
40
35
|
|
|
41
36
|
it("should return true for BlockStorage with plugin data", () => {
|
|
42
|
-
const storage =
|
|
37
|
+
const storage = updateStorageData(createBlockStorage({ foo: "bar" }), {
|
|
38
|
+
operation: "update-plugin-data",
|
|
39
|
+
pluginId: "testPlugin",
|
|
40
|
+
value: { data: 123 },
|
|
41
|
+
});
|
|
43
42
|
expect(isBlockStorage(storage)).toBe(true);
|
|
44
43
|
});
|
|
45
44
|
|
|
@@ -90,13 +89,46 @@ describe("BlockStorage", () => {
|
|
|
90
89
|
expect(storage.__dataVersion).toBe("v5");
|
|
91
90
|
expect(storage.__data).toEqual({ foo: "bar" });
|
|
92
91
|
});
|
|
92
|
+
|
|
93
|
+
it("should create storage with empty plugin fields by default", () => {
|
|
94
|
+
const storage = createBlockStorage({});
|
|
95
|
+
expect(storage.__pluginRegistry).toEqual({});
|
|
96
|
+
expect(storage.__plugins).toEqual({});
|
|
97
|
+
});
|
|
93
98
|
});
|
|
94
99
|
|
|
95
100
|
describe("normalizeBlockStorage", () => {
|
|
96
|
-
it("should return BlockStorage as-is", () => {
|
|
101
|
+
it("should return BlockStorage as-is with plugin defaults added", () => {
|
|
97
102
|
const storage = createBlockStorage({ data: "test" }, "v2");
|
|
98
103
|
const normalized = normalizeBlockStorage(storage);
|
|
99
104
|
expect(normalized).toEqual(storage);
|
|
105
|
+
expect(normalized.__pluginRegistry).toEqual({});
|
|
106
|
+
expect(normalized.__plugins).toEqual({});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it("should add plugin defaults to BlockStorage without them", () => {
|
|
110
|
+
// Simulate storage from earlier version without plugin fields
|
|
111
|
+
const oldStorage = {
|
|
112
|
+
[BLOCK_STORAGE_KEY]: "v1" as const,
|
|
113
|
+
__dataVersion: "v2",
|
|
114
|
+
__data: { data: "test" },
|
|
115
|
+
};
|
|
116
|
+
const normalized = normalizeBlockStorage(oldStorage);
|
|
117
|
+
expect(normalized.__pluginRegistry).toEqual({});
|
|
118
|
+
expect(normalized.__plugins).toEqual({});
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("should preserve existing plugin data when normalizing", () => {
|
|
122
|
+
const storageWithPlugins = {
|
|
123
|
+
[BLOCK_STORAGE_KEY]: "v1" as const,
|
|
124
|
+
__dataVersion: "v2",
|
|
125
|
+
__data: { data: "test" },
|
|
126
|
+
__pluginRegistry: { p1: "plugin1" as PluginName },
|
|
127
|
+
__plugins: { p1: { __dataVersion: "v1", __data: { foo: "bar" } } },
|
|
128
|
+
};
|
|
129
|
+
const normalized = normalizeBlockStorage(storageWithPlugins);
|
|
130
|
+
expect(normalized.__pluginRegistry).toEqual({ p1: "plugin1" as PluginName });
|
|
131
|
+
expect(normalized.__plugins).toEqual({ p1: { __dataVersion: "v1", __data: { foo: "bar" } } });
|
|
100
132
|
});
|
|
101
133
|
|
|
102
134
|
it("should wrap legacy data in BlockStorage structure", () => {
|
|
@@ -105,6 +137,8 @@ describe("BlockStorage", () => {
|
|
|
105
137
|
expect(normalized[BLOCK_STORAGE_KEY]).toBe(BLOCK_STORAGE_SCHEMA_VERSION);
|
|
106
138
|
expect(normalized.__dataVersion).toBe(DATA_MODEL_DEFAULT_VERSION);
|
|
107
139
|
expect(normalized.__data).toEqual(legacyData);
|
|
140
|
+
expect(normalized.__pluginRegistry).toEqual({});
|
|
141
|
+
expect(normalized.__plugins).toEqual({});
|
|
108
142
|
});
|
|
109
143
|
|
|
110
144
|
it("should wrap primitive legacy data", () => {
|
|
@@ -129,13 +163,9 @@ describe("BlockStorage", () => {
|
|
|
129
163
|
expect(getStorageData(storage)).toEqual({ count: 42 });
|
|
130
164
|
});
|
|
131
165
|
|
|
132
|
-
it("getStorageDataVersion should return the version", () => {
|
|
133
|
-
expect(getStorageDataVersion(storage)).toBe("v3");
|
|
134
|
-
});
|
|
135
|
-
|
|
136
166
|
it("updateStorageData should return new storage with updated data", () => {
|
|
137
167
|
const newStorage = updateStorageData(storage, {
|
|
138
|
-
operation: "update-data",
|
|
168
|
+
operation: "update-block-data",
|
|
139
169
|
value: { count: 100 },
|
|
140
170
|
});
|
|
141
171
|
expect(newStorage.__data).toEqual({ count: 100 });
|
|
@@ -144,123 +174,281 @@ describe("BlockStorage", () => {
|
|
|
144
174
|
// Original should be unchanged
|
|
145
175
|
expect(storage.__data).toEqual({ count: 42 });
|
|
146
176
|
});
|
|
147
|
-
|
|
148
|
-
it("updateStorageDataVersion should return new storage with updated version", () => {
|
|
149
|
-
const newStorage = updateStorageDataVersion(storage, "v5");
|
|
150
|
-
expect(newStorage.__dataVersion).toBe("v5");
|
|
151
|
-
expect(newStorage.__data).toEqual({ count: 42 });
|
|
152
|
-
expect(newStorage[BLOCK_STORAGE_KEY]).toBe(BLOCK_STORAGE_SCHEMA_VERSION);
|
|
153
|
-
// Original should be unchanged
|
|
154
|
-
expect(storage.__dataVersion).toBe("v3");
|
|
155
|
-
});
|
|
156
177
|
});
|
|
157
178
|
|
|
158
|
-
describe("Plugin data functions", () => {
|
|
179
|
+
describe("Plugin data functions (UI)", () => {
|
|
159
180
|
const baseStorage = createBlockStorage({});
|
|
160
181
|
|
|
161
|
-
it("
|
|
162
|
-
const storage =
|
|
163
|
-
|
|
182
|
+
it("update-plugin operation should add plugin data with default version", () => {
|
|
183
|
+
const storage = updateStorageData(baseStorage, {
|
|
184
|
+
operation: "update-plugin-data",
|
|
185
|
+
pluginId: "table1",
|
|
186
|
+
value: { columns: ["a", "b"] },
|
|
187
|
+
});
|
|
188
|
+
expect(storage.__plugins).toEqual({
|
|
189
|
+
table1: {
|
|
190
|
+
__dataVersion: DATA_MODEL_DEFAULT_VERSION,
|
|
191
|
+
__data: { columns: ["a", "b"] },
|
|
192
|
+
},
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it("update-plugin operation should preserve existing version when updating", () => {
|
|
197
|
+
let storage = {
|
|
198
|
+
...baseStorage,
|
|
199
|
+
__plugins: { table1: { __dataVersion: "v5", __data: { old: true } } },
|
|
200
|
+
};
|
|
201
|
+
storage = updateStorageData(storage, {
|
|
202
|
+
operation: "update-plugin-data",
|
|
203
|
+
pluginId: "table1",
|
|
204
|
+
value: { new: true },
|
|
205
|
+
});
|
|
206
|
+
expect(storage.__plugins?.table1).toEqual({
|
|
207
|
+
__dataVersion: "v5",
|
|
208
|
+
__data: { new: true },
|
|
209
|
+
});
|
|
164
210
|
});
|
|
165
211
|
|
|
166
212
|
it("getPluginData should retrieve plugin data", () => {
|
|
167
|
-
const storage =
|
|
168
|
-
|
|
213
|
+
const storage = updateStorageData(baseStorage, {
|
|
214
|
+
operation: "update-plugin-data",
|
|
215
|
+
pluginId: "chart1",
|
|
216
|
+
value: { type: "bar" },
|
|
217
|
+
});
|
|
218
|
+
expect(getPluginData(storage, "chart1")).toEqual({ type: "bar" });
|
|
169
219
|
});
|
|
170
220
|
|
|
171
221
|
it("getPluginData should return undefined for missing plugin", () => {
|
|
172
222
|
expect(getPluginData(baseStorage, "nonexistent")).toBeUndefined();
|
|
173
223
|
});
|
|
174
224
|
|
|
175
|
-
it("
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
225
|
+
it("should not modify original storage (immutability)", () => {
|
|
226
|
+
const storage = updateStorageData(baseStorage, {
|
|
227
|
+
operation: "update-plugin-data",
|
|
228
|
+
pluginId: "table1",
|
|
229
|
+
value: { data: "test" },
|
|
230
|
+
});
|
|
231
|
+
expect(baseStorage.__plugins).toEqual({});
|
|
232
|
+
expect(storage.__plugins?.table1).toBeDefined();
|
|
181
233
|
});
|
|
234
|
+
});
|
|
182
235
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
storage =
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
236
|
+
describe("updateStorageData operations", () => {
|
|
237
|
+
it("update-data operation should update block data", () => {
|
|
238
|
+
const storage = createBlockStorage({ count: 1 });
|
|
239
|
+
const updated = updateStorageData(storage, {
|
|
240
|
+
operation: "update-block-data",
|
|
241
|
+
value: { count: 2 },
|
|
242
|
+
});
|
|
243
|
+
expect(updated.__data).toEqual({ count: 2 });
|
|
190
244
|
});
|
|
191
245
|
|
|
192
|
-
it("
|
|
193
|
-
|
|
246
|
+
it("update-plugin operation should update plugin data", () => {
|
|
247
|
+
const storage = createBlockStorage({});
|
|
248
|
+
const updated = updateStorageData(storage, {
|
|
249
|
+
operation: "update-plugin-data",
|
|
250
|
+
pluginId: "plugin1",
|
|
251
|
+
value: { foo: "bar" },
|
|
252
|
+
});
|
|
253
|
+
expect(updated.__plugins?.plugin1).toEqual({
|
|
254
|
+
__dataVersion: DATA_MODEL_DEFAULT_VERSION,
|
|
255
|
+
__data: { foo: "bar" },
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it("should throw on unknown operation", () => {
|
|
260
|
+
const storage = createBlockStorage({});
|
|
261
|
+
expect(() => {
|
|
262
|
+
updateStorageData(storage, { operation: "invalid" } as MutateStoragePayload);
|
|
263
|
+
}).toThrow("Unknown storage operation: invalid");
|
|
194
264
|
});
|
|
195
265
|
});
|
|
196
266
|
|
|
197
|
-
describe("
|
|
198
|
-
const
|
|
267
|
+
describe("Atomic migration (migrateBlockStorage)", () => {
|
|
268
|
+
const createTestStorage = () => {
|
|
269
|
+
const storage = createBlockStorage({ count: 1 }, "v1");
|
|
270
|
+
return {
|
|
271
|
+
...storage,
|
|
272
|
+
__pluginRegistry: { plugin1: "typeA" as PluginName },
|
|
273
|
+
__plugins: { plugin1: { __dataVersion: "v1", __data: { value: "old" } } },
|
|
274
|
+
};
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
it("should migrate block data and plugins atomically on success", () => {
|
|
278
|
+
const storage = createTestStorage();
|
|
279
|
+
const newRegistry: PluginRegistry = { plugin1: "typeA" as PluginName };
|
|
280
|
+
|
|
281
|
+
const result = migrateBlockStorage(storage, {
|
|
282
|
+
migrateBlockData: (versioned) => {
|
|
283
|
+
const d = versioned.data as { count: number };
|
|
284
|
+
return { data: { count: d.count + 1 }, version: "v2" };
|
|
285
|
+
},
|
|
286
|
+
migratePluginData: (_pluginId, _versioned) => ({
|
|
287
|
+
version: "v2",
|
|
288
|
+
data: { value: "migrated" },
|
|
289
|
+
}),
|
|
290
|
+
newPluginRegistry: newRegistry,
|
|
291
|
+
createPluginData: (_pluginId) => ({ version: "v1", data: {} }),
|
|
292
|
+
});
|
|
199
293
|
|
|
200
|
-
|
|
201
|
-
|
|
294
|
+
expect(result.success).toBe(true);
|
|
295
|
+
if (result.success) {
|
|
296
|
+
expect(result.storage.__data).toEqual({ count: 2 });
|
|
297
|
+
expect(result.storage.__dataVersion).toBe("v2");
|
|
298
|
+
expect(result.storage.__plugins?.plugin1).toEqual({
|
|
299
|
+
__dataVersion: "v2",
|
|
300
|
+
__data: { value: "migrated" },
|
|
301
|
+
});
|
|
302
|
+
}
|
|
202
303
|
});
|
|
203
304
|
|
|
204
|
-
it("
|
|
205
|
-
|
|
206
|
-
|
|
305
|
+
it("should return failure and preserve original storage when block migration throws", () => {
|
|
306
|
+
const storage = createTestStorage();
|
|
307
|
+
const originalData = storage.__data;
|
|
308
|
+
|
|
309
|
+
const result = migrateBlockStorage(storage, {
|
|
310
|
+
migrateBlockData: () => {
|
|
311
|
+
throw new Error("Block migration failed");
|
|
312
|
+
},
|
|
313
|
+
migratePluginData: (_pluginId, _versioned) => ({
|
|
314
|
+
version: "v1",
|
|
315
|
+
data: {},
|
|
316
|
+
}),
|
|
317
|
+
newPluginRegistry: {},
|
|
318
|
+
createPluginData: (_pluginId) => ({ version: "v1", data: {} }),
|
|
319
|
+
});
|
|
207
320
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
321
|
+
expect(result.success).toBe(false);
|
|
322
|
+
if (!result.success) {
|
|
323
|
+
expect(result.error).toBe("Block migration failed");
|
|
324
|
+
expect(result.failedAt).toBe("block");
|
|
325
|
+
}
|
|
326
|
+
// Original storage untouched
|
|
327
|
+
expect(storage.__data).toEqual(originalData);
|
|
212
328
|
});
|
|
213
|
-
});
|
|
214
329
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
330
|
+
it("should return failure and preserve original storage when plugin migration throws", () => {
|
|
331
|
+
const storage = createTestStorage();
|
|
332
|
+
const newRegistry: PluginRegistry = { plugin1: "typeA" as PluginName };
|
|
333
|
+
|
|
334
|
+
const result = migrateBlockStorage(storage, {
|
|
335
|
+
migrateBlockData: (versioned) => ({
|
|
336
|
+
data: versioned.data as { count: number },
|
|
337
|
+
version: "v2",
|
|
338
|
+
}),
|
|
339
|
+
migratePluginData: (pluginId) => {
|
|
340
|
+
throw new Error(`Plugin ${pluginId} migration failed`);
|
|
341
|
+
},
|
|
342
|
+
newPluginRegistry: newRegistry,
|
|
343
|
+
createPluginData: (_pluginId) => ({ version: "v1", data: {} }),
|
|
222
344
|
});
|
|
223
345
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
expect(
|
|
227
|
-
|
|
346
|
+
expect(result.success).toBe(false);
|
|
347
|
+
if (!result.success) {
|
|
348
|
+
expect(result.error).toBe("Plugin plugin1 migration failed");
|
|
349
|
+
expect(result.failedAt).toBe("plugin1");
|
|
350
|
+
}
|
|
351
|
+
});
|
|
228
352
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
353
|
+
it("should reset plugin data when plugin type changes", () => {
|
|
354
|
+
const storage = createTestStorage();
|
|
355
|
+
const newRegistry: PluginRegistry = { plugin1: "typeB" as PluginName }; // Different type
|
|
356
|
+
|
|
357
|
+
const result = migrateBlockStorage(storage, {
|
|
358
|
+
migrateBlockData: (versioned) => ({
|
|
359
|
+
data: versioned.data as { count: number },
|
|
360
|
+
version: "v2",
|
|
361
|
+
}),
|
|
362
|
+
migratePluginData: () => {
|
|
363
|
+
throw new Error("Should not be called for type change");
|
|
364
|
+
},
|
|
365
|
+
newPluginRegistry: newRegistry,
|
|
366
|
+
createPluginData: (pluginId) => ({
|
|
367
|
+
version: "v1",
|
|
368
|
+
data: { fresh: true, type: newRegistry[pluginId] },
|
|
369
|
+
}),
|
|
234
370
|
});
|
|
371
|
+
|
|
372
|
+
expect(result.success).toBe(true);
|
|
373
|
+
if (result.success) {
|
|
374
|
+
expect(result.storage.__plugins?.plugin1).toEqual({
|
|
375
|
+
__dataVersion: "v1",
|
|
376
|
+
__data: { fresh: true, type: "typeB" },
|
|
377
|
+
});
|
|
378
|
+
}
|
|
235
379
|
});
|
|
236
380
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
)
|
|
243
|
-
|
|
244
|
-
|
|
381
|
+
it("should create initial data for new plugins", () => {
|
|
382
|
+
const storage = createBlockStorage({ count: 1 }, "v1");
|
|
383
|
+
const newRegistry: PluginRegistry = { newPlugin: "typeNew" as PluginName };
|
|
384
|
+
|
|
385
|
+
const result = migrateBlockStorage(storage, {
|
|
386
|
+
migrateBlockData: (versioned) => ({
|
|
387
|
+
data: versioned.data as { count: number },
|
|
388
|
+
version: "v2",
|
|
389
|
+
}),
|
|
390
|
+
migratePluginData: () => {
|
|
391
|
+
throw new Error("Should not be called for new plugin");
|
|
392
|
+
},
|
|
393
|
+
newPluginRegistry: newRegistry,
|
|
394
|
+
createPluginData: (_pluginId) => ({
|
|
395
|
+
version: "v1",
|
|
396
|
+
data: { initialized: true },
|
|
397
|
+
}),
|
|
245
398
|
});
|
|
246
399
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
...storage,
|
|
253
|
-
__data: data,
|
|
254
|
-
__dataVersion: `${storage.__dataVersion}-next`,
|
|
400
|
+
expect(result.success).toBe(true);
|
|
401
|
+
if (result.success) {
|
|
402
|
+
expect(result.storage.__plugins?.newPlugin).toEqual({
|
|
403
|
+
__dataVersion: "v1",
|
|
404
|
+
__data: { initialized: true },
|
|
255
405
|
});
|
|
406
|
+
}
|
|
407
|
+
});
|
|
256
408
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
409
|
+
it("should drop plugins not in new registry", () => {
|
|
410
|
+
const storage = createTestStorage();
|
|
411
|
+
const newRegistry: PluginRegistry = {}; // Empty - removes plugin1
|
|
412
|
+
|
|
413
|
+
const result = migrateBlockStorage(storage, {
|
|
414
|
+
migrateBlockData: (versioned) => ({
|
|
415
|
+
data: versioned.data as { count: number },
|
|
416
|
+
version: "v2",
|
|
417
|
+
}),
|
|
418
|
+
migratePluginData: () => {
|
|
419
|
+
throw new Error("Should not be called for dropped plugin");
|
|
420
|
+
},
|
|
421
|
+
newPluginRegistry: newRegistry,
|
|
422
|
+
createPluginData: () => {
|
|
423
|
+
throw new Error("Should not be called for dropped plugin");
|
|
424
|
+
},
|
|
425
|
+
});
|
|
260
426
|
|
|
261
|
-
|
|
262
|
-
|
|
427
|
+
expect(result.success).toBe(true);
|
|
428
|
+
if (result.success) {
|
|
429
|
+
expect(result.storage.__plugins).toEqual({});
|
|
430
|
+
expect(result.storage.__pluginRegistry).toEqual({});
|
|
431
|
+
}
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
it("should allow plugin migration to return undefined to remove plugin", () => {
|
|
435
|
+
const storage = createTestStorage();
|
|
436
|
+
const newRegistry: PluginRegistry = { plugin1: "typeA" as PluginName };
|
|
437
|
+
|
|
438
|
+
const result = migrateBlockStorage(storage, {
|
|
439
|
+
migrateBlockData: (versioned) => ({
|
|
440
|
+
data: versioned.data as { count: number },
|
|
441
|
+
version: "v2",
|
|
442
|
+
}),
|
|
443
|
+
migratePluginData: () => undefined, // Remove plugin
|
|
444
|
+
newPluginRegistry: newRegistry,
|
|
445
|
+
createPluginData: () => ({ version: "v1", data: {} }),
|
|
263
446
|
});
|
|
447
|
+
|
|
448
|
+
expect(result.success).toBe(true);
|
|
449
|
+
if (result.success) {
|
|
450
|
+
expect(result.storage.__plugins).toEqual({});
|
|
451
|
+
}
|
|
264
452
|
});
|
|
265
453
|
});
|
|
266
454
|
});
|