@prismicio/e2e-tests-utils 1.0.0-alpha.1

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 (65) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +128 -0
  3. package/dist/clients/authenticationApi.cjs +36 -0
  4. package/dist/clients/authenticationApi.cjs.map +1 -0
  5. package/dist/clients/authenticationApi.d.ts +6 -0
  6. package/dist/clients/authenticationApi.js +36 -0
  7. package/dist/clients/authenticationApi.js.map +1 -0
  8. package/dist/clients/customTypesApi.cjs +71 -0
  9. package/dist/clients/customTypesApi.cjs.map +1 -0
  10. package/dist/clients/customTypesApi.d.ts +11 -0
  11. package/dist/clients/customTypesApi.js +71 -0
  12. package/dist/clients/customTypesApi.js.map +1 -0
  13. package/dist/clients/wroom.cjs +78 -0
  14. package/dist/clients/wroom.cjs.map +1 -0
  15. package/dist/clients/wroom.d.ts +25 -0
  16. package/dist/clients/wroom.js +78 -0
  17. package/dist/clients/wroom.js.map +1 -0
  18. package/dist/index.cjs +8 -0
  19. package/dist/index.cjs.map +1 -0
  20. package/dist/index.d.ts +3 -0
  21. package/dist/index.js +8 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/managers/repositories.cjs +130 -0
  24. package/dist/managers/repositories.cjs.map +1 -0
  25. package/dist/managers/repositories.d.ts +84 -0
  26. package/dist/managers/repositories.js +130 -0
  27. package/dist/managers/repositories.js.map +1 -0
  28. package/dist/managers/repository.cjs +187 -0
  29. package/dist/managers/repository.cjs.map +1 -0
  30. package/dist/managers/repository.d.ts +114 -0
  31. package/dist/managers/repository.js +187 -0
  32. package/dist/managers/repository.js.map +1 -0
  33. package/dist/types.d.ts +4 -0
  34. package/dist/utils/cookies.cjs +20 -0
  35. package/dist/utils/cookies.cjs.map +1 -0
  36. package/dist/utils/cookies.d.ts +8 -0
  37. package/dist/utils/cookies.js +20 -0
  38. package/dist/utils/cookies.js.map +1 -0
  39. package/dist/utils/envVariableManager.cjs +36 -0
  40. package/dist/utils/envVariableManager.cjs.map +1 -0
  41. package/dist/utils/envVariableManager.d.ts +16 -0
  42. package/dist/utils/envVariableManager.js +36 -0
  43. package/dist/utils/envVariableManager.js.map +1 -0
  44. package/dist/utils/log.cjs +25 -0
  45. package/dist/utils/log.cjs.map +1 -0
  46. package/dist/utils/log.d.ts +3 -0
  47. package/dist/utils/log.js +25 -0
  48. package/dist/utils/log.js.map +1 -0
  49. package/dist/utils/random.cjs +9 -0
  50. package/dist/utils/random.cjs.map +1 -0
  51. package/dist/utils/random.d.ts +8 -0
  52. package/dist/utils/random.js +9 -0
  53. package/dist/utils/random.js.map +1 -0
  54. package/package.json +88 -0
  55. package/src/clients/authenticationApi.ts +53 -0
  56. package/src/clients/customTypesApi.ts +145 -0
  57. package/src/clients/wroom.ts +91 -0
  58. package/src/index.ts +3 -0
  59. package/src/managers/repositories.ts +194 -0
  60. package/src/managers/repository.ts +277 -0
  61. package/src/types.ts +1 -0
  62. package/src/utils/cookies.ts +30 -0
  63. package/src/utils/envVariableManager.ts +35 -0
  64. package/src/utils/log.ts +26 -0
  65. package/src/utils/random.ts +14 -0
