@jam-comments/server-utilities 3.0.1 → 3.2.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.
@@ -1,12 +1,20 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.markupFetcher = void 0;
4
+ const utils_1 = require("./utils");
4
5
  const markupFetcher = (platform, fetchImplementation = fetch) => {
5
- return async ({ path, domain, apiKey, baseUrl = "https://go.jamcomments.com", environment = "production", }) => {
6
+ return async ({ tz = undefined, path, domain, apiKey, baseUrl = "https://go.jamcomments.com", environment = (0, utils_1.getEnvironment)(), }) => {
7
+ const trimmedTimezone = tz?.trim();
8
+ if (trimmedTimezone && !(0, utils_1.isValidTimezone)(trimmedTimezone)) {
9
+ throw new Error(`The timezone passed to JamComments is invalid: ${trimmedTimezone}`);
10
+ }
6
11
  const params = new URLSearchParams({
7
12
  path: path || "/",
8
13
  domain,
9
14
  });
15
+ if (trimmedTimezone) {
16
+ params.set("tz", trimmedTimezone);
17
+ }
10
18
  if (environment !== "production") {
11
19
  params.set("stub", "true");
12
20
  }
@@ -16,6 +16,7 @@ const markupFetcher_1 = require("./markupFetcher");
16
16
  path: "/test",
17
17
  domain: "test.com",
18
18
  apiKey: "123abc",
19
+ environment: "production",
19
20
  });
20
21
  (0, vitest_1.expect)(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v2/markup?path=%2Ftest&domain=test.com", vitest_1.expect.objectContaining({
21
22
  headers: vitest_1.expect.objectContaining({
@@ -59,6 +60,26 @@ const markupFetcher_1 = require("./markupFetcher");
59
60
  domain: "test.com",
60
61
  apiKey: "123abc",
61
62
  baseUrl: "http://ur-mom.com",
63
+ environment: "production",
64
+ });
65
+ (0, vitest_1.expect)(fetchMock).toHaveBeenCalledWith("http://ur-mom.com/api/v2/markup?path=%2Ftest&domain=test.com", vitest_1.expect.anything());
66
+ (0, vitest_1.expect)(result).toEqual("results!");
67
+ });
68
+ (0, vitest_1.it)("respects production!!!", async () => {
69
+ const fetchMock = vitest_1.vi.fn().mockImplementation(() => {
70
+ return {
71
+ status: 200,
72
+ ok: true,
73
+ text: () => "results!",
74
+ };
75
+ });
76
+ const fetcher = (0, markupFetcher_1.markupFetcher)("test", fetchMock);
77
+ const result = await fetcher({
78
+ path: "/test",
79
+ domain: "test.com",
80
+ apiKey: "123abc",
81
+ baseUrl: "http://ur-mom.com",
82
+ environment: "production",
62
83
  });
63
84
  (0, vitest_1.expect)(fetchMock).toHaveBeenCalledWith("http://ur-mom.com/api/v2/markup?path=%2Ftest&domain=test.com", vitest_1.expect.anything());
64
85
  (0, vitest_1.expect)(result).toEqual("results!");
@@ -75,6 +96,8 @@ const markupFetcher_1 = require("./markupFetcher");
75
96
  const result = await fetcher({
76
97
  path: null,
77
98
  domain: "test.com",
99
+ apiKey: "123abc",
100
+ environment: "production",
78
101
  });
79
102
  (0, vitest_1.expect)(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v2/markup?path=%2F&domain=test.com", vitest_1.expect.anything());
80
103
  (0, vitest_1.expect)(result).toEqual("results!");
@@ -109,4 +132,56 @@ const markupFetcher_1 = require("./markupFetcher");
109
132
  apiKey: "123abc",
110
133
  })).rejects.toThrowError(/request failed! Status code: 500/);
111
134
  });
