@fullstackunicorn/create-root 1.0.27 → 1.0.29

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.
Files changed (48) hide show
  1. package/assets/root.fullstackunicorn.dev/assets/config.cmd.sh +2 -2
  2. package/assets/root.fullstackunicorn.dev/backend/modules/loader.js +1 -0
  3. package/assets/root.fullstackunicorn.dev/backend/modules/pulse.js +22 -0
  4. package/assets/root.fullstackunicorn.dev/backend/server/router.js +10 -0
  5. package/assets/root.fullstackunicorn.dev/frontend/App.uri.js +10 -4
  6. package/assets/root.fullstackunicorn.dev/frontend/assets/index.webmanifest +3 -3
  7. package/assets/root.fullstackunicorn.dev/frontend/base/account/@use.js +9 -16
  8. package/assets/root.fullstackunicorn.dev/frontend/base/alerts/Alert.pod.js +2 -2
  9. package/assets/root.fullstackunicorn.dev/frontend/base/callout/Callout.pod.js +3 -3
  10. package/assets/root.fullstackunicorn.dev/frontend/base/cookies/@tools.js +2 -46
  11. package/assets/root.fullstackunicorn.dev/frontend/base/layout/Header.pod.js +2 -2
  12. package/assets/root.fullstackunicorn.dev/frontend/base/layout/Layout.pod.js +3 -3
  13. package/assets/root.fullstackunicorn.dev/frontend/base/layout/sideTwo/IconTwo.pod.js +1 -1
  14. package/assets/root.fullstackunicorn.dev/frontend/base/layout/sideTwo/SidebarTwo.pod.js +2 -2
  15. package/assets/root.fullstackunicorn.dev/frontend/base/loader/@tools.js +2 -1
  16. package/assets/root.fullstackunicorn.dev/frontend/base/modals/Modal.pod.js +2 -2
  17. package/assets/root.fullstackunicorn.dev/frontend/base/modals/ModalPopup.pod.js +3 -3
  18. package/assets/root.fullstackunicorn.dev/frontend/client/auth.js +52 -66
  19. package/assets/root.fullstackunicorn.dev/frontend/client/statics.js +3 -2
  20. package/assets/root.fullstackunicorn.dev/frontend/configure/env.json +1 -0
  21. package/assets/root.fullstackunicorn.dev/frontend/configure/env.prod.json +1 -0
  22. package/assets/root.fullstackunicorn.dev/frontend/imports/animated/Button.js +2 -2
  23. package/assets/root.fullstackunicorn.dev/frontend/imports/animated/Crossfader.js +1 -1
  24. package/assets/root.fullstackunicorn.dev/frontend/imports/animated/HoverCard.js +1 -1
  25. package/assets/root.fullstackunicorn.dev/frontend/imports/client.js +22 -10
  26. package/assets/root.fullstackunicorn.dev/frontend/imports/core/Img.js +62 -10
  27. package/assets/root.fullstackunicorn.dev/frontend/imports/core/Img.pod.js +4 -4
  28. package/assets/root.fullstackunicorn.dev/frontend/imports/core/Scrollable.js +10 -1
  29. package/assets/root.fullstackunicorn.dev/frontend/imports/core/Text.js +11 -2
  30. package/assets/root.fullstackunicorn.dev/frontend/imports/device.js +46 -0
  31. package/assets/root.fullstackunicorn.dev/frontend/imports/router.js +2 -0
  32. package/assets/root.fullstackunicorn.dev/frontend/imports/service.js +2 -2
  33. package/assets/root.fullstackunicorn.dev/frontend/index.html +5 -5
  34. package/assets/root.fullstackunicorn.dev/frontend/modules/base/ComingSoon.pod.js +2 -2
  35. package/assets/root.fullstackunicorn.dev/frontend/modules/base/PageTitle.pod.js +1 -1
  36. package/assets/root.fullstackunicorn.dev/frontend/modules/layout/Wrapper.pod.js +1 -1
  37. package/assets/root.fullstackunicorn.dev/frontend/modules/modals/select/SelectItem.pod.js +1 -1
  38. package/assets/root.fullstackunicorn.dev/frontend/modules/modals/select/SelectPicked.pod.js +1 -1
  39. package/assets/root.fullstackunicorn.dev/frontend/panels/slideshows/Slideshow.pod.js +4 -4
  40. package/assets/root.fullstackunicorn.dev/frontend/templates/cards.js +9 -9
  41. package/assets/root.fullstackunicorn.dev/frontend/templates/page.js +4 -4
  42. package/assets/root.fullstackunicorn.dev/frontend/templates/root.js +1 -1
  43. package/assets/root.fullstackunicorn.dev/manager/modules/pulse.js +22 -0
  44. package/assets/root.fullstackunicorn.dev/manager/server/router.js +11 -1
  45. package/assets/root.fullstackunicorn.dev/workspace/config/workers.json +14 -2
  46. package/index.cmd.help.js +33 -0
  47. package/index.cmd.js +20 -3
  48. package/package.json +2 -1
