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