@carrierllc/sdk 0.2.2 → 0.2.3

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/README.md CHANGED
@@ -35,4 +35,4 @@ const agentTools = restTools(carrier)
35
35
 
36
36
  `new Mcp(token, { auth: "bearer" })` sends an OAuth access token or a Clerk organization API key. The default sends `?TOKEN=` to `https://mcp.carrier.llc/mcp`. `Cli` never invokes a shell. Catalog entries marked `internal` do not accept a customer API key.
37
37
 
38
- `npm install @carrierllc/sdk@0.2.2` installs this surface. `0.1.0` only creates connectivity intents and products. The published tarball is the compiled `dist` output, including the generated operation catalog.
38
+ `npm install @carrierllc/sdk@0.2.3` installs this surface. `0.1.0` only creates connectivity intents and products. The published tarball is the compiled `dist` output, including the generated operation catalog.
@@ -9,7 +9,21 @@ export type LabelResult = {
9
9
  ok: false;
10
10
  message: string;
11
11
  };
12
- export declare function parseDataGb(raw: string): LabelResult;
12
+ /**
13
+ * `unlimited` is always explicit, never inferred later from a bare 0.
14
+ * A caller reading only `value` and forgetting to check `unlimited` gets a
15
+ * finite 0, which every downstream consumer treats as "no data" and rejects
16
+ * or hides, not as "unlimited" — the failure mode is loud, not silent.
17
+ */
18
+ export type DataGbResult = {
19
+ ok: true;
20
+ value: number;
21
+ unlimited: boolean;
22
+ } | {
23
+ ok: false;
24
+ message: string;
25
+ };
26
+ export declare function parseDataGb(raw: string): DataGbResult;
13
27
  export declare function parseValidityDays(raw: string): LabelResult;
14
28
  /** Stripe minor units. Yen is already the minor unit, so 1000 JPY stays 1000. */
15
29
  export declare function majorToCents(input: string, currency?: string): {
@@ -21,8 +21,11 @@ NAME_TO_CODE.set("uk", "GB");
21
21
  const CODE_ALIASES = { UK: "GB" };
22
22
  export function parseDataGb(raw) {
23
23
  if (raw.trim().toLowerCase() === "unlimited")
24
- return { ok: true, value: 0 };
25
- return parseAmount(raw, /gigabytes?|gbs?|gb/gi, "Enter data like 1, 1 GB, or Unlimited.", 10_000, false);
24
+ return { ok: true, value: 0, unlimited: true };
25
+ const parsed = parseAmount(raw, /gigabytes?|gbs?|gb/gi, "Enter data like 1, 1 GB, or Unlimited.", 10_000, false);
26
+ if (!parsed.ok)
27
+ return parsed;
28
+ return { ok: true, value: parsed.value, unlimited: false };
26
29
  }
27
30
  export function parseValidityDays(raw) {
28
31
  return parseAmount(raw, /days?/gi, "Enter validity like 7 or 7 days.", 3650, true);
@@ -23,6 +23,8 @@ export interface StorefrontPlanInput {
23
23
  currency?: string;
24
24
  templateId?: number;
25
25
  dataGb?: number;
26
+ /** The only way a plan becomes unlimited. A 0 or missing dataGb without this stays finite. */
27
+ unlimited?: boolean;
26
28
  validityDays?: number;
27
29
  regions?: string[];
28
30
  description?: string;
@@ -40,6 +42,7 @@ export interface StorefrontPlanBody {
40
42
  currency?: string;
41
43
  ocs_package_template_id?: number;
42
44
  data_gb?: number;
45
+ unlimited?: boolean;
43
46
  validity_days?: number;
44
47
  regions?: string[];
45
48
  description?: string;
@@ -36,6 +36,7 @@ export function completePlanInput(input, plans) {
36
36
  input.currency,
37
37
  input.templateId,
38
38
  input.dataGb,
39
+ input.unlimited,
39
40
  input.validityDays,
40
41
  input.regions,
41
42
  input.description,
@@ -82,6 +83,7 @@ export function storefrontPlanBody(input) {
82
83
  input.currency,
83
84
  input.templateId,
84
85
  input.dataGb,
86
+ input.unlimited,
85
87
  input.validityDays,
86
88
  input.regions,
87
89
  input.description,
@@ -92,6 +94,13 @@ export function storefrontPlanBody(input) {
92
94
  if (!input.slug || !input.name || input.priceCents === undefined || !input.currency || input.templateId === undefined) {
93
95
  return { error: "A plan needs a slug, name, price in minor units, currency, and OCS template id." };
94
96
  }
97
+ // A missing or zero dataGb never means unlimited on its own: that reading is
98
+ // exactly the bug a forgotten field falls into. `unlimited: true` is the
99
+ // only way in. A caller that means "unlimited" and sends 0 without the flag
100
+ // gets a loud rejection, not a silently unlimited plan.
101
+ if (input.dataGb !== undefined && input.dataGb <= 0 && input.unlimited !== true) {
102
+ return { error: "data_gb of 0 is refused. Send unlimited: true to sell an unlimited plan." };
103
+ }
95
104
  const body = {
96
105
  slug: input.slug,
97
106
  name: input.name,
@@ -101,6 +110,8 @@ export function storefrontPlanBody(input) {
101
110
  };
102
111
  if (input.dataGb !== undefined)
103
112
  body.data_gb = input.dataGb;
113
+ if (input.unlimited !== undefined)
114
+ body.unlimited = input.unlimited;
104
115
  if (input.validityDays !== undefined)
105
116
  body.validity_days = input.validityDays;
106
117
  if (input.regions !== undefined)
package/dist/types.d.ts CHANGED
@@ -9,6 +9,8 @@ export interface ConnectivityPlan {
9
9
  object: "connectivity.plan";
10
10
  name: string;
11
11
  data_mb: number;
12
+ /** True only when the plan is explicitly unlimited. A 0 or missing data_mb never implies this. */
13
+ unlimited: boolean;
12
14
  validity_days: number;
13
15
  countries: string[];
14
16
  livemode: boolean;
@@ -78,6 +80,8 @@ export interface StorefrontPlanParams {
78
80
  product_id?: string;
79
81
  description?: string;
80
82
  data_gb?: number;
83
+ /** The only way to sell an unlimited plan. A 0 or missing data_gb without this is refused. */
84
+ unlimited?: boolean;
81
85
  validity_days?: number;
82
86
  regions?: string[];
83
87
  active?: boolean;
package/dist/version.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  /** Published version. Keep this equal to package.json. */
2
- export declare const SDK_VERSION = "0.2.2";
3
- export declare const USER_AGENT = "@carrierllc/sdk/0.2.2";
2
+ export declare const SDK_VERSION = "0.2.3";
3
+ export declare const USER_AGENT = "@carrierllc/sdk/0.2.3";
package/dist/version.js CHANGED
@@ -1,3 +1,3 @@
1
1
  /** Published version. Keep this equal to package.json. */
2
- export const SDK_VERSION = "0.2.2";
2
+ export const SDK_VERSION = "0.2.3";
3
3
  export const USER_AGENT = `@carrierllc/sdk/${SDK_VERSION}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@carrierllc/sdk",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "TypeScript client for the Carrier API, MCP server, and CLI.",
5
5
  "license": "MIT",
6
6
  "type": "module",