@hot-updater/console 1.1.4 → 1.2.0-rc.1
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/.output/nitro.json +1 -1
- package/.output/public/assets/-native-builds-search-C-TGpFAm.js +1 -0
- package/.output/public/assets/{ConsoleFeatureUnavailable-C0KfsKWL.js → ConsoleFeatureUnavailable-CUtcXuY2.js} +1 -1
- package/.output/public/assets/EventDetails-Dl2RvPAk.js +1 -0
- package/.output/public/assets/HashValueDisplay-6lNRxDJX.js +1 -0
- package/.output/public/assets/InsightsPageHeader-DHhqY3DT.js +1 -0
- package/.output/public/assets/NotFoundPage-DZ3DxyRA.js +1 -0
- package/.output/public/assets/PlatformIcon-BBWQlWm9.js +1 -0
- package/.output/public/assets/RolloutPercentageBadge-Cxogpi8F.js +1 -0
- package/.output/public/assets/StoreSubmission-JpngSvHS.js +1 -0
- package/.output/public/assets/alert-dialog-BqYScr9y.js +1 -0
- package/.output/public/assets/api-P2g8dCNg.js +1 -0
- package/.output/public/assets/api-keys-DWQC2q6y.js +1 -0
- package/.output/public/assets/api-keys-FueRkF9q.js +1 -0
- package/.output/public/assets/arrow-left-g9cKqXuC.js +1 -0
- package/.output/public/assets/arrow-right-CNII8TYn.js +1 -0
- package/.output/public/assets/arrow-up-right-DK8Zdg40.js +1 -0
- package/.output/public/assets/badge-DWFcDWho.js +1 -0
- package/.output/public/assets/check-CXVR3s3X.js +1 -0
- package/.output/public/assets/chevron-right-BoUXo82O.js +1 -0
- package/.output/public/assets/circle-off-C7Muo0ss.js +1 -0
- package/.output/public/assets/{clipboard-DTkrlIMn.js → clipboard-DQbOcrL7.js} +1 -1
- package/.output/public/assets/console-features-api-DEXSwFtc.js +1 -0
- package/.output/public/assets/copy-DsuLj3oj.js +1 -0
- package/.output/public/assets/dialog-CNUPxNxH.js +1 -0
- package/.output/public/assets/{dist-dDj-R6uh.js → dist-CPlO6ko9.js} +1 -1
- package/.output/public/assets/download-Cf24LBde.js +1 -0
- package/.output/public/assets/{empty-Bf4DanOL.js → empty-B3Uwdd6k.js} +1 -1
- package/.output/public/assets/{field-GxF9SyUo.js → field-D-2-mnNh.js} +1 -1
- package/.output/public/assets/history-DqHlgSuV.js +1 -0
- package/.output/public/assets/index-BWU6owTG.js +10 -0
- package/.output/public/assets/{input-group-B4nrqIh0.js → input-group-D3OUBk4n.js} +1 -1
- package/.output/public/assets/insights-B-0odqpt.js +42 -0
- package/.output/public/assets/insights-BSVGfxSL.js +1 -0
- package/.output/public/assets/insights-NK5B6ReS.js +2 -0
- package/.output/public/assets/insights-api-BVCXJsoV.js +1 -0
- package/.output/public/assets/insights-search-DghCbEnk.js +1 -0
- package/.output/public/assets/insights-usage-rpc-CKQH0pUS.js +1 -0
- package/.output/public/assets/insights_.distribution-CJvgwcVZ.js +2 -0
- package/.output/public/assets/insights_.distribution-DblZM0mO.js +1 -0
- package/.output/public/assets/insights_.distribution-dvk6vYDM.js +1 -0
- package/.output/public/assets/installations-B674P5Z5.js +2 -0
- package/.output/public/assets/installations-BWxczZ2t.js +1 -0
- package/.output/public/assets/installations-Dv4kWQYz.js +1 -0
- package/.output/public/assets/{key-round-B4fI1psK.js → key-round-DwNKkHhy.js} +1 -1
- package/.output/public/assets/link-DTEyW70e.js +2 -0
- package/.output/public/assets/{list-Dtj7TtzV.js → list--NIee1FZ.js} +1 -1
- package/.output/public/assets/native-builds-BOC71grI.js +1 -0
- package/.output/public/assets/native-builds-BswZazmc.js +1 -0
- package/.output/public/assets/native-builds-c4BpOLAe.js +2 -0
- package/.output/public/assets/native-builds_._buildId-D_Spjl10.js +1 -0
- package/.output/public/assets/native-builds_._buildId-DtoXD8rz.js +2 -0
- package/.output/public/assets/plus-BReVKct-.js +1 -0
- package/.output/public/assets/preload-helper-B44EvKhG.js +1 -0
- package/.output/public/assets/{refresh-cw-DjIKjmrS.js → refresh-cw-B9HHjLej.js} +1 -1
- package/.output/public/assets/relativeTime-YQt84dYr.js +1 -0
- package/.output/public/assets/remote-config-B7ujqhLa.js +6 -0
- package/.output/public/assets/remote-config-WjpozBG5.js +1 -0
- package/.output/public/assets/remote-config-gXeH6PBW.js +1 -0
- package/.output/public/assets/rotate-cw-Cv2aVbYr.js +1 -0
- package/.output/public/assets/routes-BDdBIxYS.js +1 -0
- package/.output/public/assets/routes-CCD33Azv.js +2 -0
- package/.output/public/assets/search-BCel4Oy6.js +1 -0
- package/.output/public/assets/select-CBIU0_M1.js +1 -0
- package/.output/public/assets/{sidebar-BqX460IW.js → sidebar-Di9SN47G.js} +1 -1
- package/.output/public/assets/smartphone-CMaSy_ir.js +1 -0
- package/.output/public/assets/styles-Ccxthuz1.css +2 -0
- package/.output/public/assets/switch-BpdiHL_t.js +1 -0
- package/.output/public/assets/{table-ek1DmRHq.js → table-Bpy3SvSo.js} +1 -1
- package/.output/public/assets/{tabs-CgEH_fMT.js → tabs-Xmt7tZeG.js} +1 -1
- package/.output/public/assets/{undo-2-DxXx9Zvr.js → undo-2-CUX96_BG.js} +1 -1
- package/.output/public/assets/useCompositeListItem-JmyDfo3-.js +1 -0
- package/.output/public/assets/useInfiniteQuery-DX4WpBRG.js +1 -0
- package/.output/public/assets/useMutation-DbYw7boA.js +1 -0
- package/.output/public/assets/uuidv7-zXMtwR9Q.js +1 -0
- package/.output/public/assets/{valueToPercent-B44vDssN.js → valueToPercent-BLwGy_xK.js} +1 -1
- package/.output/server/{__23tanstack-start-server-fn-resolver-KpQ5Z_24.mjs → __23tanstack-start-server-fn-resolver-CygMPYHZ.mjs} +64 -40
- package/.output/server/_chunks/ssr-renderer.mjs +2 -2
- package/.output/server/_libs/@tanstack/react-router+[...].mjs +1 -1
- package/.output/server/_libs/@tanstack/react-router-ssr-query+[...].mjs +1 -1
- package/.output/server/_libs/lucide-react.mjs +88 -1
- package/.output/server/_libs/uqr.mjs +858 -0
- package/.output/server/_ssr/-native-builds-search-CwNcoXf4.mjs +37 -0
- package/.output/server/_ssr/{BundleIdDisplay-CjSnY65J.mjs → BundleIdDisplay-DOPz4pUS.mjs} +2 -2
- package/.output/server/_ssr/{ConsoleFeatureUnavailable-CHxn9f-w.mjs → ConsoleFeatureUnavailable-Xb1JKqcc.mjs} +7 -7
- package/.output/server/_ssr/{EventDetails-l6dF54zp.mjs → EventDetails-D7MejFCN.mjs} +8 -8
- package/.output/server/_ssr/{HashValueDisplay-Zs7ABoOi.mjs → HashValueDisplay-Dd-wu5rY.mjs} +2 -2
- package/.output/server/_ssr/{InsightsPageHeader-ZlAlDxQy.mjs → InsightsPageHeader-CWf1n4Vt.mjs} +13 -11
- package/.output/server/_ssr/{NotFoundPage-u28ndvp1.mjs → NotFoundPage-C5rFdUpg.mjs} +2 -2
- package/.output/server/_ssr/PlatformIcon-CFLiTjh1.mjs +29 -0
- package/.output/server/_ssr/RolloutPercentageBadge-g0Bhfl3M.mjs +21 -0
- package/.output/server/_ssr/StoreSubmission-JZ2Zltak.mjs +139 -0
- package/.output/server/_ssr/{alert-dialog-B8AqlJwo.mjs → alert-dialog-CvNvTvIJ.mjs} +1 -1
- package/.output/server/_ssr/{api-C_0B7NXM.mjs → api-0vtwA5vY.mjs} +126 -7
- package/.output/server/_ssr/{api-keys-pRNvn2-9.mjs → api-keys-D5dyA4D1.mjs} +10 -10
- package/.output/server/_ssr/{api-keys-rpc-wecWs0nA.mjs → api-keys-rpc-BOIUHhDi.mjs} +5 -5
- package/.output/server/_ssr/{api-keys-CLH38u9B.mjs → api-keys-yFlQDwQF.mjs} +2 -2
- package/.output/server/_ssr/{api-rpc-DWN8eOHS.mjs → api-rpc-COeFOpYi.mjs} +79 -12
- package/.output/server/_ssr/{auth-UP0wXs4i.mjs → auth-Z-wLddzh.mjs} +1 -1
- package/.output/server/_ssr/{auth-rpc-CLRArbIl.mjs → auth-rpc-D1ss2GUI.mjs} +6 -6
- package/.output/server/_ssr/{auth.server-DR9zc0EU.mjs → auth.server-DYS1OJ6P.mjs} +771 -641
- package/.output/server/_ssr/{badge-BpT7r-ng.mjs → badge-CEdVRgyl.mjs} +1 -1
- package/.output/server/_ssr/{bundleActivity-0qFIcvqt.mjs → bundleActivity-MLrjNJCT.mjs} +1 -1
- package/.output/server/_ssr/{config-WVX4IxSR.mjs → config-CjIBFhJX.mjs} +1 -1
- package/.output/server/_ssr/config.server-NnMFjMFX.mjs +43 -0
- package/.output/server/_ssr/{console-access-aUpQs49I.mjs → console-access-33BNlH97.mjs} +3 -3
- package/.output/server/_ssr/{console-features-4xAGfZHw.mjs → console-features-BTV-XuhQ.mjs} +1 -1
- package/.output/server/_ssr/{console-features-api-DSSgCV3v.mjs → console-features-api-v1fSycue.mjs} +6 -6
- package/.output/server/_ssr/{console-features-rpc-D6kMlR2A.mjs → console-features-rpc-C7XNVqm0.mjs} +5 -5
- package/.output/server/_ssr/createCsrfMiddleware-BwHbC8n-.mjs +159 -0
- package/.output/server/_ssr/createMiddleware-C3ACsfuG.mjs +24 -0
- package/.output/server/_ssr/{createMiddleware-B1iPez7u.mjs → createServerFn-AQvBMBjJ.mjs} +2 -23
- package/.output/server/_ssr/{createServerRpc-BaDJLGBx.mjs → createServerRpc-BVvRVOz5.mjs} +2 -2
- package/.output/server/_ssr/{databaseConfig-C5SkAyUy.mjs → databaseConfig-B_Bg7qS5.mjs} +1 -1
- package/.output/server/_ssr/{databaseJsonValue-Csbuzc9Q.mjs → databaseJsonValue-kS7cvEtz.mjs} +1 -1
- package/.output/server/_ssr/{databaseRows-CPphvbag.mjs → databaseRows-B6H8Cmgq.mjs} +3 -3
- package/.output/server/_ssr/{dialog-B4ALf7NJ.mjs → dialog-C8CS8RMt.mjs} +1 -1
- package/.output/server/_ssr/{dist-CbQbBIw-.mjs → dist-TEpM_UAD.mjs} +125 -125
- package/.output/server/_ssr/{downloadBundle-94jPBGSO.mjs → downloadBundle-DCmr7vsj.mjs} +1 -1
- package/.output/server/_ssr/{empty-Bh1FEeYF.mjs → empty-CkdEAvCY.mjs} +2 -2
- package/.output/server/_ssr/{empty-plugin-adapters-CpCHi1TV.mjs → empty-plugin-adapters-zrZ0xs6n.mjs} +1 -1
- package/.output/server/_ssr/{failureReports-Bh22wois.mjs → failureReports-Cn_zU9S8.mjs} +3 -3
- package/.output/server/_ssr/{field-HKCaPH3e.mjs → field-CW08sZXd.mjs} +2 -2
- package/.output/server/_ssr/{getBundleChildren-DfxB2K8D.mjs → getBundleChildren-rtkEEJw5.mjs} +2 -2
- package/.output/server/_ssr/git-CTA8Aqr0.mjs +56 -0
- package/.output/server/_ssr/{input-group-xm3LzDuq.mjs → input-group-D-TpFPuG.mjs} +1 -1
- package/.output/server/_ssr/{insights-BKZpJ_K4.mjs → insights-CMyzPs8l.mjs} +28 -27
- package/.output/server/_ssr/{insights-CCyTACIw.mjs → insights-CYeBl8N9.mjs} +5 -5
- package/.output/server/_ssr/{insights-CNqWQLJR.mjs → insights-DAi9KknT.mjs} +2 -2
- package/.output/server/_ssr/{insights-api-DtRFz5X3.mjs → insights-api-BFARQ5ct.mjs} +6 -6
- package/.output/server/_ssr/{insights-errors-Iy-lBaM7.mjs → insights-errors-7BCwFybo.mjs} +2 -2
- package/.output/server/_ssr/{insights-failures-BJN3RfLu.mjs → insights-failures-B9VPkzZE.mjs} +2 -2
- package/.output/server/_ssr/{insights-failures-rpc-DLZ91uOG.mjs → insights-failures-rpc-Q4WNNJkU.mjs} +12 -12
- package/.output/server/_ssr/{insights-recovery-BUuQdlA3.mjs → insights-recovery-BtXVU3ro.mjs} +1 -1
- package/.output/server/_ssr/{insights-recovery-rpc-BQHUhPi7.mjs → insights-recovery-rpc-CY5RYJKa.mjs} +8 -8
- package/.output/server/_ssr/{insights-rpc-C6Vukyn7.mjs → insights-rpc-BO7_evvs.mjs} +5 -5
- package/.output/server/_ssr/{insights-search-CBYoxT7v.mjs → insights-search-DKfxgHD3.mjs} +5 -5
- package/.output/server/_ssr/{insights-usage-CHqvtehH.mjs → insights-usage-DiGnuxW8.mjs} +1 -1
- package/.output/server/_ssr/{insights-usage-rpc-BJ7a-xco.mjs → insights-usage-rpc-B4czku50.mjs} +8 -8
- package/.output/server/_ssr/{insights-usage-rpc-C-lNUIsD.mjs → insights-usage-rpc-CUCTFska.mjs} +5 -5
- package/.output/server/_ssr/{insightsUsage-COUG-_-U.mjs → insightsUsage-ClAmoUz8.mjs} +3 -3
- package/.output/server/_ssr/{insights_.distribution-DmLW8I8a.mjs → insights_.distribution-BDeUhZGj.mjs} +2 -2
- package/.output/server/_ssr/{insights_.distribution-CTwilMPm.mjs → insights_.distribution-BRrbZN1X.mjs} +5 -5
- package/.output/server/_ssr/{insights_.distribution-DztDyrBj.mjs → insights_.distribution-C2MXpzKd.mjs} +15 -14
- package/.output/server/_ssr/{installations-Bct7ag5y.mjs → installations-BVk7okiY.mjs} +4 -4
- package/.output/server/_ssr/{installations-B6MK5iA8.mjs → installations-BjLMgBoH.mjs} +2 -2
- package/.output/server/_ssr/{installations-_N4PtYFl.mjs → installations-DxGZEC5G.mjs} +12 -12
- package/.output/server/_ssr/{listReleases-BfUBlCHo.mjs → listReleases-D_GY00SQ.mjs} +1 -1
- package/.output/server/_ssr/native-builds-CSCgFB21.mjs +10 -0
- package/.output/server/_ssr/native-builds-CdlyAldW.mjs +569 -0
- package/.output/server/_ssr/native-builds-DhXL5zf_.mjs +137 -0
- package/.output/server/_ssr/native-builds_._buildId-CMp1h8dT.mjs +10 -0
- package/.output/server/_ssr/native-builds_._buildId-GHpGaYyE.mjs +813 -0
- package/.output/server/_ssr/nativeBuildQr-84cnFQPX.mjs +59 -0
- package/.output/server/_ssr/nativeBuilds-B_7BPjt_.mjs +133 -0
- package/.output/server/_ssr/{plugins-BaD1slHx.mjs → plugins-RIryUNWj.mjs} +6 -5
- package/.output/server/_ssr/qr-code-C7kNRIDX.mjs +22 -0
- package/.output/server/_ssr/{release-adoption-DuYJTGuX.mjs → release-adoption-DoAtNPED.mjs} +2 -2
- package/.output/server/_ssr/{release-adoption-rpc-CHl7G_Zy.mjs → release-adoption-rpc-BJXZvtoQ.mjs} +10 -10
- package/.output/server/_ssr/{releaseAdoption-B39cpvfo.mjs → releaseAdoption-a2byXMfz.mjs} +4 -4
- package/.output/server/_ssr/releaseCatalogCompiler-DLcean2k.mjs +364 -0
- package/.output/server/_ssr/{releaseManagement-DFMUnDF5.mjs → releaseManagement-DHUux2az.mjs} +1 -1
- package/.output/server/_ssr/{releaseReachability-bFsuElSS.mjs → releaseReachability-DZOK_dH-.mjs} +2 -2
- package/.output/server/_ssr/{remote-config-Mj05qVYZ.mjs → remote-config-DjsEl270.mjs} +20 -19
- package/.output/server/_ssr/{remote-config-10-obSZ0.mjs → remote-config-DlyyohL2.mjs} +2 -2
- package/.output/server/_ssr/{remote-config-Dj1eTYi4.mjs → remote-config-XdYuByHz.mjs} +2 -2
- package/.output/server/_ssr/{remote-config-rpc-lteqDSLn.mjs → remote-config-rpc-GMLPb-90.mjs} +6 -6
- package/.output/server/_ssr/request-guard-CPdRBuGW.mjs +108 -0
- package/.output/server/_ssr/{router-Dr4jjjhx.mjs → router-vpxd56RW.mjs} +317 -71
- package/.output/server/_ssr/{routes-BZbrY_qw.mjs → routes-DyEM4b3x.mjs} +14 -14
- package/.output/server/_ssr/{routes-B5KrCDwk.mjs → routes-dQe3XhiS.mjs} +99 -81
- package/.output/server/_ssr/{runtime.server-DsHqVqTr.mjs → runtime.server-BdMY1blX.mjs} +4 -4
- package/.output/server/_ssr/schema-ChlRtZIo.mjs +23 -0
- package/.output/server/_ssr/schema-migration-rpc-BfGzEK_o.mjs +65 -0
- package/.output/server/_ssr/{select-BtdGNSmp.mjs → select-DM1uwtk9.mjs} +3 -27
- package/.output/server/_ssr/{server-BxaHSwHh.mjs → server-BUUKNSPI.mjs} +7 -161
- package/.output/server/_ssr/{sidebar-CVsgosaD.mjs → sidebar-DB2YQlok.mjs} +4 -4
- package/.output/server/_ssr/ssr.mjs +1 -1
- package/.output/server/_ssr/start-BvDsQehg.mjs +49 -0
- package/.output/server/_ssr/{switch-BmARgkUP.mjs → switch-DLD58zLy.mjs} +2 -2
- package/.output/server/_ssr/{table-M5P3YUfY.mjs → table-P4TnAZhl.mjs} +1 -1
- package/.output/server/_ssr/{tabs-CrmfOlJj.mjs → tabs-B7ZeLicF.mjs} +2 -2
- package/.output/server/_ssr/{updateFailures-z1IQy_4q.mjs → updateFailures-n-tGv90S.mjs} +3 -3
- package/.output/server/_ssr/{uuidv7-C88s9jWF.mjs → uuidv7-BIF4nb_q.mjs} +2 -2
- package/.output/server/_ssr/{schema-BiAVyEj2.mjs → version-CQ98ZBpL-CWSkTT9J.mjs} +2 -22
- package/.output/server/_tanstack-start-manifest_v-C-KC63Zq.mjs +184 -0
- package/.output/server/index.mjs +432 -271
- package/lib/vite-internal.mjs +32 -1
- package/package.json +8 -7
- package/src/components/AppSidebar.tsx +12 -1
- package/src/components/ConsoleAccessPage.tsx +49 -3
- package/src/components/QrCode.tsx +35 -0
- package/src/components/SchemaMigrationRequired.tsx +139 -0
- package/src/components/features/insights/BuiltinBundle.tsx +5 -3
- package/src/components/features/native-builds/BuiltInBundleCard.tsx +163 -0
- package/src/components/features/native-builds/CommitLink.tsx +30 -0
- package/src/components/features/native-builds/CopyableText.tsx +48 -0
- package/src/components/features/native-builds/ImportBuild.tsx +91 -0
- package/src/components/features/native-builds/InstallCard.tsx +205 -0
- package/src/components/features/native-builds/NativeBuildDetailPage.tsx +175 -0
- package/src/components/features/native-builds/NativeBuildsPage.tsx +151 -0
- package/src/components/features/native-builds/NativeBuildsTable.tsx +426 -0
- package/src/components/features/native-builds/PatchesCard.tsx +222 -0
- package/src/components/features/native-builds/ReleaseNativeBuildLink.tsx +101 -0
- package/src/components/features/native-builds/ServedNowCard.tsx +214 -0
- package/src/components/features/native-builds/ShortHash.tsx +41 -0
- package/src/components/features/native-builds/StoreSubmission.tsx +73 -0
- package/src/components/features/releases/ReleaseEditorSheet.tsx +8 -0
- package/src/lib/api-rpc.ts +98 -0
- package/src/lib/api.ts +120 -0
- package/src/lib/native-builds.ts +162 -0
- package/src/lib/qr-code.ts +16 -0
- package/src/lib/schema-migration-api.ts +54 -0
- package/src/lib/schema-migration-rpc.ts +26 -0
- package/src/lib/schema-migration.ts +101 -0
- package/src/lib/server/config.server.ts +23 -14
- package/src/lib/server/console-runtime.server.ts +4 -6
- package/src/lib/server/local-console.ts +164 -0
- package/src/lib/server/nativeBuildQr.ts +73 -0
- package/src/lib/server/nativeBuilds.ts +288 -0
- package/src/lib/shell.ts +9 -0
- package/src/routeTree.gen.ts +88 -1
- package/src/router.tsx +11 -1
- package/src/routes/-native-builds-search.ts +51 -0
- package/src/routes/[_]hot-updater/native-builds/qr.ts +14 -0
- package/src/routes/__root.tsx +11 -1
- package/src/routes/api/native-builds/$buildId/download.ts +50 -0
- package/src/routes/native-builds.tsx +21 -0
- package/src/routes/native-builds_.$buildId.tsx +23 -0
- package/src/start.ts +33 -0
- package/src/virtual-modules.d.ts +18 -0
- package/src/vite-internal.ts +57 -1
- package/.output/public/assets/EventDetails-gbD_fCqc.js +0 -1
- package/.output/public/assets/HashValueDisplay-BGkDPaYi.js +0 -1
- package/.output/public/assets/InsightsPageHeader-BRw8XkJW.js +0 -1
- package/.output/public/assets/NotFoundPage-Cei6W2lm.js +0 -1
- package/.output/public/assets/alert-dialog-BtVg50WQ.js +0 -1
- package/.output/public/assets/api-DoicFJfd.js +0 -1
- package/.output/public/assets/api-keys-D81VHHNM.js +0 -1
- package/.output/public/assets/api-keys-Dia6i8K1.js +0 -1
- package/.output/public/assets/arrow-left-DsivSewE.js +0 -1
- package/.output/public/assets/arrow-up-right-B5aM0F7f.js +0 -1
- package/.output/public/assets/badge-Bqf3UDee.js +0 -1
- package/.output/public/assets/circle-off-BsbZQtsF.js +0 -1
- package/.output/public/assets/console-features-api-DPE4C06Y.js +0 -2
- package/.output/public/assets/dialog-CGKPxz3n.js +0 -1
- package/.output/public/assets/index-DrkdiRIn.js +0 -10
- package/.output/public/assets/insights-C-5t8wh2.js +0 -2
- package/.output/public/assets/insights-D_ngQdiz.js +0 -1
- package/.output/public/assets/insights-KigRBDgC.js +0 -42
- package/.output/public/assets/insights-api-1ZjVu3Sb.js +0 -1
- package/.output/public/assets/insights-search-aT8BVCci.js +0 -1
- package/.output/public/assets/insights-usage-rpc-DqTiXI1_.js +0 -1
- package/.output/public/assets/insights_.distribution-Bzl6RFBR.js +0 -2
- package/.output/public/assets/insights_.distribution-Cthgttqb.js +0 -1
- package/.output/public/assets/insights_.distribution-D2c2v1bu.js +0 -1
- package/.output/public/assets/installations-2Nx8Htf-.js +0 -1
- package/.output/public/assets/installations-BskJ1xQr.js +0 -2
- package/.output/public/assets/installations-K2iJ_r0h.js +0 -1
- package/.output/public/assets/remote-config-D9X3NiwV.js +0 -6
- package/.output/public/assets/remote-config-DzOOiBIO.js +0 -1
- package/.output/public/assets/remote-config-ikg7kak0.js +0 -1
- package/.output/public/assets/routes-9rb9P5Y7.js +0 -2
- package/.output/public/assets/routes-P7683vKQ.js +0 -1
- package/.output/public/assets/search-DuI1FBpg.js +0 -1
- package/.output/public/assets/select-M3H2gxCc.js +0 -1
- package/.output/public/assets/smartphone-CtsHuiIC.js +0 -1
- package/.output/public/assets/styles-CpiW_YdW.css +0 -2
- package/.output/public/assets/switch-By_vfm8I.js +0 -1
- package/.output/public/assets/useCompositeListItem-B-UkrDlu.js +0 -1
- package/.output/server/_ssr/config.server-DTdsG47T.mjs +0 -35
- package/.output/server/_ssr/start-B6ECIE_7.mjs +0 -4
- package/.output/server/_tanstack-start-manifest_v-_BY9hYTm.mjs +0 -136
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import { n as DatabaseBundleNotFoundError, r as DatabaseRowReferencedError } from "./databaseJsonValue-
|
|
2
|
-
import {
|
|
3
|
-
import { i as rowToBundle, n as bundleToRow, r as releaseRowToRelease, t as bundleToPatchRows } from "./databaseRows-
|
|
4
|
-
import { t as ReleaseManagementError } from "./releaseManagement-
|
|
5
|
-
import { n as createUUIDv7After, t as createUUIDv7 } from "./uuidv7-
|
|
6
|
-
import {
|
|
7
|
-
import { t as
|
|
1
|
+
import { n as DatabaseBundleNotFoundError, r as DatabaseRowReferencedError } from "./databaseJsonValue-kS7cvEtz.mjs";
|
|
2
|
+
import { O as parseReleaseCatalogScopeKey, a as RELEASE_CATALOG_FALLBACK_POLICY, c as createReleaseCatalogScopeKey, d as getAssetBaseStorageUri, f as getBundlePatch, h as getManifestStorageUri, l as decodeChannelKey, m as getManifestFileHash, r as NIL_UUID, s as canonicalizeAppVersion, u as encodeChannelKey, w as isUUIDv7 } from "./dist-TEpM_UAD.mjs";
|
|
3
|
+
import { i as rowToBundle, n as bundleToRow, r as releaseRowToRelease, t as bundleToPatchRows } from "./databaseRows-B6H8Cmgq.mjs";
|
|
4
|
+
import { t as ReleaseManagementError } from "./releaseManagement-DHUux2az.mjs";
|
|
5
|
+
import { n as createUUIDv7After, t as createUUIDv7 } from "./uuidv7-BIF4nb_q.mjs";
|
|
6
|
+
import { i as normalizeRange } from "./version-CQ98ZBpL-CWSkTT9J.mjs";
|
|
7
|
+
import { n as projectCompiledCatalog, r as projectCompiledRollbackCatalog, t as compileReleaseCatalog } from "./releaseCatalogCompiler-DLcean2k.mjs";
|
|
8
|
+
import { t as isRemoteDatabase } from "./databaseConfig-B_Bg7qS5.mjs";
|
|
9
|
+
import { n as defineTable, t as defineAggregate } from "./schema-ChlRtZIo.mjs";
|
|
8
10
|
import { r as rangesIntersect } from "../_libs/verkit.mjs";
|
|
9
|
-
//#region node_modules/.nitro/vite/services/ssr/assets/auth.server-
|
|
11
|
+
//#region node_modules/.nitro/vite/services/ssr/assets/auth.server-DYS1OJ6P.js
|
|
10
12
|
var SHA256_FILE_HASH_RE = /^[0-9a-f]{64}$/;
|
|
11
13
|
var isContentAddressedAssetFileHash = (value) => {
|
|
12
14
|
return typeof value === "string" && SHA256_FILE_HASH_RE.test(value);
|
|
@@ -136,365 +138,6 @@ var getBundleArchiveStorageUri = ({ manifestStorageUri, bundleId }) => replaceSt
|
|
|
136
138
|
function assertStorageOperations(adapter, operations) {
|
|
137
139
|
for (const operation of operations) if (typeof adapter[operation] !== "function") throw new Error(`Storage adapter "${adapter.name}" does not implement ${operation}.`);
|
|
138
140
|
}
|
|
139
|
-
var ReleaseCatalogCompilationError = class extends Error {
|
|
140
|
-
code;
|
|
141
|
-
constructor(code, message) {
|
|
142
|
-
super(message);
|
|
143
|
-
this.name = "ReleaseCatalogCompilationError";
|
|
144
|
-
this.code = code;
|
|
145
|
-
}
|
|
146
|
-
};
|
|
147
|
-
function compareBounds(left, right) {
|
|
148
|
-
return compare(left, right);
|
|
149
|
-
}
|
|
150
|
-
function strongerLower(current, candidate) {
|
|
151
|
-
if (current === null) return candidate;
|
|
152
|
-
const compared = compareBounds(candidate.version, current.version);
|
|
153
|
-
if (compared > 0) return candidate;
|
|
154
|
-
if (compared < 0) return current;
|
|
155
|
-
return {
|
|
156
|
-
version: current.version,
|
|
157
|
-
inclusive: current.inclusive && candidate.inclusive
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
function strongerUpper(current, candidate) {
|
|
161
|
-
if (current === null) return candidate;
|
|
162
|
-
const compared = compareBounds(candidate.version, current.version);
|
|
163
|
-
if (compared < 0) return candidate;
|
|
164
|
-
if (compared > 0) return current;
|
|
165
|
-
return {
|
|
166
|
-
version: current.version,
|
|
167
|
-
inclusive: current.inclusive && candidate.inclusive
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
function comparatorVersion(comparator) {
|
|
171
|
-
const version = comparator.version && normalize(comparator.version);
|
|
172
|
-
if (version === null) throw new ReleaseCatalogCompilationError("INVALID_TARGET_RANGE", `Invalid comparator: ${comparator.value}`);
|
|
173
|
-
return version;
|
|
174
|
-
}
|
|
175
|
-
function comparatorSetToInterval(comparators) {
|
|
176
|
-
let lower = null;
|
|
177
|
-
let upper = null;
|
|
178
|
-
for (const comparator of comparators) {
|
|
179
|
-
if (comparator.version === null) continue;
|
|
180
|
-
const version = comparatorVersion(comparator);
|
|
181
|
-
if (comparator.operator === "") {
|
|
182
|
-
lower = strongerLower(lower, {
|
|
183
|
-
inclusive: true,
|
|
184
|
-
version
|
|
185
|
-
});
|
|
186
|
-
upper = strongerUpper(upper, {
|
|
187
|
-
inclusive: true,
|
|
188
|
-
version
|
|
189
|
-
});
|
|
190
|
-
} else if (comparator.operator === ">") lower = strongerLower(lower, {
|
|
191
|
-
inclusive: false,
|
|
192
|
-
version
|
|
193
|
-
});
|
|
194
|
-
else if (comparator.operator === ">=") lower = strongerLower(lower, {
|
|
195
|
-
inclusive: true,
|
|
196
|
-
version
|
|
197
|
-
});
|
|
198
|
-
else if (comparator.operator === "<") upper = strongerUpper(upper, {
|
|
199
|
-
inclusive: false,
|
|
200
|
-
version
|
|
201
|
-
});
|
|
202
|
-
else if (comparator.operator === "<=") upper = strongerUpper(upper, {
|
|
203
|
-
inclusive: true,
|
|
204
|
-
version
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
if (lower !== null && upper !== null) {
|
|
208
|
-
const compared = compareBounds(lower.version, upper.version);
|
|
209
|
-
if (compared > 0 || compared === 0 && (!lower.inclusive || !upper.inclusive)) return null;
|
|
210
|
-
}
|
|
211
|
-
return {
|
|
212
|
-
lower,
|
|
213
|
-
upper
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
function rangeToIntervals(range) {
|
|
217
|
-
try {
|
|
218
|
-
return parseRange(range).sets.flatMap((comparators) => {
|
|
219
|
-
const interval = comparatorSetToInterval(comparators);
|
|
220
|
-
return interval === null ? [] : [interval];
|
|
221
|
-
});
|
|
222
|
-
} catch {
|
|
223
|
-
throw new ReleaseCatalogCompilationError("INVALID_TARGET_RANGE", `Invalid target app-version range: ${range}`);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
function releaseDescriptor(release) {
|
|
227
|
-
return {
|
|
228
|
-
releaseId: release.id,
|
|
229
|
-
kind: release.kind,
|
|
230
|
-
bundleId: release.bundleId,
|
|
231
|
-
rolloutCohortCount: release.rolloutCohortCount,
|
|
232
|
-
targetCohorts: [...new Set(release.targetCohorts)].sort(),
|
|
233
|
-
shouldForceUpdate: release.shouldForceUpdate,
|
|
234
|
-
message: release.message
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
function validateReleases(releases, strategy) {
|
|
238
|
-
const enabled = releases.filter((release) => release.enabled).sort((left, right) => right.id.localeCompare(left.id));
|
|
239
|
-
const seenIds = /* @__PURE__ */ new Set();
|
|
240
|
-
for (const release of enabled) {
|
|
241
|
-
if (!isUUIDv7(release.id)) throw new ReleaseCatalogCompilationError("INVALID_RELEASE", `Release ${release.id} must use a canonical lowercase UUIDv7 ID`);
|
|
242
|
-
if (seenIds.has(release.id)) throw new ReleaseCatalogCompilationError("INVALID_RELEASE", `Duplicate Release ID: ${release.id}`);
|
|
243
|
-
seenIds.add(release.id);
|
|
244
|
-
if (release.strategy !== strategy) throw new ReleaseCatalogCompilationError("INVALID_RELEASE", `Release ${release.id} has the wrong strategy`);
|
|
245
|
-
if (release.bundleId === null) throw new ReleaseCatalogCompilationError("INVALID_RELEASE", `Release ${release.id} has no Bundle`);
|
|
246
|
-
if (release.targetCohorts.length > 100) throw new ReleaseCatalogCompilationError("TARGET_COHORT_LIMIT", `Release ${release.id} exceeds 100 target cohorts`);
|
|
247
|
-
if (strategy === "APP_VERSION" && (release.targetAppVersion === null || release.fingerprintHash !== null)) throw new ReleaseCatalogCompilationError("INVALID_RELEASE", `Release ${release.id} has an invalid app-version target`);
|
|
248
|
-
if (strategy === "FINGERPRINT" && (release.fingerprintHash === null || release.targetAppVersion !== null)) throw new ReleaseCatalogCompilationError("INVALID_RELEASE", `Release ${release.id} has an invalid fingerprint target`);
|
|
249
|
-
}
|
|
250
|
-
return enabled;
|
|
251
|
-
}
|
|
252
|
-
function collectFrontierReleaseIds(releases) {
|
|
253
|
-
if (releases.every((release) => normalizeRolloutCohortCount(release.rolloutCohortCount) >= 1e3)) {
|
|
254
|
-
const retained = /* @__PURE__ */ new Set();
|
|
255
|
-
const bundleIds = /* @__PURE__ */ new Set();
|
|
256
|
-
for (const release of releases) {
|
|
257
|
-
if (release.bundleId !== null && !bundleIds.has(release.bundleId)) {
|
|
258
|
-
bundleIds.add(release.bundleId);
|
|
259
|
-
retained.add(release.id);
|
|
260
|
-
}
|
|
261
|
-
if (bundleIds.size >= 11) break;
|
|
262
|
-
}
|
|
263
|
-
return retained;
|
|
264
|
-
}
|
|
265
|
-
const explicitTargetCohorts = new Set(releases.flatMap((release) => release.targetCohorts));
|
|
266
|
-
const cohortStates = [
|
|
267
|
-
void 0,
|
|
268
|
-
...Array.from({ length: 1e3 }, (_, index) => String(index + 1)),
|
|
269
|
-
...[...explicitTargetCohorts].sort(),
|
|
270
|
-
"release-catalog-non-targeted-cohort"
|
|
271
|
-
].map((cohort) => {
|
|
272
|
-
const normalized = cohort === void 0 ? void 0 : normalizeCohortValue(cohort);
|
|
273
|
-
return {
|
|
274
|
-
isCustom: normalized !== void 0 && isCustomCohort(normalized),
|
|
275
|
-
normalized,
|
|
276
|
-
numeric: normalized === void 0 ? null : getNumericCohortValue(normalized),
|
|
277
|
-
bundleIds: /* @__PURE__ */ new Set(),
|
|
278
|
-
complete: false
|
|
279
|
-
};
|
|
280
|
-
});
|
|
281
|
-
const stateIndexesByCohort = /* @__PURE__ */ new Map();
|
|
282
|
-
const fullRolloutStateIndexes = [];
|
|
283
|
-
for (const [index, state] of cohortStates.entries()) {
|
|
284
|
-
if (state.normalized !== void 0) {
|
|
285
|
-
const indexes = stateIndexesByCohort.get(state.normalized) ?? [];
|
|
286
|
-
indexes.push(index);
|
|
287
|
-
stateIndexesByCohort.set(state.normalized, indexes);
|
|
288
|
-
}
|
|
289
|
-
if (state.normalized === void 0 || state.numeric !== null || state.isCustom) fullRolloutStateIndexes.push(index);
|
|
290
|
-
}
|
|
291
|
-
const retained = /* @__PURE__ */ new Set();
|
|
292
|
-
let incompleteStateCount = cohortStates.length;
|
|
293
|
-
for (const release of releases) {
|
|
294
|
-
const rolloutCohortCount = normalizeRolloutCohortCount(release.rolloutCohortCount);
|
|
295
|
-
const eligibleStateIndexes = /* @__PURE__ */ new Set();
|
|
296
|
-
if (rolloutCohortCount >= 1e3) for (const index of fullRolloutStateIndexes) eligibleStateIndexes.add(index);
|
|
297
|
-
else if (rolloutCohortCount > 0) for (const numericCohort of getRolledOutNumericCohorts(release.id, rolloutCohortCount)) for (const index of stateIndexesByCohort.get(String(numericCohort)) ?? []) eligibleStateIndexes.add(index);
|
|
298
|
-
for (const targetCohort of new Set(release.targetCohorts.map(normalizeCohortValue))) for (const index of stateIndexesByCohort.get(targetCohort) ?? []) eligibleStateIndexes.add(index);
|
|
299
|
-
for (const index of eligibleStateIndexes) {
|
|
300
|
-
const state = cohortStates[index];
|
|
301
|
-
if (state.complete) continue;
|
|
302
|
-
if (release.bundleId !== null && !state.bundleIds.has(release.bundleId)) {
|
|
303
|
-
state.bundleIds.add(release.bundleId);
|
|
304
|
-
retained.add(release.id);
|
|
305
|
-
}
|
|
306
|
-
if (state.bundleIds.size >= 11) {
|
|
307
|
-
state.complete = true;
|
|
308
|
-
incompleteStateCount -= 1;
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
if (incompleteStateCount === 0) break;
|
|
312
|
-
}
|
|
313
|
-
return retained;
|
|
314
|
-
}
|
|
315
|
-
function intervalContainsSegment(interval, segment) {
|
|
316
|
-
if (interval.lower !== null) {
|
|
317
|
-
if (segment.lower === null) return false;
|
|
318
|
-
const compared = compareBounds(segment.lower.version, interval.lower.version);
|
|
319
|
-
if (compared < 0 || compared === 0 && segment.lower.inclusive && !interval.lower.inclusive) return false;
|
|
320
|
-
}
|
|
321
|
-
if (interval.upper !== null) {
|
|
322
|
-
if (segment.upper === null) return false;
|
|
323
|
-
const compared = compareBounds(segment.upper.version, interval.upper.version);
|
|
324
|
-
if (compared > 0 || compared === 0 && segment.upper.inclusive && !interval.upper.inclusive) return false;
|
|
325
|
-
}
|
|
326
|
-
return true;
|
|
327
|
-
}
|
|
328
|
-
function atomicVersionSegments(intervals) {
|
|
329
|
-
const endpoints = [...new Set(intervals.flatMap((interval) => [interval.lower?.version, interval.upper?.version].filter((version) => version !== void 0)))].sort(compareBounds);
|
|
330
|
-
if (endpoints.length === 0) return [{
|
|
331
|
-
lower: null,
|
|
332
|
-
upper: null
|
|
333
|
-
}];
|
|
334
|
-
const segments = [{
|
|
335
|
-
lower: null,
|
|
336
|
-
upper: {
|
|
337
|
-
inclusive: false,
|
|
338
|
-
version: endpoints[0]
|
|
339
|
-
}
|
|
340
|
-
}];
|
|
341
|
-
for (let index = 0; index < endpoints.length; index += 1) {
|
|
342
|
-
const endpoint = endpoints[index];
|
|
343
|
-
segments.push({
|
|
344
|
-
lower: {
|
|
345
|
-
inclusive: true,
|
|
346
|
-
version: endpoint
|
|
347
|
-
},
|
|
348
|
-
upper: {
|
|
349
|
-
inclusive: true,
|
|
350
|
-
version: endpoint
|
|
351
|
-
}
|
|
352
|
-
});
|
|
353
|
-
const next = endpoints[index + 1];
|
|
354
|
-
if (next !== void 0) segments.push({
|
|
355
|
-
lower: {
|
|
356
|
-
inclusive: false,
|
|
357
|
-
version: endpoint
|
|
358
|
-
},
|
|
359
|
-
upper: {
|
|
360
|
-
inclusive: false,
|
|
361
|
-
version: next
|
|
362
|
-
}
|
|
363
|
-
});
|
|
364
|
-
}
|
|
365
|
-
segments.push({
|
|
366
|
-
lower: {
|
|
367
|
-
inclusive: false,
|
|
368
|
-
version: endpoints.at(-1)
|
|
369
|
-
},
|
|
370
|
-
upper: null
|
|
371
|
-
});
|
|
372
|
-
return segments;
|
|
373
|
-
}
|
|
374
|
-
function sameIndexes(left, right) {
|
|
375
|
-
return left.length === right.length && left.every((value, index) => value === right[index]);
|
|
376
|
-
}
|
|
377
|
-
function mergeSegments(segments) {
|
|
378
|
-
const merged = [];
|
|
379
|
-
for (const segment of segments) {
|
|
380
|
-
const previous = merged.at(-1);
|
|
381
|
-
if (previous && sameIndexes(previous.releaseIndexes, segment.releaseIndexes) && sameIndexes(previous.rollbackReleaseIndexes, segment.rollbackReleaseIndexes)) merged[merged.length - 1] = {
|
|
382
|
-
...previous,
|
|
383
|
-
upper: segment.upper
|
|
384
|
-
};
|
|
385
|
-
else merged.push(segment);
|
|
386
|
-
}
|
|
387
|
-
return merged;
|
|
388
|
-
}
|
|
389
|
-
function compileAppVersion(releases) {
|
|
390
|
-
const ranges = /* @__PURE__ */ new Map();
|
|
391
|
-
for (const release of releases) ranges.set(release.id, rangeToIntervals(release.targetAppVersion));
|
|
392
|
-
const segmentReleases = atomicVersionSegments([...ranges.values()].flat()).map((segment) => {
|
|
393
|
-
const applicable = releases.filter((release) => ranges.get(release.id).some((range) => intervalContainsSegment(range, segment)));
|
|
394
|
-
return {
|
|
395
|
-
rollbackIds: new Set(applicable.map(({ id }) => id)),
|
|
396
|
-
segment,
|
|
397
|
-
retainedIds: collectFrontierReleaseIds(applicable)
|
|
398
|
-
};
|
|
399
|
-
});
|
|
400
|
-
const retainedIds = new Set(segmentReleases.flatMap(({ retainedIds, rollbackIds }) => [...retainedIds, ...rollbackIds]));
|
|
401
|
-
const retainedReleases = releases.filter((release) => retainedIds.has(release.id));
|
|
402
|
-
const descriptorIndex = new Map(retainedReleases.map((release, index) => [release.id, index]));
|
|
403
|
-
return {
|
|
404
|
-
envelope: {
|
|
405
|
-
fallbackPolicy: RELEASE_CATALOG_FALLBACK_POLICY,
|
|
406
|
-
schemaVersion: 1,
|
|
407
|
-
segments: mergeSegments(segmentReleases.map(({ segment, retainedIds, rollbackIds }) => ({
|
|
408
|
-
...segment,
|
|
409
|
-
releaseIndexes: releases.filter((release) => retainedIds.has(release.id)).map((release) => descriptorIndex.get(release.id)).filter((index) => index !== void 0),
|
|
410
|
-
rollbackReleaseIndexes: releases.filter((release) => rollbackIds.has(release.id)).map((release) => descriptorIndex.get(release.id)).filter((index) => index !== void 0)
|
|
411
|
-
}))).filter((segment) => segment.releaseIndexes.length > 0 || segment.rollbackReleaseIndexes.length > 0),
|
|
412
|
-
strategy: "APP_VERSION"
|
|
413
|
-
},
|
|
414
|
-
retainedReleases
|
|
415
|
-
};
|
|
416
|
-
}
|
|
417
|
-
function compileFingerprint(releases) {
|
|
418
|
-
const retainedIds = collectFrontierReleaseIds(releases);
|
|
419
|
-
const retainedReleases = releases;
|
|
420
|
-
return {
|
|
421
|
-
envelope: {
|
|
422
|
-
fallbackPolicy: RELEASE_CATALOG_FALLBACK_POLICY,
|
|
423
|
-
releaseIndexes: retainedReleases.map((release, index) => retainedIds.has(release.id) ? index : -1).filter((index) => index >= 0),
|
|
424
|
-
rollbackReleaseIndexes: retainedReleases.map((_, index) => index),
|
|
425
|
-
schemaVersion: 1,
|
|
426
|
-
strategy: "FINGERPRINT"
|
|
427
|
-
},
|
|
428
|
-
retainedReleases
|
|
429
|
-
};
|
|
430
|
-
}
|
|
431
|
-
async function sha256(value) {
|
|
432
|
-
const digest = await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(value));
|
|
433
|
-
return `sha256:${[...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("")}`;
|
|
434
|
-
}
|
|
435
|
-
function canonicalStringify(value) {
|
|
436
|
-
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
437
|
-
if (Array.isArray(value)) return `[${value.map(canonicalStringify).join(",")}]`;
|
|
438
|
-
const record = value;
|
|
439
|
-
return `{${Object.keys(record).sort().map((key) => `${JSON.stringify(key)}:${canonicalStringify(record[key])}`).join(",")}}`;
|
|
440
|
-
}
|
|
441
|
-
async function compileReleaseCatalog(input) {
|
|
442
|
-
const releases = validateReleases(input.releases, input.strategy);
|
|
443
|
-
const targetCohorts = new Set(releases.flatMap((release) => release.targetCohorts));
|
|
444
|
-
if (targetCohorts.size > 512) throw new ReleaseCatalogCompilationError("DISTINCT_TARGET_COHORT_LIMIT", `Scope exceeds 512 distinct target cohorts`);
|
|
445
|
-
const { envelope, retainedReleases } = input.strategy === "APP_VERSION" ? compileAppVersion(releases) : compileFingerprint(releases);
|
|
446
|
-
const payload = {
|
|
447
|
-
...envelope,
|
|
448
|
-
releaseDescriptors: retainedReleases.map(releaseDescriptor)
|
|
449
|
-
};
|
|
450
|
-
const canonicalPayload = canonicalStringify(payload);
|
|
451
|
-
const byteSize = new TextEncoder().encode(canonicalPayload).byteLength;
|
|
452
|
-
if (byteSize > 262144) throw new ReleaseCatalogCompilationError("CATALOG_OVERSIZE", `Compiled Release catalog is ${byteSize} bytes; maximum is ${MAX_COMPILED_CATALOG_BYTES}`);
|
|
453
|
-
return {
|
|
454
|
-
byteSize,
|
|
455
|
-
canonicalPayload,
|
|
456
|
-
catalogHash: await sha256(canonicalPayload),
|
|
457
|
-
diagnostics: {
|
|
458
|
-
byteSize,
|
|
459
|
-
descriptorCount: payload.releaseDescriptors.length,
|
|
460
|
-
distinctTargetCohortCount: targetCohorts.size,
|
|
461
|
-
releaseCount: releases.length,
|
|
462
|
-
segmentCount: payload.strategy === "APP_VERSION" ? payload.segments.length : 1
|
|
463
|
-
},
|
|
464
|
-
payload
|
|
465
|
-
};
|
|
466
|
-
}
|
|
467
|
-
function versionInSegment(version, segment) {
|
|
468
|
-
if (segment.lower !== null) {
|
|
469
|
-
const compared = compareBounds(version, segment.lower.version);
|
|
470
|
-
if (compared < 0 || compared === 0 && !segment.lower.inclusive) return false;
|
|
471
|
-
}
|
|
472
|
-
if (segment.upper !== null) {
|
|
473
|
-
const compared = compareBounds(version, segment.upper.version);
|
|
474
|
-
if (compared > 0 || compared === 0 && !segment.upper.inclusive) return false;
|
|
475
|
-
}
|
|
476
|
-
return true;
|
|
477
|
-
}
|
|
478
|
-
function projectCompiledCatalog(catalog, appVersion) {
|
|
479
|
-
let indexes;
|
|
480
|
-
if (catalog.strategy === "FINGERPRINT") indexes = catalog.releaseIndexes;
|
|
481
|
-
else {
|
|
482
|
-
const canonicalVersion = appVersion && canonicalizeAppVersion(appVersion);
|
|
483
|
-
if (!canonicalVersion) return [];
|
|
484
|
-
indexes = catalog.segments.find((segment) => versionInSegment(canonicalVersion, segment))?.releaseIndexes ?? [];
|
|
485
|
-
}
|
|
486
|
-
return indexes.map((index) => catalog.releaseDescriptors[index]);
|
|
487
|
-
}
|
|
488
|
-
function projectCompiledRollbackCatalog(catalog, appVersion) {
|
|
489
|
-
let indexes;
|
|
490
|
-
if (catalog.strategy === "FINGERPRINT") indexes = catalog.rollbackReleaseIndexes;
|
|
491
|
-
else {
|
|
492
|
-
const canonicalVersion = appVersion && canonicalizeAppVersion(appVersion);
|
|
493
|
-
if (!canonicalVersion) return [];
|
|
494
|
-
indexes = catalog.segments.find((segment) => versionInSegment(canonicalVersion, segment))?.rollbackReleaseIndexes ?? [];
|
|
495
|
-
}
|
|
496
|
-
return indexes.map((index) => catalog.releaseDescriptors[index]);
|
|
497
|
-
}
|
|
498
141
|
var ReleaseCatalogMutationError = class extends Error {
|
|
499
142
|
code;
|
|
500
143
|
name = "ReleaseCatalogMutationError";
|
|
@@ -957,12 +600,17 @@ var SETTINGS_TABLE = {
|
|
|
957
600
|
var ENGINE_SCHEMA_KEY = "schema.engine";
|
|
958
601
|
var CORE_SCHEMA_KEY = "schema.core";
|
|
959
602
|
var stored = ({ key, expected, found }) => `"${key}" is ${found === null ? "missing" : `"${found}"`}; expected "${expected}"`;
|
|
960
|
-
|
|
603
|
+
/**
|
|
604
|
+
* How to migrate a database the fence refused: doctor names the command for
|
|
605
|
+
* it, init again for a deployment init manages, or the database's own
|
|
606
|
+
* tooling in the server's project.
|
|
607
|
+
*/
|
|
608
|
+
var MIGRATE_SCHEMA_FIX = "Run `npx hot-updater doctor` in the project whose hot-updater.config.ts names this database: it names the command that migrates it. In a server project, `hot-updater db migrate` migrates the database its server file names.";
|
|
609
|
+
var settingMessage = (adapterName, { key, expected, found }) => `Hot Updater schema setting "${key}" for ${adapterName} is ${found === null ? "missing" : `"${found}"`}; expected "${expected}". ${MIGRATE_SCHEMA_FIX}`;
|
|
961
610
|
/** The plugin a `schema.<id>` setting belongs to; undefined for core's and the engine's. */
|
|
962
611
|
var pluginOf = ({ key }) => key.startsWith("schema.") && key !== "schema.engine" && key !== CORE_SCHEMA_KEY ? key.slice(7) : void 0;
|
|
963
612
|
var listed = (items) => items.length < 2 ? items.join("") : `${items.slice(0, -1).join(", ")} and ${items.at(-1)}`;
|
|
964
|
-
|
|
965
|
-
var PLUGIN_TABLES_FIX = "Run `hot-updater db migrate`. A managed server runs only its provider's plugins, and rerunning `hot-updater init --provider <provider>` applies the provider's migrations. Run `hot-updater db` commands in the server's project: they load the server file named on the command line, or src/hotUpdater.* or src/db.*, and don't read hot-updater.config.ts.";
|
|
613
|
+
var settingsMessage = (adapterName, settings) => `Hot Updater schema settings for ${adapterName} are not migrated: ${settings.map(stored).join(", and ")}. ${MIGRATE_SCHEMA_FIX}`;
|
|
966
614
|
var pluginsMessage = (adapterName, plugins, settings, fix) => `The tables of ${plugins.length === 1 ? "plugin" : "plugins"} ${listed(plugins.map((id) => `"${id}"`))} are not migrated on ${adapterName}: schema ${settings.length === 1 ? "setting" : "settings"} ${settings.map(stored).join(", and ")}. ${fix}`;
|
|
967
615
|
/** The database needs `hot-updater db migrate`, or a new database; the handler answers 503. */
|
|
968
616
|
var HotUpdaterSchemaMigrationRequiredError = class extends Error {
|
|
@@ -979,7 +627,7 @@ var HotUpdaterSchemaMigrationRequiredError = class extends Error {
|
|
|
979
627
|
constructor(adapterName, currentVersion, setting, options) {
|
|
980
628
|
const settings = options?.settings ?? (setting === void 0 ? [] : [setting]);
|
|
981
629
|
const plugins = settings.flatMap((mismatch) => pluginOf(mismatch) ?? []);
|
|
982
|
-
super(setting === void 0 ? currentVersion === void 0 ? `Hot Updater database schema is not initialized for ${adapterName}.
|
|
630
|
+
super(setting === void 0 ? currentVersion === void 0 ? `Hot Updater database schema is not initialized for ${adapterName}. ${MIGRATE_SCHEMA_FIX}` : `Hot Updater v1 cannot migrate schema ${currentVersion} in place. Create a new empty database and run \`hot-updater db migrate\`.` : plugins.length > 0 && plugins.length === settings.length ? pluginsMessage(adapterName, plugins, settings, options?.fix ?? MIGRATE_SCHEMA_FIX) : settings.length > 1 && !(setting.key === "schema.engine" && setting.found === null) ? settingsMessage(adapterName, settings) : settingMessage(adapterName, setting), options?.cause === void 0 ? void 0 : { cause: options.cause });
|
|
983
631
|
this.adapterName = adapterName;
|
|
984
632
|
this.currentVersion = currentVersion;
|
|
985
633
|
this.setting = setting;
|
|
@@ -1043,17 +691,37 @@ var checkSchemaFence = async (adapter, adapterName, expected, fix) => {
|
|
|
1043
691
|
};
|
|
1044
692
|
/** The database name a fenced adapter carries, so a server can fence its plugins' rows too. */
|
|
1045
693
|
var FENCED = Symbol.for("@hot-updater/server/schema-fence");
|
|
694
|
+
/**
|
|
695
|
+
* The adapter a fence reads its settings through and the settings it
|
|
696
|
+
* expects, so a fence over it checks them with its own in one read. Another
|
|
697
|
+
* key than `FENCED`, whose value another copy of plugin-core reads as the
|
|
698
|
+
* name.
|
|
699
|
+
*/
|
|
700
|
+
var FENCED_SETTINGS = Symbol.for("@hot-updater/server/schema-fence-settings");
|
|
1046
701
|
/** The database name an adapter behind the schema fence reports under. */
|
|
1047
702
|
var fencedName = (adapter) => adapter[FENCED];
|
|
1048
703
|
/**
|
|
1049
704
|
* The adapter behind the schema fence: a process's first read or write
|
|
1050
705
|
* checks the settings first. Success is kept; a failure is checked again on
|
|
1051
|
-
* the next call.
|
|
706
|
+
* the next call. A fence over another one, as a server's plugins' over
|
|
707
|
+
* core's, checks the inner fence's settings with its own in that one read,
|
|
708
|
+
* so its refusal lists every setting missing or different.
|
|
1052
709
|
*/
|
|
1053
710
|
var withSchemaFence = (adapter, adapterName, expected, fix) => {
|
|
711
|
+
const inner = adapter[FENCED_SETTINGS];
|
|
712
|
+
const settings = inner === void 0 ? {
|
|
713
|
+
adapter,
|
|
714
|
+
expected
|
|
715
|
+
} : {
|
|
716
|
+
adapter: inner.adapter,
|
|
717
|
+
expected: {
|
|
718
|
+
...inner.expected,
|
|
719
|
+
...expected
|
|
720
|
+
}
|
|
721
|
+
};
|
|
1054
722
|
let ready;
|
|
1055
723
|
const fence = () => {
|
|
1056
|
-
ready ??= checkSchemaFence(adapter, adapterName, expected, fix).catch((error) => {
|
|
724
|
+
ready ??= checkSchemaFence(settings.adapter, adapterName, settings.expected, fix).catch((error) => {
|
|
1057
725
|
ready = void 0;
|
|
1058
726
|
throw error;
|
|
1059
727
|
});
|
|
@@ -1062,6 +730,7 @@ var withSchemaFence = (adapter, adapterName, expected, fix) => {
|
|
|
1062
730
|
return {
|
|
1063
731
|
...adapter,
|
|
1064
732
|
[FENCED]: adapterName,
|
|
733
|
+
[FENCED_SETTINGS]: settings,
|
|
1065
734
|
get: (table, keys) => fence().then(() => adapter.get(table, keys)),
|
|
1066
735
|
query: (table, request) => fence().then(() => adapter.query(table, request)),
|
|
1067
736
|
write: (ops) => fence().then(() => adapter.write(ops)),
|
|
@@ -1077,257 +746,375 @@ var CHANNEL_ID = {
|
|
|
1077
746
|
maxLength: 1408,
|
|
1078
747
|
ascii: true
|
|
1079
748
|
};
|
|
749
|
+
var bundles = defineTable({
|
|
750
|
+
id: {
|
|
751
|
+
type: "string",
|
|
752
|
+
maxLength: 36
|
|
753
|
+
},
|
|
754
|
+
platform: {
|
|
755
|
+
type: "string",
|
|
756
|
+
maxLength: 16
|
|
757
|
+
},
|
|
758
|
+
git_commit_hash: {
|
|
759
|
+
type: "string",
|
|
760
|
+
maxLength: 255,
|
|
761
|
+
required: false
|
|
762
|
+
},
|
|
763
|
+
metadata: { type: "json" },
|
|
764
|
+
manifest_storage_uri: { type: "string" },
|
|
765
|
+
manifest_file_hash: { type: "string" },
|
|
766
|
+
asset_base_storage_uri: { type: "string" }
|
|
767
|
+
}, {
|
|
768
|
+
key: ["id"],
|
|
769
|
+
indexes: {
|
|
770
|
+
byPlatform: {
|
|
771
|
+
eq: ["platform"],
|
|
772
|
+
sort: ["id"]
|
|
773
|
+
},
|
|
774
|
+
all: {
|
|
775
|
+
eq: [],
|
|
776
|
+
sort: ["id"]
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
});
|
|
780
|
+
var bundlePatches = defineTable({
|
|
781
|
+
id: {
|
|
782
|
+
type: "string",
|
|
783
|
+
maxLength: 255
|
|
784
|
+
},
|
|
785
|
+
bundle_id: {
|
|
786
|
+
type: "string",
|
|
787
|
+
maxLength: 36,
|
|
788
|
+
references: {
|
|
789
|
+
model: "bundles",
|
|
790
|
+
onDelete: "cascade"
|
|
791
|
+
}
|
|
792
|
+
},
|
|
793
|
+
base_bundle_id: {
|
|
794
|
+
type: "string",
|
|
795
|
+
maxLength: 36,
|
|
796
|
+
references: {
|
|
797
|
+
model: "bundles",
|
|
798
|
+
onDelete: "cascade"
|
|
799
|
+
}
|
|
800
|
+
},
|
|
801
|
+
base_file_hash: { type: "string" },
|
|
802
|
+
patch_file_hash: { type: "string" },
|
|
803
|
+
patch_storage_uri: { type: "string" },
|
|
804
|
+
byte_size: { type: "integer" },
|
|
805
|
+
order_index: { type: "integer" }
|
|
806
|
+
}, {
|
|
807
|
+
key: ["id"],
|
|
808
|
+
indexes: {
|
|
809
|
+
pair: {
|
|
810
|
+
eq: ["bundle_id", "base_bundle_id"],
|
|
811
|
+
sort: [],
|
|
812
|
+
unique: true
|
|
813
|
+
},
|
|
814
|
+
byBundle: {
|
|
815
|
+
eq: ["bundle_id"],
|
|
816
|
+
sort: ["order_index"],
|
|
817
|
+
root: { model: "bundles" }
|
|
818
|
+
},
|
|
819
|
+
byBase: {
|
|
820
|
+
eq: ["base_bundle_id"],
|
|
821
|
+
sort: ["bundle_id"]
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
});
|
|
825
|
+
var releases = defineTable({
|
|
826
|
+
id: {
|
|
827
|
+
type: "string",
|
|
828
|
+
maxLength: 36
|
|
829
|
+
},
|
|
830
|
+
revision: { type: "integer" },
|
|
831
|
+
scope_key: {
|
|
832
|
+
type: "string",
|
|
833
|
+
maxLength: 2048,
|
|
834
|
+
ascii: true
|
|
835
|
+
},
|
|
836
|
+
channel_id: {
|
|
837
|
+
...CHANNEL_ID,
|
|
838
|
+
references: {
|
|
839
|
+
model: "channels",
|
|
840
|
+
onDelete: "restrict"
|
|
841
|
+
}
|
|
842
|
+
},
|
|
843
|
+
platform: {
|
|
844
|
+
type: "string",
|
|
845
|
+
maxLength: 16
|
|
846
|
+
},
|
|
847
|
+
kind: {
|
|
848
|
+
type: "string",
|
|
849
|
+
maxLength: 16
|
|
850
|
+
},
|
|
851
|
+
bundle_id: {
|
|
852
|
+
type: "string",
|
|
853
|
+
maxLength: 36,
|
|
854
|
+
required: false,
|
|
855
|
+
references: {
|
|
856
|
+
model: "bundles",
|
|
857
|
+
onDelete: "restrict"
|
|
858
|
+
}
|
|
859
|
+
},
|
|
860
|
+
strategy: {
|
|
861
|
+
type: "string",
|
|
862
|
+
maxLength: 16
|
|
863
|
+
},
|
|
864
|
+
target_app_version: {
|
|
865
|
+
type: "string",
|
|
866
|
+
required: false
|
|
867
|
+
},
|
|
868
|
+
fingerprint_hash: {
|
|
869
|
+
type: "string",
|
|
870
|
+
maxLength: 255,
|
|
871
|
+
required: false
|
|
872
|
+
},
|
|
873
|
+
enabled: { type: "boolean" },
|
|
874
|
+
should_force_update: { type: "boolean" },
|
|
875
|
+
message: {
|
|
876
|
+
type: "string",
|
|
877
|
+
required: false
|
|
878
|
+
},
|
|
879
|
+
rollout_cohort_count: { type: "integer" },
|
|
880
|
+
target_cohorts: { type: "json" },
|
|
881
|
+
operation: {
|
|
882
|
+
type: "string",
|
|
883
|
+
maxLength: 16
|
|
884
|
+
},
|
|
885
|
+
source_release_id: {
|
|
886
|
+
type: "string",
|
|
887
|
+
maxLength: 36,
|
|
888
|
+
required: false,
|
|
889
|
+
references: {
|
|
890
|
+
model: "releases",
|
|
891
|
+
onDelete: "none"
|
|
892
|
+
}
|
|
893
|
+
},
|
|
894
|
+
created_at_ms: { type: "integer" },
|
|
895
|
+
updated_at_ms: { type: "integer" }
|
|
896
|
+
}, {
|
|
897
|
+
key: ["id"],
|
|
898
|
+
indexes: {
|
|
899
|
+
byScope: {
|
|
900
|
+
eq: ["scope_key"],
|
|
901
|
+
sort: ["id"],
|
|
902
|
+
root: { model: "release_catalogs" }
|
|
903
|
+
},
|
|
904
|
+
byScopeEnabled: {
|
|
905
|
+
eq: ["scope_key", "enabled"],
|
|
906
|
+
sort: ["id"],
|
|
907
|
+
root: { model: "release_catalogs" }
|
|
908
|
+
},
|
|
909
|
+
byChannelPlatform: {
|
|
910
|
+
eq: ["channel_id", "platform"],
|
|
911
|
+
sort: ["id"]
|
|
912
|
+
},
|
|
913
|
+
byChannelPlatformEnabled: {
|
|
914
|
+
eq: [
|
|
915
|
+
"channel_id",
|
|
916
|
+
"platform",
|
|
917
|
+
"enabled"
|
|
918
|
+
],
|
|
919
|
+
sort: ["id"]
|
|
920
|
+
},
|
|
921
|
+
byBundle: {
|
|
922
|
+
eq: ["bundle_id"],
|
|
923
|
+
sort: ["id"]
|
|
924
|
+
},
|
|
925
|
+
all: {
|
|
926
|
+
eq: [],
|
|
927
|
+
sort: ["id"]
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
});
|
|
931
|
+
/** One compiled catalog per scope; the update check reads exactly this row. */
|
|
932
|
+
var releaseCatalogs = defineTable({
|
|
933
|
+
scope_key: {
|
|
934
|
+
type: "string",
|
|
935
|
+
maxLength: 2048,
|
|
936
|
+
ascii: true
|
|
937
|
+
},
|
|
938
|
+
catalog_id: {
|
|
939
|
+
type: "string",
|
|
940
|
+
maxLength: 255
|
|
941
|
+
},
|
|
942
|
+
strategy: {
|
|
943
|
+
type: "string",
|
|
944
|
+
maxLength: 16
|
|
945
|
+
},
|
|
946
|
+
channel_id: {
|
|
947
|
+
...CHANNEL_ID,
|
|
948
|
+
references: {
|
|
949
|
+
model: "channels",
|
|
950
|
+
onDelete: "none"
|
|
951
|
+
}
|
|
952
|
+
},
|
|
953
|
+
channel_key: {
|
|
954
|
+
type: "string",
|
|
955
|
+
maxLength: 1400,
|
|
956
|
+
ascii: true
|
|
957
|
+
},
|
|
958
|
+
platform: {
|
|
959
|
+
type: "string",
|
|
960
|
+
maxLength: 16
|
|
961
|
+
},
|
|
962
|
+
fingerprint_hash: {
|
|
963
|
+
type: "string",
|
|
964
|
+
maxLength: 255,
|
|
965
|
+
required: false
|
|
966
|
+
},
|
|
967
|
+
generation: { type: "integer" },
|
|
968
|
+
payload: { type: "string" },
|
|
969
|
+
catalog_hash: {
|
|
970
|
+
type: "string",
|
|
971
|
+
maxLength: 71
|
|
972
|
+
},
|
|
973
|
+
byte_size: { type: "integer" },
|
|
974
|
+
is_tombstone: { type: "boolean" },
|
|
975
|
+
updated_at_ms: { type: "integer" }
|
|
976
|
+
}, {
|
|
977
|
+
key: ["scope_key"],
|
|
978
|
+
indexes: { all: {
|
|
979
|
+
eq: [],
|
|
980
|
+
sort: ["scope_key"]
|
|
981
|
+
} }
|
|
982
|
+
});
|
|
983
|
+
var channels = defineTable({
|
|
984
|
+
id: CHANNEL_ID,
|
|
985
|
+
name: {
|
|
986
|
+
type: "string",
|
|
987
|
+
maxLength: 255,
|
|
988
|
+
unique: true
|
|
989
|
+
}
|
|
990
|
+
}, {
|
|
991
|
+
key: ["id"],
|
|
992
|
+
indexes: { all: {
|
|
993
|
+
eq: [],
|
|
994
|
+
sort: ["name"]
|
|
995
|
+
} }
|
|
996
|
+
});
|
|
997
|
+
/**
|
|
998
|
+
* The native builds `native-build android` and `native-build ios` track, newest first
|
|
999
|
+
* in each scope: a platform, a channel, and the fingerprint or app version
|
|
1000
|
+
* the build compiled in. `min_bundle_id` names the build's built-in bundle,
|
|
1001
|
+
* a `bundles` row no release publishes. Its references keep no counters, so
|
|
1002
|
+
* adding this table changes no existing one; a channel with builds is
|
|
1003
|
+
* refused deletion through `byChannel`. `build_key` is the native build key
|
|
1004
|
+
* of every input the artifact was built from (`nbk1:` and a SHA-256), which
|
|
1005
|
+
* a build with the same inputs reuses it by; a build registered without
|
|
1006
|
+
* one is never reused. `build_number` is the artifact's `CFBundleVersion`
|
|
1007
|
+
* or `versionCode`. `submitted_to`, `submitted_at_ms` and
|
|
1008
|
+
* `submitted_version` record the store track a build went to, when, and
|
|
1009
|
+
* the store's label of the build; they stay null for a build no store took.
|
|
1010
|
+
*/
|
|
1011
|
+
var nativeBuilds = defineTable({
|
|
1012
|
+
id: {
|
|
1013
|
+
type: "string",
|
|
1014
|
+
maxLength: 36
|
|
1015
|
+
},
|
|
1016
|
+
scope_key: {
|
|
1017
|
+
type: "string",
|
|
1018
|
+
maxLength: 2048,
|
|
1019
|
+
ascii: true
|
|
1020
|
+
},
|
|
1021
|
+
platform: {
|
|
1022
|
+
type: "string",
|
|
1023
|
+
maxLength: 16
|
|
1024
|
+
},
|
|
1025
|
+
channel_id: {
|
|
1026
|
+
...CHANNEL_ID,
|
|
1027
|
+
references: {
|
|
1028
|
+
model: "channels",
|
|
1029
|
+
onDelete: "none"
|
|
1030
|
+
}
|
|
1031
|
+
},
|
|
1032
|
+
fingerprint_hash: {
|
|
1033
|
+
type: "string",
|
|
1034
|
+
maxLength: 255,
|
|
1035
|
+
required: false
|
|
1036
|
+
},
|
|
1037
|
+
app_version: {
|
|
1038
|
+
type: "string",
|
|
1039
|
+
required: false
|
|
1040
|
+
},
|
|
1041
|
+
min_bundle_id: {
|
|
1042
|
+
type: "string",
|
|
1043
|
+
maxLength: 36,
|
|
1044
|
+
unique: true,
|
|
1045
|
+
references: {
|
|
1046
|
+
model: "bundles",
|
|
1047
|
+
onDelete: "none"
|
|
1048
|
+
}
|
|
1049
|
+
},
|
|
1050
|
+
artifact_kind: {
|
|
1051
|
+
type: "string",
|
|
1052
|
+
maxLength: 16
|
|
1053
|
+
},
|
|
1054
|
+
artifact_storage_uri: { type: "string" },
|
|
1055
|
+
byte_size: { type: "integer" },
|
|
1056
|
+
git_commit_hash: {
|
|
1057
|
+
type: "string",
|
|
1058
|
+
maxLength: 255,
|
|
1059
|
+
required: false
|
|
1060
|
+
},
|
|
1061
|
+
created_at_ms: { type: "integer" },
|
|
1062
|
+
build_key: {
|
|
1063
|
+
type: "string",
|
|
1064
|
+
maxLength: 69,
|
|
1065
|
+
ascii: true,
|
|
1066
|
+
required: false
|
|
1067
|
+
},
|
|
1068
|
+
build_number: {
|
|
1069
|
+
type: "string",
|
|
1070
|
+
maxLength: 64,
|
|
1071
|
+
required: false
|
|
1072
|
+
},
|
|
1073
|
+
submitted_to: {
|
|
1074
|
+
type: "string",
|
|
1075
|
+
maxLength: 16,
|
|
1076
|
+
required: false
|
|
1077
|
+
},
|
|
1078
|
+
submitted_at_ms: {
|
|
1079
|
+
type: "integer",
|
|
1080
|
+
required: false
|
|
1081
|
+
},
|
|
1082
|
+
submitted_version: {
|
|
1083
|
+
type: "string",
|
|
1084
|
+
maxLength: 255,
|
|
1085
|
+
required: false
|
|
1086
|
+
}
|
|
1087
|
+
}, {
|
|
1088
|
+
key: ["id"],
|
|
1089
|
+
indexes: {
|
|
1090
|
+
byScope: {
|
|
1091
|
+
eq: ["scope_key"],
|
|
1092
|
+
sort: ["id"]
|
|
1093
|
+
},
|
|
1094
|
+
byBuildKey: {
|
|
1095
|
+
eq: ["scope_key", "build_key"],
|
|
1096
|
+
sort: ["id"]
|
|
1097
|
+
},
|
|
1098
|
+
byChannel: {
|
|
1099
|
+
eq: ["channel_id"],
|
|
1100
|
+
sort: ["id"],
|
|
1101
|
+
root: { model: "channels" }
|
|
1102
|
+
},
|
|
1103
|
+
all: {
|
|
1104
|
+
eq: [],
|
|
1105
|
+
sort: ["id"]
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
});
|
|
1080
1109
|
/** Core's module: always installed, never a plugin. */
|
|
1081
1110
|
var coreModule = {
|
|
1082
1111
|
id: "core",
|
|
1083
1112
|
schema: {
|
|
1084
|
-
bundles
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
platform: {
|
|
1090
|
-
type: "string",
|
|
1091
|
-
maxLength: 16
|
|
1092
|
-
},
|
|
1093
|
-
git_commit_hash: {
|
|
1094
|
-
type: "string",
|
|
1095
|
-
maxLength: 255,
|
|
1096
|
-
required: false
|
|
1097
|
-
},
|
|
1098
|
-
metadata: { type: "json" },
|
|
1099
|
-
manifest_storage_uri: { type: "string" },
|
|
1100
|
-
manifest_file_hash: { type: "string" },
|
|
1101
|
-
asset_base_storage_uri: { type: "string" }
|
|
1102
|
-
}, {
|
|
1103
|
-
key: ["id"],
|
|
1104
|
-
indexes: {
|
|
1105
|
-
byPlatform: {
|
|
1106
|
-
eq: ["platform"],
|
|
1107
|
-
sort: ["id"]
|
|
1108
|
-
},
|
|
1109
|
-
all: {
|
|
1110
|
-
eq: [],
|
|
1111
|
-
sort: ["id"]
|
|
1112
|
-
}
|
|
1113
|
-
}
|
|
1114
|
-
}),
|
|
1115
|
-
bundle_patches: defineTable({
|
|
1116
|
-
id: {
|
|
1117
|
-
type: "string",
|
|
1118
|
-
maxLength: 255
|
|
1119
|
-
},
|
|
1120
|
-
bundle_id: {
|
|
1121
|
-
type: "string",
|
|
1122
|
-
maxLength: 36,
|
|
1123
|
-
references: {
|
|
1124
|
-
model: "bundles",
|
|
1125
|
-
onDelete: "cascade"
|
|
1126
|
-
}
|
|
1127
|
-
},
|
|
1128
|
-
base_bundle_id: {
|
|
1129
|
-
type: "string",
|
|
1130
|
-
maxLength: 36,
|
|
1131
|
-
references: {
|
|
1132
|
-
model: "bundles",
|
|
1133
|
-
onDelete: "cascade"
|
|
1134
|
-
}
|
|
1135
|
-
},
|
|
1136
|
-
base_file_hash: { type: "string" },
|
|
1137
|
-
patch_file_hash: { type: "string" },
|
|
1138
|
-
patch_storage_uri: { type: "string" },
|
|
1139
|
-
byte_size: { type: "integer" },
|
|
1140
|
-
order_index: { type: "integer" }
|
|
1141
|
-
}, {
|
|
1142
|
-
key: ["id"],
|
|
1143
|
-
indexes: {
|
|
1144
|
-
pair: {
|
|
1145
|
-
eq: ["bundle_id", "base_bundle_id"],
|
|
1146
|
-
sort: [],
|
|
1147
|
-
unique: true
|
|
1148
|
-
},
|
|
1149
|
-
byBundle: {
|
|
1150
|
-
eq: ["bundle_id"],
|
|
1151
|
-
sort: ["order_index"],
|
|
1152
|
-
root: { model: "bundles" }
|
|
1153
|
-
},
|
|
1154
|
-
byBase: {
|
|
1155
|
-
eq: ["base_bundle_id"],
|
|
1156
|
-
sort: ["bundle_id"]
|
|
1157
|
-
}
|
|
1158
|
-
}
|
|
1159
|
-
}),
|
|
1160
|
-
releases: defineTable({
|
|
1161
|
-
id: {
|
|
1162
|
-
type: "string",
|
|
1163
|
-
maxLength: 36
|
|
1164
|
-
},
|
|
1165
|
-
revision: { type: "integer" },
|
|
1166
|
-
scope_key: {
|
|
1167
|
-
type: "string",
|
|
1168
|
-
maxLength: 2048,
|
|
1169
|
-
ascii: true
|
|
1170
|
-
},
|
|
1171
|
-
channel_id: {
|
|
1172
|
-
...CHANNEL_ID,
|
|
1173
|
-
references: {
|
|
1174
|
-
model: "channels",
|
|
1175
|
-
onDelete: "restrict"
|
|
1176
|
-
}
|
|
1177
|
-
},
|
|
1178
|
-
platform: {
|
|
1179
|
-
type: "string",
|
|
1180
|
-
maxLength: 16
|
|
1181
|
-
},
|
|
1182
|
-
kind: {
|
|
1183
|
-
type: "string",
|
|
1184
|
-
maxLength: 16
|
|
1185
|
-
},
|
|
1186
|
-
bundle_id: {
|
|
1187
|
-
type: "string",
|
|
1188
|
-
maxLength: 36,
|
|
1189
|
-
required: false,
|
|
1190
|
-
references: {
|
|
1191
|
-
model: "bundles",
|
|
1192
|
-
onDelete: "restrict"
|
|
1193
|
-
}
|
|
1194
|
-
},
|
|
1195
|
-
strategy: {
|
|
1196
|
-
type: "string",
|
|
1197
|
-
maxLength: 16
|
|
1198
|
-
},
|
|
1199
|
-
target_app_version: {
|
|
1200
|
-
type: "string",
|
|
1201
|
-
required: false
|
|
1202
|
-
},
|
|
1203
|
-
fingerprint_hash: {
|
|
1204
|
-
type: "string",
|
|
1205
|
-
maxLength: 255,
|
|
1206
|
-
required: false
|
|
1207
|
-
},
|
|
1208
|
-
enabled: { type: "boolean" },
|
|
1209
|
-
should_force_update: { type: "boolean" },
|
|
1210
|
-
message: {
|
|
1211
|
-
type: "string",
|
|
1212
|
-
required: false
|
|
1213
|
-
},
|
|
1214
|
-
rollout_cohort_count: { type: "integer" },
|
|
1215
|
-
target_cohorts: { type: "json" },
|
|
1216
|
-
operation: {
|
|
1217
|
-
type: "string",
|
|
1218
|
-
maxLength: 16
|
|
1219
|
-
},
|
|
1220
|
-
source_release_id: {
|
|
1221
|
-
type: "string",
|
|
1222
|
-
maxLength: 36,
|
|
1223
|
-
required: false,
|
|
1224
|
-
references: {
|
|
1225
|
-
model: "releases",
|
|
1226
|
-
onDelete: "none"
|
|
1227
|
-
}
|
|
1228
|
-
},
|
|
1229
|
-
created_at_ms: { type: "integer" },
|
|
1230
|
-
updated_at_ms: { type: "integer" }
|
|
1231
|
-
}, {
|
|
1232
|
-
key: ["id"],
|
|
1233
|
-
indexes: {
|
|
1234
|
-
byScope: {
|
|
1235
|
-
eq: ["scope_key"],
|
|
1236
|
-
sort: ["id"],
|
|
1237
|
-
root: { model: "release_catalogs" }
|
|
1238
|
-
},
|
|
1239
|
-
byScopeEnabled: {
|
|
1240
|
-
eq: ["scope_key", "enabled"],
|
|
1241
|
-
sort: ["id"],
|
|
1242
|
-
root: { model: "release_catalogs" }
|
|
1243
|
-
},
|
|
1244
|
-
byChannelPlatform: {
|
|
1245
|
-
eq: ["channel_id", "platform"],
|
|
1246
|
-
sort: ["id"]
|
|
1247
|
-
},
|
|
1248
|
-
byChannelPlatformEnabled: {
|
|
1249
|
-
eq: [
|
|
1250
|
-
"channel_id",
|
|
1251
|
-
"platform",
|
|
1252
|
-
"enabled"
|
|
1253
|
-
],
|
|
1254
|
-
sort: ["id"]
|
|
1255
|
-
},
|
|
1256
|
-
byBundle: {
|
|
1257
|
-
eq: ["bundle_id"],
|
|
1258
|
-
sort: ["id"]
|
|
1259
|
-
},
|
|
1260
|
-
all: {
|
|
1261
|
-
eq: [],
|
|
1262
|
-
sort: ["id"]
|
|
1263
|
-
}
|
|
1264
|
-
}
|
|
1265
|
-
}),
|
|
1266
|
-
release_catalogs: defineTable({
|
|
1267
|
-
scope_key: {
|
|
1268
|
-
type: "string",
|
|
1269
|
-
maxLength: 2048,
|
|
1270
|
-
ascii: true
|
|
1271
|
-
},
|
|
1272
|
-
catalog_id: {
|
|
1273
|
-
type: "string",
|
|
1274
|
-
maxLength: 255
|
|
1275
|
-
},
|
|
1276
|
-
strategy: {
|
|
1277
|
-
type: "string",
|
|
1278
|
-
maxLength: 16
|
|
1279
|
-
},
|
|
1280
|
-
channel_id: {
|
|
1281
|
-
...CHANNEL_ID,
|
|
1282
|
-
references: {
|
|
1283
|
-
model: "channels",
|
|
1284
|
-
onDelete: "none"
|
|
1285
|
-
}
|
|
1286
|
-
},
|
|
1287
|
-
channel_key: {
|
|
1288
|
-
type: "string",
|
|
1289
|
-
maxLength: 1400,
|
|
1290
|
-
ascii: true
|
|
1291
|
-
},
|
|
1292
|
-
platform: {
|
|
1293
|
-
type: "string",
|
|
1294
|
-
maxLength: 16
|
|
1295
|
-
},
|
|
1296
|
-
fingerprint_hash: {
|
|
1297
|
-
type: "string",
|
|
1298
|
-
maxLength: 255,
|
|
1299
|
-
required: false
|
|
1300
|
-
},
|
|
1301
|
-
generation: { type: "integer" },
|
|
1302
|
-
payload: { type: "string" },
|
|
1303
|
-
catalog_hash: {
|
|
1304
|
-
type: "string",
|
|
1305
|
-
maxLength: 71
|
|
1306
|
-
},
|
|
1307
|
-
byte_size: { type: "integer" },
|
|
1308
|
-
is_tombstone: { type: "boolean" },
|
|
1309
|
-
updated_at_ms: { type: "integer" }
|
|
1310
|
-
}, {
|
|
1311
|
-
key: ["scope_key"],
|
|
1312
|
-
indexes: { all: {
|
|
1313
|
-
eq: [],
|
|
1314
|
-
sort: ["scope_key"]
|
|
1315
|
-
} }
|
|
1316
|
-
}),
|
|
1317
|
-
channels: defineTable({
|
|
1318
|
-
id: CHANNEL_ID,
|
|
1319
|
-
name: {
|
|
1320
|
-
type: "string",
|
|
1321
|
-
maxLength: 255,
|
|
1322
|
-
unique: true
|
|
1323
|
-
}
|
|
1324
|
-
}, {
|
|
1325
|
-
key: ["id"],
|
|
1326
|
-
indexes: { all: {
|
|
1327
|
-
eq: [],
|
|
1328
|
-
sort: ["name"]
|
|
1329
|
-
} }
|
|
1330
|
-
}),
|
|
1113
|
+
bundles,
|
|
1114
|
+
bundle_patches: bundlePatches,
|
|
1115
|
+
releases,
|
|
1116
|
+
release_catalogs: releaseCatalogs,
|
|
1117
|
+
channels,
|
|
1331
1118
|
bundle_totals: defineAggregate({ platform_key: {
|
|
1332
1119
|
type: "string",
|
|
1333
1120
|
maxLength: 16
|
|
@@ -1338,7 +1125,8 @@ var coreModule = {
|
|
|
1338
1125
|
eq: ["platform_key"],
|
|
1339
1126
|
sort: []
|
|
1340
1127
|
} }
|
|
1341
|
-
})
|
|
1128
|
+
}),
|
|
1129
|
+
native_builds: nativeBuilds
|
|
1342
1130
|
}
|
|
1343
1131
|
};
|
|
1344
1132
|
var encoder = new TextEncoder();
|
|
@@ -3044,9 +2832,9 @@ var createDatabaseEngine = ({ batching, now = Date.now, meter, ...options }) =>
|
|
|
3044
2832
|
*/
|
|
3045
2833
|
var pluginTablesFix = (database) => {
|
|
3046
2834
|
const { createMigrator, generateSchema } = database;
|
|
3047
|
-
const
|
|
2835
|
+
const doctor = "Run `npx hot-updater doctor` in the project whose hot-updater.config.ts names this database: it names the command that migrates it.";
|
|
3048
2836
|
const serverProject = "Run `hot-updater db` commands in the server's project: they load the server file named on the command line, or src/hotUpdater.* or src/db.*, and don't read hot-updater.config.ts.";
|
|
3049
|
-
return createMigrator !== void 0 ?
|
|
2837
|
+
return createMigrator !== void 0 ? `${doctor} In a server project, run \`hot-updater db migrate\`. ${serverProject}` : generateSchema !== void 0 ? `${doctor} On a database \`hot-updater init\` created, that is init again with its saved inputs; for your own server, run \`hot-updater db generate\` and apply the file it writes. ${serverProject}` : `${doctor} On a database \`hot-updater init\` created, that is init again with its saved inputs.`;
|
|
3050
2838
|
};
|
|
3051
2839
|
/**
|
|
3052
2840
|
* The storage engine over a database, as a server runs it: core's tables
|
|
@@ -3098,7 +2886,7 @@ var createEngine = (database, { plugins = [], now = Date.now } = {}) => {
|
|
|
3098
2886
|
dispose: () => engine.dispose()
|
|
3099
2887
|
};
|
|
3100
2888
|
};
|
|
3101
|
-
var HOT_UPDATER_SERVER_VERSION = "1.1
|
|
2889
|
+
var HOT_UPDATER_SERVER_VERSION = "1.2.0-rc.1";
|
|
3102
2890
|
/**
|
|
3103
2891
|
* `/version` on both mounts. The admin mount also lists the ids of the
|
|
3104
2892
|
* plugins the server runs, sorted; apps never learn which plugins a server
|
|
@@ -3533,8 +3321,8 @@ var baseBundleIdsOf = (row, range, bundleId, limit) => {
|
|
|
3533
3321
|
return ids;
|
|
3534
3322
|
};
|
|
3535
3323
|
var PAGE$2 = 500;
|
|
3536
|
-
var pick = (fields) => (row) => Object.fromEntries(fields.map((field) => [field, row[field]]));
|
|
3537
|
-
var toBundleRow = pick([
|
|
3324
|
+
var pick$1 = (fields) => (row) => Object.fromEntries(fields.map((field) => [field, row[field]]));
|
|
3325
|
+
var toBundleRow = pick$1([
|
|
3538
3326
|
"id",
|
|
3539
3327
|
"platform",
|
|
3540
3328
|
"git_commit_hash",
|
|
@@ -3543,7 +3331,7 @@ var toBundleRow = pick([
|
|
|
3543
3331
|
"manifest_file_hash",
|
|
3544
3332
|
"asset_base_storage_uri"
|
|
3545
3333
|
]);
|
|
3546
|
-
var toPatchRow = pick([
|
|
3334
|
+
var toPatchRow = pick$1([
|
|
3547
3335
|
"id",
|
|
3548
3336
|
"bundle_id",
|
|
3549
3337
|
"base_bundle_id",
|
|
@@ -3553,7 +3341,7 @@ var toPatchRow = pick([
|
|
|
3553
3341
|
"byte_size",
|
|
3554
3342
|
"order_index"
|
|
3555
3343
|
]);
|
|
3556
|
-
var toReleaseRow = pick([
|
|
3344
|
+
var toReleaseRow = pick$1([
|
|
3557
3345
|
"id",
|
|
3558
3346
|
"revision",
|
|
3559
3347
|
"scope_key",
|
|
@@ -3574,7 +3362,7 @@ var toReleaseRow = pick([
|
|
|
3574
3362
|
"created_at_ms",
|
|
3575
3363
|
"updated_at_ms"
|
|
3576
3364
|
]);
|
|
3577
|
-
var toCatalogRow = pick([
|
|
3365
|
+
var toCatalogRow = pick$1([
|
|
3578
3366
|
"scope_key",
|
|
3579
3367
|
"catalog_id",
|
|
3580
3368
|
"strategy",
|
|
@@ -3589,7 +3377,7 @@ var toCatalogRow = pick([
|
|
|
3589
3377
|
"is_tombstone",
|
|
3590
3378
|
"updated_at_ms"
|
|
3591
3379
|
]);
|
|
3592
|
-
var toChannelRow = pick(["id", "name"]);
|
|
3380
|
+
var toChannelRow = pick$1(["id", "name"]);
|
|
3593
3381
|
/** Every page of one read, in order. */
|
|
3594
3382
|
var drain = async (read) => {
|
|
3595
3383
|
const rows = [];
|
|
@@ -3601,6 +3389,8 @@ var drain = async (read) => {
|
|
|
3601
3389
|
} while (cursor !== void 0);
|
|
3602
3390
|
return rows;
|
|
3603
3391
|
};
|
|
3392
|
+
/** A keyset page's range: the keys strictly after `after`, in `order`. */
|
|
3393
|
+
var after = (input) => input.after === void 0 ? {} : { range: (input.order ?? "asc") === "asc" ? { gt: input.after } : { lt: input.after } };
|
|
3604
3394
|
/** Core's reads, each through one declared index or key. */
|
|
3605
3395
|
var createCoreReads = (db, storage) => {
|
|
3606
3396
|
/** A bundle row's patches, exactly as many as its reference counter holds. */
|
|
@@ -3625,7 +3415,6 @@ var createCoreReads = (db, storage) => {
|
|
|
3625
3415
|
childCount: row._refs_bundle_patches_base_bundle_id ?? 0
|
|
3626
3416
|
};
|
|
3627
3417
|
};
|
|
3628
|
-
const after = (input) => input.after === void 0 ? {} : { range: (input.order ?? "asc") === "asc" ? { gt: input.after } : { lt: input.after } };
|
|
3629
3418
|
return {
|
|
3630
3419
|
async getReleaseCatalog(input) {
|
|
3631
3420
|
const scopeKey = releaseCatalogScopeKeyOf(input);
|
|
@@ -3802,9 +3591,13 @@ var insertBundle = (tx, row) => {
|
|
|
3802
3591
|
tx.create("bundles", row);
|
|
3803
3592
|
countBundle(tx, row.platform, 1);
|
|
3804
3593
|
};
|
|
3805
|
-
|
|
3594
|
+
/**
|
|
3595
|
+
* Updates a bundle; a platform change moves it between platform totals,
|
|
3596
|
+
* except for a native build's built-in bundle, which they never count.
|
|
3597
|
+
*/
|
|
3598
|
+
var updateBundle = (tx, current, set, { counted = true } = {}) => {
|
|
3806
3599
|
tx.update("bundles", current, set);
|
|
3807
|
-
if (set.platform !== void 0 && set.platform !== current.platform) {
|
|
3600
|
+
if (counted && set.platform !== void 0 && set.platform !== current.platform) {
|
|
3808
3601
|
countBundle(tx, current.platform, -1);
|
|
3809
3602
|
countBundle(tx, set.platform, 1);
|
|
3810
3603
|
}
|
|
@@ -3865,7 +3658,7 @@ var insertChannel = async (db, row) => {
|
|
|
3865
3658
|
throw error;
|
|
3866
3659
|
}
|
|
3867
3660
|
};
|
|
3868
|
-
/** Deletes a channel no release uses: 1 read
|
|
3661
|
+
/** Deletes a channel no release or native build uses: 1 read, 1 query, 1 write. */
|
|
3869
3662
|
var deleteChannel = (db, id) => db.transaction(async (tx) => {
|
|
3870
3663
|
const row = await tx.findOne("channels", { id });
|
|
3871
3664
|
if (row === null) return {
|
|
@@ -3876,9 +3669,240 @@ var deleteChannel = (db, id) => db.transaction(async (tx) => {
|
|
|
3876
3669
|
deleted: false,
|
|
3877
3670
|
reason: "not_empty"
|
|
3878
3671
|
};
|
|
3672
|
+
const { rows: builds } = await tx.findMany("native_builds", {
|
|
3673
|
+
index: "byChannel",
|
|
3674
|
+
where: { channel_id: id },
|
|
3675
|
+
limit: 1
|
|
3676
|
+
});
|
|
3677
|
+
if (builds.length > 0) return {
|
|
3678
|
+
deleted: false,
|
|
3679
|
+
reason: "not_empty"
|
|
3680
|
+
};
|
|
3879
3681
|
await tx.delete("channels", row);
|
|
3880
3682
|
return { deleted: true };
|
|
3881
3683
|
});
|
|
3684
|
+
/** The artifacts each platform's build produces. */
|
|
3685
|
+
var ARTIFACT_KINDS = {
|
|
3686
|
+
android: ["apk", "aab"],
|
|
3687
|
+
ios: ["ipa", "app"]
|
|
3688
|
+
};
|
|
3689
|
+
/** `native_builds.scope_key`'s bound in core's schema. */
|
|
3690
|
+
var SCOPE_KEY_MAX_LENGTH = 2048;
|
|
3691
|
+
/** The `git_commit_hash` bound of `bundles` and `native_builds`. */
|
|
3692
|
+
var GIT_COMMIT_HASH_MAX_LENGTH = 255;
|
|
3693
|
+
/**
|
|
3694
|
+
* A native build key: `nbk1:` and a SHA-256, as the CLI computes it. The
|
|
3695
|
+
* format is the CLI's convention, implemented here so the registry stores
|
|
3696
|
+
* and looks up nothing else.
|
|
3697
|
+
*/
|
|
3698
|
+
var BUILD_KEY = /^nbk1:[0-9a-f]{64}$/;
|
|
3699
|
+
/** A native build or scope core cannot store or look up: the caller's input. */
|
|
3700
|
+
var NativeBuildInputError = class extends TypeError {
|
|
3701
|
+
name = "NativeBuildInputError";
|
|
3702
|
+
};
|
|
3703
|
+
var pick = (row) => ({
|
|
3704
|
+
id: row.id,
|
|
3705
|
+
scope_key: row.scope_key,
|
|
3706
|
+
platform: row.platform,
|
|
3707
|
+
channel_id: row.channel_id,
|
|
3708
|
+
fingerprint_hash: row.fingerprint_hash ?? null,
|
|
3709
|
+
app_version: row.app_version ?? null,
|
|
3710
|
+
min_bundle_id: row.min_bundle_id,
|
|
3711
|
+
artifact_kind: row.artifact_kind,
|
|
3712
|
+
artifact_storage_uri: row.artifact_storage_uri,
|
|
3713
|
+
byte_size: row.byte_size,
|
|
3714
|
+
git_commit_hash: row.git_commit_hash ?? null,
|
|
3715
|
+
created_at_ms: row.created_at_ms,
|
|
3716
|
+
build_key: row.build_key ?? null,
|
|
3717
|
+
build_number: row.build_number ?? null,
|
|
3718
|
+
submitted_to: row.submitted_to ?? null,
|
|
3719
|
+
submitted_at_ms: row.submitted_at_ms ?? null,
|
|
3720
|
+
submitted_version: row.submitted_version ?? null
|
|
3721
|
+
});
|
|
3722
|
+
/** The store track each platform's builds are submitted to. */
|
|
3723
|
+
var SUBMISSION_DESTINATIONS = {
|
|
3724
|
+
android: "play-internal",
|
|
3725
|
+
ios: "testflight"
|
|
3726
|
+
};
|
|
3727
|
+
/** `native_builds.build_number`'s bound in core's schema. */
|
|
3728
|
+
var BUILD_NUMBER_MAX_LENGTH = 64;
|
|
3729
|
+
/** `native_builds.submitted_version`'s bound in core's schema. */
|
|
3730
|
+
var SUBMITTED_VERSION_MAX_LENGTH = 255;
|
|
3731
|
+
/**
|
|
3732
|
+
* A native build scope's key: the Release Catalog scope key of a
|
|
3733
|
+
* fingerprint, or of the app-version strategy followed by the exact app
|
|
3734
|
+
* version the build compiled in. One key serves both strategies, so one
|
|
3735
|
+
* index finds the newest build of either.
|
|
3736
|
+
*/
|
|
3737
|
+
var nativeBuildScopeKey = (scope) => {
|
|
3738
|
+
let scopeKey;
|
|
3739
|
+
try {
|
|
3740
|
+
const channelKey = encodeChannelKey(scope.channel);
|
|
3741
|
+
scopeKey = scope.fingerprintHash === null ? `${createReleaseCatalogScopeKey({
|
|
3742
|
+
channelKey,
|
|
3743
|
+
platform: scope.platform,
|
|
3744
|
+
strategy: "APP_VERSION"
|
|
3745
|
+
})}:${encodeURIComponent(scope.appVersion)}` : createReleaseCatalogScopeKey({
|
|
3746
|
+
channelKey,
|
|
3747
|
+
fingerprintHash: scope.fingerprintHash,
|
|
3748
|
+
platform: scope.platform,
|
|
3749
|
+
strategy: "FINGERPRINT"
|
|
3750
|
+
});
|
|
3751
|
+
} catch (error) {
|
|
3752
|
+
throw new NativeBuildInputError(`Invalid native build scope: ${error instanceof Error ? error.message : String(error)}.`);
|
|
3753
|
+
}
|
|
3754
|
+
if (scopeKey.length > SCOPE_KEY_MAX_LENGTH) throw new NativeBuildInputError(`Invalid native build scope: its key is longer than ${SCOPE_KEY_MAX_LENGTH} characters; shorten the channel or app version.`);
|
|
3755
|
+
return scopeKey;
|
|
3756
|
+
};
|
|
3757
|
+
/** Whether `bundleId` is a native build's built-in bundle: one unique read. */
|
|
3758
|
+
var isBuiltInBundle = async (db, bundleId) => await db.findOne("native_builds", { min_bundle_id: bundleId }) !== null;
|
|
3759
|
+
var problemOf = ({ id, minBundleId, platform, channel, fingerprintHash, appVersion, gitCommitHash, buildKey, buildNumber, artifact }) => {
|
|
3760
|
+
if (!isUUIDv7(id)) return "id must be a UUIDv7";
|
|
3761
|
+
if (!isUUIDv7(minBundleId)) return "minBundleId must be the UUIDv7 a release build compiles in";
|
|
3762
|
+
if (platform !== "ios" && platform !== "android") return "platform must be ios or android";
|
|
3763
|
+
if (channel.trim().length === 0) return "channel is required";
|
|
3764
|
+
if (gitCommitHash !== null && gitCommitHash.length > GIT_COMMIT_HASH_MAX_LENGTH) return `gitCommitHash must be at most ${GIT_COMMIT_HASH_MAX_LENGTH} characters`;
|
|
3765
|
+
if (fingerprintHash === null === (appVersion === null)) return "exactly one of fingerprintHash and appVersion is required";
|
|
3766
|
+
if (buildKey !== null && !BUILD_KEY.test(buildKey)) return "buildKey must be nbk1: and a SHA-256, or null";
|
|
3767
|
+
if (buildNumber !== void 0 && buildNumber !== null && (buildNumber.trim().length === 0 || buildNumber.length > BUILD_NUMBER_MAX_LENGTH)) return `buildNumber must be the artifact's build number, up to ${BUILD_NUMBER_MAX_LENGTH} characters, or null`;
|
|
3768
|
+
const kinds = ARTIFACT_KINDS[platform];
|
|
3769
|
+
if (!kinds.includes(artifact.kind)) return `artifact.kind of an ${platform} build must be ${kinds.join(" or ")}`;
|
|
3770
|
+
if (!Number.isSafeInteger(artifact.byteSize) || artifact.byteSize < 0) return "artifact.byteSize must be a byte count";
|
|
3771
|
+
return null;
|
|
3772
|
+
};
|
|
3773
|
+
/** The native build registry: core's `native_builds` and the built-in bundle rows. */
|
|
3774
|
+
var createNativeBuildApi = (db, { now = Date.now } = {}) => ({
|
|
3775
|
+
async registerNativeBuild(registration) {
|
|
3776
|
+
const problem = problemOf(registration);
|
|
3777
|
+
if (problem !== null) throw new NativeBuildInputError(`Invalid native build: ${problem}.`);
|
|
3778
|
+
const scopeKey = nativeBuildScopeKey(registration);
|
|
3779
|
+
const channelId = `channel:${encodeChannelKey(registration.channel)}`;
|
|
3780
|
+
const { embeddedBundle } = registration;
|
|
3781
|
+
const row = {
|
|
3782
|
+
id: registration.id,
|
|
3783
|
+
scope_key: scopeKey,
|
|
3784
|
+
platform: registration.platform,
|
|
3785
|
+
channel_id: channelId,
|
|
3786
|
+
fingerprint_hash: registration.fingerprintHash,
|
|
3787
|
+
app_version: registration.appVersion,
|
|
3788
|
+
min_bundle_id: registration.minBundleId,
|
|
3789
|
+
artifact_kind: registration.artifact.kind,
|
|
3790
|
+
artifact_storage_uri: registration.artifact.storageUri,
|
|
3791
|
+
byte_size: registration.artifact.byteSize,
|
|
3792
|
+
git_commit_hash: registration.gitCommitHash,
|
|
3793
|
+
created_at_ms: now(),
|
|
3794
|
+
build_key: registration.buildKey,
|
|
3795
|
+
build_number: registration.buildNumber ?? null,
|
|
3796
|
+
submitted_to: null,
|
|
3797
|
+
submitted_at_ms: null,
|
|
3798
|
+
submitted_version: null
|
|
3799
|
+
};
|
|
3800
|
+
for (let attempt = 1;; attempt += 1) {
|
|
3801
|
+
await insertChannel(db, {
|
|
3802
|
+
id: channelId,
|
|
3803
|
+
name: registration.channel
|
|
3804
|
+
});
|
|
3805
|
+
try {
|
|
3806
|
+
await db.transaction(async (tx) => {
|
|
3807
|
+
tx.create("bundles", {
|
|
3808
|
+
id: registration.minBundleId,
|
|
3809
|
+
platform: registration.platform,
|
|
3810
|
+
git_commit_hash: registration.gitCommitHash,
|
|
3811
|
+
metadata: embeddedBundle.metadata ?? {},
|
|
3812
|
+
manifest_storage_uri: embeddedBundle.manifestStorageUri,
|
|
3813
|
+
manifest_file_hash: embeddedBundle.manifestFileHash,
|
|
3814
|
+
asset_base_storage_uri: embeddedBundle.assetBaseStorageUri
|
|
3815
|
+
});
|
|
3816
|
+
tx.create("native_builds", row);
|
|
3817
|
+
});
|
|
3818
|
+
break;
|
|
3819
|
+
} catch (error) {
|
|
3820
|
+
if (!(error instanceof DatabaseConstraintError)) throw error;
|
|
3821
|
+
if (error.reason === "exists" || error.reason === "unique") throw new DatabaseConstraintError(error.reason, "native_builds");
|
|
3822
|
+
if (attempt < 3 && error.reason === "not_found" && error.model === "channels") continue;
|
|
3823
|
+
throw error;
|
|
3824
|
+
}
|
|
3825
|
+
}
|
|
3826
|
+
return row;
|
|
3827
|
+
},
|
|
3828
|
+
async getNativeBuild(id) {
|
|
3829
|
+
const row = await db.findOne("native_builds", { id });
|
|
3830
|
+
return row === null ? null : pick(row);
|
|
3831
|
+
},
|
|
3832
|
+
async findNativeBuild(scope, options) {
|
|
3833
|
+
const scopeKey = nativeBuildScopeKey(scope);
|
|
3834
|
+
const buildKey = options?.buildKey;
|
|
3835
|
+
if (buildKey !== void 0 && !BUILD_KEY.test(buildKey)) throw new NativeBuildInputError("Invalid native build key: it must be nbk1: and a SHA-256.");
|
|
3836
|
+
const { rows } = buildKey === void 0 ? await db.findMany("native_builds", {
|
|
3837
|
+
index: "byScope",
|
|
3838
|
+
where: { scope_key: scopeKey },
|
|
3839
|
+
order: "desc",
|
|
3840
|
+
limit: 1
|
|
3841
|
+
}) : await db.findMany("native_builds", {
|
|
3842
|
+
index: "byBuildKey",
|
|
3843
|
+
where: {
|
|
3844
|
+
scope_key: scopeKey,
|
|
3845
|
+
build_key: buildKey
|
|
3846
|
+
},
|
|
3847
|
+
order: "desc",
|
|
3848
|
+
limit: 1
|
|
3849
|
+
});
|
|
3850
|
+
return rows[0] === void 0 ? null : pick(rows[0]);
|
|
3851
|
+
},
|
|
3852
|
+
async recordNativeBuildSubmission(id, { destination, version }) {
|
|
3853
|
+
if (version.trim().length === 0 || version.length > SUBMITTED_VERSION_MAX_LENGTH) throw new NativeBuildInputError(`Invalid native build submission: version must be the store's label of the build, up to ${SUBMITTED_VERSION_MAX_LENGTH} characters.`);
|
|
3854
|
+
return db.transaction(async (tx) => {
|
|
3855
|
+
const row = await tx.findOne("native_builds", { id });
|
|
3856
|
+
if (row === null) return null;
|
|
3857
|
+
const build = pick(row);
|
|
3858
|
+
if (SUBMISSION_DESTINATIONS[build.platform] !== destination) throw new NativeBuildInputError(`Invalid native build submission: an ${build.platform} build is submitted to ${SUBMISSION_DESTINATIONS[build.platform]}, not ${destination}.`);
|
|
3859
|
+
const set = {
|
|
3860
|
+
submitted_to: destination,
|
|
3861
|
+
submitted_at_ms: now(),
|
|
3862
|
+
submitted_version: version
|
|
3863
|
+
};
|
|
3864
|
+
tx.update("native_builds", row, set);
|
|
3865
|
+
return {
|
|
3866
|
+
...build,
|
|
3867
|
+
...set
|
|
3868
|
+
};
|
|
3869
|
+
});
|
|
3870
|
+
},
|
|
3871
|
+
async deleteNativeBuild(id) {
|
|
3872
|
+
return db.transaction(async (tx) => {
|
|
3873
|
+
const row = await tx.findOne("native_builds", { id });
|
|
3874
|
+
if (row === null) return {
|
|
3875
|
+
deleted: false,
|
|
3876
|
+
reason: "not_found"
|
|
3877
|
+
};
|
|
3878
|
+
await tx.delete("native_builds", row);
|
|
3879
|
+
const bundle = await tx.findOne("bundles", { id: row.min_bundle_id });
|
|
3880
|
+
if (bundle !== null) await tx.delete("bundles", bundle);
|
|
3881
|
+
return {
|
|
3882
|
+
deleted: true,
|
|
3883
|
+
nativeBuild: pick(row)
|
|
3884
|
+
};
|
|
3885
|
+
});
|
|
3886
|
+
},
|
|
3887
|
+
async listNativeBuilds(input) {
|
|
3888
|
+
const page = {
|
|
3889
|
+
order: input.order ?? "asc",
|
|
3890
|
+
limit: input.limit
|
|
3891
|
+
};
|
|
3892
|
+
const { rows } = input.channelId === void 0 ? await db.findMany("native_builds", {
|
|
3893
|
+
index: "all",
|
|
3894
|
+
where: {},
|
|
3895
|
+
...page,
|
|
3896
|
+
...after(input)
|
|
3897
|
+
}) : await db.findMany("native_builds", {
|
|
3898
|
+
index: "byChannel",
|
|
3899
|
+
where: { channel_id: input.channelId },
|
|
3900
|
+
...page,
|
|
3901
|
+
...after(input)
|
|
3902
|
+
});
|
|
3903
|
+
return rows.map(pick);
|
|
3904
|
+
}
|
|
3905
|
+
});
|
|
3882
3906
|
var PAGE = 500;
|
|
3883
3907
|
var fail$1 = (code, message) => {
|
|
3884
3908
|
throw new ReleaseCatalogMutationError(code, message);
|
|
@@ -4188,6 +4212,7 @@ var createCoreOperations = (db, { now = Date.now } = {}) => {
|
|
|
4188
4212
|
if (!("bundleId" in deployment) || platforms.has(deployment.bundleId)) continue;
|
|
4189
4213
|
const row = await db.findOne("bundles", { id: deployment.bundleId });
|
|
4190
4214
|
if (row === null) throw new DatabaseBundleNotFoundError(deployment.bundleId);
|
|
4215
|
+
if (await isBuiltInBundle(db, deployment.bundleId)) throw new ReleaseManagementError("TARGET_RELEASE_INVALID", `Bundle "${deployment.bundleId}" is a native build's built-in bundle, which no release publishes.`);
|
|
4191
4216
|
platforms.set(deployment.bundleId, toBundleRow(row).platform);
|
|
4192
4217
|
}
|
|
4193
4218
|
const updatedAtMs = now();
|
|
@@ -4383,7 +4408,7 @@ var createCoreOperations = (db, { now = Date.now } = {}) => {
|
|
|
4383
4408
|
id
|
|
4384
4409
|
};
|
|
4385
4410
|
const { id: _id, ...set } = bundleToRow(next);
|
|
4386
|
-
updateBundle(tx, current, set);
|
|
4411
|
+
updateBundle(tx, current, set, { counted: set.platform === current.platform || !await isBuiltInBundle(tx, id) });
|
|
4387
4412
|
if (patches !== void 0) await replaceBundlePatches(tx, current, bundleToPatchRows({
|
|
4388
4413
|
...next,
|
|
4389
4414
|
patches
|
|
@@ -4394,7 +4419,9 @@ var createCoreOperations = (db, { now = Date.now } = {}) => {
|
|
|
4394
4419
|
await db.transaction(async (tx) => {
|
|
4395
4420
|
for (const id of new Set(ids)) {
|
|
4396
4421
|
const current = await tx.findOne("bundles", { id });
|
|
4397
|
-
if (current
|
|
4422
|
+
if (current === null) continue;
|
|
4423
|
+
if (await isBuiltInBundle(tx, id)) throw new DatabaseRowReferencedError();
|
|
4424
|
+
await deleteBundle(tx, current);
|
|
4398
4425
|
}
|
|
4399
4426
|
});
|
|
4400
4427
|
} catch (error) {
|
|
@@ -4444,6 +4471,7 @@ var createCoreApi = (db, storage, options = {}) => {
|
|
|
4444
4471
|
return {
|
|
4445
4472
|
...reads,
|
|
4446
4473
|
...createCoreOperations(purgingCachedRoutes(db, options.onCachedRoutesChange), options),
|
|
4474
|
+
...createNativeBuildApi(db, options),
|
|
4447
4475
|
ready: async () => {
|
|
4448
4476
|
await reads.listReleaseCatalogs({ limit: 1 });
|
|
4449
4477
|
}
|
|
@@ -4635,6 +4663,10 @@ var answer = async (operation) => {
|
|
|
4635
4663
|
code: "REFERENCED",
|
|
4636
4664
|
error: error.message
|
|
4637
4665
|
}, 409);
|
|
4666
|
+
if (error instanceof DatabaseConstraintError && error.model === "native_builds") return json({
|
|
4667
|
+
code: "NATIVE_BUILD_EXISTS",
|
|
4668
|
+
error: "A native build with this ID or built-in bundle ID is already registered."
|
|
4669
|
+
}, 409);
|
|
4638
4670
|
throw error;
|
|
4639
4671
|
}
|
|
4640
4672
|
};
|
|
@@ -4737,6 +4769,42 @@ var bundleUpdateOf = (value, bundleId) => {
|
|
|
4737
4769
|
if (id !== void 0 && id !== bundleId) throw new HandlerBadRequestError("Bundle id mismatch");
|
|
4738
4770
|
return update;
|
|
4739
4771
|
};
|
|
4772
|
+
var NATIVE_BUILD_ARTIFACT_KINDS = /* @__PURE__ */ new Set([
|
|
4773
|
+
"apk",
|
|
4774
|
+
"aab",
|
|
4775
|
+
"ipa",
|
|
4776
|
+
"app"
|
|
4777
|
+
]);
|
|
4778
|
+
/** A native build's scope: `fingerprintHash` or `appVersion`, never both. */
|
|
4779
|
+
var nativeBuildScopeOf = (url) => {
|
|
4780
|
+
const params = url.searchParams;
|
|
4781
|
+
const platform = platformOf(url);
|
|
4782
|
+
const channel = params.get("channel");
|
|
4783
|
+
const fingerprintHash = params.get("fingerprintHash");
|
|
4784
|
+
const appVersion = params.get("appVersion");
|
|
4785
|
+
if (platform === void 0 || !isText(channel) || fingerprintHash === null === (appVersion === null) || fingerprintHash === "" || appVersion === "") throw new HandlerBadRequestError("A native build lookup needs platform, channel, and fingerprintHash or appVersion.");
|
|
4786
|
+
return fingerprintHash !== null ? {
|
|
4787
|
+
platform,
|
|
4788
|
+
channel,
|
|
4789
|
+
fingerprintHash,
|
|
4790
|
+
appVersion: null
|
|
4791
|
+
} : {
|
|
4792
|
+
platform,
|
|
4793
|
+
channel,
|
|
4794
|
+
fingerprintHash: null,
|
|
4795
|
+
appVersion
|
|
4796
|
+
};
|
|
4797
|
+
};
|
|
4798
|
+
/** A native build or scope core refuses: a bad request. */
|
|
4799
|
+
var refusingInvalid = async (operation) => {
|
|
4800
|
+
try {
|
|
4801
|
+
return await operation();
|
|
4802
|
+
} catch (error) {
|
|
4803
|
+
if (error instanceof NativeBuildInputError) throw new HandlerBadRequestError(error.message);
|
|
4804
|
+
throw error;
|
|
4805
|
+
}
|
|
4806
|
+
};
|
|
4807
|
+
var isNativeBuildRegistration = (value) => isRecord$1(value) && isText(value.id) && isText(value.minBundleId) && typeof value.platform === "string" && isPlatform(value.platform) && isText(value.channel) && isTextOrNull(value.fingerprintHash) && isTextOrNull(value.appVersion) && value.fingerprintHash === null !== (value.appVersion === null) && isTextOrNull(value.gitCommitHash) && isTextOrNull(value.buildKey) && (value.buildNumber === void 0 || isTextOrNull(value.buildNumber)) && isRecord$1(value.artifact) && typeof value.artifact.kind === "string" && NATIVE_BUILD_ARTIFACT_KINDS.has(value.artifact.kind) && isText(value.artifact.storageUri) && Number.isSafeInteger(value.artifact.byteSize) && value.artifact.byteSize >= 0 && isRecord$1(value.embeddedBundle) && isText(value.embeddedBundle.manifestStorageUri) && isText(value.embeddedBundle.manifestFileHash) && isText(value.embeddedBundle.assetBaseStorageUri) && (value.embeddedBundle.metadata === void 0 || isRecord$1(value.embeddedBundle.metadata));
|
|
4740
4808
|
var scopeKeyOf = (params) => decodeMaybe(requireRouteParam(params, "scopeKey")) ?? "";
|
|
4741
4809
|
/** Every admin route's handler, by the name `ADMIN_ROUTES` mounts it under. */
|
|
4742
4810
|
var createAdminRouteHandlers = () => ({
|
|
@@ -4849,6 +4917,37 @@ var createAdminRouteHandlers = () => ({
|
|
|
4849
4917
|
}) });
|
|
4850
4918
|
}),
|
|
4851
4919
|
preflightReleaseCatalogRebuild: onCore(async (core, _request, params) => json({ data: await core.preflightReleaseCatalogRebuild(scopeKeyOf(params)) })),
|
|
4920
|
+
registerNativeBuild: onCore(async (core, request) => {
|
|
4921
|
+
const input = await body(request);
|
|
4922
|
+
if (!isNativeBuildRegistration(input)) throw new HandlerBadRequestError("Invalid native build");
|
|
4923
|
+
return json({ data: await refusingInvalid(() => core.registerNativeBuild(input)) }, 201);
|
|
4924
|
+
}),
|
|
4925
|
+
findNativeBuild: onCore(async (core, request) => {
|
|
4926
|
+
const url = new URL(request.url);
|
|
4927
|
+
const scope = nativeBuildScopeOf(url);
|
|
4928
|
+
const buildKey = url.searchParams.get("buildKey");
|
|
4929
|
+
return json({ data: await refusingInvalid(() => buildKey === null ? core.findNativeBuild(scope) : core.findNativeBuild(scope, { buildKey })) });
|
|
4930
|
+
}),
|
|
4931
|
+
getNativeBuild: onCore(async (core, _request, params) => json({ data: await core.getNativeBuild(requireRouteParam(params, "id")) })),
|
|
4932
|
+
listNativeBuilds: onCore(async (core, request) => {
|
|
4933
|
+
const url = new URL(request.url);
|
|
4934
|
+
const input = keyset(url);
|
|
4935
|
+
const channelId = url.searchParams.get("channelId");
|
|
4936
|
+
return page(await core.listNativeBuilds({
|
|
4937
|
+
...input,
|
|
4938
|
+
...channelId === null ? {} : { channelId }
|
|
4939
|
+
}), input, ({ id }) => id);
|
|
4940
|
+
}),
|
|
4941
|
+
recordNativeBuildSubmission: onCore(async (core, request, params) => {
|
|
4942
|
+
const input = await body(request);
|
|
4943
|
+
if (!isRecord$1(input) || input.destination !== "testflight" && input.destination !== "play-internal" || !isText(input.version)) throw new HandlerBadRequestError("A native build submission needs destination (testflight or play-internal) and version.");
|
|
4944
|
+
const submission = {
|
|
4945
|
+
destination: input.destination,
|
|
4946
|
+
version: input.version
|
|
4947
|
+
};
|
|
4948
|
+
return json({ data: await refusingInvalid(() => core.recordNativeBuildSubmission(requireRouteParam(params, "id"), submission)) });
|
|
4949
|
+
}),
|
|
4950
|
+
deleteNativeBuild: onCore(async (core, _request, params) => json({ data: await core.deleteNativeBuild(requireRouteParam(params, "id")) })),
|
|
4852
4951
|
deleteBundles: onCore(async (core, request) => {
|
|
4853
4952
|
const { ids } = await body(request);
|
|
4854
4953
|
if (!Array.isArray(ids) || !ids.every((id) => typeof id === "string" && id.length > 0)) throw new HandlerBadRequestError("Bundle deletion needs ids");
|
|
@@ -4967,6 +5066,36 @@ var ADMIN_ROUTES = [
|
|
|
4967
5066
|
method: "GET",
|
|
4968
5067
|
path: "/base-candidates/:candidateKey",
|
|
4969
5068
|
handler: "findBaseCandidates"
|
|
5069
|
+
},
|
|
5070
|
+
{
|
|
5071
|
+
method: "POST",
|
|
5072
|
+
path: "/native-builds",
|
|
5073
|
+
handler: "registerNativeBuild"
|
|
5074
|
+
},
|
|
5075
|
+
{
|
|
5076
|
+
method: "GET",
|
|
5077
|
+
path: "/native-builds/latest",
|
|
5078
|
+
handler: "findNativeBuild"
|
|
5079
|
+
},
|
|
5080
|
+
{
|
|
5081
|
+
method: "GET",
|
|
5082
|
+
path: "/native-builds/:id",
|
|
5083
|
+
handler: "getNativeBuild"
|
|
5084
|
+
},
|
|
5085
|
+
{
|
|
5086
|
+
method: "GET",
|
|
5087
|
+
path: "/native-builds",
|
|
5088
|
+
handler: "listNativeBuilds"
|
|
5089
|
+
},
|
|
5090
|
+
{
|
|
5091
|
+
method: "POST",
|
|
5092
|
+
path: "/native-builds/:id/submission",
|
|
5093
|
+
handler: "recordNativeBuildSubmission"
|
|
5094
|
+
},
|
|
5095
|
+
{
|
|
5096
|
+
method: "DELETE",
|
|
5097
|
+
path: "/native-builds/:id",
|
|
5098
|
+
handler: "deleteNativeBuild"
|
|
4970
5099
|
}
|
|
4971
5100
|
];
|
|
4972
5101
|
var CATALOG_CONTENT_TYPE = "application/vnd.hot-updater.release-catalog+json; version=1";
|
|
@@ -5468,20 +5597,21 @@ var assemble = (database, storage, plugins) => createHotUpdater({
|
|
|
5468
5597
|
...plugins.some((plugin) => plugin.provides?.clientAuth) ? {} : { clientAccess: "public" }
|
|
5469
5598
|
});
|
|
5470
5599
|
var getConsoleAuthAdapter = async () => {
|
|
5471
|
-
return (await import("./auth-
|
|
5600
|
+
return (await import("./auth-Z-wLddzh.mjs")).default;
|
|
5472
5601
|
};
|
|
5473
5602
|
var resolveConsoleConfig = async (request) => {
|
|
5474
|
-
const { default: source } = await import("./config-
|
|
5603
|
+
const { default: source } = await import("./config-CjIBFhJX.mjs");
|
|
5475
5604
|
const config = typeof source === "function" ? await source(request) : source;
|
|
5476
5605
|
const { database, storage, plugins = [] } = config;
|
|
5477
|
-
const gitUrl = config.console
|
|
5606
|
+
const { gitUrl } = config.console ?? {};
|
|
5607
|
+
const consoleOptions = gitUrl === void 0 ? {} : { gitUrl };
|
|
5478
5608
|
if (isRemoteDatabase(database)) {
|
|
5479
5609
|
const checked = assemble({
|
|
5480
5610
|
name: "memory",
|
|
5481
5611
|
adapter: createMemoryAdapter()
|
|
5482
5612
|
}, storage, plugins);
|
|
5483
5613
|
return {
|
|
5484
|
-
...
|
|
5614
|
+
...consoleOptions,
|
|
5485
5615
|
database,
|
|
5486
5616
|
core: database.core,
|
|
5487
5617
|
storage,
|
|
@@ -5490,7 +5620,7 @@ var resolveConsoleConfig = async (request) => {
|
|
|
5490
5620
|
}
|
|
5491
5621
|
const server = assemble(database, storage, plugins);
|
|
5492
5622
|
return {
|
|
5493
|
-
...
|
|
5623
|
+
...consoleOptions,
|
|
5494
5624
|
database,
|
|
5495
5625
|
core: server.core,
|
|
5496
5626
|
storage,
|