@olenbetong/appframe-core 2.11.0 → 2.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/esm/af.common.js +123 -143
  2. package/dist/esm/af.common.legacy.js +129 -149
  3. package/dist/esm/af.common.legacy.min.js +1 -1
  4. package/dist/esm/af.common.legacy.min.js.map +4 -4
  5. package/dist/esm/af.common.min.js +2 -2
  6. package/dist/esm/af.common.min.js.map +4 -4
  7. package/dist/iife/af.common.js +123 -143
  8. package/dist/iife/af.common.legacy.js +129 -149
  9. package/dist/iife/af.common.legacy.min.js +1 -1
  10. package/dist/iife/af.common.legacy.min.js.map +4 -4
  11. package/dist/iife/af.common.min.js +2 -2
  12. package/dist/iife/af.common.min.js.map +4 -4
  13. package/es/SessionHandler.js +1 -3
  14. package/es/UserSession.js +33 -29
  15. package/es/date.js +3 -3
  16. package/es/date.test.d.ts +1 -0
  17. package/es/date.test.js +23 -0
  18. package/es/errorHandler.d.ts +1 -0
  19. package/es/errorHandler.js +5 -21
  20. package/es/expose.d.ts +1 -1
  21. package/es/expose.js +1 -2
  22. package/es/expose.test.d.ts +10 -0
  23. package/es/expose.test.js +36 -0
  24. package/es/getLocalizedString.js +1 -2
  25. package/es/getUserImage.test.d.ts +1 -0
  26. package/es/getUserImage.test.js +30 -0
  27. package/es/index.d.ts +0 -1
  28. package/es/index.js +1 -2
  29. package/es/invariant.d.ts +8 -0
  30. package/es/invariant.js +8 -0
  31. package/es/invariant.test.d.ts +1 -0
  32. package/es/invariant.test.js +19 -0
  33. package/es/localStorage.js +1 -3
  34. package/es/parseFunc.js +1 -1
  35. package/es/parseFunc.test.d.ts +1 -0
  36. package/es/parseFunc.test.js +14 -0
  37. package/package.json +5 -3
  38. package/src/date.test.ts +27 -0
  39. package/src/date.ts +3 -3
  40. package/src/errorHandler.ts +6 -21
  41. package/src/expose.test.ts +59 -0
  42. package/src/expose.ts +2 -3
  43. package/src/getLocalizedString.ts +1 -3
  44. package/src/getUserImage.test.ts +50 -0
  45. package/src/index.ts +0 -1
  46. package/src/invariant.test.ts +23 -0
  47. package/src/invariant.ts +8 -0
  48. package/src/parseFunc.test.ts +17 -0
  49. package/src/parseFunc.ts +1 -1
  50. package/es/has.d.ts +0 -1
  51. package/es/has.js +0 -3
  52. package/src/has.ts +0 -3
@@ -0,0 +1,19 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { invariant } from "./invariant";
3
+ describe("invariant", () => {
4
+ test("should throw error when condition is false", () => {
5
+ expect(() => {
6
+ invariant(false, "Test message");
7
+ }).toThrowError("Test message");
8
+ });
9
+ test("should throw error when condition is false and message is a function", () => {
10
+ expect(() => {
11
+ invariant(false, () => "Test message");
12
+ }).toThrowError("Test message");
13
+ });
14
+ test("should not throw error when condition is true", () => {
15
+ expect(() => {
16
+ invariant(true, "Test message");
17
+ }).not.toThrowError();
18
+ });
19
+ });
@@ -2,9 +2,7 @@ function getLocalKey(key) {
2
2
  return [af?.article?.id || "", "common", key].join(".");
3
3
  }