@@ -0,0 +1,36 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => {
4
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
+ return value;
6
+ };
7
+ class EnvVariableManager {
8
+ constructor(variableName) {
9
+ __publicField(this, "variableName");
10
+ this.variableName = variableName;
11
+ }
12
+ /** add a string and persist it in the environment variable */
13
+ add(value) {
14
+ const existingValues = this.getAll();
15
+ existingValues.push(value);
16
+ this.setAll(existingValues);
17
+ }
18
+ /** remove a string from the environment variable */
19
+ remove(value) {
20
+ const existingValues = this.getAll();
21
+ const updatedValues = existingValues.filter((item) => item !== value);
22
+ this.setAll(updatedValues);
23
+ }
24
+ /** return all items stored in the environment variable */
25
+ getAll() {
26
+ const value = process.env[this.variableName] || "[]";
27
+ return JSON.parse(value);
28
+ }
29
+ setAll(values) {
30
+ process.env[this.variableName] = JSON.stringify(values);
31
+ }
32
+ }
33
+ export {
34
+ EnvVariableManager
35
+ };
36
+ //# sourceMappingURL=envVariableManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envVariableManager.js","sources":["../../../src/utils/envVariableManager.ts"],"sourcesContent":["/**\n * Manage a list of strings within an environment variable. This is useful to\n * share data across different test phases (setup, teardown, test execution) as\n * most test frameworks run these in independent states\n */\nexport class EnvVariableManager {\n\tconstructor(private variableName: string) {}\n\n\t/** add a string and persist it in the environment variable */\n\tadd(value: string): void {\n\t\tconst existingValues = this.getAll();\n\t\texistingValues.push(value);\n\n\t\tthis.setAll(existingValues);\n\t}\n\n\t/** remove a string from the environment variable */\n\tremove(value: string): void {\n\t\tconst existingValues = this.getAll();\n\t\tconst updatedValues = existingValues.filter((item) => item !== value);\n\n\t\tthis.setAll(updatedValues);\n\t}\n\n\t/** return all items stored in the environment variable */\n\tgetAll(): string[] {\n\t\tconst value = process.env[this.variableName] || \"[]\";\n\n\t\treturn JSON.parse(value);\n\t}\n\n\tprivate setAll(values: string[]): void {\n\t\tprocess.env[this.variableName] = JSON.stringify(values);\n\t}\n}\n"],"names":[],"mappings":";;;;;;MAKa,mBAAkB;AAAA,EAC9B,YAAoB,cAAoB;AAApB;AAAA,SAAY,eAAZ;AAAA,EAAuB;AAAA;AAAA,EAG3C,IAAI,OAAa;AACV,UAAA,iBAAiB,KAAK;AAC5B,mBAAe,KAAK,KAAK;AAEzB,SAAK,OAAO,cAAc;AAAA,EAC3B;AAAA;AAAA,EAGA,OAAO,OAAa;AACb,UAAA,iBAAiB,KAAK;AAC5B,UAAM,gBAAgB,eAAe,OAAO,CAAC,SAAS,SAAS,KAAK;AAEpE,SAAK,OAAO,aAAa;AAAA,EAC1B;AAAA;AAAA,EAGA,SAAM;AACL,UAAM,QAAQ,QAAQ,IAAI,KAAK,YAAY,KAAK;AAEzC,WAAA,KAAK,MAAM,KAAK;AAAA,EACxB;AAAA,EAEQ,OAAO,QAAgB;AAC9B,YAAQ,IAAI,KAAK,YAAY,IAAI,KAAK,UAAU,MAAM;AAAA,EACvD;AACA;"}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const winston = require("winston");
4
+ const logHttpResponse = (response) => {
5
+ const { status, data } = response;
6
+ const { url = "" } = response.config;
7
+ logger.info(`Call to ${url} failed, received [${status}] ${data}`);
8
+ };
9
+ const { combine, printf } = winston.format;
10
+ const customFormat = printf(({ message, durationMs }) => {
11
+ const baseMsg = `[test data] ${message}`;
12
+ if (durationMs) {
13
+ return `${baseMsg} in ${durationMs}ms`;
14
+ }
15
+ return baseMsg;
16
+ });
17
+ const logger = winston.createLogger({
18
+ silent: process.env["prismic_e2e_tests_utils_silent"] === "true",
19
+ level: process.env["prismic_e2e_tests_utils_log_level"] || "info",
20
+ format: combine(customFormat),
21
+ transports: [new winston.transports.Console()]
22
+ });
23
+ exports.logHttpResponse = logHttpResponse;
24
+ exports.logger = logger;
25
+ //# sourceMappingURL=log.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.cjs","sources":["../../../src/utils/log.ts"],"sourcesContent":["import { AxiosResponse } from \"axios\";\nimport { createLogger, format, transports } from \"winston\";\n\nexport const logHttpResponse = (response: AxiosResponse): void => {\n\tconst { status, data } = response;\n\tconst { url = \"\" } = response.config;\n\tlogger.info(`Call to ${url} failed, received [${status}] ${data}`);\n};\n\nconst { combine, printf } = format;\n\nconst customFormat = printf(({ message, durationMs }) => {\n\tconst baseMsg = `[test data] ${message}`;\n\tif (durationMs) {\n\t\treturn `${baseMsg} in ${durationMs}ms`;\n\t}\n\n\treturn baseMsg;\n});\n\nexport const logger = createLogger({\n\tsilent: process.env[\"prismic_e2e_tests_utils_silent\"] === \"true\",\n\tlevel: process.env[\"prismic_e2e_tests_utils_log_level\"] || \"info\",\n\tformat: combine(customFormat),\n\ttransports: [new transports.Console()],\n});\n"],"names":["format","createLogger","transports"],"mappings":";;;AAGa,MAAA,kBAAkB,CAAC,aAAiC;AAC1D,QAAA,EAAE,QAAQ,KAAS,IAAA;AACzB,QAAM,EAAE,MAAM,OAAO,SAAS;AAC9B,SAAO,KAAK,WAAW,GAAG,sBAAsB,MAAM,KAAK,IAAI,EAAE;AAClE;AAEA,MAAM,EAAE,SAAS,OAAW,IAAAA;AAE5B,MAAM,eAAe,OAAO,CAAC,EAAE,SAAS,iBAAgB;AACjD,QAAA,UAAU,eAAe,OAAO;AACtC,MAAI,YAAY;AACR,WAAA,GAAG,OAAO,OAAO,UAAU;AAAA,EAClC;AAEM,SAAA;AACR,CAAC;AAEM,MAAM,SAASC,QAAAA,aAAa;AAAA,EAClC,QAAQ,QAAQ,IAAI,gCAAgC,MAAM;AAAA,EAC1D,OAAO,QAAQ,IAAI,mCAAmC,KAAK;AAAA,EAC3D,QAAQ,QAAQ,YAAY;AAAA,EAC5B,YAAY,CAAC,IAAIC,mBAAW,SAAS;AACrC,CAAA;;;"}
@@ -0,0 +1,3 @@
1
+ import { AxiosResponse } from "axios";
2
+ export declare const logHttpResponse: (response: AxiosResponse) => void;
3
+ export declare const logger: import("winston").Logger;
@@ -0,0 +1,25 @@
1
+ import { createLogger, transports, format } from "winston";
2
+ const logHttpResponse = (response) => {
3
+ const { status, data } = response;
4
+ const { url = "" } = response.config;
5
+ logger.info(`Call to ${url} failed, received [${status}] ${data}`);
6
+ };
7
+ const { combine, printf } = format;
8
+ const customFormat = printf(({ message, durationMs }) => {
9
+ const baseMsg = `[test data] ${message}`;
10
+ if (durationMs) {
11
+ return `${baseMsg} in ${durationMs}ms`;
12
+ }
13
+ return baseMsg;
14
+ });
15
+ const logger = createLogger({
16
+ silent: process.env["prismic_e2e_tests_utils_silent"] === "true",
17
+ level: process.env["prismic_e2e_tests_utils_log_level"] || "info",
18
+ format: combine(customFormat),
19
+ transports: [new transports.Console()]
20
+ });
21
+ export {
22
+ logHttpResponse,
23
+ logger
24
+ };
25
+ //# sourceMappingURL=log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.js","sources":["../../../src/utils/log.ts"],"sourcesContent":["import { AxiosResponse } from \"axios\";\nimport { createLogger, format, transports } from \"winston\";\n\nexport const logHttpResponse = (response: AxiosResponse): void => {\n\tconst { status, data } = response;\n\tconst { url = \"\" } = response.config;\n\tlogger.info(`Call to ${url} failed, received [${status}] ${data}`);\n};\n\nconst { combine, printf } = format;\n\nconst customFormat = printf(({ message, durationMs }) => {\n\tconst baseMsg = `[test data] ${message}`;\n\tif (durationMs) {\n\t\treturn `${baseMsg} in ${durationMs}ms`;\n\t}\n\n\treturn baseMsg;\n});\n\nexport const logger = createLogger({\n\tsilent: process.env[\"prismic_e2e_tests_utils_silent\"] === \"true\",\n\tlevel: process.env[\"prismic_e2e_tests_utils_log_level\"] || \"info\",\n\tformat: combine(customFormat),\n\ttransports: [new transports.Console()],\n});\n"],"names":[],"mappings":";AAGa,MAAA,kBAAkB,CAAC,aAAiC;AAC1D,QAAA,EAAE,QAAQ,KAAS,IAAA;AACzB,QAAM,EAAE,MAAM,OAAO,SAAS;AAC9B,SAAO,KAAK,WAAW,GAAG,sBAAsB,MAAM,KAAK,IAAI,EAAE;AAClE;AAEA,MAAM,EAAE,SAAS,OAAW,IAAA;AAE5B,MAAM,eAAe,OAAO,CAAC,EAAE,SAAS,iBAAgB;AACjD,QAAA,UAAU,eAAe,OAAO;AACtC,MAAI,YAAY;AACR,WAAA,GAAG,OAAO,OAAO,UAAU;AAAA,EAClC;AAEM,SAAA;AACR,CAAC;AAEM,MAAM,SAAS,aAAa;AAAA,EAClC,QAAQ,QAAQ,IAAI,gCAAgC,MAAM;AAAA,EAC1D,OAAO,QAAQ,IAAI,mCAAmC,KAAK;AAAA,EAC3D,QAAQ,QAAQ,YAAY;AAAA,EAC5B,YAAY,CAAC,IAAI,WAAW,SAAS;AACrC,CAAA;"}
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const crypto = require("crypto");
4
+ const randomString = (length = 16) => {
5
+ const uniqueInput = Math.random().toString();
6
+ return crypto.createHash("md5").update(uniqueInput).digest("hex").slice(0, length);
7
+ };
8
+ exports.randomString = randomString;
9
+ //# sourceMappingURL=random.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"random.cjs","sources":["../../../src/utils/random.ts"],"sourcesContent":["import { createHash } from \"crypto\";\n\n/**\n * Generate a random string\n *\n * @param length - max 32\n *\n * @returns\n */\nexport const randomString = (length = 16): string => {\n\tconst uniqueInput = Math.random().toString();\n\n\treturn createHash(\"md5\").update(uniqueInput).digest(\"hex\").slice(0, length);\n};\n"],"names":["createHash"],"mappings":";;;AASa,MAAA,eAAe,CAAC,SAAS,OAAc;AACnD,QAAM,cAAc,KAAK,OAAQ,EAAC,SAAQ;AAEnC,SAAAA,kBAAW,KAAK,EAAE,OAAO,WAAW,EAAE,OAAO,KAAK,EAAE,MAAM,GAAG,MAAM;AAC3E;;"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Generate a random string
3
+ *
4
+ * @param length - max 32
5
+ *
6
+ * @returns
7
+ */
8
+ export declare const randomString: (length?: number) => string;
@@ -0,0 +1,9 @@
1
+ import { createHash } from "crypto";
2
+ const randomString = (length = 16) => {
3
+ const uniqueInput = Math.random().toString();
4
+ return createHash("md5").update(uniqueInput).digest("hex").slice(0, length);
5
+ };
6
+ export {
7
+ randomString
8
+ };
9
+ //# sourceMappingURL=random.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"random.js","sources":["../../../src/utils/random.ts"],"sourcesContent":["import { createHash } from \"crypto\";\n\n/**\n * Generate a random string\n *\n * @param length - max 32\n *\n * @returns\n */\nexport const randomString = (length = 16): string => {\n\tconst uniqueInput = Math.random().toString();\n\n\treturn createHash(\"md5\").update(uniqueInput).digest(\"hex\").slice(0, length);\n};\n"],"names":[],"mappings":";AASa,MAAA,eAAe,CAAC,SAAS,OAAc;AACnD,QAAM,cAAc,KAAK,OAAQ,EAAC,SAAQ;AAEnC,SAAA,WAAW,KAAK,EAAE,OAAO,WAAW,EAAE,OAAO,KAAK,EAAE,MAAM,GAAG,MAAM;AAC3E;"}
package/package.json ADDED
@@ -0,0 +1,88 @@
1
+ {
2
+ "name": "@prismicio/e2e-tests-utils",
3
+ "version": "1.0.0-alpha.1",
4
+ "description": "A collection of utilities for to manage Prismic test data",
5
+ "keywords": [
6
+ "typescript",
7
+ "prismic"
8
+ ],
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+ssh://git@github.com/prismicio/prismic-e2e-tests-utils.git"
12
+ },
13
+ "license": "Apache-2.0",
14
+ "author": "Prismic <contact@prismic.io> (https://prismic.io)",
15
+ "type": "module",
16
+ "exports": {
17
+ ".": {
18
+ "require": {
19
+ "types": "./dist/index.d.ts",
20
+ "default": "./dist/index.cjs"
21
+ },
22
+ "import": {
23
+ "types": "./dist/index.d.ts",
24
+ "default": "./dist/index.js"
25
+ }
26
+ },
27
+ "./package.json": "./package.json"
28
+ },
29
+ "main": "./dist/index.cjs",
30
+ "module": "./dist/index.js",
31
+ "types": "./dist/index.d.ts",
32
+ "files": [
33
+ "./dist",
34
+ "./src"
35
+ ],
36
+ "scripts": {
37
+ "build": "vite build",
38
+ "dev": "vite build --watch",
39
+ "format": "prettier --write .",
40
+ "prepare": "npm run build",
41
+ "release": "npm run test && standard-version && git push --follow-tags && npm run build && npm publish",
42
+ "release:dry": "standard-version --dry-run",
43
+ "release:alpha": "npm run test && standard-version --release-as major --prerelease alpha && git push --follow-tags && npm run build && npm publish --tag alpha",
44
+ "release:alpha:dry": "standard-version --release-as major --prerelease alpha --dry-run",
45
+ "lint": "eslint --ext .js,.ts .",
46
+ "lint:fix": "eslint --fix --ext .js,.ts .",
47
+ "types": "vitest --typecheck --run && tsc --noEmit",
48
+ "types:watch": "vitest --typecheck",
49
+ "unit": "vitest run --coverage",
50
+ "unit:watch": "vitest watch",
51
+ "size": "size-limit",
52
+ "test": "npm run lint && npm run types && npm run unit && npm run build && npm run size"
53
+ },
54
+ "dependencies": {
55
+ "@prismicio/types-internal": "^2.3.1",
56
+ "axios": "^1.6.2",
57
+ "lodash.isequal": "^4.5.0",
58
+ "winston": "^3.11.0"
59
+ },
60
+ "devDependencies": {
61
+ "@size-limit/preset-small-lib": "^11.0.1",
62
+ "@trivago/prettier-plugin-sort-imports": "^4.2.0",
63
+ "@types/lodash.isequal": "^4.5.8",
64
+ "@types/node": "^20.9.2",
65
+ "@typescript-eslint/eslint-plugin": "^6.8.0",
66
+ "@typescript-eslint/parser": "^6.8.0",
67
+ "@vitest/coverage-v8": "^1.0.4",
68
+ "eslint": "^8.51.0",
69
+ "eslint-config-prettier": "^9.0.0",
70
+ "eslint-plugin-prettier": "^5.0.1",
71
+ "eslint-plugin-tsdoc": "^0.2.17",
72
+ "msw": "^2.0.11",
73
+ "prettier": "^3.0.3",
74
+ "prettier-plugin-jsdoc": "^1.1.1",
75
+ "size-limit": "^11.0.1",
76
+ "standard-version": "^9.5.0",
77
+ "typescript": "^5.2.2",
78
+ "vite": "^5.0.9",
79
+ "vite-plugin-sdk": "^0.1.1",
80
+ "vitest": "^1.0.4"
81
+ },
82
+ "engines": {
83
+ "node": ">=18.0.0"
84
+ },
85
+ "publishConfig": {
86
+ "access": "restricted"
87
+ }
88
+ }
@@ -0,0 +1,53 @@
1
+ import axios, { AxiosInstance } from "axios";
2
+
3
+ import { Credentials } from "../types";
4
+
5
+ import { logHttpResponse, logger } from "../utils/log";
6
+
7
+ export type AuthenticationClient = {
8
+ getToken: () => Promise<string>;
9
+ };
10
+
11
+ /** Client for interacting with an authentication service to generate API tokens. */
12
+ export const createAuthenticationApiClient = (
13
+ baseURL: string,
14
+ auth: Credentials,
15
+ ): AuthenticationClient => {
16
+ let authToken: string;
17
+
18
+ const client: AxiosInstance = axios.create({
19
+ baseURL,
20
+ validateStatus: () => true, // Don't throw on 4XX errors
21
+ });
22
+
23
+ async function login(): Promise<string> {
24
+ const profiler = logger.startTimer();
25
+
26
+ const result = await client.post("/login", {
27
+ email: auth.email,
28
+ password: auth.password,
29
+ });
30
+
31
+ if (!result.data || typeof result.data !== "string") {
32
+ logHttpResponse(result);
33
+ throw new Error("Authentication failed, no token received.");
34
+ }
35
+
36
+ profiler.done({ message: "generated user token from auth service" });
37
+
38
+ return result.data;
39
+ }
40
+
41
+ /** Return an api user token. Creates one if needed. */
42
+ async function getToken() {
43
+ if (!authToken) {
44
+ authToken = await login();
45
+ }
46
+
47
+ return authToken;
48
+ }
49
+
50
+ return {
51
+ getToken,
52
+ };
53
+ };
@@ -0,0 +1,145 @@
1
+ import axios, { AxiosInstance } from "axios";
2
+ import isEqual from "lodash.isequal";
3
+
4
+ import {
5
+ CustomType,
6
+ SharedSlice,
7
+ } from "@prismicio/types-internal/lib/customtypes";
8
+
9
+ import { logHttpResponse, logger } from "../utils/log";
10
+
11
+ import { AuthenticationClient } from "./authenticationApi";
12
+
13
+ export type CustomTypesClient = {
14
+ createCustomTypes(customTypes: CustomType[]): Promise<void>;
15
+ createSlices(slices: SharedSlice[]): Promise<void>;
16
+ };
17
+
18
+ /**
19
+ * Client for interacting with the Custom Types API to create/update custom
20
+ * types and slices.
21
+ */
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
+ });
49
+
50
+ /**
51
+ * Create or update a custom type or slice.
52
+ *
53
+ * @param endpoint - - The API endpoint for custom types or slices
54
+ * ('customtypes' or 'slices').
55
+ * @param data - - The data representing the custom type or slice.
56
+ *
57
+ * @throws Error if the item status cannot be retrieved or the item cannot be
58
+ * created/updated.
59
+ */
60
+ async function upsert(
61
+ endpoint: ItemTypePath,
62
+ operation: ItemOperation,
63
+ data: ItemType,
64
+ ) {
65
+ const profiler = logger.startTimer();
66
+ const path = `${endpoint}/${operation}`;
67
+
68
+ const result = await client.post(path, data, { headers: {} });
69
+ if (![201, 204].includes(result.status)) {
70
+ logHttpResponse(result);
71
+ throw new Error(`Could not ${operation} item`);
72
+ }
73
+ profiler.done({
74
+ message: `called customtypes api /${path} for item with id '${data.id}'`,
75
+ });
76
+ }
77
+
78
+ async function getRemoteItems(
79
+ endpoint: ItemTypePath,
80
+ ): Promise<CustomType[] | SharedSlice[]> {
81
+ const result = await client.get(endpoint);
82
+
83
+ if (![200].includes(result.status)) {
84
+ logHttpResponse(result);
85
+ throw new Error("Could not get items status from the Custom Type api.");
86
+ }
87
+
88
+ return result.data;
89
+ }
90
+
91
+ async function getDifference(
92
+ remoteItems: CustomType[] | SharedSlice[],
93
+ local: ItemType,
94
+ ): Promise<ItemOperation | undefined> {
95
+ const remoteItem = remoteItems.find(
96
+ (remote: CustomType | SharedSlice) => remote.id === local.id,
97
+ );
98
+ if (!remoteItem) {
99
+ return "insert";
100
+ }
101
+ if (!isEqual(local, remoteItem)) {
102
+ return "update";
103
+ }
104
+
105
+ return;
106
+ }
107
+
108
+ /** Create items only if they have changed compared to their remote status */
109
+ async function upsertIfChanged(
110
+ itemType: ItemTypePath,
111
+ localItems: ItemType[] = [],
112
+ ) {
113
+ const remoteItems = await getRemoteItems(itemType);
114
+ await Promise.all(
115
+ localItems.map(async (localItem) => {
116
+ const operation = await getDifference(remoteItems, localItem);
117
+
118
+ return operation && upsert(itemType, operation, localItem);
119
+ }),
120
+ );
121
+ }
122
+
123
+ /**
124
+ * Create Custom Types using the Custom types api.
125
+ *
126
+ * @param customTypes -
127
+ */
128
+ async function createCustomTypes(customTypes: CustomType[] = []) {
129
+ await upsertIfChanged("customtypes", customTypes);
130
+ }
131
+
132
+ /**
133
+ * Create slices using the Custom types api.
134
+ *
135
+ * @param slices -
136
+ */
137
+ async function createSlices(slices: SharedSlice[] = []) {
138
+ await upsertIfChanged("slices", slices);
139
+ }
140
+
141
+ return {
142
+ createCustomTypes,
143
+ createSlices,
144
+ };
145
+ };
@@ -0,0 +1,91 @@
1
+ import axios, { AxiosInstance, AxiosResponse } from "axios";
2
+
3
+ import { Credentials } from "../types";
4
+
5
+ import { extractCookie } from "../utils/cookies";
6
+ import { logHttpResponse, logger } from "../utils/log";
7
+
8
+ /**
9
+ * Client for interacting with the Wroom service to perform operations on
10
+ * repositories.
11
+ */
12
+ export class WroomClient {
13
+ private readonly client: AxiosInstance;
14
+ private loggedIn = false;
15
+
16
+ /**
17
+ * @param baseURL - The base URL of the Wroom app. ex: https://prismic.io
18
+ * @param auth - Authentication credentials.
19
+ */
20
+ constructor(
21
+ baseURL: string,
22
+ private readonly auth: Credentials,
23
+ ) {
24
+ this.client = axios.create({
25
+ baseURL,
26
+ withCredentials: true,
27
+ validateStatus: () => true,
28
+ xsrfCookieName: "X_XSRF",
29
+ headers: {
30
+ "User-Agent": "prismic-cli/prismic-e2e-tests-utils",
31
+ },
32
+ });
33
+
34
+ // cookies are not forwarded automatically in a non-browser env
35
+ this.client.interceptors.response.use((response) => {
36
+ const cookies = response.headers["set-cookie"];
37
+ if (cookies && extractCookie(cookies, "SESSION")) {
38
+ this.client.defaults.headers["Cookie"] = cookies;
39
+ }
40
+
41
+ return response;
42
+ });
43
+ }
44
+
45
+ getBaseURL(): string {
46
+ return this.client.getUri();
47
+ }
48
+
49
+ /** authenticated POST request on the wroom backend */
50
+ async post(
51
+ repository: string | null,
52
+ path: string,
53
+ data?: unknown,
54
+ ): Promise<AxiosResponse> {
55
+ if (!this.loggedIn) {
56
+ await this.login();
57
+ }
58
+
59
+ const url = new URL(path, this.client.getUri());
60
+ if (repository) {
61
+ url.hostname = `${repository}.${url.hostname}`;
62
+ }
63
+ const response = await this.client.post(url.toString(), data, {
64
+ params: {
65
+ _: extractCookie(this.client.defaults.headers["Cookie"], "X_XSRF"),
66
+ },
67
+ });
68
+
69
+ return response;
70
+ }
71
+
72
+ /**
73
+ * Authenticate Wroom to call Wroom unofficial endpoints.
74
+ *
75
+ * @throws Error if the login to Wroom fails.
76
+ */
77
+ private async login(): Promise<void> {
78
+ const profiler = logger.startTimer();
79
+ const response = await this.client.post<string>("/authentication/signin", {
80
+ email: this.auth.email,
81
+ password: this.auth.password,
82
+ });
83
+
84
+ if (response.status !== 200) {
85
+ logHttpResponse(response);
86
+ throw new Error("Could not login to Prismic, check your credentials");
87
+ }
88
+ this.loggedIn = true;
89
+ profiler.done({ message: "logged in to Prismic" });
90
+ }
91
+ }
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from "./managers/repositories";
2
+ export * from "./managers/repository";
3
+ export * from "./types";