@grest-ts/common 0.0.6 → 0.0.7

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/src/Secret.ts CHANGED
@@ -1,76 +1,76 @@
1
- /**
2
- * Secret - A wrapper for sensitive values that prevents accidental logging.
3
- *
4
- * Secrets are automatically redacted when:
5
- * - Converted to string (toString)
6
- * - Serialized to JSON (toJSON)
7
- * - Logged with console.log or util.inspect
8
- *
9
- * To access the actual value, you must explicitly call unwrap().
10
- *
11
- * @example
12
- * ```typescript
13
- * const dbPassword = new Secret('super-secret-password');
14
- *
15
- * console.log(dbPassword); // "[REDACTED]"
16
- * console.log(JSON.stringify(dbPassword)); // "[REDACTED]"
17
- *
18
- * // Explicit unwrap required to get value
19
- * const password = dbPassword.unwrap();
20
- * ```
21
- */
22
- export class Secret {
23
- #value: string;
24
- constructor(value: string) {
25
- this.#value = value;
26
- }
27
-
28
- /**
29
- * Get the actual secret value.
30
- * Use with care - avoid logging the result.
31
- */
32
- unwrap(): string {
33
- return this.#value;
34
- }
35
-
36
- /**
37
- * Check if the secret has a non-empty value.
38
- */
39
- hasValue(): boolean {
40
- return this.#value.length > 0;
41
- }
42
-
43
- /**
44
- * Compare with another secret without exposing either value.
45
- */
46
- equals(other: Secret): boolean {
47
- return this.#value === other.#value;
48
- }
49
-
50
- // Prevent accidental logging/serialization
51
-
52
- toString(): string {
53
- return '[REDACTED]';
54
- }
55
-
56
- toJSON(): string {
57
- return '[REDACTED]';
58
- }
59
-
60
- // Node.js console.log and util.inspect use this
61
- [Symbol.for('nodejs.util.inspect.custom')](): string {
62
- return '[REDACTED]';
63
- }
64
-
65
- // Prevent valueOf from leaking
66
- valueOf(): string {
67
- return '[REDACTED]';
68
- }
69
- }
70
-
71
- /**
72
- * Type guard to check if a value is a Secret.
73
- */
74
- export function isSecret(value: unknown): value is Secret {
75
- return value instanceof Secret;
76
- }
1
+ /**
2
+ * Secret - A wrapper for sensitive values that prevents accidental logging.
3
+ *
4
+ * Secrets are automatically redacted when:
5
+ * - Converted to string (toString)
6
+ * - Serialized to JSON (toJSON)
7
+ * - Logged with console.log or util.inspect
8
+ *
9
+ * To access the actual value, you must explicitly call unwrap().
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * const dbPassword = new Secret('super-secret-password');
14
+ *
15
+ * console.log(dbPassword); // "[REDACTED]"
16
+ * console.log(JSON.stringify(dbPassword)); // "[REDACTED]"
17
+ *
18
+ * // Explicit unwrap required to get value
19
+ * const password = dbPassword.unwrap();
20
+ * ```
21
+ */
22
+ export class Secret {
23
+ #value: string;
24
+ constructor(value: string) {
25
+ this.#value = value;
26
+ }
27
+
28
+ /**
29
+ * Get the actual secret value.
30
+ * Use with care - avoid logging the result.
31
+ */
32
+ unwrap(): string {
33
+ return this.#value;
34
+ }
35
+
36
+ /**
37
+ * Check if the secret has a non-empty value.
38
+ */
39
+ hasValue(): boolean {
40
+ return this.#value.length > 0;
41
+ }
42
+
43
+ /**
44
+ * Compare with another secret without exposing either value.
45
+ */
46
+ equals(other: Secret): boolean {
47
+ return this.#value === other.#value;
48
+ }
49
+
50
+ // Prevent accidental logging/serialization
51
+
52
+ toString(): string {
53
+ return '[REDACTED]';
54
+ }
55
+
56
+ toJSON(): string {
57
+ return '[REDACTED]';
58
+ }
59
+
60
+ // Node.js console.log and util.inspect use this
61
+ [Symbol.for('nodejs.util.inspect.custom')](): string {
62
+ return '[REDACTED]';
63
+ }
64
+
65
+ // Prevent valueOf from leaking
66
+ valueOf(): string {
67
+ return '[REDACTED]';
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Type guard to check if a value is a Secret.
73
+ */
74
+ export function isSecret(value: unknown): value is Secret {
75
+ return value instanceof Secret;
76
+ }
@@ -1,9 +1,9 @@
1
- export class UnreachableCode {
2
- public static never<T>(input: never, defaultValue?: T): T {
3
- return defaultValue;
4
- }
5
-
6
- public static throwNever<T>(input: never, defaultValue?: Error): T {
7
- throw defaultValue;
8
- }
9
- }
1
+ export class UnreachableCode {
2
+ public static never<T>(input: never, defaultValue?: T): T {
3
+ return defaultValue;
4
+ }
5
+
6
+ public static throwNever<T>(input: never, defaultValue?: Error): T {
7
+ throw defaultValue;
8
+ }
9
+ }
package/src/deepClone.ts CHANGED
@@ -1,43 +1,43 @@
1
- /**
2
- * Recursively clones an object and all its nested properties.
3
- * Handles: primitives, arrays, plain objects, Date, Map, Set.
4
- */
5
- export function deepClone<T>(obj: T): T {
6
- if (obj === null || obj === undefined) {
7
- return obj;
8
- }
9
-
10
- if (typeof obj !== 'object') {
11
- return obj;
12
- }
13
-
14
- if (obj instanceof Date) {
15
- return new Date(obj.getTime()) as T;
16
- }
17
-
18
- if (obj instanceof Map) {
19
- const clonedMap = new Map();
20
- for (const [key, value] of obj) {
21
- clonedMap.set(deepClone(key), deepClone(value));
22
- }
23
- return clonedMap as T;
24
- }
25
-
26
- if (obj instanceof Set) {
27
- const clonedSet = new Set();
28
- for (const value of obj) {
29
- clonedSet.add(deepClone(value));
30
- }
31
- return clonedSet as T;
32
- }
33
-
34
- if (Array.isArray(obj)) {
35
- return obj.map(item => deepClone(item)) as T;
36
- }
37
-
38
- const clonedObj: Record<string, unknown> = {};
39
- for (const key of Object.keys(obj)) {
40
- clonedObj[key] = deepClone((obj as Record<string, unknown>)[key]);
41
- }
42
- return clonedObj as T;
43
- }
1
+ /**
2
+ * Recursively clones an object and all its nested properties.
3
+ * Handles: primitives, arrays, plain objects, Date, Map, Set.
4
+ */
5
+ export function deepClone<T>(obj: T): T {
6
+ if (obj === null || obj === undefined) {
7
+ return obj;
8
+ }
9
+
10
+ if (typeof obj !== 'object') {
11
+ return obj;
12
+ }
13
+
14
+ if (obj instanceof Date) {
15
+ return new Date(obj.getTime()) as T;
16
+ }
17
+
18
+ if (obj instanceof Map) {
19
+ const clonedMap = new Map();
20
+ for (const [key, value] of obj) {
21
+ clonedMap.set(deepClone(key), deepClone(value));
22
+ }
23
+ return clonedMap as T;
24
+ }
25
+
26
+ if (obj instanceof Set) {
27
+ const clonedSet = new Set();
28
+ for (const value of obj) {
29
+ clonedSet.add(deepClone(value));
30
+ }
31
+ return clonedSet as T;
32
+ }
33
+
34
+ if (Array.isArray(obj)) {
35
+ return obj.map(item => deepClone(item)) as T;
36
+ }
37
+
38
+ const clonedObj: Record<string, unknown> = {};
39
+ for (const key of Object.keys(obj)) {
40
+ clonedObj[key] = deepClone((obj as Record<string, unknown>)[key]);
41
+ }
42
+ return clonedObj as T;
43
+ }
package/src/deepFreeze.ts CHANGED
@@ -1,21 +1,21 @@
1
- /**
2
- * Recursively freezes an object and all its nested properties.
3
- * Used to create immutable objects.
4
- */
5
- export function deepFreeze<T>(o: T): T {
6
- if (o === undefined) {
7
- return o;
8
- }
9
- Object.freeze(o);
10
- Object.getOwnPropertyNames(o).forEach(function (prop) {
11
- if (prop === "renderers") {
12
- return;
13
- }
14
- if ((o as any)[prop] !== null
15
- && (typeof (o as any)[prop] === "object" || typeof (o as any)[prop] === "function")
16
- && !Object.isFrozen((o as any)[prop])) {
17
- deepFreeze((o as any)[prop]);
18
- }
19
- });
20
- return o;
21
- }
1
+ /**
2
+ * Recursively freezes an object and all its nested properties.
3
+ * Used to create immutable objects.
4
+ */
5
+ export function deepFreeze<T>(o: T): T {
6
+ if (o === undefined) {
7
+ return o;
8
+ }
9
+ Object.freeze(o);
10
+ Object.getOwnPropertyNames(o).forEach(function (prop) {
11
+ if (prop === "renderers") {
12
+ return;
13
+ }
14
+ if ((o as any)[prop] !== null
15
+ && (typeof (o as any)[prop] === "object" || typeof (o as any)[prop] === "function")
16
+ && !Object.isFrozen((o as any)[prop])) {
17
+ deepFreeze((o as any)[prop]);
18
+ }
19
+ });
20
+ return o;
21
+ }
@@ -1,22 +1,22 @@
1
- /**
2
- * Environment detection utilities that work without DOM lib
3
- * Uses type assertions to avoid TypeScript errors in Node-only contexts
4
- */
5
-
6
- // Declare window type to avoid TS errors when DOM lib is not included
7
- declare const window: { document?: unknown } | undefined
8
-
9
- /**
10
- * Check if code is running in a browser environment
11
- * Works in both Node.js and browser contexts without requiring DOM lib
12
- */
13
- export function isBrowser(): boolean {
14
- return typeof window !== 'undefined' && typeof window.document !== 'undefined'
15
- }
16
-
17
- /**
18
- * Check if code is running in a Node.js environment
19
- */
20
- export function isNode(): boolean {
21
- return !isBrowser()
22
- }
1
+ /**
2
+ * Environment detection utilities that work without DOM lib
3
+ * Uses type assertions to avoid TypeScript errors in Node-only contexts
4
+ */
5
+
6
+ // Declare window type to avoid TS errors when DOM lib is not included
7
+ declare const window: { document?: unknown } | undefined
8
+
9
+ /**
10
+ * Check if code is running in a browser environment
11
+ * Works in both Node.js and browser contexts without requiring DOM lib
12
+ */
13
+ export function isBrowser(): boolean {
14
+ return typeof window !== 'undefined' && typeof window.document !== 'undefined'
15
+ }
16
+
17
+ /**
18
+ * Check if code is running in a Node.js environment
19
+ */
20
+ export function isNode(): boolean {
21
+ return !isBrowser()
22
+ }
package/src/http.ts CHANGED
@@ -1,52 +1,52 @@
1
- export enum HttpStatusCode {
2
- OK200 = 200,
3
- /**
4
- * Completely fails to handle the request
5
- */
6
- BadRequest400 = 400,
7
- /**
8
- * User must send auth headers or in other ways be "logged in".
9
- */
10
- Unauthorized401 = 401,
11
- /**
12
- * User does not have access to resource
13
- */
14
- Forbidden403 = 403,
15
- /**
16
- * Entity not found
17
- */
18
- NotFound404 = 404,
19
- /**
20
- * Duplicate entity somewhere
21
- */
22
- Exists409 = 409,
23
- /**
24
- * These are validation errors - automatic or manual.
25
- */
26
- ValidationError422 = 422,
27
- /**
28
- * Method not allowed on this resource.
29
- */
30
- MethodNotAllowed405 = 405,
31
- /**
32
- * Generic "something went wrong".
33
- */
34
- InternalServerError500 = 500,
35
- /**
36
- * Bad Gateway - proxy/gateway received invalid response.
37
- */
38
- BadGateway502 = 502,
39
- /**
40
- * Server is shutting down and is not able to handle the request.
41
- */
42
- ServerTemporarilyNotAvailable503 = 503,
43
-
44
-
45
- /**
46
- * Non standard HTTP error! This is used in the test framework in case request failes because of some testing check.
47
- * Request itself maybe succeeded, but some check caused it to still fail. This never comes up in production, only in automated tests.
48
- */
49
- TestingError = 800
50
- }
51
-
1
+ export enum HttpStatusCode {
2
+ OK200 = 200,
3
+ /**
4
+ * Completely fails to handle the request
5
+ */
6
+ BadRequest400 = 400,
7
+ /**
8
+ * User must send auth headers or in other ways be "logged in".
9
+ */
10
+ Unauthorized401 = 401,
11
+ /**
12
+ * User does not have access to resource
13
+ */
14
+ Forbidden403 = 403,
15
+ /**
16
+ * Entity not found
17
+ */
18
+ NotFound404 = 404,
19
+ /**
20
+ * Duplicate entity somewhere
21
+ */
22
+ Exists409 = 409,
23
+ /**
24
+ * These are validation errors - automatic or manual.
25
+ */
26
+ ValidationError422 = 422,
27
+ /**
28
+ * Method not allowed on this resource.
29
+ */
30
+ MethodNotAllowed405 = 405,
31
+ /**
32
+ * Generic "something went wrong".
33
+ */
34
+ InternalServerError500 = 500,
35
+ /**
36
+ * Bad Gateway - proxy/gateway received invalid response.
37
+ */
38
+ BadGateway502 = 502,
39
+ /**
40
+ * Server is shutting down and is not able to handle the request.
41
+ */
42
+ ServerTemporarilyNotAvailable503 = 503,
43
+
44
+
45
+ /**
46
+ * Non standard HTTP error! This is used in the test framework in case request failes because of some testing check.
47
+ * Request itself maybe succeeded, but some check caused it to still fail. This never comes up in production, only in automated tests.
48
+ */
49
+ TestingError = 800
50
+ }
51
+
52
52
  export type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS";
@@ -1,12 +1,12 @@
1
- export * from './deepFreeze';
2
- export * from './deepClone';
3
- export * from './withTimeout';
4
- export * from './GGError';
5
- export * from './UnreachableCode';
6
- export * from './types';
7
- export * from './http';
8
- export * from './Secret';
9
- export * from "./sleep"
10
- export * from "./environment"
11
- export * from "./GGAsyncStorage"
12
- // GGExtensionDiscovery excluded — uses Node.js fs/path/url
1
+ export * from './deepFreeze';
2
+ export * from './deepClone';
3
+ export * from './withTimeout';
4
+ export * from './GGError';
5
+ export * from './UnreachableCode';
6
+ export * from './types';
7
+ export * from './http';
8
+ export * from './Secret';
9
+ export * from "./sleep"
10
+ export * from "./environment"
11
+ export * from "./GGAsyncStorage"
12
+ // GGExtensionDiscovery excluded — uses Node.js fs/path/url
package/src/index-node.ts CHANGED
@@ -1,12 +1,12 @@
1
- export * from './deepFreeze';
2
- export * from './deepClone';
3
- export * from './withTimeout';
4
- export * from './GGError';
5
- export * from './UnreachableCode';
6
- export * from './types';
7
- export * from './http';
8
- export * from './Secret';
9
- export * from "./sleep"
10
- export * from "./environment"
11
- export * from "./GGAsyncStorage"
1
+ export * from './deepFreeze';
2
+ export * from './deepClone';
3
+ export * from './withTimeout';
4
+ export * from './GGError';
5
+ export * from './UnreachableCode';
6
+ export * from './types';
7
+ export * from './http';
8
+ export * from './Secret';
9
+ export * from "./sleep"
10
+ export * from "./environment"
11
+ export * from "./GGAsyncStorage"
12
12
  export * from "./GGExtensionDiscovery"
package/src/sleep.ts CHANGED
@@ -1,3 +1,3 @@
1
- export function sleep(ms: number, _reason?: string): Promise<void> {
2
- return new Promise(resolve => setTimeout(resolve, ms));
1
+ export function sleep(ms: number, _reason?: string): Promise<void> {
2
+ return new Promise(resolve => setTimeout(resolve, ms));
3
3
  }
package/src/types.ts CHANGED
@@ -1,16 +1,16 @@
1
- /**
2
- * Recursively makes all properties of an object optional.
3
- * Useful for partial matching in tests and validation.
4
- */
5
- export type DeepPartial<T> = T extends object
6
- ? T extends Array<infer U>
7
- ? Array<DeepPartial<U>>
8
- : { [P in keyof T]?: DeepPartial<T[P]> }
9
- : T
10
-
11
- export type ConstructorOf<T> = new (...args: any[]) => T;
12
-
13
- /**
14
- * Returns the instance of a class. T would be the class reference.
15
- */
1
+ /**
2
+ * Recursively makes all properties of an object optional.
3
+ * Useful for partial matching in tests and validation.
4
+ */
5
+ export type DeepPartial<T> = T extends object
6
+ ? T extends Array<infer U>
7
+ ? Array<DeepPartial<U>>
8
+ : { [P in keyof T]?: DeepPartial<T[P]> }
9
+ : T
10
+
11
+ export type ConstructorOf<T> = new (...args: any[]) => T;
12
+
13
+ /**
14
+ * Returns the instance of a class. T would be the class reference.
15
+ */
16
16
  export type InstanceOf<T> = T extends { new(...args: any[]): infer S } ? S : undefined
@@ -1,20 +1,20 @@
1
- /**
2
- * Wraps a promise with a timeout. If the promise doesn't resolve/reject within
3
- * the specified timeout, the returned promise will reject with an error.
4
- *
5
- * @param promise - The promise to wrap
6
- * @param timeoutMs - Timeout in milliseconds
7
- * @param errorMessage - Error message to use when timeout occurs
8
- * @returns A promise that resolves/rejects with the original promise or times out
9
- */
10
- export async function withTimeout<T>(promise: Promise<T>, timeoutMs: number, errorMessage: string): Promise<T> {
11
- let timeoutId: any;
12
- const timeoutPromise = new Promise<never>((_, reject) => {
13
- timeoutId = setTimeout(() => reject(new Error(errorMessage)), timeoutMs);
14
- });
15
- try {
16
- return await Promise.race([promise, timeoutPromise]);
17
- } finally {
18
- clearTimeout(timeoutId!);
19
- }
20
- }
1
+ /**
2
+ * Wraps a promise with a timeout. If the promise doesn't resolve/reject within
3
+ * the specified timeout, the returned promise will reject with an error.
4
+ *
5
+ * @param promise - The promise to wrap
6
+ * @param timeoutMs - Timeout in milliseconds
7
+ * @param errorMessage - Error message to use when timeout occurs
8
+ * @returns A promise that resolves/rejects with the original promise or times out
9
+ */
10
+ export async function withTimeout<T>(promise: Promise<T>, timeoutMs: number, errorMessage: string): Promise<T> {
11
+ let timeoutId: any;
12
+ const timeoutPromise = new Promise<never>((_, reject) => {
13
+ timeoutId = setTimeout(() => reject(new Error(errorMessage)), timeoutMs);
14
+ });
15
+ try {
16
+ return await Promise.race([promise, timeoutPromise]);
17
+ } finally {
18
+ clearTimeout(timeoutId!);
19
+ }
20
+ }