@highstate/backend 0.17.0 → 0.19.1

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.
Files changed (89) hide show
  1. package/dist/{chunk-JT4KWE3B.js → chunk-V2NILDHS.js} +3 -2
  2. package/dist/chunk-V2NILDHS.js.map +1 -0
  3. package/dist/highstate.manifest.json +3 -4
  4. package/dist/index.js +190 -280
  5. package/dist/index.js.map +1 -1
  6. package/dist/shared/index.js +1 -1
  7. package/package.json +9 -10
  8. package/prisma/backend/postgresql/main.prisma +0 -2
  9. package/prisma/backend/sqlite/main.prisma +0 -2
  10. package/prisma/project/main.prisma +0 -1
  11. package/src/business/project.ts +1 -2
  12. package/src/database/_generated/backend/postgresql/browser.ts +54 -0
  13. package/src/database/_generated/backend/postgresql/client.ts +7 -8
  14. package/src/database/_generated/backend/postgresql/commonInputTypes.ts +3 -2
  15. package/src/database/_generated/backend/postgresql/enums.ts +3 -1
  16. package/src/database/_generated/backend/postgresql/internal/class.ts +24 -71
  17. package/src/database/_generated/backend/postgresql/internal/prismaNamespace.ts +41 -43
  18. package/src/database/_generated/backend/postgresql/internal/prismaNamespaceBrowser.ts +191 -0
  19. package/src/database/_generated/backend/postgresql/models/BackendUnlockMethod.ts +12 -11
  20. package/src/database/_generated/backend/postgresql/models/Library.ts +29 -28
  21. package/src/database/_generated/backend/postgresql/models/Project.ts +69 -68
  22. package/src/database/_generated/backend/postgresql/models/ProjectModelStorage.ts +29 -28
  23. package/src/database/_generated/backend/postgresql/models/ProjectSpace.ts +26 -25
  24. package/src/database/_generated/backend/postgresql/models/PulumiBackend.ts +29 -28
  25. package/src/database/_generated/backend/postgresql/models/UserWorkspaceLayout.ts +12 -11
  26. package/src/database/_generated/backend/postgresql/models.ts +2 -1
  27. package/src/database/_generated/backend/postgresql/pjtg.ts +1 -0
  28. package/src/database/_generated/backend/sqlite/browser.ts +54 -0
  29. package/src/database/_generated/backend/sqlite/client.ts +7 -8
  30. package/src/database/_generated/backend/sqlite/commonInputTypes.ts +3 -2
  31. package/src/database/_generated/backend/sqlite/enums.ts +3 -1
  32. package/src/database/_generated/backend/sqlite/internal/class.ts +24 -71
  33. package/src/database/_generated/backend/sqlite/internal/prismaNamespace.ts +41 -43
  34. package/src/database/_generated/backend/sqlite/internal/prismaNamespaceBrowser.ts +188 -0
  35. package/src/database/_generated/backend/sqlite/models/BackendUnlockMethod.ts +12 -11
  36. package/src/database/_generated/backend/sqlite/models/Library.ts +29 -28
  37. package/src/database/_generated/backend/sqlite/models/Project.ts +69 -68
  38. package/src/database/_generated/backend/sqlite/models/ProjectModelStorage.ts +29 -28
  39. package/src/database/_generated/backend/sqlite/models/ProjectSpace.ts +26 -25
  40. package/src/database/_generated/backend/sqlite/models/PulumiBackend.ts +29 -28
  41. package/src/database/_generated/backend/sqlite/models/UserWorkspaceLayout.ts +12 -11
  42. package/src/database/_generated/backend/sqlite/models.ts +2 -1
  43. package/src/database/_generated/backend/sqlite/pjtg.ts +1 -0
  44. package/src/database/_generated/project/browser.ts +1 -0
  45. package/src/database/_generated/project/client.ts +4 -5
  46. package/src/database/_generated/project/commonInputTypes.ts +1 -0
  47. package/src/database/_generated/project/enums.ts +1 -0
  48. package/src/database/_generated/project/internal/class.ts +20 -62
  49. package/src/database/_generated/project/internal/prismaNamespace.ts +40 -36
  50. package/src/database/_generated/project/internal/prismaNamespaceBrowser.ts +9 -6
  51. package/src/database/_generated/project/models/ApiKey.ts +1 -0
  52. package/src/database/_generated/project/models/Artifact.ts +1 -0
  53. package/src/database/_generated/project/models/HubModel.ts +1 -0
  54. package/src/database/_generated/project/models/InstanceCustomStatus.ts +1 -0
  55. package/src/database/_generated/project/models/InstanceEvaluationState.ts +1 -0
  56. package/src/database/_generated/project/models/InstanceLock.ts +1 -0
  57. package/src/database/_generated/project/models/InstanceModel.ts +1 -0
  58. package/src/database/_generated/project/models/InstanceOperationState.ts +1 -0
  59. package/src/database/_generated/project/models/InstanceState.ts +1 -0
  60. package/src/database/_generated/project/models/Operation.ts +1 -0
  61. package/src/database/_generated/project/models/OperationLog.ts +1 -0
  62. package/src/database/_generated/project/models/Page.ts +1 -0
  63. package/src/database/_generated/project/models/Secret.ts +1 -0
  64. package/src/database/_generated/project/models/ServiceAccount.ts +1 -0
  65. package/src/database/_generated/project/models/Terminal.ts +1 -0
  66. package/src/database/_generated/project/models/TerminalSession.ts +1 -0
  67. package/src/database/_generated/project/models/TerminalSessionLog.ts +1 -0
  68. package/src/database/_generated/project/models/Trigger.ts +1 -0
  69. package/src/database/_generated/project/models/UnlockMethod.ts +1 -0
  70. package/src/database/_generated/project/models/UserCompositeViewport.ts +1 -0
  71. package/src/database/_generated/project/models/UserProjectViewport.ts +1 -0
  72. package/src/database/_generated/project/models/Worker.ts +1 -0
  73. package/src/database/_generated/project/models/WorkerUnitRegistration.ts +1 -0
  74. package/src/database/_generated/project/models/WorkerVersion.ts +1 -0
  75. package/src/database/_generated/project/models/WorkerVersionLog.ts +1 -0
  76. package/src/database/_generated/project/models.ts +1 -0
  77. package/src/database/abstractions.ts +1 -7
  78. package/src/database/index.ts +1 -0
  79. package/src/database/local/backend.ts +19 -30
  80. package/src/database/local/project.ts +4 -9
  81. package/src/database/manager.ts +28 -34
  82. package/src/database/migration.ts +126 -0
  83. package/src/shared/resolvers/input.ts +2 -0
  84. package/src/test-utils/database.ts +28 -14
  85. package/dist/chunk-JT4KWE3B.js.map +0 -1
  86. package/dist/database/local/prisma.config.js +0 -26
  87. package/dist/database/local/prisma.config.js.map +0 -1
  88. package/src/database/local/prisma.config.ts +0 -25
  89. package/src/database/migrate.ts +0 -35
