@37signals/basecamp 0.13.0 → 0.15.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 (71) hide show
  1. package/README.md +4 -3
  2. package/dist/client.d.ts +2 -2
  3. package/dist/client.js +2 -2
  4. package/dist/download.d.ts +3 -1
  5. package/dist/download.d.ts.map +1 -1
  6. package/dist/download.js +17 -4
  7. package/dist/download.js.map +1 -1
  8. package/dist/errors.d.ts +27 -1
  9. package/dist/errors.d.ts.map +1 -1
  10. package/dist/errors.js +89 -13
  11. package/dist/errors.js.map +1 -1
  12. package/dist/generated/metadata.d.ts.map +1 -1
  13. package/dist/generated/metadata.js +12 -1
  14. package/dist/generated/metadata.js.map +1 -1
  15. package/dist/generated/metadata.ts +12 -1
  16. package/dist/generated/openapi-stripped.json +559 -30
  17. package/dist/generated/path-mapping.d.ts.map +1 -1
  18. package/dist/generated/path-mapping.js +1 -0
  19. package/dist/generated/path-mapping.js.map +1 -1
  20. package/dist/generated/path-mapping.ts +1 -0
  21. package/dist/generated/schema.d.ts +468 -29
  22. package/dist/generated/services/checkins.d.ts +1 -1
  23. package/dist/generated/services/checkins.d.ts.map +1 -1
  24. package/dist/generated/services/checkins.ts +1 -1
  25. package/dist/generated/services/gauges.d.ts +3 -2
  26. package/dist/generated/services/gauges.d.ts.map +1 -1
  27. package/dist/generated/services/gauges.ts +2 -2
  28. package/dist/generated/services/search.d.ts +2 -1
  29. package/dist/generated/services/search.d.ts.map +1 -1
  30. package/dist/generated/services/search.ts +1 -1
  31. package/dist/generated/services/uploads.d.ts +36 -2
  32. package/dist/generated/services/uploads.d.ts.map +1 -1
  33. package/dist/generated/services/uploads.js +37 -1
  34. package/dist/generated/services/uploads.js.map +1 -1
  35. package/dist/generated/services/uploads.ts +65 -2
  36. package/dist/index.d.ts +1 -1
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js.map +1 -1
  39. package/dist/oauth/authorization-document.d.ts +208 -0
  40. package/dist/oauth/authorization-document.d.ts.map +1 -0
  41. package/dist/oauth/authorization-document.js +135 -0
  42. package/dist/oauth/authorization-document.js.map +1 -0
  43. package/dist/oauth/identity.d.ts +7 -1
  44. package/dist/oauth/identity.d.ts.map +1 -1
  45. package/dist/oauth/identity.js +8 -19
  46. package/dist/oauth/identity.js.map +1 -1
  47. package/dist/oauth/index.d.ts +1 -0
  48. package/dist/oauth/index.d.ts.map +1 -1
  49. package/dist/oauth/index.js +2 -0
  50. package/dist/oauth/index.js.map +1 -1
  51. package/dist/retry.d.ts +23 -0
  52. package/dist/retry.d.ts.map +1 -1
  53. package/dist/retry.js +45 -10
  54. package/dist/retry.js.map +1 -1
  55. package/dist/services/authorization.d.ts +22 -52
  56. package/dist/services/authorization.d.ts.map +1 -1
  57. package/dist/services/authorization.js +14 -32
  58. package/dist/services/authorization.js.map +1 -1
  59. package/dist/services/base.d.ts +25 -2
  60. package/dist/services/base.d.ts.map +1 -1
  61. package/dist/services/base.js +85 -15
  62. package/dist/services/base.js.map +1 -1
  63. package/package.json +6 -4
  64. package/src/generated/metadata.ts +12 -1
  65. package/src/generated/openapi-stripped.json +559 -30
  66. package/src/generated/path-mapping.ts +1 -0
  67. package/src/generated/schema.d.ts +468 -29
  68. package/src/generated/services/checkins.ts +1 -1
  69. package/src/generated/services/gauges.ts +2 -2
  70. package/src/generated/services/search.ts +1 -1
  71. package/src/generated/services/uploads.ts +65 -2
