@tansohq/credit-forecast-core 0.1.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.
@@ -0,0 +1,2 @@
1
+ export declare const calendarDates: (startDate: string, endDate: string) => readonly string[];
2
+ //# sourceMappingURL=calendar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar.d.ts","sourceRoot":"","sources":["../src/calendar.ts"],"names":[],"mappings":"AAoCA,eAAO,MAAM,aAAa,GAAI,WAAW,MAAM,EAAE,SAAS,MAAM,KAAG,SAAS,MAAM,EAMjF,CAAC"}
@@ -0,0 +1,39 @@
1
+ const isLeapYear = (year) => year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
2
+ const nextDate = (date) => {
3
+ const [yearText = "", monthText = "", dayText = ""] = date.split("-");
4
+ let year = Number(yearText);
5
+ let month = Number(monthText);
6
+ let day = Number(dayText);
7
+ const daysInMonth = [
8
+ 31,
9
+ isLeapYear(year) ? 29 : 28,
10
+ 31,
11
+ 30,
12
+ 31,
13
+ 30,
14
+ 31,
15
+ 31,
16
+ 30,
17
+ 31,
18
+ 30,
19
+ 31,
20
+ ];
21
+ day += 1;
22
+ if (day > (daysInMonth[month - 1] ?? 0)) {
23
+ day = 1;
24
+ month += 1;
25
+ }
26
+ if (month > 12) {
27
+ month = 1;
28
+ year += 1;
29
+ }
30
+ return `${String(year).padStart(4, "0")}-${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
31
+ };
32
+ export const calendarDates = (startDate, endDate) => {
33
+ const dates = [];
34
+ for (let date = startDate; date < endDate; date = nextDate(date)) {
35
+ dates.push(date);
36
+ }
37
+ return dates;
38
+ };
39
+ //# sourceMappingURL=calendar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar.js","sourceRoot":"","sources":["../src/calendar.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,GAAG,CAAC,IAAY,EAAW,EAAE,CAC3C,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,GAAG,KAAK,CAAC,IAAI,IAAI,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC;AAE3D,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAU,EAAE;IACxC,MAAM,CAAC,QAAQ,GAAG,EAAE,EAAE,SAAS,GAAG,EAAE,EAAE,OAAO,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACtE,IAAI,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC5B,IAAI,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;IAC9B,IAAI,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAC1B,MAAM,WAAW,GAAG;QAClB,EAAE;QACF,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;QAC1B,EAAE;QACF,EAAE;QACF,EAAE;QACF,EAAE;QACF,EAAE;QACF,EAAE;QACF,EAAE;QACF,EAAE;QACF,EAAE;QACF,EAAE;KACH,CAAC;IAEF,GAAG,IAAI,CAAC,CAAC;IACT,IAAI,GAAG,GAAG,CAAC,WAAW,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QACxC,GAAG,GAAG,CAAC,CAAC;QACR,KAAK,IAAI,CAAC,CAAC;IACb,CAAC;IACD,IAAI,KAAK,GAAG,EAAE,EAAE,CAAC;QACf,KAAK,GAAG,CAAC,CAAC;QACV,IAAI,IAAI,CAAC,CAAC;IACZ,CAAC;IAED,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;AAC9G,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,SAAiB,EAAE,OAAe,EAAqB,EAAE;IACrF,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,IAAI,IAAI,GAAG,SAAS,EAAE,IAAI,GAAG,OAAO,EAAE,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACjE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ForecastResult } from "@tansohq/credit-forecast-schema";
2
+ export declare const forecastCreditUsage: (rawInput: unknown) => ForecastResult;
3
+ //# sourceMappingURL=forecast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forecast.d.ts","sourceRoot":"","sources":["../src/forecast.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,cAAc,EASf,MAAM,iCAAiC,CAAC;AAwEzC,eAAO,MAAM,mBAAmB,GAAI,UAAU,OAAO,KAAG,cA4PvD,CAAC"}
@@ -0,0 +1,275 @@
1
+ import { Decimal } from "decimal.js";
2
+ import { calendarDates } from "./calendar.js";
3
+ import { parseAndValidateForecastInput } from "./validation.js";
4
+ const decimalInputs = (input) => [
5
+ input.period.allocation,
6
+ input.period.lowBalanceThreshold,
7
+ input.balance.current,
8
+ ...input.dailyUsage.map(({ creditsUsed }) => creditsUsed),
9
+ ...input.balance.schedule.map(({ creditDelta }) => creditDelta),
10
+ ...input.scenarios.map(({ burnMultiplier }) => burnMultiplier),
11
+ ];
12
+ const decimalPrecision = (input) => {
13
+ const longestInput = Math.max(...decimalInputs(input).map((value) => value.replace(/[-.]/g, "").length));
14
+ const operationGrowth = String(input.dailyUsage.length + input.balance.schedule.length + 1).length;
15
+ return Math.max(40, longestInput * 2 + operationGrowth + 30);
16
+ };
17
+ const asTracePoints = (points) => points.map((point) => ({ ...point }));
18
+ const sourceInputs = (input) => [
19
+ { path: "input.asOf", value: input.asOf },
20
+ { path: "input.period.startDate", value: input.period.startDate },
21
+ { path: "input.period.endDate", value: input.period.endDate },
22
+ { path: "input.period.allocation", value: input.period.allocation },
23
+ {
24
+ path: "input.period.lowBalanceThreshold",
25
+ value: input.period.lowBalanceThreshold,
26
+ },
27
+ { path: "input.lookbackDays", value: input.lookbackDays },
28
+ { path: "input.balance.current", value: input.balance.current },
29
+ {
30
+ path: "input.scenarios[1].burnMultiplier",
31
+ value: input.scenarios[1]?.burnMultiplier ?? null,
32
+ },
33
+ { path: "input.schemaVersion", value: input.schemaVersion },
34
+ { path: "input.methodologyVersion", value: input.methodologyVersion },
35
+ {
36
+ path: "input.dailyUsage",
37
+ value: input.dailyUsage.map(({ date, creditsUsed }) => ({ date, creditsUsed })),
38
+ },
39
+ {
40
+ path: "input.balance.schedule",
41
+ value: input.balance.schedule.map(({ date, creditDelta, reason }) => ({
42
+ date,
43
+ creditDelta,
44
+ ...(reason === undefined ? {} : { reason }),
45
+ })),
46
+ },
47
+ {
48
+ path: "input.scenarios[0].burnMultiplier",
49
+ value: input.scenarios[0]?.burnMultiplier ?? null,
50
+ },
51
+ {
52
+ path: "input.scenarios[2].burnMultiplier",
53
+ value: input.scenarios[2]?.burnMultiplier ?? null,
54
+ },
55
+ ];
56
+ export const forecastCreditUsage = (rawInput) => {
57
+ const input = parseAndValidateForecastInput(rawInput);
58
+ const DecimalType = Decimal.clone({
59
+ precision: decimalPrecision(input),
60
+ rounding: Decimal.ROUND_HALF_UP,
61
+ toExpNeg: -1_000_000_000,
62
+ toExpPos: 1_000_000_000,
63
+ });
64
+ const decimal = (value) => new DecimalType(value);
65
+ const rounded = (value) => value.toDecimalPlaces(12, Decimal.ROUND_HALF_UP);
66
+ const formatted = (value) => {
67
+ const result = rounded(value).toFixed();
68
+ return result === "-0" ? "0" : result;
69
+ };
70
+ let cumulative = decimal(0);
71
+ const observedPoints = input.dailyUsage.map(({ date, creditsUsed }) => {
72
+ cumulative = rounded(cumulative.plus(decimal(creditsUsed)));
73
+ return {
74
+ date,
75
+ creditsUsed,
76
+ cumulativeCreditsUsed: formatted(cumulative),
77
+ };
78
+ });
79
+ const creditsUsedToDate = formatted(cumulative);
80
+ const lookbackUsage = input.dailyUsage
81
+ .slice(-input.lookbackDays)
82
+ .map(({ creditsUsed }) => creditsUsed);
83
+ const lookbackSum = lookbackUsage.reduce((total, value) => total.plus(decimal(value)), decimal(0));
84
+ const baselineDailyBurn = formatted(rounded(lookbackSum.dividedBy(input.lookbackDays)));
85
+ const projectedDates = calendarDates(input.asOf, input.period.endDate);
86
+ const daysRemaining = projectedDates.length;
87
+ const commonSteps = [
88
+ {
89
+ key: "observedCumulativeCreditsUsed",
90
+ formula: "cumulative[n] = cumulative[n - 1] + creditsUsed[n]",
91
+ operands: { dailyCreditsUsed: input.dailyUsage.map(({ creditsUsed }) => creditsUsed) },
92
+ result: observedPoints.map(({ cumulativeCreditsUsed }) => cumulativeCreditsUsed),
93
+ },
94
+ {
95
+ key: "creditsUsedToDate",
96
+ formula: "sum(dailyUsage[*].creditsUsed)",
97
+ operands: { dailyCreditsUsed: input.dailyUsage.map(({ creditsUsed }) => creditsUsed) },
98
+ result: creditsUsedToDate,
99
+ },
100
+ {
101
+ key: "baselineDailyBurn",
102
+ formula: "sum(lookbackCreditsUsed) / lookbackDays",
103
+ operands: { lookbackCreditsUsed: lookbackUsage, lookbackDays: input.lookbackDays },
104
+ result: baselineDailyBurn,
105
+ },
106
+ {
107
+ key: "daysRemaining",
108
+ formula: "calendar_days_in_[asOf,period.endDate)",
109
+ operands: { asOf: input.asOf, periodEndDate: input.period.endDate },
110
+ result: daysRemaining,
111
+ },
112
+ ];
113
+ const calculateScenario = (scenarioKey) => {
114
+ const scenario = input.scenarios.find(({ key }) => key === scenarioKey);
115
+ if (scenario === undefined) {
116
+ throw new Error(`Validated scenario ${scenarioKey} is missing`);
117
+ }
118
+ const dailyBurn = formatted(rounded(decimal(baselineDailyBurn).times(decimal(scenario.burnMultiplier))));
119
+ const projectedCreditsUsed = formatted(rounded(decimal(dailyBurn).times(daysRemaining)));
120
+ const projectedPeriodConsumption = formatted(rounded(decimal(creditsUsedToDate).plus(decimal(projectedCreditsUsed))));
121
+ const utilization = formatted(rounded(decimal(projectedPeriodConsumption).dividedBy(decimal(input.period.allocation))));
122
+ let currentBalance = rounded(decimal(input.balance.current));
123
+ let depletionDate = null;
124
+ const points = projectedDates.map((date) => {
125
+ const startBalance = formatted(currentBalance);
126
+ const balanceDeltaValue = input.balance.schedule
127
+ .filter((entry) => entry.date === date)
128
+ .reduce((total, entry) => total.plus(decimal(entry.creditDelta)), decimal(0));
129
+ const balanceDelta = formatted(rounded(balanceDeltaValue));
130
+ currentBalance = rounded(decimal(startBalance).plus(decimal(balanceDelta)).minus(decimal(dailyBurn)));
131
+ const endingBalance = formatted(currentBalance);
132
+ if (depletionDate === null && currentBalance.lessThanOrEqualTo(0)) {
133
+ depletionDate = date;
134
+ }
135
+ return { date, startBalance, balanceDelta, creditsUsed: dailyBurn, endingBalance };
136
+ });
137
+ const endingBalance = formatted(currentBalance);
138
+ const shortfall = formatted(currentBalance.isNegative() ? rounded(currentBalance.negated()) : decimal(0));
139
+ const status = depletionDate !== null
140
+ ? "DEPLETION_PROJECTED"
141
+ : currentBalance.lessThanOrEqualTo(decimal(input.period.lowBalanceThreshold))
142
+ ? "LOW_BALANCE_PROJECTED"
143
+ : "ON_TRACK";
144
+ const scheduledDeltas = input.balance.schedule.map(({ date, creditDelta }) => ({
145
+ date,
146
+ creditDelta,
147
+ }));
148
+ const endingBalances = points.map((point) => point.endingBalance);
149
+ const steps = [
150
+ {
151
+ key: `${scenarioKey}.dailyBurn`,
152
+ formula: "baselineDailyBurn * burnMultiplier",
153
+ operands: { baselineDailyBurn, burnMultiplier: scenario.burnMultiplier },
154
+ result: dailyBurn,
155
+ },
156
+ {
157
+ key: `${scenarioKey}.projectedCreditsUsed`,
158
+ formula: "dailyBurn * daysRemaining",
159
+ operands: { dailyBurn, daysRemaining },
160
+ result: projectedCreditsUsed,
161
+ },
162
+ {
163
+ key: `${scenarioKey}.projectedPeriodConsumption`,
164
+ formula: "creditsUsedToDate + projectedCreditsUsed",
165
+ operands: { creditsUsedToDate, projectedCreditsUsed },
166
+ result: projectedPeriodConsumption,
167
+ },
168
+ {
169
+ key: `${scenarioKey}.utilization`,
170
+ formula: "projectedPeriodConsumption / periodAllocation",
171
+ operands: {
172
+ projectedPeriodConsumption,
173
+ periodAllocation: input.period.allocation,
174
+ },
175
+ result: utilization,
176
+ },
177
+ {
178
+ key: `${scenarioKey}.points`,
179
+ formula: "endingBalance = startBalance + balanceDelta - creditsUsed",
180
+ operands: {
181
+ initialBalance: input.balance.current,
182
+ dailyBurn,
183
+ scheduledDeltas,
184
+ },
185
+ result: asTracePoints(points),
186
+ },
187
+ {
188
+ key: `${scenarioKey}.depletionDate`,
189
+ formula: "first date where endingBalance <= 0",
190
+ operands: { endingBalances },
191
+ result: depletionDate,
192
+ },
193
+ {
194
+ key: `${scenarioKey}.shortfall`,
195
+ formula: "max(0, -endingBalance)",
196
+ operands: { endingBalance },
197
+ result: shortfall,
198
+ },
199
+ {
200
+ key: `${scenarioKey}.status`,
201
+ formula: "status_from_depletion_date_ending_balance_and_threshold",
202
+ operands: {
203
+ depletionDate,
204
+ endingBalance,
205
+ lowBalanceThreshold: input.period.lowBalanceThreshold,
206
+ },
207
+ result: status,
208
+ },
209
+ {
210
+ key: `${scenarioKey}.endingBalance`,
211
+ formula: "last projected point endingBalance",
212
+ operands: { endingBalances },
213
+ result: endingBalance,
214
+ },
215
+ ];
216
+ return {
217
+ forecast: {
218
+ key: scenarioKey,
219
+ dailyBurn,
220
+ projectedCreditsUsed,
221
+ projectedPeriodConsumption,
222
+ utilization,
223
+ endingBalance,
224
+ depletionDate,
225
+ shortfall,
226
+ status,
227
+ points,
228
+ },
229
+ steps,
230
+ };
231
+ };
232
+ const calculations = ["low", "base", "high"].map(calculateScenario);
233
+ const scenarios = calculations.map(({ forecast }) => forecast);
234
+ const warnings = [];
235
+ scenarios.forEach((scenario) => {
236
+ if (scenario.depletionDate !== null) {
237
+ warnings.push({
238
+ code: "DEPLETION_PROJECTED",
239
+ scenarioKey: scenario.key,
240
+ depletionDate: scenario.depletionDate,
241
+ shortfall: scenario.shortfall,
242
+ });
243
+ }
244
+ if (decimal(scenario.endingBalance).greaterThan(0) &&
245
+ decimal(scenario.endingBalance).lessThanOrEqualTo(decimal(input.period.lowBalanceThreshold))) {
246
+ warnings.push({
247
+ code: "LOW_BALANCE_PROJECTED",
248
+ scenarioKey: scenario.key,
249
+ endingBalance: scenario.endingBalance,
250
+ threshold: input.period.lowBalanceThreshold,
251
+ });
252
+ }
253
+ });
254
+ const traceOrder = [
255
+ calculations[1],
256
+ calculations[0],
257
+ calculations[2],
258
+ ].flatMap((calculation) => calculation?.steps ?? []);
259
+ return {
260
+ schemaVersion: input.schemaVersion,
261
+ methodologyVersion: input.methodologyVersion,
262
+ asOf: input.asOf,
263
+ daysRemaining,
264
+ creditsUsedToDate,
265
+ baselineDailyBurn,
266
+ observedPoints,
267
+ scenarios,
268
+ warnings,
269
+ calculationTrace: {
270
+ sourceInputs: sourceInputs(input),
271
+ steps: [...commonSteps, ...traceOrder],
272
+ },
273
+ };
274
+ };
275
+ //# sourceMappingURL=forecast.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forecast.js","sourceRoot":"","sources":["../src/forecast.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { forecastCreditUsage } from "./forecast.js";
2
+ export { ForecastValidationError, parseAndValidateForecastInput, } from "./validation.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EACL,uBAAuB,EACvB,6BAA6B,GAC9B,MAAM,iBAAiB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { forecastCreditUsage } from "./forecast.js";
2
+ export { ForecastValidationError, parseAndValidateForecastInput, } from "./validation.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EACL,uBAAuB,EACvB,6BAA6B,GAC9B,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { type ForecastInput, type ForecastValidationFailure, type ValidationIssue } from "@tansohq/credit-forecast-schema";
2
+ export declare class ForecastValidationError extends Error {
3
+ readonly schemaVersion: string | null;
4
+ readonly methodologyVersion: string | null;
5
+ readonly code: "INVALID_INPUT";
6
+ readonly issues: readonly ValidationIssue[];
7
+ constructor(failure: ForecastValidationFailure);
8
+ toJSON(): ForecastValidationFailure;
9
+ }
10
+ export declare const parseAndValidateForecastInput: (input: unknown) => ForecastInput;
11
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,yBAAyB,EAC9B,KAAK,eAAe,EACrB,MAAM,iCAAiC,CAAC;AAmEzC,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3C,QAAQ,CAAC,IAAI,EAAG,eAAe,CAAU;IACzC,QAAQ,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,CAAC;gBAEhC,OAAO,EAAE,yBAAyB;IAQ9C,MAAM,IAAI,yBAAyB;CAQpC;AAED,eAAO,MAAM,6BAA6B,GAAI,OAAO,OAAO,KAAG,aAY9D,CAAC"}
@@ -0,0 +1,78 @@
1
+ import { ForecastInputSchema, } from "@tansohq/credit-forecast-schema";
2
+ const portableVersion = (input, key) => {
3
+ if (typeof input !== "object" || input === null) {
4
+ return null;
5
+ }
6
+ const value = input[key];
7
+ return typeof value === "string" && value.length > 0 ? value : null;
8
+ };
9
+ const pathToString = (path) => path.reduce((result, segment) => typeof segment === "number" ? `${result}[${segment}]` : `${result}.${segment}`, "input");
10
+ const schemaIssueCode = (issue) => {
11
+ if (typeof issue.params?.forecastCode === "string") {
12
+ return issue.params.forecastCode;
13
+ }
14
+ if (issue.code === "invalid_type" && issue.received === "undefined") {
15
+ return "REQUIRED_FIELD";
16
+ }
17
+ if (issue.code === "unrecognized_keys") {
18
+ return "UNRECOGNIZED_FIELD";
19
+ }
20
+ const path = pathToString(issue.path);
21
+ if (path.endsWith("Date") || path.endsWith(".asOf") || path.endsWith(".date")) {
22
+ return "INVALID_DATE";
23
+ }
24
+ if (path.endsWith(".allocation") ||
25
+ path.endsWith(".lowBalanceThreshold") ||
26
+ path.endsWith(".creditsUsed") ||
27
+ path.endsWith(".current") ||
28
+ path.endsWith(".creditDelta") ||
29
+ path.endsWith(".burnMultiplier")) {
30
+ return "INVALID_DECIMAL";
31
+ }
32
+ return "INVALID_VALUE";
33
+ };
34
+ const toValidationIssue = (schemaIssue) => {
35
+ const path = pathToString(schemaIssue.path);
36
+ const unknownKeys = schemaIssue.keys?.join(", ");
37
+ return {
38
+ code: schemaIssueCode(schemaIssue),
39
+ path,
40
+ message: unknownKeys === undefined
41
+ ? schemaIssue.message
42
+ : `${schemaIssue.message}: ${unknownKeys}`,
43
+ };
44
+ };
45
+ export class ForecastValidationError extends Error {
46
+ schemaVersion;
47
+ methodologyVersion;
48
+ code = "INVALID_INPUT";
49
+ issues;
50
+ constructor(failure) {
51
+ super("Forecast input validation failed");
52
+ this.name = "ForecastValidationError";
53
+ this.schemaVersion = failure.schemaVersion;
54
+ this.methodologyVersion = failure.methodologyVersion;
55
+ this.issues = failure.issues;
56
+ }
57
+ toJSON() {
58
+ return {
59
+ schemaVersion: this.schemaVersion,
60
+ methodologyVersion: this.methodologyVersion,
61
+ code: this.code,
62
+ issues: this.issues,
63
+ };
64
+ }
65
+ }
66
+ export const parseAndValidateForecastInput = (input) => {
67
+ const parsed = ForecastInputSchema.safeParse(input);
68
+ if (parsed.success) {
69
+ return parsed.data;
70
+ }
71
+ throw new ForecastValidationError({
72
+ schemaVersion: portableVersion(input, "schemaVersion"),
73
+ methodologyVersion: portableVersion(input, "methodologyVersion"),
74
+ code: "INVALID_INPUT",
75
+ issues: parsed.error.issues.map((issue) => toValidationIssue(issue)),
76
+ });
77
+ };
78
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@tansohq/credit-forecast-core",
3
+ "version": "0.1.0",
4
+ "description": "Deterministic provider-neutral credit usage forecasting engine",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/tansohq/credit-estimator.git",
20
+ "directory": "packages/core"
21
+ },
22
+ "homepage": "https://github.com/tansohq/credit-estimator#readme",
23
+ "bugs": {
24
+ "url": "https://github.com/tansohq/credit-estimator/issues"
25
+ },
26
+ "publishConfig": {
27
+ "access": "public"
28
+ },
29
+ "dependencies": {
30
+ "decimal.js": "^10.4.3",
31
+ "@tansohq/credit-forecast-schema": "0.1.0"
32
+ },
33
+ "devDependencies": {
34
+ "typescript": "^5.7.2"
35
+ },
36
+ "engines": {
37
+ "node": ">=20"
38
+ },
39
+ "sideEffects": false,
40
+ "scripts": {
41
+ "build": "tsc -p tsconfig.build.json",
42
+ "typecheck": "tsc -p tsconfig.json --noEmit"
43
+ }
44
+ }