@fluyappgocore/commons-backend 1.0.215 → 1.0.216

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.
@@ -11,6 +11,12 @@ interface LicenseCache {
11
11
  };
12
12
  tier: string;
13
13
  fetchedAt: number;
14
+ status?: string;
15
+ licenseStatus?: string;
16
+ message?: string;
17
+ expiresAt?: string | null;
18
+ daysUntilExpiry?: number | null;
19
+ inGracePeriod?: boolean;
14
20
  unreachable?: boolean;
15
21
  unreachableSince?: number | null;
16
22
  unreachableGraceDaysLeft?: number | null;
@@ -48,8 +54,17 @@ export declare function getLicenseStatus(): Promise<{
48
54
  readOnly: boolean;
49
55
  blocked: boolean;
50
56
  tier: string;
57
+ status: string | null;
58
+ licenseStatus: string | null;
59
+ message: string | null;
60
+ expiresAt: string | null;
61
+ daysUntilExpiry: number | null;
62
+ inGracePeriod: boolean;
63
+ lastValidatedAt: number;
64
+ lastValidatedAtIso: string;
51
65
  unreachable: boolean;
52
66
  unreachableSince: number | null;
67
+ unreachableSinceIso: string | null;
53
68
  unreachableGraceDaysLeft: number | null;
54
69
  } | null>;
55
70
  export {};
