@arke-institute/sdk 0.1.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/README.md +258 -0
- package/dist/collections/index.d.mts +1 -0
- package/dist/collections/index.d.ts +1 -0
- package/dist/collections/index.js +232 -0
- package/dist/collections/index.js.map +1 -0
- package/dist/collections/index.mjs +204 -0
- package/dist/collections/index.mjs.map +1 -0
- package/dist/index.d.mts +189 -0
- package/dist/index.d.ts +189 -0
- package/dist/index.js +232 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +204 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +53 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
// src/collections/errors.ts
|
|
2
|
+
var CollectionsError = class extends Error {
|
|
3
|
+
constructor(message, code = "UNKNOWN_ERROR", details) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.code = code;
|
|
6
|
+
this.details = details;
|
|
7
|
+
this.name = "CollectionsError";
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// src/collections/client.ts
|
|
12
|
+
var CollectionsClient = class {
|
|
13
|
+
constructor(config) {
|
|
14
|
+
this.baseUrl = config.gatewayUrl.replace(/\/$/, "");
|
|
15
|
+
this.authToken = config.authToken;
|
|
16
|
+
this.fetchImpl = config.fetchImpl ?? fetch;
|
|
17
|
+
}
|
|
18
|
+
setAuthToken(token) {
|
|
19
|
+
this.authToken = token;
|
|
20
|
+
}
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Request helpers
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
buildUrl(path, query) {
|
|
25
|
+
const url = new URL(`${this.baseUrl}${path}`);
|
|
26
|
+
if (query) {
|
|
27
|
+
Object.entries(query).forEach(([key, value]) => {
|
|
28
|
+
if (value !== void 0 && value !== null) {
|
|
29
|
+
url.searchParams.set(key, String(value));
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
return url.toString();
|
|
34
|
+
}
|
|
35
|
+
getHeaders(authRequired) {
|
|
36
|
+
const headers = { "Content-Type": "application/json" };
|
|
37
|
+
if (authRequired || this.authToken) {
|
|
38
|
+
if (!this.authToken && authRequired) {
|
|
39
|
+
throw new CollectionsError("Authentication required for this operation", "AUTH_REQUIRED");
|
|
40
|
+
}
|
|
41
|
+
if (this.authToken) {
|
|
42
|
+
headers["Authorization"] = `Bearer ${this.authToken}`;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return headers;
|
|
46
|
+
}
|
|
47
|
+
async request(path, options = {}) {
|
|
48
|
+
const authRequired = options.authRequired ?? false;
|
|
49
|
+
const url = this.buildUrl(path, options.query);
|
|
50
|
+
const headers = new Headers(this.getHeaders(authRequired));
|
|
51
|
+
if (options.headers) {
|
|
52
|
+
Object.entries(options.headers).forEach(([k, v]) => {
|
|
53
|
+
if (v !== void 0) headers.set(k, v);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
const response = await this.fetchImpl(url, { ...options, headers });
|
|
57
|
+
if (response.ok) {
|
|
58
|
+
if (response.status === 204) {
|
|
59
|
+
return void 0;
|
|
60
|
+
}
|
|
61
|
+
const contentType = response.headers.get("content-type") || "";
|
|
62
|
+
if (contentType.includes("application/json")) {
|
|
63
|
+
return await response.json();
|
|
64
|
+
}
|
|
65
|
+
return await response.text();
|
|
66
|
+
}
|
|
67
|
+
let body;
|
|
68
|
+
try {
|
|
69
|
+
body = await response.json();
|
|
70
|
+
} catch {
|
|
71
|
+
body = await response.text();
|
|
72
|
+
}
|
|
73
|
+
const message = body?.error && typeof body.error === "string" ? body.error : `Request failed with status ${response.status}`;
|
|
74
|
+
throw new CollectionsError(message, "HTTP_ERROR", {
|
|
75
|
+
status: response.status,
|
|
76
|
+
body
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
// Collections
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
async listCollections(params) {
|
|
83
|
+
return this.request("/collections", {
|
|
84
|
+
method: "GET",
|
|
85
|
+
query: { limit: params?.limit, offset: params?.offset }
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
async getCollection(id) {
|
|
89
|
+
return this.request(`/collections/${id}`, { method: "GET" });
|
|
90
|
+
}
|
|
91
|
+
async getCollectionRoot(id) {
|
|
92
|
+
return this.request(`/collections/${id}/root`, { method: "GET" });
|
|
93
|
+
}
|
|
94
|
+
async getMyAccess(id) {
|
|
95
|
+
return this.request(`/collections/${id}/my-access`, { method: "GET", authRequired: true });
|
|
96
|
+
}
|
|
97
|
+
async createCollection(payload) {
|
|
98
|
+
return this.request("/collections", {
|
|
99
|
+
method: "POST",
|
|
100
|
+
authRequired: true,
|
|
101
|
+
body: JSON.stringify(payload)
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
async registerRoot(payload) {
|
|
105
|
+
return this.request("/collections/register-root", {
|
|
106
|
+
method: "POST",
|
|
107
|
+
authRequired: true,
|
|
108
|
+
body: JSON.stringify(payload)
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
async updateCollection(id, payload) {
|
|
112
|
+
return this.request(`/collections/${id}`, {
|
|
113
|
+
method: "PATCH",
|
|
114
|
+
authRequired: true,
|
|
115
|
+
body: JSON.stringify(payload)
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
async changeRoot(id, payload) {
|
|
119
|
+
return this.request(`/collections/${id}/change-root`, {
|
|
120
|
+
method: "PATCH",
|
|
121
|
+
authRequired: true,
|
|
122
|
+
body: JSON.stringify(payload)
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
async deleteCollection(id) {
|
|
126
|
+
return this.request(`/collections/${id}`, {
|
|
127
|
+
method: "DELETE",
|
|
128
|
+
authRequired: true
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
// ---------------------------------------------------------------------------
|
|
132
|
+
// Members
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
async listMembers(collectionId) {
|
|
135
|
+
return this.request(`/collections/${collectionId}/members`, { method: "GET" });
|
|
136
|
+
}
|
|
137
|
+
async updateMemberRole(collectionId, userId, role) {
|
|
138
|
+
return this.request(`/collections/${collectionId}/members/${userId}`, {
|
|
139
|
+
method: "PATCH",
|
|
140
|
+
authRequired: true,
|
|
141
|
+
body: JSON.stringify({ role })
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
async removeMember(collectionId, userId) {
|
|
145
|
+
return this.request(`/collections/${collectionId}/members/${userId}`, {
|
|
146
|
+
method: "DELETE",
|
|
147
|
+
authRequired: true
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
// ---------------------------------------------------------------------------
|
|
151
|
+
// Invitations
|
|
152
|
+
// ---------------------------------------------------------------------------
|
|
153
|
+
async createInvitation(collectionId, email, role) {
|
|
154
|
+
return this.request(`/collections/${collectionId}/invitations`, {
|
|
155
|
+
method: "POST",
|
|
156
|
+
authRequired: true,
|
|
157
|
+
body: JSON.stringify({ email, role })
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
async listInvitations(collectionId) {
|
|
161
|
+
return this.request(`/collections/${collectionId}/invitations`, {
|
|
162
|
+
method: "GET",
|
|
163
|
+
authRequired: true
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
async acceptInvitation(invitationId) {
|
|
167
|
+
return this.request(`/invitations/${invitationId}/accept`, {
|
|
168
|
+
method: "POST",
|
|
169
|
+
authRequired: true
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
async declineInvitation(invitationId) {
|
|
173
|
+
return this.request(`/invitations/${invitationId}/decline`, {
|
|
174
|
+
method: "POST",
|
|
175
|
+
authRequired: true
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
async revokeInvitation(invitationId) {
|
|
179
|
+
return this.request(`/invitations/${invitationId}`, {
|
|
180
|
+
method: "DELETE",
|
|
181
|
+
authRequired: true
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
// ---------------------------------------------------------------------------
|
|
185
|
+
// Current user
|
|
186
|
+
// ---------------------------------------------------------------------------
|
|
187
|
+
async getMyCollections() {
|
|
188
|
+
return this.request("/me/collections", { method: "GET", authRequired: true });
|
|
189
|
+
}
|
|
190
|
+
async getMyInvitations() {
|
|
191
|
+
return this.request("/me/invitations", { method: "GET", authRequired: true });
|
|
192
|
+
}
|
|
193
|
+
// ---------------------------------------------------------------------------
|
|
194
|
+
// PI permissions
|
|
195
|
+
// ---------------------------------------------------------------------------
|
|
196
|
+
async getPiPermissions(pi) {
|
|
197
|
+
return this.request(`/pi/${pi}/permissions`, { method: "GET" });
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
export {
|
|
201
|
+
CollectionsClient,
|
|
202
|
+
CollectionsError
|
|
203
|
+
};
|
|
204
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/collections/errors.ts","../../src/collections/client.ts"],"sourcesContent":["export class CollectionsError extends Error {\n constructor(\n message: string,\n public code: string = 'UNKNOWN_ERROR',\n public details?: unknown\n ) {\n super(message);\n this.name = 'CollectionsError';\n }\n}\n","import { CollectionsError } from './errors';\nimport type {\n ChangeRootPayload,\n ChangeRootResponse,\n Collection,\n CollectionDetails,\n CollectionRole,\n CreateCollectionPayload,\n Invitation,\n InvitationsResponse,\n Member,\n MembersResponse,\n MyAccessResponse,\n MyCollectionsResponse,\n PaginatedCollections,\n PiPermissions,\n RegisterRootPayload,\n RootResponse,\n SuccessResponse,\n UpdateCollectionPayload,\n} from './types';\n\nexport interface CollectionsClientConfig {\n /**\n * Gateway base URL (e.g., https://api.arke.institute).\n * Must already point at the Arke gateway that proxies /collections/*.\n */\n gatewayUrl: string;\n /**\n * Optional bearer token for authenticated routes.\n * Public routes will still include it if provided.\n */\n authToken?: string;\n /**\n * Optional custom fetch (useful for testing).\n */\n fetchImpl?: typeof fetch;\n}\n\ntype JsonBody = Record<string, unknown>;\n\nexport class CollectionsClient {\n private baseUrl: string;\n private authToken?: string;\n private fetchImpl: typeof fetch;\n\n constructor(config: CollectionsClientConfig) {\n this.baseUrl = config.gatewayUrl.replace(/\\/$/, '');\n this.authToken = config.authToken;\n this.fetchImpl = config.fetchImpl ?? fetch;\n }\n\n setAuthToken(token?: string) {\n this.authToken = token;\n }\n\n // ---------------------------------------------------------------------------\n // Request helpers\n // ---------------------------------------------------------------------------\n\n private buildUrl(path: string, query?: Record<string, string | number | undefined>) {\n const url = new URL(`${this.baseUrl}${path}`);\n if (query) {\n Object.entries(query).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, String(value));\n }\n });\n }\n return url.toString();\n }\n\n private getHeaders(authRequired: boolean): HeadersInit {\n const headers: HeadersInit = { 'Content-Type': 'application/json' };\n if (authRequired || this.authToken) {\n if (!this.authToken && authRequired) {\n throw new CollectionsError('Authentication required for this operation', 'AUTH_REQUIRED');\n }\n if (this.authToken) {\n headers['Authorization'] = `Bearer ${this.authToken}`;\n }\n }\n return headers;\n }\n\n private async request<T>(\n path: string,\n options: RequestInit & {\n authRequired?: boolean;\n query?: Record<string, string | number | undefined>;\n } = {}\n ): Promise<T> {\n const authRequired = options.authRequired ?? false;\n const url = this.buildUrl(path, options.query);\n const headers = new Headers(this.getHeaders(authRequired));\n if (options.headers) {\n Object.entries(options.headers).forEach(([k, v]) => {\n if (v !== undefined) headers.set(k, v as string);\n });\n }\n\n const response = await this.fetchImpl(url, { ...options, headers });\n\n if (response.ok) {\n if (response.status === 204) {\n return undefined as T;\n }\n const contentType = response.headers.get('content-type') || '';\n if (contentType.includes('application/json')) {\n return (await response.json()) as T;\n }\n return (await response.text()) as unknown as T;\n }\n\n let body: unknown;\n try {\n body = await response.json();\n } catch {\n body = await response.text();\n }\n\n const message =\n (body as JsonBody)?.error && typeof (body as JsonBody).error === 'string'\n ? ((body as JsonBody).error as string)\n : `Request failed with status ${response.status}`;\n\n throw new CollectionsError(message, 'HTTP_ERROR', {\n status: response.status,\n body,\n });\n }\n\n // ---------------------------------------------------------------------------\n // Collections\n // ---------------------------------------------------------------------------\n\n async listCollections(params?: { limit?: number; offset?: number }): Promise<PaginatedCollections> {\n return this.request('/collections', {\n method: 'GET',\n query: { limit: params?.limit, offset: params?.offset },\n });\n }\n\n async getCollection(id: string): Promise<CollectionDetails> {\n return this.request(`/collections/${id}`, { method: 'GET' });\n }\n\n async getCollectionRoot(id: string): Promise<RootResponse> {\n return this.request(`/collections/${id}/root`, { method: 'GET' });\n }\n\n async getMyAccess(id: string): Promise<MyAccessResponse> {\n return this.request(`/collections/${id}/my-access`, { method: 'GET', authRequired: true });\n }\n\n async createCollection(payload: CreateCollectionPayload): Promise<Collection> {\n return this.request('/collections', {\n method: 'POST',\n authRequired: true,\n body: JSON.stringify(payload),\n });\n }\n\n async registerRoot(payload: RegisterRootPayload): Promise<Collection & { rootPi: string }> {\n return this.request('/collections/register-root', {\n method: 'POST',\n authRequired: true,\n body: JSON.stringify(payload),\n });\n }\n\n async updateCollection(id: string, payload: UpdateCollectionPayload): Promise<Collection> {\n return this.request(`/collections/${id}`, {\n method: 'PATCH',\n authRequired: true,\n body: JSON.stringify(payload),\n });\n }\n\n async changeRoot(id: string, payload: ChangeRootPayload): Promise<ChangeRootResponse> {\n return this.request(`/collections/${id}/change-root`, {\n method: 'PATCH',\n authRequired: true,\n body: JSON.stringify(payload),\n });\n }\n\n async deleteCollection(id: string): Promise<SuccessResponse> {\n return this.request(`/collections/${id}`, {\n method: 'DELETE',\n authRequired: true,\n });\n }\n\n // ---------------------------------------------------------------------------\n // Members\n // ---------------------------------------------------------------------------\n\n async listMembers(collectionId: string): Promise<MembersResponse> {\n return this.request(`/collections/${collectionId}/members`, { method: 'GET' });\n }\n\n async updateMemberRole(\n collectionId: string,\n userId: string,\n role: CollectionRole\n ): Promise<{ success: true; role: CollectionRole }> {\n return this.request(`/collections/${collectionId}/members/${userId}`, {\n method: 'PATCH',\n authRequired: true,\n body: JSON.stringify({ role }),\n });\n }\n\n async removeMember(collectionId: string, userId: string): Promise<SuccessResponse> {\n return this.request(`/collections/${collectionId}/members/${userId}`, {\n method: 'DELETE',\n authRequired: true,\n });\n }\n\n // ---------------------------------------------------------------------------\n // Invitations\n // ---------------------------------------------------------------------------\n\n async createInvitation(collectionId: string, email: string, role: CollectionRole): Promise<Invitation> {\n return this.request(`/collections/${collectionId}/invitations`, {\n method: 'POST',\n authRequired: true,\n body: JSON.stringify({ email, role }),\n });\n }\n\n async listInvitations(collectionId: string): Promise<InvitationsResponse> {\n return this.request(`/collections/${collectionId}/invitations`, {\n method: 'GET',\n authRequired: true,\n });\n }\n\n async acceptInvitation(invitationId: string): Promise<{ success: true; role: CollectionRole }> {\n return this.request(`/invitations/${invitationId}/accept`, {\n method: 'POST',\n authRequired: true,\n });\n }\n\n async declineInvitation(invitationId: string): Promise<SuccessResponse> {\n return this.request(`/invitations/${invitationId}/decline`, {\n method: 'POST',\n authRequired: true,\n });\n }\n\n async revokeInvitation(invitationId: string): Promise<SuccessResponse> {\n return this.request(`/invitations/${invitationId}`, {\n method: 'DELETE',\n authRequired: true,\n });\n }\n\n // ---------------------------------------------------------------------------\n // Current user\n // ---------------------------------------------------------------------------\n\n async getMyCollections(): Promise<MyCollectionsResponse> {\n return this.request('/me/collections', { method: 'GET', authRequired: true });\n }\n\n async getMyInvitations(): Promise<InvitationsResponse> {\n return this.request('/me/invitations', { method: 'GET', authRequired: true });\n }\n\n // ---------------------------------------------------------------------------\n // PI permissions\n // ---------------------------------------------------------------------------\n\n async getPiPermissions(pi: string): Promise<PiPermissions> {\n return this.request(`/pi/${pi}/permissions`, { method: 'GET' });\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
type CollectionVisibility = 'public' | 'private';
|
|
2
|
+
type CollectionRole = 'owner' | 'editor';
|
|
3
|
+
interface Collection {
|
|
4
|
+
id: string;
|
|
5
|
+
title: string;
|
|
6
|
+
slug: string;
|
|
7
|
+
description?: string | null;
|
|
8
|
+
visibility: CollectionVisibility;
|
|
9
|
+
creator_user_id?: string;
|
|
10
|
+
created_at?: string;
|
|
11
|
+
updated_at?: string;
|
|
12
|
+
}
|
|
13
|
+
interface CollectionDetails extends Collection {
|
|
14
|
+
member_count: number;
|
|
15
|
+
root_pi: string | null;
|
|
16
|
+
users?: {
|
|
17
|
+
email?: string;
|
|
18
|
+
name?: string | null;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
interface PaginatedCollections {
|
|
22
|
+
collections: CollectionDetails[];
|
|
23
|
+
pagination: {
|
|
24
|
+
total: number | null;
|
|
25
|
+
limit: number;
|
|
26
|
+
offset: number;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
interface MemberUser {
|
|
30
|
+
id: string;
|
|
31
|
+
email: string;
|
|
32
|
+
name?: string | null;
|
|
33
|
+
}
|
|
34
|
+
interface Member {
|
|
35
|
+
role: CollectionRole;
|
|
36
|
+
created_at?: string;
|
|
37
|
+
user: MemberUser;
|
|
38
|
+
}
|
|
39
|
+
interface MembersResponse {
|
|
40
|
+
members: Member[];
|
|
41
|
+
}
|
|
42
|
+
interface InvitationUser {
|
|
43
|
+
email: string;
|
|
44
|
+
name?: string | null;
|
|
45
|
+
}
|
|
46
|
+
interface Invitation {
|
|
47
|
+
id: string;
|
|
48
|
+
role: CollectionRole;
|
|
49
|
+
status: 'pending' | 'accepted' | 'declined' | 'expired';
|
|
50
|
+
expires_at: string;
|
|
51
|
+
created_at: string;
|
|
52
|
+
responded_at?: string | null;
|
|
53
|
+
invitee?: InvitationUser;
|
|
54
|
+
inviter?: InvitationUser;
|
|
55
|
+
collection?: {
|
|
56
|
+
id: string;
|
|
57
|
+
title: string;
|
|
58
|
+
slug: string;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
interface InvitationsResponse {
|
|
62
|
+
invitations: Invitation[];
|
|
63
|
+
}
|
|
64
|
+
interface CreateCollectionPayload {
|
|
65
|
+
title: string;
|
|
66
|
+
slug: string;
|
|
67
|
+
description?: string;
|
|
68
|
+
visibility?: CollectionVisibility;
|
|
69
|
+
}
|
|
70
|
+
interface RegisterRootPayload extends CreateCollectionPayload {
|
|
71
|
+
rootPi: string;
|
|
72
|
+
}
|
|
73
|
+
interface UpdateCollectionPayload {
|
|
74
|
+
title?: string;
|
|
75
|
+
description?: string;
|
|
76
|
+
visibility?: CollectionVisibility;
|
|
77
|
+
}
|
|
78
|
+
interface ChangeRootPayload {
|
|
79
|
+
newRootPi: string;
|
|
80
|
+
}
|
|
81
|
+
interface MyCollectionsResponse {
|
|
82
|
+
owned: Array<Collection & {
|
|
83
|
+
role: CollectionRole;
|
|
84
|
+
}>;
|
|
85
|
+
editing: Array<Collection & {
|
|
86
|
+
role: CollectionRole;
|
|
87
|
+
}>;
|
|
88
|
+
total: number;
|
|
89
|
+
}
|
|
90
|
+
interface MyAccessResponse {
|
|
91
|
+
isMember: boolean;
|
|
92
|
+
role: CollectionRole | null;
|
|
93
|
+
canView: boolean;
|
|
94
|
+
canEdit: boolean;
|
|
95
|
+
canInvite: boolean;
|
|
96
|
+
canManageMembers: boolean;
|
|
97
|
+
canDelete: boolean;
|
|
98
|
+
}
|
|
99
|
+
interface RootResponse {
|
|
100
|
+
rootPi: string;
|
|
101
|
+
}
|
|
102
|
+
interface ChangeRootResponse {
|
|
103
|
+
previousRoot: string | null;
|
|
104
|
+
newRoot: string;
|
|
105
|
+
}
|
|
106
|
+
interface SuccessResponse {
|
|
107
|
+
success: boolean;
|
|
108
|
+
}
|
|
109
|
+
interface PiPermissions {
|
|
110
|
+
pi: string;
|
|
111
|
+
canView: boolean;
|
|
112
|
+
canEdit: boolean;
|
|
113
|
+
canAdminister: boolean;
|
|
114
|
+
collection: {
|
|
115
|
+
id: string;
|
|
116
|
+
title: string;
|
|
117
|
+
slug: string;
|
|
118
|
+
visibility: CollectionVisibility;
|
|
119
|
+
role: CollectionRole | null;
|
|
120
|
+
rootPi: string;
|
|
121
|
+
hops: number;
|
|
122
|
+
} | null;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
interface CollectionsClientConfig {
|
|
126
|
+
/**
|
|
127
|
+
* Gateway base URL (e.g., https://api.arke.institute).
|
|
128
|
+
* Must already point at the Arke gateway that proxies /collections/*.
|
|
129
|
+
*/
|
|
130
|
+
gatewayUrl: string;
|
|
131
|
+
/**
|
|
132
|
+
* Optional bearer token for authenticated routes.
|
|
133
|
+
* Public routes will still include it if provided.
|
|
134
|
+
*/
|
|
135
|
+
authToken?: string;
|
|
136
|
+
/**
|
|
137
|
+
* Optional custom fetch (useful for testing).
|
|
138
|
+
*/
|
|
139
|
+
fetchImpl?: typeof fetch;
|
|
140
|
+
}
|
|
141
|
+
declare class CollectionsClient {
|
|
142
|
+
private baseUrl;
|
|
143
|
+
private authToken?;
|
|
144
|
+
private fetchImpl;
|
|
145
|
+
constructor(config: CollectionsClientConfig);
|
|
146
|
+
setAuthToken(token?: string): void;
|
|
147
|
+
private buildUrl;
|
|
148
|
+
private getHeaders;
|
|
149
|
+
private request;
|
|
150
|
+
listCollections(params?: {
|
|
151
|
+
limit?: number;
|
|
152
|
+
offset?: number;
|
|
153
|
+
}): Promise<PaginatedCollections>;
|
|
154
|
+
getCollection(id: string): Promise<CollectionDetails>;
|
|
155
|
+
getCollectionRoot(id: string): Promise<RootResponse>;
|
|
156
|
+
getMyAccess(id: string): Promise<MyAccessResponse>;
|
|
157
|
+
createCollection(payload: CreateCollectionPayload): Promise<Collection>;
|
|
158
|
+
registerRoot(payload: RegisterRootPayload): Promise<Collection & {
|
|
159
|
+
rootPi: string;
|
|
160
|
+
}>;
|
|
161
|
+
updateCollection(id: string, payload: UpdateCollectionPayload): Promise<Collection>;
|
|
162
|
+
changeRoot(id: string, payload: ChangeRootPayload): Promise<ChangeRootResponse>;
|
|
163
|
+
deleteCollection(id: string): Promise<SuccessResponse>;
|
|
164
|
+
listMembers(collectionId: string): Promise<MembersResponse>;
|
|
165
|
+
updateMemberRole(collectionId: string, userId: string, role: CollectionRole): Promise<{
|
|
166
|
+
success: true;
|
|
167
|
+
role: CollectionRole;
|
|
168
|
+
}>;
|
|
169
|
+
removeMember(collectionId: string, userId: string): Promise<SuccessResponse>;
|
|
170
|
+
createInvitation(collectionId: string, email: string, role: CollectionRole): Promise<Invitation>;
|
|
171
|
+
listInvitations(collectionId: string): Promise<InvitationsResponse>;
|
|
172
|
+
acceptInvitation(invitationId: string): Promise<{
|
|
173
|
+
success: true;
|
|
174
|
+
role: CollectionRole;
|
|
175
|
+
}>;
|
|
176
|
+
declineInvitation(invitationId: string): Promise<SuccessResponse>;
|
|
177
|
+
revokeInvitation(invitationId: string): Promise<SuccessResponse>;
|
|
178
|
+
getMyCollections(): Promise<MyCollectionsResponse>;
|
|
179
|
+
getMyInvitations(): Promise<InvitationsResponse>;
|
|
180
|
+
getPiPermissions(pi: string): Promise<PiPermissions>;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
declare class CollectionsError extends Error {
|
|
184
|
+
code: string;
|
|
185
|
+
details?: unknown | undefined;
|
|
186
|
+
constructor(message: string, code?: string, details?: unknown | undefined);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export { type ChangeRootPayload, type ChangeRootResponse, type Collection, type CollectionDetails, type CollectionRole, type CollectionVisibility, CollectionsClient, type CollectionsClientConfig, CollectionsError, type CreateCollectionPayload, type Invitation, type InvitationUser, type InvitationsResponse, type Member, type MemberUser, type MembersResponse, type MyAccessResponse, type MyCollectionsResponse, type PaginatedCollections, type PiPermissions, type RegisterRootPayload, type RootResponse, type SuccessResponse, type UpdateCollectionPayload };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
type CollectionVisibility = 'public' | 'private';
|
|
2
|
+
type CollectionRole = 'owner' | 'editor';
|
|
3
|
+
interface Collection {
|
|
4
|
+
id: string;
|
|
5
|
+
title: string;
|
|
6
|
+
slug: string;
|
|
7
|
+
description?: string | null;
|
|
8
|
+
visibility: CollectionVisibility;
|
|
9
|
+
creator_user_id?: string;
|
|
10
|
+
created_at?: string;
|
|
11
|
+
updated_at?: string;
|
|
12
|
+
}
|
|
13
|
+
interface CollectionDetails extends Collection {
|
|
14
|
+
member_count: number;
|
|
15
|
+
root_pi: string | null;
|
|
16
|
+
users?: {
|
|
17
|
+
email?: string;
|
|
18
|
+
name?: string | null;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
interface PaginatedCollections {
|
|
22
|
+
collections: CollectionDetails[];
|
|
23
|
+
pagination: {
|
|
24
|
+
total: number | null;
|
|
25
|
+
limit: number;
|
|
26
|
+
offset: number;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
interface MemberUser {
|
|
30
|
+
id: string;
|
|
31
|
+
email: string;
|
|
32
|
+
name?: string | null;
|
|
33
|
+
}
|
|
34
|
+
interface Member {
|
|
35
|
+
role: CollectionRole;
|
|
36
|
+
created_at?: string;
|
|
37
|
+
user: MemberUser;
|
|
38
|
+
}
|
|
39
|
+
interface MembersResponse {
|
|
40
|
+
members: Member[];
|
|
41
|
+
}
|
|
42
|
+
interface InvitationUser {
|
|
43
|
+
email: string;
|
|
44
|
+
name?: string | null;
|
|
45
|
+
}
|
|
46
|
+
interface Invitation {
|
|
47
|
+
id: string;
|
|
48
|
+
role: CollectionRole;
|
|
49
|
+
status: 'pending' | 'accepted' | 'declined' | 'expired';
|
|
50
|
+
expires_at: string;
|
|
51
|
+
created_at: string;
|
|
52
|
+
responded_at?: string | null;
|
|
53
|
+
invitee?: InvitationUser;
|
|
54
|
+
inviter?: InvitationUser;
|
|
55
|
+
collection?: {
|
|
56
|
+
id: string;
|
|
57
|
+
title: string;
|
|
58
|
+
slug: string;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
interface InvitationsResponse {
|
|
62
|
+
invitations: Invitation[];
|
|
63
|
+
}
|
|
64
|
+
interface CreateCollectionPayload {
|
|
65
|
+
title: string;
|
|
66
|
+
slug: string;
|
|
67
|
+
description?: string;
|
|
68
|
+
visibility?: CollectionVisibility;
|
|
69
|
+
}
|
|
70
|
+
interface RegisterRootPayload extends CreateCollectionPayload {
|
|
71
|
+
rootPi: string;
|
|
72
|
+
}
|
|
73
|
+
interface UpdateCollectionPayload {
|
|
74
|
+
title?: string;
|
|
75
|
+
description?: string;
|
|
76
|
+
visibility?: CollectionVisibility;
|
|
77
|
+
}
|
|
78
|
+
interface ChangeRootPayload {
|
|
79
|
+
newRootPi: string;
|
|
80
|
+
}
|
|
81
|
+
interface MyCollectionsResponse {
|
|
82
|
+
owned: Array<Collection & {
|
|
83
|
+
role: CollectionRole;
|
|
84
|
+
}>;
|
|
85
|
+
editing: Array<Collection & {
|
|
86
|
+
role: CollectionRole;
|
|
87
|
+
}>;
|
|
88
|
+
total: number;
|
|
89
|
+
}
|
|
90
|
+
interface MyAccessResponse {
|
|
91
|
+
isMember: boolean;
|
|
92
|
+
role: CollectionRole | null;
|
|
93
|
+
canView: boolean;
|
|
94
|
+
canEdit: boolean;
|
|
95
|
+
canInvite: boolean;
|
|
96
|
+
canManageMembers: boolean;
|
|
97
|
+
canDelete: boolean;
|
|
98
|
+
}
|
|
99
|
+
interface RootResponse {
|
|
100
|
+
rootPi: string;
|
|
101
|
+
}
|
|
102
|
+
interface ChangeRootResponse {
|
|
103
|
+
previousRoot: string | null;
|
|
104
|
+
newRoot: string;
|
|
105
|
+
}
|
|
106
|
+
interface SuccessResponse {
|
|
107
|
+
success: boolean;
|
|
108
|
+
}
|
|
109
|
+
interface PiPermissions {
|
|
110
|
+
pi: string;
|
|
111
|
+
canView: boolean;
|
|
112
|
+
canEdit: boolean;
|
|
113
|
+
canAdminister: boolean;
|
|
114
|
+
collection: {
|
|
115
|
+
id: string;
|
|
116
|
+
title: string;
|
|
117
|
+
slug: string;
|
|
118
|
+
visibility: CollectionVisibility;
|
|
119
|
+
role: CollectionRole | null;
|
|
120
|
+
rootPi: string;
|
|
121
|
+
hops: number;
|
|
122
|
+
} | null;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
interface CollectionsClientConfig {
|
|
126
|
+
/**
|
|
127
|
+
* Gateway base URL (e.g., https://api.arke.institute).
|
|
128
|
+
* Must already point at the Arke gateway that proxies /collections/*.
|
|
129
|
+
*/
|
|
130
|
+
gatewayUrl: string;
|
|
131
|
+
/**
|
|
132
|
+
* Optional bearer token for authenticated routes.
|
|
133
|
+
* Public routes will still include it if provided.
|
|
134
|
+
*/
|
|
135
|
+
authToken?: string;
|
|
136
|
+
/**
|
|
137
|
+
* Optional custom fetch (useful for testing).
|
|
138
|
+
*/
|
|
139
|
+
fetchImpl?: typeof fetch;
|
|
140
|
+
}
|
|
141
|
+
declare class CollectionsClient {
|
|
142
|
+
private baseUrl;
|
|
143
|
+
private authToken?;
|
|
144
|
+
private fetchImpl;
|
|
145
|
+
constructor(config: CollectionsClientConfig);
|
|
146
|
+
setAuthToken(token?: string): void;
|
|
147
|
+
private buildUrl;
|
|
148
|
+
private getHeaders;
|
|
149
|
+
private request;
|
|
150
|
+
listCollections(params?: {
|
|
151
|
+
limit?: number;
|
|
152
|
+
offset?: number;
|
|
153
|
+
}): Promise<PaginatedCollections>;
|
|
154
|
+
getCollection(id: string): Promise<CollectionDetails>;
|
|
155
|
+
getCollectionRoot(id: string): Promise<RootResponse>;
|
|
156
|
+
getMyAccess(id: string): Promise<MyAccessResponse>;
|
|
157
|
+
createCollection(payload: CreateCollectionPayload): Promise<Collection>;
|
|
158
|
+
registerRoot(payload: RegisterRootPayload): Promise<Collection & {
|
|
159
|
+
rootPi: string;
|
|
160
|
+
}>;
|
|
161
|
+
updateCollection(id: string, payload: UpdateCollectionPayload): Promise<Collection>;
|
|
162
|
+
changeRoot(id: string, payload: ChangeRootPayload): Promise<ChangeRootResponse>;
|
|
163
|
+
deleteCollection(id: string): Promise<SuccessResponse>;
|
|
164
|
+
listMembers(collectionId: string): Promise<MembersResponse>;
|
|
165
|
+
updateMemberRole(collectionId: string, userId: string, role: CollectionRole): Promise<{
|
|
166
|
+
success: true;
|
|
167
|
+
role: CollectionRole;
|
|
168
|
+
}>;
|
|
169
|
+
removeMember(collectionId: string, userId: string): Promise<SuccessResponse>;
|
|
170
|
+
createInvitation(collectionId: string, email: string, role: CollectionRole): Promise<Invitation>;
|
|
171
|
+
listInvitations(collectionId: string): Promise<InvitationsResponse>;
|
|
172
|
+
acceptInvitation(invitationId: string): Promise<{
|
|
173
|
+
success: true;
|
|
174
|
+
role: CollectionRole;
|
|
175
|
+
}>;
|
|
176
|
+
declineInvitation(invitationId: string): Promise<SuccessResponse>;
|
|
177
|
+
revokeInvitation(invitationId: string): Promise<SuccessResponse>;
|
|
178
|
+
getMyCollections(): Promise<MyCollectionsResponse>;
|
|
179
|
+
getMyInvitations(): Promise<InvitationsResponse>;
|
|
180
|
+
getPiPermissions(pi: string): Promise<PiPermissions>;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
declare class CollectionsError extends Error {
|
|
184
|
+
code: string;
|
|
185
|
+
details?: unknown | undefined;
|
|
186
|
+
constructor(message: string, code?: string, details?: unknown | undefined);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export { type ChangeRootPayload, type ChangeRootResponse, type Collection, type CollectionDetails, type CollectionRole, type CollectionVisibility, CollectionsClient, type CollectionsClientConfig, CollectionsError, type CreateCollectionPayload, type Invitation, type InvitationUser, type InvitationsResponse, type Member, type MemberUser, type MembersResponse, type MyAccessResponse, type MyCollectionsResponse, type PaginatedCollections, type PiPermissions, type RegisterRootPayload, type RootResponse, type SuccessResponse, type UpdateCollectionPayload };
|