@@ -0,0 +1,135 @@
1
+ /**
2
+ * The authorization document, as served by both issuers.
3
+ *
4
+ * Two different services fetch this document — {@link ../services/authorization.js | AuthorizationService}
5
+ * and {@link ./identity.js | discoverIdentity} — and they used to carry a copy of
6
+ * the mapping each. The copies had already drifted apart (`app_href` was required
7
+ * in one and optional in the other), which is exactly how a shape fix gets applied
8
+ * to one caller and missed on the other. The mapping lives here once.
9
+ *
10
+ * This module is a leaf on purpose: it imports nothing from the SDK, so either
11
+ * caller can take a *value* dependency on it without adding a runtime edge to the
12
+ * `base.ts` / `client.ts` cycle.
13
+ *
14
+ * ## Two issuers, two shapes
15
+ *
16
+ * Launchpad and a BC5 (bc3) issuer both serve `GET /authorization.json`, and the
17
+ * documents are not the same shape. bc3 renders its own from
18
+ * `app/views/api/authorizations/show.json.jbuilder`:
19
+ *
20
+ * | Field | Launchpad | BC5 |
21
+ * |---|---|---|
22
+ * | `identity.first_name` / `last_name` / `email_address` | present | absent |
23
+ * | `accounts[].product` / `app_href` | present | absent |
24
+ * | `accounts[].resource` | absent | present (RFC 8707 indicator) |
25
+ * | `scope` | absent | present, BC3-issued tokens only |
26
+ * | `expires_at` | ISO-8601 string | ISO-8601 string (integer epoch **seconds** before bc3 #12646; still accepted) |
27
+ *
28
+ * Every field either issuer omits is typed optional here. The union is modelled
29
+ * rather than either shape alone, because a consumer reaches a BC5 issuer just by
30
+ * passing `endpoint:`, and BC5 issuers serving their own document is the intended
31
+ * end state.
32
+ *
33
+ * @see spec/api-gaps/bc5-authorization-document-shape.md
34
+ */
35
+ /**
36
+ * Parses `expires_at` from any spelling either issuer has ever used.
37
+ *
38
+ * Both issuers send an ISO-8601 string today; bc3 sent `@token.expires_at.to_i`
39
+ * — integer epoch **seconds** — before bc3 #12646 converged it, and the integer
40
+ * spelling stays accepted (recorded documents, older deploys). The `typeof`
41
+ * branch matters because `new Date(2085213356)` treats the number as
42
+ * *milliseconds* and yields a date in 1970 — a wrong answer rather than an
43
+ * exception, which then reads as an expired credential rather than a schema
44
+ * mismatch.
45
+ *
46
+ * A `0`, a `null` and an absent field are all "no expiry known" and produce an
47
+ * Invalid Date, which is what a `Date`-typed field can say about absence. No
48
+ * production issuer emits any of the three — bc3 tokens validate presence and
49
+ * are always set at mint — so the `0` handling is defensive, guarding the
50
+ * RFC 7591 collision where `0` means "never expires".
51
+ */
52
+ export function parseExpiresAt(value) {
53
+ if (typeof value === "number") {
54
+ // Epoch seconds, not milliseconds. `0` is the defensive no-expiry sentinel
55
+ // (RFC 7591 gives 0 the meaning "never expires"); no issuer emits it.
56
+ return value === 0 ? new Date(NaN) : new Date(value * 1000);
57
+ }
58
+ if (typeof value === "string" && value !== "") {
59
+ return new Date(value);
60
+ }
61
+ return new Date(NaN);
62
+ }
63
+ /**
64
+ * Filters accounts by product, or reports that it could not.
65
+ *
66
+ * A BC5 document carries no `product` on any account, so filtering it by product
67
+ * matches nothing. Returning `[]` there is silently wrong — the accounts exist,
68
+ * and the caller's next step is to pick a `href` out of a list the SDK just
69
+ * emptied. Instead: when *no* account in the document carries a `product`, the
70
+ * filter is inapplicable, and all accounts are returned with `applied: false` so
71
+ * a caller that cares can tell the two situations apart.
72
+ *
73
+ * When at least one account carries a `product`, the filter is meaningful and is
74
+ * applied normally — an empty result then genuinely means "no account matched".
75
+ *
76
+ * An **empty** account list is the edge that needs saying out loud. "No account
77
+ * carries a `product`" is vacuously true of `[]`, which would report the filter
78
+ * inapplicable — but Launchpad returns `accounts: []` for an identity with no
79
+ * currently accessible accounts, and that document is perfectly filterable. The
80
+ * result is the same list either way, so nothing observable changes; what changes
81
+ * is the claim the flag makes, and `applied: false` would assert "this issuer
82
+ * cannot filter by product" on no evidence at all. An empty list carries no
83
+ * evidence about the issuer, so treat the filter as applied: filtering nothing by
84
+ * anything yields nothing, which is exactly what happened.
85
+ */
86
+ export function filterAccountsByProduct(accounts, product) {
87
+ const filterable = accounts.length === 0 || accounts.some((a) => a.product !== undefined);
88
+ if (!filterable) {
89
+ return { accounts, applied: false };
90
+ }
91
+ return { accounts: accounts.filter((a) => a.product === product), applied: true };
92
+ }
93
+ /**
94
+ * Maps a raw authorization document to {@link AuthorizationInfo}.
95
+ *
96
+ * Optionally applies a product filter; see {@link filterAccountsByProduct} for
97
+ * what happens when the document cannot be filtered by product.
98
+ */
99
+ export function parseAuthorizationDocument(raw, options = {}) {
100
+ let accounts = raw.accounts.map((a) => ({
101
+ id: a.id,
102
+ name: a.name,
103
+ product: a.product,
104
+ href: a.href,
105
+ appHref: a.app_href,
106
+ resource: a.resource,
107
+ hidden: a.hidden,
108
+ expired: a.expired,
109
+ featured: a.featured,
110
+ }));
111
+ let productFilterApplied;
112
+ if (options.filterProduct !== undefined && options.filterProduct !== "") {
113
+ const filtered = filterAccountsByProduct(accounts, options.filterProduct);
114
+ accounts = filtered.accounts;
115
+ productFilterApplied = filtered.applied;
116
+ }
117
+ const info = {
118
+ expiresAt: parseExpiresAt(raw.expires_at),
119
+ identity: {
120
+ id: raw.identity.id,
121
+ firstName: raw.identity.first_name,
122
+ lastName: raw.identity.last_name,
123
+ emailAddress: raw.identity.email_address,
124
+ },
125
+ accounts,
126
+ };
127
+ if (raw.scope !== undefined) {
128
+ info.scope = raw.scope;
129
+ }
130
+ if (productFilterApplied !== undefined) {
131
+ info.productFilterApplied = productFilterApplied;
132
+ }
133
+ return info;
134
+ }
135
+ //# sourceMappingURL=authorization-document.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorization-document.js","sourceRoot":"","sources":["../../src/oauth/authorization-document.ts"],"names":[],"mappings":"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"}
@@ -3,9 +3,15 @@
3
3
  *
4
4
  * Fetches authorization information (identity and accounts) from
5
5
  * the Launchpad endpoint without requiring a full client instance.
6
+ *
7
+ * The endpoint is fixed to Launchpad here — unlike
8
+ * {@link ../services/authorization.js | AuthorizationService.getInfo}, which
9
+ * accepts an `endpoint:` override and so can be pointed at a BC5 issuer. Both
10
+ * share one mapping regardless; see `./authorization-document.js` for why the two
11
+ * documents differ and how the shared parser reconciles them.
6
12
  */
7
13
  import type { TokenProvider } from "../client.js";
8
- import type { AuthorizationInfo } from "../services/authorization.js";
14
+ import { type AuthorizationInfo } from "./authorization-document.js";
9
15
  /**
10
16
  * Fetches authorization information using an access token.
11
17
  *
@@ -1 +1 @@
1
- {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/oauth/identity.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AA2BtE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,gBAAgB,CAAC,WAAW,EAAE,aAAa,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAsD7F"}
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/oauth/identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAEL,KAAK,iBAAiB,EAEvB,MAAM,6BAA6B,CAAC;AAIrC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,gBAAgB,CAAC,WAAW,EAAE,aAAa,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAoC7F"}
@@ -3,8 +3,15 @@
3
3
  *
4
4
  * Fetches authorization information (identity and accounts) from
5
5
  * the Launchpad endpoint without requiring a full client instance.
6
+ *
7
+ * The endpoint is fixed to Launchpad here — unlike
8
+ * {@link ../services/authorization.js | AuthorizationService.getInfo}, which
9
+ * accepts an `endpoint:` override and so can be pointed at a BC5 issuer. Both
10
+ * share one mapping regardless; see `./authorization-document.js` for why the two
11
+ * documents differ and how the shared parser reconciles them.
6
12
  */
7
13
  import { BasecampError } from "../errors.js";
14
+ import { parseAuthorizationDocument, } from "./authorization-document.js";
8
15
  const AUTHORIZATION_ENDPOINT = "https://launchpad.37signals.com/authorization.json";
