@noambz/app-utils 1.0.0 → 1.2.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.
package/dist/dates.d.ts CHANGED
@@ -6,8 +6,6 @@
6
6
  * @example formatDate("Asia/Jerusalem", "he-IL", someDate)
7
7
  */
8
8
  export declare function formatDate(tz: string, locale?: string, date?: Date): string;
9
- /** @deprecated Use `formatDate` instead. */
10
- export declare const nowFormatted: typeof formatDate;
11
9
  /**
12
10
  * Get today's date as an ISO string (YYYY-MM-DD) in the given timezone.
13
11
  * Falls back to UTC if no timezone is provided.
@@ -27,4 +25,26 @@ export declare function getZonedDateAndHour(tz: string, when?: Date): {
27
25
  dateKey: string;
28
26
  hour: number;
29
27
  };
28
+ export interface DateHelpers {
29
+ now(): string;
30
+ format(date: Date): string;
31
+ todayISO(): string;
32
+ timeHHMM(): string;
33
+ getZonedDateAndHour(when?: Date): {
34
+ dateKey: string;
35
+ hour: number;
36
+ };
37
+ }
38
+ /**
39
+ * Create timezone+locale-bound date helpers so each app doesn't need
40
+ * to pass tz/locale on every call.
41
+ *
42
+ * @example
43
+ * const il = createDateHelpers({ tz: "Asia/Jerusalem", locale: "he-IL" });
44
+ * il.now() // "30.3.2026, 14:05:30"
45
+ */
46
+ export declare function createDateHelpers(defaults: {
47
+ tz: string;
48
+ locale?: string;
49
+ }): DateHelpers;
30
50
  //# sourceMappingURL=dates.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dates.d.ts","sourceRoot":"","sources":["../src/dates.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,SAAU,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,MAAM,CAE5E;AAED,4CAA4C;AAC5C,eAAO,MAAM,YAAY,mBAAa,CAAC;AAEvC;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAU5C;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAO3C;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,MAAM,EACV,IAAI,GAAE,IAAiB,GACtB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAgBnC"}
