@forumulate/cli 0.4.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (229) hide show
  1. package/README.md +116 -5
  2. package/dist/api/args.d.ts +21 -0
  3. package/dist/api/args.d.ts.map +1 -0
  4. package/dist/api/args.js +81 -0
  5. package/dist/api/args.js.map +1 -0
  6. package/dist/api/command.d.ts +17 -0
  7. package/dist/api/command.d.ts.map +1 -0
  8. package/dist/api/command.js +182 -0
  9. package/dist/api/command.js.map +1 -0
  10. package/dist/api/describe.d.ts +5 -0
  11. package/dist/api/describe.d.ts.map +1 -0
  12. package/dist/api/describe.js +121 -0
  13. package/dist/api/describe.js.map +1 -0
  14. package/dist/api/http.d.ts +81 -0
  15. package/dist/api/http.d.ts.map +1 -0
  16. package/dist/api/http.js +183 -0
  17. package/dist/api/http.js.map +1 -0
  18. package/dist/api/operations.json +1 -0
  19. package/dist/api/output.d.ts +35 -0
  20. package/dist/api/output.d.ts.map +1 -0
  21. package/dist/api/output.js +176 -0
  22. package/dist/api/output.js.map +1 -0
  23. package/dist/api/request.d.ts +37 -0
  24. package/dist/api/request.d.ts.map +1 -0
  25. package/dist/api/request.js +230 -0
  26. package/dist/api/request.js.map +1 -0
  27. package/dist/api/send.d.ts +35 -0
  28. package/dist/api/send.d.ts.map +1 -0
  29. package/dist/api/send.js +85 -0
  30. package/dist/api/send.js.map +1 -0
  31. package/dist/api/spec.d.ts +96 -0
  32. package/dist/api/spec.d.ts.map +1 -0
  33. package/dist/api/spec.js +126 -0
  34. package/dist/api/spec.js.map +1 -0
  35. package/dist/cli.js +12 -0
  36. package/dist/cli.js.map +1 -1
  37. package/dist/commands/completion.d.ts +12 -0
  38. package/dist/commands/completion.d.ts.map +1 -0
  39. package/dist/commands/completion.js +153 -0
  40. package/dist/commands/completion.js.map +1 -0
  41. package/dist/commands/config.d.ts +33 -0
  42. package/dist/commands/config.d.ts.map +1 -0
  43. package/dist/commands/config.js +144 -0
  44. package/dist/commands/config.js.map +1 -0
  45. package/dist/commands/context.d.ts +35 -0
  46. package/dist/commands/context.d.ts.map +1 -0
  47. package/dist/commands/context.js +59 -0
  48. package/dist/commands/context.js.map +1 -0
  49. package/dist/commands/groups-api.d.ts +11 -0
  50. package/dist/commands/groups-api.d.ts.map +1 -0
  51. package/dist/commands/groups-api.js +140 -0
  52. package/dist/commands/groups-api.js.map +1 -0
  53. package/dist/commands/groups-community.d.ts +15 -0
  54. package/dist/commands/groups-community.d.ts.map +1 -0
  55. package/dist/commands/groups-community.js +344 -0
  56. package/dist/commands/groups-community.js.map +1 -0
  57. package/dist/commands/groups-content.d.ts +10 -0
  58. package/dist/commands/groups-content.d.ts.map +1 -0
  59. package/dist/commands/groups-content.js +331 -0
  60. package/dist/commands/groups-content.js.map +1 -0
  61. package/dist/commands/groups-docs.d.ts +12 -0
  62. package/dist/commands/groups-docs.d.ts.map +1 -0
  63. package/dist/commands/groups-docs.js +414 -0
  64. package/dist/commands/groups-docs.js.map +1 -0
  65. package/dist/commands/groups-org.d.ts +10 -0
  66. package/dist/commands/groups-org.d.ts.map +1 -0
  67. package/dist/commands/groups-org.js +405 -0
  68. package/dist/commands/groups-org.js.map +1 -0
  69. package/dist/commands/groups-site.d.ts +3 -0
  70. package/dist/commands/groups-site.d.ts.map +1 -0
  71. package/dist/commands/groups-site.js +230 -0
  72. package/dist/commands/groups-site.js.map +1 -0
  73. package/dist/commands/groups-spaces.d.ts +3 -0
  74. package/dist/commands/groups-spaces.d.ts.map +1 -0
  75. package/dist/commands/groups-spaces.js +273 -0
  76. package/dist/commands/groups-spaces.js.map +1 -0
  77. package/dist/commands/groups-types.d.ts +3 -0
  78. package/dist/commands/groups-types.d.ts.map +1 -0
  79. package/dist/commands/groups-types.js +251 -0
  80. package/dist/commands/groups-types.js.map +1 -0
  81. package/dist/commands/groups.d.ts +4 -0
  82. package/dist/commands/groups.d.ts.map +1 -0
  83. package/dist/commands/groups.js +71 -0
  84. package/dist/commands/groups.js.map +1 -0
  85. package/dist/commands/index.d.ts +25 -0
  86. package/dist/commands/index.d.ts.map +1 -0
  87. package/dist/commands/index.js +118 -0
  88. package/dist/commands/index.js.map +1 -0
  89. package/dist/commands/resource.d.ts +86 -0
  90. package/dist/commands/resource.d.ts.map +1 -0
  91. package/dist/commands/resource.js +314 -0
  92. package/dist/commands/resource.js.map +1 -0
  93. package/dist/content/command.d.ts +34 -0
  94. package/dist/content/command.d.ts.map +1 -0
  95. package/dist/content/command.js +225 -0
  96. package/dist/content/command.js.map +1 -0
  97. package/dist/content/library.d.ts +23 -0
  98. package/dist/content/library.d.ts.map +1 -0
  99. package/dist/content/library.js +41 -0
  100. package/dist/content/library.js.map +1 -0
  101. package/dist/content/render.d.ts +15 -0
  102. package/dist/content/render.d.ts.map +1 -0
  103. package/dist/content/render.js +85 -0
  104. package/dist/content/render.js.map +1 -0
  105. package/dist/content/types-gen.d.ts +40 -0
  106. package/dist/content/types-gen.d.ts.map +1 -0
  107. package/dist/content/types-gen.js +200 -0
  108. package/dist/content/types-gen.js.map +1 -0
  109. package/dist/help.d.ts +3 -0
  110. package/dist/help.d.ts.map +1 -0
  111. package/dist/help.js +142 -0
  112. package/dist/help.js.map +1 -0
  113. package/dist/import/coerce.d.ts +34 -0
  114. package/dist/import/coerce.d.ts.map +1 -0
  115. package/dist/import/coerce.js +134 -0
  116. package/dist/import/coerce.js.map +1 -0
  117. package/dist/import/command.d.ts +25 -0
  118. package/dist/import/command.d.ts.map +1 -0
  119. package/dist/import/command.js +127 -0
  120. package/dist/import/command.js.map +1 -0
  121. package/dist/import/config.d.ts +39 -0
  122. package/dist/import/config.d.ts.map +1 -0
  123. package/dist/import/config.js +48 -0
  124. package/dist/import/config.js.map +1 -0
  125. package/dist/import/contentful.d.ts +3 -0
  126. package/dist/import/contentful.d.ts.map +1 -0
  127. package/dist/import/contentful.js +179 -0
  128. package/dist/import/contentful.js.map +1 -0
  129. package/dist/import/disk.d.ts +4 -0
  130. package/dist/import/disk.d.ts.map +1 -0
  131. package/dist/import/disk.js +19 -0
  132. package/dist/import/disk.js.map +1 -0
  133. package/dist/import/engine-locales.d.ts +35 -0
  134. package/dist/import/engine-locales.d.ts.map +1 -0
  135. package/dist/import/engine-locales.js +61 -0
  136. package/dist/import/engine-locales.js.map +1 -0
  137. package/dist/import/engine.d.ts +29 -0
  138. package/dist/import/engine.d.ts.map +1 -0
  139. package/dist/import/engine.js +248 -0
  140. package/dist/import/engine.js.map +1 -0
  141. package/dist/import/media.d.ts +24 -0
  142. package/dist/import/media.d.ts.map +1 -0
  143. package/dist/import/media.js +39 -0
  144. package/dist/import/media.js.map +1 -0
  145. package/dist/import/model-fields.d.ts +22 -0
  146. package/dist/import/model-fields.d.ts.map +1 -0
  147. package/dist/import/model-fields.js +60 -0
  148. package/dist/import/model-fields.js.map +1 -0
  149. package/dist/import/payload/index.d.ts +9 -0
  150. package/dist/import/payload/index.d.ts.map +1 -0
  151. package/dist/import/payload/index.js +129 -0
  152. package/dist/import/payload/index.js.map +1 -0
  153. package/dist/import/report.d.ts +5 -0
  154. package/dist/import/report.d.ts.map +1 -0
  155. package/dist/import/report.js +52 -0
  156. package/dist/import/report.js.map +1 -0
  157. package/dist/import/richtext-core.d.ts +26 -0
  158. package/dist/import/richtext-core.d.ts.map +1 -0
  159. package/dist/import/richtext-core.js +65 -0
  160. package/dist/import/richtext-core.js.map +1 -0
  161. package/dist/import/richtext-html.d.ts +5 -0
  162. package/dist/import/richtext-html.d.ts.map +1 -0
  163. package/dist/import/richtext-html.js +311 -0
  164. package/dist/import/richtext-html.js.map +1 -0
  165. package/dist/import/richtext-json.d.ts +10 -0
  166. package/dist/import/richtext-json.d.ts.map +1 -0
  167. package/dist/import/richtext-json.js +250 -0
  168. package/dist/import/richtext-json.js.map +1 -0
  169. package/dist/import/sanity.d.ts +8 -0
  170. package/dist/import/sanity.d.ts.map +1 -0
  171. package/dist/import/sanity.js +158 -0
  172. package/dist/import/sanity.js.map +1 -0
  173. package/dist/import/strapi-archive.d.ts +6 -0
  174. package/dist/import/strapi-archive.d.ts.map +1 -0
  175. package/dist/import/strapi-archive.js +127 -0
  176. package/dist/import/strapi-archive.js.map +1 -0
  177. package/dist/import/strapi.d.ts +7 -0
  178. package/dist/import/strapi.d.ts.map +1 -0
  179. package/dist/import/strapi.js +185 -0
  180. package/dist/import/strapi.js.map +1 -0
  181. package/dist/import/tar.d.ts +3 -0
  182. package/dist/import/tar.d.ts.map +1 -0
  183. package/dist/import/tar.js +48 -0
  184. package/dist/import/tar.js.map +1 -0
  185. package/dist/import/types.d.ts +157 -0
  186. package/dist/import/types.d.ts.map +1 -0
  187. package/dist/import/types.js +12 -0
  188. package/dist/import/types.js.map +1 -0
  189. package/dist/import/wordpress.d.ts +15 -0
  190. package/dist/import/wordpress.d.ts.map +1 -0
  191. package/dist/import/wordpress.js +147 -0
  192. package/dist/import/wordpress.js.map +1 -0
  193. package/dist/publish/scan.d.ts +1 -1
  194. package/dist/publish/scan.d.ts.map +1 -1
  195. package/dist/publish/scan.js +2 -2
  196. package/dist/publish/scan.js.map +1 -1
  197. package/dist/publish-dir.d.ts +54 -0
  198. package/dist/publish-dir.d.ts.map +1 -0
  199. package/dist/publish-dir.js +119 -0
  200. package/dist/publish-dir.js.map +1 -0
  201. package/dist/run.d.ts +21 -1
  202. package/dist/run.d.ts.map +1 -1
  203. package/dist/run.js +70 -65
  204. package/dist/run.js.map +1 -1
  205. package/dist/translations/command.d.ts +36 -0
  206. package/dist/translations/command.d.ts.map +1 -0
  207. package/dist/translations/command.js +411 -0
  208. package/dist/translations/command.js.map +1 -0
  209. package/dist/translations/extras.d.ts +29 -0
  210. package/dist/translations/extras.d.ts.map +1 -0
  211. package/dist/translations/extras.js +123 -0
  212. package/dist/translations/extras.js.map +1 -0
  213. package/dist/translations/files.d.ts +22 -0
  214. package/dist/translations/files.d.ts.map +1 -0
  215. package/dist/translations/files.js +75 -0
  216. package/dist/translations/files.js.map +1 -0
  217. package/dist/translations/sync.d.ts +89 -0
  218. package/dist/translations/sync.d.ts.map +1 -0
  219. package/dist/translations/sync.js +215 -0
  220. package/dist/translations/sync.js.map +1 -0
  221. package/dist/translations/target.d.ts +33 -0
  222. package/dist/translations/target.d.ts.map +1 -0
  223. package/dist/translations/target.js +54 -0
  224. package/dist/translations/target.js.map +1 -0
  225. package/dist/translations/xliff.d.ts +29 -0
  226. package/dist/translations/xliff.d.ts.map +1 -0
  227. package/dist/translations/xliff.js +62 -0
  228. package/dist/translations/xliff.js.map +1 -0
  229. package/package.json +6 -4