@@ -136,12 +136,13 @@ function writeGraceState(state) {
136
136
  function fetchLicense() {
137
137
  return __awaiter(this, void 0, void 0, function () {
138
138
  function tryFetch(url, isProxy) {
139
+ var _a;
139
140
  return __awaiter(this, void 0, void 0, function () {
140
- var controller_1, timeout_1, headers, res, data, _a;
141
- return __generator(this, function (_b) {
142
- switch (_b.label) {
141
+ var controller_1, timeout_1, headers, res, data, _b;
142
+ return __generator(this, function (_c) {
143
+ switch (_c.label) {
143
144
  case 0:
144
- _b.trys.push([0, 3, , 4]);
145
+ _c.trys.push([0, 3, , 4]);
145
146
  controller_1 = new AbortController();
146
147
  timeout_1 = setTimeout(function () { return controller_1.abort(); }, 5000);
147
148
  headers = {};
@@ -150,12 +151,12 @@ function fetchLicense() {
150
151
  return [4 /*yield*/, fetch(url, { signal: controller_1.signal, headers: headers })
151
152
  .finally(function () { return clearTimeout(timeout_1); })];
152
153
  case 1:
153
- res = _b.sent();
154
+ res = _c.sent();
154
155
  if (!res.ok)
155
156
  return [2 /*return*/, null];
156
157
  return [4 /*yield*/, res.json()];
157
158
  case 2:
158
- data = _b.sent();
159
+ data = _c.sent();
159
160
  return [2 /*return*/, {
160
161
  valid: data.valid,
161
162
  readOnly: data.readOnly || false,
@@ -164,9 +165,17 @@ function fetchLicense() {
164
165
  limits: data.limits || {},
165
166
  tier: data.tier || "BASIC",
166
167
  fetchedAt: Date.now(),
168
+ // Capturamos el detalle del estado para que las respuestas 403
169
+ // tengan informacion accionable en lugar de un mensaje generico.
170
+ status: data.status,
171
+ licenseStatus: data.licenseStatus,
172
+ message: data.message,
173
+ expiresAt: (_a = data.expiresAt) !== null && _a !== void 0 ? _a : null,
174
+ daysUntilExpiry: typeof data.daysUntilExpiry === "number" ? data.daysUntilExpiry : null,
175
+ inGracePeriod: data.inGracePeriod === true,
167
176
  }];
168
177
  case 3:
169
- _a = _b.sent();
178
+ _b = _c.sent();
170
179
  return [2 /*return*/, null];
171
180
  case 4: return [2 /*return*/];
172
181
  }
@@ -334,8 +343,10 @@ function licenseGuard() {
334
343
  // If license is not valid (expired/revoked), block
335
344
  if (!license.valid) {
336
345
  return [2 /*return*/, res.status(403).json({
337
- error: "Licencia no valida",
346
+ error: license.message || "Licencia no valida",
338
347
  code: "LICENSE_INVALID",
348
+ // Detalle accionable para que el cliente sepa el motivo exacto.
349
+ details: buildLicenseDetails(license),
339
350
  })];
340
351
  }
341
352
  // If no features defined in license, allow everything
@@ -350,6 +361,7 @@ function licenseGuard() {
350
361
  code: "FEATURE_DISABLED",
351
362
  feature: feature,
352
363
  tier: license.tier,
364
+ details: buildLicenseDetails(license),
353
365
  })];
354
366
  }
355
367
  }
@@ -360,6 +372,42 @@ function licenseGuard() {
360
372
  }); };
361
373
  }
362
374
  exports.licenseGuard = licenseGuard;
375
+ /**
376
+ * Helper compartido por los tres guards para enriquecer la respuesta 403
377
+ * con la informacion completa del estado de la licencia.
378
+ *
379
+ * Incluye:
380
+ * - status / licenseStatus / message del servidor licensing
381
+ * - expiresAt y daysUntilExpiry para que el cliente sepa cuanto tiempo paso
382
+ * - inGracePeriod para mostrar el banner correcto
383
+ * - tier
384
+ * - lastValidatedAt (timestamp en ms y formato ISO) — cuando fue la
385
+ * ultima vez que se consulto exitosamente el servidor licensing.
386
+ * Critico para distinguir "el server esta caido hace 3 dias" vs
387
+ * "el server respondio recien que la licencia esta revocada".
388
+ * - unreachable / unreachableSince / unreachableGraceDaysLeft cuando el
389
+ * servidor licensing no responde y estamos dentro/fuera del grace.
390
+ */
391
+ function buildLicenseDetails(license) {
392
+ var _a, _b, _c, _d;
393
+ return {
394
+ status: license.status || null,
395
+ licenseStatus: license.licenseStatus || null,
396
+ message: license.message || null,
397
+ tier: license.tier,
398
+ expiresAt: (_a = license.expiresAt) !== null && _a !== void 0 ? _a : null,
399
+ daysUntilExpiry: (_b = license.daysUntilExpiry) !== null && _b !== void 0 ? _b : null,
400
+ inGracePeriod: license.inGracePeriod === true,
401
+ readOnly: license.readOnly,
402
+ blocked: license.blocked,
403
+ lastValidatedAt: license.fetchedAt,
404
+ lastValidatedAtIso: new Date(license.fetchedAt).toISOString(),
405
+ unreachable: license.unreachable === true,
406
+ unreachableSince: (_c = license.unreachableSince) !== null && _c !== void 0 ? _c : null,
407
+ unreachableSinceIso: license.unreachableSince ? new Date(license.unreachableSince).toISOString() : null,
408
+ unreachableGraceDaysLeft: (_d = license.unreachableGraceDaysLeft) !== null && _d !== void 0 ? _d : null,
409
+ };
410
+ }
363
411
  /**
364
412
  * Blocks write operations (POST/PUT/DELETE) when license is in READONLY mode.
365
413
  * Use on all mutation routes. GET requests are always allowed in readonly.
@@ -381,14 +429,16 @@ function licenseWriteGuard() {
381
429
  return [2 /*return*/, next()]; // Can't check → allow
382
430
  if (license.blocked) {
383
431
  return [2 /*return*/, res.status(403).json({
384
- error: "Licencia expirada. Acceso bloqueado.",
432
+ error: license.message || "Licencia expirada. Acceso bloqueado.",
385
433
  code: "LICENSE_BLOCKED",
434
+ details: buildLicenseDetails(license),
386
435
  })];
387
436
  }
388
437
  if (license.readOnly) {
389
438
  return [2 /*return*/, res.status(403).json({
390
- error: "Licencia en modo solo lectura. No se permiten cambios.",
439
+ error: license.message || "Licencia en modo solo lectura. No se permiten cambios.",
391
440
  code: "LICENSE_READONLY",
441
+ details: buildLicenseDetails(license),
392
442
  })];
393
443
  }
394
444
  next();
@@ -415,8 +465,9 @@ function licenseLoginGuard() {
415
465
  return [2 /*return*/, next()]; // Can't check → allow
416
466
  if (license.blocked) {
417
467
  return [2 /*return*/, res.status(403).json({
418
- error: "Licencia expirada. El acceso ha sido suspendido. Contacte al administrador.",
468
+ error: license.message || "Licencia expirada. El acceso ha sido suspendido. Contacte al administrador.",
419
469
  code: "LICENSE_BLOCKED",
470
+ details: buildLicenseDetails(license),
420
471
  })];
421
472
  }
422
473
  next();
@@ -432,14 +483,14 @@ exports.licenseLoginGuard = licenseLoginGuard;
432
483
  * "licensing server unreachable, X days left" banner.
433
484
  */
434
485
  function getLicenseStatus() {
435
- var _a, _b;
486
+ var _a, _b, _c, _d;
436
487
  return __awaiter(this, void 0, void 0, function () {
437
488
  var lic;
438
- return __generator(this, function (_c) {
439
- switch (_c.label) {
489
+ return __generator(this, function (_e) {
490
+ switch (_e.label) {
440
491
  case 0: return [4 /*yield*/, getCachedLicense()];
441
492
  case 1:
442
- lic = _c.sent();
493
+ lic = _e.sent();
443
494
  if (!lic)
444
495
  return [2 /*return*/, null];
445
496
  return [2 /*return*/, {
@@ -447,9 +498,18 @@ function getLicenseStatus() {
447
498
  readOnly: lic.readOnly,
448
499
  blocked: lic.blocked,
449
500
  tier: lic.tier,
501
+ status: lic.status || null,
502
+ licenseStatus: lic.licenseStatus || null,
503
+ message: lic.message || null,
504
+ expiresAt: (_a = lic.expiresAt) !== null && _a !== void 0 ? _a : null,
505
+ daysUntilExpiry: (_b = lic.daysUntilExpiry) !== null && _b !== void 0 ? _b : null,
506
+ inGracePeriod: lic.inGracePeriod === true,
507
+ lastValidatedAt: lic.fetchedAt,
508
+ lastValidatedAtIso: new Date(lic.fetchedAt).toISOString(),
450
509
  unreachable: lic.unreachable === true,
451
- unreachableSince: (_a = lic.unreachableSince) !== null && _a !== void 0 ? _a : null,
452
- unreachableGraceDaysLeft: (_b = lic.unreachableGraceDaysLeft) !== null && _b !== void 0 ? _b : null,
510
+ unreachableSince: (_c = lic.unreachableSince) !== null && _c !== void 0 ? _c : null,
511
+ unreachableSinceIso: lic.unreachableSince ? new Date(lic.unreachableSince).toISOString() : null,
512
+ unreachableGraceDaysLeft: (_d = lic.unreachableGraceDaysLeft) !== null && _d !== void 0 ? _d : null,
453
513
  }];
454
514
  }
455
515
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluyappgocore/commons-backend",
3
- "version": "1.0.215",
3
+ "version": "1.0.216",
4
4
  "description": "",
5
5
  "main": "./build/index.js",
6
6
  "types": "./build/index.d.ts",