@fullstackunicorn/create-root 1.0.17 → 1.0.19
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/assets/root.fullstackunicorn.dev/.gitlab-ci.yml +42 -0
- package/assets/root.fullstackunicorn.dev/assets/.env +6 -0
- package/assets/root.fullstackunicorn.dev/assets/config.cmd.sh +86 -0
- package/assets/root.fullstackunicorn.dev/assets/index.cmd.js +30 -0
- package/assets/root.fullstackunicorn.dev/assets/index.def.js +190 -0
- package/assets/root.fullstackunicorn.dev/assets/index.dep.js +20 -0
- package/assets/root.fullstackunicorn.dev/assets/index.init.js +8 -0
- package/assets/root.fullstackunicorn.dev/assets/index.js +4 -0
- package/assets/root.fullstackunicorn.dev/assets/modules/sync.auth.js +3 -0
- package/assets/root.fullstackunicorn.dev/assets/modules/sync.js +430 -0
- package/assets/root.fullstackunicorn.dev/assets/modules/sync.local.js +117 -0
- package/assets/root.fullstackunicorn.dev/assets/modules/sync.tools.js +102 -0
- package/assets/root.fullstackunicorn.dev/assets/package.json +32 -0
- package/assets/root.fullstackunicorn.dev/assets/package.md +13 -0
- package/assets/root.fullstackunicorn.dev/assets/webapp.runner.js +63 -0
- package/assets/root.fullstackunicorn.dev/backend/.env +13 -0
- package/assets/root.fullstackunicorn.dev/backend/config.cmd.sh +79 -0
- package/assets/root.fullstackunicorn.dev/backend/dockerfile +12 -0
- package/assets/root.fullstackunicorn.dev/backend/index.def.js +15 -0
- package/assets/root.fullstackunicorn.dev/backend/index.dep.js +19 -0
- package/assets/root.fullstackunicorn.dev/backend/index.init.js +25 -0
- package/assets/root.fullstackunicorn.dev/backend/index.js +15 -0
- package/assets/root.fullstackunicorn.dev/backend/modules/cookies.js +64 -0
- package/assets/root.fullstackunicorn.dev/backend/modules/loader.js +103 -0
- package/assets/root.fullstackunicorn.dev/backend/modules/loader.tools.js +22 -0
- package/assets/root.fullstackunicorn.dev/backend/modules/stripe.js +299 -0
- package/assets/root.fullstackunicorn.dev/backend/modules/stripe.session.js +1 -0
- package/assets/root.fullstackunicorn.dev/backend/modules/stripe.tools.js +126 -0
- package/assets/root.fullstackunicorn.dev/backend/package.json +35 -0
- package/assets/root.fullstackunicorn.dev/backend/server/errors.js +29 -0
- package/assets/root.fullstackunicorn.dev/backend/server/errors.list.js +69 -0
- package/assets/root.fullstackunicorn.dev/backend/server/middleware.auth.js +4 -0
- package/assets/root.fullstackunicorn.dev/backend/server/middleware.js +29 -0
- package/assets/root.fullstackunicorn.dev/backend/server/middleware.prod.js +18 -0
- package/assets/root.fullstackunicorn.dev/backend/server/resolvers.js +21 -0
- package/assets/root.fullstackunicorn.dev/backend/server/router.js +60 -0
- package/assets/root.fullstackunicorn.dev/config.cmd.sh +182 -0
- package/assets/root.fullstackunicorn.dev/config.code-workspace +7 -0
- package/assets/root.fullstackunicorn.dev/config.reduce.js +84 -0
- package/assets/root.fullstackunicorn.dev/frontend/.env +3 -0
- package/assets/root.fullstackunicorn.dev/frontend/App.js +23 -0
- package/assets/root.fullstackunicorn.dev/frontend/App.sw.js +12 -0
- package/assets/root.fullstackunicorn.dev/frontend/App.tracking.js +13 -0
- package/assets/root.fullstackunicorn.dev/frontend/App.uri.js +63 -0
- package/assets/root.fullstackunicorn.dev/frontend/abstracts/abs.js +148 -0
- package/assets/root.fullstackunicorn.dev/frontend/abstracts/dateTime.js +120 -0
- package/assets/root.fullstackunicorn.dev/frontend/abstracts/err.js +31 -0
- package/assets/root.fullstackunicorn.dev/frontend/abstracts/img.js +38 -0
- package/assets/root.fullstackunicorn.dev/frontend/assets/index.webmanifest +21 -0
- package/assets/root.fullstackunicorn.dev/frontend/assets/llms.dev.txt +2 -0
- package/assets/root.fullstackunicorn.dev/frontend/assets/llms.txt +8 -0
- package/assets/root.fullstackunicorn.dev/frontend/assets/robots.dev.txt +2 -0
- package/assets/root.fullstackunicorn.dev/frontend/assets/robots.txt +4 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/account/@use.js +95 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/account/AccountCard.js +37 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/account/AccountLogo.js +27 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/account/AccountLogo.pod.js +34 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/alerts/@use.js +7 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/alerts/Alert.js +24 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/alerts/Alert.pod.js +28 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/alerts/Alerts.js +35 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/callout/Callout.js +16 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/callout/Callout.pod.js +25 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/checkout/@tools.js +41 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/checkout/@use.js +34 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/checkout/CheckoutCard.js +29 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/checkout/CheckoutCard.pod.js +25 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/cookies/@tools.js +67 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/cookies/@use.js +218 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/cookies/CookiesCard.js +19 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/errors/@use.js +7 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/errors/Errors.js +14 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/language/@tools.js +45 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/language/@use.js +144 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/language/LanguageButton.js +18 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/language/LanguageCard.js +20 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/layout/@use.js +91 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/layout/Footer.js +5 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/layout/Footer.pod.js +19 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/layout/Header.js +22 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/layout/Header.pod.js +37 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/layout/Layout.js +41 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/layout/Layout.pod.js +30 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/layout/menus/@use.js +21 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/layout/menus/MenuTwo.js +41 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/layout/menus/MenuTwo.pod.js +38 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/layout/sideTwo/@use.js +48 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/layout/sideTwo/IconTwo.js +30 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/layout/sideTwo/IconTwo.pod.js +22 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/layout/sideTwo/SidebarTwo.js +46 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/layout/sideTwo/SidebarTwo.pod.js +29 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/legals/LegalCard.js +17 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/legals/LegalsCard.js +20 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/loader/@tools.js +111 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/loader/@use.js +35 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/loader/Loader.js +20 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/loader/Normalizer.js +58 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/loader/Starter.js +17 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/lookups/@use.js +85 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/modals/@use.js +67 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/modals/Modal.js +42 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/modals/Modal.pod.js +43 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/modals/ModalPopup.pod.js +41 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/modals/Modals.js +12 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/router/@tools.js +26 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/router/@use.js +212 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/router/Router.js +21 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/statics/@use.js +46 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/theme/@use.js +28 -0
- package/assets/root.fullstackunicorn.dev/frontend/base/theme/ThemeCard.js +21 -0
- package/assets/root.fullstackunicorn.dev/frontend/client/@api.js +15 -0
- package/assets/root.fullstackunicorn.dev/frontend/client/auth.js +213 -0
- package/assets/root.fullstackunicorn.dev/frontend/client/cookies.js +41 -0
- package/assets/root.fullstackunicorn.dev/frontend/client/fonts.js +19 -0
- package/assets/root.fullstackunicorn.dev/frontend/client/load.js +26 -0
- package/assets/root.fullstackunicorn.dev/frontend/client/statics.js +47 -0
- package/assets/root.fullstackunicorn.dev/frontend/client/stripe.js +38 -0
- package/assets/root.fullstackunicorn.dev/frontend/config.cmd.sh +94 -0
- package/assets/root.fullstackunicorn.dev/frontend/config.cmd.vite.js +205 -0
- package/assets/root.fullstackunicorn.dev/frontend/config.meta.js +0 -0
- package/assets/root.fullstackunicorn.dev/frontend/config.style.js +86 -0
- package/assets/root.fullstackunicorn.dev/frontend/configure/cache.json +4 -0
- package/assets/root.fullstackunicorn.dev/frontend/configure/env.json +8 -0
- package/assets/root.fullstackunicorn.dev/frontend/configure/env.prod.json +8 -0
- package/assets/root.fullstackunicorn.dev/frontend/configure/layout.json +9 -0
- package/assets/root.fullstackunicorn.dev/frontend/configure/logo.json +4 -0
- package/assets/root.fullstackunicorn.dev/frontend/configure/services.json +10 -0
- package/assets/root.fullstackunicorn.dev/frontend/configure/trademark.json +9 -0
- package/assets/root.fullstackunicorn.dev/frontend/eslint.config.js +41 -0
- package/assets/root.fullstackunicorn.dev/frontend/features/legal/Legal.js +15 -0
- package/assets/root.fullstackunicorn.dev/frontend/features/legal/Legal.pod.js +11 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/animated/Button.js +66 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/animated/Crossfader.js +32 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/animated/Fader.js +46 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/animated/HoverCard.js +31 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/animated/Layout.js +68 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/animated/Layout.use.js +33 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/animated/Layout.vars.js +20 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/animated/Root.js +26 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/cache.js +81 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/client.js +248 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/core/Backdrop.js +21 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/core/Background.js +21 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/core/Background.pod.js +20 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/core/Href.js +22 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/core/Iframe.js +13 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/core/Img.js +88 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/core/Img.pod.js +69 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/core/InputFile.js +26 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/core/InputTextItem.js +23 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/core/InputTextarea.js +39 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/core/InputTextline.js +23 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/core/Json.js +19 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/core/Link.js +105 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/core/List.js +18 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/core/Main.js +7 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/core/Pressable.js +14 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/core/Scrollable.js +27 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/core/Svg.js +23 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/core/Svg.pod.js +24 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/core/Text.js +118 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/core/View.js +13 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/fonts/tools.js +72 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/fonts/use.js +52 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/head/Head.js +39 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/npm.js +20 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/router.js +21 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/scroll/@use.js +85 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/scroll/scroll.js +33 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/service.js +27 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/storage.js +48 -0
- package/assets/root.fullstackunicorn.dev/frontend/imports/use.js +62 -0
- package/assets/root.fullstackunicorn.dev/frontend/index.html +36 -0
- package/assets/root.fullstackunicorn.dev/frontend/jsconfig.json +18 -0
- package/assets/root.fullstackunicorn.dev/frontend/menus/@use.js +15 -0
- package/assets/root.fullstackunicorn.dev/frontend/menus/Main.js +33 -0
- package/assets/root.fullstackunicorn.dev/frontend/menus/Main.use.js +22 -0
- package/assets/root.fullstackunicorn.dev/frontend/modals/countries/countries.js +39 -0
- package/assets/root.fullstackunicorn.dev/frontend/modules/buttons/IconTextButton.js +17 -0
- package/assets/root.fullstackunicorn.dev/frontend/modules/buttons/IconTextButton.pod.js +24 -0
- package/assets/root.fullstackunicorn.dev/frontend/modules/buttons/TextButton.js +47 -0
- package/assets/root.fullstackunicorn.dev/frontend/modules/buttons/TextButton.pod.js +94 -0
- package/assets/root.fullstackunicorn.dev/frontend/modules/core/Back.js +26 -0
- package/assets/root.fullstackunicorn.dev/frontend/modules/core/Back.pod.js +37 -0
- package/assets/root.fullstackunicorn.dev/frontend/modules/core/Bulleted.js +37 -0
- package/assets/root.fullstackunicorn.dev/frontend/modules/core/Icon.js +20 -0
- package/assets/root.fullstackunicorn.dev/frontend/modules/core/Icon.pod.js +28 -0
- package/assets/root.fullstackunicorn.dev/frontend/modules/core/Img.js +19 -0
- package/assets/root.fullstackunicorn.dev/frontend/modules/core/Img.pod.js +26 -0
- package/assets/root.fullstackunicorn.dev/frontend/modules/core/Link.js +35 -0
- package/assets/root.fullstackunicorn.dev/frontend/modules/core/Link.pod.js +28 -0
- package/assets/root.fullstackunicorn.dev/frontend/modules/core/Slider.js +1 -0
- package/assets/root.fullstackunicorn.dev/frontend/modules/core/Slider.pod.js +30 -0
- package/assets/root.fullstackunicorn.dev/frontend/modules/page/PageBox.js +15 -0
- package/assets/root.fullstackunicorn.dev/frontend/modules/trademarks/@use.js +25 -0
- package/assets/root.fullstackunicorn.dev/frontend/modules/trademarks/Logo.js +19 -0
- package/assets/root.fullstackunicorn.dev/frontend/modules/trademarks/Logo.pod.js +17 -0
- package/assets/root.fullstackunicorn.dev/frontend/modules/trademarks/Trademark.js +20 -0
- package/assets/root.fullstackunicorn.dev/frontend/modules/trademarks/Trademark.pod.js +17 -0
- package/assets/root.fullstackunicorn.dev/frontend/package.json +58 -0
- package/assets/root.fullstackunicorn.dev/frontend/pages/@use.js +50 -0
- package/assets/root.fullstackunicorn.dev/frontend/pages/app/Checkout.js +10 -0
- package/assets/root.fullstackunicorn.dev/frontend/pages/app/Home.abs.js +11 -0
- package/assets/root.fullstackunicorn.dev/frontend/pages/app/Home.api.js +18 -0
- package/assets/root.fullstackunicorn.dev/frontend/pages/app/Home.js +23 -0
- package/assets/root.fullstackunicorn.dev/frontend/pages/root/Callout.api.js +31 -0
- package/assets/root.fullstackunicorn.dev/frontend/pages/root/Callout.js +13 -0
- package/assets/root.fullstackunicorn.dev/frontend/pages/root/Legal.api.js +35 -0
- package/assets/root.fullstackunicorn.dev/frontend/pages/root/Legal.js +15 -0
- package/assets/root.fullstackunicorn.dev/frontend/pages/root/Legals.api.js +19 -0
- package/assets/root.fullstackunicorn.dev/frontend/pages/root/Legals.js +29 -0
- package/assets/root.fullstackunicorn.dev/frontend/pages/root/User.api.js +18 -0
- package/assets/root.fullstackunicorn.dev/frontend/pages/root/User.js +25 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/card/book/BookCard.js +58 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/card/book/BookCard.pod.js +37 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/card/book/BookProse.js +22 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/cards/Account.js +26 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/cards/Account.pod.js +48 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/cards/Launcher.js +19 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/cards/Launcher.pod.js +38 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/cards/Linker.js +20 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/cards/Linker.pod.js +38 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/cards/Slider.js +22 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/cards/Slider.pod.js +39 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/error/ErrorPage.js +12 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/error/ErrorPage.pod.js +23 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/grid/book/Grid.js +115 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/grid/book/Grid.pod.js +65 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/grid/book/Item.js +3 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/grid/book/Item.pod.js +50 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/layout/Bottom.js +12 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/layout/Bottom.pod.js +40 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/layout/PageTitle.js +3 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/layout/PageTitle.pod.js +21 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/page/PageScrollable.js +13 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/page/PageScrollable.pod.js +85 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/prose/@formatter.js +113 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/prose/@use.js +21 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/prose/Basic.js +30 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/prose/Basic.pod.js +16 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/prose/Prose.js +84 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/prose/Prose.pod.js +58 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/selectors/actions/Actions.js +45 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/selectors/actions/Actions.pod.js +19 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/selectors/actions/SelectPicked.js +21 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/selectors/actions/SelectPicked.pod.js +35 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/selectors/popup/PopupModal.js +54 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/selectors/select/SelectItem.js +20 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/selectors/select/SelectItem.pod.js +33 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/selectors/select/SelectModal.js +52 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/selectors/select/SelectPage.js +33 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/selectors/select/SelectPage.pod.js +18 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/shopper/bookstore/Buy.js +19 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/shopper/bookstore/Buy.pod.js +17 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/shopper/bookstore/Shopper.js +39 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/shopper/bookstore/Shopper.pod.js +187 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/slider/Slider.js +138 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/slider/Slider.pod.js +102 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/sliders/actions/Actions.js +12 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/sliders/actions/Actions.pod.js +22 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/sliders/slider/SliderItem.js +30 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/sliders/slider/SliderItem.pod.js +39 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/sliders/slider/SliderModal.js +39 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/sliders/slider/SliderPage.js +37 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/sliders/slider/SliderPage.pod.js +24 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/wrapper/fixed/Wrapper.js +25 -0
- package/assets/root.fullstackunicorn.dev/frontend/panels/wrapper/fixed/Wrapper.pod.js +23 -0
- package/assets/root.fullstackunicorn.dev/frontend/preloader/@use.js +14 -0
- package/assets/root.fullstackunicorn.dev/frontend/preloader/Preloader.js +46 -0
- package/assets/root.fullstackunicorn.dev/frontend/root/constants.js +4 -0
- package/assets/root.fullstackunicorn.dev/frontend/root/constants.root.js +15 -0
- package/assets/root.fullstackunicorn.dev/frontend/root/constants.scope.js +5 -0
- package/assets/root.fullstackunicorn.dev/frontend/root/errors.js +4 -0
- package/assets/root.fullstackunicorn.dev/frontend/root/errors.root.js +6 -0
- package/assets/root.fullstackunicorn.dev/frontend/root/errors.scope.js +6 -0
- package/assets/root.fullstackunicorn.dev/frontend/root/menus.js +9 -0
- package/assets/root.fullstackunicorn.dev/frontend/root/menus.root.js +6 -0
- package/assets/root.fullstackunicorn.dev/frontend/root/menus.scope.js +6 -0
- package/assets/root.fullstackunicorn.dev/frontend/root/modals.js +4 -0
- package/assets/root.fullstackunicorn.dev/frontend/root/modals.root.js +11 -0
- package/assets/root.fullstackunicorn.dev/frontend/root/modals.scope.js +5 -0
- package/assets/root.fullstackunicorn.dev/frontend/root/pages.js +4 -0
- package/assets/root.fullstackunicorn.dev/frontend/root/pages.root.js +12 -0
- package/assets/root.fullstackunicorn.dev/frontend/root/pages.scope.js +11 -0
- package/assets/root.fullstackunicorn.dev/frontend/root/preload.js +18 -0
- package/assets/root.fullstackunicorn.dev/frontend/root/preload.root.js +30 -0
- package/assets/root.fullstackunicorn.dev/frontend/root/preload.scope.js +33 -0
- package/assets/root.fullstackunicorn.dev/frontend/root/routes.js +7 -0
- package/assets/root.fullstackunicorn.dev/frontend/root/routes.root.js +47 -0
- package/assets/root.fullstackunicorn.dev/frontend/root/routes.scope.js +31 -0
- package/assets/root.fullstackunicorn.dev/frontend/sworker/sw.js +104 -0
- package/assets/root.fullstackunicorn.dev/frontend/templates/cards.js +25 -0
- package/assets/root.fullstackunicorn.dev/frontend/templates/index.js +11 -0
- package/assets/root.fullstackunicorn.dev/frontend/templates/page.js +16 -0
- package/assets/root.fullstackunicorn.dev/frontend/templates/root.js +32 -0
- package/assets/root.fullstackunicorn.dev/frontend/tracking/errors.js +5 -0
- package/assets/root.fullstackunicorn.dev/frontend/tracking/logging.js +5 -0
- package/assets/root.fullstackunicorn.dev/frontend/tracking/performance.js +5 -0
- package/assets/root.fullstackunicorn.dev/frontend/tracking/vitals.js +5 -0
- package/assets/root.fullstackunicorn.dev/frontend/vite.config.js +64 -0
- package/assets/root.fullstackunicorn.dev/frontend/vite.jsx.js +10 -0
- package/assets/root.fullstackunicorn.dev/frontend/vite.sworker.js +56 -0
- package/assets/root.fullstackunicorn.dev/frontend/vite.volume.js +94 -0
- package/assets/root.fullstackunicorn.dev/manager/.env +10 -0
- package/assets/root.fullstackunicorn.dev/manager/config.cmd.sh +81 -0
- package/assets/root.fullstackunicorn.dev/manager/dockerfile +12 -0
- package/assets/root.fullstackunicorn.dev/manager/index.def.js +17 -0
- package/assets/root.fullstackunicorn.dev/manager/index.dep.js +17 -0
- package/assets/root.fullstackunicorn.dev/manager/index.init.js +38 -0
- package/assets/root.fullstackunicorn.dev/manager/index.js +17 -0
- package/assets/root.fullstackunicorn.dev/manager/modules/clone.js +65 -0
- package/assets/root.fullstackunicorn.dev/manager/modules/sync.server.js +65 -0
- package/assets/root.fullstackunicorn.dev/manager/modules/sync.tools.js +55 -0
- package/assets/root.fullstackunicorn.dev/manager/modules/workspace.js +77 -0
- package/assets/root.fullstackunicorn.dev/manager/modules/workspace.tools.js +49 -0
- package/assets/root.fullstackunicorn.dev/manager/package.json +36 -0
- package/assets/root.fullstackunicorn.dev/manager/server/errors.js +30 -0
- package/assets/root.fullstackunicorn.dev/manager/server/errors.list.js +24 -0
- package/assets/root.fullstackunicorn.dev/manager/server/middleware.auth.js +4 -0
- package/assets/root.fullstackunicorn.dev/manager/server/middleware.js +29 -0
- package/assets/root.fullstackunicorn.dev/manager/server/middleware.prod.js +18 -0
- package/assets/root.fullstackunicorn.dev/manager/server/resolvers.js +21 -0
- package/assets/root.fullstackunicorn.dev/manager/server/router.js +58 -0
- package/assets/root.fullstackunicorn.dev/package.json +16 -0
- package/assets/root.fullstackunicorn.dev/package.md +44 -0
- package/assets/root.fullstackunicorn.dev/root.config.app.js +85 -0
- package/package.json +1 -1
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { StripeSdk, jwtEncode, fsa } from '#@/index.dep.js'
|
|
2
|
+
import { Def } from '#@/index.def.js'
|
|
3
|
+
import { Tools } from '#@/modules/stripe.tools.js'
|
|
4
|
+
|
|
5
|
+
export class Stripe {
|
|
6
|
+
|
|
7
|
+
constructor() {
|
|
8
|
+
|
|
9
|
+
this.def = new Def()
|
|
10
|
+
this.tools = new Tools()
|
|
11
|
+
this.client = new StripeSdk(process.env.STRIPE_SECRET_KEY)
|
|
12
|
+
|
|
13
|
+
this.url = {}
|
|
14
|
+
this.url.pay = `https://${process.env.CLIENT_URL}/pay`
|
|
15
|
+
|
|
16
|
+
this.secret = {}
|
|
17
|
+
this.secret.checkout = process.env.CHECKOUT_TOKEN_SECRET
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
getToken = (payload = {}) => {
|
|
21
|
+
try {
|
|
22
|
+
return jwtEncode(payload, this.secret.checkout)
|
|
23
|
+
} catch (e) { F3.catch.throw(e, 'Stripe.getToken-failed') }
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
getPayUrl = ({ status, product, seller }) => {
|
|
27
|
+
|
|
28
|
+
const payload = {}
|
|
29
|
+
payload.type = 'checkout'
|
|
30
|
+
payload.status = status
|
|
31
|
+
payload.product = product
|
|
32
|
+
payload.seller = seller
|
|
33
|
+
|
|
34
|
+
const token = this.getToken(payload)
|
|
35
|
+
|
|
36
|
+
return `${this.url.pay}?token=${encodeURIComponent(token)}`
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
getClientReferenceId = ({ product, seller }) => {
|
|
40
|
+
return `${seller.code || 'noseller'}__${product.code}__${product.lang}`
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
getMetadata = ({ product, seller }) => {
|
|
44
|
+
|
|
45
|
+
const metadata = {}
|
|
46
|
+
|
|
47
|
+
metadata.product_code = product.code
|
|
48
|
+
metadata.product_path = product.path
|
|
49
|
+
metadata.product_lang = product.lang
|
|
50
|
+
metadata.fulfillment_key = `${product.code}__${product.lang}`
|
|
51
|
+
metadata.product_name = product.name
|
|
52
|
+
metadata.seller_code = seller.code || ''
|
|
53
|
+
metadata.seller_name = seller.name || ''
|
|
54
|
+
|
|
55
|
+
return metadata
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
getSeller = () => {
|
|
59
|
+
|
|
60
|
+
const seller = {}
|
|
61
|
+
seller.code = 'home'
|
|
62
|
+
seller.name = 'home'
|
|
63
|
+
|
|
64
|
+
return seller
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
getCheckoutBody = (request = {}) => {
|
|
68
|
+
|
|
69
|
+
const body = request?.body
|
|
70
|
+
if (!F3.isObj(body)) F3.throw('checkout-request-invalid')
|
|
71
|
+
|
|
72
|
+
const response = {}
|
|
73
|
+
response.lang = body?.lang
|
|
74
|
+
response.code = body?.code
|
|
75
|
+
response.currency = body?.currency
|
|
76
|
+
response.price = body?.price
|
|
77
|
+
response.quantity = Number(body?.quantity)
|
|
78
|
+
|
|
79
|
+
if (!F3.str.isGood(response.lang)) F3.throw('checkout-request-invalid')
|
|
80
|
+
if (!F3.str.isGood(response.code)) F3.throw('checkout-product-invalid')
|
|
81
|
+
if (!F3.str.isGood(response.currency)) F3.throw('checkout-currency-invalid')
|
|
82
|
+
if (!F3.isNum(response.quantity) || response.quantity <= 0) F3.throw('checkout-request-invalid')
|
|
83
|
+
if (!F3.str.isGood(String(response.price || '')) && !F3.isNum(response.price)) F3.throw('checkout-price-invalid')
|
|
84
|
+
|
|
85
|
+
return response
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
getCheckoutBase = code => `/get/data/modules/checkout/${code}`
|
|
89
|
+
|
|
90
|
+
getVolumeJson = async url => {
|
|
91
|
+
|
|
92
|
+
const filePath = `${this.def.volume}${url}.json`
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
const data = await fsa.readJSON(filePath)
|
|
96
|
+
if (!F3.obj.isGood(data)) F3.throw('checkout-product-invalid', { url })
|
|
97
|
+
return data
|
|
98
|
+
} catch {
|
|
99
|
+
F3.throw('checkout-product-invalid', { url, filePath })
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
getCheckoutFiles = async ({ lang, code }) => {
|
|
104
|
+
|
|
105
|
+
const base = this.getCheckoutBase(code)
|
|
106
|
+
|
|
107
|
+
const verbal = await this.getVolumeJson(`${base}/${lang}`)
|
|
108
|
+
const logic = await this.getVolumeJson(`${base}/@logic`)
|
|
109
|
+
|
|
110
|
+
return { verbal, logic }
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
getServerPrice = ({ logic = {}, currency = '' }) => {
|
|
114
|
+
|
|
115
|
+
const item = logic?.['@data']?.price?.[currency]
|
|
116
|
+
if (!F3.obj.isGood(item)) F3.throw('checkout-currency-invalid', { currency })
|
|
117
|
+
|
|
118
|
+
return item?.price?.value
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
verifyClientPrice = ({ input = {}, serverPrice }) => {
|
|
122
|
+
|
|
123
|
+
const clientPrice = this.tools.getComparablePrice(input.price)
|
|
124
|
+
const verifiedServerPrice = this.tools.getComparablePrice(serverPrice)
|
|
125
|
+
|
|
126
|
+
if (clientPrice === verifiedServerPrice) return
|
|
127
|
+
|
|
128
|
+
F3.logs({
|
|
129
|
+
type: 'checkout-price-mismatch',
|
|
130
|
+
code: input.code,
|
|
131
|
+
lang: input.lang,
|
|
132
|
+
currency: input.currency,
|
|
133
|
+
clientPrice,
|
|
134
|
+
serverPrice: verifiedServerPrice
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
F3.throw('checkout-price-invalid')
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
getStripeProduct = async ({ input = {}, verbal = {}, logic = {} }) => {
|
|
141
|
+
|
|
142
|
+
const item = verbal?.['@data']?.product?.item || {}
|
|
143
|
+
const serverPrice = this.getServerPrice({ logic, currency: input.currency })
|
|
144
|
+
|
|
145
|
+
this.verifyClientPrice({ input, serverPrice })
|
|
146
|
+
|
|
147
|
+
const product = {}
|
|
148
|
+
product.code = item.code
|
|
149
|
+
product.path = item.path
|
|
150
|
+
product.lang = input.lang
|
|
151
|
+
product.name = item.title
|
|
152
|
+
product.description = item.description
|
|
153
|
+
product.image = await this.tools.getImageUrl(item.image)
|
|
154
|
+
product.price = this.tools.getStripeAmount({ value: serverPrice, currency: input.currency })
|
|
155
|
+
product.currency = input.currency
|
|
156
|
+
product.quantity = input.quantity
|
|
157
|
+
|
|
158
|
+
if (!F3.str.isGood(product.code)) F3.throw('checkout-product-invalid')
|
|
159
|
+
if (!F3.str.isGood(product.path)) F3.throw('checkout-product-invalid')
|
|
160
|
+
if (!F3.str.isGood(product.name)) F3.throw('checkout-product-invalid')
|
|
161
|
+
if (!F3.str.isGood(product.description)) F3.throw('checkout-product-invalid')
|
|
162
|
+
if (!F3.str.isGood(product.image)) F3.throw('checkout-product-invalid')
|
|
163
|
+
|
|
164
|
+
return product
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
getStripeSessionInput = ({ product, seller }) => {
|
|
168
|
+
|
|
169
|
+
const client_reference_id = this.getClientReferenceId({ product, seller })
|
|
170
|
+
const metadata = this.getMetadata({ product, seller })
|
|
171
|
+
const success_url = this.getPayUrl({ status: 'success', product, seller })
|
|
172
|
+
const cancel_url = this.getPayUrl({ status: 'cancel', product, seller })
|
|
173
|
+
const payment_intent_data = { metadata }
|
|
174
|
+
|
|
175
|
+
return {
|
|
176
|
+
mode: 'payment',
|
|
177
|
+
client_reference_id,
|
|
178
|
+
success_url,
|
|
179
|
+
cancel_url,
|
|
180
|
+
metadata,
|
|
181
|
+
payment_intent_data,
|
|
182
|
+
line_items: [
|
|
183
|
+
{
|
|
184
|
+
quantity: product.quantity,
|
|
185
|
+
price_data: {
|
|
186
|
+
currency: product.currency,
|
|
187
|
+
unit_amount: product.price,
|
|
188
|
+
product_data: {
|
|
189
|
+
name: product.name,
|
|
190
|
+
description: product.description,
|
|
191
|
+
images: [product.image],
|
|
192
|
+
metadata: {
|
|
193
|
+
product_code: product.code,
|
|
194
|
+
product_path: product.path,
|
|
195
|
+
product_lang: product.lang
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
],
|
|
201
|
+
shipping_address_collection: {
|
|
202
|
+
allowed_countries: ['IT', 'IE', 'GB']
|
|
203
|
+
},
|
|
204
|
+
shipping_options: [
|
|
205
|
+
{
|
|
206
|
+
shipping_rate_data: {
|
|
207
|
+
type: 'fixed_amount',
|
|
208
|
+
fixed_amount: {
|
|
209
|
+
amount: 0,
|
|
210
|
+
currency: product.currency
|
|
211
|
+
},
|
|
212
|
+
display_name: 'Free shipping'
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
],
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
verifyGet = (request = {}) => {
|
|
220
|
+
|
|
221
|
+
const session_id = request?.body?.session_id
|
|
222
|
+
if (!F3.str.isGood(session_id)) F3.throw('missing-session-id')
|
|
223
|
+
|
|
224
|
+
return { session_id }
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
handleStripeError = error => {
|
|
228
|
+
|
|
229
|
+
const code = error?.code || ''
|
|
230
|
+
const type = error?.type || ''
|
|
231
|
+
|
|
232
|
+
if (code === 'parameter_invalid_integer') F3.throw('invalid-product-price')
|
|
233
|
+
if (code === 'parameter_invalid_empty') F3.throw('checkout-product-invalid')
|
|
234
|
+
if (code === 'resource_missing') F3.throw('missing-session')
|
|
235
|
+
if (code === 'url_invalid') F3.throw('checkout-url-invalid')
|
|
236
|
+
if (code === 'amount_too_small') F3.throw('checkout-price-invalid')
|
|
237
|
+
if (code === 'amount_too_large') F3.throw('checkout-price-invalid')
|
|
238
|
+
if (code === 'currency_not_supported') F3.throw('checkout-currency-invalid')
|
|
239
|
+
|
|
240
|
+
if (type === 'StripeAuthenticationError') F3.throw('checkout-provider-invalid')
|
|
241
|
+
if (type === 'StripePermissionError') F3.throw('checkout-provider-forbidden')
|
|
242
|
+
if (type === 'StripeConnectionError') F3.throw('checkout-provider-unavailable')
|
|
243
|
+
if (type === 'StripeAPIError') F3.throw('checkout-provider-error')
|
|
244
|
+
if (type === 'StripeInvalidRequestError') F3.throw('checkout-request-invalid')
|
|
245
|
+
|
|
246
|
+
throw error
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
set = async request => {
|
|
250
|
+
|
|
251
|
+
try {
|
|
252
|
+
|
|
253
|
+
const input = this.getCheckoutBody(request)
|
|
254
|
+
const seller = this.getSeller()
|
|
255
|
+
const { verbal, logic } = await this.getCheckoutFiles(input)
|
|
256
|
+
const product = await this.getStripeProduct({ input, verbal, logic })
|
|
257
|
+
const payload = this.getStripeSessionInput({ product, seller })
|
|
258
|
+
|
|
259
|
+
const session = await this.client.checkout.sessions.create(payload)
|
|
260
|
+
|
|
261
|
+
if (!F3.str.isGood(session?.url)) F3.throw('missing-session-url')
|
|
262
|
+
if (!F3.str.isGood(session?.id)) F3.throw('missing-session-id')
|
|
263
|
+
|
|
264
|
+
return { isValid: true, id: session.id, url: session.url }
|
|
265
|
+
|
|
266
|
+
} catch (e) {
|
|
267
|
+
F3.logs(e)
|
|
268
|
+
try { this.handleStripeError(e) }
|
|
269
|
+
catch (error) { F3.catch.throw(error, 'Stripe.set-failed') }
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
get = async request => {
|
|
274
|
+
|
|
275
|
+
try {
|
|
276
|
+
|
|
277
|
+
const { session_id } = this.verifyGet(request)
|
|
278
|
+
|
|
279
|
+
const session = await this.client.checkout.sessions.retrieve(session_id)
|
|
280
|
+
|
|
281
|
+
if (!session?.id) F3.throw('missing-session')
|
|
282
|
+
|
|
283
|
+
return {
|
|
284
|
+
isValid: true,
|
|
285
|
+
id: session.id,
|
|
286
|
+
status: session.status,
|
|
287
|
+
payment_status: session.payment_status,
|
|
288
|
+
client_reference_id: session.client_reference_id,
|
|
289
|
+
metadata: session.metadata || {}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
} catch (e) {
|
|
293
|
+
F3.logs(e)
|
|
294
|
+
try { this.handleStripeError(e) }
|
|
295
|
+
catch (error) { F3.catch.throw(error, 'Stripe.get-failed') }
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { fsa } from '#@/index.dep.js'
|
|
2
|
+
import { Def } from '#@/index.def.js'
|
|
3
|
+
|
|
4
|
+
export class Tools {
|
|
5
|
+
|
|
6
|
+
constructor() {
|
|
7
|
+
|
|
8
|
+
this.def = new Def()
|
|
9
|
+
this.imageBaseUrl = `https://${process.env.CLIENT_URL}`
|
|
10
|
+
|
|
11
|
+
this.currencyDecimals = {}
|
|
12
|
+
this.currencyDecimals.EUR = 2
|
|
13
|
+
this.currencyDecimals.DKK = 2
|
|
14
|
+
this.currencyDecimals.CZK = 2
|
|
15
|
+
this.currencyDecimals.CHF = 2
|
|
16
|
+
this.currencyDecimals.USD = 2
|
|
17
|
+
this.currencyDecimals.HUF = 2
|
|
18
|
+
|
|
19
|
+
this.widths = {}
|
|
20
|
+
this.widths.TS = 64
|
|
21
|
+
this.widths.TM = 256
|
|
22
|
+
this.widths.TL = 512
|
|
23
|
+
this.widths.SD = 960
|
|
24
|
+
this.widths.MD = 1440
|
|
25
|
+
this.widths.HD = 1920
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
getMediaMetaPath = (src = '') => {
|
|
29
|
+
|
|
30
|
+
if (!F3.str.isGood(src)) F3.throw('checkout-product-invalid', { src })
|
|
31
|
+
|
|
32
|
+
const normalized = src
|
|
33
|
+
.replace(/^\/+/, '')
|
|
34
|
+
.replace(/\/(TS|TM|TL|SD|MD|HD)\//, '/')
|
|
35
|
+
|
|
36
|
+
return normalized
|
|
37
|
+
.replace(/\.[^.]+$/, '.json')
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
getMediaVariant = max => {
|
|
41
|
+
|
|
42
|
+
const current = this.widths?.[max]
|
|
43
|
+
const target = this.widths.TL
|
|
44
|
+
|
|
45
|
+
if (!F3.isNum(current) || current <= 0) return 'TS'
|
|
46
|
+
if (current >= target) return 'TL'
|
|
47
|
+
return max
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
getMediaVariantPath = ({ src = '', variant = 'TS' }) => {
|
|
51
|
+
return src
|
|
52
|
+
.replace(/^\/+/, '')
|
|
53
|
+
.replace(/\/(TS|TM|TL|SD|MD|HD)\//, `/${variant}/`)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
getImageUrl = async (image = {}) => {
|
|
57
|
+
|
|
58
|
+
const src = F3.isStr(image) ? image : (image?.src || '')
|
|
59
|
+
if (!F3.str.isGood(src)) F3.throw('checkout-product-invalid', { image })
|
|
60
|
+
|
|
61
|
+
const metaPath = this.getMediaMetaPath(src)
|
|
62
|
+
const filePath = `${this.def.volume}/get/media/${metaPath}`
|
|
63
|
+
|
|
64
|
+
let meta = {}
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
meta = await fsa.readJSON(filePath)
|
|
68
|
+
} catch {
|
|
69
|
+
F3.throw('checkout-product-invalid', { image, filePath })
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const variant = this.getMediaVariant(meta?.max)
|
|
73
|
+
const nextPath = this.getMediaVariantPath({ src, variant })
|
|
74
|
+
|
|
75
|
+
return `${this.imageBaseUrl}/get/media/${nextPath}`
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
getCurrencyDecimals = currency => {
|
|
79
|
+
|
|
80
|
+
const decimals = this.currencyDecimals?.[currency]
|
|
81
|
+
if (!F3.isNum(decimals) || decimals < 0) F3.throw('checkout-currency-invalid', { currency })
|
|
82
|
+
|
|
83
|
+
return decimals
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
getComparablePrice = value => {
|
|
87
|
+
|
|
88
|
+
const text = String(value ?? '').trim()
|
|
89
|
+
if (!F3.str.isGood(text)) F3.throw('checkout-price-invalid', { value })
|
|
90
|
+
|
|
91
|
+
return text.replace(/\s+/g, '')
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
normalizeDecimalSeparator = value => {
|
|
95
|
+
|
|
96
|
+
const text = this.getComparablePrice(value)
|
|
97
|
+
|
|
98
|
+
if (text.includes(',') && text.includes('.')) {
|
|
99
|
+
return text.replace(/\./g, '').replace(',', '.')
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (text.includes(',')) return text.replace(',', '.')
|
|
103
|
+
return text
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
getStripeAmount = ({ value, currency }) => {
|
|
107
|
+
|
|
108
|
+
const decimals = this.getCurrencyDecimals(currency)
|
|
109
|
+
const normalized = this.normalizeDecimalSeparator(value)
|
|
110
|
+
const amount = Number(normalized)
|
|
111
|
+
|
|
112
|
+
if (!F3.isNum(amount) || amount <= 0) F3.throw('checkout-price-invalid', { value, currency, normalized })
|
|
113
|
+
|
|
114
|
+
const multiplier = 10 ** decimals
|
|
115
|
+
const stripeAmount = Math.round(amount * multiplier)
|
|
116
|
+
|
|
117
|
+
if (!F3.isNum(stripeAmount) || stripeAmount <= 0) F3.throw('checkout-price-invalid', {
|
|
118
|
+
value,
|
|
119
|
+
currency,
|
|
120
|
+
normalized,
|
|
121
|
+
decimals
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
return stripeAmount
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@root.fullstackunicorn.dev/backend",
|
|
3
|
+
"author": "lucanigido (https://fullstackunicorn.dev/author/lucanigido)",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "UNLICENSED",
|
|
7
|
+
"private": true,
|
|
8
|
+
"main": "index.js",
|
|
9
|
+
"imports": {
|
|
10
|
+
"#@": "./",
|
|
11
|
+
"#@/*": "./*"
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"initialize": "chmod +x ./config.cmd.sh && bash ./config.cmd.sh add",
|
|
15
|
+
"cmd": "chmod +x ./config.cmd.sh && ./config.cmd.sh",
|
|
16
|
+
"start": "env-cmd -f .env node index.js",
|
|
17
|
+
"start:nodemon": "env-cmd -f .env nodemon --ignore ./volume/ --ignore ./private/ --trace-warnings -L index.js",
|
|
18
|
+
"start:prod": "NODE_ENV=production node index.js"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@fullstackunicorn/auth": "^1.0.1",
|
|
22
|
+
"@fullstackunicorn/filesystem": "^1.0.16",
|
|
23
|
+
"@fullstackunicorn/initialize": "^1.0.15",
|
|
24
|
+
"axios": "^1.15.0",
|
|
25
|
+
"cors": "^2.8.6",
|
|
26
|
+
"express": "^5.2.1",
|
|
27
|
+
"jwt-decode": "^4.0.0",
|
|
28
|
+
"jwt-encode": "^1.0.1",
|
|
29
|
+
"stripe": "^22.0.2"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"env-cmd": "^11.0.0",
|
|
33
|
+
"nodemon": "^3.1.14"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { list } from '#@/server/errors.list.js'
|
|
2
|
+
|
|
3
|
+
class Errors {
|
|
4
|
+
|
|
5
|
+
error = {
|
|
6
|
+
send: { error: 'server-error' },
|
|
7
|
+
status: 400
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
getClientError = ({ service, message, params }) => {
|
|
11
|
+
const error = list?.[service]?.[message]
|
|
12
|
+
if (!F3.obj.isGood(error)) return this.error
|
|
13
|
+
const response = {}
|
|
14
|
+
response.status = error.status
|
|
15
|
+
response.send = {}
|
|
16
|
+
response.send.error = error.error
|
|
17
|
+
if (error.isParams) response.send.params = params
|
|
18
|
+
return response
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
returns = (response, path, error) => {
|
|
22
|
+
const { service, message, params } = error
|
|
23
|
+
const { status, send } = this.getClientError(error)
|
|
24
|
+
F3.logs('ERROR:', service, path, message, params, status, send)
|
|
25
|
+
return response.status(status).send(send)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
}
|
|
29
|
+
export const errors = new Errors()
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export const list = {
|
|
2
|
+
[F3.service]: {
|
|
3
|
+
'server-error': {
|
|
4
|
+
'isParams': false,
|
|
5
|
+
'error': 'server-error',
|
|
6
|
+
'status': 400,
|
|
7
|
+
},
|
|
8
|
+
'not-admitted-user': {
|
|
9
|
+
'isParams': false,
|
|
10
|
+
'error': `not-admitted-user`,
|
|
11
|
+
'status': 401
|
|
12
|
+
},
|
|
13
|
+
'not-authenticated': {
|
|
14
|
+
'isParams': false,
|
|
15
|
+
'error': 'not-authenticated',
|
|
16
|
+
'status': 401,
|
|
17
|
+
},
|
|
18
|
+
'already-admitted-user': {
|
|
19
|
+
'isParams': false,
|
|
20
|
+
'error': `already-admitted-user`,
|
|
21
|
+
'status': 401,
|
|
22
|
+
},
|
|
23
|
+
'checkout-product-invalid': {
|
|
24
|
+
isParams: false,
|
|
25
|
+
error: 'checkout-product-invalid',
|
|
26
|
+
status: 400
|
|
27
|
+
},
|
|
28
|
+
'checkout-url-invalid': {
|
|
29
|
+
isParams: false,
|
|
30
|
+
error: 'checkout-url-invalid',
|
|
31
|
+
status: 400
|
|
32
|
+
},
|
|
33
|
+
'checkout-provider-invalid': {
|
|
34
|
+
isParams: false,
|
|
35
|
+
error: 'checkout-provider-invalid',
|
|
36
|
+
status: 400
|
|
37
|
+
},
|
|
38
|
+
'checkout-provider-forbidden': {
|
|
39
|
+
isParams: false,
|
|
40
|
+
error: 'checkout-provider-forbidden',
|
|
41
|
+
status: 400
|
|
42
|
+
},
|
|
43
|
+
'checkout-provider-unavailable': {
|
|
44
|
+
isParams: false,
|
|
45
|
+
error: 'checkout-provider-unavailable',
|
|
46
|
+
status: 400
|
|
47
|
+
},
|
|
48
|
+
'checkout-provider-error': {
|
|
49
|
+
isParams: false,
|
|
50
|
+
error: 'checkout-provider-error',
|
|
51
|
+
status: 400
|
|
52
|
+
},
|
|
53
|
+
'checkout-request-invalid': {
|
|
54
|
+
isParams: false,
|
|
55
|
+
error: 'checkout-request-invalid',
|
|
56
|
+
status: 400
|
|
57
|
+
},
|
|
58
|
+
'checkout-price-invalid': {
|
|
59
|
+
isParams: false,
|
|
60
|
+
error: 'checkout-price-invalid',
|
|
61
|
+
status: 400
|
|
62
|
+
},
|
|
63
|
+
'checkout-currency-invalid': {
|
|
64
|
+
isParams: false,
|
|
65
|
+
error: 'checkout-currency-invalid',
|
|
66
|
+
status: 400
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { errors } from '#@/server/errors.js'
|
|
2
|
+
import { auth } from '#@/server/middleware.auth.js'
|
|
3
|
+
|
|
4
|
+
class Middleware {
|
|
5
|
+
|
|
6
|
+
constructor () {
|
|
7
|
+
this.token = auth.getToken()
|
|
8
|
+
this.userId = auth.getUserId()
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
user = async (authorization) => {
|
|
12
|
+
const user = { id: this.userId }
|
|
13
|
+
if (authorization === this.token) return user
|
|
14
|
+
throw new Error("not-authorized")
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
verify = user => user?.id ?? F3.throw("not-authenticated")
|
|
18
|
+
|
|
19
|
+
auth = async (path, request, response, next) => {
|
|
20
|
+
try {
|
|
21
|
+
const user = await this.user(request?.headers?.authorization)
|
|
22
|
+
this.verify(user)
|
|
23
|
+
request.user = user
|
|
24
|
+
return next()
|
|
25
|
+
} catch (error) { return errors.returns(response, path, error) }
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const middleware = new Middleware()
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { auth } from '#@/index.dep.js'
|
|
2
|
+
import { errors } from '#@/server/errors.js'
|
|
3
|
+
|
|
4
|
+
class Middleware {
|
|
5
|
+
|
|
6
|
+
verify = user => user?.id && F3.throw('not-authenticated')
|
|
7
|
+
auth = async (path, request, response, next) => {
|
|
8
|
+
try {
|
|
9
|
+
const user = await auth.user(request.headers?.authorization, request.method)
|
|
10
|
+
this.verify(user)
|
|
11
|
+
request.user = user
|
|
12
|
+
return next()
|
|
13
|
+
} catch (error) { return errors.returns(response, path, error) }
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const middleware = new Middleware()
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { errors } from '#@/server/errors.js'
|
|
2
|
+
|
|
3
|
+
class Resolver {
|
|
4
|
+
|
|
5
|
+
resolve = async (func, path, request, response, next) => {
|
|
6
|
+
try {
|
|
7
|
+
const data = await func(request)
|
|
8
|
+
return response.status(200).send(data)
|
|
9
|
+
} catch (error) { return errors.returns(response, path, error) }
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
permission = async ({ func, path, type }, request, response, next) => {
|
|
13
|
+
try {
|
|
14
|
+
request.body.change_type = type
|
|
15
|
+
const data = await func(request)
|
|
16
|
+
return response.status(200).send(data)
|
|
17
|
+
} catch (error) { return errors.returns(response, path, error) }
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const resolver = new Resolver ()
|