@api-client/core 0.12.7 → 0.12.10

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 (62) hide show
  1. package/build/src/browser.d.ts +3 -2
  2. package/build/src/browser.d.ts.map +1 -1
  3. package/build/src/browser.js +2 -1
  4. package/build/src/browser.js.map +1 -1
  5. package/build/src/index.d.ts +3 -2
  6. package/build/src/index.d.ts.map +1 -1
  7. package/build/src/index.js +2 -1
  8. package/build/src/index.js.map +1 -1
  9. package/build/src/mocking/lib/User.d.ts.map +1 -1
  10. package/build/src/mocking/lib/User.js +1 -0
  11. package/build/src/mocking/lib/User.js.map +1 -1
  12. package/build/src/models/kinds.d.ts +2 -0
  13. package/build/src/models/kinds.d.ts.map +1 -1
  14. package/build/src/models/kinds.js +2 -0
  15. package/build/src/models/kinds.js.map +1 -1
  16. package/build/src/models/store/Invitation.d.ts +146 -0
  17. package/build/src/models/store/Invitation.d.ts.map +1 -0
  18. package/build/src/models/store/Invitation.js +186 -0
  19. package/build/src/models/store/Invitation.js.map +1 -0
  20. package/build/src/models/store/Organization.d.ts +4 -4
  21. package/build/src/models/store/Organization.d.ts.map +1 -1
  22. package/build/src/models/store/Organization.js +9 -9
  23. package/build/src/models/store/Organization.js.map +1 -1
  24. package/build/src/models/store/User.d.ts +14 -0
  25. package/build/src/models/store/User.d.ts.map +1 -1
  26. package/build/src/models/store/User.js.map +1 -1
  27. package/build/src/runtime/store/HttpWeb.js +5 -5
  28. package/build/src/runtime/store/HttpWeb.js.map +1 -1
  29. package/build/src/runtime/store/OrganizationsSdk.d.ts +77 -2
  30. package/build/src/runtime/store/OrganizationsSdk.d.ts.map +1 -1
  31. package/build/src/runtime/store/OrganizationsSdk.js +278 -3
  32. package/build/src/runtime/store/OrganizationsSdk.js.map +1 -1
  33. package/build/src/runtime/store/RouteBuilder.d.ts +15 -2
  34. package/build/src/runtime/store/RouteBuilder.d.ts.map +1 -1
  35. package/build/src/runtime/store/RouteBuilder.js +33 -6
  36. package/build/src/runtime/store/RouteBuilder.js.map +1 -1
  37. package/build/src/runtime/store/Sdk.d.ts +1 -1
  38. package/build/src/runtime/store/Sdk.d.ts.map +1 -1
  39. package/build/src/runtime/store/Sdk.js +1 -1
  40. package/build/src/runtime/store/Sdk.js.map +1 -1
  41. package/build/src/runtime/store/SdkBase.d.ts +2 -2
  42. package/build/src/runtime/store/SdkBase.d.ts.map +1 -1
  43. package/build/src/runtime/store/SdkBase.js +2 -2
  44. package/build/src/runtime/store/SdkBase.js.map +1 -1
  45. package/build/src/runtime/store/UsersSdk.d.ts +2 -0
  46. package/build/src/runtime/store/UsersSdk.d.ts.map +1 -1
  47. package/build/src/runtime/store/UsersSdk.js +6 -0
  48. package/build/src/runtime/store/UsersSdk.js.map +1 -1
  49. package/eslint.config.js +6 -5
  50. package/package.json +23 -5
  51. package/src/mocking/lib/User.ts +1 -0
  52. package/src/models/kinds.ts +2 -0
  53. package/src/models/store/Invitation.ts +287 -0
  54. package/src/models/store/Organization.ts +11 -12
  55. package/src/models/store/User.ts +16 -0
  56. package/src/runtime/store/HttpWeb.ts +5 -5
  57. package/src/runtime/store/OrganizationsSdk.ts +293 -5
  58. package/src/runtime/store/RouteBuilder.ts +42 -8
  59. package/src/runtime/store/Sdk.ts +1 -1
  60. package/src/runtime/store/SdkBase.ts +2 -2
  61. package/src/runtime/store/UsersSdk.ts +6 -0
  62. package/tests/unit/models/store/Invitation.spec.ts +223 -0