1
+ {"version":3,"file":"dates.d.ts","sourceRoot":"","sources":["../src/dates.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,SAAU,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,MAAM,CAE5E;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAU5C;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAO3C;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,MAAM,EACV,IAAI,GAAE,IAAiB,GACtB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAgBnC;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,IAAI,MAAM,CAAC;IACd,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAAC;IAC3B,QAAQ,IAAI,MAAM,CAAC;IACnB,QAAQ,IAAI,MAAM,CAAC;IACnB,mBAAmB,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACrE;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,WAAW,CASd"}
package/dist/dates.js CHANGED
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.nowFormatted = void 0;
4
3
  exports.formatDate = formatDate;
5
4
  exports.todayISO = todayISO;
6
5
  exports.timeHHMM = timeHHMM;
7
6
  exports.getZonedDateAndHour = getZonedDateAndHour;
7
+ exports.createDateHelpers = createDateHelpers;
8
8
  /**
9
9
  * Format a date for a specific timezone and locale.
10
10
  * Defaults to "now" when no date is provided.
@@ -15,8 +15,6 @@ exports.getZonedDateAndHour = getZonedDateAndHour;
15
15
  function formatDate(tz, locale = "en-GB", date) {
16
16
  return (date ?? new Date()).toLocaleString(locale, { timeZone: tz });
17
17
  }
18
- /** @deprecated Use `formatDate` instead. */
19
- exports.nowFormatted = formatDate;
20
18
  /**
21
19
  * Get today's date as an ISO string (YYYY-MM-DD) in the given timezone.
22
20
  * Falls back to UTC if no timezone is provided.
@@ -66,4 +64,22 @@ function getZonedDateAndHour(tz, when = new Date()) {
66
64
  const hour = parseInt(get("hour"), 10);
67
65
  return { dateKey: `${y}-${m}-${d}`, hour: Number.isNaN(hour) ? 0 : hour };
68
66
  }
67
+ /**
68
+ * Create timezone+locale-bound date helpers so each app doesn't need
69
+ * to pass tz/locale on every call.
70
+ *
71
+ * @example
72
+ * const il = createDateHelpers({ tz: "Asia/Jerusalem", locale: "he-IL" });
73
+ * il.now() // "30.3.2026, 14:05:30"
74
+ */
75
+ function createDateHelpers(defaults) {
76
+ const { tz, locale = "en-GB" } = defaults;
77
+ return {
78
+ now: () => formatDate(tz, locale),
79
+ format: (date) => formatDate(tz, locale, date),
80
+ todayISO: () => todayISO(tz),
81
+ timeHHMM: () => timeHHMM(tz),
82
+ getZonedDateAndHour: (when) => getZonedDateAndHour(tz, when),
83
+ };
84
+ }
69
85
  //# sourceMappingURL=dates.js.map
package/dist/dates.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"dates.js","sourceRoot":"","sources":["../src/dates.ts"],"names":[],"mappings":";;;AAOA,gCAEC;AASD,4BAUC;AAKD,4BAOC;AAQD,kDAmBC;AAnED;;;;;;GAMG;AACH,SAAgB,UAAU,CAAC,EAAU,EAAE,MAAM,GAAG,OAAO,EAAE,IAAW;IAClE,OAAO,CAAC,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC,cAAc,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;AACvE,CAAC;AAED,4CAA4C;AAC/B,QAAA,YAAY,GAAG,UAAU,CAAC;AAEvC;;;GAGG;AACH,SAAgB,QAAQ,CAAC,EAAW;IAClC,IAAI,CAAC,EAAE;QAAE,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACtD,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE;QAC7C,QAAQ,EAAE,EAAE;QACZ,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,SAAS;QAChB,GAAG,EAAE,SAAS;KACf,CAAC,CAAC,aAAa,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IAC7B,MAAM,GAAG,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;IAC9E,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;AACxD,CAAC;AAED;;GAEG;AACH,SAAgB,QAAQ,CAAC,EAAU;IACjC,OAAO,IAAI,IAAI,EAAE,CAAC,kBAAkB,CAAC,OAAO,EAAE;QAC5C,QAAQ,EAAE,EAAE;QACZ,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,KAAK;KACd,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,SAAgB,mBAAmB,CACjC,EAAU,EACV,OAAa,IAAI,IAAI,EAAE;IAEvB,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE;QAC7C,QAAQ,EAAE,EAAE;QACZ,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,SAAS;QAChB,GAAG,EAAE,SAAS;QACd,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,KAAK;KACd,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAEvB,MAAM,GAAG,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;IAC9E,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;IACtB,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC;IACvB,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;IACrB,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;IACvC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AAC5E,CAAC"}
1
+ {"version":3,"file":"dates.js","sourceRoot":"","sources":["../src/dates.ts"],"names":[],"mappings":"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"}
package/dist/env.d.ts ADDED
@@ -0,0 +1,21 @@
1
+ interface ZodLikeIssue {
2
+ path: (string | number)[];
3
+ message: string;
4
+ }
5
+ interface ZodLikeResult<T> {
6
+ success: boolean;
7
+ data?: T;
8
+ error?: {
9
+ issues: ZodLikeIssue[];
10
+ };
11
+ }
12
+ interface ZodLikeSchema<T> {
13
+ safeParse(data: unknown): ZodLikeResult<T>;
14
+ }
15
+ /**
16
+ * Validate `process.env` against a Zod schema.
17
+ * Returns the parsed config on success; throws a formatted error on failure.
18
+ */
19
+ export declare function validateEnv<T>(schema: ZodLikeSchema<T>): T;
20
+ export {};
21
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA,UAAU,YAAY;IACpB,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,aAAa,CAAC,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,KAAK,CAAC,EAAE;QAAE,MAAM,EAAE,YAAY,EAAE,CAAA;KAAE,CAAC;CACpC;AAED,UAAU,aAAa,CAAC,CAAC;IACvB,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;CAC5C;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAQ1D"}
package/dist/env.js ADDED
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateEnv = validateEnv;
4
+ /**
5
+ * Validate `process.env` against a Zod schema.
6
+ * Returns the parsed config on success; throws a formatted error on failure.
7
+ */
8
+ function validateEnv(schema) {
9
+ const result = schema.safeParse(process.env);
10
+ if (result.success)
11
+ return result.data;
12
+ const formatted = result.error.issues
13
+ .map((i) => ` ${i.path.join(".")}: ${i.message}`)
14
+ .join("\n");
15
+ throw new Error(`Environment validation failed:\n${formatted}`);
16
+ }
17
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":";;AAmBA,kCAQC;AAZD;;;GAGG;AACH,SAAgB,WAAW,CAAI,MAAwB;IACrD,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC7C,IAAI,MAAM,CAAC,OAAO;QAAE,OAAO,MAAM,CAAC,IAAK,CAAC;IAExC,MAAM,SAAS,GAAG,MAAM,CAAC,KAAM,CAAC,MAAM;SACnC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;SACjD,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,MAAM,IAAI,KAAK,CAAC,mCAAmC,SAAS,EAAE,CAAC,CAAC;AAClE,CAAC"}
@@ -0,0 +1,20 @@
1
+ export type HealthStatus = "ok" | "degraded" | "error";
2
+ export interface CheckResult {
3
+ ok: boolean;
4
+ degraded?: boolean;
5
+ detail?: string;
6
+ }
7
+ export type HealthCheckFn = () => CheckResult | Promise<CheckResult>;
8
+ export interface HealthCheckResult {
9
+ status: HealthStatus;
10
+ timestamp: string;
11
+ checks: Record<string, CheckResult>;
12
+ }
13
+ /**
14
+ * Run all named health checks and aggregate into a single status.
15
+ * Any check returning `ok: false` sets status to "error".
16
+ * Any check returning `degraded: true` (with `ok: true`) sets status to "degraded".
17
+ */
18
+ export declare function runHealthChecks(checks: Record<string, HealthCheckFn>): Promise<HealthCheckResult>;
19
+ export declare function healthStatusCode(status: HealthStatus): number;
20
+ //# sourceMappingURL=health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../src/health.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,UAAU,GAAG,OAAO,CAAC;AAEvD,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;AAErE,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,YAAY,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CACrC;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,GACpC,OAAO,CAAC,iBAAiB,CAAC,CAuB5B;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAE7D"}
package/dist/health.js ADDED
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runHealthChecks = runHealthChecks;
4
+ exports.healthStatusCode = healthStatusCode;
5
+ /**
6
+ * Run all named health checks and aggregate into a single status.
7
+ * Any check returning `ok: false` sets status to "error".
8
+ * Any check returning `degraded: true` (with `ok: true`) sets status to "degraded".
9
+ */
10
+ async function runHealthChecks(checks) {
11
+ let status = "ok";
12
+ const results = {};
13
+ for (const [name, fn] of Object.entries(checks)) {
14
+ try {
15
+ const result = await fn();
16
+ results[name] = result;
17
+ if (!result.ok) {
18
+ status = "error";
19
+ }
20
+ else if (result.degraded && status !== "error") {
21
+ status = "degraded";
22
+ }
23
+ }
24
+ catch (err) {
25
+ results[name] = {
26
+ ok: false,
27
+ detail: err instanceof Error ? err.message : "unknown error",
28
+ };
29
+ status = "error";
30
+ }
31
+ }
32
+ return { status, timestamp: new Date().toISOString(), checks: results };
33
+ }
34
+ function healthStatusCode(status) {
35
+ return status === "error" ? 503 : 200;
36
+ }
37
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../src/health.ts"],"names":[],"mappings":";;AAqBA,0CAyBC;AAED,4CAEC;AAlCD;;;;GAIG;AACI,KAAK,UAAU,eAAe,CACnC,MAAqC;IAErC,IAAI,MAAM,GAAiB,IAAI,CAAC;IAChC,MAAM,OAAO,GAAgC,EAAE,CAAC;IAEhD,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAChD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,EAAE,EAAE,CAAC;YAC1B,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC;YACvB,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;gBACf,MAAM,GAAG,OAAO,CAAC;YACnB,CAAC;iBAAM,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;gBACjD,MAAM,GAAG,UAAU,CAAC;YACtB,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,GAAG;gBACd,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe;aAC7D,CAAC;YACF,MAAM,GAAG,OAAO,CAAC;QACnB,CAAC;IACH,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAC1E,CAAC;AAED,SAAgB,gBAAgB,CAAC,MAAoB;IACnD,OAAO,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;AACxC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -2,8 +2,16 @@ export { createLogger } from "./logger";
2
2
  export type { CreateLoggerOptions } from "./logger";
