@oondemand/oon-core-front 0.1.0

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.
@@ -0,0 +1,533 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+ import * as _tanstack_react_query from '@tanstack/react-query';
4
+ import { AxiosInstance } from 'axios';
5
+
6
+ /** Tipos de campo emitidos pelo `fields` do back (Seção 2.4). */
7
+ type FieldKind = "string" | "number" | "boolean" | "date" | "ref" | "enum" | "currency" | "currencyCode" | "currencyConverted" | "raw";
8
+ /** Metadata de um campo de model, vinda de `metaFields` no back. */
9
+ interface FieldMeta {
10
+ name: string;
11
+ kind: FieldKind;
12
+ label?: string;
13
+ searchable?: boolean;
14
+ /** model referenciada quando kind === "ref". */
15
+ ref?: string;
16
+ /** valores possíveis quando kind === "enum". */
17
+ options?: string[];
18
+ /** moeda base quando kind === "currencyConverted". */
19
+ base?: string;
20
+ }
21
+ /** Resumo de uma model (resposta de /core/models e /core/models/:name). */
22
+ interface ModelSummary {
23
+ name: string;
24
+ singular: string;
25
+ /** basePath em que o CRUD está montado no back (ex.: "/cotacoes"). */
26
+ basePath: string;
27
+ crud: boolean;
28
+ roles: {
29
+ read?: string[];
30
+ write?: string[];
31
+ };
32
+ fields: FieldMeta[];
33
+ searchable: string[];
34
+ }
35
+ interface MenuMeta {
36
+ label: string;
37
+ href?: string;
38
+ icon?: string;
39
+ section?: string;
40
+ order?: number;
41
+ permissions?: string[];
42
+ }
43
+ /** Resposta completa de GET /core/metadata. */
44
+ interface CoreMetadata {
45
+ service: {
46
+ name: string;
47
+ version: string;
48
+ };
49
+ models: ModelSummary[];
50
+ collections: unknown[];
51
+ documents: unknown[];
52
+ pipelines: unknown[];
53
+ integrations: unknown[];
54
+ features: unknown[];
55
+ menus: MenuMeta[];
56
+ }
57
+ interface Pagination {
58
+ currentPage: number;
59
+ totalPages: number;
60
+ totalItems: number;
61
+ itemsPerPage: number;
62
+ }
63
+ interface PaginatedResult<T = Record<string, unknown>> {
64
+ results: T[];
65
+ pagination: Pagination;
66
+ }
67
+ interface ListParams {
68
+ pageIndex?: number;
69
+ pageSize?: number;
70
+ searchTerm?: string;
71
+ /** ex.: "nome.asc" | "criadoEm.desc" */
72
+ sort?: string;
73
+ /** filtros adicionais viram query string. */
74
+ [filter: string]: unknown;
75
+ }
76
+ /** Erro normalizado (errorNormalizer). */
77
+ interface OonError {
78
+ code: string;
79
+ message: string;
80
+ status?: number;
81
+ details?: unknown;
82
+ requestId?: string;
83
+ }
84
+ /** Origem de auditoria enviada nos headers x-oon-* das mutações. */
85
+ type AuditOrigin = "datagrid" | "form" | "workflow" | "assistant" | "import" | "integration";
86
+ interface AuditContext {
87
+ origem?: AuditOrigin;
88
+ module?: string;
89
+ entity?: string;
90
+ }
91
+ interface OonUser {
92
+ tipo: string;
93
+ nome: string;
94
+ email: string;
95
+ [extra: string]: unknown;
96
+ }
97
+ interface OonAppConfig {
98
+ id: string;
99
+ name: string;
100
+ title?: string;
101
+ logo?: string;
102
+ favicon?: string;
103
+ version?: string;
104
+ }
105
+ interface OonApiConfig {
106
+ baseUrl: string;
107
+ assistantBaseUrl?: string;
108
+ meusAppsUrl?: string;
109
+ /** Prefixo de versão concatenado às chamadas. Default: "". */
110
+ versionPrefix?: string;
111
+ timeout?: number;
112
+ }
113
+ interface OonAuthConfig {
114
+ mode?: "bearer" | "cookie" | "external-sso";
115
+ /** URL de login externo (Meus Apps) para redirect quando sem token. */
116
+ loginUrl?: string;
117
+ /** Nome do query param que carrega o token na volta do SSO. Default: "code". */
118
+ tokenParam?: string;
119
+ }
120
+ interface OonSecurityConfig {
121
+ enableRouteGuard?: boolean;
122
+ enablePermissionGate?: boolean;
123
+ redactAssistantContext?: boolean;
124
+ disableConsoleInProduction?: boolean;
125
+ }
126
+ interface OonCoreFrontConfig {
127
+ app: OonAppConfig;
128
+ api: OonApiConfig;
129
+ auth?: OonAuthConfig;
130
+ theme?: Record<string, unknown>;
131
+ modules?: OonModule[];
132
+ /**
133
+ * Declaração de UI no estilo `central.ui.json` (Seção 9). Atalho para
134
+ * registrar coleções/documentos/esteiras sem escrever um módulo inteiro.
135
+ */
136
+ ui?: OonUiManifest;
137
+ security?: OonSecurityConfig;
138
+ /** Elemento DOM onde montar. Default: #root. */
139
+ rootElementId?: string;
140
+ }
141
+ interface OonRoute {
142
+ path: string;
143
+ element: ReactNode;
144
+ /** rota pública não passa pelo RouteGuard. */
145
+ public?: boolean;
146
+ permissions?: string[];
147
+ }
148
+ interface OonMenuItem {
149
+ label: string;
150
+ href: string;
151
+ icon?: ReactNode;
152
+ section?: string;
153
+ order?: number;
154
+ permissions?: string[];
155
+ }
156
+ interface OonModule {
157
+ id: string;
158
+ label: string;
159
+ version?: string;
160
+ routes?: OonRoute[];
161
+ menu?: OonMenuItem[];
162
+ /** views declarativas que o Core transforma em rota + menu. */
163
+ views?: OonViewDefinition[];
164
+ }
165
+ type CollectionMode = "full" | "minimal" | "dynamic";
166
+ interface OonColumnDef {
167
+ field: string;
168
+ label?: string;
169
+ /** kind sobrescreve o inferido da metadata. */
170
+ kind?: FieldKind;
171
+ sortable?: boolean;
172
+ width?: number;
173
+ }
174
+ interface OonFormFieldDef {
175
+ field: string;
176
+ label?: string;
177
+ kind?: FieldKind;
178
+ required?: boolean;
179
+ options?: string[];
180
+ }
181
+ /** Definição de uma coleção nas três formas da Seção 4.4. */
182
+ interface CollectionViewDef {
183
+ type: "collection";
184
+ /** id de rota/menu; default = model em minúsculas. */
185
+ id?: string;
186
+ model: string;
187
+ label?: string;
188
+ path?: string;
189
+ icon?: ReactNode;
190
+ section?: string;
191
+ /** "dynamic" monta tudo a partir de /core/models/:model. */
192
+ mode?: CollectionMode;
193
+ /** modo "full": colunas explícitas. */
194
+ columns?: OonColumnDef[];
195
+ /** modo "full": campos de formulário explícitos. */
196
+ form?: OonFormFieldDef[];
197
+ importExport?: boolean;
198
+ permissions?: string[];
199
+ }
200
+ interface DocumentViewDef {
201
+ type: "document";
202
+ id?: string;
203
+ model: string;
204
+ label?: string;
205
+ path?: string;
206
+ icon?: ReactNode;
207
+ section?: string;
208
+ approval?: boolean;
209
+ attachments?: boolean;
210
+ permissions?: string[];
211
+ }
212
+ interface PipelineViewDef {
213
+ type: "pipeline";
214
+ id?: string;
215
+ /** model dos cards (tickets). */
216
+ model: string;
217
+ label?: string;
218
+ path?: string;
219
+ icon?: ReactNode;
220
+ section?: string;
221
+ /** campo do registro que define a etapa/coluna. */
222
+ stageField?: string;
223
+ /** etapas fixas; se omitido, derivadas do enum de stageField. */
224
+ stages?: Array<{
225
+ id: string;
226
+ label: string;
227
+ }>;
228
+ permissions?: string[];
229
+ }
230
+ interface DashboardViewDef {
231
+ type: "dashboard";
232
+ id?: string;
233
+ label?: string;
234
+ path?: string;
235
+ icon?: ReactNode;
236
+ section?: string;
237
+ widgets?: DashboardWidgetDef[];
238
+ }
239
+ interface DashboardWidgetDef {
240
+ id: string;
241
+ label: string;
242
+ /** model de onde puxar a contagem/agregação. */
243
+ model?: string;
244
+ kind?: "count" | "sum" | "custom";
245
+ /** campo somado quando kind === "sum". */
246
+ field?: string;
247
+ render?: () => ReactNode;
248
+ }
249
+ type OonViewDefinition = CollectionViewDef | DocumentViewDef | PipelineViewDef | DashboardViewDef;
250
+ interface OonUiManifest {
251
+ views: OonViewDefinition[];
252
+ }
253
+
254
+ /**
255
+ * Ponto de entrada único de uma Central (Seção 3.2). O `main.tsx` da Central
256
+ * só chama isto — não conhece providers, router, auth, layout nem serviços.
257
+ *
258
+ * import { start } from "@oondemand/oon-core-front";
259
+ * import { appConfig } from "./central.ui";
260
+ * start(appConfig);
261
+ */
262
+ declare function start(config: OonCoreFrontConfig): void;
263
+ /** Alias namespaced, compatível com a doc (`oonCoreFront.start`). */
264
+ declare const oonCoreFront: {
265
+ start: typeof start;
266
+ };
267
+
268
+ /**
269
+ * Schema do `central.ui.json` (Seção 9 do escopo). É o que o frontend
270
+ * consumidor gerado pelo `create-central-oon` carrega — declaração pura, sem
271
+ * código de UI. O Core converte isto em `OonCoreFrontConfig`.
272
+ */
273
+ interface CentralUiManifest {
274
+ name: string;
275
+ slug: string;
276
+ backend?: {
277
+ metadataUrl?: string;
278
+ };
279
+ navigation?: {
280
+ mode?: "auto" | "manual";
281
+ };
282
+ collections?: Array<{
283
+ model: string;
284
+ mode?: CollectionMode;
285
+ path?: string;
286
+ label?: string;
287
+ section?: string;
288
+ }>;
289
+ pipelines?: Array<{
290
+ name?: string;
291
+ model?: string;
292
+ mode?: string;
293
+ stageField?: string;
294
+ path?: string;
295
+ label?: string;
296
+ section?: string;
297
+ }>;
298
+ documents?: Array<{
299
+ model: string;
300
+ mode?: string;
301
+ path?: string;
302
+ label?: string;
303
+ section?: string;
304
+ approval?: boolean;
305
+ attachments?: boolean;
306
+ }>;
307
+ }
308
+ /** Dados de runtime que o `central.ui.json` não carrega (vêm do .env). */
309
+ interface ManifestRuntime {
310
+ apiBaseUrl: string;
311
+ meusAppsUrl?: string;
312
+ assistantBaseUrl?: string;
313
+ versionPrefix?: string;
314
+ }
315
+ /** Converte o manifesto declarativo + runtime em config do Core. */
316
+ declare function manifestToConfig(manifest: CentralUiManifest, runtime: ManifestRuntime): OonCoreFrontConfig;
317
+ /**
318
+ * Bootstrap a partir do `central.ui.json`. É a única linha que o `main.tsx` de
319
+ * uma Central gerada precisa:
320
+ *
321
+ * import manifest from "../central.ui.json";
322
+ * startFromManifest(manifest, { apiBaseUrl: import.meta.env.VITE_API_URL });
323
+ */
324
+ declare function startFromManifest(manifest: CentralUiManifest, runtime: ManifestRuntime): void;
325
+
326
+ /**
327
+ * Helpers declarativos (API pública da Seção 4.3). São identidades tipadas que
328
+ * fixam o `type` da view — servem para o autocomplete e para registrar a view
329
+ * num módulo ou no `ui.views` da config.
330
+ */
331
+ declare function defineCollectionView(def: Omit<CollectionViewDef, "type">): CollectionViewDef;
332
+ declare function defineDocumentView(def: Omit<DocumentViewDef, "type">): DocumentViewDef;
333
+ declare function definePipelineView(def: Omit<PipelineViewDef, "type">): PipelineViewDef;
334
+ declare function defineDashboard(def: Omit<DashboardViewDef, "type">): DashboardViewDef;
335
+ /** Açúcar para declarar um módulo com tipagem. */
336
+ declare function defineOonModule(mod: OonModule): OonModule;
337
+
338
+ interface CoreCollectionProps {
339
+ model: string;
340
+ label?: string;
341
+ /**
342
+ * Três formas de declarar a coleção (Seção 4.4):
343
+ * - "full" : colunas + form explícitos (passe `columns` e `form`).
344
+ * - "minimal" : só `model`; Core busca a metadata e deriva tudo.
345
+ * - "dynamic" : 100% dirigido por /core/models/:model (default).
346
+ */
347
+ mode?: CollectionMode;
348
+ /** basePath do recurso; default vem da metadata da model. */
349
+ endpoint?: string;
350
+ columns?: OonColumnDef[];
351
+ form?: OonFormFieldDef[];
352
+ importExport?: boolean;
353
+ }
354
+ /**
355
+ * Componente Core de coleção. Renderiza grid + form de qualquer model do back
356
+ * sem código de UI por entidade. No modo dinâmico, lê /core/models/:model e
357
+ * monta colunas, formulário e endpoint a partir da metadata — esse é o
358
+ * critério de pronto da Fase 3.
359
+ */
360
+ declare function CoreCollection({ model, label, mode, endpoint, columns, form, importExport }: CoreCollectionProps): react.JSX.Element;
361
+
362
+ interface CoreDocumentProps {
363
+ model: string;
364
+ label?: string;
365
+ endpoint?: string;
366
+ columns?: OonColumnDef[];
367
+ form?: OonFormFieldDef[];
368
+ /** liga ações de aprovar/reprovar (RESTful: /:id/actions/approve|reject). */
369
+ approval?: boolean;
370
+ /** liga gestão de anexos (futuro: /:id/files). */
371
+ attachments?: boolean;
372
+ }
373
+ /**
374
+ * Tipo documental. Hoje reusa a coleção genérica (list + CRUD). Quando
375
+ * `approval` está ligado, expõe o helper `approveDocument` para as ações
376
+ * RESTful do back (Seção 5.2) — documentos fiscais e cadastrais viram
377
+ * configuração, não páginas escritas à mão.
378
+ */
379
+ declare function CoreDocument({ model, label, endpoint, columns, form }: CoreDocumentProps): react.JSX.Element;
380
+
381
+ interface CorePipelineProps {
382
+ model: string;
383
+ label?: string;
384
+ endpoint?: string;
385
+ /** campo do registro que define a coluna/etapa. Default: "status". */
386
+ stageField?: string;
387
+ /** etapas fixas; se omitido, derivadas do enum de `stageField`. */
388
+ stages?: Array<{
389
+ id: string;
390
+ label: string;
391
+ }>;
392
+ /** campo exibido como título do card. Default: primeiro string. */
393
+ titleField?: string;
394
+ }
395
+ /**
396
+ * Esteira (kanban) genérica do Core. Agrupa registros por `stageField` em
397
+ * colunas. As etapas vêm das props ou são derivadas do enum declarado na
398
+ * metadata da model — nenhuma esteira específica hardcoded.
399
+ */
400
+ declare function CorePipeline({ model, label, endpoint, stageField, stages, titleField }: CorePipelineProps): react.JSX.Element;
401
+
402
+ interface CoreIntegrationProps {
403
+ label?: string;
404
+ }
405
+ /**
406
+ * Painel de integrações: lista o que o back declarou em /core/integrations e
407
+ * permite reprocessar via action RESTful (POST /integrations/actions/process-active).
408
+ */
409
+ declare function CoreIntegration({ label }: CoreIntegrationProps): react.JSX.Element;
410
+
411
+ interface CoreCurrencyProps {
412
+ /** model das moedas. Default: "Moeda". */
413
+ model?: string;
414
+ label?: string;
415
+ endpoint?: string;
416
+ columns?: OonColumnDef[];
417
+ }
418
+ /**
419
+ * Multi-moedas (módulo de domínio, Seção 4.6/2.11). Lista as moedas e expõe a
420
+ * ação RESTful de atualizar cotações (POST /<endpoint>/actions/update-rates).
421
+ */
422
+ declare function CoreCurrency({ model, label, endpoint, columns }: CoreCurrencyProps): react.JSX.Element;
423
+
424
+ interface CoreAssistantProps {
425
+ /** code do assistente registrado no back (ex.: "servicos-tomados.revisao"). */
426
+ assistantCode: string;
427
+ label?: string;
428
+ /** entidade de contexto (apenas tipo + id; nada sensível). */
429
+ entity?: {
430
+ type: string;
431
+ id: string;
432
+ };
433
+ /** base de assistentes; default usa o mesmo client REST do Core. */
434
+ endpoint?: string;
435
+ }
436
+ /**
437
+ * Assistente IA do Core (Seção 2.12 / 6.2). Envia ao back apenas
438
+ * assistantCode + entity + message — NUNCA chave de IA, modelo ou prompt.
439
+ * O back resolve modelo, prompt, chave e políticas.
440
+ */
441
+ declare function CoreAssistant({ assistantCode, label, entity, endpoint }: CoreAssistantProps): react.JSX.Element;
442
+
443
+ interface CoreDashboardProps {
444
+ label?: string;
445
+ widgets?: DashboardWidgetDef[];
446
+ }
447
+ /**
448
+ * Dashboard do Core: renderiza widgets registrados (count/sum por model ou
449
+ * render custom). Cache, loading e erro ficam no Core; a Central só declara.
450
+ */
451
+ declare function CoreDashboard({ label, widgets }: CoreDashboardProps): react.JSX.Element;
452
+
453
+ interface AuthContextValue {
454
+ user: OonUser | null;
455
+ roles: string[];
456
+ status: "loading" | "authenticated" | "unauthenticated";
457
+ isAuthenticated: boolean;
458
+ hasPermission: (permission?: string | string[]) => boolean;
459
+ logout: () => void;
460
+ }
461
+ declare function useOonAuth(): AuthContextValue;
462
+
463
+ /**
464
+ * Esconde a UI quando o usuário não tem a permissão. NÃO é segurança real
465
+ * (Seção 6.2, item 3) — o back é a autoridade. Serve apenas para não exibir
466
+ * ações/menus que o usuário não pode usar.
467
+ */
468
+ declare function PermissionGate({ permission, fallback, children, }: {
469
+ permission?: string | string[];
470
+ fallback?: ReactNode;
471
+ children: ReactNode;
472
+ }): react.JSX.Element;
473
+
474
+ /**
475
+ * SDK do contrato /core/* (introspecção dirigida por metadata). É o que
476
+ * permite o modo "dynamic" das coleções: o front monta grid/form/rotas a
477
+ * partir do que o back descreve, sem código de UI por entidade.
478
+ */
479
+ interface CoreClient {
480
+ metadata(): Promise<CoreMetadata>;
481
+ models(): Promise<ModelSummary[]>;
482
+ model(name: string): Promise<ModelSummary>;
483
+ permissions(): Promise<Array<{
484
+ resource: string;
485
+ action: string;
486
+ roles: string[];
487
+ }>>;
488
+ menus(): Promise<CoreMetadata["menus"]>;
489
+ }
490
+
491
+ /**
492
+ * SDK por recurso (Seção 2.5). Espelha o CRUD gerado pelo back em `basePath`:
493
+ * GET / -> list (paginado)
494
+ * GET /:id -> get
495
+ * POST / -> create
496
+ * PUT /:id -> update
497
+ * PATCH /:id -> patch
498
+ * DELETE /:id -> delete
499
+ * POST /import -> importMany
500
+ * GET /export -> exportAll
501
+ *
502
+ * O back devolve registro único na chave do singular (`{ [singular]: {...} }`);
503
+ * `unwrap` extrai o primeiro valor não-meta para o consumidor não precisar
504
+ * conhecer o singular.
505
+ */
506
+ interface ResourceClient<T = Record<string, unknown>> {
507
+ list(params?: ListParams): Promise<PaginatedResult<T>>;
508
+ get(id: string): Promise<T>;
509
+ create(body: Partial<T>, audit?: AuditContext): Promise<T>;
510
+ update(id: string, body: Partial<T>, audit?: AuditContext): Promise<T>;
511
+ patch(id: string, body: Partial<T>, audit?: AuditContext): Promise<T>;
512
+ delete(id: string, audit?: AuditContext): Promise<T>;
513
+ importMany(rows: unknown[], audit?: AuditContext): Promise<{
514
+ inserted?: number;
515
+ [k: string]: unknown;
516
+ }>;
517
+ exportAll(params?: ListParams): Promise<T[]>;
518
+ }
519
+
520
+ interface ApiContextValue {
521
+ http: AxiosInstance;
522
+ core: CoreClient;
523
+ resource: <T = Record<string, unknown>>(basePath: string) => ResourceClient<T>;
524
+ }
525
+ declare function useOonApi(): ApiContextValue;
526
+ /** Cliente de um recurso, memoizado pelo basePath. */
527
+ declare function useOonResource<T = Record<string, unknown>>(basePath: string): ResourceClient<T>;
528
+ /** Metadata completa do back (cache de 5 min). */
529
+ declare function useCoreMetadata(): _tanstack_react_query.UseQueryResult<NoInfer<CoreMetadata>, Error>;
530
+ /** Descrição de uma model específica — base do modo "dynamic". */
531
+ declare function useModelSchema(name: string): _tanstack_react_query.UseQueryResult<NoInfer<ModelSummary>, Error>;
532
+
533
+ export { type CentralUiManifest, type CollectionMode, type CollectionViewDef, CoreAssistant, CoreCollection, CoreCurrency, CoreDashboard, CoreDocument, CoreIntegration, type CoreMetadata, CorePipeline, type DashboardViewDef, type DashboardWidgetDef, type DocumentViewDef, type FieldKind, type FieldMeta, type ListParams, type ManifestRuntime, type ModelSummary, type OonApiConfig, type OonAppConfig, type OonAuthConfig, type OonColumnDef, type OonCoreFrontConfig, type OonError, type OonFormFieldDef, type OonMenuItem, type OonModule, type OonRoute, type OonSecurityConfig, type OonUiManifest, type OonUser, type OonViewDefinition, type PaginatedResult, type Pagination, PermissionGate, type PipelineViewDef, defineCollectionView, defineDashboard, defineDocumentView, defineOonModule, definePipelineView, manifestToConfig, oonCoreFront, start, startFromManifest, useCoreMetadata, useModelSchema, useOonApi, useOonAuth, useOonResource };