@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
|
@@ -1,151 +1,257 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
BundleEventRow,
|
|
3
|
+
BundlePatchRow,
|
|
4
|
+
ChannelRow,
|
|
5
|
+
ApiKeyRow,
|
|
6
|
+
ReleaseCatalogRow,
|
|
7
|
+
} from "@hot-updater/plugin-core";
|
|
8
|
+
|
|
9
|
+
import type { StoredBundleRow, StoredReleaseRow } from "./databasePluginUtils";
|
|
1
10
|
import type { DrizzleConfig } from "./drizzle";
|
|
2
11
|
|
|
3
12
|
export type DrizzleTable = Record<string, unknown>;
|
|
4
13
|
|
|
14
|
+
type DrizzleMutation = {
|
|
15
|
+
readonly execute: () => Promise<unknown>;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type DrizzleInsertMutation = DrizzleMutation & {
|
|
19
|
+
readonly onConflictDoNothing?: () => DrizzleMutation;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
type DrizzleInsertBuilder = {
|
|
23
|
+
readonly ignore?: () => Pick<DrizzleInsertBuilder, "values">;
|
|
24
|
+
readonly values: (value: unknown) => DrizzleInsertMutation;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
type DrizzleQuery<TRow> = {
|
|
28
|
+
readonly findFirst: (args?: unknown) => Promise<TRow | undefined>;
|
|
29
|
+
readonly findMany: (args?: unknown) => Promise<TRow[]>;
|
|
30
|
+
};
|
|
31
|
+
|
|
5
32
|
export type DrizzleDB = {
|
|
6
33
|
readonly _: { readonly fullSchema: Record<string, DrizzleTable> };
|
|
7
34
|
readonly $count: (table: DrizzleTable, where?: unknown) => Promise<number>;
|
|
8
35
|
readonly delete: (table: DrizzleTable) => {
|
|
9
|
-
where: (condition: unknown) =>
|
|
36
|
+
where: (condition: unknown) => DrizzleMutation;
|
|
10
37
|
};
|
|
11
|
-
readonly insert: (table: DrizzleTable) =>
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
{
|
|
21
|
-
findFirst: (
|
|
22
|
-
args?: unknown,
|
|
23
|
-
) => Promise<Record<string, unknown> | undefined>;
|
|
24
|
-
findMany: (args?: unknown) => Promise<Record<string, unknown>[]>;
|
|
25
|
-
}
|
|
26
|
-
>;
|
|
27
|
-
readonly select: (fields?: unknown) => {
|
|
28
|
-
from: (table: DrizzleTable) => {
|
|
29
|
-
where?: (condition: unknown) => unknown;
|
|
30
|
-
orderBy?: (order: unknown) => unknown;
|
|
31
|
-
limit?: (limit: number) => unknown;
|
|
32
|
-
offset?: (offset: number) => Promise<Record<string, unknown>[]>;
|
|
33
|
-
};
|
|
38
|
+
readonly insert: (table: DrizzleTable) => DrizzleInsertBuilder;
|
|
39
|
+
readonly query: {
|
|
40
|
+
readonly bundles: DrizzleQuery<StoredBundleRow>;
|
|
41
|
+
readonly channels: DrizzleQuery<ChannelRow>;
|
|
42
|
+
readonly bundle_patches: DrizzleQuery<BundlePatchRow>;
|
|
43
|
+
readonly bundle_events: DrizzleQuery<BundleEventRow>;
|
|
44
|
+
readonly api_keys: DrizzleQuery<ApiKeyRow>;
|
|
45
|
+
readonly releases: DrizzleQuery<StoredReleaseRow>;
|
|
46
|
+
readonly release_catalogs: DrizzleQuery<ReleaseCatalogRow>;
|
|
34
47
|
};
|
|
35
48
|
readonly update: (table: DrizzleTable) => {
|
|
36
49
|
set: (values: unknown) => {
|
|
37
|
-
where: (condition: unknown) =>
|
|
50
|
+
where: (condition: unknown) => DrizzleMutation;
|
|
38
51
|
};
|
|
39
52
|
};
|
|
40
|
-
readonly transaction?: <
|
|
41
|
-
operation: (
|
|
42
|
-
) => Promise<
|
|
53
|
+
readonly transaction?: <TResult>(
|
|
54
|
+
operation: (transaction: DrizzleDB) => Promise<TResult>,
|
|
55
|
+
) => Promise<TResult>;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
class InvalidDrizzleDatabaseError extends Error {
|
|
59
|
+
readonly name = "InvalidDrizzleDatabaseError";
|
|
60
|
+
|
|
61
|
+
constructor(readonly reason: string) {
|
|
62
|
+
super(`[hot-updater] ${reason}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const isRecord = (value: unknown): value is Record<string, unknown> =>
|
|
67
|
+
typeof value === "object" && value !== null;
|
|
68
|
+
|
|
69
|
+
const hasFunction = (value: Record<string, unknown>, key: string): boolean =>
|
|
70
|
+
typeof value[key] === "function";
|
|
71
|
+
|
|
72
|
+
const isDrizzleQuery = (value: unknown): boolean =>
|
|
73
|
+
isRecord(value) &&
|
|
74
|
+
hasFunction(value, "findFirst") &&
|
|
75
|
+
hasFunction(value, "findMany");
|
|
76
|
+
|
|
77
|
+
const isDrizzleDB = (value: unknown): value is DrizzleDB => {
|
|
78
|
+
if (!isRecord(value)) return false;
|
|
79
|
+
const metadata = value["_"];
|
|
80
|
+
if (!isRecord(metadata) || !isRecord(metadata["fullSchema"])) return false;
|
|
81
|
+
const query = value["query"];
|
|
82
|
+
if (
|
|
83
|
+
!isRecord(query) ||
|
|
84
|
+
!isDrizzleQuery(query["bundle_events"]) ||
|
|
85
|
+
!isDrizzleQuery(query["bundle_patches"]) ||
|
|
86
|
+
!isDrizzleQuery(query["bundles"]) ||
|
|
87
|
+
!isDrizzleQuery(query["channels"]) ||
|
|
88
|
+
!isDrizzleQuery(query["api_keys"]) ||
|
|
89
|
+
!isDrizzleQuery(query["releases"]) ||
|
|
90
|
+
!isDrizzleQuery(query["release_catalogs"])
|
|
91
|
+
) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
if (
|
|
95
|
+
value["transaction"] !== undefined &&
|
|
96
|
+
!hasFunction(value, "transaction")
|
|
97
|
+
) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
return (
|
|
101
|
+
hasFunction(value, "$count") &&
|
|
102
|
+
hasFunction(value, "delete") &&
|
|
103
|
+
hasFunction(value, "insert") &&
|
|
104
|
+
hasFunction(value, "update")
|
|
105
|
+
);
|
|
43
106
|
};
|
|
44
107
|
|
|
45
108
|
const asDB = (db: unknown): DrizzleDB => {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
"[hot-updater] Drizzle adapter requires query mode with schema.",
|
|
109
|
+
if (!isDrizzleDB(db)) {
|
|
110
|
+
throw new InvalidDrizzleDatabaseError(
|
|
111
|
+
"Drizzle adapter requires query mode with schema.",
|
|
50
112
|
);
|
|
51
113
|
}
|
|
52
|
-
return
|
|
114
|
+
return db;
|
|
53
115
|
};
|
|
54
116
|
|
|
55
117
|
const isDBFactory = (
|
|
56
118
|
db: DrizzleConfig["db"],
|
|
57
119
|
): db is () => unknown | Promise<unknown> => typeof db === "function";
|
|
58
120
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
121
|
+
const parseSchema = (
|
|
122
|
+
schema: Record<string, unknown>,
|
|
123
|
+
): Record<string, DrizzleTable> => {
|
|
124
|
+
const parsed: Record<string, DrizzleTable> = {};
|
|
125
|
+
for (const [name, table] of Object.entries(schema)) {
|
|
126
|
+
if (!isRecord(table)) {
|
|
127
|
+
throw new InvalidDrizzleDatabaseError(
|
|
128
|
+
`Drizzle schema table "${name}" is invalid.`,
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
parsed[name] = table;
|
|
132
|
+
}
|
|
133
|
+
return parsed;
|
|
134
|
+
};
|
|
62
135
|
|
|
136
|
+
export const createLazyDB = (config: DrizzleConfig): DrizzleDB => {
|
|
137
|
+
if (!isDBFactory(config.db)) return asDB(config.db);
|
|
63
138
|
if (!config.schema) {
|
|
64
|
-
throw new
|
|
65
|
-
"
|
|
139
|
+
throw new InvalidDrizzleDatabaseError(
|
|
140
|
+
"Drizzle adapter requires schema when db is lazy.",
|
|
66
141
|
);
|
|
67
142
|
}
|
|
68
143
|
|
|
144
|
+
const source = config.db;
|
|
69
145
|
let resolvedDB: Promise<DrizzleDB> | undefined;
|
|
70
|
-
const getDB =
|
|
71
|
-
resolvedDB ??= Promise.resolve(
|
|
146
|
+
const getDB = (): Promise<DrizzleDB> => {
|
|
147
|
+
resolvedDB ??= Promise.resolve(source()).then(asDB);
|
|
72
148
|
return resolvedDB;
|
|
73
149
|
};
|
|
74
|
-
const fullSchema = config.schema as Record<string, DrizzleTable>;
|
|
75
|
-
const runInserted = async (
|
|
76
|
-
table: DrizzleTable,
|
|
77
|
-
value: unknown,
|
|
78
|
-
operation: (
|
|
79
|
-
inserted: ReturnType<ReturnType<DrizzleDB["insert"]>["values"]>,
|
|
80
|
-
) => Promise<unknown> | unknown,
|
|
81
|
-
) => {
|
|
82
|
-
const db = await getDB();
|
|
83
|
-
return operation(db.insert(table).values(value));
|
|
84
|
-
};
|
|
85
|
-
|
|
86
150
|
return {
|
|
87
|
-
_: { fullSchema },
|
|
151
|
+
_: { fullSchema: parseSchema(config.schema) },
|
|
88
152
|
$count: async (table, where) => (await getDB()).$count(table, where),
|
|
89
153
|
delete: (table) => ({
|
|
90
|
-
where:
|
|
91
|
-
|
|
154
|
+
where: (condition) => ({
|
|
155
|
+
execute: async () =>
|
|
156
|
+
(await getDB()).delete(table).where(condition).execute(),
|
|
157
|
+
}),
|
|
92
158
|
}),
|
|
93
159
|
insert: (table) => ({
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}),
|
|
102
|
-
onConflictDoUpdate: async (args) =>
|
|
103
|
-
runInserted(table, value, async (inserted) => {
|
|
104
|
-
if (typeof inserted.onConflictDoUpdate !== "function") {
|
|
105
|
-
throw new Error(
|
|
106
|
-
"[hot-updater] Drizzle insert does not support onConflictDoUpdate.",
|
|
160
|
+
ignore: () => ({
|
|
161
|
+
values: (value) => ({
|
|
162
|
+
execute: async () => {
|
|
163
|
+
const insert = (await getDB()).insert(table).ignore;
|
|
164
|
+
if (insert === undefined) {
|
|
165
|
+
throw new InvalidDrizzleDatabaseError(
|
|
166
|
+
"The resolved Drizzle database does not support insert ignore.",
|
|
107
167
|
);
|
|
108
168
|
}
|
|
109
|
-
return
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
169
|
+
return insert().values(value).execute();
|
|
170
|
+
},
|
|
171
|
+
}),
|
|
172
|
+
}),
|
|
173
|
+
values: (value) => ({
|
|
174
|
+
execute: async () =>
|
|
175
|
+
(await getDB()).insert(table).values(value).execute(),
|
|
176
|
+
onConflictDoNothing: () => ({
|
|
177
|
+
execute: async () => {
|
|
178
|
+
const insert = (await getDB()).insert(table).values(value);
|
|
179
|
+
if (insert.onConflictDoNothing === undefined) {
|
|
180
|
+
throw new InvalidDrizzleDatabaseError(
|
|
181
|
+
"The resolved Drizzle database does not support conflict-ignore inserts.",
|
|
116
182
|
);
|
|
117
183
|
}
|
|
118
|
-
return
|
|
119
|
-
}
|
|
120
|
-
}),
|
|
121
|
-
}),
|
|
122
|
-
query: new Proxy(
|
|
123
|
-
{},
|
|
124
|
-
{
|
|
125
|
-
get: (_target, tableName) => ({
|
|
126
|
-
findFirst: async (args?: unknown) =>
|
|
127
|
-
(await getDB()).query[String(tableName)]?.findFirst(args),
|
|
128
|
-
findMany: async (args?: unknown) =>
|
|
129
|
-
(await getDB()).query[String(tableName)]?.findMany(args) ?? [],
|
|
184
|
+
return insert.onConflictDoNothing().execute();
|
|
185
|
+
},
|
|
130
186
|
}),
|
|
131
|
-
},
|
|
132
|
-
) as DrizzleDB["query"],
|
|
133
|
-
select: (fields) => ({
|
|
134
|
-
from: (table) => ({
|
|
135
|
-
offset: async (offset) =>
|
|
136
|
-
(await getDB()).select(fields).from(table).offset?.(offset) ?? [],
|
|
137
187
|
}),
|
|
138
188
|
}),
|
|
189
|
+
query: {
|
|
190
|
+
bundle_events: {
|
|
191
|
+
findFirst: async (args) =>
|
|
192
|
+
(await getDB()).query.bundle_events.findFirst(args),
|
|
193
|
+
findMany: async (args) =>
|
|
194
|
+
(await getDB()).query.bundle_events.findMany(args),
|
|
195
|
+
},
|
|
196
|
+
bundle_patches: {
|
|
197
|
+
findFirst: async (args) =>
|
|
198
|
+
(await getDB()).query.bundle_patches.findFirst(args),
|
|
199
|
+
findMany: async (args) =>
|
|
200
|
+
(await getDB()).query.bundle_patches.findMany(args),
|
|
201
|
+
},
|
|
202
|
+
bundles: {
|
|
203
|
+
findFirst: async (args) =>
|
|
204
|
+
(await getDB()).query.bundles.findFirst(args),
|
|
205
|
+
findMany: async (args) => (await getDB()).query.bundles.findMany(args),
|
|
206
|
+
},
|
|
207
|
+
channels: {
|
|
208
|
+
findFirst: async (args) =>
|
|
209
|
+
(await getDB()).query.channels.findFirst(args),
|
|
210
|
+
findMany: async (args) => (await getDB()).query.channels.findMany(args),
|
|
211
|
+
},
|
|
212
|
+
api_keys: {
|
|
213
|
+
findFirst: async (args) =>
|
|
214
|
+
(await getDB()).query.api_keys.findFirst(args),
|
|
215
|
+
findMany: async (args) => (await getDB()).query.api_keys.findMany(args),
|
|
216
|
+
},
|
|
217
|
+
releases: {
|
|
218
|
+
findFirst: async (args) =>
|
|
219
|
+
(await getDB()).query.releases.findFirst(args),
|
|
220
|
+
findMany: async (args) => (await getDB()).query.releases.findMany(args),
|
|
221
|
+
},
|
|
222
|
+
release_catalogs: {
|
|
223
|
+
findFirst: async (args) =>
|
|
224
|
+
(await getDB()).query.release_catalogs.findFirst(args),
|
|
225
|
+
findMany: async (args) =>
|
|
226
|
+
(await getDB()).query.release_catalogs.findMany(args),
|
|
227
|
+
},
|
|
228
|
+
},
|
|
139
229
|
update: (table) => ({
|
|
140
230
|
set: (values) => ({
|
|
141
|
-
where:
|
|
142
|
-
|
|
231
|
+
where: (condition) => ({
|
|
232
|
+
execute: async () =>
|
|
233
|
+
(await getDB())
|
|
234
|
+
.update(table)
|
|
235
|
+
.set(values)
|
|
236
|
+
.where(condition)
|
|
237
|
+
.execute(),
|
|
238
|
+
}),
|
|
143
239
|
}),
|
|
144
240
|
}),
|
|
145
|
-
transaction
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
241
|
+
...(config.transaction === true
|
|
242
|
+
? {
|
|
243
|
+
transaction: async <TResult>(
|
|
244
|
+
operation: (transaction: DrizzleDB) => Promise<TResult>,
|
|
245
|
+
): Promise<TResult> => {
|
|
246
|
+
const db = await getDB();
|
|
247
|
+
if (db.transaction === undefined) {
|
|
248
|
+
throw new InvalidDrizzleDatabaseError(
|
|
249
|
+
"The resolved Drizzle database does not support transactions.",
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
return db.transaction(operation);
|
|
253
|
+
},
|
|
254
|
+
}
|
|
255
|
+
: {}),
|
|
150
256
|
};
|
|
151
257
|
};
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
DatabaseModel,
|
|
3
|
+
DatabaseWhere,
|
|
4
|
+
} from "@hot-updater/plugin-core/internal";
|
|
5
|
+
import {
|
|
6
|
+
eq,
|
|
7
|
+
gt,
|
|
8
|
+
gte,
|
|
9
|
+
inArray,
|
|
10
|
+
isNotNull,
|
|
11
|
+
isNull,
|
|
12
|
+
lt,
|
|
13
|
+
lte,
|
|
14
|
+
ne,
|
|
15
|
+
notInArray,
|
|
16
|
+
sql,
|
|
17
|
+
type SQL,
|
|
18
|
+
type SQLWrapper,
|
|
19
|
+
} from "drizzle-orm";
|
|
20
|
+
|
|
21
|
+
import type { ORMSQLProvider } from "../db/types";
|
|
22
|
+
import { escapeGlobPattern, escapeLikePattern } from "./databasePluginUtils";
|
|
23
|
+
import type { DrizzleTable } from "./drizzleLazyDB";
|
|
24
|
+
|
|
25
|
+
class InvalidDatabasePredicateError extends Error {
|
|
26
|
+
readonly name = "InvalidDatabasePredicateError";
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
class MissingDrizzleColumnError extends Error {
|
|
30
|
+
readonly name = "MissingDrizzleColumnError";
|
|
31
|
+
|
|
32
|
+
constructor(readonly column: string) {
|
|
33
|
+
super(`Drizzle schema is missing column "${column}".`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const isSQLWrapper = (value: unknown): value is SQLWrapper =>
|
|
38
|
+
typeof value === "object" &&
|
|
39
|
+
value !== null &&
|
|
40
|
+
"getSQL" in value &&
|
|
41
|
+
typeof value.getSQL === "function";
|
|
42
|
+
|
|
43
|
+
const column = (table: DrizzleTable, field: string): SQLWrapper => {
|
|
44
|
+
const value = table[field];
|
|
45
|
+
if (!isSQLWrapper(value)) {
|
|
46
|
+
throw new MissingDrizzleColumnError(field);
|
|
47
|
+
}
|
|
48
|
+
return value;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const stringPredicate = (
|
|
52
|
+
provider: ORMSQLProvider,
|
|
53
|
+
field: SQLWrapper,
|
|
54
|
+
operator: "contains" | "ends_with" | "starts_with",
|
|
55
|
+
value: string,
|
|
56
|
+
insensitive: boolean,
|
|
57
|
+
): SQL => {
|
|
58
|
+
if (provider === "sqlite" && !insensitive) {
|
|
59
|
+
const literal = escapeGlobPattern(value);
|
|
60
|
+
const pattern =
|
|
61
|
+
operator === "contains"
|
|
62
|
+
? `*${literal}*`
|
|
63
|
+
: operator === "starts_with"
|
|
64
|
+
? `${literal}*`
|
|
65
|
+
: `*${literal}`;
|
|
66
|
+
return sql`${field} glob ${pattern}`;
|
|
67
|
+
}
|
|
68
|
+
const literal = escapeLikePattern(value);
|
|
69
|
+
const pattern =
|
|
70
|
+
operator === "contains"
|
|
71
|
+
? `%${literal}%`
|
|
72
|
+
: operator === "starts_with"
|
|
73
|
+
? `${literal}%`
|
|
74
|
+
: `%${literal}`;
|
|
75
|
+
if (insensitive) {
|
|
76
|
+
return sql`lower(${field}) like lower(${pattern}) escape '\\'`;
|
|
77
|
+
}
|
|
78
|
+
if (provider === "mysql") {
|
|
79
|
+
return sql`binary ${field} like binary ${pattern} escape '\\'`;
|
|
80
|
+
}
|
|
81
|
+
return sql`${field} like ${pattern} escape '\\'`;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const predicate = <TModel extends DatabaseModel>(
|
|
85
|
+
provider: ORMSQLProvider,
|
|
86
|
+
table: DrizzleTable,
|
|
87
|
+
condition: DatabaseWhere<TModel>,
|
|
88
|
+
): SQL => {
|
|
89
|
+
const field = column(table, condition.field);
|
|
90
|
+
const operator = condition.operator ?? "eq";
|
|
91
|
+
switch (operator) {
|
|
92
|
+
case "eq":
|
|
93
|
+
case "ne": {
|
|
94
|
+
if (condition.value === null) {
|
|
95
|
+
return operator === "eq" ? isNull(field) : isNotNull(field);
|
|
96
|
+
}
|
|
97
|
+
const insensitive =
|
|
98
|
+
"mode" in condition && condition.mode === "insensitive";
|
|
99
|
+
if (insensitive) {
|
|
100
|
+
return operator === "eq"
|
|
101
|
+
? sql`lower(${field}) = lower(${condition.value})`
|
|
102
|
+
: sql`lower(${field}) <> lower(${condition.value})`;
|
|
103
|
+
}
|
|
104
|
+
return operator === "eq"
|
|
105
|
+
? eq(field, condition.value)
|
|
106
|
+
: ne(field, condition.value);
|
|
107
|
+
}
|
|
108
|
+
case "gt":
|
|
109
|
+
return gt(field, condition.value);
|
|
110
|
+
case "gte":
|
|
111
|
+
return gte(field, condition.value);
|
|
112
|
+
case "lt":
|
|
113
|
+
return lt(field, condition.value);
|
|
114
|
+
case "lte":
|
|
115
|
+
return lte(field, condition.value);
|
|
116
|
+
case "in":
|
|
117
|
+
case "not_in": {
|
|
118
|
+
if (!Array.isArray(condition.value)) {
|
|
119
|
+
throw new InvalidDatabasePredicateError();
|
|
120
|
+
}
|
|
121
|
+
if (operator === "in") {
|
|
122
|
+
return condition.value.length === 0
|
|
123
|
+
? sql`false`
|
|
124
|
+
: inArray(field, condition.value);
|
|
125
|
+
}
|
|
126
|
+
return condition.value.length === 0
|
|
127
|
+
? sql`true`
|
|
128
|
+
: notInArray(field, condition.value);
|
|
129
|
+
}
|
|
130
|
+
case "contains":
|
|
131
|
+
case "starts_with":
|
|
132
|
+
case "ends_with": {
|
|
133
|
+
if (typeof condition.value !== "string") {
|
|
134
|
+
throw new InvalidDatabasePredicateError();
|
|
135
|
+
}
|
|
136
|
+
return stringPredicate(
|
|
137
|
+
provider,
|
|
138
|
+
field,
|
|
139
|
+
operator,
|
|
140
|
+
condition.value,
|
|
141
|
+
"mode" in condition && condition.mode === "insensitive",
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
export const buildDrizzleWhere = <TModel extends DatabaseModel>(
|
|
148
|
+
provider: ORMSQLProvider,
|
|
149
|
+
table: DrizzleTable,
|
|
150
|
+
where: readonly DatabaseWhere<TModel>[] | undefined,
|
|
151
|
+
): SQL | undefined => {
|
|
152
|
+
const items = Array.isArray(where) ? where : [];
|
|
153
|
+
const [first, ...rest] = items;
|
|
154
|
+
if (first === undefined) return undefined;
|
|
155
|
+
let expression = predicate<TModel>(provider, table, first);
|
|
156
|
+
for (const condition of rest) {
|
|
157
|
+
const next = predicate<TModel>(provider, table, condition);
|
|
158
|
+
expression =
|
|
159
|
+
condition.connector === "OR"
|
|
160
|
+
? sql`(${expression} or ${next})`
|
|
161
|
+
: sql`(${expression} and ${next})`;
|
|
162
|
+
}
|
|
163
|
+
return expression;
|
|
164
|
+
};
|