@jam-comments/server-utilities 5.10.2 → 5.12.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 CHANGED
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Store = exports.logError = exports.log = exports.removeFalseyValues = exports.fetchAll = exports.markupFetcher = void 0;
3
+ exports.Store = exports.logError = exports.log = exports.removeFalseyValues = exports.fetchAll = exports.markupFetcher = exports.simpleMarkupFetcher = void 0;
4
+ var simpleMarkupFetcher_1 = require("./simpleMarkupFetcher");
5
+ Object.defineProperty(exports, "simpleMarkupFetcher", { enumerable: true, get: function () { return simpleMarkupFetcher_1.simpleMarkupFetcher; } });
4
6
  var markupFetcher_1 = require("./markupFetcher");
5
7
  Object.defineProperty(exports, "markupFetcher", { enumerable: true, get: function () { return markupFetcher_1.markupFetcher; } });
6
8
  Object.defineProperty(exports, "fetchAll", { enumerable: true, get: function () { return markupFetcher_1.fetchAll; } });
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BASE_URL = void 0;
3
4
  exports.fetchAll = fetchAll;
4
5
  exports.batchMarkupFetcher = batchMarkupFetcher;
5
6
  exports.fetchFreshMarkup = fetchFreshMarkup;
@@ -8,8 +9,8 @@ exports.markupFetcher = markupFetcher;
8
9
  const injectSchema_1 = require("./injectSchema");
9
10
  const utils_1 = require("./utils");
10
11
  const store_1 = require("./store");