3
3
  export { fetchWithRetry } from "./fetch-retry";
4
4
  export type { FetchRetryOptions } from "./fetch-retry";
5
- export { nowFormatted, todayISO, timeHHMM, getZonedDateAndHour } from "./dates";
5
+ export { formatDate, todayISO, timeHHMM, getZonedDateAndHour, createDateHelpers } from "./dates";
6
+ export type { DateHelpers } from "./dates";
6
7
  export { sleep } from "./sleep";
7
8
  export { checkRateLimit } from "./rate-limit";
8
9
  export type { RateLimitResult } from "./rate-limit";
10
+ export { runHealthChecks, healthStatusCode } from "./health";
11
+ export { validateEnv } from "./env";
12
+ export { createSqliteKVStore, createJsonFileKVStore } from "./kv";
13
+ export type { KVStore } from "./kv";
14
+ export { initSqlitePragmas, backupSqliteDb, pruneOldBackups } from "./sqlite";
15
+ export type { SqlitePragmaDb, SqliteBackupDb, InitSqliteOptions, BackupSqliteOptions, } from "./sqlite";
16
+ export type { HealthStatus, CheckResult, HealthCheckFn, HealthCheckResult, } from "./health";
9
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAEpD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEvD,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEhF,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAEpD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEvD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AACjG,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE7D,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAEpC,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,MAAM,CAAC;AAClE,YAAY,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEpC,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC9E,YAAY,EACV,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,UAAU,CAAC;AAClB,YAAY,EACV,YAAY,EACZ,WAAW,EACX,aAAa,EACb,iBAAiB,GAClB,MAAM,UAAU,CAAC"}
package/dist/index.js CHANGED
@@ -1,17 +1,30 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.checkRateLimit = exports.sleep = exports.getZonedDateAndHour = exports.timeHHMM = exports.todayISO = exports.nowFormatted = exports.fetchWithRetry = exports.createLogger = void 0;
3
+ exports.pruneOldBackups = exports.backupSqliteDb = exports.initSqlitePragmas = exports.createJsonFileKVStore = exports.createSqliteKVStore = exports.validateEnv = exports.healthStatusCode = exports.runHealthChecks = exports.checkRateLimit = exports.sleep = exports.createDateHelpers = exports.getZonedDateAndHour = exports.timeHHMM = exports.todayISO = exports.formatDate = exports.fetchWithRetry = exports.createLogger = void 0;
4
4
  var logger_1 = require("./logger");