4
4
  class LocalStorage {
5
- constructor() {
6
- this.isPersisted = () => true;
7
- }
5
+ isPersisted = () => true;
8
6
  getLocalStorageKey(key, global) {
9
7
  return global ? ["common", key].join(".") : getLocalKey(key);
10
8
  }
package/es/parseFunc.js CHANGED
@@ -3,5 +3,5 @@ const funcRegex = /^function(?:\s+([a-zA-Z$_][a-zA-Z0-9$_]*))?\s*\(((?:(?:\s*[a-
3
3
  export function parseFunc(func) {
4
4
  var match = func.toString().match(funcRegex);
5
5
  invariant(match, "Unable to parse function!");
6
- return { name: match[1], args: match[2].split(","), body: match[3] };
6
+ return { name: func.name ?? match[1], args: match[2].split(",").map((a) => a.trim()), body: match[3] };
7
7
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,14 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { parseFunc } from "./parseFunc";
3
+ function testFunction(arg1, arg2) {
4
+ console.log(arg1, arg2);
5
+ }
6
+ describe("parseFunc", () => {
7
+ test("should parse function", () => {
8
+ expect(parseFunc(testFunction)).toEqual({
9
+ name: "testFunction",
10
+ args: ["arg1", "arg2"],
11
+ body: "\n console.log(arg1, arg2);\n",
12
+ });
13
+ });
14
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@olenbetong/appframe-core",
3
- "version": "2.11.0",
3
+ "version": "2.11.2",
4
4
  "description": "Javascript libraries to utilize the Appframe framework",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -14,7 +14,7 @@
14
14
  },
15
15
  "types": "./es/index.d.ts",
16
16
  "scripts": {
17
- "prepack": "pnpm run build",
17
+ "prepack": "bun test && pnpm run build",
18
18
  "build": "pnpm run build:esbuild && pnpm run build:tsc",
19
19
  "build:esbuild": "node --loader ts-node/esm.mjs ../../shared/esbuild.ts",
20
20
  "build:tsc": " rm -rf ./es && tsc && node ./scripts/replace-version.js"
@@ -43,10 +43,12 @@
43
43
  ]
44
44
  },
45
45
  "dependencies": {
46
+ "@happy-dom/global-registrator": "^14.12.3",
46
47
  "mitt": "^3.0.1"
47
48
  },
48
49
  "devDependencies": {
50
+ "@types/bun": "^1.1.5",
49
51
  "chalk": "^5.3.0"
50
52
  },
51
- "gitHead": "8b9f374849381e92b3cde78cbba9a96fde0816ca"
53
+ "gitHead": "a3bcfef01480d5761a4359316facf35f7e739ca0"
52
54
  }
@@ -0,0 +1,27 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import { toLocalDateTime, toLocalISODate, toLocalISODateTime } from "./date.js";
4
+
5
+ describe("date", () => {
6
+ test("toLocalISODate", () => {
7
+ expect(toLocalISODate(new Date("2020-01-01T12:00:00Z"))).toBe("2020-01-01");
8
+ expect(toLocalISODate(new Date("2020-01-01T23:00:00Z"))).toBe("2020-01-01");
9
+ expect(toLocalISODate(new Date("2020-01-01T01:00:00Z"))).toBe("2020-01-01");
10
+ expect(toLocalISODate(null)).toBe(null);
11
+ });
12
+
13
+ test("toLocalISODateTime", () => {
14
+ expect(toLocalISODateTime(new Date("2020-01-01T12:00:00.001Z"))).toBe("2020-01-01T12:00:00.001");
15
+ expect(toLocalISODateTime(new Date("2020-01-01T23:00:00.001Z"))).toBe("2020-01-01T23:00:00.001");
16
+ expect(toLocalISODateTime(new Date("2020-01-01T01:00:00.001Z"))).toBe("2020-01-01T01:00:00.001");
17
+ expect(toLocalISODateTime(null)).toBe(null);
18
+ });
19
+
20
+ test("toLocalDateTime", () => {
21
+ expect(toLocalDateTime(new Date("2020-01-01T12:00:00.001Z"))).toBe("2020-01-01T12:00");
22
+ expect(toLocalDateTime(new Date("2020-01-01T23:00:00.001Z"))).toBe("2020-01-01T23:00");
23
+ expect(toLocalDateTime(new Date("2020-01-01T01:00:00.001Z"))).toBe("2020-01-01T01:00");
24
+ expect(toLocalDateTime(new Date("2020-01-01T12:00:00Z"))).toBe("2020-01-01T12:00");
25
+ expect(toLocalDateTime(null)).toBe("");
26
+ });
27
+ });
package/src/date.ts CHANGED
@@ -4,8 +4,8 @@ export function toLocalISODate(date: Date | null): string | null {
4
4
  return date ? toLocalISODateTime(date).substring(0, 10) : null;
5
5
  }
6
6
 
7
- function pad(num: number) {
8
- return String(num).padStart(2, "0");
7
+ function pad(num: number, digits: number = 2) {
8
+ return String(num).padStart(digits, "0");
9
9
  }
10
10
 
11
11
  /**
@@ -20,7 +20,7 @@ export function toLocalISODateTime(date: Date | null): string | null {
20
20
  return date
21
21
  ? `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(
22
22
  date.getMinutes(),
23
- )}:${pad(date.getSeconds())}.${pad(date.getMilliseconds())}`
23
+ )}:${pad(date.getSeconds())}.${pad(date.getMilliseconds(), 3)}`
24
24
  : null;
25
25
  }
26
26
 
@@ -1,26 +1,11 @@
1
+ import { logError } from "./log.js";
2
+
1
3
  if (process.env.NODE_ENV === "production") {
2
4
  globalThis.window?.addEventListener("error", (event) => {
3
- try {
4
- // Try to avoid error-logging-loop
5
- const data = {
6
- error: event.error?.message ?? event.message ?? null,
7
- file: event.filename,
8
- line: event.lineno ?? 0,
9
- column: event.colno ?? 0,
10
- stack: event.error?.stack ?? null,
11
- };
12
-
13
- fetch("/data/Logger/LogError", {
14
- body: JSON.stringify(data),
15
- headers: {
16
- Accept: "application/json",
17
- "Content-Type": "application/json; charset=utf-8",
18
- "X-Requested-With": "XMLHttpRequest",
19
- },
20
- method: "POST",
21
- });
22
- } catch (ex) {
23
- // ignore
5
+ if (typeof event === "object" && "error" in event) {
6
+ logError(event.error);
7
+ } else if (typeof event === "object" && "message" in event) {
8
+ logError(event);
24
9
  }
25
10
  });
26
11
  }
@@ -0,0 +1,59 @@
1
+ import { GlobalRegistrator } from "@happy-dom/global-registrator";
2
+
3
+ import { describe, expect, test } from "bun:test";
4
+
5
+ import { expose } from "./expose.js";
6
+
7
+ GlobalRegistrator.register();
8
+
9
+ declare global {
10
+ var test: {
11
+ value?: string;
12
+ func: () => string;
13
+ nested: {
14
+ func: () => string;
15
+ };
16
+ };
17
+ }
18
+
19
+ describe("expose", () => {
20
+ test("should expose function to global scope", () => {
21
+ function func() {
22
+ return "test";
23
+ }
24
+ expose("test", func);
25
+
26
+ expect(globalThis.test.func).toBe(func);
27
+ });
28
+
29
+ test("should expose function to global scope with nested name", () => {
30
+ function func() {
31
+ return "test";
32
+ }
33
+ expose("test.nested", func);
34
+
35
+ expect(globalThis.test.nested.func).toBe(func);
36
+ });
37
+
38
+ test("should not overwrite existing without overwrite set to true", () => {
39
+ let value1 = "test1";
40
+ let value2 = "test2";
41
+
42
+ expose("test.value", value1);
43
+ expect(globalThis.test.value).toBe(value1);
44
+
45
+ expose("test.value", value2);
46
+ expect(globalThis.test.value).not.toBe(value2);
47
+ });
48
+
49
+ test("should overwrite existing with overwrite set to true", () => {
50
+ let value1 = "test1";
51
+ let value2 = "test2";
52
+
53
+ expose("test.value", value1);
54
+ expect(globalThis.test.value).toBe(value1);
55
+
56
+ expose("test.value", value2, { overwrite: true });
57
+ expect(globalThis.test.value).toBe(value2);
58
+ });
59
+ });
package/src/expose.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { has } from "./has.js";
2
1
  import { invariant } from "./invariant.js";
3
2
  import { parseFunc } from "./parseFunc.js";
4
3
  import { requireNamespace } from "./requireNamespace.js";
@@ -17,7 +16,7 @@ export type ExposeOptions = {
17
16
  */
18
17
  export function expose(
19
18
  name: object | string,
20
- value: object | Function | Function[],
19
+ value: object | Function | Function[] | string | number,
21
20
  options: ExposeOptions = {},
22
21
  ): void {
23
22
  if (Array.isArray(value)) {
@@ -53,7 +52,7 @@ export function expose(
53
52
  invariant(false, "Invalid typeof parameter 'name', or unable to parse pValue!");
54
53
  }
55
54
 
56
- if (has(namespace, keyName) && options?.overwrite !== true) {
55
+ if (Object.hasOwn(namespace, keyName) && options?.overwrite !== true) {
57
56
  // If class is already defined, warn or show an alert
58
57
  console.warn([name, keyName].join(".") + " is already defined!");
59
58
  } else {
@@ -1,5 +1,3 @@
1
- import { has } from "./has.js";
2
-
3
1
  async function fetchLocalizedString(text: string) {
4
2
  try {
5
3
  let response = await fetch(`/api/user/localize/new/${af.article.id}`, {
@@ -45,7 +43,7 @@ export function getLocalizedString(
45
43
  }
46
44
 
47
45
  if (globalThis.af?.article?.i18n !== undefined) {
48
- if (!has(af.article.i18n, string)) {
46
+ if (!Object.hasOwn(af.article.i18n, string)) {
49
47
  af.article.i18n[string] = string;
50
48
 
51
49
  let promise = fetchLocalizedString(string).then((text) => {
@@ -0,0 +1,50 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import { getUserImage } from "./getUserImage";
4
+
5
+ describe("getUserImage", () => {
6
+ test("should return empty string when primKey is null", () => {
7
+ expect(getUserImage(null, "login", "hash")).toEqual("");
8
+ });
9
+
10
+ test("should return empty string when hash is null", () => {
11
+ expect(getUserImage("primKey", "login", null)).toEqual("");
12
+ });
13
+
14
+ test("should return empty string when primKey and hash are null", () => {
15
+ expect(getUserImage(null, "login", null)).toEqual("");
16
+ });
17
+
18
+ test("should return empty string when primKey and hash are not provided", () => {
19
+ expect(getUserImage(null, "login", null)).toEqual("");
20
+ });
21
+
22
+ test("should return empty string when primKey and hash are not provided", () => {
23
+ expect(getUserImage(null, "login", null)).toEqual("");
24
+ });
25
+
26
+ test("should return empty string when primKey and hash are not provided", () => {
27
+ expect(getUserImage(null, "login", null)).toEqual("");
28
+ });
29
+
30
+ test("should return valid image path when all values are provided", () => {
31
+ expect(getUserImage("primKey", "login", "hash")).toEqual(
32
+ "/api/data/blob/EmployeesLookup/primKey/Image/login.hash.jpg?width=64",
33
+ );
34
+ expect(getUserImage("primKey", "login", "hash", "xs")).toEqual(
35
+ "/api/data/blob/EmployeesLookup/primKey/Image/login.hash.jpg?width=64",
36
+ );
37
+ expect(getUserImage("primKey", "login", "hash", "sm")).toEqual(
38
+ "/api/data/blob/EmployeesLookup/primKey/Image/login.hash.jpg?width=128",
39
+ );
40
+ expect(getUserImage("primKey", "login", "hash", "md")).toEqual(
41
+ "/api/data/blob/EmployeesLookup/primKey/Image/login.hash.jpg?width=256",
42
+ );
43
+ expect(getUserImage("primKey", "login", "hash", "lg")).toEqual(
44
+ "/api/data/blob/EmployeesLookup/primKey/Image/login.hash.jpg?width=512",
45
+ );
46
+ expect(getUserImage("primKey", "login", "hash", "xl")).toEqual(
47
+ "/api/data/blob/EmployeesLookup/primKey/Image/login.hash.jpg",
48
+ );
49
+ });
50
+ });
package/src/index.ts CHANGED
@@ -16,7 +16,6 @@ export { expose } from "./expose.js";
16
16
  export { getUserImage } from "./getUserImage.js";
17
17
  export type { getUserImageOptions } from "./getUserImage.js";
18
18
  export { getLocalizedString } from "./getLocalizedString.js";
19
- export { has } from "./has.js";
20
19
  export { invariant } from "./invariant.js";
21
20
  export { localize } from "./localize.js";
22
21
  export { afLocalStorage as localStorage };
@@ -0,0 +1,23 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import { invariant } from "./invariant";
4
+
5
+ describe("invariant", () => {
6
+ test("should throw error when condition is false", () => {
7
+ expect(() => {
8
+ invariant(false, "Test message");
9
+ }).toThrowError("Test message");
10
+ });
11
+
12
+ test("should throw error when condition is false and message is a function", () => {
13
+ expect(() => {
14
+ invariant(false, () => "Test message");
15
+ }).toThrowError("Test message");
16
+ });
17
+
18
+ test("should not throw error when condition is true", () => {
19
+ expect(() => {
20
+ invariant(true, "Test message");
21
+ }).not.toThrowError();
22
+ });
23
+ });
package/src/invariant.ts CHANGED
@@ -1,3 +1,11 @@
1
+ /**
2
+ * Throws an error if the condition is falsy. The provided message is used as the error message.
3
+ * A function can be provided to lazily generate the message.
4
+ *
5
+ * @param {any} condition
6
+ * @param {string | (() => string)} [message]
7
+ * @returns {void}
8
+ */
1
9
  export function invariant(condition: any, message?: string | (() => string)): asserts condition {
2
10
  if (condition) {
3
11
  return;
@@ -0,0 +1,17 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import { parseFunc } from "./parseFunc";
4
+
5
+ function testFunction(arg1: string, arg2: string) {
6
+ console.log(arg1, arg2);
7
+ }
8
+
9
+ describe("parseFunc", () => {
10
+ test("should parse function", () => {
11
+ expect(parseFunc(testFunction)).toEqual({
12
+ name: "testFunction",
13
+ args: ["arg1", "arg2"],
14
+ body: "\n console.log(arg1, arg2);\n",
15
+ });
16
+ });
17
+ });
package/src/parseFunc.ts CHANGED
@@ -6,5 +6,5 @@ const funcRegex =
6
6
  export function parseFunc(func: Function) {
7
7
  var match = func.toString().match(funcRegex);
8
8
  invariant(match, "Unable to parse function!");
9
- return { name: match[1], args: match[2].split(","), body: match[3] };
9
+ return { name: func.name ?? match[1], args: match[2].split(",").map((a) => a.trim()), body: match[3] };
10
10
  }
package/es/has.d.ts DELETED
@@ -1 +0,0 @@
1
- export declare function has(obj: any, key: string | number | symbol): boolean;
package/es/has.js DELETED
@@ -1,3 +0,0 @@
1
- export function has(obj, key) {
2
- return Object.prototype.hasOwnProperty.call(obj, key);
3
- }
package/src/has.ts DELETED
@@ -1,3 +0,0 @@
1
- export function has(obj: any, key: string | number | symbol): boolean {
2
- return Object.prototype.hasOwnProperty.call(obj, key);
3
- }