-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinit.ts
182 lines (148 loc) · 5.7 KB
/
init.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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
import { Runtime } from "./runtime/runtime.ts";
import { Pointer } from "./runtime/pointers.ts";
import { LOCAL_ENDPOINT } from "./types/addressing.ts";
import { client_type } from "./utils/constants.ts";
import { Storage, registerStorageAsPointerSource } from "./storage/storage.ts";
import { logger, projectRootURL } from "./utils/global_values.ts";
import { IndexedDBStorageLocation } from "./storage/storage-locations/indexed-db.ts";
import { LocalStorageLocation } from "./storage/storage-locations/local-storage.ts";
import { loadEternalValues } from "./utils/eternals.ts";
import { DX_BOUND_LOCAL_SLOT } from "./runtime/constants.ts";
import { verboseArg } from "./utils/logger.ts";
import { MessageLogger } from "./utils/message_logger.ts";
import { Path } from "./utils/path.ts";
import { communicationHub } from "./network/communication-hub.ts";
import { LocalLoopbackInterface } from "./network/communication-interfaces/local-loopback-interface.ts";
import { Crypto } from "./runtime/crypto.ts";
let initialized = false;
/**
* Runtime init (sets ENV, storage, endpoint, ...)
*/
export async function init() {
if (initialized) return;
initialized = true;
// register DatexStorage as pointer source
registerStorageAsPointerSource();
// bind communication hub handlers to runtime
communicationHub.handler.init()
communicationHub.handler.setDatexInHandler(Runtime.datexIn.bind(Runtime))
Runtime.setDatexOutHandler(communicationHub.handler.datexOut.bind(communicationHub.handler))
await communicationHub.addInterface(new LocalLoopbackInterface())
// @ts-ignore NO_INIT
if (!globalThis.NO_INIT) {
// custom storage module (storage.ts next to .dx config)
let storageInitModule: Path|undefined
if (client_type == "browser") {
// TODO: handle storage.ts URL in browser
// storageInitModule = new URL('/storage.ts', globalThis.location.href)
}
else if (client_type == "deno") {
// TODO: dynamic storage.ts location - use uix path backend/storage.ts as workaround
storageInitModule = new Path('./backend/storage.ts', projectRootURL)
}
if (await storageInitModule?.fsExists()) {
logger.info("Initializing custom storage configuration (" + storageInitModule!.toString() + ")")
try {
await import(storageInitModule!.toString());
}
catch (e) {
console.error(e)
}
if (Storage.locations.size === 0)
logger.warn(`No storage location was added in storage.ts - cannot store persistent data!`)
}
else if (client_type == "browser") {
await Storage.addLocation(new IndexedDBStorageLocation(), {
modes: [Storage.Mode.SAVE_ON_CHANGE, Storage.Mode.SAVE_PERIODICALLY],
primary: true
})
await Storage.addLocation(new LocalStorageLocation(), {
modes: [Storage.Mode.SAVE_ON_EXIT],
primary: false
})
}
else if (client_type == "deno") {
if (Deno.env.get("SQLITE_STORAGE") == "1") {
const { SqliteStorageLocation } = await import("./storage/storage-locations/sqlite-db.ts" /* lazy */);
await Storage.addLocation(new SqliteStorageLocation({
db: "storage"
}), {
modes: [Storage.Mode.SAVE_ON_CHANGE],
primary: true
})
}
else {
await Storage.addLocation(new LocalStorageLocation(), {
modes: [Storage.Mode.SAVE_ON_EXIT, Storage.Mode.SAVE_ON_CHANGE],
primary: true
})
}
}
}
// listen for endpoint changes
Runtime.onEndpointChanged((endpoint) => {
Pointer.pointer_prefix = endpoint.getPointerPrefix();
// has only local endpoint id (%0000) or global id?
if (endpoint != LOCAL_ENDPOINT) {
Pointer.is_local = false;
// update storage entries that contain pointers with unresolved @@local origin
Storage.updateEntriesWithUnresolvedLocalDependencies();
}
else Pointer.is_local = true;
})
// enable periodic pointer subscriber cleanup
Pointer.enablePeriodicSubscriberCleanup();
// set runtime endpoint
Runtime._setEndpoint(LOCAL_ENDPOINT)
// precompiled dxb
await Runtime.precompile();
// set Runtime ENV (not persistent if globalThis.NO_INIT)
Runtime.ENV = (globalThis as any).NO_INIT ? getDefaultEnv() : await Storage.loadOrCreate("Datex.Runtime.ENV", getDefaultEnv);
(Runtime.ENV as any)[DX_BOUND_LOCAL_SLOT] = "env"
// workaround, should never happen
if (!Runtime.ENV) {
logger.error("Runtime ENV is undefined");
Runtime.ENV = getDefaultEnv()
}
// add environment variables to #env (might override existing env settings (LANG))
if (client_type === "deno") {
for (const [key, val] of Object.entries(Deno.env.toObject())) {
if (key == "LANG") {
let lang = val.split("-")[0]?.split("_")[0];
if (lang == "C" || lang?.startsWith("C.")) lang = "en";
Runtime.ENV[key] = lang;
}
else Runtime.ENV[key] = val;
}
}
Runtime.ENV.DATEX_VERSION = Runtime.VERSION;
function getDefaultEnv() {
return {
LANG: globalThis.localStorage?.lang as string ?? globalThis?.navigator?.language?.split("-")[0]?.split("_")[0] ?? 'en',
DATEX_VERSION: ""
}
}
// init persistent memory
Runtime.persistent_memory = (await Storage.loadOrCreate("Datex.Runtime.MEMORY", ()=>new Map())).setAutoDefault(Object);
if (!(globalThis as any).NO_INIT) {
Runtime.init();
// @ts-ignore
globalThis.print = Runtime.STD_STATIC_SCOPE.print
// @ts-ignore
globalThis.printf = Runtime.STD_STATIC_SCOPE.printf
// @ts-ignore
globalThis.printn = Runtime.STD_STATIC_SCOPE.printn
}
// @ts-ignore NO_INIT
if (!globalThis.NO_INIT) await loadEternalValues();
// enables message logger when running with -v
if (verboseArg) MessageLogger.enable();
if (client_type == "deno" && !(globalThis as any).NO_INIT) {
const { clear } = await import("./utils/args.ts" /*lazy*/);
if (clear) {
await Storage.clearAndReload();
}
}
// init cleanup interval to remove crypto entries (endpoint keyss)
Crypto.initCleanup();
}