5
5
  Object.defineProperty(exports, "createLogger", { enumerable: true, get: function () { return logger_1.createLogger; } });
6
6
  var fetch_retry_1 = require("./fetch-retry");
7
7
  Object.defineProperty(exports, "fetchWithRetry", { enumerable: true, get: function () { return fetch_retry_1.fetchWithRetry; } });
8
8
  var dates_1 = require("./dates");
9
- Object.defineProperty(exports, "nowFormatted", { enumerable: true, get: function () { return dates_1.nowFormatted; } });
9
+ Object.defineProperty(exports, "formatDate", { enumerable: true, get: function () { return dates_1.formatDate; } });
10
10
  Object.defineProperty(exports, "todayISO", { enumerable: true, get: function () { return dates_1.todayISO; } });
11
11
  Object.defineProperty(exports, "timeHHMM", { enumerable: true, get: function () { return dates_1.timeHHMM; } });
12
12
  Object.defineProperty(exports, "getZonedDateAndHour", { enumerable: true, get: function () { return dates_1.getZonedDateAndHour; } });
13
+ Object.defineProperty(exports, "createDateHelpers", { enumerable: true, get: function () { return dates_1.createDateHelpers; } });
13
14
  var sleep_1 = require("./sleep");
14
15
  Object.defineProperty(exports, "sleep", { enumerable: true, get: function () { return sleep_1.sleep; } });
