priceos 0.0.41 → 0.0.42

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/cli.cjs CHANGED
@@ -111,6 +111,7 @@ ${text}`);
111
111
  }
112
112
  const features = await res.json();
113
113
  const typeByKey = /* @__PURE__ */ new Map();
114
+ const trackingByKey = /* @__PURE__ */ new Map();
114
115
  for (const feature of features ?? []) {
115
116
  if (!feature?.featureKey) continue;
116
117
  const key = feature.featureKey;
@@ -118,10 +119,18 @@ ${text}`);
118
119
  const currentType = typeByKey.get(key);
119
120
  if (!currentType) {
120
121
  typeByKey.set(key, nextType);
122
+ } else if (currentType !== nextType) {
123
+ typeByKey.set(key, "unknown");
124
+ }
125
+ if (nextType !== "limit") continue;
126
+ const nextTracking = feature.tracksUsage === true ? "tracked" : feature.tracksUsage === false ? "untracked" : "unknown";
127
+ const currentTracking = trackingByKey.get(key);
128
+ if (!currentTracking) {
129
+ trackingByKey.set(key, nextTracking);
121
130
  continue;
122
131
  }
123
- if (currentType !== nextType) {
124
- typeByKey.set(key, "unknown");
132
+ if (currentTracking !== nextTracking) {
133
+ trackingByKey.set(key, "unknown");
125
134
  }
126
135
  }
127
136
  const keys = [...typeByKey.keys()].sort();
@@ -130,7 +139,7 @@ ${text}`);
130
139
  const limitUnion = limitKeys.length ? limitKeys.map((k) => JSON.stringify(k)).join(" | ") : "never";
131
140
  const mapLines = keys.map((key) => {
132
141
  const featureType = typeByKey.get(key);
133
- const accessType = featureType === "boolean" ? "BooleanFeatureAccess" : featureType === "limit" ? "LimitFeatureAccess" : "FeatureAccessEntry";
142
+ const accessType = featureType === "boolean" ? "BooleanFeatureAccess" : featureType === "limit" ? trackingByKey.get(key) === "tracked" ? "TrackedLimitFeatureAccess" : trackingByKey.get(key) === "untracked" ? "UntrackedLimitFeatureAccess" : "LimitFeatureAccess" : "FeatureAccessEntry";
134
143
  return ` ${JSON.stringify(key)}: ${accessType};`;
135
144
  });
136
145
  const content = `// Auto-generated by PriceOS (priceos generate-types). Do not edit.
@@ -140,13 +149,39 @@ export type BooleanFeatureAccess = {
140
149
  type: "boolean";
141
150
  hasAccess: boolean;
142
151
  };
