@prismicio/e2e-tests-utils 1.4.0-alpha.2 → 1.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.
Files changed (58) hide show
  1. package/README.md +16 -9
  2. package/dist/clients/apiClient.cjs +39 -0
  3. package/dist/clients/apiClient.cjs.map +1 -0
  4. package/dist/clients/apiClient.d.ts +30 -0
  5. package/dist/clients/apiClient.js +39 -0
  6. package/dist/clients/apiClient.js.map +1 -0
  7. package/dist/clients/authenticationApi.cjs +54 -34
  8. package/dist/clients/authenticationApi.cjs.map +1 -1
  9. package/dist/clients/authenticationApi.d.ts +13 -5
  10. package/dist/clients/authenticationApi.js +55 -35
  11. package/dist/clients/authenticationApi.js.map +1 -1
  12. package/dist/clients/contentApi.cjs +20 -50
  13. package/dist/clients/contentApi.cjs.map +1 -1
  14. package/dist/clients/contentApi.d.ts +27 -37
  15. package/dist/clients/contentApi.js +20 -50
  16. package/dist/clients/contentApi.js.map +1 -1
  17. package/dist/clients/coreApi.cjs +36 -31
  18. package/dist/clients/coreApi.cjs.map +1 -1
  19. package/dist/clients/coreApi.d.ts +21 -3
  20. package/dist/clients/coreApi.js +37 -32
  21. package/dist/clients/coreApi.js.map +1 -1
  22. package/dist/clients/customTypesApi.cjs +48 -42
  23. package/dist/clients/customTypesApi.cjs.map +1 -1
  24. package/dist/clients/customTypesApi.d.ts +34 -6
  25. package/dist/clients/customTypesApi.js +49 -43
  26. package/dist/clients/customTypesApi.js.map +1 -1
  27. package/dist/clients/migrationApi.cjs +30 -29
  28. package/dist/clients/migrationApi.cjs.map +1 -1
  29. package/dist/clients/migrationApi.d.ts +27 -5
  30. package/dist/clients/migrationApi.js +31 -30
  31. package/dist/clients/migrationApi.js.map +1 -1
  32. package/dist/index.cjs +1 -1
  33. package/dist/index.js +2 -2
  34. package/dist/managers/repositories.cjs +19 -9
  35. package/dist/managers/repositories.cjs.map +1 -1
  36. package/dist/managers/repositories.d.ts +2 -2
  37. package/dist/managers/repositories.js +23 -13
  38. package/dist/managers/repositories.js.map +1 -1
  39. package/dist/managers/repository.cjs +9 -1
  40. package/dist/managers/repository.cjs.map +1 -1
  41. package/dist/managers/repository.d.ts +6 -4
  42. package/dist/managers/repository.js +9 -1
  43. package/dist/managers/repository.js.map +1 -1
  44. package/dist/utils/log.cjs +4 -0
  45. package/dist/utils/log.cjs.map +1 -1
  46. package/dist/utils/log.d.ts +2 -0
  47. package/dist/utils/log.js +4 -0
  48. package/dist/utils/log.js.map +1 -1
  49. package/package.json +3 -1
  50. package/src/clients/apiClient.ts +48 -0
  51. package/src/clients/authenticationApi.ts +52 -50
  52. package/src/clients/contentApi.ts +53 -45
  53. package/src/clients/coreApi.ts +36 -42
  54. package/src/clients/customTypesApi.ts +34 -59
  55. package/src/clients/migrationApi.ts +36 -45
  56. package/src/managers/repositories.ts +26 -20
  57. package/src/managers/repository.ts +21 -8
  58. package/src/utils/log.ts +11 -0
@@ -1,82 +1,84 @@
1
- import axios, { AxiosInstance } from "axios";
1
+ import { APIRequestContext, request } from "@playwright/test";
2
2
 
3
3
  import { AuthConfig } from "../types";
4
4
 
5
- import { logHttpResponse, logger } from "../utils/log";
6
-
7
- export type AuthenticationClient = {
8
- getToken: () => Promise<string>;
9
- getMachine2MachineToken: (repository: string) => Promise<string>;
10
- };
5
+ import { logPlaywrightApiResponse, logger } from "../utils/log";
11
6
 
12
7
  /** Client for interacting with the authentication service to manage tokens */
