@forklaunch/core 1.3.9 → 1.3.11

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.
@@ -1,6 +1,5 @@
1
1
  import { Counter, Gauge, Histogram, UpDownCounter, ObservableCounter, ObservableGauge, ObservableUpDownCounter } from '@opentelemetry/api';
2
- import pino, { LevelWithSilentOrString, LevelWithSilent } from 'pino';
3
- import { AnyValueMap } from '@opentelemetry/api-logs';
2
+ import { LevelWithSilentOrString, LevelWithSilent } from 'pino';
4
3
 
5
4
  type MetricType<T extends string> = T extends 'counter' ? Counter : T extends 'gauge' ? Gauge : T extends 'histogram' ? Histogram : T extends 'upDownCounter' ? UpDownCounter : T extends 'observableCounter' ? ObservableCounter : T extends 'observableGauge' ? ObservableGauge : T extends 'observableUpDownCounter' ? ObservableUpDownCounter : undefined;
6
5
  type MetricsDefinition = Record<string, 'counter' | 'gauge' | 'histogram' | 'upDownCounter' | 'observableCounter' | 'observableGauge' | 'observableUpDownCounter'>;
@@ -21,26 +20,8 @@ interface TelemetryOptions {
21
20
  level: LevelWithSilentOrString;
22
21
  }
23
22
 