@@ -1,6 +1,7 @@
1
1
 
2
2
  /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
3
  /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
4
5
  // @ts-nocheck
5
6
  /*
6
7
  * WARNING: This is an internal file that is subject to change!
@@ -23,28 +24,30 @@ export const Decimal = runtime.Decimal
23
24
 
24
25
 
25
26
  export const NullTypes = {
26
- DbNull: runtime.objectEnumValues.classes.DbNull as (new (secret: never) => typeof runtime.objectEnumValues.instances.DbNull),
27
- JsonNull: runtime.objectEnumValues.classes.JsonNull as (new (secret: never) => typeof runtime.objectEnumValues.instances.JsonNull),
28
- AnyNull: runtime.objectEnumValues.classes.AnyNull as (new (secret: never) => typeof runtime.objectEnumValues.instances.AnyNull),
27
+ DbNull: runtime.NullTypes.DbNull as (new (secret: never) => typeof runtime.DbNull),
28
+ JsonNull: runtime.NullTypes.JsonNull as (new (secret: never) => typeof runtime.JsonNull),
29
+ AnyNull: runtime.NullTypes.AnyNull as (new (secret: never) => typeof runtime.AnyNull),
29
30
  }
30
31
  /**
31
32
  * Helper for filtering JSON entries that have `null` on the database (empty on the db)
32
33
  *
33
34
  * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
34
35
  */
