@oondemand/oon-core-back 0.5.6 → 0.6.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oondemand/oon-core-back",
3
- "version": "0.5.6",
3
+ "version": "0.6.1",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/oondemand/oon-platform.git",
@@ -9,8 +9,7 @@
9
9
  "description": "Core runtime para Centrais Oon: Model Registry, CRUD/RBAC automáticos, módulos opinativos e capabilities nativas.",
10
10
  "main": "src/index.js",
11
11
  "bin": {
12
- "oonCore-back": "bin/cli.js",
13
- "oonCore-integration-worker": "bin/integration-worker.js"
12
+ "oonCore-back": "bin/cli.js"
14
13
  },
15
14
  "files": [
16
15
  "bin",
@@ -261,7 +261,6 @@ router.get("/metadata", (_req, res) => {
261
261
  collections: registry.listCollections(),
262
262
  documents: registry.listDocuments(),
263
263
  pipelines: registry.listPipelines(),
264
- integrations: registry.listIntegrations(),
265
264
  features: registry.listFeatures(),
266
265
  menus: registry.listMenus(),
267
266
  });
@@ -276,7 +275,6 @@ router.get("/models/:name", (req, res) => {
276
275
  router.get("/collections", (_req, res) => res.json({ results: registry.listCollections() }));
277
276
  router.get("/documents", (_req, res) => res.json({ results: registry.listDocuments() }));
278
277
  router.get("/pipelines", (_req, res) => res.json({ results: registry.listPipelines() }));
279
- router.get("/integrations", (_req, res) => res.json({ results: registry.listIntegrations() }));
280
278
  router.get("/permissions", (_req, res) => {
281
279
  const permissions = registry.listModels().flatMap((entry) => {
282
280
  const roles = entry.definition.crud?.roles || {};
@@ -9,7 +9,6 @@ const correlationId = require("../core/middlewares/correlationId");
9
9
  const requestLog = require("../core/middlewares/requestLog");
10
10
  const errorMiddleware = require("../core/middlewares/error");
11
11
  const { buildModelRouter } = require("../core/factories/modelRouter");
12
- const { buildIntegrationRouter, integrationsEnabled } = require("../modules/integrations");
13
12
 
14
13
  const coreRoutes = require("../api/core.routes");
15
14
  const accessRoutes = require("../api/access.routes");
@@ -59,12 +58,6 @@ function createApp() {
59
58
  app.use("/core", coreRoutes);
60
59
  if (transactionalEmail.enabled()) app.use("/core/transactional-email", transactionalEmail.buildRouter());
61
60
 
62
- if (integrationsEnabled(ctx.config)) {
63
- const integrationRouter = buildIntegrationRouter();
64
- app.use("/integrations", integrationRouter);
65
- app.use("/integracoes", integrationRouter);
66
- }
67
-
68
61
  app.use(requestLog);
69
62
 
70
63
  for (const entry of registry.listModels()) {
@@ -1,9 +1,5 @@
1
1
  const mongoose = require("mongoose");
2
2
  const registry = require("../core/registry");
3
- const ctx = require("../core/context");
4
- const { getIntegrationModels } = require("../modules/integrations/models");
5
- const { listIntegrationProviders } = require("../modules/integrations/registry");
6
- const { getOmieModels, omieEnabled } = require("../modules/omie");
7
3
 
8
4
  function buildMongoUri() {
9
5
  const cfg = {
@@ -73,38 +69,10 @@ async function syncDeclaredIndexes(entries = registry.listModels()) {
73
69
  return results;
74
70
  }
75
71
 
76
- async function syncTechnicalIndexes() {
77
- const integrationsEnabled = Boolean(
78
- ctx.config.appManifest?.modules?.integrations
79
- || ctx.config.modules?.integrations
80
- || listIntegrationProviders().length,
81
- );
82
- if (!shouldSyncDeclaredIndexes() || !integrationsEnabled) return [];
83
-
84
- const models = Object.values(getIntegrationModels());
85
- if (omieEnabled(ctx.config)) models.push(...Object.values(getOmieModels()));
86
-
87
- const results = [];
88
- for (const model of models) {
89
- const dropped = await model.syncIndexes();
90
- const normalized = Array.isArray(dropped) ? dropped : [];
91
- results.push({ model: model.modelName, dropped: normalized });
92
- if (normalized.length) {
93
- console.log(`[OonCore] Índices técnicos obsoletos removidos de ${model.modelName}: ${normalized.join(", ")}`);
94
- }
95
- }
96
- return results;
97
- }
98
-
99
- async function syncIntegrationIndexes() {
100
- return syncTechnicalIndexes();
101
- }
102
-
103
72
  async function connectDB() {
104
73
  const uri = buildMongoUri();
105
74
  await mongoose.connect(uri, connectionOptions());
106
75
  await syncDeclaredIndexes();
107
- await syncTechnicalIndexes();
108
76
  console.log(`Conectado ao MongoDB (${databaseLabel(uri)})`);
109
77
  return mongoose.connection;
110
78
  }
@@ -116,6 +84,4 @@ module.exports = {
116
84
  databaseLabel,
117
85
  shouldSyncDeclaredIndexes,
118
86
  syncDeclaredIndexes,
119
- syncIntegrationIndexes,
120
- syncTechnicalIndexes,
121
87
  };
@@ -15,7 +15,6 @@ const {
15
15
  PROCESS_MANIFEST_FILENAME,
16
16
  loadProcessManifest,
17
17
  } = require("../manifest/processManifest");
18
- const { ensureOmieProviderRegistered } = require("../modules/omie");
19
18
 
20
19
  const DOMAIN_DIRS = [
21
20
  "models",
@@ -24,8 +23,6 @@ const DOMAIN_DIRS = [
24
23
  "routes",
25
24
  "pipelines",
26
25
  "documents",
27
- "integrations",
28
- "mappings",
29
26
  "hooks",
30
27
  ];
31
28
 
@@ -105,9 +102,6 @@ function loadCentral(cwd = process.cwd()) {
105
102
  if (fs.existsSync(full)) requireDir(full);
106
103
  }
107
104
 
108
- // O adaptador nativo é montado depois das declarações da Central. Assim,
109
- // endpoints, mappings, listas e ações permanecem fora do pacote técnico.
110
- ensureOmieProviderRegistered(ctx.config);
111
105
  return ctx.config;
112
106
  }
113
107
 
@@ -58,7 +58,7 @@ function pdfError(message, options) {
58
58
  return new PdfRenderingError(message, options);
59
59
  }
60
60
 
61
- function providerConfig() {
61
+ function implementationConfig() {
62
62
  const baseUrl = String(process.env.OON_CAPABILITY_PDF_RENDERING_URL || "").replace(/\/+$/, "");
63
63
  if (!baseUrl) throw pdfError("A capability pdfRendering não está resolvida neste ambiente.", {
64
64
  code: "PDF_RENDERING_UNAVAILABLE", statusCode: 503,
@@ -75,7 +75,7 @@ function validatePdf(input) {
75
75
  const pdf = Buffer.isBuffer(input) ? input : Buffer.from(input || "");
76
76
  const maxBytes = numberLimit("OON_PDF_RENDERING_MAX_OUTPUT_BYTES", 20 * 1024 * 1024);
77
77
  if (pdf.length < 8 || pdf.length > maxBytes || !pdf.subarray(0, 5).equals(Buffer.from("%PDF-"))) {
78
- throw pdfError("O provider retornou um PDF inválido ou acima do limite.", {
78
+ throw pdfError("A implementação retornou um PDF inválido ou acima do limite.", {
79
79
  code: "PDF_RENDERING_INVALID_OUTPUT", details: { outputBytes: pdf.length, maxBytes },
80
80
  });
81
81
  }
@@ -88,7 +88,7 @@ function traceContext(context = {}) {
88
88
  tenantId: String(context.tenantId || "unknown").slice(0, 128),
89
89
  appCode: String(context.appCode || process.env.APP_CODE || "unknown").slice(0, 128),
90
90
  environment: String(context.environment || process.env.APP_ENVIRONMENT || "unknown").slice(0, 64),
91
- integrationTicketId: String(context.integrationTicketId || "").slice(0, 128),
91
+ operationId: String(context.operationId || "").slice(0, 128),
92
92
  };
93
93
  }
94
94
 
@@ -109,11 +109,11 @@ function formFor(html, options) {
109
109
  }
110
110
 
111
111
  function defaultTransport({ html, options, trace, signal, fetchImpl = globalThis.fetch }) {
112
- const provider = providerConfig();
113
- return fetchImpl(`${provider.baseUrl}/forms/chromium/convert/html`, {
112
+ const implementation = implementationConfig();
113
+ return fetchImpl(`${implementation.baseUrl}/forms/chromium/convert/html`, {
114
114
  method: "POST",
115
115
  headers: {
116
- authorization: `Basic ${Buffer.from(`${provider.username}:${provider.password}`).toString("base64")}`,
116
+ authorization: `Basic ${Buffer.from(`${implementation.username}:${implementation.password}`).toString("base64")}`,
117
117
  "Gotenberg-Trace": trace.correlationId,
118
118
  "X-Oon-App-Code": trace.appCode,
119
119
  "X-Oon-Environment": trace.environment,
@@ -161,11 +161,11 @@ async function render(input = {}, context = {}) {
161
161
  await acquire();
162
162
  try {
163
163
  const response = await configuredTransport({ html, options, trace, signal: controller.signal, fetchImpl: context.fetchImpl });
164
- if (!response?.ok) throw pdfError(`Provider de pdfRendering indisponível (HTTP ${response?.status || 502}).`, {
165
- code: "PDF_RENDERING_PROVIDER_ERROR", statusCode: 502,
164
+ if (!response?.ok) throw pdfError(`Implementação de pdfRendering indisponível (HTTP ${response?.status || 502}).`, {
165
+ code: "PDF_RENDERING_IMPLEMENTATION_ERROR", statusCode: 502,
166
166
  });
167
167
  const pdf = validatePdf(Buffer.from(await response.arrayBuffer()));
168
- console.info(JSON.stringify({ event: "pdfRendering.completed", ...trace, durationMs: Date.now() - startedAt, inputBytes, outputBytes: pdf.length, providerVersion: process.env.OON_CAPABILITY_PDF_RENDERING_VERSION || "unknown" }));
168
+ console.info(JSON.stringify({ event: "pdfRendering.completed", ...trace, durationMs: Date.now() - startedAt, inputBytes, outputBytes: pdf.length, implementationVersion: process.env.OON_CAPABILITY_PDF_RENDERING_VERSION || "unknown" }));
169
169
  return pdf;
170
170
  } catch (error) {
171
171
  const normalized = error instanceof PdfRenderingError ? error : pdfError(
@@ -149,10 +149,6 @@ function definePipeline(name, config) {
149
149
  return registry.registerPipeline(name, { name, ...config });
150
150
  }
151
151
 
152
- function defineOmieMapping(name, config) {
153
- return registry.registerOmieMapping(name, { name, ...config });
154
- }
155
-
156
152
  function defineRoutes(basePath, builder) {
157
153
  const expressRouter = express.Router();
158
154
 
@@ -196,6 +192,5 @@ module.exports = {
196
192
  defineCollection,
197
193
  defineDocument,
198
194
  definePipeline,
199
- defineOmieMapping,
200
195
  defineRoutes,
201
- };
196
+ };
@@ -1,20 +1,12 @@
1
1
  const mongoose = require("mongoose");
2
2
 
3
3
  /**
4
- * Configuração singleton da Central (chaves de integração, remetente, etc.).
4
+ * Configuração singleton da Central. Credenciais funcionais pertencem às
5
+ * capabilities ou ao domínio do app, nunca a adaptadores nativos do Core.
5
6
  * Model interna do Core. O cliente estende via `central.config.js`.
6
7
  */
7
- const omieSchema = new mongoose.Schema(
8
- {
9
- id_conta_corrente: { type: Number },
10
- codigo_categoria: { type: String },
11
- },
12
- { _id: false }
13
- );
14
-
15
8
  const sistemaSchema = new mongoose.Schema(
16
9
  {
17
- omie: omieSchema,
18
10
  openIaKey: String,
19
11
  appKey: String,
20
12
  sendgrid_api_key: { type: String },
@@ -15,8 +15,6 @@ const store = {
15
15
  collections: new Map(),
16
16
  documents: new Map(),
17
17
  pipelines: new Map(),
18
- omieMappings: new Map(),
19
- integrations: new Map(),
20
18
  menus: [],
21
19
  features: new Map(),
22
20
  };
@@ -82,8 +80,6 @@ function reset() {
82
80
  store.collections.clear();
83
81
  store.documents.clear();
84
82
  store.pipelines.clear();
85
- store.omieMappings.clear();
86
- store.integrations.clear();
87
83
  store.menus.length = 0;
88
84
  store.features.clear();
89
85
  }
@@ -105,10 +101,6 @@ module.exports = {
105
101
  listDocuments: simpleList("documents"),
106
102
  registerPipeline: simpleRegister("pipelines"),
107
103
  listPipelines: simpleList("pipelines"),
108
- registerOmieMapping: simpleRegister("omieMappings"),
109
- listOmieMappings: simpleList("omieMappings"),
110
- registerIntegration: simpleRegister("integrations"),
111
- listIntegrations: simpleList("integrations"),
112
104
  registerFeature: simpleRegister("features"),
113
105
  listFeatures: simpleList("features"),
114
106
  registerMenu,
@@ -31,8 +31,6 @@ const DEFAULTS = {
31
31
  DB_USER: "",
32
32
  DB_PASSWORD: "",
33
33
  JWT_SECRET: "",
34
- OMIE_APP_KEY: "",
35
- OMIE_APP_SECRET: "",
36
34
  CENTRAL_ATIVACAO_URL: "",
37
35
  MEUS_APPS_BACKEND_URL: "",
38
36
  APP_CODE: "",
@@ -8,5 +8,3 @@ stringData:
8
8
  DB_USER: "${DB_USER}"
9
9
  DB_PASSWORD: "${DB_PASSWORD}"
10
10
  JWT_SECRET: "${JWT_SECRET}"
11
- OMIE_APP_KEY: "${OMIE_APP_KEY}"
12
- OMIE_APP_SECRET: "${OMIE_APP_SECRET}"
package/src/index.js CHANGED
@@ -10,8 +10,6 @@ const tenancy = require("./core/tenancy");
10
10
  const GenericError = require("./core/errors/GenericError");
11
11
  const { requirePermission } = require("./core/middlewares/permissions");
12
12
  const rbacPolicy = require("./core/rbac/policy");
13
- const omieModule = require("./modules/omie");
14
- const integrations = require("./modules/integrations");
15
13
  const capabilities = require("./capabilities");
16
14
  const { operationalRequestHeaders } = require("./core/utils/instanceActivation");
17
15
  const appManifest = require("./manifest/appManifest");
@@ -27,7 +25,7 @@ module.exports = {
27
25
  start, createApp, activate,
28
26
  defineCentral: define.defineCentral, defineModel: define.defineModel,
29
27
  defineCollection: define.defineCollection, defineDocument: define.defineDocument,
30
- definePipeline: define.definePipeline, defineOmieMapping: define.defineOmieMapping,
28
+ definePipeline: define.definePipeline,
31
29
  defineRoutes: define.defineRoutes, defineValidation: define.defineValidation,
32
30
  defineTrigger: define.defineTrigger,
33
31
  requirePermission, CORE_PERMISSIONS: rbacPolicy.CORE_PERMISSIONS,
@@ -75,19 +73,7 @@ module.exports = {
75
73
  assertDeleteAllowed: processRuntime.assertDeleteAllowed,
76
74
  recalculateDependents: processRuntime.recalculateDependents,
77
75
  drainProcessJobs: processRuntime.drainProcessJobs,
78
- fields, omie: omieModule.omie, omieModule,
79
- createOmieClient: omieModule.createOmieClient,
80
- OmieApiError: omieModule.OmieApiError,
81
- enqueueOmieCall: omieModule.enqueueOmieCall,
82
- ensureOmieProviderRegistered: omieModule.ensureOmieProviderRegistered,
83
- collectOmieDefinitions: omieModule.collectOmieDefinitions,
84
- describeOmieDefinitions: omieModule.describeOmieDefinitions,
85
- saveOmieConfiguration: omieModule.saveOmieConfiguration,
86
- listOmieConfigurations: omieModule.listOmieConfigurations,
87
- testOmieConnection: omieModule.testOmieConnection,
88
- integrations, registerIntegrationProvider: integrations.registerIntegrationProvider,
89
- enqueueIntegration: integrations.enqueueIntegration,
90
- receiveIntegrationWebhook: integrations.receiveWebhook,
76
+ fields,
91
77
  capabilities,
92
78
  operationalRequestHeaders,
93
79
  localDevelopment,
@@ -7,17 +7,15 @@ const corePackage = require("../../package.json");
7
7
  const { validateRbac } = require("./rbacManifest");
8
8
 
9
9
  const APP_MANIFEST_FILENAME = "central.app.json";
10
- const APP_MANIFEST_SCHEMA_VERSION = 1;
10
+ const APP_MANIFEST_SCHEMA_VERSION = 2;
11
11
  const SUPPORTED_APP_KINDS = Object.freeze(["root-central", "member-central", "portal-cockpit"]);
12
12
  const SUPPORTED_MODULES = Object.freeze([
13
- "collections", "documents", "pipelines", "integrations", "omie", "assistants", "currencies",
13
+ "collections", "documents", "pipelines", "assistants", "currencies",
14
14
  ]);
15
15
  const SUPPORTED_TENANCY_MODELS = Object.freeze(["none", "single_tenant", "multi_tenant"]);
16
16
  const SUPPORTED_AVAILABILITIES = Object.freeze(["system", "common", "licensed"]);
17
17
  const SUPPORTED_ACCESS_MODES = Object.freeze(["tenant_members", "explicit_users", "authenticated_users"]);
18
18
  const SUPPORTED_AUTHORIZATION_MODES = Object.freeze(["none", "rbac"]);
19
- // Compatibilidade de leitura para manifestos anteriores à separação das duas dimensões.
20
- const SUPPORTED_ACCESS_POLICIES = Object.freeze(["tenant_members", "explicit_users", "rbac"]);
21
19
  const SUPPORTED_DEPLOYMENT_MODES = Object.freeze(["singleton", "shared", "dedicated", "hybrid"]);
22
20
  const TRANSACTIONAL_EMAIL_CAPABILITY = "core.transactional-email";
23
21
  const EMAIL_SCOPE_POLICIES = Object.freeze(["app_only", "tenant_required", "tenant_override"]);
@@ -192,22 +190,13 @@ function validateDimension(value, field, supported, issues) {
192
190
  }
193
191
  }
194
192
 
195
- function legacyAccessDimensions(accessPolicy) {
196
- return {
197
- tenant_members: { accessMode: "tenant_members", authorizationMode: "none" },
198
- explicit_users: { accessMode: "explicit_users", authorizationMode: "none" },
199
- rbac: { accessMode: "explicit_users", authorizationMode: "rbac" },
200
- }[accessPolicy];
201
- }
202
-
203
193
  function dimensionsFor(manifest) {
204
194
  const defaults = APP_KIND_DIMENSIONS[manifest.appKind] || APP_KIND_DIMENSIONS["member-central"];
205
- const legacy = legacyAccessDimensions(manifest.accessPolicy) || {};
206
195
  return {
207
196
  tenancyModel: manifest.tenancyModel || defaults.tenancyModel,
208
197
  availability: manifest.availability || defaults.availability,
209
- accessMode: manifest.accessMode || legacy.accessMode || defaults.accessMode,
210
- authorizationMode: manifest.authorizationMode || legacy.authorizationMode || defaults.authorizationMode,
198
+ accessMode: manifest.accessMode || defaults.accessMode,
199
+ authorizationMode: manifest.authorizationMode || defaults.authorizationMode,
211
200
  deploymentMode: manifest.deploymentMode || defaults.deploymentMode,
212
201
  };
213
202
  }
@@ -219,7 +208,7 @@ function validateAppManifest(input, { coreVersion = corePackage.version } = {})
219
208
  }
220
209
  const allowedTopLevel = new Set([
221
210
  "$schema", "schemaVersion", "id", "name", "slug", "appKind",
222
- "tenancyModel", "availability", "accessMode", "authorizationMode", "accessPolicy", "deploymentMode",
211
+ "tenancyModel", "availability", "accessMode", "authorizationMode", "deploymentMode",
223
212
  "modules", "capabilities", "capabilitySettings", "compatibility", "activation", "auth", "rbac",
224
213
  ]);
225
214
  for (const key of Object.keys(input)) {
@@ -242,11 +231,7 @@ function validateAppManifest(input, { coreVersion = corePackage.version } = {})
242
231
  validateDimension(input.availability, "availability", SUPPORTED_AVAILABILITIES, issues);
243
232
  validateDimension(input.accessMode, "accessMode", SUPPORTED_ACCESS_MODES, issues);
244
233
  validateDimension(input.authorizationMode, "authorizationMode", SUPPORTED_AUTHORIZATION_MODES, issues);
245
- validateDimension(input.accessPolicy, "accessPolicy", SUPPORTED_ACCESS_POLICIES, issues);
246
234
  validateDimension(input.deploymentMode, "deploymentMode", SUPPORTED_DEPLOYMENT_MODES, issues);
247
- if (input.accessPolicy !== undefined && (input.accessMode !== undefined || input.authorizationMode !== undefined)) {
248
- addIssue(issues, "accessPolicy", "é legado e não pode ser combinado com accessMode/authorizationMode.");
249
- }
250
235
  const dimensions = dimensionsFor(input);
251
236
  const role = APP_KIND_ROLE[input.appKind];
252
237
  if (role === "root" && (
@@ -383,7 +368,6 @@ module.exports = {
383
368
  SUPPORTED_AVAILABILITIES,
384
369
  SUPPORTED_ACCESS_MODES,
385
370
  SUPPORTED_AUTHORIZATION_MODES,
386
- SUPPORTED_ACCESS_POLICIES,
387
371
  SUPPORTED_DEPLOYMENT_MODES,
388
372
  TRANSACTIONAL_EMAIL_CAPABILITY,
389
373
  EMAIL_SCOPE_POLICIES,
@@ -391,7 +375,6 @@ module.exports = {
391
375
  AppManifestError,
392
376
  parseVersion,
393
377
  compareVersions,
394
- legacyAccessDimensions,
395
378
  dimensionsFor,
396
379
  validateAppManifest,
397
380
  resolveAppManifestPath,
@@ -1,31 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
-
4
- const { runIntegrationWorker } = require("../src/modules/integrations");
5
-
6
- function flag(name) {
7
- const args = process.argv.slice(2);
8
- const index = args.indexOf(name);
9
- if (index < 0) return undefined;
10
- const value = args[index + 1];
11
- return value && !value.startsWith("--") ? value : true;
12
- }
13
-
14
- function positive(value) {
15
- if (value == null || value === true) return undefined;
16
- const parsed = Number(value);
17
- if (!Number.isFinite(parsed) || parsed <= 0) throw new Error(`Valor inválido: ${value}.`);
18
- return parsed;
19
- }
20
-
21
- runIntegrationWorker({
22
- cwd: process.cwd(),
23
- once: flag("--once") === true,
24
- intervalMs: positive(flag("--interval")),
25
- batchSize: positive(flag("--batch")),
26
- webhookBatchSize: positive(flag("--webhook-batch")),
27
- provider: flag("--provider") === true ? undefined : flag("--provider"),
28
- }).catch((error) => {
29
- console.error(error?.message || error);
30
- process.exit(1);
31
- });
@@ -1,26 +0,0 @@
1
- "use strict";
2
-
3
- const registry = require("./registry");
4
- const runtime = require("./runtime");
5
- const sanitizer = require("./sanitizer");
6
- const models = require("./models");
7
- const worker = require("./worker");
8
- const { buildIntegrationRouter } = require("./routes");
9
-
10
- function integrationsEnabled(config = {}) {
11
- return Boolean(
12
- config.appManifest?.modules?.integrations
13
- || config.modules?.integrations
14
- || registry.listIntegrationProviders().length,
15
- );
16
- }
17
-
18
- module.exports = {
19
- ...registry,
20
- ...runtime,
21
- ...sanitizer,
22
- ...models,
23
- ...worker,
24
- buildIntegrationRouter,
25
- integrationsEnabled,
26
- };
@@ -1,112 +0,0 @@
1
- "use strict";
2
-
3
- const mongoose = require("mongoose");
4
-
5
- const OUTBOX_STATUSES = ["Pendente", "Processando", "Erro temporário", "Concluído", "Erro definitivo", "Arquivado"];
6
- const INBOX_STATUSES = ["Pendente", "Processando", "Concluído", "Erro temporário", "Erro definitivo"];
7
- const EXECUTION_STATUSES = ["Executando", "Concluído", "Concluído com erros", "Erro"];
8
-
9
- function jsonField(defaultValue) {
10
- return { type: mongoose.Schema.Types.Mixed, default: defaultValue };
11
- }
12
-
13
- function leaseFields() {
14
- return {
15
- leaseId: { type: String, default: "", index: true },
16
- lockedAt: { type: Date, default: null },
17
- lockedBy: { type: String, default: "" },
18
- leaseExpiresAt: { type: Date, default: null, index: true },
19
- heartbeatAt: { type: Date, default: null },
20
- };
21
- }
22
-
23
- function model(name, schemaFactory, collection) {
24
- return mongoose.models[name] || mongoose.model(name, schemaFactory(), collection);
25
- }
26
-
27
- function outboxSchema() {
28
- const schema = new mongoose.Schema({
29
- provider: { type: String, required: true, index: true },
30
- handler: { type: String, required: true },
31
- resource: { type: String, default: "", index: true },
32
- operation: { type: String, default: "execute", index: true },
33
- aggregateType: { type: String, default: "", index: true },
34
- aggregateId: { type: String, default: "", index: true },
35
- idempotencyKey: { type: String, required: true, unique: true },
36
- payload: jsonField({}),
37
- status: { type: String, enum: OUTBOX_STATUSES, default: "Pendente", index: true },
38
- previousStatus: { type: String, default: "" },
39
- attempts: { type: Number, min: 0, default: 0 },
40
- nextAttemptAt: { type: Date, default: Date.now, index: true },
41
- lastError: jsonField({}),
42
- responseSummary: jsonField({}),
43
- completedAt: { type: Date, default: null },
44
- archivedAt: { type: Date, default: null },
45
- archiveReason: { type: String, default: "" },
46
- ...leaseFields(),
47
- }, { timestamps: true, minimize: false, strict: true });
48
- schema.index({ provider: 1, status: 1, nextAttemptAt: 1, createdAt: 1 });
49
- schema.index({ status: 1, leaseExpiresAt: 1 });
50
- return schema;
51
- }
52
-
53
- function inboxSchema() {
54
- const schema = new mongoose.Schema({
55
- provider: { type: String, required: true, index: true },
56
- resource: { type: String, default: "", index: true },
57
- eventType: { type: String, required: true, index: true },
58
- externalEventId: { type: String, default: "" },
59
- deduplicationKey: { type: String, required: true, unique: true },
60
- payloadHash: { type: String, required: true, index: true },
61
- payload: jsonField({}),
62
- metadata: jsonField({}),
63
- receivedAt: { type: Date, default: Date.now, index: true },
64
- status: { type: String, enum: INBOX_STATUSES, default: "Pendente", index: true },
65
- attempts: { type: Number, min: 0, default: 0 },
66
- nextAttemptAt: { type: Date, default: Date.now, index: true },
67
- processedAt: { type: Date, default: null },
68
- lastError: jsonField({}),
69
- ...leaseFields(),
70
- }, { timestamps: true, minimize: false, strict: true });
71
- schema.index({ provider: 1, status: 1, nextAttemptAt: 1, receivedAt: 1 });
72
- return schema;
73
- }
74
-
75
- function executionSchema() {
76
- const schema = new mongoose.Schema({
77
- provider: { type: String, required: true, index: true },
78
- resource: { type: String, default: "", index: true },
79
- operation: { type: String, default: "execute", index: true },
80
- title: { type: String, required: true },
81
- status: { type: String, enum: EXECUTION_STATUSES, default: "Executando", index: true },
82
- startedAt: { type: Date, default: Date.now, index: true },
83
- concludedAt: { type: Date, default: null },
84
- durationMs: { type: Number, default: 0 },
85
- message: { type: String, default: "" },
86
- error: jsonField({}),
87
- summary: jsonField({}),
88
- metadata: jsonField({}),
89
- requests: { type: [mongoose.Schema.Types.Mixed], default: [] },
90
- requestCount: { type: Number, default: 0 },
91
- requestsLimited: { type: Boolean, default: false },
92
- errors: { type: [mongoose.Schema.Types.Mixed], default: [] },
93
- errorCount: { type: Number, default: 0 },
94
- errorsLimited: { type: Boolean, default: false },
95
- items: { type: [mongoose.Schema.Types.Mixed], default: [] },
96
- itemCount: { type: Number, default: 0 },
97
- itemsLimited: { type: Boolean, default: false },
98
- }, { timestamps: true, minimize: false, strict: true });
99
- schema.index({ provider: 1, resource: 1, startedAt: -1 });
100
- schema.index({ status: 1, startedAt: -1 });
101
- return schema;
102
- }
103
-
104
- function getIntegrationModels() {
105
- return {
106
- Outbox: model("OonIntegrationOutbox", outboxSchema, "oon_integration_outbox"),
107
- Inbox: model("OonIntegrationInbox", inboxSchema, "oon_integration_inbox"),
108
- Execution: model("OonIntegrationExecution", executionSchema, "oon_integration_executions"),
109
- };
110
- }
111
-
112
- module.exports = { EXECUTION_STATUSES, INBOX_STATUSES, OUTBOX_STATUSES, getIntegrationModels };