@revfleet/hscli 0.5.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.
Files changed (329) hide show
  1. package/CHANGELOG.md +466 -0
  2. package/LICENSE +21 -0
  3. package/README.md +287 -0
  4. package/SECURITY.md +68 -0
  5. package/dist/cli.d.ts +8 -0
  6. package/dist/cli.js +192 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/commands/account/index.d.ts +3 -0
  9. package/dist/commands/account/index.js +65 -0
  10. package/dist/commands/account/index.js.map +1 -0
  11. package/dist/commands/api/index.d.ts +3 -0
  12. package/dist/commands/api/index.js +35 -0
  13. package/dist/commands/api/index.js.map +1 -0
  14. package/dist/commands/auth/index.d.ts +3 -0
  15. package/dist/commands/auth/index.js +229 -0
  16. package/dist/commands/auth/index.js.map +1 -0
  17. package/dist/commands/automation/index.d.ts +3 -0
  18. package/dist/commands/automation/index.js +119 -0
  19. package/dist/commands/automation/index.js.map +1 -0
  20. package/dist/commands/cms/blog-settings.d.ts +3 -0
  21. package/dist/commands/cms/blog-settings.js +70 -0
  22. package/dist/commands/cms/blog-settings.js.map +1 -0
  23. package/dist/commands/cms/content-ops.d.ts +13 -0
  24. package/dist/commands/cms/content-ops.js +262 -0
  25. package/dist/commands/cms/content-ops.js.map +1 -0
  26. package/dist/commands/cms/hubdb.d.ts +3 -0
  27. package/dist/commands/cms/hubdb.js +55 -0
  28. package/dist/commands/cms/hubdb.js.map +1 -0
  29. package/dist/commands/cms/index.d.ts +3 -0
  30. package/dist/commands/cms/index.js +119 -0
  31. package/dist/commands/cms/index.js.map +1 -0
  32. package/dist/commands/cms/source-code.d.ts +3 -0
  33. package/dist/commands/cms/source-code.js +101 -0
  34. package/dist/commands/cms/source-code.js.map +1 -0
  35. package/dist/commands/communication-preferences/index.d.ts +3 -0
  36. package/dist/commands/communication-preferences/index.js +107 -0
  37. package/dist/commands/communication-preferences/index.js.map +1 -0
  38. package/dist/commands/conversations/index.d.ts +3 -0
  39. package/dist/commands/conversations/index.js +233 -0
  40. package/dist/commands/conversations/index.js.map +1 -0
  41. package/dist/commands/crm/associations.d.ts +3 -0
  42. package/dist/commands/crm/associations.js +180 -0
  43. package/dist/commands/crm/associations.js.map +1 -0
  44. package/dist/commands/crm/cards.d.ts +3 -0
  45. package/dist/commands/crm/cards.js +72 -0
  46. package/dist/commands/crm/cards.js.map +1 -0
  47. package/dist/commands/crm/carts.d.ts +3 -0
  48. package/dist/commands/crm/carts.js +5 -0
  49. package/dist/commands/crm/carts.js.map +1 -0
  50. package/dist/commands/crm/communications.d.ts +3 -0
  51. package/dist/commands/crm/communications.js +5 -0
  52. package/dist/commands/crm/communications.js.map +1 -0
  53. package/dist/commands/crm/companies.d.ts +3 -0
  54. package/dist/commands/crm/companies.js +5 -0
  55. package/dist/commands/crm/companies.js.map +1 -0
  56. package/dist/commands/crm/contacts.d.ts +3 -0
  57. package/dist/commands/crm/contacts.js +5 -0
  58. package/dist/commands/crm/contacts.js.map +1 -0
  59. package/dist/commands/crm/custom-objects.d.ts +3 -0
  60. package/dist/commands/crm/custom-objects.js +83 -0
  61. package/dist/commands/crm/custom-objects.js.map +1 -0
  62. package/dist/commands/crm/dated.d.ts +9 -0
  63. package/dist/commands/crm/dated.js +247 -0
  64. package/dist/commands/crm/dated.js.map +1 -0
  65. package/dist/commands/crm/deals.d.ts +3 -0
  66. package/dist/commands/crm/deals.js +5 -0
  67. package/dist/commands/crm/deals.js.map +1 -0
  68. package/dist/commands/crm/describe.d.ts +3 -0
  69. package/dist/commands/crm/describe.js +89 -0
  70. package/dist/commands/crm/describe.js.map +1 -0
  71. package/dist/commands/crm/discounts.d.ts +3 -0
  72. package/dist/commands/crm/discounts.js +5 -0
  73. package/dist/commands/crm/discounts.js.map +1 -0
  74. package/dist/commands/crm/engagements.d.ts +3 -0
  75. package/dist/commands/crm/engagements.js +8 -0
  76. package/dist/commands/crm/engagements.js.map +1 -0
  77. package/dist/commands/crm/fees.d.ts +3 -0
  78. package/dist/commands/crm/fees.js +5 -0
  79. package/dist/commands/crm/fees.js.map +1 -0
  80. package/dist/commands/crm/goals.d.ts +3 -0
  81. package/dist/commands/crm/goals.js +30 -0
  82. package/dist/commands/crm/goals.js.map +1 -0
  83. package/dist/commands/crm/imports.d.ts +3 -0
  84. package/dist/commands/crm/imports.js +45 -0
  85. package/dist/commands/crm/imports.js.map +1 -0
  86. package/dist/commands/crm/index.d.ts +3 -0
  87. package/dist/commands/crm/index.js +64 -0
  88. package/dist/commands/crm/index.js.map +1 -0
  89. package/dist/commands/crm/invoices.d.ts +3 -0
  90. package/dist/commands/crm/invoices.js +5 -0
  91. package/dist/commands/crm/invoices.js.map +1 -0
  92. package/dist/commands/crm/leads.d.ts +3 -0
  93. package/dist/commands/crm/leads.js +5 -0
  94. package/dist/commands/crm/leads.js.map +1 -0
  95. package/dist/commands/crm/line-items.d.ts +3 -0
  96. package/dist/commands/crm/line-items.js +5 -0
  97. package/dist/commands/crm/line-items.js.map +1 -0
  98. package/dist/commands/crm/orders.d.ts +3 -0
  99. package/dist/commands/crm/orders.js +5 -0
  100. package/dist/commands/crm/orders.js.map +1 -0
  101. package/dist/commands/crm/owners.d.ts +3 -0
  102. package/dist/commands/crm/owners.js +22 -0
  103. package/dist/commands/crm/owners.js.map +1 -0
  104. package/dist/commands/crm/payments.d.ts +3 -0
  105. package/dist/commands/crm/payments.js +5 -0
  106. package/dist/commands/crm/payments.js.map +1 -0
  107. package/dist/commands/crm/pipelines.d.ts +3 -0
  108. package/dist/commands/crm/pipelines.js +70 -0
  109. package/dist/commands/crm/pipelines.js.map +1 -0
  110. package/dist/commands/crm/products.d.ts +3 -0
  111. package/dist/commands/crm/products.js +5 -0
  112. package/dist/commands/crm/products.js.map +1 -0
  113. package/dist/commands/crm/properties.d.ts +3 -0
  114. package/dist/commands/crm/properties.js +103 -0
  115. package/dist/commands/crm/properties.js.map +1 -0
  116. package/dist/commands/crm/quotes.d.ts +3 -0
  117. package/dist/commands/crm/quotes.js +5 -0
  118. package/dist/commands/crm/quotes.js.map +1 -0
  119. package/dist/commands/crm/shared.d.ts +17 -0
  120. package/dist/commands/crm/shared.js +256 -0
  121. package/dist/commands/crm/shared.js.map +1 -0
  122. package/dist/commands/crm/subscriptions.d.ts +3 -0
  123. package/dist/commands/crm/subscriptions.js +5 -0
  124. package/dist/commands/crm/subscriptions.js.map +1 -0
  125. package/dist/commands/crm/sync.d.ts +3 -0
  126. package/dist/commands/crm/sync.js +116 -0
  127. package/dist/commands/crm/sync.js.map +1 -0
  128. package/dist/commands/crm/taxes.d.ts +3 -0
  129. package/dist/commands/crm/taxes.js +5 -0
  130. package/dist/commands/crm/taxes.js.map +1 -0
  131. package/dist/commands/crm/tickets.d.ts +3 -0
  132. package/dist/commands/crm/tickets.js +5 -0
  133. package/dist/commands/crm/tickets.js.map +1 -0
  134. package/dist/commands/crm/users.d.ts +3 -0
  135. package/dist/commands/crm/users.js +5 -0
  136. package/dist/commands/crm/users.js.map +1 -0
  137. package/dist/commands/doctor/index.d.ts +3 -0
  138. package/dist/commands/doctor/index.js +232 -0
  139. package/dist/commands/doctor/index.js.map +1 -0
  140. package/dist/commands/domains/shared.d.ts +13 -0
  141. package/dist/commands/domains/shared.js +56 -0
  142. package/dist/commands/domains/shared.js.map +1 -0
  143. package/dist/commands/email-events/index.d.ts +3 -0
  144. package/dist/commands/email-events/index.js +77 -0
  145. package/dist/commands/email-events/index.js.map +1 -0
  146. package/dist/commands/events/index.d.ts +3 -0
  147. package/dist/commands/events/index.js +80 -0
  148. package/dist/commands/events/index.js.map +1 -0
  149. package/dist/commands/exports/index.d.ts +3 -0
  150. package/dist/commands/exports/index.js +45 -0
  151. package/dist/commands/exports/index.js.map +1 -0
  152. package/dist/commands/extensions/index.d.ts +3 -0
  153. package/dist/commands/extensions/index.js +118 -0
  154. package/dist/commands/extensions/index.js.map +1 -0
  155. package/dist/commands/feature-flags/index.d.ts +3 -0
  156. package/dist/commands/feature-flags/index.js +65 -0
  157. package/dist/commands/feature-flags/index.js.map +1 -0
  158. package/dist/commands/files/folders.d.ts +3 -0
  159. package/dist/commands/files/folders.js +74 -0
  160. package/dist/commands/files/folders.js.map +1 -0
  161. package/dist/commands/files/index.d.ts +3 -0
  162. package/dist/commands/files/index.js +30 -0
  163. package/dist/commands/files/index.js.map +1 -0
  164. package/dist/commands/forms/index.d.ts +3 -0
  165. package/dist/commands/forms/index.js +37 -0
  166. package/dist/commands/forms/index.js.map +1 -0
  167. package/dist/commands/integrations/index.d.ts +3 -0
  168. package/dist/commands/integrations/index.js +64 -0
  169. package/dist/commands/integrations/index.js.map +1 -0
  170. package/dist/commands/integrators/index.d.ts +3 -0
  171. package/dist/commands/integrators/index.js +79 -0
  172. package/dist/commands/integrators/index.js.map +1 -0
  173. package/dist/commands/legacy/index.d.ts +13 -0
  174. package/dist/commands/legacy/index.js +254 -0
  175. package/dist/commands/legacy/index.js.map +1 -0
  176. package/dist/commands/legacy-v1/index.d.ts +29 -0
  177. package/dist/commands/legacy-v1/index.js +568 -0
  178. package/dist/commands/legacy-v1/index.js.map +1 -0
  179. package/dist/commands/lists/index.d.ts +3 -0
  180. package/dist/commands/lists/index.js +148 -0
  181. package/dist/commands/lists/index.js.map +1 -0
  182. package/dist/commands/marketing/ads.d.ts +3 -0
  183. package/dist/commands/marketing/ads.js +45 -0
  184. package/dist/commands/marketing/ads.js.map +1 -0
  185. package/dist/commands/marketing/behavioral-events.d.ts +3 -0
  186. package/dist/commands/marketing/behavioral-events.js +38 -0
  187. package/dist/commands/marketing/behavioral-events.js.map +1 -0
  188. package/dist/commands/marketing/events.d.ts +3 -0
  189. package/dist/commands/marketing/events.js +69 -0
  190. package/dist/commands/marketing/events.js.map +1 -0
  191. package/dist/commands/marketing/index.d.ts +3 -0
  192. package/dist/commands/marketing/index.js +55 -0
  193. package/dist/commands/marketing/index.js.map +1 -0
  194. package/dist/commands/marketing/landing-pages.d.ts +3 -0
  195. package/dist/commands/marketing/landing-pages.js +48 -0
  196. package/dist/commands/marketing/landing-pages.js.map +1 -0
  197. package/dist/commands/marketing/seo.d.ts +3 -0
  198. package/dist/commands/marketing/seo.js +35 -0
  199. package/dist/commands/marketing/seo.js.map +1 -0
  200. package/dist/commands/marketing/social.d.ts +3 -0
  201. package/dist/commands/marketing/social.js +45 -0
  202. package/dist/commands/marketing/social.js.map +1 -0
  203. package/dist/commands/marketing/subscriptions.d.ts +3 -0
  204. package/dist/commands/marketing/subscriptions.js +27 -0
  205. package/dist/commands/marketing/subscriptions.js.map +1 -0
  206. package/dist/commands/marketing/transactional.d.ts +3 -0
  207. package/dist/commands/marketing/transactional.js +30 -0
  208. package/dist/commands/marketing/transactional.js.map +1 -0
  209. package/dist/commands/marketing-emails-v1/index.d.ts +3 -0
  210. package/dist/commands/marketing-emails-v1/index.js +72 -0
  211. package/dist/commands/marketing-emails-v1/index.js.map +1 -0
  212. package/dist/commands/mcp.d.ts +2 -0
  213. package/dist/commands/mcp.js +10 -0
  214. package/dist/commands/mcp.js.map +1 -0
  215. package/dist/commands/media-bridge/index.d.ts +3 -0
  216. package/dist/commands/media-bridge/index.js +209 -0
  217. package/dist/commands/media-bridge/index.js.map +1 -0
  218. package/dist/commands/reporting/index.d.ts +3 -0
  219. package/dist/commands/reporting/index.js +73 -0
  220. package/dist/commands/reporting/index.js.map +1 -0
  221. package/dist/commands/sales/calling.d.ts +3 -0
  222. package/dist/commands/sales/calling.js +32 -0
  223. package/dist/commands/sales/calling.js.map +1 -0
  224. package/dist/commands/sales/index.d.ts +3 -0
  225. package/dist/commands/sales/index.js +10 -0
  226. package/dist/commands/sales/index.js.map +1 -0
  227. package/dist/commands/sales/meetings.d.ts +3 -0
  228. package/dist/commands/sales/meetings.js +37 -0
  229. package/dist/commands/sales/meetings.js.map +1 -0
  230. package/dist/commands/sales/sequences.d.ts +3 -0
  231. package/dist/commands/sales/sequences.js +78 -0
  232. package/dist/commands/sales/sequences.js.map +1 -0
  233. package/dist/commands/seed/cms.d.ts +6 -0
  234. package/dist/commands/seed/cms.js +204 -0
  235. package/dist/commands/seed/cms.js.map +1 -0
  236. package/dist/commands/seed/commerce.d.ts +3 -0
  237. package/dist/commands/seed/commerce.js +117 -0
  238. package/dist/commands/seed/commerce.js.map +1 -0
  239. package/dist/commands/seed/context.d.ts +8 -0
  240. package/dist/commands/seed/context.js +76 -0
  241. package/dist/commands/seed/context.js.map +1 -0
  242. package/dist/commands/seed/crm-core.d.ts +3 -0
  243. package/dist/commands/seed/crm-core.js +137 -0
  244. package/dist/commands/seed/crm-core.js.map +1 -0
  245. package/dist/commands/seed/data.d.ts +73 -0
  246. package/dist/commands/seed/data.js +49 -0
  247. package/dist/commands/seed/data.js.map +1 -0
  248. package/dist/commands/seed/engagements.d.ts +3 -0
  249. package/dist/commands/seed/engagements.js +89 -0
  250. package/dist/commands/seed/engagements.js.map +1 -0
  251. package/dist/commands/seed/index.d.ts +3 -0
  252. package/dist/commands/seed/index.js +95 -0
  253. package/dist/commands/seed/index.js.map +1 -0
  254. package/dist/commands/seed/infra.d.ts +6 -0
  255. package/dist/commands/seed/infra.js +163 -0
  256. package/dist/commands/seed/infra.js.map +1 -0
  257. package/dist/commands/seed/marketing.d.ts +3 -0
  258. package/dist/commands/seed/marketing.js +172 -0
  259. package/dist/commands/seed/marketing.js.map +1 -0
  260. package/dist/commands/seed/shared.d.ts +8 -0
  261. package/dist/commands/seed/shared.js +37 -0
  262. package/dist/commands/seed/shared.js.map +1 -0
  263. package/dist/commands/seed/types.d.ts +44 -0
  264. package/dist/commands/seed/types.js +2 -0
  265. package/dist/commands/seed/types.js.map +1 -0
  266. package/dist/commands/service/chatflows.d.ts +3 -0
  267. package/dist/commands/service/chatflows.js +30 -0
  268. package/dist/commands/service/chatflows.js.map +1 -0
  269. package/dist/commands/service/index.d.ts +3 -0
  270. package/dist/commands/service/index.js +25 -0
  271. package/dist/commands/service/index.js.map +1 -0
  272. package/dist/commands/service/knowledge-base.d.ts +3 -0
  273. package/dist/commands/service/knowledge-base.js +19 -0
  274. package/dist/commands/service/knowledge-base.js.map +1 -0
  275. package/dist/commands/service/pipelines.d.ts +3 -0
  276. package/dist/commands/service/pipelines.js +36 -0
  277. package/dist/commands/service/pipelines.js.map +1 -0
  278. package/dist/commands/settings/index.d.ts +3 -0
  279. package/dist/commands/settings/index.js +149 -0
  280. package/dist/commands/settings/index.js.map +1 -0
  281. package/dist/commands/site-search/index.d.ts +3 -0
  282. package/dist/commands/site-search/index.js +36 -0
  283. package/dist/commands/site-search/index.js.map +1 -0
  284. package/dist/commands/timeline/index.d.ts +3 -0
  285. package/dist/commands/timeline/index.js +32 -0
  286. package/dist/commands/timeline/index.js.map +1 -0
  287. package/dist/commands/webhooks/index.d.ts +3 -0
  288. package/dist/commands/webhooks/index.js +41 -0
  289. package/dist/commands/webhooks/index.js.map +1 -0
  290. package/dist/commands/workflows/index.d.ts +3 -0
  291. package/dist/commands/workflows/index.js +13 -0
  292. package/dist/commands/workflows/index.js.map +1 -0
  293. package/dist/core/auth.d.ts +33 -0
  294. package/dist/core/auth.js +137 -0
  295. package/dist/core/auth.js.map +1 -0
  296. package/dist/core/capabilities.d.ts +60 -0
  297. package/dist/core/capabilities.js +559 -0
  298. package/dist/core/capabilities.js.map +1 -0
  299. package/dist/core/http.d.ts +47 -0
  300. package/dist/core/http.js +433 -0
  301. package/dist/core/http.js.map +1 -0
  302. package/dist/core/output.d.ts +23 -0
  303. package/dist/core/output.js +197 -0
  304. package/dist/core/output.js.map +1 -0
  305. package/dist/core/permissions.d.ts +9 -0
  306. package/dist/core/permissions.js +27 -0
  307. package/dist/core/permissions.js.map +1 -0
  308. package/dist/core/plugins.d.ts +42 -0
  309. package/dist/core/plugins.js +94 -0
  310. package/dist/core/plugins.js.map +1 -0
  311. package/dist/core/policy.d.ts +2 -0
  312. package/dist/core/policy.js +38 -0
  313. package/dist/core/policy.js.map +1 -0
  314. package/dist/core/schema-cache.d.ts +56 -0
  315. package/dist/core/schema-cache.js +338 -0
  316. package/dist/core/schema-cache.js.map +1 -0
  317. package/dist/core/schemas.d.ts +96 -0
  318. package/dist/core/schemas.js +104 -0
  319. package/dist/core/schemas.js.map +1 -0
  320. package/dist/core/urls.d.ts +50 -0
  321. package/dist/core/urls.js +122 -0
  322. package/dist/core/urls.js.map +1 -0
  323. package/dist/core/vault.d.ts +37 -0
  324. package/dist/core/vault.js +143 -0
  325. package/dist/core/vault.js.map +1 -0
  326. package/dist/mcp/server.d.ts +5 -0
  327. package/dist/mcp/server.js +680 -0
  328. package/dist/mcp/server.js.map +1 -0
  329. package/package.json +84 -0