9
16
  /**
10
17
  * Fetches authorization information using an access token.
@@ -59,24 +66,6 @@ export async function discoverIdentity(accessToken) {
59
66
  catch {
60
67
  throw new BasecampError("api_error", "Identity discovery returned invalid JSON");
61
68
  }
62
- return {
63
- expiresAt: new Date(raw.expires_at),
64
- identity: {
65
- id: raw.identity.id,
66
- firstName: raw.identity.first_name,
67
- lastName: raw.identity.last_name,
68
- emailAddress: raw.identity.email_address,
69
- },
70
- accounts: raw.accounts.map((a) => ({
71
- id: a.id,
72
- name: a.name,
73
- product: a.product,
74
- href: a.href,
75
- appHref: a.app_href ?? "",
76
- hidden: a.hidden,
77
- expired: a.expired,
78
- featured: a.featured,
79
- })),
80
- };
69
+ return parseAuthorizationDocument(raw);
81
70
  }
82
71
  //# sourceMappingURL=identity.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/oauth/identity.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AA2B7C,MAAM,sBAAsB,GAAG,oDAAoD,CAAC;AAEpF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,WAA0B;IAC/D,MAAM,KAAK,GAAG,OAAO,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,WAAW,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;IAEpF,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,KAAK,CAAC,sBAAsB,EAAE;YAC7C,MAAM,EAAE,KAAK;YACb,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,KAAK,EAAE;gBAChC,MAAM,EAAE,kBAAkB;aAC3B;SACF,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,aAAa,CAAC,SAAS,EAAE,8BAA8B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACvH,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,MAAM,IAAI,aAAa,CAAC,eAAe,EAAE,iCAAiC,EAAE;gBAC1E,UAAU,EAAE,GAAG;gBACf,IAAI,EAAE,2CAA2C;aAClD,CAAC,CAAC;QACL,CAAC;QACD,MAAM,IAAI,aAAa,CAAC,WAAW,EAAE,mCAAmC,QAAQ,CAAC,MAAM,EAAE,EAAE;YACzF,UAAU,EAAE,QAAQ,CAAC,MAAM;SAC5B,CAAC,CAAC;IACL,CAAC;IAED,IAAI,GAA6B,CAAC;IAClC,IAAI,CAAC;QACH,GAAG,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAA6B,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,aAAa,CAAC,WAAW,EAAE,0CAA0C,CAAC,CAAC;IACnF,CAAC;IAED,OAAO;QACL,SAAS,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC;QACnC,QAAQ,EAAE;YACR,EAAE,EAAE,GAAG,CAAC,QAAQ,CAAC,EAAE;YACnB,SAAS,EAAE,GAAG,CAAC,QAAQ,CAAC,UAAU;YAClC,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,SAAS;YAChC,YAAY,EAAE,GAAG,CAAC,QAAQ,CAAC,aAAa;SACzC;QACD,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACjC,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,OAAO,EAAE,CAAC,CAAC,QAAQ,IAAI,EAAE;YACzB,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,QAAQ,EAAE,CAAC,CAAC,QAAQ;SACrB,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/oauth/identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,EACL,0BAA0B,GAG3B,MAAM,6BAA6B,CAAC;AAErC,MAAM,sBAAsB,GAAG,oDAAoD,CAAC;AAEpF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,WAA0B;IAC/D,MAAM,KAAK,GAAG,OAAO,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,WAAW,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;IAEpF,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,KAAK,CAAC,sBAAsB,EAAE;YAC7C,MAAM,EAAE,KAAK;YACb,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,KAAK,EAAE;gBAChC,MAAM,EAAE,kBAAkB;aAC3B;SACF,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,aAAa,CAAC,SAAS,EAAE,8BAA8B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACvH,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,MAAM,IAAI,aAAa,CAAC,eAAe,EAAE,iCAAiC,EAAE;gBAC1E,UAAU,EAAE,GAAG;gBACf,IAAI,EAAE,2CAA2C;aAClD,CAAC,CAAC;QACL,CAAC;QACD,MAAM,IAAI,aAAa,CAAC,WAAW,EAAE,mCAAmC,QAAQ,CAAC,MAAM,EAAE,EAAE;YACzF,UAAU,EAAE,QAAQ,CAAC,MAAM;SAC5B,CAAC,CAAC;IACL,CAAC;IAED,IAAI,GAA6B,CAAC;IAClC,IAAI,CAAC;QACH,GAAG,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAA6B,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,aAAa,CAAC,WAAW,EAAE,0CAA0C,CAAC,CAAC;IACnF,CAAC;IAED,OAAO,0BAA0B,CAAC,GAAG,CAAC,CAAC;AACzC,CAAC"}
@@ -50,4 +50,5 @@ export { TokenManager, type TokenManagerOptions, } from "./token-manager.js";
50
50
  export { startCallbackServer, type CallbackResult, type CallbackServerOptions, } from "./callback-server.js";
51
51
  export { performInteractiveLogin, type InteractiveLoginOptions, } from "./interactive-login.js";
52
52
  export { discoverIdentity, } from "./identity.js";
53
+ export { parseAuthorizationDocument, parseExpiresAt, filterAccountsByProduct, type RawAuthorizationDocument, } from "./authorization-document.js";
53
54
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/oauth/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAGH,YAAY,EACV,WAAW,EACX,UAAU,EACV,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,yBAAyB,EACzB,cAAc,EACd,6BAA6B,EAC7B,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,0BAA0B,EAC1B,eAAe,EACf,sBAAsB,EACtB,KAAK,gCAAgC,EACrC,KAAK,qBAAqB,EAC1B,KAAK,cAAc,GACpB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,kBAAkB,EAClB,KAAK,kBAAkB,GACxB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,eAAe,EACf,KAAK,gBAAgB,GACtB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,QAAQ,EACR,yBAAyB,EACzB,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EACjB,uBAAuB,EACvB,kBAAkB,EAClB,KAAK,eAAe,EACpB,KAAK,2BAA2B,GACjC,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,KAAK,YAAY,GAClB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,YAAY,EACZ,aAAa,EACb,KAAK,IAAI,GACV,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,qBAAqB,EACrB,KAAK,eAAe,GACrB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,cAAc,EACd,KAAK,UAAU,GAChB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,YAAY,EACZ,KAAK,mBAAmB,GACzB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,mBAAmB,EACnB,KAAK,cAAc,EACnB,KAAK,qBAAqB,GAC3B,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,uBAAuB,EACvB,KAAK,uBAAuB,GAC7B,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EACL,gBAAgB,GACjB,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/oauth/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAGH,YAAY,EACV,WAAW,EACX,UAAU,EACV,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,yBAAyB,EACzB,cAAc,EACd,6BAA6B,EAC7B,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,0BAA0B,EAC1B,eAAe,EACf,sBAAsB,EACtB,KAAK,gCAAgC,EACrC,KAAK,qBAAqB,EAC1B,KAAK,cAAc,GACpB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,kBAAkB,EAClB,KAAK,kBAAkB,GACxB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,eAAe,EACf,KAAK,gBAAgB,GACtB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,QAAQ,EACR,yBAAyB,EACzB,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EACjB,uBAAuB,EACvB,kBAAkB,EAClB,KAAK,eAAe,EACpB,KAAK,2BAA2B,GACjC,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,KAAK,YAAY,GAClB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,YAAY,EACZ,aAAa,EACb,KAAK,IAAI,GACV,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,qBAAqB,EACrB,KAAK,eAAe,GACrB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,cAAc,EACd,KAAK,UAAU,GAChB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,YAAY,EACZ,KAAK,mBAAmB,GACzB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,mBAAmB,EACnB,KAAK,cAAc,EACnB,KAAK,qBAAqB,GAC3B,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,uBAAuB,EACvB,KAAK,uBAAuB,GAC7B,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EACL,gBAAgB,GACjB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,0BAA0B,EAC1B,cAAc,EACd,uBAAuB,EACvB,KAAK,wBAAwB,GAC9B,MAAM,6BAA6B,CAAC"}
@@ -59,4 +59,6 @@ export { startCallbackServer, } from "./callback-server.js";
59
59
  export { performInteractiveLogin, } from "./interactive-login.js";
60
60
  // Identity
61
61
  export { discoverIdentity, } from "./identity.js";
62
+ // The authorization document, shared by discoverIdentity and AuthorizationService
63
+ export { parseAuthorizationDocument, parseExpiresAt, filterAccountsByProduct, } from "./authorization-document.js";
62
64
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/oauth/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAiBH,yBAAyB;AACzB,OAAO,EACL,0BAA0B,EAC1B,eAAe,EACf,sBAAsB,GAIvB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,kBAAkB,GAEnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,eAAe,GAEhB,MAAM,oBAAoB,CAAC;AAE5B,YAAY;AACZ,OAAO,EACL,QAAQ,EACR,yBAAyB,EACzB,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EACjB,uBAAuB,EACvB,kBAAkB,GAGnB,MAAM,gBAAgB,CAAC;AAExB,iBAAiB;AACjB,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,cAAc,GAEf,MAAM,eAAe,CAAC;AAEvB,iBAAiB;AACjB,OAAO,EACL,YAAY,EACZ,aAAa,GAEd,MAAM,WAAW,CAAC;AAEnB,oBAAoB;AACpB,OAAO,EACL,qBAAqB,GAEtB,MAAM,gBAAgB,CAAC;AAExB,cAAc;AACd,OAAO,EACL,cAAc,GAEf,MAAM,kBAAkB,CAAC;AAE1B,gBAAgB;AAChB,OAAO,EACL,YAAY,GAEb,MAAM,oBAAoB,CAAC;AAE5B,kBAAkB;AAClB,OAAO,EACL,mBAAmB,GAGpB,MAAM,sBAAsB,CAAC;AAE9B,oBAAoB;AACpB,OAAO,EACL,uBAAuB,GAExB,MAAM,wBAAwB,CAAC;AAEhC,WAAW;AACX,OAAO,EACL,gBAAgB,GACjB,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/oauth/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAiBH,yBAAyB;AACzB,OAAO,EACL,0BAA0B,EAC1B,eAAe,EACf,sBAAsB,GAIvB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,kBAAkB,GAEnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,eAAe,GAEhB,MAAM,oBAAoB,CAAC;AAE5B,YAAY;AACZ,OAAO,EACL,QAAQ,EACR,yBAAyB,EACzB,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EACjB,uBAAuB,EACvB,kBAAkB,GAGnB,MAAM,gBAAgB,CAAC;AAExB,iBAAiB;AACjB,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,cAAc,GAEf,MAAM,eAAe,CAAC;AAEvB,iBAAiB;AACjB,OAAO,EACL,YAAY,EACZ,aAAa,GAEd,MAAM,WAAW,CAAC;AAEnB,oBAAoB;AACpB,OAAO,EACL,qBAAqB,GAEtB,MAAM,gBAAgB,CAAC;AAExB,cAAc;AACd,OAAO,EACL,cAAc,GAEf,MAAM,kBAAkB,CAAC;AAE1B,gBAAgB;AAChB,OAAO,EACL,YAAY,GAEb,MAAM,oBAAoB,CAAC;AAE5B,kBAAkB;AAClB,OAAO,EACL,mBAAmB,GAGpB,MAAM,sBAAsB,CAAC;AAE9B,oBAAoB;AACpB,OAAO,EACL,uBAAuB,GAExB,MAAM,wBAAwB,CAAC;AAEhC,WAAW;AACX,OAAO,EACL,gBAAgB,GACjB,MAAM,eAAe,CAAC;AAEvB,kFAAkF;AAClF,OAAO,EACL,0BAA0B,EAC1B,cAAc,EACd,uBAAuB,GAExB,MAAM,6BAA6B,CAAC"}
package/dist/retry.d.ts CHANGED
@@ -25,6 +25,29 @@ export declare const NO_RETRY_CONFIG: RetryConfig;
25
25
  * `MAX_JITTER_MS`.
26
26
  */
