@hobenakicoffee/libraries 1.3.0 → 1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hobenakicoffee/libraries",
3
- "version": "1.3.0",
3
+ "version": "1.5.0",
4
4
  "type": "module",
5
5
  "types": "src/index.ts",
6
6
  "exports": {
@@ -284,9 +284,11 @@ export type Database = {
284
284
  display_name: string | null
285
285
  full_name: string | null
286
286
  id: string
287
+ is_page_active: boolean | null
287
288
  layout: Json | null
288
289
  page_slug: string
289
290
  role: Database["public"]["Enums"]["user_role"]
291
+ social_links: Json | null
290
292
  theme: Json | null
291
293
  updated_at: string | null
292
294
  username: string
@@ -301,9 +303,11 @@ export type Database = {
301
303
  display_name?: string | null
302
304
  full_name?: string | null
303
305
  id: string
306
+ is_page_active?: boolean | null
304
307
  layout?: Json | null
305
308
  page_slug: string
306
309
  role?: Database["public"]["Enums"]["user_role"]
310
+ social_links?: Json | null
307
311
  theme?: Json | null
308
312
  updated_at?: string | null
309
313
  username: string
@@ -318,9 +322,11 @@ export type Database = {
318
322
  display_name?: string | null
319
323
  full_name?: string | null
320
324
  id?: string
325
+ is_page_active?: boolean | null
321
326
  layout?: Json | null
322
327
  page_slug?: string
323
328
  role?: Database["public"]["Enums"]["user_role"]
329
+ social_links?: Json | null
324
330
  theme?: Json | null
325
331
  updated_at?: string | null
326
332
  username?: string
@@ -0,0 +1,29 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { formatNumber } from "./format-number";
3
+
4
+ function digitsFromFormatted(formatted: string) {
5
+ const digits = formatted.replace(/\D/g, "");
6
+ return Number(digits);
7
+ }
8
+
9
+ describe("formatNumber", () => {
10
+ test("formats positive numbers and rounds correctly", () => {
11
+ expect(digitsFromFormatted(formatNumber(1234.56))).toBe(1235);
12
+ });
13
+
14
+ test("formats negative numbers using absolute value", () => {
15
+ expect(digitsFromFormatted(formatNumber(-9876.5))).toBe(9877);
16
+ });
17
+
18
+ test("formats zero", () => {
19
+ expect(digitsFromFormatted(formatNumber(0))).toBe(0);
20
+ });
21
+
22
+ test("rounds small fractional numbers to 0", () => {
23
+ expect(digitsFromFormatted(formatNumber(-0.4))).toBe(0);
24
+ });
25
+
26
+ test("formats large numbers", () => {
27
+ expect(digitsFromFormatted(formatNumber(1000000))).toBe(1000000);
28
+ });
29
+ });
@@ -0,0 +1,5 @@
1
+ export function formatNumber(value: number) {
2
+ return new Intl.NumberFormat(undefined, {
3
+ maximumFractionDigits: 0,
4
+ }).format(Math.abs(value));
5
+ }
@@ -0,0 +1,63 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { getSocialLink } from "./get-social-link";
3
+ import { SupporterPlatforms } from "../constants";
4
+
5
+ describe("getSocialLink", () => {
6
+ test("returns null when username or platform is missing", () => {
7
+ expect(getSocialLink(undefined, SupporterPlatforms.FACEBOOK)).toBeNull();
8
+ expect(getSocialLink("alice", undefined)).toBeNull();
9
+ expect(getSocialLink()).toBeNull();
10
+ });
11
+
12
+ test("returns correct Facebook URL", () => {
13
+ expect(getSocialLink("alice", SupporterPlatforms.FACEBOOK)).toBe(
14
+ "https://facebook.com/alice",
15
+ );
16
+ });
17
+
18
+ test("returns correct Instagram URL with spaces", () => {
19
+ expect(getSocialLink(" john doe ", SupporterPlatforms.INSTAGRAM)).toBe(
20
+ "https://instagram.com/johndoe",
21
+ );
22
+ });
23
+
24
+ test("returns correct TikTok URL", () => {
25
+ expect(getSocialLink("user123", SupporterPlatforms.TIKTOK)).toBe(
26
+ "https://tiktok.com/@user123",
27
+ );
28
+ });
29
+
30
+ test("returns correct YouTube URL", () => {
31
+ expect(getSocialLink("Jane", SupporterPlatforms.YOUTUBE)).toBe(
32
+ "https://youtube.com/Jane",
33
+ );
34
+ });
35
+
36
+ test("returns correct X (Twitter) URL", () => {
37
+ expect(getSocialLink("bob", SupporterPlatforms.X)).toBe(
38
+ "https://x.com/bob",
39
+ );
40
+ });
41
+
42
+ test("returns correct LinkedIn URL", () => {
43
+ expect(getSocialLink("johnsmith", SupporterPlatforms.LINKEDIN)).toBe(
44
+ "https://linkedin.com/in/johnsmith",
45
+ );
46
+ });
47
+
48
+ test("returns correct GitHub URL", () => {
49
+ expect(getSocialLink("octocat", SupporterPlatforms.GITHUB)).toBe(
50
+ "https://github.com/octocat",
51
+ );
52
+ });
53
+
54
+ test("returns null for unsupported platform", () => {
55
+ expect(getSocialLink("alice", "MYSPACE" as any)).toBeNull();
56
+ });
57
+
58
+ test("sanitizes username with special characters", () => {
59
+ expect(getSocialLink("user name!@#", SupporterPlatforms.FACEBOOK)).toBe(
60
+ "https://facebook.com/username!%40%23",
61
+ );
62
+ });
63
+ });
@@ -0,0 +1,29 @@
1
+ import { SupporterPlatforms, type SupporterPlatform } from "../constants";
2
+
3
+ export function getSocialLink(username?: string, platform?: SupporterPlatform) {
4
+ console.log("getSocialLink called with:", { username, platform });
5
+ if (!username || !platform) return null;
6
+
7
+ const sanitizedUsername = encodeURIComponent(
8
+ username.trim().replace(/\s+/g, ""),
9
+ );
10
+
11
+ switch (platform) {
12
+ case SupporterPlatforms.FACEBOOK:
13
+ return `https://facebook.com/${sanitizedUsername}`;
14
+ case SupporterPlatforms.INSTAGRAM:
15
+ return `https://instagram.com/${sanitizedUsername}`;
16
+ case SupporterPlatforms.TIKTOK:
17
+ return `https://tiktok.com/@${sanitizedUsername}`;
18
+ case SupporterPlatforms.YOUTUBE:
19
+ return `https://youtube.com/${sanitizedUsername}`;
20
+ case SupporterPlatforms.X:
21
+ return `https://x.com/${sanitizedUsername}`;
22
+ case SupporterPlatforms.LINKEDIN:
23
+ return `https://linkedin.com/in/${sanitizedUsername}`;
24
+ case SupporterPlatforms.GITHUB:
25
+ return `https://github.com/${sanitizedUsername}`;
26
+ default:
27
+ return null;
28
+ }
29
+ }
@@ -0,0 +1,34 @@
1
+ import { getInitials } from "./get-user-name-initials";
2
+ import { describe, expect, test } from "bun:test";
3
+
4
+ describe("getInitials", () => {
5
+ test("returns initials for a full name", () => {
6
+ expect(getInitials("John Doe")).toBe("JD");
7
+ expect(getInitials("Jane Ann Smith")).toBe("JS");
8
+ expect(getInitials("Alice Bob Carol")).toBe("AC");
9
+ });
10
+
11
+ test("returns single initial for single name", () => {
12
+ expect(getInitials("John")).toBe("J");
13
+ expect(getInitials("A")).toBe("A");
14
+ });
15
+
16
+ test("handles extra spaces", () => {
17
+ expect(getInitials(" John Doe ")).toBe("JD");
18
+ expect(getInitials(" Alice ")).toBe("A");
19
+ expect(getInitials(" Alice Bob Carol ")).toBe("AC");
20
+ });
21
+
22
+ test("returns ? for empty or undefined", () => {
23
+ expect(getInitials("")).toBe("?");
24
+ expect(getInitials(" ")).toBe("?");
25
+ expect(getInitials(undefined)).toBe("?");
26
+ expect(getInitials(null)).toBe("?");
27
+ });
28
+
29
+ test("handles non-ASCII and special characters", () => {
30
+ expect(getInitials("Élodie Durand")).toBe("ÉD");
31
+ expect(getInitials("李 小龙")).toBe("李小");
32
+ expect(getInitials("O’Connor")).toBe("O");
33
+ });
34
+ });
@@ -0,0 +1,8 @@
1
+ const regexPattern = /\s+/;
2
+
3
+ export function getInitials(name?: string | null) {
4
+ const parts = name?.trim().split(regexPattern).filter(Boolean) ?? [];
5
+ const first = parts[0]?.[0] ?? "?";
6
+ const last = parts.length > 1 ? (parts.at(-1)?.[0] ?? "") : "";
7
+ return `${first}${last}`.toUpperCase();
8
+ }
@@ -11,3 +11,6 @@ export * from "./post-to-x";
11
11
  export * from "./qr-svg-utils";
12
12
  export * from "./validate-phone-number";
13
13
  export * from "./to-human-readable";
14
+ export * from "./get-social-link";
15
+ export * from "./format-number";
16
+ export * from "./get-user-name-initials";