@dxos/migrations 0.8.4-main.d05539e30a → 0.8.4-main.d9fc60f731

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.
@@ -1,17 +1,26 @@
1
+ // src/annotations.ts
2
+ import * as Schema from "effect/Schema";
3
+ import { Annotation } from "@dxos/echo";
4
+ var MigrationVersionAnnotation = Annotation.make({
5
+ id: "org.dxos.migrations.version",
6
+ schema: Schema.String
7
+ });
8
+
1
9
  // src/migration-builder.ts
2
10
  import { next as A } from "@automerge/automerge";
3
11
  import { CreateEpochRequest } from "@dxos/client/halo";
4
12
  import { ObjectCore, migrateDocument } from "@dxos/echo-db";
5
13
  import { EncodedReference, SpaceDocVersion } from "@dxos/echo-protocol";
6
- import { getSchemaDXN } from "@dxos/echo/internal";
14
+ import { getSchemaURI } from "@dxos/echo/internal";
15
+ import * as Type from "@dxos/echo/Type";
7
16
  import { invariant } from "@dxos/invariant";
8
- import { DXN } from "@dxos/keys";
17
+ import { EID, EntityId } from "@dxos/keys";
9
18
  var __dxlog_file = "/__w/dxos/dxos/packages/sdk/migrations/src/migration-builder.ts";