@@ -17,7 +17,7 @@ add() {
17
17
  yarn add axios --latest
18
18
  yarn add blurhash --latest
19
19
  yarn add jszip --latest
20
- yarn add sharp --latest
20
+ yarn add sharp@0.34.5
21
21
 
22
22
  echo "🚀 [assets] Adding Dev Dependencies"
23
23
 
@@ -83,4 +83,4 @@ if declare -F "$cmd" >/dev/null && [[ "$cmd" != "info" ]]; then
83
83
  else
84
84
  info "$cmd"
85
85
  fi
86
- # ============================================================
86
+ # ============================================================
@@ -1,3 +1,4 @@
1
+ import path from 'path'
1
2
  import { fsa } from '#@/index.dep.js'
2
3
  import { Def } from '#@/index.def.js'
3
4
  import { tools } from '#@/modules/loader.tools.js'
@@ -0,0 +1,22 @@
1
+ class Pulse {
2
+
3
+ get = async () => this.formatDate(new Date())
4
+
5
+ formatDate = date => {
6
+ const parts = new Intl.DateTimeFormat('en-GB', {
7
+ weekday: 'short',
8
+ day: '2-digit',
9
+ month: 'short',
10
+ year: 'numeric',
11
+ hour: '2-digit',
12
+ minute: '2-digit',
13
+ hour12: false,
14
+ timeZone: 'UTC'
15
+ }).formatToParts(date)
16
+
17
+ const value = type => parts.find(part => part.type === type)?.value ?? ''
18
+ return `${value('weekday')} ${value('day')} ${value('month')} ${value('year')} ${value('hour')}:${value('minute')}`
19
+ }
20
+ }
21
+
22
+ export { Pulse }
@@ -1,12 +1,22 @@
1
1
  import { Router } from '#@/index.dep.js'
2
2
  import { middleware } from '#@/server/middleware.js'
3
3
  import { resolver } from '#@/server/resolvers.js'
4
+ import { Pulse } from '#@/modules/pulse.js'
4
5
  import { Loader } from '#@/modules/loader.js'
5
6
  import { Cookies } from '#@/modules/cookies.js'
6
7
  import { Stripe } from '#@/modules/stripe.js'
7
8
 
8
9
  const rs = {}
9
10
 
11
+ // pulse
12
+
13
+ rs.pulse = {}
14
+ rs.pulse.method = 'get'
15
+ rs.pulse.name = 'pulse'
16
+ rs.pulse.path = '/pulse'
17
+ rs.pulse.resolve = async (...args) => await resolver.resolve(new Pulse().get, rs.pulse.path, ...args)
18
+ rs.pulse.funcs = [ rs.pulse.resolve ]
19
+
10
20
  // loader
11
21
 
12
22
  rs.index = {}
@@ -51,10 +51,16 @@ uri.errors.error = `:lang/errors/:message`
51
51
  uri.auth = {}
52
52
  const { env } = constants
53
53
 
54
- uri.auth.client = {}
55
- uri.auth.client.login = `${env.SERVER_URL_AUTH}/auth/login`
56
- uri.auth.client.logout = `${env.SERVER_URL_AUTH}/auth/logout`
57
- uri.auth.client.refresh = `${env.SERVER_URL_AUTH}/auth/refresh`
54
+ uri.auth.gateway = {}
55
+ uri.auth.gateway.login = `${env.SERVER_URL_AUTH}/auth/login`
56
+ uri.auth.gateway.logout = `${env.SERVER_URL_AUTH}/auth/logout`
57
+ uri.auth.gateway.refresh = `${env.SERVER_URL_AUTH}/auth/refresh`
58
+
59
+ uri.auth.bff = {}
60
+ uri.auth.bff.login = `${env.SERVER_URL_BFF}/auth/login`
61
+ uri.auth.bff.logout = `${env.SERVER_URL_BFF}/auth/logout`
62
+ uri.auth.bff.sessionMe = `${env.SERVER_URL_BFF}/session/me`
63
+ uri.auth.bff.bootstrap = `${env.SERVER_URL_BFF}/bootstrap`
58
64
 
59
65
  uri.auth.user = {}
60
66
  uri.auth.user.login = `${env.CLIENT_URL_AUTH}/auth?:type&:token`
@@ -5,17 +5,17 @@
5
5
  "display": "fullscreen",
6
6
  "icons": [
7
7
  {
8
- "src": "/icons/icon-192.png",
8
+ "src": "/get/media/icons/icon-192.png",
9
9
  "sizes": "192x192",
10
10
  "type": "image/png",
11
11
  "purpose": "maskable"
12
12
  },
13
13
  {
14
- "src": "/icons/icon-512.png",
14
+ "src": "/get/media/icons/icon-512.png",
15
15
  "sizes": "512x512",
16
16
  "type": "image/png",
17
17
  "purpose": "maskable"
18
18
  }
19
19
  ],
20
20
  "theme_color": "#ffffff"
21
- }
21
+ }
@@ -1,6 +1,6 @@
1
- import { atom, useAtom, useSetAtom, useGetAtom, makeId } from '#@/imports/npm.js'
2
- import { useNavigateUrl } from '#@/imports/router.js'
3
- import { storage } from '#@/imports/storage.js'
1
+ import { atom, useAtom, useSetAtom, useGetAtom } from '#@/imports/npm.js'
2
+ import { getCurrentHref, useNavigate, useNavigateUrl } from '#@/imports/router.js'
3
+ import { useSetAlerts } from '#@/base/alerts/@use.js'
4
4
  import { uri } from '#@/App.uri.js'