143
- export type LimitFeatureAccess = {
152
+ export type LimitFeatureUsage = {
153
+ used: number;
154
+ remaining: number | null;
155
+ bonusRemaining: number;
156
+ bonusUsed: number;
157
+ resetsWhen: "billing_period" | "calendar";
158
+ resetType: "never" | "day" | "week" | "month" | "year";
159
+ nextReset: number | null;
160
+ lastReset: number | null;
161
+ };
162
+ export type TrackedLimitFeatureAccess = {
163
+ type: "limit";
164
+ hasAccess: boolean;
165
+ isUnlimited: boolean;
166
+ limit: number | null;
167
+ used: number;
168
+ remaining: number | null;
169
+ bonusRemaining: number;
170
+ bonusUsed: number;
171
+ usage: LimitFeatureUsage;
172
+ };
173
+ export type UntrackedLimitFeatureAccess = {
144
174
  type: "limit";
145
175
  hasAccess: boolean;
146
176
  isUnlimited: boolean;
147
177
  limit: number | null;
148
178
  used: number;
179
+ remaining: number | null;
180
+ bonusRemaining: number;
181
+ bonusUsed: number;
182
+ usage: LimitFeatureUsage;
149
183
  };
184
+ export type LimitFeatureAccess = TrackedLimitFeatureAccess | UntrackedLimitFeatureAccess;
150
185
  export type FeatureAccessEntry = BooleanFeatureAccess | LimitFeatureAccess;
151
186
  export type FeatureAccessMap = {
152
187
  __limitFeatureKey?: LimitFeatureKey;
package/dist/cli.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\ntype Feature = { featureKey: string; type?: \"boolean\" | \"limit\" | null };\n\nfunction argValue(args: string[], name: string) {\n const idx = args.indexOf(name);\n if (idx === -1) return undefined;\n return args[idx + 1];\n}\n\nfunction hasFlag(args: string[], name: string) {\n return args.includes(name);\n}\n\nasync function readEnvFile(filePath: string) {\n try {\n const raw = await fs.readFile(filePath, \"utf8\");\n const entries: Record<string, string> = {};\n for (const line of raw.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(\"#\")) continue;\n const eqIdx = trimmed.indexOf(\"=\");\n if (eqIdx === -1) continue;\n const rawKey = trimmed.slice(0, eqIdx).trim();\n const key = rawKey.startsWith(\"export \") ? rawKey.slice(\"export \".length).trim() : rawKey;\n let value = trimmed.slice(eqIdx + 1).trim();\n if (\n (value.startsWith(\"\\\"\") && value.endsWith(\"\\\"\")) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n if (key) {\n entries[key] = value;\n }\n }\n return entries;\n } catch {\n return {};\n }\n}\n\nfunction printHelp() {\n console.log(`\npriceos generate-types\n\nGenerates TypeScript feature access types for your PriceOS workspace.\n\nOptions:\n --api-key <key> PriceOS API key (defaults to .env.local, .env, or env PRICEOS_API_KEY) [required]\n --out <path> Output .d.ts file (default: priceos.d.ts in current directory)\n --out-dir <path> Output directory for priceos.d.ts (ignored if --out is set)\n -h, --help Show help\n\nExamples:\n priceos generate-types --api-key sk_test_... --out ./priceos.d.ts\n priceos generate-types --api-key sk_test_... --out-dir ./src\n`.trim());\n}\n\nasync function main() {\n const args = process.argv.slice(2);\n\n if (args.length === 0 || hasFlag(args, \"--help\") || hasFlag(args, \"-h\")) {\n printHelp();\n process.exit(args.length === 0 ? 1 : 0);\n }\n\n const cmd = args[0];\n if (cmd !== \"generate-types\") {\n console.error(`Unknown command: ${cmd}`);\n printHelp();\n process.exit(1);\n }\n\n const envLocal = await readEnvFile(path.resolve(process.cwd(), \".env.local\"));\n const envDefault = await readEnvFile(path.resolve(process.cwd(), \".env\"));\n const apiKey =\n argValue(args, \"--api-key\") ??\n envLocal.PRICEOS_API_KEY ??\n envDefault.PRICEOS_API_KEY ??\n process.env.PRICEOS_API_KEY;\n\n if (!apiKey) {\n console.error(\"Missing API key. Provide --api-key <key> or set PRICEOS_API_KEY in .env.local/.env.\");\n process.exit(1);\n }\n\n const outRel = argValue(args, \"--out\");\n const outDir = argValue(args, \"--out-dir\");\n const outFile = outRel ?? \"priceos.d.ts\";\n const outPath = outDir && !outRel\n ? path.resolve(process.cwd(), outDir, outFile)\n : path.resolve(process.cwd(), outFile);\n const outDisplay = outDir && !outRel ? path.join(outDir, outFile) : outFile;\n\n const url = \"https://api.priceos.com/v1/features\";\n const res = await fetch(url, {\n headers: { \"x-api-key\": apiKey },\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n console.error(`Failed to fetch features: ${res.status} ${res.statusText}\\n${text}`);\n process.exit(1);\n }\n\n const features = (await res.json()) as Feature[];\n const typeByKey = new Map<string, \"boolean\" | \"limit\" | \"unknown\">();\n\n for (const feature of features ?? []) {\n if (!feature?.featureKey) continue;\n const key = feature.featureKey;\n const nextType = feature.type === \"boolean\" || feature.type === \"limit\" ? feature.type : \"unknown\";\n const currentType = typeByKey.get(key);\n if (!currentType) {\n typeByKey.set(key, nextType);\n continue;\n }\n if (currentType !== nextType) {\n typeByKey.set(key, \"unknown\");\n }\n }\n\n const keys = [...typeByKey.keys()].sort();\n const union = keys.length ? keys.map((k) => JSON.stringify(k)).join(\" | \") : \"never\";\n const limitKeys = keys.filter((key) => typeByKey.get(key) === \"limit\");\n const limitUnion = limitKeys.length ? limitKeys.map((k) => JSON.stringify(k)).join(\" | \") : \"never\";\n const mapLines = keys.map((key) => {\n const featureType = typeByKey.get(key);\n const accessType =\n featureType === \"boolean\"\n ? \"BooleanFeatureAccess\"\n : featureType === \"limit\"\n ? \"LimitFeatureAccess\"\n : \"FeatureAccessEntry\";\n return ` ${JSON.stringify(key)}: ${accessType};`;\n });\n\n const content = `// Auto-generated by PriceOS (priceos generate-types). Do not edit.\nexport type FeatureKey = ${union};\nexport type LimitFeatureKey = ${limitUnion};\nexport type BooleanFeatureAccess = {\n type: \"boolean\";\n hasAccess: boolean;\n};\nexport type LimitFeatureAccess = {\n type: \"limit\";\n hasAccess: boolean;\n isUnlimited: boolean;\n limit: number | null;\n used: number;\n};\nexport type FeatureAccessEntry = BooleanFeatureAccess | LimitFeatureAccess;\nexport type FeatureAccessMap = {\n __limitFeatureKey?: LimitFeatureKey;\n${mapLines.join(\"\\n\")}\n} & Record<string, FeatureAccessEntry>;\n`;\n\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.writeFile(outPath, content, \"utf8\");\n\n console.log(`Generated ${outDisplay} (${keys.length} feature keys)`);\n}\n\nmain().catch((e) => {\n console.error(e);\n process.exit(1);\n});\n"],"mappings":"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","names":["fs","path"]}
1
+ {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\ntype Feature = {\n featureKey: string;\n type?: \"boolean\" | \"limit\" | null;\n tracksUsage?: boolean | null;\n};\n\nfunction argValue(args: string[], name: string) {\n const idx = args.indexOf(name);\n if (idx === -1) return undefined;\n return args[idx + 1];\n}\n\nfunction hasFlag(args: string[], name: string) {\n return args.includes(name);\n}\n\nasync function readEnvFile(filePath: string) {\n try {\n const raw = await fs.readFile(filePath, \"utf8\");\n const entries: Record<string, string> = {};\n for (const line of raw.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(\"#\")) continue;\n const eqIdx = trimmed.indexOf(\"=\");\n if (eqIdx === -1) continue;\n const rawKey = trimmed.slice(0, eqIdx).trim();\n const key = rawKey.startsWith(\"export \") ? rawKey.slice(\"export \".length).trim() : rawKey;\n let value = trimmed.slice(eqIdx + 1).trim();\n if (\n (value.startsWith(\"\\\"\") && value.endsWith(\"\\\"\")) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n if (key) {\n entries[key] = value;\n }\n }\n return entries;\n } catch {\n return {};\n }\n}\n\nfunction printHelp() {\n console.log(`\npriceos generate-types\n\nGenerates TypeScript feature access types for your PriceOS workspace.\n\nOptions:\n --api-key <key> PriceOS API key (defaults to .env.local, .env, or env PRICEOS_API_KEY) [required]\n --out <path> Output .d.ts file (default: priceos.d.ts in current directory)\n --out-dir <path> Output directory for priceos.d.ts (ignored if --out is set)\n -h, --help Show help\n\nExamples:\n priceos generate-types --api-key sk_test_... --out ./priceos.d.ts\n priceos generate-types --api-key sk_test_... --out-dir ./src\n`.trim());\n}\n\nasync function main() {\n const args = process.argv.slice(2);\n\n if (args.length === 0 || hasFlag(args, \"--help\") || hasFlag(args, \"-h\")) {\n printHelp();\n process.exit(args.length === 0 ? 1 : 0);\n }\n\n const cmd = args[0];\n if (cmd !== \"generate-types\") {\n console.error(`Unknown command: ${cmd}`);\n printHelp();\n process.exit(1);\n }\n\n const envLocal = await readEnvFile(path.resolve(process.cwd(), \".env.local\"));\n const envDefault = await readEnvFile(path.resolve(process.cwd(), \".env\"));\n const apiKey =\n argValue(args, \"--api-key\") ??\n envLocal.PRICEOS_API_KEY ??\n envDefault.PRICEOS_API_KEY ??\n process.env.PRICEOS_API_KEY;\n\n if (!apiKey) {\n console.error(\"Missing API key. Provide --api-key <key> or set PRICEOS_API_KEY in .env.local/.env.\");\n process.exit(1);\n }\n\n const outRel = argValue(args, \"--out\");\n const outDir = argValue(args, \"--out-dir\");\n const outFile = outRel ?? \"priceos.d.ts\";\n const outPath = outDir && !outRel\n ? path.resolve(process.cwd(), outDir, outFile)\n : path.resolve(process.cwd(), outFile);\n const outDisplay = outDir && !outRel ? path.join(outDir, outFile) : outFile;\n\n const url = \"https://api.priceos.com/v1/features\";\n const res = await fetch(url, {\n headers: { \"x-api-key\": apiKey },\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n console.error(`Failed to fetch features: ${res.status} ${res.statusText}\\n${text}`);\n process.exit(1);\n }\n\n const features = (await res.json()) as Feature[];\n const typeByKey = new Map<string, \"boolean\" | \"limit\" | \"unknown\">();\n const trackingByKey = new Map<string, \"tracked\" | \"untracked\" | \"unknown\">();\n\n for (const feature of features ?? []) {\n if (!feature?.featureKey) continue;\n const key = feature.featureKey;\n const nextType = feature.type === \"boolean\" || feature.type === \"limit\" ? feature.type : \"unknown\";\n const currentType = typeByKey.get(key);\n if (!currentType) {\n typeByKey.set(key, nextType);\n } else if (currentType !== nextType) {\n typeByKey.set(key, \"unknown\");\n }\n\n if (nextType !== \"limit\") continue;\n\n const nextTracking =\n feature.tracksUsage === true\n ? \"tracked\"\n : feature.tracksUsage === false\n ? \"untracked\"\n : \"unknown\";\n const currentTracking = trackingByKey.get(key);\n if (!currentTracking) {\n trackingByKey.set(key, nextTracking);\n continue;\n }\n if (currentTracking !== nextTracking) {\n trackingByKey.set(key, \"unknown\");\n }\n }\n\n const keys = [...typeByKey.keys()].sort();\n const union = keys.length ? keys.map((k) => JSON.stringify(k)).join(\" | \") : \"never\";\n const limitKeys = keys.filter((key) => typeByKey.get(key) === \"limit\");\n const limitUnion = limitKeys.length ? limitKeys.map((k) => JSON.stringify(k)).join(\" | \") : \"never\";\n const mapLines = keys.map((key) => {\n const featureType = typeByKey.get(key);\n const accessType =\n featureType === \"boolean\"\n ? \"BooleanFeatureAccess\"\n : featureType === \"limit\"\n ? trackingByKey.get(key) === \"tracked\"\n ? \"TrackedLimitFeatureAccess\"\n : trackingByKey.get(key) === \"untracked\"\n ? \"UntrackedLimitFeatureAccess\"\n : \"LimitFeatureAccess\"\n : \"FeatureAccessEntry\";\n return ` ${JSON.stringify(key)}: ${accessType};`;\n });\n\n const content = `// Auto-generated by PriceOS (priceos generate-types). Do not edit.\nexport type FeatureKey = ${union};\nexport type LimitFeatureKey = ${limitUnion};\nexport type BooleanFeatureAccess = {\n type: \"boolean\";\n hasAccess: boolean;\n};\nexport type LimitFeatureUsage = {\n used: number;\n remaining: number | null;\n bonusRemaining: number;\n bonusUsed: number;\n resetsWhen: \"billing_period\" | \"calendar\";\n resetType: \"never\" | \"day\" | \"week\" | \"month\" | \"year\";\n nextReset: number | null;\n lastReset: number | null;\n};\nexport type TrackedLimitFeatureAccess = {\n type: \"limit\";\n hasAccess: boolean;\n isUnlimited: boolean;\n limit: number | null;\n used: number;\n remaining: number | null;\n bonusRemaining: number;\n bonusUsed: number;\n usage: LimitFeatureUsage;\n};\nexport type UntrackedLimitFeatureAccess = {\n type: \"limit\";\n hasAccess: boolean;\n isUnlimited: boolean;\n limit: number | null;\n used: number;\n remaining: number | null;\n bonusRemaining: number;\n bonusUsed: number;\n usage: LimitFeatureUsage;\n};\nexport type LimitFeatureAccess = TrackedLimitFeatureAccess | UntrackedLimitFeatureAccess;\nexport type FeatureAccessEntry = BooleanFeatureAccess | LimitFeatureAccess;\nexport type FeatureAccessMap = {\n __limitFeatureKey?: LimitFeatureKey;\n${mapLines.join(\"\\n\")}\n} & Record<string, FeatureAccessEntry>;\n`;\n\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.writeFile(outPath, content, \"utf8\");\n\n console.log(`Generated ${outDisplay} (${keys.length} feature keys)`);\n}\n\nmain().catch((e) => {\n console.error(e);\n process.exit(1);\n});\n"],"mappings":"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","names":["fs","path"]}
package/dist/cli.js CHANGED
@@ -88,6 +88,7 @@ ${text}`);
88
88
  }
89
89
  const features = await res.json();
90
90
  const typeByKey = /* @__PURE__ */ new Map();
91
+ const trackingByKey = /* @__PURE__ */ new Map();
91
92
  for (const feature of features ?? []) {
92
93
  if (!feature?.featureKey) continue;
93
94
  const key = feature.featureKey;
@@ -95,10 +96,18 @@ ${text}`);
95
96
  const currentType = typeByKey.get(key);
