@geexcode/geex-angular 0.0.34 → 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,17 +209,31 @@ function createTenantModule(injector) {
164
209
  return module2;
165
210
  }
166
211
  function createAuthModule(injector) {
167
- const user = (0, import_core.signal)(null);
212
+ const _user = (0, import_core.signal)(null);
213
+ let _initPromise = Promise.resolve();
214
+ _initPromise._completed = false;
168
215
  const module2 = {
169
- init: async () => {
170
- try {
171
- const userData = await module2.loadUserData();
172
- user.set(userData ?? null);
173
- } catch (err) {
174
- console.error(err);
216
+ init: async (force = false) => {
217
+ if (_initPromise._completed && !force) {
218
+ return;
219
+ }
220
+ if (force) {
221
+ _initPromise._completed = false;
175
222
  }
223
+ _initPromise = (async () => {
224
+ try {
225
+ const userData = await module2.loadUserData();
226
+ _user.set(userData ?? null);
227
+ } catch (err) {
228
+ console.error(err);
229
+ throw err;
230
+ } finally {
231
+ _initPromise._completed = true;
232
+ }
233
+ })();
234
+ return _initPromise;
176
235
  },
177
- user,
236
+ user: wrapSignal(_user, () => _initPromise),
178
237
  async loadUserData() {
179
238
  const oAuthService = injector.get(import_angular_oauth2_oidc.OAuthService);
180
239
  try {
@@ -203,51 +262,92 @@ function createAuthModule(injector) {
203
262
  return module2;
204
263
  }
205
264
  function createIdentityModule(injector) {
206
- const orgsSignal = (0, import_core.signal)([]);
207
- 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;
208
269
  const module2 = {
209
- orgs: orgsSignal,
210
- userOwnedOrgs: userOwnedOrgsSignal,
211
- async init() {
212
- try {
213
- 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)));
214
- orgs$.subscribe((orgs) => {
215
- (0, import_core.runInInjectionContext)(injector, () => {
216
- orgsSignal.set(orgs);
217
- const userData = geex.auth.user();
218
- let allOwned = [];
219
- if (orgs?.length && userData) {
220
- if (userData.id === "000000000000000000000001") {
221
- allOwned = (0, import_util.deepCopy)(orgs);
222
- } else {
223
- const ownedCodes = userData.orgs.map((x) => x.code);
224
- 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);
225
308
  }
226
- }
227
- userOwnedOrgsSignal.set(allOwned);
309
+ });
228
310
  });
229
- });
230
- } catch (error) {
231
- console.error(error);
232
- }
311
+ } catch (error) {
312
+ console.error(error);
313
+ throw error;
314
+ } finally {
315
+ _initPromise._completed = true;
316
+ }
317
+ })();
318
+ return _initPromise;
233
319
  }
234
320
  };
235
321
  return module2;
236
322
  }