35
- export const DbNull = runtime.objectEnumValues.instances.DbNull
36
+ export const DbNull = runtime.DbNull
37
+
36
38
  /**
37
39
  * Helper for filtering JSON entries that have JSON `null` values (not empty on the db)
38
40
  *
39
41
  * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
40
42
  */
41
- export const JsonNull = runtime.objectEnumValues.instances.JsonNull
43
+ export const JsonNull = runtime.JsonNull
44
+
42
45
  /**
43
46
  * Helper for filtering JSON entries that are `Prisma.DbNull` or `Prisma.JsonNull`
44
47
  *
45
48
  * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
46
49
  */
47
- export const AnyNull = runtime.objectEnumValues.instances.AnyNull
50
+ export const AnyNull = runtime.AnyNull
48
51
 
49
52
 
50
53
  export const ModelName = {
@@ -1,6 +1,7 @@
1
1
 
2
2
  /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
3
  /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
4
5
  // @ts-nocheck
5
6
  /*
6
7
  * This file exports the `ApiKey` model and its related types.
@@ -1,6 +1,7 @@
1
1
 
2
2
  /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
3
  /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
4
5
  // @ts-nocheck
5
6
  /*
6
7
  * This file exports the `Artifact` model and its related types.
@@ -1,6 +1,7 @@
1
1
 
2
2
  /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
3
  /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
4
5
  // @ts-nocheck
5
6
  /*
6
7
  * This file exports the `HubModel` model and its related types.
@@ -1,6 +1,7 @@
1
1
 
2
2
  /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
3
  /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
4
5
  // @ts-nocheck
5
6
  /*
6
7
  * This file exports the `InstanceCustomStatus` model and its related types.
@@ -1,6 +1,7 @@
1
1
 
2
2
  /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
3
  /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
4
5
  // @ts-nocheck
5
6
  /*
6
7
  * This file exports the `InstanceEvaluationState` model and its related types.
@@ -1,6 +1,7 @@
1
1
 
2
2
  /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
3
  /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
4
5
  // @ts-nocheck
5
6
  /*
6
7
  * This file exports the `InstanceLock` model and its related types.
@@ -1,6 +1,7 @@
1
1
 
2
2
  /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
3
  /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
4
5
  // @ts-nocheck
5
6
  /*
6
7
  * This file exports the `InstanceModel` model and its related types.
@@ -1,6 +1,7 @@
1
1
 
2
2
  /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
3
  /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
4
5
  // @ts-nocheck
5
6
  /*
6
7
  * This file exports the `InstanceOperationState` model and its related types.
@@ -1,6 +1,7 @@
1
1
 
2
2
  /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
3
  /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
4
5
  // @ts-nocheck
5
6
  /*
6
7
  * This file exports the `InstanceState` model and its related types.
@@ -1,6 +1,7 @@
1
1
 
2
2
  /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
3
  /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
4
5
  // @ts-nocheck
5
6
  /*
6
7
  * This file exports the `Operation` model and its related types.
@@ -1,6 +1,7 @@
1
1
 
2
2
  /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
3
  /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
4
5
  // @ts-nocheck
5
6
  /*
6
7
  * This file exports the `OperationLog` model and its related types.
@@ -1,6 +1,7 @@
1
1
 
2
2
  /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
3
  /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
4
5
  // @ts-nocheck
5
6
  /*
6
7
  * This file exports the `Page` model and its related types.
@@ -1,6 +1,7 @@
1
1
 
2
2
  /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
3
  /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
4
5
  // @ts-nocheck
5
6
  /*
6
7
  * This file exports the `Secret` model and its related types.
@@ -1,6 +1,7 @@
1
1
 
2
2
  /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
3
  /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
4
5
  // @ts-nocheck
5
6
  /*
6
7
  * This file exports the `ServiceAccount` model and its related types.
@@ -1,6 +1,7 @@
1
1
 
2
2
  /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
3
  /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
4
5
  // @ts-nocheck
5
6
  /*
6
7
  * This file exports the `Terminal` model and its related types.
@@ -1,6 +1,7 @@
1
1
 
2
2
  /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
3
  /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
4
5
  // @ts-nocheck
5
6
  /*
6
7
  * This file exports the `TerminalSession` model and its related types.
@@ -1,6 +1,7 @@
1
1
 
2
2
  /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
3
  /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
4
5
  // @ts-nocheck
5
6
  /*
6
7
  * This file exports the `TerminalSessionLog` model and its related types.
@@ -1,6 +1,7 @@
1
1
 
2
2
  /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
3
  /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
4
5
  // @ts-nocheck
5
6
  /*
6
7
  * This file exports the `Trigger` model and its related types.
@@ -1,6 +1,7 @@
1
1
 
2
2
  /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
3
  /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
4
5
  // @ts-nocheck
5
6
  /*
6
7
  * This file exports the `UnlockMethod` model and its related types.
@@ -1,6 +1,7 @@
1
1
 
2
2
  /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
3
  /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
4
5
  // @ts-nocheck
5
6
  /*
6
7
  * This file exports the `UserCompositeViewport` model and its related types.
@@ -1,6 +1,7 @@
1
1
 
2
2
  /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
3
  /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
4
5
  // @ts-nocheck
5
6
  /*
6
7
  * This file exports the `UserProjectViewport` model and its related types.
@@ -1,6 +1,7 @@
1
1
 
2
2
  /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
3
  /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
4
5
  // @ts-nocheck
5
6
  /*
6
7
  * This file exports the `Worker` model and its related types.
@@ -1,6 +1,7 @@
1
1
 
2
2
  /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
3
  /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
4
5
  // @ts-nocheck
5
6
  /*
6
7
  * This file exports the `WorkerUnitRegistration` model and its related types.
@@ -1,6 +1,7 @@
1
1
 
2
2
  /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
3
  /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
4
5
  // @ts-nocheck
5
6
  /*
6
7
  * This file exports the `WorkerVersion` model and its related types.
@@ -1,6 +1,7 @@
1
1
 
2
2
  /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
3
  /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
4
5
  // @ts-nocheck
5
6
  /*
6
7
  * This file exports the `WorkerVersionLog` model and its related types.
@@ -1,6 +1,7 @@
1
1
 
2
2
  /* !!! This is code generated by Prisma. Do not edit directly. !!! */
3
3
  /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
4
5
  // @ts-nocheck
5
6
  /*
6
7
  * This is a barrel export file for all models and their related types.
@@ -31,11 +31,5 @@ export interface ProjectDatabaseBackend {
31
31
  * @param projectId The ID of the project to open the database for.
32
32
  * @param masterKey The master key to decrypt the project database. If not provided, the encryption is assumed to be disabled.
33
33
  */
34
- openProjectDatabase(
35
- projectId: string,
36
- masterKey?: string,
37
- ): Promise<[database: ProjectDatabase, url: string]>
34
+ openProjectDatabase(projectId: string, masterKey?: string): Promise<ProjectDatabase>
38
35
  }