96
97
  if (!currentType) {
97
98
  typeByKey.set(key, nextType);
99
+ } else if (currentType !== nextType) {
100
+ typeByKey.set(key, "unknown");
101
+ }
102
+ if (nextType !== "limit") continue;
103
+ const nextTracking = feature.tracksUsage === true ? "tracked" : feature.tracksUsage === false ? "untracked" : "unknown";
104
+ const currentTracking = trackingByKey.get(key);
105
+ if (!currentTracking) {
106
+ trackingByKey.set(key, nextTracking);
98
107
  continue;
99
108
  }
100
- if (currentType !== nextType) {
101
- typeByKey.set(key, "unknown");
109
+ if (currentTracking !== nextTracking) {
110
+ trackingByKey.set(key, "unknown");
102
111
  }
103
112
  }
104
113
  const keys = [...typeByKey.keys()].sort();
@@ -107,7 +116,7 @@ ${text}`);
107
116
  const limitUnion = limitKeys.length ? limitKeys.map((k) => JSON.stringify(k)).join(" | ") : "never";
108
117
  const mapLines = keys.map((key) => {
109
118
  const featureType = typeByKey.get(key);
110
- const accessType = featureType === "boolean" ? "BooleanFeatureAccess" : featureType === "limit" ? "LimitFeatureAccess" : "FeatureAccessEntry";
119
+ const accessType = featureType === "boolean" ? "BooleanFeatureAccess" : featureType === "limit" ? trackingByKey.get(key) === "tracked" ? "TrackedLimitFeatureAccess" : trackingByKey.get(key) === "untracked" ? "UntrackedLimitFeatureAccess" : "LimitFeatureAccess" : "FeatureAccessEntry";
111
120
  return ` ${JSON.stringify(key)}: ${accessType};`;
112
121
  });
113
122
  const content = `// Auto-generated by PriceOS (priceos generate-types). Do not edit.
@@ -117,13 +126,39 @@ export type BooleanFeatureAccess = {
117
126
  type: "boolean";
118
127
  hasAccess: boolean;
119
128
  };