11
- const BASE_URL = "https://go.jamcomments.com";
12
- async function fetchAll({ tz = undefined, dateFormat = undefined, domain, apiKey, baseUrl = BASE_URL, environment = (0, utils_1.getEnvironment)(), copy = {}, }, platform, fetchImplementation = fetch, batchMarkupFetcherImpl = batchMarkupFetcher, store = new store_1.Store()) {
12
+ exports.BASE_URL = "https://go.jamcomments.com";
13
+ async function fetchAll({ tz = undefined, dateFormat = undefined, domain, apiKey, baseUrl = exports.BASE_URL, environment = (0, utils_1.getEnvironment)(), copy = {}, }, platform, fetchImplementation = fetch, batchMarkupFetcherImpl = batchMarkupFetcher, store = new store_1.Store()) {
13
14
  const fetchBatchMarkup = batchMarkupFetcherImpl(platform, fetchImplementation);
14
15
  let shouldKeepFetching = true;
15
16
  let page = 1;
@@ -45,16 +46,16 @@ async function fetchAll({ tz = undefined, dateFormat = undefined, domain, apiKey
45
46
  return store.store;
46
47
  }
47
48
  function batchMarkupFetcher(platform, fetchImplementation = fetch) {
48
- return async ({ tz, copy, domain, apiKey, dateFormat, baseUrl = BASE_URL, environment = (0, utils_1.getEnvironment)(), page = 1, }) => {
49
+ return async ({ tz, copy, domain, apiKey, dateFormat, baseUrl = exports.BASE_URL, environment = (0, utils_1.getEnvironment)(), page = 1, }) => {
49
50
  const response = await makeMarkupRequest({ tz, domain, apiKey, baseUrl, environment, page, copy, dateFormat }, "/api/v3/markup/all", fetchImplementation, platform);
50
51
  return response.json();
51
52
  };
52
53
  }
53
- async function fetchFreshMarkup({ tz, path, copy, domain, apiKey, dateFormat, baseUrl = BASE_URL, environment = (0, utils_1.getEnvironment)(), }, fetchImplementation = fetch, platform) {
54
- const response = await makeMarkupRequest({ tz, path, domain, apiKey, baseUrl, environment, copy, dateFormat }, "/api/v3/markup", fetchImplementation, platform);
54
+ async function fetchFreshMarkup({ tz, path, copy, cache, domain, apiKey, dateFormat, baseUrl = exports.BASE_URL, environment = (0, utils_1.getEnvironment)(), }, fetchImplementation = fetch, platform) {
55
+ const response = await makeMarkupRequest({ tz, path, domain, apiKey, baseUrl, environment, copy, dateFormat, cache }, "/api/v3/markup", fetchImplementation, platform);
55
56
  return response.text();
56
57
  }
57
- async function makeMarkupRequest({ tz, path, page, domain, apiKey, dateFormat, copy = {}, baseUrl = BASE_URL, environment = (0, utils_1.getEnvironment)(), }, baseServicePath, fetchImplementation = fetch, platform) {
58
+ async function makeMarkupRequest({ tz, path, page, cache, domain, apiKey, dateFormat, copy = {}, baseUrl = exports.BASE_URL, environment = (0, utils_1.getEnvironment)(), }, baseServicePath, fetchImplementation = fetch, platform) {
58
59
  const trimmedTimezone = tz?.trim();
59
60
  if (trimmedTimezone && !(0, utils_1.isValidTimezone)(trimmedTimezone)) {
60
61
  throw new Error(`The timezone passed to JamComments is invalid: ${trimmedTimezone}`);
@@ -62,6 +63,10 @@ async function makeMarkupRequest({ tz, path, page, domain, apiKey, dateFormat, c
62
63
  const params = new URLSearchParams({
63
64
  domain,
64
65
  });
66
+ if (cache !== undefined) {
67
+ console.info("DOING IT", cache);
68
+ params.set("cache", cache.toString());
69
+ }
65
70
  if (path) {
66
71
  params.set("path", path);
67
72
  }
@@ -98,7 +103,7 @@ async function makeMarkupRequest({ tz, path, page, domain, apiKey, dateFormat, c
98
103
  return response;
99
104
  }
100
105
  function markupFetcher(platform, fetchImplementation = fetch, store = new store_1.Store()) {
101
- return async ({ tz = undefined, path, domain, apiKey, schema, dateFormat, baseUrl = BASE_URL, environment = (0, utils_1.getEnvironment)(), copy = {}, }) => {
106
+ return async ({ tz = undefined, path, cache, domain, apiKey, schema, dateFormat, baseUrl = exports.BASE_URL, environment = (0, utils_1.getEnvironment)(), copy = {}, }) => {
102
107
  path = path || "/";
103
108
  const cachedMarkup = (() => {
104
109
  if (!store.hasData) {
@@ -108,7 +113,17 @@ function markupFetcher(platform, fetchImplementation = fetch, store = new store_
108
113
  })();
109
114
  const markup = cachedMarkup
110
115
  ? cachedMarkup
111
- : await fetchFreshMarkup({ tz, path, domain, apiKey, baseUrl, environment, copy, dateFormat }, fetchImplementation, platform);
116
+ : await fetchFreshMarkup({
117
+ tz,
118
+ path,
119
+ domain,
120
+ apiKey,
121
+ baseUrl,
122
+ environment,
123
+ copy,
124
+ dateFormat,
125
+ cache,
126
+ }, fetchImplementation, platform);
112
127
  if (schema) {
113
128
  const preparedSchema = typeof schema !== "string" ? JSON.stringify(schema) : schema;
114
129
  const parsedSchema = (0, utils_1.parseJson)(preparedSchema);
@@ -15,13 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
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
- };
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
25
35
  Object.defineProperty(exports, "__esModule", { value: true });
26
36
  const vitest_1 = require("vitest");
27
37
  const injectSchema = __importStar(require("./injectSchema"));
@@ -359,6 +369,25 @@ const { markupFetcher, batchMarkupFetcher } = fetcherExports;
359
369
  (0, vitest_1.expect)(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v3/markup?domain=test.com&path=%2Ftest&stub=true", vitest_1.expect.anything());
360
370
  (0, vitest_1.expect)(result).toEqual("results!");
361
371
  });
372
+ (0, vitest_1.it)("sets cache control header on response", async () => {
373
+ const fetchMock = vitest_1.vi.fn().mockImplementation(() => {
374
+ return {
375
+ status: 200,
376
+ ok: true,
377
+ text: () => "results!",
378
+ };
379
+ });
380
+ const fetcher = markupFetcher("test", fetchMock);
381
+ const result = await fetcher({
382
+ path: "/test",
383
+ domain: "test.com",
384
+ apiKey: "123abc",
385
+ environment: "development",
386
+ cache: true,
387
+ });
388
+ (0, vitest_1.expect)(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v3/markup?domain=test.com&cache=true&path=%2Ftest&stub=true", vitest_1.expect.anything());
389
+ (0, vitest_1.expect)(result).toEqual("results!");
390
+ });
362
391
  (0, vitest_1.it)("uses different base URL", async () => {
363
392
  const fetchMock = vitest_1.vi.fn().mockImplementation(() => {
364
393
  return {
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.simpleMarkupFetcher = simpleMarkupFetcher;
4
+ const injectSchema_1 = require("./injectSchema");
5
+ const markupFetcher_1 = require("./markupFetcher");
6
+ const utils_1 = require("./utils");
7
+ function simpleMarkupFetcher(platform, fetchImplementation = fetch) {
8
+ return async ({ tz = undefined, path, domain, apiKey, schema, dateFormat, baseUrl = markupFetcher_1.BASE_URL, environment = (0, utils_1.getEnvironment)(), copy = {}, }) => {
9
+ path = path || "/";
10
+ const markup = await (0, markupFetcher_1.fetchFreshMarkup)({ tz, path, domain, apiKey, baseUrl, environment, copy, dateFormat }, fetchImplementation, platform);
11
+ if (schema) {
12
+ const preparedSchema = typeof schema !== "string" ? JSON.stringify(schema) : schema;
13
+ const parsedSchema = (0, utils_1.parseJson)(preparedSchema);
14
+ if (!parsedSchema) {
15
+ return markup;
16
+ }
17
+ return (0, injectSchema_1.injectSchema)(markup, parsedSchema);
18
+ }
19
+ return markup;
20
+ };
21
+ }
@@ -0,0 +1,301 @@
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 () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const injectSchema = __importStar(require("./injectSchema"));
37
+ const vitest_1 = require("vitest");
38
+ const simpleMarkupFetcher_1 = require("./simpleMarkupFetcher");
39
+ (0, vitest_1.describe)("simpleMarkupFetcher", () => {
40
+ (0, vitest_1.it)("constructs fetch request correctly", async () => {
41
+ const injectSchemaSpy = vitest_1.vi.spyOn(injectSchema, "injectSchema");
42
+ const fetchMock = vitest_1.vi.fn().mockImplementation(() => {
43
+ return {
44
+ status: 200,
45
+ ok: true,
46
+ text: () => "results!",
47
+ };
48
+ });
49
+ const fetcher = (0, simpleMarkupFetcher_1.simpleMarkupFetcher)("test", fetchMock);
50
+ const result = await fetcher({
51
+ path: "/test",
52
+ domain: "test.com",
53
+ apiKey: "123abc",
54
+ environment: "production",
55
+ });
56
+ (0, vitest_1.expect)(injectSchemaSpy).not.toHaveBeenCalled();
57
+ (0, vitest_1.expect)(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v3/markup?domain=test.com&path=%2Ftest", vitest_1.expect.objectContaining({
58
+ headers: vitest_1.expect.objectContaining({
59
+ Accept: "application/json",
60
+ Authorization: "Bearer 123abc",
61
+ "X-Platform": "test",
62
+ }),
63
+ method: "GET",
64
+ }));
65
+ (0, vitest_1.expect)(result).toEqual("results!");
66
+ });
67
+ (0, vitest_1.it)("stubs comments", async () => {
68
+ const fetchMock = vitest_1.vi.fn().mockImplementation(() => {
69
+ return {
70
+ status: 200,
71
+ ok: true,
72
+ text: () => "results!",
73
+ };
74
+ });
75
+ const fetcher = (0, simpleMarkupFetcher_1.simpleMarkupFetcher)("test", fetchMock);
76
+ const result = await fetcher({
77
+ path: "/test",
78
+ domain: "test.com",
79
+ apiKey: "123abc",
80
+ environment: "development",
81
+ });
82
+ (0, vitest_1.expect)(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v3/markup?domain=test.com&path=%2Ftest&stub=true", vitest_1.expect.anything());
83
+ (0, vitest_1.expect)(result).toEqual("results!");
84
+ });
85
+ (0, vitest_1.it)("uses different base URL", async () => {
86
+ const fetchMock = vitest_1.vi.fn().mockImplementation(() => {
87
+ return {
88
+ status: 200,
89
+ ok: true,
90
+ text: () => "results!",
91
+ };
92
+ });
93
+ const fetcher = (0, simpleMarkupFetcher_1.simpleMarkupFetcher)("test", fetchMock);
94
+ const result = await fetcher({
95
+ path: "/test",
96
+ domain: "test.com",
97
+ apiKey: "123abc",
98
+ baseUrl: "http://ur-mom.com",
99
+ environment: "production",
100
+ });
101
+ (0, vitest_1.expect)(fetchMock).toHaveBeenCalledWith("http://ur-mom.com/api/v3/markup?domain=test.com&path=%2Ftest", vitest_1.expect.anything());
102
+ (0, vitest_1.expect)(result).toEqual("results!");
103
+ });
104
+ (0, vitest_1.it)("respects production!!!", async () => {
105
+ const fetchMock = vitest_1.vi.fn().mockImplementation(() => {
106
+ return {
107
+ status: 200,
108
+ ok: true,
109
+ text: () => "results!",
110
+ };
111
+ });
112
+ const fetcher = (0, simpleMarkupFetcher_1.simpleMarkupFetcher)("test", fetchMock);
113
+ const result = await fetcher({
114
+ path: "/test",
115
+ domain: "test.com",
116
+ apiKey: "123abc",
117
+ baseUrl: "http://ur-mom.com",
118
+ environment: "production",
119
+ });
120
+ (0, vitest_1.expect)(fetchMock).toHaveBeenCalledWith("http://ur-mom.com/api/v3/markup?domain=test.com&path=%2Ftest", vitest_1.expect.anything());
121
+ (0, vitest_1.expect)(result).toEqual("results!");
122
+ });
123
+ (0, vitest_1.it)("falls back to root path", async () => {
124
+ const fetchMock = vitest_1.vi.fn().mockImplementation(() => {
125
+ return {
126
+ status: 200,
127
+ ok: true,
128
+ text: () => "results!",
129
+ };
130
+ });
131
+ const fetcher = (0, simpleMarkupFetcher_1.simpleMarkupFetcher)("test", fetchMock);
132
+ const result = await fetcher({
133
+ path: null,
134
+ domain: "test.com",
135
+ apiKey: "123abc",
136
+ environment: "production",
137
+ });
138
+ (0, vitest_1.expect)(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v3/markup?domain=test.com&path=%2F", vitest_1.expect.anything());
139
+ (0, vitest_1.expect)(result).toEqual("results!");
140
+ });
141
+ (0, vitest_1.it)("credentials are invalid", async () => {
142
+ const fetchMock = vitest_1.vi.fn().mockImplementation(() => {
143
+ return {
144
+ status: 401,
145
+ ok: false,
146
+ text: () => "bad results!",
147
+ };
148
+ });
149
+ const fetcher = (0, simpleMarkupFetcher_1.simpleMarkupFetcher)("test", fetchMock);
150
+ (0, vitest_1.expect)(fetcher({
151
+ path: "/test",
152
+ domain: "test.com",
153
+ apiKey: "123abc",
154
+ })).rejects.toThrowError(/Unauthorized!/);
155
+ });
156
+ (0, vitest_1.it)("response isn't ok", async () => {
157
+ const fetchMock = vitest_1.vi.fn().mockImplementation(() => {
158
+ return {
159
+ status: 500,
160
+ ok: false,
161
+ text: () => "bad results!",
162
+ };
163
+ });
164
+ const fetcher = (0, simpleMarkupFetcher_1.simpleMarkupFetcher)("test", fetchMock);
165
+ (0, vitest_1.expect)(fetcher({
166
+ path: "/test",
167
+ domain: "test.com",
168
+ apiKey: "123abc",
169
+ })).rejects.toThrowError(/request failed! Status code: 500/);
170
+ });
171
+ (0, vitest_1.it)("passes custom copy", async () => {
172
+ const fetchMock = vitest_1.vi.fn().mockImplementation(() => {
173
+ return {
174
+ status: 200,
175
+ ok: true,
176
+ text: () => "results!",
177
+ };
178
+ });
179
+ const fetcher = (0, simpleMarkupFetcher_1.simpleMarkupFetcher)("test", fetchMock);
180
+ const result = await fetcher({
181
+ path: null,
182
+ domain: "test.com",
183
+ apiKey: "123abc",
184
+ environment: "production",
185
+ copy: {
186
+ copy_confirmation_message: "custom confirmation message",
187
+ copy_submit_button: "custom submit button",
188
+ },
189
+ });
190
+ (0, vitest_1.expect)(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v3/markup?domain=test.com&path=%2F&copy_confirmation_message=custom+confirmation+message&copy_submit_button=custom+submit+button", vitest_1.expect.anything());
191
+ (0, vitest_1.expect)(result).toEqual("results!");
192
+ });
193
+ (0, vitest_1.it)("passes date format string", async () => {
194
+ const fetchMock = vitest_1.vi.fn().mockImplementation(() => {
195
+ return {
196
+ status: 200,
197
+ ok: true,
198
+ text: () => "results!",
199
+ };
200
+ });
201
+ const fetcher = (0, simpleMarkupFetcher_1.simpleMarkupFetcher)("test", fetchMock);
202
+ await fetcher({
203
+ path: null,
204
+ domain: "test.com",
205
+ apiKey: "123abc",
206
+ environment: "production",
207
+ dateFormat: "yyyy-MM-dd",
208
+ });
209
+ (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());
210
+ });
211
+ (0, vitest_1.it)("response isn't ok", async () => {
212
+ const fetchMock = vitest_1.vi.fn().mockImplementation(() => {
213
+ return {
214
+ status: 500,
215
+ ok: false,
216
+ text: () => "bad results!",
217
+ };
218
+ });
219
+ const fetcher = (0, simpleMarkupFetcher_1.simpleMarkupFetcher)("test", fetchMock);
220
+ (0, vitest_1.expect)(fetcher({
221
+ path: "/test",
222
+ domain: "test.com",
223
+ apiKey: "123abc",
224
+ })).rejects.toThrowError(/request failed! Status code: 500/);
225
+ });
226
+ (0, vitest_1.describe)("copy overrides", () => {
227
+ (0, vitest_1.it)("encodes copy overrides", async () => {
228
+ const fetchMock = vitest_1.vi.fn().mockImplementation(() => {
229
+ return {
230
+ status: 200,
231
+ ok: true,
232
+ text: () => "results!",
233
+ };
234
+ });
235
+ const fetcher = (0, simpleMarkupFetcher_1.simpleMarkupFetcher)("test", fetchMock);
236
+ await fetcher({
237
+ path: "/some/path",
238
+ domain: "test.com",
239
+ apiKey: "123abc",
240
+ environment: "production",
241
+ copy: {
242
+ copy_confirmation_message: "custom confirmation message",
243
+ copy_submit_button: "custom submit button",
244
+ },
245
+ });
246
+ (0, vitest_1.expect)(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v3/markup?domain=test.com&path=%2Fsome%2Fpath&copy_confirmation_message=custom+confirmation+message&copy_submit_button=custom+submit+button", vitest_1.expect.anything());
247
+ });
248
+ });
249
+ (0, vitest_1.describe)("timezone validation", () => {
250
+ (0, vitest_1.it)("throws error when invalid timezone is provided", async () => {
251
+ const fetchImplMock = vitest_1.vi.fn();
252
+ const fetcher = (0, simpleMarkupFetcher_1.simpleMarkupFetcher)("test", fetchImplMock);
253
+ (0, vitest_1.expect)(fetchImplMock).not.toHaveBeenCalled();
254
+ (0, vitest_1.expect)(fetcher({
255
+ path: "/test",
256
+ domain: "test.com",
257
+ apiKey: "123abc",
258
+ tz: "in/valid",
259
+ environment: "production",
260
+ })).rejects.toThrowError("The timezone passed to JamComments is invalid: in/valid");
261
+ });
262
+ (0, vitest_1.it)("does not throw error when valid timezone is provided", async () => {
263
+ const fetchMock = vitest_1.vi.fn().mockImplementation(() => {
264
+ return {
265
+ status: 200,
266
+ ok: true,
267
+ text: () => "results!",
268
+ };
269
+ });
270
+ const fetcher = (0, simpleMarkupFetcher_1.simpleMarkupFetcher)("test", fetchMock);
271
+ const result = await fetcher({
272
+ path: "/some/path",
273
+ domain: "test.com",
274
+ apiKey: "123abc",
275
+ tz: "America/New_York",
276
+ environment: "production",
277
+ });
278
+ (0, vitest_1.expect)(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v3/markup?domain=test.com&path=%2Fsome%2Fpath&tz=America%2FNew_York", vitest_1.expect.anything());
279
+ (0, vitest_1.expect)(result).toEqual("results!");
280
+ });
281
+ (0, vitest_1.it)("trims a valid timezone", async () => {
282
+ const fetchMock = vitest_1.vi.fn().mockImplementation(() => {
283
+ return {
284
+ status: 200,
285
+ ok: true,
286
+ text: () => "results!",
287
+ };
288
+ });
289
+ const fetcher = (0, simpleMarkupFetcher_1.simpleMarkupFetcher)("test", fetchMock);
290
+ const result = await fetcher({
291
+ path: "/some/path",
292
+ domain: "test.com",
293
+ apiKey: "123abc",
294
+ tz: " America/Chicago ",
295
+ environment: "production",
296
+ });
297
+ (0, vitest_1.expect)(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v3/markup?domain=test.com&path=%2Fsome%2Fpath&tz=America%2FChicago", vitest_1.expect.anything());
298
+ (0, vitest_1.expect)(result).toEqual("results!");
299
+ });
300
+ });
301
+ });
package/dist/esm/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ export { simpleMarkupFetcher } from "./simpleMarkupFetcher";
1
2
  export { markupFetcher, fetchAll } from "./markupFetcher";
2
3
  export { removeFalseyValues } from "./utils";
3
4
  export { log, logError } from "./log";
@@ -1,7 +1,7 @@
1
1
  import { injectSchema } from "./injectSchema";
2
2
  import { getEnvironment, isValidTimezone, parseJson } from "./utils";
3
3
  import { Store } from "./store";
4
- const BASE_URL = "https://go.jamcomments.com";
4
+ export const BASE_URL = "https://go.jamcomments.com";
5
5
  export async function fetchAll({ tz = undefined, dateFormat = undefined, domain, apiKey, baseUrl = BASE_URL, environment = getEnvironment(), copy = {}, }, platform, fetchImplementation = fetch, batchMarkupFetcherImpl = batchMarkupFetcher, store = new Store()) {
6
6
  const fetchBatchMarkup = batchMarkupFetcherImpl(platform, fetchImplementation);
7
7
  let shouldKeepFetching = true;
@@ -43,11 +43,11 @@ export function batchMarkupFetcher(platform, fetchImplementation = fetch) {
43
43
  return response.json();
44
44
  };
45
45
  }
46
- export async function fetchFreshMarkup({ tz, path, copy, domain, apiKey, dateFormat, baseUrl = BASE_URL, environment = getEnvironment(), }, fetchImplementation = fetch, platform) {
47
- const response = await makeMarkupRequest({ tz, path, domain, apiKey, baseUrl, environment, copy, dateFormat }, "/api/v3/markup", fetchImplementation, platform);
46
+ export async function fetchFreshMarkup({ tz, path, copy, cache, domain, apiKey, dateFormat, baseUrl = BASE_URL, environment = getEnvironment(), }, fetchImplementation = fetch, platform) {
47
+ const response = await makeMarkupRequest({ tz, path, domain, apiKey, baseUrl, environment, copy, dateFormat, cache }, "/api/v3/markup", fetchImplementation, platform);
48
48
  return response.text();
49
49
  }
50
- export async function makeMarkupRequest({ tz, path, page, domain, apiKey, dateFormat, copy = {}, baseUrl = BASE_URL, environment = getEnvironment(), }, baseServicePath, fetchImplementation = fetch, platform) {
50
+ export async function makeMarkupRequest({ tz, path, page, cache, domain, apiKey, dateFormat, copy = {}, baseUrl = BASE_URL, environment = getEnvironment(), }, baseServicePath, fetchImplementation = fetch, platform) {
51
51
  const trimmedTimezone = tz?.trim();
52
52
  if (trimmedTimezone && !isValidTimezone(trimmedTimezone)) {
53
53
  throw new Error(`The timezone passed to JamComments is invalid: ${trimmedTimezone}`);
@@ -55,6 +55,10 @@ export async function makeMarkupRequest({ tz, path, page, domain, apiKey, dateFo
55
55
  const params = new URLSearchParams({
56
56
  domain,
57
57
  });
58
+ if (cache !== undefined) {
59
+ console.info("DOING IT", cache);
60
+ params.set("cache", cache.toString());
61
+ }
58
62
  if (path) {
59
63
  params.set("path", path);
60
64
  }
@@ -91,7 +95,7 @@ export async function makeMarkupRequest({ tz, path, page, domain, apiKey, dateFo
91
95
  return response;
92
96
  }
93
97
  export function markupFetcher(platform, fetchImplementation = fetch, store = new Store()) {
94
- return async ({ tz = undefined, path, domain, apiKey, schema, dateFormat, baseUrl = BASE_URL, environment = getEnvironment(), copy = {}, }) => {
98
+ return async ({ tz = undefined, path, cache, domain, apiKey, schema, dateFormat, baseUrl = BASE_URL, environment = getEnvironment(), copy = {}, }) => {
95
99
  path = path || "/";
96
100
  const cachedMarkup = (() => {
97
101
  if (!store.hasData) {
@@ -101,7 +105,17 @@ export function markupFetcher(platform, fetchImplementation = fetch, store = new
101
105
  })();
102
106
  const markup = cachedMarkup
103
107
  ? cachedMarkup
104
- : await fetchFreshMarkup({ tz, path, domain, apiKey, baseUrl, environment, copy, dateFormat }, fetchImplementation, platform);
108
+ : await fetchFreshMarkup({
109
+ tz,
110
+ path,
111
+ domain,
112
+ apiKey,
113
+ baseUrl,
114
+ environment,
115
+ copy,
116
+ dateFormat,
117
+ cache,
118
+ }, fetchImplementation, platform);
105
119
  if (schema) {
106
120
  const preparedSchema = typeof schema !== "string" ? JSON.stringify(schema) : schema;
107
121
  const parsedSchema = parseJson(preparedSchema);
@@ -334,6 +334,25 @@ describe("markupFetcher", () => {
334
334
  expect(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v3/markup?domain=test.com&path=%2Ftest&stub=true", expect.anything());
335
335
  expect(result).toEqual("results!");
336
336
  });
337
+ it("sets cache control header on response", async () => {
338
+ const fetchMock = vi.fn().mockImplementation(() => {
339
+ return {
340
+ status: 200,
341
+ ok: true,
342
+ text: () => "results!",
343
+ };
344
+ });
345
+ const fetcher = markupFetcher("test", fetchMock);
346
+ const result = await fetcher({
347
+ path: "/test",
348
+ domain: "test.com",
349
+ apiKey: "123abc",
350
+ environment: "development",
351
+ cache: true,
352
+ });
353
+ expect(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v3/markup?domain=test.com&cache=true&path=%2Ftest&stub=true", expect.anything());
354
+ expect(result).toEqual("results!");
355
+ });
337
356
  it("uses different base URL", async () => {
338
357
  const fetchMock = vi.fn().mockImplementation(() => {
339
358
  return {
@@ -0,0 +1,18 @@
1
+ import { injectSchema } from "./injectSchema";
2
+ import { BASE_URL, fetchFreshMarkup } from "./markupFetcher";
3
+ import { getEnvironment, parseJson } from "./utils";
4
+ export function simpleMarkupFetcher(platform, fetchImplementation = fetch) {
5
+ return async ({ tz = undefined, path, domain, apiKey, schema, dateFormat, baseUrl = BASE_URL, environment = getEnvironment(), copy = {}, }) => {
6
+ path = path || "/";
7
+ const markup = await fetchFreshMarkup({ tz, path, domain, apiKey, baseUrl, environment, copy, dateFormat }, fetchImplementation, platform);
8
+ if (schema) {
9
+ const preparedSchema = typeof schema !== "string" ? JSON.stringify(schema) : schema;
10
+ const parsedSchema = parseJson(preparedSchema);
11
+ if (!parsedSchema) {
12
+ return markup;
13
+ }
14
+ return injectSchema(markup, parsedSchema);
15
+ }
16
+ return markup;
17
+ };
18
+ }
@@ -0,0 +1,266 @@
1
+ import * as injectSchema from "./injectSchema";
2
+ import { describe, expect, it, vi } from "vitest";
3
+ import { simpleMarkupFetcher } from "./simpleMarkupFetcher";
4
+ describe("simpleMarkupFetcher", () => {
5
+ it("constructs fetch request correctly", async () => {
6
+ const injectSchemaSpy = vi.spyOn(injectSchema, "injectSchema");
7
+ const fetchMock = vi.fn().mockImplementation(() => {
8
+ return {
9
+ status: 200,
10
+ ok: true,
11
+ text: () => "results!",
12
+ };
13
+ });
14
+ const fetcher = simpleMarkupFetcher("test", fetchMock);
15
+ const result = await fetcher({
16
+ path: "/test",
17
+ domain: "test.com",
18
+ apiKey: "123abc",
19
+ environment: "production",
20
+ });
21
+ expect(injectSchemaSpy).not.toHaveBeenCalled();
22
+ expect(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v3/markup?domain=test.com&path=%2Ftest", expect.objectContaining({
23
+ headers: expect.objectContaining({
24
+ Accept: "application/json",
25
+ Authorization: "Bearer 123abc",
26
+ "X-Platform": "test",
27
+ }),
28
+ method: "GET",
29
+ }));
30
+ expect(result).toEqual("results!");
31
+ });
32
+ it("stubs comments", async () => {
33
+ const fetchMock = vi.fn().mockImplementation(() => {
34
+ return {
35
+ status: 200,
36
+ ok: true,
37
+ text: () => "results!",
38
+ };
39
+ });
40
+ const fetcher = simpleMarkupFetcher("test", fetchMock);
41
+ const result = await fetcher({
42
+ path: "/test",
43
+ domain: "test.com",
44
+ apiKey: "123abc",
45
+ environment: "development",
46
+ });
47
+ expect(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v3/markup?domain=test.com&path=%2Ftest&stub=true", expect.anything());
48
+ expect(result).toEqual("results!");
49
+ });
50
+ it("uses different base URL", async () => {
51
+ const fetchMock = vi.fn().mockImplementation(() => {
52
+ return {
53
+ status: 200,
54
+ ok: true,
55
+ text: () => "results!",
56
+ };
57
+ });
58
+ const fetcher = simpleMarkupFetcher("test", fetchMock);
59
+ const result = await fetcher({
60
+ path: "/test",
61
+ domain: "test.com",
62
+ apiKey: "123abc",
63
+ baseUrl: "http://ur-mom.com",
64
+ environment: "production",
65
+ });
66
+ expect(fetchMock).toHaveBeenCalledWith("http://ur-mom.com/api/v3/markup?domain=test.com&path=%2Ftest", expect.anything());
67
+ expect(result).toEqual("results!");
68
+ });
69
+ it("respects production!!!", async () => {
70
+ const fetchMock = vi.fn().mockImplementation(() => {
71
+ return {
72
+ status: 200,
73
+ ok: true,
74
+ text: () => "results!",
75
+ };
76
+ });
77
+ const fetcher = simpleMarkupFetcher("test", fetchMock);
78
+ const result = await fetcher({
79
+ path: "/test",
80
+ domain: "test.com",
81
+ apiKey: "123abc",
82
+ baseUrl: "http://ur-mom.com",
83
+ environment: "production",
84
+ });
85
+ expect(fetchMock).toHaveBeenCalledWith("http://ur-mom.com/api/v3/markup?domain=test.com&path=%2Ftest", expect.anything());
86
+ expect(result).toEqual("results!");
87
+ });
88
+ it("falls back to root path", async () => {
89
+ const fetchMock = vi.fn().mockImplementation(() => {
90
+ return {
91
+ status: 200,
92
+ ok: true,
93
+ text: () => "results!",
94
+ };
95
+ });
96
+ const fetcher = simpleMarkupFetcher("test", fetchMock);
97
+ const result = await fetcher({
98
+ path: null,
99
+ domain: "test.com",
100
+ apiKey: "123abc",
101
+ environment: "production",
102
+ });
103
+ expect(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v3/markup?domain=test.com&path=%2F", expect.anything());
104
+ expect(result).toEqual("results!");
105
+ });
106
+ it("credentials are invalid", async () => {
107
+ const fetchMock = vi.fn().mockImplementation(() => {
108
+ return {
109
+ status: 401,
110
+ ok: false,
111
+ text: () => "bad results!",
112
+ };
113
+ });
114
+ const fetcher = simpleMarkupFetcher("test", fetchMock);
115
+ expect(fetcher({
116
+ path: "/test",
117
+ domain: "test.com",
118
+ apiKey: "123abc",
119
+ })).rejects.toThrowError(/Unauthorized!/);
120
+ });
121
+ it("response isn't ok", async () => {
122
+ const fetchMock = vi.fn().mockImplementation(() => {
123
+ return {
124
+ status: 500,
125
+ ok: false,
126
+ text: () => "bad results!",
127
+ };
128
+ });
129
+ const fetcher = simpleMarkupFetcher("test", fetchMock);
130
+ expect(fetcher({
131
+ path: "/test",
132
+ domain: "test.com",
133
+ apiKey: "123abc",
134
+ })).rejects.toThrowError(/request failed! Status code: 500/);
135
+ });
136
+ it("passes custom copy", async () => {
137
+ const fetchMock = vi.fn().mockImplementation(() => {
138
+ return {
139
+ status: 200,
140
+ ok: true,
141
+ text: () => "results!",
142
+ };
143
+ });
144
+ const fetcher = simpleMarkupFetcher("test", fetchMock);
145
+ const result = await fetcher({
146
+ path: null,
147
+ domain: "test.com",
148
+ apiKey: "123abc",
149
+ environment: "production",
150
+ copy: {
151
+ copy_confirmation_message: "custom confirmation message",
152
+ copy_submit_button: "custom submit button",
153
+ },
154
+ });
155
+ expect(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v3/markup?domain=test.com&path=%2F&copy_confirmation_message=custom+confirmation+message&copy_submit_button=custom+submit+button", expect.anything());
156
+ expect(result).toEqual("results!");
157
+ });
158
+ it("passes date format string", async () => {
159
+ const fetchMock = vi.fn().mockImplementation(() => {
160
+ return {
161
+ status: 200,
162
+ ok: true,
163
+ text: () => "results!",
164
+ };
165
+ });
166
+ const fetcher = simpleMarkupFetcher("test", fetchMock);
167
+ await fetcher({
168
+ path: null,
169
+ domain: "test.com",
170
+ apiKey: "123abc",
171
+ environment: "production",
172
+ dateFormat: "yyyy-MM-dd",
173
+ });
174
+ expect(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v3/markup?domain=test.com&path=%2F&date_format=yyyy-MM-dd", expect.anything());
175
+ });
176
+ it("response isn't ok", async () => {
177
+ const fetchMock = vi.fn().mockImplementation(() => {
178
+ return {
179
+ status: 500,
180
+ ok: false,
181
+ text: () => "bad results!",
182
+ };
183
+ });
184
+ const fetcher = simpleMarkupFetcher("test", fetchMock);
185
+ expect(fetcher({
186
+ path: "/test",
187
+ domain: "test.com",
188
+ apiKey: "123abc",
189
+ })).rejects.toThrowError(/request failed! Status code: 500/);
190
+ });
191
+ describe("copy overrides", () => {
192
+ it("encodes copy overrides", async () => {
193
+ const fetchMock = vi.fn().mockImplementation(() => {
194
+ return {
195
+ status: 200,
196
+ ok: true,
197
+ text: () => "results!",
198
+ };
199
+ });
200
+ const fetcher = simpleMarkupFetcher("test", fetchMock);
201
+ await fetcher({
202
+ path: "/some/path",
203
+ domain: "test.com",
204
+ apiKey: "123abc",
205
+ environment: "production",
206
+ copy: {
207
+ copy_confirmation_message: "custom confirmation message",
208
+ copy_submit_button: "custom submit button",
209
+ },
210
+ });
211
+ expect(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v3/markup?domain=test.com&path=%2Fsome%2Fpath&copy_confirmation_message=custom+confirmation+message&copy_submit_button=custom+submit+button", expect.anything());
212
+ });
213
+ });
214
+ describe("timezone validation", () => {
215
+ it("throws error when invalid timezone is provided", async () => {
216
+ const fetchImplMock = vi.fn();
217
+ const fetcher = simpleMarkupFetcher("test", fetchImplMock);
218
+ expect(fetchImplMock).not.toHaveBeenCalled();
219
+ expect(fetcher({
220
+ path: "/test",
221
+ domain: "test.com",
222
+ apiKey: "123abc",
223
+ tz: "in/valid",
224
+ environment: "production",
225
+ })).rejects.toThrowError("The timezone passed to JamComments is invalid: in/valid");
226
+ });
227
+ it("does not throw error when valid timezone is provided", async () => {
228
+ const fetchMock = vi.fn().mockImplementation(() => {
229
+ return {
230
+ status: 200,
231
+ ok: true,
232
+ text: () => "results!",
233
+ };
234
+ });
235
+ const fetcher = simpleMarkupFetcher("test", fetchMock);
236
+ const result = await fetcher({
237
+ path: "/some/path",
238
+ domain: "test.com",
239
+ apiKey: "123abc",
240
+ tz: "America/New_York",
241
+ environment: "production",
242
+ });
243
+ expect(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v3/markup?domain=test.com&path=%2Fsome%2Fpath&tz=America%2FNew_York", expect.anything());
244
+ expect(result).toEqual("results!");
245
+ });
246
+ it("trims a valid timezone", async () => {
247
+ const fetchMock = vi.fn().mockImplementation(() => {
248
+ return {
249
+ status: 200,
250
+ ok: true,
251
+ text: () => "results!",
252
+ };
253
+ });
254
+ const fetcher = simpleMarkupFetcher("test", fetchMock);
255
+ const result = await fetcher({
256
+ path: "/some/path",
257
+ domain: "test.com",
258
+ apiKey: "123abc",
259
+ tz: " America/Chicago ",
260
+ environment: "production",
261
+ });
262
+ expect(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v3/markup?domain=test.com&path=%2Fsome%2Fpath&tz=America%2FChicago", expect.anything());
263
+ expect(result).toEqual("results!");
264
+ });
265
+ });
266
+ });
@@ -1,4 +1,5 @@
1
1
  export type { CustomCopy } from "./markupFetcher";
2
+ export { simpleMarkupFetcher } from "./simpleMarkupFetcher";
2
3
  export { markupFetcher, fetchAll } from "./markupFetcher";
3
4
  export { removeFalseyValues } from "./utils";
4
5
  export { log, logError } from "./log";
@@ -19,6 +19,7 @@ export interface IFetchData {
19
19
  baseUrl?: string;
20
20
  environment?: string;
21
21
  dateFormat?: string;
22
+ cache?: boolean;
22
23
  copy?: {
23
24
  copy_confirmation_message?: string;
24
25
  copy_submit_button?: string;
@@ -49,9 +50,10 @@ interface IBatchResponse {
49
50
  total: number;
50
51
  };
51
52
  }
53
+ export declare const BASE_URL = "https://go.jamcomments.com";
52
54
  export declare function fetchAll({ tz, dateFormat, domain, apiKey, baseUrl, environment, copy, }: IBatchFetchData, platform: string, fetchImplementation?: any, batchMarkupFetcherImpl?: any, store?: Store): Promise<Map<string, string>>;
53
55
  export declare function batchMarkupFetcher(platform: string, fetchImplementation?: typeof fetch): (args: IBatchFetchData) => Promise<IBatchResponse>;
54
- export declare function fetchFreshMarkup({ tz, path, copy, domain, apiKey, dateFormat, baseUrl, environment, }: IFetchData, fetchImplementation: typeof fetch, platform: string): Promise<string>;
55
- 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>;
56
+ export declare function fetchFreshMarkup({ tz, path, copy, cache, domain, apiKey, dateFormat, baseUrl, environment, }: IFetchData, fetchImplementation: typeof fetch, platform: string): Promise<string>;
57
+ export declare function makeMarkupRequest<T extends Partial<IBatchFetchData & IFetchData>>({ tz, path, page, cache, domain, apiKey, dateFormat, copy, baseUrl, environment, }: T, baseServicePath: string, fetchImplementation: typeof fetch, platform: string): Promise<Response>;
56
58
  export declare function markupFetcher(platform: string, fetchImplementation?: typeof fetch, store?: Store): (args: IFetchData) => Promise<string>;
57
59
  export {};
@@ -0,0 +1,2 @@
1
+ import { IFetchData } from "./markupFetcher";
2
+ export declare function simpleMarkupFetcher(platform: string, fetchImplementation?: typeof fetch): (args: IFetchData) => Promise<string>;
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jam-comments/server-utilities",
3
- "version": "5.10.2",
3
+ "version": "5.12.0",
4
4
  "description": "Various JavaScript utilities for JamComments.",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -22,11 +22,11 @@
22
22
  "homepage": "https://jamcomments.com",
23
23
  "license": "GPL-2.0",
24
24
  "devDependencies": {
25
- "@types/node": "^22.9.0",
26
- "prettier": "^3.3.3",
27
- "typescript": "^5.6.3",
28
- "vite": "^5.4.11",
29
- "vitest": "^2.1.5"
25
+ "@types/node": "^22.10.1",
26
+ "prettier": "^3.4.1",
27
+ "typescript": "^5.7.2",
28
+ "vite": "^6.0.1",
29
+ "vitest": "^2.1.6"
30
30
  },
31
31
  "publishConfig": {
32
32
  "access": "public"