teraprox-core-sdk 0.3.10 → 0.3.14
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/README.md +515 -0
- package/dist/{chunk-JK654W4P.mjs → chunk-CBKXJHPL.mjs} +195 -25
- package/dist/{federation-Bhx0XhSP.d.mts → federation-Cp_lk0Xd.d.mts} +231 -49
- package/dist/{federation-Bhx0XhSP.d.ts → federation-Cp_lk0Xd.d.ts} +231 -49
- package/dist/federation.d.mts +1 -1
- package/dist/federation.d.ts +1 -1
- package/dist/federation.js +199 -26
- package/dist/federation.mjs +9 -3
- package/dist/index.d.mts +1414 -21
- package/dist/index.d.ts +1414 -21
- package/dist/index.js +2467 -886
- package/dist/index.mjs +2172 -827
- package/package.json +2 -1
|
@@ -78,6 +78,12 @@ interface IObservabilityPort {
|
|
|
78
78
|
logBreadcrumb(payload: BreadcrumbPayload): void;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
interface RateLimitEntry {
|
|
82
|
+
used: number;
|
|
83
|
+
limit: number;
|
|
84
|
+
exceeded: boolean;
|
|
85
|
+
windowReset: string;
|
|
86
|
+
}
|
|
81
87
|
interface CoreService {
|
|
82
88
|
/** Cria um HttpController configurado para um contexto/endpoint */
|
|
83
89
|
createController(context: string, baseEndPoint?: string): HttpController;
|
|
@@ -97,6 +103,8 @@ interface CoreService {
|
|
|
97
103
|
hostedByCore: boolean;
|
|
98
104
|
/** Porta de observabilidade — tracking, vitals e breadcrumbs */
|
|
99
105
|
observability: IObservabilityPort;
|
|
106
|
+
/** Estado de rate limit em tempo real via RTDB. pathGroup → uso atual. */
|
|
107
|
+
rateLimits: Record<string, RateLimitEntry>;
|
|
100
108
|
}
|
|
101
109
|
|
|
102
110
|
interface FederatedBridgeProps {
|
|
@@ -123,28 +131,151 @@ interface FederatedBridgeProps {
|
|
|
123
131
|
declare function FederatedBridge({ coreService, children }: FederatedBridgeProps): react_jsx_runtime.JSX.Element;
|
|
124
132
|
|
|
125
133
|
/**
|
|
126
|
-
*
|
|
134
|
+
* Indica se o bundle atual está sendo executado dentro do shell teraprox-core
|
|
135
|
+
* (Module Federation). O host define `window.__TERAPROX_HOSTED_BY_CORE__` via
|
|
136
|
+
* `FederatedBridge` ao montar o remote.
|
|
127
137
|
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
138
|
+
* Use para ramificações raras (ex.: não montar `StandaloneProvider` duplicado).
|
|
139
|
+
* Para HTTP, prefira sempre `useCoreService().createController` — no host vem
|
|
140
|
+
* do `CoreServiceProvider`; em standalone vem do `StandaloneProvider`.
|
|
141
|
+
*/
|
|
142
|
+
declare function isHostedByCore(): boolean;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Dependência de reducer declarada no manifest.
|
|
130
146
|
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
* import { createReducersBundle } from 'teraprox-core-sdk/federation'
|
|
147
|
+
* Cada rota declara quais fatias do Redux precisa.
|
|
148
|
+
* O core injeta APENAS essas fatias antes de montar o componente.
|
|
134
149
|
*
|
|
135
|
-
*
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
150
|
+
* A string é a chave no store (ex: 'tarefa', 'solicitacaoDeServico').
|
|
151
|
+
*/
|
|
152
|
+
type ReducerDep = string;
|
|
153
|
+
/**
|
|
154
|
+
* Manifesto que cada remote exporta para o Core
|
|
155
|
+
* montar menu e rotas dinamicamente.
|
|
156
|
+
*/
|
|
157
|
+
interface RemoteMenuItem {
|
|
158
|
+
/** Label exibido no menu */
|
|
159
|
+
label: string;
|
|
160
|
+
/** Rota no react-router (ex: '/manutencao/ordens-de-servico') */
|
|
161
|
+
path: string;
|
|
162
|
+
/** Nome do módulo no exposes do webpack (ex: './OrdensDeServico') */
|
|
163
|
+
module: string;
|
|
164
|
+
/** Contexto para ReducersBundle (ex: 'ordemDeServico') */
|
|
165
|
+
context: string;
|
|
166
|
+
/** Reducer keys que esta tela precisa no store do core */
|
|
167
|
+
reducers?: ReducerDep[];
|
|
168
|
+
/** ID do componente para withPermission */
|
|
169
|
+
componentId?: string;
|
|
170
|
+
/** Ícone react-icons (ex: 'FaTools') */
|
|
171
|
+
icon?: string;
|
|
172
|
+
/**
|
|
173
|
+
* Ordem dentro da sub-section (quando mesma `section.label` é declarada
|
|
174
|
+
* por múltiplos remotes e items são merged). Default = 999.
|
|
175
|
+
*/
|
|
176
|
+
order?: number;
|
|
177
|
+
}
|
|
178
|
+
interface RemoteMenuSection {
|
|
179
|
+
/** Nome da seção no menu (ex: 'Manutenção') */
|
|
180
|
+
label: string;
|
|
181
|
+
/** Ícone da seção */
|
|
182
|
+
icon?: string;
|
|
183
|
+
items: RemoteMenuItem[];
|
|
184
|
+
/**
|
|
185
|
+
* NOVO: agrupamento global na MenuBar (ex: 'SGM').
|
|
186
|
+
* Sections com mesmo `group` (ou cujo manifest tem `menuGroup.name` igual)
|
|
187
|
+
* são fundidas em 1 nó top-level.
|
|
188
|
+
*/
|
|
189
|
+
group?: string;
|
|
190
|
+
/** NOVO: ordem dentro do group (ou top-level). Default = 999 (final). */
|
|
191
|
+
order?: number;
|
|
192
|
+
/**
|
|
193
|
+
* NOVO: se true e dentro de group, items vão direto pro group
|
|
194
|
+
* (sem sub-grupo intermediário pela section.label). Default false.
|
|
195
|
+
*/
|
|
196
|
+
flatten?: boolean;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Rota de formulário / tela interna que não aparece no menu,
|
|
200
|
+
* mas precisa ser registrada como <Route> no host.
|
|
201
|
+
*/
|
|
202
|
+
interface RemoteFormRoute {
|
|
203
|
+
/** Rota no react-router (ex: '/solicitacaoDeServicoForm') */
|
|
204
|
+
path: string;
|
|
205
|
+
/** Nome do módulo no exposes do webpack (ex: './SolicitacaoDeServicoForm') */
|
|
206
|
+
module: string;
|
|
207
|
+
/** Contexto para ReducersBundle e HTTP (ex: 'solicitacaoDeServico') */
|
|
208
|
+
context: string;
|
|
209
|
+
/** Reducer keys que esta tela precisa no store do core */
|
|
210
|
+
reducers?: ReducerDep[];
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Reducers que o remote disponibiliza, agrupados por chave do store.
|
|
214
|
+
* O manifest declara quais cada rota precisa; o ReducersBundle provê os importadores.
|
|
215
|
+
*/
|
|
216
|
+
interface RemoteReducerMap {
|
|
217
|
+
[storeKey: string]: () => Promise<any>;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Reducers defaults que são injetados em TODAS as rotas do remote,
|
|
221
|
+
* independentemente do que cada rota declara.
|
|
222
|
+
*/
|
|
223
|
+
type DefaultReducerKeys = string[];
|
|
224
|
+
interface RemoteManifest {
|
|
225
|
+
/** Nome do remote (deve corresponder ao name do ModuleFederationPlugin) */
|
|
226
|
+
name: string;
|
|
227
|
+
/** Versão semântica */
|
|
228
|
+
version: string;
|
|
229
|
+
/** Seções de menu que este remote contribui */
|
|
230
|
+
menuSections: RemoteMenuSection[];
|
|
231
|
+
/** Rotas internas (formulários, detalhe) que não aparecem no menu */
|
|
232
|
+
formRoutes?: RemoteFormRoute[];
|
|
233
|
+
/**
|
|
234
|
+
* Mapa de TODOS os reducers que este remote disponibiliza.
|
|
235
|
+
* Chave = nome no store, valor = lazy import do reducer.
|
|
236
|
+
* Se presente, o core usa isso + reducers[] de cada rota para injeção granular.
|
|
237
|
+
* Se ausente, fallback para o ReducersBundle legado.
|
|
238
|
+
*/
|
|
239
|
+
reducerMap?: RemoteReducerMap;
|
|
240
|
+
/** Reducer keys injetados em TODAS as rotas deste remote */
|
|
241
|
+
defaultReducers?: DefaultReducerKeys;
|
|
242
|
+
/**
|
|
243
|
+
* NOVO opcional: aplica `group=name` a TODAS as `menuSections` deste remote
|
|
244
|
+
* (atalho declarativo). Sections com seu próprio `group` ainda têm precedência.
|
|
245
|
+
*/
|
|
246
|
+
menuGroup?: {
|
|
247
|
+
name: string;
|
|
248
|
+
icon?: string;
|
|
249
|
+
order?: number;
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Factories for creating standardized ReducersBundles.
|
|
255
|
+
*
|
|
256
|
+
* Two APIs:
|
|
257
|
+
*
|
|
258
|
+
* 1. `createReducersFromManifest` (RECOMENDADO) — Manifest-driven.
|
|
259
|
+
* O manifest.js é a FONTE ÚNICA DE VERDADE: declara rotas, menu E reducer deps.
|
|
260
|
+
* Zero contextMap manual.
|
|
261
|
+
*
|
|
262
|
+
* ```ts
|
|
263
|
+
* import { createReducersFromManifest } from 'teraprox-core-sdk/federation'
|
|
264
|
+
* import { manifest } from './manifest'
|
|
265
|
+
*
|
|
266
|
+
* export default createReducersFromManifest(manifest, {
|
|
267
|
+
* solicitacaoDeServico: () => import('../Reducers/solicitacaoDeServicoReducer'),
|
|
268
|
+
* tarefa: () => import('../Reducers/tarefaReducer'),
|
|
269
|
+
* justificativa: () => import('../Reducers/justificativaReducer'),
|
|
270
|
+
* globalError: () => import('../Reducers/default-reducers/globalErrorReducer'),
|
|
271
|
+
* })
|
|
272
|
+
* ```
|
|
273
|
+
*
|
|
274
|
+
* 2. `createReducersBundle` (LEGADO) — contextMap manual.
|
|
275
|
+
* Mantido para retrocompatibilidade com remotes que ainda não declararam
|
|
276
|
+
* `reducers[]` nas rotas do manifest.
|
|
147
277
|
*/
|
|
278
|
+
|
|
148
279
|
interface ReducersBundleConfig {
|
|
149
280
|
/** Map de nome → importador lazy do reducer */
|
|
150
281
|
reducers: Record<string, () => Promise<any>>;
|
|
@@ -159,10 +290,22 @@ interface ReducersBundle {
|
|
|
159
290
|
getReducersForModule(opts: {
|
|
160
291
|
context?: string;
|
|
161
292
|
modulePath?: string;
|
|
293
|
+
reducerKeys?: string[];
|
|
162
294
|
}): Promise<Record<string, any>>;
|
|
163
295
|
loadAllReducers(): Promise<Record<string, any>>;
|
|
164
296
|
baseReducers: Record<string, never>;
|
|
165
297
|
}
|
|
298
|
+
/**
|
|
299
|
+
* Cria um ReducersBundle a partir do manifest + mapa de importadores.
|
|
300
|
+
*
|
|
301
|
+
* O contextMap é DERIVADO automaticamente dos campos `reducers[]` e `context`
|
|
302
|
+
* de cada rota do manifest. Nenhuma declaração manual de contexto é necessária.
|
|
303
|
+
*
|
|
304
|
+
* @param manifest — O mesmo objeto exportado como ./Manifest
|
|
305
|
+
* @param reducerMap — { storeKey: () => import('...') } para TODOS os reducers do remote
|
|
306
|
+
* @param defaultReducerKeys — Keys injetadas em todas as rotas (ex: 'globalError', 'notification')
|
|
307
|
+
*/
|
|
308
|
+
declare function createReducersFromManifest(manifest: RemoteManifest, reducerMap: Record<string, () => Promise<any>>, defaultReducerKeys?: string[]): ReducersBundle;
|
|
166
309
|
declare function createReducersBundle(config: ReducersBundleConfig): ReducersBundle;
|
|
167
310
|
|
|
168
311
|
interface EmulatorConfig {
|
|
@@ -172,12 +315,30 @@ interface EmulatorConfig {
|
|
|
172
315
|
}
|
|
173
316
|
interface StandaloneConfig {
|
|
174
317
|
/**
|
|
175
|
-
*
|
|
176
|
-
*
|
|
318
|
+
* Implementação de `CoreService.createController` **somente para modo standalone**
|
|
319
|
+
* (npm start do remote sem o shell). É a mesma *assinatura* que o core expõe
|
|
320
|
+
* em `CoreServiceProvider`, mas o host injeta a dele via `FederatedBridge`;
|
|
321
|
+
* telas devem sempre usar `useCoreService().createController` — nunca chamar
|
|
322
|
+
* esta factory diretamente.
|
|
177
323
|
*/
|
|
178
324
|
createController: (context: string, baseEndPoint?: string) => HttpController;
|
|
179
|
-
/**
|
|
180
|
-
|
|
325
|
+
/**
|
|
326
|
+
* Pass a ToastService implementation directly (preferred).
|
|
327
|
+
* Eliminates the need for an addToast bridge in every remote.
|
|
328
|
+
*
|
|
329
|
+
* Example:
|
|
330
|
+
* ```
|
|
331
|
+
* const myToast: ToastService = { success: ..., warning: ..., error: ..., info: ... }
|
|
332
|
+
* <StandaloneProvider toast={myToast} ...>
|
|
333
|
+
* ```
|
|
334
|
+
*/
|
|
335
|
+
toast?: ToastService;
|
|
336
|
+
/**
|
|
337
|
+
* react-toast-notifications style callback — kept for backward compatibility
|
|
338
|
+
* with remotes that already use ToastProvider + useToasts().
|
|
339
|
+
* When `toast` prop is provided, `addToast` is ignored.
|
|
340
|
+
*/
|
|
341
|
+
addToast?: (message: string, options?: any) => void;
|
|
181
342
|
/**
|
|
182
343
|
* Firebase client config object (from REACT_APP_FIREBASE_CONFIG).
|
|
183
344
|
* When provided together with `tenant`, enables real-time matching
|
|
@@ -201,6 +362,13 @@ interface StandaloneConfig {
|
|
|
201
362
|
/**
|
|
202
363
|
* Tenant / company ID used to build the RTDB path:
|
|
203
364
|
* `{tenant}/matchingObjects`
|
|
365
|
+
*
|
|
366
|
+
* Resolution order (first non-empty value wins):
|
|
367
|
+
* 1. This prop (dynamic — typically from Redux state after login)
|
|
368
|
+
* 2. `REACT_APP_RTDB_TENANT` env var (static — set in the app's .env)
|
|
369
|
+
* 3. `'dev-local'` as last resort in NODE_ENV=development
|
|
370
|
+
*
|
|
371
|
+
* In production the prop MUST be provided; env-var fallback is for dev only.
|
|
204
372
|
*/
|
|
205
373
|
tenant?: string;
|
|
206
374
|
children: React__default.ReactNode;
|
|
@@ -238,7 +406,7 @@ interface StandaloneConfig {
|
|
|
238
406
|
* }
|
|
239
407
|
* ```
|
|
240
408
|
*/
|
|
241
|
-
declare function StandaloneProvider({ createController, addToast, firebaseConfig, emulator, tenant, children }: StandaloneConfig): react_jsx_runtime.JSX.Element;
|
|
409
|
+
declare function StandaloneProvider({ createController, toast: toastProp, addToast, firebaseConfig, emulator, tenant, children, }: StandaloneConfig): react_jsx_runtime.JSX.Element;
|
|
242
410
|
|
|
243
411
|
interface DevUser {
|
|
244
412
|
firstName: string;
|
|
@@ -283,37 +451,51 @@ interface DevAutoLoginProps {
|
|
|
283
451
|
declare function DevAutoLogin({ actions, devUser, children }: DevAutoLoginProps): react_jsx_runtime.JSX.Element;
|
|
284
452
|
|
|
285
453
|
/**
|
|
286
|
-
*
|
|
287
|
-
*
|
|
454
|
+
* Nó top-level da árvore de menu agregada.
|
|
455
|
+
* Pode representar um `group` (vários remotes/sections fundidos)
|
|
456
|
+
* ou uma section sem group (legacy / retrocompat).
|
|
288
457
|
*/
|
|
289
|
-
interface
|
|
290
|
-
/**
|
|
458
|
+
interface MenuTreeNode {
|
|
459
|
+
/** Identificador único — `group:<name>` ou `<remote>:<sectionLabel>` */
|
|
460
|
+
key: string;
|
|
461
|
+
/** Label exibido no dropdown principal */
|
|
291
462
|
label: string;
|
|
292
|
-
/**
|
|
293
|
-
path: string;
|
|
294
|
-
/** Nome do módulo no exposes do webpack (ex: './OrdensDeServico') */
|
|
295
|
-
module: string;
|
|
296
|
-
/** Contexto para ReducersBundle (ex: 'ordemDeServico') */
|
|
297
|
-
context: string;
|
|
298
|
-
/** ID do componente para withPermission */
|
|
299
|
-
componentId?: string;
|
|
300
|
-
/** Ícone react-icons (ex: 'FaTools') */
|
|
463
|
+
/** Ícone (react-icons name) */
|
|
301
464
|
icon?: string;
|
|
465
|
+
/** Order (default 999) — usado para sort estável */
|
|
466
|
+
order: number;
|
|
467
|
+
/** Filhos: sub-sections (quando agrupando) ou items diretos */
|
|
468
|
+
children: MenuTreeChild[];
|
|
302
469
|
}
|
|
303
|
-
|
|
304
|
-
|
|
470
|
+
/**
|
|
471
|
+
* Filho de um MenuTreeNode.
|
|
472
|
+
* - kind='section': sub-cabeçalho com items aninhados (default p/ group)
|
|
473
|
+
* - kind='item': item direto (top-level legacy ou flatten=true)
|
|
474
|
+
*/
|
|
475
|
+
type MenuTreeChild = {
|
|
476
|
+
kind: 'section';
|
|
305
477
|
label: string;
|
|
306
|
-
/** Ícone da seção */
|
|
307
478
|
icon?: string;
|
|
308
479
|
items: RemoteMenuItem[];
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
480
|
+
order?: number;
|
|
481
|
+
} | {
|
|
482
|
+
kind: 'item';
|
|
483
|
+
item: RemoteMenuItem;
|
|
484
|
+
order?: number;
|
|
485
|
+
};
|
|
486
|
+
/**
|
|
487
|
+
* Recebe array de manifests e produz árvore agregada por `group`.
|
|
488
|
+
*
|
|
489
|
+
* Regras:
|
|
490
|
+
* - Sections sem group e sem `manifest.menuGroup` → top-level node próprio
|
|
491
|
+
* (children = items diretos kind='item' — comportamento legado)
|
|
492
|
+
* - Sections com group (próprio ou herdado de menuGroup) → fundidas sob 1 node
|
|
493
|
+
* `{ key='group:<name>', label=<name> }`
|
|
494
|
+
* - flatten=true: items entram direto como children kind='item'
|
|
495
|
+
* - flatten=false (default): wrapping `{kind:'section', label, items}`
|
|
496
|
+
* - `menuGroup` do manifest aplica fallback para sections que não declaram
|
|
497
|
+
* o próprio `group` (não sobrescreve override por section).
|
|
498
|
+
*/
|
|
499
|
+
declare function groupMenuSections(manifests: RemoteManifest[]): MenuTreeNode[];
|
|
318
500
|
|
|
319
|
-
export { type BreadcrumbPayload as B, type CoreService as C,
|
|
501
|
+
export { type BreadcrumbPayload as B, type CoreService as C, type DefaultReducerKeys as D, FederatedBridge as F, type HttpController as H, type IObservabilityPort as I, type MatchingObjectSubscription as M, type RateLimitEntry as R, StandaloneProvider as S, type ToastService as T, type VitalsPayload as V, type InteractionPayload as a, DevAutoLogin as b, type MenuTreeChild as c, type MenuTreeNode as d, type ReducerDep as e, type ReducersBundle as f, type ReducersBundleConfig as g, type RemoteFormRoute as h, type RemoteManifest as i, type RemoteMenuItem as j, type RemoteMenuSection as k, type RemoteReducerMap as l, type ToastOptions as m, createReducersBundle as n, createReducersFromManifest as o, groupMenuSections as p, isHostedByCore as q };
|
package/dist/federation.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { D as DevAutoLogin, F as FederatedBridge,
|
|
1
|
+
export { D as DefaultReducerKeys, b as DevAutoLogin, F as FederatedBridge, c as MenuTreeChild, d as MenuTreeNode, e as ReducerDep, f as ReducersBundle, g as ReducersBundleConfig, h as RemoteFormRoute, i as RemoteManifest, j as RemoteMenuItem, k as RemoteMenuSection, l as RemoteReducerMap, S as StandaloneProvider, n as createReducersBundle, o as createReducersFromManifest, p as groupMenuSections, q as isHostedByCore } from './federation-Cp_lk0Xd.mjs';
|
|
2
2
|
import 'react/jsx-runtime';
|
|
3
3
|
import 'react';
|
package/dist/federation.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { D as DevAutoLogin, F as FederatedBridge,
|
|
1
|
+
export { D as DefaultReducerKeys, b as DevAutoLogin, F as FederatedBridge, c as MenuTreeChild, d as MenuTreeNode, e as ReducerDep, f as ReducersBundle, g as ReducersBundleConfig, h as RemoteFormRoute, i as RemoteManifest, j as RemoteMenuItem, k as RemoteMenuSection, l as RemoteReducerMap, S as StandaloneProvider, n as createReducersBundle, o as createReducersFromManifest, p as groupMenuSections, q as isHostedByCore } from './federation-Cp_lk0Xd.js';
|
|
2
2
|
import 'react/jsx-runtime';
|
|
3
3
|
import 'react';
|
package/dist/federation.js
CHANGED
|
@@ -33,7 +33,10 @@ __export(federation_exports, {
|
|
|
33
33
|
DevAutoLogin: () => DevAutoLogin,
|
|
34
34
|
FederatedBridge: () => FederatedBridge,
|
|
35
35
|
StandaloneProvider: () => StandaloneProvider,
|
|
36
|
-
createReducersBundle: () => createReducersBundle
|
|
36
|
+
createReducersBundle: () => createReducersBundle,
|
|
37
|
+
createReducersFromManifest: () => createReducersFromManifest,
|
|
38
|
+
groupMenuSections: () => groupMenuSections,
|
|
39
|
+
isHostedByCore: () => isHostedByCore
|
|
37
40
|
});
|
|
38
41
|
module.exports = __toCommonJS(federation_exports);
|
|
39
42
|
|
|
@@ -58,25 +61,78 @@ function FederatedBridge({ coreService, children }) {
|
|
|
58
61
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CoreServiceContext.Provider, { value: coreService, children });
|
|
59
62
|
}
|
|
60
63
|
|
|
64
|
+
// src/federation/isHostedByCore.ts
|
|
65
|
+
function isHostedByCore() {
|
|
66
|
+
if (typeof window === "undefined") return false;
|
|
67
|
+
return !!window.__TERAPROX_HOSTED_BY_CORE__;
|
|
68
|
+
}
|
|
69
|
+
|
|
61
70
|
// src/federation/createReducersBundle.ts
|
|
71
|
+
function buildGetReducersForKeys(reducers) {
|
|
72
|
+
return async (keys = []) => {
|
|
73
|
+
const uniqueKeys = [...new Set(keys)].filter((key) => !!reducers[key]);
|
|
74
|
+
const loaded = await Promise.all(
|
|
75
|
+
uniqueKeys.map(async (key) => {
|
|
76
|
+
const mod = await reducers[key]();
|
|
77
|
+
return [key, mod.default || mod];
|
|
78
|
+
})
|
|
79
|
+
);
|
|
80
|
+
return Object.fromEntries(loaded);
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function createReducersFromManifest(manifest, reducerMap, defaultReducerKeys = []) {
|
|
84
|
+
var _a, _b, _c, _d, _e, _f;
|
|
85
|
+
const allKeys = Object.keys(reducerMap);
|
|
86
|
+
const getReducersForKeys = buildGetReducersForKeys(reducerMap);
|
|
87
|
+
const allRoutes = [];
|
|
88
|
+
for (const section of (_a = manifest.menuSections) != null ? _a : []) {
|
|
89
|
+
allRoutes.push(...(_b = section.items) != null ? _b : []);
|
|
90
|
+
}
|
|
91
|
+
allRoutes.push(...(_c = manifest.formRoutes) != null ? _c : []);
|
|
92
|
+
const derivedContextMap = {};
|
|
93
|
+
for (const route of allRoutes) {
|
|
94
|
+
if (!route.context) continue;
|
|
95
|
+
const routeReducers = (_d = route.reducers) != null ? _d : [];
|
|
96
|
+
const existing = (_e = derivedContextMap[route.context]) != null ? _e : [];
|
|
97
|
+
derivedContextMap[route.context] = [.../* @__PURE__ */ new Set([...existing, ...routeReducers])];
|
|
98
|
+
}
|
|
99
|
+
const mergedDefaults = [
|
|
100
|
+
.../* @__PURE__ */ new Set([...defaultReducerKeys, ...(_f = manifest.defaultReducers) != null ? _f : []])
|
|
101
|
+
];
|
|
102
|
+
const getReducerKeysByContext = (context) => {
|
|
103
|
+
const contextKeys = derivedContextMap[context];
|
|
104
|
+
if (!contextKeys || contextKeys.length === 0) return allKeys;
|
|
105
|
+
return [.../* @__PURE__ */ new Set([...mergedDefaults, ...contextKeys])];
|
|
106
|
+
};
|
|
107
|
+
const getReducersForModule = async ({
|
|
108
|
+
context,
|
|
109
|
+
reducerKeys
|
|
110
|
+
} = {}) => {
|
|
111
|
+
if (reducerKeys && reducerKeys.length > 0) {
|
|
112
|
+
const keys2 = [.../* @__PURE__ */ new Set([...mergedDefaults, ...reducerKeys])];
|
|
113
|
+
return getReducersForKeys(keys2);
|
|
114
|
+
}
|
|
115
|
+
const keys = getReducerKeysByContext(context || "");
|
|
116
|
+
return getReducersForKeys(keys);
|
|
117
|
+
};
|
|
118
|
+
const loadAllReducers = () => getReducersForKeys(allKeys);
|
|
119
|
+
return {
|
|
120
|
+
getReducerKeysByContext,
|
|
121
|
+
getReducersForKeys,
|
|
122
|
+
getReducersForModule,
|
|
123
|
+
loadAllReducers,
|
|
124
|
+
baseReducers: {}
|
|
125
|
+
};
|
|
126
|
+
}
|
|
62
127
|
function createReducersBundle(config) {
|
|
63
128
|
const { reducers, contextMap, defaults = [] } = config;
|
|
64
129
|
const allKeys = Object.keys(reducers);
|
|
130
|
+
const getReducersForKeys = buildGetReducersForKeys(reducers);
|
|
65
131
|
const getReducerKeysByContext = (context) => {
|
|
66
132
|
const contextKeys = contextMap[context];
|
|
67
133
|
if (!contextKeys) return allKeys;
|
|
68
134
|
return [.../* @__PURE__ */ new Set([...defaults, ...contextKeys])];
|
|
69
135
|
};
|
|
70
|
-
const getReducersForKeys = async (keys = []) => {
|
|
71
|
-
const uniqueKeys = [...new Set(keys)].filter((key) => !!reducers[key]);
|
|
72
|
-
const loaded = await Promise.all(
|
|
73
|
-
uniqueKeys.map(async (key) => {
|
|
74
|
-
const module2 = await reducers[key]();
|
|
75
|
-
return [key, module2.default || module2];
|
|
76
|
-
})
|
|
77
|
-
);
|
|
78
|
-
return Object.fromEntries(loaded);
|
|
79
|
-
};
|
|
80
136
|
const getReducersForModule = async ({
|
|
81
137
|
context
|
|
82
138
|
} = {}) => {
|
|
@@ -215,20 +271,38 @@ function RtdbConfigWarning({ onDismiss }) {
|
|
|
215
271
|
}
|
|
216
272
|
);
|
|
217
273
|
}
|
|
218
|
-
function StandaloneProvider({
|
|
274
|
+
function StandaloneProvider({
|
|
275
|
+
createController,
|
|
276
|
+
toast: toastProp,
|
|
277
|
+
addToast,
|
|
278
|
+
firebaseConfig,
|
|
279
|
+
emulator,
|
|
280
|
+
tenant,
|
|
281
|
+
children
|
|
282
|
+
}) {
|
|
219
283
|
const [subscriptions] = (0, import_react3.useState)([]);
|
|
220
284
|
const subscriptionsRef = (0, import_react3.useRef)(subscriptions);
|
|
221
285
|
subscriptionsRef.current = subscriptions;
|
|
222
286
|
const [rtdbWarning, setRtdbWarning] = (0, import_react3.useState)(false);
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
287
|
+
const _envTenant = typeof process !== "undefined" ? process.env.REACT_APP_RTDB_TENANT : void 0;
|
|
288
|
+
const resolvedTenant = tenant || _envTenant || (process.env.NODE_ENV !== "production" ? "dev-local" : void 0);
|
|
289
|
+
const toast = (0, import_react3.useMemo)(() => {
|
|
290
|
+
if (toastProp) return toastProp;
|
|
291
|
+
if (addToast) {
|
|
292
|
+
return {
|
|
293
|
+
success: (msg, opts) => addToast(msg, { appearance: "success", autoDismiss: true, ...opts }),
|
|
294
|
+
warning: (msg, opts) => addToast(msg, { appearance: "warning", autoDismiss: true, ...opts }),
|
|
295
|
+
error: (msg, opts) => addToast(msg, { appearance: "error", autoDismiss: true, ...opts }),
|
|
296
|
+
info: (msg, opts) => addToast(msg, { appearance: "info", autoDismiss: true, ...opts })
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
const noop = (msg) => {
|
|
300
|
+
if (process.env.NODE_ENV !== "production") {
|
|
301
|
+
console.warn("[StandaloneProvider] Toast called but no toast/addToast prop provided:", msg);
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
return { success: noop, warning: noop, error: noop, info: noop };
|
|
305
|
+
}, [toastProp, addToast]);
|
|
232
306
|
const subscribe = (0, import_react3.useCallback)(
|
|
233
307
|
(mo) => {
|
|
234
308
|
subscriptions.push(mo);
|
|
@@ -245,7 +319,16 @@ function StandaloneProvider({ createController, addToast, firebaseConfig, emulat
|
|
|
245
319
|
[subscriptions]
|
|
246
320
|
);
|
|
247
321
|
(0, import_react3.useEffect)(() => {
|
|
248
|
-
if (
|
|
322
|
+
if (resolvedTenant || process.env.NODE_ENV === "production") return;
|
|
323
|
+
const timer = setTimeout(() => {
|
|
324
|
+
console.warn(
|
|
325
|
+
'[StandaloneProvider] RTDB listener deferred: tenant could not be resolved after 5 s.\nFix with any of:\n \u2022 Pass `tenant` prop (e.g. from Redux state.global.companyId)\n \u2022 Set REACT_APP_RTDB_TENANT=<companyId> in your .env\n \u2022 Run in NODE_ENV=development (auto-falls back to "dev-local")'
|
|
326
|
+
);
|
|
327
|
+
}, 5e3);
|
|
328
|
+
return () => clearTimeout(timer);
|
|
329
|
+
}, [resolvedTenant]);
|
|
330
|
+
(0, import_react3.useEffect)(() => {
|
|
331
|
+
if (!resolvedTenant) return;
|
|
249
332
|
let cleanup;
|
|
250
333
|
let cancelled = false;
|
|
251
334
|
(async () => {
|
|
@@ -288,7 +371,7 @@ function StandaloneProvider({ createController, addToast, firebaseConfig, emulat
|
|
|
288
371
|
const cloudApp = existingApp != null ? existingApp : initializeApp(strategy.config);
|
|
289
372
|
db = getDatabase(cloudApp);
|
|
290
373
|
}
|
|
291
|
-
const moRef = ref(db, `${
|
|
374
|
+
const moRef = ref(db, `${resolvedTenant}/matchingObjects`);
|
|
292
375
|
const unsub = onChildAdded(moRef, (snapshot) => {
|
|
293
376
|
const data = snapshot.val();
|
|
294
377
|
if (!data) return;
|
|
@@ -318,7 +401,7 @@ function StandaloneProvider({ createController, addToast, firebaseConfig, emulat
|
|
|
318
401
|
cancelled = true;
|
|
319
402
|
cleanup == null ? void 0 : cleanup();
|
|
320
403
|
};
|
|
321
|
-
}, [firebaseConfig, emulator,
|
|
404
|
+
}, [firebaseConfig, emulator, resolvedTenant]);
|
|
322
405
|
const value = (0, import_react3.useMemo)(
|
|
323
406
|
() => ({
|
|
324
407
|
createController,
|
|
@@ -332,7 +415,8 @@ function StandaloneProvider({ createController, addToast, firebaseConfig, emulat
|
|
|
332
415
|
handleLogout: () => {
|
|
333
416
|
},
|
|
334
417
|
hostedByCore: false,
|
|
335
|
-
observability: new NullObservabilityAdapter()
|
|
418
|
+
observability: new NullObservabilityAdapter(),
|
|
419
|
+
rateLimits: {}
|
|
336
420
|
}),
|
|
337
421
|
[createController, toast, subscribe, unsubscribe]
|
|
338
422
|
);
|
|
@@ -377,10 +461,99 @@ function DevAutoLogin({ actions, devUser, children }) {
|
|
|
377
461
|
}, [dispatch, hostedByCore, token, actions, devUser]);
|
|
378
462
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children });
|
|
379
463
|
}
|
|
464
|
+
|
|
465
|
+
// src/federation/groupMenuSections.ts
|
|
466
|
+
function groupMenuSections(manifests) {
|
|
467
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
468
|
+
const groupMap = /* @__PURE__ */ new Map();
|
|
469
|
+
const topLevel = [];
|
|
470
|
+
for (const manifest of manifests) {
|
|
471
|
+
const fallbackGroup = manifest.menuGroup;
|
|
472
|
+
for (const section of (_a = manifest.menuSections) != null ? _a : []) {
|
|
473
|
+
const groupName = (_b = section.group) != null ? _b : fallbackGroup == null ? void 0 : fallbackGroup.name;
|
|
474
|
+
if (!groupName) {
|
|
475
|
+
topLevel.push({
|
|
476
|
+
key: `${manifest.name}:${section.label}`,
|
|
477
|
+
label: section.label,
|
|
478
|
+
icon: section.icon,
|
|
479
|
+
order: (_c = section.order) != null ? _c : 999,
|
|
480
|
+
children: section.items.map((item) => ({ kind: "item", item }))
|
|
481
|
+
});
|
|
482
|
+
continue;
|
|
483
|
+
}
|
|
484
|
+
let groupNode = groupMap.get(groupName);
|
|
485
|
+
if (!groupNode) {
|
|
486
|
+
groupNode = {
|
|
487
|
+
key: `group:${groupName}`,
|
|
488
|
+
label: groupName,
|
|
489
|
+
icon: (_d = fallbackGroup == null ? void 0 : fallbackGroup.icon) != null ? _d : section.icon,
|
|
490
|
+
order: (_f = (_e = fallbackGroup == null ? void 0 : fallbackGroup.order) != null ? _e : section.order) != null ? _f : 999,
|
|
491
|
+
children: []
|
|
492
|
+
};
|
|
493
|
+
groupMap.set(groupName, groupNode);
|
|
494
|
+
} else if (!groupNode.icon) {
|
|
495
|
+
const candidate = (_g = fallbackGroup == null ? void 0 : fallbackGroup.icon) != null ? _g : section.icon;
|
|
496
|
+
if (candidate) groupNode.icon = candidate;
|
|
497
|
+
}
|
|
498
|
+
if (section.flatten) {
|
|
499
|
+
for (const item of section.items) {
|
|
500
|
+
groupNode.children.push({ kind: "item", item, order: section.order });
|
|
501
|
+
}
|
|
502
|
+
} else {
|
|
503
|
+
const existing = groupNode.children.find(
|
|
504
|
+
(c) => c.kind === "section" && c.label === section.label
|
|
505
|
+
);
|
|
506
|
+
if (existing) {
|
|
507
|
+
existing.items = [...existing.items, ...section.items];
|
|
508
|
+
if (!existing.icon && section.icon) existing.icon = section.icon;
|
|
509
|
+
if (section.order != null && (existing.order == null || section.order < existing.order)) {
|
|
510
|
+
existing.order = section.order;
|
|
511
|
+
}
|
|
512
|
+
} else {
|
|
513
|
+
groupNode.children.push({
|
|
514
|
+
kind: "section",
|
|
515
|
+
label: section.label,
|
|
516
|
+
icon: section.icon,
|
|
517
|
+
items: [...section.items],
|
|
518
|
+
order: section.order
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
for (const node of groupMap.values()) {
|
|
525
|
+
node.children.sort((a, b) => {
|
|
526
|
+
var _a2, _b2, _c2, _d2;
|
|
527
|
+
const oa = (_a2 = a.order) != null ? _a2 : 999;
|
|
528
|
+
const ob = (_b2 = b.order) != null ? _b2 : 999;
|
|
529
|
+
if (oa !== ob) return oa - ob;
|
|
530
|
+
const la = a.kind === "section" ? a.label : (_c2 = a.item.label) != null ? _c2 : "";
|
|
531
|
+
const lb = b.kind === "section" ? b.label : (_d2 = b.item.label) != null ? _d2 : "";
|
|
532
|
+
return la.localeCompare(lb);
|
|
533
|
+
});
|
|
534
|
+
for (const child of node.children) {
|
|
535
|
+
if (child.kind === "section") {
|
|
536
|
+
child.items.sort((a, b) => {
|
|
537
|
+
var _a2, _b2, _c2, _d2;
|
|
538
|
+
const oa = (_a2 = a.order) != null ? _a2 : 999;
|
|
539
|
+
const ob = (_b2 = b.order) != null ? _b2 : 999;
|
|
540
|
+
if (oa !== ob) return oa - ob;
|
|
541
|
+
return ((_c2 = a.label) != null ? _c2 : "").localeCompare((_d2 = b.label) != null ? _d2 : "");
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
const all = [...topLevel, ...groupMap.values()];
|
|
547
|
+
all.sort((a, b) => a.order - b.order || a.label.localeCompare(b.label));
|
|
548
|
+
return all;
|
|
549
|
+
}
|
|
380
550
|
// Annotate the CommonJS export names for ESM import in node:
|
|
381
551
|
0 && (module.exports = {
|
|
382
552
|
DevAutoLogin,
|
|
383
553
|
FederatedBridge,
|
|
384
554
|
StandaloneProvider,
|
|
385
|
-
createReducersBundle
|
|
555
|
+
createReducersBundle,
|
|
556
|
+
createReducersFromManifest,
|
|
557
|
+
groupMenuSections,
|
|
558
|
+
isHostedByCore
|
|
386
559
|
});
|