120
- export type LimitFeatureAccess = {
129
+ export type LimitFeatureUsage = {
130
+ used: number;
131
+ remaining: number | null;
132
+ bonusRemaining: number;
133
+ bonusUsed: number;
134
+ resetsWhen: "billing_period" | "calendar";
135
+ resetType: "never" | "day" | "week" | "month" | "year";
136
+ nextReset: number | null;
137
+ lastReset: number | null;
138
+ };
139
+ export type TrackedLimitFeatureAccess = {
140
+ type: "limit";
141
+ hasAccess: boolean;
142
+ isUnlimited: boolean;
143
+ limit: number | null;
144
+ used: number;
145
+ remaining: number | null;
146
+ bonusRemaining: number;
147
+ bonusUsed: number;
148
+ usage: LimitFeatureUsage;
149
+ };
150
+ export type UntrackedLimitFeatureAccess = {
121
151
  type: "limit";
122
152
  hasAccess: boolean;
123
153
  isUnlimited: boolean;
124
154
  limit: number | null;
125
155
  used: number;
156
+ remaining: number | null;
157
+ bonusRemaining: number;
158
+ bonusUsed: number;
159
+ usage: LimitFeatureUsage;
126
160
  };
161
+ export type LimitFeatureAccess = TrackedLimitFeatureAccess | UntrackedLimitFeatureAccess;
127
162
  export type FeatureAccessEntry = BooleanFeatureAccess | LimitFeatureAccess;
128
163
  export type FeatureAccessMap = {
129
164
  __limitFeatureKey?: LimitFeatureKey;
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\ntype Feature = { featureKey: string; type?: \"boolean\" | \"limit\" | null };\n\nfunction argValue(args: string[], name: string) {\n const idx = args.indexOf(name);\n if (idx === -1) return undefined;\n return args[idx + 1];\n}\n\nfunction hasFlag(args: string[], name: string) {\n return args.includes(name);\n}\n\nasync function readEnvFile(filePath: string) {\n try {\n const raw = await fs.readFile(filePath, \"utf8\");\n const entries: Record<string, string> = {};\n for (const line of raw.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(\"#\")) continue;\n const eqIdx = trimmed.indexOf(\"=\");\n if (eqIdx === -1) continue;\n const rawKey = trimmed.slice(0, eqIdx).trim();\n const key = rawKey.startsWith(\"export \") ? rawKey.slice(\"export \".length).trim() : rawKey;\n let value = trimmed.slice(eqIdx + 1).trim();\n if (\n (value.startsWith(\"\\\"\") && value.endsWith(\"\\\"\")) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n if (key) {\n entries[key] = value;\n }\n }\n return entries;\n } catch {\n return {};\n }\n}\n\nfunction printHelp() {\n console.log(`\npriceos generate-types\n\nGenerates TypeScript feature access types for your PriceOS workspace.\n\nOptions:\n --api-key <key> PriceOS API key (defaults to .env.local, .env, or env PRICEOS_API_KEY) [required]\n --out <path> Output .d.ts file (default: priceos.d.ts in current directory)\n --out-dir <path> Output directory for priceos.d.ts (ignored if --out is set)\n -h, --help Show help\n\nExamples:\n priceos generate-types --api-key sk_test_... --out ./priceos.d.ts\n priceos generate-types --api-key sk_test_... --out-dir ./src\n`.trim());\n}\n\nasync function main() {\n const args = process.argv.slice(2);\n\n if (args.length === 0 || hasFlag(args, \"--help\") || hasFlag(args, \"-h\")) {\n printHelp();\n process.exit(args.length === 0 ? 1 : 0);\n }\n\n const cmd = args[0];\n if (cmd !== \"generate-types\") {\n console.error(`Unknown command: ${cmd}`);\n printHelp();\n process.exit(1);\n }\n\n const envLocal = await readEnvFile(path.resolve(process.cwd(), \".env.local\"));\n const envDefault = await readEnvFile(path.resolve(process.cwd(), \".env\"));\n const apiKey =\n argValue(args, \"--api-key\") ??\n envLocal.PRICEOS_API_KEY ??\n envDefault.PRICEOS_API_KEY ??\n process.env.PRICEOS_API_KEY;\n\n if (!apiKey) {\n console.error(\"Missing API key. Provide --api-key <key> or set PRICEOS_API_KEY in .env.local/.env.\");\n process.exit(1);\n }\n\n const outRel = argValue(args, \"--out\");\n const outDir = argValue(args, \"--out-dir\");\n const outFile = outRel ?? \"priceos.d.ts\";\n const outPath = outDir && !outRel\n ? path.resolve(process.cwd(), outDir, outFile)\n : path.resolve(process.cwd(), outFile);\n const outDisplay = outDir && !outRel ? path.join(outDir, outFile) : outFile;\n\n const url = \"https://api.priceos.com/v1/features\";\n const res = await fetch(url, {\n headers: { \"x-api-key\": apiKey },\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n console.error(`Failed to fetch features: ${res.status} ${res.statusText}\\n${text}`);\n process.exit(1);\n }\n\n const features = (await res.json()) as Feature[];\n const typeByKey = new Map<string, \"boolean\" | \"limit\" | \"unknown\">();\n\n for (const feature of features ?? []) {\n if (!feature?.featureKey) continue;\n const key = feature.featureKey;\n const nextType = feature.type === \"boolean\" || feature.type === \"limit\" ? feature.type : \"unknown\";\n const currentType = typeByKey.get(key);\n if (!currentType) {\n typeByKey.set(key, nextType);\n continue;\n }\n if (currentType !== nextType) {\n typeByKey.set(key, \"unknown\");\n }\n }\n\n const keys = [...typeByKey.keys()].sort();\n const union = keys.length ? keys.map((k) => JSON.stringify(k)).join(\" | \") : \"never\";\n const limitKeys = keys.filter((key) => typeByKey.get(key) === \"limit\");\n const limitUnion = limitKeys.length ? limitKeys.map((k) => JSON.stringify(k)).join(\" | \") : \"never\";\n const mapLines = keys.map((key) => {\n const featureType = typeByKey.get(key);\n const accessType =\n featureType === \"boolean\"\n ? \"BooleanFeatureAccess\"\n : featureType === \"limit\"\n ? \"LimitFeatureAccess\"\n : \"FeatureAccessEntry\";\n return ` ${JSON.stringify(key)}: ${accessType};`;\n });\n\n const content = `// Auto-generated by PriceOS (priceos generate-types). Do not edit.\nexport type FeatureKey = ${union};\nexport type LimitFeatureKey = ${limitUnion};\nexport type BooleanFeatureAccess = {\n type: \"boolean\";\n hasAccess: boolean;\n};\nexport type LimitFeatureAccess = {\n type: \"limit\";\n hasAccess: boolean;\n isUnlimited: boolean;\n limit: number | null;\n used: number;\n};\nexport type FeatureAccessEntry = BooleanFeatureAccess | LimitFeatureAccess;\nexport type FeatureAccessMap = {\n __limitFeatureKey?: LimitFeatureKey;\n${mapLines.join(\"\\n\")}\n} & Record<string, FeatureAccessEntry>;\n`;\n\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.writeFile(outPath, content, \"utf8\");\n\n console.log(`Generated ${outDisplay} (${keys.length} feature keys)`);\n}\n\nmain().catch((e) => {\n console.error(e);\n process.exit(1);\n});\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\ntype Feature = {\n featureKey: string;\n type?: \"boolean\" | \"limit\" | null;\n tracksUsage?: boolean | null;\n};\n\nfunction argValue(args: string[], name: string) {\n const idx = args.indexOf(name);\n if (idx === -1) return undefined;\n return args[idx + 1];\n}\n\nfunction hasFlag(args: string[], name: string) {\n return args.includes(name);\n}\n\nasync function readEnvFile(filePath: string) {\n try {\n const raw = await fs.readFile(filePath, \"utf8\");\n const entries: Record<string, string> = {};\n for (const line of raw.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(\"#\")) continue;\n const eqIdx = trimmed.indexOf(\"=\");\n if (eqIdx === -1) continue;\n const rawKey = trimmed.slice(0, eqIdx).trim();\n const key = rawKey.startsWith(\"export \") ? rawKey.slice(\"export \".length).trim() : rawKey;\n let value = trimmed.slice(eqIdx + 1).trim();\n if (\n (value.startsWith(\"\\\"\") && value.endsWith(\"\\\"\")) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n if (key) {\n entries[key] = value;\n }\n }\n return entries;\n } catch {\n return {};\n }\n}\n\nfunction printHelp() {\n console.log(`\npriceos generate-types\n\nGenerates TypeScript feature access types for your PriceOS workspace.\n\nOptions:\n --api-key <key> PriceOS API key (defaults to .env.local, .env, or env PRICEOS_API_KEY) [required]\n --out <path> Output .d.ts file (default: priceos.d.ts in current directory)\n --out-dir <path> Output directory for priceos.d.ts (ignored if --out is set)\n -h, --help Show help\n\nExamples:\n priceos generate-types --api-key sk_test_... --out ./priceos.d.ts\n priceos generate-types --api-key sk_test_... --out-dir ./src\n`.trim());\n}\n\nasync function main() {\n const args = process.argv.slice(2);\n\n if (args.length === 0 || hasFlag(args, \"--help\") || hasFlag(args, \"-h\")) {\n printHelp();\n process.exit(args.length === 0 ? 1 : 0);\n }\n\n const cmd = args[0];\n if (cmd !== \"generate-types\") {\n console.error(`Unknown command: ${cmd}`);\n printHelp();\n process.exit(1);\n }\n\n const envLocal = await readEnvFile(path.resolve(process.cwd(), \".env.local\"));\n const envDefault = await readEnvFile(path.resolve(process.cwd(), \".env\"));\n const apiKey =\n argValue(args, \"--api-key\") ??\n envLocal.PRICEOS_API_KEY ??\n envDefault.PRICEOS_API_KEY ??\n process.env.PRICEOS_API_KEY;\n\n if (!apiKey) {\n console.error(\"Missing API key. Provide --api-key <key> or set PRICEOS_API_KEY in .env.local/.env.\");\n process.exit(1);\n }\n\n const outRel = argValue(args, \"--out\");\n const outDir = argValue(args, \"--out-dir\");\n const outFile = outRel ?? \"priceos.d.ts\";\n const outPath = outDir && !outRel\n ? path.resolve(process.cwd(), outDir, outFile)\n : path.resolve(process.cwd(), outFile);\n const outDisplay = outDir && !outRel ? path.join(outDir, outFile) : outFile;\n\n const url = \"https://api.priceos.com/v1/features\";\n const res = await fetch(url, {\n headers: { \"x-api-key\": apiKey },\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n console.error(`Failed to fetch features: ${res.status} ${res.statusText}\\n${text}`);\n process.exit(1);\n }\n\n const features = (await res.json()) as Feature[];\n const typeByKey = new Map<string, \"boolean\" | \"limit\" | \"unknown\">();\n const trackingByKey = new Map<string, \"tracked\" | \"untracked\" | \"unknown\">();\n\n for (const feature of features ?? []) {\n if (!feature?.featureKey) continue;\n const key = feature.featureKey;\n const nextType = feature.type === \"boolean\" || feature.type === \"limit\" ? feature.type : \"unknown\";\n const currentType = typeByKey.get(key);\n if (!currentType) {\n typeByKey.set(key, nextType);\n } else if (currentType !== nextType) {\n typeByKey.set(key, \"unknown\");\n }\n\n if (nextType !== \"limit\") continue;\n\n const nextTracking =\n feature.tracksUsage === true\n ? \"tracked\"\n : feature.tracksUsage === false\n ? \"untracked\"\n : \"unknown\";\n const currentTracking = trackingByKey.get(key);\n if (!currentTracking) {\n trackingByKey.set(key, nextTracking);\n continue;\n }\n if (currentTracking !== nextTracking) {\n trackingByKey.set(key, \"unknown\");\n }\n }\n\n const keys = [...typeByKey.keys()].sort();\n const union = keys.length ? keys.map((k) => JSON.stringify(k)).join(\" | \") : \"never\";\n const limitKeys = keys.filter((key) => typeByKey.get(key) === \"limit\");\n const limitUnion = limitKeys.length ? limitKeys.map((k) => JSON.stringify(k)).join(\" | \") : \"never\";\n const mapLines = keys.map((key) => {\n const featureType = typeByKey.get(key);\n const accessType =\n featureType === \"boolean\"\n ? \"BooleanFeatureAccess\"\n : featureType === \"limit\"\n ? trackingByKey.get(key) === \"tracked\"\n ? \"TrackedLimitFeatureAccess\"\n : trackingByKey.get(key) === \"untracked\"\n ? \"UntrackedLimitFeatureAccess\"\n : \"LimitFeatureAccess\"\n : \"FeatureAccessEntry\";\n return ` ${JSON.stringify(key)}: ${accessType};`;\n });\n\n const content = `// Auto-generated by PriceOS (priceos generate-types). Do not edit.\nexport type FeatureKey = ${union};\nexport type LimitFeatureKey = ${limitUnion};\nexport type BooleanFeatureAccess = {\n type: \"boolean\";\n hasAccess: boolean;\n};\nexport type LimitFeatureUsage = {\n used: number;\n remaining: number | null;\n bonusRemaining: number;\n bonusUsed: number;\n resetsWhen: \"billing_period\" | \"calendar\";\n resetType: \"never\" | \"day\" | \"week\" | \"month\" | \"year\";\n nextReset: number | null;\n lastReset: number | null;\n};\nexport type TrackedLimitFeatureAccess = {\n type: \"limit\";\n hasAccess: boolean;\n isUnlimited: boolean;\n limit: number | null;\n used: number;\n remaining: number | null;\n bonusRemaining: number;\n bonusUsed: number;\n usage: LimitFeatureUsage;\n};\nexport type UntrackedLimitFeatureAccess = {\n type: \"limit\";\n hasAccess: boolean;\n isUnlimited: boolean;\n limit: number | null;\n used: number;\n remaining: number | null;\n bonusRemaining: number;\n bonusUsed: number;\n usage: LimitFeatureUsage;\n};\nexport type LimitFeatureAccess = TrackedLimitFeatureAccess | UntrackedLimitFeatureAccess;\nexport type FeatureAccessEntry = BooleanFeatureAccess | LimitFeatureAccess;\nexport type FeatureAccessMap = {\n __limitFeatureKey?: LimitFeatureKey;\n${mapLines.join(\"\\n\")}\n} & Record<string, FeatureAccessEntry>;\n`;\n\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.writeFile(outPath, content, \"utf8\");\n\n console.log(`Generated ${outDisplay} (${keys.length} feature keys)`);\n}\n\nmain().catch((e) => {\n console.error(e);\n process.exit(1);\n});\n"],"mappings":"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","names":[]}
package/dist/index.d.cts CHANGED
@@ -80,7 +80,20 @@ interface paths {
80
80
  * "type": "limit",
81
81
  * "limit": 1000,
82
82
  * "isUnlimited": false,
83
- * "used": 120
83
+ * "used": 120,
84
+ * "remaining": 880,
85
+ * "bonusRemaining": 25,
86
+ * "bonusUsed": 5,
87
+ * "usage": {
88
+ * "used": 120,
89
+ * "remaining": 880,
90
+ * "bonusRemaining": 25,
91
+ * "bonusUsed": 5,
92
+ * "resetsWhen": "billing_period",
93
+ * "resetType": "month",
94
+ * "nextReset": 1738368000000,
95
+ * "lastReset": 1735689600000
96
+ * }
84
97
  * },
85
98
  * "team_seats": {
86
99
  * "hasAccess": true,
@@ -204,6 +217,31 @@ interface paths {
204
217
  bonusRemaining: number;
205
218
  /** @description Bonus amount consumed. */
206
219
  bonusUsed: number;
220
+ /** @description Usage details for the feature. */
221
+ usage: {
222
+ /** @description Usage consumed for the feature. */
223
+ used: number;
224
+ /** @description Remaining base limit (limit - used). */
225
+ remaining: number | null;
226
+ /** @description Remaining bonus amount. */
227
+ bonusRemaining: number;
228
+ /** @description Bonus amount consumed. */
229
+ bonusUsed: number;
230
+ /**
231
+ * @description When usage resets are anchored.
232
+ * @enum {string}
233
+ */
234
+ resetsWhen: "billing_period" | "calendar";
235
+ /**
236
+ * @description How frequently usage resets.
237
+ * @enum {string}
238
+ */
239
+ resetType: "never" | "day" | "week" | "month" | "year";
240
+ /** @description Unix timestamp (ms) for the next reset, when applicable. */
241
+ nextReset: number | null;
242
+ /** @description Unix timestamp (ms) for the last reset, when applicable. */
243
+ lastReset: number | null;
244
+ };
207
245
  };
208
246
  };
209
247
  /** @description Customer bonuses. */
@@ -355,7 +393,20 @@ interface paths {
355
393
  * "type": "limit",
356
394
  * "limit": 1000,
357
395
  * "isUnlimited": false,
358
- * "used": 120
396
+ * "used": 120,
397
+ * "remaining": 880,
398
+ * "bonusRemaining": 25,
399
+ * "bonusUsed": 5,
400
+ * "usage": {
401
+ * "used": 120,
402
+ * "remaining": 880,
403
+ * "bonusRemaining": 25,
404
+ * "bonusUsed": 5,
405
+ * "resetsWhen": "billing_period",
406
+ * "resetType": "month",
407
+ * "nextReset": 1738368000000,
408
+ * "lastReset": 1735689600000
409
+ * }
359
410
  * },
360
411
  * "team_seats": {
361
412
  * "hasAccess": true,
@@ -479,6 +530,31 @@ interface paths {
479
530
  bonusRemaining: number;
480
531
  /** @description Bonus amount consumed. */
481
532
  bonusUsed: number;
533
+ /** @description Usage details for the feature. */
534
+ usage: {
535
+ /** @description Usage consumed for the feature. */
536
+ used: number;
537
+ /** @description Remaining base limit (limit - used). */
538
+ remaining: number | null;
539
+ /** @description Remaining bonus amount. */
540
+ bonusRemaining: number;
541
+ /** @description Bonus amount consumed. */
542
+ bonusUsed: number;
543
+ /**
544
+ * @description When usage resets are anchored.
545
+ * @enum {string}
546
+ */
547
+ resetsWhen: "billing_period" | "calendar";
548
+ /**
549
+ * @description How frequently usage resets.
550
+ * @enum {string}
551
+ */
552
+ resetType: "never" | "day" | "week" | "month" | "year";
553
+ /** @description Unix timestamp (ms) for the next reset, when applicable. */
554
+ nextReset: number | null;
555
+ /** @description Unix timestamp (ms) for the last reset, when applicable. */
556
+ lastReset: number | null;
557
+ };
482
558
  };
483
559
  };
484
560
  /** @description Customer bonuses. */
@@ -737,7 +813,20 @@ interface paths {
737
813
  * "type": "limit",
738
814
  * "limit": 1000,
739
815
  * "isUnlimited": false,
740
- * "used": 120
816
+ * "used": 120,
817
+ * "remaining": 880,
818
+ * "bonusRemaining": 25,
819
+ * "bonusUsed": 5,
820
+ * "usage": {
821
+ * "used": 120,
822
+ * "remaining": 880,
823
+ * "bonusRemaining": 25,
824
+ * "bonusUsed": 5,
825
+ * "resetsWhen": "billing_period",
826
+ * "resetType": "month",
827
+ * "nextReset": 1738368000000,
828
+ * "lastReset": 1735689600000
829
+ * }
741
830
  * },
742
831
  * "team_seats": {
743
832
  * "hasAccess": true,
@@ -861,6 +950,31 @@ interface paths {
861
950
  bonusRemaining: number;
862
951
  /** @description Bonus amount consumed. */
863
952
  bonusUsed: number;
953
+ /** @description Usage details for the feature. */
954
+ usage: {
955
+ /** @description Usage consumed for the feature. */
956
+ used: number;
957
+ /** @description Remaining base limit (limit - used). */
958
+ remaining: number | null;
959
+ /** @description Remaining bonus amount. */
960
+ bonusRemaining: number;
961
+ /** @description Bonus amount consumed. */
962
+ bonusUsed: number;
963
+ /**
964
+ * @description When usage resets are anchored.
965
+ * @enum {string}
966
+ */
967
+ resetsWhen: "billing_period" | "calendar";
968
+ /**
969
+ * @description How frequently usage resets.
970
+ * @enum {string}
971
+ */
972
+ resetType: "never" | "day" | "week" | "month" | "year";
973
+ /** @description Unix timestamp (ms) for the next reset, when applicable. */
974
+ nextReset: number | null;
975
+ /** @description Unix timestamp (ms) for the last reset, when applicable. */
976
+ lastReset: number | null;
977
+ };
864
978
  };
865
979
  };
866
980
  /** @description Customer bonuses. */
@@ -1032,7 +1146,20 @@ interface paths {
1032
1146
  * "type": "limit",
1033
1147
  * "limit": 1000,
1034
1148
  * "isUnlimited": false,
1035
- * "used": 120
1149
+ * "used": 120,
1150
+ * "remaining": 880,
1151
+ * "bonusRemaining": 25,
1152
+ * "bonusUsed": 5,
1153
+ * "usage": {
1154
+ * "used": 120,
1155
+ * "remaining": 880,
1156
+ * "bonusRemaining": 25,
1157
+ * "bonusUsed": 5,
1158
+ * "resetsWhen": "billing_period",
1159
+ * "resetType": "month",
1160
+ * "nextReset": 1738368000000,
1161
+ * "lastReset": 1735689600000
1162
+ * }
1036
1163
  * },
1037
1164
  * "team_seats": {
1038
1165
  * "hasAccess": true,
@@ -1156,6 +1283,31 @@ interface paths {
1156
1283
  bonusRemaining: number;
1157
1284
  /** @description Bonus amount consumed. */
1158
1285
  bonusUsed: number;
1286
+ /** @description Usage details for the feature. */
1287
+ usage: {
1288
+ /** @description Usage consumed for the feature. */
1289
+ used: number;
1290
+ /** @description Remaining base limit (limit - used). */
1291
+ remaining: number | null;
1292
+ /** @description Remaining bonus amount. */
1293
+ bonusRemaining: number;
1294
+ /** @description Bonus amount consumed. */
1295
+ bonusUsed: number;
1296
+ /**
1297
+ * @description When usage resets are anchored.
1298
+ * @enum {string}
1299
+ */
1300
+ resetsWhen: "billing_period" | "calendar";
1301
+ /**
1302
+ * @description How frequently usage resets.
1303
+ * @enum {string}
1304
+ */
1305
+ resetType: "never" | "day" | "week" | "month" | "year";
1306
+ /** @description Unix timestamp (ms) for the next reset, when applicable. */
1307
+ nextReset: number | null;
1308
+ /** @description Unix timestamp (ms) for the last reset, when applicable. */
1309
+ lastReset: number | null;
1310
+ };
1159
1311
  };
1160
1312
  };
1161
1313
  /** @description Customer bonuses. */
@@ -1294,7 +1446,20 @@ interface paths {
1294
1446
  * "type": "limit",
1295
1447
  * "limit": 1000,
1296
1448
  * "isUnlimited": false,
1297
- * "used": 120
1449
+ * "used": 120,
1450
+ * "remaining": 880,
1451
+ * "bonusRemaining": 25,
1452
+ * "bonusUsed": 5,
1453
+ * "usage": {
1454
+ * "used": 120,
1455
+ * "remaining": 880,
1456
+ * "bonusRemaining": 25,
1457
+ * "bonusUsed": 5,
1458
+ * "resetsWhen": "billing_period",
1459
+ * "resetType": "month",
1460
+ * "nextReset": 1738368000000,
1461
+ * "lastReset": 1735689600000
1462
+ * }
1298
1463
  * },
1299
1464
  * "team_seats": {
1300
1465
  * "hasAccess": true,
@@ -1331,6 +1496,31 @@ interface paths {
1331
1496
  bonusRemaining: number;
1332
1497
  /** @description Bonus amount consumed. */
1333
1498
  bonusUsed: number;
1499
+ /** @description Usage details for the feature. */
1500
+ usage: {
1501
+ /** @description Usage consumed for the feature. */
1502
+ used: number;
1503
+ /** @description Remaining base limit (limit - used). */
1504
+ remaining: number | null;
1505
+ /** @description Remaining bonus amount. */
1506
+ bonusRemaining: number;
1507
+ /** @description Bonus amount consumed. */
1508
+ bonusUsed: number;
1509
+ /**
1510
+ * @description When usage resets are anchored.
1511
+ * @enum {string}
1512
+ */
1513
+ resetsWhen: "billing_period" | "calendar";
1514
+ /**
1515
+ * @description How frequently usage resets.
1516
+ * @enum {string}
1517
+ */
1518
+ resetType: "never" | "day" | "week" | "month" | "year";
1519
+ /** @description Unix timestamp (ms) for the next reset, when applicable. */
1520
+ nextReset: number | null;
1521
+ /** @description Unix timestamp (ms) for the last reset, when applicable. */
1522
+ lastReset: number | null;
1523
+ };
1334
1524
  };
1335
1525
  };
1336
1526
  };
