@hot-updater/server 0.36.6 → 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,357 @@
|
|
|
1
|
+
import { HOT_UPDATER_SETTINGS_TABLE } from "./types.mjs";
|
|
2
|
+
import { bool, check, column, float, foreignKey, idColumn, index, integer, json, largeString, relation, schema, stringColumn, table, uniqueIndex, uuid, varchar } from "./dsl.mjs";
|
|
3
|
+
import { createSettingsTable } from "./settings.mjs";
|
|
4
|
+
//#region src/schema/v1_0_0.ts
|
|
5
|
+
const channelIdentityCollations = {
|
|
6
|
+
mysql: "utf8mb4_bin",
|
|
7
|
+
mssql: "Latin1_General_100_BIN2_SC",
|
|
8
|
+
sqlite: "binary"
|
|
9
|
+
};
|
|
10
|
+
const catalogKeyCollations = {
|
|
11
|
+
mysql: "ascii_bin",
|
|
12
|
+
mssql: "Latin1_General_100_BIN2",
|
|
13
|
+
sqlite: "binary"
|
|
14
|
+
};
|
|
15
|
+
const channelsV100 = table("channels", {
|
|
16
|
+
id: idColumn("id", varchar(255)).collate(channelIdentityCollations),
|
|
17
|
+
name: column("name", varchar(255)).collate(channelIdentityCollations)
|
|
18
|
+
}, {
|
|
19
|
+
indexes: [uniqueIndex("channels_name_key", ["name"])],
|
|
20
|
+
checks: [check({
|
|
21
|
+
name: "channels_id_length_check",
|
|
22
|
+
expression: "char_length(id) between 1 and 255",
|
|
23
|
+
providerExpressions: {
|
|
24
|
+
mssql: "len(id collate Latin1_General_100_BIN2_SC + N'#') - 1 between 1 and 255",
|
|
25
|
+
sqlite: "length(id) between 1 and 255"
|
|
26
|
+
},
|
|
27
|
+
sqliteInline: true
|
|
28
|
+
}), check({
|
|
29
|
+
name: "channels_name_length_check",
|
|
30
|
+
expression: "char_length(name) between 1 and 255",
|
|
31
|
+
providerExpressions: {
|
|
32
|
+
mssql: "len(name collate Latin1_General_100_BIN2_SC + N'#') - 1 between 1 and 255",
|
|
33
|
+
sqlite: "length(name) between 1 and 255"
|
|
34
|
+
},
|
|
35
|
+
sqliteInline: true
|
|
36
|
+
})]
|
|
37
|
+
});
|
|
38
|
+
const bundlePatchesV100 = table("bundle_patches", {
|
|
39
|
+
id: idColumn("id", varchar(255)),
|
|
40
|
+
bundle_id: uuid("bundle_id"),
|
|
41
|
+
base_bundle_id: uuid("base_bundle_id"),
|
|
42
|
+
base_file_hash: column("base_file_hash", "string"),
|
|
43
|
+
patch_file_hash: column("patch_file_hash", "string"),
|
|
44
|
+
patch_storage_uri: column("patch_storage_uri", "string"),
|
|
45
|
+
byte_size: float("byte_size"),
|
|
46
|
+
order_index: integer("order_index").defaultTo(0)
|
|
47
|
+
}, {
|
|
48
|
+
indexes: [index("bundle_patches_bundle_id_idx", ["bundle_id"]), index("bundle_patches_base_bundle_id_idx", ["base_bundle_id"])],
|
|
49
|
+
foreignKeys: [foreignKey("bundle_patches_bundle_id_fk", ["bundle_id"], "bundles", ["id"]), foreignKey("bundle_patches_base_bundle_id_fk", ["base_bundle_id"], "bundles", ["id"])],
|
|
50
|
+
relations: [relation({
|
|
51
|
+
name: "bundle",
|
|
52
|
+
fieldName: "patches",
|
|
53
|
+
targetFieldName: "bundle",
|
|
54
|
+
relationName: "bundle_patches_bundles_patches",
|
|
55
|
+
columns: ["bundle_id"],
|
|
56
|
+
referencedTable: "bundles",
|
|
57
|
+
referencedColumns: ["id"]
|
|
58
|
+
}), relation({
|
|
59
|
+
name: "baseBundle",
|
|
60
|
+
fieldName: "baseForPatches",
|
|
61
|
+
targetFieldName: "baseBundle",
|
|
62
|
+
relationName: "bundle_patches_bundles_baseForPatches",
|
|
63
|
+
columns: ["base_bundle_id"],
|
|
64
|
+
referencedTable: "bundles",
|
|
65
|
+
referencedColumns: ["id"]
|
|
66
|
+
})],
|
|
67
|
+
checks: [check({
|
|
68
|
+
name: "bundle_patches_byte_size_check",
|
|
69
|
+
expression: "byte_size >= 0 and byte_size <= 9007199254740991",
|
|
70
|
+
sqliteInline: true
|
|
71
|
+
})]
|
|
72
|
+
});
|
|
73
|
+
const apiKeysV100 = table("api_keys", {
|
|
74
|
+
id: idColumn("id", varchar(255)),
|
|
75
|
+
hash: stringColumn("hash"),
|
|
76
|
+
name: stringColumn("name"),
|
|
77
|
+
prefix: stringColumn("prefix"),
|
|
78
|
+
role: stringColumn("role"),
|
|
79
|
+
created_at_ms: float("created_at_ms"),
|
|
80
|
+
revoked_at_ms: float("revoked_at_ms").nullable()
|
|
81
|
+
}, {
|
|
82
|
+
indexes: [uniqueIndex("api_keys_hash_key", ["hash"]), index("api_keys_created_at_idx", ["created_at_ms", "id"])],
|
|
83
|
+
checks: [
|
|
84
|
+
check({
|
|
85
|
+
name: "api_keys_role_check",
|
|
86
|
+
expression: "role = 'client'",
|
|
87
|
+
sqliteInline: true
|
|
88
|
+
}),
|
|
89
|
+
check({
|
|
90
|
+
name: "api_keys_created_at_check",
|
|
91
|
+
expression: "created_at_ms >= 0",
|
|
92
|
+
sqliteInline: true
|
|
93
|
+
}),
|
|
94
|
+
check({
|
|
95
|
+
name: "api_keys_revoked_at_check",
|
|
96
|
+
expression: "revoked_at_ms is null or revoked_at_ms >= 0",
|
|
97
|
+
sqliteInline: true
|
|
98
|
+
})
|
|
99
|
+
]
|
|
100
|
+
});
|
|
101
|
+
const bundlesV100 = table("bundles", {
|
|
102
|
+
id: idColumn("id", "uuid"),
|
|
103
|
+
platform: stringColumn("platform"),
|
|
104
|
+
file_hash: stringColumn("file_hash"),
|
|
105
|
+
git_commit_hash: stringColumn("git_commit_hash").nullable(),
|
|
106
|
+
storage_uri: stringColumn("storage_uri"),
|
|
107
|
+
archive_byte_size: float("archive_byte_size"),
|
|
108
|
+
metadata: json("metadata").defaultTo({}),
|
|
109
|
+
manifest_storage_uri: stringColumn("manifest_storage_uri").nullable(),
|
|
110
|
+
manifest_file_hash: stringColumn("manifest_file_hash").nullable(),
|
|
111
|
+
asset_base_storage_uri: stringColumn("asset_base_storage_uri").nullable()
|
|
112
|
+
}, {
|
|
113
|
+
indexes: [index("bundles_platform_idx", ["platform"], ["mongodb"])],
|
|
114
|
+
checks: [check({
|
|
115
|
+
name: "bundles_archive_byte_size_check",
|
|
116
|
+
expression: "archive_byte_size >= 0 and archive_byte_size <= 9007199254740991",
|
|
117
|
+
sqliteInline: true
|
|
118
|
+
})]
|
|
119
|
+
});
|
|
120
|
+
const releasesV100 = table("releases", {
|
|
121
|
+
id: idColumn("id", "uuid"),
|
|
122
|
+
revision: integer("revision"),
|
|
123
|
+
scope_key: column("scope_key", varchar(2048)).collate(catalogKeyCollations),
|
|
124
|
+
channel_id: column("channel_id", varchar(255)).collate(channelIdentityCollations),
|
|
125
|
+
platform: stringColumn("platform"),
|
|
126
|
+
kind: stringColumn("kind"),
|
|
127
|
+
bundle_id: column("bundle_id", "uuid").nullable(),
|
|
128
|
+
strategy: stringColumn("strategy"),
|
|
129
|
+
target_app_version: stringColumn("target_app_version").nullable(),
|
|
130
|
+
fingerprint_hash: stringColumn("fingerprint_hash").nullable(),
|
|
131
|
+
enabled: bool("enabled"),
|
|
132
|
+
should_force_update: bool("should_force_update"),
|
|
133
|
+
message: stringColumn("message").nullable(),
|
|
134
|
+
rollout_cohort_count: integer("rollout_cohort_count").defaultTo(1e3),
|
|
135
|
+
target_cohorts: json("target_cohorts").defaultTo([]),
|
|
136
|
+
operation: stringColumn("operation"),
|
|
137
|
+
source_release_id: column("source_release_id", "uuid").nullable(),
|
|
138
|
+
created_at_ms: float("created_at_ms"),
|
|
139
|
+
updated_at_ms: float("updated_at_ms")
|
|
140
|
+
}, {
|
|
141
|
+
indexes: [
|
|
142
|
+
index("releases_scope_order_idx", ["scope_key", "id"]),
|
|
143
|
+
index("releases_channel_platform_order_idx", [
|
|
144
|
+
"channel_id",
|
|
145
|
+
"platform",
|
|
146
|
+
"id"
|
|
147
|
+
]),
|
|
148
|
+
index("releases_bundle_id_idx", ["bundle_id"]),
|
|
149
|
+
index("releases_fingerprint_hash_idx", ["fingerprint_hash"]),
|
|
150
|
+
index("releases_enabled_idx", ["enabled"])
|
|
151
|
+
],
|
|
152
|
+
checks: [
|
|
153
|
+
check({
|
|
154
|
+
name: "releases_revision_check",
|
|
155
|
+
expression: "revision >= 1",
|
|
156
|
+
sqliteInline: true
|
|
157
|
+
}),
|
|
158
|
+
check({
|
|
159
|
+
name: "releases_kind_bundle_check",
|
|
160
|
+
expression: "(kind = 'BUNDLE' and bundle_id is not null) or (kind = 'EMBEDDED' and bundle_id is null)",
|
|
161
|
+
sqliteInline: true
|
|
162
|
+
}),
|
|
163
|
+
check({
|
|
164
|
+
name: "releases_strategy_target_check",
|
|
165
|
+
expression: "(strategy = 'APP_VERSION' and target_app_version is not null and fingerprint_hash is null) or (strategy = 'FINGERPRINT' and target_app_version is null and fingerprint_hash is not null)",
|
|
166
|
+
sqliteInline: true
|
|
167
|
+
}),
|
|
168
|
+
check({
|
|
169
|
+
name: "releases_rollout_cohort_count_check",
|
|
170
|
+
expression: "rollout_cohort_count >= 0 and rollout_cohort_count <= 1000",
|
|
171
|
+
sqliteInline: true
|
|
172
|
+
}),
|
|
173
|
+
check({
|
|
174
|
+
name: "releases_operation_check",
|
|
175
|
+
expression: "operation in ('DEPLOY', 'PROMOTE', 'ROLLBACK')",
|
|
176
|
+
sqliteInline: true
|
|
177
|
+
})
|
|
178
|
+
],
|
|
179
|
+
foreignKeys: [
|
|
180
|
+
foreignKey("releases_channel_id_fk", ["channel_id"], "channels", ["id"], { onDelete: "restrict" }),
|
|
181
|
+
foreignKey("releases_bundle_id_fk", ["bundle_id"], "bundles", ["id"], { onDelete: "restrict" }),
|
|
182
|
+
foreignKey("releases_source_release_id_fk", ["source_release_id"], "releases", ["id"], { onDelete: "set null" })
|
|
183
|
+
],
|
|
184
|
+
relations: [
|
|
185
|
+
relation({
|
|
186
|
+
name: "channelRecord",
|
|
187
|
+
fieldName: "releases",
|
|
188
|
+
targetFieldName: "channelRecord",
|
|
189
|
+
relationName: "releases_channels",
|
|
190
|
+
columns: ["channel_id"],
|
|
191
|
+
referencedTable: "channels",
|
|
192
|
+
referencedColumns: ["id"]
|
|
193
|
+
}),
|
|
194
|
+
relation({
|
|
195
|
+
name: "bundle",
|
|
196
|
+
fieldName: "releases",
|
|
197
|
+
targetFieldName: "bundle",
|
|
198
|
+
relationName: "releases_bundles",
|
|
199
|
+
columns: ["bundle_id"],
|
|
200
|
+
referencedTable: "bundles",
|
|
201
|
+
referencedColumns: ["id"]
|
|
202
|
+
}),
|
|
203
|
+
relation({
|
|
204
|
+
name: "sourceRelease",
|
|
205
|
+
fieldName: "derivedReleases",
|
|
206
|
+
targetFieldName: "sourceRelease",
|
|
207
|
+
relationName: "releases_source_release",
|
|
208
|
+
columns: ["source_release_id"],
|
|
209
|
+
referencedTable: "releases",
|
|
210
|
+
referencedColumns: ["id"]
|
|
211
|
+
})
|
|
212
|
+
]
|
|
213
|
+
});
|
|
214
|
+
const releaseCatalogsV100 = table("release_catalogs", {
|
|
215
|
+
scope_key: idColumn("scope_key", varchar(2048)).collate(catalogKeyCollations),
|
|
216
|
+
catalog_id: column("catalog_id", varchar(255)),
|
|
217
|
+
strategy: stringColumn("strategy"),
|
|
218
|
+
channel_id: column("channel_id", varchar(255)).collate(channelIdentityCollations),
|
|
219
|
+
channel_key: column("channel_key", varchar(1400)).collate(catalogKeyCollations),
|
|
220
|
+
platform: stringColumn("platform"),
|
|
221
|
+
fingerprint_hash: stringColumn("fingerprint_hash").nullable(),
|
|
222
|
+
generation: float("generation"),
|
|
223
|
+
payload: largeString("payload"),
|
|
224
|
+
catalog_hash: column("catalog_hash", varchar(71)),
|
|
225
|
+
byte_size: integer("byte_size"),
|
|
226
|
+
is_tombstone: bool("is_tombstone"),
|
|
227
|
+
updated_at_ms: float("updated_at_ms")
|
|
228
|
+
}, {
|
|
229
|
+
indexes: [index("release_catalogs_channel_idx", ["channel_id"])],
|
|
230
|
+
checks: [
|
|
231
|
+
check({
|
|
232
|
+
name: "release_catalogs_strategy_target_check",
|
|
233
|
+
expression: "(strategy = 'APP_VERSION' and fingerprint_hash is null) or (strategy = 'FINGERPRINT' and fingerprint_hash is not null)",
|
|
234
|
+
sqliteInline: true
|
|
235
|
+
}),
|
|
236
|
+
check({
|
|
237
|
+
name: "release_catalogs_generation_check",
|
|
238
|
+
expression: "generation >= 1 and generation <= 9007199254740991",
|
|
239
|
+
sqliteInline: true
|
|
240
|
+
}),
|
|
241
|
+
check({
|
|
242
|
+
name: "release_catalogs_byte_size_check",
|
|
243
|
+
expression: "byte_size >= 0 and byte_size <= 262144",
|
|
244
|
+
sqliteInline: true
|
|
245
|
+
})
|
|
246
|
+
],
|
|
247
|
+
foreignKeys: [foreignKey("release_catalogs_channel_id_fk", ["channel_id"], "channels", ["id"], { onDelete: "restrict" })],
|
|
248
|
+
relations: [relation({
|
|
249
|
+
name: "channelRecord",
|
|
250
|
+
fieldName: "releaseCatalogs",
|
|
251
|
+
targetFieldName: "channelRecord",
|
|
252
|
+
relationName: "release_catalogs_channels",
|
|
253
|
+
columns: ["channel_id"],
|
|
254
|
+
referencedTable: "channels",
|
|
255
|
+
referencedColumns: ["id"]
|
|
256
|
+
})]
|
|
257
|
+
});
|
|
258
|
+
const bundleEventsV100 = table("bundle_events", {
|
|
259
|
+
id: idColumn("id", "uuid"),
|
|
260
|
+
type: stringColumn("type"),
|
|
261
|
+
install_id: stringColumn("install_id"),
|
|
262
|
+
user_id: stringColumn("user_id").nullable(),
|
|
263
|
+
username: stringColumn("username").nullable(),
|
|
264
|
+
from_release_id: uuid("from_release_id").nullable(),
|
|
265
|
+
from_bundle_id: uuid("from_bundle_id").nullable(),
|
|
266
|
+
to_release_id: uuid("to_release_id").nullable(),
|
|
267
|
+
to_bundle_id: uuid("to_bundle_id"),
|
|
268
|
+
platform: stringColumn("platform"),
|
|
269
|
+
app_version: stringColumn("app_version"),
|
|
270
|
+
channel: stringColumn("channel"),
|
|
271
|
+
cohort: stringColumn("cohort"),
|
|
272
|
+
update_strategy: stringColumn("update_strategy").nullable(),
|
|
273
|
+
fingerprint_hash: stringColumn("fingerprint_hash").nullable(),
|
|
274
|
+
sdk_version: stringColumn("sdk_version").nullable(),
|
|
275
|
+
received_at_ms: float("received_at_ms")
|
|
276
|
+
}, {
|
|
277
|
+
indexes: [
|
|
278
|
+
index("bundle_events_received_at_idx", ["received_at_ms", "id"]),
|
|
279
|
+
index("bundle_events_install_idx", [
|
|
280
|
+
"install_id",
|
|
281
|
+
"received_at_ms",
|
|
282
|
+
"id"
|
|
283
|
+
]),
|
|
284
|
+
index("bundle_events_user_id_idx", [
|
|
285
|
+
"user_id",
|
|
286
|
+
"received_at_ms",
|
|
287
|
+
"id"
|
|
288
|
+
]),
|
|
289
|
+
index("bundle_events_username_idx", [
|
|
290
|
+
"username",
|
|
291
|
+
"received_at_ms",
|
|
292
|
+
"id"
|
|
293
|
+
]),
|
|
294
|
+
index("bundle_events_to_bundle_idx", [
|
|
295
|
+
"type",
|
|
296
|
+
"to_bundle_id",
|
|
297
|
+
"received_at_ms",
|
|
298
|
+
"id"
|
|
299
|
+
]),
|
|
300
|
+
index("bundle_events_from_bundle_idx", [
|
|
301
|
+
"type",
|
|
302
|
+
"from_bundle_id",
|
|
303
|
+
"received_at_ms",
|
|
304
|
+
"id"
|
|
305
|
+
]),
|
|
306
|
+
index("bundle_events_to_release_idx", [
|
|
307
|
+
"type",
|
|
308
|
+
"to_release_id",
|
|
309
|
+
"received_at_ms",
|
|
310
|
+
"id"
|
|
311
|
+
]),
|
|
312
|
+
index("bundle_events_from_release_idx", [
|
|
313
|
+
"type",
|
|
314
|
+
"from_release_id",
|
|
315
|
+
"received_at_ms",
|
|
316
|
+
"id"
|
|
317
|
+
])
|
|
318
|
+
],
|
|
319
|
+
checks: [
|
|
320
|
+
check({
|
|
321
|
+
name: "bundle_events_type_check",
|
|
322
|
+
expression: "type in ('UPDATE_APPLIED', 'RECOVERED', 'RELEASE_ADOPTED', 'UNCHANGED')",
|
|
323
|
+
sqliteInline: true
|
|
324
|
+
}),
|
|
325
|
+
check({
|
|
326
|
+
name: "bundle_events_platform_check",
|
|
327
|
+
expression: "platform in ('ios', 'android')",
|
|
328
|
+
sqliteInline: true
|
|
329
|
+
}),
|
|
330
|
+
check({
|
|
331
|
+
name: "bundle_events_shape_check",
|
|
332
|
+
expression: "((type in ('UPDATE_APPLIED', 'RECOVERED', 'RELEASE_ADOPTED')) and from_bundle_id is not null and update_strategy is not null and update_strategy in ('fingerprint', 'appVersion')) or (type = 'UNCHANGED' and from_bundle_id is null and update_strategy is null)",
|
|
333
|
+
sqliteInline: true
|
|
334
|
+
}),
|
|
335
|
+
check({
|
|
336
|
+
name: "bundle_events_received_at_check",
|
|
337
|
+
expression: "received_at_ms >= 0",
|
|
338
|
+
sqliteInline: true
|
|
339
|
+
})
|
|
340
|
+
]
|
|
341
|
+
});
|
|
342
|
+
const v1_0_0 = schema({
|
|
343
|
+
version: "1.0.0",
|
|
344
|
+
settingsTable: HOT_UPDATER_SETTINGS_TABLE,
|
|
345
|
+
tables: [
|
|
346
|
+
channelsV100,
|
|
347
|
+
bundlesV100,
|
|
348
|
+
bundlePatchesV100,
|
|
349
|
+
releasesV100,
|
|
350
|
+
releaseCatalogsV100,
|
|
351
|
+
bundleEventsV100,
|
|
352
|
+
apiKeysV100,
|
|
353
|
+
createSettingsTable("1.0.0")
|
|
354
|
+
]
|
|
355
|
+
});
|
|
356
|
+
//#endregion
|
|
357
|
+
export { apiKeysV100, bundleEventsV100, bundlePatchesV100, bundlesV100, channelsV100, releaseCatalogsV100, releasesV100, v1_0_0 };
|
package/dist/storageAccess.cjs
CHANGED
|
@@ -1,41 +1,85 @@
|
|
|
1
|
+
require("./_virtual/_rolldown/runtime.cjs");
|
|
2
|
+
let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
|
|
1
3
|
//#region src/storageAccess.ts
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
} catch {}
|
|
7
|
-
throw new Error("Storage plugin returned a local file path; runtime update checks require an HTTP(S) download URL.");
|
|
4
|
+
const assertRemoteUrl = (value) => {
|
|
5
|
+
const protocol = new URL(value).protocol;
|
|
6
|
+
if (protocol !== "http:" && protocol !== "https:") throw new Error("Storage getDownloadUrl must resolve to an HTTP(S) URL.");
|
|
7
|
+
return value;
|
|
8
8
|
};
|
|
9
9
|
const getStorageProtocol = (storageUri) => new URL(storageUri).protocol.replace(":", "");
|
|
10
10
|
const isRemoteUrlProtocol = (protocol) => protocol === "http" || protocol === "https";
|
|
11
|
+
const resolveDownloadPath = (value, storageUri) => {
|
|
12
|
+
const parsed = (0, _hot_updater_plugin_core.parseStorageDownloadPath)(value);
|
|
13
|
+
if (!parsed || parsed.storageUri !== storageUri) throw new Error("Storage getDownloadUrl must return an HTTP(S) URL or a valid storage download path.");
|
|
14
|
+
return value;
|
|
15
|
+
};
|
|
16
|
+
const tokensEqual = (left, right) => {
|
|
17
|
+
const leftBytes = new TextEncoder().encode(left);
|
|
18
|
+
const rightBytes = new TextEncoder().encode(right);
|
|
19
|
+
let difference = leftBytes.length ^ rightBytes.length;
|
|
20
|
+
const length = Math.max(leftBytes.length, rightBytes.length);
|
|
21
|
+
for (let index = 0; index < length; index += 1) difference |= (leftBytes[index] ?? 0) ^ (rightBytes[index] ?? 0);
|
|
22
|
+
return difference === 0;
|
|
23
|
+
};
|
|
11
24
|
const createStorageAccess = (storagePlugins) => {
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
25
|
+
const protocols = /* @__PURE__ */ new Set();
|
|
26
|
+
for (const storage of storagePlugins) {
|
|
27
|
+
if (protocols.has(storage.protocol)) throw new Error(`Multiple storage plugins handle protocol: ${storage.protocol}`);
|
|
28
|
+
protocols.add(storage.protocol);
|
|
29
|
+
}
|
|
30
|
+
const findStorage = (protocol) => storagePlugins.find((item) => item.protocol === protocol);
|
|
31
|
+
const readStorageResponse = async (storageUri) => {
|
|
17
32
|
const protocol = getStorageProtocol(storageUri);
|
|
18
|
-
const
|
|
19
|
-
if (
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return
|
|
33
|
+
const storage = findStorage(protocol);
|
|
34
|
+
if (storage) return (await storage.get({ storageUri })).response;
|
|
35
|
+
if (isRemoteUrlProtocol(protocol)) {
|
|
36
|
+
const response = await fetch(storageUri);
|
|
37
|
+
return response.ok ? response : null;
|
|
23
38
|
}
|
|
24
|
-
if (isRemoteUrlProtocol(protocol)) return storageUri;
|
|
25
39
|
throw new Error(`No storage plugin for protocol: ${protocol}`);
|
|
26
40
|
};
|
|
27
|
-
const
|
|
41
|
+
const resolveFileUrl = async (storageUri) => {
|
|
42
|
+
if (!storageUri) return null;
|
|
28
43
|
const protocol = getStorageProtocol(storageUri);
|
|
29
|
-
const
|
|
30
|
-
if (
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (!response.ok) return null;
|
|
34
|
-
return response.text();
|
|
44
|
+
const storage = findStorage(protocol);
|
|
45
|
+
if (!storage) {
|
|
46
|
+
if (isRemoteUrlProtocol(protocol)) return storageUri;
|
|
47
|
+
throw new Error(`No storage plugin for protocol: ${protocol}`);
|
|
35
48
|
}
|
|
36
|
-
throw new Error(`
|
|
49
|
+
if (!storage.getDownloadUrl) throw new Error(`Storage plugin "${storage.name}" does not implement getDownloadUrl.`);
|
|
50
|
+
const { url: downloadUrl } = await storage.getDownloadUrl({ storageUri });
|
|
51
|
+
try {
|
|
52
|
+
return assertRemoteUrl(downloadUrl);
|
|
53
|
+
} catch (error) {
|
|
54
|
+
if (/^[a-z][a-z\d+.-]*:/i.test(downloadUrl)) throw error;
|
|
55
|
+
}
|
|
56
|
+
return resolveDownloadPath(downloadUrl, storageUri);
|
|
57
|
+
};
|
|
58
|
+
const readStorageText = async (storageUri) => {
|
|
59
|
+
return (await readStorageResponse(storageUri))?.text() ?? null;
|
|
37
60
|
};
|
|
38
61
|
return {
|
|
62
|
+
downloadStorageObject: storagePlugins.some((storage) => storage.getDownloadUrl !== void 0) ? async (storageUriToken, encodedSignature) => {
|
|
63
|
+
const requestedPath = `/storage/${storageUriToken}/${encodedSignature}`;
|
|
64
|
+
const requested = (0, _hot_updater_plugin_core.parseStorageDownloadPath)(requestedPath);
|
|
65
|
+
if (!requested) return null;
|
|
66
|
+
let storage;
|
|
67
|
+
try {
|
|
68
|
+
storage = findStorage(getStorageProtocol(requested.storageUri));
|
|
69
|
+
} catch {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
if (!storage?.getDownloadUrl) return null;
|
|
73
|
+
const { url: downloadUrl } = await storage.getDownloadUrl({ storageUri: requested.storageUri });
|
|
74
|
+
try {
|
|
75
|
+
new URL(downloadUrl);
|
|
76
|
+
return null;
|
|
77
|
+
} catch {
|
|
78
|
+
if (/^[a-z][a-z\d+.-]*:/i.test(downloadUrl)) return null;
|
|
79
|
+
}
|
|
80
|
+
if (!tokensEqual(downloadUrl, requestedPath)) return null;
|
|
81
|
+
return (await storage.get({ storageUri: requested.storageUri })).response;
|
|
82
|
+
} : void 0,
|
|
39
83
|
readStorageText,
|
|
40
84
|
resolveFileUrl
|
|
41
85
|
};
|
package/dist/storageAccess.mjs
CHANGED
|
@@ -1,41 +1,84 @@
|
|
|
1
|
+
import { parseStorageDownloadPath } from "@hot-updater/plugin-core";
|
|
1
2
|
//#region src/storageAccess.ts
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
} catch {}
|
|
7
|
-
throw new Error("Storage plugin returned a local file path; runtime update checks require an HTTP(S) download URL.");
|
|
3
|
+
const assertRemoteUrl = (value) => {
|
|
4
|
+
const protocol = new URL(value).protocol;
|
|
5
|
+
if (protocol !== "http:" && protocol !== "https:") throw new Error("Storage getDownloadUrl must resolve to an HTTP(S) URL.");
|
|
6
|
+
return value;
|
|
8
7
|
};
|
|
9
8
|
const getStorageProtocol = (storageUri) => new URL(storageUri).protocol.replace(":", "");
|
|
10
9
|
const isRemoteUrlProtocol = (protocol) => protocol === "http" || protocol === "https";
|
|
10
|
+
const resolveDownloadPath = (value, storageUri) => {
|
|
11
|
+
const parsed = parseStorageDownloadPath(value);
|
|
12
|
+
if (!parsed || parsed.storageUri !== storageUri) throw new Error("Storage getDownloadUrl must return an HTTP(S) URL or a valid storage download path.");
|
|
13
|
+
return value;
|
|
14
|
+
};
|
|
15
|
+
const tokensEqual = (left, right) => {
|
|
16
|
+
const leftBytes = new TextEncoder().encode(left);
|
|
17
|
+
const rightBytes = new TextEncoder().encode(right);
|
|
18
|
+
let difference = leftBytes.length ^ rightBytes.length;
|
|
19
|
+
const length = Math.max(leftBytes.length, rightBytes.length);
|
|
20
|
+
for (let index = 0; index < length; index += 1) difference |= (leftBytes[index] ?? 0) ^ (rightBytes[index] ?? 0);
|
|
21
|
+
return difference === 0;
|
|
22
|
+
};
|
|
11
23
|
const createStorageAccess = (storagePlugins) => {
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
24
|
+
const protocols = /* @__PURE__ */ new Set();
|
|
25
|
+
for (const storage of storagePlugins) {
|
|
26
|
+
if (protocols.has(storage.protocol)) throw new Error(`Multiple storage plugins handle protocol: ${storage.protocol}`);
|
|
27
|
+
protocols.add(storage.protocol);
|
|
28
|
+
}
|
|
29
|
+
const findStorage = (protocol) => storagePlugins.find((item) => item.protocol === protocol);
|
|
30
|
+
const readStorageResponse = async (storageUri) => {
|
|
17
31
|
const protocol = getStorageProtocol(storageUri);
|
|
18
|
-
const
|
|
19
|
-
if (
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return
|
|
32
|
+
const storage = findStorage(protocol);
|
|
33
|
+
if (storage) return (await storage.get({ storageUri })).response;
|
|
34
|
+
if (isRemoteUrlProtocol(protocol)) {
|
|
35
|
+
const response = await fetch(storageUri);
|
|
36
|
+
return response.ok ? response : null;
|
|
23
37
|
}
|
|
24
|
-
if (isRemoteUrlProtocol(protocol)) return storageUri;
|
|
25
38
|
throw new Error(`No storage plugin for protocol: ${protocol}`);
|
|
26
39
|
};
|
|
27
|
-
const
|
|
40
|
+
const resolveFileUrl = async (storageUri) => {
|
|
41
|
+
if (!storageUri) return null;
|
|
28
42
|
const protocol = getStorageProtocol(storageUri);
|
|
29
|
-
const
|
|
30
|
-
if (
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (!response.ok) return null;
|
|
34
|
-
return response.text();
|
|
43
|
+
const storage = findStorage(protocol);
|
|
44
|
+
if (!storage) {
|
|
45
|
+
if (isRemoteUrlProtocol(protocol)) return storageUri;
|
|
46
|
+
throw new Error(`No storage plugin for protocol: ${protocol}`);
|
|
35
47
|
}
|
|
36
|
-
throw new Error(`
|
|
48
|
+
if (!storage.getDownloadUrl) throw new Error(`Storage plugin "${storage.name}" does not implement getDownloadUrl.`);
|
|
49
|
+
const { url: downloadUrl } = await storage.getDownloadUrl({ storageUri });
|
|
50
|
+
try {
|
|
51
|
+
return assertRemoteUrl(downloadUrl);
|
|
52
|
+
} catch (error) {
|
|
53
|
+
if (/^[a-z][a-z\d+.-]*:/i.test(downloadUrl)) throw error;
|
|
54
|
+
}
|
|
55
|
+
return resolveDownloadPath(downloadUrl, storageUri);
|
|
56
|
+
};
|
|
57
|
+
const readStorageText = async (storageUri) => {
|
|
58
|
+
return (await readStorageResponse(storageUri))?.text() ?? null;
|
|
37
59
|
};
|
|
38
60
|
return {
|
|
61
|
+
downloadStorageObject: storagePlugins.some((storage) => storage.getDownloadUrl !== void 0) ? async (storageUriToken, encodedSignature) => {
|
|
62
|
+
const requestedPath = `/storage/${storageUriToken}/${encodedSignature}`;
|
|
63
|
+
const requested = parseStorageDownloadPath(requestedPath);
|
|
64
|
+
if (!requested) return null;
|
|
65
|
+
let storage;
|
|
66
|
+
try {
|
|
67
|
+
storage = findStorage(getStorageProtocol(requested.storageUri));
|
|
68
|
+
} catch {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
if (!storage?.getDownloadUrl) return null;
|
|
72
|
+
const { url: downloadUrl } = await storage.getDownloadUrl({ storageUri: requested.storageUri });
|
|
73
|
+
try {
|
|
74
|
+
new URL(downloadUrl);
|
|
75
|
+
return null;
|
|
76
|
+
} catch {
|
|
77
|
+
if (/^[a-z][a-z\d+.-]*:/i.test(downloadUrl)) return null;
|
|
78
|
+
}
|
|
79
|
+
if (!tokensEqual(downloadUrl, requestedPath)) return null;
|
|
80
|
+
return (await storage.get({ storageUri: requested.storageUri })).response;
|
|
81
|
+
} : void 0,
|
|
39
82
|
readStorageText,
|
|
40
83
|
resolveFileUrl
|
|
41
84
|
};
|
package/dist/types/index.d.cts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { HotUpdaterAPI } from "../createHotUpdaterCore.cjs";
|
|
2
|
-
import { Bundle, Bundle as Bundle$
|
|
2
|
+
import { Bundle, Bundle as Bundle$2 } from "@hot-updater/core";
|
|
3
|
+
import { ChannelRow } from "@hot-updater/plugin-core";
|
|
3
4
|
|
|
4
5
|
//#region src/types/index.d.ts
|
|
5
6
|
interface PaginationInfo {
|
|
@@ -23,7 +24,7 @@ interface Paginated<TData> extends DataResponse<TData> {
|
|
|
23
24
|
}
|
|
24
25
|
type PaginatedResult = Paginated<Bundle[]>;
|
|
25
26
|
type ChannelsResponse = DataResponse<{
|
|
26
|
-
channels:
|
|
27
|
+
channels: readonly ChannelRow[];
|
|
27
28
|
}>;
|
|
28
29
|
//#endregion
|
|
29
|
-
export { type Bundle$
|
|
30
|
+
export { type Bundle$2 as Bundle, ChannelsResponse, DataResponse, Paginated, PaginatedResult, PaginationInfo, PaginationOptions };
|
package/dist/types/index.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { HotUpdaterAPI } from "../createHotUpdaterCore.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { ChannelRow } from "@hot-updater/plugin-core";
|
|
3
|
+
import { Bundle as Bundle$1, Bundle as Bundle$2 } from "@hot-updater/core";
|
|
3
4
|
|
|
4
5
|
//#region src/types/index.d.ts
|
|
5
6
|
interface PaginationInfo {
|
|
@@ -21,9 +22,9 @@ interface DataResponse<TData> {
|
|
|
21
22
|
interface Paginated<TData> extends DataResponse<TData> {
|
|
22
23
|
pagination: PaginationInfo;
|
|
23
24
|
}
|
|
24
|
-
type PaginatedResult = Paginated<Bundle[]>;
|
|
25
|
+
type PaginatedResult = Paginated<Bundle$1[]>;
|
|
25
26
|
type ChannelsResponse = DataResponse<{
|
|
26
|
-
channels:
|
|
27
|
+
channels: readonly ChannelRow[];
|
|
27
28
|
}>;
|
|
28
29
|
//#endregion
|
|
29
|
-
export { type Bundle$
|
|
30
|
+
export { type Bundle$2 as Bundle, ChannelsResponse, DataResponse, Paginated, PaginatedResult, PaginationInfo, PaginationOptions };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hot-updater/server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0-rc.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "React Native OTA solution for self-hosted",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -55,10 +55,9 @@
|
|
|
55
55
|
"dependencies": {
|
|
56
56
|
"rou3": "0.7.9",
|
|
57
57
|
"verkit": "0.3.2",
|
|
58
|
-
"@hot-updater/
|
|
59
|
-
"@hot-updater/
|
|
60
|
-
"@hot-updater/
|
|
61
|
-
"@hot-updater/js": "0.36.6"
|
|
58
|
+
"@hot-updater/plugin-core": "1.0.0-rc.0",
|
|
59
|
+
"@hot-updater/bsdiff": "1.0.0-rc.0",
|
|
60
|
+
"@hot-updater/core": "1.0.0-rc.0"
|
|
62
61
|
},
|
|
63
62
|
"peerDependencies": {
|
|
64
63
|
"@prisma/client": "*",
|
|
@@ -82,16 +81,18 @@
|
|
|
82
81
|
},
|
|
83
82
|
"devDependencies": {
|
|
84
83
|
"@electric-sql/pglite": "0.4.1",
|
|
84
|
+
"@types/express": "^5.0.0",
|
|
85
85
|
"@types/node": "^20",
|
|
86
86
|
"drizzle-orm": "0.45.2",
|
|
87
|
+
"express": "^4.22.2",
|
|
87
88
|
"execa": "9.5.2",
|
|
88
89
|
"kysely": "0.28.17",
|
|
89
90
|
"kysely-pglite-dialect": "1.2.0",
|
|
90
91
|
"mongodb": "6.20.0",
|
|
91
92
|
"msw": "^2.7.0",
|
|
92
93
|
"uuidv7": "^1.0.2",
|
|
93
|
-
"@hot-updater/standalone": "0.
|
|
94
|
-
"@hot-updater/test-utils": "0.
|
|
94
|
+
"@hot-updater/standalone": "1.0.0-rc.0",
|
|
95
|
+
"@hot-updater/test-utils": "1.0.0-rc.0"
|
|
95
96
|
},
|
|
96
97
|
"scripts": {
|
|
97
98
|
"build": "tsdown",
|