39
-
40
- export const backendDatabaseVersion = 1
41
- export const projectDatabaseVersion = 2
@@ -2,5 +2,6 @@ export * from "./abstractions"
2
2
  export * from "./factory"
3
3
  export { getOrCreateBackendIdentity } from "./local"
4
4
  export * from "./manager"
5
+ export * from "./migration"
5
6
  export * from "./prisma"
6
7
  export * from "./well-known"
@@ -1,14 +1,14 @@
1
1
  import type { Logger } from "pino"
2
+ import type { BackendDatabaseBackend } from "../abstractions"
2
3
  import type { BackendDatabase } from "../prisma"
3
4
  import { randomBytes } from "node:crypto"
4
5
  import { hostname } from "node:os"
5
- import { PrismaLibSQL } from "@prisma/adapter-libsql"
6
+ import { PrismaLibSql } from "@prisma/adapter-libsql"
6
7
  import { armor, Decrypter, Encrypter, identityToRecipient } from "age-encryption"
7
8
  import { z } from "zod"
8
9
  import { codebaseConfig, getCodebaseHighstatePath } from "../../common"
9
10
  import { PrismaClient } from "../_generated/backend/sqlite/client"
10
- import { type BackendDatabaseBackend, backendDatabaseVersion } from "../abstractions"
11
- import { migrateDatabase } from "../migrate"
11
+ import { migrateDatabase, migrationPacks } from "../migration"
12
12
  import { ensureWellKnownEntitiesCreated } from "../well-known"