package/dist/index.d.ts CHANGED
@@ -80,7 +80,20 @@ interface paths {
80
80
  * "type": "limit",
81
81
  * "limit": 1000,
82
82
  * "isUnlimited": false,
83
- * "used": 120
83
+ * "used": 120,
84
+ * "remaining": 880,
85
+ * "bonusRemaining": 25,
86
+ * "bonusUsed": 5,
87
+ * "usage": {
88
+ * "used": 120,
89
+ * "remaining": 880,
90
+ * "bonusRemaining": 25,
91
+ * "bonusUsed": 5,
92
+ * "resetsWhen": "billing_period",
93
+ * "resetType": "month",
94
+ * "nextReset": 1738368000000,
95
+ * "lastReset": 1735689600000
96
+ * }
84
97
  * },
85
98
  * "team_seats": {
86
99
  * "hasAccess": true,
@@ -204,6 +217,31 @@ interface paths {
204
217
  bonusRemaining: number;
205
218
  /** @description Bonus amount consumed. */
206
219
  bonusUsed: number;
220
+ /** @description Usage details for the feature. */
221
+ usage: {
222
+ /** @description Usage consumed for the feature. */
223
+ used: number;
224
+ /** @description Remaining base limit (limit - used). */
225
+ remaining: number | null;
226
+ /** @description Remaining bonus amount. */
227
+ bonusRemaining: number;
228
+ /** @description Bonus amount consumed. */
229
+ bonusUsed: number;
230
+ /**
231
+ * @description When usage resets are anchored.
232
+ * @enum {string}
233
+ */
234
+ resetsWhen: "billing_period" | "calendar";
235
+ /**
236
+ * @description How frequently usage resets.
237
+ * @enum {string}
238
+ */
239
+ resetType: "never" | "day" | "week" | "month" | "year";
240
+ /** @description Unix timestamp (ms) for the next reset, when applicable. */
241
+ nextReset: number | null;
242
+ /** @description Unix timestamp (ms) for the last reset, when applicable. */
243
+ lastReset: number | null;
244
+ };
207
245
  };
208
246
  };