135
+ (0, vitest_1.describe)("timezone validation", () => {
136
+ (0, vitest_1.it)("throws error when invalid timezone is provided", async () => {
137
+ const fetchMock = vitest_1.vi.fn();
138
+ const fetcher = (0, markupFetcher_1.markupFetcher)("test", fetchMock);
139
+ (0, vitest_1.expect)(fetchMock).not.toHaveBeenCalled();
140
+ (0, vitest_1.expect)(fetcher({
141
+ path: "/test",
142
+ domain: "test.com",
143
+ apiKey: "123abc",
144
+ tz: "in/valid",
145
+ environment: "production",
146
+ })).rejects.toThrowError("The timezone passed to JamComments is invalid: in/valid");
147
+ });
148
+ (0, vitest_1.it)("does not throw error when valid timezone is provided", async () => {
149
+ const fetchMock = vitest_1.vi.fn().mockImplementation(() => {
150
+ return {
151
+ status: 200,
152
+ ok: true,
153
+ text: () => "results!",
154
+ };
155
+ });
156
+ const fetcher = (0, markupFetcher_1.markupFetcher)("test", fetchMock);
157
+ const result = await fetcher({
158
+ path: null,
159
+ domain: "test.com",
160
+ apiKey: "123abc",
161
+ tz: "America/New_York",
162
+ environment: "production",
163
+ });
164
+ (0, vitest_1.expect)(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v2/markup?path=%2F&domain=test.com&tz=America%2FNew_York", vitest_1.expect.anything());
165
+ (0, vitest_1.expect)(result).toEqual("results!");
166
+ });
167
+ (0, vitest_1.it)("trims a valid timezone", async () => {
168
+ const fetchMock = vitest_1.vi.fn().mockImplementation(() => {
169
+ return {
170
+ status: 200,
171
+ ok: true,
172
+ text: () => "results!",
173
+ };
174
+ });
175
+ const fetcher = (0, markupFetcher_1.markupFetcher)("test", fetchMock);
176
+ const result = await fetcher({
177
+ path: null,
178
+ domain: "test.com",
179
+ apiKey: "123abc",
180
+ tz: " America/Chicago ",
181
+ environment: "production",
182
+ });
183
+ (0, vitest_1.expect)(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v2/markup?path=%2F&domain=test.com&tz=America%2FChicago", vitest_1.expect.anything());
184
+ (0, vitest_1.expect)(result).toEqual("results!");
185
+ });
186
+ });
112
187
  });
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getEnvironment = exports.isValidTimezone = void 0;
4
+ function isValidTimezone(tz) {
5
+ try {
6
+ Intl.DateTimeFormat(undefined, { timeZone: tz });
7
+ return true;
8
+ }
9
+ catch (ex) {
10
+ return false;
11
+ }
12
+ }
13
+ exports.isValidTimezone = isValidTimezone;
14
+ function getEnvironment() {
15
+ if (typeof process === "undefined") {
16
+ return "production";
17
+ }
18
+ return process.env?.NODE_ENV || "development";
19
+ }
20
+ exports.getEnvironment = getEnvironment;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const utils_1 = require("./utils");
5
+ const env = process.env;
6
+ (0, vitest_1.beforeEach)(() => {
7
+ vitest_1.vi.resetModules();
8
+ process.env = { ...env };
9
+ });
10
+ (0, vitest_1.afterEach)(() => {
11
+ process.env = env;
12
+ });
13
+ (0, vitest_1.describe)("getEnvironment()", () => {
14
+ (0, vitest_1.it)("returns environment", () => {
15
+ (0, vitest_1.expect)((0, utils_1.getEnvironment)()).toEqual("test");
16
+ });
17
+ (0, vitest_1.it)("falls back to development", () => {
18
+ process.env.NODE_ENV = undefined;
19
+ (0, vitest_1.expect)((0, utils_1.getEnvironment)()).toEqual("development");
20
+ });
21
+ (0, vitest_1.it)("returns production environment", () => {
22
+ process.env.NODE_ENV = "production";
23
+ (0, vitest_1.expect)((0, utils_1.getEnvironment)()).toEqual("production");
24
+ });
25
+ });
@@ -1,9 +1,17 @@
1
+ import { getEnvironment, isValidTimezone } from "./utils";
1
2
  export const markupFetcher = (platform, fetchImplementation = fetch) => {
2
- return async ({ path, domain, apiKey, baseUrl = "https://go.jamcomments.com", environment = "production", }) => {
3
+ return async ({ tz = undefined, path, domain, apiKey, baseUrl = "https://go.jamcomments.com", environment = getEnvironment(), }) => {
4
+ const trimmedTimezone = tz?.trim();
5
+ if (trimmedTimezone && !isValidTimezone(trimmedTimezone)) {
6
+ throw new Error(`The timezone passed to JamComments is invalid: ${trimmedTimezone}`);
7
+ }
3
8
  const params = new URLSearchParams({
4
9
  path: path || "/",
5
10
  domain,
6
11
  });
12
+ if (trimmedTimezone) {
13
+ params.set("tz", trimmedTimezone);
14
+ }
7
15
  if (environment !== "production") {
8
16
  params.set("stub", "true");
9
17
  }
@@ -14,6 +14,7 @@ describe("markupFetcher", () => {
14
14
  path: "/test",
15
15
  domain: "test.com",
16
16
  apiKey: "123abc",
17
+ environment: "production",
17
18
  });
18
19
  expect(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v2/markup?path=%2Ftest&domain=test.com", expect.objectContaining({
19
20
  headers: expect.objectContaining({
@@ -57,6 +58,26 @@ describe("markupFetcher", () => {
57
58
  domain: "test.com",
58
59
  apiKey: "123abc",
59
60
  baseUrl: "http://ur-mom.com",
61
+ environment: "production",
62
+ });
63
+ expect(fetchMock).toHaveBeenCalledWith("http://ur-mom.com/api/v2/markup?path=%2Ftest&domain=test.com", expect.anything());
64
+ expect(result).toEqual("results!");
65
+ });
66
+ it("respects production!!!", async () => {
67
+ const fetchMock = vi.fn().mockImplementation(() => {
68
+ return {
69
+ status: 200,
70
+ ok: true,
71
+ text: () => "results!",
72
+ };
73
+ });
74
+ const fetcher = markupFetcher("test", fetchMock);
75
+ const result = await fetcher({
76
+ path: "/test",
77
+ domain: "test.com",
78
+ apiKey: "123abc",
79
+ baseUrl: "http://ur-mom.com",
80
+ environment: "production",
60
81
  });
61
82
  expect(fetchMock).toHaveBeenCalledWith("http://ur-mom.com/api/v2/markup?path=%2Ftest&domain=test.com", expect.anything());
62
83
  expect(result).toEqual("results!");
@@ -73,6 +94,8 @@ describe("markupFetcher", () => {
73
94
  const result = await fetcher({
74
95
  path: null,
75
96
  domain: "test.com",
97
+ apiKey: "123abc",
98
+ environment: "production",
76
99
  });
77
100
  expect(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v2/markup?path=%2F&domain=test.com", expect.anything());
78
101
  expect(result).toEqual("results!");
@@ -107,4 +130,56 @@ describe("markupFetcher", () => {
107
130
  apiKey: "123abc",
108
131
  })).rejects.toThrowError(/request failed! Status code: 500/);
109
132
  });
133
+ describe("timezone validation", () => {
134
+ it("throws error when invalid timezone is provided", async () => {
135
+ const fetchMock = vi.fn();
136
+ const fetcher = markupFetcher("test", fetchMock);
137
+ expect(fetchMock).not.toHaveBeenCalled();
138
+ expect(fetcher({
139
+ path: "/test",
140
+ domain: "test.com",
141
+ apiKey: "123abc",
142
+ tz: "in/valid",
143
+ environment: "production",
144
+ })).rejects.toThrowError("The timezone passed to JamComments is invalid: in/valid");
145
+ });
146
+ it("does not throw error when valid timezone is provided", async () => {
147
+ const fetchMock = vi.fn().mockImplementation(() => {
148
+ return {
149
+ status: 200,
150
+ ok: true,
151
+ text: () => "results!",
152
+ };
153
+ });
154
+ const fetcher = markupFetcher("test", fetchMock);
155
+ const result = await fetcher({
156
+ path: null,
157
+ domain: "test.com",
158
+ apiKey: "123abc",
159
+ tz: "America/New_York",
160
+ environment: "production",
161
+ });
162
+ expect(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v2/markup?path=%2F&domain=test.com&tz=America%2FNew_York", expect.anything());
163
+ expect(result).toEqual("results!");
164
+ });
165
+ it("trims a valid timezone", async () => {
166
+ const fetchMock = vi.fn().mockImplementation(() => {
167
+ return {
168
+ status: 200,
169
+ ok: true,
170
+ text: () => "results!",
171
+ };
172
+ });
173
+ const fetcher = markupFetcher("test", fetchMock);
174
+ const result = await fetcher({
175
+ path: null,
176
+ domain: "test.com",
177
+ apiKey: "123abc",
178
+ tz: " America/Chicago ",
179
+ environment: "production",
180
+ });
181
+ expect(fetchMock).toHaveBeenCalledWith("https://go.jamcomments.com/api/v2/markup?path=%2F&domain=test.com&tz=America%2FChicago", expect.anything());
182
+ expect(result).toEqual("results!");
183
+ });
184
+ });
110
185
  });
@@ -0,0 +1,15 @@
1
+ export function isValidTimezone(tz) {
2
+ try {
3
+ Intl.DateTimeFormat(undefined, { timeZone: tz });
4
+ return true;
5
+ }
6
+ catch (ex) {
7
+ return false;
8
+ }
9
+ }
10
+ export function getEnvironment() {
11
+ if (typeof process === "undefined") {
12
+ return "production";
13
+ }
14
+ return process.env?.NODE_ENV || "development";
15
+ }
@@ -0,0 +1,23 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
+ import { getEnvironment } from "./utils";
3
+ const env = process.env;
4
+ beforeEach(() => {
5
+ vi.resetModules();
6
+ process.env = { ...env };
7
+ });
8
+ afterEach(() => {
9
+ process.env = env;
10
+ });
11
+ describe("getEnvironment()", () => {
12
+ it("returns environment", () => {
13
+ expect(getEnvironment()).toEqual("test");
14
+ });
15
+ it("falls back to development", () => {
16
+ process.env.NODE_ENV = undefined;
17
+ expect(getEnvironment()).toEqual("development");
18
+ });
19
+ it("returns production environment", () => {
20
+ process.env.NODE_ENV = "production";
21
+ expect(getEnvironment()).toEqual("production");
22
+ });
23
+ });
@@ -1 +1,10 @@
1
- export declare const markupFetcher: (platform: string, fetchImplementation?: typeof fetch) => Function;
1
+ interface IFetchData {
2
+ path: string;
3
+ domain: string;
4
+ apiKey: string;
5
+ tz?: string;
6
+ baseUrl?: string;
7
+ environment?: string;
8
+ }
9
+ export declare const markupFetcher: (platform: string, fetchImplementation?: typeof fetch) => (args: IFetchData) => Promise<string>;
10
+ export {};
@@ -0,0 +1,2 @@
1
+ export declare function isValidTimezone(tz: string): boolean;
2
+ export declare function getEnvironment(): 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": "3.0.1",
3
+ "version": "3.2.0",
4
4
  "description": "Various JavaScript utilities for JamComments.",
5
5
  "main": "dist/cjs/index.js",
6
6
  "types": "dist/types/index.d.ts",
@@ -21,11 +21,11 @@
21
21
  "homepage": "https://jamcomments.com",
22
22
  "license": "GPL-2.0",
23
23
  "devDependencies": {
24
- "@types/node": "^18.15.8",
25
- "prettier": "^2.8.7",
26
- "typescript": "^5.0.2",
27
- "vite": "^4.2.1",
28
- "vitest": "^0.29.7"
24
+ "@types/node": "^20.2.5",
25
+ "prettier": "^2.8.8",
26
+ "typescript": "^5.0.4",
27
+ "vite": "^4.3.9",
28
+ "vitest": "^0.31.1"
29
29
  },
30
30
  "publishConfig": {
31
31
  "access": "public"