@hot-updater/server 0.36.7 → 1.0.0-rc.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/adapters/databaseConstraintErrors.cjs +23 -0
- package/dist/adapters/databaseConstraintErrors.mjs +21 -0
- package/dist/adapters/databasePluginUtils.cjs +117 -0
- package/dist/adapters/databasePluginUtils.mjs +106 -0
- package/dist/adapters/drizzle.cjs +53 -176
- package/dist/adapters/drizzle.d.cts +6 -4
- package/dist/adapters/drizzle.d.mts +6 -4
- package/dist/adapters/drizzle.mjs +54 -177
- package/dist/adapters/drizzleCrud.cjs +250 -0
- package/dist/adapters/drizzleCrud.mjs +249 -0
- package/dist/adapters/drizzleLazyDB.cjs +84 -36
- package/dist/adapters/drizzleLazyDB.mjs +84 -36
- package/dist/adapters/drizzleQuery.cjs +68 -0
- package/dist/adapters/drizzleQuery.mjs +67 -0
- package/dist/adapters/kysely.cjs +18 -138
- package/dist/adapters/kysely.d.cts +3 -12
- package/dist/adapters/kysely.d.mts +3 -12
- package/dist/adapters/kysely.mjs +19 -139
- package/dist/adapters/kyselyCrud.cjs +254 -0
- package/dist/adapters/kyselyCrud.mjs +253 -0
- package/dist/adapters/kyselyQuery.cjs +56 -0
- package/dist/adapters/kyselyQuery.mjs +55 -0
- package/dist/adapters/mongodb.cjs +21 -174
- package/dist/adapters/mongodb.d.cts +3 -2
- package/dist/adapters/mongodb.d.mts +3 -2
- package/dist/adapters/mongodb.mjs +21 -174
- package/dist/adapters/mongodbCollections.cjs +36 -0
- package/dist/adapters/mongodbCollections.mjs +30 -0
- package/dist/adapters/mongodbQuery.cjs +77 -0
- package/dist/adapters/mongodbQuery.mjs +70 -0
- package/dist/adapters/mongodbReads.cjs +148 -0
- package/dist/adapters/mongodbReads.mjs +147 -0
- package/dist/adapters/mongodbWrites.cjs +134 -0
- package/dist/adapters/mongodbWrites.mjs +133 -0
- package/dist/adapters/prisma.cjs +205 -180
- package/dist/adapters/prisma.d.cts +3 -3
- package/dist/adapters/prisma.d.mts +3 -3
- package/dist/adapters/prisma.mjs +206 -181
- package/dist/adapters/prismaQuery.cjs +58 -0
- package/dist/adapters/prismaQuery.mjs +56 -0
- package/dist/adapters/prismaRows.cjs +198 -0
- package/dist/adapters/prismaRows.mjs +188 -0
- package/dist/analytics/bounded/activeOverview.cjs +87 -0
- package/dist/analytics/bounded/activeOverview.mjs +85 -0
- package/dist/analytics/bounded/installationSearch.cjs +42 -0
- package/dist/analytics/bounded/installationSearch.mjs +42 -0
- package/dist/analytics/bounded/persistence.cjs +39 -0
- package/dist/analytics/bounded/persistence.mjs +38 -0
- package/dist/analytics/bounded/provider.cjs +170 -0
- package/dist/analytics/bounded/provider.d.cts +7 -0
- package/dist/analytics/bounded/provider.d.mts +7 -0
- package/dist/analytics/bounded/provider.mjs +170 -0
- package/dist/analytics/bounded/scan.cjs +144 -0
- package/dist/analytics/bounded/scan.mjs +138 -0
- package/dist/analytics/domain.d.cts +121 -0
- package/dist/analytics/domain.d.mts +121 -0
- package/dist/analytics/errors.cjs +22 -0
- package/dist/analytics/errors.mjs +20 -0
- package/dist/analytics/eventInput.cjs +111 -0
- package/dist/analytics/eventInput.mjs +111 -0
- package/dist/analytics/persistence.d.cts +6 -0
- package/dist/analytics/persistence.d.mts +6 -0
- package/dist/analytics/queryInput.cjs +58 -0
- package/dist/analytics/queryInput.mjs +55 -0
- package/dist/analytics/routes.cjs +63 -0
- package/dist/analytics/routes.mjs +61 -0
- package/dist/analytics/types.d.cts +17 -0
- package/dist/analytics/types.d.mts +17 -0
- package/dist/apiKeys.cjs +139 -0
- package/dist/apiKeys.d.cts +50 -0
- package/dist/apiKeys.d.mts +50 -0
- package/dist/apiKeys.mjs +133 -0
- package/dist/createHotUpdaterCore.cjs +48 -26
- package/dist/createHotUpdaterCore.d.cts +49 -17
- package/dist/createHotUpdaterCore.d.mts +49 -17
- package/dist/createHotUpdaterCore.mjs +51 -29
- package/dist/db/createBundleDiff.cjs +45 -68
- package/dist/db/createBundleDiff.d.cts +3 -3
- package/dist/db/createBundleDiff.d.mts +3 -3
- package/dist/db/createBundleDiff.mjs +47 -68
- package/dist/db/databasePluginCore.cjs +138 -0
- package/dist/db/databasePluginCore.mjs +137 -0
- package/dist/db/fixedMigrator.cjs +36 -93
- package/dist/db/fixedMigrator.mjs +36 -93
- package/dist/db/fixedMigratorMongo.cjs +319 -0
- package/dist/db/fixedMigratorMongo.mjs +319 -0
- package/dist/db/fixedMigratorShared.cjs +23 -0
- package/dist/db/fixedMigratorShared.mjs +18 -0
- package/dist/db/mongoMigrationExecution.cjs +11 -0
- package/dist/db/mongoMigrationExecution.mjs +11 -0
- package/dist/db/releaseCatalog.cjs +66 -0
- package/dist/db/releaseCatalog.d.cts +17 -0
- package/dist/db/releaseCatalog.d.mts +17 -0
- package/dist/db/releaseCatalog.mjs +64 -0
- package/dist/db/schema/mongodb.cjs +14 -6
- package/dist/db/schema/mongodb.mjs +14 -6
- package/dist/db/schema/registry.cjs +0 -2
- package/dist/db/schema/registry.mjs +1 -2
- package/dist/db/schema/sql.cjs +31 -14
- package/dist/db/schema/sql.mjs +32 -13
- package/dist/db/schema/sqlOperations.cjs +4 -4
- package/dist/db/schema/sqlOperations.mjs +5 -5
- package/dist/db/schemaGenerators.cjs +52 -18
- package/dist/db/schemaGenerators.mjs +52 -18
- package/dist/db/schemaReadiness.cjs +4 -3
- package/dist/db/schemaReadiness.mjs +4 -3
- package/dist/db/sqlMigrationExecution.cjs +67 -0
- package/dist/db/sqlMigrationExecution.mjs +66 -0
- package/dist/db/types.cjs +2 -6
- package/dist/db/types.d.cts +60 -16
- package/dist/db/types.d.mts +60 -16
- package/dist/db/types.mjs +3 -6
- package/dist/db/updateArtifacts.cjs +114 -60
- package/dist/db/updateArtifacts.mjs +117 -62
- package/dist/handler.cjs +108 -282
- package/dist/handler.d.cts +3 -46
- package/dist/handler.d.mts +3 -46
- package/dist/handler.mjs +107 -281
- package/dist/handlerBundleRoutes.cjs +155 -0
- package/dist/handlerBundleRoutes.mjs +155 -0
- package/dist/handlerErrors.cjs +9 -0
- package/dist/handlerErrors.mjs +9 -0
- package/dist/handlerParameters.cjs +39 -0
- package/dist/handlerParameters.mjs +34 -0
- package/dist/handlerReleaseCatalogRoutes.cjs +111 -0
- package/dist/handlerReleaseCatalogRoutes.mjs +110 -0
- package/dist/handlerReleaseManagementRoutes.cjs +125 -0
- package/dist/handlerReleaseManagementRoutes.mjs +124 -0
- package/dist/handlerTypes.d.cts +63 -0
- package/dist/handlerTypes.d.mts +63 -0
- package/dist/handlerVersionRoutes.cjs +10 -0
- package/dist/handlerVersionRoutes.d.cts +4 -0
- package/dist/handlerVersionRoutes.d.mts +4 -0
- package/dist/handlerVersionRoutes.mjs +9 -0
- package/dist/index.cjs +10 -1
- package/dist/index.d.cts +9 -3
- package/dist/index.d.mts +9 -3
- package/dist/index.mjs +5 -2
- package/dist/node.cjs +19 -12
- package/dist/node.d.cts +15 -10
- package/dist/node.d.mts +15 -10
- package/dist/node.mjs +19 -13
- package/dist/package.cjs +1 -1
- package/dist/package.mjs +1 -1
- package/dist/schema/dsl.cjs +19 -2
- package/dist/schema/dsl.mjs +17 -3
- package/dist/schema/index.cjs +1 -8
- package/dist/schema/index.mjs +2 -8
- package/dist/schema/types.cjs +3 -1
- package/dist/schema/types.mjs +3 -2
- package/dist/schema/v1_0_0.cjs +364 -0
- package/dist/schema/v1_0_0.mjs +357 -0
- package/dist/storageAccess.cjs +69 -25
- package/dist/storageAccess.mjs +68 -25
- package/dist/types/index.d.cts +4 -3
- package/dist/types/index.d.mts +5 -4
- package/package.json +8 -7
- package/src/adapters/databaseConstraintErrors.ts +25 -0
- package/src/adapters/databasePluginTestDatabase.ts +106 -0
- package/src/adapters/databasePluginUtils.spec.ts +29 -0
- package/src/adapters/databasePluginUtils.ts +214 -0
- package/src/adapters/drizzle.spec.ts +208 -47
- package/src/adapters/drizzle.ts +106 -293
- package/src/adapters/drizzleCrud.ts +419 -0
- package/src/adapters/drizzleLazyDB.ts +206 -100
- package/src/adapters/drizzleQuery.ts +164 -0
- package/src/adapters/kysely.spec.ts +126 -88
- package/src/adapters/kysely.ts +76 -334
- package/src/adapters/kyselyCrud.ts +588 -0
- package/src/adapters/kyselyQuery.ts +128 -0
- package/src/adapters/mongodb.spec.ts +141 -0
- package/src/adapters/mongodb.ts +60 -288
- package/src/adapters/mongodbCollections.ts +62 -0
- package/src/adapters/mongodbQuery.ts +226 -0
- package/src/adapters/mongodbReads.ts +311 -0
- package/src/adapters/mongodbRows.spec.ts +64 -0
- package/src/adapters/mongodbRows.ts +118 -0
- package/src/adapters/mongodbTestClient.ts +342 -0
- package/src/adapters/mongodbTestFilter.ts +166 -0
- package/src/adapters/mongodbWrites.ts +260 -0
- package/src/adapters/prisma.spec.ts +196 -0
- package/src/adapters/prisma.ts +417 -292
- package/src/adapters/prismaQuery.ts +129 -0
- package/src/adapters/prismaRows.spec.ts +98 -0
- package/src/adapters/prismaRows.ts +301 -0
- package/src/adapters/prismaTestClient.ts +396 -0
- package/src/analytics/analytics.integration.spec.ts +144 -0
- package/src/analytics/bounded/activeOverview.spec.ts +189 -0
- package/src/analytics/bounded/activeOverview.ts +148 -0
- package/src/analytics/bounded/installationSearch.spec.ts +130 -0
- package/src/analytics/bounded/installationSearch.ts +69 -0
- package/src/analytics/bounded/persistence.ts +43 -0
- package/src/analytics/bounded/provider.spec.ts +219 -0
- package/src/analytics/bounded/provider.ts +229 -0
- package/src/analytics/bounded/scan.ts +235 -0
- package/src/analytics/domain.ts +139 -0
- package/src/analytics/errors.ts +18 -0
- package/src/analytics/eventInput.ts +168 -0
- package/src/analytics/persistence.ts +10 -0
- package/src/analytics/queryInput.ts +102 -0
- package/src/analytics/routes.ts +123 -0
- package/src/analytics/types.ts +44 -0
- package/src/apiKeys.integration.spec.ts +192 -0
- package/src/apiKeys.spec.ts +162 -0
- package/src/apiKeys.ts +220 -0
- package/src/createHotUpdaterCore.ts +164 -100
- package/src/db/bundleRows.spec.ts +164 -0
- package/src/db/bundleRows.ts +10 -140
- package/src/db/createBundleDiff.spec.ts +172 -127
- package/src/db/createBundleDiff.ts +91 -110
- package/src/db/databasePluginCore.spec.ts +62 -0
- package/src/db/databasePluginCore.testFixtures.ts +76 -0
- package/src/db/databasePluginCore.ts +185 -0
- package/src/db/databasePluginUpdateCheck.bench.ts +107 -0
- package/src/db/fixedMigrator.spec.ts +184 -42
- package/src/db/fixedMigrator.ts +64 -205
- package/src/db/fixedMigratorMongo.spec.ts +192 -0
- package/src/db/fixedMigratorMongo.ts +425 -0
- package/src/db/fixedMigratorShared.ts +36 -0
- package/src/db/hotUpdaterSchema.ts +0 -1
- package/src/db/index.spec.ts +333 -1025
- package/src/db/mongoMigrationExecution.ts +23 -0
- package/src/db/node-sqlite.d.ts +25 -0
- package/src/db/releaseCatalog.ts +148 -0
- package/src/db/schema/mongodb.ts +20 -6
- package/src/db/schema/sql.ts +52 -11
- package/src/db/schema/sqlOperations.ts +5 -4
- package/src/db/schemaGenerators.ts +107 -23
- package/src/db/schemaReadiness.ts +2 -1
- package/src/db/sqlMigrationExecution.spec.ts +65 -0
- package/src/db/sqlMigrationExecution.ts +108 -0
- package/src/db/types.spec.ts +55 -0
- package/src/db/types.ts +129 -65
- package/src/db/updateArtifacts.spec.ts +359 -0
- package/src/db/updateArtifacts.ts +290 -126
- package/src/handler-standalone.integration.spec.ts +401 -364
- package/src/handler.spec.ts +137 -582
- package/src/handler.testFixtures.ts +30 -0
- package/src/handler.ts +218 -616
- package/src/handlerAuth.integration.spec.ts +33 -0
- package/src/handlerBundleRoutes.ts +259 -0
- package/src/handlerErrors.ts +7 -0
- package/src/handlerManagement.spec.ts +262 -0
- package/src/handlerParameters.ts +105 -0
- package/src/handlerReleaseCatalogRoutes.ts +154 -0
- package/src/handlerReleaseManagementRoutes.ts +213 -0
- package/src/handlerTypes.ts +96 -0
- package/src/handlerVersionRoutes.ts +12 -0
- package/src/index.ts +22 -2
- package/src/node.spec.ts +79 -10
- package/src/node.ts +20 -17
- package/src/releaseCatalogRoutes.integration.spec.ts +238 -0
- package/src/runtime.spec.ts +126 -959
- package/src/runtime.testFixtures.ts +71 -0
- package/src/schema/dsl-all-versions.spec.ts +26 -17
- package/src/schema/dsl.ts +41 -2
- package/src/schema/index.ts +3 -9
- package/src/schema/types.ts +9 -3
- package/src/schema/v1_0_0.spec.ts +146 -0
- package/src/schema/v1_0_0.ts +465 -0
- package/src/storageAccess.spec.ts +127 -32
- package/src/storageAccess.ts +106 -55
- package/src/types/index.ts +2 -1
- package/dist/db/bundleRows.cjs +0 -82
- package/dist/db/bundleRows.d.cts +0 -33
- package/dist/db/bundleRows.d.mts +0 -33
- package/dist/db/bundleRows.mjs +0 -79
- package/dist/db/pluginCore.cjs +0 -242
- package/dist/db/pluginCore.mjs +0 -241
- package/dist/db/schema/sqlMigrations.cjs +0 -74
- package/dist/db/schema/sqlMigrations.mjs +0 -73
- package/dist/db/schemaEnhancements.cjs +0 -20
- package/dist/db/schemaEnhancements.mjs +0 -19
- package/dist/route.cjs +0 -7
- package/dist/route.mjs +0 -7
- package/dist/schema/v0_21_0.cjs +0 -38
- package/dist/schema/v0_21_0.mjs +0 -37
- package/dist/schema/v0_29_0.cjs +0 -45
- package/dist/schema/v0_29_0.mjs +0 -44
- package/dist/schema/v0_31_0.cjs +0 -82
- package/dist/schema/v0_31_0.mjs +0 -80
- package/src/db/pluginCore.spec.ts +0 -1095
- package/src/db/pluginCore.ts +0 -475
- package/src/db/pluginUpdateCheck.bench.ts +0 -254
- package/src/db/schema/sqlMigrations.ts +0 -219
- package/src/db/schemaEnhancements.ts +0 -55
- package/src/route.ts +0 -7
- package/src/schema/v0_21_0.ts +0 -52
- package/src/schema/v0_29_0.ts +0 -62
- package/src/schema/v0_31_0.spec.ts +0 -73
- package/src/schema/v0_31_0.ts +0 -120
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { Bundle } from "@hot-updater/core";
|
|
2
|
+
import type {
|
|
3
|
+
DatabasePlugin,
|
|
4
|
+
StoragePlugin,
|
|
5
|
+
StoragePluginWith,
|
|
6
|
+
} from "@hot-updater/plugin-core";
|
|
7
|
+
import { createStoragePlugin } from "@hot-updater/plugin-core";
|
|
8
|
+
|
|
9
|
+
import { createInMemoryDatabasePlugin } from "../../test-utils/test/inMemoryDatabasePlugin";
|
|
10
|
+
import type { DatabaseAdapterCapabilities, Migrator } from "./db/types";
|
|
11
|
+
|
|
12
|
+
export const runtimeBundle: Bundle = {
|
|
13
|
+
id: "00000000-0000-0000-0000-000000000001",
|
|
14
|
+
platform: "ios",
|
|
15
|
+
fileHash: "hash123",
|
|
16
|
+
gitCommitHash: null,
|
|
17
|
+
storageUri: "s3://test-bucket/bundles/bundle.zip",
|
|
18
|
+
archiveByteSize: 3_000_000_001,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const createRuntimeStorage = (
|
|
22
|
+
get: NonNullable<StoragePlugin["get"]> = async () => ({ response: null }),
|
|
23
|
+
getDownloadUrl?: StoragePlugin["getDownloadUrl"],
|
|
24
|
+
): StoragePluginWith<"get"> =>
|
|
25
|
+
createStoragePlugin({
|
|
26
|
+
name: "testStorage",
|
|
27
|
+
protocol: "s3",
|
|
28
|
+
get,
|
|
29
|
+
...(getDownloadUrl ? { getDownloadUrl } : {}),
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const createMigrator = (version: string | undefined): Migrator => ({
|
|
33
|
+
async getVersion() {
|
|
34
|
+
return version;
|
|
35
|
+
},
|
|
36
|
+
async getNameVariants() {
|
|
37
|
+
return {};
|
|
38
|
+
},
|
|
39
|
+
async next() {
|
|
40
|
+
return undefined;
|
|
41
|
+
},
|
|
42
|
+
async previous() {
|
|
43
|
+
return undefined;
|
|
44
|
+
},
|
|
45
|
+
async up() {
|
|
46
|
+
throw new Error("not implemented");
|
|
47
|
+
},
|
|
48
|
+
async down() {
|
|
49
|
+
throw new Error("not implemented");
|
|
50
|
+
},
|
|
51
|
+
async migrateTo() {
|
|
52
|
+
throw new Error("not implemented");
|
|
53
|
+
},
|
|
54
|
+
async migrateToLatest() {
|
|
55
|
+
throw new Error("not implemented");
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
export const createRuntimeDatabase = (): DatabasePlugin => ({
|
|
60
|
+
...createInMemoryDatabasePlugin(),
|
|
61
|
+
name: "testDatabase",
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
export const createSchemaManagedDatabase = (
|
|
65
|
+
adapterName: string,
|
|
66
|
+
version: string | undefined,
|
|
67
|
+
): DatabasePlugin & DatabaseAdapterCapabilities => ({
|
|
68
|
+
...createRuntimeDatabase(),
|
|
69
|
+
adapterName,
|
|
70
|
+
createMigrator: () => createMigrator(version),
|
|
71
|
+
});
|
|
@@ -1,26 +1,35 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
2
|
|
|
3
|
+
import { hotUpdaterSchemaVersions } from "./index";
|
|
3
4
|
import { createSettingsTable } from "./settings";
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
import {
|
|
6
|
+
bundlePatchesV100,
|
|
7
|
+
bundlesV100,
|
|
8
|
+
channelsV100,
|
|
9
|
+
releaseCatalogsV100,
|
|
10
|
+
releasesV100,
|
|
11
|
+
v1_0_0,
|
|
12
|
+
} from "./v1_0_0";
|
|
7
13
|
|
|
8
14
|
describe("versioned schema DSL", () => {
|
|
9
|
-
it("uses the local functional DSL for
|
|
10
|
-
expect(
|
|
11
|
-
expect(
|
|
12
|
-
expect(
|
|
15
|
+
it("uses the local functional DSL for the current schema", () => {
|
|
16
|
+
expect(v1_0_0.dsl).toBe("schema");
|
|
17
|
+
expect(channelsV100.dsl).toBe("table");
|
|
18
|
+
expect(bundlesV100.dsl).toBe("table");
|
|
19
|
+
expect(bundlePatchesV100.dsl).toBe("table");
|
|
20
|
+
expect(releasesV100.dsl).toBe("table");
|
|
21
|
+
expect(releaseCatalogsV100.dsl).toBe("table");
|
|
22
|
+
expect(createSettingsTable("1.0.0").dsl).toBe("table");
|
|
13
23
|
|
|
14
|
-
expect(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
expect(createSettingsTable("0.31.0").dsl).toBe("table");
|
|
18
|
-
|
|
19
|
-
for (const schema of [v0_21_0, v0_29_0, v0_31_0]) {
|
|
20
|
-
expect(Object.keys(schema)).not.toContain("dsl");
|
|
21
|
-
for (const table of schema.tables) {
|
|
22
|
-
expect(Object.keys(table)).not.toContain("dsl");
|
|
23
|
-
}
|
|
24
|
+
expect(Object.keys(v1_0_0)).not.toContain("dsl");
|
|
25
|
+
for (const table of v1_0_0.tables) {
|
|
26
|
+
expect(Object.keys(table)).not.toContain("dsl");
|
|
24
27
|
}
|
|
25
28
|
});
|
|
29
|
+
|
|
30
|
+
it("registers only schema 1.0.0", () => {
|
|
31
|
+
expect(hotUpdaterSchemaVersions.map((item) => item.version)).toEqual([
|
|
32
|
+
"1.0.0",
|
|
33
|
+
]);
|
|
34
|
+
});
|
|
26
35
|
});
|
package/src/schema/dsl.ts
CHANGED
|
@@ -10,7 +10,12 @@ import type {
|
|
|
10
10
|
HotUpdaterVersionedSchema,
|
|
11
11
|
} from "./types";
|
|
12
12
|
|
|
13
|
-
type DefaultValue =
|
|
13
|
+
type DefaultValue =
|
|
14
|
+
| boolean
|
|
15
|
+
| number
|
|
16
|
+
| string
|
|
17
|
+
| Record<string, unknown>
|
|
18
|
+
| readonly unknown[];
|
|
14
19
|
|
|
15
20
|
export type HotUpdaterColumnDsl = {
|
|
16
21
|
readonly dsl: "column";
|
|
@@ -19,8 +24,14 @@ export type HotUpdaterColumnDsl = {
|
|
|
19
24
|
readonly default?: HotUpdaterDefault;
|
|
20
25
|
readonly nullableValue?: true;
|
|
21
26
|
readonly primaryKeyValue?: true;
|
|
27
|
+
readonly providerCollations?: HotUpdaterColumnSchema["providerCollations"];
|
|
22
28
|
readonly nullable: () => HotUpdaterColumnDsl;
|
|
23
29
|
readonly primaryKey: () => HotUpdaterColumnDsl;
|
|
30
|
+
readonly collate: (
|
|
31
|
+
providerCollations: NonNullable<
|
|
32
|
+
HotUpdaterColumnSchema["providerCollations"]
|
|
33
|
+
>,
|
|
34
|
+
) => HotUpdaterColumnDsl;
|
|
24
35
|
readonly defaultTo: (value: DefaultValue) => HotUpdaterColumnDsl;
|
|
25
36
|
};
|
|
26
37
|
|
|
@@ -45,6 +56,9 @@ const defaultValue = (value: DefaultValue): HotUpdaterDefault =>
|
|
|
45
56
|
const columnSchema = (column: HotUpdaterColumnDsl): HotUpdaterColumnSchema => ({
|
|
46
57
|
ormName: column.ormName,
|
|
47
58
|
type: column.type,
|
|
59
|
+
...(column.providerCollations
|
|
60
|
+
? { providerCollations: column.providerCollations }
|
|
61
|
+
: {}),
|
|
48
62
|
...(column.nullableValue ? { nullable: true } : {}),
|
|
49
63
|
...(column.primaryKeyValue ? { primaryKey: true } : {}),
|
|
50
64
|
...(column.default ? { default: column.default } : {}),
|
|
@@ -59,11 +73,16 @@ const createColumn = (state: ColumnState): HotUpdaterColumnDsl => ({
|
|
|
59
73
|
dsl: "column",
|
|
60
74
|
ormName: state.ormName,
|
|
61
75
|
type: state.type,
|
|
76
|
+
...(state.providerCollations
|
|
77
|
+
? { providerCollations: state.providerCollations }
|
|
78
|
+
: {}),
|
|
62
79
|
...(state.nullableValue ? { nullableValue: true } : {}),
|
|
63
80
|
...(state.primaryKeyValue ? { primaryKeyValue: true } : {}),
|
|
64
81
|
...(state.default ? { default: state.default } : {}),
|
|
65
82
|
nullable: () => createColumn({ ...state, nullableValue: true }),
|
|
66
83
|
primaryKey: () => createColumn({ ...state, primaryKeyValue: true }),
|
|
84
|
+
collate: (providerCollations) =>
|
|
85
|
+
createColumn({ ...state, providerCollations }),
|
|
67
86
|
defaultTo: (value) =>
|
|
68
87
|
createColumn({ ...state, default: defaultValue(value) }),
|
|
69
88
|
});
|
|
@@ -88,6 +107,9 @@ export const uuid = (ormName: string): HotUpdaterColumnDsl =>
|
|
|
88
107
|
export const integer = (ormName: string): HotUpdaterColumnDsl =>
|
|
89
108
|
column(ormName, "integer");
|
|
90
109
|
|
|
110
|
+
export const float = (ormName: string): HotUpdaterColumnDsl =>
|
|
111
|
+
column(ormName, "float");
|
|
112
|
+
|
|
91
113
|
export const bool = (ormName: string): HotUpdaterColumnDsl =>
|
|
92
114
|
column(ormName, "bool");
|
|
93
115
|
|
|
@@ -97,6 +119,9 @@ export const json = (ormName: string): HotUpdaterColumnDsl =>
|
|
|
97
119
|
export const stringColumn = (ormName: string): HotUpdaterColumnDsl =>
|
|
98
120
|
column(ormName, "string");
|
|
99
121
|
|
|
122
|
+
export const largeString = (ormName: string): HotUpdaterColumnDsl =>
|
|
123
|
+
column(ormName, "large-string");
|
|
124
|
+
|
|
100
125
|
export const index = (
|
|
101
126
|
name: string,
|
|
102
127
|
columns: readonly string[],
|
|
@@ -107,18 +132,32 @@ export const index = (
|
|
|
107
132
|
...(providers ? { providers } : {}),
|
|
108
133
|
});
|
|
109
134
|
|
|
135
|
+
export const uniqueIndex = (
|
|
136
|
+
name: string,
|
|
137
|
+
columns: readonly string[],
|
|
138
|
+
providers?: HotUpdaterIndexSchema["providers"],
|
|
139
|
+
): HotUpdaterIndexSchema => ({
|
|
140
|
+
name,
|
|
141
|
+
columns,
|
|
142
|
+
...(providers ? { providers } : {}),
|
|
143
|
+
unique: true,
|
|
144
|
+
});
|
|
145
|
+
|
|
110
146
|
export const foreignKey = (
|
|
111
147
|
name: string,
|
|
112
148
|
columns: readonly string[],
|
|
113
149
|
referencedTable: string,
|
|
114
150
|
referencedColumns: readonly string[],
|
|
151
|
+
options: {
|
|
152
|
+
readonly onDelete?: HotUpdaterForeignKeySchema["onDelete"];
|
|
153
|
+
} = {},
|
|
115
154
|
): HotUpdaterForeignKeySchema => ({
|
|
116
155
|
name,
|
|
117
156
|
columns,
|
|
118
157
|
referencedTable,
|
|
119
158
|
referencedColumns,
|
|
120
159
|
onUpdate: "restrict",
|
|
121
|
-
onDelete: "cascade",
|
|
160
|
+
onDelete: options.onDelete ?? "cascade",
|
|
122
161
|
});
|
|
123
162
|
|
|
124
163
|
export const check = (config: HotUpdaterCheckSchema): HotUpdaterCheckSchema =>
|
package/src/schema/index.ts
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
import type { HotUpdaterVersionedSchema } from "./types";
|
|
2
|
-
import {
|
|
3
|
-
import { v0_29_0 } from "./v0_29_0";
|
|
4
|
-
import { v0_31_0 } from "./v0_31_0";
|
|
2
|
+
import { v1_0_0 } from "./v1_0_0";
|
|
5
3
|
|
|
6
4
|
export * from "./settings";
|
|
7
5
|
export * from "./types";
|
|
8
|
-
export * from "./
|
|
9
|
-
export * from "./v0_29_0";
|
|
10
|
-
export * from "./v0_31_0";
|
|
6
|
+
export * from "./v1_0_0";
|
|
11
7
|
|
|
12
8
|
export const hotUpdaterSchemaVersions: readonly HotUpdaterVersionedSchema[] = [
|
|
13
|
-
|
|
14
|
-
v0_29_0,
|
|
15
|
-
v0_31_0,
|
|
9
|
+
v1_0_0,
|
|
16
10
|
];
|
package/src/schema/types.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import type { ORMProvider } from "../db/types";
|
|
2
2
|
|
|
3
|
-
export const HOT_UPDATER_SCHEMA_VERSION = "0.
|
|
3
|
+
export const HOT_UPDATER_SCHEMA_VERSION = "1.0.0";
|
|
4
|
+
export const HOT_UPDATER_CORE_SCHEMA_KEY = "schema.core";
|
|
4
5
|
export const HOT_UPDATER_SETTINGS_TABLE = "private_hot_updater_settings";
|
|
5
6
|
|
|
6
7
|
export type HotUpdaterColumnType =
|
|
7
8
|
| "bool"
|
|
9
|
+
| "float"
|
|
8
10
|
| "integer"
|
|
9
11
|
| "json"
|
|
12
|
+
| "large-string"
|
|
10
13
|
| "string"
|
|
11
14
|
| "uuid"
|
|
12
15
|
| `varchar(${number})`;
|
|
@@ -18,6 +21,7 @@ export type HotUpdaterDefault =
|
|
|
18
21
|
export interface HotUpdaterColumnSchema {
|
|
19
22
|
readonly ormName: string;
|
|
20
23
|
readonly type: HotUpdaterColumnType;
|
|
24
|
+
readonly providerCollations?: Partial<Record<ORMProvider, string>>;
|
|
21
25
|
readonly nullable?: boolean;
|
|
22
26
|
readonly primaryKey?: boolean;
|
|
23
27
|
readonly default?: HotUpdaterDefault;
|
|
@@ -27,11 +31,13 @@ export interface HotUpdaterIndexSchema {
|
|
|
27
31
|
readonly name: string;
|
|
28
32
|
readonly columns: readonly string[];
|
|
29
33
|
readonly providers?: readonly ORMProvider[];
|
|
34
|
+
readonly unique?: true;
|
|
30
35
|
}
|
|
31
36
|
|
|
32
37
|
export interface HotUpdaterCheckSchema {
|
|
33
38
|
readonly name: string;
|
|
34
39
|
readonly expression: string;
|
|
40
|
+
readonly providerExpressions?: Partial<Record<ORMProvider, string>>;
|
|
35
41
|
readonly sqliteInline?: boolean;
|
|
36
42
|
}
|
|
37
43
|
|
|
@@ -41,7 +47,7 @@ export interface HotUpdaterForeignKeySchema {
|
|
|
41
47
|
readonly referencedTable: string;
|
|
42
48
|
readonly referencedColumns: readonly string[];
|
|
43
49
|
readonly onUpdate: "restrict";
|
|
44
|
-
readonly onDelete: "cascade";
|
|
50
|
+
readonly onDelete: "cascade" | "restrict" | "set null";
|
|
45
51
|
}
|
|
46
52
|
|
|
47
53
|
export interface HotUpdaterRelationSchema {
|
|
@@ -70,4 +76,4 @@ export interface HotUpdaterVersionedSchema {
|
|
|
70
76
|
readonly tables: readonly HotUpdaterTableSchema[];
|
|
71
77
|
}
|
|
72
78
|
|
|
73
|
-
export type HotUpdaterSchemaVersion = "
|
|
79
|
+
export type HotUpdaterSchemaVersion = "1.0.0";
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
|
|
3
|
+
import { createTableSql } from "../db/schema/sql";
|
|
4
|
+
import {
|
|
5
|
+
generateDrizzleSchema,
|
|
6
|
+
generatePrismaSchema,
|
|
7
|
+
} from "../db/schemaGenerators";
|
|
8
|
+
import {
|
|
9
|
+
bundleEventsV100,
|
|
10
|
+
bundlePatchesV100,
|
|
11
|
+
bundlesV100,
|
|
12
|
+
releaseCatalogsV100,
|
|
13
|
+
releasesV100,
|
|
14
|
+
v1_0_0,
|
|
15
|
+
} from "./v1_0_0";
|
|
16
|
+
|
|
17
|
+
describe("v1.0.0 Release Catalog schema", () => {
|
|
18
|
+
it("adds the canonical Release and catalog access paths", () => {
|
|
19
|
+
expect(v1_0_0.tables.map(({ ormName }) => ormName)).toContain("releases");
|
|
20
|
+
expect(v1_0_0.tables.map(({ ormName }) => ormName)).toContain(
|
|
21
|
+
"release_catalogs",
|
|
22
|
+
);
|
|
23
|
+
expect(releasesV100.indexes).toContainEqual({
|
|
24
|
+
columns: ["scope_key", "id"],
|
|
25
|
+
name: "releases_scope_order_idx",
|
|
26
|
+
});
|
|
27
|
+
expect(
|
|
28
|
+
releaseCatalogsV100.columns.find(({ ormName }) => ormName === "scope_key")
|
|
29
|
+
?.primaryKey,
|
|
30
|
+
).toBe(true);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("keeps only immutable artifact fields on Bundle rows", () => {
|
|
34
|
+
const fields = bundlesV100.columns.map(({ ormName }) => ormName);
|
|
35
|
+
|
|
36
|
+
expect(fields).toEqual([
|
|
37
|
+
"id",
|
|
38
|
+
"platform",
|
|
39
|
+
"file_hash",
|
|
40
|
+
"git_commit_hash",
|
|
41
|
+
"storage_uri",
|
|
42
|
+
"archive_byte_size",
|
|
43
|
+
"metadata",
|
|
44
|
+
"manifest_storage_uri",
|
|
45
|
+
"manifest_file_hash",
|
|
46
|
+
"asset_base_storage_uri",
|
|
47
|
+
]);
|
|
48
|
+
expect(fields).not.toContain("channel_id");
|
|
49
|
+
expect(fields).not.toContain("enabled");
|
|
50
|
+
expect(fields).not.toContain("target_app_version");
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("stores required archive and patch sizes as bounded floating columns", () => {
|
|
54
|
+
const archiveSize = bundlesV100.columns.find(
|
|
55
|
+
({ ormName }) => ormName === "archive_byte_size",
|
|
56
|
+
);
|
|
57
|
+
const patchSize = bundlePatchesV100.columns.find(
|
|
58
|
+
({ ormName }) => ormName === "byte_size",
|
|
59
|
+
);
|
|
60
|
+
const sql = createTableSql("postgresql").join("\n");
|
|
61
|
+
const prisma = generatePrismaSchema("postgresql", v1_0_0);
|
|
62
|
+
const drizzle = generateDrizzleSchema("postgresql", v1_0_0);
|
|
63
|
+
|
|
64
|
+
expect(archiveSize?.type).toBe("float");
|
|
65
|
+
expect(archiveSize?.nullable).toBeUndefined();
|
|
66
|
+
expect(patchSize?.type).toBe("float");
|
|
67
|
+
expect(patchSize?.nullable).toBeUndefined();
|
|
68
|
+
expect(sql).toContain("archive_byte_size double precision not null");
|
|
69
|
+
expect(sql).toContain("byte_size double precision not null");
|
|
70
|
+
expect(sql).toContain("archive_byte_size <= 9007199254740991");
|
|
71
|
+
expect(sql).toContain("byte_size <= 9007199254740991");
|
|
72
|
+
expect(prisma).toContain("archive_byte_size Float");
|
|
73
|
+
expect(prisma).toContain("byte_size Float");
|
|
74
|
+
expect(drizzle).toContain(
|
|
75
|
+
'archive_byte_size: doublePrecision("archive_byte_size").notNull()',
|
|
76
|
+
);
|
|
77
|
+
expect(drizzle).toContain(
|
|
78
|
+
'byte_size: doublePrecision("byte_size").notNull()',
|
|
79
|
+
);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("keeps nullable sources while requiring the reported target Bundle", () => {
|
|
83
|
+
for (const field of [
|
|
84
|
+
"from_release_id",
|
|
85
|
+
"to_release_id",
|
|
86
|
+
"from_bundle_id",
|
|
87
|
+
]) {
|
|
88
|
+
expect(
|
|
89
|
+
bundleEventsV100.columns.find(({ ormName }) => ormName === field)
|
|
90
|
+
?.nullable,
|
|
91
|
+
).toBe(true);
|
|
92
|
+
}
|
|
93
|
+
expect(
|
|
94
|
+
bundleEventsV100.columns.find(({ ormName }) => ormName === "to_bundle_id")
|
|
95
|
+
?.nullable,
|
|
96
|
+
).toBeUndefined();
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("generates nullable source and artifact relations with the intended deletion rules", () => {
|
|
100
|
+
const prisma = generatePrismaSchema("postgresql", v1_0_0);
|
|
101
|
+
const drizzle = generateDrizzleSchema("postgresql", v1_0_0);
|
|
102
|
+
|
|
103
|
+
expect(prisma).toContain("model releases {");
|
|
104
|
+
expect(prisma).toContain("sourceRelease releases? @relation(");
|
|
105
|
+
expect(prisma).toContain("onDelete: SetNull");
|
|
106
|
+
expect(prisma).toContain("bundle bundles? @relation(");
|
|
107
|
+
expect(drizzle).toContain("export const release_catalogs = pgTable(");
|
|
108
|
+
expect(drizzle).toContain('index("releases_scope_order_idx")');
|
|
109
|
+
expect(drizzle).toContain("foreignColumns: [table.id]");
|
|
110
|
+
expect(drizzle).not.toContain("foreignColumns: [releases.id]");
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("creates both projection tables and their constraints from empty", () => {
|
|
114
|
+
const sql = createTableSql("postgresql").join("\n");
|
|
115
|
+
|
|
116
|
+
expect(sql).toContain("create table releases");
|
|
117
|
+
expect(sql).toContain("create table release_catalogs");
|
|
118
|
+
expect(sql).toContain("releases_scope_order_idx");
|
|
119
|
+
expect(sql).toContain("release_catalogs_generation_check");
|
|
120
|
+
expect(sql).toContain("to_bundle_id uuid not null");
|
|
121
|
+
expect(sql).toContain("from_bundle_id is not null");
|
|
122
|
+
expect(sql).toContain("type = 'UNCHANGED' and from_bundle_id is null");
|
|
123
|
+
expect(sql).toContain("on delete set null");
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it("uses byte-bounded MySQL catalog keys", () => {
|
|
127
|
+
const sql = createTableSql("mysql").join("\n");
|
|
128
|
+
|
|
129
|
+
expect(sql).toContain(
|
|
130
|
+
"scope_key varchar(2048) character set ascii collate ascii_bin",
|
|
131
|
+
);
|
|
132
|
+
expect(sql).toContain(
|
|
133
|
+
"channel_key varchar(1400) character set ascii collate ascii_bin",
|
|
134
|
+
);
|
|
135
|
+
expect(sql).toContain(
|
|
136
|
+
"create index releases_scope_order_idx on releases(scope_key, id)",
|
|
137
|
+
);
|
|
138
|
+
expect(sql).toContain("payload mediumtext not null");
|
|
139
|
+
expect(generatePrismaSchema("mysql", v1_0_0)).toContain(
|
|
140
|
+
"payload String @db.MediumText",
|
|
141
|
+
);
|
|
142
|
+
expect(generateDrizzleSchema("mysql", v1_0_0)).toContain(
|
|
143
|
+
'payload: mediumtext("payload").notNull()',
|
|
144
|
+
);
|
|
145
|
+
});
|
|
146
|
+
});
|