@@ -0,0 +1,433 @@
1
+ import { CliError } from "./output.js";
2
+ import { appendFileSync } from "node:fs";
3
+ import { randomUUID } from "node:crypto";
4
+ import { mapEndpointAvailabilityError, preflightEndpointCapability, recordEndpointSuccess } from "./capabilities.js";
5
+ import { getToken, getApiBaseUrl } from "./auth.js";
6
+ import { enforcePermissionProfile } from "./permissions.js";
7
+ /**
8
+ * Create a HubSpotClient that is hublet-aware.
9
+ * Automatically resolves the API base URL from the profile's hublet setting.
10
+ */
11
+ export function createClient(profile, options = {}) {
12
+ const token = getToken(profile);
13
+ const apiBaseUrl = getApiBaseUrl(profile);
14
+ return new HubSpotClient(token, { ...options, apiBaseUrl, profile });
15
+ }
16
+ const REQUEST_TIMEOUT_MS = 30_000;
17
+ const MAX_RETRIES = 3;
18
+ const MAX_BACKOFF_MS = 10_000;
19
+ const ROLLING_SAFETY_BUFFER = 1;
20
+ const DAILY_MIN_REMAINING_BUFFER = 5;
21
+ const DAILY_LOW_WATERMARK_RATIO = 0.02;
22
+ const ALLOWED_PATH_SCOPES = [
23
+ "crm",
24
+ "oauth",
25
+ "marketing",
26
+ "files",
27
+ "forms",
28
+ "cms",
29
+ "automation",
30
+ "conversations",
31
+ "settings",
32
+ "events",
33
+ "communication-preferences",
34
+ "webhooks",
35
+ "account-info",
36
+ "integrations",
37
+ "analytics",
38
+ "email",
39
+ "media-bridge",
40
+ "feature",
41
+ "broadcast",
42
+ "broadcasts",
43
+ "channels",
44
+ "companies",
45
+ "contacts",
46
+ "content",
47
+ "deals",
48
+ "engagements",
49
+ "extensions",
50
+ "form",
51
+ "owners",
52
+ "reports",
53
+ "submissions",
54
+ "marketing-emails",
55
+ "communication",
56
+ "visitor-identification",
57
+ "integrators",
58
+ "calling",
59
+ "properties",
60
+ "tax",
61
+ "scheduler",
62
+ "appinstalls",
63
+ "payments",
64
+ "business-units",
65
+ "form-integrations",
66
+ "comments",
67
+ ];
68
+ export class HubSpotClient {
69
+ token;
70
+ baseUrl;
71
+ requestId;
72
+ telemetryFile;
73
+ profile;
74
+ strictCapabilities;
75
+ rateLimitState = { nextRequestAtMs: 0 };
76
+ // Portal timezone (e.g. "US/Eastern"). Fetched lazily from
77
+ // /account-info/v3/details the first time daily quota headers appear,
78
+ // then used so the daily reset calculation matches HubSpot's actual
79
+ // reset time (HubSpot resets daily usage at midnight in the portal's
80
+ // own timezone, not UTC). Falls back to "UTC" if detection fails.
81
+ portalTimeZone;
82
+ portalTimeZoneFetching;
83
+ constructor(token, options = {}) {
84
+ this.token = token;
85
+ this.baseUrl = new URL(options.apiBaseUrl?.trim() || "https://api.hubapi.com");
86
+ this.requestId = options.requestId?.trim() || process.env.HSCLI_REQUEST_ID?.trim() || randomUUID();
87
+ this.telemetryFile = options.telemetryFile?.trim() || process.env.HSCLI_TELEMETRY_FILE?.trim() || undefined;
88
+ this.profile = options.profile?.trim() || process.env.HSCLI_PROFILE?.trim() || "default";
89
+ this.strictCapabilities = options.strictCapabilities ?? isEnvTrue(process.env.HSCLI_STRICT_CAPABILITIES);
90
+ }
91
+ async request(path, options = {}, attempt = 0) {
92
+ const method = options.method ?? "GET";
93
+ enforcePermissionProfile(this.profile, method);
94
+ const url = this.resolveUrl(path);
95
+ const pathname = new URL(url).pathname;
96
+ const idempotencyKey = resolveIdempotencyKey(method, options.idempotencyKey);
97
+ const startedAt = Date.now();
98
+ await this.beforeRateLimitedRequest(pathname);
99
+ preflightEndpointCapability({
100
+ profile: this.profile,
101
+ path: pathname,
102
+ strict: this.strictCapabilities,
103
+ });
104
+ try {
105
+ const response = await fetch(url, {
106
+ method,
107
+ headers: {
108
+ Authorization: `Bearer ${this.token}`,
109
+ "Content-Type": "application/json",
110
+ "X-Hubcli-Request-Id": this.requestId,
111
+ ...(idempotencyKey ? { "Idempotency-Key": idempotencyKey } : {}),
112
+ },
113
+ body: options.body ? JSON.stringify(options.body) : undefined,
114
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
115
+ });
116
+ this.observeRateLimitHeaders(response.headers);
117
+ if (response.status === 429 || response.status >= 500) {
118
+ if (response.status === 429) {
119
+ this.observeTooManyRequests(response.headers);
120
+ }
121
+ if (attempt >= MAX_RETRIES) {
122
+ throw new CliError("HTTP_RETRY_EXHAUSTED", `Request failed after ${MAX_RETRIES + 1} attempts`, response.status);
123
+ }
124
+ const retryAfter = Number(response.headers.get("retry-after") ?? "0");
125
+ const backoff = retryAfter > 0 ? retryAfter * 1000 : 1000 * 2 ** attempt;
126
+ await new Promise((r) => setTimeout(r, Math.min(backoff, MAX_BACKOFF_MS)));
127
+ return this.request(path, { ...options, idempotencyKey }, attempt + 1);
128
+ }
129
+ if (!response.ok) {
130
+ const details = await safeJson(response);
131
+ this.emitTelemetry({ method, path: pathname, status: response.status, durationMs: Date.now() - startedAt, attempt });
132
+ const endpointError = mapEndpointAvailabilityError({
133
+ profile: this.profile,
134
+ path: pathname,
135
+ statusCode: response.status,
136
+ details,
137
+ });
138
+ if (endpointError)
139
+ throw endpointError;
140
+ throw new CliError("HTTP_ERROR", `HubSpot API request failed (${response.status})`, response.status, details);
141
+ }
142
+ recordEndpointSuccess({ profile: this.profile, path: pathname, statusCode: response.status });
143
+ if (response.status === 204)
144
+ return { ok: true };
145
+ this.emitTelemetry({ method, path: pathname, status: response.status, durationMs: Date.now() - startedAt, attempt });
146
+ return safeJson(response);
147
+ }
148
+ catch (error) {
149
+ this.emitTelemetry({
150
+ method,
151
+ path: pathname,
152
+ durationMs: Date.now() - startedAt,
153
+ attempt,
154
+ error: error instanceof Error ? error.message : String(error),
155
+ });
156
+ if (error instanceof CliError)
157
+ throw error;
158
+ if (error instanceof DOMException && error.name === "TimeoutError") {
159
+ throw new CliError("HTTP_TIMEOUT", `Request timed out after ${REQUEST_TIMEOUT_MS}ms`);
160
+ }
161
+ if (attempt >= MAX_RETRIES) {
162
+ throw new CliError("NETWORK_ERROR", "Network request failed", undefined, { cause: String(error) });
163
+ }
164
+ await new Promise((r) => setTimeout(r, 1000 * 2 ** attempt));
165
+ return this.request(path, { ...options, idempotencyKey }, attempt + 1);
166
+ }
167
+ }
168
+ resolveUrl(path) {
169
+ if (!path.startsWith("/")) {
170
+ throw new CliError("INVALID_PATH", "Request path must start with '/'");
171
+ }
172
+ const url = new URL(path, this.baseUrl);
173
+ if (url.origin !== this.baseUrl.origin) {
174
+ throw new CliError("INVALID_PATH", "Request URL origin is not allowed");
175
+ }
176
+ if (!ALLOWED_PATH_SCOPES.some((scope) => url.pathname === `/${scope}` || url.pathname.startsWith(`/${scope}/`))) {
177
+ throw new CliError("INVALID_PATH_SCOPE", "Request path escapes allowed HubSpot API scope");
178
+ }
179
+ return url.toString();
180
+ }
181
+ emitTelemetry(event) {
182
+ if (!this.telemetryFile)
183
+ return;
184
+ try {
185
+ appendFileSync(this.telemetryFile, JSON.stringify({
186
+ ts: new Date().toISOString(),
187
+ requestId: this.requestId,
188
+ ...event,
189
+ }) + "\n", "utf8");
190
+ }
191
+ catch {
192
+ // Telemetry must not break CLI execution.
193
+ }
194
+ }
195
+ async beforeRateLimitedRequest(path) {
196
+ const waitMs = this.computeWaitMs();
197
+ if (waitMs > 0) {
198
+ await new Promise((resolve) => setTimeout(resolve, waitMs));
199
+ this.emitTelemetry({
200
+ method: "THROTTLE",
201
+ path,
202
+ durationMs: waitMs,
203
+ attempt: 0,
204
+ });
205
+ }
206
+ this.reserveBudget();
207
+ const now = Date.now();
208
+ const daily = this.rateLimitState.daily;
209
+ if (daily && now < daily.resetAtMs && daily.remaining <= 0) {
210
+ throw new CliError("RATE_LIMIT_DAILY_EXHAUSTED", "HubSpot daily API quota appears exhausted for current credentials.", 429, {
211
+ resetAt: new Date(daily.resetAtMs).toISOString(),
212
+ dailyMax: daily.max,
213
+ dailyRemaining: daily.remaining,
214
+ });
215
+ }
216
+ }
217
+ computeWaitMs() {
218
+ const now = Date.now();
219
+ let waitMs = 0;
220
+ const rolling = this.rateLimitState.rolling;
221
+ if (rolling) {
222
+ if (now >= rolling.resetAtMs) {
223
+ rolling.remaining = rolling.max;
224
+ }
225
+ else if (rolling.remaining <= ROLLING_SAFETY_BUFFER) {
226
+ waitMs = Math.max(waitMs, rolling.resetAtMs - now + 25);
227
+ }
228
+ }
229
+ const nextRequestAt = this.rateLimitState.nextRequestAtMs;
230
+ if (nextRequestAt > now) {
231
+ waitMs = Math.max(waitMs, nextRequestAt - now);
232
+ }
233
+ return waitMs;
234
+ }
235
+ reserveBudget() {
236
+ const now = Date.now();
237
+ const rolling = this.rateLimitState.rolling;
238
+ if (rolling && now < rolling.resetAtMs && rolling.remaining > 0) {
239
+ rolling.remaining -= 1;
240
+ }
241
+ const daily = this.rateLimitState.daily;
242
+ if (daily && now < daily.resetAtMs && daily.remaining > 0) {
243
+ daily.remaining -= 1;
244
+ }
245
+ }
246
+ observeRateLimitHeaders(headers) {
247
+ const now = Date.now();
248
+ const intervalMs = parsePositiveInt(headers.get("x-hubspot-ratelimit-interval-milliseconds"));
249
+ const max = parsePositiveInt(headers.get("x-hubspot-ratelimit-max"));
250
+ const remaining = parseNonNegativeInt(headers.get("x-hubspot-ratelimit-remaining"));
251
+ if (intervalMs !== undefined && max !== undefined && remaining !== undefined) {
252
+ this.rateLimitState.rolling = {
253
+ intervalMs,
254
+ max,
255
+ remaining,
256
+ resetAtMs: now + intervalMs,
257
+ };
258
+ }
259
+ const dailyMax = parsePositiveInt(headers.get("x-hubspot-ratelimit-daily"));
260
+ const dailyRemaining = parseNonNegativeInt(headers.get("x-hubspot-ratelimit-daily-remaining"));
261
+ if (dailyMax !== undefined && dailyRemaining !== undefined) {
262
+ const resetAtMs = nextMidnightMs(now, this.portalTimeZone ?? "UTC");
263
+ this.rateLimitState.daily = {
264
+ max: dailyMax,
265
+ remaining: dailyRemaining,
266
+ resetAtMs,
267
+ };
268
+ this.rateLimitState.nextRequestAtMs = this.computeDailyPacingNextAt(resetAtMs, dailyMax, dailyRemaining);
269
+ // Lazily fetch the portal's timezone on first daily-quota sighting so
270
+ // subsequent resets use the correct local midnight.
271
+ this.ensurePortalTimeZoneFetched();
272
+ }
273
+ }
274
+ /**
275
+ * Fetch the portal's timezone once and cache it on the client instance.
276
+ * /account-info/v3/details returns a `timeZone` string (e.g. "US/Eastern").
277
+ * If the request fails or times out, fall back to "UTC" silently — daily
278
+ * quota tracking still works, just off by a few hours for non-UTC portals.
279
+ */
280
+ ensurePortalTimeZoneFetched() {
281
+ if (this.portalTimeZone || this.portalTimeZoneFetching)
282
+ return;
283
+ const url = this.resolveUrl("/account-info/v3/details");
284
+ this.portalTimeZoneFetching = (async () => {
285
+ try {
286
+ const response = await fetch(url, {
287
+ method: "GET",
288
+ headers: {
289
+ Authorization: `Bearer ${this.token}`,
290
+ "X-Hubcli-Request-Id": this.requestId,
291
+ },
292
+ signal: AbortSignal.timeout(5_000),
293
+ });
294
+ if (response.ok) {
295
+ const body = await response.json().catch(() => null);
296
+ if (body?.timeZone && typeof body.timeZone === "string") {
297
+ this.portalTimeZone = body.timeZone;
298
+ return;
299
+ }
300
+ }
301
+ }
302
+ catch {
303
+ // silent fallback
304
+ }
305
+ this.portalTimeZone = "UTC";
306
+ })();
307
+ }
308
+ observeTooManyRequests(headers) {
309
+ const now = Date.now();
310
+ const retryAfterSeconds = parsePositiveInt(headers.get("retry-after"));
311
+ const retryAtMs = retryAfterSeconds !== undefined
312
+ ? now + retryAfterSeconds * 1000
313
+ : now + 1000;
314
+ this.rateLimitState.nextRequestAtMs = Math.max(this.rateLimitState.nextRequestAtMs, retryAtMs);
315
+ if (this.rateLimitState.rolling) {
316
+ this.rateLimitState.rolling.remaining = 0;
317
+ this.rateLimitState.rolling.resetAtMs = Math.max(this.rateLimitState.rolling.resetAtMs, retryAtMs);
318
+ return;
319
+ }
320
+ this.rateLimitState.rolling = {
321
+ max: 1,
322
+ remaining: 0,
323
+ intervalMs: Math.max(1000, retryAtMs - now),
324
+ resetAtMs: retryAtMs,
325
+ };
326
+ }
327
+ computeDailyPacingNextAt(resetAtMs, dailyMax, dailyRemaining) {
328
+ const now = Date.now();
329
+ if (dailyRemaining <= 0)
330
+ return now;
331
+ const lowWatermark = Math.max(DAILY_MIN_REMAINING_BUFFER, Math.floor(dailyMax * DAILY_LOW_WATERMARK_RATIO));
332
+ if (dailyRemaining > lowWatermark)
333
+ return 0;
334
+ const msUntilReset = Math.max(0, resetAtMs - now);
335
+ const spreadMs = Math.max(200, Math.floor(msUntilReset / Math.max(dailyRemaining, 1)));
336
+ return now + spreadMs;
337
+ }
338
+ }
339
+ function isEnvTrue(value) {
340
+ if (!value)
341
+ return false;
342
+ const normalized = value.trim().toLowerCase();
343
+ return normalized === "1" || normalized === "true" || normalized === "yes";
344
+ }
345
+ async function safeJson(response) {
346
+ // Read body as text first, then JSON.parse, to avoid "Body is unusable"
347
+ // error when response.json() consumes the stream and fails on non-JSON.
348
+ let text;
349
+ try {
350
+ text = await response.text();
351
+ }
352
+ catch {
353
+ // Fallback if text() is unavailable (shouldn't happen with real fetch)
354
+ try {
355
+ return await response.json();
356
+ }
357
+ catch {
358
+ return {};
359
+ }
360
+ }
361
+ try {
362
+ return JSON.parse(text);
363
+ }
364
+ catch {
365
+ return { message: text };
366
+ }
367
+ }
368
+ function resolveIdempotencyKey(method, provided) {
369
+ if (!isWriteMethod(method))
370
+ return undefined;
371
+ const normalized = provided?.trim();
372
+ if (normalized)
373
+ return normalized;
374
+ return randomUUID();
375
+ }
376
+ function isWriteMethod(method) {
377
+ return method === "POST" || method === "PATCH" || method === "PUT" || method === "DELETE";
378
+ }
379
+ function parsePositiveInt(value) {
380
+ if (!value)
381
+ return undefined;
382
+ const parsed = Number(value);
383
+ if (!Number.isFinite(parsed) || parsed <= 0)
384
+ return undefined;
385
+ return Math.floor(parsed);
386
+ }
387
+ function parseNonNegativeInt(value) {
388
+ if (!value)
389
+ return undefined;
390
+ const parsed = Number(value);
391
+ if (!Number.isFinite(parsed) || parsed < 0)
392
+ return undefined;
393
+ return Math.floor(parsed);
394
+ }
395
+ function nextUtcMidnightMs(nowMs) {
396
+ const now = new Date(nowMs);
397
+ return Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() + 1, 0, 0, 0, 0);
398
+ }
399
+ /**
400
+ * Return the epoch ms of the next midnight in the given IANA timezone.
401
+ * HubSpot resets daily usage at midnight in the portal's own timezone.
402
+ * Falls back to UTC if the timeZone is "UTC" or if Intl formatting fails.
403
+ */
404
+ function nextMidnightMs(nowMs, timeZone) {
405
+ if (!timeZone || timeZone === "UTC")
406
+ return nextUtcMidnightMs(nowMs);
407
+ try {
408
+ // Render the current instant as the local date in the target timezone.
409
+ const fmt = new Intl.DateTimeFormat("en-US", {
410
+ timeZone,
411
+ year: "numeric",
412
+ month: "2-digit",
413
+ day: "2-digit",
414
+ hour: "2-digit",
415
+ minute: "2-digit",
416
+ second: "2-digit",
417
+ hour12: false,
418
+ });
419
+ const parts = Object.fromEntries(fmt.formatToParts(new Date(nowMs)).map(p => [p.type, p.value]));
420
+ const localNow = new Date(`${parts.year}-${parts.month}-${parts.day}T${parts.hour === "24" ? "00" : parts.hour}:${parts.minute}:${parts.second}Z`).getTime();
421
+ // Offset between UTC and local wall time (ms)
422
+ const offsetMs = localNow - nowMs;
423
+ // Compute midnight in local wall time, expressed in UTC-epoch ms
424
+ const localDate = new Date(localNow);
425
+ const localMidnightUtcMs = Date.UTC(localDate.getUTCFullYear(), localDate.getUTCMonth(), localDate.getUTCDate() + 1, 0, 0, 0, 0);
426
+ // Adjust back from "local wall time expressed as UTC" to actual UTC epoch
427
+ return localMidnightUtcMs - offsetMs;
428
+ }
429
+ catch {
430
+ return nextUtcMidnightMs(nowMs);
431
+ }
432
+ }
433
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/core/http.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ export type OutputMode = "human" | "json";
2
+ export type OutputFormat = "json" | "table" | "csv" | "yaml";
3
+ export interface CliContext {
4
+ profile: string;
5
+ json: boolean;
6
+ dryRun: boolean;
7
+ force: boolean;
8
+ strictCapabilities?: boolean;
9
+ format?: OutputFormat;
10
+ policyFile?: string;
11
+ changeTicket?: string;
12
+ runId?: string;
13
+ telemetryFile?: string;
14
+ }
15
+ export declare class CliError extends Error {
16
+ code: string;
17
+ status?: number | undefined;
18
+ details?: unknown | undefined;
19
+ constructor(code: string, message: string, status?: number | undefined, details?: unknown | undefined);
20
+ }
21
+ export declare function redactSensitive<T>(input: T): T;
22
+ export declare function printResult(ctx: CliContext, data: unknown): void;
23
+ export declare function printError(ctx: CliContext, err: unknown): void;
@@ -0,0 +1,197 @@
1
+ export class CliError extends Error {
2
+ code;
3
+ status;
4
+ details;
5
+ constructor(code, message, status, details) {
6
+ super(message);
7
+ this.code = code;
8
+ this.status = status;
9
+ this.details = details;
10
+ }
11
+ }
12
+ const SENSITIVE_KEYWORDS = ["token", "authorization", "api_key", "apikey", "secret", "password", "privateapp"];
13
+ const BEARER_PATTERN = /bearer\s+[a-z0-9._~+/\-=]+/gi;
14
+ const HUBSPOT_PRIVATE_APP_TOKEN_PATTERN = /\bpat-[a-z0-9-]{10,}\b/gi;
15
+ const SECRET_ASSIGNMENT_PATTERNS = [
16
+ /((?:^|[\s?&,;])(?:token|access_token|refresh_token|api[_-]?key|apikey|secret|password|privateapp)\s*=\s*)([^\s&;,]+)/gi,
17
+ /((?:token|access_token|refresh_token|api[_-]?key|apikey|secret|password|privateapp)\s*:\s*)([^\s,;]+)/gi,
18
+ ];
19
+ function isSensitiveKey(key) {
20
+ const normalized = key.toLowerCase();
21
+ return SENSITIVE_KEYWORDS.some((k) => normalized.includes(k));
22
+ }
23
+ function redactString(value) {
24
+ let redacted = value.replace(BEARER_PATTERN, "Bearer [REDACTED]");
25
+ for (const pattern of SECRET_ASSIGNMENT_PATTERNS) {
26
+ redacted = redacted.replace(pattern, (_match, prefix) => `${prefix}[REDACTED]`);
27
+ }
28
+ redacted = redacted.replace(HUBSPOT_PRIVATE_APP_TOKEN_PATTERN, "[REDACTED]");
29
+ return redacted;
30
+ }
31
+ export function redactSensitive(input) {
32
+ if (input === null || input === undefined)
33
+ return input;
34
+ if (typeof input === "string") {
35
+ return redactString(input);
36
+ }
37
+ if (Array.isArray(input)) {
38
+ return input.map((item) => redactSensitive(item));
39
+ }
40
+ if (typeof input === "object") {
41
+ const out = {};
42
+ for (const [key, value] of Object.entries(input)) {
43
+ if (isSensitiveKey(key)) {
44
+ out[key] = "[REDACTED]";
45
+ }
46
+ else {
47
+ out[key] = redactSensitive(value);
48
+ }
49
+ }
50
+ return out;
51
+ }
52
+ return input;
53
+ }
54
+ export function printResult(ctx, data) {
55
+ const safeData = redactSensitive(data);
56
+ const selectedFormat = ctx.json ? "json" : (ctx.format ?? "table");
57
+ if (selectedFormat === "json") {
58
+ // eslint-disable-next-line no-console
59
+ console.log(JSON.stringify({ ok: true, data: safeData }, null, 2));
60
+ return;
61
+ }
62
+ if (selectedFormat === "csv") {
63
+ // eslint-disable-next-line no-console
64
+ console.log(toCsv(safeData));
65
+ return;
66
+ }
67
+ if (selectedFormat === "yaml") {
68
+ // eslint-disable-next-line no-console
69
+ console.log(toYaml(safeData));
70
+ return;
71
+ }
72
+ // eslint-disable-next-line no-console
73
+ console.log(toTable(safeData));
74
+ }
75
+ export function printError(ctx, err) {
76
+ const e = err instanceof CliError
77
+ ? err
78
+ : new CliError("UNEXPECTED_ERROR", err instanceof Error ? err.message : String(err));
79
+ const safeMessage = redactSensitive(e.message);
80
+ const safeDetails = redactSensitive(e.details);
81
+ const selectedFormat = ctx.json ? "json" : (ctx.format ?? "table");
82
+ if (selectedFormat === "json") {
83
+ console.error(JSON.stringify({ ok: false, error: { code: e.code, message: safeMessage, status: e.status, details: safeDetails } }, null, 2));
84
+ }
85
+ else {
86
+ console.error(`[${e.code}] ${safeMessage}`);
87
+ if (e.status)
88
+ console.error(`status=${e.status}`);
89
+ if (safeDetails)
90
+ console.error(JSON.stringify(safeDetails, null, 2));
91
+ }
92
+ }
93
+ function toTabularRows(data) {
94
+ if (Array.isArray(data)) {
95
+ return data
96
+ .filter((item) => item && typeof item === "object" && !Array.isArray(item))
97
+ .map((item) => item);
98
+ }
99
+ if (data && typeof data === "object" && !Array.isArray(data)) {
100
+ const record = data;
101
+ if (Array.isArray(record.results)) {
102
+ return record.results
103
+ .filter((item) => item && typeof item === "object" && !Array.isArray(item))
104
+ .map((item) => item);
105
+ }
106
+ return [record];
107
+ }
108
+ return [{ value: data }];
109
+ }
110
+ function toCell(value) {
111
+ if (value === null || value === undefined)
112
+ return "";
113
+ if (typeof value === "string")
114
+ return value;
115
+ if (typeof value === "number" || typeof value === "boolean")
116
+ return String(value);
117
+ return JSON.stringify(value);
118
+ }
119
+ function toTable(data) {
120
+ if (typeof data === "string")
121
+ return data;
122
+ const rows = toTabularRows(data);
123
+ if (rows.length === 0)
124
+ return "(empty)";
125
+ const headers = Array.from(new Set(rows.flatMap((row) => Object.keys(row))));
126
+ if (headers.length === 0)
127
+ return "(empty)";
128
+ const widths = headers.map((header) => {
129
+ const maxCell = Math.max(...rows.map((row) => toCell(row[header]).length), 0);
130
+ return Math.max(header.length, maxCell);
131
+ });
132
+ const headerLine = headers.map((header, index) => header.padEnd(widths[index])).join(" | ");
133
+ const dividerLine = widths.map((width) => "-".repeat(width)).join("-|-");
134
+ const bodyLines = rows.map((row) => (headers.map((header, index) => toCell(row[header]).padEnd(widths[index])).join(" | ")));
135
+ return [headerLine, dividerLine, ...bodyLines].join("\n");
136
+ }
137
+ function toCsv(data) {
138
+ const rows = toTabularRows(data);
139
+ if (rows.length === 0)
140
+ return "";
141
+ const headers = Array.from(new Set(rows.flatMap((row) => Object.keys(row))));
142
+ if (headers.length === 0)
143
+ return "";
144
+ const escape = (value) => {
145
+ if (!value.includes("\"") && !value.includes(",") && !value.includes("\n"))
146
+ return value;
147
+ return `"${value.replace(/"/g, "\"\"")}"`;
148
+ };
149
+ const lines = [
150
+ headers.map((header) => escape(header)).join(","),
151
+ ...rows.map((row) => headers.map((header) => escape(toCell(row[header]))).join(",")),
152
+ ];
153
+ return lines.join("\n");
154
+ }
155
+ function toYaml(data, indent = 0) {
156
+ const spacing = " ".repeat(indent);
157
+ if (data === null)
158
+ return "null";
159
+ if (data === undefined)
160
+ return "null";
161
+ if (typeof data === "number" || typeof data === "boolean")
162
+ return String(data);
163
+ if (typeof data === "string")
164
+ return formatYamlString(data);
165
+ if (Array.isArray(data)) {
166
+ if (data.length === 0)
167
+ return "[]";
168
+ return data.map((item) => {
169
+ if (isScalar(item))
170
+ return `${spacing}- ${toYaml(item, indent + 2)}`;
171
+ const nested = toYaml(item, indent + 2);
172
+ return `${spacing}-\n${nested}`;
173
+ }).join("\n");
174
+ }
175
+ const record = data;
176
+ const entries = Object.entries(record);
177
+ if (entries.length === 0)
178
+ return "{}";
179
+ return entries.map(([key, value]) => {
180
+ const safeKey = /^[a-zA-Z0-9_-]+$/.test(key) ? key : JSON.stringify(key);
181
+ if (isScalar(value)) {
182
+ return `${spacing}${safeKey}: ${toYaml(value, indent + 2)}`;
183
+ }
184
+ return `${spacing}${safeKey}:\n${toYaml(value, indent + 2)}`;
185
+ }).join("\n");
186
+ }
187
+ function isScalar(value) {
188
+ return value === null || value === undefined || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
189
+ }
190
+ function formatYamlString(value) {
191
+ if (value === "")
192
+ return "\"\"";
193
+ if (/^[a-zA-Z0-9_./-]+$/.test(value))
194
+ return value;
195
+ return JSON.stringify(value);
196
+ }
197
+ //# sourceMappingURL=output.js.map