@cloudcannon/sdk 0.0.1 → 0.0.3
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/dist/index.d.ts +21 -3
- package/dist/index.js +39 -3
- package/dist/schema.d.ts +998 -161
- package/dist/src/backup.d.ts +6 -0
- package/dist/src/backup.js +15 -0
- package/dist/src/build.d.ts +6 -0
- package/dist/src/build.js +15 -0
- package/dist/src/editing-session-file.d.ts +13 -0
- package/dist/src/editing-session-file.js +58 -0
- package/dist/src/editing-session.d.ts +14 -0
- package/dist/src/editing-session.js +54 -0
- package/dist/src/helpers/query.d.ts +28 -0
- package/dist/src/helpers/query.js +34 -0
- package/dist/src/inbox.d.ts +3 -1
- package/dist/src/inbox.js +5 -3
- package/dist/src/org.d.ts +4 -3
- package/dist/src/org.js +13 -9
- package/dist/src/site.d.ts +19 -3
- package/dist/src/site.js +124 -6
- package/dist/src/sync.d.ts +6 -0
- package/dist/src/sync.js +15 -0
- package/package.json +3 -2
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export class BackupClient {
|
|
2
|
+
#uuid;
|
|
3
|
+
#client;
|
|
4
|
+
constructor(uuid, client) {
|
|
5
|
+
this.#uuid = uuid;
|
|
6
|
+
this.#client = client;
|
|
7
|
+
}
|
|
8
|
+
async download() {
|
|
9
|
+
const resp = await this.#client.fetch(`/site-archives/${this.#uuid}/download`);
|
|
10
|
+
if (resp.status === 401 || resp.status === 403) {
|
|
11
|
+
throw new Error('Error downloading backup. Permission denied');
|
|
12
|
+
}
|
|
13
|
+
return resp;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export class BuildClient {
|
|
2
|
+
#uuid;
|
|
3
|
+
#client;
|
|
4
|
+
constructor(uuid, client) {
|
|
5
|
+
this.#uuid = uuid;
|
|
6
|
+
this.#client = client;
|
|
7
|
+
}
|
|
8
|
+
async get() {
|
|
9
|
+
const resp = await this.#client.fetch(`/builds/${this.#uuid}`);
|
|
10
|
+
if (resp.status === 401 || resp.status === 403) {
|
|
11
|
+
throw new Error('Error fetching build. Permission denied');
|
|
12
|
+
}
|
|
13
|
+
return resp;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type CloudCannonClient from '../index.ts';
|
|
2
|
+
import type { EditingSessionFile, EditingSessionFileContribution } from '../index.ts';
|
|
3
|
+
import type { operations } from '../schema.js';
|
|
4
|
+
export type CreateContributionOptions = operations['Editing Session Contributions_Create']['requestBody']['content']['application/json'];
|
|
5
|
+
export type UnlockOptions = operations['Editing Session File_Unlock']['requestBody']['content']['application/json'];
|
|
6
|
+
export declare class EditingSessionFileClient {
|
|
7
|
+
#private;
|
|
8
|
+
constructor(uuid: string, client: CloudCannonClient);
|
|
9
|
+
get(): Promise<EditingSessionFile>;
|
|
10
|
+
getContributions(): Promise<EditingSessionFileContribution[]>;
|
|
11
|
+
createContribution(body: CreateContributionOptions): Promise<EditingSessionFileContribution>;
|
|
12
|
+
unlock(body: UnlockOptions): Promise<EditingSessionFileContribution>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { ApiError } from "./errors.js";
|
|
2
|
+
export class EditingSessionFileClient {
|
|
3
|
+
#uuid;
|
|
4
|
+
#client;
|
|
5
|
+
constructor(uuid, client) {
|
|
6
|
+
this.#uuid = uuid;
|
|
7
|
+
this.#client = client;
|
|
8
|
+
}
|
|
9
|
+
async get() {
|
|
10
|
+
const resp = await this.#client.fetch(`/editing_session_files/${this.#uuid}`);
|
|
11
|
+
if (resp.status === 403) {
|
|
12
|
+
throw new Error('Error fetching editing session file. Permission denied');
|
|
13
|
+
}
|
|
14
|
+
const file = await resp.json();
|
|
15
|
+
return file;
|
|
16
|
+
}
|
|
17
|
+
async getContributions() {
|
|
18
|
+
const resp = await this.#client.fetch(`/editing_session_files/${this.#uuid}/contributions`);
|
|
19
|
+
if (resp.status === 403) {
|
|
20
|
+
throw new Error('Error fetching editing session file contributions. Permission denied');
|
|
21
|
+
}
|
|
22
|
+
const contributions = await resp.json();
|
|
23
|
+
return contributions;
|
|
24
|
+
}
|
|
25
|
+
async createContribution(body) {
|
|
26
|
+
const resp = await this.#client.fetch(`/editing_session_files/${this.#uuid}/contributions`, {
|
|
27
|
+
method: 'POST',
|
|
28
|
+
body,
|
|
29
|
+
});
|
|
30
|
+
if (resp.status === 401 || resp.status === 403) {
|
|
31
|
+
throw new Error('Error creating editing session file contribution. Permission denied');
|
|
32
|
+
}
|
|
33
|
+
if (resp.status === 422) {
|
|
34
|
+
const errorResp = await resp.json();
|
|
35
|
+
throw new ApiError('Error creating editing session file contribution. Invalid request', errorResp.errors, `/editing_session_files/${this.#uuid}/contributions`, { method: 'POST', body }, resp.status);
|
|
36
|
+
}
|
|
37
|
+
const contribution = await resp.json();
|
|
38
|
+
return contribution;
|
|
39
|
+
}
|
|
40
|
+
async unlock(body) {
|
|
41
|
+
const resp = await this.#client.fetch(`/editing_session_files/${this.#uuid}/unlock`, {
|
|
42
|
+
method: 'PUT',
|
|
43
|
+
body,
|
|
44
|
+
});
|
|
45
|
+
if (resp.status === 403) {
|
|
46
|
+
throw new Error('Error unlocking editing session file. Permission denied');
|
|
47
|
+
}
|
|
48
|
+
if (resp.status === 404) {
|
|
49
|
+
throw new Error('Error unlocking editing session file. File not found');
|
|
50
|
+
}
|
|
51
|
+
if (resp.status === 422) {
|
|
52
|
+
const errorResp = await resp.json();
|
|
53
|
+
throw new ApiError('Error unlocking editing session file. Invalid request', errorResp.errors, `/editing_session_files/${this.#uuid}/unlock`, { method: 'PUT', body }, resp.status);
|
|
54
|
+
}
|
|
55
|
+
const contribution = await resp.json();
|
|
56
|
+
return contribution;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type CloudCannonClient from '../index.ts';
|
|
2
|
+
import type { EditingSession, EditingSessionFile } from '../index.ts';
|
|
3
|
+
import type { operations } from '../schema.js';
|
|
4
|
+
export type CreateEditingSessionFileOptions = operations['Editing Session Files_Create']['requestBody']['content']['application/json'];
|
|
5
|
+
export type CommitEditingSessionOptions = operations['Editing Session_Commit']['requestBody']['content']['application/json'];
|
|
6
|
+
export type CommitEditingSessionResponse = operations['Editing Session_Commit']['responses']['200']['content']['application/json'];
|
|
7
|
+
export declare class EditingSessionClient {
|
|
8
|
+
#private;
|
|
9
|
+
constructor(uuid: string, client: CloudCannonClient);
|
|
10
|
+
get(): Promise<EditingSession>;
|
|
11
|
+
getFiles(): Promise<EditingSessionFile[]>;
|
|
12
|
+
createFile(body: CreateEditingSessionFileOptions): Promise<EditingSessionFile>;
|
|
13
|
+
commit(): Promise<CommitEditingSessionResponse>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { ApiError } from "./errors.js";
|
|
2
|
+
export class EditingSessionClient {
|
|
3
|
+
#uuid;
|
|
4
|
+
#client;
|
|
5
|
+
constructor(uuid, client) {
|
|
6
|
+
this.#uuid = uuid;
|
|
7
|
+
this.#client = client;
|
|
8
|
+
}
|
|
9
|
+
async get() {
|
|
10
|
+
const resp = await this.#client.fetch(`/editing_sessions/${this.#uuid}`);
|
|
11
|
+
if (resp.status === 403) {
|
|
12
|
+
throw new Error('Error fetching editing session. Permission denied');
|
|
13
|
+
}
|
|
14
|
+
const editingSession = await resp.json();
|
|
15
|
+
return editingSession;
|
|
16
|
+
}
|
|
17
|
+
async getFiles() {
|
|
18
|
+
const resp = await this.#client.fetch(`/editing_sessions/${this.#uuid}/files`);
|
|
19
|
+
if (resp.status === 403) {
|
|
20
|
+
throw new Error('Error fetching editing session files. Permission denied');
|
|
21
|
+
}
|
|
22
|
+
const files = await resp.json();
|
|
23
|
+
return files;
|
|
24
|
+
}
|
|
25
|
+
async createFile(body) {
|
|
26
|
+
const resp = await this.#client.fetch(`/editing_sessions/${this.#uuid}/files`, {
|
|
27
|
+
method: 'POST',
|
|
28
|
+
body,
|
|
29
|
+
});
|
|
30
|
+
if (resp.status === 403) {
|
|
31
|
+
throw new Error('Error creating editing session file. Permission denied');
|
|
32
|
+
}
|
|
33
|
+
if (resp.status === 422) {
|
|
34
|
+
const errorResp = await resp.json();
|
|
35
|
+
throw new ApiError('Error creating editing session file. Invalid request', errorResp.errors, `/editing_sessions/${this.#uuid}/files`, { method: 'POST', body }, resp.status);
|
|
36
|
+
}
|
|
37
|
+
const file = await resp.json();
|
|
38
|
+
return file;
|
|
39
|
+
}
|
|
40
|
+
async commit() {
|
|
41
|
+
const resp = await this.#client.fetch(`/editing_sessions/${this.#uuid}/commit`, {
|
|
42
|
+
method: 'POST',
|
|
43
|
+
});
|
|
44
|
+
if (resp.status === 403) {
|
|
45
|
+
throw new Error('Error committing editing session. Permission denied');
|
|
46
|
+
}
|
|
47
|
+
if (resp.status === 422) {
|
|
48
|
+
const errorResp = await resp.json();
|
|
49
|
+
throw new ApiError('Error committing editing session. Invalid request', errorResp.errors, `/editing_sessions/${this.#uuid}/commit`, { method: 'POST' }, resp.status);
|
|
50
|
+
}
|
|
51
|
+
const result = await resp.json();
|
|
52
|
+
return result;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type PaginationOptions = {
|
|
2
|
+
page?: number;
|
|
3
|
+
items?: number;
|
|
4
|
+
};
|
|
5
|
+
export type SortingOptions<Op> = Op extends {
|
|
6
|
+
parameters: {
|
|
7
|
+
query?: infer Q;
|
|
8
|
+
};
|
|
9
|
+
} ? Pick<NonNullable<Q>, Extract<keyof NonNullable<Q>, 'sort_attribute' | 'sort_direction'>> : never;
|
|
10
|
+
export type FilterOptions<Op> = Op extends {
|
|
11
|
+
parameters: {
|
|
12
|
+
query?: infer Q;
|
|
13
|
+
};
|
|
14
|
+
} ? {
|
|
15
|
+
filters?: Omit<NonNullable<Q>, 'page' | 'items' | 'sort_attribute' | 'sort_direction'>;
|
|
16
|
+
} : never;
|
|
17
|
+
export type PaginatedResponse<T> = {
|
|
18
|
+
items: T[];
|
|
19
|
+
current_page?: number;
|
|
20
|
+
total_items?: number;
|
|
21
|
+
total_pages?: number;
|
|
22
|
+
};
|
|
23
|
+
export declare function buildQuery(options?: PaginationOptions & {
|
|
24
|
+
sort_attribute?: string;
|
|
25
|
+
sort_direction?: 'ASC' | 'DESC';
|
|
26
|
+
filters?: Record<string, unknown>;
|
|
27
|
+
}): string;
|
|
28
|
+
export declare function paginatedResponse<T>(items: T[], headers: Headers): PaginatedResponse<T>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export function buildQuery(options = {}) {
|
|
2
|
+
const params = new URLSearchParams();
|
|
3
|
+
if (options.page !== undefined)
|
|
4
|
+
params.set('page', String(options.page));
|
|
5
|
+
if (options.items !== undefined)
|
|
6
|
+
params.set('item', String(options.items));
|
|
7
|
+
if (options.sort_attribute !== undefined)
|
|
8
|
+
params.set('sort_attribute', options.sort_attribute);
|
|
9
|
+
if (options.sort_direction !== undefined)
|
|
10
|
+
params.set('sort_direction', options.sort_direction);
|
|
11
|
+
if (options.filters) {
|
|
12
|
+
for (const [key, value] of Object.entries(options.filters)) {
|
|
13
|
+
if (value !== undefined) {
|
|
14
|
+
params.set(key, String(value));
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return params.toString();
|
|
19
|
+
}
|
|
20
|
+
export function paginatedResponse(items, headers) {
|
|
21
|
+
const parse = (name) => {
|
|
22
|
+
const value = headers.get(name);
|
|
23
|
+
if (value === null)
|
|
24
|
+
return undefined;
|
|
25
|
+
const parsed = Number(value);
|
|
26
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
27
|
+
};
|
|
28
|
+
return {
|
|
29
|
+
items,
|
|
30
|
+
current_page: parse('current_page'),
|
|
31
|
+
total_items: parse('total_items'),
|
|
32
|
+
total_pages: parse('total_pages'),
|
|
33
|
+
};
|
|
34
|
+
}
|
package/dist/src/inbox.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type CloudCannonClient from '../index.ts';
|
|
2
2
|
import type { FormSubmission } from '../index.ts';
|
|
3
|
+
import type { operations } from '../schema.js';
|
|
4
|
+
import { type FilterOptions, type PaginatedResponse, type PaginationOptions, type SortingOptions } from './helpers/query.ts';
|
|
3
5
|
export declare class InboxClient {
|
|
4
6
|
#private;
|
|
5
7
|
constructor(uuid: string, client: CloudCannonClient);
|
|
6
|
-
getSubmissions(): Promise<FormSubmission
|
|
8
|
+
getSubmissions(options?: PaginationOptions & SortingOptions<operations['Inbox Form Hooks_Index']> & FilterOptions<operations['Inbox Form Hooks_Index']>): Promise<PaginatedResponse<FormSubmission>>;
|
|
7
9
|
}
|
package/dist/src/inbox.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { buildQuery, paginatedResponse, } from "./helpers/query.js";
|
|
1
2
|
export class InboxClient {
|
|
2
3
|
#uuid;
|
|
3
4
|
#client;
|
|
@@ -5,12 +6,13 @@ export class InboxClient {
|
|
|
5
6
|
this.#uuid = uuid;
|
|
6
7
|
this.#client = client;
|
|
7
8
|
}
|
|
8
|
-
async getSubmissions() {
|
|
9
|
-
const
|
|
9
|
+
async getSubmissions(options = {}) {
|
|
10
|
+
const query = buildQuery(options);
|
|
11
|
+
const resp = await this.#client.fetch(`/inboxes/${this.#uuid}/form-hooks?${query}`);
|
|
10
12
|
if (resp.status === 401 || resp.status === 403) {
|
|
11
13
|
throw new Error('Error fetching submissions. Permission denied');
|
|
12
14
|
}
|
|
13
15
|
const submissions = await resp.json();
|
|
14
|
-
return submissions;
|
|
16
|
+
return paginatedResponse(submissions, resp.headers);
|
|
15
17
|
}
|
|
16
18
|
}
|
package/dist/src/org.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type CloudCannonClient from '../index.ts';
|
|
2
2
|
import type { Dam, Inbox, Org, Provider, ProviderDetails, Site } from '../index.ts';
|
|
3
3
|
import type { operations } from '../schema.js';
|
|
4
|
+
import { type FilterOptions, type PaginatedResponse, type PaginationOptions, type SortingOptions } from './helpers/query.ts';
|
|
4
5
|
export interface ConnectSiteOptions extends ProviderDetails {
|
|
5
6
|
folder?: string;
|
|
6
7
|
}
|
|
@@ -10,13 +11,13 @@ export type CreateDamOptions = operations['DAMs_Create']['requestBody']['content
|
|
|
10
11
|
export declare class OrgClient {
|
|
11
12
|
#private;
|
|
12
13
|
constructor(uuid: string, client: CloudCannonClient);
|
|
13
|
-
sites(): Promise<Site
|
|
14
|
+
sites(options?: PaginationOptions & SortingOptions<operations['Sites_Index']> & FilterOptions<operations['Sites_Index']>): Promise<PaginatedResponse<Site>>;
|
|
14
15
|
createSite(name: string, stableDomain?: string): Promise<Site>;
|
|
15
16
|
connectSite(name: string, providerDetails: ConnectSiteOptions, stableDomain?: string): Promise<Site>;
|
|
16
17
|
get(): Promise<Org>;
|
|
17
|
-
getInboxes(): Promise<Inbox
|
|
18
|
+
getInboxes(options?: PaginationOptions & SortingOptions<operations['Organization Inboxes_Index']> & FilterOptions<operations['Organization Inboxes_Index']>): Promise<PaginatedResponse<Inbox>>;
|
|
18
19
|
createInbox(body: CreateInboxOptions): Promise<Inbox>;
|
|
19
|
-
getDams(): Promise<Dam
|
|
20
|
+
getDams(options?: PaginationOptions & SortingOptions<operations['DAMs_Index']> & FilterOptions<operations['DAMs_Index']>): Promise<PaginatedResponse<Dam>>;
|
|
20
21
|
createDam(body: CreateDamOptions): Promise<Dam>;
|
|
21
22
|
getRepositories(provider: Provider): Promise<Repository[]>;
|
|
22
23
|
}
|
package/dist/src/org.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ApiError } from "./errors.js";
|
|
2
|
+
import { buildQuery, paginatedResponse, } from "./helpers/query.js";
|
|
2
3
|
export class OrgClient {
|
|
3
4
|
#uuid;
|
|
4
5
|
#client;
|
|
@@ -6,13 +7,14 @@ export class OrgClient {
|
|
|
6
7
|
this.#uuid = uuid;
|
|
7
8
|
this.#client = client;
|
|
8
9
|
}
|
|
9
|
-
async sites() {
|
|
10
|
-
const
|
|
10
|
+
async sites(options = {}) {
|
|
11
|
+
const query = buildQuery(options);
|
|
12
|
+
const resp = await this.#client.fetch(`/orgs/${this.#uuid}/sites?${query}`);
|
|
11
13
|
if (resp.status === 401 || resp.status === 403) {
|
|
12
14
|
throw new Error('Error fetching sites. Permission denied');
|
|
13
15
|
}
|
|
14
16
|
const sites = await resp.json();
|
|
15
|
-
return sites;
|
|
17
|
+
return paginatedResponse(sites, resp.headers);
|
|
16
18
|
}
|
|
17
19
|
async createSite(name, stableDomain) {
|
|
18
20
|
const resp = await this.#client.fetch(`/orgs/${this.#uuid}/sites`, {
|
|
@@ -63,13 +65,14 @@ export class OrgClient {
|
|
|
63
65
|
const org = await resp.json();
|
|
64
66
|
return org;
|
|
65
67
|
}
|
|
66
|
-
async getInboxes() {
|
|
67
|
-
const
|
|
68
|
+
async getInboxes(options = {}) {
|
|
69
|
+
const query = buildQuery(options);
|
|
70
|
+
const resp = await this.#client.fetch(`/orgs/${this.#uuid}/inboxes?${query}`);
|
|
68
71
|
if (resp.status === 403) {
|
|
69
72
|
throw new Error('Error fetching inboxes. Permission denied');
|
|
70
73
|
}
|
|
71
74
|
const inboxes = await resp.json();
|
|
72
|
-
return inboxes;
|
|
75
|
+
return paginatedResponse(inboxes, resp.headers);
|
|
73
76
|
}
|
|
74
77
|
async createInbox(body) {
|
|
75
78
|
const resp = await this.#client.fetch(`/orgs/${this.#uuid}/inboxes`, {
|
|
@@ -86,10 +89,11 @@ export class OrgClient {
|
|
|
86
89
|
const inbox = await resp.json();
|
|
87
90
|
return inbox;
|
|
88
91
|
}
|
|
89
|
-
async getDams() {
|
|
90
|
-
const
|
|
92
|
+
async getDams(options = {}) {
|
|
93
|
+
const query = buildQuery(options);
|
|
94
|
+
const resp = await this.#client.fetch(`/orgs/${this.#uuid}/dams?${query}`);
|
|
91
95
|
const dams = await resp.json();
|
|
92
|
-
return dams;
|
|
96
|
+
return paginatedResponse(dams, resp.headers);
|
|
93
97
|
}
|
|
94
98
|
async createDam(body) {
|
|
95
99
|
const resp = await this.#client.fetch(`/orgs/${this.#uuid}/dams`, {
|
package/dist/src/site.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type CloudCannonClient from '../index.ts';
|
|
2
|
-
import type { Build, ProviderDetails, Site, SiteDam, SiteInbox, SiteScan, Sync } from '../index.ts';
|
|
2
|
+
import type { Backup, Build, EditingSession, ProviderDetails, Site, SiteDam, SiteInbox, SiteScan, Sync } from '../index.ts';
|
|
3
3
|
import type { operations } from '../schema.js';
|
|
4
|
+
import { type FilterOptions, type PaginatedResponse, type PaginationOptions, type SortingOptions } from './helpers/query.ts';
|
|
4
5
|
export type BuildConfiguration = Partial<Omit<operations['Sites_UpdateBuild']['requestBody']['content']['application/json'], 'build_configuration'>> & {
|
|
5
6
|
compile?: {
|
|
6
7
|
install_command?: string;
|
|
@@ -22,8 +23,14 @@ export type BuildConfiguration = Partial<Omit<operations['Sites_UpdateBuild']['r
|
|
|
22
23
|
};
|
|
23
24
|
export type UpdateSiteOptions = operations['Sites_Update']['requestBody']['content']['application/json'];
|
|
24
25
|
export type CopySiteOptions = operations['Sites_Copy']['requestBody']['content']['application/json'];
|
|
26
|
+
export type CreateBackupOptions = operations['Backups_Create']['requestBody']['content']['application/json'];
|
|
25
27
|
export type ConnectInboxOptions = operations['Site Inboxes_Create']['requestBody']['content']['application/json'];
|
|
26
28
|
export type ConnectDamOptions = operations['Dams_Create']['requestBody']['content']['application/json'];
|
|
29
|
+
export type FileListing = operations['Files_Index']['responses']['200']['content']['application/json'][number];
|
|
30
|
+
export type UploadFileOptions = {
|
|
31
|
+
type?: string;
|
|
32
|
+
overwriteExistingFile?: boolean;
|
|
33
|
+
};
|
|
27
34
|
export declare class SiteClient {
|
|
28
35
|
#private;
|
|
29
36
|
constructor(uuid: string, client: CloudCannonClient);
|
|
@@ -32,10 +39,15 @@ export declare class SiteClient {
|
|
|
32
39
|
delete(): Promise<void>;
|
|
33
40
|
copy(body: CopySiteOptions): Promise<Site>;
|
|
34
41
|
updateBuildConfig(options: BuildConfiguration): Promise<Site>;
|
|
35
|
-
getBuilds(): Promise<Build
|
|
42
|
+
getBuilds(options?: PaginationOptions & SortingOptions<operations['Builds_Index']> & FilterOptions<operations['Builds_Index']>): Promise<PaginatedResponse<Build>>;
|
|
36
43
|
rebuild(): Promise<void>;
|
|
44
|
+
listBackups(options?: PaginationOptions & SortingOptions<operations['Backups_Index']> & FilterOptions<operations['Backups_Index']>): Promise<PaginatedResponse<Backup>>;
|
|
45
|
+
createBackup(body?: CreateBackupOptions): Promise<{
|
|
46
|
+
socket_message_id?: string;
|
|
47
|
+
}>;
|
|
48
|
+
listFiles(): Promise<FileListing[]>;
|
|
37
49
|
getFile(path: string): Promise<Response>;
|
|
38
|
-
getSyncs(): Promise<Sync
|
|
50
|
+
getSyncs(options?: PaginationOptions & SortingOptions<operations['Syncs_Index']> & FilterOptions<operations['Syncs_Index']>): Promise<PaginatedResponse<Sync>>;
|
|
39
51
|
getScan(): Promise<SiteScan>;
|
|
40
52
|
getScreenshotHashes(): Promise<Record<string, string>>;
|
|
41
53
|
getScreenshot(device: 'desktop' | 'mobile', path: string): Promise<Response>;
|
|
@@ -48,4 +60,8 @@ export declare class SiteClient {
|
|
|
48
60
|
connectInbox(body: ConnectInboxOptions): Promise<SiteInbox>;
|
|
49
61
|
getDamConnections(): Promise<SiteDam[]>;
|
|
50
62
|
connectDam(body: ConnectDamOptions): Promise<SiteDam>;
|
|
63
|
+
getEditingSessions(): Promise<EditingSession[]>;
|
|
64
|
+
createEditingSession(): Promise<EditingSession>;
|
|
65
|
+
getLatestEditingSession(): Promise<EditingSession>;
|
|
66
|
+
uploadFile(path: string, content: BlobPart, options?: UploadFileOptions): Promise<void>;
|
|
51
67
|
}
|
package/dist/src/site.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ApiError } from "./errors.js";
|
|
2
|
+
import { buildQuery, paginatedResponse, } from "./helpers/query.js";
|
|
2
3
|
export class SiteClient {
|
|
3
4
|
#uuid;
|
|
4
5
|
#client;
|
|
@@ -70,13 +71,14 @@ export class SiteClient {
|
|
|
70
71
|
const site = await resp.json();
|
|
71
72
|
return site;
|
|
72
73
|
}
|
|
73
|
-
async getBuilds() {
|
|
74
|
-
const
|
|
74
|
+
async getBuilds(options = {}) {
|
|
75
|
+
const query = buildQuery(options);
|
|
76
|
+
const resp = await this.#client.fetch(`/sites/${this.#uuid}/builds?${query}`);
|
|
75
77
|
if (resp.status === 401 || resp.status === 403) {
|
|
76
78
|
throw new Error('Error fetching builds. Permission denied');
|
|
77
79
|
}
|
|
78
80
|
const builds = await resp.json();
|
|
79
|
-
return builds;
|
|
81
|
+
return paginatedResponse(builds, resp.headers);
|
|
80
82
|
}
|
|
81
83
|
async rebuild() {
|
|
82
84
|
const resp = await this.#client.fetch(`/sites/${this.#uuid}/builds`, {
|
|
@@ -86,6 +88,42 @@ export class SiteClient {
|
|
|
86
88
|
throw new Error('Error creating build. Permission denied');
|
|
87
89
|
}
|
|
88
90
|
}
|
|
91
|
+
async listBackups(options = {}) {
|
|
92
|
+
const query = buildQuery(options);
|
|
93
|
+
const resp = await this.#client.fetch(`/sites/${this.#uuid}/archives?${query}`);
|
|
94
|
+
if (resp.status === 401) {
|
|
95
|
+
throw new Error('Error fetching backups. Permission denied');
|
|
96
|
+
}
|
|
97
|
+
const items = await resp.json();
|
|
98
|
+
return paginatedResponse(items, resp.headers);
|
|
99
|
+
}
|
|
100
|
+
async createBackup(body = {}) {
|
|
101
|
+
const resp = await this.#client.fetch(`/sites/${this.#uuid}/archives`, {
|
|
102
|
+
method: 'POST',
|
|
103
|
+
body,
|
|
104
|
+
});
|
|
105
|
+
if (resp.status === 401) {
|
|
106
|
+
throw new Error('Error creating backup. Permission denied');
|
|
107
|
+
}
|
|
108
|
+
if (resp.status === 422) {
|
|
109
|
+
const errorResp = await resp.json();
|
|
110
|
+
throw new ApiError('Error creating backup. Invalid request', errorResp.errors, `/sites/${this.#uuid}/archives`, { method: 'POST', body }, resp.status);
|
|
111
|
+
}
|
|
112
|
+
const result = await resp.json();
|
|
113
|
+
return result;
|
|
114
|
+
}
|
|
115
|
+
async listFiles() {
|
|
116
|
+
const resp = await this.#client.fetch(`/sites/${this.#uuid}/files`);
|
|
117
|
+
if (resp.status === 401) {
|
|
118
|
+
throw new Error('Error fetching files. Permission denied');
|
|
119
|
+
}
|
|
120
|
+
if (resp.status === 422) {
|
|
121
|
+
const errorResp = await resp.json();
|
|
122
|
+
throw new ApiError('Error fetching files. Invalid request', errorResp.errors, `/sites/${this.#uuid}/files`, {}, resp.status);
|
|
123
|
+
}
|
|
124
|
+
const files = await resp.json();
|
|
125
|
+
return files;
|
|
126
|
+
}
|
|
89
127
|
async getFile(path) {
|
|
90
128
|
const resp = await this.#client.fetch(`/sites/${this.#uuid}/files/${encodeURIComponent(path)}`);
|
|
91
129
|
if (resp.status === 401 || resp.status === 403) {
|
|
@@ -100,13 +138,14 @@ export class SiteClient {
|
|
|
100
138
|
}
|
|
101
139
|
return resp;
|
|
102
140
|
}
|
|
103
|
-
async getSyncs() {
|
|
104
|
-
const
|
|
141
|
+
async getSyncs(options = {}) {
|
|
142
|
+
const query = buildQuery(options);
|
|
143
|
+
const resp = await this.#client.fetch(`/sites/${this.#uuid}/syncs?${query}`);
|
|
105
144
|
if (resp.status === 401) {
|
|
106
145
|
throw new Error('Error fetching syncs. Permission denied');
|
|
107
146
|
}
|
|
108
147
|
const syncs = await resp.json();
|
|
109
|
-
return syncs;
|
|
148
|
+
return paginatedResponse(syncs, resp.headers);
|
|
110
149
|
}
|
|
111
150
|
async getScan() {
|
|
112
151
|
const resp = await this.#client.fetch(`/sites/${this.#uuid}/scans`);
|
|
@@ -251,4 +290,83 @@ export class SiteClient {
|
|
|
251
290
|
const dam = await resp.json();
|
|
252
291
|
return dam;
|
|
253
292
|
}
|
|
293
|
+
async getEditingSessions() {
|
|
294
|
+
const resp = await this.#client.fetch(`/sites/${this.#uuid}/editing_sessions`);
|
|
295
|
+
if (resp.status === 403) {
|
|
296
|
+
throw new Error('Error fetching editing sessions. Permission denied');
|
|
297
|
+
}
|
|
298
|
+
const editingSessions = await resp.json();
|
|
299
|
+
return editingSessions;
|
|
300
|
+
}
|
|
301
|
+
async createEditingSession() {
|
|
302
|
+
const resp = await this.#client.fetch(`/sites/${this.#uuid}/editing_sessions`, {
|
|
303
|
+
method: 'POST',
|
|
304
|
+
});
|
|
305
|
+
if (resp.status === 401 || resp.status === 403) {
|
|
306
|
+
throw new Error('Error creating editing session. Permission denied');
|
|
307
|
+
}
|
|
308
|
+
if (resp.status === 422) {
|
|
309
|
+
const errorResp = await resp.json();
|
|
310
|
+
throw new ApiError('Error creating editing session. Invalid request', errorResp.errors, `/sites/${this.#uuid}/editing_sessions`, { method: 'POST' }, resp.status);
|
|
311
|
+
}
|
|
312
|
+
const editingSession = await resp.json();
|
|
313
|
+
return editingSession;
|
|
314
|
+
}
|
|
315
|
+
async getLatestEditingSession() {
|
|
316
|
+
const resp = await this.#client.fetch(`/sites/${this.#uuid}/editing_sessions/latest`);
|
|
317
|
+
if (resp.status === 403) {
|
|
318
|
+
throw new Error('Error fetching latest editing session. Permission denied');
|
|
319
|
+
}
|
|
320
|
+
const editingSession = await resp.json();
|
|
321
|
+
return editingSession;
|
|
322
|
+
}
|
|
323
|
+
async uploadFile(path, content, options = {}) {
|
|
324
|
+
if (!path.startsWith('/')) {
|
|
325
|
+
path = `/${path}`;
|
|
326
|
+
}
|
|
327
|
+
const files = await this.listFiles();
|
|
328
|
+
const existingFile = files.find((file) => file.sitePath === path);
|
|
329
|
+
if (existingFile && !options.overwriteExistingFile) {
|
|
330
|
+
throw new Error('File already exists and overwriteExistingFile is not set');
|
|
331
|
+
}
|
|
332
|
+
const uploadData = await this.#client.getUploadData();
|
|
333
|
+
const editingSession = await this.createEditingSession();
|
|
334
|
+
const file = await this.#client.editingSession(editingSession.uuid).createFile({
|
|
335
|
+
path,
|
|
336
|
+
source_path: existingFile ? path : undefined,
|
|
337
|
+
edit_type: 'update',
|
|
338
|
+
});
|
|
339
|
+
const contributions = await this.#client.editingSessionFile(file.uuid).getContributions();
|
|
340
|
+
contributions.sort((a, b) => a.updated_at.localeCompare(b.updated_at));
|
|
341
|
+
const latestContribution = contributions.at(-1);
|
|
342
|
+
if (latestContribution && !options.overwriteExistingFile) {
|
|
343
|
+
throw new Error('File already exists and overwriteExistingFile is not set');
|
|
344
|
+
}
|
|
345
|
+
const s3Key = `${uploadData.prefix}/${Date.now()}${path}`;
|
|
346
|
+
const formData = new FormData();
|
|
347
|
+
formData.append('key', s3Key);
|
|
348
|
+
Object.keys(uploadData.fields).forEach((field) => {
|
|
349
|
+
if (field !== 'key') {
|
|
350
|
+
formData.append(field, uploadData.fields[field]);
|
|
351
|
+
}
|
|
352
|
+
});
|
|
353
|
+
formData.append('file', new Blob([content], { type: options.type ?? 'text/plain' }));
|
|
354
|
+
const uploadResp = await fetch(uploadData.url, {
|
|
355
|
+
method: 'POST',
|
|
356
|
+
body: formData,
|
|
357
|
+
});
|
|
358
|
+
const etag = uploadResp.headers.get('ETag');
|
|
359
|
+
if (!etag) {
|
|
360
|
+
throw new Error('ETag not found in upload response');
|
|
361
|
+
}
|
|
362
|
+
const contentHash = etag.slice(1, -1);
|
|
363
|
+
await this.#client.editingSessionFile(file.uuid).createContribution({
|
|
364
|
+
s3_key: s3Key,
|
|
365
|
+
content_hash: contentHash,
|
|
366
|
+
previous_content_hash: latestContribution?.content_hash ?? existingFile?.md5,
|
|
367
|
+
});
|
|
368
|
+
await this.#client.editingSessionFile(file.uuid).unlock({
|
|
369
|
+
previous_content_hash: contentHash,
|
|
370
|
+
});
|
|
371
|
+
}
|
|
254
372
|
}
|
package/dist/src/sync.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export class SyncClient {
|
|
2
|
+
#uuid;
|
|
3
|
+
#client;
|
|
4
|
+
constructor(uuid, client) {
|
|
5
|
+
this.#uuid = uuid;
|
|
6
|
+
this.#client = client;
|
|
7
|
+
}
|
|
8
|
+
async get() {
|
|
9
|
+
const resp = await this.#client.fetch(`/syncs/${this.#uuid}`);
|
|
10
|
+
if (resp.status === 401 || resp.status === 403) {
|
|
11
|
+
throw new Error('Error fetching sync. Permission denied');
|
|
12
|
+
}
|
|
13
|
+
return resp;
|
|
14
|
+
}
|
|
15
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudcannon/sdk",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.3",
|
|
5
5
|
"description": "REST API client for the CloudCannon CMS.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"cloudcannon",
|
|
@@ -43,7 +43,8 @@
|
|
|
43
43
|
"test:watch": "node --test --watch",
|
|
44
44
|
"test:coverage": "node --test --test-coverage --test-reporter=lcov --test-reporter-destination=lcov.info",
|
|
45
45
|
"lint": "biome check && tsc --noEmit",
|
|
46
|
-
"lint:fix": "biome check --fix"
|
|
46
|
+
"lint:fix": "biome check --fix",
|
|
47
|
+
"generate-schema": "npx openapi-typescript $1 -o ./schema.ts"
|
|
47
48
|
},
|
|
48
49
|
"author": "CloudCannon <support@cloudcannon.com>",
|
|
49
50
|
"license": "ISC",
|