27
27
  export declare const MAX_BACKOFF_DELAY_MS = 30000;
28
+ /**
29
+ * Converts server-directed `Retry-After` seconds into a delay a timer will
30
+ * actually serve.
31
+ *
32
+ * `Retry-After` is exempt from the backoff ceiling above (SPEC §7) — it is the
33
+ * server's instruction, not our computation — but it is not exempt from the
34
+ * platform. Above the 32-bit bound `setTimeout` does not sleep longer, it
35
+ * sleeps 1ms, so an unclamped `Retry-After: 2147484` (a hair over 24.85 days)
36
+ * or any HTTP-date more than that far out becomes a tight retry loop against a
37
+ * server that asked for a month — the exact failure the ceiling exists to
38
+ * prevent, arriving through the one value exempt from it.
39
+ *
40
+ * Clamping rather than falling back to backoff follows `oauth/device.ts`:
41
+ * waiting the longest the platform can schedule honours the throttle, where a
42
+ * ~1s backoff would defeat it.
43
+ *
44
+ * This lives HERE, at the scheduling boundary, and not in the parser. The
45
+ * parser's result is also the public `BasecampError.retryAfter`, and clamping
46
+ * there reported a server's 3000000 to callers as 2147483 — the SDK
47
+ * understating what it was told. Parsing and scheduling are different questions
48
+ * and only one of them has a timer.
49
+ */
50
+ export declare function timerSafeDelayMs(retryAfterSeconds: number): number;
28
51
  /**
29
52
  * Lifecycle seams the retry loop emits through. The loop begins EVERY attempt
30
53
  * and finalizes the attempts it abandons (before the backoff sleep); the
@@ -1 +1 @@
1
- {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,aAAa,GAAG,QAAQ,GAAG,UAAU,CAAC;IAC/C,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,+EAA+E;AAC/E,eAAO,MAAM,oBAAoB,EAAE,WAKlC,CAAC;AAEF,yDAAyD;AACzD,eAAO,MAAM,eAAe,EAAE,WAK7B,CAAC;AAIF;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,QAAS,CAAC;AAE3C;;;;;;;GAOG;AACH,MAAM,WAAW,SAAS;IACxB,qEAAqE;IACrE,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,6EAA6E;IAC7E,QAAQ,CAAC,OAAO,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,KAAK,CAAA;KAAE,GAAG,IAAI,CAAC;IAC/D,kFAAkF;IAClF,QAAQ,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACtE;AAED;;;;;GAKG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAC/B,QAAQ,CAAC,MAAM,EAAE,OAAO;gBAAf,MAAM,EAAE,OAAO;CAIrC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,EACnD,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,SAAS,EACf,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,GAC1B,OAAO,CAAC,QAAQ,CAAC,CAqFnB;AAwCD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,EAC/B,OAAO,EAAE,MAAM,GACd,MAAM,CAyBR;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAMlF;AAED;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBrE"}
1
+ {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,aAAa,GAAG,QAAQ,GAAG,UAAU,CAAC;IAC/C,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,+EAA+E;AAC/E,eAAO,MAAM,oBAAoB,EAAE,WAKlC,CAAC;AAEF,yDAAyD;AACzD,eAAO,MAAM,eAAe,EAAE,WAK7B,CAAC;AAIF;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,QAAS,CAAC;AAU3C;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,gBAAgB,CAAC,iBAAiB,EAAE,MAAM,GAAG,MAAM,CAElE;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,SAAS;IACxB,qEAAqE;IACrE,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,6EAA6E;IAC7E,QAAQ,CAAC,OAAO,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,KAAK,CAAA;KAAE,GAAG,IAAI,CAAC;IAC/D,kFAAkF;IAClF,QAAQ,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACtE;AAED;;;;;GAKG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAC/B,QAAQ,CAAC,MAAM,EAAE,OAAO;gBAAf,MAAM,EAAE,OAAO;CAIrC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,EACnD,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,SAAS,EACf,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,GAC1B,OAAO,CAAC,QAAQ,CAAC,CAwFnB;AAwCD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,EAC/B,OAAO,EAAE,MAAM,GACd,MAAM,CAyBR;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAMlF;AAED;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBrE"}
package/dist/retry.js CHANGED
@@ -6,6 +6,8 @@
6
6
  * preparation (auth, request construction) via `makeAttempt` and hook
7
7
  * emission via `RetryEmit`.
8
8
  */