13
13
  import {
14
14
  type BackendIdentityConfig,
@@ -94,7 +94,6 @@ async function createMasterKey(config: BackendIdentityConfig, logger: Logger) {
94
94
  }
95
95
 
96
96
  type DatabaseInitializationResult = {
97
- shouldMigrate: boolean
98
97
  masterKey?: string
99
98
  metaFile: DatabaseMetaFile
100
99
  created: boolean
@@ -115,12 +114,11 @@ async function ensureDatabaseInitialized(
115
114
  const masterKey = encryptionEnabled ? await createMasterKey(config, logger) : undefined
116
115
 
117
116
  const metaFile: DatabaseMetaFile = {
118
- version: backendDatabaseVersion,
117
+ version: 0,
119
118
  masterKey: masterKey?.armoredMasterKey,
120
119
  }
121
120
 
122
121
  return {
123
- shouldMigrate: true,
124
122
  masterKey: masterKey?.masterKey,
125
123
  metaFile,
126
124
  created: true,
@@ -128,15 +126,8 @@ async function ensureDatabaseInitialized(
128
126
  }
129
127
  }
130
128
 
131
- if (meta.version > backendDatabaseVersion) {
132
- throw new Error(
133
- `Database version (${meta.version}) is newer than expected (${backendDatabaseVersion}). You likely need to update the Highstate.`,
134
- )
135
- }
136
-
137
129
  if (!encryptionEnabled) {
138
130
  return {
139
- shouldMigrate: meta.version < backendDatabaseVersion,
140
131
  masterKey: undefined,
141
132
  metaFile: meta,
142
133
  created: false,
@@ -158,7 +149,6 @@ async function ensureDatabaseInitialized(
158
149
  const masterKey = await decrypter.decrypt(encryptedMasterKey, "text")
159
150
 
160
151
  return {
161
- shouldMigrate: meta.version < backendDatabaseVersion,
162
152
  masterKey,
163
153
  metaFile: meta,
164
154
  created: false,
@@ -183,23 +173,16 @@ export async function createLocalBackendDatabaseBackend(
183
173
  let databasePath = config.HIGHSTATE_BACKEND_DATABASE_LOCAL_PATH
184
174
  databasePath ??= await getCodebaseHighstatePath(config, logger)
185
175
 
186
- const { shouldMigrate, masterKey, metaFile, created, initialRecipient } =
187
- await ensureDatabaseInitialized(
188
- databasePath,
189
- config.HIGHSTATE_ENCRYPTION_ENABLED,
190
- config,
191
- logger,
192
- )
176
+ const { masterKey, metaFile, created, initialRecipient } = await ensureDatabaseInitialized(
177
+ databasePath,
178
+ config.HIGHSTATE_ENCRYPTION_ENABLED,
179
+ config,
180
+ logger,
181
+ )
193
182
 
194
183
  const databaseUrl = `file:${databasePath}/backend.db`
195
184
 
196
- if (shouldMigrate) {
197
- await migrateDatabase(databaseUrl, "backend/sqlite", masterKey, logger)
198
-
199
- await writeMetaFile(databasePath, { ...metaFile, version: backendDatabaseVersion })
200
- }
201
-
202
- const adapter = new PrismaLibSQL({
185
+ const adapter = new PrismaLibSql({
203
186
  url: databaseUrl,
204
187
  encryptionKey: masterKey,
205
188
  })
@@ -208,6 +191,14 @@ export async function createLocalBackendDatabaseBackend(
208
191
  adapter,
209
192
  })
210
193
 
194
+ await migrateDatabase(
195
+ prismaClient,
196
+ migrationPacks["backend/sqlite"],
197
+ metaFile.version,
198
+ async version => await writeMetaFile(databasePath, { ...metaFile, version }),
199
+ logger,
200
+ )
201
+
211
202
  const database = prismaClient as BackendDatabase
212
203
 
213
204
  await ensureWellKnownEntitiesCreated(database)
@@ -216,8 +207,6 @@ export async function createLocalBackendDatabaseBackend(
216
207
 
217
208
  await ensureInitialUnlockMethod(database, created, initialRecipient, backendLogger)
218
209
 
219
- backendLogger.info("database is ready")
220
-
221
210
  return new LocalBackendDatabaseBackend(
222
211
  database,
223
212
  databasePath,
@@ -2,30 +2,25 @@ import type { Logger } from "pino"
2
2
  import type { z } from "zod"
3
3
  import type { ProjectDatabaseBackend } from "../abstractions"
4
4
  import { mkdir } from "node:fs/promises"
5
- import { PrismaLibSQL } from "@prisma/adapter-libsql"
5
+ import { PrismaLibSql } from "@prisma/adapter-libsql"
6
6
  import { type codebaseConfig, getCodebaseHighstatePath } from "../../common"
7
7
  import { ProjectDatabase } from "../prisma"
8
8
 
9
9
  export class LocalProjectDatabaseBackend implements ProjectDatabaseBackend {
10
10
  constructor(private readonly highstatePath: string) {}
11
11
 
12
- async openProjectDatabase(
13
- projectId: string,
14
- masterKey?: string,
15
- ): Promise<[database: ProjectDatabase, url: string]> {
12
+ async openProjectDatabase(projectId: string, masterKey?: string): Promise<ProjectDatabase> {
16
13
  const databasePath = `${this.highstatePath}/projects/${projectId}`
17
14
  await mkdir(databasePath, { recursive: true })
18
15
 
19
16
  const databaseUrl = `file:${databasePath}/project.db`
20
17
 
21
- const adapter = new PrismaLibSQL({
18
+ const adapter = new PrismaLibSql({
22
19
  url: databaseUrl,
23
20
  encryptionKey: masterKey,
24
21
  })
25
22
 
26
- const database = new ProjectDatabase({ adapter })
27
-
28
- return [database, databaseUrl]
23
+ return new ProjectDatabase({ adapter })
29
24
  }
30
25
 
31
26
  static async create(
@@ -1,16 +1,12 @@
1
1
  import type { Logger } from "pino"
2
2
  import type { ProjectUnlockBackend } from "../unlock"
3
+ import type { BackendDatabaseBackend, ProjectDatabaseBackend } from "./abstractions"
3
4
  import type { BackendDatabase, ProjectDatabase } from "./prisma"
4
5
  import { LRUCache } from "lru-cache"
5
6
  import z from "zod"
6
7
  import { createProjectLogger } from "../common"
7
- import { BackendError, ProjectLockedError, ProjectNotFoundError } from "../shared"
8
- import {
9
- type BackendDatabaseBackend,
10
- type ProjectDatabaseBackend,
11
- projectDatabaseVersion,
12
- } from "./abstractions"
13
- import { migrateDatabase } from "./migrate"
8
+ import { ProjectLockedError, ProjectNotFoundError } from "../shared"
9
+ import { migrateDatabase, migrationPacks } from "./migration"
14
10
 
15
11
  export const databaseManagerConfig = z.object({
16
12
  HIGHSTATE_ENCRYPTION_ENABLED: z.stringbool().default(true),
@@ -132,13 +128,16 @@ export class DatabaseManagerImpl implements DatabaseManager {
132
128
  const masterKey = await this.getProjectMasterKey(projectId)
133
129
  const hexMasterKey = masterKey?.toString("hex")
134
130
 
135
- const [database, databaseUrl] = await this.projectDatabaseBackend.openProjectDatabase(
136
- projectId,
137
- hexMasterKey,
138
- )
131
+ const database = await this.projectDatabaseBackend.openProjectDatabase(projectId, hexMasterKey)
139
132
 
140
133
  // can safely apply migrations here, because no one knows about the database yet
141
- await migrateDatabase(databaseUrl, "project", hexMasterKey, logger)
134
+ await migrateDatabase(
135
+ database,
136
+ migrationPacks.project,
137
+ 0, // current version
138
+ () => Promise.resolve(), // project will be created later
139
+ logger,
140
+ )
142
141
 
143
142
  this.projectDatabases.set(projectId, database)
144
143
 
@@ -151,50 +150,45 @@ export class DatabaseManagerImpl implements DatabaseManager {
151
150
  return cachedDatabase
152
151
  }
153
152
 
153
+ const logger = createProjectLogger(this.logger, projectId)
154
154
  const masterKey = await this.getProjectMasterKey(projectId)
155
155
  const hexMasterKey = masterKey?.toString("hex")
156
156
 
157
157
  // TODO: is it really necessary to migrate the database inside the transaction?
158
158
  let database = await this.backend.$transaction(async tx => {
159
- const databaseEntity = await tx.project.findUnique({
159
+ const project = await tx.project.findUnique({
160
160
  where: { id: projectId },
161
161
  select: { databaseVersion: true },
162
162
  })
163
163
 
164
- if (!databaseEntity) {
164
+ if (!project) {
165
165
  throw new ProjectNotFoundError(projectId)
166
166
  }
167
167
 
168
- if (databaseEntity.databaseVersion > projectDatabaseVersion) {
169
- throw new BackendError(
170
- `Project database version (${databaseEntity.databaseVersion}) is newer than expected (${projectDatabaseVersion}).`,
171
- )
172
- }
173
-
174
- if (databaseEntity.databaseVersion === projectDatabaseVersion) {
175
- return
176
- }
177
-
178
- const [database, databaseUrl] = await this.projectDatabaseBackend.openProjectDatabase(
168
+ const database = await this.projectDatabaseBackend.openProjectDatabase(
179
169
  projectId,
180
170
  hexMasterKey,
181
171
  )
182
172
 
183
- if (databaseEntity.databaseVersion < projectDatabaseVersion) {
184
- await migrateDatabase(databaseUrl, "project", hexMasterKey, this.logger)
185
- }
186
-
187
- await tx.project.update({
188
- where: { id: projectId },
189
- data: { databaseVersion: projectDatabaseVersion },
190
- })
173
+ await migrateDatabase(
174
+ database,
175
+ migrationPacks.project,
176
+ project.databaseVersion,
177
+ async version => {
178
+ await tx.project.update({
179
+ where: { id: projectId },
180
+ data: { databaseVersion: version },
181
+ })
182
+ },
183
+ logger,
184
+ )
191
185
 
192
186
  return database
193
187
  })
194
188
 
195
189
  if (!database) {
196
190
  // open database if was not migrated in the transaction
197
- const [_database] = await this.projectDatabaseBackend.openProjectDatabase(
191
+ const _database = await this.projectDatabaseBackend.openProjectDatabase(
198
192
  projectId,
199
193
  hexMasterKey,
200
194
  )