24
- declare function meta(meta: Record<string, unknown>): LoggerMeta;
25
- declare class PinoLogger {
26
- private pinoLogger;
27
- private meta;
28
- constructor(level: LevelWithSilentOrString, meta?: AnyValueMap);
29
- log(level: LevelWithSilent, ...args: (string | unknown | LoggerMeta)[]): void;
30
- error: LogFn;
31
- info: LogFn;
32
- debug: LogFn;
33
- warn: LogFn;
34
- trace: LogFn;
35
- child(meta?: AnyValueMap): PinoLogger;
36
- getBaseLogger(): pino.Logger;
37
- }
38
- declare function logger(level: LevelWithSilentOrString, meta?: AnyValueMap): PinoLogger;
39
-
40
23
  declare class OpenTelemetryCollector<AppliedMetricsDefinition extends MetricsDefinition> {
41
- _logger: PinoLogger;
42
- _serviceName: string;
43
- _metrics: Record<keyof AppliedMetricsDefinition, Counter | Gauge | Histogram | UpDownCounter | ObservableCounter | ObservableGauge | ObservableUpDownCounter>;
24
+ #private;
44
25
  constructor(serviceName: string, level?: LevelWithSilentOrString, metricDefinitions?: AppliedMetricsDefinition);
45
26
  log(level: LevelWithSilent, ...args: (string | unknown | LoggerMeta)[]): void;
46
27
  info: LogFn;
@@ -67,4 +48,4 @@ declare const httpServerDurationHistogram: Histogram<{
67
48
  "http.response.status_code": number;
68
49
  }>;
69
50
 
70
- export { type LogFn as L, type MetricsDefinition as M, OpenTelemetryCollector as O, PinoLogger as P, type TelemetryOptions as T, type LoggerMeta as a, type MetricType as b, httpServerDurationHistogram as c, httpRequestsTotalCounter as h, logger as l, meta as m };
51
+ export { type LoggerMeta as L, type MetricsDefinition as M, OpenTelemetryCollector as O, type TelemetryOptions as T, type LogFn as a, type MetricType as b, httpServerDurationHistogram as c, httpRequestsTotalCounter as h };
@@ -1,6 +1,5 @@
1
1
  import { Counter, Gauge, Histogram, UpDownCounter, ObservableCounter, ObservableGauge, ObservableUpDownCounter } from '@opentelemetry/api';
2
- import pino, { LevelWithSilentOrString, LevelWithSilent } from 'pino';
3
- import { AnyValueMap } from '@opentelemetry/api-logs';
2
+ import { LevelWithSilentOrString, LevelWithSilent } from 'pino';
4
3
 
5
4
  type MetricType<T extends string> = T extends 'counter' ? Counter : T extends 'gauge' ? Gauge : T extends 'histogram' ? Histogram : T extends 'upDownCounter' ? UpDownCounter : T extends 'observableCounter' ? ObservableCounter : T extends 'observableGauge' ? ObservableGauge : T extends 'observableUpDownCounter' ? ObservableUpDownCounter : undefined;
6
5
  type MetricsDefinition = Record<string, 'counter' | 'gauge' | 'histogram' | 'upDownCounter' | 'observableCounter' | 'observableGauge' | 'observableUpDownCounter'>;
@@ -21,26 +20,8 @@ interface TelemetryOptions {
21
20
  level: LevelWithSilentOrString;
22
21
  }
23
22
 
24
- declare function meta(meta: Record<string, unknown>): LoggerMeta;
25
- declare class PinoLogger {
26
- private pinoLogger;
27
- private meta;
28
- constructor(level: LevelWithSilentOrString, meta?: AnyValueMap);
29
- log(level: LevelWithSilent, ...args: (string | unknown | LoggerMeta)[]): void;
30
- error: LogFn;
31
- info: LogFn;
32
- debug: LogFn;
33
- warn: LogFn;
34
- trace: LogFn;
35
- child(meta?: AnyValueMap): PinoLogger;
36
- getBaseLogger(): pino.Logger;
37
- }
38
- declare function logger(level: LevelWithSilentOrString, meta?: AnyValueMap): PinoLogger;
39
-
40
23
  declare class OpenTelemetryCollector<AppliedMetricsDefinition extends MetricsDefinition> {
41
- _logger: PinoLogger;
42
- _serviceName: string;
43
- _metrics: Record<keyof AppliedMetricsDefinition, Counter | Gauge | Histogram | UpDownCounter | ObservableCounter | ObservableGauge | ObservableUpDownCounter>;
24
+ #private;
44
25
  constructor(serviceName: string, level?: LevelWithSilentOrString, metricDefinitions?: AppliedMetricsDefinition);
45
26
  log(level: LevelWithSilent, ...args: (string | unknown | LoggerMeta)[]): void;
46
27
  info: LogFn;
@@ -67,4 +48,4 @@ declare const httpServerDurationHistogram: Histogram<{
67
48
  "http.response.status_code": number;
68
49
  }>;
69
50
 
70
- export { type LogFn as L, type MetricsDefinition as M, OpenTelemetryCollector as O, PinoLogger as P, type TelemetryOptions as T, type LoggerMeta as a, type MetricType as b, httpServerDurationHistogram as c, httpRequestsTotalCounter as h, logger as l, meta as m };
51
+ export { type LoggerMeta as L, type MetricsDefinition as M, OpenTelemetryCollector as O, type TelemetryOptions as T, type LogFn as a, type MetricType as b, httpServerDurationHistogram as c, httpRequestsTotalCounter as h };
@@ -186,31 +186,32 @@ declare function getCurrentTenantId(): string;
186
186
  /**
187
187
  * MikroORM custom Type that transparently encrypts/decrypts values.
188
188
  *
189
- * Works with any JS type (string, number, boolean, object/JSON).
190
- * Non-string values are JSON-serialized before encryption and
191
- * JSON-parsed after decryption.
189
+ * Works with any JS type. Non-string values are serialized before
190
+ * encryption and hydrated after decryption using the original Type's
191
+ * runtimeType for correct JS type reconstruction.
192
192
  *
193
193
  * DB column is always `text` — the encrypted ciphertext is a string
194
194
  * regardless of the original JS type.
195
195
  *
196
- * Operates at the data conversion layer before the identity map,
197
- * during hydration, and during persistence. Entities always hold
198
- * their original JS values (plaintext).
196
+ * For array container types, the element type is tracked separately
197
+ * so each element is hydrated individually after decryption.
199
198
  */
200
199
  declare class EncryptedType extends Type<unknown, string | null> {
201
- private readonly originalType;
200
+ #private;
202
201
  /**
203
- * @param originalType - The original JS type hint ('string' | 'json' | 'number' | 'boolean').
204
- * Used to determine serialization strategy.
202
+ * @param elementRuntimeType - The runtimeType of the (element) type,
203
+ * e.g. 'string', 'number', 'Date', 'bigint', 'Buffer', 'any'.
204
+ * @param isArray - Whether this is an array container type.
205
205
  */
206
- constructor(originalType?: string);
206
+ constructor(elementRuntimeType?: string, isArray?: boolean);
207
207
  convertToDatabaseValue(value: unknown, _platform: Platform, _context?: TransformContext): string | null;
208
208
  convertToJSValue(value: string | null, _platform: Platform): unknown;
209
209
  getColumnType(): string;
210
210
  get runtimeType(): string;
211
211
  ensureComparable(): boolean;
212
- private serializeValue;
213
- private deserializeValue;
212
+ private serialize;
213
+ private deserialize;
214
+ private tryJsonParse;
214
215
  }
215
216
 
216
217
  /**
@@ -186,31 +186,32 @@ declare function getCurrentTenantId(): string;
186
186
  /**
187
187
  * MikroORM custom Type that transparently encrypts/decrypts values.
188
188
  *
189
- * Works with any JS type (string, number, boolean, object/JSON).
190
- * Non-string values are JSON-serialized before encryption and
191
- * JSON-parsed after decryption.
189
+ * Works with any JS type. Non-string values are serialized before
190
+ * encryption and hydrated after decryption using the original Type's
191
+ * runtimeType for correct JS type reconstruction.
192
192
  *
193
193
  * DB column is always `text` — the encrypted ciphertext is a string
194
194
  * regardless of the original JS type.
195
195
  *
196
- * Operates at the data conversion layer before the identity map,
197
- * during hydration, and during persistence. Entities always hold
198
- * their original JS values (plaintext).
196
+ * For array container types, the element type is tracked separately
197
+ * so each element is hydrated individually after decryption.
199
198
  */
200
199
  declare class EncryptedType extends Type<unknown, string | null> {
201
- private readonly originalType;
200
+ #private;
202
201
  /**
203
- * @param originalType - The original JS type hint ('string' | 'json' | 'number' | 'boolean').
204
- * Used to determine serialization strategy.
202
+ * @param elementRuntimeType - The runtimeType of the (element) type,
203
+ * e.g. 'string', 'number', 'Date', 'bigint', 'Buffer', 'any'.
204
+ * @param isArray - Whether this is an array container type.
205
205
  */
206
- constructor(originalType?: string);
206
+ constructor(elementRuntimeType?: string, isArray?: boolean);
207
207
  convertToDatabaseValue(value: unknown, _platform: Platform, _context?: TransformContext): string | null;
208
208
  convertToJSValue(value: string | null, _platform: Platform): unknown;
209
209
  getColumnType(): string;
210
210
  get runtimeType(): string;
211
211
  ensureComparable(): boolean;
212
- private serializeValue;
213
- private deserializeValue;
212
+ private serialize;
213
+ private deserialize;
214
+ private tryJsonParse;
214
215
  }
215
216
 
216
217
  /**
@@ -170,39 +170,75 @@ function setEncryptionTenantId(tenantId) {
170
170
  function getCurrentTenantId() {
171
171
  return _tenantContext.getStore()?.tenantId ?? "";
172
172
  }
173
+ function resolveTypeInstance(type) {
174
+ if (type instanceof import_core.Type) return type;
175
+ if (typeof type === "function") {
176
+ try {
177
+ const inst = new type();
178
+ return inst instanceof import_core.Type ? inst : void 0;
179
+ } catch {
180
+ return void 0;
181
+ }
182
+ }
183
+ return void 0;
184
+ }
185
+ function hydrateValue(value, runtimeType) {
186
+ if (value === null || value === void 0) return value;
187
+ switch (runtimeType) {
188
+ case "string":
189
+ return typeof value === "string" ? value : String(value);
190
+ case "number":
191
+ return typeof value === "number" ? value : Number(value);
192
+ case "boolean":
193
+ return typeof value === "boolean" ? value : typeof value === "string" ? value === "true" : Boolean(value);
194
+ case "Date":
195
+ return value instanceof Date ? value : new Date(value);
196
+ case "bigint":
197
+ return typeof value === "bigint" ? value : BigInt(value);
198
+ case "Buffer":
199
+ return Buffer.isBuffer(value) ? value : typeof value === "string" ? Buffer.from(value, "base64") : Buffer.from(value);
200
+ case "any":
201
+ // json — return as-is after JSON.parse
202
+ default:
203
+ return value;
204
+ }
205
+ }
173
206
  var EncryptedType = class extends import_core.Type {
174
- originalType;
207
+ #elementRuntimeType;
208
+ #isArray;
175
209
  /**
176
- * @param originalType - The original JS type hint ('string' | 'json' | 'number' | 'boolean').
177
- * Used to determine serialization strategy.
210
+ * @param elementRuntimeType - The runtimeType of the (element) type,
211
+ * e.g. 'string', 'number', 'Date', 'bigint', 'Buffer', 'any'.
212
+ * @param isArray - Whether this is an array container type.
178
213
  */
179
- constructor(originalType = "string") {
214
+ constructor(elementRuntimeType = "string", isArray = false) {
180
215
  super();
181
- this.originalType = originalType;
216
+ this.#elementRuntimeType = elementRuntimeType;
217
+ this.#isArray = isArray;
182
218
  }
183
219
  convertToDatabaseValue(value, _platform, _context) {
184
220
  if (value === null || value === void 0) return null;
185
221
  if (typeof value === "string" && value.length === 0) return "";
186
222
  if (!_encryptor) {
187
- return this.serializeValue(value);
223
+ return this.serialize(value);
188
224
  }
189
225
  if (typeof value === "string" && isEncrypted(value)) {
190
226
  return value;
191
227
  }
192
- const serialized = this.serializeValue(value);
228
+ const serialized = this.serialize(value);
193
229
  return _encryptor.encrypt(serialized, getCurrentTenantId()) ?? serialized;
194
230
  }
195
231
  convertToJSValue(value, _platform) {
196
232
  if (value === null || value === void 0) return null;
197
233
  if (typeof value !== "string") return value;
198
234
  if (!isEncrypted(value)) {
199
- return this.deserializeValue(value);
235
+ return this.deserialize(value);
200
236
  }
201
237
  if (!_encryptor) return value;
202
238
  try {
203
239
  const decrypted = _encryptor.decrypt(value, getCurrentTenantId());
204
240
  if (decrypted === null) return null;
205
- return this.deserializeValue(decrypted);
241
+ return this.deserialize(decrypted);
206
242
  } catch {
207
243
  return value;
208
244
  }
@@ -211,7 +247,8 @@ var EncryptedType = class extends import_core.Type {
211
247
  return "text";
212
248
  }
213
249
  get runtimeType() {
214
- return this.originalType === "json" ? "object" : this.originalType;
250
+ if (this.#isArray) return "object";
251
+ return this.#elementRuntimeType;
215
252
  }
216
253
  ensureComparable() {
217
254
  return false;
@@ -219,25 +256,50 @@ var EncryptedType = class extends import_core.Type {
219
256
  // ---------------------------------------------------------------------------
220
257
  // Serialization helpers
221
258
  // ---------------------------------------------------------------------------
222
- serializeValue(value) {
259
+ serialize(value) {
223
260
  if (typeof value === "string") return value;
261
+ if (value instanceof Date) return value.toISOString();
262
+ if (typeof value === "bigint") return value.toString();
263
+ if (Buffer.isBuffer(value) || value instanceof Uint8Array)
264
+ return Buffer.from(value).toString("base64");
224
265
  return JSON.stringify(value);
225
266
  }
226
- deserializeValue(value) {
227
- switch (this.originalType) {
267
+ deserialize(value) {
268
+ if (this.#isArray) {
269
+ try {
270
+ const arr = JSON.parse(value);
271
+ if (!Array.isArray(arr)) return arr;
272
+ return arr.map(
273
+ (el) => hydrateValue(el, this.#elementRuntimeType)
274
+ );
275
+ } catch {
276
+ return value;
277
+ }
278
+ }
279
+ switch (this.#elementRuntimeType) {
228
280
  case "string":
229
281
  return value;
230
- case "number":
231
- return Number(value);
232
- case "boolean":
233
- return value === "true";
234
- case "json":
235
- default:
282
+ case "any":
236
283
  try {
237
284
  return JSON.parse(value);
238
285
  } catch {
239
286
  return value;
240
287
  }
288
+ // Types serialized via toString/toISOString/base64 — hydrate from string directly
289
+ case "bigint":
290
+ case "Date":
291
+ case "Buffer":
292
+ return hydrateValue(value, this.#elementRuntimeType);
293
+ // Types where JSON.parse recovers the native JS value (number, boolean)
294
+ default:
295
+ return hydrateValue(this.tryJsonParse(value), this.#elementRuntimeType);
296
+ }
297
+ }
298
+ tryJsonParse(value) {
299
+ try {
300
+ return JSON.parse(value);
301
+ } catch {
302
+ return value;
241
303
  }
242
304
  }
243
305
  };
@@ -273,32 +335,27 @@ var ENCRYPTED_LEVELS = /* @__PURE__ */ new Set([
273
335
  "phi",
274
336
  "pci"
275
337
  ]);
276
- function detectOriginalType(options) {
338
+ function resolveEncryptedTypeArgs(options) {
277
339
  const type = options.type;
278
- if (!type) return "string";
279
- let t;
280
- if (typeof type === "string") {
281
- t = type.toLowerCase();
282
- } else if (typeof type === "object" && type !== null) {
283
- const rt = type.runtimeType;
284
- t = rt ?? type.constructor?.name?.toLowerCase() ?? "string";
285
- } else {
286
- return "string";
287
- }
288
- if (t.includes("json") || t === "object") return "json";
289
- if (t.includes("int") || t === "number" || t === "double" || t === "float" || t === "decimal" || t === "smallint" || t === "tinyint")
290
- return "number";
291
- if (t === "boolean" || t === "bool") return "boolean";
292
- return "string";
340
+ const isArray = options.array === true;
341
+ const resolved = resolveTypeInstance(type);
342
+ if (resolved) {
343
+ const rt = resolved.runtimeType;
344
+ if (rt.endsWith("[]")) {
345
+ return { elementRuntimeType: rt.slice(0, -2) || "string", isArray: true };
346
+ }
347
+ return { elementRuntimeType: rt, isArray };
348
+ }
349
+ return { elementRuntimeType: "string", isArray };
293
350
  }
294
351
  function wrapClassified(builder, level) {
295
352
  if (ENCRYPTED_LEVELS.has(level)) {
296
353
  const options = builder["~options"];
297
354
  if (options) {
298
- const originalType = detectOriginalType(options);
299
- options.type = new EncryptedType(originalType);
355
+ const { elementRuntimeType, isArray } = resolveEncryptedTypeArgs(options);
356
+ options.type = new EncryptedType(elementRuntimeType, isArray);
300
357
  options.columnType = "text";
301
- options.runtimeType = originalType === "json" ? "object" : originalType;
358
+ options.runtimeType = isArray ? "object" : elementRuntimeType;
302
359
  }
303
360
  }
304
361
  return new Proxy(builder, {