10
19
  var MigrationBuilder = class {
11
20
  _space;
12
21
  _repo;
13
22
  _rootDoc;
14
- // echoId -> automergeUrl
23
+ // echoUri -> automergeUrl
15
24
  _newLinks = {};
16
25
  _flushIds = [];
17
26
  _deleteObjects = [];
@@ -36,9 +45,10 @@ var MigrationBuilder = class {
36
45
  if (!objectStructure) {
37
46
  return;
38
47
  }
39
- const { schema, props } = await migrate(objectStructure);
48
+ const { type, props } = await migrate(objectStructure);
49
+ const schema = Type.getSchema(type);
40
50
  const oldHandle = await this._findObjectContainingHandle(id);
41
- invariant(oldHandle, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 59, S: this, A: ["oldHandle", ""] });
51
+ invariant(oldHandle, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 61, S: this, A: ["oldHandle", ""] });
42
52
  const newState = {
43
53
  version: SpaceDocVersion.CURRENT,
44
54
  access: {
@@ -47,7 +57,7 @@ var MigrationBuilder = class {
47
57
  objects: {
48
58
  [id]: {
49
59
  system: {
50
- type: EncodedReference.fromDXN(getSchemaDXN(schema))
60
+ type: EncodedReference.fromURI(getSchemaURI(schema))
51
61
  },
52
62
  data: props,
53
63
  meta: {
@@ -59,19 +69,23 @@ var MigrationBuilder = class {
59
69
  const migratedDoc = migrateDocument(oldHandle.doc(), newState);
60
70
  const newHandle = this._repo.import(A.save(migratedDoc));
61
71
  await newHandle.whenReady();
62
- invariant(newHandle.url, "Migrated document URL not available after whenReady", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 80, S: this, A: ["newHandle.url", "'Migrated document URL not available after whenReady'"] });
72
+ invariant(newHandle.url, "Migrated document URL not available after whenReady", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 82, S: this, A: ["newHandle.url", "'Migrated document URL not available after whenReady'"] });
63
73
  this._newLinks[id] = newHandle.url;
64
74
  this._addHandleToFlushList(newHandle.documentId);
65
75
  }
66
- async addObject(schema, props) {
76
+ async addObject(type, props) {
77
+ const resolved = Type.getSchema(type);
67
78
  const core = await this._createObject({
68
- schema,
79
+ schema: resolved,
69
80
  props
70
81
  });
71
82
  return core.id;
72
83
  }
73
84
  createReference(id) {
74
- return EncodedReference.fromDXN(DXN.fromLocalObjectId(id));
85
+ invariant(EntityId.isValid(id), "Invalid EntityId.", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 95, S: this, A: ["EntityId.isValid(id)", "'Invalid EntityId.'"] });
86
+ return EncodedReference.fromURI(EID.make({
87
+ entityId: id
88
+ }));
75
89
  }
76
90
  deleteObject(id) {
77
91
  this._deleteObjects.push(id);
@@ -80,7 +94,7 @@ var MigrationBuilder = class {
80
94
  if (!this._newRoot) {
81
95
  await this._buildNewRoot();
82
96
  }
83
- invariant(this._newRoot, "New root not created", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 101, S: this, A: ["this._newRoot", "'New root not created'"] });
97
+ invariant(this._newRoot, "New root not created", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 107, S: this, A: ["this._newRoot", "'New root not created'"] });
84
98
  this._newRoot.change((doc) => {
85
99
  const propertiesStructure = doc.objects?.[this._space.properties.id];
86
100
  propertiesStructure && changeFn(propertiesStructure);
@@ -95,9 +109,9 @@ var MigrationBuilder = class {
95
109
  if (!this._newRoot) {
96
110
  await this._buildNewRoot();
97
111
  }
98
- invariant(this._newRoot, "New root not created", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 115, S: this, A: ["this._newRoot", "'New root not created'"] });
112
+ invariant(this._newRoot, "New root not created", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 121, S: this, A: ["this._newRoot", "'New root not created'"] });
99
113
  await this._space.db.flush();
100
- invariant(this._newRoot.url, "New root URL not available", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 118, S: this, A: ["this._newRoot.url", "'New root URL not available'"] });
114
+ invariant(this._newRoot.url, "New root URL not available", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 124, S: this, A: ["this._newRoot.url", "'New root URL not available'"] });
101
115
  await this._space.internal.createEpoch({
102
116
  migration: CreateEpochRequest.Migration.REPLACE_AUTOMERGE_ROOT,
103
117
  automergeRootUrl: this._newRoot.url
@@ -139,7 +153,7 @@ var MigrationBuilder = class {
139
153
  core.id = id;
140
154
  }
141
155
  core.initNewObject(props);
142
- core.setType(EncodedReference.fromDXN(getSchemaDXN(schema)));
156
+ core.setType(EncodedReference.fromURI(getSchemaURI(schema)));
143
157
  const newHandle = this._repo.create({
144
158
  version: SpaceDocVersion.CURRENT,
145
159
  access: {
@@ -162,7 +176,9 @@ var MigrationBuilder = class {
162
176
  // src/migrations.ts
163
177
  import { Atom } from "@effect-atom/atom";
164
178
  import * as Registry from "@effect-atom/atom/Registry";
179
+ import * as Option from "effect/Option";
165
180
  import { SpaceState } from "@dxos/client/echo";
181
+ import { Annotation as Annotation2, Obj } from "@dxos/echo";
166
182
  import { invariant as invariant2 } from "@dxos/invariant";
167
183
  var __dxlog_file2 = "/__w/dxos/dxos/packages/sdk/migrations/src/migrations.ts";
168
184
  var Migrations = class {
@@ -172,6 +188,9 @@ var Migrations = class {
172
188
  static _stateAtom = Atom.make({
173
189
  running: []
174
190
  }).pipe(Atom.keepAlive);
191
+ /**
192
+ * @deprecated Use `MigrationVersionAnnotation` via `Annotation.get/set` on space properties.
193
+ */
175
194
  static get versionProperty() {
176
195
  return this.namespace && `${this.namespace}.version`;
177
196
  }
@@ -187,10 +206,9 @@ var Migrations = class {
187
206
  this.migrations = migrations;
188
207
  }
189
208
  static async migrate(space, targetVersion) {
190
- invariant2(!this.running(space), "Migration already running", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 31, S: this, A: ["!this.running(space)", "'Migration already running'"] });
191
- invariant2(this.versionProperty, "Migrations namespace not set", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 32, S: this, A: ["this.versionProperty", "'Migrations namespace not set'"] });
192
- invariant2(space.state.get() === SpaceState.SPACE_READY, "Space not ready", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 33, S: this, A: ["space.state.get() === SpaceState.SPACE_READY", "'Space not ready'"] });
193
- const currentVersion = space.properties[this.versionProperty];
209
+ invariant2(!this.running(space), "Migration already running", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 36, S: this, A: ["!this.running(space)", "'Migration already running'"] });
210
+ invariant2(space.state.get() === SpaceState.SPACE_READY, "Space not ready", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 37, S: this, A: ["space.state.get() === SpaceState.SPACE_READY", "'Space not ready'"] });
211
+ const currentVersion = Annotation2.get(space.properties, MigrationVersionAnnotation).pipe(Option.getOrUndefined);
194
212
  const currentIndex = this.migrations.findIndex((m) => m.version === currentVersion) + 1;
195
213
  const i = this.migrations.findIndex((m) => m.version === targetVersion);
196
214
  const targetIndex = i === -1 ? this.migrations.length : i + 1;
@@ -205,30 +223,33 @@ var Migrations = class {
205
223
  spaceKey
206
224
  ]
207
225
  });
208
- if (targetIndex > currentIndex) {
209
- const migrations = this.migrations.slice(currentIndex, targetIndex);
210
- for (const migration of migrations) {
211
- const builder = new MigrationBuilder(space);
212
- await migration.next({
213
- space,
214
- builder
215
- });
216
- await builder.changeProperties((propertiesStructure) => {
217
- invariant2(this.versionProperty, "Migrations namespace not set", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 58, S: this, A: ["this.versionProperty", "'Migrations namespace not set'"] });
218
- propertiesStructure.data[this.versionProperty] = migration.version;
219
- });
220
- await builder._commit();
226
+ try {
227
+ if (targetIndex > currentIndex) {
228
+ const migrations = this.migrations.slice(currentIndex, targetIndex);
229
+ for (const migration of migrations) {
230
+ const builder = new MigrationBuilder(space);
231
+ await migration.next({
232
+ space,
233
+ builder
234
+ });
235
+ await builder._commit();
236
+ Obj.update(space.properties, (properties) => {
237
+ Annotation2.set(properties, MigrationVersionAnnotation, migration.version);
238
+ });
239
+ }
221
240
  }
241
+ } finally {
242
+ const finalState = this._registry.get(this._stateAtom);
243
+ this._registry.set(this._stateAtom, {
244
+ running: finalState.running.filter((key) => key !== spaceKey)
245
+ });
222
246
  }
223
- const finalState = this._registry.get(this._stateAtom);
224
- this._registry.set(this._stateAtom, {
225
- running: finalState.running.filter((key) => key !== spaceKey)
226
- });
227
247
  return true;
228
248
  }
229
249
  };
230
250
  export {
231
251
  MigrationBuilder,
252
+ MigrationVersionAnnotation,
232
253
  Migrations
233
254
  };
234
255
  //# sourceMappingURL=index.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../../src/migration-builder.ts", "../../../src/migrations.ts"],
4
- "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { next as A, type Doc } from '@automerge/automerge';\nimport { type AnyDocumentId, type DocumentId } from '@automerge/automerge-repo';\nimport type * as Schema from 'effect/Schema';\n\nimport { type Space } from '@dxos/client/echo';\nimport { CreateEpochRequest } from '@dxos/client/halo';\nimport { type DocHandleProxy, ObjectCore, type RepoProxy, migrateDocument } from '@dxos/echo-db';\nimport { type DatabaseDirectory, EncodedReference, type ObjectStructure, SpaceDocVersion } from '@dxos/echo-protocol';\nimport { getSchemaDXN } from '@dxos/echo/internal';\nimport { invariant } from '@dxos/invariant';\nimport { DXN } from '@dxos/keys';\nimport { type MaybePromise } from '@dxos/util';\n\n/*\n\nConsidering a better API for this:\n\n```ts\nconst migration = space.db.beginMigration(); // all actions are not visible to queries and are only applied once you call `apply`\n\nmigration.applyObjectMigration(defineMigration(From, To, { ... }));\n\nmigration.delete(id);\nmigration.add(obj);\n\nawait migration.apply(); // Will create new epoch.\n```\n\n*/\n\n// TODO(dmaretskyi): We no longer need to hook into ECHO internals, with the changes to echo APIs.\nexport class MigrationBuilder {\n private readonly _repo: RepoProxy;\n private readonly _rootDoc: Doc<DatabaseDirectory>;\n\n // echoId -> automergeUrl\n private readonly _newLinks: Record<string, string> = {};\n private readonly _flushIds: DocumentId[] = [];\n private readonly _deleteObjects: string[] = [];\n\n private _newRoot?: DocHandleProxy<DatabaseDirectory> = undefined;\n\n constructor(private readonly _space: Space) {\n this._repo = this._space.internal.db.coreDatabase._repo;\n // TODO(wittjosiah): Accessing private API.\n this._rootDoc = (this._space.internal.db.coreDatabase as any)._automergeDocLoader\n .getSpaceRootDocHandle()\n .doc() as Doc<DatabaseDirectory>;\n }\n\n async findObject(id: string): Promise<ObjectStructure | undefined> {\n const documentId = (this._rootDoc.links?.[id] || this._newLinks[id])?.toString() as AnyDocumentId | undefined;\n const docHandle = documentId && this._repo.find(documentId);\n if (!docHandle) {\n return undefined;\n }\n\n await docHandle.whenReady();\n const doc = docHandle.doc() as Doc<DatabaseDirectory>;\n return doc.objects?.[id];\n }\n\n async migrateObject(\n id: string,\n migrate: (objectStructure: ObjectStructure) => MaybePromise<{ schema: Schema.Schema.AnyNoContext; props: any }>,\n ): Promise<void> {\n const objectStructure = await this.findObject(id);\n if (!objectStructure) {\n return;\n }\n\n const { schema, props } = await migrate(objectStructure);\n\n const oldHandle = await this._findObjectContainingHandle(id);\n invariant(oldHandle);\n\n const newState: DatabaseDirectory = {\n version: SpaceDocVersion.CURRENT,\n access: {\n spaceKey: this._space.key.toHex(),\n },\n objects: {\n [id]: {\n system: {\n type: EncodedReference.fromDXN(getSchemaDXN(schema)!),\n },\n data: props,\n meta: {\n keys: [],\n },\n },\n },\n };\n const migratedDoc = migrateDocument(oldHandle.doc() as Doc<DatabaseDirectory>, newState);\n const newHandle = this._repo.import<DatabaseDirectory>(A.save(migratedDoc));\n await newHandle.whenReady();\n invariant(newHandle.url, 'Migrated document URL not available after whenReady');\n this._newLinks[id] = newHandle.url;\n this._addHandleToFlushList(newHandle.documentId!);\n }\n\n async addObject(schema: Schema.Schema.AnyNoContext, props: any): Promise<string> {\n const core = await this._createObject({ schema, props });\n return core.id;\n }\n\n createReference(id: string) {\n return EncodedReference.fromDXN(DXN.fromLocalObjectId(id));\n }\n\n deleteObject(id: string): void {\n this._deleteObjects.push(id);\n }\n\n async changeProperties(changeFn: (properties: ObjectStructure) => void): Promise<void> {\n if (!this._newRoot) {\n await this._buildNewRoot();\n }\n invariant(this._newRoot, 'New root not created');\n\n this._newRoot.change((doc: DatabaseDirectory) => {\n const propertiesStructure = doc.objects?.[this._space.properties.id];\n propertiesStructure && changeFn(propertiesStructure);\n });\n await this._newRoot.whenReady();\n this._addHandleToFlushList(this._newRoot.documentId!);\n }\n\n /**\n * @internal\n */\n async _commit(): Promise<void> {\n if (!this._newRoot) {\n await this._buildNewRoot();\n }\n invariant(this._newRoot, 'New root not created');\n\n await this._space.db.flush();\n\n // Create new epoch.\n invariant(this._newRoot.url, 'New root URL not available');\n await this._space.internal.createEpoch({\n migration: CreateEpochRequest.Migration.REPLACE_AUTOMERGE_ROOT,\n automergeRootUrl: this._newRoot.url,\n });\n }\n\n private async _findObjectContainingHandle(id: string): Promise<DocHandleProxy<DatabaseDirectory> | undefined> {\n const documentId = (this._rootDoc.links?.[id] || this._newLinks[id])?.toString() as AnyDocumentId | undefined;\n const docHandle = documentId && this._repo.find(documentId);\n if (!docHandle) {\n return undefined;\n }\n\n await docHandle.whenReady();\n return docHandle;\n }\n\n private async _buildNewRoot(): Promise<void> {\n const links = { ...(this._rootDoc.links ?? {}) };\n for (const id of this._deleteObjects) {\n delete links[id];\n }\n\n for (const [id, url] of Object.entries(this._newLinks)) {\n links[id] = new A.RawString(url);\n }\n\n this._newRoot = this._repo.create<DatabaseDirectory>({\n version: SpaceDocVersion.CURRENT,\n access: {\n spaceKey: this._space.key.toHex(),\n },\n objects: this._rootDoc.objects,\n links,\n });\n await this._newRoot.whenReady();\n this._addHandleToFlushList(this._newRoot.documentId!);\n }\n\n private async _createObject({\n id,\n schema,\n props,\n }: {\n id?: string;\n schema: Schema.Schema.AnyNoContext;\n props: any;\n }): Promise<ObjectCore> {\n const core = new ObjectCore();\n if (id) {\n core.id = id;\n }\n\n core.initNewObject(props);\n core.setType(EncodedReference.fromDXN(getSchemaDXN(schema)!));\n const newHandle = this._repo.create<DatabaseDirectory>({\n version: SpaceDocVersion.CURRENT,\n access: {\n spaceKey: this._space.key.toHex(),\n },\n objects: {\n [core.id]: core.getDoc() as ObjectStructure,\n },\n });\n await newHandle.whenReady();\n this._newLinks[core.id] = newHandle.url!;\n this._addHandleToFlushList(newHandle.documentId!);\n\n return core;\n }\n\n private _addHandleToFlushList(id: DocumentId): void {\n this._flushIds.push(id);\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { Atom } from '@effect-atom/atom';\nimport * as Registry from '@effect-atom/atom/Registry';\n\nimport { type Space, SpaceState } from '@dxos/client/echo';\nimport { invariant } from '@dxos/invariant';\nimport { type MaybePromise } from '@dxos/util';\n\nimport { MigrationBuilder } from './migration-builder';\n\nexport type MigrationContext = {\n space: Space;\n builder: MigrationBuilder;\n};\n\nexport type Migration = {\n version: string;\n next: (context: MigrationContext) => MaybePromise<void>;\n};\n\nexport class Migrations {\n static namespace?: string;\n static migrations: Migration[] = [];\n private static _registry = Registry.make();\n private static _stateAtom = Atom.make<{ running: string[] }>({ running: [] }).pipe(Atom.keepAlive);\n\n static get versionProperty() {\n return this.namespace && `${this.namespace}.version`;\n }\n\n static get targetVersion() {\n return this.migrations[this.migrations.length - 1]?.version;\n }\n\n static running(space: Space): boolean {\n const state = this._registry.get(this._stateAtom);\n return state.running.includes(space.key.toHex());\n }\n\n static define(namespace: string, migrations: Migration[]): void {\n this.namespace = namespace;\n this.migrations = migrations;\n }\n\n static async migrate(space: Space, targetVersion?: string | number): Promise<boolean> {\n invariant(!this.running(space), 'Migration already running');\n invariant(this.versionProperty, 'Migrations namespace not set');\n invariant(space.state.get() === SpaceState.SPACE_READY, 'Space not ready');\n const currentVersion = space.properties[this.versionProperty];\n const currentIndex = this.migrations.findIndex((m) => m.version === currentVersion) + 1;\n const i = this.migrations.findIndex((m) => m.version === targetVersion);\n const targetIndex = i === -1 ? this.migrations.length : i + 1;\n if (currentIndex === targetIndex) {\n return false;\n }\n\n const spaceKey = space.key.toHex();\n const currentState = this._registry.get(this._stateAtom);\n this._registry.set(this._stateAtom, { running: [...currentState.running, spaceKey] });\n if (targetIndex > currentIndex) {\n const migrations = this.migrations.slice(currentIndex, targetIndex);\n for (const migration of migrations) {\n const builder = new MigrationBuilder(space);\n await migration.next({ space, builder });\n await builder.changeProperties((propertiesStructure) => {\n invariant(this.versionProperty, 'Migrations namespace not set');\n propertiesStructure.data[this.versionProperty] = migration.version;\n });\n await builder._commit();\n }\n }\n const finalState = this._registry.get(this._stateAtom);\n this._registry.set(this._stateAtom, { running: finalState.running.filter((key) => key !== spaceKey) });\n\n return true;\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["next", "A", "CreateEpochRequest", "ObjectCore", "migrateDocument", "EncodedReference", "SpaceDocVersion", "getSchemaDXN", "invariant", "DXN", "_repo", "_rootDoc", "_newLinks", "_deleteObjects", "_newRoot", "undefined", "_space", "internal", "db", "coreDatabase", "findObject", "docHandle", "objects", "migrateObject", "migrate", "objectStructure", "oldHandle", "newState", "version", "access", "spaceKey", "system", "data", "props", "meta", "keys", "newHandle", "whenReady", "id", "_addHandleToFlushList", "addObject", "schema", "createReference", "deleteObject", "changeProperties", "changeFn", "_buildNewRoot", "propertiesStructure", "properties", "migration", "REPLACE_AUTOMERGE_ROOT", "automergeRootUrl", "documentId", "url", "create", "links", "_createObject", "core", "initNewObject", "CURRENT", "Atom", "Registry", "SpaceState", "invariant", "__dxlog_file", "Migrations", "migrations", "_registry", "_stateAtom", "Atom", "running", "keepAlive", "versionProperty", "namespace", "targetVersion", "space", "state", "define", "invariant", "get", "SpaceState", "currentVersion", "properties", "currentIndex", "findIndex", "version", "i", "m", "targetIndex", "length", "spaceKey", "set", "currentState", "migration", "builder", "MigrationBuilder", "propertiesStructure", "finalState", "filter", "key"]
3
+ "sources": ["../../../src/annotations.ts", "../../../src/migration-builder.ts", "../../../src/migrations.ts"],
4
+ "sourcesContent": ["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Schema from 'effect/Schema';\n\nimport { Annotation } from '@dxos/echo';\n\n/** Migration version stored on space properties meta. */\nexport const MigrationVersionAnnotation = Annotation.make({\n id: 'org.dxos.migrations.version',\n schema: Schema.String,\n});\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { next as A, type Doc } from '@automerge/automerge';\nimport { type AnyDocumentId, type DocumentId } from '@automerge/automerge-repo';\nimport type * as Schema from 'effect/Schema';\n\nimport { type Space } from '@dxos/client/echo';\nimport { CreateEpochRequest } from '@dxos/client/halo';\nimport { type DocHandleProxy, ObjectCore, type RepoProxy, migrateDocument } from '@dxos/echo-db';\nimport { type DatabaseDirectory, EncodedReference, type EntityStructure, SpaceDocVersion } from '@dxos/echo-protocol';\nimport { getSchemaURI } from '@dxos/echo/internal';\nimport * as Type from '@dxos/echo/Type';\nimport { invariant } from '@dxos/invariant';\nimport { EID, EntityId } from '@dxos/keys';\nimport { type MaybePromise } from '@dxos/util';\n\n/*\n\nConsidering a better API for this:\n\n```ts\nconst migration = space.db.beginMigration(); // all actions are not visible to queries and are only applied once you call `apply`\n\nmigration.applyObjectMigration(defineMigration(From, To, { ... }));\n\nmigration.delete(id);\nmigration.add(obj);\n\nawait migration.apply(); // Will create new epoch.\n```\n\n*/\n\n// TODO(dmaretskyi): We no longer need to hook into ECHO internals, with the changes to echo APIs.\nexport class MigrationBuilder {\n private readonly _repo: RepoProxy;\n private readonly _rootDoc: Doc<DatabaseDirectory>;\n\n // echoUri -> automergeUrl\n private readonly _newLinks: Record<string, string> = {};\n private readonly _flushIds: DocumentId[] = [];\n private readonly _deleteObjects: string[] = [];\n\n private _newRoot?: DocHandleProxy<DatabaseDirectory> = undefined;\n\n constructor(private readonly _space: Space) {\n this._repo = this._space.internal.db.coreDatabase._repo;\n // TODO(wittjosiah): Accessing private API.\n this._rootDoc = (this._space.internal.db.coreDatabase as any)._automergeDocLoader\n .getSpaceRootDocHandle()\n .doc() as Doc<DatabaseDirectory>;\n }\n\n async findObject(id: string): Promise<EntityStructure | undefined> {\n const documentId = (this._rootDoc.links?.[id] || this._newLinks[id])?.toString() as AnyDocumentId | undefined;\n const docHandle = documentId && this._repo.find(documentId);\n if (!docHandle) {\n return undefined;\n }\n\n await docHandle.whenReady();\n const doc = docHandle.doc() as Doc<DatabaseDirectory>;\n return doc.objects?.[id];\n }\n\n async migrateObject(\n id: string,\n migrate: (objectStructure: EntityStructure) => MaybePromise<{ type: Type.AnyEntity; props: any }>,\n ): Promise<void> {\n const objectStructure = await this.findObject(id);\n if (!objectStructure) {\n return;\n }\n\n const { type, props } = await migrate(objectStructure);\n const schema = Type.getSchema(type);\n\n const oldHandle = await this._findObjectContainingHandle(id);\n invariant(oldHandle);\n\n const newState: DatabaseDirectory = {\n version: SpaceDocVersion.CURRENT,\n access: {\n spaceKey: this._space.key.toHex(),\n },\n objects: {\n [id]: {\n system: {\n type: EncodedReference.fromURI(getSchemaURI(schema)!),\n },\n data: props,\n meta: {\n keys: [],\n },\n },\n },\n };\n const migratedDoc = migrateDocument(oldHandle.doc() as Doc<DatabaseDirectory>, newState);\n const newHandle = this._repo.import<DatabaseDirectory>(A.save(migratedDoc));\n await newHandle.whenReady();\n invariant(newHandle.url, 'Migrated document URL not available after whenReady');\n this._newLinks[id] = newHandle.url;\n this._addHandleToFlushList(newHandle.documentId!);\n }\n\n async addObject(type: Type.AnyEntity, props: any): Promise<string> {\n const resolved = Type.getSchema(type);\n const core = await this._createObject({ schema: resolved, props });\n return core.id;\n }\n\n createReference(id: string) {\n invariant(EntityId.isValid(id), 'Invalid EntityId.');\n return EncodedReference.fromURI(EID.make({ entityId: id }));\n }\n\n deleteObject(id: string): void {\n this._deleteObjects.push(id);\n }\n\n async changeProperties(changeFn: (properties: EntityStructure) => void): Promise<void> {\n if (!this._newRoot) {\n await this._buildNewRoot();\n }\n invariant(this._newRoot, 'New root not created');\n\n this._newRoot.change((doc: DatabaseDirectory) => {\n const propertiesStructure = doc.objects?.[this._space.properties.id];\n propertiesStructure && changeFn(propertiesStructure);\n });\n await this._newRoot.whenReady();\n this._addHandleToFlushList(this._newRoot.documentId!);\n }\n\n /**\n * @internal\n */\n async _commit(): Promise<void> {\n if (!this._newRoot) {\n await this._buildNewRoot();\n }\n invariant(this._newRoot, 'New root not created');\n\n await this._space.db.flush();\n\n // Create new epoch.\n invariant(this._newRoot.url, 'New root URL not available');\n await this._space.internal.createEpoch({\n migration: CreateEpochRequest.Migration.REPLACE_AUTOMERGE_ROOT,\n automergeRootUrl: this._newRoot.url,\n });\n }\n\n private async _findObjectContainingHandle(id: string): Promise<DocHandleProxy<DatabaseDirectory> | undefined> {\n const documentId = (this._rootDoc.links?.[id] || this._newLinks[id])?.toString() as AnyDocumentId | undefined;\n const docHandle = documentId && this._repo.find(documentId);\n if (!docHandle) {\n return undefined;\n }\n\n await docHandle.whenReady();\n return docHandle;\n }\n\n private async _buildNewRoot(): Promise<void> {\n const links = { ...(this._rootDoc.links ?? {}) };\n for (const id of this._deleteObjects) {\n delete links[id];\n }\n\n for (const [id, url] of Object.entries(this._newLinks)) {\n links[id] = new A.RawString(url);\n }\n\n this._newRoot = this._repo.create<DatabaseDirectory>({\n version: SpaceDocVersion.CURRENT,\n access: {\n spaceKey: this._space.key.toHex(),\n },\n objects: this._rootDoc.objects,\n links,\n });\n await this._newRoot.whenReady();\n this._addHandleToFlushList(this._newRoot.documentId!);\n }\n\n private async _createObject({\n id,\n schema,\n props,\n }: {\n id?: string;\n schema: Schema.Schema.AnyNoContext;\n props: any;\n }): Promise<ObjectCore> {\n const core = new ObjectCore();\n if (id) {\n core.id = id;\n }\n\n core.initNewObject(props);\n core.setType(EncodedReference.fromURI(getSchemaURI(schema)!));\n const newHandle = this._repo.create<DatabaseDirectory>({\n version: SpaceDocVersion.CURRENT,\n access: {\n spaceKey: this._space.key.toHex(),\n },\n objects: {\n [core.id]: core.getDoc() as EntityStructure,\n },\n });\n await newHandle.whenReady();\n this._newLinks[core.id] = newHandle.url!;\n this._addHandleToFlushList(newHandle.documentId!);\n\n return core;\n }\n\n private _addHandleToFlushList(id: DocumentId): void {\n this._flushIds.push(id);\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { Atom } from '@effect-atom/atom';\nimport * as Registry from '@effect-atom/atom/Registry';\nimport * as Option from 'effect/Option';\n\nimport { type Space, SpaceState } from '@dxos/client/echo';\nimport { Annotation, Obj } from '@dxos/echo';\nimport { invariant } from '@dxos/invariant';\nimport { type MaybePromise } from '@dxos/util';\n\nimport { MigrationVersionAnnotation } from './annotations';\nimport { MigrationBuilder } from './migration-builder';\n\nexport type MigrationContext = {\n space: Space;\n builder: MigrationBuilder;\n};\n\nexport type Migration = {\n version: string;\n next: (context: MigrationContext) => MaybePromise<void>;\n};\n\nexport class Migrations {\n static namespace?: string;\n static migrations: Migration[] = [];\n private static _registry = Registry.make();\n private static _stateAtom = Atom.make<{ running: string[] }>({ running: [] }).pipe(Atom.keepAlive);\n\n /**\n * @deprecated Use `MigrationVersionAnnotation` via `Annotation.get/set` on space properties.\n */\n static get versionProperty() {\n return this.namespace && `${this.namespace}.version`;\n }\n\n static get targetVersion() {\n return this.migrations[this.migrations.length - 1]?.version;\n }\n\n static running(space: Space): boolean {\n const state = this._registry.get(this._stateAtom);\n return state.running.includes(space.key.toHex());\n }\n\n static define(namespace: string, migrations: Migration[]): void {\n this.namespace = namespace;\n this.migrations = migrations;\n }\n\n static async migrate(space: Space, targetVersion?: string | number): Promise<boolean> {\n invariant(!this.running(space), 'Migration already running');\n invariant(space.state.get() === SpaceState.SPACE_READY, 'Space not ready');\n const currentVersion = Annotation.get(space.properties, MigrationVersionAnnotation).pipe(Option.getOrUndefined);\n const currentIndex = this.migrations.findIndex((m) => m.version === currentVersion) + 1;\n const i = this.migrations.findIndex((m) => m.version === targetVersion);\n const targetIndex = i === -1 ? this.migrations.length : i + 1;\n if (currentIndex === targetIndex) {\n return false;\n }\n\n const spaceKey = space.key.toHex();\n const currentState = this._registry.get(this._stateAtom);\n this._registry.set(this._stateAtom, { running: [...currentState.running, spaceKey] });\n try {\n if (targetIndex > currentIndex) {\n const migrations = this.migrations.slice(currentIndex, targetIndex);\n for (const migration of migrations) {\n const builder = new MigrationBuilder(space);\n await migration.next({ space, builder });\n await builder._commit();\n Obj.update(space.properties, (properties) => {\n Annotation.set(properties, MigrationVersionAnnotation, migration.version);\n });\n }\n }\n } finally {\n const finalState = this._registry.get(this._stateAtom);\n this._registry.set(this._stateAtom, { running: finalState.running.filter((key) => key !== spaceKey) });\n }\n\n return true;\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["Schema", "Annotation", "MigrationVersionAnnotation", "make", "id", "schema", "String", "next", "A", "CreateEpochRequest", "ObjectCore", "migrateDocument", "EncodedReference", "SpaceDocVersion", "getSchemaURI", "Type", "invariant", "EID", "EntityId", "_repo", "_rootDoc", "_newLinks", "_deleteObjects", "_newRoot", "undefined", "_space", "internal", "db", "coreDatabase", "findObject", "docHandle", "objects", "migrateObject", "migrate", "objectStructure", "oldHandle", "_findObjectContainingHandle", "newState", "version", "access", "spaceKey", "system", "data", "props", "meta", "keys", "newHandle", "whenReady", "id", "_addHandleToFlushList", "addObject", "core", "_createObject", "schema", "resolved", "createReference", "entityId", "deleteObject", "changeProperties", "changeFn", "_buildNewRoot", "propertiesStructure", "properties", "migration", "REPLACE_AUTOMERGE_ROOT", "automergeRootUrl", "documentId", "url", "create", "links", "initNewObject", "CURRENT", "Atom", "Registry", "Option", "SpaceState", "Annotation", "Obj", "invariant", "__dxlog_file", "Migrations", "migrations", "_registry", "_stateAtom", "Atom", "running", "keepAlive", "targetVersion", "space", "state", "define", "namespace", "invariant", "get", "SpaceState", "currentVersion", "Annotation", "MigrationVersionAnnotation", "pipe", "getOrUndefined", "currentIndex", "findIndex", "version", "i", "m", "targetIndex", "length", "spaceKey", "set", "currentState", "migration", "builder", "MigrationBuilder", "Obj", "properties", "finalState", "filter", "key"]
7
7
  }
@@ -1 +1 @@
1
- {"inputs":{"src/migration-builder.ts":{"bytes":23409,"imports":[{"path":"@automerge/automerge","kind":"import-statement","external":true},{"path":"@dxos/client/halo","kind":"import-statement","external":true},{"path":"@dxos/echo-db","kind":"import-statement","external":true},{"path":"@dxos/echo-protocol","kind":"import-statement","external":true},{"path":"@dxos/echo/internal","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true}],"format":"esm"},"src/migrations.ts":{"bytes":10982,"imports":[{"path":"@effect-atom/atom","kind":"import-statement","external":true},{"path":"@effect-atom/atom/Registry","kind":"import-statement","external":true},{"path":"@dxos/client/echo","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"src/migration-builder.ts","kind":"import-statement","original":"./migration-builder"}],"format":"esm"},"src/index.ts":{"bytes":575,"imports":[{"path":"src/migration-builder.ts","kind":"import-statement","original":"./migration-builder"},{"path":"src/migrations.ts","kind":"import-statement","original":"./migrations"}],"format":"esm"}},"outputs":{"dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":16635},"dist/lib/browser/index.mjs":{"imports":[{"path":"@automerge/automerge","kind":"import-statement","external":true},{"path":"@dxos/client/halo","kind":"import-statement","external":true},{"path":"@dxos/echo-db","kind":"import-statement","external":true},{"path":"@dxos/echo-protocol","kind":"import-statement","external":true},{"path":"@dxos/echo/internal","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true},{"path":"@effect-atom/atom","kind":"import-statement","external":true},{"path":"@effect-atom/atom/Registry","kind":"import-statement","external":true},{"path":"@dxos/client/echo","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true}],"exports":["MigrationBuilder","Migrations"],"entryPoint":"src/index.ts","inputs":{"src/migration-builder.ts":{"bytesInOutput":5430},"src/index.ts":{"bytesInOutput":0},"src/migrations.ts":{"bytesInOutput":3055}},"bytes":8615}}}
1
+ {"inputs":{"src/annotations.ts":{"bytes":1241,"imports":[{"path":"effect/Schema","kind":"import-statement","external":true},{"path":"@dxos/echo","kind":"import-statement","external":true}],"format":"esm"},"src/migration-builder.ts":{"bytes":24278,"imports":[{"path":"@automerge/automerge","kind":"import-statement","external":true},{"path":"@dxos/client/halo","kind":"import-statement","external":true},{"path":"@dxos/echo-db","kind":"import-statement","external":true},{"path":"@dxos/echo-protocol","kind":"import-statement","external":true},{"path":"@dxos/echo/internal","kind":"import-statement","external":true},{"path":"@dxos/echo/Type","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true}],"format":"esm"},"src/migrations.ts":{"bytes":11492,"imports":[{"path":"@effect-atom/atom","kind":"import-statement","external":true},{"path":"@effect-atom/atom/Registry","kind":"import-statement","external":true},{"path":"effect/Option","kind":"import-statement","external":true},{"path":"@dxos/client/echo","kind":"import-statement","external":true},{"path":"@dxos/echo","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"src/annotations.ts","kind":"import-statement","original":"./annotations"},{"path":"src/migration-builder.ts","kind":"import-statement","original":"./migration-builder"}],"format":"esm"},"src/index.ts":{"bytes":674,"imports":[{"path":"src/annotations.ts","kind":"import-statement","original":"./annotations"},{"path":"src/migration-builder.ts","kind":"import-statement","original":"./migration-builder"},{"path":"src/migrations.ts","kind":"import-statement","original":"./migrations"}],"format":"esm"}},"outputs":{"dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":17813},"dist/lib/browser/index.mjs":{"imports":[{"path":"effect/Schema","kind":"import-statement","external":true},{"path":"@dxos/echo","kind":"import-statement","external":true},{"path":"@automerge/automerge","kind":"import-statement","external":true},{"path":"@dxos/client/halo","kind":"import-statement","external":true},{"path":"@dxos/echo-db","kind":"import-statement","external":true},{"path":"@dxos/echo-protocol","kind":"import-statement","external":true},{"path":"@dxos/echo/internal","kind":"import-statement","external":true},{"path":"@dxos/echo/Type","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true},{"path":"@dxos/keys","kind":"import-statement","external":true},{"path":"@effect-atom/atom","kind":"import-statement","external":true},{"path":"@effect-atom/atom/Registry","kind":"import-statement","external":true},{"path":"effect/Option","kind":"import-statement","external":true},{"path":"@dxos/client/echo","kind":"import-statement","external":true},{"path":"@dxos/echo","kind":"import-statement","external":true},{"path":"@dxos/invariant","kind":"import-statement","external":true}],"exports":["MigrationBuilder","MigrationVersionAnnotation","Migrations"],"entryPoint":"src/index.ts","inputs":{"src/annotations.ts":{"bytesInOutput":198},"src/index.ts":{"bytesInOutput":0},"src/migration-builder.ts":{"bytesInOutput":5754},"src/migrations.ts":{"bytesInOutput":2983}},"bytes":9118}}}
@@ -1,19 +1,28 @@
1
1
  import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
2
 
3
+ // src/annotations.ts
4
+ import * as Schema from "effect/Schema";
5
+ import { Annotation } from "@dxos/echo";
6
+ var MigrationVersionAnnotation = Annotation.make({
7
+ id: "org.dxos.migrations.version",
8
+ schema: Schema.String
9
+ });
10
+
3
11
  // src/migration-builder.ts
4
12
  import { next as A } from "@automerge/automerge";
5
13
  import { CreateEpochRequest } from "@dxos/client/halo";
6
14
  import { ObjectCore, migrateDocument } from "@dxos/echo-db";
7
15
  import { EncodedReference, SpaceDocVersion } from "@dxos/echo-protocol";
8
- import { getSchemaDXN } from "@dxos/echo/internal";
16
+ import { getSchemaURI } from "@dxos/echo/internal";
17
+ import * as Type from "@dxos/echo/Type";
9
18
  import { invariant } from "@dxos/invariant";
10
- import { DXN } from "@dxos/keys";
19
+ import { EID, EntityId } from "@dxos/keys";
11
20
  var __dxlog_file = "/__w/dxos/dxos/packages/sdk/migrations/src/migration-builder.ts";
12
21
  var MigrationBuilder = class {
13
22
  _space;
14
23
  _repo;
15
24
  _rootDoc;
16
- // echoId -> automergeUrl
25
+ // echoUri -> automergeUrl
17
26
  _newLinks = {};
18
27
  _flushIds = [];
19
28
  _deleteObjects = [];
@@ -38,9 +47,10 @@ var MigrationBuilder = class {
38
47
  if (!objectStructure) {
39
48
  return;
40
49
  }
41
- const { schema, props } = await migrate(objectStructure);
50
+ const { type, props } = await migrate(objectStructure);
51
+ const schema = Type.getSchema(type);
42
52
  const oldHandle = await this._findObjectContainingHandle(id);
43
- invariant(oldHandle, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 59, S: this, A: ["oldHandle", ""] });
53
+ invariant(oldHandle, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 61, S: this, A: ["oldHandle", ""] });
44
54
  const newState = {
45
55
  version: SpaceDocVersion.CURRENT,
46
56
  access: {
@@ -49,7 +59,7 @@ var MigrationBuilder = class {
49
59
  objects: {
50
60
  [id]: {
51
61
  system: {
52
- type: EncodedReference.fromDXN(getSchemaDXN(schema))
62
+ type: EncodedReference.fromURI(getSchemaURI(schema))
53
63
  },
54
64
  data: props,
55
65
  meta: {
@@ -61,19 +71,23 @@ var MigrationBuilder = class {
61
71
  const migratedDoc = migrateDocument(oldHandle.doc(), newState);
62
72
  const newHandle = this._repo.import(A.save(migratedDoc));
63
73
  await newHandle.whenReady();
64
- invariant(newHandle.url, "Migrated document URL not available after whenReady", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 80, S: this, A: ["newHandle.url", "'Migrated document URL not available after whenReady'"] });
74
+ invariant(newHandle.url, "Migrated document URL not available after whenReady", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 82, S: this, A: ["newHandle.url", "'Migrated document URL not available after whenReady'"] });
65
75
  this._newLinks[id] = newHandle.url;
66
76
  this._addHandleToFlushList(newHandle.documentId);
67
77
  }
68
- async addObject(schema, props) {
78
+ async addObject(type, props) {
79
+ const resolved = Type.getSchema(type);
69
80
  const core = await this._createObject({
70
- schema,
81
+ schema: resolved,
71
82
  props
72
83
  });
73
84
  return core.id;
74
85
  }
75
86
  createReference(id) {
76
- return EncodedReference.fromDXN(DXN.fromLocalObjectId(id));
87
+ invariant(EntityId.isValid(id), "Invalid EntityId.", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 95, S: this, A: ["EntityId.isValid(id)", "'Invalid EntityId.'"] });
88
+ return EncodedReference.fromURI(EID.make({
89
+ entityId: id
90
+ }));
77
91
  }
78
92
  deleteObject(id) {
79
93
  this._deleteObjects.push(id);
@@ -82,7 +96,7 @@ var MigrationBuilder = class {
82
96
  if (!this._newRoot) {
83
97
  await this._buildNewRoot();
84
98
  }
85
- invariant(this._newRoot, "New root not created", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 101, S: this, A: ["this._newRoot", "'New root not created'"] });
99
+ invariant(this._newRoot, "New root not created", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 107, S: this, A: ["this._newRoot", "'New root not created'"] });
86
100
  this._newRoot.change((doc) => {
87
101
  const propertiesStructure = doc.objects?.[this._space.properties.id];
88
102
  propertiesStructure && changeFn(propertiesStructure);
@@ -97,9 +111,9 @@ var MigrationBuilder = class {
97
111
  if (!this._newRoot) {
98
112
  await this._buildNewRoot();
99
113
  }
100
- invariant(this._newRoot, "New root not created", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 115, S: this, A: ["this._newRoot", "'New root not created'"] });
114
+ invariant(this._newRoot, "New root not created", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 121, S: this, A: ["this._newRoot", "'New root not created'"] });
101
115
  await this._space.db.flush();
102
- invariant(this._newRoot.url, "New root URL not available", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 118, S: this, A: ["this._newRoot.url", "'New root URL not available'"] });
116
+ invariant(this._newRoot.url, "New root URL not available", { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 124, S: this, A: ["this._newRoot.url", "'New root URL not available'"] });
103
117
  await this._space.internal.createEpoch({
104
118
  migration: CreateEpochRequest.Migration.REPLACE_AUTOMERGE_ROOT,
105
119
  automergeRootUrl: this._newRoot.url
@@ -141,7 +155,7 @@ var MigrationBuilder = class {
141
155
  core.id = id;
142
156
  }
143
157
  core.initNewObject(props);
144
- core.setType(EncodedReference.fromDXN(getSchemaDXN(schema)));
158
+ core.setType(EncodedReference.fromURI(getSchemaURI(schema)));
145
159
  const newHandle = this._repo.create({
146
160
  version: SpaceDocVersion.CURRENT,
147
161
  access: {
@@ -164,7 +178,9 @@ var MigrationBuilder = class {
164
178
  // src/migrations.ts
165
179
  import { Atom } from "@effect-atom/atom";
166
180
  import * as Registry from "@effect-atom/atom/Registry";
181
+ import * as Option from "effect/Option";
167
182
  import { SpaceState } from "@dxos/client/echo";
183
+ import { Annotation as Annotation2, Obj } from "@dxos/echo";
168
184
  import { invariant as invariant2 } from "@dxos/invariant";
169
185
  var __dxlog_file2 = "/__w/dxos/dxos/packages/sdk/migrations/src/migrations.ts";
170
186
  var Migrations = class {
@@ -174,6 +190,9 @@ var Migrations = class {
174
190
  static _stateAtom = Atom.make({
175
191
  running: []
176
192
  }).pipe(Atom.keepAlive);
193
+ /**
194
+ * @deprecated Use `MigrationVersionAnnotation` via `Annotation.get/set` on space properties.
195
+ */
177
196
  static get versionProperty() {
178
197
  return this.namespace && `${this.namespace}.version`;
179
198
  }
@@ -189,10 +208,9 @@ var Migrations = class {
189
208
  this.migrations = migrations;
190
209
  }
191
210
  static async migrate(space, targetVersion) {
192
- invariant2(!this.running(space), "Migration already running", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 31, S: this, A: ["!this.running(space)", "'Migration already running'"] });
193
- invariant2(this.versionProperty, "Migrations namespace not set", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 32, S: this, A: ["this.versionProperty", "'Migrations namespace not set'"] });
194
- invariant2(space.state.get() === SpaceState.SPACE_READY, "Space not ready", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 33, S: this, A: ["space.state.get() === SpaceState.SPACE_READY", "'Space not ready'"] });
195
- const currentVersion = space.properties[this.versionProperty];
211
+ invariant2(!this.running(space), "Migration already running", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 36, S: this, A: ["!this.running(space)", "'Migration already running'"] });
212
+ invariant2(space.state.get() === SpaceState.SPACE_READY, "Space not ready", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 37, S: this, A: ["space.state.get() === SpaceState.SPACE_READY", "'Space not ready'"] });
213
+ const currentVersion = Annotation2.get(space.properties, MigrationVersionAnnotation).pipe(Option.getOrUndefined);
196
214
  const currentIndex = this.migrations.findIndex((m) => m.version === currentVersion) + 1;
197
215
  const i = this.migrations.findIndex((m) => m.version === targetVersion);
198
216
  const targetIndex = i === -1 ? this.migrations.length : i + 1;
@@ -207,30 +225,33 @@ var Migrations = class {
207
225
  spaceKey
208
226
  ]
209
227
  });
210
- if (targetIndex > currentIndex) {
211
- const migrations = this.migrations.slice(currentIndex, targetIndex);
212
- for (const migration of migrations) {
213
- const builder = new MigrationBuilder(space);
214
- await migration.next({
215
- space,
216
- builder
217
- });
218
- await builder.changeProperties((propertiesStructure) => {
219
- invariant2(this.versionProperty, "Migrations namespace not set", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 58, S: this, A: ["this.versionProperty", "'Migrations namespace not set'"] });
220
- propertiesStructure.data[this.versionProperty] = migration.version;
221
- });
222
- await builder._commit();
228
+ try {
229
+ if (targetIndex > currentIndex) {
230
+ const migrations = this.migrations.slice(currentIndex, targetIndex);
231
+ for (const migration of migrations) {
232
+ const builder = new MigrationBuilder(space);
233
+ await migration.next({
234
+ space,
235
+ builder
236
+ });
237
+ await builder._commit();
238
+ Obj.update(space.properties, (properties) => {
239
+ Annotation2.set(properties, MigrationVersionAnnotation, migration.version);
240
+ });
241
+ }
223
242
  }
243
+ } finally {
244
+ const finalState = this._registry.get(this._stateAtom);
245
+ this._registry.set(this._stateAtom, {
246
+ running: finalState.running.filter((key) => key !== spaceKey)
247
+ });
224
248
  }
225
- const finalState = this._registry.get(this._stateAtom);
226
- this._registry.set(this._stateAtom, {
227
- running: finalState.running.filter((key) => key !== spaceKey)
228
- });
229
249
  return true;
230
250
  }
231
251
  };
232
252
  export {
233
253
  MigrationBuilder,
254
+ MigrationVersionAnnotation,
234
255
  Migrations
235
256
  };
236
257
  //# sourceMappingURL=index.mjs.map