@voltro/plugin-releases 0.83.1 → 0.85.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/CHANGELOG.md +1191 -0
- package/THIRD-PARTY-NOTICES.md +123 -577
- package/dist/errors.d.ts +10 -12
- package/dist/errors.js +5 -1
- package/dist/index.d.ts +22 -20
- package/dist/index.js +342 -287
- package/dist/{rpc-U7ytx6SC.js → rpc-DrfZqJIA.js} +50 -35
- package/dist/rpc.d.ts +136 -114
- package/dist/rpc.js +1 -1
- package/dist/web.js +1 -1
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { ReleaseNotFound as e, ReleaseRefused as t } from "./errors.js";
|
|
2
2
|
import { a as n, i as r, n as i, o as a, r as o, s, t as c } from "./rollout-CGRKMTfv.js";
|
|
3
|
-
import { _ as l, a as u, c as
|
|
4
|
-
import { Effect as v } from "effect";
|
|
3
|
+
import { _ as l, a as u, c as ee, d as te, f as ne, g as d, h as f, l as re, m as ie, o as ae, p as oe, r as p, s as se, t as m, u as ce, v as h, y as g } from "./rpc-DrfZqJIA.js";
|
|
4
|
+
import { Effect as _, Result as v, Schema as le } from "effect";
|
|
5
5
|
import { randomBytes as y } from "node:crypto";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
|
|
6
|
+
import { AsyncLocalStorage as b } from "node:async_hooks";
|
|
7
|
+
import { definePlugin as ue } from "@voltro/protocol";
|
|
8
|
+
import { and as de, boolean as x, eq as S, id as C, inSet as fe, integer as w, json as T, queryFor as E, registerRetention as pe, retentionTtlMsFromEnv as me, table as D, text as O, timestamp as k } from "@voltro/database";
|
|
9
|
+
import { newTraceId as he } from "@voltro/runtime";
|
|
10
|
+
var ge = (e, t, n) => {
|
|
10
11
|
let r = /* @__PURE__ */ new Set();
|
|
11
12
|
for (let e of t) e.currentReleaseId !== null && r.add(e.currentReleaseId);
|
|
12
13
|
let i = [];
|
|
@@ -15,92 +16,93 @@ var fe = (e, t, n) => {
|
|
|
15
16
|
for (let e of s.slice(o)) r.has(e.id) || i.push(e);
|
|
16
17
|
}
|
|
17
18
|
return i;
|
|
18
|
-
},
|
|
19
|
+
}, A = [
|
|
19
20
|
"web",
|
|
20
21
|
"ios",
|
|
21
22
|
"android",
|
|
22
23
|
"macos",
|
|
23
24
|
"windows",
|
|
24
25
|
"linux"
|
|
25
|
-
],
|
|
26
|
+
], j = [
|
|
26
27
|
"pwa",
|
|
27
28
|
"expo",
|
|
28
29
|
"tauri",
|
|
29
30
|
"electron"
|
|
30
|
-
],
|
|
31
|
-
id:
|
|
32
|
-
app:
|
|
33
|
-
platform:
|
|
34
|
-
shell:
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
], M = D(d, {
|
|
32
|
+
id: C({ prefix: "relapp" }),
|
|
33
|
+
app: O(),
|
|
34
|
+
platform: O(),
|
|
35
|
+
shell: O(),
|
|
36
|
+
revision: w().default(0),
|
|
37
|
+
bundleId: O().nullable(),
|
|
38
|
+
updaterPublicKey: O().nullable(),
|
|
39
|
+
runtimeVersion: O().nullable(),
|
|
40
|
+
createdAt: k().default("now")
|
|
39
41
|
}).index("byReleaseAppTarget", [
|
|
40
42
|
"app",
|
|
41
43
|
"platform",
|
|
42
44
|
"shell"
|
|
43
|
-
]),
|
|
44
|
-
id:
|
|
45
|
-
appId:
|
|
46
|
-
name:
|
|
47
|
-
currentReleaseId:
|
|
48
|
-
minSupportedVersion:
|
|
49
|
-
killSwitches:
|
|
50
|
-
public:
|
|
51
|
-
allowUnsigned:
|
|
52
|
-
updatedAt:
|
|
53
|
-
}).index("byReleaseChannelApp", ["appId", "name"]),
|
|
54
|
-
id:
|
|
55
|
-
appId:
|
|
56
|
-
channelId:
|
|
57
|
-
version:
|
|
58
|
-
buildId:
|
|
59
|
-
notes:
|
|
60
|
-
state:
|
|
61
|
-
rolloutPercent:
|
|
62
|
-
rolloutSalt:
|
|
63
|
-
cohorts:
|
|
64
|
-
createdBy:
|
|
65
|
-
createdAt:
|
|
66
|
-
updatedAt:
|
|
67
|
-
}).index("byReleaseAppChannel", ["appId", "channelId"]).index("byReleaseVersion", ["appId", "version"]),
|
|
68
|
-
id:
|
|
69
|
-
releaseId:
|
|
70
|
-
kind:
|
|
71
|
-
target:
|
|
72
|
-
url:
|
|
73
|
-
sha256:
|
|
74
|
-
size:
|
|
75
|
-
signature:
|
|
76
|
-
notarized:
|
|
77
|
-
assetKey:
|
|
78
|
-
contentType:
|
|
79
|
-
createdAt:
|
|
80
|
-
}).index("byReleaseArtifactRelease", ["releaseId"]),
|
|
81
|
-
id:
|
|
82
|
-
appId:
|
|
83
|
-
channelId:
|
|
84
|
-
releaseId:
|
|
85
|
-
kind:
|
|
86
|
-
reason:
|
|
87
|
-
actorId:
|
|
88
|
-
detail:
|
|
89
|
-
at:
|
|
90
|
-
}).index("byReleaseEventApp", ["appId", "at"]),
|
|
91
|
-
k,
|
|
92
|
-
A,
|
|
93
|
-
j,
|
|
45
|
+
]), N = D(h, {
|
|
46
|
+
id: C({ prefix: "relch" }),
|
|
47
|
+
appId: O(),
|
|
48
|
+
name: O(),
|
|
49
|
+
currentReleaseId: O().nullable(),
|
|
50
|
+
minSupportedVersion: O().nullable(),
|
|
51
|
+
killSwitches: T().nullable(),
|
|
52
|
+
public: x().default(!1),
|
|
53
|
+
allowUnsigned: x().default(!1),
|
|
54
|
+
updatedAt: k().default("now").onUpdate("now")
|
|
55
|
+
}).index("byReleaseChannelApp", ["appId", "name"]), P = D(f, {
|
|
56
|
+
id: C({ prefix: "rel" }),
|
|
57
|
+
appId: O(),
|
|
58
|
+
channelId: O(),
|
|
59
|
+
version: O(),
|
|
60
|
+
buildId: O().nullable(),
|
|
61
|
+
notes: O().nullable(),
|
|
62
|
+
state: O().default("draft"),
|
|
63
|
+
rolloutPercent: w().default(0),
|
|
64
|
+
rolloutSalt: O(),
|
|
65
|
+
cohorts: T().nullable(),
|
|
66
|
+
createdBy: O().nullable(),
|
|
67
|
+
createdAt: k().default("now"),
|
|
68
|
+
updatedAt: k().default("now").onUpdate("now")
|
|
69
|
+
}).index("byReleaseAppChannel", ["appId", "channelId"]).index("byReleaseVersion", ["appId", "version"]), F = D(l, {
|
|
70
|
+
id: C({ prefix: "relart" }),
|
|
71
|
+
releaseId: O(),
|
|
72
|
+
kind: O(),
|
|
73
|
+
target: O().nullable(),
|
|
74
|
+
url: O(),
|
|
75
|
+
sha256: O(),
|
|
76
|
+
size: w(),
|
|
77
|
+
signature: O().nullable(),
|
|
78
|
+
notarized: x().default(!1),
|
|
79
|
+
assetKey: O().nullable(),
|
|
80
|
+
contentType: O().nullable(),
|
|
81
|
+
createdAt: k().default("now")
|
|
82
|
+
}).index("byReleaseArtifactRelease", ["releaseId"]), I = D(g, {
|
|
83
|
+
id: C({ prefix: "relev" }),
|
|
84
|
+
appId: O(),
|
|
85
|
+
channelId: O().nullable(),
|
|
86
|
+
releaseId: O().nullable(),
|
|
87
|
+
kind: O(),
|
|
88
|
+
reason: O().nullable(),
|
|
89
|
+
actorId: O().nullable(),
|
|
90
|
+
detail: T().nullable(),
|
|
91
|
+
at: k().default("now")
|
|
92
|
+
}).index("byReleaseEventApp", ["appId", "at"]), L = [
|
|
94
93
|
M,
|
|
95
|
-
N
|
|
96
|
-
|
|
94
|
+
N,
|
|
95
|
+
P,
|
|
96
|
+
F,
|
|
97
|
+
I
|
|
98
|
+
], R = (e, t) => t.currentVersion !== null && c(e.version, t.currentVersion) <= 0 ? !1 : o({
|
|
97
99
|
installId: t.installId,
|
|
98
100
|
salt: e.rolloutSalt,
|
|
99
101
|
percent: e.rolloutPercent,
|
|
100
102
|
...t.cohorts === void 0 ? {} : { installCohorts: t.cohorts },
|
|
101
103
|
releaseCohorts: e.cohorts
|
|
102
|
-
}),
|
|
103
|
-
if (!
|
|
104
|
+
}), z = (e, t) => {
|
|
105
|
+
if (!R(e, t)) return null;
|
|
104
106
|
let n = e.artifacts.find((e) => e.target === t.target && e.signature !== null);
|
|
105
107
|
return !n || n.signature === null ? null : {
|
|
106
108
|
version: e.version,
|
|
@@ -111,7 +113,7 @@ var fe = (e, t, n) => {
|
|
|
111
113
|
url: n.url
|
|
112
114
|
} }
|
|
113
115
|
};
|
|
114
|
-
},
|
|
116
|
+
}, B = (e, t, n = {}) => {
|
|
115
117
|
let r = {
|
|
116
118
|
win: [
|
|
117
119
|
"nsis",
|
|
@@ -136,14 +138,14 @@ var fe = (e, t, n) => {
|
|
|
136
138
|
a.push(`path: ${o.url}`);
|
|
137
139
|
let s = n[o.sha256];
|
|
138
140
|
return a.push(s === void 0 ? `sha256: ${o.sha256}` : `sha512: ${s}`), a.push(`releaseDate: '${e.createdAt.toISOString()}'`), e.notes && a.push(`releaseNotes: ${JSON.stringify(e.notes)}`), a.join("\n") + "\n";
|
|
139
|
-
},
|
|
141
|
+
}, _e = (e, t, n) => {
|
|
140
142
|
if (n.rolledBackTo !== null) return {
|
|
141
143
|
kind: "rollback",
|
|
142
144
|
commitTime: n.rolledBackTo.commitTime.toISOString()
|
|
143
145
|
};
|
|
144
146
|
if (e === null || n.runtimeVersion !== null && n.runtimeVersion !== t.runtimeVersion) return { kind: "no-update" };
|
|
145
147
|
let r = e.buildId ?? e.id;
|
|
146
|
-
if (t.currentUpdateId === r || !
|
|
148
|
+
if (t.currentUpdateId === r || !R(e, {
|
|
147
149
|
installId: t.installId,
|
|
148
150
|
currentVersion: null,
|
|
149
151
|
...t.cohorts === void 0 ? {} : { cohorts: t.cohorts }
|
|
@@ -176,7 +178,7 @@ var fe = (e, t, n) => {
|
|
|
176
178
|
}
|
|
177
179
|
}
|
|
178
180
|
};
|
|
179
|
-
},
|
|
181
|
+
}, ve = {
|
|
180
182
|
macos: ["dmg", "zip"],
|
|
181
183
|
windows: [
|
|
182
184
|
"nsis",
|
|
@@ -190,21 +192,21 @@ var fe = (e, t, n) => {
|
|
|
190
192
|
],
|
|
191
193
|
ios: ["ipa"],
|
|
192
194
|
android: ["apk", "aab"]
|
|
193
|
-
},
|
|
194
|
-
let r =
|
|
195
|
+
}, V = (e, t, n) => {
|
|
196
|
+
let r = ve[t] ?? [], i = e.artifacts.filter((e) => r.includes(e.kind));
|
|
195
197
|
if (i.length === 0) return null;
|
|
196
198
|
if (n !== void 0) {
|
|
197
199
|
let e = i.find((e) => e.target !== null && e.target.endsWith(n));
|
|
198
200
|
if (e) return e;
|
|
199
201
|
}
|
|
200
202
|
return i[0];
|
|
201
|
-
},
|
|
203
|
+
}, H = (e) => /Windows/i.test(e) ? {
|
|
202
204
|
os: "windows",
|
|
203
205
|
arch: /ARM64|aarch64/i.test(e) ? "aarch64" : "x86_64"
|
|
204
206
|
} : /Macintosh|Mac OS X/i.test(e) ? { os: "macos" } : /Android/i.test(e) ? { os: "android" } : /iPhone|iPad|iPod/i.test(e) ? { os: "ios" } : /Linux/i.test(e) ? {
|
|
205
207
|
os: "linux",
|
|
206
208
|
arch: /aarch64|arm64/i.test(e) ? "aarch64" : "x86_64"
|
|
207
|
-
} : null,
|
|
209
|
+
} : null, U = (e, t, n = {}) => ({
|
|
208
210
|
status: e,
|
|
209
211
|
body: JSON.stringify(t),
|
|
210
212
|
contentType: "application/json; charset=utf-8",
|
|
@@ -212,38 +214,41 @@ var fe = (e, t, n) => {
|
|
|
212
214
|
"cache-control": "no-store",
|
|
213
215
|
...n
|
|
214
216
|
}
|
|
215
|
-
}),
|
|
217
|
+
}), ye = (e, t, n) => ({
|
|
216
218
|
status: e,
|
|
217
219
|
body: t,
|
|
218
220
|
contentType: n,
|
|
219
221
|
headers: { "cache-control": "no-store" }
|
|
220
|
-
}),
|
|
222
|
+
}), W = (e) => ({
|
|
221
223
|
status: e,
|
|
222
224
|
body: "",
|
|
223
225
|
headers: { "cache-control": "no-store" }
|
|
224
|
-
}),
|
|
225
|
-
let r = (n.prefix ?? "/releases").replace(/\/+$/, ""), a = n.now ?? Date.now, o, s = () => {
|
|
226
|
+
}), G = (e) => `${e}_${y(9).toString("base64url")}`, be = (n) => {
|
|
227
|
+
let r = (n.prefix ?? "/releases").replace(/\/+$/, ""), a = n.now ?? Date.now, o, s = new b(), p = new b(), y = () => {
|
|
228
|
+
let e = s.getStore();
|
|
229
|
+
if (e) return e;
|
|
226
230
|
if (!o) throw new t({ reason: "releases: the app store is not bound yet" });
|
|
227
231
|
return o;
|
|
228
|
-
},
|
|
229
|
-
let t = (await
|
|
230
|
-
t ||= await
|
|
231
|
-
id:
|
|
232
|
+
}, x = null, C = async (e) => {
|
|
233
|
+
let t = (await y().query(E(M).where(S("app", e.app)).descriptor)).find((t) => t.platform === e.platform && t.shell === e.shell), n = !t;
|
|
234
|
+
t ||= await y().insert(d, {
|
|
235
|
+
id: G("relapp"),
|
|
232
236
|
app: e.app,
|
|
233
237
|
platform: e.platform,
|
|
234
238
|
shell: e.shell,
|
|
239
|
+
revision: 0,
|
|
235
240
|
bundleId: e.bundleId ?? null,
|
|
236
241
|
updaterPublicKey: e.updaterPublicKey ?? null,
|
|
237
242
|
runtimeVersion: e.runtimeVersion ?? null,
|
|
238
243
|
createdAt: new Date(a())
|
|
239
244
|
});
|
|
240
|
-
let r = await
|
|
245
|
+
let r = await y().query(E(N).where(S("appId", t.id)).descriptor);
|
|
241
246
|
for (let n of e.channels ?? [
|
|
242
247
|
"stable",
|
|
243
248
|
"beta",
|
|
244
249
|
"internal"
|
|
245
|
-
]) r.some((e) => e.name === n) || await
|
|
246
|
-
id:
|
|
250
|
+
]) r.some((e) => e.name === n) || await y().insert(h, {
|
|
251
|
+
id: G("relch"),
|
|
247
252
|
appId: t.id,
|
|
248
253
|
name: n,
|
|
249
254
|
currentReleaseId: null,
|
|
@@ -257,19 +262,19 @@ var fe = (e, t, n) => {
|
|
|
257
262
|
row: t,
|
|
258
263
|
created: n
|
|
259
264
|
};
|
|
260
|
-
},
|
|
261
|
-
for (let e of n.apps) await
|
|
262
|
-
},
|
|
265
|
+
}, w = async () => {
|
|
266
|
+
for (let e of n.apps) await C(e);
|
|
267
|
+
}, T = () => x ?? Promise.resolve(), D = (t, n, r) => _.tryPromise({
|
|
263
268
|
try: async () => {
|
|
264
|
-
await
|
|
265
|
-
let i =
|
|
266
|
-
if (!
|
|
267
|
-
return
|
|
269
|
+
await T();
|
|
270
|
+
let i = await y().query(E(M).where(S("app", t)).descriptor), a = p.getStore(), o = i.find((e) => (a === void 0 || e.id === a) && (n === void 0 || e.platform === n) && (r === void 0 || e.shell === r));
|
|
271
|
+
if (!o) throw new e({ app: t });
|
|
272
|
+
return o;
|
|
268
273
|
},
|
|
269
274
|
catch: (n) => n instanceof e ? n : new e({ app: t })
|
|
270
|
-
}),
|
|
275
|
+
}), O = (t, n, r) => _.tryPromise({
|
|
271
276
|
try: async () => {
|
|
272
|
-
let i = (await
|
|
277
|
+
let i = (await y().query(E(N).where(S("appId", t)).descriptor)).find((e) => e.name === n);
|
|
273
278
|
if (!i) throw new e({
|
|
274
279
|
app: r,
|
|
275
280
|
channel: n
|
|
@@ -280,11 +285,11 @@ var fe = (e, t, n) => {
|
|
|
280
285
|
app: r,
|
|
281
286
|
channel: n
|
|
282
287
|
})
|
|
283
|
-
}),
|
|
284
|
-
let n = await
|
|
288
|
+
}), k = (e) => y().query(E(P).where(S("id", e)).descriptor).then((e) => e[0] ?? null), A = (e) => y().query(E(P).where(S("appId", e)).descriptor), j = (e) => y().query(E(F).where(S("releaseId", e)).descriptor), R = (e) => y().query(E(N).where(S("appId", e)).descriptor), ve = (e) => n.retention?.perChannel?.[e] ?? n.retention?.keep ?? 10, be = async (e, t) => {
|
|
289
|
+
let n = await R(e), r = ge(await A(e), n, ve);
|
|
285
290
|
if (r.length === 0) return [];
|
|
286
|
-
for (let e of r) await
|
|
287
|
-
return await
|
|
291
|
+
for (let e of r) await y().deleteMany(l, { where: S("releaseId", e.id) }), await y().delete(f, e.id);
|
|
292
|
+
return await q({
|
|
288
293
|
appId: e,
|
|
289
294
|
kind: "prune",
|
|
290
295
|
actorId: t,
|
|
@@ -293,8 +298,8 @@ var fe = (e, t, n) => {
|
|
|
293
298
|
channel: n.find((t) => t.id === e.channelId)?.name ?? null
|
|
294
299
|
})) }
|
|
295
300
|
}), r;
|
|
296
|
-
},
|
|
297
|
-
let t = await
|
|
301
|
+
}, Ce = async (e) => {
|
|
302
|
+
let t = await j(e.id);
|
|
298
303
|
return {
|
|
299
304
|
id: e.id,
|
|
300
305
|
version: e.version,
|
|
@@ -315,8 +320,8 @@ var fe = (e, t, n) => {
|
|
|
315
320
|
contentType: e.contentType
|
|
316
321
|
}))
|
|
317
322
|
};
|
|
318
|
-
},
|
|
319
|
-
let n = await
|
|
323
|
+
}, K = async (e, t) => {
|
|
324
|
+
let n = await _.runPromise(D(e)), r = await _.runPromise(O(n.id, t, e)), i = r.currentReleaseId ? await k(r.currentReleaseId) : null;
|
|
320
325
|
return {
|
|
321
326
|
app: e,
|
|
322
327
|
channel: t,
|
|
@@ -327,8 +332,8 @@ var fe = (e, t, n) => {
|
|
|
327
332
|
rolloutSalt: i?.rolloutSalt ?? null,
|
|
328
333
|
cohorts: i?.cohorts ?? null
|
|
329
334
|
};
|
|
330
|
-
},
|
|
331
|
-
id:
|
|
335
|
+
}, q = (e) => y().insert(g, {
|
|
336
|
+
id: G("relev"),
|
|
332
337
|
appId: e.appId,
|
|
333
338
|
channelId: e.channelId ?? null,
|
|
334
339
|
releaseId: e.releaseId ?? null,
|
|
@@ -337,41 +342,54 @@ var fe = (e, t, n) => {
|
|
|
337
342
|
actorId: e.actorId ?? null,
|
|
338
343
|
detail: e.detail ?? null,
|
|
339
344
|
at: new Date(a())
|
|
340
|
-
}),
|
|
341
|
-
...
|
|
345
|
+
}), J = (e) => e.request.subject.type === "user" ? e.request.subject.id : null, we = {
|
|
346
|
+
...se,
|
|
342
347
|
description: "The reactive release policy of a channel: latest version, minimum supported version, kill switches, rollout.",
|
|
343
|
-
execute: (e) =>
|
|
344
|
-
try: () =>
|
|
348
|
+
execute: (e) => _.tryPromise({
|
|
349
|
+
try: () => K(e.app, e.channel),
|
|
345
350
|
catch: (e) => e
|
|
346
351
|
})
|
|
347
|
-
},
|
|
348
|
-
...
|
|
352
|
+
}, Te = {
|
|
353
|
+
...ae,
|
|
349
354
|
description: "Every release of an app target, newest first.",
|
|
350
|
-
execute: (e) =>
|
|
351
|
-
let t = yield*
|
|
355
|
+
execute: (e) => _.gen(function* () {
|
|
356
|
+
let t = yield* D(e.app), n = yield* _.promise(() => A(t.id)), r = yield* _.promise(() => y().query(E(N).where(S("appId", t.id)).descriptor)), i = /* @__PURE__ */ new Map();
|
|
357
|
+
for (let e of r) i.has(e.id) || i.set(e.id, e.name);
|
|
358
|
+
let a = /* @__PURE__ */ new Map(), o = [...new Set(n.map((e) => e.id))];
|
|
359
|
+
for (let e = 0; e < o.length; e += 500) {
|
|
360
|
+
let t = yield* _.promise(() => y().query(E(F).where(fe("releaseId", o.slice(e, e + 500))).descriptor));
|
|
361
|
+
for (let e of t) {
|
|
362
|
+
let t = a.get(e.releaseId) ?? {
|
|
363
|
+
count: 0,
|
|
364
|
+
signed: !0
|
|
365
|
+
};
|
|
366
|
+
t.count++, t.signed &&= e.signature !== null, a.set(e.releaseId, t);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
let s = [];
|
|
352
370
|
for (let e of [...n].sort((e, t) => t.createdAt.getTime() - e.createdAt.getTime() || c(t.version, e.version))) {
|
|
353
|
-
let t =
|
|
354
|
-
|
|
371
|
+
let t = a.get(e.id);
|
|
372
|
+
s.push({
|
|
355
373
|
id: e.id,
|
|
356
374
|
version: e.version,
|
|
357
375
|
buildId: e.buildId,
|
|
358
376
|
state: e.state,
|
|
359
377
|
rolloutPercent: e.rolloutPercent,
|
|
360
|
-
channel:
|
|
378
|
+
channel: i.get(e.channelId) ?? "?",
|
|
361
379
|
createdAt: e.createdAt.toISOString(),
|
|
362
|
-
artifacts: t
|
|
363
|
-
signed: t
|
|
380
|
+
artifacts: t?.count ?? 0,
|
|
381
|
+
signed: t !== void 0 && t.count > 0 && t.signed
|
|
364
382
|
});
|
|
365
383
|
}
|
|
366
|
-
return
|
|
384
|
+
return s;
|
|
367
385
|
})
|
|
368
|
-
},
|
|
369
|
-
...
|
|
386
|
+
}, Ee = {
|
|
387
|
+
...re,
|
|
370
388
|
description: "Register an app target at runtime, with its channels; idempotent.",
|
|
371
|
-
execute: (e) =>
|
|
389
|
+
execute: (e) => _.tryPromise({
|
|
372
390
|
try: async () => {
|
|
373
|
-
await
|
|
374
|
-
let { row: t, created: n } = await
|
|
391
|
+
await T();
|
|
392
|
+
let { row: t, created: n } = await C({
|
|
375
393
|
app: e.app,
|
|
376
394
|
platform: e.platform,
|
|
377
395
|
shell: e.shell,
|
|
@@ -387,14 +405,14 @@ var fe = (e, t, n) => {
|
|
|
387
405
|
},
|
|
388
406
|
catch: (n) => new t({ reason: `releases: ${e.app} could not be registered: ${n instanceof Error ? n.message : String(n)}` })
|
|
389
407
|
})
|
|
390
|
-
},
|
|
408
|
+
}, De = {
|
|
391
409
|
...u,
|
|
392
410
|
description: "Create a draft release of a version on a channel.",
|
|
393
|
-
execute: (e, n) =>
|
|
394
|
-
let r = yield*
|
|
395
|
-
if ((yield*
|
|
396
|
-
let o =
|
|
397
|
-
return yield*
|
|
411
|
+
execute: (e, n) => _.gen(function* () {
|
|
412
|
+
let r = yield* D(e.app), i = yield* O(r.id, e.channel, e.app);
|
|
413
|
+
if ((yield* _.promise(() => A(r.id))).some((t) => t.version === e.version)) return yield* _.fail(new t({ reason: `version ${e.version} already exists for ${e.app}` }));
|
|
414
|
+
let o = G("rel");
|
|
415
|
+
return yield* _.promise(() => y().insert(f, {
|
|
398
416
|
id: o,
|
|
399
417
|
appId: r.id,
|
|
400
418
|
channelId: i.id,
|
|
@@ -403,32 +421,32 @@ var fe = (e, t, n) => {
|
|
|
403
421
|
notes: e.notes ?? null,
|
|
404
422
|
state: "draft",
|
|
405
423
|
rolloutPercent: 0,
|
|
406
|
-
rolloutSalt:
|
|
424
|
+
rolloutSalt: G("salt"),
|
|
407
425
|
cohorts: e.cohorts ?? null,
|
|
408
|
-
createdBy:
|
|
426
|
+
createdBy: J(n),
|
|
409
427
|
createdAt: new Date(a()),
|
|
410
428
|
updatedAt: new Date(a())
|
|
411
|
-
})), yield*
|
|
429
|
+
})), yield* _.promise(() => q({
|
|
412
430
|
appId: r.id,
|
|
413
431
|
channelId: i.id,
|
|
414
432
|
releaseId: o,
|
|
415
433
|
kind: "create",
|
|
416
|
-
actorId:
|
|
434
|
+
actorId: J(n),
|
|
417
435
|
detail: { version: e.version }
|
|
418
|
-
})), yield*
|
|
436
|
+
})), yield* _.promise(() => be(r.id, J(n))), { id: o };
|
|
419
437
|
})
|
|
420
|
-
},
|
|
421
|
-
...
|
|
438
|
+
}, Oe = {
|
|
439
|
+
...ie,
|
|
422
440
|
description: "Attach an artefact (a file the client downloads) to a release.",
|
|
423
|
-
execute: (n, r) =>
|
|
424
|
-
let i = yield*
|
|
425
|
-
if (!i) return yield*
|
|
441
|
+
execute: (n, r) => _.gen(function* () {
|
|
442
|
+
let i = yield* _.promise(() => k(n.releaseId));
|
|
443
|
+
if (!i) return yield* _.fail(new e({
|
|
426
444
|
app: "?",
|
|
427
445
|
version: n.releaseId
|
|
428
446
|
}));
|
|
429
|
-
if (!/^[a-f0-9]{64}$/i.test(n.sha256)) return yield*
|
|
430
|
-
let o =
|
|
431
|
-
return yield*
|
|
447
|
+
if (!/^[a-f0-9]{64}$/i.test(n.sha256)) return yield* _.fail(new t({ reason: "sha256 must be 64 hex characters" }));
|
|
448
|
+
let o = G("relart");
|
|
449
|
+
return yield* _.promise(() => y().insert(l, {
|
|
432
450
|
id: o,
|
|
433
451
|
releaseId: i.id,
|
|
434
452
|
kind: n.kind,
|
|
@@ -441,158 +459,158 @@ var fe = (e, t, n) => {
|
|
|
441
459
|
assetKey: n.assetKey ?? null,
|
|
442
460
|
contentType: n.contentType ?? null,
|
|
443
461
|
createdAt: new Date(a())
|
|
444
|
-
})), yield*
|
|
462
|
+
})), yield* _.promise(() => q({
|
|
445
463
|
appId: i.appId,
|
|
446
464
|
releaseId: i.id,
|
|
447
465
|
kind: "upload",
|
|
448
|
-
actorId:
|
|
466
|
+
actorId: J(r),
|
|
449
467
|
detail: {
|
|
450
468
|
kind: n.kind,
|
|
451
469
|
target: n.target ?? null
|
|
452
470
|
}
|
|
453
471
|
})), { id: o };
|
|
454
472
|
})
|
|
455
|
-
},
|
|
456
|
-
...
|
|
473
|
+
}, ke = {
|
|
474
|
+
...ee,
|
|
457
475
|
description: "Point a channel at a release (no rebuild) and start its rollout.",
|
|
458
|
-
execute: (n, r) =>
|
|
459
|
-
let i = yield*
|
|
460
|
-
if (!
|
|
476
|
+
execute: (n, r) => _.gen(function* () {
|
|
477
|
+
let i = yield* D(n.app), o = yield* O(i.id, n.to, n.app), s = yield* _.promise(() => A(i.id)), c = s.find((e) => e.version === n.version);
|
|
478
|
+
if (!c) return yield* _.fail(new e({
|
|
461
479
|
app: n.app,
|
|
462
480
|
version: n.version
|
|
463
481
|
}));
|
|
464
|
-
let
|
|
465
|
-
if (!o.allowUnsigned &&
|
|
466
|
-
let
|
|
467
|
-
return yield*
|
|
482
|
+
let l = yield* _.promise(() => j(c.id));
|
|
483
|
+
if (!o.allowUnsigned && l.some((e) => e.signature === null)) return yield* _.fail(new t({ reason: `release ${n.version} has unsigned artefacts; channel ${n.to} refuses them` }));
|
|
484
|
+
let u = Math.max(0, Math.min(100, n.rolloutPercent ?? 100));
|
|
485
|
+
return yield* _.promise(() => y().update(f, c.id, {
|
|
468
486
|
channelId: o.id,
|
|
469
|
-
state:
|
|
470
|
-
rolloutPercent:
|
|
487
|
+
state: u >= 100 ? "complete" : "rolling",
|
|
488
|
+
rolloutPercent: u,
|
|
471
489
|
updatedAt: new Date(a())
|
|
472
|
-
})), yield*
|
|
473
|
-
currentReleaseId:
|
|
490
|
+
})), yield* _.promise(() => y().update(h, o.id, {
|
|
491
|
+
currentReleaseId: c.id,
|
|
474
492
|
updatedAt: new Date(a())
|
|
475
|
-
})), yield*
|
|
493
|
+
})), yield* _.promise(() => q({
|
|
476
494
|
appId: i.id,
|
|
477
495
|
channelId: o.id,
|
|
478
|
-
releaseId:
|
|
496
|
+
releaseId: c.id,
|
|
479
497
|
kind: "promote",
|
|
480
|
-
actorId:
|
|
498
|
+
actorId: J(r),
|
|
481
499
|
detail: {
|
|
482
|
-
from:
|
|
500
|
+
from: s.find((e) => e.id === o.currentReleaseId)?.version ?? null,
|
|
483
501
|
to: n.version,
|
|
484
|
-
rolloutPercent:
|
|
502
|
+
rolloutPercent: u
|
|
485
503
|
}
|
|
486
504
|
})), {
|
|
487
505
|
channel: n.to,
|
|
488
506
|
version: n.version,
|
|
489
|
-
rolloutPercent:
|
|
507
|
+
rolloutPercent: u
|
|
490
508
|
};
|
|
491
509
|
})
|
|
492
|
-
},
|
|
493
|
-
...
|
|
510
|
+
}, Ae = {
|
|
511
|
+
...ne,
|
|
494
512
|
description: "Change the rollout percentage of the channel's current release.",
|
|
495
|
-
execute: (n, r) =>
|
|
496
|
-
let i = yield*
|
|
497
|
-
if (!o.currentReleaseId) return yield*
|
|
498
|
-
let
|
|
499
|
-
if (!
|
|
513
|
+
execute: (n, r) => _.gen(function* () {
|
|
514
|
+
let i = yield* D(n.app), o = yield* O(i.id, n.channel, n.app);
|
|
515
|
+
if (!o.currentReleaseId) return yield* _.fail(new t({ reason: `channel ${n.channel} has no current release` }));
|
|
516
|
+
let s = yield* _.promise(() => k(o.currentReleaseId));
|
|
517
|
+
if (!s) return yield* _.fail(new e({
|
|
500
518
|
app: n.app,
|
|
501
519
|
channel: n.channel
|
|
502
520
|
}));
|
|
503
|
-
let
|
|
504
|
-
return yield*
|
|
505
|
-
rolloutPercent:
|
|
506
|
-
state:
|
|
521
|
+
let c = Math.max(0, Math.min(100, n.percent));
|
|
522
|
+
return yield* _.promise(() => y().update(f, s.id, {
|
|
523
|
+
rolloutPercent: c,
|
|
524
|
+
state: c >= 100 ? "complete" : "rolling",
|
|
507
525
|
updatedAt: new Date(a())
|
|
508
|
-
})), yield*
|
|
526
|
+
})), yield* _.promise(() => q({
|
|
509
527
|
appId: i.id,
|
|
510
528
|
channelId: o.id,
|
|
511
|
-
releaseId:
|
|
529
|
+
releaseId: s.id,
|
|
512
530
|
kind: "rollout",
|
|
513
|
-
actorId:
|
|
514
|
-
detail: { percent:
|
|
531
|
+
actorId: J(r),
|
|
532
|
+
detail: { percent: c }
|
|
515
533
|
})), {
|
|
516
|
-
version:
|
|
517
|
-
rolloutPercent:
|
|
534
|
+
version: s.version,
|
|
535
|
+
rolloutPercent: c
|
|
518
536
|
};
|
|
519
537
|
})
|
|
520
|
-
},
|
|
521
|
-
...
|
|
538
|
+
}, je = {
|
|
539
|
+
...te,
|
|
522
540
|
description: "Point the channel back at the previous release; the current one is marked rolled back.",
|
|
523
|
-
execute: (e, n) =>
|
|
524
|
-
let r = yield*
|
|
525
|
-
if (!i.currentReleaseId) return yield*
|
|
526
|
-
let o = yield*
|
|
527
|
-
return
|
|
541
|
+
execute: (e, n) => _.gen(function* () {
|
|
542
|
+
let r = yield* D(e.app), i = yield* O(r.id, e.channel, e.app);
|
|
543
|
+
if (!i.currentReleaseId) return yield* _.fail(new t({ reason: `channel ${e.channel} has no current release` }));
|
|
544
|
+
let o = yield* _.promise(() => A(r.id)), s = o.find((e) => e.id === i.currentReleaseId), l = o.filter((e) => e.channelId === i.id && e.id !== i.currentReleaseId && e.state !== "rolledBack").sort((e, t) => c(t.version, e.version))[0];
|
|
545
|
+
return s && (yield* _.promise(() => y().update(f, s.id, {
|
|
528
546
|
state: "rolledBack",
|
|
529
547
|
updatedAt: new Date(a())
|
|
530
|
-
}))), yield*
|
|
531
|
-
currentReleaseId:
|
|
548
|
+
}))), yield* _.promise(() => y().update(h, i.id, {
|
|
549
|
+
currentReleaseId: l?.id ?? null,
|
|
532
550
|
updatedAt: new Date(a())
|
|
533
|
-
})), yield*
|
|
551
|
+
})), yield* _.promise(() => q({
|
|
534
552
|
appId: r.id,
|
|
535
553
|
channelId: i.id,
|
|
536
|
-
releaseId:
|
|
554
|
+
releaseId: s?.id ?? null,
|
|
537
555
|
kind: "rollback",
|
|
538
556
|
reason: e.reason,
|
|
539
|
-
actorId:
|
|
557
|
+
actorId: J(n),
|
|
540
558
|
detail: {
|
|
541
|
-
from:
|
|
542
|
-
to:
|
|
559
|
+
from: s?.version ?? null,
|
|
560
|
+
to: l?.version ?? null
|
|
543
561
|
}
|
|
544
|
-
})), { version:
|
|
562
|
+
})), { version: l?.version ?? null };
|
|
545
563
|
})
|
|
546
|
-
},
|
|
547
|
-
...
|
|
564
|
+
}, Me = {
|
|
565
|
+
...oe,
|
|
548
566
|
description: "Set the minimum supported version and kill switches of a channel.",
|
|
549
|
-
execute: (e, t) =>
|
|
550
|
-
let n = yield*
|
|
551
|
-
return yield*
|
|
567
|
+
execute: (e, t) => _.gen(function* () {
|
|
568
|
+
let n = yield* D(e.app), r = yield* O(n.id, e.channel, e.app);
|
|
569
|
+
return yield* _.promise(() => y().update(h, r.id, {
|
|
552
570
|
...e.minSupportedVersion === void 0 ? {} : { minSupportedVersion: e.minSupportedVersion },
|
|
553
571
|
...e.killSwitches === void 0 ? {} : { killSwitches: e.killSwitches },
|
|
554
572
|
updatedAt: new Date(a())
|
|
555
|
-
})), yield*
|
|
573
|
+
})), yield* _.promise(() => q({
|
|
556
574
|
appId: n.id,
|
|
557
575
|
channelId: r.id,
|
|
558
576
|
kind: "policy",
|
|
559
577
|
reason: e.reason,
|
|
560
|
-
actorId:
|
|
578
|
+
actorId: J(t),
|
|
561
579
|
detail: {
|
|
562
580
|
minSupportedVersion: e.minSupportedVersion ?? null,
|
|
563
581
|
killSwitches: e.killSwitches ?? null
|
|
564
582
|
}
|
|
565
|
-
})), yield*
|
|
583
|
+
})), yield* _.promise(() => K(e.app, e.channel));
|
|
566
584
|
})
|
|
567
585
|
}, Y = async (e, t) => {
|
|
568
|
-
let n = await
|
|
586
|
+
let n = await _.runPromise(D(e)), r = await _.runPromise(O(n.id, t, e)), i = r.currentReleaseId ? await k(r.currentReleaseId) : null;
|
|
569
587
|
return {
|
|
570
588
|
app: n,
|
|
571
589
|
channel: r,
|
|
572
|
-
release: i ? await
|
|
590
|
+
release: i ? await Ce(i) : null
|
|
573
591
|
};
|
|
574
|
-
}, X = (e, t) => t.get("install") ?? e.headers["x-voltro-install-id"] ?? e.headers["expo-embedded-update-id"] ?? "anonymous",
|
|
592
|
+
}, X = (e, t) => t.get("install") ?? e.headers["x-voltro-install-id"] ?? e.headers["expo-embedded-update-id"] ?? "anonymous", Ne = {
|
|
575
593
|
method: "GET",
|
|
576
594
|
path: r,
|
|
577
595
|
handle: async (t) => {
|
|
578
|
-
if (t.method !== "GET" && t.method !== "HEAD") return
|
|
596
|
+
if (t.method !== "GET" && t.method !== "HEAD") return U(405, { error: "method_not_allowed" });
|
|
579
597
|
let n = t.path.slice(r.length).split("/").filter((e) => e.length > 0).map(decodeURIComponent), a = new URLSearchParams(t.query), [o, s] = n;
|
|
580
|
-
if (!o || !s) return
|
|
598
|
+
if (!o || !s) return U(404, { error: "not_found" });
|
|
581
599
|
try {
|
|
582
600
|
if (s === "tauri") {
|
|
583
601
|
let [, , e, r, i] = n;
|
|
584
|
-
if (!e || !r || !i) return
|
|
585
|
-
let { release: s } = await Y(o, e), c = s ?
|
|
602
|
+
if (!e || !r || !i) return U(400, { error: "expected /tauri/:channel/:target/:currentVersion" });
|
|
603
|
+
let { release: s } = await Y(o, e), c = s ? z(s, {
|
|
586
604
|
installId: X(t, a),
|
|
587
605
|
currentVersion: i,
|
|
588
606
|
target: r
|
|
589
607
|
}) : null;
|
|
590
|
-
return c ?
|
|
608
|
+
return c ? U(200, c) : W(204);
|
|
591
609
|
}
|
|
592
610
|
if (s === "expo" && n[2] === "manifest") {
|
|
593
611
|
let e = t.headers["expo-channel-name"] ?? a.get("channel") ?? "stable", n = t.headers["expo-platform"] ?? a.get("platform"), r = t.headers["expo-runtime-version"] ?? a.get("runtimeVersion") ?? "";
|
|
594
|
-
if (n !== "ios" && n !== "android") return
|
|
595
|
-
let { app: i, release: s } = await Y(o, e), c =
|
|
612
|
+
if (n !== "ios" && n !== "android") return U(400, { error: "expo-platform must be ios or android" });
|
|
613
|
+
let { app: i, release: s } = await Y(o, e), c = _e(s, {
|
|
596
614
|
installId: X(t, a),
|
|
597
615
|
currentVersion: null,
|
|
598
616
|
platform: n,
|
|
@@ -602,16 +620,16 @@ var fe = (e, t, n) => {
|
|
|
602
620
|
runtimeVersion: i.runtimeVersion,
|
|
603
621
|
rolledBackTo: null
|
|
604
622
|
});
|
|
605
|
-
return c.kind === "no-update" ?
|
|
623
|
+
return c.kind === "no-update" ? U(200, { type: "noUpdateAvailable" }, {
|
|
606
624
|
"expo-protocol-version": "1",
|
|
607
625
|
"expo-sfv-version": "0"
|
|
608
|
-
}) : c.kind === "rollback" ?
|
|
626
|
+
}) : c.kind === "rollback" ? U(200, {
|
|
609
627
|
type: "rollBackToEmbedded",
|
|
610
628
|
parameters: { commitTime: c.commitTime }
|
|
611
629
|
}, {
|
|
612
630
|
"expo-protocol-version": "1",
|
|
613
631
|
"expo-sfv-version": "0"
|
|
614
|
-
}) :
|
|
632
|
+
}) : U(200, c.manifest, {
|
|
615
633
|
"expo-protocol-version": "1",
|
|
616
634
|
"expo-sfv-version": "0",
|
|
617
635
|
"expo-manifest-filters": ""
|
|
@@ -619,21 +637,21 @@ var fe = (e, t, n) => {
|
|
|
619
637
|
}
|
|
620
638
|
if (s === "electron") {
|
|
621
639
|
let [, , e, t] = n;
|
|
622
|
-
if (!e || !t) return
|
|
640
|
+
if (!e || !t) return U(400, { error: "expected /electron/:channel/latest.yml" });
|
|
623
641
|
let r = t === "latest-mac.yml" ? "mac" : t === "latest-linux.yml" ? "linux" : t === "latest.yml" ? "win" : null;
|
|
624
|
-
if (r === null) return
|
|
625
|
-
let { release: i } = await Y(o, e), a = i ?
|
|
626
|
-
return a ?
|
|
642
|
+
if (r === null) return U(404, { error: "not_found" });
|
|
643
|
+
let { release: i } = await Y(o, e), a = i ? B(i, r) : null;
|
|
644
|
+
return a ? ye(200, a, "text/yaml; charset=utf-8") : W(204);
|
|
627
645
|
}
|
|
628
646
|
if (s === "download") {
|
|
629
647
|
let [, , e] = n;
|
|
630
|
-
if (!e) return
|
|
648
|
+
if (!e) return U(400, { error: "expected /download/:channel" });
|
|
631
649
|
let { channel: r, release: i } = await Y(o, e);
|
|
632
|
-
if (!r.public) return
|
|
633
|
-
if (!i) return
|
|
634
|
-
let s = a.get("os") ??
|
|
635
|
-
if (!s) return
|
|
636
|
-
let l =
|
|
650
|
+
if (!r.public) return U(403, { error: "channel_not_public" });
|
|
651
|
+
if (!i) return W(204);
|
|
652
|
+
let s = a.get("os") ?? H(t.headers["user-agent"] ?? "")?.os, c = a.get("arch") ?? H(t.headers["user-agent"] ?? "")?.arch;
|
|
653
|
+
if (!s) return U(400, { error: "os is required (?os=macos|windows|linux|ios|android)" });
|
|
654
|
+
let l = V(i, s, c);
|
|
637
655
|
return l ? {
|
|
638
656
|
status: 302,
|
|
639
657
|
body: "",
|
|
@@ -641,23 +659,23 @@ var fe = (e, t, n) => {
|
|
|
641
659
|
location: l.url,
|
|
642
660
|
"cache-control": "no-store"
|
|
643
661
|
}
|
|
644
|
-
} :
|
|
662
|
+
} : U(404, { error: "no_artifact_for_os" });
|
|
645
663
|
}
|
|
646
664
|
if (s === "policy") {
|
|
647
665
|
let [, , e] = n;
|
|
648
|
-
if (!e) return
|
|
649
|
-
let r = await
|
|
666
|
+
if (!e) return U(400, { error: "expected /policy/:channel" });
|
|
667
|
+
let r = await K(o, e), s = a.get("version"), c = s ? i(r, {
|
|
650
668
|
version: s,
|
|
651
669
|
installId: X(t, a)
|
|
652
670
|
}) : null;
|
|
653
|
-
return
|
|
671
|
+
return U(200, {
|
|
654
672
|
policy: r,
|
|
655
673
|
...c ? { verdict: c } : {}
|
|
656
674
|
});
|
|
657
675
|
}
|
|
658
|
-
return
|
|
676
|
+
return U(404, { error: "not_found" });
|
|
659
677
|
} catch (t) {
|
|
660
|
-
if (t instanceof e) return
|
|
678
|
+
if (t instanceof e) return U(404, {
|
|
661
679
|
error: "not_found",
|
|
662
680
|
app: t.app
|
|
663
681
|
});
|
|
@@ -667,20 +685,27 @@ var fe = (e, t, n) => {
|
|
|
667
685
|
}, Z = (e) => ({
|
|
668
686
|
kind: "json",
|
|
669
687
|
data: e
|
|
670
|
-
}),
|
|
688
|
+
}), Pe = [{
|
|
671
689
|
method: "GET",
|
|
672
690
|
path: "/overview",
|
|
673
691
|
scope: "shared-store",
|
|
674
692
|
description: "Every app target with its channels, current versions and rollout state.",
|
|
675
|
-
handler: () =>
|
|
676
|
-
let e = await
|
|
693
|
+
handler: () => _.promise(async () => {
|
|
694
|
+
let e = await y().query(E(M).descriptor), t = await y().query(E(N).descriptor), n = await y().query(E(P).descriptor), r = /* @__PURE__ */ new Map();
|
|
695
|
+
for (let e of t) {
|
|
696
|
+
let t = r.get(e.appId);
|
|
697
|
+
t === void 0 ? r.set(e.appId, [e]) : t.push(e);
|
|
698
|
+
}
|
|
699
|
+
let i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Map();
|
|
700
|
+
for (let e of n) i.has(e.id) || i.set(e.id, e), a.set(e.appId, (a.get(e.appId) ?? 0) + 1);
|
|
677
701
|
return Z({ apps: e.map((e) => ({
|
|
678
702
|
id: e.id,
|
|
679
703
|
app: e.app,
|
|
680
704
|
platform: e.platform,
|
|
681
705
|
shell: e.shell,
|
|
682
|
-
|
|
683
|
-
|
|
706
|
+
revision: e.revision,
|
|
707
|
+
channels: (r.get(e.id) ?? []).map((e) => {
|
|
708
|
+
let t = e.currentReleaseId === null ? void 0 : i.get(e.currentReleaseId);
|
|
684
709
|
return {
|
|
685
710
|
name: e.name,
|
|
686
711
|
current: t?.version ?? null,
|
|
@@ -690,7 +715,7 @@ var fe = (e, t, n) => {
|
|
|
690
715
|
public: e.public
|
|
691
716
|
};
|
|
692
717
|
}),
|
|
693
|
-
releases:
|
|
718
|
+
releases: a.get(e.id) ?? 0
|
|
694
719
|
})) });
|
|
695
720
|
})
|
|
696
721
|
}, {
|
|
@@ -698,20 +723,48 @@ var fe = (e, t, n) => {
|
|
|
698
723
|
path: "/events",
|
|
699
724
|
scope: "shared-store",
|
|
700
725
|
description: "The last 100 release events (promote, rollback, rollout, policy).",
|
|
701
|
-
handler: () =>
|
|
702
|
-
let e = await
|
|
726
|
+
handler: () => _.promise(async () => {
|
|
727
|
+
let e = await y().query(E(I).descriptor), t = await y().query(E(N).descriptor), n = new Map(t.map((e) => [e.id, e.name]));
|
|
703
728
|
return Z({ events: [...e].sort((e, t) => t.at.getTime() - e.at.getTime()).slice(0, 100).map((e) => ({
|
|
704
729
|
...e,
|
|
730
|
+
channelName: e.channelId === null ? null : n.get(e.channelId) ?? null,
|
|
705
731
|
at: e.at.toISOString()
|
|
706
732
|
})) });
|
|
707
733
|
})
|
|
708
|
-
}],
|
|
734
|
+
}], Fe = async (n, r) => {
|
|
735
|
+
let i = n.releaseId === void 0 ? null : await k(n.releaseId);
|
|
736
|
+
if (n.releaseId !== void 0 && !i) throw new e({ app: n.releaseId });
|
|
737
|
+
let a = (await y().query(E(M).descriptor)).filter((e) => (n.app === void 0 || e.app === n.app) && (n.platform === void 0 || e.platform === n.platform) && (n.shell === void 0 || e.shell === n.shell) && (i === null || e.id === i.appId) && (n.expectedTarget === void 0 || e.id === n.expectedTarget.id));
|
|
738
|
+
if (a.length === 0 && r) return;
|
|
739
|
+
if (a.length === 0) throw new e({ app: n.app ?? n.releaseId ?? "" });
|
|
740
|
+
if (a.length !== 1) throw new t({ reason: "Multiple release targets match this app. Select an exact target." });
|
|
741
|
+
let o = a[0], s = n.expectedTarget?.revision ?? o.revision;
|
|
742
|
+
if (!Number.isSafeInteger(s) || s < 0 || s >= 2 ** 53 - 1 || o.revision !== s || await y().updateMany("_voltro_release_apps", { revision: s + 1 }, { where: de(S("id", o.id), S("revision", s)) }) !== 1) throw new t({ reason: "Release target changed. Refresh and review the action again." });
|
|
743
|
+
return o.id;
|
|
744
|
+
}, Ie = (e) => e.kind === "mutation" ? {
|
|
745
|
+
...e,
|
|
746
|
+
execute: (t, n) => _.gen(function* () {
|
|
747
|
+
let r = yield* _.context();
|
|
748
|
+
return yield* _.tryPromise({
|
|
749
|
+
try: async (i) => {
|
|
750
|
+
await T();
|
|
751
|
+
let a = (a) => s.run(a, async () => {
|
|
752
|
+
let a = await Fe(t, e.name === "releases.registerApp"), o = () => _.runPromiseWith(r)(e.execute(t, n).pipe(_.result), { signal: i }), s = a === void 0 ? await o() : await p.run(a, o);
|
|
753
|
+
if (v.isFailure(s)) throw s.failure;
|
|
754
|
+
return s.success;
|
|
755
|
+
});
|
|
756
|
+
return n.mutationStore ? a(n.mutationStore) : y().transactional(a);
|
|
757
|
+
},
|
|
758
|
+
catch: (e) => e
|
|
759
|
+
});
|
|
760
|
+
})
|
|
761
|
+
} : e, Le = () => ({ request: {
|
|
709
762
|
subject: {
|
|
710
763
|
type: "anonymous",
|
|
711
764
|
id: null,
|
|
712
765
|
tenantId: null
|
|
713
766
|
},
|
|
714
|
-
traceId:
|
|
767
|
+
traceId: he()
|
|
715
768
|
} }), Q = (e, t) => ({
|
|
716
769
|
kind: "json",
|
|
717
770
|
status: e,
|
|
@@ -720,7 +773,7 @@ var fe = (e, t, n) => {
|
|
|
720
773
|
method: "POST",
|
|
721
774
|
path: n,
|
|
722
775
|
description: i,
|
|
723
|
-
handler: (n) =>
|
|
776
|
+
handler: (n) => _.gen(function* () {
|
|
724
777
|
let i;
|
|
725
778
|
try {
|
|
726
779
|
i = JSON.parse(n.body || "{}");
|
|
@@ -728,30 +781,32 @@ var fe = (e, t, n) => {
|
|
|
728
781
|
return Q(400, "invalid JSON body");
|
|
729
782
|
}
|
|
730
783
|
if (typeof i != "object" || !i || Array.isArray(i)) return Q(400, "expected a JSON object body");
|
|
731
|
-
let a = yield* r.
|
|
732
|
-
if (a
|
|
733
|
-
|
|
734
|
-
|
|
784
|
+
let a = yield* le.decodeUnknownEffect(r.input)(i).pipe(_.result);
|
|
785
|
+
if (v.isFailure(a)) return Q(400, "invalid action input");
|
|
786
|
+
let o = yield* Ie(r).execute(a.success, Le()).pipe(_.result);
|
|
787
|
+
if (v.isFailure(o)) {
|
|
788
|
+
let n = o.failure;
|
|
789
|
+
return n instanceof e ? Q(404, `not found: ${n.app}${n.version ? ` ${n.version}` : ""}${n.channel ? ` (${n.channel})` : ""}`) : n instanceof t ? Q(409, n.reason) : Q(500, "release action failed");
|
|
735
790
|
}
|
|
736
|
-
return Z({ result:
|
|
791
|
+
return Z({ result: o.success });
|
|
737
792
|
})
|
|
738
|
-
}),
|
|
739
|
-
$("/apps",
|
|
740
|
-
$("/create",
|
|
741
|
-
$("/upload",
|
|
742
|
-
$("/promote",
|
|
743
|
-
$("/rollout",
|
|
744
|
-
$("/rollback",
|
|
745
|
-
$("/policy",
|
|
793
|
+
}), Re = [
|
|
794
|
+
$("/apps", Ee, "Register an app target at runtime: { app, platform, shell, channels? }."),
|
|
795
|
+
$("/create", De, "Create a draft release: { app, channel, version, buildId?, notes? }."),
|
|
796
|
+
$("/upload", Oe, "Attach an artefact: { releaseId, kind, target?, url, sha256, size, signature? }."),
|
|
797
|
+
$("/promote", ke, "Promote a version onto a channel: { app, version, to, rolloutPercent? }."),
|
|
798
|
+
$("/rollout", Ae, "Set the rollout percentage: { app, channel, percent }."),
|
|
799
|
+
$("/rollback", je, "Roll a channel back: { app, channel, reason }."),
|
|
800
|
+
$("/policy", Me, "Set the policy: { app, channel, minSupportedVersion?, killSwitches?, reason }.")
|
|
746
801
|
];
|
|
747
|
-
return
|
|
802
|
+
return pe({
|
|
748
803
|
source: "plugin",
|
|
749
|
-
table:
|
|
804
|
+
table: g,
|
|
750
805
|
timeColumn: "at",
|
|
751
|
-
ttlMs:
|
|
806
|
+
ttlMs: me(process.env.VOLTRO_RELEASE_EVENTS_TTL_HOURS, 8760),
|
|
752
807
|
envVar: "VOLTRO_RELEASE_EVENTS_TTL_HOURS"
|
|
753
|
-
}),
|
|
754
|
-
name: n.name ? `${
|
|
808
|
+
}), ue({
|
|
809
|
+
name: n.name ? `${m}#${n.name}` : m,
|
|
755
810
|
description: "Release channels, artefacts and rollouts — the self-hosted update server behind Tauri, Expo OTA, electron-updater and PWA feeds, with a reactive release policy.",
|
|
756
811
|
permissions: [
|
|
757
812
|
"inspect:read",
|
|
@@ -759,40 +814,40 @@ var fe = (e, t, n) => {
|
|
|
759
814
|
"store:write"
|
|
760
815
|
],
|
|
761
816
|
routes: [
|
|
762
|
-
ve,
|
|
763
|
-
ye,
|
|
764
|
-
be,
|
|
765
|
-
xe,
|
|
766
|
-
Se,
|
|
767
|
-
Ce,
|
|
768
817
|
we,
|
|
769
818
|
Te,
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
819
|
+
Ee,
|
|
820
|
+
De,
|
|
821
|
+
Oe,
|
|
822
|
+
ke,
|
|
823
|
+
Ae,
|
|
824
|
+
je,
|
|
825
|
+
Me
|
|
826
|
+
].map(Ie),
|
|
827
|
+
rpcClientDescriptors: ce,
|
|
828
|
+
httpRoutes: [Ne],
|
|
829
|
+
inspectEndpoints: [...Pe, ...Re],
|
|
830
|
+
extendSchema: { tables: [...L] },
|
|
831
|
+
declaredEnv: Se,
|
|
832
|
+
privacy: xe,
|
|
778
833
|
bindDataStore: (e) => {
|
|
779
|
-
o = e,
|
|
834
|
+
o = e, x = w(), x.catch(() => {});
|
|
780
835
|
},
|
|
781
|
-
onActivate: () =>
|
|
836
|
+
onActivate: () => _.tryPromise({
|
|
782
837
|
catch: (e) => /* @__PURE__ */ Error(`@voltro/plugin-releases could not seed its targets and channels: ${e instanceof Error ? e.message : String(e)}`),
|
|
783
|
-
try: () =>
|
|
838
|
+
try: () => T()
|
|
784
839
|
})
|
|
785
840
|
});
|
|
786
|
-
},
|
|
841
|
+
}, xe = { collects: [{
|
|
787
842
|
category: "device-id",
|
|
788
843
|
linked: !1,
|
|
789
844
|
tracking: !1,
|
|
790
845
|
purposes: ["app-functionality"]
|
|
791
|
-
}] },
|
|
846
|
+
}] }, Se = [{
|
|
792
847
|
name: "VOLTRO_RELEASE_EVENTS_TTL_HOURS",
|
|
793
848
|
required: !1,
|
|
794
849
|
secret: !1,
|
|
795
850
|
description: "Hours a release event (create, upload, promote, rollout, rollback, policy, prune) is kept before the retention sweep removes it. Default 8760 (one year)."
|
|
796
851
|
}];
|
|
797
852
|
//#endregion
|
|
798
|
-
export {
|
|
853
|
+
export { m as BASE_NAME, p as RELEASES_MANAGE_SCOPE, f as RELEASES_TABLE, d as RELEASE_APPS_TABLE, l as RELEASE_ARTIFACTS_TABLE, h as RELEASE_CHANNELS_TABLE, g as RELEASE_EVENTS_TABLE, A as RELEASE_PLATFORMS, j as RELEASE_SHELLS, e as ReleaseNotFound, t as ReleaseRefused, c as compareVersions, i as evaluatePolicy, o as inRollout, r as isNewerVersion, R as offeredTo, H as osFromUserAgent, n as parseVersion, V as pickDownload, M as releaseAppsTable, F as releaseArtifactsTable, N as releaseChannelsTable, I as releaseEventsTable, L as releaseTables, be as releasesPlugin, P as releasesTable, B as renderElectronLatestYml, _e as renderExpoFeed, z as renderTauriFeed, a as rolloutBucket, s as sortVersionsDesc };
|