@omega.js/desktop 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +98 -0
- package/README.md +166 -0
- package/bin/omega +2 -0
- package/bin/omega-desktop +2 -0
- package/bin/omg +2 -0
- package/dist/assets/css/core/_fontawesome.scss +146 -0
- package/dist/assets/css/core/_initialize.scss +38 -0
- package/dist/assets/css/omega-desktop.scss +39 -0
- package/dist/assets/css/shell/_index.scss +207 -0
- package/dist/assets/css/tokens/_index.scss +166 -0
- package/dist/assets/js/bootstrap.bundle.js +1 -0
- package/dist/assets/js/core/app-shell.js +136 -0
- package/dist/assets/themes/_template/README.md +115 -0
- package/dist/assets/themes/_template/_config.scss +60 -0
- package/dist/assets/themes/_template/_theme.js +14 -0
- package/dist/assets/themes/_template/_theme.scss +28 -0
- package/dist/assets/themes/_template/css/base/_root.scss +19 -0
- package/dist/assets/themes/_template/css/components/_components.scss +23 -0
- package/dist/assets/themes/base/README.md +5 -0
- package/dist/assets/themes/base/_components/data/org-chart/component.html +33 -0
- package/dist/assets/themes/base/_components/data/org-chart/component.json5 +33 -0
- package/dist/assets/themes/base/_components/data/org-chart/component.scss +183 -0
- package/dist/assets/themes/base/_components/heading/masthead/component.html +22 -0
- package/dist/assets/themes/base/_components/heading/masthead/component.json5 +30 -0
- package/dist/assets/themes/base/_components/heading/section-head/component.html +18 -0
- package/dist/assets/themes/base/_components/heading/section-head/component.json5 +27 -0
- package/dist/assets/themes/base/_components/pricing/features/component.html +29 -0
- package/dist/assets/themes/base/_components/pricing/features/component.json5 +30 -0
- package/dist/assets/themes/base/_hero/orbit/index.html +30 -0
- package/dist/assets/themes/base/_hero/orbit/script.js +33 -0
- package/dist/assets/themes/base/_hero/orbit/style.scss +133 -0
- package/dist/assets/themes/base/_includes/admin/sections/sidebar.html +3 -0
- package/dist/assets/themes/base/_includes/admin/sections/topbar.html +3 -0
- package/dist/assets/themes/base/_includes/backend/sections/sidebar.html +3 -0
- package/dist/assets/themes/base/_includes/backend/sections/topbar.html +3 -0
- package/dist/assets/themes/base/_includes/frontend/components/connection-card.html +49 -0
- package/dist/assets/themes/base/_includes/frontend/components/post-card.html +54 -0
- package/dist/assets/themes/base/_includes/frontend/sections/account-connections.html +42 -0
- package/dist/assets/themes/base/_includes/frontend/sections/account-section-header.html +11 -0
- package/dist/assets/themes/base/_includes/frontend/sections/footer.html +154 -0
- package/dist/assets/themes/base/_includes/frontend/sections/nav.html +276 -0
- package/dist/assets/themes/base/_includes/global/sections/account.html +72 -0
- package/dist/assets/themes/base/_includes/global/sections/app-sidebar.html +248 -0
- package/dist/assets/themes/base/_includes/global/sections/app-topbar.html +228 -0
- package/dist/assets/themes/base/_includes/global/sections/page-header.html +99 -0
- package/dist/assets/themes/base/_layouts/admin/core/minimal-viewport-locked.html +22 -0
- package/dist/assets/themes/base/_layouts/admin/core/minimal.html +23 -0
- package/dist/assets/themes/base/_layouts/backend/core/base.html +57 -0
- package/dist/assets/themes/base/_layouts/backend/core/minimal-viewport-locked.html +32 -0
- package/dist/assets/themes/base/_layouts/backend/core/minimal.html +32 -0
- package/dist/assets/themes/base/_layouts/backend/pages/dashboard/index.html +230 -0
- package/dist/assets/themes/base/_layouts/frontend/core/base.html +31 -0
- package/dist/assets/themes/base/_layouts/frontend/core/cover.html +40 -0
- package/dist/assets/themes/base/_layouts/frontend/core/minimal.html +47 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/404.html +54 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/about.html +144 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/account/index.html +2104 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/alternatives/alternative.html +319 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/alternatives/index.html +186 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/app.html +142 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/auth/reset.html +53 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/auth/signin.html +90 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/auth/signup.html +141 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/auth/token.html +44 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/blog/categories/category.html +88 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/blog/categories/index.html +88 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/blog/index.html +255 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/blog/post.html +261 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/blog/tags/index.html +84 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/blog/tags/tag.html +88 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/collection/category.html +72 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/collection/document.html +54 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/collection/index.html +84 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/connections/callback.html +55 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/contact.html +214 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/download.html +793 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/extension/index.html +253 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/extension/installed.html +198 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/feedback.html +171 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/index.html +66 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/legal/document.html +78 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/payment/checkout.html +459 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/payment/confirmation.html +131 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/portal/email-preferences.html +104 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/pricing.html +596 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/status.html +361 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/team/index.html +210 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/team/member.html +125 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/updates/index.html +119 -0
- package/dist/assets/themes/base/_layouts/frontend/pages/updates/update.html +118 -0
- package/dist/assets/themes/base/_sections/about/hero/section.html +68 -0
- package/dist/assets/themes/base/_sections/about/hero/section.json5 +58 -0
- package/dist/assets/themes/base/_sections/about/letter/section.html +60 -0
- package/dist/assets/themes/base/_sections/about/letter/section.json5 +56 -0
- package/dist/assets/themes/base/_sections/about/photo-band/section.html +24 -0
- package/dist/assets/themes/base/_sections/about/photo-band/section.json5 +23 -0
- package/dist/assets/themes/base/_sections/about/principles/section.html +17 -0
- package/dist/assets/themes/base/_sections/about/principles/section.json5 +34 -0
- package/dist/assets/themes/base/_sections/about/timeline/section.html +20 -0
- package/dist/assets/themes/base/_sections/about/timeline/section.json5 +34 -0
- package/dist/assets/themes/base/_sections/marketing/bento/section.html +91 -0
- package/dist/assets/themes/base/_sections/marketing/bento/section.json5 +152 -0
- package/dist/assets/themes/base/_sections/marketing/cta/section.html +44 -0
- package/dist/assets/themes/base/_sections/marketing/cta/section.json5 +47 -0
- package/dist/assets/themes/base/_sections/marketing/faq/section.html +52 -0
- package/dist/assets/themes/base/_sections/marketing/faq/section.json5 +68 -0
- package/dist/assets/themes/base/_sections/marketing/hero/section.html +349 -0
- package/dist/assets/themes/base/_sections/marketing/hero/section.json5 +335 -0
- package/dist/assets/themes/base/_sections/marketing/newsletter-cta/section.html +38 -0
- package/dist/assets/themes/base/_sections/marketing/newsletter-cta/section.js +86 -0
- package/dist/assets/themes/base/_sections/marketing/newsletter-cta/section.json5 +29 -0
- package/dist/assets/themes/base/_sections/marketing/pricing-cards/section.html +115 -0
- package/dist/assets/themes/base/_sections/marketing/pricing-cards/section.json5 +72 -0
- package/dist/assets/themes/base/_sections/marketing/product-demo/section.html +62 -0
- package/dist/assets/themes/base/_sections/marketing/product-demo/section.js +44 -0
- package/dist/assets/themes/base/_sections/marketing/product-demo/section.json5 +52 -0
- package/dist/assets/themes/base/_sections/marketing/prose/section.html +22 -0
- package/dist/assets/themes/base/_sections/marketing/prose/section.json5 +41 -0
- package/dist/assets/themes/base/_sections/marketing/showcase/section.html +35 -0
- package/dist/assets/themes/base/_sections/marketing/showcase/section.json5 +52 -0
- package/dist/assets/themes/base/_sections/marketing/stats/section.html +32 -0
- package/dist/assets/themes/base/_sections/marketing/stats/section.json5 +44 -0
- package/dist/assets/themes/base/_sections/marketing/testimonials/section.html +54 -0
- package/dist/assets/themes/base/_sections/marketing/testimonials/section.json5 +70 -0
- package/dist/assets/themes/base/_sections/marketing/trusted-by/section.html +30 -0
- package/dist/assets/themes/base/_sections/marketing/trusted-by/section.json5 +38 -0
- package/dist/assets/themes/base/_sections/verts/unit/section.html +7 -0
- package/dist/assets/themes/base/_sections/verts/unit/section.js +22 -0
- package/dist/assets/themes/base/_sections/verts/unit/section.json5 +24 -0
- package/dist/assets/themes/base/_sections/verts/unit/section.scss +24 -0
- package/dist/assets/themes/base/_theme.js +13 -0
- package/dist/assets/themes/base/_theme.scss +4 -0
- package/dist/assets/themes/bootstrap/_theme.js +16 -0
- package/dist/assets/themes/bootstrap/_theme.scss +11 -0
- package/dist/assets/themes/bootstrap/js/index.esm.js +19 -0
- package/dist/assets/themes/bootstrap/js/index.umd.js +34 -0
- package/dist/assets/themes/bootstrap/js/src/alert.js +87 -0
- package/dist/assets/themes/bootstrap/js/src/base-component.js +86 -0
- package/dist/assets/themes/bootstrap/js/src/button.js +72 -0
- package/dist/assets/themes/bootstrap/js/src/carousel.js +474 -0
- package/dist/assets/themes/bootstrap/js/src/collapse.js +297 -0
- package/dist/assets/themes/bootstrap/js/src/dom/data.js +55 -0
- package/dist/assets/themes/bootstrap/js/src/dom/event-handler.js +317 -0
- package/dist/assets/themes/bootstrap/js/src/dom/manipulator.js +71 -0
- package/dist/assets/themes/bootstrap/js/src/dom/selector-engine.js +126 -0
- package/dist/assets/themes/bootstrap/js/src/dropdown.js +458 -0
- package/dist/assets/themes/bootstrap/js/src/modal.js +378 -0
- package/dist/assets/themes/bootstrap/js/src/offcanvas.js +282 -0
- package/dist/assets/themes/bootstrap/js/src/popover.js +97 -0
- package/dist/assets/themes/bootstrap/js/src/scrollspy.js +296 -0
- package/dist/assets/themes/bootstrap/js/src/tab.js +315 -0
- package/dist/assets/themes/bootstrap/js/src/toast.js +224 -0
- package/dist/assets/themes/bootstrap/js/src/tooltip.js +632 -0
- package/dist/assets/themes/bootstrap/js/src/util/backdrop.js +151 -0
- package/dist/assets/themes/bootstrap/js/src/util/component-functions.js +35 -0
- package/dist/assets/themes/bootstrap/js/src/util/config.js +65 -0
- package/dist/assets/themes/bootstrap/js/src/util/focustrap.js +115 -0
- package/dist/assets/themes/bootstrap/js/src/util/index.js +306 -0
- package/dist/assets/themes/bootstrap/js/src/util/sanitizer.js +117 -0
- package/dist/assets/themes/bootstrap/js/src/util/scrollbar.js +114 -0
- package/dist/assets/themes/bootstrap/js/src/util/swipe.js +146 -0
- package/dist/assets/themes/bootstrap/js/src/util/template-factory.js +160 -0
- package/dist/assets/themes/bootstrap/overrides/_accordion.scss +21 -0
- package/dist/assets/themes/bootstrap/overrides/_avatars.scss +51 -0
- package/dist/assets/themes/bootstrap/overrides/_blog-images.scss +45 -0
- package/dist/assets/themes/bootstrap/overrides/_buttons-adaptive.scss +141 -0
- package/dist/assets/themes/bootstrap/overrides/_color-shades.scss +25 -0
- package/dist/assets/themes/bootstrap/overrides/_cursor-utilities.scss +13 -0
- package/dist/assets/themes/bootstrap/overrides/_index.scss +30 -0
- package/dist/assets/themes/bootstrap/overrides/_links.scss +26 -0
- package/dist/assets/themes/bootstrap/overrides/_soft-colors.scss +99 -0
- package/dist/assets/themes/bootstrap/overrides/_spacing-extended.scss +74 -0
- package/dist/assets/themes/bootstrap/overrides/_spinners.scss +22 -0
- package/dist/assets/themes/bootstrap/overrides/_typography-utilities.scss +40 -0
- package/dist/assets/themes/bootstrap/scss/_accordion.scss +153 -0
- package/dist/assets/themes/bootstrap/scss/_alert.scss +68 -0
- package/dist/assets/themes/bootstrap/scss/_badge.scss +38 -0
- package/dist/assets/themes/bootstrap/scss/_breadcrumb.scss +40 -0
- package/dist/assets/themes/bootstrap/scss/_button-group.scss +147 -0
- package/dist/assets/themes/bootstrap/scss/_buttons.scss +216 -0
- package/dist/assets/themes/bootstrap/scss/_card.scss +238 -0
- package/dist/assets/themes/bootstrap/scss/_carousel.scss +226 -0
- package/dist/assets/themes/bootstrap/scss/_close.scss +66 -0
- package/dist/assets/themes/bootstrap/scss/_containers.scss +41 -0
- package/dist/assets/themes/bootstrap/scss/_dropdown.scss +250 -0
- package/dist/assets/themes/bootstrap/scss/_forms.scss +9 -0
- package/dist/assets/themes/bootstrap/scss/_functions.scss +302 -0
- package/dist/assets/themes/bootstrap/scss/_grid.scss +39 -0
- package/dist/assets/themes/bootstrap/scss/_helpers.scss +12 -0
- package/dist/assets/themes/bootstrap/scss/_images.scss +42 -0
- package/dist/assets/themes/bootstrap/scss/_list-group.scss +199 -0
- package/dist/assets/themes/bootstrap/scss/_maps.scss +174 -0
- package/dist/assets/themes/bootstrap/scss/_mixins.scss +42 -0
- package/dist/assets/themes/bootstrap/scss/_modal.scss +240 -0
- package/dist/assets/themes/bootstrap/scss/_nav.scss +197 -0
- package/dist/assets/themes/bootstrap/scss/_navbar.scss +289 -0
- package/dist/assets/themes/bootstrap/scss/_offcanvas.scss +147 -0
- package/dist/assets/themes/bootstrap/scss/_pagination.scss +109 -0
- package/dist/assets/themes/bootstrap/scss/_placeholders.scss +51 -0
- package/dist/assets/themes/bootstrap/scss/_popover.scss +196 -0
- package/dist/assets/themes/bootstrap/scss/_progress.scss +68 -0
- package/dist/assets/themes/bootstrap/scss/_reboot.scss +611 -0
- package/dist/assets/themes/bootstrap/scss/_root.scss +187 -0
- package/dist/assets/themes/bootstrap/scss/_spinners.scss +85 -0
- package/dist/assets/themes/bootstrap/scss/_tables.scss +171 -0
- package/dist/assets/themes/bootstrap/scss/_toasts.scss +73 -0
- package/dist/assets/themes/bootstrap/scss/_tooltip.scss +119 -0
- package/dist/assets/themes/bootstrap/scss/_transitions.scss +27 -0
- package/dist/assets/themes/bootstrap/scss/_type.scss +106 -0
- package/dist/assets/themes/bootstrap/scss/_utilities.scss +806 -0
- package/dist/assets/themes/bootstrap/scss/_variables-dark.scss +102 -0
- package/dist/assets/themes/bootstrap/scss/_variables.scss +1753 -0
- package/dist/assets/themes/bootstrap/scss/bootstrap-grid.scss +62 -0
- package/dist/assets/themes/bootstrap/scss/bootstrap-reboot.scss +10 -0
- package/dist/assets/themes/bootstrap/scss/bootstrap-utilities.scss +19 -0
- package/dist/assets/themes/bootstrap/scss/bootstrap.scss +52 -0
- package/dist/assets/themes/bootstrap/scss/forms/_floating-labels.scss +97 -0
- package/dist/assets/themes/bootstrap/scss/forms/_form-check.scss +189 -0
- package/dist/assets/themes/bootstrap/scss/forms/_form-control.scss +214 -0
- package/dist/assets/themes/bootstrap/scss/forms/_form-range.scss +91 -0
- package/dist/assets/themes/bootstrap/scss/forms/_form-select.scss +80 -0
- package/dist/assets/themes/bootstrap/scss/forms/_form-text.scss +11 -0
- package/dist/assets/themes/bootstrap/scss/forms/_input-group.scss +132 -0
- package/dist/assets/themes/bootstrap/scss/forms/_labels.scss +36 -0
- package/dist/assets/themes/bootstrap/scss/forms/_validation.scss +12 -0
- package/dist/assets/themes/bootstrap/scss/helpers/_clearfix.scss +3 -0
- package/dist/assets/themes/bootstrap/scss/helpers/_color-bg.scss +7 -0
- package/dist/assets/themes/bootstrap/scss/helpers/_colored-links.scss +30 -0
- package/dist/assets/themes/bootstrap/scss/helpers/_focus-ring.scss +5 -0
- package/dist/assets/themes/bootstrap/scss/helpers/_icon-link.scss +25 -0
- package/dist/assets/themes/bootstrap/scss/helpers/_position.scss +36 -0
- package/dist/assets/themes/bootstrap/scss/helpers/_ratio.scss +26 -0
- package/dist/assets/themes/bootstrap/scss/helpers/_stacks.scss +15 -0
- package/dist/assets/themes/bootstrap/scss/helpers/_stretched-link.scss +15 -0
- package/dist/assets/themes/bootstrap/scss/helpers/_text-truncation.scss +7 -0
- package/dist/assets/themes/bootstrap/scss/helpers/_visually-hidden.scss +8 -0
- package/dist/assets/themes/bootstrap/scss/helpers/_vr.scss +8 -0
- package/dist/assets/themes/bootstrap/scss/mixins/_alert.scss +18 -0
- package/dist/assets/themes/bootstrap/scss/mixins/_backdrop.scss +14 -0
- package/dist/assets/themes/bootstrap/scss/mixins/_banner.scss +7 -0
- package/dist/assets/themes/bootstrap/scss/mixins/_border-radius.scss +78 -0
- package/dist/assets/themes/bootstrap/scss/mixins/_box-shadow.scss +18 -0
- package/dist/assets/themes/bootstrap/scss/mixins/_breakpoints.scss +127 -0
- package/dist/assets/themes/bootstrap/scss/mixins/_buttons.scss +70 -0
- package/dist/assets/themes/bootstrap/scss/mixins/_caret.scss +69 -0
- package/dist/assets/themes/bootstrap/scss/mixins/_clearfix.scss +9 -0
- package/dist/assets/themes/bootstrap/scss/mixins/_color-mode.scss +21 -0
- package/dist/assets/themes/bootstrap/scss/mixins/_color-scheme.scss +7 -0
- package/dist/assets/themes/bootstrap/scss/mixins/_container.scss +11 -0
- package/dist/assets/themes/bootstrap/scss/mixins/_deprecate.scss +10 -0
- package/dist/assets/themes/bootstrap/scss/mixins/_forms.scss +163 -0
- package/dist/assets/themes/bootstrap/scss/mixins/_gradients.scss +47 -0
- package/dist/assets/themes/bootstrap/scss/mixins/_grid.scss +151 -0
- package/dist/assets/themes/bootstrap/scss/mixins/_image.scss +16 -0
- package/dist/assets/themes/bootstrap/scss/mixins/_list-group.scss +26 -0
- package/dist/assets/themes/bootstrap/scss/mixins/_lists.scss +7 -0
- package/dist/assets/themes/bootstrap/scss/mixins/_pagination.scss +10 -0
- package/dist/assets/themes/bootstrap/scss/mixins/_reset-text.scss +17 -0
- package/dist/assets/themes/bootstrap/scss/mixins/_resize.scss +6 -0
- package/dist/assets/themes/bootstrap/scss/mixins/_table-variants.scss +24 -0
- package/dist/assets/themes/bootstrap/scss/mixins/_text-truncate.scss +8 -0
- package/dist/assets/themes/bootstrap/scss/mixins/_transition.scss +26 -0
- package/dist/assets/themes/bootstrap/scss/mixins/_utilities.scss +97 -0
- package/dist/assets/themes/bootstrap/scss/mixins/_visually-hidden.scss +38 -0
- package/dist/assets/themes/bootstrap/scss/tests/jasmine.js +16 -0
- package/dist/assets/themes/bootstrap/scss/tests/mixins/_auto-import-of-variables-dark.test.scss +7 -0
- package/dist/assets/themes/bootstrap/scss/tests/mixins/_color-modes.test.scss +69 -0
- package/dist/assets/themes/bootstrap/scss/tests/mixins/_media-query-color-mode-full.test.scss +8 -0
- package/dist/assets/themes/bootstrap/scss/tests/mixins/_utilities.test.scss +393 -0
- package/dist/assets/themes/bootstrap/scss/tests/sass-true/register.js +14 -0
- package/dist/assets/themes/bootstrap/scss/tests/sass-true/runner.js +17 -0
- package/dist/assets/themes/bootstrap/scss/tests/utilities/_api.test.scss +75 -0
- package/dist/assets/themes/bootstrap/scss/utilities/_api.scss +47 -0
- package/dist/assets/themes/bootstrap/scss/vendor/_rfs.scss +348 -0
- package/dist/assets/themes/classy/README.md +89 -0
- package/dist/assets/themes/classy/_config.scss +245 -0
- package/dist/assets/themes/classy/_theme.js +31 -0
- package/dist/assets/themes/classy/_theme.scss +57 -0
- package/dist/assets/themes/classy/css/app/_panels.scss +183 -0
- package/dist/assets/themes/classy/css/base/_fonts.scss +79 -0
- package/dist/assets/themes/classy/css/base/_no-raise.scss +49 -0
- package/dist/assets/themes/classy/css/base/_root.scss +113 -0
- package/dist/assets/themes/classy/css/base/_typography.scss +154 -0
- package/dist/assets/themes/classy/css/base/_utilities.scss +284 -0
- package/dist/assets/themes/classy/css/components/_alerts.scss +51 -0
- package/dist/assets/themes/classy/css/components/_badges.scss +46 -0
- package/dist/assets/themes/classy/css/components/_buttons.scss +175 -0
- package/dist/assets/themes/classy/css/components/_cards.scss +41 -0
- package/dist/assets/themes/classy/css/components/_dropdowns.scss +48 -0
- package/dist/assets/themes/classy/css/components/_forms.scss +171 -0
- package/dist/assets/themes/classy/css/components/_receipt.scss +45 -0
- package/dist/assets/themes/classy/css/layout/_footer.scss +298 -0
- package/dist/assets/themes/classy/css/layout/_general.scss +209 -0
- package/dist/assets/themes/classy/css/layout/_nav.scss +154 -0
- package/dist/assets/themes/classy/css/layout/_shell.scss +458 -0
- package/dist/assets/themes/classy/css/marketing/_bento.scss +238 -0
- package/dist/assets/themes/classy/css/marketing/_content.scss +1328 -0
- package/dist/assets/themes/classy/css/marketing/_downloads.scss +246 -0
- package/dist/assets/themes/classy/css/marketing/_hero.scss +311 -0
- package/dist/assets/themes/classy/css/marketing/_sections.scss +649 -0
- package/dist/assets/themes/classy/css/pages/404/index.scss +67 -0
- package/dist/assets/themes/classy/css/pages/_auth.scss +235 -0
- package/dist/assets/themes/classy/css/pages/admin/firebase/index.scss +22 -0
- package/dist/assets/themes/classy/css/pages/blog/[slug].scss +56 -0
- package/dist/assets/themes/classy/css/pages/cookies.scss +2 -0
- package/dist/assets/themes/classy/css/pages/dashboard/account/index.scss +31 -0
- package/dist/assets/themes/classy/css/pages/feedback/index.scss +39 -0
- package/dist/assets/themes/classy/css/pages/legal/_document.scss +192 -0
- package/dist/assets/themes/classy/css/pages/payment/checkout/index.scss +585 -0
- package/dist/assets/themes/classy/css/pages/payment/confirmation/index.scss +9 -0
- package/dist/assets/themes/classy/css/pages/privacy.scss +2 -0
- package/dist/assets/themes/classy/css/pages/status/index.scss +164 -0
- package/dist/assets/themes/classy/css/pages/terms.scss +2 -0
- package/dist/assets/themes/classy/css/pages/updates/index.scss +128 -0
- package/dist/assets/themes/classy/fonts/inter-italic-latin-ext.woff2 +0 -0
- package/dist/assets/themes/classy/fonts/inter-italic-latin.woff2 +0 -0
- package/dist/assets/themes/classy/fonts/inter-normal-latin-ext.woff2 +0 -0
- package/dist/assets/themes/classy/fonts/inter-normal-latin.woff2 +0 -0
- package/dist/assets/themes/classy/fonts/newsreader-italic-latin-ext.woff2 +0 -0
- package/dist/assets/themes/classy/fonts/newsreader-italic-latin.woff2 +0 -0
- package/dist/assets/themes/classy/fonts/newsreader-normal-latin-ext.woff2 +0 -0
- package/dist/assets/themes/classy/fonts/newsreader-normal-latin.woff2 +0 -0
- package/dist/assets/themes/classy/js/hero-demo-form.js +56 -0
- package/dist/assets/themes/neobrutalism/README.md +118 -0
- package/dist/assets/themes/neobrutalism/_config.scss +139 -0
- package/dist/assets/themes/neobrutalism/_layouts/frontend/core/base.html +30 -0
- package/dist/assets/themes/neobrutalism/_layouts/frontend/pages/index.html +275 -0
- package/dist/assets/themes/neobrutalism/_theme.js +24 -0
- package/dist/assets/themes/neobrutalism/_theme.scss +61 -0
- package/dist/assets/themes/neobrutalism/css/base/_mixins.scss +46 -0
- package/dist/assets/themes/neobrutalism/css/base/_root.scss +169 -0
- package/dist/assets/themes/neobrutalism/css/base/_typography.scss +61 -0
- package/dist/assets/themes/neobrutalism/css/base/_utilities.scss +89 -0
- package/dist/assets/themes/neobrutalism/css/components/_billing-toggle.scss +74 -0
- package/dist/assets/themes/neobrutalism/css/components/_buttons.scss +148 -0
- package/dist/assets/themes/neobrutalism/css/components/_cards.scss +47 -0
- package/dist/assets/themes/neobrutalism/css/components/_forms.scss +88 -0
- package/dist/assets/themes/neobrutalism/css/components/_marketing.scss +244 -0
- package/dist/assets/themes/neobrutalism/css/layout/_general.scss +213 -0
- package/dist/assets/themes/neobrutalism/css/layout/_navigation.scss +171 -0
- package/dist/assets/themes/neobrutalism/css/pages/index.scss +203 -0
- package/dist/assets/themes/neobrutalism/css/pages/pricing/index.scss +58 -0
- package/dist/assets/themes/neobrutalism/css/pages/test/libraries/layers/index.scss +7 -0
- package/dist/assets/themes/neobrutalism/js/pages/test/libraries/layers/index.js +9 -0
- package/dist/assets/themes/newsflash/README.md +117 -0
- package/dist/assets/themes/newsflash/_components/heading/lede/component.html +14 -0
- package/dist/assets/themes/newsflash/_components/heading/lede/component.json5 +23 -0
- package/dist/assets/themes/newsflash/_components/heading/rule-head/component.html +17 -0
- package/dist/assets/themes/newsflash/_components/heading/rule-head/component.json5 +23 -0
- package/dist/assets/themes/newsflash/_components/news/byline/component.html +12 -0
- package/dist/assets/themes/newsflash/_components/news/byline/component.json5 +18 -0
- package/dist/assets/themes/newsflash/_components/news/story-card/component.html +25 -0
- package/dist/assets/themes/newsflash/_components/news/story-card/component.json5 +21 -0
- package/dist/assets/themes/newsflash/_config.scss +147 -0
- package/dist/assets/themes/newsflash/_layouts/frontend/core/base.html +51 -0
- package/dist/assets/themes/newsflash/_layouts/frontend/pages/blog/index.html +299 -0
- package/dist/assets/themes/newsflash/_layouts/frontend/pages/blog/post.html +235 -0
- package/dist/assets/themes/newsflash/_layouts/frontend/pages/index.html +328 -0
- package/dist/assets/themes/newsflash/_sections/marketing/desks/section.html +39 -0
- package/dist/assets/themes/newsflash/_sections/marketing/desks/section.json5 +49 -0
- package/dist/assets/themes/newsflash/_sections/marketing/newsletter-cta/section.html +103 -0
- package/dist/assets/themes/newsflash/_sections/marketing/newsletter-cta/section.json5 +50 -0
- package/dist/assets/themes/newsflash/_sections/marketing/rundown/section.html +28 -0
- package/dist/assets/themes/newsflash/_sections/marketing/rundown/section.json5 +40 -0
- package/dist/assets/themes/newsflash/_theme.js +24 -0
- package/dist/assets/themes/newsflash/_theme.scss +70 -0
- package/dist/assets/themes/newsflash/css/base/_fonts.scss +80 -0
- package/dist/assets/themes/newsflash/css/base/_mixins.scss +51 -0
- package/dist/assets/themes/newsflash/css/base/_root.scss +257 -0
- package/dist/assets/themes/newsflash/css/base/_typography.scss +49 -0
- package/dist/assets/themes/newsflash/css/base/_utilities.scss +122 -0
- package/dist/assets/themes/newsflash/css/components/_badges.scss +65 -0
- package/dist/assets/themes/newsflash/css/components/_billing-toggle.scss +61 -0
- package/dist/assets/themes/newsflash/css/components/_buttons.scss +139 -0
- package/dist/assets/themes/newsflash/css/components/_cards.scss +47 -0
- package/dist/assets/themes/newsflash/css/components/_editorial.scss +173 -0
- package/dist/assets/themes/newsflash/css/components/_forms.scss +75 -0
- package/dist/assets/themes/newsflash/css/components/_infinite-scroll.scss +102 -0
- package/dist/assets/themes/newsflash/css/components/_panels.scss +156 -0
- package/dist/assets/themes/newsflash/css/components/_ticker.scss +67 -0
- package/dist/assets/themes/newsflash/css/layout/_general.scss +330 -0
- package/dist/assets/themes/newsflash/css/layout/_navigation.scss +168 -0
- package/dist/assets/themes/newsflash/css/pages/404/index.scss +79 -0
- package/dist/assets/themes/newsflash/css/pages/blog/[slug].scss +186 -0
- package/dist/assets/themes/newsflash/css/pages/blog/index.scss +17 -0
- package/dist/assets/themes/newsflash/css/pages/index.scss +157 -0
- package/dist/assets/themes/newsflash/css/pages/pricing/index.scss +55 -0
- package/dist/assets/themes/newsflash/css/pages/test/libraries/layers/index.scss +7 -0
- package/dist/assets/themes/newsflash/fonts/fraunces-italic-latin-ext.woff2 +0 -0
- package/dist/assets/themes/newsflash/fonts/fraunces-italic-latin.woff2 +0 -0
- package/dist/assets/themes/newsflash/fonts/fraunces-normal-latin-ext.woff2 +0 -0
- package/dist/assets/themes/newsflash/fonts/fraunces-normal-latin.woff2 +0 -0
- package/dist/assets/themes/newsflash/fonts/schibsted-grotesk-italic-latin-ext.woff2 +0 -0
- package/dist/assets/themes/newsflash/fonts/schibsted-grotesk-italic-latin.woff2 +0 -0
- package/dist/assets/themes/newsflash/fonts/schibsted-grotesk-normal-latin-ext.woff2 +0 -0
- package/dist/assets/themes/newsflash/fonts/schibsted-grotesk-normal-latin.woff2 +0 -0
- package/dist/assets/themes/newsflash/js/pages/blog/[slug].js +29 -0
- package/dist/assets/themes/newsflash/js/pages/test/libraries/layers/index.js +9 -0
- package/dist/build.js +249 -0
- package/dist/cli-run.js +34 -0
- package/dist/cli.js +49 -0
- package/dist/commands/build.js +32 -0
- package/dist/commands/cdp/capture.js +91 -0
- package/dist/commands/cdp/client.js +140 -0
- package/dist/commands/cdp/eval.js +20 -0
- package/dist/commands/cdp/quit.js +84 -0
- package/dist/commands/cdp/relaunch.js +62 -0
- package/dist/commands/cdp/shot.js +20 -0
- package/dist/commands/cdp/status.js +38 -0
- package/dist/commands/cdp/theme.js +21 -0
- package/dist/commands/cdp.js +53 -0
- package/dist/commands/clean.js +34 -0
- package/dist/commands/deploy.js +75 -0
- package/dist/commands/finalize-release.js +238 -0
- package/dist/commands/install.js +37 -0
- package/dist/commands/launch.js +150 -0
- package/dist/commands/lib/dependencies.js +35 -0
- package/dist/commands/lib/deploy-precheck.js +117 -0
- package/dist/commands/lib/ensure-target.js +300 -0
- package/dist/commands/logs.js +185 -0
- package/dist/commands/package.js +31 -0
- package/dist/commands/publish.js +34 -0
- package/dist/commands/push-secrets.js +141 -0
- package/dist/commands/release.js +286 -0
- package/dist/commands/runner.js +1874 -0
- package/dist/commands/sign-windows.js +563 -0
- package/dist/commands/test.js +121 -0
- package/dist/commands/update.js +21 -0
- package/dist/commands/validate-certs.js +238 -0
- package/dist/commands/version.js +9 -0
- package/dist/config/page-template.html +35 -0
- package/dist/defaults/.github/workflows/build.yml +276 -0
- package/dist/defaults/AGENTS.md +109 -0
- package/dist/defaults/CHANGELOG.md +15 -0
- package/dist/defaults/CLAUDE.md +1 -0
- package/dist/defaults/_.gitignore +24 -0
- package/dist/defaults/_mas/README.md +49 -0
- package/dist/defaults/_mas/entitlements.mas.inherit.plist +12 -0
- package/dist/defaults/_mas/entitlements.mas.loginhelper.plist +8 -0
- package/dist/defaults/_mas/entitlements.mas.plist +33 -0
- package/dist/defaults/config/certs/.gitkeep +0 -0
- package/dist/defaults/config/certs/README.md +60 -0
- package/dist/defaults/config/icons/macos/dmg.png +0 -0
- package/dist/defaults/config/icons/macos/icon.png +0 -0
- package/dist/defaults/config/icons/macos/tray.png +0 -0
- package/dist/defaults/config/icons/windows/icon.png +0 -0
- package/dist/defaults/config/omega.json5 +279 -0
- package/dist/defaults/docs/README.md +17 -0
- package/dist/defaults/gulpfile.js +6 -0
- package/dist/defaults/hooks/build/post.js +9 -0
- package/dist/defaults/hooks/build/pre.js +9 -0
- package/dist/defaults/hooks/notarize/post.js +16 -0
- package/dist/defaults/hooks/release/post.js +9 -0
- package/dist/defaults/hooks/release/pre.js +9 -0
- package/dist/defaults/src/assets/js/components/about/index.js +10 -0
- package/dist/defaults/src/assets/js/components/main/index.js +14 -0
- package/dist/defaults/src/assets/js/components/settings/index.js +10 -0
- package/dist/defaults/src/assets/scss/main.scss +34 -0
- package/dist/defaults/src/assets/scss/pages/about.scss +3 -0
- package/dist/defaults/src/assets/scss/pages/main.scss +4 -0
- package/dist/defaults/src/assets/scss/pages/settings.scss +3 -0
- package/dist/defaults/src/integrations/context-menu/index.js +60 -0
- package/dist/defaults/src/integrations/menu/index.js +58 -0
- package/dist/defaults/src/integrations/tray/index.js +60 -0
- package/dist/defaults/src/main.js +78 -0
- package/dist/defaults/src/preload.js +15 -0
- package/dist/defaults/src/views/about/index.html +3 -0
- package/dist/defaults/src/views/main/index.html +8 -0
- package/dist/defaults/src/views/settings/index.html +3 -0
- package/dist/defaults/test/README.md +41 -0
- package/dist/defaults/test/_init.js +10 -0
- package/dist/gulp/main.js +144 -0
- package/dist/gulp/tasks/audit.js +82 -0
- package/dist/gulp/tasks/build-config.js +445 -0
- package/dist/gulp/tasks/bundle.js +451 -0
- package/dist/gulp/tasks/defaults.js +20 -0
- package/dist/gulp/tasks/distribute.js +8 -0
- package/dist/gulp/tasks/html.js +95 -0
- package/dist/gulp/tasks/package-quick.js +102 -0
- package/dist/gulp/tasks/package.js +53 -0
- package/dist/gulp/tasks/release.js +57 -0
- package/dist/gulp/tasks/sass.js +82 -0
- package/dist/gulp/tasks/serve.js +191 -0
- package/dist/hooks/notarize.js +70 -0
- package/dist/index.js +14 -0
- package/dist/lib/_menu-mixin.js +199 -0
- package/dist/lib/analytics.js +360 -0
- package/dist/lib/app-state.js +220 -0
- package/dist/lib/auth-flow.js +160 -0
- package/dist/lib/auth-persistence.js +207 -0
- package/dist/lib/auto-updater.js +752 -0
- package/dist/lib/client-bridge.js +371 -0
- package/dist/lib/context-menu.js +302 -0
- package/dist/lib/context.js +162 -0
- package/dist/lib/deep-link.js +370 -0
- package/dist/lib/fontawesome.js +203 -0
- package/dist/lib/ipc.js +169 -0
- package/dist/lib/logger-lite.js +259 -0
- package/dist/lib/logger.js +4 -0
- package/dist/lib/menu.js +521 -0
- package/dist/lib/protocol.js +85 -0
- package/dist/lib/remote-config.js +224 -0
- package/dist/lib/remote-scripts.js +158 -0
- package/dist/lib/restart-manager/index.js +550 -0
- package/dist/lib/restart-manager/install.js +353 -0
- package/dist/lib/restart-manager/protocol.js +274 -0
- package/dist/lib/sign-helpers/auto-unlock.js +95 -0
- package/dist/lib/sign-helpers/entitlements.js +98 -0
- package/dist/lib/sign-helpers/resolve-icons.js +171 -0
- package/dist/lib/sign-helpers/sign-events.js +75 -0
- package/dist/lib/sign-helpers/update-info.js +186 -0
- package/dist/lib/startup.js +214 -0
- package/dist/lib/storage.js +193 -0
- package/dist/lib/templating.js +85 -0
- package/dist/lib/theme.js +173 -0
- package/dist/lib/tray.js +414 -0
- package/dist/lib/usage.js +141 -0
- package/dist/lib/window-manager.js +509 -0
- package/dist/main.js +542 -0
- package/dist/omega-bin.js +6 -0
- package/dist/preload.js +241 -0
- package/dist/renderer.js +456 -0
- package/dist/test/assert.js +4 -0
- package/dist/test/fixtures/consumer-app/config/omega.json5 +39 -0
- package/dist/test/fixtures/consumer-app/package.json +13 -0
- package/dist/test/fixtures/consumer-app/src/assets/js/components/main/index.js +11 -0
- package/dist/test/fixtures/consumer-app/src/assets/scss/main.scss +3 -0
- package/dist/test/fixtures/consumer-app/src/main.js +17 -0
- package/dist/test/fixtures/consumer-app/src/preload.js +4 -0
- package/dist/test/fixtures/consumer-app/src/views/main/index.html +4 -0
- package/dist/test/harness/boot-entry.js +237 -0
- package/dist/test/harness/main-entry.js +494 -0
- package/dist/test/harness/package.json +6 -0
- package/dist/test/harness/renderer-entry.js +173 -0
- package/dist/test/harness/renderer-preload.js +310 -0
- package/dist/test/harness/renderer.html +12 -0
- package/dist/test/index.js +65 -0
- package/dist/test/runner.js +99 -0
- package/dist/test/runners/boot.js +414 -0
- package/dist/test/runners/electron.js +92 -0
- package/dist/test/runners/render-event.js +46 -0
- package/dist/test/suites/boot/build-isolation.test.js +54 -0
- package/dist/test/suites/boot/consumer-app-boots.test.js +99 -0
- package/dist/test/suites/boot/restart-manager.test.js +38 -0
- package/dist/test/suites/boot/storage-bundled.test.js +59 -0
- package/dist/test/suites/boot/theme.test.js +68 -0
- package/dist/test/suites/boot/view-suite.test.js +47 -0
- package/dist/test/suites/build/attach-log-file.test.js +99 -0
- package/dist/test/suites/build/audit.test.js +271 -0
- package/dist/test/suites/build/boot-fixture.test.js +48 -0
- package/dist/test/suites/build/build-config.test.js +457 -0
- package/dist/test/suites/build/build-verbs.test.js +156 -0
- package/dist/test/suites/build/build-workflow-jobs.test.js +55 -0
- package/dist/test/suites/build/cdp.test.js +89 -0
- package/dist/test/suites/build/cli.test.js +135 -0
- package/dist/test/suites/build/config-schema.test.js +133 -0
- package/dist/test/suites/build/defaults-scaffold.test.js +192 -0
- package/dist/test/suites/build/deliver-certs.test.js +95 -0
- package/dist/test/suites/build/derive-signing-env.test.js +122 -0
- package/dist/test/suites/build/electron-node-version.test.js +49 -0
- package/dist/test/suites/build/electron-targets.test.js +92 -0
- package/dist/test/suites/build/ensure-target.test.js +131 -0
- package/dist/test/suites/build/entitlements.test.js +107 -0
- package/dist/test/suites/build/env-delivery.test.js +166 -0
- package/dist/test/suites/build/env-watch.test.js +86 -0
- package/dist/test/suites/build/exports.test.js +63 -0
- package/dist/test/suites/build/finalize-release.test.js +152 -0
- package/dist/test/suites/build/format-fetch-error.test.js +85 -0
- package/dist/test/suites/build/framework-deps.test.js +173 -0
- package/dist/test/suites/build/get-config.test.js +137 -0
- package/dist/test/suites/build/github-utils.test.js +54 -0
- package/dist/test/suites/build/icon-sheet.test.js +62 -0
- package/dist/test/suites/build/license-stamp.test.js +63 -0
- package/dist/test/suites/build/logger-lite.test.js +148 -0
- package/dist/test/suites/build/logs-command.test.js +226 -0
- package/dist/test/suites/build/manager.test.js +193 -0
- package/dist/test/suites/build/menu-mixin.test.js +130 -0
- package/dist/test/suites/build/merge-line-files.test.js +230 -0
- package/dist/test/suites/build/omega-shell.test.js +94 -0
- package/dist/test/suites/build/omega-tokens.test.js +64 -0
- package/dist/test/suites/build/project-scripts-deps.test.js +90 -0
- package/dist/test/suites/build/push-secrets.test.js +226 -0
- package/dist/test/suites/build/release-pipeline.test.js +365 -0
- package/dist/test/suites/build/renderer-auth-bridge.test.js +158 -0
- package/dist/test/suites/build/renderer-entry-key.test.js +37 -0
- package/dist/test/suites/build/renderer-node-shims.test.js +125 -0
- package/dist/test/suites/build/resolve-icons.test.js +296 -0
- package/dist/test/suites/build/resolve-signing-cert.test.js +342 -0
- package/dist/test/suites/build/restart-manager-install.test.js +178 -0
- package/dist/test/suites/build/restart-manager-protocol.test.js +158 -0
- package/dist/test/suites/build/run-consumer-hook.test.js +137 -0
- package/dist/test/suites/build/runner.test.js +2599 -0
- package/dist/test/suites/build/sanitize-signing-env.test.js +98 -0
- package/dist/test/suites/build/sanitize-url.test.js +78 -0
- package/dist/test/suites/build/secure-remote-url.test.js +42 -0
- package/dist/test/suites/build/sentry.test.js +89 -0
- package/dist/test/suites/build/serve-resolve-electron.test.js +58 -0
- package/dist/test/suites/build/setup-scripts.test.js +172 -0
- package/dist/test/suites/build/sign-events.test.js +90 -0
- package/dist/test/suites/build/sign-windows-e2e.test.js +302 -0
- package/dist/test/suites/build/sign-windows.test.js +313 -0
- package/dist/test/suites/build/strip-dev-blocks.test.js +116 -0
- package/dist/test/suites/build/templating.test.js +95 -0
- package/dist/test/suites/build/test-discovery.test.js +64 -0
- package/dist/test/suites/build/test-stealth.test.js +83 -0
- package/dist/test/suites/build/test-target-no-match.test.js +119 -0
- package/dist/test/suites/build/update-info.test.js +224 -0
- package/dist/test/suites/build/url-helpers.test.js +289 -0
- package/dist/test/suites/build/validate-certs.test.js +103 -0
- package/dist/test/suites/build/validate-config.test.js +90 -0
- package/dist/test/suites/build/verb-logs.test.js +43 -0
- package/dist/test/suites/build/wave5-pins.test.js +35 -0
- package/dist/test/suites/main/analytics.test.js +364 -0
- package/dist/test/suites/main/app-state.test.js +197 -0
- package/dist/test/suites/main/auth-flow.test.js +196 -0
- package/dist/test/suites/main/auth-persistence.test.js +167 -0
- package/dist/test/suites/main/auto-updater.test.js +1138 -0
- package/dist/test/suites/main/boot-sequence.test.js +77 -0
- package/dist/test/suites/main/client-bridge.integration.test.js +134 -0
- package/dist/test/suites/main/client-bridge.test.js +249 -0
- package/dist/test/suites/main/context-menu.test.js +365 -0
- package/dist/test/suites/main/context.test.js +155 -0
- package/dist/test/suites/main/deep-link.test.js +288 -0
- package/dist/test/suites/main/epipe-handler.test.js +40 -0
- package/dist/test/suites/main/fontawesome.test.js +147 -0
- package/dist/test/suites/main/harness-cdp.test.js +49 -0
- package/dist/test/suites/main/ipc.test.js +165 -0
- package/dist/test/suites/main/menu.test.js +419 -0
- package/dist/test/suites/main/protocol.test.js +77 -0
- package/dist/test/suites/main/remote-config.test.js +189 -0
- package/dist/test/suites/main/remote-scripts.test.js +276 -0
- package/dist/test/suites/main/restart-manager.test.js +328 -0
- package/dist/test/suites/main/startup-paths-and-ua.test.js +99 -0
- package/dist/test/suites/main/startup.test.js +129 -0
- package/dist/test/suites/main/stealth-window.test.js +74 -0
- package/dist/test/suites/main/storage.test.js +89 -0
- package/dist/test/suites/main/theme.test.js +137 -0
- package/dist/test/suites/main/tray.test.js +322 -0
- package/dist/test/suites/main/truncate-on-boot.test.js +22 -0
- package/dist/test/suites/main/url-helpers.test.js +429 -0
- package/dist/test/suites/main/usage.test.js +127 -0
- package/dist/test/suites/main/window-bounds.test.js +169 -0
- package/dist/test/suites/main/window-manager.test.js +233 -0
- package/dist/test/suites/renderer/analytics-bridge.test.js +128 -0
- package/dist/test/suites/renderer/cross-context-helpers.test.js +131 -0
- package/dist/test/suites/renderer/fontawesome.test.js +190 -0
- package/dist/test/suites/renderer/round-trip.test.js +107 -0
- package/dist/test/suites/renderer/theme.test.js +118 -0
- package/dist/test/suites/renderer/tooltips.test.js +166 -0
- package/dist/test/suites/renderer/verts.test.js +100 -0
- package/dist/test/suites/renderer/window-em-surface.test.js +107 -0
- package/dist/test/utils/dist-snapshot.js +36 -0
- package/dist/test/utils/extended-mode-warning.js +13 -0
- package/dist/utils/app-root.js +28 -0
- package/dist/utils/attach-log-file.js +4 -0
- package/dist/utils/build-pipeline.js +58 -0
- package/dist/utils/deliver-certs.js +69 -0
- package/dist/utils/derive-signing-env.js +56 -0
- package/dist/utils/dist-root.js +21 -0
- package/dist/utils/electron-node-version.js +48 -0
- package/dist/utils/electron-targets.js +72 -0
- package/dist/utils/format-fetch-error.js +38 -0
- package/dist/utils/github.js +73 -0
- package/dist/utils/load-consumer-file.js +26 -0
- package/dist/utils/merge-line-files.js +5 -0
- package/dist/utils/mode-helpers.js +147 -0
- package/dist/utils/resolve-signing-cert.js +175 -0
- package/dist/utils/run-consumer-hook.js +38 -0
- package/dist/utils/runner-env.js +687 -0
- package/dist/utils/safe-install.js +4 -0
- package/dist/utils/sanitize-signing-env.js +45 -0
- package/dist/utils/sanitize-url.js +28 -0
- package/dist/utils/secure-remote-url.js +25 -0
- package/dist/utils/stealth-window.js +37 -0
- package/dist/utils/test-stealth.js +29 -0
- package/dist/utils/url-helpers.js +169 -0
- package/dist/vendor/account/engine.js +182 -0
- package/dist/vendor/account/features.js +220 -0
- package/dist/vendor/account/index.js +53 -0
- package/dist/vendor/account/schema.js +272 -0
- package/dist/vendor/account/subscription.js +38 -0
- package/dist/vendor/analytics/adapters/ga4.js +26 -0
- package/dist/vendor/analytics/adapters/meta.js +26 -0
- package/dist/vendor/analytics/adapters/resolve.js +130 -0
- package/dist/vendor/analytics/adapters/tiktok.js +27 -0
- package/dist/vendor/analytics/catalog.js +908 -0
- package/dist/vendor/analytics/consent.js +49 -0
- package/dist/vendor/analytics/core.js +141 -0
- package/dist/vendor/analytics/identity.js +136 -0
- package/dist/vendor/analytics/index.js +170 -0
- package/dist/vendor/analytics/logger.js +40 -0
- package/dist/vendor/analytics/transports/browser.js +110 -0
- package/dist/vendor/config/company.js +31 -0
- package/dist/vendor/config/defaults.js +173 -0
- package/dist/vendor/config/demo.js +18 -0
- package/dist/vendor/config/desktop-artifacts.js +110 -0
- package/dist/vendor/config/edit.js +769 -0
- package/dist/vendor/config/env-delivery.js +145 -0
- package/dist/vendor/config/env-rules.js +93 -0
- package/dist/vendor/config/env-schema.js +1078 -0
- package/dist/vendor/config/env.js +445 -0
- package/dist/vendor/config/hooks.js +97 -0
- package/dist/vendor/config/index.js +237 -0
- package/dist/vendor/config/instances.js +208 -0
- package/dist/vendor/config/load.js +490 -0
- package/dist/vendor/config/merge.js +68 -0
- package/dist/vendor/config/order.js +139 -0
- package/dist/vendor/config/ports.js +374 -0
- package/dist/vendor/config/providers.js +32 -0
- package/dist/vendor/config/repo.js +142 -0
- package/dist/vendor/config/retired-keys.js +430 -0
- package/dist/vendor/config/schema.js +1610 -0
- package/dist/vendor/config/secrets.js +50 -0
- package/dist/vendor/config/seed.js +34 -0
- package/dist/vendor/config/site-global.js +205 -0
- package/dist/vendor/config/validate.js +554 -0
- package/dist/vendor/config/winback.js +61 -0
- package/dist/vendor/devkit/actions-secrets.js +145 -0
- package/dist/vendor/devkit/attach-log-file.js +262 -0
- package/dist/vendor/devkit/bundle.js +292 -0
- package/dist/vendor/devkit/certs.js +199 -0
- package/dist/vendor/devkit/ci-workflows.js +520 -0
- package/dist/vendor/devkit/clean-dirs.js +28 -0
- package/dist/vendor/devkit/cli-router.js +156 -0
- package/dist/vendor/devkit/defaults-engine.js +372 -0
- package/dist/vendor/devkit/deploy-precheck.js +54 -0
- package/dist/vendor/devkit/deploy-record.js +180 -0
- package/dist/vendor/devkit/deploy.js +286 -0
- package/dist/vendor/devkit/empty-modules-plugin.js +64 -0
- package/dist/vendor/devkit/env-watch.js +132 -0
- package/dist/vendor/devkit/framework-deps.js +46 -0
- package/dist/vendor/devkit/license.js +155 -0
- package/dist/vendor/devkit/local.js +1905 -0
- package/dist/vendor/devkit/logger.js +128 -0
- package/dist/vendor/devkit/merge-line-files.js +296 -0
- package/dist/vendor/devkit/npm-registry.js +52 -0
- package/dist/vendor/devkit/omega-bin.js +345 -0
- package/dist/vendor/devkit/prompt.js +187 -0
- package/dist/vendor/devkit/safe-install.js +18 -0
- package/dist/vendor/devkit/scaffold-guard.js +96 -0
- package/dist/vendor/devkit/stop-signals.js +28 -0
- package/dist/vendor/devkit/strip-dev-blocks-plugin.js +29 -0
- package/dist/vendor/devkit/strip-dev-blocks.js +32 -0
- package/dist/vendor/devkit/target-dependencies.js +137 -0
- package/dist/vendor/devkit/target-secrets.js +165 -0
- package/dist/vendor/devkit/test/assert.js +120 -0
- package/dist/vendor/devkit/test/define-cases.js +104 -0
- package/dist/vendor/devkit/test/extended-mode-warning.js +22 -0
- package/dist/vendor/devkit/test/runner-core.js +554 -0
- package/dist/vendor/devkit/test/scope.js +162 -0
- package/dist/vendor/devkit/update.js +569 -0
- package/dist/vendor/monitoring/core.js +180 -0
- package/dist/vendor/monitoring/env.js +49 -0
- package/dist/vendor/monitoring/index.js +28 -0
- package/dist/vendor/monitoring/logger.js +39 -0
- package/dist/vendor/monitoring/main.js +99 -0
- package/dist/vendor/monitoring/preload.js +45 -0
- package/dist/vendor/monitoring/renderer.js +87 -0
- package/docs/analytics.md +140 -0
- package/docs/app-state.md +92 -0
- package/docs/audit.md +69 -0
- package/docs/auto-updater.md +243 -0
- package/docs/boot-sequence.md +39 -0
- package/docs/build-system.md +161 -0
- package/docs/cdp-debugging.md +169 -0
- package/docs/client-bridge.md +267 -0
- package/docs/common-mistakes.md +21 -0
- package/docs/config-schema.md +120 -0
- package/docs/context-menu.md +112 -0
- package/docs/context.md +81 -0
- package/docs/css.md +84 -0
- package/docs/deep-link.md +178 -0
- package/docs/environment-detection.md +104 -0
- package/docs/fontawesome.md +107 -0
- package/docs/hooks.md +87 -0
- package/docs/icons.md +79 -0
- package/docs/index.md +279 -0
- package/docs/installer-options.md +162 -0
- package/docs/ipc.md +61 -0
- package/docs/lib-modules.md +53 -0
- package/docs/logging.md +229 -0
- package/docs/menu.md +160 -0
- package/docs/releasing.md +229 -0
- package/docs/remote-config.md +118 -0
- package/docs/remote-scripts.md +144 -0
- package/docs/restart-manager.md +144 -0
- package/docs/runner.md +253 -0
- package/docs/sentry.md +97 -0
- package/docs/shared/agent-docs.md +89 -0
- package/docs/shared/analytics.md +612 -0
- package/docs/shared/brands.md +51 -0
- package/docs/shared/breaking-changes.md +497 -0
- package/docs/shared/config.md +1387 -0
- package/docs/shared/deploys.md +215 -0
- package/docs/shared/icons.md +201 -0
- package/docs/shared/local-dev.md +147 -0
- package/docs/shared/logging.md +202 -0
- package/docs/shared/monitoring.md +153 -0
- package/docs/shared/publishing.md +183 -0
- package/docs/shared/rulings.md +34 -0
- package/docs/shared/testing.md +147 -0
- package/docs/shared/theming.md +604 -0
- package/docs/shared/translation.md +291 -0
- package/docs/shared/updates.md +61 -0
- package/docs/signing.md +267 -0
- package/docs/startup.md +142 -0
- package/docs/storage.md +59 -0
- package/docs/templating.md +101 -0
- package/docs/test-boot-layer.md +157 -0
- package/docs/test-framework.md +357 -0
- package/docs/themes.md +135 -0
- package/docs/tooltips.md +99 -0
- package/docs/tray.md +164 -0
- package/docs/usage.md +58 -0
- package/docs/verts.md +62 -0
- package/docs/windows.md +149 -0
- package/package.json +184 -0
- package/scripts/sync-nvmrc.js +100 -0
|
@@ -0,0 +1,752 @@
|
|
|
1
|
+
// Auto-updater — wraps electron-updater with these triggers:
|
|
2
|
+
//
|
|
3
|
+
// 1. Startup check — fires `startupDelayMs` after `whenReady` (default 10s, non-blocking).
|
|
4
|
+
// 2. Feed-check timer — every `feedCheckIntervalMs` (default 1h). HTTP-bound — hits the
|
|
5
|
+
// release feed. Hourly to match Discord/Slack/VS Code; running this
|
|
6
|
+
// every minute would hammer GitHub at 60× the necessary rate.
|
|
7
|
+
// 3. Idle-eval timer — every `idleEvalIntervalMs` (default 1m). In-process arithmetic only,
|
|
8
|
+
// no HTTP. Decides whether to install an already-downloaded update
|
|
9
|
+
// based on user idle time. Frequent so a downloaded update installs
|
|
10
|
+
// promptly when the user steps away (rather than waiting up to an
|
|
11
|
+
// hour for the next feed-check).
|
|
12
|
+
// 4. 30-day pending gate — once an update is downloaded, store `downloadedAt`. On every
|
|
13
|
+
// feed-check tick + at app start, if (now - downloadedAt) >= maxAgeMs
|
|
14
|
+
// (default 30d), force `quitAndInstall()`. Counter is set on the FIRST
|
|
15
|
+
// download and not reset by subsequent downloads — first one wins.
|
|
16
|
+
// Cleared only when the app actually launches at the
|
|
17
|
+
// pendingUpdate.version (i.e. install applied).
|
|
18
|
+
//
|
|
19
|
+
// State machine (broadcast to renderers as `desktop:auto-updater:status`):
|
|
20
|
+
// idle / checking / available / downloading / downloaded / not-available / error
|
|
21
|
+
//
|
|
22
|
+
// Dev simulation: set `OMEGA_DEV_UPDATE=available|unavailable|error` env var. The updater synthesizes
|
|
23
|
+
// the appropriate event sequence so you can test the UI flow without a real update server.
|
|
24
|
+
// `simulate(scenario)` is the same cascade on demand (View > Developer > Simulate update in the
|
|
25
|
+
// default menu), so a QA pass walks all three outcomes without relaunching per scenario.
|
|
26
|
+
//
|
|
27
|
+
// Renderer surface (added to preload.js as `window.desktop.autoUpdater`):
|
|
28
|
+
// getStatus() → { code, version, percent, error?, downloadedAt? }
|
|
29
|
+
// onStatus(fn) → unsubscribe fn; called on every state change.
|
|
30
|
+
// checkNow() → user-initiated check (shows dialogs on completion).
|
|
31
|
+
// installNow() → quitAndInstall() if status === 'downloaded'.
|
|
32
|
+
|
|
33
|
+
const LoggerLite = require('./logger-lite.js');
|
|
34
|
+
const logger = new LoggerLite('auto-updater');
|
|
35
|
+
|
|
36
|
+
const STORAGE_KEY = 'autoUpdater';
|
|
37
|
+
|
|
38
|
+
// Idle-aware install constant — hardcoded for now (not config-shaped). Tune here.
|
|
39
|
+
//
|
|
40
|
+
// A downloaded update no longer auto-installs after a flat 5s delay. Instead, the
|
|
41
|
+
// idle-eval timer (every `DEFAULTS.idleEvalIntervalMs`, default 1m) makes the
|
|
42
|
+
// install decision:
|
|
43
|
+
// 1. Any UI activity (mouse / keyboard / wheel / touch / window focus) bumps
|
|
44
|
+
// `_lastActivityAt = Date.now()`.
|
|
45
|
+
// 2. The idle-eval tick checks `state.code === 'downloaded'`:
|
|
46
|
+
// - If user idle ≥ IDLE_INSTALL_THRESHOLD_MS → installNow().
|
|
47
|
+
// - Else if we haven't prompted for this version yet → native dialog (once).
|
|
48
|
+
// 3. Dismissal ("Later") is "not now" — the idle-eval tick keeps polling and the
|
|
49
|
+
// install fires whenever the user eventually walks away. We never re-prompt
|
|
50
|
+
// for the same version (tracked via `_promptedForVersion`).
|
|
51
|
+
//
|
|
52
|
+
// Consumer hook: `manager.autoUpdater.markActive()` lets app code force-bump the
|
|
53
|
+
// activity timestamp from anywhere (e.g. just received an auth event, finished a
|
|
54
|
+
// long-running renderer task, etc.). Use sparingly — the built-in signals cover
|
|
55
|
+
// 99% of real activity.
|
|
56
|
+
//
|
|
57
|
+
// Test mode: when `manager.isTesting()` is true, the threshold collapses to 3s so
|
|
58
|
+
// integration tests can drive a real download → idle wait → install in ~5s instead
|
|
59
|
+
// of 15min. Both timers (feed-check + idle-eval) likewise drop to 500ms in tests so
|
|
60
|
+
// the full sequence fires inside a test run. Wired in `_idleThresholdMs()` and the
|
|
61
|
+
// initialize() timer setup based on the manager's `isTesting()` helper.
|
|
62
|
+
const IDLE_INSTALL_THRESHOLD_MS = 15 * 60 * 1000; // 15 min — production
|
|
63
|
+
const IDLE_INSTALL_THRESHOLD_MS_TESTING = 3 * 1000; // 3 sec — when isTesting()
|
|
64
|
+
const IDLE_TICK_MS_TESTING = 500; // 500ms periodic tick when testing
|
|
65
|
+
|
|
66
|
+
// The dev simulator's scenarios. Doubles as the OMEGA_DEV_UPDATE value set and the
|
|
67
|
+
// argument set simulate() accepts, so the env var and the menu trigger can never drift.
|
|
68
|
+
const SIMULATION_SCENARIOS = ['available', 'unavailable', 'error'];
|
|
69
|
+
|
|
70
|
+
// The version the simulator claims to have downloaded. A RESERVED sentinel: the
|
|
71
|
+
// reconciler discards any stored pendingUpdate carrying it (see _reconcilePendingUpdate),
|
|
72
|
+
// so an app must never ship a real release at this version.
|
|
73
|
+
const SIMULATED_VERSION = '999.0.0';
|
|
74
|
+
|
|
75
|
+
// Two separate timers, two different jobs:
|
|
76
|
+
//
|
|
77
|
+
// feedCheckIntervalMs — how often to hit the update feed (HTTP request). EXPENSIVE
|
|
78
|
+
// (network I/O against a third-party host every running app
|
|
79
|
+
// instance). Default 1h matches Discord/Slack/VS Code.
|
|
80
|
+
// idleEvalIntervalMs — how often to re-evaluate "is now a good time to install
|
|
81
|
+
// the downloaded update?" CHEAP (in-process arithmetic on
|
|
82
|
+
// _lastActivityAt + state check). Default 1min so a downloaded
|
|
83
|
+
// update installs promptly when the user steps away.
|
|
84
|
+
//
|
|
85
|
+
// They were briefly merged into a single timer in 1.2.38; that was a mistake — running
|
|
86
|
+
// the feed-check at idle-eval cadence (60s) was hammering GitHub at 60× the necessary
|
|
87
|
+
// rate. Restored as separate timers in 1.3.1.
|
|
88
|
+
const DEFAULTS = {
|
|
89
|
+
enabled: true,
|
|
90
|
+
channel: 'latest',
|
|
91
|
+
startupDelayMs: 10 * 1000, // 10s after whenReady
|
|
92
|
+
feedCheckIntervalMs: 60 * 60 * 1000, // 1h — feed poll cadence
|
|
93
|
+
idleEvalIntervalMs: 1 * 60 * 1000, // 1m — idle-install evaluator cadence
|
|
94
|
+
maxAgeMs: 30 * 24 * 60 * 60 * 1000, // 30 days
|
|
95
|
+
autoDownload: true,
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
// Fresh state object so a single `Object.assign` never bleeds between instances or test runs.
|
|
99
|
+
function freshState() {
|
|
100
|
+
return {
|
|
101
|
+
code: 'idle',
|
|
102
|
+
version: null,
|
|
103
|
+
percent: 0,
|
|
104
|
+
error: null,
|
|
105
|
+
downloadedAt: null,
|
|
106
|
+
lastCheckedAt: null,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const autoUpdater = {
|
|
111
|
+
_initialized: false,
|
|
112
|
+
_manager: null,
|
|
113
|
+
_library: null,
|
|
114
|
+
_options: null,
|
|
115
|
+
_state: freshState(),
|
|
116
|
+
_feedCheckIntervalId: null,
|
|
117
|
+
_idleEvalIntervalId: null,
|
|
118
|
+
_pendingTimers: [],
|
|
119
|
+
_userInitiated: false,
|
|
120
|
+
_devSimulating: false, // a cascade is running RIGHT NOW (re-entrancy guard)
|
|
121
|
+
_devSimulationSession: false, // this process has simulated at least once (see _isSimulating)
|
|
122
|
+
|
|
123
|
+
// Idle-aware install state.
|
|
124
|
+
_lastActivityAt: Date.now(), // bumped by markActive(); seed to "now" so we don't auto-install the instant we boot
|
|
125
|
+
_promptedForVersion: null, // version string we've already prompted about — never prompt twice for the same version
|
|
126
|
+
_activityHooksWired: false, // guard: only wire main-side activity listeners once per process
|
|
127
|
+
|
|
128
|
+
async initialize(manager) {
|
|
129
|
+
autoUpdater._manager = manager;
|
|
130
|
+
autoUpdater._initialized = true;
|
|
131
|
+
autoUpdater._state = freshState();
|
|
132
|
+
|
|
133
|
+
const cfg = (manager && manager.config && manager.config.autoUpdate) || {};
|
|
134
|
+
autoUpdater._options = { ...DEFAULTS, ...cfg };
|
|
135
|
+
|
|
136
|
+
if (autoUpdater._options.enabled === false) {
|
|
137
|
+
logger.log('auto-updater disabled via config.autoUpdate.enabled=false');
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// 1. Reconcile any pending update from a prior session.
|
|
142
|
+
autoUpdater._reconcilePendingUpdate();
|
|
143
|
+
|
|
144
|
+
// 2. Wire the electron-updater instance (or dev simulator).
|
|
145
|
+
if (autoUpdater._isSimulating()) {
|
|
146
|
+
logger.log(`Dev simulation mode active (OMEGA_DEV_UPDATE=${process.env.OMEGA_DEV_UPDATE})`);
|
|
147
|
+
autoUpdater._wireDevSimulator();
|
|
148
|
+
} else {
|
|
149
|
+
autoUpdater._wireElectronUpdater();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// 3. IPC: renderer status query + actions. Unhandle first so re-init is idempotent.
|
|
153
|
+
if (manager && manager.ipc) {
|
|
154
|
+
const channels = [
|
|
155
|
+
['desktop:auto-updater:status', async () => autoUpdater.getStatus()],
|
|
156
|
+
['desktop:auto-updater:check-now', async () => autoUpdater.checkNow({ userInitiated: true })],
|
|
157
|
+
['desktop:auto-updater:install-now', async () => autoUpdater.installNow()],
|
|
158
|
+
];
|
|
159
|
+
for (const [chan, fn] of channels) {
|
|
160
|
+
manager.ipc.unhandle(chan);
|
|
161
|
+
manager.ipc.handle(chan, fn);
|
|
162
|
+
}
|
|
163
|
+
// Activity ping from preload (debounced renderer-side mouse/keyboard/focus).
|
|
164
|
+
// Listener (not handle) — fire-and-forget, no response needed. Set-backed
|
|
165
|
+
// listener registry deduplicates same-fn re-adds, so re-init is safe.
|
|
166
|
+
if (typeof manager.ipc.on === 'function') {
|
|
167
|
+
manager.ipc.on('desktop:auto-updater:activity', autoUpdater._onActivityIpc);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// 3b. Wire main-side activity hooks (browser-window focus, tray clicks, menu
|
|
172
|
+
// invocations, deep-link arrivals — see _wireActivityHooks). One-shot per process.
|
|
173
|
+
autoUpdater._wireActivityHooks();
|
|
174
|
+
|
|
175
|
+
// 4. Schedule startup check (non-blocking).
|
|
176
|
+
const startupDelay = autoUpdater._options.startupDelayMs;
|
|
177
|
+
autoUpdater._pendingTimers.push(setTimeout(() => {
|
|
178
|
+
autoUpdater.checkNow({ userInitiated: false }).catch((e) => logger.warn(`startup check failed: ${e.message}`));
|
|
179
|
+
}, startupDelay));
|
|
180
|
+
|
|
181
|
+
// 5. Schedule TWO independent timers:
|
|
182
|
+
//
|
|
183
|
+
// a) Feed-check timer (EXPENSIVE — HTTP). Hits the GitHub release feed.
|
|
184
|
+
// Default 1h cadence. Also enforces the 30-day max-age gate as a safety net
|
|
185
|
+
// since this tick is when we'd notice a long-pending update.
|
|
186
|
+
//
|
|
187
|
+
// b) Idle-eval timer (CHEAP — in-process). Re-evaluates whether to install
|
|
188
|
+
// a downloaded update based on user idle time. Default 1m cadence so a
|
|
189
|
+
// downloaded update installs promptly when the user steps away.
|
|
190
|
+
//
|
|
191
|
+
// In tests (`manager.isTesting() === true`) both cadences collapse to
|
|
192
|
+
// IDLE_TICK_MS_TESTING (500ms) so an integration test sees the full sequence
|
|
193
|
+
// fire within seconds of a download.
|
|
194
|
+
const isTesting = manager.isTesting();
|
|
195
|
+
const feedInterval = isTesting ? IDLE_TICK_MS_TESTING : autoUpdater._options.feedCheckIntervalMs;
|
|
196
|
+
const idleInterval = isTesting ? IDLE_TICK_MS_TESTING : autoUpdater._options.idleEvalIntervalMs;
|
|
197
|
+
|
|
198
|
+
if (feedInterval > 0) {
|
|
199
|
+
autoUpdater._feedCheckIntervalId = setInterval(() => autoUpdater._feedCheckTick(), feedInterval);
|
|
200
|
+
}
|
|
201
|
+
if (idleInterval > 0) {
|
|
202
|
+
autoUpdater._idleEvalIntervalId = setInterval(() => autoUpdater._idleEvalTick(), idleInterval);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
logger.log(`auto-updater initialized (feed-check=${feedInterval}ms, idle-eval=${idleInterval}ms, maxAge=${autoUpdater._options.maxAgeMs}ms, idle-install threshold=${autoUpdater._idleThresholdMs() / 1000}s${isTesting ? ' [testing]' : ''})`);
|
|
206
|
+
},
|
|
207
|
+
|
|
208
|
+
// Feed-check tick — hits the GitHub release feed. Expensive (HTTP). Also enforces
|
|
209
|
+
// the 30-day max-age gate since this is the slower-cadence tick.
|
|
210
|
+
async _feedCheckTick() {
|
|
211
|
+
try {
|
|
212
|
+
await autoUpdater.checkNow({ userInitiated: false });
|
|
213
|
+
} catch (e) {
|
|
214
|
+
logger.warn(`feed-check failed: ${e.message}`);
|
|
215
|
+
}
|
|
216
|
+
autoUpdater._enforceMaxAgeGate();
|
|
217
|
+
},
|
|
218
|
+
|
|
219
|
+
// Idle-eval tick — cheap, no network. Just decides whether to install the
|
|
220
|
+
// already-downloaded update. Runs frequently so a downloaded update installs
|
|
221
|
+
// promptly when the user steps away (rather than waiting for the next hourly
|
|
222
|
+
// feed-check).
|
|
223
|
+
_idleEvalTick() {
|
|
224
|
+
autoUpdater._evaluateIdleInstall();
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
// Public API ─────────────────────────────────────────────────────────────────────
|
|
228
|
+
|
|
229
|
+
getStatus() {
|
|
230
|
+
return { ...autoUpdater._state };
|
|
231
|
+
},
|
|
232
|
+
|
|
233
|
+
async checkNow(opts) {
|
|
234
|
+
opts = opts || {};
|
|
235
|
+
autoUpdater._state.lastCheckedAt = Date.now();
|
|
236
|
+
|
|
237
|
+
if (!autoUpdater._readyToCheck()) {
|
|
238
|
+
// Already mid-check or sitting on a downloaded update — return without mutating
|
|
239
|
+
// _userInitiated. Otherwise a user clicking "Check for Updates" while a periodic
|
|
240
|
+
// background check is in flight would flip _userInitiated=true, which then makes
|
|
241
|
+
// _evaluateIdleInstall() skip the auto-install path (see line ~303). The flag must
|
|
242
|
+
// only flip when we actually start a new check.
|
|
243
|
+
logger.log(`Skipping check — current state=${autoUpdater._state.code}`);
|
|
244
|
+
return autoUpdater.getStatus();
|
|
245
|
+
}
|
|
246
|
+
autoUpdater._userInitiated = !!opts.userInitiated;
|
|
247
|
+
|
|
248
|
+
if (autoUpdater._isSimulating()) {
|
|
249
|
+
autoUpdater._runDevSimulation();
|
|
250
|
+
return autoUpdater.getStatus();
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (!autoUpdater._library) {
|
|
254
|
+
logger.warn('checkNow() called before library wired.');
|
|
255
|
+
return autoUpdater.getStatus();
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
try {
|
|
259
|
+
await autoUpdater._library.checkForUpdates();
|
|
260
|
+
} catch (e) {
|
|
261
|
+
autoUpdater._setState({ code: 'error', error: { message: e.message } });
|
|
262
|
+
}
|
|
263
|
+
return autoUpdater.getStatus();
|
|
264
|
+
},
|
|
265
|
+
|
|
266
|
+
// Dev-only runtime trigger for the update simulator, wired to the default menu's
|
|
267
|
+
// View > Developer > Simulate update items. Runs the same synthetic cascade the
|
|
268
|
+
// OMEGA_DEV_UPDATE env var drives at boot, except per call, so update UX can be
|
|
269
|
+
// walked scenario by scenario without relaunching the app (or shipping a release).
|
|
270
|
+
// Resolves with the status once the cascade is running, exactly like checkNow();
|
|
271
|
+
// the terminal state arrives over the status broadcast a few hundred ms later.
|
|
272
|
+
async simulate(scenario) {
|
|
273
|
+
const name = String(scenario || '').toLowerCase();
|
|
274
|
+
if (!name) {
|
|
275
|
+
throw new Error(`simulate(): scenario required, one of ${SIMULATION_SCENARIOS.join('|')}`);
|
|
276
|
+
}
|
|
277
|
+
if (!SIMULATION_SCENARIOS.includes(name)) {
|
|
278
|
+
throw new Error(`simulate(): unknown scenario "${scenario}". Expected one of: ${SIMULATION_SCENARIOS.join(', ')}.`);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Same doctrine as _isSimulating(): a packaged production build may simulate, but
|
|
282
|
+
// only when it was LAUNCHED for QA with OMEGA_DEV_UPDATE set. Without that opt-in a
|
|
283
|
+
// shipped binary must never be talked into faking an update it cannot deliver.
|
|
284
|
+
if (autoUpdater._manager.isProduction() && !autoUpdater._isSimulating()) {
|
|
285
|
+
throw new Error('simulate(): refused in a production build. Relaunch with OMEGA_DEV_UPDATE set to simulate updates.');
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// A cascade runs on fire-and-forget timers, so a second one cannot share the state
|
|
289
|
+
// machine with the first: it would reset the state to idle underneath it and then
|
|
290
|
+
// lose its own scenario to _runDevSimulation's re-entrancy guard. Refuse loudly
|
|
291
|
+
// rather than accept a call that silently does nothing.
|
|
292
|
+
if (autoUpdater._devSimulating) {
|
|
293
|
+
logger.warn(`simulate(${name}): refused, a simulation is already running.`);
|
|
294
|
+
throw new Error('simulate(): a simulation is already running. Wait for it to finish before starting another.');
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Swap the real electron-updater instance out for the synthetic one and LEAVE it
|
|
298
|
+
// swapped for the rest of the session. Swapping back is not safe: the cascade is
|
|
299
|
+
// async and fire-and-forget (there is no moment we know it ended), and the real
|
|
300
|
+
// library's listeners are still attached to its singleton, so a feed check landing
|
|
301
|
+
// mid-cascade would overwrite the synthetic states. A session that has simulated is
|
|
302
|
+
// a QA session; relaunch to get the real updater back. Idempotent when the boot-time
|
|
303
|
+
// simulator is already wired.
|
|
304
|
+
autoUpdater._wireDevSimulator();
|
|
305
|
+
|
|
306
|
+
// Latch the session ON with the swap, never apart from it: the two facts (a
|
|
307
|
+
// synthetic library is wired / the updater is simulating) must not disagree.
|
|
308
|
+
autoUpdater._devSimulationSession = true;
|
|
309
|
+
|
|
310
|
+
// Clear the visible state so a second simulation does not inherit the version,
|
|
311
|
+
// percent, or error the previous one left behind. downloadedAt is deliberately
|
|
312
|
+
// kept: the 30-day pending-update record is not ours to erase.
|
|
313
|
+
autoUpdater._userInitiated = true; // keeps the idle-eval tick from installing a simulated download
|
|
314
|
+
autoUpdater._setState({ code: 'idle', version: null, percent: 0, error: null, lastCheckedAt: Date.now() });
|
|
315
|
+
|
|
316
|
+
logger.log(`simulate(${name}): running the dev update cascade`);
|
|
317
|
+
await autoUpdater._library.checkForUpdates(name);
|
|
318
|
+
return autoUpdater.getStatus();
|
|
319
|
+
},
|
|
320
|
+
|
|
321
|
+
// Bump the activity timestamp. Called automatically by the built-in activity hooks
|
|
322
|
+
// (renderer mouse/keyboard, browser-window focus). Consumer code can also call this
|
|
323
|
+
// directly from anywhere (`manager.autoUpdater.markActive()`) to force-bump on
|
|
324
|
+
// app-specific activity.
|
|
325
|
+
markActive() {
|
|
326
|
+
autoUpdater._lastActivityAt = Date.now();
|
|
327
|
+
},
|
|
328
|
+
|
|
329
|
+
// Named handler for the IPC activity listener so the listener registry's Set-based
|
|
330
|
+
// dedupe collapses repeated re-init calls into one entry.
|
|
331
|
+
_onActivityIpc() {
|
|
332
|
+
autoUpdater.markActive();
|
|
333
|
+
},
|
|
334
|
+
|
|
335
|
+
async installNow() {
|
|
336
|
+
if (autoUpdater._state.code !== 'downloaded') {
|
|
337
|
+
logger.log(`installNow ignored — state=${autoUpdater._state.code}`);
|
|
338
|
+
return false;
|
|
339
|
+
}
|
|
340
|
+
if (autoUpdater._isSimulating()) {
|
|
341
|
+
logger.log('Dev mode — skipping real quitAndInstall().');
|
|
342
|
+
return true;
|
|
343
|
+
}
|
|
344
|
+
// Flip the manager's quit flag so the window-manager close handler lets the
|
|
345
|
+
// close events through instead of trapping them with hide-on-close. Without
|
|
346
|
+
// this, quitAndInstall() fires before-quit but the BrowserWindow's close
|
|
347
|
+
// handler (which runs FIRST since it has its own listener) would call
|
|
348
|
+
// event.preventDefault() and the install would just hide the window.
|
|
349
|
+
if (autoUpdater._manager) {
|
|
350
|
+
autoUpdater._manager._allowQuit = true;
|
|
351
|
+
}
|
|
352
|
+
if (autoUpdater._library && typeof autoUpdater._library.quitAndInstall === 'function') {
|
|
353
|
+
autoUpdater._library.quitAndInstall();
|
|
354
|
+
return true;
|
|
355
|
+
}
|
|
356
|
+
return false;
|
|
357
|
+
},
|
|
358
|
+
|
|
359
|
+
// Lifecycle teardown — used by tests.
|
|
360
|
+
shutdown() {
|
|
361
|
+
if (autoUpdater._feedCheckIntervalId) clearInterval(autoUpdater._feedCheckIntervalId);
|
|
362
|
+
if (autoUpdater._idleEvalIntervalId) clearInterval(autoUpdater._idleEvalIntervalId);
|
|
363
|
+
autoUpdater._pendingTimers.forEach((t) => clearTimeout(t));
|
|
364
|
+
autoUpdater._feedCheckIntervalId = null;
|
|
365
|
+
autoUpdater._idleEvalIntervalId = null;
|
|
366
|
+
autoUpdater._pendingTimers = [];
|
|
367
|
+
autoUpdater._initialized = false;
|
|
368
|
+
autoUpdater._library = null;
|
|
369
|
+
autoUpdater._userInitiated = false;
|
|
370
|
+
autoUpdater._devSimulating = false;
|
|
371
|
+
autoUpdater._devSimulationSession = false;
|
|
372
|
+
autoUpdater._promptedForVersion = null;
|
|
373
|
+
autoUpdater._activityHooksWired = false;
|
|
374
|
+
|
|
375
|
+
const m = autoUpdater._manager;
|
|
376
|
+
if (m && m.ipc && typeof m.ipc.unhandle === 'function') {
|
|
377
|
+
['desktop:auto-updater:status', 'desktop:auto-updater:check-now', 'desktop:auto-updater:install-now'].forEach((c) => {
|
|
378
|
+
m.ipc.unhandle(c);
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
},
|
|
382
|
+
|
|
383
|
+
// Internals ──────────────────────────────────────────────────────────────────────
|
|
384
|
+
|
|
385
|
+
// Auto-updater dev SIMULATION mode — controls whether checkForUpdates() is wired
|
|
386
|
+
// to electron-updater (real) or our synthetic event sequence (fake). Triggered by
|
|
387
|
+
// setting OMEGA_DEV_UPDATE=available|unavailable|error. NOT the same as
|
|
388
|
+
// `manager.isDevelopment()` (which is the runtime "are we packaged" signal); a
|
|
389
|
+
// packaged production build can absolutely run with OMEGA_DEV_UPDATE set for QA.
|
|
390
|
+
//
|
|
391
|
+
// The runtime simulate() latches `_devSimulationSession` for the rest of the process
|
|
392
|
+
// (cleared by shutdown()). It has to: simulate() leaves the synthetic library wired,
|
|
393
|
+
// so every LATER trigger drives the simulator too. The feed-check tick would then
|
|
394
|
+
// produce a fake 'downloaded' that this flag is the only thing keeping out of the
|
|
395
|
+
// real install path (_evaluateIdleInstall and installNow both bail on it). Reading
|
|
396
|
+
// only the env var here means a plain dev session could be talked into a native
|
|
397
|
+
// "restart to update" prompt, `_allowQuit = true`, and a stored pendingUpdate for a
|
|
398
|
+
// version that does not exist.
|
|
399
|
+
_isSimulating() {
|
|
400
|
+
return !!process.env.OMEGA_DEV_UPDATE || autoUpdater._devSimulationSession;
|
|
401
|
+
},
|
|
402
|
+
|
|
403
|
+
_idleThresholdMs() {
|
|
404
|
+
return autoUpdater._manager.isTesting() ? IDLE_INSTALL_THRESHOLD_MS_TESTING : IDLE_INSTALL_THRESHOLD_MS;
|
|
405
|
+
},
|
|
406
|
+
|
|
407
|
+
_readyToCheck() {
|
|
408
|
+
// Don't re-check while we're already mid-flight (checking/available/downloading) or sitting
|
|
409
|
+
// on a downloaded update waiting to install — re-checking would just re-download the same thing.
|
|
410
|
+
return ['idle', 'not-available', 'error'].includes(autoUpdater._state.code);
|
|
411
|
+
},
|
|
412
|
+
|
|
413
|
+
_setState(patch) {
|
|
414
|
+
const prevCode = autoUpdater._state.code;
|
|
415
|
+
autoUpdater._state = { ...autoUpdater._state, ...patch };
|
|
416
|
+
autoUpdater._broadcastStatus();
|
|
417
|
+
|
|
418
|
+
// No post-download install trigger here. All install-decision logic lives in the
|
|
419
|
+
// idle-eval tick (`_evaluateIdleInstall`). It runs every idleEvalIntervalMs
|
|
420
|
+
// (default 1m); first evaluation happens on the next tick after download
|
|
421
|
+
// completes (gives a user who's currently active a chance to reach a natural
|
|
422
|
+
// pause before any prompt fires).
|
|
423
|
+
},
|
|
424
|
+
|
|
425
|
+
// Evaluate whether to auto-install or prompt. Called from the idle-eval tick.
|
|
426
|
+
// The 30-day gate runs on the feed-check tick separately.
|
|
427
|
+
// - Only runs when state.code === 'downloaded' (i.e. an update is sitting ready).
|
|
428
|
+
// - Skips if the original check was user-initiated (consumer UI handles that path).
|
|
429
|
+
// - If user idle ≥ _idleThresholdMs() (15min in prod, 3s in tests) → installNow().
|
|
430
|
+
// - Else if we haven't prompted for this version yet → show native dialog.
|
|
431
|
+
// - Else: do nothing this tick. Try again next tick.
|
|
432
|
+
_evaluateIdleInstall() {
|
|
433
|
+
if (autoUpdater._state.code !== 'downloaded') return;
|
|
434
|
+
if (autoUpdater._userInitiated) return; // user-initiated path — consumer UI owns the install affordance
|
|
435
|
+
if (autoUpdater._isSimulating()) return; // dev simulator never really installs
|
|
436
|
+
|
|
437
|
+
const idleMs = Date.now() - autoUpdater._lastActivityAt;
|
|
438
|
+
const threshold = autoUpdater._idleThresholdMs();
|
|
439
|
+
if (idleMs >= threshold) {
|
|
440
|
+
logger.log(`User idle for ${Math.round(idleMs / 1000)}s (threshold=${Math.round(threshold / 1000)}s) — auto-installing update v${autoUpdater._state.version}.`);
|
|
441
|
+
// installNow is async; any internal throw becomes a rejection caught by
|
|
442
|
+
// the global unhandledRejection handler in main.js.
|
|
443
|
+
autoUpdater.installNow().catch((e) => logger.warn(`idle auto-install failed: ${e.message}`));
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// User is active — prompt once per version.
|
|
448
|
+
const v = autoUpdater._state.version;
|
|
449
|
+
if (v && autoUpdater._promptedForVersion !== v) {
|
|
450
|
+
autoUpdater._promptedForVersion = v;
|
|
451
|
+
autoUpdater._promptToInstall(v).catch((e) => logger.warn(`install prompt failed: ${e.message}`));
|
|
452
|
+
}
|
|
453
|
+
},
|
|
454
|
+
|
|
455
|
+
// Show a native dialog asking the user to restart now. Non-blocking (fire-and-forget).
|
|
456
|
+
// Dismissal ("Later") is fine — the watcher keeps polling and will auto-install once
|
|
457
|
+
// the user goes idle.
|
|
458
|
+
async _promptToInstall(version) {
|
|
459
|
+
// In test mode we short-circuit BEFORE invoking the real native dialog. The
|
|
460
|
+
// dialog is modal + blocking on a real desktop session and pops a window the
|
|
461
|
+
// user can't dismiss programmatically — exactly what we don't want firing
|
|
462
|
+
// during automated runs. Tests that want to assert prompt behavior should
|
|
463
|
+
// override `_promptToInstall` per-test (see auto-updater.test.js).
|
|
464
|
+
if (autoUpdater._manager.isTesting()) {
|
|
465
|
+
logger.log(`Test mode: _promptToInstall(${version}) — skipped native dialog.`);
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
const { dialog, BrowserWindow } = require('electron');
|
|
470
|
+
if (!dialog) return; // renderer/preload context — no dialog API
|
|
471
|
+
|
|
472
|
+
const focusedWindow = BrowserWindow.getFocusedWindow();
|
|
473
|
+
const productName = autoUpdater._manager.config.app?.productName
|
|
474
|
+
|| autoUpdater._manager.config.brand.name;
|
|
475
|
+
|
|
476
|
+
// showMessageBox CAN reject (e.g. dialog destroyed, no display) — wrap just
|
|
477
|
+
// the call. Synchronous setup above doesn't need a try.
|
|
478
|
+
let result;
|
|
479
|
+
try {
|
|
480
|
+
result = await dialog.showMessageBox(focusedWindow, {
|
|
481
|
+
type: 'info',
|
|
482
|
+
buttons: ['Restart Now', 'Later'],
|
|
483
|
+
defaultId: 0,
|
|
484
|
+
cancelId: 1,
|
|
485
|
+
title: 'Update Ready',
|
|
486
|
+
message: `${productName} is ready to install version ${version}.`,
|
|
487
|
+
detail: `Restart to apply the update now, or it will install automatically the next time you're idle.`,
|
|
488
|
+
});
|
|
489
|
+
} catch (e) {
|
|
490
|
+
logger.warn(`_promptToInstall: dialog.showMessageBox failed: ${e.message}`);
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
if (result.response === 0) {
|
|
495
|
+
logger.log(`User accepted install prompt — installing v${version}.`);
|
|
496
|
+
autoUpdater.installNow();
|
|
497
|
+
} else {
|
|
498
|
+
logger.log(`User dismissed install prompt for v${version} — watcher continues.`);
|
|
499
|
+
// Bump activity so we don't re-prompt within the same tick window.
|
|
500
|
+
autoUpdater.markActive();
|
|
501
|
+
}
|
|
502
|
+
},
|
|
503
|
+
|
|
504
|
+
// Wire main-process activity hooks. Idempotent — only runs once per process.
|
|
505
|
+
// Renderer-side activity arrives via the 'desktop:auto-updater:activity' IPC listener
|
|
506
|
+
// wired in initialize() (mouse/keyboard/wheel/touch/focus debounced in preload).
|
|
507
|
+
// This method covers main-process signals that don't go through the renderer:
|
|
508
|
+
// - browser-window-focus: user alt-tabbed back, clicked a window from elsewhere,
|
|
509
|
+
// or surfaced the app via tray click / dock click — any path that gives the
|
|
510
|
+
// window focus fires this. Tray/menu clicks that show/focus a window are also
|
|
511
|
+
// covered by this transitively.
|
|
512
|
+
// Deep-link arrivals are a softer signal (the user might have clicked a link in a
|
|
513
|
+
// browser hours ago and walked away) — we deliberately don't bump activity from
|
|
514
|
+
// them. If a consumer wants to count something specific, they can call markActive().
|
|
515
|
+
_wireActivityHooks() {
|
|
516
|
+
if (autoUpdater._activityHooksWired) return;
|
|
517
|
+
autoUpdater._activityHooksWired = true;
|
|
518
|
+
|
|
519
|
+
const { app } = require('electron');
|
|
520
|
+
app.on('browser-window-focus', () => autoUpdater.markActive());
|
|
521
|
+
},
|
|
522
|
+
|
|
523
|
+
_broadcastStatus() {
|
|
524
|
+
const m = autoUpdater._manager;
|
|
525
|
+
if (m && m.ipc && typeof m.ipc.broadcast === 'function') {
|
|
526
|
+
m.ipc.broadcast('desktop:auto-updater:status', autoUpdater.getStatus());
|
|
527
|
+
}
|
|
528
|
+
autoUpdater._updateMenuItem();
|
|
529
|
+
autoUpdater._updateTrayItem();
|
|
530
|
+
logger.log(`status → ${autoUpdater._state.code}${autoUpdater._state.version ? ` v${autoUpdater._state.version}` : ''}${autoUpdater._state.percent ? ` (${autoUpdater._state.percent}%)` : ''}`);
|
|
531
|
+
},
|
|
532
|
+
|
|
533
|
+
// Compute the label + enabled fields for any "check for updates" UI item from current state.
|
|
534
|
+
// Used by both the menu and tray patchers so they stay in lockstep.
|
|
535
|
+
_menuItemFieldsForState() {
|
|
536
|
+
const s = autoUpdater._state;
|
|
537
|
+
let label, enabled = true;
|
|
538
|
+
switch (s.code) {
|
|
539
|
+
case 'checking': label = 'Checking for Updates...'; enabled = false; break;
|
|
540
|
+
case 'available': label = `Downloading Update v${s.version || ''}...`; enabled = false; break;
|
|
541
|
+
case 'downloading': label = `Downloading Update (${Math.round(s.percent)}%)`; enabled = false; break;
|
|
542
|
+
case 'downloaded': label = `Restart to Update v${s.version || ''}`; enabled = true; break;
|
|
543
|
+
case 'not-available': label = 'You\'re up to date'; enabled = true; break;
|
|
544
|
+
case 'error': label = 'Check for Updates...'; enabled = true; break;
|
|
545
|
+
case 'idle':
|
|
546
|
+
default: label = 'Check for Updates...'; enabled = true; break;
|
|
547
|
+
}
|
|
548
|
+
return { label, enabled };
|
|
549
|
+
},
|
|
550
|
+
|
|
551
|
+
// Reflect updater state into the @omega.js/desktop Check-for-Updates item. The item lives under
|
|
552
|
+
// `main/check-for-updates` on macOS (App menu) and `help/check-for-updates` on win/linux —
|
|
553
|
+
// we just patch whichever one exists. Consumer can remove either via
|
|
554
|
+
// manager.menu.remove('main/check-for-updates') in their integrations/menu/index.js.
|
|
555
|
+
_updateMenuItem() {
|
|
556
|
+
const m = autoUpdater._manager;
|
|
557
|
+
const { label, enabled } = autoUpdater._menuItemFieldsForState();
|
|
558
|
+
|
|
559
|
+
// Patch whichever id-path exists. .update() returns false (and warns) if missing,
|
|
560
|
+
// so try both without doubling up on warnings — silence by checking has() first.
|
|
561
|
+
if (m.menu.has('main/check-for-updates')) {
|
|
562
|
+
m.menu.update('main/check-for-updates', { label, enabled });
|
|
563
|
+
} else if (m.menu.has('help/check-for-updates')) {
|
|
564
|
+
m.menu.update('help/check-for-updates', { label, enabled });
|
|
565
|
+
}
|
|
566
|
+
},
|
|
567
|
+
|
|
568
|
+
// Reflect updater state into the tray's `check-for-updates` item, if present. Same
|
|
569
|
+
// label/enabled semantics as the menu item — keeps both UIs in lockstep.
|
|
570
|
+
_updateTrayItem() {
|
|
571
|
+
const m = autoUpdater._manager;
|
|
572
|
+
const { label, enabled } = autoUpdater._menuItemFieldsForState();
|
|
573
|
+
|
|
574
|
+
if (m.tray.has('check-for-updates')) {
|
|
575
|
+
m.tray.update('check-for-updates', { label, enabled });
|
|
576
|
+
}
|
|
577
|
+
},
|
|
578
|
+
|
|
579
|
+
// 30-day gate ────────────────────────────────────────────────────────────────────
|
|
580
|
+
|
|
581
|
+
_reconcilePendingUpdate() {
|
|
582
|
+
const m = autoUpdater._manager;
|
|
583
|
+
const pending = m.storage.get(`${STORAGE_KEY}.pendingUpdate`);
|
|
584
|
+
if (!pending || !pending.downloadedAt) return;
|
|
585
|
+
|
|
586
|
+
// A simulated record (written by a build from before the simulator stopped
|
|
587
|
+
// touching this key) can never be applied — nothing ships at the sentinel
|
|
588
|
+
// version, so the clear-on-apply check below would never match it. Discard
|
|
589
|
+
// it here, or its fake timestamp gets restored into _state.downloadedAt and
|
|
590
|
+
// force-installs the first REAL download the moment it lands.
|
|
591
|
+
if (pending.version === SIMULATED_VERSION) {
|
|
592
|
+
logger.log(`Discarding simulated pendingUpdate record (v${pending.version}) — the dev simulator never downloaded anything.`);
|
|
593
|
+
m.storage.set(`${STORAGE_KEY}.pendingUpdate`, null);
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
const currentVersion = autoUpdater._manager.getVersion();
|
|
598
|
+
if (pending.version === currentVersion) {
|
|
599
|
+
logger.log(`Pending update v${pending.version} appears to be applied — clearing flag.`);
|
|
600
|
+
m.storage.set(`${STORAGE_KEY}.pendingUpdate`, null);
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
autoUpdater._state.downloadedAt = pending.downloadedAt;
|
|
605
|
+
autoUpdater._state.version = pending.version;
|
|
606
|
+
logger.log(`Pending update v${pending.version} carried from prior session (downloadedAt=${new Date(pending.downloadedAt).toISOString()})`);
|
|
607
|
+
// The gate can't install HERE — electron-updater has no download this
|
|
608
|
+
// session (installNow() requires state 'downloaded'). The startup check
|
|
609
|
+
// (startupDelayMs) re-downloads; update-downloaded then enforces the gate
|
|
610
|
+
// against the restored original downloadedAt.
|
|
611
|
+
},
|
|
612
|
+
|
|
613
|
+
_recordDownloadedAt(version) {
|
|
614
|
+
// The simulator's download is fake, so its record must never reach the
|
|
615
|
+
// production key: a fake timestamp there outlives the QA session and seeds
|
|
616
|
+
// the first-download-wins timer for the next REAL download (a fake record
|
|
617
|
+
// older than maxAgeMs force-installs it on arrival). The in-memory stamp
|
|
618
|
+
// still happens, so the in-session UI flow reads exactly like a real one.
|
|
619
|
+
if (autoUpdater._isSimulating()) {
|
|
620
|
+
autoUpdater._state.downloadedAt = Date.now();
|
|
621
|
+
logger.log(`Dev simulation — skipping the pendingUpdate write for v${version}.`);
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
const m = autoUpdater._manager;
|
|
626
|
+
if (!m || !m.storage) return;
|
|
627
|
+
|
|
628
|
+
const existing = m.storage.get(`${STORAGE_KEY}.pendingUpdate`);
|
|
629
|
+
// FIRST download wins for the TIMER — but the stored version must track the
|
|
630
|
+
// NEWEST download, or the clear-on-apply check (version === getVersion())
|
|
631
|
+
// never matches after the install and the stale flag force-installs every
|
|
632
|
+
// future download instantly, forever.
|
|
633
|
+
if (existing && existing.downloadedAt) {
|
|
634
|
+
logger.log(`pendingUpdate already recorded (v${existing.version} @ ${new Date(existing.downloadedAt).toISOString()}) — keeping existing timestamp.`);
|
|
635
|
+
if (existing.version !== version) {
|
|
636
|
+
m.storage.set(`${STORAGE_KEY}.pendingUpdate`, { version, downloadedAt: existing.downloadedAt });
|
|
637
|
+
}
|
|
638
|
+
autoUpdater._state.downloadedAt = existing.downloadedAt;
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
const now = Date.now();
|
|
642
|
+
m.storage.set(`${STORAGE_KEY}.pendingUpdate`, { version, downloadedAt: now });
|
|
643
|
+
autoUpdater._state.downloadedAt = now;
|
|
644
|
+
logger.log(`Recorded pendingUpdate v${version} @ ${new Date(now).toISOString()}`);
|
|
645
|
+
},
|
|
646
|
+
|
|
647
|
+
_enforceMaxAgeGate() {
|
|
648
|
+
const downloadedAt = autoUpdater._state.downloadedAt;
|
|
649
|
+
if (!downloadedAt) return false;
|
|
650
|
+
|
|
651
|
+
const age = Date.now() - downloadedAt;
|
|
652
|
+
const max = autoUpdater._options.maxAgeMs;
|
|
653
|
+
if (age < max) return false;
|
|
654
|
+
|
|
655
|
+
logger.warn(`Pending update is ${Math.round(age / 86400000)}d old (>= ${Math.round(max / 86400000)}d) — forcing install.`);
|
|
656
|
+
autoUpdater.installNow();
|
|
657
|
+
return true;
|
|
658
|
+
},
|
|
659
|
+
|
|
660
|
+
// electron-updater wiring ────────────────────────────────────────────────────────
|
|
661
|
+
|
|
662
|
+
_wireElectronUpdater() {
|
|
663
|
+
let lib;
|
|
664
|
+
try {
|
|
665
|
+
lib = require('electron-updater').autoUpdater;
|
|
666
|
+
} catch (e) {
|
|
667
|
+
logger.warn(`electron-updater not available: ${e.message}`);
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
670
|
+
autoUpdater._library = lib;
|
|
671
|
+
lib.autoDownload = autoUpdater._options.autoDownload !== false;
|
|
672
|
+
|
|
673
|
+
lib.on('checking-for-update', () => autoUpdater._setState({ code: 'checking', error: null }));
|
|
674
|
+
lib.on('update-available', (info) => autoUpdater._setState({ code: 'available', version: info?.version, error: null }));
|
|
675
|
+
lib.on('update-not-available', (info) => autoUpdater._setState({ code: 'not-available', version: info?.version, error: null }));
|
|
676
|
+
lib.on('download-progress', (p) => {
|
|
677
|
+
const percent = Math.min(100, parseFloat(((p && p.percent) || 0).toFixed(2)) || 0);
|
|
678
|
+
autoUpdater._setState({ code: 'downloading', percent });
|
|
679
|
+
});
|
|
680
|
+
lib.on('update-downloaded', (info) => {
|
|
681
|
+
autoUpdater._recordDownloadedAt(info?.version);
|
|
682
|
+
autoUpdater._setState({ code: 'downloaded', version: info?.version, percent: 100, error: null });
|
|
683
|
+
// A pending update carried from a prior session keeps its ORIGINAL
|
|
684
|
+
// downloadedAt (first-download-wins), so the 30-day gate can trip the
|
|
685
|
+
// moment the startup re-download lands — installNow() only works from
|
|
686
|
+
// the 'downloaded' state, which exists from this line on.
|
|
687
|
+
autoUpdater._enforceMaxAgeGate();
|
|
688
|
+
});
|
|
689
|
+
lib.on('error', (e) => {
|
|
690
|
+
const err = (e instanceof Error) ? e : new Error(String(e || 'Unknown auto-update error'));
|
|
691
|
+
autoUpdater._setState({ code: 'error', error: { message: err.message } });
|
|
692
|
+
});
|
|
693
|
+
},
|
|
694
|
+
|
|
695
|
+
// Dev simulation ─────────────────────────────────────────────────────────────────
|
|
696
|
+
|
|
697
|
+
_wireDevSimulator() {
|
|
698
|
+
autoUpdater._library = {
|
|
699
|
+
checkForUpdates: async (scenario) => autoUpdater._runDevSimulation(scenario),
|
|
700
|
+
quitAndInstall: () => logger.log('Dev simulator: quitAndInstall() called (no-op in dev).'),
|
|
701
|
+
autoDownload: autoUpdater._options.autoDownload !== false,
|
|
702
|
+
on: () => {},
|
|
703
|
+
};
|
|
704
|
+
},
|
|
705
|
+
|
|
706
|
+
// `scenario` is the per-call override simulate() passes. The boot-time path (checkNow
|
|
707
|
+
// while _isSimulating()) passes nothing and falls back to the OMEGA_DEV_UPDATE value
|
|
708
|
+
// that put the updater in simulation mode to begin with, so that path is unchanged.
|
|
709
|
+
_runDevSimulation(scenario) {
|
|
710
|
+
if (autoUpdater._devSimulating) return;
|
|
711
|
+
autoUpdater._devSimulating = true;
|
|
712
|
+
|
|
713
|
+
const name = (scenario || process.env.OMEGA_DEV_UPDATE || 'available').toLowerCase();
|
|
714
|
+
const NEW_VERSION = SIMULATED_VERSION;
|
|
715
|
+
|
|
716
|
+
autoUpdater._setState({ code: 'checking' });
|
|
717
|
+
|
|
718
|
+
setTimeout(() => {
|
|
719
|
+
if (name === 'unavailable') {
|
|
720
|
+
autoUpdater._setState({ code: 'not-available', version: NEW_VERSION });
|
|
721
|
+
autoUpdater._devSimulating = false;
|
|
722
|
+
return;
|
|
723
|
+
}
|
|
724
|
+
if (name === 'error') {
|
|
725
|
+
autoUpdater._setState({ code: 'error', error: { message: 'Simulated dev-update error' } });
|
|
726
|
+
autoUpdater._devSimulating = false;
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
// 'available' → cascade through download progress → downloaded.
|
|
731
|
+
autoUpdater._setState({ code: 'available', version: NEW_VERSION });
|
|
732
|
+
|
|
733
|
+
let percent = 0;
|
|
734
|
+
const tick = () => {
|
|
735
|
+
percent = Math.min(100, percent + 25);
|
|
736
|
+
autoUpdater._setState({ code: 'downloading', version: NEW_VERSION, percent });
|
|
737
|
+
if (percent < 100) {
|
|
738
|
+
autoUpdater._pendingTimers.push(setTimeout(tick, 400));
|
|
739
|
+
} else {
|
|
740
|
+
autoUpdater._pendingTimers.push(setTimeout(() => {
|
|
741
|
+
autoUpdater._recordDownloadedAt(NEW_VERSION);
|
|
742
|
+
autoUpdater._setState({ code: 'downloaded', version: NEW_VERSION, percent: 100 });
|
|
743
|
+
autoUpdater._devSimulating = false;
|
|
744
|
+
}, 400));
|
|
745
|
+
}
|
|
746
|
+
};
|
|
747
|
+
autoUpdater._pendingTimers.push(setTimeout(tick, 400));
|
|
748
|
+
}, 400);
|
|
749
|
+
},
|
|
750
|
+
};
|
|
751
|
+
|
|
752
|
+
module.exports = autoUpdater;
|