@hot-updater/postgres 1.0.0-rc.1 → 1.0.0-rc.14
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/index.cjs +34 -3
- package/dist/index.d.cts +1 -3
- package/dist/index.d.mts +1 -3
- package/dist/index.mjs +33 -2
- package/package.json +4 -4
- package/sql/bundles.sql +30 -18
package/dist/index.cjs
CHANGED
|
@@ -16,7 +16,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
16
16
|
}
|
|
17
17
|
return to;
|
|
18
18
|
};
|
|
19
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
|
|
20
20
|
value: mod,
|
|
21
21
|
enumerable: true
|
|
22
22
|
}) : target, mod));
|
|
@@ -25,7 +25,7 @@ let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
|
|
|
25
25
|
let _hot_updater_plugin_core_internal = require("@hot-updater/plugin-core/internal");
|
|
26
26
|
let kysely = require("kysely");
|
|
27
27
|
let pg = require("pg");
|
|
28
|
-
pg = __toESM(pg);
|
|
28
|
+
pg = __toESM(pg, 1);
|
|
29
29
|
//#region src/postgresQuery.ts
|
|
30
30
|
const applyOrder = (order, clause) => {
|
|
31
31
|
const directed = clause.direction === "asc" ? order.asc() : order.desc();
|
|
@@ -51,6 +51,11 @@ const countPostgresRows = async (db, input, where) => {
|
|
|
51
51
|
const query = rows.select(({ fn }) => fn.countAll().as("count"));
|
|
52
52
|
return Number((await query.executeTakeFirstOrThrow()).count);
|
|
53
53
|
}
|
|
54
|
+
case "bundle_events": {
|
|
55
|
+
let rows = db.selectFrom("bundle_events");
|
|
56
|
+
if (where !== void 0) rows = rows.where(where);
|
|
57
|
+
return Number((await rows.select(({ fn }) => fn.countAll().as("count")).executeTakeFirstOrThrow()).count);
|
|
58
|
+
}
|
|
54
59
|
}
|
|
55
60
|
};
|
|
56
61
|
const findManyPostgresRows = async (db, input, where) => {
|
|
@@ -152,6 +157,28 @@ const buildWhere = (where) => {
|
|
|
152
157
|
return expression;
|
|
153
158
|
};
|
|
154
159
|
const createPostgresImplementation = (db) => ({
|
|
160
|
+
async recordInsights({ event }) {
|
|
161
|
+
await db.transaction().execute(async (transaction) => {
|
|
162
|
+
await transaction.insertInto("bundle_events").values(event).onConflict((oc) => oc.column("id").doNothing()).execute();
|
|
163
|
+
await kysely.sql`INSERT INTO bundle_event_heads (install_id, id, received_at_ms, user_id, platform, channel, type, from_bundle_id, to_bundle_id)
|
|
164
|
+
SELECT install_id, id, received_at_ms, user_id, platform, channel, type, from_bundle_id, to_bundle_id
|
|
165
|
+
FROM bundle_events WHERE id = ${event.id}
|
|
166
|
+
ON CONFLICT(install_id) DO UPDATE SET
|
|
167
|
+
id = excluded.id, received_at_ms = excluded.received_at_ms, user_id = excluded.user_id,
|
|
168
|
+
platform = excluded.platform, channel = excluded.channel, type = excluded.type,
|
|
169
|
+
from_bundle_id = excluded.from_bundle_id, to_bundle_id = excluded.to_bundle_id
|
|
170
|
+
WHERE (excluded.received_at_ms, excluded.id) > (bundle_event_heads.received_at_ms, bundle_event_heads.id)`.execute(transaction);
|
|
171
|
+
});
|
|
172
|
+
},
|
|
173
|
+
async findLatestInsightsEvents(input) {
|
|
174
|
+
const where = buildWhere((0, _hot_updater_plugin_core_internal.latestInsightsWhere)(input));
|
|
175
|
+
return (await kysely.sql`SELECT event.* FROM (SELECT id, install_id FROM bundle_event_heads WHERE ${where} ORDER BY install_id ASC LIMIT ${"installId" in input ? 1 : input.limit}) AS head JOIN bundle_events AS event ON event.id = head.id ORDER BY head.install_id ASC`.execute(db)).rows;
|
|
176
|
+
},
|
|
177
|
+
async countLatestInsightsEvents(input) {
|
|
178
|
+
const where = kysely.sql`(${kysely.sql.join((0, _hot_updater_plugin_core_internal.latestInsightsCountGroups)(input).map((where) => kysely.sql`(${buildWhere(where)})`), kysely.sql` OR `)})`;
|
|
179
|
+
const result = await kysely.sql`SELECT COUNT(*) AS count FROM bundle_event_heads WHERE ${where}`.execute(db);
|
|
180
|
+
return Number(result.rows[0]?.count ?? 0);
|
|
181
|
+
},
|
|
155
182
|
async create(input) {
|
|
156
183
|
switch (input.model) {
|
|
157
184
|
case "bundles": return db.insertInto("bundles").values(input.data).returningAll().executeTakeFirstOrThrow();
|
|
@@ -286,7 +313,11 @@ const createPostgresImplementation = (db) => ({
|
|
|
286
313
|
});
|
|
287
314
|
const postgres = (config) => {
|
|
288
315
|
const { dialect, ...poolConfig } = config;
|
|
289
|
-
const
|
|
316
|
+
const implementation = dialect !== void 0 ? createPostgresImplementation(new kysely.Kysely({ dialect })) : (() => {
|
|
317
|
+
const pool = new Pool(poolConfig);
|
|
318
|
+
return createPostgresImplementation(new kysely.Kysely({ dialect: new kysely.PostgresDialect({ pool }) }));
|
|
319
|
+
})();
|
|
320
|
+
const adapter = (0, _hot_updater_plugin_core_internal.createDatabasePluginAdapter)("postgres", implementation);
|
|
290
321
|
return (0, _hot_updater_plugin_core.createDatabasePlugin)({
|
|
291
322
|
name: "postgres",
|
|
292
323
|
models: adapter.models,
|
package/dist/index.d.cts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import * as _$_hot_updater_plugin_core0 from "@hot-updater/plugin-core";
|
|
2
1
|
import { Dialect } from "kysely";
|
|
3
2
|
import { PoolConfig } from "pg";
|
|
4
|
-
|
|
5
3
|
//#region src/postgres.d.ts
|
|
6
4
|
type PostgresConfig = PoolConfig & {
|
|
7
5
|
readonly dialect?: Dialect;
|
|
8
6
|
};
|
|
9
|
-
declare const postgres: (config: PostgresConfig) =>
|
|
7
|
+
declare const postgres: (config: PostgresConfig) => import("@hot-updater/plugin-core").DatabasePlugin;
|
|
10
8
|
//#endregion
|
|
11
9
|
export { PostgresConfig, postgres };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import * as _$_hot_updater_plugin_core0 from "@hot-updater/plugin-core";
|
|
2
1
|
import { Dialect } from "kysely";
|
|
3
2
|
import { PoolConfig } from "pg";
|
|
4
|
-
|
|
5
3
|
//#region src/postgres.d.ts
|
|
6
4
|
type PostgresConfig = PoolConfig & {
|
|
7
5
|
readonly dialect?: Dialect;
|
|
8
6
|
};
|
|
9
|
-
declare const postgres: (config: PostgresConfig) =>
|
|
7
|
+
declare const postgres: (config: PostgresConfig) => import("@hot-updater/plugin-core").DatabasePlugin;
|
|
10
8
|
//#endregion
|
|
11
9
|
export { PostgresConfig, postgres };
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createDatabasePlugin } from "@hot-updater/plugin-core";
|
|
2
|
-
import { DatabaseRowReferencedError, createDatabasePluginAdapter } from "@hot-updater/plugin-core/internal";
|
|
2
|
+
import { DatabaseRowReferencedError, createDatabasePluginAdapter, latestInsightsCountGroups, latestInsightsWhere } from "@hot-updater/plugin-core/internal";
|
|
3
3
|
import { Kysely, PostgresDialect, sql } from "kysely";
|
|
4
4
|
import pg from "pg";
|
|
5
5
|
//#region src/postgresQuery.ts
|
|
@@ -27,6 +27,11 @@ const countPostgresRows = async (db, input, where) => {
|
|
|
27
27
|
const query = rows.select(({ fn }) => fn.countAll().as("count"));
|
|
28
28
|
return Number((await query.executeTakeFirstOrThrow()).count);
|
|
29
29
|
}
|
|
30
|
+
case "bundle_events": {
|
|
31
|
+
let rows = db.selectFrom("bundle_events");
|
|
32
|
+
if (where !== void 0) rows = rows.where(where);
|
|
33
|
+
return Number((await rows.select(({ fn }) => fn.countAll().as("count")).executeTakeFirstOrThrow()).count);
|
|
34
|
+
}
|
|
30
35
|
}
|
|
31
36
|
};
|
|
32
37
|
const findManyPostgresRows = async (db, input, where) => {
|
|
@@ -128,6 +133,28 @@ const buildWhere = (where) => {
|
|
|
128
133
|
return expression;
|
|
129
134
|
};
|
|
130
135
|
const createPostgresImplementation = (db) => ({
|
|
136
|
+
async recordInsights({ event }) {
|
|
137
|
+
await db.transaction().execute(async (transaction) => {
|
|
138
|
+
await transaction.insertInto("bundle_events").values(event).onConflict((oc) => oc.column("id").doNothing()).execute();
|
|
139
|
+
await sql`INSERT INTO bundle_event_heads (install_id, id, received_at_ms, user_id, platform, channel, type, from_bundle_id, to_bundle_id)
|
|
140
|
+
SELECT install_id, id, received_at_ms, user_id, platform, channel, type, from_bundle_id, to_bundle_id
|
|
141
|
+
FROM bundle_events WHERE id = ${event.id}
|
|
142
|
+
ON CONFLICT(install_id) DO UPDATE SET
|
|
143
|
+
id = excluded.id, received_at_ms = excluded.received_at_ms, user_id = excluded.user_id,
|
|
144
|
+
platform = excluded.platform, channel = excluded.channel, type = excluded.type,
|
|
145
|
+
from_bundle_id = excluded.from_bundle_id, to_bundle_id = excluded.to_bundle_id
|
|
146
|
+
WHERE (excluded.received_at_ms, excluded.id) > (bundle_event_heads.received_at_ms, bundle_event_heads.id)`.execute(transaction);
|
|
147
|
+
});
|
|
148
|
+
},
|
|
149
|
+
async findLatestInsightsEvents(input) {
|
|
150
|
+
const where = buildWhere(latestInsightsWhere(input));
|
|
151
|
+
return (await sql`SELECT event.* FROM (SELECT id, install_id FROM bundle_event_heads WHERE ${where} ORDER BY install_id ASC LIMIT ${"installId" in input ? 1 : input.limit}) AS head JOIN bundle_events AS event ON event.id = head.id ORDER BY head.install_id ASC`.execute(db)).rows;
|
|
152
|
+
},
|
|
153
|
+
async countLatestInsightsEvents(input) {
|
|
154
|
+
const where = sql`(${sql.join(latestInsightsCountGroups(input).map((where) => sql`(${buildWhere(where)})`), sql` OR `)})`;
|
|
155
|
+
const result = await sql`SELECT COUNT(*) AS count FROM bundle_event_heads WHERE ${where}`.execute(db);
|
|
156
|
+
return Number(result.rows[0]?.count ?? 0);
|
|
157
|
+
},
|
|
131
158
|
async create(input) {
|
|
132
159
|
switch (input.model) {
|
|
133
160
|
case "bundles": return db.insertInto("bundles").values(input.data).returningAll().executeTakeFirstOrThrow();
|
|
@@ -262,7 +289,11 @@ const createPostgresImplementation = (db) => ({
|
|
|
262
289
|
});
|
|
263
290
|
const postgres = (config) => {
|
|
264
291
|
const { dialect, ...poolConfig } = config;
|
|
265
|
-
const
|
|
292
|
+
const implementation = dialect !== void 0 ? createPostgresImplementation(new Kysely({ dialect })) : (() => {
|
|
293
|
+
const pool = new Pool(poolConfig);
|
|
294
|
+
return createPostgresImplementation(new Kysely({ dialect: new PostgresDialect({ pool }) }));
|
|
295
|
+
})();
|
|
296
|
+
const adapter = createDatabasePluginAdapter("postgres", implementation);
|
|
266
297
|
return createDatabasePlugin({
|
|
267
298
|
name: "postgres",
|
|
268
299
|
models: adapter.models,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hot-updater/postgres",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.0-rc.
|
|
4
|
+
"version": "1.0.0-rc.14",
|
|
5
5
|
"description": "React Native OTA solution for self-hosted",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
7
7
|
"module": "./dist/index.mjs",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"kysely": "0.28.17",
|
|
36
36
|
"pg": "8.13.1",
|
|
37
|
-
"@hot-updater/core": "1.0.0-rc.
|
|
38
|
-
"@hot-updater/plugin-core": "1.0.0-rc.
|
|
37
|
+
"@hot-updater/core": "1.0.0-rc.14",
|
|
38
|
+
"@hot-updater/plugin-core": "1.0.0-rc.14"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@electric-sql/pglite": "0.4.1",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"camelcase-keys": "^9.1.3",
|
|
45
45
|
"kysely-pglite-dialect": "1.2.0",
|
|
46
46
|
"pg-minify": "^1.6.5",
|
|
47
|
-
"@hot-updater/test-utils": "1.0.0-rc.
|
|
47
|
+
"@hot-updater/test-utils": "1.0.0-rc.14"
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
50
|
"build": "tsdown",
|
package/sql/bundles.sql
CHANGED
|
@@ -70,23 +70,32 @@ create table release_catalogs (
|
|
|
70
70
|
create table bundle_events (
|
|
71
71
|
id uuid primary key not null,
|
|
72
72
|
type text not null,
|
|
73
|
-
install_id text not null,
|
|
74
|
-
user_id text,
|
|
75
|
-
username text,
|
|
73
|
+
install_id text collate "C" not null,
|
|
74
|
+
user_id text collate "C",
|
|
76
75
|
from_release_id uuid,
|
|
77
76
|
from_bundle_id uuid,
|
|
78
77
|
to_release_id uuid,
|
|
79
78
|
to_bundle_id uuid not null,
|
|
80
|
-
platform text not null,
|
|
79
|
+
platform text collate "C" not null,
|
|
81
80
|
app_version text not null,
|
|
82
|
-
channel text not null,
|
|
83
|
-
|
|
84
|
-
update_strategy text,
|
|
85
|
-
fingerprint_hash text,
|
|
86
|
-
sdk_version text,
|
|
81
|
+
channel text collate "C" not null,
|
|
82
|
+
metadata JSONB NOT NULL,
|
|
87
83
|
received_at_ms double precision not null
|
|
88
84
|
);
|
|
89
85
|
|
|
86
|
+
|
|
87
|
+
create table bundle_event_heads (
|
|
88
|
+
install_id text collate "C" primary key not null,
|
|
89
|
+
id uuid not null,
|
|
90
|
+
received_at_ms double precision not null,
|
|
91
|
+
user_id text collate "C",
|
|
92
|
+
platform text collate "C" not null,
|
|
93
|
+
channel text collate "C" not null,
|
|
94
|
+
type text not null,
|
|
95
|
+
from_bundle_id uuid,
|
|
96
|
+
to_bundle_id uuid not null
|
|
97
|
+
);
|
|
98
|
+
|
|
90
99
|
create table api_keys (
|
|
91
100
|
id varchar(255) primary key not null,
|
|
92
101
|
hash text not null,
|
|
@@ -112,13 +121,9 @@ create index releases_fingerprint_hash_idx on releases(fingerprint_hash);
|
|
|
112
121
|
create index releases_enabled_idx on releases(enabled);
|
|
113
122
|
create index release_catalogs_channel_idx on release_catalogs(channel_id);
|
|
114
123
|
create index bundle_events_received_at_idx on bundle_events(received_at_ms, id);
|
|
115
|
-
create index bundle_events_install_idx on bundle_events(install_id, received_at_ms, id);
|
|
116
|
-
create index
|
|
117
|
-
create index
|
|
118
|
-
create index bundle_events_to_bundle_idx on bundle_events(type, to_bundle_id, received_at_ms, id);
|
|
119
|
-
create index bundle_events_from_bundle_idx on bundle_events(type, from_bundle_id, received_at_ms, id);
|
|
120
|
-
create index bundle_events_to_release_idx on bundle_events(type, to_release_id, received_at_ms, id);
|
|
121
|
-
create index bundle_events_from_release_idx on bundle_events(type, from_release_id, received_at_ms, id);
|
|
124
|
+
create index bundle_events_install_idx on bundle_events(install_id, type, received_at_ms, id);
|
|
125
|
+
create index bundle_events_from_bundle_idx on bundle_events(type, platform, channel, from_bundle_id, received_at_ms, id);
|
|
126
|
+
create index bundle_events_to_bundle_idx on bundle_events(type, platform, channel, to_bundle_id, received_at_ms, id);
|
|
122
127
|
create unique index api_keys_hash_key on api_keys(hash);
|
|
123
128
|
create index api_keys_created_at_idx on api_keys(created_at_ms, id);
|
|
124
129
|
|
|
@@ -147,11 +152,11 @@ alter table release_catalogs add constraint release_catalogs_generation_check
|
|
|
147
152
|
alter table release_catalogs add constraint release_catalogs_byte_size_check
|
|
148
153
|
check (byte_size >= 0 and byte_size <= 262144);
|
|
149
154
|
alter table bundle_events add constraint bundle_events_type_check
|
|
150
|
-
check (type in ('
|
|
155
|
+
check (type in ('UPDATE_DOWNLOADED', 'UPDATE_APPLIED', 'RECOVERED', 'UNCHANGED'));
|
|
151
156
|
alter table bundle_events add constraint bundle_events_platform_check
|
|
152
157
|
check (platform in ('ios', 'android'));
|
|
153
158
|
alter table bundle_events add constraint bundle_events_shape_check
|
|
154
|
-
check (((type in ('
|
|
159
|
+
check (((type in ('UPDATE_DOWNLOADED', 'UPDATE_APPLIED', 'RECOVERED')) and from_bundle_id is not null) or (type = 'UNCHANGED' and from_bundle_id is null));
|
|
155
160
|
alter table bundle_events add constraint bundle_events_received_at_check
|
|
156
161
|
check (received_at_ms >= 0);
|
|
157
162
|
alter table api_keys add constraint api_keys_role_check
|
|
@@ -177,3 +182,10 @@ alter table release_catalogs add constraint release_catalogs_channel_id_fk
|
|
|
177
182
|
insert into private_hot_updater_settings (key, value)
|
|
178
183
|
values ('schema.core', '1.0.0')
|
|
179
184
|
on conflict (key) do update set value = excluded.value;
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
CREATE INDEX bundle_events_latest_idx ON bundle_events(install_id, received_at_ms, id);
|
|
188
|
+
CREATE INDEX bundle_event_heads_user_idx ON bundle_event_heads(user_id, install_id);
|
|
189
|
+
CREATE INDEX bundle_event_heads_scope_idx ON bundle_event_heads(platform, channel, received_at_ms);
|
|
190
|
+
CREATE INDEX bundle_event_heads_from_idx ON bundle_event_heads(type, platform, channel, from_bundle_id, received_at_ms);
|
|
191
|
+
CREATE INDEX bundle_event_heads_to_idx ON bundle_event_heads(type, platform, channel, to_bundle_id, received_at_ms);
|