@carrierllc/mcp 0.10.0 → 0.10.1

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.
@@ -1792,7 +1792,7 @@ function storefrontScreen(input) {
1792
1792
  // package.json
1793
1793
  var package_default = {
1794
1794
  name: "@carrierllc/mcp",
1795
- version: "0.10.0",
1795
+ version: "0.10.1",
1796
1796
  description: "Carrier MCP \u2014 natural-language control of MVNO/eSIM fleets via eSIMVault OCS. Stdio mode for direct integration with Claude Desktop, Cursor, Windsurf, and MCP-compatible clients. Ships the `carrier` CLI (plugin install + white-label eSIM storefront scaffold).",
1797
1797
  license: "MIT",
1798
1798
  author: "Carrier (Lifecycle Innovations Limited)",
@@ -1876,6 +1876,239 @@ var package_default = {
1876
1876
  // src/version.ts
1877
1877
  var CARRIER_VERSION = package_default.version;
1878
1878
 
1879
+ // ../../packages/ocs-client/dist/chunk-GTWOOFJA.js
1880
+ import { z } from "zod";
1881
+ var OCS_V1_METHODS = /* @__PURE__ */ new Set([
1882
+ "getResellerInfo",
1883
+ "listResellerAccount",
1884
+ "listPrepaidPackageTemplate",
1885
+ "listSubscriber",
1886
+ "getSingleSubscriber",
1887
+ "getSimProviderStatus",
1888
+ "getSubscriberLocation",
1889
+ "getSubscriberLocationByCellId",
1890
+ "subscriberUsageOverPeriod",
1891
+ "affectRecurringPackageToSubscriber",
1892
+ "deleteSubscriberPackage",
1893
+ "modifyAccountBalance",
1894
+ "modifySubscriberBalance",
1895
+ "modifySubscriberContactInfo",
1896
+ "modifySubscriberMobilePlan",
1897
+ "modifySubscriberSteeringList",
1898
+ "modifySubscriberVoipPlan",
1899
+ "modifySubscriberPrepaidPackageActivePeriod",
1900
+ "modifySubscriberPrepaidPackageLimits",
1901
+ "modifySubscriberPrepaidPackageStatus",
1902
+ "modifyPPTCore",
1903
+ "modifyPPTRecurring",
1904
+ "createPrepaidPackageTemplate",
1905
+ "createLocationZone",
1906
+ "changeNetworkProfileOfLocationZone",
1907
+ "hlrGetBitrate",
1908
+ "hlrSetBitrate",
1909
+ "listSponsor",
1910
+ "listDestinationListPrefix",
1911
+ "listDetailedLocationZone",
1912
+ "listLocationZoneElement",
1913
+ "listSubscriberVoipTariff",
1914
+ "listVoipTariffRule",
1915
+ "affectSubscriberFakePhoneNumber",
1916
+ "affectSubscriberRealPhoneNumber",
1917
+ "getCustomerTariff",
1918
+ "resetSubsGzCounter",
1919
+ "sendMtSms"
1920
+ ]);
1921
+ var OcsResponseEnvelope = z.object({
1922
+ status: z.object({
1923
+ code: z.number(),
1924
+ // Required to match the `OcsStatus` interface in client.ts ({ code, msg }).
1925
+ msg: z.string()
1926
+ }).passthrough()
1927
+ }).passthrough();
1928
+ var GetResellerInfoResponse = z.object({
1929
+ id: z.number(),
1930
+ name: z.string(),
1931
+ parentId: z.number(),
1932
+ parentName: z.string(),
1933
+ balance: z.number(),
1934
+ cdrFolder: z.string().optional(),
1935
+ trafficInfo: z.object({}).passthrough().optional(),
1936
+ chargingInfo: z.object({}).passthrough().optional(),
1937
+ contactInfo: z.object({}).passthrough().optional()
1938
+ }).passthrough();
1939
+ var ListResellerAccountResponse = z.object({
1940
+ reseller: z.array(
1941
+ z.object({
1942
+ id: z.number(),
1943
+ name: z.string(),
1944
+ account: z.array(z.object({}).passthrough())
1945
+ }).passthrough()
1946
+ )
1947
+ }).passthrough();
1948
+ var ListPrepaidPackageTemplateResponse = z.object({
1949
+ template: z.array(
1950
+ z.object({
1951
+ prepaidpackagetemplateid: z.number(),
1952
+ prepaidpackagetemplatename: z.string(),
1953
+ resellerid: z.number(),
1954
+ locationzoneid: z.number()
1955
+ }).passthrough()
1956
+ )
1957
+ }).passthrough();
1958
+ var SubscriberStatusName = z.string().regex(/^[A-Za-z]/, "subscriber status must be a non-empty alpha-leading name");
1959
+ var GetSingleSubscriberResponse = z.object({
1960
+ status: z.array(
1961
+ z.object({
1962
+ status: SubscriberStatusName
1963
+ }).passthrough()
1964
+ ).min(1, "getSingleSubscriber.status must be a non-empty array")
1965
+ }).passthrough();
1966
+ var RESPONSE_SCHEMAS = {
1967
+ getResellerInfo: GetResellerInfoResponse,
1968
+ listResellerAccount: ListResellerAccountResponse,
1969
+ listPrepaidPackageTemplate: ListPrepaidPackageTemplateResponse,
1970
+ getSingleSubscriber: GetSingleSubscriberResponse
1971
+ };
1972
+ var IccidParam = z.object({ iccid: z.string().min(1) });
1973
+ var AccountIdParam = z.object({ accountId: z.coerce.number().int().positive() });
1974
+ var PackageIdParam = z.object({ packageId: z.coerce.number().int().positive() });
1975
+ var TemplateIdParam = z.object({ templateId: z.coerce.number().int().positive() });
1976
+ var ResellerIdParam = z.object({ resellerId: z.coerce.number().int().positive() });
1977
+ var DateRangeBody = z.object({
1978
+ start: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "must be YYYY-MM-DD"),
1979
+ end: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "must be YYYY-MM-DD")
1980
+ });
1981
+ var ErrorResponse = z.object({
1982
+ error: z.string(),
1983
+ code: z.number().optional(),
1984
+ retryAfter: z.number().optional()
1985
+ });
1986
+ var OkResponse = z.object({
1987
+ ok: z.boolean(),
1988
+ data: z.unknown().optional()
1989
+ });
1990
+ var ModifySubscriberStatusBody = z.object({
1991
+ newStatus: z.enum(["active", "suspended", "deactivated"])
1992
+ });
1993
+ var ModifySubscriberBalanceBody = z.object({
1994
+ amount: z.number().optional(),
1995
+ setBalance: z.number().optional()
1996
+ }).refine((v) => v.amount !== void 0 || v.setBalance !== void 0, {
1997
+ message: "Provide either amount (delta) or setBalance (absolute)"
1998
+ });
1999
+ var ModifySubscriberContactInfoBody = z.object({
2000
+ name: z.string().optional(),
2001
+ mail: z.string().email().optional(),
2002
+ phone: z.string().optional()
2003
+ });
2004
+ var SetTrafficRestrictionsBody = z.object({
2005
+ blockData: z.boolean().optional(),
2006
+ blockVoice: z.boolean().optional(),
2007
+ blockSms: z.boolean().optional(),
2008
+ blockRoaming: z.boolean().optional()
2009
+ });
2010
+ var ModifySteeringListBody = z.object({
2011
+ steeringListId: z.number().int().positive()
2012
+ });
2013
+ var HlrSetBitrateBody = z.object({
2014
+ limit: z.number().int().positive()
2015
+ });
2016
+ var AssignPackageBody = z.object({
2017
+ packageTemplateId: z.number().int().positive(),
2018
+ startDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional()
2019
+ });
2020
+ var AssignRecurringPackageBody = z.object({
2021
+ packageTemplateId: z.number().int().positive()
2022
+ });
2023
+ var ModifyPackageLimitsBody = z.object({
2024
+ dataLimitMb: z.number().positive().optional(),
2025
+ voiceLimitMin: z.number().nonnegative().optional(),
2026
+ smsLimit: z.number().nonnegative().optional()
2027
+ });
2028
+ var ModifyPackageExpiryBody = z.object({
2029
+ expiryDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/)
2030
+ });
2031
+ var ModifyPackageStatusBody = z.object({
2032
+ status: z.enum(["active", "paused"])
2033
+ });
2034
+ var StopResumeRecurringBody = z.object({
2035
+ action: z.enum(["stop", "resume"])
2036
+ });
2037
+ var CreatePackageTemplateBody = z.object({
2038
+ name: z.string().min(1),
2039
+ dataLimitMb: z.number().positive(),
2040
+ validityDays: z.number().int().positive(),
2041
+ price: z.number().nonnegative().optional(),
2042
+ recurring: z.boolean().optional()
2043
+ });
2044
+ var ModifyTemplateCoreBody = z.object({
2045
+ name: z.string().optional(),
2046
+ dataLimitMb: z.number().positive().optional(),
2047
+ validityDays: z.number().int().positive().optional()
2048
+ });
2049
+ var ModifyTemplateRecurringBody = z.object({
2050
+ billingCycleDays: z.number().int().positive().optional(),
2051
+ autoRenew: z.boolean().optional()
2052
+ });
2053
+ var ModifyTemplateThrottlingBody = z.object({
2054
+ throttleSpeedKbps: z.number().int().nonnegative()
2055
+ });
2056
+ var ModifyAccountBalanceBody = z.object({
2057
+ amount: z.number(),
2058
+ mode: z.enum(["add", "subtract", "set"]).default("add")
2059
+ });
2060
+ var MoveSubscribersBody = z.object({
2061
+ fromAccountId: z.number().int().positive(),
2062
+ iccidStart: z.string().min(1),
2063
+ iccidEnd: z.string().min(1)
2064
+ });
2065
+ var CreateLocationZoneBody = z.object({
2066
+ name: z.string().min(1),
2067
+ countries: z.array(z.string().length(2)).min(1)
2068
+ });
2069
+ var SendSmsBody = z.object({
2070
+ text: z.string().min(1).max(160),
2071
+ senderId: z.string().optional()
2072
+ });
2073
+ var ChangeSimStatusBody = z.object({
2074
+ newStatus: z.enum(["Enable", "Disable"])
2075
+ });
2076
+ var DiagnoseSubscriberBody = z.object({
2077
+ iccid: z.string().min(1)
2078
+ });
2079
+ var FleetHealthQuery = z.object({
2080
+ accountId: z.coerce.number().int().positive().optional()
2081
+ });
2082
+ var ChurnRiskQuery = z.object({
2083
+ daysSinceUsage: z.coerce.number().int().positive().default(14),
2084
+ limit: z.coerce.number().int().positive().max(500).default(50)
2085
+ });
2086
+ var DetectUsageAnomaliesBody = z.object({
2087
+ start: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
2088
+ end: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
2089
+ thresholdMultiplier: z.number().positive().default(2.5)
2090
+ });
2091
+ var OptimizePackageBody = z.object({
2092
+ iccid: z.string().min(1)
2093
+ });
2094
+ var AuditNetworkCoverageBody = z.object({
2095
+ locationZoneId: z.number().int().positive().optional()
2096
+ });
2097
+ var MarketingIntelligenceQuery = z.object({
2098
+ segment: z.enum(["low_usage", "high_usage", "expiring_soon", "churned"]).optional()
2099
+ });
2100
+ var HighCostSubscribersQuery = z.object({
2101
+ limit: z.coerce.number().int().positive().max(200).default(20),
2102
+ start: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
2103
+ end: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional()
2104
+ });
2105
+ var WebhookEventBody = z.record(z.string(), z.unknown());
2106
+ var HealthResponse = z.object({
2107
+ ok: z.literal(true),
2108
+ version: z.string(),
2109
+ build_sha: z.string()
2110
+ });
2111
+
1879
2112
  // ../../packages/ocs-client/dist/chunk-CGMK4FTD.js
