@jam-comments/server-utilities 5.3.0 → 5.5.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/dist/cjs/index.js +1 -9
- package/dist/cjs/markupFetcher.js +47 -14
- package/dist/cjs/markupFetcher.test.js +67 -7
- package/dist/cjs/nodeUtils.js +74 -0
- package/dist/cjs/nodeUtils.test.js +48 -0
- package/dist/cjs/utils.js +0 -41
- package/dist/cjs/utils.test.js +0 -38
- package/dist/esm/index.js +0 -3
- package/dist/esm/markupFetcher.js +24 -14
- package/dist/esm/markupFetcher.test.js +67 -7
- package/dist/esm/nodeUtils.js +42 -0
- package/dist/esm/nodeUtils.test.js +46 -0
- package/dist/esm/utils.js +0 -35
- package/dist/esm/utils.test.js +1 -39
- package/dist/types/index.d.ts +0 -2
- package/dist/types/markupFetcher.d.ts +4 -3
- package/dist/types/nodeUtils.d.ts +8 -0
- package/dist/types/nodeUtils.test.d.ts +1 -0
- package/dist/types/utils.d.ts +0 -7
- package/package.json +3 -3
package/dist/cjs/index.js
CHANGED
|
@@ -1,17 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.logError = exports.log = exports.
|
|
7
|
-
const path_1 = __importDefault(require("path"));
|
|
8
|
-
exports.TEMP_DIRECTORY = path_1.default.join(process.cwd(), "_temp_jc");
|
|
3
|
+
exports.logError = exports.log = exports.fetchAll = exports.markupFetcher = void 0;
|
|
9
4
|
var markupFetcher_1 = require("./markupFetcher");
|
|
10
5
|
Object.defineProperty(exports, "markupFetcher", { enumerable: true, get: function () { return markupFetcher_1.markupFetcher; } });
|
|
11
6
|
Object.defineProperty(exports, "fetchAll", { enumerable: true, get: function () { return markupFetcher_1.fetchAll; } });
|
|
12
|
-
var utils_1 = require("./utils");
|
|
13
|
-
Object.defineProperty(exports, "deleteTempDirectory", { enumerable: true, get: function () { return utils_1.deleteTempDirectory; } });
|
|
14
|
-
Object.defineProperty(exports, "removeFalseyValues", { enumerable: true, get: function () { return utils_1.removeFalseyValues; } });
|
|
15
7
|
var log_1 = require("./log");
|
|
16
8
|
Object.defineProperty(exports, "log", { enumerable: true, get: function () { return log_1.log; } });
|
|
17
9
|
Object.defineProperty(exports, "logError", { enumerable: true, get: function () { return log_1.logError; } });
|
|
@@ -1,4 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
26
|
exports.fetchAll = fetchAll;
|
|
4
27
|
exports.batchMarkupFetcher = batchMarkupFetcher;
|
|
@@ -7,9 +30,11 @@ exports.makeMarkupRequest = makeMarkupRequest;
|
|
|
7
30
|
exports.markupFetcher = markupFetcher;
|
|
8
31
|
const injectSchema_1 = require("./injectSchema");
|
|
9
32
|
const utils_1 = require("./utils");
|
|
10
|
-
|
|
33
|
+
const BASE_URL = "https://go.jamcomments.com";
|
|
34
|
+
async function fetchAll({ tz = undefined, dateFormat = undefined, domain, apiKey, baseUrl = BASE_URL, environment = (0, utils_1.getEnvironment)(), copy = {}, }, platform, fetchImplementation = fetch, batchMarkupFetcherImpl = batchMarkupFetcher) {
|
|
35
|
+
const { createTempDirectory, deleteTempDirectory, saveFile } = await Promise.resolve().then(() => __importStar(require("./nodeUtils")));
|
|
11
36
|
const fetchBatchMarkup = batchMarkupFetcherImpl(platform, fetchImplementation);
|
|
12
|
-
|
|
37
|
+
await createTempDirectory();
|
|
13
38
|
let shouldKeepFetching = true;
|
|
14
39
|
let page = 1;
|
|
15
40
|
console.log("Fetching comments from JamComments! This might take a sec.");
|
|
@@ -22,11 +47,12 @@ async function fetchAll({ tz = undefined, domain, apiKey, baseUrl = "https://go.
|
|
|
22
47
|
environment,
|
|
23
48
|
page,
|
|
24
49
|
tz,
|
|
50
|
+
dateFormat,
|
|
25
51
|
copy,
|
|
26
52
|
});
|
|
27
53
|
console.log(`Checking for comment data. Batch: ${current_page}/${last_page}`);
|
|
28
54
|
const saveMarkupPromises = items.map((item) => {
|
|
29
|
-
return
|
|
55
|
+
return saveFile(item.path, item.markup);
|
|
30
56
|
});
|
|
31
57
|
await Promise.all(saveMarkupPromises);
|
|
32
58
|
if (current_page === last_page) {
|
|
@@ -38,21 +64,21 @@ async function fetchAll({ tz = undefined, domain, apiKey, baseUrl = "https://go.
|
|
|
38
64
|
}
|
|
39
65
|
}
|
|
40
66
|
catch (error) {
|
|
41
|
-
|
|
67
|
+
await deleteTempDirectory();
|
|
42
68
|
throw error;
|
|
43
69
|
}
|
|
44
70
|
}
|
|
45
71
|
function batchMarkupFetcher(platform, fetchImplementation = fetch) {
|
|
46
|
-
return async ({ tz
|
|
47
|
-
const response = await makeMarkupRequest({ tz, domain, apiKey, baseUrl, environment, page, copy }, "/api/v3/markup/all", fetchImplementation, platform);
|
|
72
|
+
return async ({ tz, copy, domain, apiKey, dateFormat, baseUrl = BASE_URL, environment = (0, utils_1.getEnvironment)(), page = 1, }) => {
|
|
73
|
+
const response = await makeMarkupRequest({ tz, domain, apiKey, baseUrl, environment, page, copy, dateFormat }, "/api/v3/markup/all", fetchImplementation, platform);
|
|
48
74
|
return response.json();
|
|
49
75
|
};
|
|
50
76
|
}
|
|
51
|
-
async function fetchFreshMarkup({ tz
|
|
52
|
-
const response = await makeMarkupRequest({ tz, path, domain, apiKey, baseUrl, environment, copy }, "/api/v3/markup", fetchImplementation, platform);
|
|
77
|
+
async function fetchFreshMarkup({ tz, path, copy, domain, apiKey, dateFormat, baseUrl = BASE_URL, environment = (0, utils_1.getEnvironment)(), }, fetchImplementation = fetch, platform) {
|
|
78
|
+
const response = await makeMarkupRequest({ tz, path, domain, apiKey, baseUrl, environment, copy, dateFormat }, "/api/v3/markup", fetchImplementation, platform);
|
|
53
79
|
return response.text();
|
|
54
80
|
}
|
|
55
|
-
async function makeMarkupRequest({ tz
|
|
81
|
+
async function makeMarkupRequest({ tz, path, page, domain, apiKey, dateFormat, copy = {}, baseUrl = BASE_URL, environment = (0, utils_1.getEnvironment)(), }, baseServicePath, fetchImplementation = fetch, platform) {
|
|
56
82
|
const trimmedTimezone = tz?.trim();
|
|
57
83
|
if (trimmedTimezone && !(0, utils_1.isValidTimezone)(trimmedTimezone)) {
|
|
58
84
|
throw new Error(`The timezone passed to JamComments is invalid: ${trimmedTimezone}`);
|
|
@@ -69,6 +95,9 @@ async function makeMarkupRequest({ tz = undefined, path = undefined, domain, api
|
|
|
69
95
|
if (trimmedTimezone) {
|
|
70
96
|
params.set("tz", trimmedTimezone);
|
|
71
97
|
}
|
|
98
|
+
if (dateFormat) {
|
|
99
|
+
params.set("date_format", dateFormat);
|
|
100
|
+
}
|
|
72
101
|
if (environment !== "production") {
|
|
73
102
|
params.set("stub", "true");
|
|
74
103
|
}
|
|
@@ -93,17 +122,21 @@ async function makeMarkupRequest({ tz = undefined, path = undefined, domain, api
|
|
|
93
122
|
return response;
|
|
94
123
|
}
|
|
95
124
|
function markupFetcher(platform, fetchImplementation = fetch) {
|
|
96
|
-
return async ({ tz = undefined, path, domain, apiKey, schema, baseUrl =
|
|
125
|
+
return async ({ tz = undefined, path, domain, apiKey, schema, dateFormat, baseUrl = BASE_URL, environment = (0, utils_1.getEnvironment)(), copy = {}, }) => {
|
|
97
126
|
path = path || "/";
|
|
98
|
-
const savedFile = (() => {
|
|
99
|
-
if (
|
|
127
|
+
const savedFile = await (async () => {
|
|
128
|
+
if (typeof process === "undefined") {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
const { tempDirectoryExists, readFile, getEmptyMarkup } = await Promise.resolve().then(() => __importStar(require("./nodeUtils")));
|
|
132
|
+
if (!(await tempDirectoryExists())) {
|
|
100
133
|
return null;
|
|
101
134
|
}
|
|
102
|
-
return (
|
|
135
|
+
return (await readFile(path)) || getEmptyMarkup();
|
|
103
136
|
})();
|
|
104
137
|
const markup = savedFile
|
|
105
138
|
? savedFile
|
|
106
|
-
: await fetchFreshMarkup({ tz, path, domain, apiKey, baseUrl, environment, copy }, fetchImplementation, platform);
|
|
139
|
+
: await fetchFreshMarkup({ tz, path, domain, apiKey, baseUrl, environment, copy, dateFormat }, fetchImplementation, platform);
|
|
107
140
|
if (schema) {
|
|
108
141
|
const preparedSchema = typeof schema !== "string" ? JSON.stringify(schema) : schema;
|
|
109
142
|
const parsedSchema = (0, utils_1.parseJson)(preparedSchema);
|
|
@@ -27,7 +27,7 @@ const vitest_1 = require("vitest");
|
|
|
27
27
|
const injectSchema = __importStar(require("./injectSchema"));
|
|
28
28
|
const fetcherExports = __importStar(require("./markupFetcher"));
|
|
29
29
|
const node_test_1 = require("node:test");
|
|
30
|
-
const utilsExports = __importStar(require("./
|
|
30
|
+
const utilsExports = __importStar(require("./nodeUtils"));
|
|
31
31
|
const { deleteTempDirectory } = utilsExports;
|
|
32
32
|
const { markupFetcher, batchMarkupFetcher } = fetcherExports;
|
|
33
33
|
(0, vitest_1.beforeEach)(() => {
|
|
@@ -67,6 +67,8 @@ const { markupFetcher, batchMarkupFetcher } = fetcherExports;
|
|
|
67
67
|
domain: "test.com",
|
|
68
68
|
apiKey: "123abc",
|
|
69
69
|
baseUrl: "https://go.jamcomments.com",
|
|
70
|
+
copy: {},
|
|
71
|
+
dateFormat: undefined,
|
|
70
72
|
environment: "production",
|
|
71
73
|
page: 1,
|
|
72
74
|
tz: undefined,
|
|
@@ -120,6 +122,8 @@ const { markupFetcher, batchMarkupFetcher } = fetcherExports;
|
|
|
120
122
|
domain: "test.com",
|
|
121
123
|
apiKey: "123abc",
|
|
122
124
|
baseUrl: "https://go.jamcomments.com",
|
|
125
|
+
copy: {},
|
|
126
|
+
dateFormat: undefined,
|
|
123
127
|
environment: "production",
|
|
124
128
|
page: 1,
|
|
125
129
|
tz: undefined,
|
|
@@ -129,6 +133,8 @@ const { markupFetcher, batchMarkupFetcher } = fetcherExports;
|
|
|
129
133
|
domain: "test.com",
|
|
130
134
|
apiKey: "123abc",
|
|
131
135
|
baseUrl: "https://go.jamcomments.com",
|
|
136
|
+
copy: {},
|
|
137
|
+
dateFormat: undefined,
|
|
132
138
|
environment: "production",
|
|
133
139
|
page: 2,
|
|
134
140
|
tz: undefined,
|
|
@@ -157,7 +163,7 @@ const { markupFetcher, batchMarkupFetcher } = fetcherExports;
|
|
|
157
163
|
}
|
|
158
164
|
(0, vitest_1.expect)(deleteTempDirectorySpy).toHaveBeenCalledOnce();
|
|
159
165
|
});
|
|
160
|
-
vitest_1.it
|
|
166
|
+
(0, vitest_1.it)("handles copy overrides", async () => {
|
|
161
167
|
const saveFileSpy = vitest_1.vi.spyOn(utilsExports, "saveFile");
|
|
162
168
|
const mockBatchFetcher = vitest_1.vi.fn().mockReturnValue({
|
|
163
169
|
data: [
|
|
@@ -201,6 +207,42 @@ const { markupFetcher, batchMarkupFetcher } = fetcherExports;
|
|
|
201
207
|
});
|
|
202
208
|
(0, vitest_1.expect)(saveFileSpy).toHaveBeenCalledTimes(2);
|
|
203
209
|
});
|
|
210
|
+
(0, vitest_1.it)("allows you to pass a custom date format", async () => {
|
|
211
|
+
const mockBatchFetcher = vitest_1.vi.fn().mockReturnValue({
|
|
212
|
+
data: [
|
|
213
|
+
{ path: "/test", markup: "markup1" },
|
|
214
|
+
{ path: "/test2", markup: "markup2" },
|
|
215
|
+
],
|
|
216
|
+
meta: {
|
|
217
|
+
current_page: 1,
|
|
218
|
+
from: 1,
|
|
219
|
+
last_page: 1,
|
|
220
|
+
path: "/test",
|
|
221
|
+
per_page: 10,
|
|
222
|
+
to: 2,
|
|
223
|
+
total: 2,
|
|
224
|
+
},
|
|
225
|
+
});
|
|
226
|
+
const batchMarkupFetcherMock = vitest_1.vi.fn().mockImplementation((a, b) => {
|
|
227
|
+
return mockBatchFetcher;
|
|
228
|
+
});
|
|
229
|
+
await fetcherExports.fetchAll({
|
|
230
|
+
domain: "test.com",
|
|
231
|
+
apiKey: "123abc",
|
|
232
|
+
environment: "production",
|
|
233
|
+
dateFormat: "yyyy-MM-dd",
|
|
234
|
+
}, "test_platform", vitest_1.vi.fn(), batchMarkupFetcherMock);
|
|
235
|
+
(0, vitest_1.expect)(mockBatchFetcher).toHaveBeenCalledWith({
|
|
236
|
+
domain: "test.com",
|
|
237
|
+
apiKey: "123abc",
|
|
238
|
+
baseUrl: "https://go.jamcomments.com",
|
|
239
|
+
copy: {},
|
|
240
|
+
dateFormat: "yyyy-MM-dd",
|
|
241
|
+
environment: "production",
|
|
242
|
+
page: 1,
|
|
243
|
+
tz: undefined,
|
|
244
|
+
});
|
|
245
|
+
});
|
|
204
246
|
});
|
|
205
247
|
(0, vitest_1.describe)("batchMarkupFetcher", () => {
|
|
206
248
|
(0, vitest_1.it)("constructs fetch request correctly", async () => {
|
|
@@ -419,6 +461,24 @@ const { markupFetcher, batchMarkupFetcher } = fetcherExports;
|
|
|
419
461
|
(0, vitest_1.expect)(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v3/markup?domain=test.com&path=%2F©_confirmation_message=custom+confirmation+message©_submit_button=custom+submit+button", vitest_1.expect.anything());
|
|
420
462
|
(0, vitest_1.expect)(result).toEqual("results!");
|
|
421
463
|
});
|
|
464
|
+
(0, vitest_1.it)("passes date format string", async () => {
|
|
465
|
+
const fetchMock = vitest_1.vi.fn().mockImplementation(() => {
|
|
466
|
+
return {
|
|
467
|
+
status: 200,
|
|
468
|
+
ok: true,
|
|
469
|
+
text: () => "results!",
|
|
470
|
+
};
|
|
471
|
+
});
|
|
472
|
+
const fetcher = markupFetcher("test", fetchMock);
|
|
473
|
+
await fetcher({
|
|
474
|
+
path: null,
|
|
475
|
+
domain: "test.com",
|
|
476
|
+
apiKey: "123abc",
|
|
477
|
+
environment: "production",
|
|
478
|
+
dateFormat: "yyyy-MM-dd",
|
|
479
|
+
});
|
|
480
|
+
(0, vitest_1.expect)(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v3/markup?domain=test.com&path=%2F&date_format=yyyy-MM-dd", vitest_1.expect.anything());
|
|
481
|
+
});
|
|
422
482
|
(0, vitest_1.it)("response isn't ok", async () => {
|
|
423
483
|
const fetchMock = vitest_1.vi.fn().mockImplementation(() => {
|
|
424
484
|
return {
|
|
@@ -438,7 +498,7 @@ const { markupFetcher, batchMarkupFetcher } = fetcherExports;
|
|
|
438
498
|
(0, vitest_1.it)("makes fresh request when temp directory does not exist", async () => {
|
|
439
499
|
const tempDirectoryExistsSpy = vitest_1.vi
|
|
440
500
|
.spyOn(utilsExports, "tempDirectoryExists")
|
|
441
|
-
.mockReturnValue(false);
|
|
501
|
+
.mockReturnValue(Promise.resolve(false));
|
|
442
502
|
const readFileSpy = vitest_1.vi.spyOn(utilsExports, "readFile");
|
|
443
503
|
const fetchMock = vitest_1.vi.fn().mockImplementation(() => {
|
|
444
504
|
return {
|
|
@@ -462,10 +522,10 @@ const { markupFetcher, batchMarkupFetcher } = fetcherExports;
|
|
|
462
522
|
(0, vitest_1.it)("uses saved markup when it exists", async () => {
|
|
463
523
|
const tempDirectoryExistsSpy = vitest_1.vi
|
|
464
524
|
.spyOn(utilsExports, "tempDirectoryExists")
|
|
465
|
-
.mockReturnValue(true);
|
|
525
|
+
.mockReturnValue(Promise.resolve(true));
|
|
466
526
|
const readFileSpy = vitest_1.vi
|
|
467
527
|
.spyOn(utilsExports, "readFile")
|
|
468
|
-
.mockReturnValue("saved markup");
|
|
528
|
+
.mockReturnValue(Promise.resolve("saved markup"));
|
|
469
529
|
const fetchMock = vitest_1.vi.fn();
|
|
470
530
|
const fetcher = markupFetcher("test", fetchMock);
|
|
471
531
|
const result = await fetcher({
|
|
@@ -482,13 +542,13 @@ const { markupFetcher, batchMarkupFetcher } = fetcherExports;
|
|
|
482
542
|
(0, vitest_1.it)("uses the EMPTY template when there's no saved file for a post", async () => {
|
|
483
543
|
const tempDirectoryExistsSpy = vitest_1.vi
|
|
484
544
|
.spyOn(utilsExports, "tempDirectoryExists")
|
|
485
|
-
.mockReturnValue(true);
|
|
545
|
+
.mockReturnValue(Promise.resolve(true));
|
|
486
546
|
const readFileSpy = vitest_1.vi
|
|
487
547
|
.spyOn(utilsExports, "readFile")
|
|
488
548
|
.mockReturnValue(null);
|
|
489
549
|
const getEmptyMarkupSpy = vitest_1.vi
|
|
490
550
|
.spyOn(utilsExports, "getEmptyMarkup")
|
|
491
|
-
.mockReturnValue("<!-- EMPTY -->");
|
|
551
|
+
.mockReturnValue(Promise.resolve("<!-- EMPTY -->"));
|
|
492
552
|
const fetchMock = vitest_1.vi.fn();
|
|
493
553
|
const fetcher = markupFetcher("test", fetchMock);
|
|
494
554
|
const result = await fetcher({
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.getTempDirectory = getTempDirectory;
|
|
27
|
+
exports.deleteTempDirectory = deleteTempDirectory;
|
|
28
|
+
exports.createTempDirectory = createTempDirectory;
|
|
29
|
+
exports.readFile = readFile;
|
|
30
|
+
exports.getEmptyMarkup = getEmptyMarkup;
|
|
31
|
+
exports.tempDirectoryExists = tempDirectoryExists;
|
|
32
|
+
exports.saveFile = saveFile;
|
|
33
|
+
const fs_1 = require("fs");
|
|
34
|
+
const utils_1 = require("./utils");
|
|
35
|
+
async function getTempDirectory() {
|
|
36
|
+
const path = await Promise.resolve().then(() => __importStar(require("path")));
|
|
37
|
+
return path.join(process.cwd(), "_temp_jc");
|
|
38
|
+
}
|
|
39
|
+
async function deleteTempDirectory() {
|
|
40
|
+
const tempDirectory = await getTempDirectory();
|
|
41
|
+
if ((0, fs_1.existsSync)(tempDirectory)) {
|
|
42
|
+
(0, fs_1.rmdirSync)(tempDirectory, { recursive: true });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async function createTempDirectory(mkdirSyncImpl = fs_1.mkdirSync, existsSyncImpl = fs_1.existsSync) {
|
|
46
|
+
const tempDirectory = await getTempDirectory();
|
|
47
|
+
if (!(await tempDirectoryExists(existsSyncImpl))) {
|
|
48
|
+
mkdirSyncImpl(tempDirectory);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async function readFile(name, readFileSyncImpl = fs_1.readFileSync) {
|
|
52
|
+
const fileName = (0, utils_1.toSavedFileName)(name);
|
|
53
|
+
try {
|
|
54
|
+
return readFileSyncImpl(`${await getTempDirectory()}/${fileName}`, "utf8");
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function getEmptyMarkup() {
|
|
61
|
+
return readFile("EMPTY");
|
|
62
|
+
}
|
|
63
|
+
async function tempDirectoryExists(existsSyncImpl = fs_1.existsSync) {
|
|
64
|
+
return existsSyncImpl(await getTempDirectory());
|
|
65
|
+
}
|
|
66
|
+
async function saveFile(name, data, writeFileImpl = fs_1.writeFile) {
|
|
67
|
+
const fileName = (0, utils_1.toSavedFileName)(name);
|
|
68
|
+
const tempDirectory = await getTempDirectory();
|
|
69
|
+
return new Promise(async (resolve) => {
|
|
70
|
+
writeFileImpl(`${tempDirectory}/${fileName}`, data, () => {
|
|
71
|
+
resolve();
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const nodeUtils_1 = require("./nodeUtils");
|
|
5
|
+
(0, vitest_1.describe)("createTempDirectory()", () => {
|
|
6
|
+
(0, vitest_1.it)("creates temp directory fresh", async () => {
|
|
7
|
+
const tempDirectory = await (0, nodeUtils_1.getTempDirectory)();
|
|
8
|
+
const mkdirSyncMock = vitest_1.vi.fn();
|
|
9
|
+
const existsSyncMock = vitest_1.vi.fn().mockReturnValue(false);
|
|
10
|
+
await new Promise((resolve) => {
|
|
11
|
+
(0, vitest_1.expect)(async () => {
|
|
12
|
+
await (0, nodeUtils_1.createTempDirectory)(mkdirSyncMock, existsSyncMock);
|
|
13
|
+
resolve();
|
|
14
|
+
}).not.toThrow();
|
|
15
|
+
});
|
|
16
|
+
(0, vitest_1.expect)(mkdirSyncMock).toHaveBeenCalledWith(tempDirectory);
|
|
17
|
+
});
|
|
18
|
+
(0, vitest_1.it)("does not throw error when it already exists", () => {
|
|
19
|
+
const mkdirSyncMock = vitest_1.vi.fn().mockImplementation(() => {
|
|
20
|
+
throw new Error("Directory already exists");
|
|
21
|
+
});
|
|
22
|
+
const existsSyncMock = vitest_1.vi.fn().mockReturnValue(true);
|
|
23
|
+
(0, vitest_1.expect)(() => (0, nodeUtils_1.createTempDirectory)(mkdirSyncMock, existsSyncMock)).not.toThrow();
|
|
24
|
+
(0, vitest_1.expect)(mkdirSyncMock).not.toHaveBeenCalledWith();
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
(0, vitest_1.describe)("readFile()", () => {
|
|
28
|
+
(0, vitest_1.it)("reads the file", async () => {
|
|
29
|
+
const readFileSyncMock = vitest_1.vi.fn().mockReturnValue("file contents");
|
|
30
|
+
const tempDirectory = await (0, nodeUtils_1.getTempDirectory)();
|
|
31
|
+
(0, vitest_1.expect)(await (0, nodeUtils_1.readFile)("hey/there", readFileSyncMock)).toEqual("file contents");
|
|
32
|
+
(0, vitest_1.expect)(readFileSyncMock).toHaveBeenCalledWith(`${tempDirectory}/hey::there`, "utf8");
|
|
33
|
+
});
|
|
34
|
+
(0, vitest_1.it)("returns null when file doesn't exist", async () => {
|
|
35
|
+
const readFileSyncMock = vitest_1.vi.fn().mockImplementation(() => {
|
|
36
|
+
throw new Error("File not found");
|
|
37
|
+
});
|
|
38
|
+
(0, vitest_1.expect)(await (0, nodeUtils_1.readFile)("hey/there", readFileSyncMock)).toEqual(null);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
(0, vitest_1.describe)("saveFile()", () => {
|
|
42
|
+
(0, vitest_1.it)("saves the file", async () => {
|
|
43
|
+
const writeFileMock = vitest_1.vi.fn().mockImplementation((file, data, cb) => cb());
|
|
44
|
+
const tempDirectory = await (0, nodeUtils_1.getTempDirectory)();
|
|
45
|
+
await (0, nodeUtils_1.saveFile)("hey/there", "file contents", writeFileMock);
|
|
46
|
+
(0, vitest_1.expect)(writeFileMock).toHaveBeenCalledWith(`${tempDirectory}/hey::there`, "file contents", vitest_1.expect.any(Function));
|
|
47
|
+
});
|
|
48
|
+
});
|
package/dist/cjs/utils.js
CHANGED
|
@@ -4,16 +4,8 @@ exports.isValidTimezone = isValidTimezone;
|
|
|
4
4
|
exports.getEnvironment = getEnvironment;
|
|
5
5
|
exports.parseJson = parseJson;
|
|
6
6
|
exports.unescapeHTML = unescapeHTML;
|
|
7
|
-
exports.deleteTempDirectory = deleteTempDirectory;
|
|
8
|
-
exports.createTempDirectory = createTempDirectory;
|
|
9
7
|
exports.toSavedFileName = toSavedFileName;
|
|
10
|
-
exports.readFile = readFile;
|
|
11
|
-
exports.getEmptyMarkup = getEmptyMarkup;
|
|
12
|
-
exports.tempDirectoryExists = tempDirectoryExists;
|
|
13
|
-
exports.saveFile = saveFile;
|
|
14
8
|
exports.removeFalseyValues = removeFalseyValues;
|
|
15
|
-
const fs_1 = require("fs");
|
|
16
|
-
const _1 = require(".");
|
|
17
9
|
function isValidTimezone(tz) {
|
|
18
10
|
try {
|
|
19
11
|
Intl.DateTimeFormat(undefined, { timeZone: tz });
|
|
@@ -70,42 +62,9 @@ function unescapeHTML(str) {
|
|
|
70
62
|
}
|
|
71
63
|
});
|
|
72
64
|
}
|
|
73
|
-
function deleteTempDirectory() {
|
|
74
|
-
if ((0, fs_1.existsSync)(_1.TEMP_DIRECTORY)) {
|
|
75
|
-
(0, fs_1.rmdirSync)(_1.TEMP_DIRECTORY, { recursive: true });
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
function createTempDirectory(mkdirSyncImpl = fs_1.mkdirSync, existsSyncImpl = fs_1.existsSync) {
|
|
79
|
-
if (!tempDirectoryExists(existsSyncImpl)) {
|
|
80
|
-
mkdirSyncImpl(_1.TEMP_DIRECTORY);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
65
|
function toSavedFileName(name) {
|
|
84
66
|
return name.replace(/^\//, "").replace(/\//g, "::");
|
|
85
67
|
}
|
|
86
|
-
function readFile(name, readFileSyncImpl = fs_1.readFileSync) {
|
|
87
|
-
const fileName = toSavedFileName(name);
|
|
88
|
-
try {
|
|
89
|
-
return readFileSyncImpl(`${_1.TEMP_DIRECTORY}/${fileName}`, "utf8");
|
|
90
|
-
}
|
|
91
|
-
catch (error) {
|
|
92
|
-
return null;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
function getEmptyMarkup() {
|
|
96
|
-
return readFile("EMPTY");
|
|
97
|
-
}
|
|
98
|
-
function tempDirectoryExists(existsSyncImpl = fs_1.existsSync) {
|
|
99
|
-
return existsSyncImpl(_1.TEMP_DIRECTORY);
|
|
100
|
-
}
|
|
101
|
-
function saveFile(name, data, writeFileImpl = fs_1.writeFile) {
|
|
102
|
-
const fileName = toSavedFileName(name);
|
|
103
|
-
return new Promise((resolve) => {
|
|
104
|
-
writeFileImpl(`${_1.TEMP_DIRECTORY}/${fileName}`, data, () => {
|
|
105
|
-
resolve();
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
68
|
function removeFalseyValues(obj) {
|
|
110
69
|
const filteredItems = Object.entries(obj).filter(([, value]) => value);
|
|
111
70
|
return Object.fromEntries(filteredItems);
|
package/dist/cjs/utils.test.js
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const vitest_1 = require("vitest");
|
|
4
4
|
const utils_1 = require("./utils");
|
|
5
|
-
const _1 = require(".");
|
|
6
5
|
const env = process.env;
|
|
7
6
|
(0, vitest_1.beforeEach)(() => {
|
|
8
7
|
vitest_1.vi.resetModules();
|
|
@@ -45,48 +44,11 @@ const env = process.env;
|
|
|
45
44
|
});
|
|
46
45
|
});
|
|
47
46
|
});
|
|
48
|
-
(0, vitest_1.describe)("createTempDirectory()", () => {
|
|
49
|
-
(0, vitest_1.it)("creates temp directory fresh", () => {
|
|
50
|
-
const mkdirSyncMock = vitest_1.vi.fn();
|
|
51
|
-
const existsSyncMock = vitest_1.vi.fn().mockReturnValue(false);
|
|
52
|
-
(0, vitest_1.expect)(() => (0, utils_1.createTempDirectory)(mkdirSyncMock, existsSyncMock)).not.toThrow();
|
|
53
|
-
(0, vitest_1.expect)(mkdirSyncMock).toHaveBeenCalledWith(_1.TEMP_DIRECTORY);
|
|
54
|
-
});
|
|
55
|
-
(0, vitest_1.it)("does not throw error when it already exists", () => {
|
|
56
|
-
const mkdirSyncMock = vitest_1.vi.fn().mockImplementation(() => {
|
|
57
|
-
throw new Error("Directory already exists");
|
|
58
|
-
});
|
|
59
|
-
const existsSyncMock = vitest_1.vi.fn().mockReturnValue(true);
|
|
60
|
-
(0, vitest_1.expect)(() => (0, utils_1.createTempDirectory)(mkdirSyncMock, existsSyncMock)).not.toThrow();
|
|
61
|
-
(0, vitest_1.expect)(mkdirSyncMock).not.toHaveBeenCalledWith();
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
47
|
(0, vitest_1.describe)("toSavedFileName()", () => {
|
|
65
48
|
(0, vitest_1.it)("replaces slashes with double colons", () => {
|
|
66
49
|
(0, vitest_1.expect)((0, utils_1.toSavedFileName)("/hey/there")).toEqual("hey::there");
|
|
67
50
|
});
|
|
68
51
|
});
|
|
69
|
-
(0, vitest_1.describe)("readFile()", () => {
|
|
70
|
-
(0, vitest_1.it)("reads the file", () => {
|
|
71
|
-
const readFileSyncMock = vitest_1.vi.fn().mockReturnValue("file contents");
|
|
72
|
-
(0, vitest_1.expect)((0, utils_1.readFile)("hey/there", readFileSyncMock)).toEqual("file contents");
|
|
73
|
-
(0, vitest_1.expect)(readFileSyncMock).toHaveBeenCalledWith(`${_1.TEMP_DIRECTORY}/hey::there`, "utf8");
|
|
74
|
-
});
|
|
75
|
-
(0, vitest_1.it)("returns null when file doesn't exist", () => {
|
|
76
|
-
const readFileSyncMock = vitest_1.vi.fn().mockImplementation(() => {
|
|
77
|
-
throw new Error("File not found");
|
|
78
|
-
});
|
|
79
|
-
(0, vitest_1.expect)((0, utils_1.readFile)("hey/there", readFileSyncMock)).toEqual(null);
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
(0, vitest_1.describe)("saveFile()", () => {
|
|
83
|
-
(0, vitest_1.it)("saves the file", async () => {
|
|
84
|
-
const writeFileMock = vitest_1.vi.fn();
|
|
85
|
-
const result = (0, utils_1.saveFile)("hey/there", "file contents", writeFileMock);
|
|
86
|
-
(0, vitest_1.expect)(writeFileMock).toHaveBeenCalledWith(`${_1.TEMP_DIRECTORY}/hey::there`, "file contents", vitest_1.expect.any(Function));
|
|
87
|
-
(0, vitest_1.expect)(result).toBeInstanceOf(Promise);
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
52
|
(0, vitest_1.describe)("removeFalseyValues()", () => {
|
|
91
53
|
(0, vitest_1.it)("should remove falsey values", () => {
|
|
92
54
|
(0, vitest_1.expect)((0, utils_1.removeFalseyValues)({ a: 1, b: 0, d: null, e: "" })).toEqual({
|
package/dist/esm/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { injectSchema } from "./injectSchema";
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { getEnvironment, isValidTimezone, parseJson } from "./utils";
|
|
3
|
+
const BASE_URL = "https://go.jamcomments.com";
|
|
4
|
+
export async function fetchAll({ tz = undefined, dateFormat = undefined, domain, apiKey, baseUrl = BASE_URL, environment = getEnvironment(), copy = {}, }, platform, fetchImplementation = fetch, batchMarkupFetcherImpl = batchMarkupFetcher) {
|
|
5
|
+
const { createTempDirectory, deleteTempDirectory, saveFile } = await import("./nodeUtils");
|
|
4
6
|
const fetchBatchMarkup = batchMarkupFetcherImpl(platform, fetchImplementation);
|
|
5
|
-
createTempDirectory();
|
|
7
|
+
await createTempDirectory();
|
|
6
8
|
let shouldKeepFetching = true;
|
|
7
9
|
let page = 1;
|
|
8
10
|
console.log("Fetching comments from JamComments! This might take a sec.");
|
|
@@ -15,6 +17,7 @@ export async function fetchAll({ tz = undefined, domain, apiKey, baseUrl = "http
|
|
|
15
17
|
environment,
|
|
16
18
|
page,
|
|
17
19
|
tz,
|
|
20
|
+
dateFormat,
|
|
18
21
|
copy,
|
|
19
22
|
});
|
|
20
23
|
console.log(`Checking for comment data. Batch: ${current_page}/${last_page}`);
|
|
@@ -31,21 +34,21 @@ export async function fetchAll({ tz = undefined, domain, apiKey, baseUrl = "http
|
|
|
31
34
|
}
|
|
32
35
|
}
|
|
33
36
|
catch (error) {
|
|
34
|
-
deleteTempDirectory();
|
|
37
|
+
await deleteTempDirectory();
|
|
35
38
|
throw error;
|
|
36
39
|
}
|
|
37
40
|
}
|
|
38
41
|
export function batchMarkupFetcher(platform, fetchImplementation = fetch) {
|
|
39
|
-
return async ({ tz
|
|
40
|
-
const response = await makeMarkupRequest({ tz, domain, apiKey, baseUrl, environment, page, copy }, "/api/v3/markup/all", fetchImplementation, platform);
|
|
42
|
+
return async ({ tz, copy, domain, apiKey, dateFormat, baseUrl = BASE_URL, environment = getEnvironment(), page = 1, }) => {
|
|
43
|
+
const response = await makeMarkupRequest({ tz, domain, apiKey, baseUrl, environment, page, copy, dateFormat }, "/api/v3/markup/all", fetchImplementation, platform);
|
|
41
44
|
return response.json();
|
|
42
45
|
};
|
|
43
46
|
}
|
|
44
|
-
export async function fetchFreshMarkup({ tz
|
|
45
|
-
const response = await makeMarkupRequest({ tz, path, domain, apiKey, baseUrl, environment, copy }, "/api/v3/markup", fetchImplementation, platform);
|
|
47
|
+
export async function fetchFreshMarkup({ tz, path, copy, domain, apiKey, dateFormat, baseUrl = BASE_URL, environment = getEnvironment(), }, fetchImplementation = fetch, platform) {
|
|
48
|
+
const response = await makeMarkupRequest({ tz, path, domain, apiKey, baseUrl, environment, copy, dateFormat }, "/api/v3/markup", fetchImplementation, platform);
|
|
46
49
|
return response.text();
|
|
47
50
|
}
|
|
48
|
-
export async function makeMarkupRequest({ tz
|
|
51
|
+
export async function makeMarkupRequest({ tz, path, page, domain, apiKey, dateFormat, copy = {}, baseUrl = BASE_URL, environment = getEnvironment(), }, baseServicePath, fetchImplementation = fetch, platform) {
|
|
49
52
|
const trimmedTimezone = tz?.trim();
|
|
50
53
|
if (trimmedTimezone && !isValidTimezone(trimmedTimezone)) {
|
|
51
54
|
throw new Error(`The timezone passed to JamComments is invalid: ${trimmedTimezone}`);
|
|
@@ -62,6 +65,9 @@ export async function makeMarkupRequest({ tz = undefined, path = undefined, doma
|
|
|
62
65
|
if (trimmedTimezone) {
|
|
63
66
|
params.set("tz", trimmedTimezone);
|
|
64
67
|
}
|
|
68
|
+
if (dateFormat) {
|
|
69
|
+
params.set("date_format", dateFormat);
|
|
70
|
+
}
|
|
65
71
|
if (environment !== "production") {
|
|
66
72
|
params.set("stub", "true");
|
|
67
73
|
}
|
|
@@ -86,17 +92,21 @@ export async function makeMarkupRequest({ tz = undefined, path = undefined, doma
|
|
|
86
92
|
return response;
|
|
87
93
|
}
|
|
88
94
|
export function markupFetcher(platform, fetchImplementation = fetch) {
|
|
89
|
-
return async ({ tz = undefined, path, domain, apiKey, schema, baseUrl =
|
|
95
|
+
return async ({ tz = undefined, path, domain, apiKey, schema, dateFormat, baseUrl = BASE_URL, environment = getEnvironment(), copy = {}, }) => {
|
|
90
96
|
path = path || "/";
|
|
91
|
-
const savedFile = (() => {
|
|
92
|
-
if (
|
|
97
|
+
const savedFile = await (async () => {
|
|
98
|
+
if (typeof process === "undefined") {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
const { tempDirectoryExists, readFile, getEmptyMarkup } = await import("./nodeUtils");
|
|
102
|
+
if (!(await tempDirectoryExists())) {
|
|
93
103
|
return null;
|
|
94
104
|
}
|
|
95
|
-
return readFile(path) || getEmptyMarkup();
|
|
105
|
+
return (await readFile(path)) || getEmptyMarkup();
|
|
96
106
|
})();
|
|
97
107
|
const markup = savedFile
|
|
98
108
|
? savedFile
|
|
99
|
-
: await fetchFreshMarkup({ tz, path, domain, apiKey, baseUrl, environment, copy }, fetchImplementation, platform);
|
|
109
|
+
: await fetchFreshMarkup({ tz, path, domain, apiKey, baseUrl, environment, copy, dateFormat }, fetchImplementation, platform);
|
|
100
110
|
if (schema) {
|
|
101
111
|
const preparedSchema = typeof schema !== "string" ? JSON.stringify(schema) : schema;
|
|
102
112
|
const parsedSchema = parseJson(preparedSchema);
|
|
@@ -2,7 +2,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
2
2
|
import * as injectSchema from "./injectSchema";
|
|
3
3
|
import * as fetcherExports from "./markupFetcher";
|
|
4
4
|
import { afterEach } from "node:test";
|
|
5
|
-
import * as utilsExports from "./
|
|
5
|
+
import * as utilsExports from "./nodeUtils";
|
|
6
6
|
const { deleteTempDirectory } = utilsExports;
|
|
7
7
|
const { markupFetcher, batchMarkupFetcher } = fetcherExports;
|
|
8
8
|
beforeEach(() => {
|
|
@@ -42,6 +42,8 @@ describe("fetchAll()", () => {
|
|
|
42
42
|
domain: "test.com",
|
|
43
43
|
apiKey: "123abc",
|
|
44
44
|
baseUrl: "https://go.jamcomments.com",
|
|
45
|
+
copy: {},
|
|
46
|
+
dateFormat: undefined,
|
|
45
47
|
environment: "production",
|
|
46
48
|
page: 1,
|
|
47
49
|
tz: undefined,
|
|
@@ -95,6 +97,8 @@ describe("fetchAll()", () => {
|
|
|
95
97
|
domain: "test.com",
|
|
96
98
|
apiKey: "123abc",
|
|
97
99
|
baseUrl: "https://go.jamcomments.com",
|
|
100
|
+
copy: {},
|
|
101
|
+
dateFormat: undefined,
|
|
98
102
|
environment: "production",
|
|
99
103
|
page: 1,
|
|
100
104
|
tz: undefined,
|
|
@@ -104,6 +108,8 @@ describe("fetchAll()", () => {
|
|
|
104
108
|
domain: "test.com",
|
|
105
109
|
apiKey: "123abc",
|
|
106
110
|
baseUrl: "https://go.jamcomments.com",
|
|
111
|
+
copy: {},
|
|
112
|
+
dateFormat: undefined,
|
|
107
113
|
environment: "production",
|
|
108
114
|
page: 2,
|
|
109
115
|
tz: undefined,
|
|
@@ -132,7 +138,7 @@ describe("fetchAll()", () => {
|
|
|
132
138
|
}
|
|
133
139
|
expect(deleteTempDirectorySpy).toHaveBeenCalledOnce();
|
|
134
140
|
});
|
|
135
|
-
it
|
|
141
|
+
it("handles copy overrides", async () => {
|
|
136
142
|
const saveFileSpy = vi.spyOn(utilsExports, "saveFile");
|
|
137
143
|
const mockBatchFetcher = vi.fn().mockReturnValue({
|
|
138
144
|
data: [
|
|
@@ -176,6 +182,42 @@ describe("fetchAll()", () => {
|
|
|
176
182
|
});
|
|
177
183
|
expect(saveFileSpy).toHaveBeenCalledTimes(2);
|
|
178
184
|
});
|
|
185
|
+
it("allows you to pass a custom date format", async () => {
|
|
186
|
+
const mockBatchFetcher = vi.fn().mockReturnValue({
|
|
187
|
+
data: [
|
|
188
|
+
{ path: "/test", markup: "markup1" },
|
|
189
|
+
{ path: "/test2", markup: "markup2" },
|
|
190
|
+
],
|
|
191
|
+
meta: {
|
|
192
|
+
current_page: 1,
|
|
193
|
+
from: 1,
|
|
194
|
+
last_page: 1,
|
|
195
|
+
path: "/test",
|
|
196
|
+
per_page: 10,
|
|
197
|
+
to: 2,
|
|
198
|
+
total: 2,
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
const batchMarkupFetcherMock = vi.fn().mockImplementation((a, b) => {
|
|
202
|
+
return mockBatchFetcher;
|
|
203
|
+
});
|
|
204
|
+
await fetcherExports.fetchAll({
|
|
205
|
+
domain: "test.com",
|
|
206
|
+
apiKey: "123abc",
|
|
207
|
+
environment: "production",
|
|
208
|
+
dateFormat: "yyyy-MM-dd",
|
|
209
|
+
}, "test_platform", vi.fn(), batchMarkupFetcherMock);
|
|
210
|
+
expect(mockBatchFetcher).toHaveBeenCalledWith({
|
|
211
|
+
domain: "test.com",
|
|
212
|
+
apiKey: "123abc",
|
|
213
|
+
baseUrl: "https://go.jamcomments.com",
|
|
214
|
+
copy: {},
|
|
215
|
+
dateFormat: "yyyy-MM-dd",
|
|
216
|
+
environment: "production",
|
|
217
|
+
page: 1,
|
|
218
|
+
tz: undefined,
|
|
219
|
+
});
|
|
220
|
+
});
|
|
179
221
|
});
|
|
180
222
|
describe("batchMarkupFetcher", () => {
|
|
181
223
|
it("constructs fetch request correctly", async () => {
|
|
@@ -394,6 +436,24 @@ describe("markupFetcher", () => {
|
|
|
394
436
|
expect(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v3/markup?domain=test.com&path=%2F©_confirmation_message=custom+confirmation+message©_submit_button=custom+submit+button", expect.anything());
|
|
395
437
|
expect(result).toEqual("results!");
|
|
396
438
|
});
|
|
439
|
+
it("passes date format string", async () => {
|
|
440
|
+
const fetchMock = vi.fn().mockImplementation(() => {
|
|
441
|
+
return {
|
|
442
|
+
status: 200,
|
|
443
|
+
ok: true,
|
|
444
|
+
text: () => "results!",
|
|
445
|
+
};
|
|
446
|
+
});
|
|
447
|
+
const fetcher = markupFetcher("test", fetchMock);
|
|
448
|
+
await fetcher({
|
|
449
|
+
path: null,
|
|
450
|
+
domain: "test.com",
|
|
451
|
+
apiKey: "123abc",
|
|
452
|
+
environment: "production",
|
|
453
|
+
dateFormat: "yyyy-MM-dd",
|
|
454
|
+
});
|
|
455
|
+
expect(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v3/markup?domain=test.com&path=%2F&date_format=yyyy-MM-dd", expect.anything());
|
|
456
|
+
});
|
|
397
457
|
it("response isn't ok", async () => {
|
|
398
458
|
const fetchMock = vi.fn().mockImplementation(() => {
|
|
399
459
|
return {
|
|
@@ -413,7 +473,7 @@ describe("markupFetcher", () => {
|
|
|
413
473
|
it("makes fresh request when temp directory does not exist", async () => {
|
|
414
474
|
const tempDirectoryExistsSpy = vi
|
|
415
475
|
.spyOn(utilsExports, "tempDirectoryExists")
|
|
416
|
-
.mockReturnValue(false);
|
|
476
|
+
.mockReturnValue(Promise.resolve(false));
|
|
417
477
|
const readFileSpy = vi.spyOn(utilsExports, "readFile");
|
|
418
478
|
const fetchMock = vi.fn().mockImplementation(() => {
|
|
419
479
|
return {
|
|
@@ -437,10 +497,10 @@ describe("markupFetcher", () => {
|
|
|
437
497
|
it("uses saved markup when it exists", async () => {
|
|
438
498
|
const tempDirectoryExistsSpy = vi
|
|
439
499
|
.spyOn(utilsExports, "tempDirectoryExists")
|
|
440
|
-
.mockReturnValue(true);
|
|
500
|
+
.mockReturnValue(Promise.resolve(true));
|
|
441
501
|
const readFileSpy = vi
|
|
442
502
|
.spyOn(utilsExports, "readFile")
|
|
443
|
-
.mockReturnValue("saved markup");
|
|
503
|
+
.mockReturnValue(Promise.resolve("saved markup"));
|
|
444
504
|
const fetchMock = vi.fn();
|
|
445
505
|
const fetcher = markupFetcher("test", fetchMock);
|
|
446
506
|
const result = await fetcher({
|
|
@@ -457,13 +517,13 @@ describe("markupFetcher", () => {
|
|
|
457
517
|
it("uses the EMPTY template when there's no saved file for a post", async () => {
|
|
458
518
|
const tempDirectoryExistsSpy = vi
|
|
459
519
|
.spyOn(utilsExports, "tempDirectoryExists")
|
|
460
|
-
.mockReturnValue(true);
|
|
520
|
+
.mockReturnValue(Promise.resolve(true));
|
|
461
521
|
const readFileSpy = vi
|
|
462
522
|
.spyOn(utilsExports, "readFile")
|
|
463
523
|
.mockReturnValue(null);
|
|
464
524
|
const getEmptyMarkupSpy = vi
|
|
465
525
|
.spyOn(utilsExports, "getEmptyMarkup")
|
|
466
|
-
.mockReturnValue("<!-- EMPTY -->");
|
|
526
|
+
.mockReturnValue(Promise.resolve("<!-- EMPTY -->"));
|
|
467
527
|
const fetchMock = vi.fn();
|
|
468
528
|
const fetcher = markupFetcher("test", fetchMock);
|
|
469
529
|
const result = await fetcher({
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, rmdirSync, writeFile } from "fs";
|
|
2
|
+
import { toSavedFileName } from "./utils";
|
|
3
|
+
export async function getTempDirectory() {
|
|
4
|
+
const path = await import("path");
|
|
5
|
+
return path.join(process.cwd(), "_temp_jc");
|
|
6
|
+
}
|
|
7
|
+
export async function deleteTempDirectory() {
|
|
8
|
+
const tempDirectory = await getTempDirectory();
|
|
9
|
+
if (existsSync(tempDirectory)) {
|
|
10
|
+
rmdirSync(tempDirectory, { recursive: true });
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export async function createTempDirectory(mkdirSyncImpl = mkdirSync, existsSyncImpl = existsSync) {
|
|
14
|
+
const tempDirectory = await getTempDirectory();
|
|
15
|
+
if (!(await tempDirectoryExists(existsSyncImpl))) {
|
|
16
|
+
mkdirSyncImpl(tempDirectory);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export async function readFile(name, readFileSyncImpl = readFileSync) {
|
|
20
|
+
const fileName = toSavedFileName(name);
|
|
21
|
+
try {
|
|
22
|
+
return readFileSyncImpl(`${await getTempDirectory()}/${fileName}`, "utf8");
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export function getEmptyMarkup() {
|
|
29
|
+
return readFile("EMPTY");
|
|
30
|
+
}
|
|
31
|
+
export async function tempDirectoryExists(existsSyncImpl = existsSync) {
|
|
32
|
+
return existsSyncImpl(await getTempDirectory());
|
|
33
|
+
}
|
|
34
|
+
export async function saveFile(name, data, writeFileImpl = writeFile) {
|
|
35
|
+
const fileName = toSavedFileName(name);
|
|
36
|
+
const tempDirectory = await getTempDirectory();
|
|
37
|
+
return new Promise(async (resolve) => {
|
|
38
|
+
writeFileImpl(`${tempDirectory}/${fileName}`, data, () => {
|
|
39
|
+
resolve();
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { createTempDirectory, getTempDirectory, readFile, saveFile, } from "./nodeUtils";
|
|
3
|
+
describe("createTempDirectory()", () => {
|
|
4
|
+
it("creates temp directory fresh", async () => {
|
|
5
|
+
const tempDirectory = await getTempDirectory();
|
|
6
|
+
const mkdirSyncMock = vi.fn();
|
|
7
|
+
const existsSyncMock = vi.fn().mockReturnValue(false);
|
|
8
|
+
await new Promise((resolve) => {
|
|
9
|
+
expect(async () => {
|
|
10
|
+
await createTempDirectory(mkdirSyncMock, existsSyncMock);
|
|
11
|
+
resolve();
|
|
12
|
+
}).not.toThrow();
|
|
13
|
+
});
|
|
14
|
+
expect(mkdirSyncMock).toHaveBeenCalledWith(tempDirectory);
|
|
15
|
+
});
|
|
16
|
+
it("does not throw error when it already exists", () => {
|
|
17
|
+
const mkdirSyncMock = vi.fn().mockImplementation(() => {
|
|
18
|
+
throw new Error("Directory already exists");
|
|
19
|
+
});
|
|
20
|
+
const existsSyncMock = vi.fn().mockReturnValue(true);
|
|
21
|
+
expect(() => createTempDirectory(mkdirSyncMock, existsSyncMock)).not.toThrow();
|
|
22
|
+
expect(mkdirSyncMock).not.toHaveBeenCalledWith();
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
describe("readFile()", () => {
|
|
26
|
+
it("reads the file", async () => {
|
|
27
|
+
const readFileSyncMock = vi.fn().mockReturnValue("file contents");
|
|
28
|
+
const tempDirectory = await getTempDirectory();
|
|
29
|
+
expect(await readFile("hey/there", readFileSyncMock)).toEqual("file contents");
|
|
30
|
+
expect(readFileSyncMock).toHaveBeenCalledWith(`${tempDirectory}/hey::there`, "utf8");
|
|
31
|
+
});
|
|
32
|
+
it("returns null when file doesn't exist", async () => {
|
|
33
|
+
const readFileSyncMock = vi.fn().mockImplementation(() => {
|
|
34
|
+
throw new Error("File not found");
|
|
35
|
+
});
|
|
36
|
+
expect(await readFile("hey/there", readFileSyncMock)).toEqual(null);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
describe("saveFile()", () => {
|
|
40
|
+
it("saves the file", async () => {
|
|
41
|
+
const writeFileMock = vi.fn().mockImplementation((file, data, cb) => cb());
|
|
42
|
+
const tempDirectory = await getTempDirectory();
|
|
43
|
+
await saveFile("hey/there", "file contents", writeFileMock);
|
|
44
|
+
expect(writeFileMock).toHaveBeenCalledWith(`${tempDirectory}/hey::there`, "file contents", expect.any(Function));
|
|
45
|
+
});
|
|
46
|
+
});
|
package/dist/esm/utils.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, rmdirSync, writeFile } from "fs";
|
|
2
|
-
import { TEMP_DIRECTORY } from ".";
|
|
3
1
|
export function isValidTimezone(tz) {
|
|
4
2
|
try {
|
|
5
3
|
Intl.DateTimeFormat(undefined, { timeZone: tz });
|
|
@@ -56,42 +54,9 @@ export function unescapeHTML(str) {
|
|
|
56
54
|
}
|
|
57
55
|
});
|
|
58
56
|
}
|
|
59
|
-
export function deleteTempDirectory() {
|
|
60
|
-
if (existsSync(TEMP_DIRECTORY)) {
|
|
61
|
-
rmdirSync(TEMP_DIRECTORY, { recursive: true });
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
export function createTempDirectory(mkdirSyncImpl = mkdirSync, existsSyncImpl = existsSync) {
|
|
65
|
-
if (!tempDirectoryExists(existsSyncImpl)) {
|
|
66
|
-
mkdirSyncImpl(TEMP_DIRECTORY);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
57
|
export function toSavedFileName(name) {
|
|
70
58
|
return name.replace(/^\//, "").replace(/\//g, "::");
|
|
71
59
|
}
|
|
72
|
-
export function readFile(name, readFileSyncImpl = readFileSync) {
|
|
73
|
-
const fileName = toSavedFileName(name);
|
|
74
|
-
try {
|
|
75
|
-
return readFileSyncImpl(`${TEMP_DIRECTORY}/${fileName}`, "utf8");
|
|
76
|
-
}
|
|
77
|
-
catch (error) {
|
|
78
|
-
return null;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
export function getEmptyMarkup() {
|
|
82
|
-
return readFile("EMPTY");
|
|
83
|
-
}
|
|
84
|
-
export function tempDirectoryExists(existsSyncImpl = existsSync) {
|
|
85
|
-
return existsSyncImpl(TEMP_DIRECTORY);
|
|
86
|
-
}
|
|
87
|
-
export function saveFile(name, data, writeFileImpl = writeFile) {
|
|
88
|
-
const fileName = toSavedFileName(name);
|
|
89
|
-
return new Promise((resolve) => {
|
|
90
|
-
writeFileImpl(`${TEMP_DIRECTORY}/${fileName}`, data, () => {
|
|
91
|
-
resolve();
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
60
|
export function removeFalseyValues(obj) {
|
|
96
61
|
const filteredItems = Object.entries(obj).filter(([, value]) => value);
|
|
97
62
|
return Object.fromEntries(filteredItems);
|
package/dist/esm/utils.test.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
-
import { getEnvironment,
|
|
3
|
-
import { TEMP_DIRECTORY } from ".";
|
|
2
|
+
import { getEnvironment, removeFalseyValues, toSavedFileName } from "./utils";
|
|
4
3
|
const env = process.env;
|
|
5
4
|
beforeEach(() => {
|
|
6
5
|
vi.resetModules();
|
|
@@ -43,48 +42,11 @@ describe("getEnvironment()", () => {
|
|
|
43
42
|
});
|
|
44
43
|
});
|
|
45
44
|
});
|
|
46
|
-
describe("createTempDirectory()", () => {
|
|
47
|
-
it("creates temp directory fresh", () => {
|
|
48
|
-
const mkdirSyncMock = vi.fn();
|
|
49
|
-
const existsSyncMock = vi.fn().mockReturnValue(false);
|
|
50
|
-
expect(() => createTempDirectory(mkdirSyncMock, existsSyncMock)).not.toThrow();
|
|
51
|
-
expect(mkdirSyncMock).toHaveBeenCalledWith(TEMP_DIRECTORY);
|
|
52
|
-
});
|
|
53
|
-
it("does not throw error when it already exists", () => {
|
|
54
|
-
const mkdirSyncMock = vi.fn().mockImplementation(() => {
|
|
55
|
-
throw new Error("Directory already exists");
|
|
56
|
-
});
|
|
57
|
-
const existsSyncMock = vi.fn().mockReturnValue(true);
|
|
58
|
-
expect(() => createTempDirectory(mkdirSyncMock, existsSyncMock)).not.toThrow();
|
|
59
|
-
expect(mkdirSyncMock).not.toHaveBeenCalledWith();
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
45
|
describe("toSavedFileName()", () => {
|
|
63
46
|
it("replaces slashes with double colons", () => {
|
|
64
47
|
expect(toSavedFileName("/hey/there")).toEqual("hey::there");
|
|
65
48
|
});
|
|
66
49
|
});
|
|
67
|
-
describe("readFile()", () => {
|
|
68
|
-
it("reads the file", () => {
|
|
69
|
-
const readFileSyncMock = vi.fn().mockReturnValue("file contents");
|
|
70
|
-
expect(readFile("hey/there", readFileSyncMock)).toEqual("file contents");
|
|
71
|
-
expect(readFileSyncMock).toHaveBeenCalledWith(`${TEMP_DIRECTORY}/hey::there`, "utf8");
|
|
72
|
-
});
|
|
73
|
-
it("returns null when file doesn't exist", () => {
|
|
74
|
-
const readFileSyncMock = vi.fn().mockImplementation(() => {
|
|
75
|
-
throw new Error("File not found");
|
|
76
|
-
});
|
|
77
|
-
expect(readFile("hey/there", readFileSyncMock)).toEqual(null);
|
|
78
|
-
});
|
|
79
|
-
});
|
|
80
|
-
describe("saveFile()", () => {
|
|
81
|
-
it("saves the file", async () => {
|
|
82
|
-
const writeFileMock = vi.fn();
|
|
83
|
-
const result = saveFile("hey/there", "file contents", writeFileMock);
|
|
84
|
-
expect(writeFileMock).toHaveBeenCalledWith(`${TEMP_DIRECTORY}/hey::there`, "file contents", expect.any(Function));
|
|
85
|
-
expect(result).toBeInstanceOf(Promise);
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
50
|
describe("removeFalseyValues()", () => {
|
|
89
51
|
it("should remove falsey values", () => {
|
|
90
52
|
expect(removeFalseyValues({ a: 1, b: 0, d: null, e: "" })).toEqual({
|
package/dist/types/index.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export interface IFetchData {
|
|
|
17
17
|
tz?: string;
|
|
18
18
|
baseUrl?: string;
|
|
19
19
|
environment?: string;
|
|
20
|
+
dateFormat?: string;
|
|
20
21
|
copy?: {
|
|
21
22
|
copy_confirmation_message?: string;
|
|
22
23
|
copy_submit_button?: string;
|
|
@@ -47,9 +48,9 @@ interface IBatchResponse {
|
|
|
47
48
|
total: number;
|
|
48
49
|
};
|
|
49
50
|
}
|
|
50
|
-
export declare function fetchAll({ tz, domain, apiKey, baseUrl, environment, copy, }: IBatchFetchData, platform: string, fetchImplementation?: any, batchMarkupFetcherImpl?: any): Promise<void>;
|
|
51
|
+
export declare function fetchAll({ tz, dateFormat, domain, apiKey, baseUrl, environment, copy, }: IBatchFetchData, platform: string, fetchImplementation?: any, batchMarkupFetcherImpl?: any): Promise<void>;
|
|
51
52
|
export declare function batchMarkupFetcher(platform: string, fetchImplementation?: typeof fetch): (args: IBatchFetchData) => Promise<IBatchResponse>;
|
|
52
|
-
export declare function fetchFreshMarkup({ tz, path, domain, apiKey, baseUrl, environment,
|
|
53
|
-
export declare function makeMarkupRequest<T extends Partial<IBatchFetchData & IFetchData>>({ tz, path, domain, apiKey,
|
|
53
|
+
export declare function fetchFreshMarkup({ tz, path, copy, domain, apiKey, dateFormat, baseUrl, environment, }: IFetchData, fetchImplementation: typeof fetch, platform: string): Promise<string>;
|
|
54
|
+
export declare function makeMarkupRequest<T extends Partial<IBatchFetchData & IFetchData>>({ tz, path, page, domain, apiKey, dateFormat, copy, baseUrl, environment, }: T, baseServicePath: string, fetchImplementation: typeof fetch, platform: string): Promise<Response>;
|
|
54
55
|
export declare function markupFetcher(platform: string, fetchImplementation?: typeof fetch): (args: IFetchData) => Promise<string>;
|
|
55
56
|
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync } from "fs";
|
|
2
|
+
export declare function getTempDirectory(): Promise<string>;
|
|
3
|
+
export declare function deleteTempDirectory(): Promise<void>;
|
|
4
|
+
export declare function createTempDirectory(mkdirSyncImpl?: typeof mkdirSync, existsSyncImpl?: typeof existsSync): Promise<void>;
|
|
5
|
+
export declare function readFile(name: any, readFileSyncImpl?: typeof readFileSync): Promise<string>;
|
|
6
|
+
export declare function getEmptyMarkup(): Promise<string>;
|
|
7
|
+
export declare function tempDirectoryExists(existsSyncImpl?: typeof existsSync): Promise<boolean>;
|
|
8
|
+
export declare function saveFile(name: string, data: string, writeFileImpl?: any): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/types/utils.d.ts
CHANGED
|
@@ -1,13 +1,6 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync } from "fs";
|
|
2
1
|
export declare function isValidTimezone(tz: string): boolean;
|
|
3
2
|
export declare function getEnvironment(): string;
|
|
4
3
|
export declare function parseJson(json: string): any;
|
|
5
4
|
export declare function unescapeHTML(str: any): any;
|
|
6
|
-
export declare function deleteTempDirectory(): void;
|
|
7
|
-
export declare function createTempDirectory(mkdirSyncImpl?: typeof mkdirSync, existsSyncImpl?: typeof existsSync): void;
|
|
8
5
|
export declare function toSavedFileName(name: string): string;
|
|
9
|
-
export declare function readFile(name: any, readFileSyncImpl?: typeof readFileSync): string;
|
|
10
|
-
export declare function getEmptyMarkup(): string;
|
|
11
|
-
export declare function tempDirectoryExists(existsSyncImpl?: typeof existsSync): boolean;
|
|
12
|
-
export declare function saveFile(name: string, data: string, writeFileImpl?: any): Promise<void>;
|
|
13
6
|
export declare function removeFalseyValues<T>(obj: T): Partial<T>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jam-comments/server-utilities",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.5.0",
|
|
4
4
|
"description": "Various JavaScript utilities for JamComments.",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@types/node": "^20.14.11",
|
|
26
26
|
"prettier": "^3.3.3",
|
|
27
|
-
"typescript": "^5.5.
|
|
27
|
+
"typescript": "^5.5.4",
|
|
28
28
|
"vite": "^5.3.4",
|
|
29
|
-
"vitest": "^2.0.
|
|
29
|
+
"vitest": "^2.0.4"
|
|
30
30
|
},
|
|
31
31
|
"publishConfig": {
|
|
32
32
|
"access": "public"
|