15
16
  var rate_limit_1 = require("./rate-limit");
16
17
  Object.defineProperty(exports, "checkRateLimit", { enumerable: true, get: function () { return rate_limit_1.checkRateLimit; } });
18
+ var health_1 = require("./health");
19
+ Object.defineProperty(exports, "runHealthChecks", { enumerable: true, get: function () { return health_1.runHealthChecks; } });
20
+ Object.defineProperty(exports, "healthStatusCode", { enumerable: true, get: function () { return health_1.healthStatusCode; } });
21
+ var env_1 = require("./env");
22
+ Object.defineProperty(exports, "validateEnv", { enumerable: true, get: function () { return env_1.validateEnv; } });
23
+ var kv_1 = require("./kv");
24
+ Object.defineProperty(exports, "createSqliteKVStore", { enumerable: true, get: function () { return kv_1.createSqliteKVStore; } });
25
+ Object.defineProperty(exports, "createJsonFileKVStore", { enumerable: true, get: function () { return kv_1.createJsonFileKVStore; } });
26
+ var sqlite_1 = require("./sqlite");
27
+ Object.defineProperty(exports, "initSqlitePragmas", { enumerable: true, get: function () { return sqlite_1.initSqlitePragmas; } });
28
+ Object.defineProperty(exports, "backupSqliteDb", { enumerable: true, get: function () { return sqlite_1.backupSqliteDb; } });
29
+ Object.defineProperty(exports, "pruneOldBackups", { enumerable: true, get: function () { return sqlite_1.pruneOldBackups; } });
17
30
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,mCAAwC;AAA/B,sGAAA,YAAY,OAAA;AAGrB,6CAA+C;AAAtC,6GAAA,cAAc,OAAA;AAGvB,iCAAgF;AAAvE,qGAAA,YAAY,OAAA;AAAE,iGAAA,QAAQ,OAAA;AAAE,iGAAA,QAAQ,OAAA;AAAE,4GAAA,mBAAmB,OAAA;AAE9D,iCAAgC;AAAvB,8FAAA,KAAK,OAAA;AAEd,2CAA8C;AAArC,4GAAA,cAAc,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,mCAAwC;AAA/B,sGAAA,YAAY,OAAA;AAGrB,6CAA+C;AAAtC,6GAAA,cAAc,OAAA;AAGvB,iCAAiG;AAAxF,mGAAA,UAAU,OAAA;AAAE,iGAAA,QAAQ,OAAA;AAAE,iGAAA,QAAQ,OAAA;AAAE,4GAAA,mBAAmB,OAAA;AAAE,0GAAA,iBAAiB,OAAA;AAG/E,iCAAgC;AAAvB,8FAAA,KAAK,OAAA;AAEd,2CAA8C;AAArC,4GAAA,cAAc,OAAA;AAGvB,mCAA6D;AAApD,yGAAA,eAAe,OAAA;AAAE,0GAAA,gBAAgB,OAAA;AAE1C,6BAAoC;AAA3B,kGAAA,WAAW,OAAA;AAEpB,2BAAkE;AAAzD,yGAAA,mBAAmB,OAAA;AAAE,2GAAA,qBAAqB,OAAA;AAGnD,mCAA8E;AAArE,2GAAA,iBAAiB,OAAA;AAAE,wGAAA,cAAc,OAAA;AAAE,yGAAA,eAAe,OAAA"}
package/dist/kv.d.ts ADDED
@@ -0,0 +1,29 @@
1
+ export interface KVStore {
2
+ get(key: string): string | null;
3
+ set(key: string, value: string): void;
4
+ delete(key: string): void;
5
+ }
6
+ /**
7
+ * Minimal SQLite db shape needed by the KV store.
8
+ * Compatible with better-sqlite3's Database.
9
+ */
10
+ interface SqliteKVDb {
11
+ prepare(sql: string): {
12
+ get(...params: unknown[]): {
13
+ value: string;
14
+ } | undefined;
15
+ run(...params: unknown[]): unknown;
16
+ };
17
+ }
18
+ /**
19
+ * KV store backed by a SQLite table with `key TEXT PRIMARY KEY, value TEXT`.
20
+ * The table must already exist.
21
+ */
22
+ export declare function createSqliteKVStore(db: SqliteKVDb, table?: string): KVStore;
23
+ /**
24
+ * KV store backed by a single JSON file `{ [key]: value }`.
25
+ * Reads the entire file on each `get`, writes on each `set`/`delete`.
26
+ */
27
+ export declare function createJsonFileKVStore(filePath: string): KVStore;
28
+ export {};
29
+ //# sourceMappingURL=kv.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kv.d.ts","sourceRoot":"","sources":["../src/kv.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,OAAO;IACtB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAChC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;;GAGG;AACH,UAAU,UAAU;IAClB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG;QACpB,GAAG,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,GAAG,SAAS,CAAC;QACzD,GAAG,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;KACpC,CAAC;CACH;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,UAAU,EACd,KAAK,SAAO,GACX,OAAO,CAaT;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CA8B/D"}
package/dist/kv.js ADDED
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createSqliteKVStore = createSqliteKVStore;
4
+ exports.createJsonFileKVStore = createJsonFileKVStore;
5
+ const fs_1 = require("fs");
6
+ const path_1 = require("path");
7
+ /**
8
+ * KV store backed by a SQLite table with `key TEXT PRIMARY KEY, value TEXT`.
9
+ * The table must already exist.
10
+ */
11
+ function createSqliteKVStore(db, table = "kv") {
12
+ return {
13
+ get(key) {
14
+ const row = db.prepare(`SELECT value FROM ${table} WHERE key = ?`).get(key);
15
+ return row?.value ?? null;
16
+ },
17
+ set(key, value) {
18
+ db.prepare(`INSERT OR REPLACE INTO ${table} (key, value) VALUES (?, ?)`).run(key, value);
19
+ },
20
+ delete(key) {
21
+ db.prepare(`DELETE FROM ${table} WHERE key = ?`).run(key);
22
+ },
23
+ };
24
+ }
25
+ /**
26
+ * KV store backed by a single JSON file `{ [key]: value }`.
27
+ * Reads the entire file on each `get`, writes on each `set`/`delete`.
28
+ */
29
+ function createJsonFileKVStore(filePath) {
30
+ function read() {
31
+ try {
32
+ return JSON.parse((0, fs_1.readFileSync)(filePath, "utf-8"));
33
+ }
34
+ catch {
35
+ return {};
36
+ }
37
+ }
38
+ function write(data) {
39
+ const dir = (0, path_1.dirname)(filePath);
40
+ if (!(0, fs_1.existsSync)(dir))
41
+ (0, fs_1.mkdirSync)(dir, { recursive: true });
42
+ (0, fs_1.writeFileSync)(filePath, JSON.stringify(data, null, 2), "utf-8");
43
+ }
44
+ return {
45
+ get(key) {
46
+ return read()[key] ?? null;
47
+ },
48
+ set(key, value) {
49
+ const data = read();
50
+ data[key] = value;
51
+ write(data);
52
+ },
53
+ delete(key) {
54
+ const data = read();
55
+ delete data[key];
56
+ write(data);
57
+ },
58
+ };
59
+ }
60
+ //# sourceMappingURL=kv.js.map
package/dist/kv.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kv.js","sourceRoot":"","sources":["../src/kv.ts"],"names":[],"mappings":";;AAwBA,kDAgBC;AAMD,sDA8BC;AA5ED,2BAAwE;AACxE,+BAA+B;AAmB/B;;;GAGG;AACH,SAAgB,mBAAmB,CACjC,EAAc,EACd,KAAK,GAAG,IAAI;IAEZ,OAAO;QACL,GAAG,CAAC,GAAW;YACb,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,qBAAqB,KAAK,gBAAgB,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC5E,OAAO,GAAG,EAAE,KAAK,IAAI,IAAI,CAAC;QAC5B,CAAC;QACD,GAAG,CAAC,GAAW,EAAE,KAAa;YAC5B,EAAE,CAAC,OAAO,CAAC,0BAA0B,KAAK,6BAA6B,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC3F,CAAC;QACD,MAAM,CAAC,GAAW;YAChB,EAAE,CAAC,OAAO,CAAC,eAAe,KAAK,gBAAgB,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5D,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAgB,qBAAqB,CAAC,QAAgB;IACpD,SAAS,IAAI;QACX,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAA,iBAAY,EAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;QACrD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED,SAAS,KAAK,CAAC,IAA4B;QACzC,MAAM,GAAG,GAAG,IAAA,cAAO,EAAC,QAAQ,CAAC,CAAC;QAC9B,IAAI,CAAC,IAAA,eAAU,EAAC,GAAG,CAAC;YAAE,IAAA,cAAS,EAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,IAAA,kBAAa,EAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAClE,CAAC;IAED,OAAO;QACL,GAAG,CAAC,GAAW;YACb,OAAO,IAAI,EAAE,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;QAC7B,CAAC;QACD,GAAG,CAAC,GAAW,EAAE,KAAa;YAC5B,MAAM,IAAI,GAAG,IAAI,EAAE,CAAC;YACpB,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YAClB,KAAK,CAAC,IAAI,CAAC,CAAC;QACd,CAAC;QACD,MAAM,CAAC,GAAW;YAChB,MAAM,IAAI,GAAG,IAAI,EAAE,CAAC;YACpB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;YACjB,KAAK,CAAC,IAAI,CAAC,CAAC;QACd,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,29 @@
1
+ export interface SqlitePragmaDb {
2
+ pragma(statement: string): unknown;
3
+ }
4
+ export interface SqliteBackupDb {
5
+ backup(destPath: string): Promise<unknown>;
6
+ }
7
+ export interface InitSqliteOptions {
8
+ wal?: boolean;
9
+ foreignKeys?: boolean;
10
+ busyTimeout?: number;
11
+ }
12
+ /**
13
+ * Apply standard pragmas (WAL, foreign keys, busy timeout) to a better-sqlite3 Database.
14
+ */
15
+ export declare function initSqlitePragmas(db: SqlitePragmaDb, options?: InitSqliteOptions): void;
16
+ export interface BackupSqliteOptions {
17
+ prefix?: string;
18
+ maxBackups?: number;
19
+ }
20
+ /**
21
+ * Create a timestamped SQLite backup using the better-sqlite3 backup() API.
22
+ * Returns the backup file path, or null if backup failed.
23
+ */
24
+ export declare function backupSqliteDb(db: SqliteBackupDb, backupDir: string, options?: BackupSqliteOptions): Promise<string | null>;
25
+ /**
26
+ * Remove old backup files, keeping the most recent `keep` files.
27
+ */
28
+ export declare function pruneOldBackups(dir: string, prefix: string, keep: number): string[];
29
+ //# sourceMappingURL=sqlite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../src/sqlite.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;CACpC;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC5C;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,cAAc,EAClB,OAAO,GAAE,iBAAsB,GAC9B,IAAI,CAKN;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,EAAE,EAAE,cAAc,EAClB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAaxB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACX,MAAM,EAAE,CAgBV"}
package/dist/sqlite.js ADDED
@@ -0,0 +1,57 @@
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.initSqlitePragmas = initSqlitePragmas;
7
+ exports.backupSqliteDb = backupSqliteDb;
8
+ exports.pruneOldBackups = pruneOldBackups;
9
+ const fs_1 = __importDefault(require("fs"));
10
+ const path_1 = __importDefault(require("path"));
11
+ /**
12
+ * Apply standard pragmas (WAL, foreign keys, busy timeout) to a better-sqlite3 Database.
13
+ */
14
+ function initSqlitePragmas(db, options = {}) {
15
+ const { wal = true, foreignKeys = true, busyTimeout = 5000 } = options;
16
+ if (wal)
17
+ db.pragma("journal_mode = WAL");
18
+ if (foreignKeys)
19
+ db.pragma("foreign_keys = ON");
20
+ if (busyTimeout > 0)
21
+ db.pragma(`busy_timeout = ${busyTimeout}`);
22
+ }
23
+ /**
24
+ * Create a timestamped SQLite backup using the better-sqlite3 backup() API.
25
+ * Returns the backup file path, or null if backup failed.
26
+ */
27
+ async function backupSqliteDb(db, backupDir, options = {}) {
28
+ const { prefix = "backup", maxBackups = 7 } = options;
29
+ if (!fs_1.default.existsSync(backupDir)) {
30
+ fs_1.default.mkdirSync(backupDir, { recursive: true });
31
+ }
32
+ const ts = new Date().toISOString().slice(0, 19).replace(/[T:]/g, "-");
33
+ const backupPath = path_1.default.join(backupDir, `${prefix}-${ts}.db`);
34
+ await db.backup(backupPath);
35
+ pruneOldBackups(backupDir, prefix, maxBackups);
36
+ return backupPath;
37
+ }
38
+ /**
39
+ * Remove old backup files, keeping the most recent `keep` files.
40
+ */
41
+ function pruneOldBackups(dir, prefix, keep) {
42
+ if (!fs_1.default.existsSync(dir))
43
+ return [];
44
+ const files = fs_1.default
45
+ .readdirSync(dir)
46
+ .filter((f) => f.startsWith(`${prefix}-`) && f.endsWith(".db"))
47
+ .sort()
48
+ .reverse();
49
+ const removed = [];
50
+ for (const file of files.slice(keep)) {
51
+ const filePath = path_1.default.join(dir, file);
52
+ fs_1.default.unlinkSync(filePath);
53
+ removed.push(file);
54
+ }
55
+ return removed;
56
+ }
57
+ //# sourceMappingURL=sqlite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../src/sqlite.ts"],"names":[],"mappings":";;;;;AAoBA,8CAQC;AAWD,wCAiBC;AAKD,0CAoBC;AAjFD,4CAAoB;AACpB,gDAAwB;AAgBxB;;GAEG;AACH,SAAgB,iBAAiB,CAC/B,EAAkB,EAClB,UAA6B,EAAE;IAE/B,MAAM,EAAE,GAAG,GAAG,IAAI,EAAE,WAAW,GAAG,IAAI,EAAE,WAAW,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IACvE,IAAI,GAAG;QAAE,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IACzC,IAAI,WAAW;QAAE,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAChD,IAAI,WAAW,GAAG,CAAC;QAAE,EAAE,CAAC,MAAM,CAAC,kBAAkB,WAAW,EAAE,CAAC,CAAC;AAClE,CAAC;AAOD;;;GAGG;AACI,KAAK,UAAU,cAAc,CAClC,EAAkB,EAClB,SAAiB,EACjB,UAA+B,EAAE;IAEjC,MAAM,EAAE,MAAM,GAAG,QAAQ,EAAE,UAAU,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC;IAEtD,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,YAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACvE,MAAM,UAAU,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,MAAM,IAAI,EAAE,KAAK,CAAC,CAAC;IAE9D,MAAM,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC5B,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;IAC/C,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,SAAgB,eAAe,CAC7B,GAAW,EACX,MAAc,EACd,IAAY;IAEZ,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAEnC,MAAM,KAAK,GAAG,YAAE;SACb,WAAW,CAAC,GAAG,CAAC;SAChB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;SAC9D,IAAI,EAAE;SACN,OAAO,EAAE,CAAC;IAEb,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACrC,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACtC,YAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QACxB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@noambz/app-utils",
3
- "version": "1.0.0",
4
- "description": "Shared utilities: logger, fetchWithRetry, timezone helpers, sleep, rate limiter",
3
+ "version": "1.2.0",
4
+ "description": "Shared utilities: logger, fetchWithRetry, timezone helpers, sleep, rate limiter, health checks, SQLite, KV store, env validation",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "exports": {