1880
2113
  var DEFAULT_OCS_BUDGET = {
1881
2114
  attemptMs: 3e4,
@@ -1982,7 +2215,45 @@ async function runWithBudget(method, attempt, budget = ocsBudgetFor(method)) {
1982
2215
  throw lastTimeout ?? new OcsTimeoutError(method, budget.attemptMs, budget.totalMs, Math.max(attempts, 1));
1983
2216
  }
1984
2217
 
1985
- // ../../packages/ocs-client/dist/chunk-OPUTHPZF.js
2218
+ // ../../packages/ocs-client/dist/chunk-3DUJKSSY.js
2219
+ var RATE_LIMIT = 10;
2220
+ var WINDOW_MS = 1e3;
2221
+ var windows = /* @__PURE__ */ new Map();
2222
+ function getWindowState(key) {
2223
+ let s = windows.get(key);
2224
+ if (!s) {
2225
+ s = { log: [], gate: Promise.resolve() };
2226
+ windows.set(key, s);
2227
+ }
2228
+ return s;
2229
+ }
2230
+ async function acquireToken(resellerId) {
2231
+ const proc = globalThis["process"];
2232
+ if (proc?.env?.["RATE_FLOOR_DISABLED"] === "true" || globalThis["RATE_FLOOR_DISABLED"] === "true") {
2233
+ return;
2234
+ }
2235
+ const state = getWindowState(resellerId);
2236
+ const ticket = state.gate.then(async () => {
2237
+ while (true) {
2238
+ const now = Date.now();
2239
+ if (state.log.length < RATE_LIMIT) {
2240
+ state.log.push(now);
2241
+ return;
2242
+ }
2243
+ const oldest = state.log[0];
2244
+ const age = now - oldest;
2245
+ if (age >= WINDOW_MS) {
2246
+ state.log.shift();
2247
+ state.log.push(now);
2248
+ return;
2249
+ }
2250
+ const waitMs = WINDOW_MS - age + 1;
2251
+ await new Promise((r) => setTimeout(r, waitMs));
2252
+ }
2253
+ });
2254
+ state.gate = ticket;
2255
+ return ticket;
2256
+ }
1986
2257
  var ENDPOINT_LIMITS_PER_MIN = {
1987
2258
  // Global sentinel (keyed as "__global__")
1988
2259
  __global__: 600,
@@ -2142,8 +2413,25 @@ function getRateLimitWindowCounts(resellerKey, endpoint) {
2142
2413
  }
2143
2414
  return { calls_in_window, batch_calls_in_window };
2144
2415
  }
2416
+ var OCS_BARE_INT_RESELLER_METHODS = [
2417
+ "listSponsor",
2418
+ "listSteeringList",
2419
+ "listDetailedDestinationList",
2420
+ "listDetailedLocationZone",
2421
+ "getCustomerTariff"
2422
+ ];
2423
+ var OCS_BARE_INT_OTHER_METHODS = {
2424
+ listLocationZoneElement: "locationZoneId",
2425
+ listDestinationListPrefix: "destinationListId",
2426
+ listVoipTariffRule: "voipPlanId",
2427
+ getSimProviderStatus: "simId",
2428
+ deleteSubscriberPackage: "packageId"
2429
+ };
2145
2430
  var OCS_PARAM_RENAMES = {
2146
- getResellerInfo: { resellerId: "id" }
2431
+ getResellerInfo: { resellerId: "id" },
2432
+ modifyPPTCore: { templateId: "prepaidpackagetemplateid" },
2433
+ modifyPPTRecurring: { templateId: "prepaidpackagetemplateid" },
2434
+ modifyPPTThrottling: { templateId: "prepaidpackagetemplateid" }
2147
2435
  };
2148
2436
  function applyParamRenames(method, params) {
2149
2437
  const renames = OCS_PARAM_RENAMES[method];
@@ -2160,8 +2448,257 @@ function applyParamRenames(method, params) {
2160
2448
  }
2161
2449
  return out ?? params;
2162
2450
  }
2451
+ function isBareIntResellerMethod(method) {
2452
+ return OCS_BARE_INT_RESELLER_METHODS.includes(method);
2453
+ }
2454
+ function isBareIntMethod(method) {
2455
+ return isBareIntResellerMethod(method) || Object.prototype.hasOwnProperty.call(OCS_BARE_INT_OTHER_METHODS, method);
2456
+ }
2457
+ function bareIntIdName(method) {
2458
+ if (isBareIntResellerMethod(method)) return "resellerId";
2459
+ return OCS_BARE_INT_OTHER_METHODS[method] ?? "id";
2460
+ }
2461
+ function assertBareIntParam(method, params) {
2462
+ if (!isBareIntMethod(method)) return;
2463
+ if (typeof params === "number") return;
2464
+ const shape = params === null ? "null" : Array.isArray(params) ? "array" : typeof params === "object" ? "object" : typeof params;
2465
+ throw new TypeError(
2466
+ `OCS method "${method}" takes a BARE INTEGER ${bareIntIdName(method)}, but received ${shape}. Sending an object makes OCS reject the whole request with "Cannot deserialize value of type java.lang.Integer from Object value", which surfaces in the UI as an empty panel. Pass the id itself, e.g. call("${method}", 1170).`
2467
+ );
2468
+ }
2469
+ var OcsApiError = class extends Error {
2470
+ constructor(code, message, method, details = {}) {
2471
+ super(`[${method}] OCS error ${code}: ${message}`);
2472
+ this.code = code;
2473
+ this.method = method;
2474
+ this.name = "OcsApiError";
2475
+ this.details = details;
2476
+ }
2477
+ code;
2478
+ method;
2479
+ details;
2480
+ };
2481
+ var OcsUnknownMethodError = class extends Error {
2482
+ constructor(method) {
2483
+ super(
2484
+ `[${method}] is not a known OCS v1 method. It is not in the verified set of ${OCS_V1_METHODS.size} methods (createAccount/createSubscriber do not exist on the OCS). If this is a genuinely new method, add it to OCS_V1_METHODS or construct the client without { strictMethods: true }.`
2485
+ );
2486
+ this.method = method;
2487
+ this.name = "OcsUnknownMethodError";
2488
+ }
2489
+ method;
2490
+ };
2491
+ var OcsContractError = class _OcsContractError extends Error {
2492
+ constructor(method, issues, payload) {
2493
+ super(
2494
+ `[${method}] OCS response failed contract validation: ${_OcsContractError.summarize(issues)}`
2495
+ );
2496
+ this.method = method;
2497
+ this.issues = issues;
2498
+ this.payload = payload;
2499
+ this.name = "OcsContractError";
2500
+ }
2501
+ method;
2502
+ issues;
2503
+ payload;
2504
+ /** One-line, human-readable join of the issues — for logs and the error message. */
2505
+ get summary() {
2506
+ return _OcsContractError.summarize(this.issues);
2507
+ }
2508
+ static summarize(issues) {
2509
+ return issues.map((i) => `${i.path}: ${i.message}`).join("; ");
2510
+ }
2511
+ };
2512
+ function ocsErrorMessage(code, rawMsg, rawBody) {
2513
+ switch (code) {
2514
+ case 12:
2515
+ return {
2516
+ message: "OCS resource is read-only (code 12). The package/subscriber/account state does not allow this mutation. Often returned for end-of-life subscribers or finalized invoices.",
2517
+ details: {}
2518
+ };
2519
+ case 17:
2520
+ return {
2521
+ message: "Subscriber is end-of-life (code 17). It can no longer be mutated. Use modify_subscriber_status to revive before further changes.",
2522
+ details: {}
2523
+ };
2524
+ default:
2525
+ if (code >= 10001 && code <= 10004) {
2526
+ const details = {};
2527
+ if (rawBody["invalidTadigs"] !== void 0) {
2528
+ details.invalidTadigs = rawBody["invalidTadigs"];
2529
+ }
2530
+ if (rawBody["existingLZ"] !== void 0) {
2531
+ details.existingLZ = rawBody["existingLZ"];
2532
+ }
2533
+ return { message: rawMsg || "Location zone validation failed", details };
2534
+ }
2535
+ return { message: rawMsg || "Unknown error", details: {} };
2536
+ }
2537
+ }
2538
+ var BACKOFF_BASE_MS2 = 500;
2539
+ var BACKOFF_MAX_MS = 4e3;
2540
+ var BACKOFF_MAX_RETRIES = 3;
2541
+ var BACKOFF_JITTER = 0.25;
2542
+ async function retryWithBackoff(fn) {
2543
+ let lastError;
2544
+ for (let attempt = 0; attempt <= BACKOFF_MAX_RETRIES; attempt++) {
2545
+ if (attempt > 0) {
2546
+ const base = Math.min(BACKOFF_BASE_MS2 * Math.pow(2, attempt - 1), BACKOFF_MAX_MS);
2547
+ const jitter = base * BACKOFF_JITTER * (2 * Math.random() - 1);
2548
+ const delay = Math.max(0, Math.round(base + jitter));
2549
+ await new Promise((r) => setTimeout(r, delay));
2550
+ }
2551
+ try {
2552
+ return await fn();
2553
+ } catch (err) {
2554
+ lastError = err;
2555
+ if (err instanceof OcsApiError && err.code !== 100) {
2556
+ throw err;
2557
+ }
2558
+ if (err instanceof OcsContractError) {
2559
+ throw err;
2560
+ }
2561
+ if (err instanceof OcsTimeoutError) {
2562
+ throw err;
2563
+ }
2564
+ }
2565
+ }
2566
+ throw lastError;
2567
+ }
2568
+ function isAbortError(err) {
2569
+ return err instanceof Error && (err.name === "AbortError" || err.name === "TimeoutError" || /aborted|timed? ?out/i.test(err.message));
2570
+ }
2571
+ var OcsClient = class {
2572
+ /**
2573
+ * @param baseUrl OCS base URL without trailing slash (e.g. https://ocs.esimvault.cloud).
2574
+ * @param _defaultToken Default API token; identifies the reseller for rate-floor keying.
2575
+ * @param _priority Call priority: "interactive" (MCP tool calls, 80% capacity) or
2576
+ * "batch" (cron/poll callers, 20% capacity). Default: "interactive".
2577
+ * @param options Contract-enforcement opt-outs (see `OcsClientOptions`).
2578
+ */
2579
+ constructor(baseUrl, _defaultToken, _priority = "interactive", options = {}) {
2580
+ this._defaultToken = _defaultToken;
2581
+ this._priority = _priority;
2582
+ let end = baseUrl.length;
2583
+ while (end > 0 && baseUrl.charCodeAt(end - 1) === 47) end--;
2584
+ this.baseUrl = baseUrl.slice(0, end);
2585
+ this._strictMethods = options.strictMethods ?? false;
2586
+ this._validateResponses = options.validateResponses ?? true;
2587
+ this._strictValidation = options.strictValidation ?? false;
2588
+ }
2589
+ _defaultToken;
2590
+ _priority;
2591
+ baseUrl;
2592
+ _strictMethods;
2593
+ _validateResponses;
2594
+ _strictValidation;
2595
+ // Per-instance (NOT static): a static set would dedup across requests in a
2596
+ // reused Worker isolate and silently swallow recurring contract-drift warnings.
2597
+ _warnedMethods = /* @__PURE__ */ new Set();
2598
+ _warnedValidation = /* @__PURE__ */ new Set();
2599
+ async call(method, params = {}, token) {
2600
+ if (!OCS_V1_METHODS.has(method)) {
2601
+ if (this._strictMethods) throw new OcsUnknownMethodError(method);
2602
+ if (!this._warnedMethods.has(method)) {
2603
+ this._warnedMethods.add(method);
2604
+ console.warn(
2605
+ `[ocs-client] method "${method}" is not in the verified OCS v1 set \u2014 it may not exist on this OCS instance (see OCS_V1_METHODS).`
2606
+ );
2607
+ }
2608
+ }
2609
+ const tok = token ?? this._defaultToken;
2610
+ if (!tok) {
2611
+ throw new OcsApiError(-1, "No OCS API token provided", method);
2612
+ }
2613
+ const url = `${this.baseUrl}/v1?token=${tok}`;
2614
+ assertBareIntParam(method, params);
2615
+ const wireParams = applyParamRenames(method, params);
2616
+ const body = JSON.stringify({ [method]: wireParams });
2617
+ return retryWithBackoff(async () => {
2618
+ await acquireToken(tok);
2619
+ await acquireEndpointSlot(tok, method, this._priority);
2620
+ return runWithBudget(method, async (signal, attemptMs) => {
2621
+ let res;
2622
+ try {
2623
+ res = await fetch(url, {
2624
+ method: "POST",
2625
+ headers: { "Content-Type": "application/json" },
2626
+ body,
2627
+ signal
2628
+ });
2629
+ } catch (err) {
2630
+ if (isAbortError(err)) {
2631
+ throw new OcsTimeoutError(method, attemptMs);
2632
+ }
2633
+ throw err;
2634
+ }
2635
+ if (res.status >= 500) {
2636
+ throw new Error(`HTTP ${res.status} ${res.statusText}`);
2637
+ }
2638
+ if (!res.ok) {
2639
+ throw new OcsApiError(
2640
+ res.status,
2641
+ `HTTP ${res.status} ${res.statusText}`,
2642
+ method
2643
+ );
2644
+ }
2645
+ let json;
2646
+ try {
2647
+ json = await res.json();
2648
+ } catch (err) {
2649
+ if (isAbortError(err)) {
2650
+ throw new OcsTimeoutError(method, attemptMs);
2651
+ }
2652
+ throw err;
2653
+ }
2654
+ if (json.status?.code !== 0) {
2655
+ const ocsCode = json.status?.code ?? -1;
2656
+ const rawMsg = json.status?.msg ?? "Unknown error";
2657
+ const rawBody = json;
2658
+ const { message, details } = ocsErrorMessage(ocsCode, rawMsg, rawBody);
2659
+ throw new OcsApiError(ocsCode, message, method, details);
2660
+ }
2661
+ let payload;
2662
+ if (method === "getCustomerTariff" && json["listTariffRule"] !== void 0) {
2663
+ payload = json["listTariffRule"];
2664
+ } else if (method === "getSubscriberLocationByCellId") {
2665
+ const byMethod = json[method];
2666
+ if (byMethod !== void 0) {
2667
+ payload = byMethod;
2668
+ } else if (json["subscriberLocation"] !== void 0) {
2669
+ payload = json["subscriberLocation"];
2670
+ } else {
2671
+ payload = json[method] ?? json;
2672
+ }
2673
+ } else {
2674
+ payload = json[method] ?? json;
2675
+ }
2676
+ if (this._validateResponses) {
2677
+ const schema = RESPONSE_SCHEMAS[method];
2678
+ if (schema) {
2679
+ const parsed = schema.safeParse(payload);
2680
+ if (!parsed.success) {
2681
+ const issues = parsed.error.issues.map((i) => ({
2682
+ path: i.path.join(".") || "<root>",
2683
+ message: i.message
2684
+ }));
2685
+ if (this._strictValidation) {
2686
+ throw new OcsContractError(method, issues, payload);
2687
+ }
2688
+ if (!this._warnedValidation.has(method)) {
2689
+ this._warnedValidation.add(method);
2690
+ console.warn(`[ocs-client] ${new OcsContractError(method, issues, payload).message}`);
2691
+ }
2692
+ }
2693
+ }
2694
+ }
2695
+ return payload;
2696
+ });
2697
+ });
2698
+ }
2699
+ };
2163
2700
 
2164
- // ../../packages/ocs-client/dist/chunk-JWSVJVAF.js
2701
+ // ../../packages/ocs-client/dist/chunk-BBZNZIAA.js
2165
2702
  var OCS_MAX_USAGE_WINDOW_DAYS = 7;
2166
2703
  function clampUsagePeriod(start, end, maxDays = OCS_MAX_USAGE_WINDOW_DAYS) {
2167
2704
  const endMs = Date.parse(`${end}T00:00:00Z`);
@@ -2224,6 +2761,125 @@ function imsiFromSubscriberRecord(record) {
2224
2761
  }
2225
2762
  return void 0;
2226
2763
  }
2764
+ var OCS_PREPAID_PACKAGE_LIMIT_FIELDS = [
2765
+ "dataByte",
2766
+ "mocSecond",
2767
+ "mtcSecond",
2768
+ "moSms",
2769
+ "mtSms"
2770
+ ];
2771
+ var LIMIT_ALIASES = {
2772
+ dataByte: "dataByte",
2773
+ dataBytes: "dataByte",
2774
+ dataLimit: "dataByte",
2775
+ databyte: "dataByte",
2776
+ mocSecond: "mocSecond",
2777
+ mocSeconds: "mocSecond",
2778
+ voiceOutLimit: "mocSecond",
2779
+ mtcSecond: "mtcSecond",
2780
+ mtcSeconds: "mtcSecond",
2781
+ voiceInLimit: "mtcSecond",
2782
+ moSms: "moSms",
2783
+ moSmsNumber: "moSms",
2784
+ smsOutLimit: "moSms",
2785
+ mtSms: "mtSms",
2786
+ mtSmsNumber: "mtSms",
2787
+ smsInLimit: "mtSms"
2788
+ };
2789
+ function prepaidPackageLimits(limits) {
2790
+ const out = {};
2791
+ const unknown = [];
2792
+ for (const [key, value] of Object.entries(limits)) {
2793
+ const target = LIMIT_ALIASES[key];
2794
+ if (!target) {
2795
+ unknown.push(key);
2796
+ continue;
2797
+ }
2798
+ out[target] = value;
2799
+ }
2800
+ if (unknown.length > 0) {
2801
+ throw new Error(
2802
+ `Unknown package limit field(s): ${unknown.join(", ")}. OCS accepts only ${OCS_PREPAID_PACKAGE_LIMIT_FIELDS.join(", ")} inside newLimits (aliases: ${Object.keys(LIMIT_ALIASES).join(", ")}).`
2803
+ );
2804
+ }
2805
+ if (Object.keys(out).length === 0) {
2806
+ throw new Error(
2807
+ `No package limits to change. Provide at least one of ${OCS_PREPAID_PACKAGE_LIMIT_FIELDS.join(", ")}.`
2808
+ );
2809
+ }
2810
+ return out;
2811
+ }
2812
+ function ocsLocalDateTime(value, bareDate = "end") {
2813
+ const trimmed = value.trim();
2814
+ if (/^\d{4}-\d{2}-\d{2}$/.test(trimmed)) {
2815
+ return bareDate === "start" ? `${trimmed}T00:00:00` : `${trimmed}T23:59:59`;
2816
+ }
2817
+ if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$/.test(trimmed)) return `${trimmed}:00`;
2818
+ if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(trimmed)) {
2819
+ return trimmed.replace(/(?:Z|[+-]\d{2}:?\d{2})$/, "").slice(0, 19);
2820
+ }
2821
+ throw new Error(
2822
+ `"${value}" is not a date OCS can read. Use YYYY-MM-DD or YYYY-MM-DDTHH:mm:ss \u2014 this field is a java.time.LocalDateTime and a zone offset is rejected.`
2823
+ );
2824
+ }
2825
+ function activePeriodFromPackages(listResponse, packageId) {
2826
+ const root = listResponse ?? {};
2827
+ const payload = root.listSubscriberPrepaidPackages ?? root.data ?? root;
2828
+ const packages = Array.isArray(payload?.packages) ? payload.packages : [];
2829
+ for (const entry of packages) {
2830
+ if (!entry || typeof entry !== "object") continue;
2831
+ const rec = entry;
2832
+ const id = rec.subscriberprepaidpackageid ?? rec.subscriberPrepaidPackageId;
2833
+ if (Number(id) !== packageId) continue;
2834
+ const activation = rec.tsactivationutc ?? rec.tsActivationUtc;
2835
+ const expiration = rec.tsexpirationutc ?? rec.tsExpirationUtc;
2836
+ const window = {};
2837
+ if (typeof activation === "string" && activation) window.activation = activation;
2838
+ if (typeof expiration === "string" && expiration) window.expiration = expiration;
2839
+ return window;
2840
+ }
2841
+ return void 0;
2842
+ }
2843
+ var OCS_ACTIVE_PERIOD_DEFAULT_COMMENT = "Active period changed via Carrier";
2844
+ function packageActivePeriodParams(packageId, change) {
2845
+ if (change.startDate === void 0 && change.endDate === void 0) {
2846
+ throw new Error("Provide startDate and/or endDate to change a package's active period.");
2847
+ }
2848
+ const activation = change.startDate !== void 0 ? ocsLocalDateTime(change.startDate, "start") : change.current?.activation;
2849
+ const expiration = change.endDate !== void 0 ? ocsLocalDateTime(change.endDate, "end") : change.current?.expiration;
2850
+ for (const [field, value, omitted] of [
2851
+ ["newActivationDateUtc", activation, "startDate"],
2852
+ ["newExpirationDateUtc", expiration, "endDate"]
2853
+ ]) {
2854
+ if (value !== void 0) continue;
2855
+ throw new Error(
2856
+ `OCS requires both bounds on an active-period change and rejects the whole request with "Missing '${field}'" when one is absent. Supply ${omitted}, or read the package's current window first (activePeriodFromPackages) and pass it as \`current\`.`
2857
+ );
2858
+ }
2859
+ return {
2860
+ packageId,
2861
+ // Already LocalDateTime-shaped when it came from `current`; normalising
2862
+ // again is a no-op and keeps a hand-passed value honest.
2863
+ newActivationDateUtc: ocsLocalDateTime(activation, "start"),
2864
+ newExpirationDateUtc: ocsLocalDateTime(expiration, "end"),
2865
+ comment: change.comment?.trim() || OCS_ACTIVE_PERIOD_DEFAULT_COMMENT
2866
+ };
2867
+ }
2868
+ function recurringIdForPackage(listResponse, packageId) {
2869
+ const root = listResponse ?? {};
2870
+ const payload = root.listSubscriberPrepaidPackages ?? root.data ?? root;
2871
+ const packages = Array.isArray(payload?.packages) ? payload.packages : [];
2872
+ for (const entry of packages) {
2873
+ if (!entry || typeof entry !== "object") continue;
2874
+ const rec = entry;
2875
+ const id = rec.subscriberprepaidpackageid ?? rec.subscriberPrepaidPackageId;
2876
+ if (Number(id) !== packageId) continue;
2877
+ const recurring = rec.recurringPackage ?? rec.recurringId;
2878
+ const value = Number(recurring);
2879
+ return Number.isFinite(value) && value > 0 ? value : void 0;
2880
+ }
2881
+ return void 0;
2882
+ }
2227
2883
  function emptyEsimStatusCounts() {
2228
2884
  return { active: 0, suspended: 0, inventory: 0, other: 0, total: 0 };
2229
2885
  }