@@ -0,0 +1,287 @@
1
+ import { nanoid } from 'nanoid'
2
+ import { InvitationKind } from '../kinds.js'
3
+ import type { IDeletion } from './Deletion.js'
4
+ import type { UserOrganizationGrantType } from './Organization.js'
5
+ import type { Operation } from '@api-client/json/types.js'
6
+ import { Builder } from '@api-client/json/patch/builder.js'
7
+
8
+ /**
9
+ * The status of an invitation.
10
+ * - `pending`: The invitation has been sent but not yet responded to.
11
+ * - `accepted`: The invitation has been accepted by the user.
12
+ * - `declined`: The invitation has been declined by the user.
13
+ */
14
+ export type InvitationStatus = 'pending' | 'accepted' | 'declined'
15
+
16
+ /**
17
+ * The schema for an invitation.
18
+ * This defines the structure of an invitation object in the system.
19
+ */
20
+ export interface InvitationSchema {
21
+ /**
22
+ * The kind of the invitation.
23
+ */
24
+ kind: typeof InvitationKind
25
+ /**
26
+ * The database ID of the invitation.
27
+ */
28
+ key: string
29
+ /**
30
+ * The user ID of the user who sent the invitation.
31
+ */
32
+ uid: string
33
+ /**
34
+ * The organization ID to which the invitation belongs.
35
+ */
36
+ oid: string
37
+ /**
38
+ * The email address of the user to whom the invitation is sent.
39
+ */
40
+ email: string
41
+ /**
42
+ * The name of the user to whom the invitation is sent.
43
+ * This is optional and can be empty if the user is not known.
44
+ */
45
+ name?: string
46
+ /**
47
+ * The token used to respond to the invitation.
48
+ */
49
+ token: string
50
+ /**
51
+ * The timestamp when the invitation expires.
52
+ * This is used to determine if the invitation is still valid.
53
+ */
54
+ expiresAt: number
55
+ /**
56
+ * The timestamp when the invitation was responded to.
57
+ * This is set when the user accepts or declines the invitation.
58
+ */
59
+ respondedAt?: number
60
+ /**
61
+ * The status of the invitation.
62
+ */
63
+ status: InvitationStatus
64
+ /**
65
+ * The grant type the user will have in the organization if they accept the invitation.
66
+ */
67
+ grantType: UserOrganizationGrantType
68
+ /**
69
+ * Whether the file object is deleted.
70
+ */
71
+ deleted?: boolean
72
+ /**
73
+ * The information about the delete information.
74
+ * Always set when the `delete` is true.
75
+ */
76
+ deletedInfo?: IDeletion
77
+ /**
78
+ * The timestamp when the invitation was created.
79
+ */
80
+ createdAt: number
81
+ /**
82
+ * The timestamp when the invitation was last updated.
83
+ */
84
+ updatedAt: number
85
+ }
86
+
87
+ /**
88
+ * Represents an invitation to join an organization.
89
+ * This class implements the `InvitationSchema` interface and provides methods to create and manipulate invitations.
90
+ */
91
+ export class Invitation implements InvitationSchema {
92
+ kind: typeof InvitationKind
93
+ key: string
94
+ uid: string
95
+ oid: string
96
+ email: string
97
+ name: string | undefined
98
+ token: string
99
+ expiresAt: number
100
+ respondedAt: number | undefined
101
+ status: InvitationStatus
102
+ grantType: UserOrganizationGrantType
103
+ deleted: boolean
104
+ deletedInfo: IDeletion | undefined
105
+ createdAt: number
106
+ updatedAt: number
107
+
108
+ #builder?: Builder<InvitationSchema>
109
+
110
+ /**
111
+ * The patch builder for this invitation.
112
+ */
113
+ get builder(): Builder<InvitationSchema> {
114
+ if (!this.#builder) {
115
+ this.#builder = new Builder(this.toJSON())
116
+ }
117
+ return this.#builder
118
+ }
119
+
120
+ /**
121
+ * Creates a full invitation schema with defaults.
122
+ *
123
+ * @param input The partial invitation schema.
124
+ * @returns The invitation schema.
125
+ */
126
+ static createSchema(input: Partial<InvitationSchema> = {}): InvitationSchema {
127
+ const {
128
+ key = nanoid(),
129
+ email,
130
+ oid,
131
+ grantType,
132
+ uid = '',
133
+ updatedAt = 0,
134
+ createdAt = 0,
135
+ expiresAt = 0,
136
+ status = 'pending',
137
+ token = '',
138
+ } = input
139
+ if (!email) {
140
+ throw new Error('Email is required to create an invitation schema.')
141
+ }
142
+ if (!oid) {
143
+ throw new Error('Organization ID is required to create an invitation schema.')
144
+ }
145
+ if (!grantType) {
146
+ throw new Error('Grant type is required to create an invitation schema.')
147
+ }
148
+ const result: InvitationSchema = {
149
+ kind: InvitationKind,
150
+ key,
151
+ uid,
152
+ oid,
153
+ email,
154
+ grantType,
155
+ token,
156
+ expiresAt,
157
+ status,
158
+ createdAt,
159
+ updatedAt,
160
+ }
161
+ if (input.name) {
162
+ result.name = input.name
163
+ }
164
+ if (input.token) {
165
+ result.token = input.token
166
+ }
167
+ if (input.expiresAt) {
168
+ result.expiresAt = input.expiresAt
169
+ }
170
+ if (input.respondedAt) {
171
+ result.respondedAt = input.respondedAt
172
+ }
173
+ if (input.status) {
174
+ result.status = input.status
175
+ }
176
+ if (input.deleted) {
177
+ result.deleted = input.deleted
178
+ result.deletedInfo = input.deletedInfo
179
+ }
180
+ return result
181
+ }
182
+
183
+ constructor(input?: Partial<InvitationSchema>) {
184
+ const init: InvitationSchema = Invitation.createSchema(input)
185
+ this.kind = InvitationKind
186
+ this.key = init.key
187
+ this.uid = init.uid
188
+ this.oid = init.oid
189
+ this.email = init.email
190
+ this.name = init.name
191
+ this.token = init.token
192
+ this.expiresAt = init.expiresAt
193
+ this.respondedAt = init.respondedAt
194
+ this.status = init.status
195
+ this.grantType = init.grantType
196
+ this.deleted = init.deleted || false
197
+ this.deletedInfo = init.deletedInfo
198
+ this.createdAt = init.createdAt
199
+ this.updatedAt = init.updatedAt
200
+ }
201
+
202
+ toJSON(): InvitationSchema {
203
+ const result: InvitationSchema = {
204
+ kind: this.kind,
205
+ key: this.key,
206
+ uid: this.uid,
207
+ oid: this.oid,
208
+ email: this.email,
209
+ token: this.token,
210
+ expiresAt: this.expiresAt,
211
+ status: this.status,
212
+ grantType: this.grantType,
213
+ deleted: this.deleted,
214
+ createdAt: this.createdAt,
215
+ updatedAt: this.updatedAt,
216
+ }
217
+ if (this.name) {
218
+ result.name = this.name
219
+ }
220
+ if (this.respondedAt) {
221
+ result.respondedAt = this.respondedAt
222
+ }
223
+ if (this.deletedInfo) {
224
+ result.deletedInfo = { ...this.deletedInfo }
225
+ }
226
+ return result
227
+ }
228
+
229
+ /**
230
+ * Retrieves the patch operations for this invitation.
231
+ * This method builds a JSON Patch representation of the invitation,
232
+ * which can be used to update the invitation in a database or API.
233
+ *
234
+ * Use one of the `set*` methods to modify the invitation before calling this method.
235
+ *
236
+ * @returns An array of patch operations.
237
+ * If no changes have been made, it returns an empty array.
238
+ */
239
+ getPatch(): Operation[] {
240
+ if (!this.#builder) {
241
+ return []
242
+ }
243
+ return this.builder.build()
244
+ }
245
+
246
+ /**
247
+ * Sets the name of the user to whom the invitation is sent.
248
+ * If the name is the same as the current name, no operation is performed.
249
+ *
250
+ * @param name The name to set. If undefined, it will be removed.
251
+ */
252
+ setName(name?: string): void {
253
+ if (name === this.name) {
254
+ return
255
+ }
256
+ const hasName = !!this.name
257
+ if (hasName && !name) {
258
+ this.builder.remove('/name')
259
+ } else {
260
+ // The add method handles both adding and replacing
261
+ this.builder.add('/name', name)
262
+ }
263
+ this.name = name
264
+ }
265
+
266
+ /**
267
+ * Sets the expiration timestamp of the invitation.
268
+ * @param expiresAt The timestamp when the invitation expires.
269
+ * If the expiresAt is the same as the current expiresAt, no operation is performed.
270
+ */
271
+ setExpiresAt(expiresAt: number): void {
272
+ if (this.expiresAt !== expiresAt) {
273
+ this.builder.replace('/expiresAt', expiresAt)
274
+ this.expiresAt = expiresAt
275
+ }
276
+ }
277
+
278
+ /**
279
+ * Sets the grant type of the user in the organization.
280
+ */
281
+ setGrantType(grantType: UserOrganizationGrantType): void {
282
+ if (this.grantType !== grantType) {
283
+ this.builder.replace('/grantType', grantType)
284
+ this.grantType = grantType
285
+ }
286
+ }
287
+ }
@@ -1,9 +1,8 @@
1
1
  import { nanoid } from 'nanoid'