5
5
  import { abs } from '#@/abstracts/abs.js'
6
6
  import { api } from '#@/client/@api.js'
@@ -14,7 +14,7 @@ export const initializeUser = atom(
14
14
  (get) => get(isUserInitialized),
15
15
  async (get, set, value) => {
16
16
 
17
- const userInit = await api.auth.init()
17
+ const userInit = await api.auth.bootstrap()
18
18
  const userInitialized = userInit?.id ? userInit : {}
19
19
 
20
20
  set(user, userInitialized)
@@ -38,16 +38,8 @@ export const useAuthLogin = () => {
38
38
 
39
39
  if (!types.includes(type)) return
40
40
 
41
- const tokenRaw = {}
42
- tokenRaw.nonce = makeId()
43
- tokenRaw.request_type = type
44
- tokenRaw.client_id = env.CLIENT_ID
45
- tokenRaw.protocol = env.PROTOCOL_AUTH
46
-
47
- storage.set(type, tokenRaw.nonce)
48
-
49
- const token = abs.jwt.encode(tokenRaw)
50
- const authLink = F3.fabUrl(uri.auth.user.login, { type, token })
41
+ const returnUrl = encodeURIComponent(getCurrentHref())
42
+ const authLink = `${uri.auth.bff.login}?type=${type}&client_id=${env.CLIENT_ID}&return_url=${returnUrl}`
51
43
 
52
44
  navigateUrl(authLink)
53
45
  }
@@ -58,6 +50,8 @@ export const useAuthLogout = () => {
58
50
 
59
51
  const { lang } = useUrl()
60
52
  const setUser = useSetUser()
53
+ const setAlerts = useSetAlerts()
54
+ const navigate = useNavigate()
61
55
 
62
56
  const authLogout = async () => {
63
57
 
@@ -69,8 +63,7 @@ export const useAuthLogout = () => {
69
63
  navigate(F3.fabUrl(uri.errors, { message, lang }))
70
64
  }
71
65
  else {
72
- storage.remove('accessToken')
73
- storage.remove('refreshToken')
66
+ api.auth.cleanUp()
74
67
  setUser({})
75
68
  }
76
69
  }
@@ -11,8 +11,8 @@ export const AlertPod = ({ close, message, svg, isError }) => {
11
11
 
12
12
  B.color = isError ? c.item_RR : c.item_OR
13
13
 
14
- S.overlay = [s.row_cXsY, s.absolute, s.overflowXYh, s.paddingY96, s.paddingX32, s.XY, s.G1, s.Z15, c.base_NN_B750_40]
15
- S.alert = [s.col_cX, s.X330, s.overflowXYh, s.padding32, s.radius20, c.base_NN_W700]
14
+ S.overlay = [s.row_cXsY, s.positionAbsolute, s.overflowHidden, s.paddingY96, s.paddingX32, s.XY100p, s.G1, s.Z15, c.base_NN_B750_40]
15
+ S.alert = [s.col_cX, s.X330, s.overflowHidden, s.padding32, s.radius20, c.base_NN_W700]
16
16
  S.message = [...F.message, s.row_cXcY, s.textC, s.marginY16, c.item_NN_B400]
17
17
  S.icon = [s.row_cXcY, s.XY40, B.color]
18
18
 
@@ -9,10 +9,10 @@ export const CalloutPod = ({ text, link, linkTo }) => {
9
9
 
10
10
  F.text = [s.fs16, s.lh24, s.fw500]
11
11
 
12
- // S.alpha = [s.col_cXcY, s.absolute, s.bottom0, s.Y64, s.X, c.base_RR]
13
- S.alpha = [s.col_cXcY, s.Y64, s.X, c.base_RR_B400]
12
+ // S.alpha = [s.col_cXcY, s.positionAbsolute, s.bottom0, s.Y64, s.X100p, c.base_RR]
13
+ S.alpha = [s.col_cXcY, s.Y64, s.X100p, c.base_RR_B400]
14
14
  S.link = [s.row_cXcY, s.Xc, ]
15
- S.text = [...F.text, s.textC, s.Xx, c.item_NN_W700]
15
+ S.text = [...F.text, s.textC, s.Xx100p, c.item_NN_W700]
16
16
 
17
17
  return (
18
18
  <View classes={S.alpha}>
@@ -1,4 +1,5 @@
1
1
  import { constants } from '#@/root/constants.js'
2
+ import { getSubmitMetadata } from '#@/imports/device.js'
2
3
 
3
4
  class Tools {
4
5
 
@@ -15,52 +16,7 @@ class Tools {
15
16
  getSubmit = async (device_id) => {
16
17
  const { env } = constants
17
18
 
18
- const battery = navigator.getBattery ? await navigator.getBattery() : {}
19
- const metadataObj = {
20
- timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
21
- language: window.navigator.language,
22
- pageTitle: document.title,
23
- referrer: document.referrer,
24
- pageURL: window.location.href,
25
- platform: window.navigator.platform,
26
- deviceMemory: navigator.deviceMemory,
27
- screenWidth: window.screen.width,
28
- screenHeight: window.screen.height,
29
- colorDepth: window.screen.colorDepth,
30
- maxScreenWidth: window.screen.width * window.devicePixelRatio,
31
- maxScreenHeight: window.screen.height * window.devicePixelRatio,
32
- pixelRatio: window.devicePixelRatio,
33
- screenOrientation: screen?.orientation?.type,
34
- hardwareConcurrency: navigator.hardwareConcurrency,
35
- touchSupport: 'ontouchstart' in window || navigator.maxTouchPoints > 0,
36
- colorGamut: window.matchMedia("(color-gamut: srgb)").matches
37
- ? "srgb"
38
- : window.matchMedia("(color-gamut: p3)").matches
39
- ? "p3"
40
- : window.matchMedia("(color-gamut: rec2020)").matches
41
- ? "rec2020"
42
- : "unknown",
43
- rtt: navigator?.connection?.rtt,
44
- hasGamepad: navigator.getGamepads ? navigator.getGamepads().length > 0 : false,
45
- keyboardEnabled: "onkeydown" in document,
46
- cookieEnabled: navigator.cookieEnabled,
47
- javaEnabled: navigator.javaEnabled ? navigator.javaEnabled() : false,
48
- doNotTrack: navigator.doNotTrack,
49
- networkType: navigator?.connection?.effectiveType,
50
- downlinkSpeed: navigator?.connection?.downlink,
51
- batteryLevel: battery?.level * 100,
52
- batteryCharging: battery?.charging
53
- }
54
-
55
- const metadata = {
56
- submit_timestamp: new Date().toISOString(),
57
- submit_device_id: device_id,
58
- submit_client_id: env.CLIENT_ID,
59
- submit_user_agent: window.navigator.userAgent,
60
- submit_metadata: Object.entries(metadataObj).map(([key, value]) => `${key}:${value ? value : 'unknown'}`).join(" | ")
61
- }
62
-
63
- return metadata
19
+ return await getSubmitMetadata({ clientId: env.CLIENT_ID, deviceId: device_id })
64
20
  }
65
21
  }
66
22
 
@@ -8,8 +8,8 @@ export const HeaderPod = ({ auth, center, back, logo, svg }) => {
8
8
 
9
9
  H.icon = [[c.base_NN_W700]]
10
10
 
11
- S.header = [s.col_sY, s.X, c.base_WW]
12
- S.box = [s.row_cY, s.X, s.Y64]
11
+ S.header = [s.col_sY, s.X100p, c.base_WW]
12
+ S.box = [s.row_cY, s.X100p, s.Y64]
13
13
  S.one = [s.row_sX]
14
14
  S.middle = [s.row_cXcY, s.Xr]
15
15
  S.two = [s.row_eX]
@@ -7,9 +7,9 @@ export const LayoutPod = ({ sidebarTwo, iconTwo,
7
7
 
8
8
  const { s, c, f, t, F, B, S, I, H } = useStyle()
9
9
 
10
- S.root = [s.col, s.X, s.Yc, s.Ymin0]
11
- S.layout = [s.col, s.X, s.Yc, s.Ymin0]
12
- S.body = [s.col_cX, s.X, s.Yc, s.Ymin0, s.overflowXh, c.base_NN_W750]
10
+ S.root = [s.col, s.X100p, s.Yc, s.Ymin0]
11
+ S.layout = [s.col, s.X100p, s.Yc, s.Ymin0]
12
+ S.body = [s.col_cX, s.X100p, s.Yc, s.Ymin0, s.overflowXHidden, c.base_NN_W750]
13
13
 
14
14
  return (
15
15
  <View classes={S.root} inline={I.root}>
@@ -11,7 +11,7 @@ export const IconTwoPod = ({ svg, onPress, isOn }) => {
11
11
 
12
12
  B.isOn = isOn ? s.Z10 : s.Z1
13
13
 
14
- S.iconBox = [s.absolute, s.row_cXcY, s.X48, s.Y64, s.end0, B.isOn]
14
+ S.iconBox = [s.positionAbsolute, s.row_cXcY, s.X48, s.Y64, s.end0, B.isOn]
15
15
  S.icon = [s.XY40, s.marginX4, s.marginY12, s.radius32, c.item_NN_B600]
16
16
 
17
17
  return (
@@ -8,11 +8,11 @@ export const SidebarTwoPod = ({ isClosed, menu, onPress }) => {
8
8
 
9
9
  const { s, c, f, t, F, B, S, I, H } = useStyle()
10
10
 
11
- S.overlay = [s.col, s.absolute, s.overflowXYh, s.X, s.Y, s.Z4, s.flex1]
11
+ S.overlay = [s.col, s.positionAbsolute, s.overflowHidden, s.X100p, s.Y100p, s.Z4, s.flex1]
12
12
  S.main = [s.row_sX_r, s.Xc, s.Yc,]
13
13
  S.external = [s.col, s.Xmax320, s.G100, s.paddingX8, c.base_WW]
14
14
  S.header = [s.col_cY, s.Y64, s.paddingX4, s.Xc, c.base_WW]
15
- S.bodyExt = [s.col, s.Yc, s.X, s.paddingX4]
15
+ S.bodyExt = [s.col, s.Yc, s.X100p, s.paddingX4]
16
16
  S.space = [s.row, s.Xmin16, s.XYr]
17
17
 
18
18
  return (
@@ -11,6 +11,7 @@ class Tools {
11
11
  if (user.isOffline) setAlerts({ id: 'offline', onClose: () => setIsAuthRun(true) })
12
12
  else if (user.isError) navigate(`/errors/${user.error || 'login-failed'}`)
13
13
  else {
14
+ api.auth.cleanUp()
14
15
  setUser(user)
15
16
  navigate('/user')
16
17
  }
@@ -108,4 +109,4 @@ class Tools {
108
109
  }
109
110
  }
110
111
 
111
- export const tools = new Tools()
112
+ export const tools = new Tools()
@@ -15,8 +15,8 @@ export const ModalPod = ({ children, title, svg, actions, isCloseDisabled, style
15
15
  B.isMax = style.isMax ? [s.Xr, s.Xmax600] : [s.Xr]
16
16
  B.margin = style.margin
17
17
 
18
- S.overlay = [s.row_cXcY, s.absolute, s.overflowXYh, s.paddingX16, s.XY, s.G1, s.Z10, c.base_NN_B750_40]
19
- S.modal = [s.col, s.Yr, s.Ymin0, s.overflowXYh, s.paddingX20, s.radius20, s.marginY16, ...B.isMax, ...B.margin, c.base_NN_W700]
18
+ S.overlay = [s.row_cXcY, s.positionAbsolute, s.overflowHidden, s.paddingX16, s.XY100p, s.G1, s.Z10, c.base_NN_B750_40]
19
+ S.modal = [s.col, s.Yr, s.Ymin0, s.overflowHidden, s.paddingX20, s.radius20, s.marginY16, ...B.isMax, ...B.margin, c.base_NN_W700]
20
20
  S.layout = [s.col, s.XYc, s.Ymin0]
21
21
  S.header = [s.row_cXcY, s.Xr, s.Y40, s.marginY20]
22
22
  S.icon = [s.XY32, s.margin4, c.item_NN_B400]
@@ -13,9 +13,9 @@ export const ModalPopupPod = ({ children, title, svg, actions, isCloseDisabled,
13
13
 
14
14
  B.disabled = isCloseDisabled ? c.item_NN_B600_30 : c.item_NN_B600
15
15
 
16
- S.overlay = [s.row_cXcY, s.absolute, s.overflowXYh, s.paddingX16, s.XY, s.G1, s.Z10, c.base_NN_B750_40]
17
- S.modal = [s.col, s.Xx360, s.Yy360, s.overflowXYh, s.paddingX20, s.radius20, s.marginY16, c.base_NN_W700]
18
- S.layout = [s.col, s.X, s.Y]
16
+ S.overlay = [s.row_cXcY, s.positionAbsolute, s.overflowHidden, s.paddingX16, s.XY100p, s.G1, s.Z10, c.base_NN_B750_40]
17
+ S.modal = [s.col, s.Xx360, s.Yy360, s.overflowHidden, s.paddingX20, s.radius20, s.marginY16, c.base_NN_W700]
18
+ S.layout = [s.col, s.X100p, s.Y100p]
19
19
  S.header = [s.row_cXcY, s.Xr, s.Y40, s.marginY20]
20
20
  S.icon = [s.XY32, s.margin4, c.item_NN_B400]
21
21
  S.iconCancel = [s.XY32, s.margin4, B.disabled]
@@ -8,9 +8,23 @@ import { storage } from '#@/imports/storage'
8
8
  class Auth {
9
9
 
10
10
  config = { headers: { 'Content-Type': 'application/json' } }
11
+ sessionConfig = { headers: { 'Content-Type': 'application/json' }, withCredentials: true }
11
12
  env = constants.env
12
13
 
13
14
  getUser = (token = {}) => ({ id: token.sub, logo: token.logo })
15
+ getSessionUser = (payload = {}) => ({ id: payload?.user?.id, logo: payload?.user?.logo })
16
+ getBootstrapUser = (payload = {}) => {
17
+ const user = this.getSessionUser(payload)
18
+ return {
19
+ ...user,
20
+ bootstrap: payload?.bootstrap || {},
21
+ permissions: payload?.permissions || [],
22
+ groups: payload?.groups || [],
23
+ entities: payload?.entities || {},
24
+ client: payload?.client || null,
25
+ features: payload?.features || {}
26
+ }
27
+ }
14
28
 
15
29
  loginOps = ['login', 'signup']
16
30
 
@@ -25,17 +39,9 @@ class Auth {
25
39
 
26
40
  const nonce = storage.get(type)
27
41
 
28
- // const isValid = nonce === token.nonce
29
- // if (!isValid) throw new Error('abort')
30
-
31
- // const rawToken = {}
32
- // rawToken.authcode = token.authcode
33
- // // rawToken.nonce = nonce
34
- // rawToken.client_id = env.CLIENT_ID
35
-
36
42
  const config = this.config
37
43
  const data = { token: token_encoded, nonce }
38
- const endpoint = uri.auth.client.login
44
+ const endpoint = uri.auth.gateway.login
39
45
 
40
46
  const response = await client.post(endpoint, data, config)
41
47
 
@@ -50,38 +56,45 @@ class Auth {
50
56
 
51
57
  return this.getUser(response.access_token)
52
58
 
53
- } catch (error) {
59
+ } catch (error) {
54
60
  console.log("error", error)
55
- return err.cleanup(() => storage.remove(type), { isError: true }) }
61
+ return err.cleanup(() => storage.remove(type), { isError: true })
62
+ }
56
63
  }
57
64
 
58
65
  refresh = async (refresh_token) => {
59
66
 
60
67
  const config = this.config
61
68
  const data = { refresh_token, client_id: this.env.CLIENT_ID }
62
- const endpoint = uri.auth.client.refresh
69
+ const endpoint = uri.auth.gateway.refresh
63
70
 
64
71
  return await client.post(endpoint, data, config)
65
72
 
66
73
  }
67
74
 
68
75
  logout = async () => {
76
+ const endpoint = uri.auth.bff.logout
77
+ const response = await client.post(endpoint, {}, this.sessionConfig)
78
+ return response?.isLogout ? response : { isLogout: true }
69
79
 
70
- const refresh_token = storage.get('refreshToken') || ''
71
- const access_token = storage.get('accessToken') || ''
72
-
73
- if (!refresh_token && !access_token) return { isLogout: true }
74
-
75
- const config = this.config
76
- const data = { access_token, refresh_token, client_id: this.env.CLIENT_ID }
77
- const endpoint = uri.auth.client.logout
78
-
79
- const response = await client.post(endpoint, data, config)
80
+ }
80
81
 
81
- const isLogout = response.access_token && response.refresh_token
82
+ bootstrap = async () => {
83
+ try {
84
+ const response = await client.data({
85
+ key: uri.auth.bff.bootstrap,
86
+ method: 'get',
87
+ endpoint: uri.auth.bff.bootstrap,
88
+ config: this.sessionConfig
89
+ }, true)
82
90
 
83
- return isLogout || response
91
+ if (response.isOffline) return { isOffline: true }
92
+ if (response.isError) throw new Error('is-logout')
93
+ if (!response?.user?.id) throw new Error('is-logout')
84
94
 
95
+ this.cleanUp()
96
+ return this.getBootstrapUser(response)
97
+ } catch (error) { return { isLogout: true } }
85
98
  }
86
99
 
87
100
  handleAccessToken = (accessToken) => {
@@ -156,57 +169,30 @@ class Auth {
156
169
  init = async () => {
157
170
 
158
171
  try {
172
+ const bootstrapped = await this.bootstrap()
173
+ if (bootstrapped?.id || bootstrapped?.isOffline) return bootstrapped
159
174
 
160
- const accessToken = storage.get('accessToken')
161
- if (!accessToken) throw new Error('is-logout')
162
-
163
- const refreshToken = storage.get('refreshToken')
164
- if (!refreshToken) throw new Error('is-logout')
175
+ const response = await client.data({
176
+ key: uri.auth.bff.sessionMe,
177
+ method: 'get',
178
+ endpoint: uri.auth.bff.sessionMe,
179
+ config: this.sessionConfig
180
+ }, true)
165
181
 
166
- let access
167
-
168
- access = this.handleAccessToken(accessToken)
169
- if (access.decoded?.sub) return this.getUser(access.decoded)
170
-
171
- access = await this.handleRefreshToken(refreshToken)
172
- if (access.decoded?.sub) return this.getUser(access.decoded)
173
-
174
- if (access.isOffline) {
175
- const user = this.getUserOffline(accessToken)
176
- if (user.id) return user
177
- new Error('is-logout')
178
- }
182
+ if (response.isOffline) return { isOffline: true }
183
+ if (response.isError) throw new Error('is-logout')
184
+ if (!response?.user?.id) throw new Error('is-logout')
179
185
 
180
- throw new Error('is-logout')
186
+ this.cleanUp()
187
+ return this.getSessionUser(response)
181
188
 
182
- } catch (error) {
189
+ } catch (error) {
183
190
  return { isLogout: true }
184
- // return err.cleanup(this.cleanUp, { isLogout: true })
185
191
  }
186
192
  }
187
193
 
188
194
  getAccessToken = async () => {
189
-
190
- try {
191
-
192
- const accessToken = storage.get('accessToken')
193
- if (!accessToken) throw new Error('is-logout')
194
-
195
- const refreshToken = storage.get('refreshToken')
196
- if (!refreshToken) throw new Error('is-logout')
197
-
198
- let access
199
-
200
- access = this.handleAccessToken(accessToken)
201
- if (access.token) return { accessToken: access.token }
202
-
203
- access = await this.handleRefreshToken(refreshToken)
204
- if (access.token) return { accessToken: access.token }
205
-
206
- if (access.isOffline) return { isOffline: true }
207
- throw new Error('is-logout')
208
-
209
- } catch (error) { return err.cleanup(this.cleanUp, { isLogout: true }) }
195
+ return { isLogout: true }
210
196
  }
211
197
  }
212
198
 
@@ -30,12 +30,13 @@ class Statics {
30
30
  return response
31
31
  }
32
32
 
33
- image = async (path, type) => {
33
+ image = async (path, type, config = {}) => {
34
34
 
35
35
  const payload = {}
36
36
  payload.method = 'get'
37
37
  payload.endpoint = path
38
38
  payload.key = abs.makeKey(payload.endpoint, payload.method)
39
+ payload.config = config
39
40
 
40
41
  const response = await client.image(payload, type)
41
42
 
@@ -44,4 +45,4 @@ class Statics {
44
45
  }
45
46
  }
46
47
 
47
- export const statics = new Statics()
48
+ export const statics = new Statics()
@@ -4,5 +4,6 @@
4
4
  "CLIENT_ID": "clientxx-xxxx-4xxx-8xxx-xxxxxxxxxxxx",
5
5
  "CLIENT_URL_AUTH": "https://auth.minderable.com",
6
6
  "CLIENT_URL_ACCOUNT": "https://account.minderable.com",
7
+ "SERVER_URL_BFF": "http://localhost:4820",
7
8
  "SERVER_URL_AUTH": "https://api.auth.minderable.com"
8
9
  }
@@ -4,5 +4,6 @@
4
4
  "CLIENT_ID": "clientxx-xxxx-4xxx-8xxx-xxxxxxxxxxxx",
5
5
  "CLIENT_URL_AUTH": "https://auth.minderable.com",
6
6
  "CLIENT_URL_ACCOUNT": "https://account.minderable.com",
7
+ "SERVER_URL_BFF": "https://bff.minderable.com",
7
8
  "SERVER_URL_AUTH": "https://api.auth.minderable.com"
8
9
  }
@@ -56,9 +56,9 @@ export const ControlButton = ({ onPress = () => { }, classes = [], children }) =
56
56
  onMouseUp={() => setIsPressed(false)}
57
57
  onMouseLeave={() => setIsPressed(false)}
58
58
  style={containerStyle}
59
- className={[...classes, s.relative].join(' ')}
59
+ className={[...classes, s.positionRelative].join(' ')}
60
60
  >
61
- <div className={[...classes, s.relative].join(' ')} style={iconStyle}>
61
+ <div className={[...classes, s.positionRelative].join(' ')} style={iconStyle}>
62
62
  {children}
63
63
  </div>
64
64
  </div>
@@ -13,7 +13,7 @@ export const Crossfader = ({ isActive, children, transitionMs = 600, instantMoun
13
13
 
14
14
  const { s, c, f, t, F, B, S, I, H } = useStyle()
15
15
 
16
- S.box = [s.absolute, s.XY, s.noSelect]
16
+ S.box = [s.positionAbsolute, s.XY100p, s.noSelect]
17
17
 
18
18
  I.box = {
19
19
  width: '100%',
@@ -7,7 +7,7 @@ export const HoverCard = ({ children, classes = [] }) => {
7
7
 
8
8
  const [isHover, setIsHover] = useState(false)
9
9
 
10
- S.box = [s.relative, s.radius24, s.overflowXYh, ...classes]
10
+ S.box = [s.positionRelative, s.radius24, s.overflowHidden, ...classes]
11
11
 
12
12
  I.box = {
13
13
  transition: 'transform 240ms cubic-bezier(0.2, 0, 0, 1), box-shadow 240ms cubic-bezier(0.2, 0, 0, 1)',