209
247
  /** @description Customer bonuses. */
@@ -355,7 +393,20 @@ interface paths {
355
393
  * "type": "limit",
356
394
  * "limit": 1000,
357
395
  * "isUnlimited": false,
358
- * "used": 120
396
+ * "used": 120,
397
+ * "remaining": 880,
398
+ * "bonusRemaining": 25,
399
+ * "bonusUsed": 5,
400
+ * "usage": {
401
+ * "used": 120,
402
+ * "remaining": 880,
403
+ * "bonusRemaining": 25,
404
+ * "bonusUsed": 5,
405
+ * "resetsWhen": "billing_period",
406
+ * "resetType": "month",
407
+ * "nextReset": 1738368000000,
408
+ * "lastReset": 1735689600000
409
+ * }
359
410
  * },
360
411
  * "team_seats": {
361
412
  * "hasAccess": true,
@@ -479,6 +530,31 @@ interface paths {
479
530
  bonusRemaining: number;
480
531
  /** @description Bonus amount consumed. */
481
532
  bonusUsed: number;
533
+ /** @description Usage details for the feature. */
534
+ usage: {
535
+ /** @description Usage consumed for the feature. */
536
+ used: number;
537
+ /** @description Remaining base limit (limit - used). */
538
+ remaining: number | null;
539
+ /** @description Remaining bonus amount. */
540
+ bonusRemaining: number;
541
+ /** @description Bonus amount consumed. */
542
+ bonusUsed: number;
543
+ /**
544
+ * @description When usage resets are anchored.
545
+ * @enum {string}
546
+ */
547
+ resetsWhen: "billing_period" | "calendar";
548
+ /**
549
+ * @description How frequently usage resets.
550
+ * @enum {string}
551
+ */
552
+ resetType: "never" | "day" | "week" | "month" | "year";
553
+ /** @description Unix timestamp (ms) for the next reset, when applicable. */
554
+ nextReset: number | null;
555
+ /** @description Unix timestamp (ms) for the last reset, when applicable. */
556
+ lastReset: number | null;
557
+ };
482
558
  };
483
559
  };
