@knpkv/jira-api-client 0.3.0 → 0.3.1
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/.specs/VERSION_V3 +1 -1
- package/.specs/jira-v3-1001.0.0-SNAPSHOT-05f20e18d9bde3de68f911b4915970482f536d4e.json +56275 -0
- package/.specs/jira-v3-1001.0.0-SNAPSHOT-d7cd03e966bb408ad32ffe870114289c528f56fd.json +56129 -0
- package/CHANGELOG.md +6 -0
- package/dist/generated/v3/schema.d.ts +1537 -1436
- package/package.json +6 -6
- package/scripts/regenerate.ts +74 -40
- package/src/generated/v3/schema.d.ts +1537 -1436
- package/test/JiraApiClient.test.ts +14 -7
- package/tsconfig.tsbuildinfo +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@knpkv/jira-api-client",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Effect-based Jira Cloud REST API v3 client",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "knpkv",
|
|
@@ -39,16 +39,16 @@
|
|
|
39
39
|
"access": "public"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
|
-
"effect": "4.0.0-beta.
|
|
42
|
+
"effect": "4.0.0-beta.93"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@effect/platform-node": "4.0.0-beta.
|
|
46
|
-
"@effect/vitest": "4.0.0-beta.
|
|
45
|
+
"@effect/platform-node": "4.0.0-beta.93",
|
|
46
|
+
"@effect/vitest": "4.0.0-beta.93",
|
|
47
47
|
"@types/node": "latest",
|
|
48
|
-
"effect": "4.0.0-beta.
|
|
48
|
+
"effect": "4.0.0-beta.93",
|
|
49
49
|
"openapi-typescript": "^7.13.0",
|
|
50
50
|
"openapi-typescript-helpers": "^0.1.0",
|
|
51
|
-
"tsx": "^4.
|
|
51
|
+
"tsx": "^4.23.0",
|
|
52
52
|
"typescript": "~6.0.3",
|
|
53
53
|
"vitest": "^4.1.9"
|
|
54
54
|
},
|
package/scripts/regenerate.ts
CHANGED
|
@@ -8,11 +8,12 @@ import { Command, Flag as Options } from "effect/unstable/cli"
|
|
|
8
8
|
import { NodeRuntime, NodeServices } from "@effect/platform-node"
|
|
9
9
|
import * as NodeHttpClient from "@effect/platform-node/NodeHttpClient"
|
|
10
10
|
import * as Console from "effect/Console"
|
|
11
|
+
import * as Data from "effect/Data"
|
|
11
12
|
import * as Effect from "effect/Effect"
|
|
12
13
|
import * as FileSystem from "effect/FileSystem"
|
|
13
14
|
import * as Path from "effect/Path"
|
|
14
15
|
import * as PlatformError from "effect/PlatformError"
|
|
15
|
-
import * as
|
|
16
|
+
import * as Schema from "effect/Schema"
|
|
16
17
|
import { HttpClient } from "effect/unstable/http"
|
|
17
18
|
import * as ChildProcess from "effect/unstable/process/ChildProcess"
|
|
18
19
|
import * as ChildProcessSpawner from "effect/unstable/process/ChildProcessSpawner"
|
|
@@ -34,30 +35,48 @@ interface ScriptPaths {
|
|
|
34
35
|
readonly generatedDir: string
|
|
35
36
|
}
|
|
36
37
|
|
|
37
|
-
|
|
38
|
+
class RegenerateError extends Data.TaggedError("RegenerateError")<{
|
|
39
|
+
readonly message: string
|
|
40
|
+
readonly cause?: unknown
|
|
41
|
+
}> {}
|
|
42
|
+
|
|
43
|
+
const JsonString = Schema.fromJsonString(Schema.Json)
|
|
44
|
+
|
|
45
|
+
const SpecInfoResponse = Schema.Struct({
|
|
46
|
+
info: Schema.Struct({
|
|
47
|
+
version: Schema.String,
|
|
48
|
+
title: Schema.String
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
const fetchText = (url: string): Effect.Effect<string, RegenerateError, HttpClient.HttpClient> =>
|
|
38
53
|
HttpClient.get(url).pipe(
|
|
39
54
|
Effect.flatMap((response) =>
|
|
40
55
|
response.status >= 200 && response.status < 300
|
|
41
56
|
? response.text
|
|
42
|
-
: Effect.fail(new
|
|
57
|
+
: Effect.fail(new RegenerateError({ message: `Failed to fetch ${url}`, cause: { status: response.status } }))
|
|
43
58
|
),
|
|
44
|
-
Effect.mapError((
|
|
59
|
+
Effect.mapError((cause) => new RegenerateError({ message: `Fetch failed: ${url}`, cause }))
|
|
45
60
|
)
|
|
46
61
|
|
|
47
|
-
const
|
|
62
|
+
const fetchSpecInfo = (url: string): Effect.Effect<SpecInfo, RegenerateError, HttpClient.HttpClient> =>
|
|
48
63
|
fetchText(url).pipe(
|
|
49
|
-
Effect.flatMap((
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
catch: (e) => new Error(`JSON parse failed: ${e}`)
|
|
53
|
-
})
|
|
54
|
-
)
|
|
64
|
+
Effect.flatMap(Schema.decodeUnknownEffect(Schema.fromJsonString(SpecInfoResponse))),
|
|
65
|
+
Effect.map(({ info }) => ({ version: info.version, title: info.title })),
|
|
66
|
+
Effect.mapError((cause) => new RegenerateError({ message: "JSON decode failed", cause }))
|
|
55
67
|
)
|
|
56
68
|
|
|
57
|
-
const
|
|
69
|
+
const formatJson = (text: string): Effect.Effect<string, RegenerateError> =>
|
|
70
|
+
Schema.decodeUnknownEffect(JsonString)(text).pipe(
|
|
71
|
+
Effect.flatMap(Schema.encodeEffect(JsonString)),
|
|
72
|
+
Effect.map((encoded) => `${encoded}\n`),
|
|
73
|
+
Effect.mapError((cause) => new RegenerateError({ message: "JSON format failed", cause }))
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
const scriptPaths: Effect.Effect<ScriptPaths, RegenerateError, Path.Path> = Effect.gen(function*() {
|
|
58
77
|
const path = yield* Path.Path
|
|
59
78
|
const scriptFile = yield* path.fromFileUrl(new URL(import.meta.url)).pipe(
|
|
60
|
-
Effect.mapError((
|
|
79
|
+
Effect.mapError((cause) => new RegenerateError({ message: "Script path resolution failed", cause }))
|
|
61
80
|
)
|
|
62
81
|
const scriptDir = path.dirname(scriptFile)
|
|
63
82
|
const packageDir = path.join(scriptDir, "..")
|
|
@@ -71,50 +90,52 @@ const scriptPaths: Effect.Effect<ScriptPaths, Error, Path.Path> = Effect.gen(fun
|
|
|
71
90
|
}
|
|
72
91
|
})
|
|
73
92
|
|
|
74
|
-
const fetchSpecInfo = (url: string): Effect.Effect<SpecInfo, Error, HttpClient.HttpClient> =>
|
|
75
|
-
fetchJson<{ info: { version: string; title: string } }>(url).pipe(
|
|
76
|
-
Effect.map((spec) => ({ version: spec.info.version, title: spec.info.title }))
|
|
77
|
-
)
|
|
78
|
-
|
|
79
93
|
const fetchAndSaveSpec = (
|
|
94
|
+
packageDir: string,
|
|
80
95
|
url: string,
|
|
81
96
|
outputPath: string
|
|
82
|
-
): Effect.Effect<
|
|
97
|
+
): Effect.Effect<
|
|
98
|
+
void,
|
|
99
|
+
RegenerateError,
|
|
100
|
+
ChildProcessSpawner.ChildProcessSpawner | FileSystem.FileSystem | HttpClient.HttpClient
|
|
101
|
+
> =>
|
|
83
102
|
Effect.gen(function*() {
|
|
84
103
|
const fs = yield* FileSystem.FileSystem
|
|
85
104
|
const spec = yield* fetchText(url)
|
|
86
|
-
yield*
|
|
87
|
-
|
|
105
|
+
const formattedSpec = yield* formatJson(spec)
|
|
106
|
+
yield* fs.writeFileString(outputPath, formattedSpec).pipe(
|
|
107
|
+
Effect.mapError((cause) => new RegenerateError({ message: "Save failed", cause }))
|
|
88
108
|
)
|
|
109
|
+
yield* formatFile(packageDir, outputPath)
|
|
89
110
|
})
|
|
90
111
|
|
|
91
|
-
const readVersion = (file: string): Effect.Effect<string | null,
|
|
112
|
+
const readVersion = (file: string): Effect.Effect<string | null, RegenerateError, FileSystem.FileSystem> =>
|
|
92
113
|
Effect.gen(function*() {
|
|
93
114
|
const fs = yield* FileSystem.FileSystem
|
|
94
115
|
const exists = yield* fs.exists(file).pipe(
|
|
95
|
-
Effect.mapError((
|
|
116
|
+
Effect.mapError((cause) => new RegenerateError({ message: "Version lookup failed", cause }))
|
|
96
117
|
)
|
|
97
118
|
if (!exists) return null
|
|
98
119
|
|
|
99
120
|
return yield* fs.readFileString(file).pipe(
|
|
100
121
|
Effect.map((version) => version.trim()),
|
|
101
|
-
Effect.mapError((
|
|
122
|
+
Effect.mapError((cause) => new RegenerateError({ message: "Version read failed", cause }))
|
|
102
123
|
)
|
|
103
124
|
})
|
|
104
125
|
|
|
105
|
-
const writeVersion = (file: string, version: string): Effect.Effect<void,
|
|
126
|
+
const writeVersion = (file: string, version: string): Effect.Effect<void, RegenerateError, FileSystem.FileSystem> =>
|
|
106
127
|
Effect.gen(function*() {
|
|
107
128
|
const fs = yield* FileSystem.FileSystem
|
|
108
129
|
yield* fs.writeFileString(file, version).pipe(
|
|
109
|
-
Effect.mapError((
|
|
130
|
+
Effect.mapError((cause) => new RegenerateError({ message: "Version write failed", cause }))
|
|
110
131
|
)
|
|
111
132
|
})
|
|
112
133
|
|
|
113
|
-
const ensureDir = (dir: string): Effect.Effect<void,
|
|
134
|
+
const ensureDir = (dir: string): Effect.Effect<void, RegenerateError, FileSystem.FileSystem> =>
|
|
114
135
|
Effect.gen(function*() {
|
|
115
136
|
const fs = yield* FileSystem.FileSystem
|
|
116
137
|
yield* fs.makeDirectory(dir, { recursive: true }).pipe(
|
|
117
|
-
Effect.mapError((
|
|
138
|
+
Effect.mapError((cause) => new RegenerateError({ message: "Directory creation failed", cause }))
|
|
118
139
|
)
|
|
119
140
|
})
|
|
120
141
|
|
|
@@ -122,7 +143,7 @@ const generateTypes = (
|
|
|
122
143
|
packageDir: string,
|
|
123
144
|
generatedDir: string,
|
|
124
145
|
specPath: string
|
|
125
|
-
): Effect.Effect<void,
|
|
146
|
+
): Effect.Effect<void, RegenerateError, ChildProcessSpawner.ChildProcessSpawner | Path.Path> =>
|
|
126
147
|
Effect.gen(function*() {
|
|
127
148
|
const path = yield* Path.Path
|
|
128
149
|
const outputFile = path.join(generatedDir, "schema.d.ts")
|
|
@@ -133,11 +154,11 @@ const generateTypes = (
|
|
|
133
154
|
stderr: "inherit"
|
|
134
155
|
})
|
|
135
156
|
const exitCode = yield* commandExitCode(command).pipe(
|
|
136
|
-
Effect.mapError((
|
|
157
|
+
Effect.mapError((cause) => new RegenerateError({ message: "Type generation failed", cause }))
|
|
137
158
|
)
|
|
138
159
|
|
|
139
160
|
if (exitCode !== 0) {
|
|
140
|
-
return yield* Effect.fail(new
|
|
161
|
+
return yield* Effect.fail(new RegenerateError({ message: "Type generation failed", cause: { exitCode } }))
|
|
141
162
|
}
|
|
142
163
|
})
|
|
143
164
|
|
|
@@ -148,9 +169,25 @@ const commandExitCode = (
|
|
|
148
169
|
Effect.flatMap((spawner) => spawner.exitCode(command))
|
|
149
170
|
)
|
|
150
171
|
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
172
|
+
const formatFile = (
|
|
173
|
+
packageDir: string,
|
|
174
|
+
file: string
|
|
175
|
+
): Effect.Effect<void, RegenerateError, ChildProcessSpawner.ChildProcessSpawner> =>
|
|
176
|
+
Effect.gen(function*() {
|
|
177
|
+
const command = ChildProcess.make("pnpm", ["exec", "prettier", "--write", file], {
|
|
178
|
+
cwd: packageDir,
|
|
179
|
+
stdin: "inherit",
|
|
180
|
+
stdout: "inherit",
|
|
181
|
+
stderr: "inherit"
|
|
182
|
+
})
|
|
183
|
+
const exitCode = yield* commandExitCode(command).pipe(
|
|
184
|
+
Effect.mapError((cause) => new RegenerateError({ message: "Formatting failed", cause }))
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
if (exitCode !== 0) {
|
|
188
|
+
return yield* Effect.fail(new RegenerateError({ message: "Formatting failed", cause: { exitCode } }))
|
|
189
|
+
}
|
|
190
|
+
})
|
|
154
191
|
|
|
155
192
|
const checkOnly = Options.boolean("check").pipe(
|
|
156
193
|
Options.withDescription("Check only, exit 1 if outdated"),
|
|
@@ -179,7 +216,7 @@ const regenerate = Command.make("regenerate", { checkOnly }, ({ checkOnly }) =>
|
|
|
179
216
|
if (checkOnly) {
|
|
180
217
|
yield* Console.log("Spec is outdated!")
|
|
181
218
|
yield* Console.log(` V3: ${currentV3} -> ${v3Info.version}`)
|
|
182
|
-
return yield* Effect.fail(new
|
|
219
|
+
return yield* Effect.fail(new RegenerateError({ message: "Spec outdated" }))
|
|
183
220
|
}
|
|
184
221
|
|
|
185
222
|
yield* ensureDir(paths.specsDir)
|
|
@@ -188,7 +225,7 @@ const regenerate = Command.make("regenerate", { checkOnly }, ({ checkOnly }) =>
|
|
|
188
225
|
const specPath = path.join(paths.specsDir, `jira-v3-${v3Info.version}.json`)
|
|
189
226
|
|
|
190
227
|
yield* Console.log(`Fetching V3 spec (${v3Info.version})...`)
|
|
191
|
-
yield* fetchAndSaveSpec(SPEC_URLS.v3, specPath)
|
|
228
|
+
yield* fetchAndSaveSpec(paths.packageDir, SPEC_URLS.v3, specPath)
|
|
192
229
|
yield* Console.log(`Saved: ${specPath}`)
|
|
193
230
|
|
|
194
231
|
yield* Console.log("Generating types...")
|
|
@@ -205,10 +242,7 @@ const cli = Command.run(regenerate, {
|
|
|
205
242
|
version: pkg.version
|
|
206
243
|
})
|
|
207
244
|
|
|
208
|
-
|
|
209
|
-
const argv = yield* readArgv
|
|
210
|
-
yield* cli(argv)
|
|
211
|
-
}).pipe(
|
|
245
|
+
cli.pipe(
|
|
212
246
|
Effect.provide(NodeHttpClient.layerFetch),
|
|
213
247
|
Effect.provide(NodeServices.layer),
|
|
214
248
|
NodeRuntime.runMain
|