9
+ // errors.ts imports nothing, so this edge introduces no cycle.
10
+ import { parseRetryAfter } from "./errors.js";
9
11
  /** Default retry config used when no operation-specific config is available */
10
12
  export const DEFAULT_RETRY_CONFIG = {
11
13
  maxAttempts: 3,
@@ -27,6 +29,38 @@ const MAX_JITTER_MS = 100;
27
29
  * `MAX_JITTER_MS`.
28
30
  */
29
31
  export const MAX_BACKOFF_DELAY_MS = 30_000;
32
+ /**
33
+ * Largest delay `setTimeout` schedules faithfully: Node's timers are backed by
34
+ * a signed 32-bit int, and anything above this is CLAMPED TO 1ms rather than
35
+ * honoured. `client.ts` states the same bound for `AbortSignal.timeout` and
36
+ * `oauth/device.ts` states it in seconds.
37
+ */
38
+ const MAX_TIMEOUT_MS = 2_147_483_647;
39
+ /**
40
+ * Converts server-directed `Retry-After` seconds into a delay a timer will
41
+ * actually serve.
42
+ *
43
+ * `Retry-After` is exempt from the backoff ceiling above (SPEC §7) — it is the
44
+ * server's instruction, not our computation — but it is not exempt from the
45
+ * platform. Above the 32-bit bound `setTimeout` does not sleep longer, it
46
+ * sleeps 1ms, so an unclamped `Retry-After: 2147484` (a hair over 24.85 days)
47
+ * or any HTTP-date more than that far out becomes a tight retry loop against a
48
+ * server that asked for a month — the exact failure the ceiling exists to
49
+ * prevent, arriving through the one value exempt from it.
50
+ *
51
+ * Clamping rather than falling back to backoff follows `oauth/device.ts`:
52
+ * waiting the longest the platform can schedule honours the throttle, where a
53
+ * ~1s backoff would defeat it.
54
+ *
55
+ * This lives HERE, at the scheduling boundary, and not in the parser. The
56
+ * parser's result is also the public `BasecampError.retryAfter`, and clamping
57
+ * there reported a server's 3000000 to callers as 2147483 — the SDK
58
+ * understating what it was told. Parsing and scheduling are different questions
59
+ * and only one of them has a timer.
60
+ */
61
+ export function timerSafeDelayMs(retryAfterSeconds) {
62
+ return Math.min(retryAfterSeconds * 1000, MAX_TIMEOUT_MS);
63
+ }
30
64
  /**
31
65
  * Marks an error thrown during attempt PREPARATION (e.g. a retry's auth
32
66
  * refresh) rather than by the transport. The retry loop rethrows it as-is —
@@ -98,16 +132,17 @@ export async function executeWithRetry(makeAttempt, config, emit, signal) {
98
132
  if (!config.retryOn.includes(response.status) || attempt >= config.maxAttempts) {
99
133
  return response;
100
134
  }
101
- // For 429, respect Retry-After; otherwise back off.
102
- let delay;
103
- const retryAfter = response.status === 429 ? response.headers.get("Retry-After") : null;
104
- const retryAfterSeconds = retryAfter ? parseInt(retryAfter, 10) : NaN;
105
- if (!isNaN(retryAfterSeconds)) {
106
- delay = retryAfterSeconds * 1000;
107
- }
108
- else {
109
- delay = calculateBackoffDelay(config, attempt - 1);
110
- }
135
+ // For 429, respect Retry-After; otherwise back off. The header goes through
136
+ // errors.ts's parseRetryAfter — the single SPEC §6 implementation — rather
137
+ // than a local parseInt: 0, a negative value and an unparseable one all
138
+ // come back undefined and fall through to backoff, where the local copy
139
+ // this replaced turned them into a zero or negative sleep.
140
+ const retryAfterSeconds = response.status === 429
141
+ ? parseRetryAfter(response.headers.get("Retry-After"))
142
+ : undefined;
143
+ const delay = retryAfterSeconds !== undefined
144
+ ? timerSafeDelayMs(retryAfterSeconds)
145
+ : calculateBackoffDelay(config, attempt - 1);
111
146
  const statusError = new Error(`HTTP ${response.status}: ${response.statusText || "Request failed"}`);
112
147
  // End the failed attempt before sleeping, so a slow backoff cannot leave
113
148
  // an attempt open, then announce the upcoming one.
package/dist/retry.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAYH,+EAA+E;AAC/E,MAAM,CAAC,MAAM,oBAAoB,GAAgB;IAC/C,WAAW,EAAE,CAAC;IACd,WAAW,EAAE,IAAI;IACjB,OAAO,EAAE,aAAa;IACtB,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC;CACpB,CAAC;AAEF,yDAAyD;AACzD,MAAM,CAAC,MAAM,eAAe,GAAgB;IAC1C,WAAW,EAAE,CAAC;IACd,WAAW,EAAE,CAAC;IACd,OAAO,EAAE,UAAU;IACnB,OAAO,EAAE,EAAE;CACZ,CAAC;AAEF,MAAM,aAAa,GAAG,GAAG,CAAC;AAE1B;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC;AAmB3C;;;;;GAKG;AACH,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IACtB;IAArB,YAAqB,MAAe;QAClC,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAD5B,WAAM,GAAN,MAAM,CAAS;QAElC,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,WAAmD,EACnD,MAAmB,EACnB,IAAe,EACf,MAA2B;IAE3B,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAEpB,SAAS,CAAC;QACR,IAAI,QAAkB,CAAC;QACvB,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,CAAC;QACxC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,sEAAsE;YACtE,gEAAgE;YAChE,IAAI,KAAK,YAAY,kBAAkB,EAAE,CAAC;gBACxC,MAAM,KAAK,CAAC;YACd,CAAC;YAED,MAAM,OAAO,GACX,MAAM,EAAE,OAAO,KAAK,IAAI;gBACxB,CAAC,KAAK,YAAY,YAAY;oBAC5B,CAAC,KAAK,CAAC,IAAI,KAAK,YAAY,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC,CAAC;YACpE,IAAI,OAAO,IAAI,OAAO,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;gBAC7C,MAAM,KAAK,CAAC;YACd,CAAC;YAED,sEAAsE;YACtE,oEAAoE;YACpE,4BAA4B;YAC5B,MAAM,KAAK,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YACxE,MAAM,KAAK,GAAG,qBAAqB,CAAC,MAAM,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC;YAEzD,IAAI,CAAC,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;YAC/C,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;YAErC,MAAM,KAAK,CAAC,KAAK,EAAE,MAAM,IAAI,SAAS,CAAC,CAAC;YAExC,qDAAqD;YACrD,OAAO,IAAI,CAAC,CAAC;YACb,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACpB,SAAS;QACX,CAAC;QAED,kEAAkE;QAClE,iEAAiE;QACjE,mCAAmC;QACnC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,OAAO,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;YAC/E,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,oDAAoD;QACpD,IAAI,KAAa,CAAC;QAClB,MAAM,UAAU,GACd,QAAQ,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACvE,MAAM,iBAAiB,GAAG,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QACtE,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC;YAC9B,KAAK,GAAG,iBAAiB,GAAG,IAAI,CAAC;QACnC,CAAC;aAAM,CAAC;YACN,KAAK,GAAG,qBAAqB,CAAC,MAAM,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC;QACrD,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,KAAK,CAC3B,QAAQ,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,UAAU,IAAI,gBAAgB,EAAE,CACtE,CAAC;QAEF,yEAAyE;QACzE,mDAAmD;QACnD,IAAI,CAAC,QAAQ,CAAC,EAAE,UAAU,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAC/C,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;QAE3C,0EAA0E;QAC1E,yEAAyE;QACzE,wEAAwE;QACxE,uEAAuE;QACvE,kEAAkE;QAClE,KAAK,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAE7C,MAAM,KAAK,CAAC,KAAK,EAAE,MAAM,IAAI,SAAS,CAAC,CAAC;QAExC,wEAAwE;QACxE,qEAAqE;QACrE,mEAAmE;QACnE,iEAAiE;QACjE,yEAAyE;QACzE,kBAAkB;QAClB,OAAO,IAAI,CAAC,CAAC;QACb,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACtB,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,iBAAiB,CAAC,IAAY,EAAE,QAAgB;IACvD,IAAI,MAAM,GAAG,IAAI,CAAC;IAClB,KAAK,IAAI,SAAS,GAAG,QAAQ,EAAE,SAAS,GAAG,CAAC,GAAI,CAAC;QAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACvC,MAAM,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAC5B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,OAAO,QAAQ,CAAC;QAC9C,SAAS,IAAI,IAAI,CAAC;IACpB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,kBAAkB,CAAC,IAAY;IACtC,+EAA+E;IAC/E,sDAAsD;IACtD,IAAI,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACzF,OAAO,QAAQ,GAAG,CAAC,IAAI,iBAAiB,CAAC,IAAI,EAAE,QAAQ,GAAG,CAAC,CAAC,IAAI,oBAAoB;QAAE,QAAQ,EAAE,CAAC;IACjG,OAAO,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,oBAAoB;QAAE,QAAQ,EAAE,CAAC;IAC5E,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,iBAAiB,CAC/B,WAAmB,EACnB,OAA+B,EAC/B,OAAe;IAEf,MAAM,IAAI,GAAG,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACxC,IAAI,IAAI,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAEzB,IAAI,KAAa,CAAC;IAClB,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,aAAa;YAChB,IAAI,KAAK,IAAI,kBAAkB,CAAC,IAAI,CAAC;gBAAE,OAAO,oBAAoB,CAAC;YACnE,KAAK,GAAG,iBAAiB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACvC,MAAM;QACR,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,sEAAsE;YACtE,2DAA2D;YAC3D,MAAM,UAAU,GAAG,KAAK,GAAG,CAAC,CAAC;YAC7B,IAAI,UAAU,IAAI,oBAAoB,GAAG,IAAI;gBAAE,OAAO,oBAAoB,CAAC;YAC3E,KAAK,GAAG,IAAI,GAAG,UAAU,CAAC;YAC1B,MAAM;QACR,CAAC;QACD,KAAK,UAAU,CAAC;QAChB;YACE,KAAK,GAAG,IAAI,CAAC;IACjB,CAAC;IAED,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,oBAAoB,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,MAAmB,EAAE,OAAe;IACxE,MAAM,KAAK,GAAG,iBAAiB,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAE7E,uBAAuB;IACvB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,aAAa,CAAC;IAC7C,OAAO,KAAK,GAAG,MAAM,CAAC;AACxB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,KAAK,CAAC,EAAU,EAAE,MAAoB;IACpD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACpB,MAAM,CAAC,MAAM,CAAC,MAAe,CAAC,CAAC;YAC/B,OAAO;QACT,CAAC;QACD,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,CAAC,MAAO,CAAC,MAAe,CAAC,CAAC;QAClC,CAAC,CAAC;QACF,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC9C,OAAO,EAAE,CAAC;QACZ,CAAC,EAAE,EAAE,CAAC,CAAC;QACP,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"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"}
@@ -7,51 +7,8 @@
7
7
  import { BaseService, type RawClient } from "./base.js";
8
8
  import type { BasecampHooks } from "../hooks.js";
9
9
  import type { AuthStrategy } from "../auth-strategy.js";
10
- /**
11
- * The authenticated user's identity.
12
- */
13
- export interface Identity {
14
- /** User's unique identifier */
15
- id: number;
16
- /** User's first name */
17
- firstName: string;
18
- /** User's last name */
19
- lastName: string;
20
- /** User's email address */
21
- emailAddress: string;
22
- }
23
- /**
24
- * A Basecamp account the user has access to.
25
- */
26
- export interface AuthorizedAccount {
27
- /** Account's unique identifier */
28
- id: number;
29
- /** Account name */
30
- name: string;
31
- /** Product type (e.g., "bc3" for Basecamp, "hey" for HEY) */
32
- product: string;
33
- /** API URL for this account */
34
- href: string;
35
- /** Web app URL for this account */
36
- appHref: string;
37
- /** Whether the account is hidden from the user's view */
38
- hidden?: boolean;
39
- /** Whether the account subscription has expired */
40
- expired?: boolean;
41
- /** Whether this is the user's featured/primary account */
42
- featured?: boolean;
43
- }
44
- /**
45
- * Authorization information response.
46
- */
47
- export interface AuthorizationInfo {
48
- /** Token expiration timestamp */
49
- expiresAt: Date;
50
- /** The authenticated user's identity */
51
- identity: Identity;
52
- /** List of accounts the user can access */
53
- accounts: AuthorizedAccount[];
54
- }
10
+ import { type AuthorizationInfo } from "../oauth/authorization-document.js";
11
+ export type { Identity, AuthorizedAccount, AuthorizationInfo, } from "../oauth/authorization-document.js";
55
12
  /**
56
13
  * Options for fetching authorization information.
57
14
  */
@@ -59,19 +16,29 @@ export interface GetAuthorizationInfoOptions {
59
16
  /**
60
17
  * Override the default authorization endpoint URL.
61
18
  * Defaults to "https://launchpad.37signals.com/authorization.json"
19
+ *
20
+ * This is also how you point at a BC5 issuer, whose document is a different
21
+ * shape — see `../oauth/authorization-document.js`.
62
22
  */
63
23
  endpoint?: string;
64
24
  /**
65
25
  * Filter accounts by product type.
66
26
  * Common values: "bc3" (Basecamp), "bcx" (Basecamp 2), "hey" (HEY)
27
+ *
28
+ * A BC5 document carries no `product` on any account, so the filter cannot
29
+ * apply there. In that case all accounts are returned and
30
+ * `AuthorizationInfo.productFilterApplied` is `false`, rather than the empty
31
+ * list a literal filter would produce.
67
32
  */
68
33
  filterProduct?: string;
69
34
  }
70
35
  /**
71
36
  * Service for authorization-related operations.
72
37
  *
73
- * This service communicates with the Launchpad authorization endpoint
74
- * rather than the standard Basecamp API.
38
+ * This service communicates with an authorization endpoint — Launchpad by
39
+ * default, or a BC5 issuer via `endpoint:` — rather than the standard Basecamp
40
+ * API. The two serve different-shaped documents; see
41
+ * `../oauth/authorization-document.js`.
75
42
  *
76
43
  * @example
77
44
  * ```ts
@@ -84,9 +51,11 @@ export interface GetAuthorizationInfoOptions {
84
51
  *
85
52
  * // Get all accounts
86
53
  * const info = await client.authorization.getInfo();
87
- * console.log(`Logged in as ${info.identity.firstName}`);
54
+ * console.log(`Logged in as identity ${info.identity.id}`);
88
55
  *
89
- * // Filter to only Basecamp accounts
56
+ * // Filter to only Basecamp accounts. Against a BC5 issuer, whose accounts
57
+ * // carry no `product`, this returns every account with
58
+ * // `productFilterApplied === false` instead of an empty list.
90
59
  * const bc3Info = await client.authorization.getInfo({ filterProduct: "bc3" });
91
60
  * for (const account of bc3Info.accounts) {
92
61
  * console.log(account.name);
@@ -110,12 +79,13 @@ export declare class AuthorizationService extends BaseService {
110
79
  * ```ts
111
80
  * const info = await authService.getInfo();
112
81
  *
113
- * console.log(`User: ${info.identity.firstName} ${info.identity.lastName}`);
114
- * console.log(`Email: ${info.identity.emailAddress}`);
82
+ * // A BC5 issuer emits only `identity.id`; the name and email fields are
83
+ * // Launchpad's and are `undefined` there.
84
+ * console.log(`User: ${info.identity.id}`);
115
85
  * console.log(`Token expires: ${info.expiresAt}`);
116
86
  *
117
87
  * for (const account of info.accounts) {
118
- * console.log(`${account.name} (${account.product})`);
88
+ * console.log(`${account.name}: ${account.href}`);
119
89
  * }
120
90
  * ```
121
91
  */
@@ -1 +1 @@
1
- {"version":3,"file":"authorization.d.ts","sourceRoot":"","sources":["../../src/services/authorization.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,+BAA+B;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,wBAAwB;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,uBAAuB;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,2BAA2B;IAC3B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,kCAAkC;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,mDAAmD;IACnD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,iCAAiC;IACjC,SAAS,EAAE,IAAI,CAAC;IAChB,wCAAwC;IACxC,QAAQ,EAAE,QAAQ,CAAC;IACnB,2CAA2C;IAC3C,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AA2BD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,oBAAqB,SAAQ,WAAW;IACnD,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,SAAS,CAAS;gBAGxB,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,aAAa,GAAG,SAAS,EAChC,YAAY,EAAE,YAAY,EAC1B,SAAS,EAAE,MAAM;IAOnB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACG,OAAO,CAAC,OAAO,GAAE,2BAAgC,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAgErF"}
1
+ {"version":3,"file":"authorization.d.ts","sourceRoot":"","sources":["../../src/services/authorization.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,EAEL,KAAK,iBAAiB,EAEvB,MAAM,oCAAoC,CAAC;AAI5C,YAAY,EACV,QAAQ,EACR,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,oCAAoC,CAAC;AAE5C;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,oBAAqB,SAAQ,WAAW;IACnD,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,SAAS,CAAS;gBAGxB,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,aAAa,GAAG,SAAS,EAChC,YAAY,EAAE,YAAY,EAC1B,SAAS,EAAE,MAAM;IAOnB;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACG,OAAO,CAAC,OAAO,GAAE,2BAAgC,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAsCrF"}
@@ -6,12 +6,15 @@
6
6
  */
7
7
  import { BaseService } from "./base.js";
8
8
  import { requireSecureEndpoint } from "../security.js";
9
+ import { parseAuthorizationDocument, } from "../oauth/authorization-document.js";
9
10
  const DEFAULT_AUTHORIZATION_ENDPOINT = "https://launchpad.37signals.com/authorization.json";
10
11
  /**
11
12
  * Service for authorization-related operations.
12
13
  *
13
- * This service communicates with the Launchpad authorization endpoint
14
- * rather than the standard Basecamp API.
14
+ * This service communicates with an authorization endpoint — Launchpad by
15
+ * default, or a BC5 issuer via `endpoint:` — rather than the standard Basecamp
16
+ * API. The two serve different-shaped documents; see
17
+ * `../oauth/authorization-document.js`.
15
18
  *
16
19
  * @example
17
20
  * ```ts
@@ -24,9 +27,11 @@ const DEFAULT_AUTHORIZATION_ENDPOINT = "https://launchpad.37signals.com/authoriz
24
27
  *
25
28
  * // Get all accounts
26
29
  * const info = await client.authorization.getInfo();
27
- * console.log(`Logged in as ${info.identity.firstName}`);
30
+ * console.log(`Logged in as identity ${info.identity.id}`);
28
31
  *
29
- * // Filter to only Basecamp accounts
32
+ * // Filter to only Basecamp accounts. Against a BC5 issuer, whose accounts
33
+ * // carry no `product`, this returns every account with
34
+ * // `productFilterApplied === false` instead of an empty list.
30
35
  * const bc3Info = await client.authorization.getInfo({ filterProduct: "bc3" });
31
36
  * for (const account of bc3Info.accounts) {
32
37
  * console.log(account.name);
@@ -54,12 +59,13 @@ export class AuthorizationService extends BaseService {
54
59
  * ```ts
55
60
  * const info = await authService.getInfo();
56
61
  *
57
- * console.log(`User: ${info.identity.firstName} ${info.identity.lastName}`);
58
- * console.log(`Email: ${info.identity.emailAddress}`);
62
+ * // A BC5 issuer emits only `identity.id`; the name and email fields are
63
+ * // Launchpad's and are `undefined` there.
64
+ * console.log(`User: ${info.identity.id}`);
59
65
  * console.log(`Token expires: ${info.expiresAt}`);
60
66
  *
61
67
  * for (const account of info.accounts) {
62
- * console.log(`${account.name} (${account.product})`);
68
+ * console.log(`${account.name}: ${account.href}`);
63
69
  * }
64
70
  * ```
65
71
  */
@@ -88,31 +94,7 @@ export class AuthorizationService extends BaseService {
88
94
  return { data: undefined, error: undefined, response };
89
95
  }
90
96
  const raw = (await response.json());
91
- // Transform to our clean types
92
- let accounts = raw.accounts.map((a) => ({
93
- id: a.id,
94
- name: a.name,
95
- product: a.product,
96
- href: a.href,
97
- appHref: a.app_href,
98
- hidden: a.hidden,
99
- expired: a.expired,
100
- featured: a.featured,
101
- }));
102
- // Filter by product if requested
103
- if (options.filterProduct) {
104
- accounts = accounts.filter((a) => a.product === options.filterProduct);
105
- }
106
- const data = {
107
- expiresAt: new Date(raw.expires_at),
108
- identity: {
109
- id: raw.identity.id,
110
- firstName: raw.identity.first_name,
111
- lastName: raw.identity.last_name,
112
- emailAddress: raw.identity.email_address,
113
- },
114
- accounts,
115
- };
97
+ const data = parseAuthorizationDocument(raw, { filterProduct: options.filterProduct });
116
98
  return { data, error: undefined, response };
117
99
  });
118
100
  }
