forked from hplush/slowreader
-
Notifications
You must be signed in to change notification settings - Fork 0
/
environment.ts
120 lines (101 loc) · 2.96 KB
/
environment.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import type { ClientOptions } from '@logux/client'
import type { TranslationLoader } from '@nanostores/i18n'
import {
type PersistentEvents,
type PersistentStore,
setPersistentEngine
} from '@nanostores/persistent'
import type { ReadableAtom, StoreValue } from 'nanostores'
import { SlowReaderError } from './error.js'
import type { BaseRouter, Route, Routes } from './router.js'
interface LogStoreCreator {
(): ClientOptions['store']
}
export type NetworkType = 'free' | 'paid' | 'unknown' | undefined
export interface NetworkTypeDetector {
(): {
saveData: boolean | undefined
type: NetworkType
}
}
type NormalizeParams<Params> = {
[K in keyof Params]: Params[K] extends number ? Params[K] : string
}
type RouterRoutes<Router extends BaseRouter> = {
[R in Exclude<StoreValue<Router>, undefined> as R['route']]: R['params']
}
type ExactType<Good, A, B> = A extends B ? (B extends A ? Good : never) : never
type ValidateRouter<Router extends BaseRouter> = ExactType<
Router,
NormalizeParams<RouterRoutes<Router>>,
NormalizeParams<Routes>
>
interface EnvironmentListener {
(env: Environment): (() => void)[] | (() => void) | void
}
interface ErrorEvents {
addEventListener(
event: 'unhandledrejection',
listener: (event: { reason: unknown }) => void
): void
}
export interface Environment {
baseRouter: BaseRouter
errorEvents: ErrorEvents
locale: ReadableAtom<string>
logStoreCreator: LogStoreCreator
networkType: NetworkTypeDetector
openRoute(page: Route): void
restartApp: () => void
translationLoader: TranslationLoader
}
export type EnvironmentAndStore = Environment & {
persistentEvents: PersistentEvents
persistentStore: PersistentStore
}
let currentEnvironment: Environment | undefined
let listeners: EnvironmentListener[] = []
let unbinds: ((() => void) | void)[] = []
export function onEnvironment(ch: EnvironmentListener): void {
if (currentEnvironment) {
let unbind = ch(currentEnvironment)
if (Array.isArray(unbind)) {
unbinds.push(...unbind)
} else {
unbinds.push(unbind)
}
}
listeners.push(ch)
}
export function setupEnvironment<Router extends BaseRouter>(
env: EnvironmentAndStore & {
baseRouter: ValidateRouter<Router>
}
): void {
for (let unbind of unbinds) unbind?.()
setPersistentEngine(env.persistentStore, env.persistentEvents)
currentEnvironment = {
baseRouter: env.baseRouter,
errorEvents: env.errorEvents,
locale: env.locale,
logStoreCreator: env.logStoreCreator,
networkType: env.networkType,
openRoute: env.openRoute,
restartApp: env.restartApp,
translationLoader: env.translationLoader
}
for (let listener of listeners) {
let unbind = listener(currentEnvironment)
if (Array.isArray(unbind)) {
unbinds.push(...unbind)
} else {
unbinds.push(unbind)
}
}
}
export function getEnvironment(): Environment {
if (!currentEnvironment) {
throw new SlowReaderError('NoEnvironment')
}
return currentEnvironment
}