237
323
  function createMessagingModule(injector) {
324
+ let _initPromise = Promise.resolve();
325
+ _initPromise._completed = false;
238
326
  const module2 = {
239
- async init() {
240
- try {
241
- await geex.auth.init();
242
- if (injector.get(import_angular_oauth2_oidc.OAuthService).hasValidAccessToken()) {
243
- const subClient = injector.get(import_apollo_angular.Apollo).use("subscription");
244
- subClient.subscribe({ query: GQL_ON_PUBLIC_NOTIFY }).pipe((0, import_rxjs.map)((res) => res?.data?.onPublicNotify)).subscribe((notify) => {
245
- module2.onPublicNotify(notify);
246
- });
247
- }
248
- } catch (err) {
249
- console.error(err);
327
+ async init(force = false) {
328
+ if (_initPromise._completed && !force) {
329
+ return;
330
+ }
331
+ if (force) {
332
+ _initPromise._completed = false;
250
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;
251
351
  },
252
352
  onPublicNotify(notify) {
253
353
  console.log("Public notify", notify);
@@ -256,31 +356,63 @@ function createMessagingModule(injector) {
256
356
  return module2;
257
357
  }
258
358
  function createSettingsModule(injector) {
259
- const settingsSignal = (0, import_core.signal)([]);
359
+ const _settingsSignal = (0, import_core.signal)([]);
360
+ let _initPromise = Promise.resolve();
361
+ _initPromise._completed = false;
260
362
  const module2 = {
261
- settings: settingsSignal,
262
- async init() {
263
- const res = await (0, import_rxjs.firstValueFrom)(
264
- injector.get(import_apollo_angular.Apollo).query({ query: GQL_INIT_SETTINGS })
265
- );
266
- const settings = res.data.initSettings;
267
- 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;
268
386
  }
269
387
  };
270
388
  return module2;
271
389
  }
272
390
  function createUiModule(injector) {
273
- const fullScreenSignal = (0, import_core.signal)(false);
274
- 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(
275
393
  (0, import_operators.debounceTime)(200),
276
394
  (0, import_operators.switchMap)(async () => window.innerHeight / window.innerWidth >= 1.5)
277
395
  ));
396
+ let _initPromise = Promise.resolve();
397
+ _initPromise._completed = false;
278
398
  const module2 = {
279
- fullScreen: fullScreenSignal,
280
- isMobile,
399
+ fullScreen: wrapSignal(_fullScreenSignal, () => _initPromise),
400
+ isMobile: _isMobile,
281
401
  activeRoutedComponent: void 0,
282
- async init() {
283
- 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;
284
416
  }
285
417
  };
286
418
  return module2;
@@ -294,13 +426,13 @@ function configGeex(injector, overrides = {}) {
294
426
  ...overrides
295
427
  };
296
428
  (0, import_core2.runInInjectionContext)(injector, () => {
297
- modules.init ?? (modules.init = async () => {
429
+ modules.init ?? (modules.init = async (force = false) => {
298
430
  const entries = Object.entries(modules).filter(([key]) => key !== "init");
299
431
  return Object.fromEntries(await Promise.all(
300
432
  entries.map(async ([key, mod]) => {
301
433
  const maybeInit = mod.init;
302
434
  try {
303
- return [key, await maybeInit()];
435
+ return [key, await maybeInit(force)];
304
436
  } catch (err) {
305
437
  console.error(err);
306
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,17 +163,31 @@ function createTenantModule(injector) {
118
163
  return module;
119
164
  }
120
165
  function createAuthModule(injector) {
121
- const user = signal(null);
166
+ const _user = signal(null);
167
+ let _initPromise = Promise.resolve();
168
+ _initPromise._completed = false;
122
169
  const module = {
123
- init: async () => {
124
- try {
125
- const userData = await module.loadUserData();
126
- user.set(userData ?? null);
127
- } catch (err) {
128
- console.error(err);
170
+ init: async (force = false) => {
171
+ if (_initPromise._completed && !force) {
172
+ return;
173
+ }
174
+ if (force) {
175
+ _initPromise._completed = false;
129
176
  }
177
+ _initPromise = (async () => {
178
+ try {
179
+ const userData = await module.loadUserData();
180
+ _user.set(userData ?? null);
181
+ } catch (err) {
182
+ console.error(err);
183
+ throw err;
184
+ } finally {
185
+ _initPromise._completed = true;
186
+ }
187
+ })();
188
+ return _initPromise;
130
189
  },
131
- user,
190
+ user: wrapSignal(_user, () => _initPromise),
132
191
  async loadUserData() {
133
192
  const oAuthService = injector.get(OAuthService);
134
193
  try {
@@ -157,51 +216,92 @@ function createAuthModule(injector) {
157
216
  return module;
158
217
  }
159
218
  function createIdentityModule(injector) {
160
- const orgsSignal = signal([]);
161
- const userOwnedOrgsSignal = signal([]);
219
+ const _orgsSignal = signal([]);
220
+ const _userOwnedOrgsSignal = signal([]);
221
+ let _initPromise = Promise.resolve();
222
+ _initPromise._completed = false;
162
223
  const module = {
163
- orgs: orgsSignal,
164
- userOwnedOrgs: userOwnedOrgsSignal,
165
- async init() {
166
- try {
167
- const orgs$ = injector.get(Apollo).watchQuery({ query: GQL_ORGS_CACHE }).valueChanges.pipe(map((res) => deepCopy(res.data.orgs.items)));
168
- orgs$.subscribe((orgs) => {
169
- runInInjectionContext(injector, () => {
170
- orgsSignal.set(orgs);
171
- const userData = geex.auth.user();
172
- let allOwned = [];
173
- if (orgs?.length && userData) {
174
- if (userData.id === "000000000000000000000001") {
175
- allOwned = deepCopy(orgs);
176
- } else {
177
- const ownedCodes = userData.orgs.map((x) => x.code);
178
- 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);
179
262
  }
180
- }
181
- userOwnedOrgsSignal.set(allOwned);
263
+ });
182
264
  });
183
- });
184
- } catch (error) {
185
- console.error(error);
186
- }
265
+ } catch (error) {
266
+ console.error(error);
267
+ throw error;
268
+ } finally {
269
+ _initPromise._completed = true;
270
+ }
271
+ })();
272
+ return _initPromise;
187
273
  }
188
274
  };
189
275
  return module;
190
276
  }
191
277
  function createMessagingModule(injector) {
278
+ let _initPromise = Promise.resolve();
279
+ _initPromise._completed = false;
192
280
  const module = {
193
- async init() {
194
- try {
195
- await geex.auth.init();
196
- if (injector.get(OAuthService).hasValidAccessToken()) {
197
- const subClient = injector.get(Apollo).use("subscription");
198
- subClient.subscribe({ query: GQL_ON_PUBLIC_NOTIFY }).pipe(map((res) => res?.data?.onPublicNotify)).subscribe((notify) => {
199
- module.onPublicNotify(notify);
200
- });
201
- }
202
- } catch (err) {
203
- console.error(err);
281
+ async init(force = false) {
282
+ if (_initPromise._completed && !force) {
283
+ return;
284
+ }
285
+ if (force) {
286
+ _initPromise._completed = false;
204
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;
205
305
  },
206
306
  onPublicNotify(notify) {
207
307
  console.log("Public notify", notify);
@@ -210,31 +310,63 @@ function createMessagingModule(injector) {
210
310
  return module;
211
311
  }
212
312
  function createSettingsModule(injector) {
213
- const settingsSignal = signal([]);
313
+ const _settingsSignal = signal([]);
314
+ let _initPromise = Promise.resolve();
315
+ _initPromise._completed = false;
214
316
  const module = {
215
- settings: settingsSignal,
216
- async init() {
217
- const res = await firstValueFrom(
218
- injector.get(Apollo).query({ query: GQL_INIT_SETTINGS })
219
- );
220
- const settings = res.data.initSettings;
221
- 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;
222
340
  }
223
341
  };
224
342
  return module;
225
343
  }
226
344
  function createUiModule(injector) {
227
- const fullScreenSignal = signal(false);
228
- const isMobile = toSignal(fromEvent(window, "resize").pipe(
345
+ const _fullScreenSignal = signal(false);
346
+ const _isMobile = toSignal(fromEvent(window, "resize").pipe(
229
347
  debounceTime(200),
230
348
  switchMap(async () => window.innerHeight / window.innerWidth >= 1.5)
231
349
  ));
350
+ let _initPromise = Promise.resolve();
351
+ _initPromise._completed = false;
232
352
  const module = {
233
- fullScreen: fullScreenSignal,
234
- isMobile,
353
+ fullScreen: wrapSignal(_fullScreenSignal, () => _initPromise),
354
+ isMobile: _isMobile,
235
355
  activeRoutedComponent: void 0,
236
- async init() {
237
- 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;
238
370
  }
239
371
  };
240
372
  return module;
@@ -248,13 +380,13 @@ function configGeex(injector, overrides = {}) {
248
380
  ...overrides
249
381
  };
250
382
  runInInjectionContext2(injector, () => {
251
- modules.init ?? (modules.init = async () => {
383
+ modules.init ?? (modules.init = async (force = false) => {
252
384
  const entries = Object.entries(modules).filter(([key]) => key !== "init");
253
385
  return Object.fromEntries(await Promise.all(
254
386
  entries.map(async ([key, mod]) => {
255
387
  const maybeInit = mod.init;
256
388
  try {
257
- return [key, await maybeInit()];
389
+ return [key, await maybeInit(force)];
258
390
  } catch (err) {
259
391
  console.error(err);
260
392
  return [key, null];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geexcode/geex-angular",
3
- "version": "0.0.34",
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",