@@ -2823,11 +3479,10 @@ async function generateStorefrontLogo(input) {
2823
3479
  }
2824
3480
 
2825
3481
  export {
2826
- runWithBudget,
2827
- acquireEndpointSlot,
2828
3482
  getLimitForEndpoint,
2829
3483
  getRateLimitWindowCounts,
2830
- applyParamRenames,
3484
+ OcsApiError,
3485
+ OcsClient,
2831
3486
  OCS_MAX_USAGE_WINDOW_DAYS,
2832
3487
  clampUsagePeriod,
2833
3488
  lastNDaysPeriod,
@@ -2837,6 +3492,11 @@ export {
2837
3492
  networkEventsOverPeriodParams,
2838
3493
  usageOverPeriodParams,
2839
3494
  imsiFromSubscriberRecord,
3495
+ prepaidPackageLimits,
3496
+ ocsLocalDateTime,
3497
+ activePeriodFromPackages,
3498
+ packageActivePeriodParams,
3499
+ recurringIdForPackage,
2840
3500
  extractEsimStatusCounts,
2841
3501
  esimStatusPerAccountParams,
2842
3502
  normalizePackageTemplate,
@@ -2890,4 +3550,4 @@ export {
2890
3550
  storefrontScreen,
2891
3551
  CARRIER_VERSION
2892
3552
  };
2893
- //# sourceMappingURL=chunk-DUAENMJE.js.map
3553
+ //# sourceMappingURL=chunk-DP4ICKYF.js.map