@@ -1 +1 @@
1
- {"version":3,"file":"authorization.js","sourceRoot":"","sources":["../../src/services/authorization.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"authorization.js","sourceRoot":"","sources":["../../src/services/authorization.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAkB,MAAM,WAAW,CAAC;AAGxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EACL,0BAA0B,GAG3B,MAAM,oCAAoC,CAAC;AAkC5C,MAAM,8BAA8B,GAAG,oDAAoD,CAAC;AAE5F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,OAAO,oBAAqB,SAAQ,WAAW;IAC3C,YAAY,CAAe;IAC3B,SAAS,CAAS;IAE1B,YACE,MAAiB,EACjB,KAAgC,EAChC,YAA0B,EAC1B,SAAiB;QAEjB,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACrB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,KAAK,CAAC,OAAO,CAAC,UAAuC,EAAE;QACrD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,8BAA8B,CAAC;QACpE,0EAA0E;QAC1E,qBAAqB,CAAC,QAAQ,EAAE,wBAAwB,CAAC,CAAC;QAE1D,OAAO,IAAI,CAAC,OAAO,CACjB;YACE,OAAO,EAAE,eAAe;YACxB,SAAS,EAAE,SAAS;YACpB,YAAY,EAAE,eAAe;YAC7B,UAAU,EAAE,KAAK;SAClB,EACD,KAAK,IAAI,EAAE;YACT,mCAAmC;YACnC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC;gBAC1B,YAAY,EAAE,IAAI,CAAC,SAAS;gBAC5B,MAAM,EAAE,kBAAkB;aAC3B,CAAC,CAAC;YACH,MAAM,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;YAE9C,kDAAkD;YAClD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE;gBACrC,MAAM,EAAE,KAAK;gBACb,OAAO;aACR,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;YACzD,CAAC;YAED,MAAM,GAAG,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAA6B,CAAC;YAEhE,MAAM,IAAI,GAAG,0BAA0B,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;YAEvF,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;QAC9C,CAAC,CACF,CAAC;IACJ,CAAC;CACF"}