@ycadence/sdk 0.0.0-stage → 0.2.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/LICENSE +202 -0
- package/README.md +111 -2
- package/dist/client.d.ts +190 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/errors.d.ts +100 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +538 -0
- package/dist/index.js.map +15 -0
- package/dist/operations.d.ts +128 -0
- package/dist/operations.d.ts.map +1 -0
- package/dist/pagination.d.ts +13 -0
- package/dist/pagination.d.ts.map +1 -0
- package/dist/types.d.ts +280 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/package.json +53 -4
- package/src/client.ts +550 -0
- package/src/errors.ts +144 -0
- package/src/index.ts +37 -0
- package/src/operations.ts +74 -0
- package/src/pagination.ts +36 -0
- package/src/types.ts +364 -0
- package/src/version.ts +11 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export {
|
|
2
|
+
type ClientOptions,
|
|
3
|
+
DevPulseClient,
|
|
4
|
+
DevPulseError,
|
|
5
|
+
parseRetryAfter,
|
|
6
|
+
type RequestOptions,
|
|
7
|
+
type ResponseInfo,
|
|
8
|
+
type RetryOptions,
|
|
9
|
+
YCadenceClient,
|
|
10
|
+
} from './client.js'
|
|
11
|
+
export {
|
|
12
|
+
type ApiFailure,
|
|
13
|
+
type ApiIssue,
|
|
14
|
+
createError,
|
|
15
|
+
type ErrorExtras,
|
|
16
|
+
errorClassFor,
|
|
17
|
+
RequestIntercepted,
|
|
18
|
+
YCadenceConflictError,
|
|
19
|
+
YCadenceError,
|
|
20
|
+
YCadenceNetworkError,
|
|
21
|
+
YCadenceNotFoundError,
|
|
22
|
+
YCadencePermissionError,
|
|
23
|
+
YCadencePreconditionError,
|
|
24
|
+
YCadenceRateLimitError,
|
|
25
|
+
YCadenceValidationError,
|
|
26
|
+
} from './errors.js'
|
|
27
|
+
export {
|
|
28
|
+
buildPath,
|
|
29
|
+
type HttpMethod,
|
|
30
|
+
isIdempotentMethod,
|
|
31
|
+
OPERATIONS,
|
|
32
|
+
type Operation,
|
|
33
|
+
type OperationId,
|
|
34
|
+
} from './operations.js'
|
|
35
|
+
export { collect, paginate } from './pagination.js'
|
|
36
|
+
export * from './types.js'
|
|
37
|
+
export { SDK_VERSION } from './version.js'
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every API operation the client calls, in one table.
|
|
3
|
+
*
|
|
4
|
+
* The client builds each request from this table rather than from a path
|
|
5
|
+
* written inline in a method, so there is one place to compare with the
|
|
6
|
+
* server: `apps/web/lib/api/sdk-contract.test.ts` fails when an entry has no
|
|
7
|
+
* matching route contract (unless it is marked `pending`), and the CLI's
|
|
8
|
+
* reference and `--dry-run` name operations by these ids.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export type HttpMethod = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE'
|
|
12
|
+
|
|
13
|
+
export interface Operation {
|
|
14
|
+
method: HttpMethod
|
|
15
|
+
/** The route contract's path, with `{param}` placeholders. */
|
|
16
|
+
path: string
|
|
17
|
+
/**
|
|
18
|
+
* Planned by the work management contracts and not served yet. The client
|
|
19
|
+
* still calls it; a 404 from an older server is reported as such.
|
|
20
|
+
*/
|
|
21
|
+
pending?: string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const OPERATIONS = {
|
|
25
|
+
health: { method: 'GET', path: '/api/health' },
|
|
26
|
+
me: { method: 'GET', path: '/api/v1/me' },
|
|
27
|
+
listProjects: { method: 'GET', path: '/api/v1/projects' },
|
|
28
|
+
|
|
29
|
+
listWorkItems: { method: 'GET', path: '/api/v1/projects/{projectId}/work-items' },
|
|
30
|
+
createWorkItem: { method: 'POST', path: '/api/v1/projects/{projectId}/work-items' },
|
|
31
|
+
getWorkItem: { method: 'GET', path: '/api/v1/work-items/{workItemId}' },
|
|
32
|
+
updateWorkItem: { method: 'PATCH', path: '/api/v1/work-items/{workItemId}' },
|
|
33
|
+
deleteWorkItem: { method: 'DELETE', path: '/api/v1/work-items/{workItemId}' },
|
|
34
|
+
|
|
35
|
+
listStates: { method: 'GET', path: '/api/v1/projects/{projectId}/states' },
|
|
36
|
+
listLabels: { method: 'GET', path: '/api/v1/projects/{projectId}/labels' },
|
|
37
|
+
createLabel: { method: 'POST', path: '/api/v1/projects/{projectId}/labels' },
|
|
38
|
+
listTypes: { method: 'GET', path: '/api/v1/projects/{projectId}/types' },
|
|
39
|
+
|
|
40
|
+
listCycles: { method: 'GET', path: '/api/v1/projects/{projectId}/cycles' },
|
|
41
|
+
createCycle: { method: 'POST', path: '/api/v1/projects/{projectId}/cycles' },
|
|
42
|
+
getCycleProgress: { method: 'GET', path: '/api/v1/cycles/{cycleId}/progress' },
|
|
43
|
+
addWorkItemsToCycle: { method: 'POST', path: '/api/v1/cycles/{cycleId}/work-items' },
|
|
44
|
+
|
|
45
|
+
listViews: { method: 'GET', path: '/api/v1/projects/{projectId}/views' },
|
|
46
|
+
createView: { method: 'POST', path: '/api/v1/projects/{projectId}/views' },
|
|
47
|
+
|
|
48
|
+
listIntake: { method: 'GET', path: '/api/v1/projects/{projectId}/intake' },
|
|
49
|
+
submitIntake: { method: 'POST', path: '/api/v1/projects/{projectId}/intake' },
|
|
50
|
+
triageIntake: { method: 'POST', path: '/api/v1/intake-items/{intakeItemId}/triage' },
|
|
51
|
+
|
|
52
|
+
previewImport: { method: 'POST', path: '/api/v1/projects/{projectId}/imports/preview' },
|
|
53
|
+
startImport: { method: 'POST', path: '/api/v1/projects/{projectId}/imports' },
|
|
54
|
+
listImports: { method: 'GET', path: '/api/v1/projects/{projectId}/imports' },
|
|
55
|
+
getImport: { method: 'GET', path: '/api/v1/imports/{runId}' },
|
|
56
|
+
} as const satisfies Record<string, Operation>
|
|
57
|
+
|
|
58
|
+
export type OperationId = keyof typeof OPERATIONS
|
|
59
|
+
|
|
60
|
+
/** GET and HEAD are safe to repeat; anything else needs an idempotency key first. */
|
|
61
|
+
export function isIdempotentMethod(method: string): boolean {
|
|
62
|
+
return method === 'GET' || method === 'HEAD'
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Fill `{param}` placeholders, encoding each value. */
|
|
66
|
+
export function buildPath(template: string, params: Record<string, string> = {}): string {
|
|
67
|
+
return template.replace(/\{(\w+)\}/g, (_match, name: string) => {
|
|
68
|
+
const value = params[name]
|
|
69
|
+
if (value === undefined || value === '') {
|
|
70
|
+
throw new TypeError(`Missing path parameter "${name}" for ${template}.`)
|
|
71
|
+
}
|
|
72
|
+
return encodeURIComponent(value)
|
|
73
|
+
})
|
|
74
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Page } from './types'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Follow `nextCursor` to the end, one page at a time.
|
|
5
|
+
*
|
|
6
|
+
* Lazy: a caller that breaks out early pays for the pages it read and no more.
|
|
7
|
+
*/
|
|
8
|
+
export async function* paginate<T>(
|
|
9
|
+
fetchPage: (cursor: string | undefined) => Promise<Page<T>>,
|
|
10
|
+
options: { cursor?: string; maxItems?: number } = {}
|
|
11
|
+
): AsyncGenerator<T> {
|
|
12
|
+
let cursor = options.cursor
|
|
13
|
+
let yielded = 0
|
|
14
|
+
do {
|
|
15
|
+
const page = await fetchPage(cursor)
|
|
16
|
+
for (const item of page.items) {
|
|
17
|
+
if (options.maxItems !== undefined && yielded >= options.maxItems) return
|
|
18
|
+
yielded += 1
|
|
19
|
+
yield item
|
|
20
|
+
}
|
|
21
|
+
cursor = page.nextCursor ?? undefined
|
|
22
|
+
} while (cursor !== undefined)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Every item from {@link paginate}, as an array, up to `maxItems`. */
|
|
26
|
+
export async function collect<T>(
|
|
27
|
+
iterable: AsyncIterable<T>,
|
|
28
|
+
maxItems = Number.POSITIVE_INFINITY
|
|
29
|
+
): Promise<T[]> {
|
|
30
|
+
const items: T[] = []
|
|
31
|
+
for await (const item of iterable) {
|
|
32
|
+
if (items.length >= maxItems) break
|
|
33
|
+
items.push(item)
|
|
34
|
+
}
|
|
35
|
+
return items
|
|
36
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request and response shapes of the v1 API, as they arrive over JSON.
|
|
3
|
+
*
|
|
4
|
+
* The routes define these with zod in `apps/web` (`lib/api/contracts.ts` and
|
|
5
|
+
* the route files). The SDK is published without dependencies, so it cannot
|
|
6
|
+
* import those schemas; instead each response type has a field list below that
|
|
7
|
+
* the compiler checks against the type, and `apps/web/lib/api/sdk-contract.test.ts`
|
|
8
|
+
* checks against the route's zod schema. A field added on one side and not the
|
|
9
|
+
* other fails that test rather than reaching a user.
|
|
10
|
+
*
|
|
11
|
+
* Dates are ISO strings: that is what JSON carries.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
export type Priority = 'urgent' | 'high' | 'medium' | 'low' | 'none'
|
|
15
|
+
export const PRIORITIES: readonly Priority[] = ['urgent', 'high', 'medium', 'low', 'none']
|
|
16
|
+
|
|
17
|
+
export type StateGroup = 'backlog' | 'unstarted' | 'started' | 'completed' | 'cancelled' | 'triage'
|
|
18
|
+
|
|
19
|
+
export interface WorkItem {
|
|
20
|
+
id: string
|
|
21
|
+
key: string
|
|
22
|
+
sequenceId: number
|
|
23
|
+
name: string
|
|
24
|
+
priority: Priority
|
|
25
|
+
stateId: string | null
|
|
26
|
+
assigneeIds: string[]
|
|
27
|
+
labelIds: string[]
|
|
28
|
+
parentId: string | null
|
|
29
|
+
sortOrder: string
|
|
30
|
+
createdAt: string
|
|
31
|
+
/**
|
|
32
|
+
* Returned by `GET /work-items/{id}` (always, from Slice 2A on); not yet by
|
|
33
|
+
* lists or writes.
|
|
34
|
+
*/
|
|
35
|
+
projectId?: string
|
|
36
|
+
/** Not returned yet. Sent back as `If-Match` once the server versions items. */
|
|
37
|
+
version?: number
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface WorkItemDetail extends WorkItem {
|
|
41
|
+
/** Optional only so the SDK still reads a server older than Slice 2A. */
|
|
42
|
+
projectId?: string
|
|
43
|
+
description: string | null
|
|
44
|
+
startDate: string | null
|
|
45
|
+
targetDate: string | null
|
|
46
|
+
archivedAt: string | null
|
|
47
|
+
updatedAt: string
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface Page<T> {
|
|
51
|
+
items: T[]
|
|
52
|
+
nextCursor: string | null
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface CreateWorkItemInput {
|
|
56
|
+
name: string
|
|
57
|
+
description?: string
|
|
58
|
+
stateId?: string
|
|
59
|
+
priority?: Priority
|
|
60
|
+
assigneeIds?: string[]
|
|
61
|
+
labelIds?: string[]
|
|
62
|
+
parentId?: string
|
|
63
|
+
/** ISO date. */
|
|
64
|
+
startDate?: string
|
|
65
|
+
targetDate?: string
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* The fields PATCH accepts today. The server strips anything else, so sending
|
|
70
|
+
* an unlisted field would look like success and change nothing.
|
|
71
|
+
*/
|
|
72
|
+
export interface UpdateWorkItemInput {
|
|
73
|
+
name?: string
|
|
74
|
+
description?: string
|
|
75
|
+
stateId?: string
|
|
76
|
+
priority?: Priority
|
|
77
|
+
parentId?: string | null
|
|
78
|
+
startDate?: string | null
|
|
79
|
+
targetDate?: string | null
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface ListWorkItemsOptions {
|
|
83
|
+
/** A @devpulse/query expression; sent JSON-encoded as `filter`. */
|
|
84
|
+
filter?: unknown
|
|
85
|
+
limit?: number
|
|
86
|
+
cursor?: string
|
|
87
|
+
/** A state id. */
|
|
88
|
+
state?: string
|
|
89
|
+
priority?: Priority
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface State {
|
|
93
|
+
id: string
|
|
94
|
+
name: string
|
|
95
|
+
group: StateGroup | string
|
|
96
|
+
color: string
|
|
97
|
+
description: string | null
|
|
98
|
+
/** Fractional-index sort key; the list arrives already ordered by it. */
|
|
99
|
+
sequence: string
|
|
100
|
+
isDefault: boolean
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface Label {
|
|
104
|
+
id: string
|
|
105
|
+
name: string
|
|
106
|
+
color: string
|
|
107
|
+
description: string | null
|
|
108
|
+
sortOrder: string
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export interface Cycle {
|
|
112
|
+
id: string
|
|
113
|
+
name: string
|
|
114
|
+
description: string | null
|
|
115
|
+
startDate: string | null
|
|
116
|
+
endDate: string | null
|
|
117
|
+
status: 'draft' | 'upcoming' | 'active' | 'completed'
|
|
118
|
+
sortOrder: string
|
|
119
|
+
completedAt: string | null
|
|
120
|
+
archivedAt: string | null
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export interface CycleProgress {
|
|
124
|
+
progress: unknown
|
|
125
|
+
burndown: unknown
|
|
126
|
+
frozen: boolean
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export interface View {
|
|
130
|
+
id: string
|
|
131
|
+
name: string
|
|
132
|
+
description: string | null
|
|
133
|
+
filter: unknown
|
|
134
|
+
display: unknown
|
|
135
|
+
access: 'private' | 'public'
|
|
136
|
+
ownerId: string | null
|
|
137
|
+
sortOrder: string
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export interface CreateViewInput {
|
|
141
|
+
name: string
|
|
142
|
+
description?: string
|
|
143
|
+
where?: unknown
|
|
144
|
+
display?: Record<string, unknown>
|
|
145
|
+
access?: 'private' | 'public'
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export type IntakeStatus = 'pending' | 'accepted' | 'declined' | 'snoozed' | 'duplicate'
|
|
149
|
+
|
|
150
|
+
export interface IntakeItem {
|
|
151
|
+
id: string
|
|
152
|
+
workItemId: string
|
|
153
|
+
status: IntakeStatus
|
|
154
|
+
source: string
|
|
155
|
+
sourceEmail: string | null
|
|
156
|
+
snoozedUntil: string | null
|
|
157
|
+
submittedAt: string
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export interface SubmitIntakeInput {
|
|
161
|
+
title: string
|
|
162
|
+
description?: string
|
|
163
|
+
source?: 'in_app' | 'form' | 'email' | 'api' | 'integration'
|
|
164
|
+
sourceEmail?: string
|
|
165
|
+
extra?: Record<string, unknown>
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export interface SubmitIntakeResult {
|
|
169
|
+
intakeItemId: string
|
|
170
|
+
workItemId: string
|
|
171
|
+
sequenceId: number
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export interface TriageInput {
|
|
175
|
+
status: 'accepted' | 'declined' | 'snoozed' | 'duplicate'
|
|
176
|
+
/** ISO date; required when snoozing. */
|
|
177
|
+
snoozedUntil?: string
|
|
178
|
+
/** Required when marking a duplicate. */
|
|
179
|
+
duplicateOfId?: string
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export interface TriageResult {
|
|
183
|
+
status: string
|
|
184
|
+
movedToStateId: string | null
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export interface ImportPreview {
|
|
188
|
+
source: string
|
|
189
|
+
total: number
|
|
190
|
+
states: { name: string; suggestedStateId: string | null }[]
|
|
191
|
+
labels: { name: string; exists: boolean }[]
|
|
192
|
+
assignees: { value: string; matched: boolean }[]
|
|
193
|
+
skipped: { row: number; reason: string }[]
|
|
194
|
+
unmappedPriorities: string[]
|
|
195
|
+
/**
|
|
196
|
+
* False when re-importing would create duplicates rather than update — a CSV
|
|
197
|
+
* with no id column. Worth showing before the import, not after.
|
|
198
|
+
*/
|
|
199
|
+
idempotent: boolean
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export interface ImportRun {
|
|
203
|
+
id: string
|
|
204
|
+
source: string
|
|
205
|
+
status: string
|
|
206
|
+
totalItems: number
|
|
207
|
+
createdCount: number
|
|
208
|
+
updatedCount: number
|
|
209
|
+
cursor: number
|
|
210
|
+
skipped: { row: number; reason: string }[]
|
|
211
|
+
unmatched: { kind: string; value: string; item: string }[]
|
|
212
|
+
error: string | null
|
|
213
|
+
startedAt?: string | null
|
|
214
|
+
finishedAt?: string | null
|
|
215
|
+
createdAt?: string
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export type ImportSource = 'csv' | 'github' | 'jira' | 'linear'
|
|
219
|
+
|
|
220
|
+
export interface ImportInput {
|
|
221
|
+
source: ImportSource
|
|
222
|
+
/** CSV text, or the parsed JSON export for the API sources. */
|
|
223
|
+
data: unknown
|
|
224
|
+
repository?: string
|
|
225
|
+
baseUrl?: string
|
|
226
|
+
/** Source state name to state id. Only for `startImport`. */
|
|
227
|
+
stateMap?: Record<string, string>
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export interface Health {
|
|
231
|
+
status: string
|
|
232
|
+
checks: Record<string, string>
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/** `GET /api/v1/me`: who the credential is. Never includes the key. */
|
|
236
|
+
export interface Me {
|
|
237
|
+
principal: {
|
|
238
|
+
kind: 'personal_key' | 'service_key' | string
|
|
239
|
+
scopeType?: 'project' | 'organization' | 'personal' | string
|
|
240
|
+
apiKeyId: string
|
|
241
|
+
keyPrefix: string
|
|
242
|
+
userId: string | null
|
|
243
|
+
email: string | null
|
|
244
|
+
organizationRole?: string | null
|
|
245
|
+
}
|
|
246
|
+
organization: { id: string; slug: string; name: string }
|
|
247
|
+
project: { id: string; identifier: string; name: string } | null
|
|
248
|
+
scopes: string[]
|
|
249
|
+
expiresAt: string | null
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/** `GET /api/v1/projects`. */
|
|
253
|
+
export interface Project {
|
|
254
|
+
id: string
|
|
255
|
+
identifier: string
|
|
256
|
+
name: string
|
|
257
|
+
archivedAt: string | null
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Field lists, checked by the compiler to name every key of the type (and no
|
|
262
|
+
* others), and by the contract test to match the route's response schema.
|
|
263
|
+
*/
|
|
264
|
+
type FieldsOf<T> = { [K in keyof Required<T>]: true }
|
|
265
|
+
|
|
266
|
+
export const WORK_ITEM_FIELDS: FieldsOf<WorkItem> = {
|
|
267
|
+
id: true,
|
|
268
|
+
key: true,
|
|
269
|
+
sequenceId: true,
|
|
270
|
+
name: true,
|
|
271
|
+
priority: true,
|
|
272
|
+
stateId: true,
|
|
273
|
+
assigneeIds: true,
|
|
274
|
+
labelIds: true,
|
|
275
|
+
parentId: true,
|
|
276
|
+
sortOrder: true,
|
|
277
|
+
createdAt: true,
|
|
278
|
+
projectId: true,
|
|
279
|
+
version: true,
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
export const WORK_ITEM_DETAIL_FIELDS: FieldsOf<WorkItemDetail> = {
|
|
283
|
+
...WORK_ITEM_FIELDS,
|
|
284
|
+
description: true,
|
|
285
|
+
startDate: true,
|
|
286
|
+
targetDate: true,
|
|
287
|
+
archivedAt: true,
|
|
288
|
+
updatedAt: true,
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
export const STATE_FIELDS: FieldsOf<State> = {
|
|
292
|
+
id: true,
|
|
293
|
+
name: true,
|
|
294
|
+
group: true,
|
|
295
|
+
color: true,
|
|
296
|
+
description: true,
|
|
297
|
+
sequence: true,
|
|
298
|
+
isDefault: true,
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
export const LABEL_FIELDS: FieldsOf<Label> = {
|
|
302
|
+
id: true,
|
|
303
|
+
name: true,
|
|
304
|
+
color: true,
|
|
305
|
+
description: true,
|
|
306
|
+
sortOrder: true,
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export const CYCLE_FIELDS: FieldsOf<Cycle> = {
|
|
310
|
+
id: true,
|
|
311
|
+
name: true,
|
|
312
|
+
description: true,
|
|
313
|
+
startDate: true,
|
|
314
|
+
endDate: true,
|
|
315
|
+
status: true,
|
|
316
|
+
sortOrder: true,
|
|
317
|
+
completedAt: true,
|
|
318
|
+
archivedAt: true,
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
export const VIEW_FIELDS: FieldsOf<View> = {
|
|
322
|
+
id: true,
|
|
323
|
+
name: true,
|
|
324
|
+
description: true,
|
|
325
|
+
filter: true,
|
|
326
|
+
display: true,
|
|
327
|
+
access: true,
|
|
328
|
+
ownerId: true,
|
|
329
|
+
sortOrder: true,
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
export const INTAKE_ITEM_FIELDS: FieldsOf<IntakeItem> = {
|
|
333
|
+
id: true,
|
|
334
|
+
workItemId: true,
|
|
335
|
+
status: true,
|
|
336
|
+
source: true,
|
|
337
|
+
sourceEmail: true,
|
|
338
|
+
snoozedUntil: true,
|
|
339
|
+
submittedAt: true,
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
export const IMPORT_RUN_FIELDS: FieldsOf<ImportRun> = {
|
|
343
|
+
id: true,
|
|
344
|
+
source: true,
|
|
345
|
+
status: true,
|
|
346
|
+
totalItems: true,
|
|
347
|
+
createdCount: true,
|
|
348
|
+
updatedCount: true,
|
|
349
|
+
cursor: true,
|
|
350
|
+
skipped: true,
|
|
351
|
+
unmatched: true,
|
|
352
|
+
error: true,
|
|
353
|
+
startedAt: true,
|
|
354
|
+
finishedAt: true,
|
|
355
|
+
createdAt: true,
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Fields the SDK declares ahead of the server (the work management contracts
|
|
360
|
+
* add them). The contract test allows them to be missing from today's schemas.
|
|
361
|
+
*/
|
|
362
|
+
export const PENDING_FIELDS: Record<string, readonly string[]> = {
|
|
363
|
+
workItem: ['projectId', 'version'],
|
|
364
|
+
}
|
package/src/version.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The published version, for `User-Agent`.
|
|
3
|
+
*
|
|
4
|
+
* Replaced at build time (`bun build --define`) from package.json, so the
|
|
5
|
+
* Version PR that bumps package.json needs no second edit. Unbuilt source —
|
|
6
|
+
* tests, the workspace — reports `0.0.0-dev`.
|
|
7
|
+
*/
|
|
8
|
+
declare const __YCADENCE_SDK_VERSION__: string | undefined
|
|
9
|
+
|
|
10
|
+
export const SDK_VERSION: string =
|
|
11
|
+
typeof __YCADENCE_SDK_VERSION__ === 'string' ? __YCADENCE_SDK_VERSION__ : '0.0.0-dev'
|