badmfck-api-server 4.1.46 → 4.1.48

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.
@@ -173,35 +173,12 @@ async function Deploy(opt) {
173
173
  headersTimeout: 5 * 60 * 1000,
174
174
  bodyTimeout: 5 * 60 * 1000,
175
175
  });
176
- const abortController = new AbortController();
177
- const abortTimer = setTimeout(() => abortController.abort(), 5 * 60 * 1000);
178
- let uploadResponse;
179
- try {
180
- const res = await fetch(opt.host, {
181
- method: "POST",
182
- headers: { authorization: `Bearer ${authToken}` },
183
- body: formData,
184
- signal: abortController.signal,
185
- ...{ dispatcher: uploadAgent },
186
- });
187
- const rawText = await res.text();
188
- let parsed;
189
- try {
190
- parsed = rawText.length > 0 ? JSON.parse(rawText) : null;
191
- }
192
- catch {
193
- parsed = rawText;
194
- }
195
- uploadResponse = res.ok
196
- ? { ok: true, status: res.status, data: parsed }
197
- : { ok: false, status: res.status, error: parsed };
198
- }
199
- catch (err) {
200
- uploadResponse = { ok: false, error: err };
201
- }
202
- finally {
203
- clearTimeout(abortTimer);
204
- }
176
+ const uploadResponse = await __1.Http.post(opt.host, formData, {
177
+ headers: { authorization: `Bearer ${authToken}` },
178
+ dispatcher: uploadAgent,
179
+ timeoutMs: 5 * 60 * 1000,
180
+ retry: { enabled: false },
181
+ });
205
182
  const elapsedMs = Date.now() - startedAt;
206
183
  const useColor = process.stdout.isTTY && !process.env.NO_COLOR;
207
184
  const c = (code, t) => useColor ? `\x1b[${code}m${t}\x1b[0m` : t;