484
560
  /** @description Customer bonuses. */
@@ -737,7 +813,20 @@ interface paths {
737
813
  * "type": "limit",
738
814
  * "limit": 1000,
739
815
  * "isUnlimited": false,
740
- * "used": 120
816
+ * "used": 120,
817
+ * "remaining": 880,
818
+ * "bonusRemaining": 25,
819
+ * "bonusUsed": 5,
820
+ * "usage": {
821
+ * "used": 120,
822
+ * "remaining": 880,
823
+ * "bonusRemaining": 25,
824
+ * "bonusUsed": 5,
825
+ * "resetsWhen": "billing_period",
826
+ * "resetType": "month",
827
+ * "nextReset": 1738368000000,
828
+ * "lastReset": 1735689600000
829
+ * }
741
830
  * },
742
831
  * "team_seats": {
743
832
  * "hasAccess": true,
@@ -861,6 +950,31 @@ interface paths {
861
950
  bonusRemaining: number;
862
951
  /** @description Bonus amount consumed. */
863
952
  bonusUsed: number;
953
+ /** @description Usage details for the feature. */
954
+ usage: {
955
+ /** @description Usage consumed for the feature. */
956
+ used: number;
957
+ /** @description Remaining base limit (limit - used). */
958
+ remaining: number | null;
959
+ /** @description Remaining bonus amount. */
960
+ bonusRemaining: number;
961
+ /** @description Bonus amount consumed. */
962
+ bonusUsed: number;
963
+ /**
964
+ * @description When usage resets are anchored.
965
+ * @enum {string}
966
+ */
967
+ resetsWhen: "billing_period" | "calendar";
968
+ /**
969
+ * @description How frequently usage resets.
970
+ * @enum {string}
971
+ */
972
+ resetType: "never" | "day" | "week" | "month" | "year";
973
+ /** @description Unix timestamp (ms) for the next reset, when applicable. */
974
+ nextReset: number | null;
975
+ /** @description Unix timestamp (ms) for the last reset, when applicable. */
976
+ lastReset: number | null;
977
+ };
864
978
  };
865
979
  };
