@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.
- package/CHANGELOG.md +16 -0
- package/README.md +88 -65
- package/dist/JiraApiClient.d.ts +20 -86
- package/dist/JiraApiClient.d.ts.map +1 -1
- package/dist/JiraApiClient.js +26 -75
- package/dist/JiraApiClient.js.map +1 -1
- package/dist/generated/JiraApi.d.ts +103971 -0
- package/dist/generated/JiraApi.d.ts.map +1 -0
- package/dist/generated/JiraApi.js +7608 -0
- package/dist/generated/JiraApi.js.map +1 -0
- package/dist/index.d.ts +3 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -11
- package/dist/index.js.map +1 -1
- package/package.json +13 -16
- package/scripts/regenerate.ts +209 -201
- package/scripts/tsconfig.json +13 -0
- package/src/JiraApiClient.ts +74 -104
- package/src/generated/JiraApi.ts +19596 -0
- package/src/index.ts +3 -14
- package/test/JiraApiClient.test.ts +154 -153
- package/.specs/VERSION_V3 +0 -1
- package/.specs/jira-v3-1001.0.0-SNAPSHOT-05f20e18d9bde3de68f911b4915970482f536d4e.json +0 -56275
- package/.specs/jira-v3-1001.0.0-SNAPSHOT-d7cd03e966bb408ad32ffe870114289c528f56fd.json +0 -56129
- package/.specs/jira-v3-1001.0.0-SNAPSHOT-ea9913a8c4412d2bfb1911480b023a04544e19d8.json +0 -55618
- package/dist/OpenApiFetchClient.d.ts +0 -55
- package/dist/OpenApiFetchClient.d.ts.map +0 -1
- package/dist/OpenApiFetchClient.js +0 -68
- package/dist/OpenApiFetchClient.js.map +0 -1
- package/dist/generated/v3/index.d.ts +0 -7
- package/dist/generated/v3/index.d.ts.map +0 -1
- package/dist/generated/v3/index.js +0 -2
- package/dist/generated/v3/index.js.map +0 -1
- package/dist/generated/v3/schema.d.ts +0 -64454
- package/src/OpenApiFetchClient.ts +0 -102
- package/src/generated/v3/index.ts +0 -6
- package/src/generated/v3/schema.d.ts +0 -64454
- package/tsconfig.tsbuildinfo +0 -1
package/src/JiraApiClient.ts
CHANGED
|
@@ -1,128 +1,98 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Schema-validated Jira Cloud REST API client.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
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"
|
|
23
|
-
import type {
|
|
24
|
-
import
|
|
25
|
-
import
|
|
16
|
+
import type { SchemaError } from "effect/Schema"
|
|
17
|
+
import * as HttpClient from "effect/unstable/http/HttpClient"
|
|
18
|
+
import type * as HttpClientError from "effect/unstable/http/HttpClientError"
|
|
19
|
+
import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest"
|
|
20
|
+
import * as HttpClientResponse from "effect/unstable/http/HttpClientResponse"
|
|
21
|
+
import * as Generated from "./generated/JiraApi.js"
|
|
22
|
+
import { JiraApiConfig, type JiraApiConfigShape } from "./JiraApiConfig.js"
|
|
26
23
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
* ```typescript
|
|
32
|
-
* import { toEffect } from "@knpkv/jira-api-client"
|
|
33
|
-
*
|
|
34
|
-
* // Get issue by key
|
|
35
|
-
* toEffect(client.v3.client.GET("/rest/api/3/issue/{issueIdOrKey}", {
|
|
36
|
-
* params: { path: { issueIdOrKey: "PROJ-123" } }
|
|
37
|
-
* }))
|
|
38
|
-
*
|
|
39
|
-
* // Search issues with JQL
|
|
40
|
-
* toEffect(client.v3.client.POST("/rest/api/3/search/jql", {
|
|
41
|
-
* body: { jql: "project = PROJ", maxResults: 50 }
|
|
42
|
-
* }))
|
|
43
|
-
* ```
|
|
44
|
-
*
|
|
45
|
-
* @category Client
|
|
46
|
-
*/
|
|
47
|
-
export interface JiraApiClientShape {
|
|
48
|
-
readonly v3: OpenApiFetchClient<V3Paths>
|
|
24
|
+
export interface UploadAttachmentInput {
|
|
25
|
+
readonly bytes: Uint8Array
|
|
26
|
+
readonly filename: string
|
|
27
|
+
readonly mediaType?: string | undefined
|
|
49
28
|
}
|
|
50
29
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
30
|
+
export interface JiraApiClientShape extends Generated.JiraApi {
|
|
31
|
+
readonly uploadAttachment: (
|
|
32
|
+
issueIdOrKey: string,
|
|
33
|
+
input: UploadAttachmentInput
|
|
34
|
+
) => Effect.Effect<Generated.AddAttachment200, HttpClientError.HttpClientError | SchemaError>
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const authorizationHeader = (config: JiraApiConfigShape): string =>
|
|
38
|
+
config.auth.type === "basic"
|
|
39
|
+
? `Basic ${Encoding.encodeBase64(`${config.auth.email}:${Redacted.value(config.auth.apiToken)}`)}`
|
|
40
|
+
: `Bearer ${Redacted.value(config.auth.accessToken)}`
|
|
41
|
+
|
|
42
|
+
const apiBaseUrl = (config: JiraApiConfigShape): string =>
|
|
43
|
+
config.auth.type === "oauth2"
|
|
44
|
+
? `https://api.atlassian.com/ex/jira/${config.auth.cloudId}`
|
|
45
|
+
: config.baseUrl
|
|
46
|
+
|
|
47
|
+
export const make = (
|
|
48
|
+
httpClient: HttpClient.HttpClient,
|
|
49
|
+
config: JiraApiConfigShape
|
|
50
|
+
): Generated.JiraApi =>
|
|
51
|
+
Generated.make(httpClient.pipe(
|
|
52
|
+
HttpClient.mapRequest(flow(
|
|
53
|
+
HttpClientRequest.prependUrl(apiBaseUrl(config)),
|
|
54
|
+
HttpClientRequest.setHeader("Authorization", authorizationHeader(config)),
|
|
55
|
+
HttpClientRequest.setHeader("Accept", "application/json")
|
|
56
|
+
))
|
|
57
|
+
))
|
|
58
|
+
|
|
59
|
+
const makeUploadAttachment =
|
|
60
|
+
(api: Generated.JiraApi): JiraApiClientShape["uploadAttachment"] => (issueIdOrKey, input) => {
|
|
61
|
+
const buffer = new ArrayBuffer(input.bytes.byteLength)
|
|
62
|
+
new Uint8Array(buffer).set(input.bytes)
|
|
63
|
+
const form = new FormData()
|
|
64
|
+
form.append(
|
|
65
|
+
"file",
|
|
66
|
+
new Blob([buffer], input.mediaType === undefined ? undefined : { type: input.mediaType }),
|
|
67
|
+
input.filename
|
|
68
|
+
)
|
|
69
|
+
return api.httpClient.execute(
|
|
70
|
+
HttpClientRequest.post(`/rest/api/3/issue/${encodeURIComponent(issueIdOrKey)}/attachments`).pipe(
|
|
71
|
+
HttpClientRequest.setHeader("X-Atlassian-Token", "no-check"),
|
|
72
|
+
HttpClientRequest.bodyFormData(form)
|
|
73
|
+
)
|
|
74
|
+
).pipe(
|
|
75
|
+
Effect.flatMap(HttpClientResponse.filterStatusOk),
|
|
76
|
+
Effect.flatMap(HttpClientResponse.schemaBodyJson(Generated.AddAttachment200))
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
|
|
88
80
|
export class JiraApiClient extends Context.Service<JiraApiClient, JiraApiClientShape>()(
|
|
89
81
|
"@knpkv/jira-api-client/JiraApiClient"
|
|
90
82
|
) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
static readonly layer: Layer.Layer<JiraApiClient, never, JiraApiConfig> = Layer.effect(
|
|
83
|
+
static readonly layer: Layer.Layer<
|
|
84
|
+
JiraApiClient,
|
|
85
|
+
never,
|
|
86
|
+
JiraApiConfig | HttpClient.HttpClient
|
|
87
|
+
> = Layer.effect(
|
|
97
88
|
JiraApiClient,
|
|
98
89
|
Effect.gen(function*() {
|
|
99
90
|
const config = yield* JiraApiConfig
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
? `Basic ${Encoding.encodeBase64(`${config.auth.email}:${Redacted.value(config.auth.apiToken)}`)}`
|
|
104
|
-
: `Bearer ${Redacted.value(config.auth.accessToken)}`
|
|
105
|
-
|
|
106
|
-
// Base URL differs by auth type
|
|
107
|
-
const baseUrl = config.auth.type === "oauth2"
|
|
108
|
-
? `https://api.atlassian.com/ex/jira/${config.auth.cloudId}`
|
|
109
|
-
: config.baseUrl
|
|
110
|
-
|
|
111
|
-
const headers = {
|
|
112
|
-
Authorization: authHeader,
|
|
113
|
-
Accept: "application/json"
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
return {
|
|
117
|
-
v3: makeOpenApiFetchClient<V3Paths>(baseUrl, headers)
|
|
118
|
-
}
|
|
91
|
+
const httpClient = yield* HttpClient.HttpClient
|
|
92
|
+
const api = make(httpClient, config)
|
|
93
|
+
return JiraApiClient.of({ ...api, uploadAttachment: makeUploadAttachment(api) })
|
|
119
94
|
})
|
|
120
95
|
)
|
|
121
96
|
}
|
|
122
97
|
|
|
123
|
-
/**
|
|
124
|
-
* Layer that provides JiraApiClient.
|
|
125
|
-
*
|
|
126
|
-
* @category Layers
|
|
127
|
-
*/
|
|
128
98
|
export const layer = JiraApiClient.layer
|