@@ -0,0 +1,81 @@
1
+ /**
2
+ * The one HTTP path `forumulate api` and the resource commands share.
3
+ *
4
+ * Not the SDK's `request`, for two reasons that are both about what a terminal
5
+ * user sees when something goes wrong: its error drops the response headers, so
6
+ * a 429's `Retry-After` was unreadable and the retry could only guess; and it
7
+ * parses every body as JSON, so the edge's HTML block page (Cloudflare 1010)
8
+ * surfaced as `Unexpected token <` instead of "the edge refused this".
9
+ *
10
+ * What it does on every call:
11
+ * - `Authorization: Bearer` from the stored token or `FORUMULATE_TOKEN`.
12
+ * - A named `User-Agent` — a default library UA is answered with a block page.
13
+ * - `Forumulate-Version` (default {@link DEFAULT_API_VERSION}), so collections
14
+ * answer the paging envelope `--paginate` walks.
15
+ * - `Idempotency-Key` on writes whose operation declares one, generated once
16
+ * per command and reused across retries — a retried POST is the same POST.
17
+ * - Retries: a 429 always (it was not processed), a 502/503/504 or a dropped
18
+ * connection only when the request is safe to repeat (GET/PUT/DELETE, or a
19
+ * write carrying an idempotency key). `Retry-After` is honoured, seconds or
20
+ * an HTTP date, capped so a bad header cannot park a CI job for an hour.
21
+ */
22
+ export declare const DEFAULT_API_VERSION = "2026-12-01";
23
+ export interface HttpOptions {
24
+ baseUrl: string;
25
+ token?: string;
26
+ userAgent: string;
27
+ apiVersion?: string;
28
+ fetch?: typeof fetch;
29
+ sleep?: (ms: number) => Promise<void>;
30
+ /** Retries after the first attempt. Default 3. */
31
+ retries?: number;
32
+ /** Called before each retry, so a person watching knows why it paused. */
33
+ onRetry?: (info: {
34
+ attempt: number;
35
+ waitMs: number;
36
+ status?: number;
37
+ }) => void;
38
+ }
39
+ export interface HttpRequest {
40
+ method: string;
41
+ path: string;
42
+ query?: Record<string, string | undefined>;
43
+ body?: unknown;
44
+ form?: FormData;
45
+ headers?: Record<string, string>;
46
+ /** Send `Idempotency-Key` (generated unless `headers` already carries one). */
47
+ idempotent?: boolean;
48
+ /**
49
+ * Keep a 2xx answer as bytes (a Buffer in `data`): an SDK archive, a PDF, a
50
+ * CSV export. Read as text, a zip comes back as replacement characters and
51
+ * the file a person saves will not open.
52
+ */
53
+ raw?: boolean;
54
+ }
55
+ export interface HttpResponse {
56
+ status: number;
57
+ headers: Headers;
58
+ /** Parsed JSON, or the text of a non-JSON answer, or undefined for an empty one. */
59
+ data: unknown;
60
+ }
61
+ export declare class ApiError extends Error {
62
+ readonly status: number;
63
+ readonly code: string;
64
+ readonly details?: Record<string, string[]> | undefined;
65
+ readonly docs?: string | undefined;
66
+ constructor(status: number, code: string, message: string, details?: Record<string, string[]> | undefined, docs?: string | undefined);
67
+ }
68
+ /** `Retry-After` as milliseconds: delta-seconds or an HTTP date; undefined when absent or unreadable. */
69
+ export declare function retryAfterMs(value: string | null, now?: number): number | undefined;
70
+ export declare class Http {
71
+ readonly opts: HttpOptions;
72
+ private readonly fetchImpl;
73
+ constructor(opts: HttpOptions);
74
+ get baseUrl(): string;
75
+ url(path: string, query?: Record<string, string | undefined>): string;
76
+ headersFor(req: HttpRequest): Record<string, string>;
77
+ send(req: HttpRequest): Promise<HttpResponse>;
78
+ }
79
+ /** The CLI's one error line, plus the field problems a 422 names. */
80
+ export declare function formatError(e: unknown): string[];
81
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/api/http.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,mBAAmB,eAAe,CAAC;AAEhD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0EAA0E;IAC1E,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CAChF;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IAC3C,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,+EAA+E;IAC/E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,oFAAoF;IACpF,IAAI,EAAE,OAAO,CAAC;CACf;AAED,qBAAa,QAAS,SAAQ,KAAK;IAE/B,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM;IAErB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAC3C,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM;gBAJb,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACN,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,YAAA,EAClC,IAAI,CAAC,EAAE,MAAM,YAAA;CAKzB;AAKD,yGAAyG;AACzG,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,SAAa,GAAG,MAAM,GAAG,SAAS,CAOvF;AAED,qBAAa,IAAI;IAEH,QAAQ,CAAC,IAAI,EAAE,WAAW;IADtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;gBACpB,IAAI,EAAE,WAAW;IAItC,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAM,GAAG,MAAM;IAMzE,UAAU,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAc9C,IAAI,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;CAqDpD;AA6CD,qEAAqE;AACrE,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,EAAE,CAehD"}
@@ -0,0 +1,183 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Http = exports.ApiError = exports.DEFAULT_API_VERSION = void 0;
4
+ exports.retryAfterMs = retryAfterMs;
5
+ exports.formatError = formatError;
6
+ const node_crypto_1 = require("node:crypto");
7
+ /**
8
+ * The one HTTP path `forumulate api` and the resource commands share.
9
+ *
10
+ * Not the SDK's `request`, for two reasons that are both about what a terminal
11
+ * user sees when something goes wrong: its error drops the response headers, so
12
+ * a 429's `Retry-After` was unreadable and the retry could only guess; and it
13
+ * parses every body as JSON, so the edge's HTML block page (Cloudflare 1010)
14
+ * surfaced as `Unexpected token <` instead of "the edge refused this".
15
+ *
16
+ * What it does on every call:
17
+ * - `Authorization: Bearer` from the stored token or `FORUMULATE_TOKEN`.
18
+ * - A named `User-Agent` — a default library UA is answered with a block page.
19
+ * - `Forumulate-Version` (default {@link DEFAULT_API_VERSION}), so collections
20
+ * answer the paging envelope `--paginate` walks.
21
+ * - `Idempotency-Key` on writes whose operation declares one, generated once
22
+ * per command and reused across retries — a retried POST is the same POST.
23
+ * - Retries: a 429 always (it was not processed), a 502/503/504 or a dropped
24
+ * connection only when the request is safe to repeat (GET/PUT/DELETE, or a
25
+ * write carrying an idempotency key). `Retry-After` is honoured, seconds or
26
+ * an HTTP date, capped so a bad header cannot park a CI job for an hour.
27
+ */
28
+ exports.DEFAULT_API_VERSION = '2026-12-01';
29
+ class ApiError extends Error {
30
+ status;
31
+ code;
32
+ details;
33
+ docs;
34
+ constructor(status, code, message, details, docs) {
35
+ super(message);
36
+ this.status = status;
37
+ this.code = code;
38
+ this.details = details;
39
+ this.docs = docs;
40
+ this.name = 'ApiError';
41
+ }
42
+ }
43
+ exports.ApiError = ApiError;
44
+ const sleeper = (ms) => new Promise((r) => setTimeout(r, ms));
45
+ const MAX_WAIT_MS = 60_000;
46
+ /** `Retry-After` as milliseconds: delta-seconds or an HTTP date; undefined when absent or unreadable. */
47
+ function retryAfterMs(value, now = Date.now()) {
48
+ if (!value)
49
+ return undefined;
50
+ const secs = Number(value);
51
+ if (Number.isFinite(secs) && secs >= 0)
52
+ return Math.min(secs * 1000, MAX_WAIT_MS);
53
+ const at = Date.parse(value);
54
+ if (Number.isNaN(at))
55
+ return undefined;
56
+ return Math.min(Math.max(at - now, 0), MAX_WAIT_MS);
57
+ }
58
+ class Http {
59
+ opts;
60
+ fetchImpl;
61
+ constructor(opts) {
62
+ this.opts = opts;
63
+ this.fetchImpl = opts.fetch ?? globalThis.fetch;
64
+ }
65
+ get baseUrl() {
66
+ return this.opts.baseUrl.replace(/\/+$/, '');
67
+ }
68
+ url(path, query = {}) {
69
+ const url = new URL(this.baseUrl + (path.startsWith('/') ? path : `/${path}`));
70
+ for (const [k, v] of Object.entries(query))
71
+ if (v !== undefined)
72
+ url.searchParams.set(k, v);
73
+ return url.toString();
74
+ }
75
+ headersFor(req) {
76
+ const h = {
77
+ Accept: req.raw ? '*/*' : 'application/json',
78
+ 'User-Agent': this.opts.userAgent,
79
+ 'Forumulate-Version': this.opts.apiVersion ?? exports.DEFAULT_API_VERSION,
80
+ };
81
+ if (this.opts.token)
82
+ h.Authorization = `Bearer ${this.opts.token}`;
83
+ if (req.body !== undefined && !req.form)
84
+ h['Content-Type'] = 'application/json';
85
+ Object.assign(h, req.headers ?? {});
86
+ const hasKey = Object.keys(h).some((k) => k.toLowerCase() === 'idempotency-key');
87
+ if (req.idempotent && !hasKey)
88
+ h['Idempotency-Key'] = (0, node_crypto_1.randomUUID)();
89
+ return h;
90
+ }
91
+ async send(req) {
92
+ const method = req.method.toUpperCase();
93
+ const url = this.url(req.path, req.query);
94
+ // Fixed once, outside the loop: the retry must carry the SAME key.
95
+ const headers = this.headersFor(req);
96
+ const repeatable = method === 'GET' ||
97
+ method === 'PUT' ||
98
+ method === 'DELETE' ||
99
+ Object.keys(headers).some((k) => k.toLowerCase() === 'idempotency-key');
100
+ const retries = this.opts.retries ?? 3;
101
+ const sleep = this.opts.sleep ?? sleeper;
102
+ for (let attempt = 0;; attempt++) {
103
+ let res;
104
+ try {
105
+ res = await this.fetchImpl(url, {
106
+ method,
107
+ headers,
108
+ body: req.form ?? (req.body !== undefined ? JSON.stringify(req.body) : undefined),
109
+ });
110
+ }
111
+ catch (e) {
112
+ if (repeatable && attempt < retries) {
113
+ const waitMs = 1000 * 2 ** attempt;
114
+ this.opts.onRetry?.({ attempt: attempt + 1, waitMs });
115
+ await sleep(waitMs);
116
+ continue;
117
+ }
118
+ const cause = e.cause?.code;
119
+ throw new ApiError(0, 'network', `Could not reach ${this.baseUrl}${cause ? ` (${cause})` : ''}: ${e.message}`);
120
+ }
121
+ const transient = res.status === 502 || res.status === 503 || res.status === 504;
122
+ if ((res.status === 429 || (transient && repeatable)) && attempt < retries) {
123
+ const waitMs = retryAfterMs(res.headers.get('retry-after')) ?? 1000 * 2 ** attempt;
124
+ this.opts.onRetry?.({ attempt: attempt + 1, waitMs, status: res.status });
125
+ await res.arrayBuffer().catch(() => undefined);
126
+ await sleep(waitMs);
127
+ continue;
128
+ }
129
+ if (req.raw && res.ok)
130
+ return {
131
+ status: res.status,
132
+ headers: res.headers,
133
+ data: Buffer.from(await res.arrayBuffer()),
134
+ };
135
+ const data = await readBody(res);
136
+ if (!res.ok)
137
+ throw toError(res, data);
138
+ return { status: res.status, headers: res.headers, data };
139
+ }
140
+ }
141
+ }
142
+ exports.Http = Http;
143
+ async function readBody(res) {
144
+ const text = await res.text();
145
+ if (!text)
146
+ return undefined;
147
+ const type = res.headers.get('content-type') ?? '';
148
+ if (type.includes('json') || /^[[{]/.test(text.trimStart())) {
149
+ try {
150
+ return JSON.parse(text);
151
+ }
152
+ catch {
153
+ return text;
154
+ }
155
+ }
156
+ return text;
157
+ }
158
+ function toError(res, data) {
159
+ const env = data?.error;
160
+ if (env && typeof env === 'object') {
161
+ return new ApiError(res.status, env.code ?? 'error', env.message ?? res.statusText, env.details, env.docs);
162
+ }
163
+ // Not our envelope: the edge, a proxy, or a crash page. Say which, briefly.
164
+ const text = typeof data === 'string' ? data : '';
165
+ const edge = /cloudflare|error code:? 10\d\d/i.test(text);
166
+ const message = edge
167
+ ? `${res.statusText || 'Refused'} by the edge in front of the API, not by the API (a Cloudflare block page)`
168
+ : `${res.statusText || 'HTTP error'}${text ? `: ${text.replace(/\s+/g, ' ').slice(0, 200)}` : ''}`;
169
+ return new ApiError(res.status, edge ? 'edge.blocked' : 'error', message);
170
+ }
171
+ /** The CLI's one error line, plus the field problems a 422 names. */
172
+ function formatError(e) {
173
+ const err = e;
174
+ const lines = [
175
+ `Error${err.status ? ` ${err.status}` : ''}${err.code ? ` (${err.code})` : ''}: ${err.message ?? String(e)}`,
176
+ ];
177
+ for (const [field, problems] of Object.entries(err.details ?? {}))
178
+ lines.push(` ${field}: ${(problems ?? []).join('; ')}`);
179
+ if (err.docs)
180
+ lines.push(` see: ${err.docs}`);
181
+ return lines;
182
+ }
183
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/api/http.ts"],"names":[],"mappings":"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"}