866
980
  /** @description Customer bonuses. */
@@ -1032,7 +1146,20 @@ interface paths {
1032
1146
  * "type": "limit",
1033
1147
  * "limit": 1000,
1034
1148
  * "isUnlimited": false,
1035
- * "used": 120
1149
+ * "used": 120,
1150
+ * "remaining": 880,
1151
+ * "bonusRemaining": 25,
1152
+ * "bonusUsed": 5,
1153
+ * "usage": {
1154
+ * "used": 120,
1155
+ * "remaining": 880,
1156
+ * "bonusRemaining": 25,
1157
+ * "bonusUsed": 5,
1158
+ * "resetsWhen": "billing_period",
1159
+ * "resetType": "month",
1160
+ * "nextReset": 1738368000000,
1161
+ * "lastReset": 1735689600000
1162
+ * }
1036
1163
  * },
1037
1164
  * "team_seats": {
1038
1165
  * "hasAccess": true,
@@ -1156,6 +1283,31 @@ interface paths {
1156
1283
  bonusRemaining: number;
1157
1284
  /** @description Bonus amount consumed. */
1158
1285
  bonusUsed: number;
1286
+ /** @description Usage details for the feature. */
1287
+ usage: {
1288
+ /** @description Usage consumed for the feature. */
1289
+ used: number;
1290
+ /** @description Remaining base limit (limit - used). */
1291
+ remaining: number | null;
1292
+ /** @description Remaining bonus amount. */
1293
+ bonusRemaining: number;
1294
+ /** @description Bonus amount consumed. */
1295
+ bonusUsed: number;
1296
+ /**
1297
+ * @description When usage resets are anchored.
1298
+ * @enum {string}
1299
+ */
1300
+ resetsWhen: "billing_period" | "calendar";
1301
+ /**
1302
+ * @description How frequently usage resets.
1303
+ * @enum {string}
1304
+ */
1305
+ resetType: "never" | "day" | "week" | "month" | "year";
1306
+ /** @description Unix timestamp (ms) for the next reset, when applicable. */
1307
+ nextReset: number | null;
1308
+ /** @description Unix timestamp (ms) for the last reset, when applicable. */
1309
+ lastReset: number | null;
1310
+ };
1159
1311
  };
1160
1312
  };
1161
1313
  /** @description Customer bonuses. */
@@ -1294,7 +1446,20 @@ interface paths {
1294
1446
  * "type": "limit",
1295
1447
  * "limit": 1000,
1296
1448
  * "isUnlimited": false,
1297
- * "used": 120
1449
+ * "used": 120,
1450
+ * "remaining": 880,
1451
+ * "bonusRemaining": 25,
1452
+ * "bonusUsed": 5,
1453
+ * "usage": {
1454
+ * "used": 120,
1455
+ * "remaining": 880,
1456
+ * "bonusRemaining": 25,
1457
+ * "bonusUsed": 5,
1458
+ * "resetsWhen": "billing_period",
1459
+ * "resetType": "month",
1460
+ * "nextReset": 1738368000000,
1461
+ * "lastReset": 1735689600000
1462
+ * }
1298
1463
  * },
1299
1464
  * "team_seats": {
1300
1465
  * "hasAccess": true,
@@ -1331,6 +1496,31 @@ interface paths {
1331
1496
  bonusRemaining: number;
1332
1497
  /** @description Bonus amount consumed. */
1333
1498
  bonusUsed: number;
1499
+ /** @description Usage details for the feature. */
1500
+ usage: {
1501
+ /** @description Usage consumed for the feature. */
1502
+ used: number;
1503
+ /** @description Remaining base limit (limit - used). */
1504
+ remaining: number | null;
1505
+ /** @description Remaining bonus amount. */
1506
+ bonusRemaining: number;
1507
+ /** @description Bonus amount consumed. */
1508
+ bonusUsed: number;
1509
+ /**
1510
+ * @description When usage resets are anchored.
1511
+ * @enum {string}
1512
+ */
1513
+ resetsWhen: "billing_period" | "calendar";
1514
+ /**
1515
+ * @description How frequently usage resets.
1516
+ * @enum {string}
1517
+ */
1518
+ resetType: "never" | "day" | "week" | "month" | "year";
1519
+ /** @description Unix timestamp (ms) for the next reset, when applicable. */
1520
+ nextReset: number | null;
1521
+ /** @description Unix timestamp (ms) for the last reset, when applicable. */
1522
+ lastReset: number | null;
1523
+ };
1334
1524
  };
1335
1525
  };
1336
1526
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "priceos",
3
- "version": "0.0.41",
3
+ "version": "0.0.42",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",