2
2
  import type { IDeletion } from './Deletion.js'
3
+ import { OrganizationKind } from '../kinds.js'
3
4
 
4
- export const Kind = 'Core#Organization'
5
-
6
- export type UserOrganizationGrantType = 'owner' | 'member'
5
+ export type UserOrganizationGrantType = 'owner' | 'manager' | 'editor' | 'viewer'
7
6
 
8
7
  /**
9
8
  * In the system the user identity represents registration information associated with a specific identity provider.
@@ -11,7 +10,7 @@ export type UserOrganizationGrantType = 'owner' | 'member'
11
10
  * email stays consistent.
12
11
  */
13
12
  export interface IOrganization {
14
- kind: typeof Kind
13
+ kind: typeof OrganizationKind
15
14
  /**
16
15
  * The database ID
17
16
  */
@@ -45,14 +44,14 @@ export interface IOrganization {
45
44
  }
46
45
 
47
46
  export class Organization implements IOrganization {
48
- kind: typeof Kind = Kind
47
+ kind: typeof OrganizationKind = OrganizationKind
49
48
  key = ''
50
49
  name = ''
51
50
  createdBy = ''
52
51
  createdDate = 0
53
52
  deleted = false
54
53
  deletedInfo?: IDeletion
55
- grantType: UserOrganizationGrantType = 'member'
54
+ grantType: UserOrganizationGrantType = 'viewer'
56
55
 
57
56
  constructor(input?: string | IOrganization) {
58
57
  let init: IOrganization
@@ -62,13 +61,13 @@ export class Organization implements IOrganization {
62
61
  init = input
63
62
  } else {
64
63
  init = {
65
- kind: Kind,
64
+ kind: OrganizationKind,
66
65
  key: nanoid(),
67
66
  name: '',
68
67
  createdBy: '',
69
68
  createdDate: Date.now(),
70
69
  deleted: false,
71
- grantType: 'member',
70
+ grantType: 'viewer',
72
71
  }
73
72
  }
74
73
  this.new(init)
@@ -85,9 +84,9 @@ export class Organization implements IOrganization {
85
84
  createdDate = Date.now(),
86
85
  deleted = false,
87
86
  deletedInfo,
88
- grantType = 'member',
87
+ grantType = 'viewer',
89
88
  } = init
90
- this.kind = Kind
89
+ this.kind = OrganizationKind
91
90
  this.key = key
92
91
  this.name = name
93
92
  this.createdBy = createdBy
@@ -106,7 +105,7 @@ export class Organization implements IOrganization {
106
105
  */
107
106
  static isOrganization(input: unknown): boolean {
108
107
  const typed = input as IOrganization
109
- if (!input || typed.kind !== Kind) {
108
+ if (!input || typed.kind !== OrganizationKind) {
110
109
  return false
111
110
  }
112
111
  return true
@@ -114,7 +113,7 @@ export class Organization implements IOrganization {
114
113
 
115
114
  toJSON(): IOrganization {
116
115
  const result: IOrganization = {
117
- kind: Kind,
116
+ kind: OrganizationKind,
118
117
  key: this.key,
119
118
  name: this.name,
120
119
  createdBy: this.createdBy,
@@ -1,3 +1,5 @@
1
+ import type { UserOrganizationGrantType } from './Organization.js'
2
+
1
3
  export interface IEmail {
2
4
  /**
3
5
  * When available the email of the user.
@@ -23,6 +25,8 @@ export interface IUserPicture {
23
25
 
24
26
  export const Kind = 'Core#User'
25
27
 
28
+ export type UserStatus = 'active' | 'deleted' | 'suspended' | 'pending'
29
+
26
30
  /**
27
31
  * Represents a user in the system.
28
32
  * This can be embedded in various situations like project's revision history,
@@ -63,6 +67,7 @@ export interface IUser {
63
67
  provider?: unknown
64
68
  /**
65
69
  * Whether the user is deleted from the system.
70
+ * @deprecated Use `status` instead.
66
71
  */
67
72
  deleted?: boolean
68
73
  /**
@@ -73,4 +78,15 @@ export interface IUser {
73
78
  * The id of the user that deleted the user.
74
79
  */
75
80
  deletingUser?: string
81
+ /**
82
+ * The status of the user.
83
+ * May not be populated in all cases.
84
+ * @default 'active'
85
+ */
86
+ status?: UserStatus
87
+ /**
88
+ * Populated when the user object is considered in the context of an organization.
89
+ * This is used to determine the user's role in the organization.
90
+ */
91
+ grantType?: UserOrganizationGrantType
76
92
  }
@@ -11,14 +11,14 @@ export class HttpWeb extends Http {
11
11
  * @returns The response info.
12
12
  */
13
13
  async get(url: string, opts: IStoreRequestOptions = {}): Promise<IStoreResponse> {
14
- const { method = 'GET', headers = {}, token } = opts
15
- const httpHeaders = { ...headers }
14
+ const { method = 'GET', headers = {}, token = this.sdk.token } = opts
15
+ const requestHeaders = new Headers({ ...headers })
16
16
  if (token) {
17
- httpHeaders.authorization = `Bearer ${token}`
17
+ requestHeaders.append('Authorization', `Bearer ${token}`)
18
18
  }
19
19
  const init: RequestInit = {
20
20
  method,
21
- headers: httpHeaders,
21
+ headers: requestHeaders.toJSON(),
22
22
  redirect: 'follow',
23
23
  credentials: 'include',
24
24
  mode: 'cors',
@@ -45,7 +45,7 @@ export class HttpWeb extends Http {
45
45
  }
46
46
 
47
47
  async post(url: string, opts: IStoreRequestOptions = {}): Promise<IStoreResponse> {
48
- const { method = 'POST', headers = {}, token } = opts
48
+ const { method = 'POST', headers = {}, token = this.sdk.token } = opts
49
49
  const requestHeaders = new Headers({ ...headers })
50
50
  if (token) {
51
51
  requestHeaders.append('Authorization', `Bearer ${token}`)