@geexcode/geex-angular 0.0.33 → 0.0.35

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/dist/index.d.mts CHANGED
@@ -105,7 +105,7 @@ interface UiModule extends GeexModule {
105
105
  declare const ExtensionModule: Record<string, any> & {};
106
106
  type ExtensionModule = typeof ExtensionModule;
107
107
  type GeexModules<TExtensionModules extends ExtensionModule = ExtensionModule> = {
108
- init(): Promise<{
108
+ init(force?: boolean): Promise<{
109
109
  [K in keyof GeexModules<TExtensionModules>]: any;
110
110
  }>;
111
111
  tenant: TenantModule;
@@ -120,8 +120,9 @@ type GeexModule<TExtension = ExtensionModule> = {
120
120
  * A module combines both reactive state (signals) and business logic methods.
121
121
  * Concrete modules can extend this interface to expose their own signals & methods.
122
122
  * This empty base exists mainly for typing convenience and future extension.
123
+ * @param force - If true, forces re-initialization even if already initialized. Defaults to false.
123
124
  */
124
- init: () => Promise<any>;
125
+ init: (force?: boolean) => Promise<any>;
125
126
  } & TExtension;
126
127
  declare function createTenantModule(injector: Injector): TenantModule;
127
128
  declare function createAuthModule(injector: Injector): AuthModule;
package/dist/index.d.ts CHANGED
@@ -105,7 +105,7 @@ interface UiModule extends GeexModule {
105
105
  declare const ExtensionModule: Record<string, any> & {};
106
106
  type ExtensionModule = typeof ExtensionModule;
107
107
  type GeexModules<TExtensionModules extends ExtensionModule = ExtensionModule> = {
108
- init(): Promise<{
108
+ init(force?: boolean): Promise<{
109
109
  [K in keyof GeexModules<TExtensionModules>]: any;
110
110
  }>;
111
111
  tenant: TenantModule;
@@ -120,8 +120,9 @@ type GeexModule<TExtension = ExtensionModule> = {
120
120
  * A module combines both reactive state (signals) and business logic methods.
121
121
  * Concrete modules can extend this interface to expose their own signals & methods.
122
122
  * This empty base exists mainly for typing convenience and future extension.
123
+ * @param force - If true, forces re-initialization even if already initialized. Defaults to false.
123
124
  */
124
- init: () => Promise<any>;
125
+ init: (force?: boolean) => Promise<any>;
125
126
  } & TExtension;
126
127
  declare function createTenantModule(injector: Injector): TenantModule;
127
128
  declare function createAuthModule(injector: Injector): AuthModule;
package/dist/index.js CHANGED
@@ -61,6 +61,37 @@ var import_graphql_tag = __toESM(require("graphql-tag"));
61
61
  var import_rxjs = require("rxjs");
62
62
  var import_operators = require("rxjs/operators");
63
63
  var import_rxjs_interop = require("@angular/core/rxjs-interop");
64
+ function wrapSignal(originalSignal, getInitPromise, timeout = 5e3) {
65
+ const checkInit = () => {
66
+ const initPromise = getInitPromise();
67
+ const timeoutPromise = new Promise(
68
+ (_, reject) => setTimeout(() => reject(new Error(`Module initialization timeout after ${timeout}ms`)), timeout)
69
+ );
70
+ return Promise.race([initPromise, timeoutPromise]);
71
+ };
72
+ let isWaiting = false;
73
+ let waitPromise = null;
74
+ const wrapped = (() => {
75
+ const promise = getInitPromise();
76
+ if (promise._completed) {
77
+ return originalSignal();
78
+ }
79
+ if (!isWaiting) {
80
+ isWaiting = true;
81
+ waitPromise = checkInit().finally(() => {
82
+ isWaiting = false;
83
+ waitPromise = null;
84
+ });
85
+ }
86
+ throw new Error(
87
+ "Signal accessed before module initialization completed. Please await module.init() or geex.init() before accessing signals."
88
+ );
89
+ });
90
+ wrapped.set = originalSignal.set.bind(originalSignal);
91
+ wrapped.update = originalSignal.update.bind(originalSignal);
92
+ wrapped.asReadonly = originalSignal.asReadonly.bind(originalSignal);
93
+ return wrapped;
94
+ }
64
95
  var LoginProviderEnum = {
65
96
  Local: "Local"
66
97
  };
@@ -127,20 +158,34 @@ var GQL_ON_PUBLIC_NOTIFY = import_graphql_tag.default`subscription onPublicNotif
127
158
  var GQL_ORGS_CACHE = import_graphql_tag.default`query orgsCache { orgs(take: 999) { items { id orgType code name parentOrgCode } } }`;
128
159
  var GQL_INIT_SETTINGS = import_graphql_tag.default`query initSettings { initSettings { id name value } }`;
129
160
  function createTenantModule(injector) {
130
- const current = (0, import_core.signal)(null);
161
+ const _current = (0, import_core.signal)(null);
162
+ let _initPromise = Promise.resolve();
163
+ _initPromise._completed = false;
131
164
  const module2 = {
132
- init: async () => {
133
- try {
134
- const tenantCode = injector.get(import_util.CookieService).get("__tenant");
135
- if (tenantCode) {
136
- const tenantData = await module2.loadTenantData(tenantCode);
137
- current.set(tenantData ?? null);
138
- }
139
- } catch (err) {
140
- console.error(err);
165
+ init: async (force = false) => {
166
+ if (_initPromise._completed && !force) {
167
+ return;
141
168
  }
169
+ if (force) {
170
+ _initPromise._completed = false;
171
+ }
172
+ _initPromise = (async () => {
173
+ try {
174
+ const tenantCode = injector.get(import_util.CookieService).get("__tenant");
175
+ if (tenantCode) {
176
+ const tenantData = await module2.loadTenantData(tenantCode);
177
+ _current.set(tenantData ?? null);
178
+ }
179
+ } catch (err) {
180
+ console.error(err);
181
+ throw err;
182
+ } finally {
183
+ _initPromise._completed = true;
184
+ }
185
+ })();
186
+ return _initPromise;
142
187
  },
143
- current,
188
+ current: wrapSignal(_current, () => _initPromise),
144
189
  async loadTenantData(code) {
145
190
  const res = await (0, import_rxjs.firstValueFrom)(
146
191
  injector.get(import_apollo_angular.Apollo).mutate({ mutation: GQL_CHECK_TENANT, variables: { code } })
@@ -164,24 +209,31 @@ function createTenantModule(injector) {
164
209
  return module2;
165
210
  }
166
211
  function createAuthModule(injector) {
167
- const user = (0, import_core.signal)(null);
168
- let _initPromise = null;
212
+ const _user = (0, import_core.signal)(null);
213
+ let _initPromise = Promise.resolve();
214
+ _initPromise._completed = false;
169
215
  const module2 = {
170
- init: () => {
171
- if (_initPromise) {
172
- return _initPromise;
216
+ init: async (force = false) => {
217
+ if (_initPromise._completed && !force) {
218
+ return;
219
+ }
220
+ if (force) {
221
+ _initPromise._completed = false;
173
222
  }
174
223
  _initPromise = (async () => {
175
224
  try {
176
225
  const userData = await module2.loadUserData();
177
- user.set(userData ?? null);
226
+ _user.set(userData ?? null);
178
227
  } catch (err) {
179
228
  console.error(err);
229
+ throw err;
230
+ } finally {
231
+ _initPromise._completed = true;
180
232
  }
181
233
  })();
182
234
  return _initPromise;
183
235
  },
184
- user,
236
+ user: wrapSignal(_user, () => _initPromise),
185
237
  async loadUserData() {
186
238
  const oAuthService = injector.get(import_angular_oauth2_oidc.OAuthService);
187
239
  try {
@@ -210,51 +262,92 @@ function createAuthModule(injector) {
210
262
  return module2;
211
263
  }
212
264
  function createIdentityModule(injector) {
213
- const orgsSignal = (0, import_core.signal)([]);
214
- const userOwnedOrgsSignal = (0, import_core.signal)([]);
265
+ const _orgsSignal = (0, import_core.signal)([]);
266
+ const _userOwnedOrgsSignal = (0, import_core.signal)([]);
267
+ let _initPromise = Promise.resolve();
268
+ _initPromise._completed = false;
215
269
  const module2 = {
216
- orgs: orgsSignal,
217
- userOwnedOrgs: userOwnedOrgsSignal,
218
- async init() {
219
- try {
220
- const orgs$ = injector.get(import_apollo_angular.Apollo).watchQuery({ query: GQL_ORGS_CACHE }).valueChanges.pipe((0, import_rxjs.map)((res) => (0, import_util.deepCopy)(res.data.orgs.items)));
221
- orgs$.subscribe((orgs) => {
222
- (0, import_core.runInInjectionContext)(injector, () => {
223
- orgsSignal.set(orgs);
224
- const userData = geex.auth.user();
225
- let allOwned = [];
226
- if (orgs?.length && userData) {
227
- if (userData.id === "000000000000000000000001") {
228
- allOwned = (0, import_util.deepCopy)(orgs);
229
- } else {
230
- const ownedCodes = userData.orgs.map((x) => x.code);
231
- allOwned = orgs.filter((o) => ownedCodes.some((code) => o.code.startsWith(code)));
270
+ orgs: wrapSignal(_orgsSignal, () => _initPromise),
271
+ userOwnedOrgs: wrapSignal(_userOwnedOrgsSignal, () => _initPromise),
272
+ async init(force = false) {
273
+ if (_initPromise._completed && !force) {
274
+ return;
275
+ }
276
+ if (force) {
277
+ _initPromise._completed = false;
278
+ }
279
+ _initPromise = (async () => {
280
+ try {
281
+ await new Promise((resolve, reject) => {
282
+ const orgs$ = injector.get(import_apollo_angular.Apollo).watchQuery({ query: GQL_ORGS_CACHE }).valueChanges.pipe((0, import_rxjs.map)((res) => (0, import_util.deepCopy)(res.data.orgs.items)));
283
+ let isFirstEmit = true;
284
+ orgs$.subscribe({
285
+ next: (orgs) => {
286
+ (0, import_core.runInInjectionContext)(injector, () => {
287
+ _orgsSignal.set(orgs);
288
+ const userData = geex.auth.user();
289
+ let allOwned = [];
290
+ if (orgs?.length && userData) {
291
+ if (userData.id === "000000000000000000000001") {
292
+ allOwned = (0, import_util.deepCopy)(orgs);
293
+ } else {
294
+ const ownedCodes = userData.orgs.map((x) => x.code);
295
+ allOwned = orgs.filter((o) => ownedCodes.some((code) => o.code.startsWith(code)));
296
+ }
297
+ }
298
+ _userOwnedOrgsSignal.set(allOwned);
299
+ if (isFirstEmit) {
300
+ isFirstEmit = false;
301
+ resolve();
302
+ }
303
+ });
304
+ },
305
+ error: (err) => {
306
+ console.error(err);
307
+ reject(err);
232
308
  }
233
- }
234
- userOwnedOrgsSignal.set(allOwned);
309
+ });
235
310
  });
236
- });
237
- } catch (error) {
238
- console.error(error);
239
- }
311
+ } catch (error) {
312
+ console.error(error);
313
+ throw error;
314
+ } finally {
315
+ _initPromise._completed = true;
316
+ }
317
+ })();
318
+ return _initPromise;
240
319
  }
241
320
  };
242
321
  return module2;
243
322
  }
244
323
  function createMessagingModule(injector) {
324
+ let _initPromise = Promise.resolve();
325
+ _initPromise._completed = false;
245
326
  const module2 = {
246
- async init() {
247
- try {
248
- await geex.auth.init();
249
- if (injector.get(import_angular_oauth2_oidc.OAuthService).hasValidAccessToken()) {
250
- const subClient = injector.get(import_apollo_angular.Apollo).use("subscription");
251
- subClient.subscribe({ query: GQL_ON_PUBLIC_NOTIFY }).pipe((0, import_rxjs.map)((res) => res?.data?.onPublicNotify)).subscribe((notify) => {
252
- module2.onPublicNotify(notify);
253
- });
254
- }
255
- } catch (err) {
256
- console.error(err);
327
+ async init(force = false) {
328
+ if (_initPromise._completed && !force) {
329
+ return;
257
330
  }
331
+ if (force) {
332
+ _initPromise._completed = false;
333
+ }
334
+ _initPromise = (async () => {
335
+ try {
336
+ await geex.auth.init();
337
+ if (injector.get(import_angular_oauth2_oidc.OAuthService).hasValidAccessToken()) {
338
+ const subClient = injector.get(import_apollo_angular.Apollo).use("subscription");
339
+ subClient.subscribe({ query: GQL_ON_PUBLIC_NOTIFY }).pipe((0, import_rxjs.map)((res) => res?.data?.onPublicNotify)).subscribe((notify) => {
340
+ module2.onPublicNotify(notify);
341
+ });
342
+ }
343
+ } catch (err) {
344
+ console.error(err);
345
+ throw err;
346
+ } finally {
347
+ _initPromise._completed = true;
348
+ }
349
+ })();
350
+ return _initPromise;
258
351
  },
259
352
  onPublicNotify(notify) {
260
353
  console.log("Public notify", notify);
@@ -263,31 +356,63 @@ function createMessagingModule(injector) {
263
356
  return module2;
264
357
  }
265
358
  function createSettingsModule(injector) {
266
- const settingsSignal = (0, import_core.signal)([]);
359
+ const _settingsSignal = (0, import_core.signal)([]);
360
+ let _initPromise = Promise.resolve();
361
+ _initPromise._completed = false;
267
362
  const module2 = {
268
- settings: settingsSignal,
269
- async init() {
270
- const res = await (0, import_rxjs.firstValueFrom)(
271
- injector.get(import_apollo_angular.Apollo).query({ query: GQL_INIT_SETTINGS })
272
- );
273
- const settings = res.data.initSettings;
274
- settingsSignal.set(settings);
363
+ settings: wrapSignal(_settingsSignal, () => _initPromise),
364
+ async init(force = false) {
365
+ if (_initPromise._completed && !force) {
366
+ return;
367
+ }
368
+ if (force) {
369
+ _initPromise._completed = false;
370
+ }
371
+ _initPromise = (async () => {
372
+ try {
373
+ const res = await (0, import_rxjs.firstValueFrom)(
374
+ injector.get(import_apollo_angular.Apollo).query({ query: GQL_INIT_SETTINGS })
375
+ );
376
+ const settings = res.data.initSettings;
377
+ _settingsSignal.set(settings);
378
+ } catch (err) {
379
+ console.error(err);
380
+ throw err;
381
+ } finally {
382
+ _initPromise._completed = true;
383
+ }
384
+ })();
385
+ return _initPromise;
275
386
  }
276
387
  };
277
388
  return module2;
278
389
  }
279
390
  function createUiModule(injector) {
280
- const fullScreenSignal = (0, import_core.signal)(false);
281
- const isMobile = (0, import_rxjs_interop.toSignal)((0, import_rxjs.fromEvent)(window, "resize").pipe(
391
+ const _fullScreenSignal = (0, import_core.signal)(false);
392
+ const _isMobile = (0, import_rxjs_interop.toSignal)((0, import_rxjs.fromEvent)(window, "resize").pipe(
282
393
  (0, import_operators.debounceTime)(200),
283
394
  (0, import_operators.switchMap)(async () => window.innerHeight / window.innerWidth >= 1.5)
284
395
  ));
396
+ let _initPromise = Promise.resolve();
397
+ _initPromise._completed = false;
285
398
  const module2 = {
286
- fullScreen: fullScreenSignal,
287
- isMobile,
399
+ fullScreen: wrapSignal(_fullScreenSignal, () => _initPromise),
400
+ isMobile: _isMobile,
288
401
  activeRoutedComponent: void 0,
289
- async init() {
290
- return;
402
+ async init(force = false) {
403
+ if (_initPromise._completed && !force) {
404
+ return;
405
+ }
406
+ if (force) {
407
+ _initPromise._completed = false;
408
+ }
409
+ _initPromise = (async () => {
410
+ try {
411
+ } finally {
412
+ _initPromise._completed = true;
413
+ }
414
+ })();
415
+ return _initPromise;
291
416
  }
292
417
  };
293
418
  return module2;
@@ -301,13 +426,13 @@ function configGeex(injector, overrides = {}) {
301
426
  ...overrides
302
427
  };
303
428
  (0, import_core2.runInInjectionContext)(injector, () => {
304
- modules.init ?? (modules.init = async () => {
429
+ modules.init ?? (modules.init = async (force = false) => {
305
430
  const entries = Object.entries(modules).filter(([key]) => key !== "init");
306
431
  return Object.fromEntries(await Promise.all(
307
432
  entries.map(async ([key, mod]) => {
308
433
  const maybeInit = mod.init;
309
434
  try {
310
- return [key, await maybeInit()];
435
+ return [key, await maybeInit(force)];
311
436
  } catch (err) {
312
437
  console.error(err);
313
438
  return [key, null];
package/dist/index.mjs CHANGED
@@ -15,6 +15,37 @@ import gql from "graphql-tag";
15
15
  import { firstValueFrom, map, fromEvent } from "rxjs";
16
16
  import { debounceTime, switchMap } from "rxjs/operators";
17
17
  import { toSignal } from "@angular/core/rxjs-interop";
18
+ function wrapSignal(originalSignal, getInitPromise, timeout = 5e3) {
19
+ const checkInit = () => {
20
+ const initPromise = getInitPromise();
21
+ const timeoutPromise = new Promise(
22
+ (_, reject) => setTimeout(() => reject(new Error(`Module initialization timeout after ${timeout}ms`)), timeout)
23
+ );
24
+ return Promise.race([initPromise, timeoutPromise]);
25
+ };
26
+ let isWaiting = false;
27
+ let waitPromise = null;
28
+ const wrapped = (() => {
29
+ const promise = getInitPromise();
30
+ if (promise._completed) {
31
+ return originalSignal();
32
+ }
33
+ if (!isWaiting) {
34
+ isWaiting = true;
35
+ waitPromise = checkInit().finally(() => {
36
+ isWaiting = false;
37
+ waitPromise = null;
38
+ });
39
+ }
40
+ throw new Error(
41
+ "Signal accessed before module initialization completed. Please await module.init() or geex.init() before accessing signals."
42
+ );
43
+ });
44
+ wrapped.set = originalSignal.set.bind(originalSignal);
45
+ wrapped.update = originalSignal.update.bind(originalSignal);
46
+ wrapped.asReadonly = originalSignal.asReadonly.bind(originalSignal);
47
+ return wrapped;
48
+ }
18
49
  var LoginProviderEnum = {
19
50
  Local: "Local"
20
51
  };
@@ -81,20 +112,34 @@ var GQL_ON_PUBLIC_NOTIFY = gql`subscription onPublicNotify { onPublicNotify { __
81
112
  var GQL_ORGS_CACHE = gql`query orgsCache { orgs(take: 999) { items { id orgType code name parentOrgCode } } }`;
82
113
  var GQL_INIT_SETTINGS = gql`query initSettings { initSettings { id name value } }`;
83
114
  function createTenantModule(injector) {
84
- const current = signal(null);
115
+ const _current = signal(null);
116
+ let _initPromise = Promise.resolve();
117
+ _initPromise._completed = false;
85
118
  const module = {
86
- init: async () => {
87
- try {
88
- const tenantCode = injector.get(CookieService).get("__tenant");
89
- if (tenantCode) {
90
- const tenantData = await module.loadTenantData(tenantCode);
91
- current.set(tenantData ?? null);
92
- }
93
- } catch (err) {
94
- console.error(err);
119
+ init: async (force = false) => {
120
+ if (_initPromise._completed && !force) {
121
+ return;
95
122
  }
123
+ if (force) {
124
+ _initPromise._completed = false;
125
+ }
126
+ _initPromise = (async () => {
127
+ try {
128
+ const tenantCode = injector.get(CookieService).get("__tenant");
129
+ if (tenantCode) {
130
+ const tenantData = await module.loadTenantData(tenantCode);
131
+ _current.set(tenantData ?? null);
132
+ }
133
+ } catch (err) {
134
+ console.error(err);
135
+ throw err;
136
+ } finally {
137
+ _initPromise._completed = true;
138
+ }
139
+ })();
140
+ return _initPromise;
96
141
  },
97
- current,
142
+ current: wrapSignal(_current, () => _initPromise),
98
143
  async loadTenantData(code) {
99
144
  const res = await firstValueFrom(
100
145
  injector.get(Apollo).mutate({ mutation: GQL_CHECK_TENANT, variables: { code } })
@@ -118,24 +163,31 @@ function createTenantModule(injector) {
118
163
  return module;
119
164
  }
120
165
  function createAuthModule(injector) {
121
- const user = signal(null);
122
- let _initPromise = null;
166
+ const _user = signal(null);
167
+ let _initPromise = Promise.resolve();
168
+ _initPromise._completed = false;
123
169
  const module = {
124
- init: () => {
125
- if (_initPromise) {
126
- return _initPromise;
170
+ init: async (force = false) => {
171
+ if (_initPromise._completed && !force) {
172
+ return;
173
+ }
174
+ if (force) {
175
+ _initPromise._completed = false;
127
176
  }
128
177
  _initPromise = (async () => {
129
178
  try {
130
179
  const userData = await module.loadUserData();
131
- user.set(userData ?? null);
180
+ _user.set(userData ?? null);
132
181
  } catch (err) {
133
182
  console.error(err);
183
+ throw err;
184
+ } finally {
185
+ _initPromise._completed = true;
134
186
  }
135
187
  })();
136
188
  return _initPromise;
137
189
  },
138
- user,
190
+ user: wrapSignal(_user, () => _initPromise),
139
191
  async loadUserData() {
140
192
  const oAuthService = injector.get(OAuthService);
141
193
  try {
@@ -164,51 +216,92 @@ function createAuthModule(injector) {
164
216
  return module;
165
217
  }
166
218
  function createIdentityModule(injector) {
167
- const orgsSignal = signal([]);
168
- const userOwnedOrgsSignal = signal([]);
219
+ const _orgsSignal = signal([]);
220
+ const _userOwnedOrgsSignal = signal([]);
221
+ let _initPromise = Promise.resolve();
222
+ _initPromise._completed = false;
169
223
  const module = {
170
- orgs: orgsSignal,
171
- userOwnedOrgs: userOwnedOrgsSignal,
172
- async init() {
173
- try {
174
- const orgs$ = injector.get(Apollo).watchQuery({ query: GQL_ORGS_CACHE }).valueChanges.pipe(map((res) => deepCopy(res.data.orgs.items)));
175
- orgs$.subscribe((orgs) => {
176
- runInInjectionContext(injector, () => {
177
- orgsSignal.set(orgs);
178
- const userData = geex.auth.user();
179
- let allOwned = [];
180
- if (orgs?.length && userData) {
181
- if (userData.id === "000000000000000000000001") {
182
- allOwned = deepCopy(orgs);
183
- } else {
184
- const ownedCodes = userData.orgs.map((x) => x.code);
185
- allOwned = orgs.filter((o) => ownedCodes.some((code) => o.code.startsWith(code)));
224
+ orgs: wrapSignal(_orgsSignal, () => _initPromise),
225
+ userOwnedOrgs: wrapSignal(_userOwnedOrgsSignal, () => _initPromise),
226
+ async init(force = false) {
227
+ if (_initPromise._completed && !force) {
228
+ return;
229
+ }
230
+ if (force) {
231
+ _initPromise._completed = false;
232
+ }
233
+ _initPromise = (async () => {
234
+ try {
235
+ await new Promise((resolve, reject) => {
236
+ const orgs$ = injector.get(Apollo).watchQuery({ query: GQL_ORGS_CACHE }).valueChanges.pipe(map((res) => deepCopy(res.data.orgs.items)));
237
+ let isFirstEmit = true;
238
+ orgs$.subscribe({
239
+ next: (orgs) => {
240
+ runInInjectionContext(injector, () => {
241
+ _orgsSignal.set(orgs);
242
+ const userData = geex.auth.user();
243
+ let allOwned = [];
244
+ if (orgs?.length && userData) {
245
+ if (userData.id === "000000000000000000000001") {
246
+ allOwned = deepCopy(orgs);
247
+ } else {
248
+ const ownedCodes = userData.orgs.map((x) => x.code);
249
+ allOwned = orgs.filter((o) => ownedCodes.some((code) => o.code.startsWith(code)));
250
+ }
251
+ }
252
+ _userOwnedOrgsSignal.set(allOwned);
253
+ if (isFirstEmit) {
254
+ isFirstEmit = false;
255
+ resolve();
256
+ }
257
+ });
258
+ },
259
+ error: (err) => {
260
+ console.error(err);
261
+ reject(err);
186
262
  }
187
- }
188
- userOwnedOrgsSignal.set(allOwned);
263
+ });
189
264
  });
190
- });
191
- } catch (error) {
192
- console.error(error);
193
- }
265
+ } catch (error) {
266
+ console.error(error);
267
+ throw error;
268
+ } finally {
269
+ _initPromise._completed = true;
270
+ }
271
+ })();
272
+ return _initPromise;
194
273
  }
195
274
  };
196
275
  return module;
197
276
  }
198
277
  function createMessagingModule(injector) {
278
+ let _initPromise = Promise.resolve();
279
+ _initPromise._completed = false;
199
280
  const module = {
200
- async init() {
201
- try {
202
- await geex.auth.init();
203
- if (injector.get(OAuthService).hasValidAccessToken()) {
204
- const subClient = injector.get(Apollo).use("subscription");
205
- subClient.subscribe({ query: GQL_ON_PUBLIC_NOTIFY }).pipe(map((res) => res?.data?.onPublicNotify)).subscribe((notify) => {
206
- module.onPublicNotify(notify);
207
- });
208
- }
209
- } catch (err) {
210
- console.error(err);
281
+ async init(force = false) {
282
+ if (_initPromise._completed && !force) {
283
+ return;
211
284
  }
285
+ if (force) {
286
+ _initPromise._completed = false;
287
+ }
288
+ _initPromise = (async () => {
289
+ try {
290
+ await geex.auth.init();
291
+ if (injector.get(OAuthService).hasValidAccessToken()) {
292
+ const subClient = injector.get(Apollo).use("subscription");
293
+ subClient.subscribe({ query: GQL_ON_PUBLIC_NOTIFY }).pipe(map((res) => res?.data?.onPublicNotify)).subscribe((notify) => {
294
+ module.onPublicNotify(notify);
295
+ });
296
+ }
297
+ } catch (err) {
298
+ console.error(err);
299
+ throw err;
300
+ } finally {
301
+ _initPromise._completed = true;
302
+ }
303
+ })();
304
+ return _initPromise;
212
305
  },
213
306
  onPublicNotify(notify) {
214
307
  console.log("Public notify", notify);
@@ -217,31 +310,63 @@ function createMessagingModule(injector) {
217
310
  return module;
218
311
  }
219
312
  function createSettingsModule(injector) {
220
- const settingsSignal = signal([]);
313
+ const _settingsSignal = signal([]);
314
+ let _initPromise = Promise.resolve();
315
+ _initPromise._completed = false;
221
316
  const module = {
222
- settings: settingsSignal,
223
- async init() {
224
- const res = await firstValueFrom(
225
- injector.get(Apollo).query({ query: GQL_INIT_SETTINGS })
226
- );
227
- const settings = res.data.initSettings;
228
- settingsSignal.set(settings);
317
+ settings: wrapSignal(_settingsSignal, () => _initPromise),
318
+ async init(force = false) {
319
+ if (_initPromise._completed && !force) {
320
+ return;
321
+ }
322
+ if (force) {
323
+ _initPromise._completed = false;
324
+ }
325
+ _initPromise = (async () => {
326
+ try {
327
+ const res = await firstValueFrom(
328
+ injector.get(Apollo).query({ query: GQL_INIT_SETTINGS })
329
+ );
330
+ const settings = res.data.initSettings;
331
+ _settingsSignal.set(settings);
332
+ } catch (err) {
333
+ console.error(err);
334
+ throw err;
335
+ } finally {
336
+ _initPromise._completed = true;
337
+ }
338
+ })();
339
+ return _initPromise;
229
340
  }
230
341
  };
231
342
  return module;
232
343
  }
233
344
  function createUiModule(injector) {
234
- const fullScreenSignal = signal(false);
235
- const isMobile = toSignal(fromEvent(window, "resize").pipe(
345
+ const _fullScreenSignal = signal(false);
346
+ const _isMobile = toSignal(fromEvent(window, "resize").pipe(
236
347
  debounceTime(200),
237
348
  switchMap(async () => window.innerHeight / window.innerWidth >= 1.5)
238
349
  ));
350
+ let _initPromise = Promise.resolve();
351
+ _initPromise._completed = false;
239
352
  const module = {
240
- fullScreen: fullScreenSignal,
241
- isMobile,
353
+ fullScreen: wrapSignal(_fullScreenSignal, () => _initPromise),
354
+ isMobile: _isMobile,
242
355
  activeRoutedComponent: void 0,
243
- async init() {
244
- return;
356
+ async init(force = false) {
357
+ if (_initPromise._completed && !force) {
358
+ return;
359
+ }
360
+ if (force) {
361
+ _initPromise._completed = false;
362
+ }
363
+ _initPromise = (async () => {
364
+ try {
365
+ } finally {
366
+ _initPromise._completed = true;
367
+ }
368
+ })();
369
+ return _initPromise;
245
370
  }
246
371
  };
247
372
  return module;
@@ -255,13 +380,13 @@ function configGeex(injector, overrides = {}) {
255
380
  ...overrides
256
381
  };
257
382
  runInInjectionContext2(injector, () => {
258
- modules.init ?? (modules.init = async () => {
383
+ modules.init ?? (modules.init = async (force = false) => {
259
384
  const entries = Object.entries(modules).filter(([key]) => key !== "init");
260
385
  return Object.fromEntries(await Promise.all(
261
386
  entries.map(async ([key, mod]) => {
262
387
  const maybeInit = mod.init;
263
388
  try {
264
- return [key, await maybeInit()];
389
+ return [key, await maybeInit(force)];
265
390
  } catch (err) {
266
391
  console.error(err);
267
392
  return [key, null];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geexcode/geex-angular",
3
- "version": "0.0.33",
3
+ "version": "0.0.35",
4
4
  "description": "Angular adapter for Geex core.",
5
5
  "module": "dist/index.js",
6
6
  "main": "dist/index.cjs",