13
- export const createAuthenticationApiClient = (
14
- baseURL: string,
15
- auth: AuthConfig,
16
- ): AuthenticationClient => {
17
- let authToken: string;
18
-
19
- const client: AxiosInstance = axios.create({
20
- baseURL,
21
- validateStatus: () => true, // Don't throw on 4XX errors
22
- });
23
-
24
- async function login(): Promise<string> {
8
+ export class AuthenticationApiClient {
9
+ private authToken?: string;
10
+ private _context?: APIRequestContext;
11
+
12
+ constructor(
13
+ private readonly baseURL: string,
14
+ private readonly auth: AuthConfig,
15
+ ) {}
16
+
17
+ private async getContext(): Promise<APIRequestContext> {
18
+ if (!this._context) {
19
+ this._context = await request.newContext({
20
+ baseURL: this.baseURL,
21
+ });
22
+ }
23
+
24
+ return this._context;
25
+ }
26
+
27
+ private async login(): Promise<string> {
25
28
  const profiler = logger.startTimer();
26
29
 
27
- const result = await client.post("login", {
28
- email: auth.email,
29
- password: auth.password,
30
+ const context = await this.getContext();
31
+ const result = await context.post("login", {
32
+ data: {
33
+ email: this.auth.email,
34
+ password: this.auth.password,
35
+ },
30
36
  });
31
37
 
32
- if (!result.data || typeof result.data !== "string") {
33
- logHttpResponse(result);
38
+ const token = await result.text();
39
+ if (!result.ok() || !token) {
40
+ logPlaywrightApiResponse(result);
34
41
  throw new Error("Authentication failed, no token received.");
35
42
  }
36
43
 
37
44
  profiler.done({
38
- message: `generated user token for ${auth.email} from auth service`,
45
+ message: `generated user token for ${this.auth.email} from auth service`,
39
46
  });
40
47
 
41
- return result.data;
48
+ return token;
42
49
  }
43
50
 
44
51
  /** Return an api user token. Creates one if needed. */
45
- async function getToken(): Promise<string> {
46
- if (!authToken) {
47
- authToken = await login();
52
+ async getToken(): Promise<string> {
53
+ if (!this.authToken) {
54
+ this.authToken = await this.login();
48
55
  }
49
56
 
50
- return authToken;
57
+ return this.authToken;
51
58
  }
52
59
 
53
60
  /** Return an api user token. Creates one if needed. */
54
- async function getMachine2MachineToken(repository: string): Promise<string> {
55
- if (!authToken) {
56
- authToken = await login();
61
+ async getMachine2MachineToken(repository: string): Promise<string> {
62
+ if (!this.authToken) {
63
+ this.authToken = await this.login();
57
64
  }
58
- const result = await client.get<{ token: string; timestamp: number }>(
59
- "machine2machine",
60
- {
61
- headers: {
62
- Authorization: `Bearer ${authToken}`,
63
- repository,
64
- },
65
+
66
+ const context = await this.getContext();
67
+ const result = await context.get("machine2machine", {
68
+ headers: {
69
+ Authorization: `Bearer ${this.authToken}`,
70
+ repository,
65
71
  },
66
- );
72
+ });
67
73
 
68
- if (![200].includes(result.status) || !result.data.token) {
69
- logHttpResponse(result);
74
+ if (!result.ok()) {
75
+ logPlaywrightApiResponse(result);
70
76
  throw new Error(
71
77
  "Machine2Machine token generation failed, no token received.",
72
78
  );
73
79
  }
80
+ const token = (await result.json()).token;
74
81
 
75
- return result.data.token;
82
+ return token;
76
83
  }
77
-
78
- return {
79
- getToken,
80
- getMachine2MachineToken,
81
- };
82
- };
84
+ }
@@ -1,10 +1,12 @@
1
- import { APIResponse, request } from "@playwright/test";
1
+ import { APIResponse } from "@playwright/test";
2
2
 
3
- export interface Error {
3
+ import { AuthenticatedApiClient } from "./apiClient";
4
+
5
+ export interface ContentApiError {
4
6
  type: string;
5
7
  message: string;
6
8
  }
7
- export interface SearchResponse {
9
+ export interface ContentApiSearchResponse {
8
10
  page: number;
9
11
  results_per_page: number;
10
12
  results_size: number;
@@ -12,10 +14,10 @@ export interface SearchResponse {
12
14
  total_pages: number;
13
15
  next_page: string | null;
14
16
  prev_page: string | null;
15
- results: Document[];
17
+ results: ContentApiDocument[];
16
18
  }
17
19
 
18
- export interface Document {
20
+ export interface ContentApiDocument {
19
21
  id: string;
20
22
  uid: string | null;
21
23
  url: string | null;
@@ -32,22 +34,22 @@ export interface Document {
32
34
  data: Record<string, any>;
33
35
  }
34
36
 
35
- export interface GraphQLResponse {
37
+ export interface ContentApiGraphQLResponse {
36
38
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
37
39
  data: Record<string, any>;
38
40
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
39
41
  errors?: { message: string; locations: any }[];
40
42
  }
41
43
 
42
- export interface Ref {
44
+ export interface ContentApiRef {
43
45
  id: string;
44
46
  ref: string;
45
47
  label: string;
46
48
  isMasterRef?: boolean;
47
49
  }
48
50
 
49
- export interface RepoConfig {
50
- refs: Ref[];
51
+ interface ContentApiRepoConfigResponse {
52
+ refs: ContentApiRef[];
51
53
  bookmarks: Record<string, unknown>;
52
54
  types: Record<string, string>;
53
55
  languages: {
@@ -62,7 +64,7 @@ export interface RepoConfig {
62
64
  version: string;
63
65
  }
64
66
 
65
- export type QueryParams = {
67
+ type SearchQueryParams = {
66
68
  ref?: string;
67
69
  query?: string;
68
70
  q?: string;
@@ -80,18 +82,22 @@ type ApiVersions = "v1" | "v2";
80
82
 
81
83
  /**
82
84
  * Client to query the Prismic content api. Uses Playwright to benefit from
83
- * network request traces in your reports. The @prismicio/client could have been
84
- * used but had too many abstractions (caching, error handling) that we didn't
85
- * want for test execution. See api docs:
85
+ * network request traces in your reports. See api docs:
86
86
  * https://prismic.io/docs/rest-api-technical-reference
87
87
  */
88
- export class ContentApiClient {
89
- #version: ApiVersions;
90
- #accessToken: string | undefined;
88
+ export class ContentApiClient extends AuthenticatedApiClient {
89
+ private version: ApiVersions;
90
+ private accessToken: string | undefined;
91
91
 
92
92
  /**
93
- * @example new ContentApiClient("https://my-repo.cdn.prismic.io" { version :
94
- * "v2", accessToken: "my-secret-token" })
93
+ * @example To instantiate the class:
94
+ *
95
+ * ```js
96
+ * new ContentApiClient("https://my-repo.cdn.prismic.io", {
97
+ * version: "v2",
98
+ * accessToken: "my-secret-token",
99
+ * });
100
+ * ```
95
101
  *
96
102
  * @param baseURL - the api base URL like https://my-repo.cdn.prismic.io
97
103
  * @param config - Optional configuration
@@ -101,30 +107,24 @@ export class ContentApiClient {
101
107
  * https://prismic.io/docs/access-token
102
108
  */
103
109
  constructor(
104
- private readonly baseURL: string,
110
+ baseURL: string,
105
111
  config: { version?: ApiVersions; accessToken?: string } = {},
106
112
  ) {
107
- this.#version = config.version || "v2";
108
- this.#accessToken = config.accessToken;
109
- }
110
-
111
- #context() {
112
- return request.newContext({
113
- baseURL: this.baseURL,
114
- // reset any Authorization header set globally with Playwright
115
- // didn't find a way to delete it
116
- extraHTTPHeaders: { Authorization: "" },
117
- });
113
+ // Use an empty string as auth header in case it is already set globally in the project Playwright config file.
114
+ // This is because the api returns an error whenever an auth header is present in the content api request.
115
+ super(baseURL, "");
116
+ this.version = config.version || "v2";
117
+ this.accessToken = config.accessToken;
118
118
  }
119
119
 
120
120
  async get(
121
121
  path: string,
122
- params?: QueryParams,
122
+ params?: SearchQueryParams,
123
123
  headers?: Record<string, string>,
124
124
  ): Promise<APIResponse> {
125
- const context = await this.#context();
125
+ const context = await this.getContext();
126
126
  const securityParams = {
127
- ...(this.#accessToken ? { access_token: this.#accessToken } : {}),
127
+ ...(this.accessToken ? { access_token: this.accessToken } : {}),
128
128
  };
129
129
 
130
130
  return context.get(path, {
@@ -135,7 +135,7 @@ export class ContentApiClient {
135
135
 
136
136
  async getAsJson<T>(
137
137
  url: string,
138
- params?: QueryParams,
138
+ params?: SearchQueryParams,
139
139
  headers?: Record<string, string>,
140
140
  ): Promise<T> {
141
141
  const response = await this.get(url, params, headers);
@@ -144,16 +144,21 @@ export class ContentApiClient {
144
144
  }
145
145
 
146
146
  /** Query the graphql api - https://prismic.io/docs/graphql-technical-reference */
147
- async graphql(ref: string, query: string): Promise<GraphQLResponse> {
148
- return this.getAsJson<GraphQLResponse>(
149
- "/graphql",
147
+ async graphql(
148
+ ref: string,
149
+ query: string,
150
+ ): Promise<ContentApiGraphQLResponse> {
151
+ return this.getAsJson<ContentApiGraphQLResponse>(
152
+ "graphql",
150
153
  { query },
151
154
  { "Prismic-ref": ref },
152
155
  );
153
156
  }
154
157
 
155
- async getRefs(): Promise<Ref[]> {
156
- const data = await this.getAsJson<RepoConfig>(`/api/${this.#version}`);
158
+ async getRefs(): Promise<ContentApiRef[]> {
159
+ const data = await this.getAsJson<ContentApiRepoConfigResponse>(
160
+ `api/${this.version}`,
161
+ );
157
162
 
158
163
  return data.refs;
159
164
  }
@@ -180,14 +185,14 @@ export class ContentApiClient {
180
185
  }
181
186
 
182
187
  /** Search documents from the `/api/v<version>/documents/search` endpoint. */
183
- async search(filters?: QueryParams): Promise<SearchResponse> {
188
+ async search(filters?: SearchQueryParams): Promise<ContentApiSearchResponse> {
184
189
  let ref = filters?.ref;
185
190
  if (!ref) {
186
191
  ref = await this.getMasterRef();
187
192
  }
188
193
 
189
- return this.getAsJson<SearchResponse>(
190
- `/api/${this.#version}/documents/search`,
194
+ return this.getAsJson<ContentApiSearchResponse>(
195
+ `api/${this.version}/documents/search`,
191
196
  {
192
197
  ...filters,
193
198
  ref,
@@ -199,15 +204,18 @@ export class ContentApiClient {
199
204
  * Search for a single document by its it, using the
200
205
  * `/api/v<version>/documents/search` endpoint and a default filter.
201
206
  */
202
- async searchByID(id: string, filters?: QueryParams): Promise<SearchResponse> {
207
+ async searchByID(
208
+ id: string,
209
+ filters?: SearchQueryParams,
210
+ ): Promise<ContentApiSearchResponse> {
203
211
  return this.search({ ...filters, q: `[[at(document.id, "${id}")]]` });
204
212
  }
205
213
 
206
214
  /** Retrieve a single document or undefined if not found. */
207
215
  async getDocumentByID(
208
216
  id: string,
209
- filters?: QueryParams,
210
- ): Promise<Document | undefined> {
217
+ filters?: SearchQueryParams,
218
+ ): Promise<ContentApiDocument | undefined> {
211
219
  const data = await this.searchByID(id, filters);
212
220
  switch (data.results_size) {
213
221
  case 0:
@@ -1,8 +1,6 @@
1
- import axios, { AxiosInstance } from "axios";
1
+ import { logPlaywrightApiResponse, logger } from "../utils/log";
2
2
 
3
- import { logHttpResponse, logger } from "../utils/log";
4
-
5
- import { AuthenticationClient } from "./authenticationApi";
3
+ import { AuthServerToken, AuthenticatedApiClient } from "./apiClient";
6
4
 
7
5
  type Language = {
8
6
  id: string;
@@ -15,56 +13,52 @@ export type CoreClient = {
15
13
  publishDraft(documentId: string): Promise<void>;
16
14
  };
17
15
 
18
- /** Client for interacting with the core API */
19
- export const createCoreApiClient = (
20
- baseURL: string,
21
- authClient: AuthenticationClient,
22
- ): CoreClient => {
23
- const client: AxiosInstance = axios.create({
24
- baseURL,
25
- validateStatus: () => true, // Don't throw on 4XX errors
26
- });
27
-
28
- // Add an interceptor to authenticate requests
29
- client.interceptors.request.use(async (config) => {
30
- const auth = "Authorization";
31
- if (!config.headers[auth]) {
32
- const token = await authClient.getToken();
33
- config.headers[auth] = `Bearer ${token}`;
34
- }
35
-
36
- return config;
37
- });
16
+ export class CoreApiClient extends AuthenticatedApiClient {
17
+ /**
18
+ * @example To instantiate the class:
19
+ *
20
+ * ```js
21
+ * new CoreApiClient("https://my-repo.prismic.io", {
22
+ * authToken: "my-secret-token",
23
+ * });
24
+ * ```
25
+ *
26
+ * @param baseURL - the api base URL like https://my-repo.prismic.io
27
+ * @param config - Optional configuration
28
+ *
29
+ * - {@link config.authToken}: Api token generated from the auth service or a
30
+ * function to fetch it when it's needed.
31
+ */
32
+ constructor(baseURL: string, config: AuthServerToken) {
33
+ super(baseURL, config);
34
+ }
38
35
 
39
- async function getLanguages(): Promise<Language[]> {
36
+ async getLanguages(): Promise<Language[]> {
40
37
  const profiler = logger.startTimer();
41
- const result = await client.get<{ languages: Language[] }>(
42
- "core/repository",
43
- );
38
+ const context = await this.getContext();
39
+ const result = await context.get("core/repository");
44
40
 
45
- if (200 !== result.status || !result.data.languages) {
46
- logHttpResponse(result);
41
+ if (200 !== result.status() || !(await result.json()).languages) {
42
+ await logPlaywrightApiResponse(result);
47
43
  throw new Error("Could not get languages from the core api.");
48
44
  }
49
45
 
50
46
  profiler.done({ message: "retrieved languages configuration" });
51
47
 
52
- return result.data.languages;
48
+ return (await result.json()).languages;
53
49
  }
54
50
 
55
- async function publishDraft(documentId: string): Promise<void> {
56
- const result = await client.patch(`core/documents/${documentId}/draft`, {
57
- status: "published",
51
+ async publishDraft(documentId: string): Promise<void> {
52
+ const context = await this.getContext();
53
+ const result = await context.patch(`core/documents/${documentId}/draft`, {
54
+ data: {
55
+ status: "published",
56
+ },
58
57
  });
59
58
 
60
- if (204 !== result.status) {
61
- logHttpResponse(result);
59
+ if (204 !== result.status()) {
60
+ await logPlaywrightApiResponse(result);
62
61
  throw new Error(`Could not publish document with id ${documentId}`);
63
62
  }
64
63
  }
65
-
66
- return {
67
- getLanguages,
68
- publishDraft,
69
- };
70
- };
64
+ }
@@ -1,4 +1,3 @@
1
- import axios, { AxiosInstance } from "axios";
2
1
  import isEqual from "lodash.isequal";
3
2
 
4
3
  import {
@@ -6,46 +5,25 @@ import {
6
5
  SharedSlice,
7
6
  } from "@prismicio/types-internal/lib/customtypes";
8
7
 
9
- import { logHttpResponse, logger } from "../utils/log";
8
+ import { logPlaywrightApiResponse, logger } from "../utils/log";
10
9
 
11
- import { AuthenticationClient } from "./authenticationApi";
10
+ import { AuthServerToken, AuthenticatedApiClient } from "./apiClient";
12
11
 
13
- export type CustomTypesClient = {
14
- createCustomTypes(customTypes: CustomType[]): Promise<void>;
15
- createSlices(slices: SharedSlice[]): Promise<void>;
16
- };
12
+ type ItemType = CustomType | SharedSlice;
13
+ type ItemTypePath = "customtypes" | "slices";
14
+ type ItemOperation = "insert" | "update";
17
15
 
18
16
  /**
19
17
  * Client for interacting with the Custom Types API to create/update custom
20
18
  * types and slices.
21
19
  */
22
- export const createCustomTypesApiClient = (
23
- baseURL: string,
24
- repository: string,
25
- authClient: AuthenticationClient,
26
- ): CustomTypesClient => {
27
- type ItemType = CustomType | SharedSlice;
28
- type ItemTypePath = "customtypes" | "slices";
29
- type ItemOperation = "insert" | "update";
30
-
31
- const client: AxiosInstance = axios.create({
32
- baseURL,
33
- validateStatus: () => true, // Don't throw on 4XX errors
34
- headers: {
35
- repository,
36
- },
37
- });
38
-
39
- // Add an interceptor to authenticate requests
40
- client.interceptors.request.use(async (config) => {
41
- const auth = "Authorization";
42
- if (!config.headers[auth]) {
43
- const token = await authClient.getToken();
44
- config.headers[auth] = `Bearer ${token}`;
45
- }
46
-
47
- return config;
48
- });
20
+ export class CustomTypesApiClient extends AuthenticatedApiClient {
21
+ constructor(
22
+ baseURL: string,
23
+ config: { authToken: AuthServerToken; repository: string },
24
+ ) {
25
+ super(baseURL, config.authToken, { repository: config.repository });
26
+ }
49
27
 
50
28
  /**
51
29
  * Create or update a custom type or slice.
@@ -57,7 +35,7 @@ export const createCustomTypesApiClient = (
57
35
  * @throws Error if the item status cannot be retrieved or the item cannot be
58
36
  * created/updated.
59
37
  */
60
- async function upsert(
38
+ private async upsert(
61
39
  endpoint: ItemTypePath,
62
40
  operation: ItemOperation,
63
41
  data: ItemType,
@@ -65,9 +43,10 @@ export const createCustomTypesApiClient = (
65
43
  const profiler = logger.startTimer();
66
44
  const path = `${endpoint}/${operation}`;
67
45
 
68
- const result = await client.post(path, data, { headers: {} });
69
- if (![201, 204].includes(result.status)) {
70
- logHttpResponse(result);
46
+ const context = await this.getContext();
47
+ const result = await context.post(path, { data });
48
+ if (!result.ok()) {
49
+ logPlaywrightApiResponse(result);
71
50
  throw new Error(`Could not ${operation} item`);
72
51
  }
73
52
  profiler.done({
@@ -75,20 +54,21 @@ export const createCustomTypesApiClient = (
75
54
  });
76
55
  }
77
56
 
78
- async function getRemoteItems(
57
+ private async getRemoteItems(
79
58
  endpoint: ItemTypePath,
80
59
  ): Promise<CustomType[] | SharedSlice[]> {
81
- const result = await client.get(endpoint);
60
+ const context = await this.getContext();
61
+ const result = await context.get(endpoint);
82
62
 
83
- if (![200].includes(result.status)) {
84
- logHttpResponse(result);
63
+ if (!result.ok()) {
64
+ logPlaywrightApiResponse(result);
85
65
  throw new Error("Could not get items status from the Custom Type api.");
86
66
  }
87
67
 
88
- return result.data;
68
+ return result.json();
89
69
  }
90
70
 
91
- async function getDifference(
71
+ private async getDifference(
92
72
  remoteItems: CustomType[] | SharedSlice[],
93
73
  local: ItemType,
94
74
  ): Promise<ItemOperation | undefined> {
@@ -106,16 +86,16 @@ export const createCustomTypesApiClient = (
106
86
  }
107
87
 
108
88
  /** Create items only if they have changed compared to their remote status */
109
- async function upsertIfChanged(
89
+ private async upsertIfChanged(
110
90
  itemType: ItemTypePath,
111
91
  localItems: ItemType[] = [],
112
- ) {
113
- const remoteItems = await getRemoteItems(itemType);
92
+ ): Promise<void> {
93
+ const remoteItems = await this.getRemoteItems(itemType);
114
94
  await Promise.all(
115
95
  localItems.map(async (localItem) => {
116
- const operation = await getDifference(remoteItems, localItem);
96
+ const operation = await this.getDifference(remoteItems, localItem);
117
97
 
118
- return operation && upsert(itemType, operation, localItem);
98
+ return operation && this.upsert(itemType, operation, localItem);
119
99
  }),
120
100
  );
121
101
  }
@@ -125,8 +105,8 @@ export const createCustomTypesApiClient = (
125
105
  *
126
106
  * @param customTypes -
127
107
  */
128
- async function createCustomTypes(customTypes: CustomType[] = []) {
129
- await upsertIfChanged("customtypes", customTypes);
108
+ async createCustomTypes(customTypes: CustomType[] = []): Promise<void> {
109
+ await this.upsertIfChanged("customtypes", customTypes);
130
110
  }
131
111
 
132
112
  /**
@@ -134,12 +114,7 @@ export const createCustomTypesApiClient = (
134
114
  *
135
115
  * @param slices -
136
116
  */
137
- async function createSlices(slices: SharedSlice[] = []) {
138
- await upsertIfChanged("slices", slices);
117
+ async createSlices(slices: SharedSlice[] = []): Promise<void> {
118
+ await this.upsertIfChanged("slices", slices);
139
119
  }
140
-
141
- return {
142
- createCustomTypes,
143
- createSlices,
144
- };
145
- };
120
+ }