@@ -281,18 +258,23 @@ async function Deploy(opt) {
281
258
  console.log(` ${dim("elapsed: ")} ${elapsedMs}ms`);
282
259
  console.log(` ${dim("time: ")} ${stamp}`);
283
260
  const info = body?.data?.data;
284
- if (info && typeof info === "object" && info.bluegreen === true) {
285
- const slotBadge = info.activeThisDeploy
286
- ? green(" active in production")
287
- : yellow("(inactive — deploy landed but nginx still points at " + info.active + "; run /pckg/switch to promote)");
288
- console.log(` ${dim("mode: ")} blue-green`);
289
- console.log(` ${dim("slot: ")} ${bold(String(info.slot))} ${slotBadge}`);
290
- if (info.active && info.active !== info.slot) {
291
- console.log(` ${dim("active: ")} ${info.active}`);
261
+ if (info && typeof info === "object" && "ok" in info) {
262
+ if (info.project && info.project !== opt.name) {
263
+ console.log(` ${dim("server project:")} ${info.project}`);
264
+ }
265
+ if (info.bluegreen === true) {
266
+ const slotBadge = info.activeThisDeploy
267
+ ? green("← active in production")
268
+ : yellow("(inactive — deploy landed but nginx still points at " + info.active + "; run /pckg/switch to promote)");
269
+ console.log(` ${dim("mode: ")} blue-green`);
270
+ console.log(` ${dim("slot: ")} ${bold(String(info.slot))} ${slotBadge}`);
271
+ if (info.active && info.active !== info.slot) {
272
+ console.log(` ${dim("active: ")} ${info.active}`);
273
+ }
274
+ }
275
+ else if (info.bluegreen === false) {
276
+ console.log(` ${dim("mode: ")} single-instance ${green("← active")}`);
292
277
  }
293
- }
294
- else if (info && typeof info === "object" && info.bluegreen === false) {
295
- console.log(` ${dim("mode: ")} single-instance`);
296
278
  }
297
279
  if (!emptyResponse) {
298
280
  const payload = JSON.stringify(body);
@@ -43,6 +43,32 @@ function normalizeHeaders(headers) {
43
43
  function isRetryableStatus(status, retryOnStatuses) {
44
44
  return retryOnStatuses.includes(status);
45
45
  }
46
+ function isFormDataLike(value) {
47
+ return (value !== null &&
48
+ typeof value === "object" &&
49
+ Object.prototype.toString.call(value) === "[object FormData]" &&
50
+ typeof value.entries === "function");
51
+ }
52
+ function normalizeFormData(source) {
53
+ if (source instanceof undici_1.FormData)
54
+ return source;
55
+ const target = new undici_1.FormData();
56
+ for (const [name, value] of source.entries()) {
57
+ if (typeof value === "string") {
58
+ target.append(name, value);
59
+ }
60
+ else {
61
+ target.append(name, value, value.name);
62
+ }
63
+ }
64
+ return target;
65
+ }
66
+ function removeContentTypeHeader(headers) {
67
+ for (const key of Object.keys(headers)) {
68
+ if (key.toLowerCase() === "content-type")
69
+ delete headers[key];
70
+ }
71
+ }
46
72
  function isLikelyNetworkError(err) {
47
73
  if (!err || typeof err !== "object")
48
74
  return false;
@@ -423,11 +449,12 @@ class Http {
423
449
  let body = undefined;
424
450
  const hasBody = opts.body !== undefined && opts.body !== null;
425
451
  const allowBody = opts.allowBody ?? (opts.method !== "GET" && opts.method !== "DELETE");
452
+ let isMultipart = false;
426
453
  if (hasBody && allowBody) {
427
- if (typeof FormData !== "undefined" && opts.body instanceof FormData) {
428
- body = opts.body;
429
- delete headers["content-type"];
430
- delete headers["Content-Type"];
454
+ if (isFormDataLike(opts.body)) {
455
+ isMultipart = true;
456
+ body = normalizeFormData(opts.body);
457
+ removeContentTypeHeader(headers);
431
458
  }
432
459
  else {
433
460
  const ct = (headers["content-type"] || headers["Content-Type"] || "").toLowerCase();
@@ -442,6 +469,9 @@ class Http {
442
469
  }
443
470
  }
444
471
  }
472
+ if (isMultipart && retryCfg.maxAttempts !== 1) {
473
+ retryCfg.maxAttempts = 1;
474
+ }
445
475
  const responseType = opts.responseType ?? "json";
446
476
  const throwOnJsonParseError = opts.throwOnJsonParseError ?? false;
447
477
  let attemptsMade = 0;
@@ -0,0 +1,8 @@
1
+ import { IInterceptor } from "../APIService";
2
+ import { HTTPRequestVO } from "../structures/Interfaces";
3
+ export declare class InterceptorPayAuth implements IInterceptor<any> {
4
+ intercept(req: HTTPRequestVO, authorizations: {
5
+ key: string;
6
+ kid: string;
7
+ }[]): Promise<any>;
8
+ }
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.InterceptorPayAuth = void 0;
7
+ const crypto_1 = __importDefault(require("crypto"));
8
+ const Validator_1 = require("../helper/Validator");
9
+ const DefaultErrors_1 = __importDefault(require("../structures/DefaultErrors"));
10
+ const _TAuthParams = {
11
+ v: 0,
12
+ ts: "",
13
+ nonce: "",
14
+ kid: "",
15
+ alg: "",
16
+ $__alg_optional: true,
17
+ sig: ""
18
+ };
19
+ class InterceptorPayAuth {
20
+ async intercept(req, authorizations) {
21
+ const authScheme = "payauth ";
22
+ let headerData = req.headers["authorization"];
23
+ if (!headerData)
24
+ throw { ...DefaultErrors_1.default.UNAUTHORIZED, details: "No authorization header" };
25
+ if (!headerData.toLowerCase().startsWith(authScheme))
26
+ throw { ...DefaultErrors_1.default.UNAUTHORIZED, details: "wrong authorization scheme" };
27
+ const b64 = req.data.b64;
28
+ if (req.data.b64) {
29
+ let json = null;
30
+ try {
31
+ json = Buffer.from(req.data.b64, "base64").toString("utf-8");
32
+ json = JSON.parse(json);
33
+ }
34
+ catch (e) {
35
+ throw { ...DefaultErrors_1.default.BAD_REQUEST, details: "JSON malformed" };
36
+ }
37
+ req.data = json;
38
+ }
39
+ const params = {};
40
+ headerData.substring(authScheme.length).trim().split(",").forEach(v => {
41
+ v = v.trim();
42
+ const tmp = v.split("=");
43
+ if (tmp.length === 2) {
44
+ const key = tmp[0].trim().toLowerCase();
45
+ let value = tmp[1].trim();
46
+ if (value.startsWith("'") && value.endsWith("'")) {
47
+ value = value.substring(1, value.length - 1);
48
+ }
49
+ params[key] = value;
50
+ }
51
+ });
52
+ const errors = await Validator_1.Validator.validateStructure(_TAuthParams, params);
53
+ if (errors)
54
+ throw { ...DefaultErrors_1.default.UNAUTHORIZED, details: "Malformed authorization header", stack: errors };
55
+ for (let i of authorizations) {
56
+ if (i.kid === params.kid) {
57
+ if (params.alg.toLowerCase() === "hmac-sha256") {
58
+ if (b64) {
59
+ const key = Buffer.from(i.key, "hex");
60
+ const sig = crypto_1.default.createHmac("sha256", key).update(b64 + params.ts + params.nonce).digest("hex");
61
+ if (sig === params.sig)
62
+ return i;
63
+ throw { ...DefaultErrors_1.default.UNAUTHORIZED, details: "Signature mismatch, calc:" + sig + ", got:" + params.sig, stack: params };
64
+ }
65
+ else {
66
+ throw { ...DefaultErrors_1.default.UNAUTHORIZED, details: "Can't calc signature, no b64" };
67
+ }
68
+ }
69
+ else {
70
+ throw { ...DefaultErrors_1.default.UNAUTHORIZED, details: "Unsupported alg" };
71
+ }
72
+ }
73
+ }
74
+ throw { ...DefaultErrors_1.default.UNAUTHORIZED, details: "Key not found" };
75
+ }
76
+ }
77
+ exports.InterceptorPayAuth = InterceptorPayAuth;
package/dist/index.d.ts CHANGED
@@ -18,4 +18,5 @@ import { MicroserviceHost } from "./apiServer/external/MicroserviceHost";
18
18
  import { MicroserviceClient } from "./apiServer/external/MicroserviceClient";
19
19
  import { Deploy } from "./apiServer/deployment/Deploy";
20
20
  import { Activate } from "./apiServer/deployment/Activate";
21
- export { MicroserviceHost, MicroserviceClient, Http, ZipUtils, UID, YYYYMMDDHH, JSONStableStringify, APIService, Initializer, LocalRequest, ValidationModel, MysqlService, TimeframeService, Validator, LogService, DataProvider, ErrorUtils, ExternalService, DBService, Deploy, Activate, S_MONITOR_REGISTRATE_ACTION };
21
+ import { InterceptorPayAuth } from "./apiServer/interceptors/InterceptorPayAuth";
22
+ export { MicroserviceHost, MicroserviceClient, Http, ZipUtils, UID, YYYYMMDDHH, JSONStableStringify, APIService, Initializer, LocalRequest, ValidationModel, MysqlService, TimeframeService, Validator, LogService, DataProvider, ErrorUtils, ExternalService, DBService, Deploy, Activate, InterceptorPayAuth, S_MONITOR_REGISTRATE_ACTION };
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.S_MONITOR_REGISTRATE_ACTION = exports.Activate = exports.Deploy = exports.DBService = exports.ExternalService = exports.ErrorUtils = exports.DataProvider = exports.LogService = exports.Validator = exports.TimeframeService = exports.MysqlService = exports.LocalRequest = exports.Initializer = exports.APIService = exports.JSONStableStringify = exports.YYYYMMDDHH = exports.UID = exports.ZipUtils = exports.Http = exports.MicroserviceClient = exports.MicroserviceHost = void 0;
3
+ exports.S_MONITOR_REGISTRATE_ACTION = exports.InterceptorPayAuth = exports.Activate = exports.Deploy = exports.DBService = exports.ExternalService = exports.ErrorUtils = exports.DataProvider = exports.LogService = exports.Validator = exports.TimeframeService = exports.MysqlService = exports.LocalRequest = exports.Initializer = exports.APIService = exports.JSONStableStringify = exports.YYYYMMDDHH = exports.UID = exports.ZipUtils = exports.Http = exports.MicroserviceClient = exports.MicroserviceHost = void 0;
4
4
  const APIService_1 = require("./apiServer/APIService");
5
5
  Object.defineProperty(exports, "APIService", { enumerable: true, get: function () { return APIService_1.APIService; } });
6
6
  Object.defineProperty(exports, "Initializer", { enumerable: true, get: function () { return APIService_1.Initializer; } });
@@ -42,3 +42,5 @@ const Deploy_1 = require("./apiServer/deployment/Deploy");
42
42
  Object.defineProperty(exports, "Deploy", { enumerable: true, get: function () { return Deploy_1.Deploy; } });
43
43
  const Activate_1 = require("./apiServer/deployment/Activate");
44
44
  Object.defineProperty(exports, "Activate", { enumerable: true, get: function () { return Activate_1.Activate; } });
45
+ const InterceptorPayAuth_1 = require("./apiServer/interceptors/InterceptorPayAuth");
46
+ Object.defineProperty(exports, "InterceptorPayAuth", { enumerable: true, get: function () { return InterceptorPayAuth_1.InterceptorPayAuth; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "badmfck-api-server",
3
- "version": "4.1.46",
3
+ "version": "4.1.48",
4
4
  "description": "Simple API http server based on express",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",