@knpkv/jira-api-client 0.4.0 → 1.0.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 (38) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +88 -65
  3. package/dist/JiraApiClient.d.ts +20 -86
  4. package/dist/JiraApiClient.d.ts.map +1 -1
  5. package/dist/JiraApiClient.js +26 -75
  6. package/dist/JiraApiClient.js.map +1 -1
  7. package/dist/generated/JiraApi.d.ts +103971 -0
  8. package/dist/generated/JiraApi.d.ts.map +1 -0
  9. package/dist/generated/JiraApi.js +7608 -0
  10. package/dist/generated/JiraApi.js.map +1 -0
  11. package/dist/index.d.ts +3 -12
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +3 -11
  14. package/dist/index.js.map +1 -1
  15. package/package.json +13 -16
  16. package/scripts/regenerate.ts +209 -201
  17. package/scripts/tsconfig.json +13 -0
  18. package/src/JiraApiClient.ts +74 -104
  19. package/src/generated/JiraApi.ts +19596 -0
  20. package/src/index.ts +3 -14
  21. package/test/JiraApiClient.test.ts +154 -153
  22. package/.specs/VERSION_V3 +0 -1
  23. package/.specs/jira-v3-1001.0.0-SNAPSHOT-05f20e18d9bde3de68f911b4915970482f536d4e.json +0 -56275
  24. package/.specs/jira-v3-1001.0.0-SNAPSHOT-d7cd03e966bb408ad32ffe870114289c528f56fd.json +0 -56129
  25. package/.specs/jira-v3-1001.0.0-SNAPSHOT-ea9913a8c4412d2bfb1911480b023a04544e19d8.json +0 -55618
  26. package/dist/OpenApiFetchClient.d.ts +0 -55
  27. package/dist/OpenApiFetchClient.d.ts.map +0 -1
  28. package/dist/OpenApiFetchClient.js +0 -68
  29. package/dist/OpenApiFetchClient.js.map +0 -1
  30. package/dist/generated/v3/index.d.ts +0 -7
  31. package/dist/generated/v3/index.d.ts.map +0 -1
  32. package/dist/generated/v3/index.js +0 -2
  33. package/dist/generated/v3/index.js.map +0 -1
  34. package/dist/generated/v3/schema.d.ts +0 -64454
  35. package/src/OpenApiFetchClient.ts +0 -102
  36. package/src/generated/v3/index.ts +0 -6
  37. package/src/generated/v3/schema.d.ts +0 -64454
  38. package/tsconfig.tsbuildinfo +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @knpkv/jira-api-client
2
2
 
