@cntrl-site/sdk 0.2.14 → 0.4.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/cntrl-site-sdk-0.2.12.tgz +0 -0
- package/lib/Client/Client.js +70 -24
- package/package.json +2 -2
- package/src/Client/Client.test.ts +222 -0
- package/src/Client/Client.ts +99 -27
- package/src/Client/__mock__/articleMock.ts +15 -0
- package/src/Client/__mock__/keyframesMock.ts +15 -0
- package/src/Client/__mock__/projectMock.ts +40 -0
- package/src/Client/__mock__/typePresetsMock.ts +6 -0
|
Binary file
|
package/lib/Client/Client.js
CHANGED
|
@@ -20,35 +20,42 @@ class Client {
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
async getProject() {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
try {
|
|
24
|
+
const response = await this.fetchProject();
|
|
25
|
+
const data = await response.json();
|
|
26
|
+
const project = core_1.ProjectSchema.parse(data);
|
|
27
|
+
return project;
|
|
28
|
+
}
|
|
29
|
+
catch (e) {
|
|
30
|
+
throw e;
|
|
27
31
|
}
|
|
28
|
-
const data = await response.json();
|
|
29
|
-
const project = core_1.ProjectSchema.parse(data);
|
|
30
|
-
return project;
|
|
31
32
|
}
|
|
32
33
|
async getPageArticle(pageSlug) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
throw new Error(`Page with a slug ${pageSlug} was not found in project with id #${this.projectId}`);
|
|
34
|
+
try {
|
|
35
|
+
const projectResponse = await this.fetchProject();
|
|
36
|
+
const data = await projectResponse.json();
|
|
37
|
+
const project = core_1.ProjectSchema.parse(data);
|
|
38
|
+
const articleId = this.findArticleIdByPageSlug(pageSlug, project.pages);
|
|
39
|
+
const articleResponse = await this.fetchArticle(articleId);
|
|
40
|
+
const articleData = await articleResponse.json();
|
|
41
|
+
const article = core_1.ArticleSchema.parse(articleData);
|
|
42
|
+
return article;
|
|
43
43
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (!articleResponse.ok) {
|
|
47
|
-
throw new Error(`Failed to fetch article with id #${page.articleId}: ${articleResponse.statusText}`);
|
|
44
|
+
catch (e) {
|
|
45
|
+
throw e;
|
|
48
46
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
}
|
|
48
|
+
async getTypePresets() {
|
|
49
|
+
const response = await this.fetchTypePresets();
|
|
50
|
+
const data = await response.json();
|
|
51
|
+
const typePresets = core_1.TypePresetsSchema.parse(data);
|
|
52
|
+
return typePresets;
|
|
53
|
+
}
|
|
54
|
+
async getKeyframes(articleId) {
|
|
55
|
+
const response = await this.fetchKeyframes(articleId);
|
|
56
|
+
const data = await response.json();
|
|
57
|
+
const keyframes = core_1.KeyframesSchema.parse(data);
|
|
58
|
+
return keyframes;
|
|
52
59
|
}
|
|
53
60
|
static getPageMeta(projectMeta, pageMeta) {
|
|
54
61
|
return pageMeta.enabled ? {
|
|
@@ -59,5 +66,44 @@ class Client {
|
|
|
59
66
|
favicon: projectMeta.favicon
|
|
60
67
|
} : projectMeta;
|
|
61
68
|
}
|
|
69
|
+
async fetchProject() {
|
|
70
|
+
const url = new url_1.URL(`/projects/${this.projectId}`, this.APIUrl);
|
|
71
|
+
const response = await this.fetchImpl(url.href);
|
|
72
|
+
if (!response.ok) {
|
|
73
|
+
throw new Error(`Failed to fetch project with id #${this.projectId}: ${response.statusText}`);
|
|
74
|
+
}
|
|
75
|
+
return response;
|
|
76
|
+
}
|
|
77
|
+
async fetchArticle(articleId) {
|
|
78
|
+
const url = new url_1.URL(`/articles/${articleId}`, this.APIUrl);
|
|
79
|
+
const response = await this.fetchImpl(url.href);
|
|
80
|
+
if (!response.ok) {
|
|
81
|
+
throw new Error(`Failed to fetch article with id #${articleId}: ${response.statusText}`);
|
|
82
|
+
}
|
|
83
|
+
return response;
|
|
84
|
+
}
|
|
85
|
+
async fetchKeyframes(articleId) {
|
|
86
|
+
const url = new url_1.URL(`/keyframes/${articleId}`, this.APIUrl);
|
|
87
|
+
const response = await this.fetchImpl(url.href);
|
|
88
|
+
if (!response.ok) {
|
|
89
|
+
throw new Error(`Failed to fetch keyframes for the article with id #${articleId}: ${response.statusText}`);
|
|
90
|
+
}
|
|
91
|
+
return response;
|
|
92
|
+
}
|
|
93
|
+
async fetchTypePresets() {
|
|
94
|
+
const url = new url_1.URL(`/projects/${this.projectId}/type-presets`, this.APIUrl);
|
|
95
|
+
const response = await this.fetchImpl(url.href);
|
|
96
|
+
if (!response.ok) {
|
|
97
|
+
throw new Error(`Failed to fetch type presets for the project with id #${this.projectId}: ${response.statusText}`);
|
|
98
|
+
}
|
|
99
|
+
return response;
|
|
100
|
+
}
|
|
101
|
+
findArticleIdByPageSlug(slug, pages) {
|
|
102
|
+
const page = pages.find((page) => page.slug === slug);
|
|
103
|
+
if (!page) {
|
|
104
|
+
throw new Error(`Page with a slug ${slug} was not found in project with id #${this.projectId}`);
|
|
105
|
+
}
|
|
106
|
+
return page.articleId;
|
|
107
|
+
}
|
|
62
108
|
}
|
|
63
109
|
exports.Client = Client;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cntrl-site/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Generic SDK for use in public websites.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "src/index.ts",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"lib": "lib"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@cntrl-site/core": "^1.14.
|
|
27
|
+
"@cntrl-site/core": "^1.14.1",
|
|
28
28
|
"@types/isomorphic-fetch": "^0.0.36",
|
|
29
29
|
"isomorphic-fetch": "^3.0.0",
|
|
30
30
|
"url": "^0.11.0"
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { Client } from './Client';
|
|
2
|
+
import { projectMock } from './__mock__/projectMock';
|
|
3
|
+
import { articleMock } from './__mock__/articleMock';
|
|
4
|
+
import { typePresetsMock } from './__mock__/typePresetsMock';
|
|
5
|
+
import { TMeta, TPageMeta } from '@cntrl-site/core';
|
|
6
|
+
import { keyframesMock } from './__mock__/keyframesMock';
|
|
7
|
+
|
|
8
|
+
describe('Client', () => {
|
|
9
|
+
it('returns project', async () => {
|
|
10
|
+
let fetchCalledTimes = 0;
|
|
11
|
+
const projectId = 'projectId';
|
|
12
|
+
const apiUrl = 'https://api.cntrl.site/';
|
|
13
|
+
const fetch = async (url: string) => {
|
|
14
|
+
fetchCalledTimes += 1;
|
|
15
|
+
expect(url).toBe(`${apiUrl}projects/${projectId}`);
|
|
16
|
+
return Promise.resolve({
|
|
17
|
+
ok: true,
|
|
18
|
+
json: () => Promise.resolve(projectMock),
|
|
19
|
+
statusText: ''
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
const client = new Client(projectId, apiUrl, fetch);
|
|
23
|
+
const project = await client.getProject();
|
|
24
|
+
expect(fetchCalledTimes).toBe(1);
|
|
25
|
+
expect(project).toEqual(projectMock);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('throws an error upon project fetch failure', async () => {
|
|
29
|
+
const projectId = 'projectId';
|
|
30
|
+
const apiUrl = 'https://api.cntrl.site/';
|
|
31
|
+
const fetch = async () => Promise.resolve({
|
|
32
|
+
ok: false,
|
|
33
|
+
statusText: 'reason',
|
|
34
|
+
json: () => Promise.resolve()
|
|
35
|
+
});
|
|
36
|
+
const client = new Client(projectId, apiUrl, fetch);
|
|
37
|
+
await expect(client.getProject()).rejects.toEqual(new Error('Failed to fetch project with id #projectId: reason'));
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('returns article by page slug', async () => {
|
|
41
|
+
let fetchCalledTimes = 0;
|
|
42
|
+
const projectId = 'projectId';
|
|
43
|
+
const apiUrl = 'https://api.cntrl.site/';
|
|
44
|
+
const projectApiUrl = `${apiUrl}projects/projectId`;
|
|
45
|
+
const articleApiUrl = `${apiUrl}articles/articleId`;
|
|
46
|
+
const fetch = async (url: string) => {
|
|
47
|
+
fetchCalledTimes += 1;
|
|
48
|
+
if (fetchCalledTimes === 1) {
|
|
49
|
+
expect(url).toBe(projectApiUrl);
|
|
50
|
+
}
|
|
51
|
+
if (fetchCalledTimes === 2) {
|
|
52
|
+
expect(url).toBe(articleApiUrl);
|
|
53
|
+
}
|
|
54
|
+
return Promise.resolve({
|
|
55
|
+
ok: true,
|
|
56
|
+
json: () => Promise.resolve(url === projectApiUrl ? projectMock : articleMock),
|
|
57
|
+
statusText: ''
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
const client = new Client(projectId, apiUrl, fetch);
|
|
61
|
+
const article = await client.getPageArticle('/');
|
|
62
|
+
expect(fetchCalledTimes).toBe(2);
|
|
63
|
+
expect(article).toEqual(articleMock);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('throws an error upon project fetch failure when trying to get article by slug', async () => {
|
|
67
|
+
const projectId = 'projectId';
|
|
68
|
+
const apiUrl = 'https://api.cntrl.site/';
|
|
69
|
+
const fetch = async () => Promise.resolve({
|
|
70
|
+
ok: false,
|
|
71
|
+
statusText: 'reason',
|
|
72
|
+
json: () => Promise.resolve()
|
|
73
|
+
});
|
|
74
|
+
const client = new Client(projectId, apiUrl, fetch);
|
|
75
|
+
await expect(client.getPageArticle('/'))
|
|
76
|
+
.rejects.toEqual(new Error('Failed to fetch project with id #projectId: reason'));
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('throws an error upon article fetch failure when trying to get article by slug', async () => {
|
|
80
|
+
const projectId = 'projectId';
|
|
81
|
+
const apiUrl = 'https://api.cntrl.site/';
|
|
82
|
+
const projectApiUrl = `${apiUrl}projects/projectId`;
|
|
83
|
+
const fetch = (url: string) => {
|
|
84
|
+
return Promise.resolve({
|
|
85
|
+
ok: url === projectApiUrl,
|
|
86
|
+
json: () => Promise.resolve(projectMock),
|
|
87
|
+
statusText: 'reason'
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
const client = new Client(projectId, apiUrl, fetch);
|
|
91
|
+
await expect(client.getPageArticle('/'))
|
|
92
|
+
.rejects.toEqual(new Error('Failed to fetch article with id #articleId: reason'));
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('throws an error when trying to fetch article by nonexistent slug', async () => {
|
|
96
|
+
const projectId = 'projectId';
|
|
97
|
+
const apiUrl = 'https://api.cntrl.site/';
|
|
98
|
+
const projectApiUrl = `${apiUrl}projects/projectId`;
|
|
99
|
+
const slug = '/nonexistent-slug';
|
|
100
|
+
const fetch = (url: string) => {
|
|
101
|
+
return Promise.resolve({
|
|
102
|
+
ok: url === projectApiUrl,
|
|
103
|
+
json: () => Promise.resolve(projectMock),
|
|
104
|
+
statusText: 'reason'
|
|
105
|
+
});
|
|
106
|
+
};
|
|
107
|
+
const client = new Client(projectId, apiUrl, fetch);
|
|
108
|
+
await expect(client.getPageArticle(slug))
|
|
109
|
+
.rejects.toEqual(new Error(`Page with a slug ${slug} was not found in project with id #${projectId}`));
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('returns type presets by project id', async () => {
|
|
113
|
+
let fetchCalledTimes = 0;
|
|
114
|
+
const projectId = 'projectId';
|
|
115
|
+
const apiUrl = 'https://api.cntrl.site/';
|
|
116
|
+
const fetch = (url: string) => {
|
|
117
|
+
fetchCalledTimes += 1;
|
|
118
|
+
expect(url).toBe(`${apiUrl}projects/${projectId}/type-presets`);
|
|
119
|
+
return Promise.resolve({
|
|
120
|
+
ok: true,
|
|
121
|
+
json: () => Promise.resolve(typePresetsMock),
|
|
122
|
+
statusText: ''
|
|
123
|
+
});
|
|
124
|
+
};
|
|
125
|
+
const client = new Client(projectId, apiUrl, fetch);
|
|
126
|
+
const presets = await client.getTypePresets();
|
|
127
|
+
expect(presets).toEqual(typePresetsMock);
|
|
128
|
+
expect(fetchCalledTimes).toEqual(1);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('throws an error upon type presets fetch failure', async () => {
|
|
132
|
+
const projectId = 'projectId';
|
|
133
|
+
const apiUrl = 'https://api.cntrl.site/';
|
|
134
|
+
const fetch = () => {
|
|
135
|
+
return Promise.resolve({
|
|
136
|
+
ok: false,
|
|
137
|
+
json: () => Promise.resolve(),
|
|
138
|
+
statusText: 'reason'
|
|
139
|
+
});
|
|
140
|
+
};
|
|
141
|
+
const client = new Client(projectId, apiUrl, fetch);
|
|
142
|
+
await expect(client.getTypePresets()).rejects.toEqual(
|
|
143
|
+
new Error(`Failed to fetch type presets for the project with id #${projectId}: reason`)
|
|
144
|
+
);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('returns keyframes by article id', async () => {
|
|
148
|
+
let fetchCalledTimes = 0;
|
|
149
|
+
const projectId = 'projectId';
|
|
150
|
+
const articleId = 'articleId';
|
|
151
|
+
const apiUrl = 'https://api.cntrl.site/';
|
|
152
|
+
const fetch = (url: string) => {
|
|
153
|
+
fetchCalledTimes += 1;
|
|
154
|
+
expect(url).toBe(`${apiUrl}keyframes/${articleId}`);
|
|
155
|
+
return Promise.resolve({
|
|
156
|
+
ok: true,
|
|
157
|
+
json: () => Promise.resolve(keyframesMock),
|
|
158
|
+
statusText: ''
|
|
159
|
+
});
|
|
160
|
+
};
|
|
161
|
+
const client = new Client(projectId, apiUrl, fetch);
|
|
162
|
+
const presets = await client.getKeyframes(articleId);
|
|
163
|
+
expect(presets).toEqual(keyframesMock);
|
|
164
|
+
expect(fetchCalledTimes).toEqual(1);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('throws an error upon keyframes fetch failure', async () => {
|
|
168
|
+
const projectId = 'projectId';
|
|
169
|
+
const articleId = 'articleId';
|
|
170
|
+
const apiUrl = 'https://api.cntrl.site/';
|
|
171
|
+
const fetch = () => {
|
|
172
|
+
return Promise.resolve({
|
|
173
|
+
ok: false,
|
|
174
|
+
json: () => Promise.resolve(),
|
|
175
|
+
statusText: 'reason'
|
|
176
|
+
});
|
|
177
|
+
};
|
|
178
|
+
const client = new Client(projectId, apiUrl, fetch);
|
|
179
|
+
await expect(client.getKeyframes(articleId)).rejects.toEqual(
|
|
180
|
+
new Error(`Failed to fetch keyframes for the article with id #${articleId}: reason`)
|
|
181
|
+
);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('merges two meta objects into one with priority of page-based over project-based', () => {
|
|
185
|
+
const pageMeta: TPageMeta = {
|
|
186
|
+
enabled: true,
|
|
187
|
+
description: 'page-desc',
|
|
188
|
+
title: 'page-title'
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const projectMeta: TMeta = {
|
|
192
|
+
opengraphThumbnail: 'proj-og',
|
|
193
|
+
description: 'proj-desc',
|
|
194
|
+
title: 'proj-title',
|
|
195
|
+
keywords: 'project, keywords'
|
|
196
|
+
};
|
|
197
|
+
const meta = Client.getPageMeta(projectMeta, pageMeta);
|
|
198
|
+
expect(meta.keywords).toBe(projectMeta.keywords);
|
|
199
|
+
expect(meta.opengraphThumbnail).toBe(projectMeta.opengraphThumbnail);
|
|
200
|
+
expect(meta.description).toBe(pageMeta.description);
|
|
201
|
+
expect(meta.title).toBe(pageMeta.title);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it('ignores page meta when `enabled` is set to `false` and uses only generic project meta', () => {
|
|
205
|
+
const pageMeta: TPageMeta = {
|
|
206
|
+
enabled: false,
|
|
207
|
+
description: 'page-desc',
|
|
208
|
+
title: 'page-title'
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
const projectMeta: TMeta = {
|
|
212
|
+
opengraphThumbnail: 'proj-og',
|
|
213
|
+
keywords: 'project, keywords'
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
const meta = Client.getPageMeta(projectMeta, pageMeta);
|
|
217
|
+
expect(meta.keywords).toBe(projectMeta.keywords);
|
|
218
|
+
expect(meta.opengraphThumbnail).toBe(projectMeta.opengraphThumbnail);
|
|
219
|
+
expect(meta.description).toBeUndefined();
|
|
220
|
+
expect(meta.title).toBeUndefined();
|
|
221
|
+
});
|
|
222
|
+
});
|
package/src/Client/Client.ts
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
TProject,
|
|
3
|
+
ProjectSchema,
|
|
4
|
+
TArticle,
|
|
5
|
+
ArticleSchema,
|
|
6
|
+
TMeta,
|
|
7
|
+
TPageMeta,
|
|
8
|
+
TTypePresets,
|
|
9
|
+
TypePresetsSchema,
|
|
10
|
+
TPage,
|
|
11
|
+
TKeyframeAny,
|
|
12
|
+
KeyframesSchema
|
|
13
|
+
} from '@cntrl-site/core';
|
|
2
14
|
import fetch from 'isomorphic-fetch';
|
|
3
15
|
import { URL } from 'url';
|
|
4
16
|
|
|
@@ -6,7 +18,7 @@ export class Client {
|
|
|
6
18
|
constructor(
|
|
7
19
|
private projectId: string,
|
|
8
20
|
private APIUrl: string,
|
|
9
|
-
private fetchImpl = fetch
|
|
21
|
+
private fetchImpl: FetchImpl = fetch
|
|
10
22
|
) {
|
|
11
23
|
if (projectId.length === 0) {
|
|
12
24
|
throw new Error('CNTRL SDK: Project ID is empty. Did you forget to pass it?');
|
|
@@ -17,37 +29,43 @@ export class Client {
|
|
|
17
29
|
}
|
|
18
30
|
|
|
19
31
|
async getProject(): Promise<TProject> {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
32
|
+
try {
|
|
33
|
+
const response = await this.fetchProject();
|
|
34
|
+
const data = await response.json();
|
|
35
|
+
const project = ProjectSchema.parse(data);
|
|
36
|
+
return project;
|
|
37
|
+
} catch (e) {
|
|
38
|
+
throw e;
|
|
24
39
|
}
|
|
25
|
-
const data = await response.json();
|
|
26
|
-
const project = ProjectSchema.parse(data);
|
|
27
|
-
return project;
|
|
28
40
|
}
|
|
29
41
|
|
|
30
42
|
async getPageArticle(pageSlug: string): Promise<TArticle> {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const url = new URL(`/articles/${page.articleId}`, this.APIUrl);
|
|
43
|
-
const articleResponse = await this.fetchImpl(url.href);
|
|
44
|
-
if (!articleResponse.ok) {
|
|
45
|
-
throw new Error(`Failed to fetch article with id #${page.articleId}: ${articleResponse.statusText}`);
|
|
43
|
+
try {
|
|
44
|
+
const projectResponse = await this.fetchProject();
|
|
45
|
+
const data = await projectResponse.json();
|
|
46
|
+
const project = ProjectSchema.parse(data);
|
|
47
|
+
const articleId = this.findArticleIdByPageSlug(pageSlug, project.pages);
|
|
48
|
+
const articleResponse = await this.fetchArticle(articleId);
|
|
49
|
+
const articleData = await articleResponse.json();
|
|
50
|
+
const article = ArticleSchema.parse(articleData);
|
|
51
|
+
return article;
|
|
52
|
+
} catch (e) {
|
|
53
|
+
throw e;
|
|
46
54
|
}
|
|
47
|
-
|
|
48
|
-
const article = ArticleSchema.parse(articleData);
|
|
55
|
+
}
|
|
49
56
|
|
|
50
|
-
|
|
57
|
+
async getTypePresets(): Promise<TTypePresets> {
|
|
58
|
+
const response = await this.fetchTypePresets();
|
|
59
|
+
const data = await response.json();
|
|
60
|
+
const typePresets = TypePresetsSchema.parse(data);
|
|
61
|
+
return typePresets;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async getKeyframes(articleId: string): Promise<TKeyframeAny[]> {
|
|
65
|
+
const response = await this.fetchKeyframes(articleId);
|
|
66
|
+
const data = await response.json();
|
|
67
|
+
const keyframes = KeyframesSchema.parse(data);
|
|
68
|
+
return keyframes;
|
|
51
69
|
}
|
|
52
70
|
|
|
53
71
|
public static getPageMeta(projectMeta: TMeta, pageMeta: TPageMeta): TMeta {
|
|
@@ -59,4 +77,58 @@ export class Client {
|
|
|
59
77
|
favicon: projectMeta.favicon
|
|
60
78
|
} : projectMeta;
|
|
61
79
|
}
|
|
80
|
+
|
|
81
|
+
private async fetchProject(): Promise<FetchImplResponse> {
|
|
82
|
+
const url = new URL(`/projects/${this.projectId}`, this.APIUrl);
|
|
83
|
+
const response = await this.fetchImpl(url.href);
|
|
84
|
+
if (!response.ok) {
|
|
85
|
+
throw new Error(`Failed to fetch project with id #${this.projectId}: ${response.statusText}`);
|
|
86
|
+
}
|
|
87
|
+
return response;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private async fetchArticle(articleId: string): Promise<FetchImplResponse> {
|
|
91
|
+
const url = new URL(`/articles/${articleId}`, this.APIUrl);
|
|
92
|
+
const response = await this.fetchImpl(url.href);
|
|
93
|
+
if (!response.ok) {
|
|
94
|
+
throw new Error(`Failed to fetch article with id #${articleId}: ${response.statusText}`);
|
|
95
|
+
}
|
|
96
|
+
return response;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private async fetchKeyframes(articleId: string): Promise<FetchImplResponse> {
|
|
100
|
+
const url = new URL(`/keyframes/${articleId}`, this.APIUrl);
|
|
101
|
+
const response = await this.fetchImpl(url.href);
|
|
102
|
+
if (!response.ok) {
|
|
103
|
+
throw new Error(`Failed to fetch keyframes for the article with id #${articleId}: ${response.statusText}`);
|
|
104
|
+
}
|
|
105
|
+
return response;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private async fetchTypePresets(): Promise<FetchImplResponse> {
|
|
109
|
+
const url = new URL(`/projects/${this.projectId}/type-presets`, this.APIUrl);
|
|
110
|
+
const response = await this.fetchImpl(url.href);
|
|
111
|
+
if (!response.ok) {
|
|
112
|
+
throw new Error(
|
|
113
|
+
`Failed to fetch type presets for the project with id #${this.projectId}: ${response.statusText}`
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
return response;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private findArticleIdByPageSlug(slug: string, pages: TPage[]): string {
|
|
120
|
+
const page = pages.find((page) => page.slug === slug);
|
|
121
|
+
if (!page) {
|
|
122
|
+
throw new Error(`Page with a slug ${slug} was not found in project with id #${this.projectId}`);
|
|
123
|
+
}
|
|
124
|
+
return page.articleId;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
interface FetchImplResponse {
|
|
129
|
+
ok: boolean;
|
|
130
|
+
json(): Promise<any>;
|
|
131
|
+
statusText: string;
|
|
62
132
|
}
|
|
133
|
+
|
|
134
|
+
type FetchImpl = (url: string) => Promise<FetchImplResponse>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { KeyframeType, TKeyframeAny } from '@cntrl-site/core';
|
|
2
|
+
|
|
3
|
+
export const keyframesMock: TKeyframeAny[] = [
|
|
4
|
+
{
|
|
5
|
+
id: 'keyframeId',
|
|
6
|
+
articleId: 'articleId',
|
|
7
|
+
type: KeyframeType.Color,
|
|
8
|
+
position: 100,
|
|
9
|
+
value: {
|
|
10
|
+
color: 'black'
|
|
11
|
+
},
|
|
12
|
+
itemId: 'itemId',
|
|
13
|
+
layoutId: 'layoutId'
|
|
14
|
+
}
|
|
15
|
+
];
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { TProject } from '@cntrl-site/core';
|
|
2
|
+
|
|
3
|
+
export const projectMock: TProject = {
|
|
4
|
+
id: 'projectId',
|
|
5
|
+
layouts: [],
|
|
6
|
+
fonts: {
|
|
7
|
+
google: '',
|
|
8
|
+
adobe: '',
|
|
9
|
+
custom: []
|
|
10
|
+
},
|
|
11
|
+
html: {
|
|
12
|
+
beforeBodyClose: '',
|
|
13
|
+
afterBodyOpen: '',
|
|
14
|
+
head: ''
|
|
15
|
+
},
|
|
16
|
+
meta: {
|
|
17
|
+
favicon: undefined,
|
|
18
|
+
title: undefined,
|
|
19
|
+
opengraphThumbnail: undefined,
|
|
20
|
+
keywords: undefined,
|
|
21
|
+
description: undefined
|
|
22
|
+
},
|
|
23
|
+
grid: {
|
|
24
|
+
color: 'rgba(0, 0, 0, 1)'
|
|
25
|
+
},
|
|
26
|
+
pages: [{
|
|
27
|
+
id: 'pageId',
|
|
28
|
+
title: 'Page',
|
|
29
|
+
articleId: 'articleId',
|
|
30
|
+
slug: '/',
|
|
31
|
+
isPublished: true,
|
|
32
|
+
meta: {
|
|
33
|
+
opengraphThumbnail: 'page-thumbnail',
|
|
34
|
+
title: 'page-title',
|
|
35
|
+
description: 'page-description',
|
|
36
|
+
enabled: true,
|
|
37
|
+
keywords: 'page-keywords'
|
|
38
|
+
}
|
|
39
|
+
}]
|
|
40
|
+
};
|