3
+ ## 1.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - [#125](https://github.com/knpkv/npm/pull/125) [`f820c19`](https://github.com/knpkv/npm/commit/f820c1906e00f2f2d17c2e7cc3921ba26522db43) Thanks [@konopkov](https://github.com/konopkov)! - Replace the legacy Atlassian `openapi-fetch` clients with generated,
8
+ Schema-validated Effect clients. Jira and Confluence now provide direct Effect
9
+ operations, injected `HttpClient` transports, deterministic local regeneration,
10
+ structural upstream freshness checks, and scheduled tested update pull requests.
11
+
12
+ The legacy `toEffect`, `FetchClientError`, raw `.client` operation surface, and
13
+ type-only generated subpaths are removed.
14
+
15
+ ### Patch Changes
16
+
17
+ - [#125](https://github.com/knpkv/npm/pull/125) [`f820c19`](https://github.com/knpkv/npm/commit/f820c1906e00f2f2d17c2e7cc3921ba26522db43) Thanks [@konopkov](https://github.com/konopkov)! - Upgrade the workspace to Effect 4.0.0-beta.98 and current compatible dependencies. Replace ad hoc object guards with Effect Predicate helpers and migrate retry schedules to the current Schedule API.
18
+
3
19
  ## 0.4.0
4
20
 
5
21
  ### Minor Changes
package/README.md CHANGED
@@ -1,94 +1,117 @@
1
1
  # @knpkv/jira-api-client
2
2
 
3
- Effect-based Jira Cloud REST API v3 client. Type-safe paths and responses generated from the official OpenAPI schema via `openapi-typescript` + `openapi-fetch`.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- pnpm add @knpkv/jira-api-client
9
- ```
10
-
11
- Peer dependencies: `effect`
3
+ Schema-validated Effect client for Jira Cloud REST API v3. Request parameters,
4
+ response codecs, operation errors, and the low-level client are generated from
5
+ Atlassian's official OpenAPI document with `@effect/openapi-generator`.
12
6
 
13
7
  ## Usage
14
8
 
15
- ```typescript
16
- import { Effect, Layer } from "effect"
17
- import * as Redacted from "effect/Redacted"
18
- import { JiraApiClient, JiraApiConfig, toEffect } from "@knpkv/jira-api-client"
9
+ ```ts
10
+ import { JiraApiClient, JiraApiConfig } from "@knpkv/jira-api-client"
11
+ import { NodeHttpClient } from "@effect/platform-node"
12
+ import { Effect, Layer, Redacted } from "effect"
19
13
 
20
14
  const program = Effect.gen(function* () {
21
- const client = yield* JiraApiClient
22
-
23
- // Get issue by key
24
- const issue = yield* toEffect(
25
- client.v3.client.GET("/rest/api/3/issue/{issueIdOrKey}", {
26
- params: { path: { issueIdOrKey: "PROJ-123" } }
27
- })
28
- )
29
- console.log(issue.fields?.summary)
30
-
31
- // Search with JQL
32
- const results = yield* toEffect(
33
- client.v3.client.POST("/rest/api/3/search/jql", {
34
- body: { jql: "project = PROJ AND status != Done", maxResults: 50 }
35
- })
36
- )
15
+ const jira = yield* JiraApiClient
16
+ return yield* jira.getIssue("PROJ-123", {
17
+ params: { fields: ["summary", "status"] }
18
+ })
37
19
  })
38
20
 
39
- // Basic auth
40
- const configLayer = Layer.succeed(JiraApiConfig, {
41
- baseUrl: "https://mysite.atlassian.net",
21
+ const ConfigLive = Layer.succeed(JiraApiConfig, {
22
+ baseUrl: "https://example.atlassian.net",
42
23
  auth: {
43
24
  type: "basic",
44
- email: "user@example.com",
45
- apiToken: Redacted.make("your-api-token")
46
- }
47
- })
48
-
49
- // Or OAuth2
50
- const oauthConfigLayer = Layer.succeed(JiraApiConfig, {
51
- baseUrl: "",
52
- auth: {
53
- type: "oauth2",
54
- accessToken: Redacted.make("oauth-access-token"),
55
- cloudId: "your-cloud-id"
25
+ email: "developer@example.com",
26
+ apiToken: Redacted.make("api-token")
56
27
  }
57
28
  })
58
29
 
59
- Effect.runPromise(program.pipe(Effect.provide(JiraApiClient.layer), Effect.provide(configLayer)))
30
+ Effect.runPromise(
31
+ program.pipe(
32
+ Effect.provide(JiraApiClient.layer),
33
+ Effect.provide(ConfigLive),
34
+ Effect.provide(NodeHttpClient.layerUndici)
35
+ )
36
+ )
60
37
  ```
61
38
 
62
- ## API Pattern
39
+ OAuth2 configuration uses an access token and cloud ID. Requests are routed
40
+ through `https://api.atlassian.com/ex/jira/{cloudId}` automatically.
41
+
42
+ The complete generated module is exported as `JiraApi`, and `make` constructs
43
+ the generated client from an existing Effect `HttpClient`. Application code
44
+ normally uses `JiraApiClient`, which also provides `uploadAttachment` for Jira's
45
+ multipart endpoint. The upstream schema describes that endpoint as Java server
46
+ objects rather than a native `FormData`, so multipart construction deliberately
47
+ lives in this single handwritten boundary.
48
+
49
+ All successful JSON bodies are decoded with generated Effect Schemas. Documented
50
+ 4xx and 5xx statuses fail with generated tagged errors such as `GetIssue404`;
51
+ transport and malformed-body failures remain in the typed error channel.
52
+
53
+ ## Regenerating the client
54
+
55
+ Requirements:
56
+
57
+ - dependencies installed with `pnpm install`;
58
+ - network access to Atlassian for a live regeneration;
59
+ - a clean enough worktree to review generated changes independently.
63
60
 
64
- All API calls go through `toEffect()` which wraps the openapi-fetch promise in an Effect:
61
+ Run a live regeneration from the repository root:
65
62
 
66
- ```typescript
67
- toEffect(client.v3.client.GET("/rest/api/3/..."))
68
- // → Effect<ResponseData, FetchClientError>
63
+ ```sh
64
+ pnpm --filter @knpkv/jira-api-client regenerate
69
65
  ```
70
66
 
71
- Paths are fully type-safe — autocomplete and compile-time errors for invalid paths, params, and bodies.
67
+ The command performs this deterministic pipeline:
72
68
 
73
- ## Errors
69
+ 1. Fetch `https://dac-static.atlassian.com/cloud/jira/platform/swagger-v3.v3.json`.
70
+ 2. Canonically encode the unmodified response as `.specs/jira-v3.json`.
71
+ 3. Apply `.specs/jira-v3.patch.json` as RFC 6902 JSON Patch in memory.
72
+ 4. Normalize contradictory defaults and mixed open-object schemas in memory.
73
+ 5. Remove misleading JSON content from `204 No Content` responses so they
74
+ generate as `void` instead of attempting to decode an empty body.
75
+ 6. Add permissive JSON schemas to documented bodyless error responses so they
76
+ cannot be mistaken for successful `void` responses.
77
+ 7. Generate `src/generated/JiraApi.ts` with `@effect/openapi-generator`.
74
78
 
75
- `FetchClientError` is a tagged error with `error`, `status`, and `message` fields:
79
+ Never edit the generated TypeScript or committed upstream specification by
80
+ hand. Put intentional upstream corrections in the JSON Patch, or change the
81
+ documented normalization in `scripts/regenerate.ts`.
76
82
 
77
- ```typescript
78
- import { FetchClientError } from "@knpkv/jira-api-client"
83
+ For an offline, reproducible regeneration from the committed specification:
79
84
 
80
- program.pipe(Effect.catchTag("FetchClientError", (e) => Console.log(`HTTP ${e.status}: ${e.message}`)))
85
+ ```sh
86
+ pnpm --filter @knpkv/jira-api-client regenerate --local
81
87
  ```
82
88
 
83
- ## Subpath Exports
89
+ Review and validate a regeneration with:
90
+
91
+ ```sh
92
+ git diff -- packages/jira-api-client/.specs
93
+ git diff -- packages/jira-api-client/src/generated/JiraApi.ts
94
+ pnpm --filter @knpkv/jira-api-client check
95
+ pnpm --filter @knpkv/jira-api-client build
96
+ pnpm --filter @knpkv/jira-api-client test
97
+ pnpm --filter @knpkv/jira-cli test
98
+ pnpm --filter @knpkv/jira-clockify test
99
+ ```
100
+
101
+ ## Checking specification freshness
102
+
103
+ ```sh
104
+ pnpm --filter @knpkv/jira-api-client regenerate:check
105
+ ```
84
106
 
85
- | Export | Contents |
86
- | -------------------------------------- | ------------------------------- |
87
- | `@knpkv/jira-api-client` | Client, config, toEffect, types |
88
- | `@knpkv/jira-api-client/v3` | Generated V3 OpenAPI types |
89
- | `@knpkv/jira-api-client/JiraApiClient` | Client service only |
90
- | `@knpkv/jira-api-client/JiraApiConfig` | Config service only |
107
+ This fetches the complete current document and compares its canonical JSON
108
+ structure with the committed raw specification. It does not rely only on
109
+ Atlassian's version string.
91
110
 
92
- ## License
111
+ `.github/workflows/jira-api-update.yml` runs the check daily. When the upstream
112
+ document changes, CI regenerates the client, builds and tests this package and
113
+ its Jira consumers, adds a changeset, and opens or updates a pull request on
114
+ `chore/jira-api-spec-update`.
93
115
 
94
- MIT
116
+ Generated source is excluded from handwritten-source lint rules, but remains
117
+ fully typechecked, built, and exercised through transport and decoding tests.
@@ -1,99 +1,33 @@
1
1
  /**
2
- * Effect Layer wrapping openapi-fetch Jira V3 client with auth and base URL.
2
+ * Schema-validated Jira Cloud REST API client.
3
3
  *
4
- * **Mental model**
5
- *
6
- * - **Auth-polymorphic**: Supports both Basic (email + API token) and OAuth2 (access token +
7
- * cloud ID) auth. The layer reads {@link JiraApiConfig} to build the Authorization header
8
- * and derive the correct base URL.
9
- * - **openapi-fetch wrapper**: Uses {@link OpenApiFetchClient} for Effect-based methods.
10
- *
11
- * **Common tasks**
12
- *
13
- * - Use the client: `const jira = yield* JiraApiClient; jira.v3.GET(...)`
14
- * - Provide the layer: `Effect.provide(JiraApiClient.layer)`
4
+ * Generated code owns request construction and response decoding. This module
5
+ * applies Jira authentication and contains the one multipart boundary that the
6
+ * upstream specification cannot model as a native FormData value.
15
7
  *
16
8
  * @module
17
9
  */
18
10
  import * as Context from "effect/Context";
11
+ import * as Effect from "effect/Effect";
19
12
  import * as Layer from "effect/Layer";
20
- import type { paths as V3Paths } from "./generated/v3/schema.js";
21
- import { JiraApiConfig } from "./JiraApiConfig.js";
22
- import { type OpenApiFetchClient } from "./OpenApiFetchClient.js";
23
- /**
24
- * Jira API client shape (v3 only).
25
- *
26
- * @example
27
- * ```typescript
28
- * import { toEffect } from "@knpkv/jira-api-client"
29
- *
30
- * // Get issue by key
31
- * toEffect(client.v3.client.GET("/rest/api/3/issue/{issueIdOrKey}", {
32
- * params: { path: { issueIdOrKey: "PROJ-123" } }
33
- * }))
34
- *
35
- * // Search issues with JQL
36
- * toEffect(client.v3.client.POST("/rest/api/3/search/jql", {
37
- * body: { jql: "project = PROJ", maxResults: 50 }
38
- * }))
39
- * ```
40
- *
41
- * @category Client
42
- */
43
- export interface JiraApiClientShape {
44
- readonly v3: OpenApiFetchClient<V3Paths>;
13
+ import type { SchemaError } from "effect/Schema";
14
+ import * as HttpClient from "effect/unstable/http/HttpClient";
15
+ import type * as HttpClientError from "effect/unstable/http/HttpClientError";
16
+ import * as Generated from "./generated/JiraApi.js";
17
+ import { JiraApiConfig, type JiraApiConfigShape } from "./JiraApiConfig.js";
18
+ export interface UploadAttachmentInput {
19
+ readonly bytes: Uint8Array;
20
+ readonly filename: string;
21
+ readonly mediaType?: string | undefined;
22
+ }
23
+ export interface JiraApiClientShape extends Generated.JiraApi {
24
+ readonly uploadAttachment: (issueIdOrKey: string, input: UploadAttachmentInput) => Effect.Effect<Generated.AddAttachment200, HttpClientError.HttpClientError | SchemaError>;
45
25
  }
26
+ export declare const make: (httpClient: HttpClient.HttpClient, config: JiraApiConfigShape) => Generated.JiraApi;
46
27
  declare const JiraApiClient_base: Context.ServiceClass<JiraApiClient, "@knpkv/jira-api-client/JiraApiClient", JiraApiClientShape>;
47
- /**
48
- * Jira API client service.
49
- *
50
- * @example
51
- * ```typescript
52
- * import { JiraApiClient, JiraApiConfig } from "@knpkv/jira-api-client"
53
- * import * as Redacted from "effect/Redacted"
54
- * import * as Effect from "effect/Effect"
55
- * import * as Layer from "effect/Layer"
56
- *
57
- * const program = Effect.gen(function* () {
58
- * const client = yield* JiraApiClient
59
- * const issue = yield* toEffect(client.v3.client.GET("/rest/api/3/issue/{issueIdOrKey}", {
60
- * params: { path: { issueIdOrKey: "PROJ-123" } }
61
- * }))
62
- * console.log(issue.fields?.summary)
63
- * })
64
- *
65
- * const configLayer = Layer.succeed(JiraApiConfig, {
66
- * baseUrl: "https://mysite.atlassian.net",
67
- * auth: {
68
- * type: "basic",
69
- * email: "user@example.com",
70
- * apiToken: Redacted.make("token")
71
- * }
72
- * })
73
- *
74
- * Effect.runPromise(
75
- * program.pipe(
76
- * Effect.provide(JiraApiClient.layer),
77
- * Effect.provide(configLayer)
78
- * )
79
- * )
80
- * ```
81
- *
82
- * @category Client
83
- */
84
28
  export declare class JiraApiClient extends JiraApiClient_base {
85
- /**
86
- * Layer that provides JiraApiClient.
87
- *
88
- * Requires: JiraApiConfig
89
- */
90
- static readonly layer: Layer.Layer<JiraApiClient, never, JiraApiConfig>;
29
+ static readonly layer: Layer.Layer<JiraApiClient, never, JiraApiConfig | HttpClient.HttpClient>;
91
30
  }
92
- /**
93
- * Layer that provides JiraApiClient.
94
- *
95
- * @category Layers
96
- */
97
- export declare const layer: Layer.Layer<JiraApiClient, never, JiraApiConfig>;
31
+ export declare const layer: Layer.Layer<JiraApiClient, never, HttpClient.HttpClient | JiraApiConfig>;
98
32
  export {};
99
33
  //# sourceMappingURL=JiraApiClient.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"JiraApiClient.d.ts","sourceRoot":"","sources":["../src/JiraApiClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AAGzC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAErC,OAAO,KAAK,EAAE,KAAK,IAAI,OAAO,EAAE,MAAM,0BAA0B,CAAA;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,EAA0B,KAAK,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAEzF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,EAAE,kBAAkB,CAAC,OAAO,CAAC,CAAA;CACzC;;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,qBAAa,aAAc,SAAQ,kBAElC;IACC;;;;OAIG;IACH,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,aAAa,EAAE,KAAK,EAAE,aAAa,CAAC,CAwBtE;CACF;AAED;;;;GAIG;AACH,eAAO,MAAM,KAAK,kDAAsB,CAAA"}
1
+ {"version":3,"file":"JiraApiClient.d.ts","sourceRoot":"","sources":["../src/JiraApiClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAGvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAErC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,KAAK,UAAU,MAAM,iCAAiC,CAAA;AAC7D,OAAO,KAAK,KAAK,eAAe,MAAM,sCAAsC,CAAA;AAG5E,OAAO,KAAK,SAAS,MAAM,wBAAwB,CAAA;AACnD,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAE3E,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACxC;AAED,MAAM,WAAW,kBAAmB,SAAQ,SAAS,CAAC,OAAO;IAC3D,QAAQ,CAAC,gBAAgB,EAAE,CACzB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,qBAAqB,KACzB,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,gBAAgB,EAAE,eAAe,CAAC,eAAe,GAAG,WAAW,CAAC,CAAA;CAC9F;AAYD,eAAO,MAAM,IAAI,GACf,YAAY,UAAU,CAAC,UAAU,EACjC,QAAQ,kBAAkB,KACzB,SAAS,CAAC,OAOT,CAAA;;AAuBJ,qBAAa,aAAc,SAAQ,kBAElC;IACC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAChC,aAAa,EACb,KAAK,EACL,aAAa,GAAG,UAAU,CAAC,UAAU,CACtC,CAQA;CACF;AAED,eAAO,MAAM,KAAK,0EAAsB,CAAA"}
@@ -1,93 +1,44 @@
1
1
  /**
2
- * Effect Layer wrapping openapi-fetch Jira V3 client with auth and base URL.
2
+ * Schema-validated Jira Cloud REST API client.
3
3
  *
4
- * **Mental model**
5
- *
6
- * - **Auth-polymorphic**: Supports both Basic (email + API token) and OAuth2 (access token +
7
- * cloud ID) auth. The layer reads {@link JiraApiConfig} to build the Authorization header
8
- * and derive the correct base URL.
9
- * - **openapi-fetch wrapper**: Uses {@link OpenApiFetchClient} for Effect-based methods.
10
- *
11
- * **Common tasks**
12
- *
13
- * - Use the client: `const jira = yield* JiraApiClient; jira.v3.GET(...)`
14
- * - Provide the layer: `Effect.provide(JiraApiClient.layer)`
4
+ * Generated code owns request construction and response decoding. This module
5
+ * applies Jira authentication and contains the one multipart boundary that the
6
+ * upstream specification cannot model as a native FormData value.
15
7
  *
16
8
  * @module
17
9
  */
18
10
  import * as Context from "effect/Context";
19
11
  import * as Effect from "effect/Effect";
20
12
  import * as Encoding from "effect/Encoding";
13
+ import { flow } from "effect/Function";
21
14
  import * as Layer from "effect/Layer";
22
15
  import * as Redacted from "effect/Redacted";
16
+ import * as HttpClient from "effect/unstable/http/HttpClient";
17
+ import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest";
18
+ import * as HttpClientResponse from "effect/unstable/http/HttpClientResponse";
19
+ import * as Generated from "./generated/JiraApi.js";
23
20
  import { JiraApiConfig } from "./JiraApiConfig.js";
24
- import { makeOpenApiFetchClient } from "./OpenApiFetchClient.js";
25
- /**
26
- * Jira API client service.
27
- *
28
- * @example
29
- * ```typescript
30
- * import { JiraApiClient, JiraApiConfig } from "@knpkv/jira-api-client"
31
- * import * as Redacted from "effect/Redacted"
32
- * import * as Effect from "effect/Effect"
33
- * import * as Layer from "effect/Layer"
34
- *
35
- * const program = Effect.gen(function* () {
36
- * const client = yield* JiraApiClient
37
- * const issue = yield* toEffect(client.v3.client.GET("/rest/api/3/issue/{issueIdOrKey}", {
38
- * params: { path: { issueIdOrKey: "PROJ-123" } }
39
- * }))
40
- * console.log(issue.fields?.summary)
41
- * })
42
- *
43
- * const configLayer = Layer.succeed(JiraApiConfig, {
44
- * baseUrl: "https://mysite.atlassian.net",
45
- * auth: {
46
- * type: "basic",
47
- * email: "user@example.com",
48
- * apiToken: Redacted.make("token")
49
- * }
50
- * })
51
- *
52
- * Effect.runPromise(
53
- * program.pipe(
54
- * Effect.provide(JiraApiClient.layer),
55
- * Effect.provide(configLayer)
56
- * )
57
- * )
58
- * ```
59
- *
60
- * @category Client
61
- */
21
+ const authorizationHeader = (config) => config.auth.type === "basic"
22
+ ? `Basic ${Encoding.encodeBase64(`${config.auth.email}:${Redacted.value(config.auth.apiToken)}`)}`
23
+ : `Bearer ${Redacted.value(config.auth.accessToken)}`;
24
+ const apiBaseUrl = (config) => config.auth.type === "oauth2"
25
+ ? `https://api.atlassian.com/ex/jira/${config.auth.cloudId}`
26
+ : config.baseUrl;
27
+ export const make = (httpClient, config) => Generated.make(httpClient.pipe(HttpClient.mapRequest(flow(HttpClientRequest.prependUrl(apiBaseUrl(config)), HttpClientRequest.setHeader("Authorization", authorizationHeader(config)), HttpClientRequest.setHeader("Accept", "application/json")))));
28
+ const makeUploadAttachment = (api) => (issueIdOrKey, input) => {
29
+ const buffer = new ArrayBuffer(input.bytes.byteLength);
30
+ new Uint8Array(buffer).set(input.bytes);
31
+ const form = new FormData();
32
+ form.append("file", new Blob([buffer], input.mediaType === undefined ? undefined : { type: input.mediaType }), input.filename);
33
+ return api.httpClient.execute(HttpClientRequest.post(`/rest/api/3/issue/${encodeURIComponent(issueIdOrKey)}/attachments`).pipe(HttpClientRequest.setHeader("X-Atlassian-Token", "no-check"), HttpClientRequest.bodyFormData(form))).pipe(Effect.flatMap(HttpClientResponse.filterStatusOk), Effect.flatMap(HttpClientResponse.schemaBodyJson(Generated.AddAttachment200)));
34
+ };
62
35
  export class JiraApiClient extends Context.Service()("@knpkv/jira-api-client/JiraApiClient") {
63
- /**
64
- * Layer that provides JiraApiClient.
65
- *
66
- * Requires: JiraApiConfig
67
- */
68
36
  static layer = Layer.effect(JiraApiClient, Effect.gen(function* () {
69
37
  const config = yield* JiraApiConfig;
70
- // Build auth header
71
- const authHeader = config.auth.type === "basic"
72
- ? `Basic ${Encoding.encodeBase64(`${config.auth.email}:${Redacted.value(config.auth.apiToken)}`)}`
73
- : `Bearer ${Redacted.value(config.auth.accessToken)}`;
74
- // Base URL differs by auth type
75
- const baseUrl = config.auth.type === "oauth2"
76
- ? `https://api.atlassian.com/ex/jira/${config.auth.cloudId}`
77
- : config.baseUrl;
78
- const headers = {
79
- Authorization: authHeader,
80
- Accept: "application/json"
81
- };
82
- return {
83
- v3: makeOpenApiFetchClient(baseUrl, headers)
84
- };
38
+ const httpClient = yield* HttpClient.HttpClient;
39
+ const api = make(httpClient, config);
40
+ return JiraApiClient.of({ ...api, uploadAttachment: makeUploadAttachment(api) });
85
41
  }));
86
42
  }
87
- /**
88
- * Layer that provides JiraApiClient.
89
- *
90
- * @category Layers
91
- */
92
43
  export const layer = JiraApiClient.layer;
93
44
  //# sourceMappingURL=JiraApiClient.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"JiraApiClient.js","sourceRoot":"","sources":["../src/JiraApiClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAA;AAC3C,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAA;AAE3C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,EAAE,sBAAsB,EAA2B,MAAM,yBAAyB,CAAA;AA0BzF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAM,OAAO,aAAc,SAAQ,OAAO,CAAC,OAAO,EAAqC,CACrF,sCAAsC,CACvC;IACC;;;;OAIG;IACH,MAAM,CAAU,KAAK,GAAqD,KAAK,CAAC,MAAM,CACpF,aAAa,EACb,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,aAAa,CAAA;QAEnC,oBAAoB;QACpB,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO;YAC7C,CAAC,CAAC,SAAS,QAAQ,CAAC,YAAY,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE;YAClG,CAAC,CAAC,UAAU,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAA;QAEvD,gCAAgC;QAChC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ;YAC3C,CAAC,CAAC,qCAAqC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE;YAC5D,CAAC,CAAC,MAAM,CAAC,OAAO,CAAA;QAElB,MAAM,OAAO,GAAG;YACd,aAAa,EAAE,UAAU;YACzB,MAAM,EAAE,kBAAkB;SAC3B,CAAA;QAED,OAAO;YACL,EAAE,EAAE,sBAAsB,CAAU,OAAO,EAAE,OAAO,CAAC;SACtD,CAAA;IACH,CAAC,CAAC,CACH,CAAA;;AAGH;;;;GAIG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAA"}
1
+ {"version":3,"file":"JiraApiClient.js","sourceRoot":"","sources":["../src/JiraApiClient.ts"],"names":[],"mappings":"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"}